View source
<?php
namespace Drupal\google_appliance\Service;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\google_appliance\SearchResults\KeyMatch;
use Drupal\google_appliance\SearchResults\OneBoxResult;
use Drupal\google_appliance\SearchResults\OneBoxResultSet;
use Drupal\google_appliance\SearchResults\ResultSet;
use Drupal\google_appliance\SearchResults\Result;
use Drupal\google_appliance\SearchResults\Synonym;
use SimpleXMLElement;
class Parser implements ParserInterface {
protected $response;
protected $moduleHandler;
public function __construct(ModuleHandlerInterface $moduleHandler) {
$this->moduleHandler = $moduleHandler;
}
public function parseResponse($xml, $useCached = TRUE) {
if (!$this->response || FALSE === $useCached) {
$response = new ResultSet();
libxml_use_internal_errors(TRUE);
$payload = simplexml_load_string($xml);
if ($payload === FALSE) {
$errors = [];
foreach (libxml_get_errors() as $error) {
$response
->addError($error->message);
}
}
else {
$response
->setLastResult((int) $payload->RES['EN']);
$this
->parseResultCount($payload, $response);
if (!$response
->getTotal()) {
$response
->addError('No results', ResultSet::ERROR_NO_RESULTS);
$this->response = $response;
return $this->response;
}
if (isset($payload->Spelling->Suggestion)) {
$spelling_suggestion = (string) $payload->Spelling->Suggestion;
$response
->addSpellingSuggestion(Xss::filter($spelling_suggestion, [
'b',
'i',
]));
}
$this
->parseOneboxResults($payload, $response);
foreach ($payload
->xpath('//GM') as $km) {
$keymatch = new KeyMatch((string) $km->GD, (string) $km->GL);
$response
->addKeyMatch($keymatch);
}
foreach ($payload
->xpath('//OneSynonym') as $syn_element) {
$synonym = new Synonym((string) $syn_element, (string) $syn_element['q']);
$response
->addSynonym($synonym);
}
$this
->parseResultEntries($payload, $response);
$this->moduleHandler
->alter('google_appliance_results', $results, $payload);
$this->response = $response;
}
}
return $this->response;
}
protected function parseResultCount(SimpleXMLElement $payload, ResultSet $response) {
$response
->setTotal((int) $payload->RES->M);
if (isset($payload->RES) && !$response
->getTotal()) {
$response
->setTotal((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 ($response
->getTotal() === $request_max_total) {
$response
->setTotal($response
->getTotal() + 1);
}
}
}
protected function parseResultEntries(SimpleXMLElement $payload, ResultSet $response) {
foreach ($payload
->xpath('//R') as $res) {
$result = new Result((string) $res->U, (string) $res->UE, (string) $res->T, (string) $res->S, (string) $res->FS['VALUE'], (string) $res['MIME'], isset($res['L']) ? (int) $res['L'] : 1);
foreach ($res
->xpath('./MT') as $mt) {
$result
->addMeta((string) $mt['N'], (string) $mt['V']);
}
$response
->addResult($result);
}
}
protected function parseOneboxResults(SimpleXMLElement $payload, ResultSet $response) {
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 = new OneBoxResultSet($module_name, (string) $mod->provider, (string) $mod->title->urlText, (string) $mod->title->urlLink, (string) $mod->IMAGE_SOURCE, $mod->description);
foreach ($mod
->xpath('./MODULE_RESULT') as $res) {
$result = new OneBoxResult((string) $res->U, (string) $res->Title);
foreach ($res
->xpath('./Field') as $field) {
$field_name = (string) $field['name'];
$result
->addFieldValue($field_name, (string) $field);
}
$onebox
->addResult($result);
}
$response
->addOneBoxResultSet($module_name, $onebox);
}
}
}
}