diff --git a/source/wp-content/themes/wporg-developer/functions.php b/source/wp-content/themes/wporg-developer/functions.php index 157b8343f..eb8bbaf86 100644 --- a/source/wp-content/themes/wporg-developer/functions.php +++ b/source/wp-content/themes/wporg-developer/functions.php @@ -136,6 +136,11 @@ require __DIR__ . '/inc/admin.php'; } +/** + * Custom class for modifying search queries. + */ +require __DIR__ . '/inc/advanced-search-filters.php'; + /** * Set the content width based on the theme's design and stylesheet. */ diff --git a/source/wp-content/themes/wporg-developer/inc/advanced-search-filters.php b/source/wp-content/themes/wporg-developer/inc/advanced-search-filters.php new file mode 100644 index 000000000..8c90b5871 --- /dev/null +++ b/source/wp-content/themes/wporg-developer/inc/advanced-search-filters.php @@ -0,0 +1,151 @@ + 'wp-parser-source-file', + 'name__like' => $name, + 'fields' => 'ids', + ) + ); + + return array( + 'taxonomy' => 'wp-parser-source-file', + 'terms' => $tax_ids, + ); + } + + /** + * Returns a tax query array for appending wp-parser-since taxonomy searches + * + * @param string $term + * @return array + */ + public static function get_version_tax_query( $term ) { + return array( + 'taxonomy' => 'wp-parser-since', + 'field' => 'name', + 'terms' => $term, + ); + } + + /** + * Returns a post type string. wp-parser-{post_type} + * + * @param string $post_type_partial + * @return string + */ + public static function get_post_type_string( $post_type_partial ) { + return 'wp-parser-' . strtolower( $post_type_partial ); + } + + /** + * Modifies the query if user has used advanced search filters + * + * @param \WP_Query $query + * @return void + */ + public static function modify_query( $query ) { + $post_types = array(); + $tax_queries = array(); + + // Clean up keyword. + $keyword = trim( $query->get( 's' ) ); + + // Split on spaces. + $groups = explode( ' ', $keyword ); + + // Loop through groups + foreach ( $groups as $group ) { + // Check if {qualifier}:{keyword} is used. + $split = explode( ':', $group ); + + // We have no qualifier. + if ( ! isset( $split[1] ) || + empty( $split[0] ) || // Missing a qualifier. Ie: :init + $split[1][0] == ':' // Searching for a class method. Ie: {Class}::init() + ) { + + // If user has '()' at end of a search string, assume they want a specific function/method. + $s = htmlentities( $split[0] ); + if ( str_contains( $s, '(' ) ) { + // Modify the search query to omit the parentheses. + $keyword = str_replace( array( '()', '(' ), '', $keyword ); + + // Restrict search to function-like content. + $post_types[] = 'wp-parser-function'; + $post_types[] = 'wp-parser-method'; + } + + continue; + } + + switch ( strtolower( $split[0] ) ) { + case 'type': + $type = self::get_post_type_string( $split[1] ); + + if ( in_array( $type, DevHub\get_parsed_post_types() ) ) { + $post_types[] = $type; + // Remove everything from the query. + $keyword = str_replace( $group, '', $keyword ); + } + + break; + case 'file': + $tax_queries[] = self::get_file_tax_query( $split[1] ); + + // Remove everything from the query. + $keyword = str_replace( $group, '', $keyword ); + break; + case 'version': + $tax_queries[] = self::get_version_tax_query( $split[1] ); + + // Remove everything from the query. + $keyword = str_replace( $group, '', $keyword ); + break; + } + } + + // Add relevant tax queries + $query->set( 'tax_query', array_unique( array_merge( $query->get( 'tax_query' ) ?: array(), $tax_queries ), SORT_REGULAR ) ); + + // Add relevant post_types + $query->set( 'post_type', array_unique( array_merge( $query->get( 'post_type' ) ?: array(), $post_types ), SORT_REGULAR ) ); + + // Reset the keyword + $query->set( 's', $keyword ); + } + + /** + * Reset the keyword back to the original keyword after we retrieve the posts. + * We need to because we removed parts in modify_query(). + * + * @param WP_Post[] $posts + * @param WP_Query $query + * @return WP_Post[] + */ + public static function modify_search( $posts, $query ) { + // Reset the keyword so we don't lose the qualifiers + + if ( isset( $query->query['s'] ) ) { + $query->set( 's', $query->query['s'] ); + } + + return $posts; + } +} + +Advanced_Search_Filters::init(); diff --git a/source/wp-content/themes/wporg-developer/inc/search.php b/source/wp-content/themes/wporg-developer/inc/search.php index 446e862ae..9e657bb8e 100644 --- a/source/wp-content/themes/wporg-developer/inc/search.php +++ b/source/wp-content/themes/wporg-developer/inc/search.php @@ -92,16 +92,7 @@ public static function pre_get_posts( $query ) { // Just to make sure. post type should already be set. $query->set( 'post_type', wporg_get_current_handbook() ); } else { - // If user has '()' at end of a search string, assume they want a specific function/method. - $s = htmlentities( $query->get( 's' ) ); - if ( '()' === substr( $s, -2 ) || '(' == substr( $s, -1 ) ) { - // Enable exact search. - $query->set( 'exact', true ); - // Modify the search query to omit the parentheses. - $query->set( 's', trim( $s, '()' ) ); - // Restrict search to function-like content. - $query->set( 'post_type', array( 'wp-parser-function', 'wp-parser-method' ) ); - } + Advanced_Search_Filters::modify_query( $query ); } // Get post types (if used, or set above)