Created
November 11, 2014 23:49
-
-
Save rogerlos/e57ad1e2272107c12ba3 to your computer and use it in GitHub Desktop.
Wordpress SearchWP: Substitute Post for Attachment in Search Results
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 | |
/** | |
* This function will see if a PDF or other "attachment" post-type returned by SearchWP | |
* is present in a custom field in a regular post, and will return that post instead. Note | |
* this will only process documents which are referenced via the "attachment" post type. | |
* | |
* For example, you may have a product specification PDF and would like it in the search | |
* results, but would rather people got to it by visiting the product page itself. | |
* | |
* There are some filters you can set to provide some control over both the attachments | |
* processed and the post-types they might be attached to. | |
* | |
* The ideal use case is a custom post type which sets a custom field to the ID or filename | |
* of a file from the media library. | |
* | |
*/ | |
// SearchWP hook | |
add_filter( 'searchwp_results', 'my_searchwp_search_results', 10, 2 ); | |
/** | |
* Substitute a post for an attachment by looking for attachment URL or ID in custom post field | |
* | |
* @param $posts : Array of WP_Post objects from SearchWP | |
* @param array $params : Parameters sent by SearchWP (as of 2.4.8 - unused below, but available): | |
* 'terms' => Terms searched for | |
* 'page' => Which page of search results this is | |
* 'order' => Results return order (ex: DESC) | |
* 'foundPosts' => Number of found posts in results | |
* 'maxNumPages' => Maximum number of result pages | |
* 'engine' => Which SearchWP engine is in use | |
* | |
* @return array | |
*/ | |
function my_searchwp_search_results( $posts, $params = array() ) { | |
$results = $posts; | |
$attachments = array(); | |
/** | |
* Required: $custom_meta_field (string) | |
* The field in the post you wish to substitute which will be checked for the | |
* attachment filename or ID. This field will be matched against the attachment URL | |
* and the attachment ID, if it matches either the substitution will occur. | |
*/ | |
$custom_meta_field = ''; | |
/** | |
* Optional: $custom_description_field (string) | |
* SearchWP normally returns the excerpt. Setting a custom field value here will set | |
* the WP_Post excerpt to be the contents of this field. Note: Not escaped or otherwise | |
* filtered, use caution or add checks! | |
*/ | |
$custom_description_field = null; | |
// Initial filtering of attachments by their properties: | |
/** | |
* Optional: $upload_directory_filter (string) | |
* Limit the substitution to attachments uploaded to directory with this string in path. | |
* Matched to ANY part of the path, be sure to be as specific as possible. | |
* Set to 'null' to check all attachments. | |
*/ | |
$upload_directory_filter = null; | |
/** | |
* Optional: $filename_filter (string) | |
* Limit the substitution to attachments with this string as part of filename. | |
* Matched to ANY part of the filename, be sure to be as specific as possible. | |
* Set to 'null' to check all attachments. | |
*/ | |
$filename_filter = null; | |
/** | |
* Optional: $extension_filter (array) | |
* Limit substitution to specific attachment types. Empty array | |
* allows all extensions. Example: array( 'pdf', 'txt' ) | |
*/ | |
$extension_filter = array(); | |
/** | |
* Optional: $hide_others_filter (bool) | |
* If you set filters above and want non-matching attachments removed from search | |
* results entirely, set below to true | |
*/ | |
$hide_others_filter = false; | |
// Matching filtered attachments: | |
/** | |
* Optional: $post_type_filter (array) | |
* Limit substitution to specific post types. Cannot be "attachment". Empty array | |
* dfaults to "post". Example: array( 'page', 'my_custom_post' ) | |
*/ | |
$post_types = array(); | |
/** | |
* Optional: $hide_filtered_attachments (bool) | |
* Set to true if you want attachments hidden which passed initial | |
* filtering (path/name/extension) but cannot be matched against selected posts/fields | |
*/ | |
$hide_filtered_attachments = false; | |
// if an attachment is in $results, add to $attachments | |
foreach ( $results as $key => $post ) { | |
// see if it's an attachment | |
if ( $post->post_type == 'attachment' ) { | |
// get the attachment URL and parse it | |
$check_file = wp_get_attachment_url( $post->ID ); | |
$file_parsed = parse_url( $check_file ); | |
// there has to be a path to proceed | |
if ( isset ( $file_parsed['path'] ) ) { | |
// use pathinfo to get filename | |
$check_file_info = pathinfo( $file_parsed['path'] ); | |
// filter by path contents | |
if ( $upload_directory_filter !== null && ! strstr( $check_file_info['dirname'], $upload_directory_filter ) ) { | |
$check_file_info = ''; | |
} | |
// filter by filename contents | |
if ( $filename_filter !== null && ! strstr( $check_file_info['filename'], $filename_filter ) ) { | |
$check_file_info = ''; | |
} | |
// filter by extension | |
if ( ! empty( $extension_filter ) && ! in_array( $check_file_info['extension'], $extension_filter ) ) { | |
$check_file_info = ''; | |
} | |
// did we find a filename? | |
if ( isset( $check_file_info['basename'] ) && $check_file_info['basename'] ) { | |
// Use the $posts key to facilitate later substitution | |
$attachments[ $key ]['path'] = $file_parsed['path']; | |
$attachments[ $key ]['ID'] = $post->ID; | |
} | |
} | |
// if $hide_others_filter is true and attachment was not added to $attachments, remove from results | |
if ( ! isset( $attachments[ $key ]['file'] ) && $hide_others_filter === true ) { | |
unset( $results[$key] ); | |
} | |
} | |
} | |
// if $attachments were found, match them against posts | |
if ( ! empty( $attachments ) ) { | |
// holds our posts to check for our filtered attachments | |
$check_posts = array(); | |
// if $post_types was set | |
$arg_post_type = ''; | |
if ( ! empty( $post_types ) ) { | |
$arg_post_type = $post_types; | |
} | |
/** | |
* Note, this is a very simple query. You may or will want to modify to account for | |
* taxonomy filtering, etc., etc. | |
*/ | |
$args = array( | |
'post_type' => $arg_post_type, | |
'posts_per_page' => -1, | |
'post_status' => 'publish', | |
); | |
$all_posts = new WP_Query( $args ); | |
// did we find posts? | |
if ( ! empty( $all_posts->posts ) ) { | |
$check_posts = $all_posts->posts; | |
} | |
wp_reset_postdata(); | |
// now we check those attachments to find their matching toolbox posts | |
foreach ( $attachments as $attachment_key => $attachment ) { | |
// flag to check for applying $hide_filtered_attachments | |
$ok = false; | |
foreach ( $check_posts as $post ) { | |
// get custom meta field which contains the attachment ID or filepath | |
$check_thisfile = get_post_meta( $post->ID, $custom_meta_field, true ); | |
// did we get a value back? | |
if ( $check_thisfile ) { | |
// if it is numeric, it's an ID | |
if ( is_numeric( $check_thisfile ) && ( intval( $check_thisfile ) == floatval( $check_thisfile ) ) ) { | |
// compare to our id, if it matches, make the substitution | |
if ( intval( $check_thisfile) == intval( $attachment['ID'] ) ) { | |
$results[ $attachment_key ] = $post; | |
$ok = true; | |
break; | |
} | |
} else { | |
// parse the URL from the meta field | |
$thisfile_parsed = parse_url( $check_thisfile ); | |
// if we found a path from our parsing and it matches our attachment path, make substitution | |
if ( isset ( $thisfile_parsed['path'] ) && ( $thisfile_parsed['path'] == $attachment['path'] ) ) { | |
$results[ $attachment_key ] = $post; | |
$ok = true; | |
break; | |
} | |
} | |
} | |
} | |
// we made a substitution and $custom_description_field was set, make the substitution | |
if ( $ok === true && $custom_description_field !== null ) { | |
$results[ $attachment_key ]->post_excerpt = get_post_meta( $results[ $attachment_key ]->ID, $custom_description_field, true ); | |
} | |
// unset the search result if we did not make a substitution and the filter is set to true | |
if ( $ok === false && $hide_filtered_attachments === true ) { | |
unset( $results[ $attachment_key ] ); | |
} | |
} | |
} | |
// return the search results to SearchWP | |
return array_values( $results ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment