You are here

function google_appliance_parse_device_response_xml in Google Search Appliance 7

Parse the response from the Google Search Appliance device into a php array

@arg $gsa_xml response text obtained from the device query @arg $use_cached Whether or not to use the cached version of this query

Return value

php array structure to iterate when displaying results

1 call to google_appliance_parse_device_response_xml()
google_appliance_search_view in ./google_appliance.module
Top level search execution (menu callback)
1 string reference to 'google_appliance_parse_device_response_xml'
google_appliance_block_view in ./google_appliance.module
Implements hook_block_view().

File

./google_appliance.module, line 637
Google Appliance module enables searching via a dedicated Google Search Appliance hardware device. See README.txt and the help page at admin/help/google_appliance.

Code

function google_appliance_parse_device_response_xml($gsa_xml, $use_cached = TRUE) {
  $results =& drupal_static(__FUNCTION__);
  if (!isset($results) || $use_cached === FALSE) {

    // look for xml parse errors
    libxml_use_internal_errors(TRUE);
    $payload = simplexml_load_string($gsa_xml);
    if (!$payload) {

      // XML parse error(s)
      $errors = array();
      foreach (libxml_get_errors() as $error) {
        $errors[] = $error->message;
      }

      // roll up the errors
      $errors = join(', ', $errors);
      $results['error'] = array(
        'lib_xml_parse_error' => $errors,
      );

      // displaying useful error messages depends upon the use of the array key
      // 'lib_xml_parse_error' ... the actual error is displayed elsewhere.
      // @see google_appliance.theme.inc
    }
    else {

      // store metrics for stat reporting
      $results['total_results'] = (int) $payload->RES->M;

      // somewhat unreliable
      $results['last_result'] = (string) $payload->RES['EN'];

      // check if there is an result at all ($payload->RES),
      // secure search doesn't provide a value for $payload->RES->M
      if ($results['total_results'] == 0 && isset($payload->RES)) {
        $results['total_results'] = (int) $payload->RES['EN'];
        $param_start = $payload
          ->xpath('/GSP/PARAM[@name="start"]');
        $param_num = $payload
          ->xpath('/GSP/PARAM[@name="num"]');
        $request_max_total = (int) $param_start[0]['value'] + (int) $param_num[0]['value'];
        if ($results['total_results'] == $request_max_total) {
          $results['total_results']++;
        }
      }

      // Spelling suggestions.
      if (isset($payload->Spelling->Suggestion)) {
        $spelling_suggestion = (string) $payload->Spelling->Suggestion;
        $results['spelling_suggestion'] = filter_xss($spelling_suggestion, array(
          'b',
          'i',
        ));
      }

      // Onebox results.
      // @see https://developers.google.com/search-appliance/documentation/614/oneboxguide#providerresultsschema
      // @see https://developers.google.com/search-appliance/documentation/614/oneboxguide#mergingobs
      foreach ($payload
        ->xpath('//ENTOBRESULTS/OBRES') as $mod) {
        $result_code = empty($mod->resultCode) ? '' : (string) $mod->resultCode;
        if (empty($result_code) || $result_code == 'success') {
          $module_name = (string) $mod['module_name'];
          $onebox = array();
          $onebox['module_name'] = $module_name;
          $onebox['provider'] = (string) $mod->provider;
          $onebox['url_text'] = (string) $mod->title->urlText;
          $onebox['url_link'] = (string) $mod->title->urlLink;
          $onebox['image'] = (string) $mod->IMAGE_SOURCE;
          $onebox['description'] = (string) $mod->description;
          foreach ($mod
            ->xpath('./MODULE_RESULT') as $res) {
            $result = array();
            $result['abs_url'] = (string) $res->U;
            $result['title'] = (string) $res->Title;
            foreach ($res
              ->xpath('./Field') as $field) {
              $field_name = (string) $field['name'];
              $result['fields'][$field_name] = (string) $field;
            }
            $onebox['results'][] = $result;
          }
          $results['onebox'][$module_name] = $onebox;
        }
      }
      if ($results['total_results'] == 0) {

        // search returned zero results
        $results['error'] = array(
          'gsa_no_results' => TRUE,
        );
        return $results;
      }
      else {

        // parse results
        foreach ($payload
          ->xpath('//GM') as $km) {
          $keymatch = array();

          // keymatch information
          $keymatch['description'] = (string) $km->GD;
          $keymatch['url'] = (string) $km->GL;
          $results['keymatch'][] = $keymatch;
        }

        // If there are any synonyms returned by the appliance, put them in the results as a new array
        // @see http://code.google.com/apis/searchappliance/documentation/50/xml_reference.html#tag_onesynonym
        foreach ($payload
          ->xpath('//OneSynonym') as $syn_element) {
          $synonym = array();

          // synonym information
          $synonym['description'] = (string) $syn_element;
          $synonym['url'] = (string) $syn_element['q'];
          $results['synonyms'][] = $synonym;
        }
        foreach ($payload
          ->xpath('//R') as $res) {
          $result = array();

          // handy variants of the url for the result
          $result['abs_url'] = (string) $res->U;
          $result['enc_url'] = (string) $res->UE;

          // urlencoded URL of result
          $result['short_url'] = substr($result['abs_url'], 0, 80) . (strlen($result['abs_url']) > 80 ? '...' : '');

          // result info
          $result['title'] = (string) $res->T;
          $result['snippet'] = (string) $res->S;
          $result['crawl_date'] = (string) $res->FS['VALUE'];
          $result['level'] = isset($res['L']) ? (int) $res['L'] : 1;

          // result meta data
          // here we just collect the data from the device and leave implementing
          // display of meta data to the themer (use-case specific)
          // @see google-appliance-result.tpl.php
          $meta = array();
          foreach ($res
            ->xpath('./MT') as $mt) {
            $meta[(string) $mt['N']] = (string) $mt['V'];
          }
          $result['meta'] = $meta;

          // detect the mime type to allow themes to decorate with mime icons
          // @see google-appliance-result.tpl.php
          $result['mime']['type'] = (string) $res['MIME'];

          // collect
          $results['entry'][] = $result;
        }
      }
      drupal_alter('google_appliance_results', $results, $payload);
    }
  }
  return $results;
}