$posts Posts from the main query. * @param \WP_Query $query The query object. * @return array<\WP_Post> */ public function inject_search_results( array $posts, \WP_Query $query ): array { if ( is_admin() || ! $query->is_main_query() || ! $query->is_search() ) { return $posts; } // Only inject on page 1 to avoid pagination issues $paged = (int) ( is_numeric( $query->get( 'paged' ) ) ? $query->get( 'paged' ) : 0 ); if ( $paged > 1 ) { return $posts; } $search_term = $query->get( 's' ); if ( ! is_string( $search_term ) || $search_term === '' ) { return $posts; } $event_posts = $this->search_events( sanitize_text_field( $search_term ), 10 ); if ( ! empty( $event_posts ) ) { $posts = array_merge( $posts, $event_posts ); $query->found_posts += count( $event_posts ); } return $posts; } /** * Fix permalink for virtual event posts in search results. * * @param string $url The post permalink. * @param \WP_Post $post The post object. * @return string */ public function fix_virtual_post_permalink( string $url, \WP_Post $post ): string { if ( $post->ID === 0 && str_contains( $post->guid, 'webcalendar/event/' ) ) { return $post->guid; } return $url; } /** * Fix page link for virtual event posts in search results. * * @param string $url The page permalink. * @param int $post_id The post ID. * @return string */ public function fix_virtual_post_page_link( string $url, int $post_id ): string { if ( $post_id === 0 ) { $post = get_post(); if ( $post instanceof \WP_Post && str_contains( $post->guid, 'webcalendar/event/' ) ) { return $post->guid; } } return $url; } /** * Search for events via the core EventRepository. * * @param string $search_term The search term. * @param int $limit Maximum results. * @return array<\WP_Post> */ private function search_events( string $search_term, int $limit ): array { $container = Container::get_instance(); $event_repo = $container->get_event_repository(); $mode = SingleEventPage::get_mode(); $accessLevel = ( $mode === 'all' && is_user_logged_in() ) ? null : 'P'; $events = $event_repo->search( $search_term, null, null, $accessLevel, $limit ); $virtual_posts = []; foreach ( $events as $event ) { $virtual_posts[] = $this->event_to_virtual_post( $event ); } return $virtual_posts; } /** * Convert an Event entity to a virtual WP_Post. * * @param Event $event The event entity. * @return \WP_Post */ private function event_to_virtual_post( Event $event ): \WP_Post { $slug = sanitize_title( $event->name() ); $url = home_url( 'webcalendar/event/' . $event->id()->value() . '-' . $slug . '/' ); $description = $event->description() !== '' ? wp_trim_words( wp_strip_all_tags( $event->description() ), 30, '...' ) : ''; $date = $event->start()->format( 'Y-m-d' ); return new \WP_Post( (object) [ 'ID' => 0, 'post_author' => '0', 'post_date' => $date . ' 00:00:00', 'post_date_gmt' => $date . ' 00:00:00', 'post_content' => $description, 'post_title' => $event->name(), 'post_excerpt' => $description, 'post_status' => 'publish', 'comment_status' => 'closed', 'ping_status' => 'closed', 'post_password' => '', 'post_name' => $slug, 'to_ping' => '', 'pinged' => '', 'post_modified' => current_time( 'mysql' ), 'post_modified_gmt' => current_time( 'mysql', true ), 'post_content_filtered' => '', 'post_parent' => 0, 'guid' => $url, 'menu_order' => 0, 'post_type' => 'page', 'post_mime_type' => '', 'comment_count' => '0', 'filter' => 'raw', ] ); } }