WordPress: include custom fields in search?

While adding some features to Templ33t, I ran into a situation where I need certain custom fields to be searchable. I didn’t want to add any extra input fields to the search box (wouldn’t make sense in this context) or hack apart the query with a bunch of joins and conditions. A fair amount of searching through the codex and google yielded few results. After tinkering for a while, I came up with a simple (if hack-ish) solution.

Using the content_save_pre filter, I was able to append an identifiable HTML comment containing the custom field text to the page content. This makes the custom field text searchable as it is now, for all intents and purposes, part of the main content. It also allows you to be selective about which custom fields are included. The tag is then stripped before editing the page/post using the the_editor_content filter. Here is the code.

// add filter callbacks
add_filter('content_save_pre', 'myplugin_add_comment', 10);
add_filter('the_editor_content', 'myplugin_strip_comment', 1);

/**
 * Append custom field content to main content in comment form for searchability.
 * @param string $content
 * @return string
 */
function myplugin_add_comment($content = null) {

	if(array_key_exists('meta', $_POST) && !empty($_POST['meta'])) {

		$cfields = array('mycustom_text', 'mycustom_other', 'mycustom_etc');

		$append = '';

		$content .= '  '.$append;

	}

	return $content;

}

/**
 * Remove custom field comment from end of content before editing.
 * @param string $content
 * @return string
 */
function myplugin_strip_comment($content = null) {

	$content = preg_replace('/()/mi', '', $content);

	return $content;

}

This worked rather well for me but I realized that the matched text would not show up in the search results. This isn’t too big a deal if you’re not using  any keyword highlighting or similar functionality. In order to support those scenarios though, I modified the structure of the comment and attached a callback to the the_content filter which renders the comment as appended text to the post for search results (or strips it in any other context). Here is the new code.

// add filter callbacks
add_filter('content_save_pre', 'myplugin_add_comment', 10);
add_filter('the_editor_content', 'myplugin_strip_comment', 1);
add_filter('the_content', 'myplugin_content_filter', 1);

/**
 * Append custom field content to main content in comment form for searchability.
 * @param string $content
 * @return string
 */
function myplugin_add_comment($content = null) {

	if(array_key_exists('meta', $_POST) && !empty($_POST['meta'])) {

		$cfields = array('mycustom_text', 'mycustom_other', 'mycustom_etc');

		$append = '';

		$content .= '  '.$append;

	}

}

/**
 * Remove custom field comment from end of content before editing.
 * @param string $content
 * @return string
 */
function myplugin_strip_comment($content = null) {

	$content = preg_replace('/()/mi', '', $content);

	return $content;

}

/**
 * Transform custom fields comment into appended text for search results
 * @param string $content
 * @return string
 */
function myplugin_content_filter($content = null) {

	if(is_search()) {

		$content = preg_replace('/(::[A-Z0-9\_\-]+::)/i', ' ... ', preg_replace('/()/mi', '$2', $content));

	} elseif(is_page()) {

		$content = myplugin_strip_comment($content);

	}

	return $content;

}

I know this is not the most ideal or efficient solution, but it does work. I hope it helps!


Securing a REST Web Service

At work, my latest assignment has been focused around creating web service functionality that mirrors the existing web application. I decided to use a REST based architecture. I’ve enjoyed the task thus far and feel I’ve been able to steer the app in a good direction. However, I began to fret over security. HTTP GET requests to a REST service leave data plainly visible and vulnerable. I needed to require a username and password for each transaction but didn’t want users to send them unencrypted via GET.

So instead of requiring a username/password combo for every transaction, I opted to minimize the number of times sensitive data is sent and package it more securely. I created an Authentication service that returns a transaction key when a valid username/password is posted to it. This transaction key expires 30 seconds after it is issued and can be used in place of authentication for any URI in the web service. Also, there is only one transaction key in the system for each user at any given time. When it is expired, a new key is generated upon request, replacing the old one.