Files
Portfolio-2026/lib/search-features.php
Keith SolomonandClaude Opus 4.7 e2f6270717 Release as SoloFrame Evo (#2)
* docs: Add onboarding documentation for new developers

Add four comprehensive guides to help new developers get started
with the VDI-Starter-v5 WordPress theme:

- docs/getting-started.md: Setup from zero, local WordPress options,
  env config, theme activation warnings, troubleshooting
- docs/architecture.md: Bootstrap flow, 7 architectural layers,
  namespace conventions, WP hooks cleanup, enqueue system, theme.json
- docs/creating-blocks.md: Step-by-step ACF block creation tutorial,
  helper functions, parent-child patterns, Tailwind integration
- docs/reference.md: Hooks/filters tables, design tokens, CSS import
  tree, JS module graph, class reference, CLI commands, deployment

Update README.md: trim deep-dive API docs (moved to reference),
add documentation links section, fix CSS paths (views/styles/ →
styles/), add missing contact-info block, fix deployment filename
typo (wpengine,yml → wpengine.yml), add backToTop.js and
enqEditorAssets(), add namespace conventions table.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: language graph

* docs: Update readme

* 🔵 other: Rename project and publish

* 🔵 other: Update .gitignore
2026-07-29 15:52:21 -05:00

123 lines
3.0 KiB
PHP

<?php
/**
* Search features for SoloFrameEvo theme.
*
* @package SoloFrameEvo
* @since 1.0.0
*/
namespace SoloFrameEvo;
/**
* Modifies the WordPress query object for page search functionality.
*
* @param WP_Query $query The WordPress query object.
*
* @return void
*/
function pageSearch( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search ) {
$query->set( 'paged', ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1 );
$query->set( 'posts_per_page', -1 );
}
}
add_action( 'pre_get_posts', __NAMESPACE__ . '\\pageSearch' );
/**
* Sort WP_Post objects in reverse order (most recent first).
*
* @param string $key WP_Post object property used for sorting. 'post_date' is assumed.
*
* @return int
*/
function postSort( $key ) {
return function ( $a, $b ) use ( $key ) {
if ( $a->$key < $b->$key ) {
return 1;
} elseif ( $a->$key > $b->$key ) {
return -1;
} else {
// If first comparison is equal, use title as secondary sort key.
return strnatcasecmp( $a->post_title, $b->post_title );
}
};
}
/**
* Remove duplicate posts in combined list from default and secondary queries.
*
* @param array $posts Array of WP_Post objects.
* @param string $key Search key used to identify duplicate objects. Post ID is used.
*
* @return array
*/
function dedupe( $posts, $key ) {
$unique_posts = array();
$ids = array();
foreach ( $posts as $post ) {
if ( ! in_array( $post->$key, $ids, true ) ) {
$ids[] = $post->$key;
$unique_posts[] = $post;
}
}
return $unique_posts;
}
/**
* Posts_results filter hook callback.
*
* @param array $posts Array of WP_Post objects.
* @param object $query WP_Query object from default search.
*
* @return array
*/
function searchResultFilter( $posts, $query ) {
if ( \is_search() && $query->is_search() && ! \is_admin() ) {
$args = array(
'post_type' => array( 'post', 'page' ),
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'OR', // Include both tags and categories.
array(
'taxonomy' => 'post_tag',
'field' => 'name',
'terms' => $query->get( 's' ),
),
array(
'taxonomy' => 'category',
'field' => 'name',
'terms' => $query->get( 's' ),
),
),
);
// Remove callback to avoid infinite loop.
remove_filter( 'posts_results', __NAMESPACE__ . '\\searchResultFilter', 10 );
$secondary_query = new \WP_Query( $args );
$tagged_posts = $secondary_query->get_posts();
// Combine default search results with secondary query.
$all_posts = array_merge( $posts, $tagged_posts );
// Remove duplicate posts.
$unique_posts = dedupe( $all_posts, 'ID' );
// Sort by reverse post_date order (most recent first).
usort( $unique_posts, postSort( 'post_date' ) );
// Restore posts_results callback.
add_filter( 'posts_results', __NAMESPACE__ . '\\searchResultFilter', 10, 2 );
return $unique_posts;
} else {
return $posts;
}
}
add_filter( 'posts_results', __NAMESPACE__ . '\\searchResultFilter', 10, 2 );