Skip to content

Instantly share code, notes, and snippets.

@chwnam
Last active March 19, 2022 16:57
Show Gist options
  • Save chwnam/f8140fdc2c7e19570f9a898922696ca7 to your computer and use it in GitHub Desktop.
Save chwnam/f8140fdc2c7e19570f9a898922696ca7 to your computer and use it in GitHub Desktop.
OR 키워드 검색
<?php
/**
* Plugin Name: OR 키워드 검색
* Description: 입력된 키워드를 OR 조건으로 검색합니다.
* Author: changwoo
* Author URI: https://blog.changwoo.pe.kr
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_action( 'admin_menu', 'or_search_admin_menu' );
/**
* 메뉴 페이지 추가
*
* @return void
*/
function or_search_admin_menu() {
add_menu_page(
'OR 키워드 검색 샘플 페이지',
'OR 검색',
'administrator',
'or-search',
'or_search_output_page',
'dashicons-search'
);
}
/**
* 메뉴 페이지 출력
*
* @return void
*/
function or_search_output_page() {
$s = isset( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : '';
$items = array();
$sql = '';
if ( $s ) {
// Post content 에 대해서만 검색하려면 이 필터를 쓰세요.
add_filter( 'posts_where', 'or_search_where_filter', 10, 2 );
$query = new WP_Query(
array(
'post_type' => 'post',
'post_status' => 'publish',
's' => $s,
'orderby' => 'date',
'order' => 'desc',
'nopaging' => true, // 모든 검색된 포스트 한방에.
'no_found_rows' => true, // 총 포스트 수 계산 않음.
)
);
// 필터를 썼으면 반드시 해제하세요.
remove_filter( 'posts_where', 'or_search_where_filter' );
$sql = $query->request;
$keywords = array_filter( explode( ' ', $s ) );
while ( $query->have_posts() ) {
$query->the_post();
$items[] = array(
'post_id' => get_the_ID(),
'title' => get_the_title(),
'reference' => or_search_get_reference( get_the_content(), $keywords ),
);
}
}
$allwed_tags = array(
'span' => array( 'class' => true ),
);
?>
<style>
#search-result {
margin: 20px 0;
}
.or-search-found {
color: red;
background-color: yellow;
font-weight: bold;
}
#sql-wrap {
margin: 20px 0;
}
#sql-wrap > pre {
display: inline;
white-space: pre-line;
}
</style>
<div class="wrap">
<h1>OR 키워드 검색 예제</h1>
<hr class="wp-header-end">
<div>
<form action="" method="get">
<label for="s">키워드</label>:
<input id="s"
name="s"
type="search"
placeholder="OR 검색할 키워드"
value="<?php echo esc_attr( $s ); ?>">
<button class="button button-primary">검색</button>
<input type="hidden" name="page" value="or-search">
<?php wp_nonce_field( 'or-search', '_wpnonce', false ) ?>
</form>
<?php if ( $sql ) : ?>
<div id="sql-wrap"><strong>쿼리</strong>:
<pre><?php echo esc_html( $sql ); ?></pre>
</div>
<?php endif; ?>
<table id="search-result" class="wp-list-table widefat striped">
<thead>
<tr>
<td>ID</td>
<td>제목</td>
<td>발췌</td>
</tr>
</thead>
<tbody>
<?php if ( ! empty( $items ) ) : ?>
<?php foreach ( $items as $item ): ?>
<tr>
<td><?php echo intval( $item['post_id'] ); ?></td>
<td><?php echo wp_kses( $item['title'], $allwed_tags ); ?></td>
<td><?php echo wp_kses( $item['reference'], $allwed_tags ); ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<td colspan="3">검색된 내용이 없습니다.</td>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<?php
}
/**
* 포스트 내용에서 검색된 내용을 찾음.
*
* @param string $input
* @param array<string> $keywords
*
* @return string
*/
function or_search_get_reference( $input, $keywords ) {
if ( ! $input ) {
return $input;
}
$output = esc_html( $input );
foreach ( $keywords as $keyword ) {
$k = esc_html( $keyword );
$output = str_replace( $keyword, '<span class="or-search-found">' . $k . '</span>', $output );
}
return $output;
}
/**
* @param string $where
*
* @return string
*/
function or_search_where_filter( $where ) {
global $wpdb;
$title = "({$wpdb->posts}.post_title ";
$content = "({$wpdb->posts}.post_content ";
$p2_offset = 0;
while (
false !== ( $p1 = strpos( $where, $title ) ) &&
false !== ( $p2 = strpos( $where, $content, $p2_offset ) )
) {
$before = substr( $where, 0, $p1 );
$after = substr( $where, $p2 );
$where = $before . $after;
$p2_offset = $p1 + 1;
}
return $where;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment