Compare commits
3
Commits
c4f5504fdf
...
1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fde9661c2c | ||
|
|
6f2fd40464 | ||
|
|
bcfeedc703 |
No files matched your search
@@ -635,10 +635,10 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
|
|||||||
*/
|
*/
|
||||||
public function get($coid) {
|
public function get($coid) {
|
||||||
if (is_string($coid))
|
if (is_string($coid))
|
||||||
return $this->getObject(new IRI($coid));
|
return $this->getObjectNode(new IRI($coid));
|
||||||
|
|
||||||
if (is_object($coid) && get_class($coid)=='ML\IRI\IRI')
|
if (is_object($coid) && get_class($coid)=='ML\IRI\IRI')
|
||||||
return $this->getObject($coid);
|
return $this->getObjectNode($coid);
|
||||||
|
|
||||||
throw new SDKException('COID must be passed as a string or an IRI object.');
|
throw new SDKException('COID must be passed as a string or an IRI object.');
|
||||||
}
|
}
|
||||||
@@ -650,7 +650,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
|
|||||||
* @param string $filename
|
* @param string $filename
|
||||||
*/
|
*/
|
||||||
public function getAttachment(IRI $coid, $filename) {
|
public function getAttachment(IRI $coid, $filename) {
|
||||||
$object = $this->getObject($coid);
|
$object = $this->getObjectNode($coid);
|
||||||
|
|
||||||
if (!$object)
|
if (!$object)
|
||||||
// Cannot get attachment for non-existing object
|
// Cannot get attachment for non-existing object
|
||||||
@@ -680,14 +680,35 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
|
|||||||
$this->putIntoCache($cacheId, $fileData, 0);
|
$this->putIntoCache($cacheId, $fileData, 0);
|
||||||
|
|
||||||
$this->logInfoWithTime('Fetched attachment <'.$filename.'> for <'.$object->getId().'> from Core API ['.$response->getStatusCode().'].', $ts);
|
$this->logInfoWithTime('Fetched attachment <'.$filename.'> for <'.$object->getId().'> from Core API ['.$response->getStatusCode().'].', $ts);
|
||||||
|
} catch (ConnectException $e) {
|
||||||
|
// connection failed or timed out
|
||||||
|
$this->logInfoWithTime('Attachment <'.$filename.'> for <'.$object->getId().'> could not be retrieved from Core API (connection failed).', $ts);
|
||||||
|
throw new CoreAPIException($e->getMessage(), $e);
|
||||||
|
} catch (RequestException $e) {
|
||||||
|
if ($e->hasResponse() && $e->getResponse()->getStatusCode() == 404) {
|
||||||
|
// not found (404)
|
||||||
|
$this->logInfoWithTime('Attachment <'.$filename.'> for <'.$object->getId().'> not found in Core API.', $ts);
|
||||||
|
return null;
|
||||||
|
} else
|
||||||
|
if ($e->hasResponse()) {
|
||||||
|
// other API error (4xx, 5xx)
|
||||||
|
$statusCode = $e->getResponse()->getStatusCode();
|
||||||
|
$this->logInfoWithTime('Attachment <'.$filename.'> for <'.$object->getId().'> could not be retrieved from Core API ['.$statusCode.'].', $ts);
|
||||||
|
throw new CoreAPIException($e->getMessage(), $e);
|
||||||
|
} else {
|
||||||
|
// API error without response
|
||||||
|
$this->logInfoWithTime('Attachment <'.$filename.'> for <'.$object->getId().'> could not be retrieved from Core API (no status code).', $ts);
|
||||||
|
throw new CoreAPIException($e->getMessage(), $e);
|
||||||
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->logInfoWithTime('Attachment <'.$filename.'> for <'.$object->getId().'> not found in Core API ['.$e->getResponse()->getStatusCode().'].', $ts);
|
// other exceptions
|
||||||
// ignore exception - treat as non-existing file
|
$this->logInfoWithTime('Attachment <'.$filename.'> for <'.$object->getId().'> could not be retrieved from Core API (unexpected exception).', $ts);
|
||||||
|
throw new CoreAPIException($e->getMessage(), $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $fileContent;
|
return $fileContent ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function assertAuthenticatingNamespaceAndGetId() : IRI {
|
private function assertAuthenticatingNamespaceAndGetId() : IRI {
|
||||||
@@ -709,7 +730,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
|
|||||||
* @return Node
|
* @return Node
|
||||||
*/
|
*/
|
||||||
public function getAuthenticatingNamespaceObject() : ?Node {
|
public function getAuthenticatingNamespaceObject() : ?Node {
|
||||||
return $this->getObject($this->assertAuthenticatingNamespaceAndGetId());
|
return $this->getObjectNode($this->assertAuthenticatingNamespaceAndGetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -719,7 +740,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
|
|||||||
* @return Node
|
* @return Node
|
||||||
*/
|
*/
|
||||||
public function getAuthenticatingNamespaceObjectNode() : ?Node {
|
public function getAuthenticatingNamespaceObjectNode() : ?Node {
|
||||||
return $this->getObject($this->assertAuthenticatingNamespaceAndGetId());
|
return $this->getObjectNode($this->assertAuthenticatingNamespaceAndGetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ class ObjectRetrieverMockTest extends \PHPUnit\Framework\TestCase {
|
|||||||
private $retriever;
|
private $retriever;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Response|\Throwable $response A response, or an exception to throw instead.
|
* @param Response|\Throwable ...$responses Responses in the order they are returned,
|
||||||
|
* or exceptions to throw instead.
|
||||||
*/
|
*/
|
||||||
private function setMockResponse($response) {
|
private function setMockResponse(...$responses) : MockHandler {
|
||||||
$mock = new MockHandler([$response]);
|
$mock = new MockHandler($responses);
|
||||||
$handler = HandlerStack::create($mock);
|
$handler = HandlerStack::create($mock);
|
||||||
$this->retriever->setClient(new Client(['handler' => $handler]));
|
$this->retriever->setClient(new Client(['handler' => $handler]));
|
||||||
|
return $mock;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setUp(): void {
|
protected function setUp(): void {
|
||||||
@@ -90,6 +92,58 @@ class ObjectRetrieverMockTest extends \PHPUnit\Framework\TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetAttachment() {
|
||||||
|
$mock = $this->setMockResponse(
|
||||||
|
new Response(200, ['Content-Type' => 'application/ld+json'],
|
||||||
|
'{"@id":"coid://cloudobjects.io/Test","coid://cloudobjects.io/isAtRevision":"1-abc"}'),
|
||||||
|
new Response(200, ['Content-Type' => 'text/plain'], 'Attachment content')
|
||||||
|
);
|
||||||
|
|
||||||
|
$content = $this->retriever->getAttachment(new IRI('coid://cloudobjects.io/Test'), 'file.txt');
|
||||||
|
$this->assertEquals('Attachment content', $content);
|
||||||
|
$this->assertStringEndsWith('cloudobjects.io/Test/file.txt', $mock->getLastRequest()->getUri()->getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetMissingAttachment() {
|
||||||
|
$this->setMockResponse(
|
||||||
|
new Response(200, ['Content-Type' => 'application/ld+json'],
|
||||||
|
'{"@id":"coid://cloudobjects.io/Test","coid://cloudobjects.io/isAtRevision":"1-abc"}'),
|
||||||
|
new Response(404)
|
||||||
|
);
|
||||||
|
|
||||||
|
$content = $this->retriever->getAttachment(new IRI('coid://cloudobjects.io/Test'), 'missing.txt');
|
||||||
|
$this->assertNull($content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWhenAPIThrowsErrorForAttachment() {
|
||||||
|
$this->setMockResponse(
|
||||||
|
new Response(200, ['Content-Type' => 'application/ld+json'],
|
||||||
|
'{"@id":"coid://cloudobjects.io/Test","coid://cloudobjects.io/isAtRevision":"1-abc"}'),
|
||||||
|
new Response(500)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->expectException(CoreAPIException::class);
|
||||||
|
$this->retriever->getAttachment(new IRI('coid://cloudobjects.io/Test'), 'file.txt');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWhenAPITimesOutForAttachment() {
|
||||||
|
$this->setMockResponse(
|
||||||
|
new Response(200, ['Content-Type' => 'application/ld+json'],
|
||||||
|
'{"@id":"coid://cloudobjects.io/Test","coid://cloudobjects.io/isAtRevision":"1-abc"}'),
|
||||||
|
new ConnectException(
|
||||||
|
'cURL error 28: Operation timed out',
|
||||||
|
new Request('GET', 'cloudobjects.io')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->retriever->getAttachment(new IRI('coid://cloudobjects.io/Test'), 'file.txt');
|
||||||
|
$this->fail('Expected CoreAPIException was not thrown.');
|
||||||
|
} catch (CoreAPIException $e) {
|
||||||
|
$this->assertInstanceOf(ConnectException::class, $e->getPrevious());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function createFallbackStoreDirectory() : string {
|
private function createFallbackStoreDirectory() : string {
|
||||||
$directory = sys_get_temp_dir().DIRECTORY_SEPARATOR.'clobj-fallback-'.uniqid();
|
$directory = sys_get_temp_dir().DIRECTORY_SEPARATOR.'clobj-fallback-'.uniqid();
|
||||||
mkdir($directory);
|
mkdir($directory);
|
||||||
|
|||||||
@@ -51,4 +51,34 @@ class ObjectRetrieverCacheTest extends \PHPUnit\Framework\TestCase {
|
|||||||
$this->assertEquals($object2->getRevision(), $object3->getRevision());
|
$this->assertEquals($object2->getRevision(), $object3->getRevision());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAttachmentCacheInRuntimeStorage() {
|
||||||
|
$cacheStorage = new VolatileRuntimeStorage;
|
||||||
|
$logger = new InMemoryLogger;
|
||||||
|
|
||||||
|
$coid = new IRI('coid://cloudobjects.io/Test');
|
||||||
|
$cacheId = (string)$coid.'#file.txt';
|
||||||
|
|
||||||
|
$retriever = new ObjectRetriever([
|
||||||
|
'cache_storage' => $cacheStorage,
|
||||||
|
'logger' => $logger
|
||||||
|
]);
|
||||||
|
|
||||||
|
$content1 = $retriever->getAttachment($coid, 'file.txt');
|
||||||
|
|
||||||
|
$this->assertEquals('Test file content', trim($content1));
|
||||||
|
$this->assertNotNull($cacheStorage->fetch($retriever->getCacheKey($cacheId)));
|
||||||
|
$this->assertStringContainsString('from Core API', $logger->getLastLogMessage());
|
||||||
|
|
||||||
|
// Reinitialize retriever with same cache storage to verify that cache is used
|
||||||
|
$retriever = new ObjectRetriever([
|
||||||
|
'cache_storage' => $cacheStorage,
|
||||||
|
'logger' => $logger
|
||||||
|
]);
|
||||||
|
|
||||||
|
$content2 = $retriever->getAttachment($coid, 'file.txt');
|
||||||
|
|
||||||
|
$this->assertEquals('Test file content', trim($content2));
|
||||||
|
$this->assertStringContainsString('from object cache', $logger->getLastLogMessage());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -33,6 +33,15 @@ class ObjectRetrieverPublicTest extends \PHPUnit\Framework\TestCase {
|
|||||||
$this->assertEquals('CloudObjects', $object->getProperty('http://www.w3.org/2000/01/rdf-schema#label')->getValue());
|
$this->assertEquals('CloudObjects', $object->getProperty('http://www.w3.org/2000/01/rdf-schema#label')->getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetTestObject() {
|
||||||
|
$coid = new IRI('coid://cloudobjects.io/Test');
|
||||||
|
$object = $this->retriever->getObjectNode($coid);
|
||||||
|
$this->assertNotNull($object);
|
||||||
|
$this->assertEquals((string)$coid, $object->getId());
|
||||||
|
$this->assertNotNull($object->getProperty('http://www.w3.org/2000/01/rdf-schema#label'));
|
||||||
|
$this->assertEquals('Test Object', $object->getProperty('http://www.w3.org/2000/01/rdf-schema#label')->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
public function testGetRelatedObject() {
|
public function testGetRelatedObject() {
|
||||||
$coid = new IRI('coid://cloudobjects.io');
|
$coid = new IRI('coid://cloudobjects.io');
|
||||||
$object = $this->retriever->getCloudObject($coid);
|
$object = $this->retriever->getCloudObject($coid);
|
||||||
|
|||||||
Reference in new issue
Block a user