From 6431c8f93a769d3d68920f1735af0ed0cbf8c257 Mon Sep 17 00:00:00 2001 From: Jared Whiklo Date: Wed, 9 Jan 2019 14:59:28 -0600 Subject: [PATCH] Move GeminiClient to Crayfish Commons (#16) * Move GeminiClient to Crayfish-Commons * Add tests for findByUri * Identify and test the constructor and static creator * Fix indenting --- src/Client/GeminiClient.php | 232 ++++++++++++++++++++++++++ tests/Client/GeminiClientTest.php | 266 ++++++++++++++++++++++++++++++ 2 files changed, 498 insertions(+) create mode 100644 src/Client/GeminiClient.php create mode 100644 tests/Client/GeminiClientTest.php diff --git a/src/Client/GeminiClient.php b/src/Client/GeminiClient.php new file mode 100644 index 0000000..8053693 --- /dev/null +++ b/src/Client/GeminiClient.php @@ -0,0 +1,232 @@ +client = $client; + $this->log = $log; + } + + public static function create($base_url, LoggerInterface $log) + { + $trimmed = trim($base_url); + $with_trailing_slash = rtrim($trimmed, '/') . '/'; + return new GeminiClient( + new Client(['base_uri' => $with_trailing_slash]), + $log + ); + } + + /** + * Gets a pair of drupal/fedora urls for a UUID. + * @param $uuid + * @param $token + * + * @throws \GuzzleHttp\Exception\RequestException + * + * @return array|null + */ + public function getUrls( + $uuid, + $token = null + ) { + try { + if (empty($token)) { + $response = $this->client->get($uuid); + } else { + $response = $this->client->get($uuid, [ + 'headers' => [ + 'Authorization' => $token, + ], + ]); + } + + $this->log->debug("Gemini GET response", [ + 'uuid' => $uuid, + 'response' => $response, + ]); + + return json_decode($response->getBody(), true); + } catch (RequestException $e) { + if ($e->getResponse()->getStatusCode() == 404) { + return null; + } + + throw $e; + } + } + + /** + * Mints a new Fedora URL for a UUID. + * @param $uuid + * @param $token + * + * @throws \GuzzleHttp\Exception\RequestException + * + * @return string + */ + public function mintFedoraUrl( + $uuid, + $token = null + ) { + $headers = ['Content-Type' => 'text/plain']; + + if (!empty($token)) { + $headers['Authorization'] = $token; + } + + $response = $this->client->post('', [ + 'body' => $uuid, + 'headers' => $headers, + ]); + + $this->log->debug("Gemini POST response", [ + 'uuid' => $uuid, + 'response' => $response, + ]); + + return (string)$response->getBody(); + } + + /** + * Saves a pair of drupal/fedora urls for a UUID. + * @param $uuid + * @param $drupal + * @param $fedora + * @param $token + * + * @throws \GuzzleHttp\Exception\RequestException + * + * @return bool + */ + public function saveUrls( + $uuid, + $drupal, + $fedora, + $token = null + ) { + $body = json_encode(['drupal' => $drupal, 'fedora' => $fedora]); + + $headers = ['Content-Type' => 'application/json']; + + if (!empty($token)) { + $headers['Authorization'] = $token; + } + + $response = $this->client->put($uuid, [ + 'body' => $body, + 'headers' => $headers, + ]); + + $this->log->debug("Gemini PUT response", [ + 'uuid' => $uuid, + 'response' => $response, + ]); + + return true; + } + + /** + * Deletes a pair of drupal/fedora urls for a UUID. + * @param $uuid + * @param $token + * + * @throws \GuzzleHttp\Exception\RequestException + * + * @return bool + */ + public function deleteUrls( + $uuid, + $token = null + ) { + $headers = []; + + if (!empty($token)) { + $headers['Authorization'] = $token; + } + + $response = $this->client->delete($uuid, [ + 'headers' => $headers, + ]); + + $this->log->debug("Gemini DELETE response", [ + 'uuid' => $uuid, + 'response' => $response, + ]); + + return true; + } + + /** + * Find the URLs given one of them. + * @param $uri + * The Drupal or Fedora URI. + * @param null $token + * Authorization token. + * + * @return null|string[] + * + */ + public function findByUri( + $uri, + $token = null + ) { + $headers['X-Islandora-URI'] = $uri; + + if (!empty($token)) { + $headers["Authorization"] = $token; + } + + try { + $response = $this->client->get('by_uri', [ + 'headers' => $headers, + ]); + } catch (ClientException $e) { + // Got a 404 + $this->log->debug('Gemini findByURI 404 response', [ + 'uri' => $uri, + ]); + return null; + } + + $this->log->debug("Gemini findByURI response", [ + 'uri' => $uri, + 'response' => $response, + ]); + + return $response->getHeader('Location'); + } +} diff --git a/tests/Client/GeminiClientTest.php b/tests/Client/GeminiClientTest.php new file mode 100644 index 0000000..4fbaa29 --- /dev/null +++ b/tests/Client/GeminiClientTest.php @@ -0,0 +1,266 @@ +logger = new Logger('milliner'); + $this->logger->pushHandler(new NullHandler()); + } + + /** + * @covers ::getUrls + * @covers ::__construct + */ + public function testGetUrls() + { + $response = $this->prophesize(ResponseInterface::class); + $response->getBody()->willReturn('{"drupal" : "foo", "fedora": "bar"}'); + $response = $response->reveal(); + + $client = $this->prophesize(Client::class); + $client->get(Argument::any(), Argument::any())->willReturn($response); + $client = $client->reveal(); + + $gemini = new GeminiClient( + $client, + $this->logger + ); + + $out = $gemini->getUrls("abc123"); + $this->assertTrue( + $out['drupal'] == 'foo', + "Gemini client must return response unaltered. Expected 'foo' but received {$out['drupal']}" + ); + $this->assertTrue( + $out['fedora'] == 'bar', + "Gemini client must return response unaltered. Expected 'bar' but received {$out['fedora']}" + ); + + $out = $gemini->getUrls("abc123", "some_token"); + $this->assertTrue( + $out['drupal'] == 'foo', + "Gemini client must return response unaltered. Expected 'foo' but received {$out['drupal']}" + ); + $this->assertTrue( + $out['fedora'] == 'bar', + "Gemini client must return response unaltered. Expected 'bar' but received {$out['fedora']}" + ); + } + + /** + * @covers ::getUrls + */ + public function testGetUrlsReturnsEmptyArrayWhenNotFound() + { + $request = $this->prophesize(RequestInterface::class)->reveal(); + + $response = $this->prophesize(ResponseInterface::class); + $response->getStatusCode()->willReturn(404); + $response = $response->reveal(); + + $client = $this->prophesize(Client::class); + $client->get(Argument::any(), Argument::any())->willThrow( + new RequestException("Not Found", $request, $response) + ); + $client = $client->reveal(); + + $gemini = new GeminiClient( + $client, + $this->logger + ); + + $this->assertTrue( + empty($gemini->getUrls("abc123")), + "Gemini client must return empty array if not found" + ); + $this->assertTrue( + empty($gemini->getUrls("abc123", "some_token")), + "Gemini client must return empty array if not found" + ); + } + + /** + * @covers ::mintFedoraUrl + */ + public function testMintFedoraUrl() + { + $response = $this->prophesize(ResponseInterface::class); + $response->getBody()->willReturn("http://foo.com/bar"); + $response = $response->reveal(); + + $client = $this->prophesize(Client::class); + $client->post(Argument::any(), Argument::any())->willReturn($response); + $client = $client->reveal(); + + $gemini = new GeminiClient( + $client, + $this->logger + ); + + $url = $gemini->mintFedoraUrl("abc123"); + $this->assertTrue( + $url == "http://foo.com/bar", + "Gemini client must return response unaltered. Expected 'http://foo.com/bar' but received $url" + ); + + $url = $gemini->mintFedoraUrl("abc123", "some_token"); + $this->assertTrue( + $url == "http://foo.com/bar", + "Gemini client must return response unaltered. Expected 'http://foo.com/bar' but received $url" + ); + } + + /** + * @covers ::saveUrls + */ + public function testSaveUrls() + { + $client = $this->prophesize(Client::class)->reveal(); + + $gemini = new GeminiClient( + $client, + $this->logger + ); + + $out = $gemini->saveUrls("abc123", "foo", "bar"); + $this->assertTrue( + $out, + "Gemini client must return true on successful saveUrls(). Received $out" + ); + + $out = $gemini->saveUrls("abc123", "foo", "bar", "some_token"); + $this->assertTrue( + $out, + "Gemini client must return true on successful saveUrls(). Received $out" + ); + } + + /** + * @covers ::deleteUrls + */ + public function testDeleteUrls() + { + $client = $this->prophesize(Client::class)->reveal(); + + $gemini = new GeminiClient( + $client, + $this->logger + ); + + $out = $gemini->deleteUrls("abc123"); + $this->assertTrue( + $out, + "Gemini client must return true on successful deleteUrls(). Received $out" + ); + + $out = $gemini->deleteUrls("abc123", "some_token"); + $this->assertTrue( + $out, + "Gemini client must return true on successful deleteUrls(). Received $out" + ); + } + + /** + * @covers ::findByUri + */ + public function testGetByUriFailed() + { + $prophesize = $this->prophesize(Client::class); + + $request = new Request('GET', '/by_uri'); + $prophesize->get(Argument::any(), Argument::any()) + ->willThrow(new ClientException('Uri not found', $request)); + $client = $prophesize->reveal(); + + $gemini = new GeminiClient( + $client, + $this->logger + ); + + $out = $gemini->findByUri('blah'); + $this->assertNull( + $out, + "Gemini client must return null when 404 is returned." + ); + + $out = $gemini->findByUri('blah', 'some_token'); + $this->assertNull( + $out, + "Gemini client must return null when 404 is returned." + ); + } + + /** + * @covers ::findByUri + */ + public function testGetByUriOk() + { + $prophesize = $this->prophesize(Client::class); + + $prophesize->get(Argument::any(), Argument::any()) + ->willReturn(new Response( + 200, + ['Location' => 'some-uri'] + )); + $client = $prophesize->reveal(); + + $gemini = new GeminiClient( + $client, + $this->logger + ); + + $out = $gemini->findByUri('blah'); + $this->assertNotNull( + $out, + "Gemini client must return null when 404 is returned." + ); + + $out = $gemini->findByUri('blah', 'some_token'); + $this->assertNotNull( + $out, + "Gemini client must return null when 404 is returned." + ); + } + + /** + * @covers ::create + */ + public function testCreate() + { + $base_url = 'http://localhost:1234/example'; + $client = GeminiClient::create($base_url, $this->logger); + $this->assertTrue($client instanceof GeminiClient); + } +}