I've got a custom post type that in the CMS I would to be able to alter the search so it only searches by title of the post, then also pulls through all sub pages of that page.
Currently I have the following, which does limit search to title but I'm struggling how to best approach pulling through the subpages and returning them on this query.
add_filter( 'posts_search', 'admin_search_shops', null, 2 );
function admin_search_shops( $search, $a_wp_query ) {
if ( !is_admin() ) return $search;
$search = preg_replace( "# OR \(.*posts\.post_content LIKE \\'%.*%\\'\)#", "", $search );
return $search;
}
Rather than trying to reconstruct a complicated SQL query, it would be much simpler to add the children in the 'posts_results' filter at the end. Combined with what you have done already (limiting the search to the titles), the following will add in any child pages.
add_filter( 'posts_results', 'admin_postsearch_shops', null, 2);
function admin_postsearch_shops( $posts ) {
foreach( $posts as $post ) {
$args = array( 'post_parent' => $post->ID);
foreach ( get_children( $args ) as $child ) {
$posts[] = $child;
}
}
return $posts;
}
Related
I need to move certain articles on my website, all of them, to another unique category. I am using specific phrases which are at bottom of every article, but after code execution, only two articles are moved to a new category, not all of them.
Also when I search through all posts using the native Dashboard-All posts option, it returns only those two articles, not all of them. I assume that is because the text is not stored in the database because it shows only when the post renders itself on the front end.
How can I include dynamically created text in my code?
My code, just for reference:
<?php
// Move to the category Breaking News.
$target_category_id = 1982;
// Get all posts that contain the search phrase from Syndication.
$posts = get_posts(
array(
's' => 'and has been published here with permission',
'post_status' => 'any',
'posts_per_page' => -1, // This will retrieve all posts.
)
);
// Loop through the posts and move them to the target category.
foreach ( $posts as $post ) {
// Remove the post from any existing categories.
$current_categories = wp_get_post_categories( $post->ID );
wp_remove_object_terms( $post->ID, $current_categories, 'category' );
// Add the post to the target category.
wp_set_post_categories( $post->ID, array( $target_category_id ), true );
}
That specific phrase is created dynamically because I am using the WP Broadcast plugin to add text at the bottom of every broadcasted article, but I am not sure if that phrase is stored in a database or that text is dynamically populated (created) every time post is rendered on the frontend.
This is the code I am using to generate a message (and has been published here with permission) at the bottom of every article:
<?php
function broadcasted_from() {
// Check that Broadcast is enabled.
if ( ! function_exists( 'ThreeWP_Broadcast' ) ) {
return;
}
// Load the broadcast data for this post.
global $post;
$broadcast_data = ThreeWP_Broadcast()->get_post_broadcast_data( get_current_blog_id(), $post->ID );
// This post must be a child. Check for a parent.
$parent = $broadcast_data->get_linked_parent();
if ( ! $parent ) {
return;
}
// Fetch the permalink
switch_to_blog( $parent['blog_id'] );
$blog_name = get_bloginfo( 'name' );
$permalink = get_post_permalink( $parent['post_id'] );
restore_current_blog();
// And now assemble a text.
$r = sprintf( 'This article appeared in %s and has been published here with permission.', $permalink, $blog_name );
return $r;
}
add_shortcode( 'broadcasted_from', 'broadcasted_from' );
add_filter(
'the_content',
function( $content ) {
// Get the broadcast from the text.
$sc_text = do_shortcode( '[broadcasted_from]' );
// Add the text to the content.
$content .= $sc_text;
// Return the expanded content.
return $content;
}
);
I have added this function in my functions.php file to show category option for wordpress pages. It works fine.
function support_category_for_pages() {
// Add category support to pages
register_taxonomy_for_object_type('category', 'page');
}
add_action( 'init', 'support_category_for_pages' );
But is it possible to show/limit some categories for pages only(they must not appear under posts) ?
I hope I am writing this correctly. Basically the requirement is to keep different categories for post & pages and they should not appear in each other's category option.
There are two approaches i can think off. I am not sure how you want it to work regarding the archive page and search page so second approach may not work for you.
First solution creating templates:
For example category-news.php
Inside you can modify the query specificly for this category
$args = array(
'post_type' => 'posts'
//add more arguments if needed
);
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
// Do Stuff
} // end while
} // endif
// Reset Post Data
wp_reset_postdata();
Second solution using pre_get_posts:
function wp50_exclude_post_type_pages() {
//in the array you can add ids, slugs or names
if ( is_category( array( 9, 'cat2', 'Category 3' )) && $query->is_main_query() ) {
//here we tell the query to show posts type only
$query->set( 'post_type', 'posts' );
return $query;
}
}
add_action( 'pre_get_posts', 'wp50_exclude_post_type_pages');
I've searched everywhere for an answer to this and keep finding different suggestions, but none that seem to fit my particular needs. I currently have a website using a custom built search (no plugin). Website: GayBarsIn.com
The search functions I found work for searching custom post titles, post meta data (Advanced Custom Fields) and a combination of both title and post meta data, but only one post meta keyword works. I'm trying to find a way to search multiple post meta keywords.
For instance: The site shows bar listings.
If I search for a single keyword... say "Cleveland," it will return all listings with that keyword (whether in the title or post meta).
If I search for "Cleveland Ohio," it will return only those values found first in the title, then in the post meta, but just one instance of post meta. So if the title has Cleveland in it and the post meta has Ohio, it will return those results, but it will not show those that contain two instances of post meta data with keywords "Cleveland Ohio."
What I need for it to do is show results using multiple search terms for ALL post meta (custom fields). Example: "Cleveland and Ohio" or "Nightclub and Lounge and Houston"
Here is the code I found that works okay for a single keyword search:
/* ========================================
* SEARCH CUSTOM POST TYPES
* ======================================== */
function searchfilter($query) {
if ($query->is_search && !is_admin() ) {
$query->set('post_type', array('listing'));
}
return $query;
}
add_filter('pre_get_posts','searchfilter');
function cf_search_join( $join ) {
global $wpdb;
if ( is_search() ) {
$join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
}
return $join;
}
add_filter('posts_join', 'cf_search_join' );
/**
* Modify the search query with posts_where
*
* http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
*/
function cf_search_where( $where ) {
global $pagenow, $wpdb;
if ( is_search() ) {
$where = preg_replace(
"/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
"(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where );
}
return $where;
}
add_filter( 'posts_where', 'cf_search_where' );
/**
* Prevent duplicates
*
* http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct
*/
function cf_search_distinct( $where ) {
global $wpdb;
if ( is_search() ) {
return "DISTINCT";
}
return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );
About half-way down the code, this section seems to be what should be edited, but I can't figure out how. I've tried switching 'OR' to 'AND' but that returns no results.
if ( is_search() ) {
$where = preg_replace(
"/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
"(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where );
}
I apologize if this has been asked before. I've looked for a few days and found others circling around what I'm trying to do, but not specifically enough for it to work for me. Any help or guidance would be much appreciated!
You should create your own form with input field for search, and catch data after post. You could split the words for example with explode() and put them into an array. You need to check if words exists as tag, so you need to loop through your array and check if it exists in get_tags($args). After that you should have an array with only useful tags. Now you can use get_posts()
$postargs = array(
'posts_per_page' => '-1',
'tag__and' => YOUR_ARRAY,
'orderby' => 'date',
'order' => 'DESC',
'post_type' => YOUR_CUSTOM_POST_TYPE,
'post_status' => 'publish',
'suppress_filters' => true
);
$posts_array = get_posts( $postargs );
You only need to loop (foreach) through your post-array and output results.
I am working with the Wordpress Query Object using the WP Types/Views Toolset.
http://wp-types.com
We built out the parametric search which allows the user to search through posts using various taxonomies. It works fine, it display search results as needed. BUT..
Most of the posts don't have featured images, we want to display posts with featured images at the top, and the featured imageless posts would go below.
I have a good head start on this as far as logic goes, just need a bit of help.
The code below allows me manipulate the query before rendering it to the user.
add_filter( 'wpv_filter_query_post_process', 'prefix_rearrange_by_thumbnail', 10, 3 );
function prefix_rearrange_by_thumbnail( $query, $view_settings, $view_id ) {
// sort posts by thumbnail
return $query;
}
How can I sort through the query->posts and rearrange them so the ones that do have featured images show up before those without.
All of the WP_Post objects are found in an array under $query->posts. You can sort the array using usort() based on whatever criteria you want. Keep in mind that this will only sort each page of results as that is what is returned.
add_filter( 'wpv_filter_query_post_process', 'prefix_rearrange_by_thumbnail' );
function prefix_rearrange_by_thumbnail( $query ) {
$posts = $query->posts;
usort( $posts, 'sort_by_thumbnail' );
return $query;
}
// function used to sort the posts array
function sort_by_thumbnail( $a, $b ){
// the the featured image id so we can sort by it
$a_thumb = get_post_meta( $a->ID, '_thumbnail_id', true );
$b_thumb = get_post_meta( $b->ID, '_thumbnail_id', true );
if ( empty( $a_thumb ) && ! empty( $b_thumb ) ) return 1;
if ( ! empty( $a_thumb ) && empty( $b_thumb ) ) return -1;
return 0;
}
To sort all the pages of the results you need to modify the arguments that are passed to WP_Query using the wpv_filter_query filter. There is a meta_key called "_thumbnail_id" set for each post/page that has a featured image, but the issue is that this meta_key is not set at all for posts/pages without a featured image, so if you use it the results will be sorted by the ID of the featured images, but if it is missing they will be omitted. One option is to set another flag based on that meta_key to use in your sort. A one time cleaned would be needed then you could use a hook on save_post
One time SQL (adjust for your db prefix):
INSERT INTO wp_postmeta( post_id, meta_key, meta_value )
SELECT p.ID, '_has_featured_image', IF ( meta_value IS NULL, 0, 1 ) AS _has_featured_image
FROM wp_posts p
LEFT JOIN wp_postmeta m ON p.ID = m.post_id AND meta_key = '_thumbnail_id'
WHERE p.post_status = 'publish'
AND p.post_type IN ('post','page')
Hook on save_post to keep "_has_featured_image" clean going forward:
add_action( 'save_post', 'set_has_featured_image' );
function set_has_featured_image( $post_id ){
$post = get_post( $post_id );
switch ( $post->post_type ){
case 'post': case 'page':
$thumbnail_id = get_post_meta( $post_id, '_thumbnail_id', true );
update_post_meta( $post_id, '_has_featured_image', ! empty( $thumbnail_id ) );
break;
}
}
Now you can filter on the "_has_featured_image" meta_key:
add_filter( 'wpv_filter_query', 'prefix_rearrange_by_thumbnail' );
function prefix_rearrange_by_thumbnail( $args ){
$args['orderby'] = 'meta_value';
$args['meta_key'] = '_has_featured_image';
return $args;
}
I managed to do it in an easier way...
add_filter( 'wpv_filter_query_post_process', 'prefix_rearrange_by_thumbnail', 10, 3 );
function prefix_rearrange_by_thumbnail( $query, $view_settings, $view_id ) {
if ( !empty( $query->posts ) ) {
$sorted_posts_top = array();
$sorted_posts_bottom = array();
$all_posts = $query->posts;
foreach ($all_posts as $post) {
if ( has_post_thumbnail($post->ID) ) {
$sorted_posts_top[] = $post;
}
else {
$sorted_posts_bottom[] = $post;
}
$query->posts = array_merge((array)$sorted_posts_top, (array)$sorted_posts_bottom);
}
}
return $query;
}
However, your answer is still VERY helpful. Thank you SO MUCH for sharing!!!!!!!!!!!!!!!!
I have many categories, but for clearity I will do an example with only two:
News that contains many posts
Products that contains many pages (I've added this feature in functions.php)
I want that archive.php displays:
the posts when the user choose the category News
the pages when the user choose the category Products
At the moment Wordpress by deafult shows only posts and not pages.
I know that this is possible by adding a simple function in functions.php but I can't find it.
EDIT: For another project with custom post type "Books" I used this code
function query_post_type($query) {
$post_types = get_post_types();
if ( is_category() || is_tag()) {
$post_type = get_query_var('books');
if ( $post_type ) {
$post_type = $post_type;
} else {
$post_type = $post_types;
}
$query->set( 'post_type', $post_type );
return $query;
}
}
add_filter('pre_get_posts', 'query_post_type');
Is there something like that for my case?
You can query for solely pages in the WP Query.
PHP:
$args = array(
'post_type' => 'page'
);
$query = new WP_Query( $args );
This will return all pages in your database, and zero posts. Vice versa, you could have 'post_type' => 'post' to query all posts, but that's the default behaviour of the WP Query.
For more documentation on this, check out the WP Query reference in the Wordpress Codex.