Compare commits

16 Commits

Author SHA1 Message Date
5f5a31df68 Improved cache reading 2026-06-01 17:45:55 +00:00
58585a6875 Fixed copy&paste error in README 2026-05-26 15:39:03 +00:00
23f00b2374 Remove outdated doctrine/cache package and change configuration 2026-05-26 15:38:15 +00:00
9f339953fe Fixed Buddy badge 2026-05-15 14:46:22 +00:00
d5d766cbf4 Added getRevision() helper function, refactored revision constant 2026-05-15 14:06:15 +00:00
06df8b0be1 Use new API endpoint URL 2026-05-15 11:24:21 +00:00
de355ff2f9 Added a has() method to CloudObject 2026-05-15 11:22:15 +00:00
7d8ece0df1 Set visibility of getReader to allow inheritance 2026-05-15 11:20:41 +00:00
1122b9faf5 Implemented getObjectNode as well, renamed other function for consistency 2026-05-15 10:58:54 +00:00
0cb2655494 Add retriever to CloudObject and allow retrieval of related objects 2026-05-15 10:54:39 +00:00
a9689d5a2b Extend and reformat tests 2026-05-15 10:41:38 +00:00
6cb8a9d603 Added default reader functionality 2026-05-15 10:41:25 +00:00
4724c4988e Make setReader fluent 2026-05-15 10:39:42 +00:00
bb738a1d79 Replace deprecated getObject with getObjectNode 2026-05-15 10:05:41 +00:00
fd029a79bf Ignore bash and phpUnit files 2026-05-15 09:49:16 +00:00
2954d9fc99 Remove phpUnit cache from version control 2026-05-15 09:48:38 +00:00
18 changed files with 569 additions and 652 deletions

2
.gitignore vendored
View File

@@ -6,3 +6,5 @@ cache
.local .local
*.phar *.phar
.composer .composer
.phpunit*
.bash_history

File diff suppressed because one or more lines are too long

View File

