View source
<?php
namespace Drupal\google_cse;
use Drupal\Core\Extension\ModuleHandler;
use Drupal\Core\Language\LanguageManager;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\Renderer;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Pager\PagerManagerInterface;
class GoogleCSEServices implements ContainerFactoryPluginInterface {
const GOOGLE_MAX_SEARCH_RESULTS = 1000;
private $requestStack;
private $CSEconfig;
private $languageManager;
private $renderer;
private $moduleHandler;
private $pagerManager;
public function __construct(RequestStack $requestStack, ConfigFactoryInterface $configFactory, LanguageManager $languageManager, Renderer $renderer, ModuleHandler $moduleHandler, PagerManagerInterface $pagerManager) {
$this->requestStack = $requestStack;
$this->CSEconfig = $configFactory
->get('search.page.google_cse_search');
$this->languageManager = $languageManager;
$this->renderer = $renderer;
$this->moduleHandler = $moduleHandler;
$this->pagerManager = $pagerManager;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('request_stack'), $container
->get('config.factory'), $container
->get('language_manager'), $container
->get('renderer'), $container
->get('module_handler'), $container
->get('pager.manager'));
}
public function service($keys, $offset = 0) {
$page = 0;
$response = [];
if ($this->requestStack
->getCurrentRequest()->query
->has('page')) {
$page = $this->requestStack
->getCurrentRequest()->query
->get('page');
}
if (isset($response[$keys])) {
return $response[$keys];
}
$rows = (int) $this->CSEconfig
->get('configuration')['google_cse_adv_results_per_page'];
$query = [
'cx' => $this->CSEconfig
->get('configuration')['cx'],
'client' => 'google-csbe',
'output' => 'xml_no_dtd',
'filter' => '1',
'hl' => $this
->paramhl(),
'lr' => $this
->paramlr(),
'q' => $keys,
'num' => $rows,
'start' => $offset ? $offset : $page * $rows,
'as_sitesearch' => $this->CSEconfig
->get('configuration')['limit_domain'],
];
if ($this->requestStack
->getCurrentRequest()->query
->has('more')) {
$query['+more:'] = urlencode($this->requestStack
->getCurrentRequest()->query
->get('more'));
}
$url = Url::fromUri($this
->getProtocol() . 'www.google.com/cse', [
'query' => $query,
]);
$response = $this
->getResponse($url
->toString());
return $response;
}
public function paramhl() {
$language = $this->CSEconfig
->get('configuration')['google_cse_adv_language'];
switch ($language) {
case 'active':
$language = $this->languageManager
->getCurrentLanguage();
return $language
->getId();
default:
return '';
}
}
public function getProtocol() {
$request = \Drupal::request();
return $request
->isSecure() == TRUE ? 'https://' : 'http://';
}
public function paramlr() {
switch ($this->CSEconfig
->get('configuration')['google_cse_adv_language']) {
case 'active':
$language = $this->languageManager
->getCurrentLanguage();
return 'lang_' . $language
->getId();
default:
return '';
}
}
public function getResponse($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
if ($this->moduleHandler
->moduleExists('proxy_settings') && ($proxy_host = proxy_settings_host('google_cse_adv'))) {
if ($proxy_port = proxy_settings_port('google_cse_adv')) {
curl_setopt($curl, CURLOPT_PROXY, $proxy_host . ':' . $proxy_port);
}
else {
curl_setopt($curl, CURLOPT_PROXY, $proxy_host);
}
if ($user = proxy_settings_username('google_cse_adv') && ($password = proxy_settings_password('google_cse_adv'))) {
curl_setopt($curl, CURLOPT_PROXYUSERPWD, $user . ':' . $password);
}
}
$response[] = curl_exec($curl);
curl_close($curl);
return $response;
}
protected function thumbnail($title, array $image_att) {
if ($this->CSEconfig
->get('configuration')['results_display_images']) {
$image = [
'type' => 'image',
'path' => isset($image_att['value']) ? $image_att['value'] : '',
'alt' => $title,
'title' => $title,
'attributes' => [
'width' => '100px',
],
'getsize' => FALSE,
];
return $this->renderer
->render($image);
}
return '';
}
public function responseResults($response, $keys, $conditions) {
$xml = simplexml_load_string($response);
$results = [];
$total = 0;
if (isset($xml->RES->R)) {
$max_results = $this->CSEconfig
->get('configuration')['google_cse_adv_maximum_results'];
$total = (int) $xml->RES->M;
$xml->RES->M_ORIGINAL = $total;
if (!$this
->isAccurateResult($response)) {
$total = $this
->getAccurateResultsCount($keys, $total);
}
if ($total > $max_results) {
$xml->RES->M = $total = $max_results;
}
foreach ($xml->RES->R as $result) {
$title = $this
->cleanString((string) $result->T);
if ($result->PageMap) {
$att = $result->PageMap->DataObject
->attributes();
switch ($att['type']) {
case "cse_image":
$image_att = $result->PageMap->DataObject->Attribute
->attributes();
$text_snippet = $this
->cleanString((string) $result->S);
$snippet = $this
->thumbnail($title, $image_att) . $text_snippet;
$extra = $this
->cleanString((string) $result->U);
$extra = parse_url($extra);
$extra = $extra['host'];
break;
case "metatags":
$snippet = $this
->cleanString((string) $result->S);
$extra = $this
->cleanString(Html::escape((string) $result->U));
$extra = parse_url($extra);
$extra = $extra['host'] . " | Document";
break;
}
}
else {
if ($result->SL_RESULTS) {
$snippet = strip_tags((string) $result->SL_RESULTS->SL_MAIN->BODY_LINE->BLOCK->T);
}
else {
$snippet = (string) $result->S;
}
$snippet = $this
->cleanString($snippet);
$extra = $this
->cleanString(Html::escape((string) $result->U));
$extra = parse_url($extra);
$extra = $extra['host'];
}
$results[] = [
'link' => (string) $result->U,
'title' => $title,
'snippet' => $snippet,
'keys' => Html::escape($keys),
'extra' => [
$extra,
],
'date' => NULL,
];
}
$limit = $this->CSEconfig
->get('configuration')['google_cse_adv_results_per_page'];
$this->pagerManager
->createPager($total, $limit);
}
$this->moduleHandler
->alter('google_cse_num_results', $total);
return $results;
}
public function isAccurateResult($response) {
$accurate = FALSE;
$xml = simplexml_load_string($response);
if (isset($xml->RES->XT)) {
$accurate = TRUE;
}
return $accurate;
}
public function getAccurateResultsCount($keys, $total) {
$total_num_results = 0;
$this->moduleHandler
->alter('google_cse_searched_keys', $keys);
$offset = self::GOOGLE_MAX_SEARCH_RESULTS - $this->CSEconfig
->get('configuration')['google_cse_adv_results_per_page'];
$response = $this
->service($keys, $offset);
$xml = simplexml_load_string($response[0]);
if (isset($xml->RES)) {
$attributes = $xml->RES
->attributes();
$total_num_results += (int) $attributes['EN'];
}
if (!$total_num_results) {
$total_num_results = $total;
}
return $total_num_results;
}
public function cleanString($input_str) {
$cleaned_str = $input_str;
if (function_exists('htmlspecialchars_decode')) {
$cleaned_str = htmlspecialchars_decode($input_str, ENT_QUOTES);
}
$cleaned_str = strip_tags($cleaned_str);
return $cleaned_str;
}
public function siteSearchForm(&$form) {
if ($options = $this
->sitesearchOptions()) {
$form['sitesearch'] = [
'#type' => $this->CSEconfig
->get('sitesearch_form'),
'#options' => $options,
'#default_value' => $this
->sitesearchDefault(),
];
if ($form['sitesearch']['#type'] == 'select' && isset($form['sa'])) {
$form['sa']['#weight'] = 10;
}
}
}
public function sitesearchOptions() {
static $options;
if (!isset($options)) {
$options = [];
if ($sites = preg_split('/[\\n\\r]+/', $this->CSEconfig
->get('configuration')['sitesearch'], -1, PREG_SPLIT_NO_EMPTY)) {
$options[''] = ($var = $this->CSEconfig
->get('configuration')['sitesearch_option']) ? $var : t('Search the web');
foreach ($sites as $site) {
$site = preg_split('/[\\s]+/', trim($site), 2, PREG_SPLIT_NO_EMPTY);
$options[$site[0]] = isset($site[1]) ? $site[1] : t('Search %sitesearch', [
'%sitesearch' => $site[0],
]);
}
}
}
return $options;
}
public function sitesearchDefault() {
$options = $this
->sitesearchOptions();
if ($this->requestStack
->getCurrentRequest()->query
->has('sitesearch') && isset($options[$this->requestStack
->getCurrentRequest()->query
->get('sitesearch')])) {
return $this->requestStack
->getCurrentRequest()->query
->get('sitesearch');
}
elseif ($this->CSEconfig
->get('configuration')['sitesearch_default']) {
return key(array_slice($options, 1, 1));
}
return '';
}
public function advancedSettings() {
$language = $this->languageManager
->getCurrentLanguage()
->getId();
$settings = [];
foreach ([
'cr',
'gl',
'hl',
'ie',
'lr',
'oe',
'safe',
] as $parameter) {
if ($setting = $this->CSEconfig
->get('configuration')[$parameter]) {
$settings[$parameter] = $setting;
}
}
if ($this->CSEconfig
->get('configuration')['locale_hl']) {
$settings['hl'] = $language;
}
if ($this->CSEconfig
->get('configuration')['locale_lr']) {
$settings['lr'] = 'lang_' . $language;
}
return $settings;
}
}