diff --git a/src/Client.php b/src/Client.php index ac56494..81f45a7 100644 --- a/src/Client.php +++ b/src/Client.php @@ -4,7 +4,6 @@ use GuzzleHttp\Client as HttpClient; use OramaCloud\Client\Query; -use OramaCloud\Telemetry\Collector; use OramaCloud\Traits\GeneratesUniqueId; use OramaCloud\Traits\ValidatesParams; @@ -24,31 +23,17 @@ public function __construct(array $params, HttpClient $http = null) { $params = $this->validate($params, [ 'api_key' => ['required', 'string'], - 'endpoint' => ['required', 'string'], - 'telemetry' => ['optional', 'boolean'], - 'answersApiBaseURL' => ['optional', 'string'] + 'endpoint' => ['required', 'string'] ]); $this->id = $this->generateUniqueId(); $this->http = !is_null($http) ? $http : new HttpClient(); $this->apiKey = $params['api_key']; $this->endpoint = $params['endpoint']; - $this->answersApiBaseURL = $params['answersApiBaseURL']; - - // Telemetry is enabled by default - if ($params['telemetry'] !== false) { - $this->collector = Collector::create([ - 'id' => $this->id, - 'api_key' => $this->apiKey - ], $this->http); - } - - $this->init(); } public function search(Query $query) { - $startTime = microtime(true); $endpoint = "{$this->endpoint}/search?api-key={$this->apiKey}"; $response = $this->http->request('POST', $endpoint, [ 'form_params' => [ @@ -58,62 +43,6 @@ public function search(Query $query) $results = json_decode($response->getBody()->getContents(), true); - $endTime = microtime(true); - $roundTripTime = ($endTime - $startTime) * 1000; - - if ($this->collector !== null) { - $this->collector->add([ - 'rawSearchString' => $query->toArray()['term'], - 'resultsCount' => $results['count'] ?? 0, - 'roundTripTime' => $roundTripTime, - 'query' => $query->toJson(), - 'cached' => false, - 'searchedAt' => time() - ]); - } - return $results; } - - private function init() - { - $response = $this->fetch('init', 'POST'); - $response = json_decode($response, true); - - if ( - $this->collector !== null && - isset($response['collectUrl']) && - isset($response['deploymentID']) && - isset($response['index']) - ) { - $this->collector->setParams( - $response['collectUrl'], - $response['deploymentID'], - $response['index'] - ); - } - } - - private function fetch($path, $method, $body = []) - { - $endpoint = "{$this->endpoint}/{$path}?api-key={$this->apiKey}"; - - $requestOptions = [ - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded' - ] - ]; - - if ($method === 'POST' && $body !== []) { - $b = $body; - $b['version'] = 'php-sdk-1.0.0'; - $b['id'] = $this->id; - - $requestOptions['body'] = http_build_query($body); - } - - $response = $this->http->request('POST', $endpoint, $requestOptions); - - return $response->getBody(); - } } diff --git a/src/Client/Query.php b/src/Client/Query.php index bca3d7d..ebf7d17 100644 --- a/src/Client/Query.php +++ b/src/Client/Query.php @@ -21,14 +21,18 @@ public function __construct($term = '', $mode = 'fulltext') $this->mode = $mode; } - public function term($term) + public function term(string $term) { $this->term = $term; return $this; } - public function mode($mode) + public function mode(string $mode) { + if (!in_array($mode, ['fulltext', 'vector', 'hybrid'])) { + throw new QueryException('Invalid search mode. Must be one of: fulltext, vector, hybrid.'); + } + $this->mode = $mode; return $this; } diff --git a/src/Client/QueryException.php b/src/Client/QueryException.php new file mode 100644 index 0000000..fb2fe40 --- /dev/null +++ b/src/Client/QueryException.php @@ -0,0 +1,11 @@ +client = $http; - $this->data = []; - $this->config = [ - 'id' => $id, - 'api_key' => $apiKey - ]; - } - - public function setParams($endpoint, $deploymentID, $indexID) - { - $this->params = [ - 'endpoint' => $endpoint, - 'deploymentID' => $deploymentID, - 'index' => $indexID - ]; - } - - public static function create($config, Client $http) - { - if (!isset($config['id']) || !isset($config['api_key'])) { - throw new \InvalidArgumentException('The id and api_key parameters are required.'); - } - - $collector = new Collector($config['id'], $config['api_key'], $http); - - $collector->start(); - - return $collector; - } - - public function add($data) - { - $this->data[] = $data; - - $this->flush(); - } - - public function flush() - { - if ($this->params == null || count($this->data) === 0) { - return null; - } - - $data = $this->data; - $this->data = []; - - $body = [ - 'source' => 'be', - 'deploymentID' => $this->params['deploymentID'], - 'index' => $this->params['index'], - 'oramaId' => $this->config['id'], - 'oramaVersion' => 'php-sdk-1.0.0', - 'userAgent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null, - 'events' => $data - ]; - - return $this->sendBeacon($body); - } - - private function start() - { - $this->flush(); - } - - private function sendBeacon($body) - { - if ($this->params == null || !isset($this->params['endpoint'])) { - return null; - } - - $url = $this->params['endpoint'] . '?api-key=' . $this->config['api_key']; - - return $this->client->requestAsync('POST', $url, [ - 'form_params' => $body - ]); - } -} diff --git a/tests/Feature/ClientTest.php b/tests/Feature/ClientTest.php index e9e7ae6..20fffa4 100644 --- a/tests/Feature/ClientTest.php +++ b/tests/Feature/ClientTest.php @@ -15,35 +15,42 @@ class ClientTest extends TestCase const API_ENDPOINT = 'mock-endpoint'; const PUBLIC_API_KEY = 'mock-api-key'; - public function testBasicFulltextSearch() + protected $capturedRequests; + protected $httpClient; + + protected function setUp(): void { - // Create a mock handler and queue a response. - $mock = new MockHandler([ - // initial request to get the collect URL - new Response(200, [], json_encode([ - 'collectUrl' => 'mock-url', - 'deploymentID' => 'mock-deployment-id', - 'index' => 'mock-index', - ])), + // Reset capturedRequests before each test + $this->capturedRequests = []; + + // Middleware to capture requests + $captureMiddleware = function ($handler) { + return function ($request, $options) use ($handler) { + $this->capturedRequests[] = $request; + return $handler($request, $options); + }; + }; + + $mockResponse = new MockHandler([ // search request new Response(200, [], json_encode([ 'hits' => [['id' => 2]], 'elapsed' => 0.2, 'count' => 1, - ])), - // telemetry data collection - new Response(200, [], json_encode([ - 'message' => 'Telemetry data collected successfully', - ])), + ])) ]); - $handlerStack = HandlerStack::create($mock); - $mockClient = new GuzzleClient(['handler' => $handlerStack]); + $handlerStack = HandlerStack::create($mockResponse); + $handlerStack->push($captureMiddleware, 'capture_middleware'); + $this->httpClient = new GuzzleClient(['handler' => $handlerStack]); + } + public function testBasicFulltextSearch() + { $client = new Client([ 'api_key' => self::PUBLIC_API_KEY, 'endpoint' => self::API_ENDPOINT, - ], $mockClient); + ], $this->httpClient); $result = $client->search( (new Query()) @@ -58,5 +65,9 @@ public function testBasicFulltextSearch() $this->assertGreaterThan(0, $result['count']); $this->assertLessThanOrEqual(10, count($result['hits'])); + + $lastRequest = end($this->capturedRequests); + $this->assertEquals('POST', $lastRequest->getMethod()); + $this->assertEquals(self::API_ENDPOINT . '/search', $lastRequest->getUri()->getPath()); } } diff --git a/tests/Unit/QueryTest.php b/tests/Unit/QueryTest.php index abae670..9e20e42 100644 --- a/tests/Unit/QueryTest.php +++ b/tests/Unit/QueryTest.php @@ -51,7 +51,7 @@ public function testQueryParamsFromArray() { $params = [ 'term' => 'mock-term', - 'mode' => 'mock-mode', + 'mode' => 'vector', 'where' => [ 'foo' => [ 'eq' => 99