Index: google_cse.theme.inc
===================================================================
--- google_cse.theme.inc (revision 1192)
+++ google_cse.theme.inc (revision 1293)
@@ -1,5 +1,5 @@
intval($results['from']),
+ '!to' => intval($results['to']),
+ '!total' => intval($results['total'])
+ )
+ );
+
+ $perpage = variable_get('google_cse_results_num', 10);
+ $query = array('query' => $_GET['query']);
+
+ if ($results['from'] > 1) {
+ $newstart = intval($results['from']) - $perpage - 1;
+ if ($newstart < 0) {
+ $newstart = 0;
+ }
+ $query['start'] = $newstart;
+
+ $variables['pager_prev'] = l(t('Previous page'),
+ variable_get('google_cse_results_path', 'search/google'),
+ array('query' => drupal_query_string_encode($query)));
+ }
+
+ if ($results['to'] < $results['total']) {
+ $query['start'] = intval($results['to']);
+
+ $variables['pager_next'] = l(t('Next page'),
+ variable_get('google_cse_results_path', 'search/google'),
+ array('query' => drupal_query_string_encode($query)));
+ }
+
+ preg_match('/ more:([^&]*)/', $_GET['query'], $selected_label);
+ $variables['original_query'] = preg_replace('/ more:[^&]*/', '', $_GET['query']);
+ $variables['has_refinements'] = count($results['labels']) == TRUE;
+
+ $selected_label = $selected_label[1];
+
+ $variables['refinements_label'] = t('Refine results for');
+
+ $variables['refinements'] = array();
+ foreach ($results['labels'] as $label => $title) {
+ $selected = ($label == $selected_label) ? ' selected' : '';
+ $classes = "google-cse-refinements-label" . $selected;
+ $attributes = drupal_attributes(array('class' => $classes));
+ $new_query['query'] = $original_query . " more:$label";
+ $link = l(t($title),
+ variable_get('google_cse_results_path', 'search/google'),
+ array('query' => drupal_query_string_encode($new_query)));
+ $variables['refinements'][] = array('link' => $link, 'attributes' => $attributes);
+ }
+
+ $variables['results'] = array();
+ foreach ($results['items'] as $item) {
+ $link = l($item['title'], $item['url'], array('html' => TRUE));
+ $filtered_excerpt = filter_xss_admin(preg_replace('/
/', '', $item['excerpt']));
+ $url = l($item['url'], $item['url']);
+ $variables['results'][] = array('title' => $link, 'excerpt' => $filtered_excerpt, 'url' => $url);
+ }
+}
+
+/**
* Display an Add-to-Google button.
*/
function template_preprocess_google_cse_results_gadget(&$variables) {
Index: google_cse.admin.inc
===================================================================
--- google_cse.admin.inc (revision 1192)
+++ google_cse.admin.inc (revision 1293)
@@ -23,9 +23,10 @@
'#default_value' => variable_get('google_cse_results_display', 'here'),
'#options' => array(
'here' => t('On this site (requires JavaScript)'),
+ 'xml' => t('On this site (without JavaScript or frames, requires current Google Business account)'),
'google' => t('On Google'),
),
- '#description' => t('Search results can be displayed on this site, using JavaScript, or on Google, which does not require JavaScript.'),
+ '#description' => t('Search results can be displayed on this site, using JavaScript, or on Google, which does not require JavaScript. If you have a Business account on Google Custom Search, you can also display results on this site without using JavaScript.'),
);
$form['google_cse_results_title'] = array(
'#title' => t('Search results page title'),
Index: google_cse.module
===================================================================
--- google_cse.module (revision 1192)
+++ google_cse.module (revision 1293)
@@ -1,5 +1,5 @@
array('search Google CSE'),
'title callback' => 'google_cse_results_tab',
'description' => 'Google Custom Search Engine',
@@ -41,6 +42,11 @@
'file' => 'google_cse.theme.inc',
'template' => 'google_cse_results',
),
+ 'google_cse_xml_results' => array(
+ 'arguments' => array('form' => TRUE, 'self' => FALSE),
+ 'file' => 'google_cse.theme.inc',
+ 'template' => 'google_cse_xml_results',
+ ),
'google_cse_results_gadget' => array(
'arguments' => array(),
'file' => 'google_cse.theme.inc',
@@ -91,37 +97,48 @@
function google_cse_searchbox_form_builder(&$form_state, $form_id, $self = FALSE) {
$form = array();
// The default form.
- if (variable_get('google_cse_results_display', 'here') == 'here') {
- $form['#action'] = url($self ? $_GET['q'] : 'search/google');
+ if (variable_get('google_cse_results_display', 'here') != 'google') {
+ $form['#action'] = url($self ? $_GET['q'] : variable_get('google_cse_results_path', 'search/google'));
$cof = variable_get('google_cse_cof_here', 'FORID:11');
}
else {
$form['#action'] = 'http://'. variable_get('google_cse_domain', 'www.google.com') .'/cse';
$cof = variable_get('google_cse_cof_google', 'FORID:0');
}
+
$form['#method'] = 'get';
+
+ $form['query'] = array(
+ '#type' => 'textfield',
+ '#default_value' => isset($_GET['query']) ? preg_replace('/ more:[^&]*/', '', $_GET['query']) : '',
+ );
+ $form['sa'] = array(
+ '#type' => 'submit',
+ '#value' => t('Search'),
+ );
+
+ // items needed for non-XML-display versions of search form,
+ // whether it is in the block or on the results page
+
+ if (variable_get('google_cse_results_display', 'here') != 'xml') {
$form['cx'] = array(
'#type' => 'hidden',
'#value' => variable_get('google_cse_cx', ''),
);
+
$form['cof'] = array(
'#type' => 'hidden',
'#value' => $cof,
);
- $form['query'] = array(
- '#type' => 'textfield',
- '#default_value' => isset($_GET['query']) ? $_GET['query'] : '',
- );
- $form['sa'] = array(
- '#type' => 'submit',
- '#value' => t('Search'),
- );
+
foreach (google_cse_advanced_settings() as $parameter => $setting) {
$form[$parameter] = array(
'#type' => 'hidden',
'#value' => $setting,
);
}
+ }
+
// And the small differences between both.
switch ($form_id) {
case 'google_cse_searchbox_form':
@@ -130,12 +147,13 @@
break;
case 'google_cse_results_searchbox_form':
$form['query']['#size'] = intval(variable_get('google_cse_results_searchbox_width', 40));
- $form['query']['#title'] = t('Enter your keywords');
+ $form['query']['#title'] = variable_get('google_cse_searchbox_header', t('Enter your keywords'));
if (variable_get('google_cse_results_gadget', 1)) {
$form['sa']['#suffix'] = theme('google_cse_results_gadget');
}
- break;
}
+
+ // TODO: May need to remove
google_cse_sitesearch_form($form);
return $form;
}
@@ -145,8 +163,13 @@
*/
function google_cse_results() {
google_cse_results_set_title();
- return theme('google_cse_results');
+ if (variable_get('google_cse_results_display', 'here') == 'here') {
+ print theme('page', theme('google_cse_results'));
+ } else {
+ $results = _google_cse_get_search_results();
+ print theme('page', theme('google_cse_xml_results', $results));
}
+}
/**
* Return the Google CSE tab title, either a setting or a translation.
@@ -235,3 +258,214 @@
function google_cse_sitesearch_default() {
return isset($_GET['sitesearch']) ? $_GET['sitesearch'] : (variable_get('google_cse_sitesearch_default', 0) ? array_shift(preg_split('/[\s]+/', variable_get('google_cse_sitesearch', ''))) : '');
}
+
+/* Queries Google to get XML results, and parses them into an array
+ * of search items -- see theme_google_cse_result_items() function below
+ * for documentation of this array.
+ */
+function _google_cse_get_search_results() {
+
+ // formulate the query for Google
+
+ $url = 'http://www.google.com/search';
+
+ $query = array(
+ 'q' => $_GET['refinement'] == '' ? $_GET['query'] : $_GET['query'] . ' more:' . $_GET['refinement'],
+ 'start' => $_GET['start'],
+ 'num' => variable_get('google_cse_results_num', 10),
+ 'client' => 'google-csbe',
+ 'output' => 'xml_no_dtd',
+ 'cx' => variable_get('google_cse_cx', ''),
+ ) + google_cse_advanced_settings();
+
+ // get the XML results
+
+ $res = drupal_http_request($url . '?' . drupal_query_string_encode($query));
+
+ if ($res->code != '200') {
+ return array();
+ }
+
+ // parse results and return them
+ return _google_cse_parse_xml_results($res->data);
+
+}
+
+
+/*
+ * Internal function: parses the XML results returned by Google into
+ * a results array (see function theme_google_cse_result_items for doc)
+ */
+function _google_cse_parse_xml_results($data) {
+
+ global $google_cse_elem;
+ global $google_cse_item_index;
+ global $google_cse_results;
+ global $google_cse_in_facet_item;
+
+ $google_cse_in_facet_item = FALSE;
+
+ $xml_p = drupal_xml_parser_create($data);
+ xml_set_element_handler($xml_p, '_google_cse_xml_elem_start',
+ '_google_cse_xml_elem_end');
+ xml_set_character_data_handler($xml_p, '_google_cse_xml_character_data');
+
+ $google_cse_elem = '';
+ $google_cse_item_index = 0;
+ $google_cse_results = array('items' => array());
+
+ if (!xml_parse($xml_p, $data, 1)) {
+ return array();
+ }
+
+ return $google_cse_results;
+}
+
+/*
+ * Internal function for handling XML elements when parsing Google results.
+ */
+function _google_cse_xml_elem_start($parser, $name, $attribs = array()) {
+ global $google_cse_elem;
+ global $google_cse_item_index;
+ global $google_cse_results;
+ global $google_cse_partial_data;
+ global $google_cse_in_facet_item;
+ global $google_cse_curr_facet_label;
+
+ // we only care about some of the XML elements in the Google results
+ // See http://www.google.com/coop/docs/cse/resultsxml.html for doc
+
+ switch ($name) {
+ case 'RES':
+ // attributes give the from/to indices of this results set
+ $google_cse_results['from'] = $attribs['SN'];
+ $google_cse_results['to'] = $attribs['EN'];
+ break;
+
+ case 'M':
+ // gives approx total number of results of search
+ $google_cse_elem = 'total';
+ break;
+
+ case 'R':
+ // starts a new search result item
+ $google_cse_item_index = count($google_cse_results['items']);
+ $google_cse_results['items'][$google_cse_item_index] = array();
+ break;
+
+ case 'FACETITEM':
+ // starts a new facet item
+ $google_cse_in_facet_item = TRUE;
+ break;
+
+ case 'LABEL':
+ $google_cse_elem = $google_cse_in_facet_item ? 'facetlabel' : 'label';
+ break;
+
+ case 'ANCHOR_TEXT':
+ $google_cse_elem = 'anchor_text';
+ break;
+
+ // The rest of these are components of search result items
+
+ case 'U':
+ $google_cse_elem = 'url';
+ break;
+
+ case 'T':
+ $google_cse_elem = 'title';
+ break;
+
+ case 'CRAWLDATE':
+ $google_cse_elem = 'crawldate';
+ break;
+
+ case 'S':
+ $google_cse_elem = 'excerpt';
+ break;
+
+ case 'LANG':
+ $google_cse_elem = 'lang';
+ break;
+
+ case 'HN':
+ $google_cse_elem = 'crowd_host';
+ break;
+
+ // anything else: make sure we are not getting data now!
+ default:
+ $google_cse_elem = '';
+ break;
+
+ }
+
+ // this flag makes sure the character data handler gets reset
+ $google_cse_partial_data = 0;
+}
+
+/*
+ * Internal function for handling XML elements when parsing Google results
+ */
+function _google_cse_xml_elem_end($parser, $name) {
+ global $google_cse_elem;
+ global $google_cse_item_index;
+ global $google_cse_partial_data;
+ global $google_cse_in_facet_item;
+
+ // close out the element and make sure character data handler gets reset
+ $google_cse_elem = '';
+ $google_cse_partial_data = 0;
+ switch ($name) {
+ case 'FACETITEM':
+ $google_cse_in_facet_item = FALSE;
+ break;
+ }
+}
+
+
+/*
+ * Internal function for handling XML elements when parsing Google results
+ */
+function _google_cse_xml_character_data($parser, $data) {
+ global $google_cse_elem;
+ global $google_cse_item_index;
+ global $google_cse_results;
+ global $google_cse_partial_data;
+ global $google_cse_curr_facet_label;
+
+ if ($google_cse_elem == 'total') {
+ // handle the "total" element
+ if (!$google_cse_partial_data) {
+ $google_cse_results['total'] = '';
+ }
+ $google_cse_results['total'] .= $data;
+
+ } else if ($google_cse_elem == 'facetlabel') {
+ if (!$google_cse_partial_data) {
+ $google_cse_curr_facet_label = '';
+ }
+ $google_cse_curr_facet_label .= html_entity_decode($data);
+
+ } else if ($google_cse_elem == 'anchor_text') {
+ if (!$google_cse_partial_data) {
+ $google_cse_results['labels'][$google_cse_curr_facet_label] = '';
+ }
+ $google_cse_results['labels'][$google_cse_curr_facet_label] .= html_entity_decode($data);
+
+ } else if (array_search($google_cse_elem,
+ array('url', 'title', 'crawldate',
+ 'excerpt', 'lang', 'crowd_host')) !== FALSE) {
+
+ // handle the item sub-elements
+ if (!$google_cse_partial_data) {
+ $google_cse_results['items'][$google_cse_item_index][$google_cse_elem] = '';
+ }
+
+ $google_cse_results['items'][$google_cse_item_index][$google_cse_elem] .= html_entity_decode($data);
+
+ }
+
+ // sometimes this gets called multiple times within the same element,
+ // due to line breaks or whatever, so make sure we append data
+ $google_cse_partial_data = 1;
+}
\ No newline at end of file
Index: google_cse_xml_results.tpl.php
===================================================================
--- google_cse_xml_results.tpl.php (revision 0)
+++ google_cse_xml_results.tpl.php (revision 1293)
@@ -0,0 +1,56 @@
+
+
+ +
+ + + +:
+ + > + ++ + | + + +
+ + ++ + | + + +
+ + + + + + +