Como aperfeiçoo esse snippet de consulta de administrador para evitar a geração de resultados duplicados em pesquisas que não são meta meta?

11

Venho brincando com trechos de código que adicionam metadados às pesquisas de administrador.

O melhor trecho que encontrei foi escrito por Stefano sobre esta questão .

No entanto, parece ter um bug irritante ao pesquisar termos não meta.

Aqui estão algumas dicas da minha instalação local do desenvolvedor. Eu imprimi as 2 consultas MySQL na tela.

Visualização da postagem única de CPT que estou usando para testar

Visualização da postagem única de CPT que estou usando para testar

Este é o código que funciona como esperado e me permite pesquisar metadados do administrador

Este é o código que funciona como esperado e me permite pesquisar metadados do administrador

Infelizmente, o código cria duplicatas em correspondências não meta, neste caso no título da postagem

Infelizmente, o código cria duplicatas em correspondências não meta, neste caso no título da postagem

Uma garra mostrando o status da postagem, o tipo de postagem e os ancestrais das postagens

! Uma garra mostrando o status da postagem, o tipo de postagem e os ancestrais de dupes

Aqui está o código que estou executando, é basicamente o mesmo de Stefano, mas com minhas tentativas grosseiras de fazer a consulta funcionar.

/*
 * Search custom fields from admin keyword searches
 */

function rel_search_join( $join ) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == 'edit.php' && $_GET['post_type'] == 'listings' && $_GET['s'] != '') {    
        $join .= 'LEFT JOIN ' . $wpdb->postmeta . ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    echo '<br><strong>JOIN</strong>: ';
    print_r ( $join );
    echo '<br>';
    return $join;
}
add_filter('posts_join', 'rel_search_join' );

function rel_search_where( $where ) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == 'edit.php' && $_GET['post_type']=='listings' && $_GET['s'] != '' ) {
        $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 );
        $where = str_replace( "OR wp_posts.post_status = 'pending'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = 'private'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = 'draft'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = 'future'", "", $where );
    }
    echo '<br><strong>WHERE</strong>: ';
    print_r ( $where );
    echo '<br>';
    return $where;
}
add_filter( 'posts_where', 'rel_search_where' );  
jnthnclrk
fonte
Talvez ele também lista as revisões?
passatgt
Eu pensei que estava olhando apenas para publicação, porque removi o pendente, o privado, o rascunho e o futuro. Não notou um tipo de revisão.
Jnthnclrk
Hmmm, não parece ser um status de "revisões": codex.wordpress.org/Post_Status
jnthnclrk
tente imprimir o tipo de postagem ou o ID da postagem em uma das colunas, acho que as revisões são tipos de postagem, portanto, se você pode ver as revisões, você também terá isso nos resultados. Mas também posso ver que você só exibe resultados do tipo de publicação de listagem, então acho que estou errado. Mas vale a pena uma tentativa :)
passatgt
Foi adicionada uma nova captura com status, tipos e ancestrais de postagem.
Jnthnclrk

Respostas:

11

Uma GROUP BYdeclaração pode agrupar suas postagens após o JOIN. Para o Wordpress, você pode usar o posts_groupbyfiltro.

add_filter( 'posts_groupby', 'my_post_limits' );
function my_post_limits($groupby) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == 'edit.php' && $_GET['post_type']=='listings' && $_GET['s'] != '' ) {
        $groupby = "$wpdb->posts.ID";
    }
    return $groupby;
}
epilético
fonte
4

Obrigado pelo seu trabalho nisso, pessoal. Esse código me levou a maior parte do caminho até lá, mas usando o WP 3.8 eu estava recebendo um erro de tabela / alias não exclusivo do SQL, então fiz algumas alterações. Para que funcionasse na minha configuração, tive que definir um alias $ wpdb-> postmeta que foi usado na instrução JOIN. Também verifico apenas uma vez para ver se os ganchos devem ser usados ​​para que eles não disparem toda vez. Espero que isso ajude alguém!

global $postmeta_alias, $is_specials_search;
$cpt_name = 'special';
$postmeta_alias = 'pdpm'; // Change this to whatever your custom post type is
$is_specials_search = is_admin() && $pagenow=='edit.php' && isset( $_GET['post_type'] ) && $_GET['post_type']==$cpt_name && isset( $_GET['s'] );

// Extend search to include 'description' field
if ( $is_specials_search ) {
  add_filter( 'posts_join',      'pd_description_search_join' );
  add_filter( 'posts_where',     'pd_description_search_where' );
  add_filter( 'posts_groupby',   'pd_search_dupe_fix' );
}

function pd_description_search_join ($join){
  global $pagenow, $wpdb, $postmeta_alias, $is_specials_search;

  if ( $is_specials_search )  
    $join .='LEFT JOIN '.$wpdb->postmeta. ' as ' . $postmeta_alias . ' ON '. $wpdb->posts . '.ID = ' . $postmeta_alias . '.post_id ';

  return $join;
} // END search_join

function pd_description_search_where( $where ){
  global $pagenow, $wpdb, $postmeta_alias, $is_specials_search;

  if ( $is_specials_search )
    $where = preg_replace(
     "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
     "(".$wpdb->posts.".post_title LIKE $1) OR (".$postmeta_alias.".meta_value LIKE $1)", $where );

  return $where;
} // END search_where

function pd_search_dupe_fix($groupby) {
    global $pagenow, $wpdb, $is_specials_search;

    if ( $is_specials_search )
      $groupby = "$wpdb->posts.ID";

    return $groupby;
} // END pd_search_dupe_fix
souverian
fonte