@@ -19,7 +19,8 @@ class CloudObject {
private $coid; private $coid;
private $node; private $node;
private $reader; private $reader = null;
private $retriever = null;
public function __construct(IRI $coid, Node $node) { public function __construct(IRI $coid, Node $node) {
Assert::eq((string)$coid, $node->getId(), "COID and Node ID must match."); Assert::eq((string)$coid, $node->getId(), "COID and Node ID must match.");
@@ -32,17 +33,33 @@ class CloudObject {
* Specify a custom NodeReader to use for this CloudObject. * Specify a custom NodeReader to use for this CloudObject.
* If not set, a default NodeReader will be used. * If not set, a default NodeReader will be used.
*/ */
public function setReader(NodeReader $reader) { public function setReader(NodeReader $reader) : self {
$this->reader = $reader; $this->reader = $reader;
return $this;
} }
private function getReader() { /**
* Get the NodeReader used for this CloudObject.
* Returns a default NodeReader if non has been set.
*/
protected function getReader() : NodeReader {
if (!$this->reader) { if (!$this->reader) {
$this->reader = new NodeReader; $this->reader = new NodeReader;
} }
return $this->reader; return $this->reader;
} }
/**
* Specify an ObjectRetriever to use for retrieval
* of related objects.
*/
public function setObjectRetriever(ObjectRetriever $retriever) : self {
$this->retriever = $retriever;
return $this;
}
/** /**
* Get the COID of this object. * Get the COID of this object.
*/ */
@@ -51,12 +68,19 @@ class CloudObject {
} }
/** /**
* Get the raw object node. * Get the object node encapsulated in this CloudObject.
*/ */
public function getObjectNode() : Node { public function getAsNode() : Node {
return $this->node; return $this->node;
} }
/**
* Checks if a property exists on this object.
*/
public function has($property) : bool {
return $this->getReader()->hasProperty($this->node, $property);
}
/** /**
* Get the value of a property as a string. * Get the value of a property as a string.
* If the property has multiple values, only the first is returned. * If the property has multiple values, only the first is returned.
@@ -105,4 +129,41 @@ class CloudObject {
return $this->getReader()->getFirstValueNode($this->node, $property, $default); return $this->getReader()->getFirstValueNode($this->node, $property, $default);
} }
/**
* Get the value of a property and, if it's a COID, retrieve the corresponding CloudObject.
*/
public function getCloudObject($property) : ?CloudObject {
Assert::notNull($this->retriever, "No ObjectRetriever set for CloudObject. Cannot retrieve related object.");
$coid = $this->getReader()->getFirstValueIRI($this->node, $property);
if (!($coid instanceof IRI)) {
return null;
}
return $this->retriever->getCloudObject($coid);
}
/**
* Get the value of a property and, if it's a COID, retrieve the corresponding object node.
*/
public function getObjectNode($property) : ?Node {
Assert::notNull($this->retriever, "No ObjectRetriever set for CloudObject. Cannot retrieve related object.");
$coid = $this->getReader()->getFirstValueIRI($this->node, $property);
if (!($coid instanceof IRI)) {
return null;
}
return $this->retriever->getObjectNode($coid);
}
/**
* Get the revision of the object.
*/
public function getRevision() : string {
return $this->getString(Constants::PROPERTY_REVISION);
}
} }

View File

@@ -59,7 +59,7 @@ class CryptoHelper {
$this->objectRetriever = $objectRetriever; $this->objectRetriever = $objectRetriever;
$this->namespace = isset($namespaceCoid) $this->namespace = isset($namespaceCoid)
? $objectRetriever->getObject($namespaceCoid) ? $objectRetriever->getObjectNode($namespaceCoid)
: $objectRetriever->getAuthenticatingNamespaceObject(); : $objectRetriever->getAuthenticatingNamespaceObject();
$this->reader = new NodeReader([ $this->reader = new NodeReader([

View File

@@ -0,0 +1,13 @@
<?php
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
namespace CloudObjects\SDK;
class Constants {
const PROPERTY_REVISION = 'coid://cloudobjects.io/isAtRevision';
}

View File

@@ -0,0 +1,14 @@
<?php
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
namespace CloudObjects\SDK\Exceptions;
/**
* An Exception that is thrown when the SDK's configuration isn't valid.
*/
class InvalidSDKConfigurationException extends \Exception {
}

View File

@@ -50,7 +50,7 @@ class SharedSecretAuthentication {
return self::RESULT_INVALID_PASSWORD; return self::RESULT_INVALID_PASSWORD;
// Retrieve namespace // Retrieve namespace
$namespace = $retriever->getObject($namespaceCoid); $namespace = $retriever->getObjectNode($namespaceCoid);
if (!isset($namespace)) if (!isset($namespace))
return self::RESULT_NAMESPACE_NOT_FOUND; return self::RESULT_NAMESPACE_NOT_FOUND;
@@ -87,7 +87,7 @@ class SharedSecretAuthentication {
return self::RESULT_INVALID_PASSWORD; return self::RESULT_INVALID_PASSWORD;
// Retrieve namespace // Retrieve namespace
$namespace = $this->objectRetriever->getObject($namespaceCoid); $namespace = $this->objectRetriever->getObjectNode($namespaceCoid);
if (!isset($namespace)) if (!isset($namespace))
return self::RESULT_NAMESPACE_NOT_FOUND; return self::RESULT_NAMESPACE_NOT_FOUND;

View File

@@ -68,7 +68,7 @@ class SchemaValidator {
* @param Node $node The COID of the specification. * @param Node $node The COID of the specification.
*/ */
public function validateAgainstCOID($data, IRI $coid) { public function validateAgainstCOID($data, IRI $coid) {
$object = $this->objectRetriever->getObject($coid); $object = $this->objectRetriever->getObjectNode($coid);
Assert::true($this->reader->hasType($object, 'json:Element'), Assert::true($this->reader->hasType($object, 'json:Element'),
"You can only validate data against JSON elements!"); "You can only validate data against JSON elements!");
$this->validateAgainstNode($data, $object); $this->validateAgainstNode($data, $object);

View File

@@ -6,15 +6,23 @@
namespace CloudObjects\SDK; namespace CloudObjects\SDK;
use Exception; use DateTime, Exception;
use ML\IRI\IRI, ML\JsonLD\JsonLD; use ML\IRI\IRI, ML\JsonLD\JsonLD;
use Doctrine\Common\Cache\RedisCache;
use Psr\Log\LoggerInterface, Psr\Log\LoggerAwareTrait; use Psr\Log\LoggerInterface, Psr\Log\LoggerAwareTrait;
use GuzzleHttp\ClientInterface, GuzzleHttp\Client, GuzzleHttp\HandlerStack; use GuzzleHttp\ClientInterface, GuzzleHttp\Client, GuzzleHttp\HandlerStack;
use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\RequestException;
use Kevinrob\GuzzleCache\CacheMiddleware, Kevinrob\GuzzleCache\Storage\DoctrineCacheStorage; use GuzzleHttp\Psr7\Request,
GuzzleHttp\Psr7\Response;
use Kevinrob\GuzzleCache\CacheMiddleware;
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy; use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use CloudObjects\SDK\Exceptions\CoreAPIException; use Kevinrob\GuzzleCache\Storage\CacheStorageInterface,
Kevinrob\GuzzleCache\Storage\Psr6CacheStorage,
Kevinrob\GuzzleCache\Storage\Psr16CacheStorage,
Kevinrob\GuzzleCache\CacheEntry;
use Psr\Cache\CacheItemPoolInterface;
use Psr\SimpleCache\CacheInterface;
use CloudObjects\SDK\Exceptions\CoreAPIException,
CloudObjects\SDK\Exceptions\InvalidSDKConfigurationException;
use CloudObjects\SDK\AccountGateway\AccountContext; use CloudObjects\SDK\AccountGateway\AccountContext;
/** /**
@@ -29,15 +37,15 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
private $options; private $options;
private $cache; private $cache;
private $objects; private $objects;
private $defaultReader;
private $customCacheDefaultRequest;
const CO_API_URL = 'https://api.cloudobjects.net/'; const CO_API_URL = 'https://od.coid.link/';
const REVISION_PROPERTY = 'coid://cloudobjects.io/isAtRevision';
public function __construct($options = []) { public function __construct($options = []) {
// Merge options with defaults // Merge options with defaults
$this->options = array_merge([ $this->options = array_merge([
'cache_provider' => 'none', 'cache_storage' => null,
'cache_prefix' => 'clobj:', 'cache_prefix' => 'clobj:',
'cache_ttl' => 60, 'cache_ttl' => 60,
'static_config_path' => null, 'static_config_path' => null,
@@ -49,35 +57,27 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
'connect_timeout' => 5 'connect_timeout' => 5
], $options); ], $options);
// Set up object cache // Check object cache configuration
switch ($this->options['cache_provider']) { if (isset($this->options['cache_storage'])
case 'none': && !($this->options['cache_storage'] instanceof CacheStorageInterface)
// no caching && !($this->options['cache_storage'] instanceof CacheItemPoolInterface)
$this->cache = null; && !($this->options['cache_storage'] instanceof CacheInterface)
break; ) {
case 'redis': throw new InvalidSDKConfigurationException('Invalid cache_storage specified; must be an instance of Kevinrob\GuzzleCache\CacheStorageInterface, Psr\Cache\CacheItemPoolInterface or Psr\SimpleCache\CacheInterface.');
// caching with Redis }
$redis = new \Redis();
$redis->pconnect(
isset($this->options['cache_provider.redis.host']) ? $this->options['cache_provider.redis.host'] : '127.0.0.1',
isset($this->options['cache_provider.redis.port']) ? $this->options['cache_provider.redis.port'] : 6379);
$this->cache = new RedisCache(); if ($this->options['cache_storage'] instanceof CacheStorageInterface) {
$this->cache->setRedis($redis); $this->cache = $this->options['cache_storage'];
break; } elseif ($this->options['cache_storage'] instanceof CacheItemPoolInterface) {
case 'file': $this->cache = new Psr6CacheStorage($this->options['cache_storage']);
// caching on the filesystem } elseif ($this->options['cache_storage'] instanceof CacheInterface) {
$this->cache = new \Doctrine\Common\Cache\FilesystemCache( $this->cache = new Psr16CacheStorage($this->options['cache_storage']);
isset($this->options['cache_provider.file.directory']) ? $this->options['cache_provider.file.directory'] : sys_get_temp_dir()
);
break;
default:
throw new Exception('Valid values for cache_provider are: none, redis, file');
} }
// Set up logger // Set up logger
if (is_a($this->options['logger'], LoggerInterface::class)) if (is_a($this->options['logger'], LoggerInterface::class)) {
$this->setLogger($this->options['logger']); $this->setLogger($this->options['logger']);
}
// Set up handler stack // Set up handler stack
$stack = HandlerStack::create(); $stack = HandlerStack::create();
@@ -86,11 +86,14 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
if (isset($this->cache)) { if (isset($this->cache)) {
$stack->push( $stack->push(
new CacheMiddleware( new CacheMiddleware(
new PrivateCacheStrategy( new PrivateCacheStrategy($this->cache)
new DoctrineCacheStorage($this->cache)
)
) )
); );
// We also use the cache for storing object descriptions and attachments
// without the HTTP request, so we create a dummy request; this way
// we can reuse GuzzleCache for maximum compatibility
$this->customCacheDefaultRequest = new Request('GET', '/');
} }
// Initialize client // Initialize client
@@ -107,23 +110,53 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
$this->client = new Client($options); $this->client = new Client($options);
} }
/**
* Set a default reader for CloudObject instances.
*/
public function setDefaultReader(NodeReader $reader) : self {
$this->defaultReader = $reader;
return $this;
}
/**
* Get the default reader for CloudObject instances.
*/
public function getDefaultReader() : NodeReader {
return $this->defaultReader;
}
public function logInfoWithTime($message, $ts) { public function logInfoWithTime($message, $ts) {
if (isset($this->logger)) if (isset($this->logger))
$this->logger->info($message, [ 'elapsed_ms' => round((microtime(true) - $ts) * 1000) ]); $this->logger->info($message, [ 'elapsed_ms' => round((microtime(true) - $ts) * 1000) ]);
} }
private function getCacheKey($id) { public function getCacheKey($id) {
return $this->options['cache_prefix'] . $this->options['auth_ns'] . '/' . $id; return $this->options['cache_prefix'] . $this->options['auth_ns'] . '/' . $id;
} }
private function getFromCache($id) { private function getFromCache($id) {
return (isset($this->cache) && $this->cache->contains($this->getCacheKey($id))) if (!$this->cache) {
? $this->cache->fetch($this->getCacheKey($id)) : null; return null;
}
$cachedData = $this->cache->fetch($this->getCacheKey($id));
if (!$cachedData) {
return null;
}
return (string)$cachedData->getResponse()->getBody(true);
} }
private function putIntoCache($id, $data, $ttl) { private function putIntoCache($id, $data, $ttl) {
if (isset($this->cache)) if ($this->cache) {
$this->cache->save($this->getCacheKey($id), $data, $ttl); $entry = new CacheEntry($this->customCacheDefaultRequest,
new Response(200, [], $data),
((new DateTime)->modify('+'.$ttl.' seconds')));
$this->cache->save($this->getCacheKey($id), $entry, $ttl);
}
} }
public function getFromCacheCustom($id) { public function getFromCacheCustom($id) {
@@ -179,7 +212,15 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
return null; return null;
} }
return new CloudObject($coid, $node); $object = (new CloudObject($coid, $node))
->setObjectRetriever($this);
if ($this->defaultReader) {
// Initialize CloudObject with default reader if it is set
$object->setReader($this->defaultReader);
}
return $object;
} }
/** /**
@@ -454,7 +495,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
} }
if (!isset($fileData) if (!isset($fileData)
|| $fileRevision!=$object->getProperty(self::REVISION_PROPERTY)->getValue()) { || $fileRevision !== $object->getProperty(Constants::PROPERTY_REVISION)->getValue()) {
// Does not exist in cache or is outdated, fetch from CloudObjects // Does not exist in cache or is outdated, fetch from CloudObjects
try { try {
@@ -462,7 +503,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
.'/'.basename($filename)); .'/'.basename($filename));
$fileContent = $response->getBody()->getContents(); $fileContent = $response->getBody()->getContents();
$fileData = $object->getProperty(self::REVISION_PROPERTY)->getValue().'#'.$fileContent; $fileData = $object->getProperty(Constants::PROPERTY_REVISION)->getValue().'#'.$fileContent;
$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);

View File

@@ -0,0 +1,63 @@
<?php
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
namespace CloudObjects\SDK\TestHelpers;
use Psr\Log\LoggerInterface;
class InMemoryLogger implements LoggerInterface {
private $logs = [];
public function getLogs() : array {
return $this->logs;
}
public function getLastLogMessage() : string {
if (empty($this->logs)) {
return '';
}
return end($this->logs)['message'];
}
public function emergency(string|\Stringable $message, array $context = []): void {
$this->logs[] = [ 'level' => 'emergency', 'message' => (string)$message, 'context' => $context ];
}
public function alert(string|\Stringable $message, array $context = []): void {
$this->logs[] = [ 'level' => 'alert', 'message' => (string)$message, 'context' => $context ];
}
public function critical(string|\Stringable $message, array $context = []): void {
$this->logs[] = [ 'level' => 'critical', 'message' => (string)$message, 'context' => $context ];
}
public function error(string|\Stringable $message, array $context = []): void {
$this->logs[] = [ 'level' => 'error', 'message' => (string)$message, 'context' => $context ];
}
public function warning(string|\Stringable $message, array $context = []): void {
$this->logs[] = [ 'level' => 'warning', 'message' => (string)$message, 'context' => $context ];
}
public function notice(string|\Stringable $message, array $context = []): void {
$this->logs[] = [ 'level' => 'notice', 'message' => (string)$message, 'context' => $context ];
}
public function info(string|\Stringable $message, array $context = []): void {
$this->logs[] = [ 'level' => 'info', 'message' => (string)$message, 'context' => $context ];
}
public function debug(string|\Stringable $message, array $context = []): void {
$this->logs[] = [ 'level' => 'debug', 'message' => (string)$message, 'context' => $context ];
}
public function log($level, string|\Stringable $message, array $context = []): void {
$this->logs[] = [ 'level' => $level, 'message' => (string)$message, 'context' => $context ];
}
}

View File

@@ -157,7 +157,7 @@ class APIClientFactory {
if ($this->reader->hasProperty($api, 'oauth2:hasAuthorizationServer')) { if ($this->reader->hasProperty($api, 'oauth2:hasAuthorizationServer')) {
// We have an authorization server for this endpoint/API // We have an authorization server for this endpoint/API
$authServerCoid = $this->reader->getFirstValueIRI($api, 'oauth2:hasAuthorizationServer'); $authServerCoid = $this->reader->getFirstValueIRI($api, 'oauth2:hasAuthorizationServer');
$authServerObject = $this->objectRetriever->getObject($authServerCoid); $authServerObject = $this->objectRetriever->getObjectNode($authServerCoid);
if (!isset($authServerObject)) if (!isset($authServerObject))
throw new InvalidObjectConfigurationException("Authorization server object <" throw new InvalidObjectConfigurationException("Authorization server object <"
. (string)$authServerCoid . "> not available."); . (string)$authServerCoid . "> not available.");
@@ -220,7 +220,7 @@ class APIClientFactory {
public function __construct(ObjectRetriever $objectRetriever, IRI $namespaceCoid = null) { public function __construct(ObjectRetriever $objectRetriever, IRI $namespaceCoid = null) {
$this->objectRetriever = $objectRetriever; $this->objectRetriever = $objectRetriever;
$this->namespace = isset($namespaceCoid) $this->namespace = isset($namespaceCoid)
? $objectRetriever->getObject($namespaceCoid) ? $objectRetriever->getObjectNode($namespaceCoid)
: $objectRetriever->getAuthenticatingNamespaceObject(); : $objectRetriever->getAuthenticatingNamespaceObject();
$this->reader = new NodeReader([ $this->reader = new NodeReader([
@@ -242,7 +242,7 @@ class APIClientFactory {
public function getClientWithCOID(IRI $apiCoid, bool $specificClient = false) { public function getClientWithCOID(IRI $apiCoid, bool $specificClient = false) {
$idString = (string)$apiCoid.(string)$specificClient; $idString = (string)$apiCoid.(string)$specificClient;
if (!isset($this->apiClients[$idString])) { if (!isset($this->apiClients[$idString])) {
$object = $this->objectRetriever->getObject($apiCoid); $object = $this->objectRetriever->getObjectNode($apiCoid);
if (!isset($object)) if (!isset($object))
throw new CoreAPIException("Could not retrieve API <".(string)$apiCoid.">."); throw new CoreAPIException("Could not retrieve API <".(string)$apiCoid.">.");
$this->apiClients[$idString] = $this->createClient($object, $specificClient); $this->apiClients[$idString] = $this->createClient($object, $specificClient);

View File

@@ -2,66 +2,17 @@
[![Latest Stable Version](https://poser.pugx.org/cloudobjects/sdk/v/stable)](https://packagist.org/packages/cloudobjects/sdk) [![Total Downloads](https://poser.pugx.org/cloudobjects/sdk/downloads)](https://packagist.org/packages/cloudobjects/sdk) [![Latest Stable Version](https://poser.pugx.org/cloudobjects/sdk/v/stable)](https://packagist.org/packages/cloudobjects/sdk) [![Total Downloads](https://poser.pugx.org/cloudobjects/sdk/downloads)](https://packagist.org/packages/cloudobjects/sdk)
[![buddy branch](https://app.buddy.works/cloudobjects/php-sdk/repository/branch/main/badge.svg?token=52ae28bf71dbbd3dde018f3f3e7caafa04f95bdb451b3dfca547414ec7a01739 "buddy branch")](https://app.buddy.works/cloudobjects/php-sdk/repository/branch/main) [![buddy pipeline](https://app.buddy.works/cloudobjects/cloudobjects-php-sdk/pipelines/pipeline/561203/badge.svg?token=40c63ec4ea9e432a9edc8ebfb0ba0e203f70a02a8208339b119ff16772f4abd4 "buddy pipeline")](https://app.buddy.works/cloudobjects/cloudobjects-php-sdk/pipelines/pipeline/561203)
The CloudObjects PHP SDK provides simple access to [CloudObjects](https://cloudobjects.io/) from PHP-based applications. It wraps the [Object API](https://coid.link/cloudobjects.io/ObjectAPI/1.0) to fetch objects from the CloudObjects Core database and provides object-based access to their RDF description. A two-tiered caching mechanism (in-memory and Doctrine cache drivers) is included. The SDK also contains a helper class to validate COIDs.
## Installation ## Installation
The SDK is [distributed through packagist](https://packagist.org/packages/cloudobjects/sdk). Add `cloudobjects/sdk` to the `require` section of your `composer.json`, like this: The SDK is [distributed through packagist](https://packagist.org/packages/cloudobjects/sdk).
````json Install with the following command:
{
"require": {
"cloudobjects/sdk" : ">=0.7"
}
}
````
## Retrieving Objects ```
composer require cloudobjects/sdk
In order to retrieve objects from the CloudObjects Core database you need to create an instance of `CloudObjects\SDK\ObjectRetriever`. Then you can call `getObject()`. This method returns an `ML\JsonLD\Node` instance or `null` if the object is not found. You can use the object interface of the [JsonLD library](https://github.com/lanthaler/JsonLD/) to read the information from the object. ```
Here's a simple example:
````php
use ML\IRI\IRI;
use CloudObjects\SDK\ObjectRetriever;
/* ... */
$retriever = new ObjectRetriever();
$object = $this->retriever->getObject(new IRI('coid://cloudobjects.io'));
if (isset($object))
echo $object->getProperty('http://www.w3.org/2000/01/rdf-schema#label')->getValue();
else
echo "Object not found.";
````
### Configuration
You can pass an array of configuration options to the ObjectRetriever's constructor:
| Option | Description | Default |
|---|---|---|
| `cache_provider` | The type of cache used. Currently supports `redis`, `file` and `none`. | `none` |
| `cache_prefix` | A prefix used for cache IDs. Normally this should not be set but might be necessary on shared caches. | `clobj:` |
| `cache_ttl` | Determines how long objects can remain cached. | `60` |
| `auth_ns` | The namespace of the service that this retriever acts for. If not set the API is accessed anonymously. | `null` |
| `auth_secret` | The shared secret between the namespace in `auth_ns` and `cloudobjects.io` for authenticated. If not set the API is accessed anonymously. | `null` |
#### For `redis` cache:
| Option | Description | Default |
|---|---|---|
| `cache_provider.redis.host` | The hostname or IP of the Redis instance. | `127.0.0.1` |
| `cache_provider.redis.port` | The port number of the Redis instance. | `6379` |
#### For `file` cache:
| Option | Description | Default |
|---|---|---|
| `cache_provider.file.directory` | The directory to store cache data in. | The system's temporary directory. |
## License ## License

View File

@@ -6,12 +6,12 @@
"license": "MPL-2.0", "license": "MPL-2.0",
"require" : { "require" : {
"ml/json-ld": ">=1.0.7", "ml/json-ld": ">=1.0.7",
"doctrine/common" : ">=2.6.1",
"doctrine/cache" : "1.*",
"guzzlehttp/guzzle" : ">=6.0", "guzzlehttp/guzzle" : ">=6.0",
"psr/cache": ">=1.0",
"psr/log": ">=1.1", "psr/log": ">=1.1",
"kevinrob/guzzle-cache-middleware": "^7.0.0", "kevinrob/guzzle-cache-middleware": "^7.0.0",
"webmozart/assert": "^1.6" "webmozart/assert": "^1.6",
"psr/simple-cache": "^3.0"
}, },
"authors": [ "authors": [
{ {

530
composer.lock generated
View File

@@ -4,395 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "c3afb3b29d3f46223386d29810f6e8d5", "content-hash": "659b8e6e4e495bf62452eb85772ac9aa",
"packages": [ "packages": [
{
"name": "doctrine/cache",
"version": "1.13.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
"reference": "56cd022adb5514472cb144c087393c1821911d09"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/56cd022adb5514472cb144c087393c1821911d09",
"reference": "56cd022adb5514472cb144c087393c1821911d09",
"shasum": ""
},
"require": {
"php": "~7.1 || ^8.0"
},
"conflict": {
"doctrine/common": ">2.2,<2.4"
},
"require-dev": {
"alcaeus/mongo-php-adapter": "^1.1",
"cache/integration-tests": "dev-master",
"doctrine/coding-standard": "^9",
"mongodb/mongodb": "^1.1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"predis/predis": "~1.0",
"psr/cache": "^1.0 || ^2.0 || ^3.0",
"symfony/cache": "^4.4 || ^5.4 || ^6",
"symfony/var-exporter": "^4.4 || ^5.4 || ^6"
},
"suggest": {
"alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.",
"homepage": "https://www.doctrine-project.org/projects/cache.html",
"keywords": [
"abstraction",
"apcu",
"cache",
"caching",
"couchdb",
"memcached",
"php",
"redis",
"xcache"
],
"support": {
"issues": "https://github.com/doctrine/cache/issues",
"source": "https://github.com/doctrine/cache/tree/1.13.0"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache",
"type": "tidelift"
}
],
"abandoned": true,
"time": "2022-05-20T20:06:54+00:00"
},
{
"name": "doctrine/common",
"version": "3.5.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/common.git",
"reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/common/zipball/d9ea4a54ca2586db781f0265d36bea731ac66ec5",
"reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5",
"shasum": ""
},
"require": {
"doctrine/persistence": "^2.0 || ^3.0 || ^4.0",
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9.0 || ^10.0",
"doctrine/collections": "^1",
"phpstan/phpstan": "^1.4.1",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5.20 || ^8.5 || ^9.0",
"squizlabs/php_codesniffer": "^3.0",
"symfony/phpunit-bridge": "^6.1",
"vimeo/psalm": "^4.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
},
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
}
],
"description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.",
"homepage": "https://www.doctrine-project.org/projects/common.html",
"keywords": [
"common",
"doctrine",
"php"
],
"support": {
"issues": "https://github.com/doctrine/common/issues",
"source": "https://github.com/doctrine/common/tree/3.5.0"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcommon",
"type": "tidelift"
}
],
"time": "2025-01-01T22:12:03+00:00"
},
{
"name": "doctrine/event-manager",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/event-manager.git",
"reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/event-manager/zipball/dda33921b198841ca8dbad2eaa5d4d34769d18cf",
"reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf",
"shasum": ""
},
"require": {
"php": "^8.1"
},
"conflict": {
"doctrine/common": "<2.9"
},
"require-dev": {
"doctrine/coding-standard": "^14",
"phpdocumentor/guides-cli": "^1.4",
"phpstan/phpstan": "^2.1.32",
"phpunit/phpunit": "^10.5.58"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
},
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
}
],
"description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.",
"homepage": "https://www.doctrine-project.org/projects/event-manager.html",
"keywords": [
"event",
"event dispatcher",
"event manager",
"event system",
"events"
],
"support": {
"issues": "https://github.com/doctrine/event-manager/issues",
"source": "https://github.com/doctrine/event-manager/tree/2.1.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager",
"type": "tidelift"
}
],
"time": "2026-01-29T07:11:08+00:00"
},
{
"name": "doctrine/persistence",
"version": "4.1.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/persistence.git",
"reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/persistence/zipball/b9c49ad3558bb77ef973f4e173f2e9c2eca9be09",
"reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09",
"shasum": ""
},
"require": {
"doctrine/event-manager": "^1 || ^2",
"php": "^8.1",
"psr/cache": "^1.0 || ^2.0 || ^3.0"
},
"require-dev": {
"doctrine/coding-standard": "^14",
"phpstan/phpstan": "2.1.30",
"phpstan/phpstan-phpunit": "^2",
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "^10.5.58 || ^12",
"symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0",
"symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Persistence\\": "src/Persistence"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
},
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
}
],
"description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.",
"homepage": "https://www.doctrine-project.org/projects/persistence.html",
"keywords": [
"mapper",
"object",
"odm",
"orm",
"persistence"
],
"support": {
"issues": "https://github.com/doctrine/persistence/issues",
"source": "https://github.com/doctrine/persistence/tree/4.1.1"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fpersistence",
"type": "tidelift"
}
],
"time": "2025-10-16T20:13:18+00:00"
},
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
"version": "7.10.0", "version": "7.10.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/guzzle.git", "url": "https://github.com/guzzle/guzzle.git",
"reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" "reference": "aec528da477062d3af11f51e6b33402be233b21f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aec528da477062d3af11f51e6b33402be233b21f",
"reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "reference": "aec528da477062d3af11f51e6b33402be233b21f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -410,8 +35,9 @@
"bamarni/composer-bin-plugin": "^1.8.2", "bamarni/composer-bin-plugin": "^1.8.2",
"ext-curl": "*", "ext-curl": "*",
"guzzle/client-integration-tests": "3.0.2", "guzzle/client-integration-tests": "3.0.2",
"guzzlehttp/test-server": "^0.3.2",
"php-http/message-factory": "^1.1", "php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.39 || ^9.6.20", "phpunit/phpunit": "^8.5.52 || ^9.6.34",
"psr/log": "^1.1 || ^2.0 || ^3.0" "psr/log": "^1.1 || ^2.0 || ^3.0"
}, },
"suggest": { "suggest": {
@@ -489,7 +115,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/guzzle/guzzle/issues", "issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.10.0" "source": "https://github.com/guzzle/guzzle/tree/7.10.4"
}, },
"funding": [ "funding": [
{ {
@@ -505,20 +131,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-08-23T22:36:01+00:00" "time": "2026-05-22T19:00:53+00:00"
}, },
{ {
"name": "guzzlehttp/promises", "name": "guzzlehttp/promises",
"version": "2.3.0", "version": "2.4.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/promises.git", "url": "https://github.com/guzzle/promises.git",
"reference": "481557b130ef3790cf82b713667b43030dc9c957" "reference": "09e8a212562fb1fb6a512c4156ed71525969d6c2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", "url": "https://api.github.com/repos/guzzle/promises/zipball/09e8a212562fb1fb6a512c4156ed71525969d6c2",
"reference": "481557b130ef3790cf82b713667b43030dc9c957", "reference": "09e8a212562fb1fb6a512c4156ed71525969d6c2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -526,7 +152,7 @@
}, },
"require-dev": { "require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2", "bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.44 || ^9.6.25" "phpunit/phpunit": "^8.5.52 || ^9.6.34"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@@ -572,7 +198,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/guzzle/promises/issues", "issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/2.3.0" "source": "https://github.com/guzzle/promises/tree/2.4.1"
}, },
"funding": [ "funding": [
{ {
@@ -588,20 +214,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-08-22T14:34:08+00:00" "time": "2026-05-20T22:57:30+00:00"
}, },
{ {
"name": "guzzlehttp/psr7", "name": "guzzlehttp/psr7",
"version": "2.8.0", "version": "2.10.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/psr7.git", "url": "https://github.com/guzzle/psr7.git",
"reference": "21dc724a0583619cd1652f673303492272778051" "reference": "a1bbdc172f32a25fe999965b65b6e71fd87da9ed"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", "url": "https://api.github.com/repos/guzzle/psr7/zipball/a1bbdc172f32a25fe999965b65b6e71fd87da9ed",
"reference": "21dc724a0583619cd1652f673303492272778051", "reference": "a1bbdc172f32a25fe999965b65b6e71fd87da9ed",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -616,8 +242,9 @@
}, },
"require-dev": { "require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2", "bamarni/composer-bin-plugin": "^1.8.2",
"http-interop/http-factory-tests": "0.9.0", "http-interop/http-factory-tests": "1.1.0",
"phpunit/phpunit": "^8.5.44 || ^9.6.25" "jshttp/mime-db": "1.54.0.1",
"phpunit/phpunit": "^8.5.52 || ^9.6.34"
}, },
"suggest": { "suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
@@ -688,7 +315,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/guzzle/psr7/issues", "issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.8.0" "source": "https://github.com/guzzle/psr7/tree/2.10.2"
}, },
"funding": [ "funding": [
{ {
@@ -704,7 +331,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-08-23T21:21:41+00:00" "time": "2026-05-25T22:58:15+00:00"
}, },
{ {
"name": "kevinrob/guzzle-cache-middleware", "name": "kevinrob/guzzle-cache-middleware",
@@ -1151,6 +778,57 @@
}, },
"time": "2024-09-11T13:17:53+00:00" "time": "2024-09-11T13:17:53+00:00"
}, },
{
"name": "psr/simple-cache",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"support": {
"source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
},
"time": "2021-10-29T13:26:27+00:00"
},
{ {
"name": "ralouphie/getallheaders", "name": "ralouphie/getallheaders",
"version": "3.0.3", "version": "3.0.3",
@@ -1197,16 +875,16 @@
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
"version": "v3.6.0", "version": "v3.7.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git", "url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b",
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1219,7 +897,7 @@
"name": "symfony/contracts" "name": "symfony/contracts"
}, },
"branch-alias": { "branch-alias": {
"dev-main": "3.6-dev" "dev-main": "3.7-dev"
} }
}, },
"autoload": { "autoload": {
@@ -1244,7 +922,7 @@
"description": "A generic function and convention to trigger deprecation notices", "description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0"
}, },
"funding": [ "funding": [
{ {
@@ -1255,12 +933,16 @@
"url": "https://github.com/fabpot", "url": "https://github.com/fabpot",
"type": "github" "type": "github"
}, },
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{ {
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-09-25T14:21:43+00:00" "time": "2026-04-13T15:52:40+00:00"
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
@@ -2348,6 +2030,7 @@
"type": "github" "type": "github"
} }
], ],
"abandoned": true,
"time": "2023-02-03T06:58:43+00:00" "time": "2023-02-03T06:58:43+00:00"
}, },
{ {
@@ -2403,6 +2086,7 @@
"type": "github" "type": "github"
} }
], ],
"abandoned": true,
"time": "2023-02-03T06:59:15+00:00" "time": "2023-02-03T06:59:15+00:00"
}, },
{ {
@@ -3192,16 +2876,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v7.4.5", "version": "v7.4.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "446d0db2b1f21575f1284b74533e425096abdfb6" "reference": "9381209597ec66c25be154cbf2289076e64d1eab"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/446d0db2b1f21575f1284b74533e425096abdfb6", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9381209597ec66c25be154cbf2289076e64d1eab",
"reference": "446d0db2b1f21575f1284b74533e425096abdfb6", "reference": "9381209597ec66c25be154cbf2289076e64d1eab",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3250,7 +2934,7 @@
"description": "Defines an object-oriented layer for the HTTP specification", "description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-foundation/tree/v7.4.5" "source": "https://github.com/symfony/http-foundation/tree/v7.4.8"
}, },
"funding": [ "funding": [
{ {
@@ -3270,20 +2954,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-27T16:16:02+00:00" "time": "2026-03-24T13:12:05+00:00"
}, },
{ {
"name": "symfony/polyfill-mbstring", "name": "symfony/polyfill-mbstring",
"version": "v1.33.0", "version": "v1.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git", "url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" "reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/14c5439eec4ccff081ac14eca2dc57feb2a66d92",
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3335,7 +3019,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.1"
}, },
"funding": [ "funding": [
{ {
@@ -3355,20 +3039,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-12-23T08:48:59+00:00" "time": "2026-05-26T12:51:13+00:00"
}, },
{ {
"name": "symfony/psr-http-message-bridge", "name": "symfony/psr-http-message-bridge",
"version": "v7.4.4", "version": "v7.4.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/psr-http-message-bridge.git", "url": "https://github.com/symfony/psr-http-message-bridge.git",
"reference": "929ffe10bbfbb92e711ac3818d416f9daffee067" "reference": "76f1a57719a4a04c0ea18678a6c9305b5dcb9da8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/929ffe10bbfbb92e711ac3818d416f9daffee067", "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/76f1a57719a4a04c0ea18678a6c9305b5dcb9da8",
"reference": "929ffe10bbfbb92e711ac3818d416f9daffee067", "reference": "76f1a57719a4a04c0ea18678a6c9305b5dcb9da8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3423,7 +3107,7 @@
"psr-7" "psr-7"
], ],
"support": { "support": {
"source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.4" "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.8"
}, },
"funding": [ "funding": [
{ {
@@ -3443,7 +3127,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-03T23:30:35+00:00" "time": "2026-03-24T13:12:05+00:00"
}, },
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",

View File

@@ -7,6 +7,7 @@
namespace CloudObjects\SDK; namespace CloudObjects\SDK;
use ML\IRI\IRI; use ML\IRI\IRI;
use ML\JsonLD\Node;
use GuzzleHttp\Client, GuzzleHttp\Handler\MockHandler, use GuzzleHttp\Client, GuzzleHttp\Handler\MockHandler,
GuzzleHttp\HandlerStack, GuzzleHttp\Psr7\Response; GuzzleHttp\HandlerStack, GuzzleHttp\Psr7\Response;
@@ -24,7 +25,8 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
private function useRootResourceMock() { private function useRootResourceMock() {
$this->setMockResponse(new Response(200, $this->setMockResponse(new Response(200,
['Content-Type' => 'application/ld+json'], ['Content-Type' => 'application/ld+json'],
'{"@context":{"co":"coid:\/\/cloudobjects.io\/","rdf":"http:\/\/www.w3.org\/1999\/02\/22-rdf-syntax-ns#","agws":"coid:\/\/aauid.net\/","rdfs":"http:\/\/www.w3.org\/2000\/01\/rdf-schema#"},"@id":"coid:\/\/cloudobjects.io","@type":["agws:Service","co:Namespace"],"co:isAtRevision":"6-fbea0c90b2c5e5300e4039ed99be9b2d","co:isVisibleTo":{"@id":"co:Public"},"co:recommendsPrefix":"co","co:wasUpdatedAt":{"@type":"http:\/\/www.w3.org\/2001\/XMLSchema#dateTime","@value":"2017-01-16T17:29:22+00:00"},"rdfs:comment":"The CloudObjects namespace defines the essential objects.","rdfs:label":"CloudObjects"}')); '{"@context":{"co":"coid:\/\/cloudobjects.io\/","rdf":"http:\/\/www.w3.org\/1999\/02\/22-rdf-syntax-ns#","agws":"coid:\/\/aauid.net\/","rdfs":"http:\/\/www.w3.org\/2000\/01\/rdf-schema#"},"@id":"coid:\/\/cloudobjects.io","@type":["agws:Service","co:Namespace"],"co:isAtRevision":"6-fbea0c90b2c5e5300e4039ed99be9b2d","co:isVisibleTo":{"@id":"co:Public"},"co:recommendsPrefix":"co","co:wasUpdatedAt":{"@type":"http:\/\/www.w3.org\/2001\/XMLSchema#dateTime","@value":"2017-01-16T17:29:22+00:00"},"rdfs:comment":"The CloudObjects namespace defines the essential objects.","rdfs:label":"CloudObjects"}'
));
} }
protected function setUp(): void { protected function setUp(): void {
@@ -35,12 +37,13 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#' 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#'
] ]
]); ]);
$this->retriever->setDefaultReader($this->reader);
} }
public function testHasType1() { public function testHasType1() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock(); $this->useRootResourceMock();
$object = $this->retriever->getObject($coid); $object = $this->retriever->getObjectNode($coid);
$this->assertTrue($this->reader->hasType($object, 'coid://cloudobjects.io/Namespace')); $this->assertTrue($this->reader->hasType($object, 'coid://cloudobjects.io/Namespace'));
$this->assertTrue($this->reader->hasType($object, 'co:Namespace')); $this->assertTrue($this->reader->hasType($object, 'co:Namespace'));
@@ -51,7 +54,7 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
public function testHasPropertyValue1() { public function testHasPropertyValue1() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock(); $this->useRootResourceMock();
$object = $this->retriever->getObject($coid); $object = $this->retriever->getObjectNode($coid);
$this->assertTrue($this->reader->hasPropertyValue($object, 'http://www.w3.org/2000/01/rdf-schema#label', 'CloudObjects')); $this->assertTrue($this->reader->hasPropertyValue($object, 'http://www.w3.org/2000/01/rdf-schema#label', 'CloudObjects'));
$this->assertTrue($this->reader->hasPropertyValue($object, 'rdfs:label', 'CloudObjects')); $this->assertTrue($this->reader->hasPropertyValue($object, 'rdfs:label', 'CloudObjects'));
@@ -60,7 +63,7 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
public function testGetFirstValueString1() { public function testGetFirstValueString1() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock(); $this->useRootResourceMock();
$object = $this->retriever->getObject($coid); $object = $this->retriever->getObjectNode($coid);
$this->assertEquals('CloudObjects', $this->reader->getFirstValueString($object, 'http://www.w3.org/2000/01/rdf-schema#label')); $this->assertEquals('CloudObjects', $this->reader->getFirstValueString($object, 'http://www.w3.org/2000/01/rdf-schema#label'));
$this->assertEquals('CloudObjects', $this->reader->getFirstValueString($object, 'rdfs:label')); $this->assertEquals('CloudObjects', $this->reader->getFirstValueString($object, 'rdfs:label'));
@@ -70,36 +73,63 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals('theDefaultValue', $this->reader->getFirstValueString($object, 'coid://cloudobjects.io/makesTriplesVisibleTo', 'theDefaultValue')); $this->assertEquals('theDefaultValue', $this->reader->getFirstValueString($object, 'coid://cloudobjects.io/makesTriplesVisibleTo', 'theDefaultValue'));
$this->assertEquals('theDefaultValue', $this->reader->getFirstValueString($object, 'co:makesTriplesVisibleTo', 'theDefaultValue')); $this->assertEquals('theDefaultValue', $this->reader->getFirstValueString($object, 'co:makesTriplesVisibleTo', 'theDefaultValue'));
$object = $this->retriever->getCloudObject($coid);
$this->assertEquals('CloudObjects', $object->getString('http://www.w3.org/2000/01/rdf-schema#label'));
$this->assertEquals('CloudObjects', $object->getString('rdfs:label'));
$this->assertNull($object->getString('coid://cloudobjects.io/makesTriplesVisibleTo'));
$this->assertNull($object->getString('co:makesTriplesVisibleTo'));
$this->assertEquals('theDefaultValue', $object->getString('coid://cloudobjects.io/makesTriplesVisibleTo', 'theDefaultValue'));
$this->assertEquals('theDefaultValue', $object->getString('co:makesTriplesVisibleTo', 'theDefaultValue'));
} }
public function testGetFirstValueIRI1() { public function testGetFirstValueIRI1() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock(); $this->useRootResourceMock();
$object = $this->retriever->getObject($coid); $object = $this->retriever->getObjectNode($coid);
$this->assertInstanceOf('ML\IRI\IRI', $this->reader->getFirstValueIRI($object, 'coid://cloudobjects.io/isVisibleTo')); $this->assertInstanceOf(IRI::class, $this->reader->getFirstValueIRI($object, 'coid://cloudobjects.io/isVisibleTo'));
$this->assertInstanceOf('ML\IRI\IRI', $this->reader->getFirstValueIRI($object, 'co:isVisibleTo')); $this->assertInstanceOf(IRI::class, $this->reader->getFirstValueIRI($object, 'co:isVisibleTo'));
$this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $this->reader->getFirstValueIRI($object, 'coid://cloudobjects.io/isVisibleTo')); $this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $this->reader->getFirstValueIRI($object, 'coid://cloudobjects.io/isVisibleTo'));
$this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $this->reader->getFirstValueIRI($object, 'co:isVisibleTo')); $this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $this->reader->getFirstValueIRI($object, 'co:isVisibleTo'));
$object = $this->retriever->getCloudObject($coid);
$this->assertInstanceOf(IRI::class, $object->getIRI('coid://cloudobjects.io/isVisibleTo'));
$this->assertInstanceOf(IRI::class, $object->getIRI('co:isVisibleTo'));
$this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $object->getIRI('coid://cloudobjects.io/isVisibleTo'));
$this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $object->getIRI('co:isVisibleTo'));
} }
public function testGetFirstValueNode1() { public function testGetFirstValueNode1() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock(); $this->useRootResourceMock();
$object = $this->retriever->getObject($coid); $object = $this->retriever->getObjectNode($coid);
$this->assertInstanceOf('ML\JsonLD\Node', $this->reader->getFirstValueNode($object, 'coid://cloudobjects.io/isVisibleTo')); $this->assertInstanceOf(Node::class, $this->reader->getFirstValueNode($object, 'coid://cloudobjects.io/isVisibleTo'));
$this->assertInstanceOf('ML\JsonLD\Node', $this->reader->getFirstValueNode($object, 'co:isVisibleTo')); $this->assertInstanceOf(Node::class, $this->reader->getFirstValueNode($object, 'co:isVisibleTo'));
$this->assertEquals('coid://cloudobjects.io/Public', $this->reader->getFirstValueNode($object, 'coid://cloudobjects.io/isVisibleTo')->getId()); $this->assertEquals('coid://cloudobjects.io/Public', $this->reader->getFirstValueNode($object, 'coid://cloudobjects.io/isVisibleTo')->getId());
$this->assertEquals('coid://cloudobjects.io/Public', $this->reader->getFirstValueNode($object, 'co:isVisibleTo')->getId()); $this->assertEquals('coid://cloudobjects.io/Public', $this->reader->getFirstValueNode($object, 'co:isVisibleTo')->getId());
$object = $this->retriever->getCloudObject($coid);
$this->assertInstanceOf(Node::class, $object->getNode('coid://cloudobjects.io/isVisibleTo'));
$this->assertInstanceOf(Node::class, $object->getNode('co:isVisibleTo'));
$this->assertEquals('coid://cloudobjects.io/Public', $object->getNode('coid://cloudobjects.io/isVisibleTo')->getId());
$this->assertEquals('coid://cloudobjects.io/Public', $object->getNode('co:isVisibleTo')->getId());
} }
public function testGetAllValuesString1() { public function testGetAllValuesString1() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock(); $this->useRootResourceMock();
$object = $this->retriever->getObject($coid); $object = $this->retriever->getObjectNode($coid);
$this->assertCount(1, $this->reader->getAllValuesString($object, 'http://www.w3.org/2000/01/rdf-schema#label')); $this->assertCount(1, $this->reader->getAllValuesString($object, 'http://www.w3.org/2000/01/rdf-schema#label'));
$this->assertCount(1, $this->reader->getAllValuesString($object, 'rdfs:label')); $this->assertCount(1, $this->reader->getAllValuesString($object, 'rdfs:label'));
@@ -116,7 +146,7 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
public function testGetAllValuesIRI1() { public function testGetAllValuesIRI1() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock(); $this->useRootResourceMock();
$object = $this->retriever->getObject($coid); $object = $this->retriever->getObjectNode($coid);
$this->assertCount(0, $this->reader->getAllValuesIRI($object, 'http://www.w3.org/2000/01/rdf-schema#label')); $this->assertCount(0, $this->reader->getAllValuesIRI($object, 'http://www.w3.org/2000/01/rdf-schema#label'));
$this->assertCount(0, $this->reader->getAllValuesIRI($object, 'rdfs:label')); $this->assertCount(0, $this->reader->getAllValuesIRI($object, 'rdfs:label'));
@@ -126,8 +156,8 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
$this->assertCount(2, $this->reader->getAllValuesIRI($object, '@type')); $this->assertCount(2, $this->reader->getAllValuesIRI($object, '@type'));
$this->assertInstanceOf('ML\IRI\IRI', $this->reader->getAllValuesIRI($object, 'coid://cloudobjects.io/isVisibleTo')[0]); $this->assertInstanceOf(IRI::class, $this->reader->getAllValuesIRI($object, 'coid://cloudobjects.io/isVisibleTo')[0]);
$this->assertInstanceOf('ML\IRI\IRI', $this->reader->getAllValuesIRI($object, 'co:isVisibleTo')[0]); $this->assertInstanceOf(IRI::class, $this->reader->getAllValuesIRI($object, 'co:isVisibleTo')[0]);
$this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $this->reader->getAllValuesIRI($object, 'coid://cloudobjects.io/isVisibleTo')[0]); $this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $this->reader->getAllValuesIRI($object, 'coid://cloudobjects.io/isVisibleTo')[0]);
$this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $this->reader->getAllValuesIRI($object, 'co:isVisibleTo')[0]); $this->assertEquals(new IRI('coid://cloudobjects.io/Public'), $this->reader->getAllValuesIRI($object, 'co:isVisibleTo')[0]);
@@ -136,7 +166,7 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
public function testGetAllValuesNode1() { public function testGetAllValuesNode1() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock(); $this->useRootResourceMock();
$object = $this->retriever->getObject($coid); $object = $this->retriever->getObjectNode($coid);
$this->assertCount(0, $this->reader->getAllValuesNode($object, 'http://www.w3.org/2000/01/rdf-schema#label')); $this->assertCount(0, $this->reader->getAllValuesNode($object, 'http://www.w3.org/2000/01/rdf-schema#label'));
$this->assertCount(0, $this->reader->getAllValuesNode($object, 'rdfs:label')); $this->assertCount(0, $this->reader->getAllValuesNode($object, 'rdfs:label'));
@@ -146,8 +176,8 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
$this->assertCount(2, $this->reader->getAllValuesNode($object, '@type')); $this->assertCount(2, $this->reader->getAllValuesNode($object, '@type'));
$this->assertInstanceOf('ML\JsonLD\Node', $this->reader->getAllValuesNode($object, 'coid://cloudobjects.io/isVisibleTo')[0]); $this->assertInstanceOf(Node::class, $this->reader->getAllValuesNode($object, 'coid://cloudobjects.io/isVisibleTo')[0]);
$this->assertInstanceOf('ML\JsonLD\Node', $this->reader->getAllValuesNode($object, 'co:isVisibleTo')[0]); $this->assertInstanceOf(Node::class, $this->reader->getAllValuesNode($object, 'co:isVisibleTo')[0]);
$this->assertEquals('coid://cloudobjects.io/Public', $this->reader->getAllValuesNode($object, 'coid://cloudobjects.io/isVisibleTo')[0]->getId()); $this->assertEquals('coid://cloudobjects.io/Public', $this->reader->getAllValuesNode($object, 'coid://cloudobjects.io/isVisibleTo')[0]->getId());
$this->assertEquals('coid://cloudobjects.io/Public', $this->reader->getAllValuesNode($object, 'co:isVisibleTo')[0]->getId()); $this->assertEquals('coid://cloudobjects.io/Public', $this->reader->getAllValuesNode($object, 'co:isVisibleTo')[0]->getId());

View File

@@ -43,7 +43,7 @@ class ObjectRetrieverMockTest extends \PHPUnit\Framework\TestCase {
// Test CloudObject interface // Test CloudObject interface
$object = $this->retriever->getCloudObject($coid); $object = $this->retriever->getCloudObject($coid);
$this->assertNotNull($object); $this->assertNotNull($object);
$this->assertEquals((string)$coid, $object->getObjectNode()->getID()); $this->assertEquals((string)$coid, $object->getAsNode()->getId());
$this->assertEquals($coid, $object->getCOID()); $this->assertEquals($coid, $object->getCOID());
$this->assertNotNull($object->getString('http://www.w3.org/2000/01/rdf-schema#label')); $this->assertNotNull($object->getString('http://www.w3.org/2000/01/rdf-schema#label'));
$this->assertEquals('CloudObjects', $object->getString('http://www.w3.org/2000/01/rdf-schema#label')); $this->assertEquals('CloudObjects', $object->getString('http://www.w3.org/2000/01/rdf-schema#label'));

View File

@@ -0,0 +1,47 @@
<?php
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
namespace CloudObjects\SDK;
use ML\IRI\IRI;
use Kevinrob\GuzzleCache\Storage\VolatileRuntimeStorage;
use CloudObjects\SDK\TestHelpers\InMemoryLogger;
class ObjectRetrieverCacheTest extends \PHPUnit\Framework\TestCase {
public function testCacheInRuntimeStorage() {
$cacheStorage = new VolatileRuntimeStorage;
$logger = new InMemoryLogger;
$coid = new IRI('coid://cloudobjects.io');
$retriever = new ObjectRetriever([
'cache_storage' => $cacheStorage,
'logger' => $logger
]);
$object1 = $retriever->getCloudObject($coid);
$this->assertNotNull($object1);
$this->assertNotNull($cacheStorage->fetch($retriever->getCacheKey((string)$coid)));
$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
]);
$object2 = $retriever->getCloudObject($coid);
$this->assertNotNull($object2);
$this->assertNotNull($cacheStorage->fetch($retriever->getCacheKey((string)$coid)));
$this->assertStringContainsString('from object cache', $logger->getLastLogMessage());
$this->assertEquals($object1->getRevision(), $object2->getRevision());
}
}

View File

@@ -26,13 +26,25 @@ class ObjectRetrieverPublicTest extends \PHPUnit\Framework\TestCase {
public function testGetRootObject() { public function testGetRootObject() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$object = $this->retriever->getObject($coid); $object = $this->retriever->getObjectNode($coid);
$this->assertNotNull($object); $this->assertNotNull($object);
$this->assertEquals((string)$coid, $object->getID()); $this->assertEquals((string)$coid, $object->getId());
$this->assertNotNull($object->getProperty('http://www.w3.org/2000/01/rdf-schema#label')); $this->assertNotNull($object->getProperty('http://www.w3.org/2000/01/rdf-schema#label'));
$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 testGetRelatedObject() {
$coid = new IRI('coid://cloudobjects.io');
$object = $this->retriever->getCloudObject($coid);
$this->assertNotNull($object);
$this->assertNotNull($object->getIRI('coid://cloudobjects.io/isVisibleTo'));
$this->assertEquals('coid://cloudobjects.io/Public', $object->getString('coid://cloudobjects.io/isVisibleTo'));
$relatedObject = $object->getCloudObject('coid://cloudobjects.io/isVisibleTo');
$this->assertNotNull($relatedObject);
$this->assertEquals('coid://cloudobjects.io/Public', (string)$relatedObject->getCOID());
}
public function testGetCOIDList() { public function testGetCOIDList() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$list = $this->stringifyItems( $list = $this->stringifyItems(