diff --git a/css-dev/style.scss b/css-dev/style.scss index 8439f901..b24815e8 100644 --- a/css-dev/style.scss +++ b/css-dev/style.scss @@ -1,5 +1,5 @@ /* -Theme Name: Responsive Framework 2.x +Theme Name: Responsive Framework Search Branch Author: Boston University Interactive Design Website: http://www.bu.edu/interactive-design/ Version: 2.5.0 diff --git a/functions.php b/functions.php index 11a354f5..3d5f8a8f 100755 --- a/functions.php +++ b/functions.php @@ -851,6 +851,7 @@ function responsive_branding_copyright() { * * @link http://github.com/bu-ist/bu-cms */ +require __DIR__ . '/inc/search/SearchPage.php'; require __DIR__ . '/inc/search-form.php'; /** diff --git a/inc/search-form.php b/inc/search-form.php index e6204d81..7c26b5b4 100755 --- a/inc/search-form.php +++ b/inc/search-form.php @@ -16,3 +16,101 @@ function responsive_bu_search_form_contexts() { ); } add_filter( 'bu_search_form_contexts', 'responsive_bu_search_form_contexts' ); + + +/** + * Submit the form to the current site, and display results in the searchpage.php template + * + * @return String The site's url where the form should be submited. + */ +function filter_search_action( $url ) { + return get_search_link(); +} +add_filter( 'bu_search_form_action', 'filter_search_action', 10, 1 ); + +/** + * Filter the submit button to not submit it's value. + * + * @param String $input_submit_html The old input field + * @return String The new button + */ +function filter_search_form_input_submit( $input_submit_html ) { + return ''; +} +add_filter( 'bu_search_form_input_submit', 'filter_search_form_input_submit', 10, 1 ); + +/** + * Remove the context and site input fields from the search form. No need for them now that /phpbin/search doesn't exist. + * + * @param String $input_site_html The input html markup for the site url field + * @return String Empty string. + */ +function filter_search_ignore_input( $input_site_html ) { + return ''; +} +add_filter( 'bu_search_form_input_site', 'filter_search_ignore_input', 10, 1 ); +add_filter( 'bu_search_form_input_context', 'filter_search_ignore_input', 10, 1 ); + +/** + * Search results filter for a specific result item. + * + * @param String $html the html of the item being filtered + * @param Object $item See item returned by GSS: https://developers.google.com/custom-search/json-api/v1/reference/cse/list#response + * @return String html for the specific search result. + */ +function filter_search_results_item( $html, $item ) { + return $html; +} +add_filter( 'search_results_item', 'filter_search_results_item', 10, 2 ); + +/** + * Seach results filter for paginator's Prev page link. + * + * @param String $html tag for the previous page + * @param String $url the previous result's page url + * @return String the html for the previous page + */ +function filter_results_previous_page( $html, $url ) { + return $html; +} +add_filter( 'search_results_previous_page', 'filter_results_previous_page', 10, 2 ); + +/** + * Search results filter for a specific results page. + * + * @param String $html tag for the previous page. + * @param Array $url Array where: 0=>url of current element, 1=>index of current element, 2=>current of of search results + * @return String the html for the page at index $index. + */ +function filter_results_page( $html, $options ) { + $opts = array_replace( array( '', 1, 1 ), $options ); + $url = $opts[0]; + $index = $opts[1]; + $current_results_page = $opts[2]; + return $html; +} +add_filter( 'search_results_page', 'filter_results_page', 10, 2 ); + +/** + * Search results filter for the next page + * + * @param String $html tag for the next page + * @param String $url the next resutl's page url. + * @return String the html for the next page + */ +function filter_Results_next_page( $html, $url ) { + return $html; +} +add_filter( 'search_results_next_page', 'filter_Results_next_page', 10, 2 ); + +/** + * search results filter for pager wrapper + * + * @param String $html the html pager being filtered + * @param String $pager the pager links + * @return String the html for the final pager in it's container. + */ +function filter_results_pager( $html, $pager ) { + return $html; +} +add_filter( 'search_results_pager', 'filter_results_pager', 10, 2 ); diff --git a/inc/search/SearchPage.php b/inc/search/SearchPage.php new file mode 100644 index 00000000..37e3926d --- /dev/null +++ b/inc/search/SearchPage.php @@ -0,0 +1,89 @@ +provider = new GSS_Provider(); + $this->provider->site = $site_url; + $got_results = $this->provider->get_results(); + } + + /** + * Render a result item + * + * @param Object $item Search result item returned by Google Site Search + * @param boolean $echo True if results should be echo'ed + * @return String the result item + */ + function render_item( $item, $echo = false ) { + $mime = empty( $item->mime ) ? '' : $item->mime; + $preview = empty( $item->pagemap->cse_thumbnail ) ? '' : $item->pagemap->cse_thumbnail; + $meta = empty( $item->pagemap->metatags ) ? '' : $item->pagemap->metatags; + $render_string = '

' . $item->htmlTitle . ' [' . $mime . ']

'; + $render_string .= '

' . $item->htmlSnippet . '

'; + $render_string .= '' . $item->link . ''; + if ( $preview ) { + $render_string .= ''; + } + + if ( $meta[0]->creationdate ) { + $render_string .= '

Created on ' . $meta[0]->creationdate . '

'; + } + + if ( $meta[0]->moddate ) { + $render_string .= '

Modified on ' . $meta[0]->moddate . '

'; + } + apply_filters( 'search_results_item', $render_string, $item ); + if ( $echo ) { + echo $render_string; + } + return $render_string; + } + + /** + * Get the pager for the current page. + * + * @param boolean $echo True if results should be echo'ed. + * @return string results for the current page. + */ + function render_pager( $echo = false, $container_class = 'search-pagenator', $current_page_class = 'current' ) { + + $pages = ''; + if ( $this->provider->have_prev_search_page() ) { + $prev_page = sprintf( 'prev', $this->provider->prev_page_search_url() ); + $pages .= apply_filters( 'search_results_previous_page', $prev_page, $this->provider->prev_page_search_url() ); + } + + // max 10 pages of results. + $num_pages_results = ceil( $this->provider->page_count / $this->provider->results_per_page ); + $last_page = min( 10, $num_pages_results ); + for ( $i = 1; $i <= $last_page; $i++ ) { + $pager = sprintf( '%s', $this->provider->page_search_url( $i ), $i ); + if ( $i == $this->provider->page_current ) { + $pager = sprintf( '%s', $this->provider->page_search_url( $i ), $i ); + } + $options = array( $this->provider->page_search_url( $i ), $i, $this->provider->page_current ); + $pages .= apply_filters( 'search_results_page', $pager, $options ); + } + + if ( $this->provider->have_next_search_page() && $this->provider->page_current < $last_page ) { + $next_pager = sprintf( 'next', $this->provider->next_page_search_url() ); + $pages .= apply_filters( 'search_results_next_page', $next_pager, $this->provider->next_page_search_url() ); + } + $pager = sprintf( '
%s
', $class, $pages ); + $pager = apply_filters( 'search_results_pager', $pager, $pages ); + if ( $echo ) { + echo $pager; + } + return $pager; + } +} diff --git a/inc/search/providers/GSS_Provider.php b/inc/search/providers/GSS_Provider.php new file mode 100644 index 00000000..b671101a --- /dev/null +++ b/inc/search/providers/GSS_Provider.php @@ -0,0 +1,115 @@ +query = $_GET['q']; + $this->page_current = $_GET['pg']; + if(!$this->page_current) + $this->page_current = 1; + $this->site = get_site_url(); + } + + private function get_wp_search_url($query, $page){ + if(!$query) $query = $this->query; + if(!$page) $page = $this->page_current; + return sprintf ( "%s?q=%s&pg=%s", get_search_link(), $query, $page ); + } + + /** + * Fetches and set's the instance's search results. + * @return bool true if fetch was successful. False otherwise. + */ + public function get_results(){ + $query = urlencode($this->query); + //$site = urlencode($this->site); + $site = urlencode('https://www.bu.edu/dining/'); + $result_start_idx = (($this->page_current-1) * $this->results_per_page) + 1; //if results_per_page = 10, page 1 starts with result 1, page 2 starts with result 11; + $results_per_page = $this->results_per_page; + /* + Note: the API key below is restricted to cms-devl sites only. It's not for production use. + Use your own key during development. + Also, the site needs to be manually set, because cms-devl isn't indexed by Google. + This is why I have the site hardcoded to Research Support above. + Parameters available here: https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list + Possibilities: search by file type (&fileType=pdf), date range + Sort by date, name, in either order + Potentially filter by post type or other metadata, if we add structured markup and PageMaps: https://developers.google.com/custom-search/docs/structured_data#addtopage + https://support.google.com/programmable-search/answer/1628213?hl=en + Custom attributes: + https://support.google.com/programmable-search/answer/1628215?hl=en&ref_topic=2642610 + The idea being that maybe we add a custom attribute, such as post type + If we're making multiple calls, we may also be able to grab stuff from the Brink, or ask + IS&T if they can set up a custom search engine just for Research sites. + Maybe even BU Editorial and non-BU editorial sites, excluding the main sites + */ + $remote_url = "https://webapi.bu.edu/web/?siteSearchFilter=i&siteSearch=".$site."&q=".$query.'&num='.$results_per_page.'&start='.$result_start_idx; + $args = array( + 'timeout' => 5, + 'redirection' => 5, + 'httpversion' => '1.0', + 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url(), + 'blocking' => true, + 'cookies' => array(), + 'body' => null, + 'compress' => false, + 'decompress' => true, + 'sslverify' => true, + 'stream' => false, + 'filename' => null + ); + $response = wp_remote_get($remote_url, $args); + if(is_wp_error($response) || $response['response']['code'] !== 200){ + return false; + } + $this->results = json_decode($response['body']); + $this->page_count = ceil ( $this->results->queries->request[0]->totalResults / $this->results_per_page ) ; + return true; + } + + /** + * return true if fetched results have a next page. + * @return boolean true is results have a next page, false otherwise. + */ + public function have_next_search_page(){ + return $this->page_current < $this->page_count; + } + /** + * Return the url of the next page for the current search query. + * @return string the url + */ + public function next_page_search_url(){ + return $this->get_wp_search_url($this->query, $this->page_current+1); + } + /** + * Return true if there's a page before the current one in the pager. + * @return boolean true if current_page > 1 + */ + public function have_prev_search_page(){ + return $this->page_current > 1; + } + /** + * Fetch the pagenator's previous page. + * @return String String url of the previous pagenator's page + */ + public function prev_page_search_url(){ + return $this->get_wp_search_url($this->query, $this->page_current-1); + } + /** + * page specific search url + * @param int $page the requesting page number + * @return string url of the page for the current search query. + */ + public function page_search_url($page){ + return $this->get_wp_search_url($this->query, $page); + } +} diff --git a/inc/template-tags.php b/inc/template-tags.php index cb87acac..7e0e5f42 100755 --- a/inc/template-tags.php +++ b/inc/template-tags.php @@ -1205,3 +1205,26 @@ function responsive_get_the_excerpt( $post_id = null, $length = 55 ) { } return $excerpt; } + + + +/** + * Print the search results for a query. + * This function uses the site_search_url option to determiner the source site. + * If no site_search_url option is set, get_site_url() is used by default. + * @return None Echo's the search results to the page. + */ +function responsive_search_results(){ + $search_site = get_option('site_search_url', get_site_url()); + $search_page = new SearchPage($search_site); + + if(empty($search_page->provider->results) || empty($search_page->provider->results->items)){ + echo '

There are no results matching your search terms.

'; + }else{ + foreach($search_page->provider->results->items as $index => $value){ + $search_page->render_item($value, true); + } + $search_page->render_pager(true); + } + +} \ No newline at end of file diff --git a/searchpage.php b/searchpage.php new file mode 100644 index 00000000..0c8fbb96 --- /dev/null +++ b/searchpage.php @@ -0,0 +1,11 @@ + + +
+ +

+ +

+ + + + + + Tags: ', ', ', '' ); + } ?> + + ', '

' ); ?> + +
+ + + \ No newline at end of file