Last active
March 19, 2022 16:57
-
-
Save chwnam/f8140fdc2c7e19570f9a898922696ca7 to your computer and use it in GitHub Desktop.
OR 키워드 검색
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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