post_status !== 'publish' ) return; $wiki_id = (int) get_post_meta( $post_id, '_wmw_wiki_id', true ); $keywords = wp_strip_all_tags( $post->post_title . ' ' . $post->post_content . ' ' . $post->post_excerpt ); $wpdb->replace( $wpdb->prefix . 'wmw_search_index', array( 'article_id' => $post_id, 'wiki_id' => $wiki_id, 'keywords' => $keywords, ), array( '%d', '%d', '%s' ) ); } /** * Artikel aus dem Index entfernen. */ public function remove_from_index( $post_id ) { global $wpdb; $wpdb->delete( $wpdb->prefix . 'wmw_search_index', array( 'article_id' => $post_id ), array( '%d' ) ); } /** * Alle vorhandenen Artikel in den Index aufnehmen. * Wird aufgerufen wenn der Index leer ist (z.B. nach Gitea-Import). */ public static function reindex_all() { global $wpdb; $articles = get_posts( array( 'post_type' => 'wmw_article', 'post_status' => 'publish', 'posts_per_page' => -1, ) ); foreach ( $articles as $post ) { $wiki_id = (int) get_post_meta( $post->ID, '_wmw_wiki_id', true ); $keywords = wp_strip_all_tags( $post->post_title . ' ' . $post->post_content . ' ' . $post->post_excerpt ); $wpdb->replace( $wpdb->prefix . 'wmw_search_index', array( 'article_id' => $post->ID, 'wiki_id' => $wiki_id, 'keywords' => $keywords, ), array( '%d', '%d', '%s' ) ); } return count( $articles ); } /** * Artikel suchen. * 1. Versucht den schnellen Custom-Index. * 2. Fällt auf WP_Query zurück, wenn der Index leer ist (z.B. nach Gitea-Import). * 3. Baut den Index automatisch auf, wenn er leer war. */ public static function search( $query, $wiki_id = 0, $limit = 20 ) { global $wpdb; $table = $wpdb->prefix . 'wmw_search_index'; $like = '%' . $wpdb->esc_like( $query ) . '%'; // ── Prüfen ob der Index überhaupt Einträge hat ──────────────────── $index_count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM $table" ); $ids = array(); if ( $index_count > 0 ) { // ── Custom-Index nutzen ─────────────────────────────────────── if ( $wiki_id ) { $rows = $wpdb->get_results( $wpdb->prepare( "SELECT article_id FROM $table WHERE wiki_id = %d AND keywords LIKE %s LIMIT %d", $wiki_id, $like, $limit ) ); } else { $rows = $wpdb->get_results( $wpdb->prepare( "SELECT article_id FROM $table WHERE keywords LIKE %s LIMIT %d", $like, $limit ) ); } $ids = wp_list_pluck( $rows, 'article_id' ); } // ── Fallback: WP_Query (wenn Index leer oder keine Treffer) ─────── if ( empty( $ids ) ) { $args = array( 'post_type' => 'wmw_article', 'post_status' => 'publish', 'posts_per_page' => $limit, 's' => $query, 'orderby' => 'relevance', ); if ( $wiki_id ) { $args['meta_query'] = array( array( 'key' => '_wmw_wiki_id', 'value' => $wiki_id, ), ); } $fallback = get_posts( $args ); // Index war leer → jetzt automatisch aufbauen (im Hintergrund) if ( $index_count === 0 ) { self::reindex_all(); } foreach ( $fallback as &$post ) { $excerpt = $post->post_excerpt ?: wp_trim_words( $post->post_content, 25 ); $post->wmw_excerpt = self::highlight( $excerpt, $query ); $post->wmw_title = self::highlight( $post->post_title, $query ); } return $fallback; } // ── Artikel-Objekte aus IDs laden ───────────────────────────────── $posts = get_posts( array( 'post_type' => 'wmw_article', 'post_status' => 'publish', 'post__in' => $ids, 'posts_per_page' => $limit, 'orderby' => 'post_title', 'order' => 'ASC', ) ); foreach ( $posts as &$post ) { $excerpt = $post->post_excerpt ?: wp_trim_words( $post->post_content, 25 ); $post->wmw_excerpt = self::highlight( $excerpt, $query ); $post->wmw_title = self::highlight( $post->post_title, $query ); } return $posts; } /** * Suchtreffer hervorheben. */ public static function highlight( $text, $query ) { $words = explode( ' ', preg_quote( trim( $query ), '/' ) ); foreach ( $words as $word ) { if ( strlen( $word ) < 2 ) continue; $text = preg_replace( '/(' . $word . ')/iu', '$1', $text ); } return $text; } }