<?php
namespace Website\Widgets\GoogleSearch; use Moto; use Website\Widgets\GoogleSearch; class FrontendService extends Moto\Service\AbstractStaticService { protected static $_resourceName = ''; public static function doSearch() { $request = static::getRequest(); $token = trim((string) $request->getParam('token')); $payload = GoogleSearch\Service::parseToken($token); if (!is_array($payload)) { static::throwBadRequest(['token' => ['invalid']], ['$token' => $token]); } $engine = GoogleSearch\Service::getSearchEngine(Moto\Util::getValue($payload, 'params.engine')); if (!$engine) { static::throwBadRequest(['engine' => ['notExists']], ['$payload' => $payload, '$token' => $token]); } $searchQuery = Moto\Util::getValue($payload, 'query'); $searchQuery = (string) $searchQuery; $searchQuery = trim($searchQuery); if ($searchQuery === '') { static::throwBadRequest(['query' => ['isEmpty']], ['$payload' => $payload, '$token' => $token]); } $perPage = (int) Moto\Util::getValue($payload, 'params.perPage', 10); $params = [ 'start' => (int) Moto\Util::getValue($payload, 'params.start', 0), 'perPage' => Moto\Util::getValue($payload, 'params.perPage'), 'language' => Moto\Util::getValue($payload, 'params.language'), ]; $url = GoogleSearch\Service::generateApiUrl($engine, $payload['query'], $params); $cacheLifetime = (int) Moto\Util::getValue($payload, 'params.cacheLifetime'); $response = null; $cachedResponse = true; if ($cacheLifetime > 0) { $response = static::getCache($url, $cacheLifetime); } if (!$response) { $cachedResponse = false; $client = new Moto\Http\Client($url); $client->send(); $client->getAdapter()->close(); if ($client->hasErrors()) { throw new Moto\System\Exception('COMMON.ERROR.DOWNLOAD_FAILED', 500, $client->getErrors()); } $response = $client->getResponse()->getBody(); static::putCache($url, $response, $cacheLifetime); } if (!$response) { return null; } $response = json_decode($response, true); $results = Moto\Util::arrayOnly($response, ['searchInformation', 'items']); $pagination = null; $totalResults = (int) Moto\Util::getValue($response, 'searchInformation.totalResults'); $availableResults = min($totalResults, 100); if ($availableResults > $perPage) { $pagination = static::generatePagination(ceil($availableResults / $perPage), $payload); $results['pagination'] = $pagination; } return [ 'cached' => $cachedResponse, 'results' => $results, ]; } protected static function generatePagination($pageCount, $payload) { $searchQuery = $payload['query']; $perPage = $payload['params']['perPage']; $pagination = [ 'current' => (int) Moto\Util::getValue($payload, 'params.page', 1), 'pageCount' => $pageCount, 'first' => null, 'last' => null, 'pages' => [], ]; $params = $payload['params']; $params['page'] = 1; $params['start'] = 1; $pagination['first'] = [ 'number' => $params['page'], 'start' => $params['start'], 'token' => GoogleSearch\Service::generateToken($searchQuery, $params), ]; $params['page'] = $pageCount; $params['start'] = ($pageCount - 1) * $perPage + 1; $pagination['last'] = [ 'number' => $params['page'], 'start' => $params['start'], 'token' => GoogleSearch\Service::generateToken($searchQuery, $params), ]; for ($i = 0; $i < $pageCount; $i++) { $params['page'] = ($i + 1); $params['start'] = $i * $perPage + 1; $page = [ 'number' => $params['page'], 'start' => $params['start'], 'token' => GoogleSearch\Service::generateToken($searchQuery, $params), ]; $pagination['pages'][] = $page; } return $pagination; } protected static function throwBadRequest($errors, $env = null) { $errors = (array) $errors; if (Moto\System::isDevelopmentStage()) { $errors['$env'] = $env; } throw new Moto\System\Exception(Moto\System\Exception::ERROR_BAD_REQUEST_MESSAGE, Moto\System\Exception::ERROR_SESSION_EXPIRED_CODE, $errors); } protected static function getCacheFile($url) { $cacheKey = md5($url); return Moto\System::getAbsolutePath('@temp/google_search/' . substr($cacheKey, 0, 3) . '/' . $cacheKey . '.tmp.json'); } protected static function getCache($url, $cacheLifetime) { if ($cacheLifetime < 1) { return null; } $cacheFilePath = static::getCacheFile($url); if (!file_exists($cacheFilePath)) { return null; } $delta = abs(time() - filemtime($cacheFilePath)); if ($delta > ($cacheLifetime * 60) || !is_readable($cacheFilePath)) { @unlink($cacheFilePath); return null; } return file_get_contents($cacheFilePath); } protected static function putCache($url, $content, $cacheLifetime) { if ($cacheLifetime < 1) { return null; } $cacheFilePath = static::getCacheFile($url); if (is_array($content) || is_object($content)) { $content = json_encode($content); } return Moto\Util::filePutContents($cacheFilePath, $content); } } 