diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..fda7325 --- /dev/null +++ b/readme.txt @@ -0,0 +1,28 @@ +=== WP Sphinx Search === +Contributors: prettyboymp +Donate link: http://voceconnect.com/ +Tags: sphinx, search, sphinx search, advanced search +Requires at least: 3.0 +Tested up to: 3.0. +Stable tag: trunk + +Adds Sphinx integration to WordPress' search capability. + +== Description == + +Sphinx is a GPL version 2 full-text search engine with the ability to run high speed search queries. It can give users a more robust search experience by providing better phrase and word matching to better sort results by relevance. This plugin integrates Sphinx's search capabilities to replace the normal search that WordPress provides. + +== Installation == + +1. Configure Sphinx, see http://vocecommunications.com/blog/2010/07/extending-wordpress-search-with-sphinx-part-i/ for more details. +2. Upload the `wp-sphinx-search` folder to the `/wp-content/plugins/` directory +3. Activate the plugin through the 'Plugins' menu in WordPress +4. Configure the options under Settings -> Sphinx Search to match your Sphinx Server. + +== Screenshots == + +1. Options page. + +== Changelog == += 0.1.0 = +* Initial Release diff --git a/screenshot-1.png b/screenshot-1.png new file mode 100644 index 0000000..80f584a Binary files /dev/null and b/screenshot-1.png differ diff --git a/wp-sphinx-search.php b/wp-sphinx-search.php new file mode 100644 index 0000000..58a6922 --- /dev/null +++ b/wp-sphinx-search.php @@ -0,0 +1,285 @@ + '127.0.0.1', + 'port' => '9312', + 'index' => "*", + 'timeout' => 15 + ); + + $options = get_option('sphinx_options', false); + if(!is_array($options)) { + $options = array(); + } + return wp_parse_args($options, $defaults); + } + + /** + * Updates the options with the given options array + * + * @param array $options + */ + private function update_options($options = array()) { + update_option('sphinx_options', $options); + } + + /** + * Initialization function, registers needed hooks. + * Runs on 'init' + * + */ + public function initialize() { + add_action('admin_menu', array($this, 'admin_add_menu_items')); + register_uninstall_hook(__FILE__, array($this, 'uninstall')); + if(class_exists('SphinxClient')) { + add_action('parse_query', array($this, 'parse_query'), 10, 1); + add_filter('found_posts', array($this, 'search_filter_found_posts'), 10, 2); + } + } + + /** + * Checks query to see if it is a search, and if so, kicks off the + * Sphinx search + * + * @param WP_Query $wp_query + */ + public function parse_query(&$wp_query) { + if($wp_query->is_search) { + if(class_exists('SphinxClient')) { + switch($wp_query->query_vars['sort']) { + case 'date': + $wp_query->query_vars['orderby'] = 'date'; + $wp_query->query_vars['order'] = 'DESC'; + break; + case 'title': + $wp_query->query_vars['orderby'] = 'title'; + $wp_query->query_vars['order'] = 'ASC'; + break; + default: + $wp_query->query_vars['sort'] = 'match'; //setting this so sort link will be hilighted + } + $results = $this->search_posts($wp_query->query_vars); + if($results) { + $matching_ids = array(); + if(intval($results['total']) > 0 ) { + foreach($results['matches'] as $result) { + $matching_ids[] = intval($result['attrs']['post_id']); + } + } else { + $matching_ids[] = -1; + } + //clear the search query var so posts aren't filtered based on the search + $wp_query->query_vars['sphinx_search_term'] = $wp_query->query_vars['s']; + unset($wp_query->query_vars['s']); + if(isset($wp_query->query_vars['paged'])) { + //set our own copy of paged so that wordpress doesn't try to page a query already limiting posts + $wp_query->query_vars['sphinx_paged'] = $wp_query->query_vars['paged']; + unset($wp_query->query_vars['paged']); + } + $wp_query->query_vars['post__in'] = $matching_ids; + $wp_query->query_vars['sphinx_num_matches'] = intval($results['total']); + } + } + } + } + + /** + * Runs a search against sphinx + * + * @param array $args + * @return array Sphinx result set + */ + public function search_posts($args) { + $options = $this->get_options(); + $defaults = array( + 'search_using' => 'any', + 'sort' => 'match', + 'paged' => 1, + 'posts_per_page' => 0, + 'showposts' => 0 + ); + $args = wp_parse_args($args, $defaults); + $sphinx = new SphinxClient(); + $sphinx->setServer($options['server'], $options['port']); + + $search = $args['s']; + switch($args['search_using']) { + case 'all': + $sphinx->setMatchMode(SPH_MATCH_ALL); + break; + case 'exact': + $sphinx->setMatchMode(SPH_MATCH_PHRASE); + break; + default: + $sphinx->setMatchMode(SPH_MATCH_ANY); + } + + switch($args['sort']) { + case 'date': + $sphinx->setSortMode(SPH_SORT_ATTR_DESC, 'date_added'); + break; + case 'title': + $sphinx->setSortMode(SPH_SORT_ATTR_ASC, 'title'); + break; + default: + $sphinx->setSortMode(SPH_SORT_RELEVANCE); + } + + $page = isset($args['paged']) && (intval($args['paged']) > 0) ? intval($args['paged']) : 1; + $per_page = max(array($args['posts_per_page'], $args['showposts'])); + if($per_page < 1) { + $per_page = get_option('posts_per_page'); + } + + $sphinx->setLimits(($page - 1) * $per_page, $per_page); + $sphinx->setMaxQueryTime(intval($options['timeout'])); + $result = $sphinx->query($search, $options['index']); + $this->last_error = $sphinx->getLastError(); + $this->last_warning = $sphinx->getLastWarning(); + return $result; + } + + private function test_settings() { + $result = $this->search_posts(array('s'=>'test search', 'posts_per_page' => 1)); + if(!$result) { + return $this->last_error; + } + return false; + } + + /** + * Filters the found posts to reflect the number returned by sphinx + * + * @param int $found_posts + * @param WP_Query $wp_query + */ + public function search_filter_found_posts($found_posts, &$wp_query = null) { + if(!is_null($wp_query)) { + if(isset($wp_query->query_vars['sphinx_num_matches'])) { + $found_posts = intval($wp_query->query_vars['sphinx_num_matches']); + } + if(isset($wp_query->query_vars['sphinx_search_term'])) { + $wp_query->query_vars['s'] = $wp_query->query_vars['sphinx_search_term']; + } + if(isset($wp_query->query_vars['sphinx_paged'])) { + $wp_query->query_vars['paged'] = $wp_query->query_vars['sphinx_paged']; + } + } + + return $found_posts; + } + + /** + * Adds options page to manage sphinx settings + * + */ + public function admin_add_menu_items() { + add_options_page(__('Sphinx Search', 'sphinx-search'), __('Sphinx Search', 'sphinx-search'), 'manage_options', 'sphinx-search', array($this, 'admin_options_page')); + } + + public function admin_options_page() { + $options = $this->get_options(); + $error = false; + $updated = false; + if(isset($_REQUEST['submit']) && wp_verify_nonce($_REQUEST['sphinx_nonce'], 'save_sphinx_options')) { + if(isset($_REQUEST['sphinx_server'])) { + $options['server'] = $_REQUEST['sphinx_server']; + } + if(isset($_REQUEST['sphinx_port'])) { + $options['port'] = $_REQUEST['sphinx_port']; + } + if(isset($_REQUEST['sphinx_server'])) { + $options['index'] = $_REQUEST['sphinx_index']; + } + if(isset($_REQUEST['sphinx_timeout'])) { + $options['timeout'] = (intval($_REQUEST['sphinx_timeout']) > 0) ? intval($_REQUEST['sphinx_timeout']) : 15; + } + $this->update_options($options); + $updated = true; + $error = $this->test_settings(); + } + ?> +
+

+ +

+ + +

+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+

Sphinx Reference Manual.', 'sphinx-search')?>

+

+ + +

+
+
+