仅在自定义帖子类型中搜索附件

时间:2015-10-13 作者:Rick Alday

我有一个带有自定义分类的自定义帖子类型,基本上是一个库帖子类型。我想能够在帖子类型中搜索图像。我为帖子类型和附件创建了一个自定义搜索查询,但效果不太好。我得到了一些图像的重复搜索结果。因为图像是CPT条目的一部分,但也存在于媒体库中。是否有办法仅从CPT中搜索附件?

<?php

Class SMGallerySearch {

private $query_instance;

public function __construct(){
    add_filter( \'posts_join\', array( &$this, \'terms_join\' ) );
    add_filter( \'posts_search\', array( &$this, \'search_where\' ), 10, 2 );
    add_filter( \'posts_request\', array( &$this, \'distinct\' ) );
    add_filter( \'pre_get_posts\', array( &$this, \'search_query\' ) );
    add_filter( \'attachment_link\', array( &$this, \'the_search_attachment_link\' ), 10, 2 );
    add_filter( \'the_excerpt\', array( &$this, \'the_search_excerpt\' ) );
}

public function terms_join( $join ) {
    global $wpdb;

    if ( ! empty( $this->query_instance->query_vars[\'s\'] ) ) {

        // searching custom taxonomies
        $taxonomies = get_object_taxonomies( array( \'sm_gallery_item\', \'attachment\' ) );
        foreach ( $taxonomies as $taxonomy ) {
            $on[] = "ttax.taxonomy = \'" . addslashes( $taxonomy )."\'";
        }

        // build our final string
        $on = \' ( \' . implode( \' OR \', $on ) . \' ) \';
        $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) ";
    }
    return $join;
}


/**
 * Creates the list of search keywords from the \'s\' parameters
 *
 * @since 1.8.7
 */
public function get_search_terms() {
    global $wpdb;
    $s = isset( $this->query_instance->query_vars[\'s\'] ) ? $this->query_instance->query_vars[\'s\'] : \'\';
    $sentence = isset( $this->query_instance->query_vars[\'sentence\'] ) ? $this->query_instance->query_vars[\'sentence\'] : false;
    $search_terms = array();

    if ( !empty( $s ) ) {
        // added slashes screw with quote grouping when done early, so done later
        $s = stripslashes( $s );
        if ( $sentence ) {
            $search_terms = array( $s );
        } else {
            preg_match_all( \'/".*?("|$)|((?<=[\\\\s",+])|^)[^\\\\s",+]+/\', $s, $matches );
            $search_terms = array_map( create_function( \'$a\', \'return trim($a, "\\\\"\\\'\\\\n\\\\r ");\' ), $matches[0] );
        }
    }
    return $search_terms;
}


/**
 * Add where clause to the search query
 *
 * @since 1.8.7
 */
public function search_where( $where, $wp_query ) {

    $this->query_instance = &$wp_query;
    global $wpdb;

    $searchQuery = $this->search_default();

    $searchQuery .= $this->build_search_categories();

    if ( $searchQuery != \'\' ) {
        $where = preg_replace( \'#\\(\\(\\(.*?\\)\\)\\)#\', \'((\'.$searchQuery.\'))\', $where );

    }
    return $where;
}


/**
 * Search for terms in default locations like title and content
 * replacing the old search terms seems to be the best way to
 * avoid issue with multiple terms
 *
 * @since 1.8.7
 */
public function search_default(){
    global $wpdb;

    $not_exact = empty( $this->query_instance->query_vars[\'exact\'] );
    $search_sql_query = \'\';
    $seperator = \'\';
    $terms = $this->get_search_terms();

    // if it\'s not a sentance add other terms
    $search_sql_query .= \'(\';
    foreach ( $terms as $term ) {
        $search_sql_query .= $seperator;

        $esc_term = esc_sql( $term );
        if ($not_exact) {
            $esc_term = "%$esc_term%";
        }

        $like_title = "($wpdb->posts.post_title LIKE \'$esc_term\')";
        $like_post = "($wpdb->posts.post_content LIKE \'$esc_term\')";

        $search_sql_query .= "($like_title OR $like_post)";

        $seperator = \' AND \';
    }

    $search_sql_query .= \')\';
    return $search_sql_query;
}


/**
 * Create the search categories query
 *
 * @since 1.8.7
 */
public function build_search_categories() {
    global $wpdb;
    $vars = $this->query_instance->query_vars;

    $s = $vars[\'s\'];
    $search_terms = $this->get_search_terms();
    $exact = isset( $vars[\'exact\'] ) ? $vars[\'exact\'] : \'\';
    $search = \'\';

    if ( ! empty( $search_terms ) ) {
        // Building search query for categories slug.
        $n = ( $exact ) ? \'\' : \'%\';
        $searchand = \'\';
        $searchSlug = \'\';
        foreach ( $search_terms as $term ) {
            $term = addslashes_gpc( $term );
            $searchSlug .= "{$searchand}(tter.slug LIKE \'{$n}".sanitize_title_with_dashes( $term )."{$n}\')";
            $searchand = \' AND \';
        }
        if ( count( $search_terms ) > 1 && $search_terms[0] != $s ) {
            $searchSlug = "($searchSlug) OR (tter.slug LIKE \'{$n}".sanitize_title_with_dashes( $s )."{$n}\')";
        }
        if ( ! empty( $searchSlug ) )
            $search = " OR ({$searchSlug}) ";

        // Building search query for categories description.
        $searchand = \'\';
        $searchDesc = \'\';
        foreach ( $search_terms as $term ) {
            $term = addslashes_gpc( $term );
            $searchDesc .= "{$searchand}(ttax.description LIKE \'{$n}{$term}{$n}\')";
            $searchand = \' AND \';
        }
        $sentence_term = esc_sql( $s );
        if ( count( $search_terms ) > 1 && $search_terms[0] != $sentence_term ) {
            $searchDesc = "($searchDesc) OR (ttax.description LIKE \'{$n}{$sentence_term}{$n}\')";
        }
        if ( ! empty( $searchDesc ) )
            $search = $search." OR ({$searchDesc}) ";
    }
    return $search;
}

public function distinct( $query ) {
    global $wpdb;
    if ( ! empty( $this->query_instance->query_vars[\'s\'] ) ) {
        if ( strstr( $query, \'DISTINCT\' ) ) {}
        else {
            $query = str_replace( \'SELECT\', \'SELECT DISTINCT\', $query );
        }
    }
    return $query;
}

public function search_query( $query ) {

    if ( ! $query->is_search )
        return $query;

    if ( $query->get( \'post_type\' ) && \'sm_gallery_item\' == $query->get( \'post_type\' ) ) {

        $post_types = $query->get( \'post_type\' );
        if ( $post_types && \'sm_gallery_item\' == $post_types )
            $post_types = array( \'sm_gallery_item\', \'attachment\' );

        $query->set( \'post_type\', $post_types );

        /**
         * Add post status "inherit" (for attachments) since WP only searches "publish"
         */
        $post_status = $query->get( \'post_status\' );
        if ( ! $post_status || \'publish\' == $post_status )
            $post_status = array( \'publish\', \'inherit\' );

        if ( is_array( $post_status ) )
            $post_status[] = \'inherit\';

        $query->set( \'post_status\', $post_status );

        return $query;

    }

 }


}

1 个回复
SO网友:Sam Edgecombe

我想我已经破解了。将前14行代码替换为

类SellMediaSearch{

private $query_instance;

/**
 * Init
 */
public function __construct(){
    add_filter( \'posts_join\', array( &$this, \'terms_join\' ) );
    add_filter( \'posts_search\', array( &$this, \'search_where\' ), 10, 2 );
    add_filter( \'posts_request\', array( &$this, \'distinct\' ) );
    add_filter( \'pre_get_posts\', array( &$this, \'search_query\' ) );
    add_filter( \'attachment_link\', array( &$this, \'the_search_attachment_link\' ), 10, 2 );
    add_filter( \'the_excerpt\', array( &$this, \'the_search_excerpt\' ) );
    add_filter( \'posts_where\' , array( &$this, \'posts_where\' ));
}


public function posts_where( $where ) {

    global $wpdb;
    if( is_search() ) {
                    $where .= \' AND ( post_type = \\\'sell_media_item\\\' OR ( post_type = \\\'attachment\\\' AND post_parent !=  0 ) ) \';
    }
    return $where;
}
需要测试,但最初对我有效。有关更多注释,请参阅github。

相关推荐