Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a search template to Responsive Framework #274

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion css-dev/style.scss
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/**
Expand Down
98 changes: 98 additions & 0 deletions inc/search-form.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 '<button class="button search-submit" type="submit" />' . esc_attr_x( 'Search', 'submit button', 'responsive-framework' ) . '</button>';
}
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 <a> 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 <a> 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 <a> 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 );
89 changes: 89 additions & 0 deletions inc/search/SearchPage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

/**
* This class handles the logic used in searchpage.php
*/
require_once 'providers/GSS_Provider.php';
class SearchPage {

public $provider;

function __construct( $site_url ) {
if ( ! $site_url ) {
$site_url = get_site_url();
}
$this->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 = '<h3><a href="' . $item->link . '">' . $item->htmlTitle . '</a>&nbsp;<span class="mime u-visually-hidden" data-type="' . urlencode($mime) . '">[' . $mime . ']</span></h3>';
$render_string .= '<p>' . $item->htmlSnippet . '</p>';
$render_string .= '<cite>' . $item->link . '</cite>';
if ( $preview ) {
$render_string .= '<img src="' . $preview[0]->src .'" />';
}

if ( $meta[0]->creationdate ) {
$render_string .= '<p>Created on ' . $meta[0]->creationdate . '</p>';
}

if ( $meta[0]->moddate ) {
$render_string .= '<p>Modified on ' . $meta[0]->moddate . '</p>';
}
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( '<a href="%s">prev</a>', $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( '<a class="page" href="%s">%s</a>', $this->provider->page_search_url( $i ), $i );
if ( $i == $this->provider->page_current ) {
$pager = sprintf( '<a class="page current" href="%s">%s</a>', $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( '<a href="%s">next</a>', $this->provider->next_page_search_url() );
$pages .= apply_filters( 'search_results_next_page', $next_pager, $this->provider->next_page_search_url() );
}
$pager = sprintf( '<div class="%s">%s</div>', $class, $pages );
$pager = apply_filters( 'search_results_pager', $pager, $pages );
if ( $echo ) {
echo $pager;
}
return $pager;
}
}
115 changes: 115 additions & 0 deletions inc/search/providers/GSS_Provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php
/**
* A Google Site Search Results provider.
*/
class GSS_Provider{

public $query;
public $page_current;
public $page_count;
public $results;
public $site;
public $results_per_page = 10;

function __construct(){
$this->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);
}
}
23 changes: 23 additions & 0 deletions inc/template-tags.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 '<p>There are no results matching your search terms.</p>';
}else{
foreach($search_page->provider->results->items as $index => $value){
$search_page->render_item($value, true);
}
$search_page->render_pager(true);
}

}
11 changes: 11 additions & 0 deletions searchpage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
/**
* Template file used to render a Search Results Index page.
* Template Name: Search Page
*/

get_header();

get_template_part( 'template-parts/content-search', 'search' );

get_footer();
4 changes: 2 additions & 2 deletions style.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading