12 Commits
16 changed files with 581 additions and 267 deletions
@@ -40,7 +40,7 @@ class AccountContext {
/** /**
* Create a new context using an AAUID and an OAuth 2.0 bearer access token. * Create a new context using an AAUID and an OAuth 2.0 bearer access token.
*/ */
public function __construct(IRI $aauid, $accessToken, DataLoader $dataLoader = null) { public function __construct(IRI $aauid, $accessToken, ?DataLoader $dataLoader = null) {
if (AAUIDParser::getType($aauid) != AAUIDParser::AAUID_ACCOUNT) if (AAUIDParser::getType($aauid) != AAUIDParser::AAUID_ACCOUNT)
throw new \Exception("Not a valid AAUID"); throw new \Exception("Not a valid AAUID");
+9 -9
View File
@@ -20,7 +20,7 @@ class COIDParser {
const COID_VERSIONED = 3; const COID_VERSIONED = 3;
const COID_VERSION_WILDCARD = 4; const COID_VERSION_WILDCARD = 4;
const REGEX_HOSTNAME = "/^([a-z0-9-]+\.)?[a-z0-9-]+\.[a-z]+$/"; const REGEX_HOSTNAME = "/^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]+$/";
const REGEX_SEGMENT = "/^[A-Za-z-_0-9\.]+$/"; const REGEX_SEGMENT = "/^[A-Za-z-_0-9\.]+$/";
const REGEX_VERSION_WILDCARD = "/^((\^|~)(\d+\.)?\d|(\d+\.){1,2}\*)$/"; const REGEX_VERSION_WILDCARD = "/^((\^|~)(\d+\.)?\d|(\d+\.){1,2}\*)$/";
@@ -31,7 +31,7 @@ class COIDParser {
* @param string $coidString A COID string. * @param string $coidString A COID string.
* @return IRI * @return IRI
*/ */
public static function fromString($coidString) { public static function fromString($coidString) : IRI {
$coidPre = new IRI( $coidPre = new IRI(
(strtolower(substr($coidString, 0, 7)) == 'coid://') ? $coidString : 'coid://'.$coidString (strtolower(substr($coidString, 0, 7)) == 'coid://') ? $coidString : 'coid://'.$coidString
); );
@@ -45,7 +45,7 @@ class COIDParser {
* @param IRI $coid * @param IRI $coid
* @return int|null * @return int|null
*/ */
public static function getType(IRI $coid) { public static function getType(IRI $coid) : ?int {
if ($coid->getScheme()!='coid' || $coid->getHost()=='' if ($coid->getScheme()!='coid' || $coid->getHost()==''
|| preg_match(self::REGEX_HOSTNAME, $coid->getHost()) != 1) || preg_match(self::REGEX_HOSTNAME, $coid->getHost()) != 1)
return self::COID_INVALID; return self::COID_INVALID;
@@ -79,9 +79,9 @@ class COIDParser {
* Checks whether the given IRI object is a valid COID. * Checks whether the given IRI object is a valid COID.
* *
* @param IRI $coid * @param IRI $coid
* @return boolean * @return bool
*/ */
public static function isValidCOID(IRI $coid) { public static function isValidCOID(IRI $coid) : bool {
return (self::getType($coid)!=self::COID_INVALID); return (self::getType($coid)!=self::COID_INVALID);
} }
@@ -91,7 +91,7 @@ class COIDParser {
* @param IRI $coid * @param IRI $coid
* @return string|null * @return string|null
*/ */
public static function getName(IRI $coid) { public static function getName(IRI $coid) : ?string {
if (self::getType($coid)!=self::COID_INVALID if (self::getType($coid)!=self::COID_INVALID
&& self::getType($coid)!=self::COID_ROOT) { && self::getType($coid)!=self::COID_ROOT) {
$segments = explode('/', $coid->getPath()); $segments = explode('/', $coid->getPath());
@@ -106,7 +106,7 @@ class COIDParser {
* @param IRI $coid * @param IRI $coid
* @return string|null * @return string|null
*/ */
public static function getVersion(IRI $coid) { public static function getVersion(IRI $coid) : ?string {
if (self::getType($coid)==self::COID_VERSIONED) { if (self::getType($coid)==self::COID_VERSIONED) {
$segments = explode('/', $coid->getPath()); $segments = explode('/', $coid->getPath());
return $segments[2]; return $segments[2];
@@ -121,7 +121,7 @@ class COIDParser {
* @param IRI $coid * @param IRI $coid
* @return string|null * @return string|null
*/ */
public static function getVersionWildcard(IRI $coid) { public static function getVersionWildcard(IRI $coid) : ?string {
if (self::getType($coid)==self::COID_VERSION_WILDCARD) { if (self::getType($coid)==self::COID_VERSION_WILDCARD) {
$segments = explode('/', $coid->getPath()); $segments = explode('/', $coid->getPath());
return $segments[2]; return $segments[2];
@@ -136,7 +136,7 @@ class COIDParser {
* @param IRI $coid * @param IRI $coid
* @return IRI|null * @return IRI|null
*/ */
public static function getNamespaceCOID(IRI $coid) { public static function getNamespaceCOID(IRI $coid) : ?IRI {
switch (self::getType($coid)) { switch (self::getType($coid)) {
case self::COID_ROOT: case self::COID_ROOT:
return $coid; return $coid;
+13 -6
View File
@@ -85,7 +85,7 @@ class CloudObject {
* 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.
*/ */
public function getString($property, string $default = null) : ?string { public function getString($property, ?string $default = null) : ?string {
return $this->getReader()->getFirstValueString($this->node, $property, $default); return $this->getReader()->getFirstValueString($this->node, $property, $default);
} }
@@ -93,7 +93,7 @@ class CloudObject {
* Get the value of a property as an integer. * Get the value of a property as an integer.
* If the property has multiple values, only the first is returned. * If the property has multiple values, only the first is returned.
*/ */
public function getInt($property, int $default = null) : ?int { public function getInt($property, ?int $default = null) : ?int {
return $this->getReader()->getFirstValueInt($this->node, $property, $default); return $this->getReader()->getFirstValueInt($this->node, $property, $default);
} }
@@ -101,7 +101,7 @@ class CloudObject {
* Get the value of a property as a float. * Get the value of a property as a float.
* If the property has multiple values, only the first is returned. * If the property has multiple values, only the first is returned.
*/ */
public function getFloat($property, float $default = null) : ?float { public function getFloat($property, ?float $default = null) : ?float {
return $this->getReader()->getFirstValueFloat($this->node, $property, $default); return $this->getReader()->getFirstValueFloat($this->node, $property, $default);
} }
@@ -109,7 +109,7 @@ class CloudObject {
* Get the value of a property as a boolean. * Get the value of a property as a boolean.
* If the property has multiple values, only the first is returned. * If the property has multiple values, only the first is returned.
*/ */
public function getBool($property, bool $default = null) : ?bool { public function getBool($property, ?bool $default = null) : ?bool {
return $this->getReader()->getFirstValueBool($this->node, $property, $default); return $this->getReader()->getFirstValueBool($this->node, $property, $default);
} }
@@ -117,7 +117,7 @@ class CloudObject {
* Get the value of a property as an IRI. * Get the value of a property as an IRI.
* If the property has multiple values, only the first is returned. * If the property has multiple values, only the first is returned.
*/ */
public function getIRI($property, IRI $default = null) : ?IRI { public function getIRI($property, ?IRI $default = null) : ?IRI {
return $this->getReader()->getFirstValueIRI($this->node, $property, $default); return $this->getReader()->getFirstValueIRI($this->node, $property, $default);
} }
@@ -125,7 +125,7 @@ class CloudObject {
* Get the value of a property as a Node. * Get the value of a property as a Node.
* If the property has multiple values, only the first is returned. * If the property has multiple values, only the first is returned.
*/ */
public function getNode($property, Node $default = null) : ?Node { public function getNode($property, ?Node $default = null) : ?Node {
return $this->getReader()->getFirstValueNode($this->node, $property, $default); return $this->getReader()->getFirstValueNode($this->node, $property, $default);
} }
@@ -166,4 +166,11 @@ class CloudObject {
return $this->getString(Constants::PROPERTY_REVISION); return $this->getString(Constants::PROPERTY_REVISION);
} }
/**
* Get the label of the object.
*/
public function getLabel() : ?string {
return $this->getString(Constants::RDFS_LABEL);
}
} }
+1 -1
View File
@@ -53,7 +53,7 @@ class CryptoHelper {
* @param ObjectRetriever $objectRetriever An initialized and authenticated object retriever. * @param ObjectRetriever $objectRetriever An initialized and authenticated object retriever.
* @param IRI|null $namespaceCoid The namespace used to retrieve keys. If this parameter is not provided, the namespace provided with the "auth_ns" configuration option from the object retriever is used. * @param IRI|null $namespaceCoid The namespace used to retrieve keys. If this parameter is not provided, the namespace provided with the "auth_ns" configuration option from the object retriever is used.
*/ */
public function __construct(ObjectRetriever $objectRetriever, IRI $namespaceCoid = null) { public function __construct(ObjectRetriever $objectRetriever, ?IRI $namespaceCoid = null) {
if (!class_exists('Defuse\Crypto\Crypto')) if (!class_exists('Defuse\Crypto\Crypto'))
throw new Exception("Run composer require defuse/php-encryption before using CryptoHelper."); throw new Exception("Run composer require defuse/php-encryption before using CryptoHelper.");
+1
View File
@@ -9,5 +9,6 @@ namespace CloudObjects\SDK;
class Constants { class Constants {
const PROPERTY_REVISION = 'coid://cloudobjects.io/isAtRevision'; const PROPERTY_REVISION = 'coid://cloudobjects.io/isAtRevision';
const RDFS_LABEL = 'http://www.w3.org/2000/01/rdf-schema#label';
} }
+38 -4
View File
@@ -7,6 +7,7 @@
namespace CloudObjects\SDK\Helpers; namespace CloudObjects\SDK\Helpers;
use Exception; use Exception;
use CloudObjects\SDK\Exceptions\InvalidSDKConfigurationException;
use CloudObjects\SDK\NodeReader, CloudObjects\SDK\ObjectRetriever; use CloudObjects\SDK\NodeReader, CloudObjects\SDK\ObjectRetriever;
/** /**
@@ -27,20 +28,53 @@ class SDKLoader {
$this->reader = new NodeReader; $this->reader = new NodeReader;
} }
/**
* Initialize the SDK with the given name and options; used for
* SDKs that are initialized with a function and not a class name.
*
* @param string $sdkName The name of the SDK to initialize.
* @param array $options Additional options for the SDK (if necessary).
* @return mixed The return value of the SDK initialization, which may vary depending on the SDK.
* @throws Exception If the SDK is not supported or cannot be initialized.
*/
public function init(string $sdkName, array $options = []) : mixed {
$namespace = $this->objectRetriever->getAuthenticatingNamespaceCloudObject();
if (!$namespace)
throw new InvalidSDKConfigurationException("The authenticating namespace object could not be retrieved.");
switch (strtolower($sdkName)) {
case "sentry":
// --- Sentry (https://sentry.io/) ---
$initFunction = '\Sentry\init';
return $initFunction(array_merge([
'dsn' => $namespace->getString('coid://sentry.io.3rd-party.co/DSN')
], $options));
default:
throw new Exception("No rules defined to initialize SDK with name <".$sdkName.">.");
}
}
/** /**
* Initialize and return the SDK with the given classname. * Initialize and return the SDK with the given classname.
* Throws Exception if the SDK is not supported. * Throws Exception if the SDK is not supported.
* *
* @param $classname Classname for the SDK's main class * @param string $classname Classname for the SDK's main class.
* @param array $options Additional options for the SDK (if necessary) * @param array $options Additional options for the SDK (if necessary).
* @return mixed The initialized SDK instance.
* @throws Exception If the SDK is not supported or cannot be initialized.
*/ */
public function get($classname, array $options) { public function get(string $classname, array $options) : mixed {
if (!class_exists($classname)) if (!class_exists($classname))
throw new Exception("<".$classname."> is not a valid classname."); throw new Exception("<".$classname."> is not a valid classname.");
$hashkey = md5($classname.serialize($options)); $hashkey = md5($classname.serialize($options));
if (!isset($this->classes[$hashkey])) { if (!isset($this->classes[$hashkey])) {
$nsNode = $this->objectRetriever->getAuthenticatingNamespaceObject(); $nsNode = $this->objectRetriever->getAuthenticatingNamespaceObjectNode();
if (!$nsNode)
throw new InvalidSDKConfigurationException("The authenticating namespace object could not be retrieved.");
// --- Amazon Web Services (https://aws.amazon.com/) --- // --- Amazon Web Services (https://aws.amazon.com/) ---
// has multiple classnames, so check for common superclass // has multiple classnames, so check for common superclass
+18 -18
View File
@@ -38,7 +38,7 @@ class NodeReader {
* @param string|object $type The type to check for. * @param string|object $type The type to check for.
* @return boolean * @return boolean
*/ */
public function hasType(Node $node = null, $type) { public function hasType(?Node $node = null, $type) {
if (!isset($node)) if (!isset($node))
return false; return false;
$type = $this->expand($type); $type = $this->expand($type);
@@ -60,7 +60,7 @@ class NodeReader {
return false; return false;
} }
private function getFirstValue(Node $node = null, $property, $default = null) { private function getFirstValue(?Node $node = null, $property, $default = null) {
if (!isset($node)) if (!isset($node))
return $default; return $default;
$valueFromNode = $node->getProperty($this->expand($property)); $valueFromNode = $node->getProperty($this->expand($property));
@@ -82,7 +82,7 @@ class NodeReader {
* @param $default The default that is returned if no value for the property exists on the node. * @param $default The default that is returned if no value for the property exists on the node.
* @return string|null * @return string|null
*/ */
public function getFirstValueString(Node $node = null, $property, $default = null) { public function getFirstValueString(?Node $node = null, $property, $default = null) {
$valueFromNode = $this->getFirstValue($node, $property, $default); $valueFromNode = $this->getFirstValue($node, $property, $default);
if ($valueFromNode == $default) if ($valueFromNode == $default)
return $default; return $default;
@@ -103,7 +103,7 @@ class NodeReader {
* @param $default The default that is returned if no value for the property exists on the node. * @param $default The default that is returned if no value for the property exists on the node.
* @return bool|null * @return bool|null
*/ */
public function getFirstValueBool(Node $node = null, $property, $default = null) { public function getFirstValueBool(?Node $node = null, $property, $default = null) {
return (in_array( return (in_array(
$this->getFirstValueString($node, $property, $default), $this->getFirstValueString($node, $property, $default),
[ '1', 'true' ] [ '1', 'true' ]
@@ -120,7 +120,7 @@ class NodeReader {
* @param $default The default that is returned if no value for the property exists on the node. * @param $default The default that is returned if no value for the property exists on the node.
* @return int|null * @return int|null
*/ */
public function getFirstValueInt(Node $node = null, $property, $default = null) { public function getFirstValueInt(?Node $node = null, $property, $default = null) {
$value = $this->getFirstValueString($node, $property); $value = $this->getFirstValueString($node, $property);
if (is_numeric($value)) if (is_numeric($value))
return (int)($value); return (int)($value);
@@ -138,7 +138,7 @@ class NodeReader {
* @param $default The default that is returned if no value for the property exists on the node. * @param $default The default that is returned if no value for the property exists on the node.
* @return float|null * @return float|null
*/ */
public function getFirstValueFloat(Node $node = null, $property, $default = null) { public function getFirstValueFloat(?Node $node = null, $property, $default = null) {
$value = $this->getFirstValueString($node, $property); $value = $this->getFirstValueString($node, $property);
if (is_numeric($value)) if (is_numeric($value))
return (float)($value); return (float)($value);
@@ -156,7 +156,7 @@ class NodeReader {
* @param $default The default that is returned if no value for the property exists on the node. * @param $default The default that is returned if no value for the property exists on the node.
* @return string|null * @return string|null
*/ */
public function getFirstValueIRI(Node $node = null, $property, IRI $default = null) { public function getFirstValueIRI(?Node $node = null, $property, ?IRI $default = null) {
$valueFromNode = $this->getFirstValue($node, $property, $default); $valueFromNode = $this->getFirstValue($node, $property, $default);
if ($valueFromNode == $default) if ($valueFromNode == $default)
return $default; return $default;
@@ -177,7 +177,7 @@ class NodeReader {
* @param $default The default that is returned if no value for the property exists on the node. * @param $default The default that is returned if no value for the property exists on the node.
* @return string|null * @return string|null
*/ */
public function getFirstValueNode(Node $node = null, $property, Node $default = null) { public function getFirstValueNode(?Node $node = null, $property, ?Node $default = null) {
$valueFromNode = $this->getFirstValue($node, $property, $default); $valueFromNode = $this->getFirstValue($node, $property, $default);
if ($valueFromNode == $default) if ($valueFromNode == $default)
return $default; return $default;
@@ -196,7 +196,7 @@ class NodeReader {
* @param string|object $value The expected value. * @param string|object $value The expected value.
* @return boolean * @return boolean
*/ */
public function hasPropertyValue(Node $node = null, $property, $value) { public function hasPropertyValue(?Node $node = null, $property, $value) {
if (!isset($node)) if (!isset($node))
return false; return false;
$valuesFromNode = $node->getProperty($this->expand($property)); $valuesFromNode = $node->getProperty($this->expand($property));
@@ -225,14 +225,14 @@ class NodeReader {
* @param string|object $property The property to read. * @param string|object $property The property to read.
* @return boolean * @return boolean
*/ */
public function hasProperty(Node $node = null, $property) { public function hasProperty(?Node $node = null, $property) {
if (!isset($node)) if (!isset($node))
return false; return false;
return ($node->getProperty($this->expand($property)) != null); return ($node->getProperty($this->expand($property)) != null);
} }
private function getAllValues(Node $node = null, $property) { private function getAllValues(?Node $node = null, $property) {
if (!isset($node)) if (!isset($node))
return []; return [];
@@ -248,7 +248,7 @@ class NodeReader {
* Get the language-tagged-string for the property in the specified language. * Get the language-tagged-string for the property in the specified language.
* If no value is found for the specified language, the default is returned. * If no value is found for the specified language, the default is returned.
*/ */
public function getLocalizedString(Node $node = null, $property, $language, $default = null) { public function getLocalizedString(?Node $node = null, $property, $language, $default = null) {
$values = $this->getAllValues($node, $property); $values = $this->getAllValues($node, $property);
foreach ($values as $v) { foreach ($values as $v) {
if (is_a($v, 'ML\JsonLD\LanguageTaggedString') && $v->getLanguage() == $language) if (is_a($v, 'ML\JsonLD\LanguageTaggedString') && $v->getLanguage() == $language)
@@ -265,7 +265,7 @@ class NodeReader {
* @param string|object $property The property to read. * @param string|object $property The property to read.
* @return array<string> * @return array<string>
*/ */
public function getAllValuesString(Node $node = null, $property) { public function getAllValuesString(?Node $node = null, $property) {
$allValues = $this->getAllValues($node, $property); $allValues = $this->getAllValues($node, $property);
$output = []; $output = [];
foreach ($allValues as $a) foreach ($allValues as $a)
@@ -284,7 +284,7 @@ class NodeReader {
* @param string|object $property The property to read. * @param string|object $property The property to read.
* @return array<bool> * @return array<bool>
*/ */
public function getAllValuesBool(Node $node = null, $property) { public function getAllValuesBool(?Node $node = null, $property) {
$allValues = $this->getAllValuesString($node, $property); $allValues = $this->getAllValuesString($node, $property);
$output = []; $output = [];
foreach ($allValues as $a) foreach ($allValues as $a)
@@ -300,7 +300,7 @@ class NodeReader {
* @param string|object $property The property to read. * @param string|object $property The property to read.
* @return array<bool> * @return array<bool>
*/ */
public function getAllValuesInt(Node $node = null, $property) { public function getAllValuesInt(?Node $node = null, $property) {
$allValues = $this->getAllValuesString($node, $property); $allValues = $this->getAllValuesString($node, $property);
$output = []; $output = [];
foreach ($allValues as $a) foreach ($allValues as $a)
@@ -316,7 +316,7 @@ class NodeReader {
* @param string|object $property The property to read. * @param string|object $property The property to read.
* @return array<bool> * @return array<bool>
*/ */
public function getAllValuesFloat(Node $node = null, $property) { public function getAllValuesFloat(?Node $node = null, $property) {
$allValues = $this->getAllValuesString($node, $property); $allValues = $this->getAllValuesString($node, $property);
$output = []; $output = [];
foreach ($allValues as $a) foreach ($allValues as $a)
@@ -333,7 +333,7 @@ class NodeReader {
* @param string|object $property The property to read. * @param string|object $property The property to read.
* @return array<IRI> * @return array<IRI>
*/ */
public function getAllValuesIRI(Node $node = null, $property) { public function getAllValuesIRI(?Node $node = null, $property) {
$allValues = $this->getAllValues($node, $property); $allValues = $this->getAllValues($node, $property);
$output = []; $output = [];
foreach ($allValues as $a) foreach ($allValues as $a)
@@ -351,7 +351,7 @@ class NodeReader {
* @param string|object $property The property to read. * @param string|object $property The property to read.
* @return array<Node> * @return array<Node>
*/ */
public function getAllValuesNode(Node $node = null, $property) { public function getAllValuesNode(?Node $node = null, $property) {
$allValues = $this->getAllValues($node, $property); $allValues = $this->getAllValues($node, $property);
$output = []; $output = [];
foreach ($allValues as $a) foreach ($allValues as $a)
+5 -5
View File
@@ -206,7 +206,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
/** /**
* Get an object description and return a CloudObject. * Get an object description and return a CloudObject.
*/ */
public function getCloudObject(IRI $coid) : CloudObject { public function getCloudObject(IRI $coid) : ?CloudObject {
$node = $this->getObjectNode($coid); $node = $this->getObjectNode($coid);
if (!$node) { if (!$node) {
// Object not found // Object not found
@@ -239,7 +239,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
* @param IRI $coid COID of the object * @param IRI $coid COID of the object
* @return Node|null * @return Node|null
*/ */
public function getObjectNode(IRI $coid) : Node { public function getObjectNode(IRI $coid) : ?Node {
if (!COIDParser::isValidCOID($coid)) if (!COIDParser::isValidCOID($coid))
throw new Exception("Not a valid COID."); throw new Exception("Not a valid COID.");
@@ -536,7 +536,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
* @deprecated Use getAuthenticatingNamespaceObjectNode() instead * @deprecated Use getAuthenticatingNamespaceObjectNode() instead
* @return Node * @return Node
*/ */
public function getAuthenticatingNamespaceObject() : Node { public function getAuthenticatingNamespaceObject() : ?Node {
return $this->getObject($this->assertAuthenticatingNamespaceAndGetId()); return $this->getObject($this->assertAuthenticatingNamespaceAndGetId());
} }
@@ -546,7 +546,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
* *
* @return Node * @return Node
*/ */
public function getAuthenticatingNamespaceObjectNode() : Node { public function getAuthenticatingNamespaceObjectNode() : ?Node {
return $this->getObject($this->assertAuthenticatingNamespaceAndGetId()); return $this->getObject($this->assertAuthenticatingNamespaceAndGetId());
} }
@@ -556,7 +556,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
* *
* @return CloudObject * @return CloudObject
*/ */
public function getAuthenticatingNamespaceCloudObject() : CloudObject { public function getAuthenticatingNamespaceCloudObject() : ?CloudObject {
return $this->getCloudObject($this->assertAuthenticatingNamespaceAndGetId()); return $this->getCloudObject($this->assertAuthenticatingNamespaceAndGetId());
} }
@@ -0,0 +1,80 @@
<?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 Exception;
use ML\IRI\IRI;
use ML\JsonLD\Node;
/**
* Static facade for ObjectRetriever. Call setObjectRetriever() once to
* initialize; all subsequent static calls are forwarded to that instance.
*/
class ObjectRetrieverFacade {
private static ?ObjectRetriever $instance = null;
public static function setObjectRetriever(ObjectRetriever $retriever) : void {
self::$instance = $retriever;
}
private static function getInstance() : ObjectRetriever {
if (self::$instance === null)
throw new Exception('ObjectRetrieverFacade has not been initialized. Call setObjectRetriever() first.');
return self::$instance;
}
public static function setDefaultReader(NodeReader $reader) : ObjectRetriever {
return self::getInstance()->setDefaultReader($reader);
}
public static function getDefaultReader() : NodeReader {
return self::getInstance()->getDefaultReader();
}
public static function getClient() {
return self::getInstance()->getClient();
}
public static function getCloudObject(IRI $coid) : ?CloudObject {
return self::getInstance()->getCloudObject($coid);
}
public static function getObjectNode(IRI $coid) : ?Node {
return self::getInstance()->getObjectNode($coid);
}
public static function fetchObjectsInNamespaceWithType(IRI $namespaceCoid, $type) : array {
return self::getInstance()->fetchObjectsInNamespaceWithType($namespaceCoid, $type);
}
public static function fetchAllObjectsInNamespace(IRI $namespaceCoid) : array {
return self::getInstance()->fetchAllObjectsInNamespace($namespaceCoid);
}
public static function getCOIDListForNamespace(IRI $namespaceCoid) : array {
return self::getInstance()->getCOIDListForNamespace($namespaceCoid);
}
public static function getCOIDListForNamespaceWithType(IRI $namespaceCoid, $type) : array {
return self::getInstance()->getCOIDListForNamespaceWithType($namespaceCoid, $type);
}
public static function getAttachment(IRI $coid, $filename) {
return self::getInstance()->getAttachment($coid, $filename);
}
public static function getAuthenticatingNamespaceObjectNode() : ?Node {
return self::getInstance()->getAuthenticatingNamespaceObjectNode();
}
public static function getAuthenticatingNamespaceCloudObject() : ?CloudObject {
return self::getInstance()->getAuthenticatingNamespaceCloudObject();
}
}
+1 -1
View File
@@ -217,7 +217,7 @@ class APIClientFactory {
* @param ObjectRetriever $objectRetriever An initialized and authenticated object retriever. * @param ObjectRetriever $objectRetriever An initialized and authenticated object retriever.
* @param IRI|null $namespaceCoid The namespace of the API client. Used to retrieve credentials. If this parameter is not provided, the namespace provided with the "auth_ns" configuration option from the object retriever is used. * @param IRI|null $namespaceCoid The namespace of the API client. Used to retrieve credentials. If this parameter is not provided, the namespace provided with the "auth_ns" configuration option from the object retriever is used.
*/ */
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->getObjectNode($namespaceCoid) ? $objectRetriever->getObjectNode($namespaceCoid)
+6 -3
View File
@@ -19,9 +19,12 @@
} }
], ],
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"CloudObjects\\SDK" : "" "CloudObjects\\SDK\\" : "CloudObjects/SDK/"
} },
"files": [
"functions.php"
]
}, },
"require-dev" : { "require-dev" : {
"phpunit/phpunit": "^10", "phpunit/phpunit": "^10",
+23
View File
@@ -0,0 +1,23 @@
<?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/. */
use ML\IRI\IRI;
use CloudObjects\SDK\CloudObject,
CloudObjects\SDK\ObjectRetrieverFacade;
if (!function_exists('cloudobjects_get_object')) {
/**
* Retrieve a CloudObject by COID. Accepts a COID as an IRI object or a string.
*/
function cloudobjects_get_object($coid) : ?CloudObject {
if (is_string($coid))
$coid = new IRI($coid);
elseif (!($coid instanceof IRI))
throw new InvalidArgumentException('COID must be a string or an IRI object.');
return ObjectRetrieverFacade::getCloudObject($coid);
}
}
+21 -3
View File
@@ -13,13 +13,21 @@ class COIDParserTest extends \PHPUnit\Framework\TestCase {
public function testRootCOID() { public function testRootCOID() {
$coid = new IRI('coid://example.com'); $coid = new IRI('coid://example.com');
$this->assertEquals(COIDParser::COID_ROOT, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_ROOT, COIDParser::getType($coid));
$coid = new IRI('coid://subdomain.example.com');
$this->assertEquals(COIDParser::COID_ROOT, COIDParser::getType($coid));
$coid = new IRI('coid://anotherlevel.subdomain.example.com');
$this->assertEquals(COIDParser::COID_ROOT, COIDParser::getType($coid));
} }
public function testInvalidRootCOID() { public function testInvalidRootCOID() {
$coid = new IRI('coid://example'); $coid = new IRI('coid://example');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
$coid = new IRI('coid://exämple.com'); $coid = new IRI('coid://exämple.com');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
$coid = new IRI('coid://ex&mple.com'); $coid = new IRI('coid://ex&mple.com');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
} }
@@ -27,34 +35,41 @@ class COIDParserTest extends \PHPUnit\Framework\TestCase {
public function testInvalidCOID() { public function testInvalidCOID() {
$coid = new IRI('http://example.com'); $coid = new IRI('http://example.com');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
$coid = new IRI('example.com'); $coid = new IRI('example.com');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
$coid = new IRI('COID://example.com'); $coid = new IRI('COID://example.com');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
$coid = new IRI('Coid://example.com'); $coid = new IRI('Coid://example.com');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
$coid = new IRI('coid://EXAMPLE.COM'); $coid = new IRI('coid://EXAMPLE.COM');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
$coid = new IRI('coid://exAMPle.CoM'); $coid = new IRI('coid://exAMPle.CoM');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
} }
public function testUnversionedCOID() { public function testUnversionedCOID() {
$coid = new IRI('coid://example.com/Example'); $coid = new IRI('coid://subdomain.example.com/Example');
$this->assertEquals(COIDParser::COID_UNVERSIONED, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_UNVERSIONED, COIDParser::getType($coid));
} }
public function testInvalidUnversionedCOID() { public function testInvalidUnversionedCOID() {
$coid = new IRI('coid://example.com/Exümple'); $coid = new IRI('coid://example.com/Exümple');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
$coid = new IRI('coid://example.com/Examp%e'); $coid = new IRI('coid://example.com/Examp%e');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
} }
public function testVersionedCOID() { public function testVersionedCOID() {
$coid = new IRI('coid://example.com/Example/1.0'); $coid = new IRI('coid://anotherlevel.subdomain.example.com/Example/1.0');
$this->assertEquals(COIDParser::COID_VERSIONED, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_VERSIONED, COIDParser::getType($coid));
$coid = new IRI('coid://example.com/Example/alpha');
$coid = new IRI('coid://subdomain.example.com/Example/alpha');
$this->assertEquals(COIDParser::COID_VERSIONED, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_VERSIONED, COIDParser::getType($coid));
} }
@@ -66,8 +81,10 @@ class COIDParserTest extends \PHPUnit\Framework\TestCase {
public function testVersionWildcardCOID() { public function testVersionWildcardCOID() {
$coid = new IRI('coid://example.com/Example/^1.0'); $coid = new IRI('coid://example.com/Example/^1.0');
$this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid));
$coid = new IRI('coid://example.com/Example/~1.0'); $coid = new IRI('coid://example.com/Example/~1.0');
$this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid));
$coid = new IRI('coid://example.com/Example/1.*'); $coid = new IRI('coid://example.com/Example/1.*');
$this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid));
} }
@@ -75,6 +92,7 @@ class COIDParserTest extends \PHPUnit\Framework\TestCase {
public function testInvalidVersionWildcardCOID() { public function testInvalidVersionWildcardCOID() {
$coid = new IRI('coid://example.com/Example/^1.*'); $coid = new IRI('coid://example.com/Example/^1.*');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
$coid = new IRI('coid://example.com/Example/1.a.*'); $coid = new IRI('coid://example.com/Example/1.a.*');
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
} }
+63
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;
use ML\IRI\IRI;
use ReflectionProperty,
InvalidArgumentException;
class FunctionsTest extends \PHPUnit\Framework\TestCase {
protected function setUp(): void {
$prop = new ReflectionProperty(ObjectRetrieverFacade::class, 'instance');
$prop->setAccessible(true);
$prop->setValue(null, null);
}
private function makeMockRetrieverReturning(?CloudObject $object) : ObjectRetriever {
$mock = $this->createMock(ObjectRetriever::class);
$mock->method('getCloudObject')->willReturn($object);
return $mock;
}
public function testAcceptsIRI(): void {
$coid = new IRI('coid://cloudobjects.io');
$mockObject = $this->createMock(CloudObject::class);
$mockRetriever = $this->createMock(ObjectRetriever::class);
$mockRetriever->expects($this->once())
->method('getCloudObject')
->with($coid)
->willReturn($mockObject);
ObjectRetrieverFacade::setObjectRetriever($mockRetriever);
$this->assertSame($mockObject, cloudobjects_get_object($coid));
}
public function testConvertsStringToIRI(): void {
$mockObject = $this->createMock(CloudObject::class);
$mockRetriever = $this->createMock(ObjectRetriever::class);
$mockRetriever->expects($this->once())
->method('getCloudObject')
->with($this->callback(fn($arg) => $arg instanceof IRI && (string)$arg === 'coid://cloudobjects.io'))
->willReturn($mockObject);
ObjectRetrieverFacade::setObjectRetriever($mockRetriever);
$this->assertSame($mockObject, cloudobjects_get_object('coid://cloudobjects.io'));
}
public function testThrowsOnInvalidArgumentType(): void {
ObjectRetrieverFacade::setObjectRetriever($this->makeMockRetrieverReturning(null));
$this->expectException(InvalidArgumentException::class);
cloudobjects_get_object(42);
}
}
@@ -126,6 +126,15 @@ class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals('coid://cloudobjects.io/Public', $object->getNode('co:isVisibleTo')->getId()); $this->assertEquals('coid://cloudobjects.io/Public', $object->getNode('co:isVisibleTo')->getId());
} }
public function testConstants() {
$coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock();
$object = $this->retriever->getCloudObject($coid);
$this->assertEquals('6-fbea0c90b2c5e5300e4039ed99be9b2d', $object->getRevision());
$this->assertEquals('CloudObjects', $object->getLabel());
}
public function testGetAllValuesString1() { public function testGetAllValuesString1() {
$coid = new IRI('coid://cloudobjects.io'); $coid = new IRI('coid://cloudobjects.io');
$this->useRootResourceMock(); $this->useRootResourceMock();
@@ -0,0 +1,76 @@
<?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 Exception;
use ML\IRI\IRI;
use ML\JsonLD\Node;
use ReflectionProperty;
class ObjectRetrieverFacadeTest extends \PHPUnit\Framework\TestCase {
protected function setUp(): void {
$prop = new ReflectionProperty(ObjectRetrieverFacade::class, 'instance');
$prop->setAccessible(true);
$prop->setValue(null, null);
}
public function testThrowsExceptionBeforeInitialization(): void {
$this->expectException(Exception::class);
ObjectRetrieverFacade::getObjectNode(new IRI('coid://cloudobjects.io'));
}
public function testForwardsGetObjectNodeToInstance(): void {
$coid = new IRI('coid://cloudobjects.io');
$mockNode = $this->createMock(Node::class);
$mockRetriever = $this->createMock(ObjectRetriever::class);
$mockRetriever->expects($this->once())
->method('getObjectNode')
->with($coid)
->willReturn($mockNode);
ObjectRetrieverFacade::setObjectRetriever($mockRetriever);
$this->assertSame($mockNode, ObjectRetrieverFacade::getObjectNode($coid));
}
public function testForwardsGetCloudObjectToInstance(): void {
$coid = new IRI('coid://cloudobjects.io');
$mockCloudObject = $this->createMock(CloudObject::class);
$mockRetriever = $this->createMock(ObjectRetriever::class);
$mockRetriever->expects($this->once())
->method('getCloudObject')
->with($coid)
->willReturn($mockCloudObject);
ObjectRetrieverFacade::setObjectRetriever($mockRetriever);
$this->assertSame($mockCloudObject, ObjectRetrieverFacade::getCloudObject($coid));
}
public function testReplacingRetrieverUsesNewInstance(): void {
$coid = new IRI('coid://cloudobjects.io');
$mockNode = $this->createMock(Node::class);
$firstRetriever = $this->createMock(ObjectRetriever::class);
$firstRetriever->expects($this->never())->method('getObjectNode');
$secondRetriever = $this->createMock(ObjectRetriever::class);
$secondRetriever->expects($this->once())
->method('getObjectNode')
->with($coid)
->willReturn($mockNode);
ObjectRetrieverFacade::setObjectRetriever($firstRetriever);
ObjectRetrieverFacade::setObjectRetriever($secondRetriever);
$this->assertSame($mockNode, ObjectRetrieverFacade::getObjectNode($coid));
}
}