Compare commits
30 Commits
0.9
...
ce77709d37
| Author | SHA1 | Date | |
|---|---|---|---|
| ce77709d37 | |||
| a7eb83be44 | |||
| 3653513818 | |||
| 58df9cb476 | |||
| 3c958dc5df | |||
| 993218f21d | |||
| aa37259a21 | |||
| 69a16e64d1 | |||
| cb03c811ef | |||
| 6f3c7338c7 | |||
| da0ddd572e | |||
| 5f5a31df68 | |||
| 58585a6875 | |||
| 23f00b2374 | |||
| 9f339953fe | |||
| d5d766cbf4 | |||
| 06df8b0be1 | |||
| de355ff2f9 | |||
| 7d8ece0df1 | |||
| 1122b9faf5 | |||
| 0cb2655494 | |||
| a9689d5a2b | |||
| 6cb8a9d603 | |||
| 4724c4988e | |||
| bb738a1d79 | |||
| fd029a79bf | |||
| 2954d9fc99 | |||
| f29af2b664 | |||
| 5584f10462 | |||
| f937f2b426 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -4,4 +4,7 @@ cache
|
|||||||
.cache
|
.cache
|
||||||
.config
|
.config
|
||||||
.local
|
.local
|
||||||
*.phar
|
*.phar
|
||||||
|
.composer
|
||||||
|
.phpunit*
|
||||||
|
.bash_history
|
||||||
@@ -13,140 +13,140 @@ use ML\IRI\IRI;
|
|||||||
*/
|
*/
|
||||||
class COIDParser {
|
class COIDParser {
|
||||||
|
|
||||||
const COID_INVALID = 0;
|
const COID_INVALID = 0;
|
||||||
|
|
||||||
const COID_ROOT = 1;
|
const COID_ROOT = 1;
|
||||||
const COID_UNVERSIONED = 2;
|
const COID_UNVERSIONED = 2;
|
||||||
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}\*)$/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new IRI object representing a COID from a string.
|
* Creates a new IRI object representing a COID from a string.
|
||||||
* Adds the "coid://" prefix if necessary and normalizes case.
|
* Adds the "coid://" prefix if necessary and normalizes case.
|
||||||
*
|
*
|
||||||
* @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
|
||||||
);
|
);
|
||||||
// Normalize scheme and host segments to lower case
|
// Normalize scheme and host segments to lower case
|
||||||
return new IRI('coid://'.strtolower($coidPre->getHost()).$coidPre->getPath());
|
return new IRI('coid://'.strtolower($coidPre->getHost()).$coidPre->getPath());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the type of a COID.
|
|
||||||
*
|
|
||||||
* @param IRI $coid
|
|
||||||
* @return int|null
|
|
||||||
*/
|
|
||||||
public static function getType(IRI $coid) {
|
|
||||||
if ($coid->getScheme()!='coid' || $coid->getHost()==''
|
|
||||||
|| preg_match(self::REGEX_HOSTNAME, $coid->getHost()) != 1)
|
|
||||||
return self::COID_INVALID;
|
|
||||||
|
|
||||||
if ($coid->getPath()=='' || $coid->getPath()=='/')
|
|
||||||
return self::COID_ROOT;
|
|
||||||
|
|
||||||
$segments = explode('/', $coid->getPath());
|
|
||||||
switch (count($segments)) {
|
|
||||||
case 2:
|
|
||||||
return (preg_match(self::REGEX_SEGMENT, $segments[1]) == 1)
|
|
||||||
? self::COID_UNVERSIONED
|
|
||||||
: self::COID_INVALID;
|
|
||||||
case 3:
|
|
||||||
if (preg_match(self::REGEX_SEGMENT, $segments[1]) != 1)
|
|
||||||
return self::COID_INVALID;
|
|
||||||
|
|
||||||
if (preg_match(self::REGEX_SEGMENT, $segments[2]) == 1)
|
|
||||||
return self::COID_VERSIONED;
|
|
||||||
else
|
|
||||||
if (preg_match(self::REGEX_VERSION_WILDCARD, $segments[2]) == 1)
|
|
||||||
return self::COID_VERSION_WILDCARD;
|
|
||||||
else
|
|
||||||
return self::COID_INVALID;
|
|
||||||
default:
|
|
||||||
return self::COID_INVALID;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the given IRI object is a valid COID.
|
* Get the type of a COID.
|
||||||
*
|
*
|
||||||
* @param IRI $coid
|
* @param IRI $coid
|
||||||
* @return boolean
|
* @return int|null
|
||||||
*/
|
*/
|
||||||
public static function isValidCOID(IRI $coid) {
|
public static function getType(IRI $coid) : ?int {
|
||||||
return (self::getType($coid)!=self::COID_INVALID);
|
if ($coid->getScheme()!='coid' || $coid->getHost()==''
|
||||||
}
|
|| preg_match(self::REGEX_HOSTNAME, $coid->getHost()) != 1)
|
||||||
|
return self::COID_INVALID;
|
||||||
|
|
||||||
/**
|
if ($coid->getPath()=='' || $coid->getPath()=='/')
|
||||||
* Get the name segment of a valid COID or null if not available.
|
return self::COID_ROOT;
|
||||||
*
|
|
||||||
* @param IRI $coid
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public static function getName(IRI $coid) {
|
|
||||||
if (self::getType($coid)!=self::COID_INVALID
|
|
||||||
&& self::getType($coid)!=self::COID_ROOT) {
|
|
||||||
$segments = explode('/', $coid->getPath());
|
|
||||||
return $segments[1];
|
|
||||||
} else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$segments = explode('/', $coid->getPath());
|
||||||
* Get the version segment of a valid, versioned COID or null if not available.
|
switch (count($segments)) {
|
||||||
*
|
case 2:
|
||||||
* @param IRI $coid
|
return (preg_match(self::REGEX_SEGMENT, $segments[1]) == 1)
|
||||||
* @return string|null
|
? self::COID_UNVERSIONED
|
||||||
*/
|
: self::COID_INVALID;
|
||||||
public static function getVersion(IRI $coid) {
|
case 3:
|
||||||
if (self::getType($coid)==self::COID_VERSIONED) {
|
if (preg_match(self::REGEX_SEGMENT, $segments[1]) != 1)
|
||||||
$segments = explode('/', $coid->getPath());
|
return self::COID_INVALID;
|
||||||
return $segments[2];
|
|
||||||
} else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (preg_match(self::REGEX_SEGMENT, $segments[2]) == 1)
|
||||||
* Get the version segment of a versioned or version wildcard COID or
|
return self::COID_VERSIONED;
|
||||||
* null if not available.
|
else
|
||||||
*
|
if (preg_match(self::REGEX_VERSION_WILDCARD, $segments[2]) == 1)
|
||||||
* @param IRI $coid
|
return self::COID_VERSION_WILDCARD;
|
||||||
* @return string|null
|
else
|
||||||
*/
|
return self::COID_INVALID;
|
||||||
public static function getVersionWildcard(IRI $coid) {
|
default:
|
||||||
if (self::getType($coid)==self::COID_VERSION_WILDCARD) {
|
return self::COID_INVALID;
|
||||||
$segments = explode('/', $coid->getPath());
|
}
|
||||||
return $segments[2];
|
}
|
||||||
} else
|
|
||||||
return null;
|
/**
|
||||||
}
|
* Checks whether the given IRI object is a valid COID.
|
||||||
|
*
|
||||||
/**
|
* @param IRI $coid
|
||||||
* Returns the COID itself if it is a root COID or a new IRI object
|
* @return bool
|
||||||
* representing the namespace underlying the given COID.
|
*/
|
||||||
*
|
public static function isValidCOID(IRI $coid) : bool {
|
||||||
* @param IRI $coid
|
return (self::getType($coid)!=self::COID_INVALID);
|
||||||
* @return IRI|null
|
}
|
||||||
*/
|
|
||||||
public static function getNamespaceCOID(IRI $coid) {
|
/**
|
||||||
switch (self::getType($coid)) {
|
* Get the name segment of a valid COID or null if not available.
|
||||||
case self::COID_ROOT:
|
*
|
||||||
return $coid;
|
* @param IRI $coid
|
||||||
case self::COID_UNVERSIONED:
|
* @return string|null
|
||||||
case self::COID_VERSIONED:
|
*/
|
||||||
case self::COID_VERSION_WILDCARD:
|
public static function getName(IRI $coid) : ?string {
|
||||||
return new IRI('coid://'.$coid->getHost());
|
if (self::getType($coid)!=self::COID_INVALID
|
||||||
default:
|
&& self::getType($coid)!=self::COID_ROOT) {
|
||||||
return null;
|
$segments = explode('/', $coid->getPath());
|
||||||
|
return $segments[1];
|
||||||
|
} else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the version segment of a valid, versioned COID or null if not available.
|
||||||
|
*
|
||||||
|
* @param IRI $coid
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public static function getVersion(IRI $coid) : ?string {
|
||||||
|
if (self::getType($coid)==self::COID_VERSIONED) {
|
||||||
|
$segments = explode('/', $coid->getPath());
|
||||||
|
return $segments[2];
|
||||||
|
} else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the version segment of a versioned or version wildcard COID or
|
||||||
|
* null if not available.
|
||||||
|
*
|
||||||
|
* @param IRI $coid
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public static function getVersionWildcard(IRI $coid) : ?string {
|
||||||
|
if (self::getType($coid)==self::COID_VERSION_WILDCARD) {
|
||||||
|
$segments = explode('/', $coid->getPath());
|
||||||
|
return $segments[2];
|
||||||
|
} else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the COID itself if it is a root COID or a new IRI object
|
||||||
|
* representing the namespace underlying the given COID.
|
||||||
|
*
|
||||||
|
* @param IRI $coid
|
||||||
|
* @return IRI|null
|
||||||
|
*/
|
||||||
|
public static function getNamespaceCOID(IRI $coid) : ?IRI {
|
||||||
|
switch (self::getType($coid)) {
|
||||||
|
case self::COID_ROOT:
|
||||||
|
return $coid;
|
||||||
|
case self::COID_UNVERSIONED:
|
||||||
|
case self::COID_VERSIONED:
|
||||||
|
case self::COID_VERSION_WILDCARD:
|
||||||
|
return new IRI('coid://'.$coid->getHost());
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
176
CloudObjects/SDK/CloudObject.php
Normal file
176
CloudObjects/SDK/CloudObject.php
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
<?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 ML\JsonLD\Node;
|
||||||
|
use CloudObjects\SDK\NodeReader;
|
||||||
|
use Webmozart\Assert\Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A CloudObject encapsulates an object node for an object stored in CloudObjects Core
|
||||||
|
* with convenience methods to access properties.
|
||||||
|
*/
|
||||||
|
class CloudObject {
|
||||||
|
|
||||||
|
private $coid;
|
||||||
|
private $node;
|
||||||
|
private $reader = null;
|
||||||
|
private $retriever = null;
|
||||||
|
|
||||||
|
public function __construct(IRI $coid, Node $node) {
|
||||||
|
Assert::eq((string)$coid, $node->getId(), "COID and Node ID must match.");
|
||||||
|
|
||||||
|
$this->coid = $coid;
|
||||||
|
$this->node = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify a custom NodeReader to use for this CloudObject.
|
||||||
|
* If not set, a default NodeReader will be used.
|
||||||
|
*/
|
||||||
|
public function setReader(NodeReader $reader) : self {
|
||||||
|
$this->reader = $reader;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the NodeReader used for this CloudObject.
|
||||||
|
* Returns a default NodeReader if non has been set.
|
||||||
|
*/
|
||||||
|
protected function getReader() : NodeReader {
|
||||||
|
if (!$this->reader) {
|
||||||
|
$this->reader = new NodeReader;
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
public function getCOID() : IRI {
|
||||||
|
return $this->coid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the object node encapsulated in this CloudObject.
|
||||||
|
*/
|
||||||
|
public function getAsNode() : 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.
|
||||||
|
* If the property has multiple values, only the first is returned.
|
||||||
|
*/
|
||||||
|
public function getString($property, string $default = null) : ?string {
|
||||||
|
return $this->getReader()->getFirstValueString($this->node, $property, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a property as an integer.
|
||||||
|
* If the property has multiple values, only the first is returned.
|
||||||
|
*/
|
||||||
|
public function getInt($property, int $default = null) : ?int {
|
||||||
|
return $this->getReader()->getFirstValueInt($this->node, $property, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a property as a float.
|
||||||
|
* If the property has multiple values, only the first is returned.
|
||||||
|
*/
|
||||||
|
public function getFloat($property, float $default = null) : ?float {
|
||||||
|
return $this->getReader()->getFirstValueFloat($this->node, $property, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a property as a boolean.
|
||||||
|
* If the property has multiple values, only the first is returned.
|
||||||
|
*/
|
||||||
|
public function getBool($property, bool $default = null) : ?bool {
|
||||||
|
return $this->getReader()->getFirstValueBool($this->node, $property, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a property as an IRI.
|
||||||
|
* If the property has multiple values, only the first is returned.
|
||||||
|
*/
|
||||||
|
public function getIRI($property, IRI $default = null) : ?IRI {
|
||||||
|
return $this->getReader()->getFirstValueIRI($this->node, $property, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a property as a Node.
|
||||||
|
* If the property has multiple values, only the first is returned.
|
||||||
|
*/
|
||||||
|
public function getNode($property, Node $default = null) : ?Node {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the label of the object.
|
||||||
|
*/
|
||||||
|
public function getLabel() : ?string {
|
||||||
|
return $this->getString(Constants::RDFS_LABEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -59,8 +59,8 @@ 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->getAuthenticatingNamespaceObjectNode();
|
||||||
|
|
||||||
$this->reader = new NodeReader([
|
$this->reader = new NodeReader([
|
||||||
'prefixes' => [
|
'prefixes' => [
|
||||||
|
|||||||
14
CloudObjects/SDK/Constants.php
Normal file
14
CloudObjects/SDK/Constants.php
Normal 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;
|
||||||
|
|
||||||
|
class Constants {
|
||||||
|
|
||||||
|
const PROPERTY_REVISION = 'coid://cloudobjects.io/isAtRevision';
|
||||||
|
const RDFS_LABEL = 'http://www.w3.org/2000/01/rdf-schema#label';
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -6,15 +6,24 @@
|
|||||||
|
|
||||||
namespace CloudObjects\SDK;
|
namespace CloudObjects\SDK;
|
||||||
|
|
||||||
use Exception;
|
use DateTime, Exception;
|
||||||
use ML\IRI\IRI, ML\JsonLD\JsonLD;
|
use ML\IRI\IRI;
|
||||||
use Doctrine\Common\Cache\RedisCache;
|
use ML\JsonLD\JsonLD, ML\JsonLD\Node;
|
||||||
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 +38,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 +58,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 +87,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 +111,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) {
|
||||||
@@ -170,15 +204,42 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an object description from CloudObjects. Attempts to get object
|
* Get an object description and return a CloudObject.
|
||||||
* from in-memory cache first, stored static configurations next,
|
*/
|
||||||
* configured external cache third, and finally calls the Object API
|
public function getCloudObject(IRI $coid) : ?CloudObject {
|
||||||
* on CloudObjects Core. Returns null if the object was not found.
|
$node = $this->getObjectNode($coid);
|
||||||
|
if (!$node) {
|
||||||
|
// Object not found
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an object description and return a node.
|
||||||
|
*
|
||||||
|
* @deprecated Use getObjectNode() instead
|
||||||
|
*/
|
||||||
|
public function getObject(IRI $coid) {
|
||||||
|
return $this->getObjectNode($coid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an object description from CloudObjects and return a node.
|
||||||
*
|
*
|
||||||
* @param IRI $coid COID of the object
|
* @param IRI $coid COID of the object
|
||||||
* @return Node|null
|
* @return Node|null
|
||||||
*/
|
*/
|
||||||
public function getObject(IRI $coid) {
|
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.");
|
||||||
|
|
||||||
@@ -394,10 +455,11 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an object description from CloudObjects. Shorthand method for
|
* Get an object description from CloudObjects. Shorthand method for
|
||||||
* "getObject" which allows passing the COID as string instead of IRI.
|
* "getObjectNode" which allows passing the COID as string instead of IRI.
|
||||||
*
|
*
|
||||||
* @param any $coid
|
* @param any $coid
|
||||||
* @return Node|null
|
* @return Node|null
|
||||||
|
* @deprecated Interface may change
|
||||||
*/
|
*/
|
||||||
public function get($coid) {
|
public function get($coid) {
|
||||||
if (is_string($coid))
|
if (is_string($coid))
|
||||||
@@ -425,7 +487,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
|
|||||||
$ts = microtime(true);
|
$ts = microtime(true);
|
||||||
|
|
||||||
$cacheId = $object->getId().'#'.$filename;
|
$cacheId = $object->getId().'#'.$filename;
|
||||||
$fileData = $this->getFromCache($cacheId);
|
$fileData = $this->getFromCache($cacheId);
|
||||||
|
|
||||||
// Parse cached data into revision and content
|
// Parse cached data into revision and content
|
||||||
if (isset($fileData)) {
|
if (isset($fileData)) {
|
||||||
@@ -434,7 +496,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 {
|
||||||
@@ -442,7 +504,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);
|
||||||
@@ -456,21 +518,46 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
|
|||||||
return $fileContent;
|
return $fileContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function assertAuthenticatingNamespaceAndGetId() : IRI {
|
||||||
* Retrieve the object that describes the namespace provided with the "auth_ns"
|
|
||||||
* configuration option.
|
|
||||||
*
|
|
||||||
* @return Node
|
|
||||||
*/
|
|
||||||
public function getAuthenticatingNamespaceObject() {
|
|
||||||
if (!isset($this->options['auth_ns']))
|
if (!isset($this->options['auth_ns']))
|
||||||
throw new Exception("Missing 'auth_ns' configuration option.");
|
throw new InvalidSDKConfigurationException("Missing 'auth_ns' configuration option.");
|
||||||
|
|
||||||
$namespaceCoid = COIDParser::fromString($this->options['auth_ns']);
|
$namespaceCoid = COIDParser::fromString($this->options['auth_ns']);
|
||||||
if (COIDParser::getType($namespaceCoid) != COIDParser::COID_ROOT)
|
if (COIDParser::getType($namespaceCoid) != COIDParser::COID_ROOT)
|
||||||
throw new Exception("The 'auth_ns' configuration option is not a valid namespace/root COID.");
|
throw new InvalidSDKConfigurationException("The 'auth_ns' configuration option is not a valid namespace/root COID.");
|
||||||
|
|
||||||
return $this->getObject($namespaceCoid);
|
return $namespaceCoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the object node that describes the namespace
|
||||||
|
* provided with the "auth_ns" configuration option.
|
||||||
|
*
|
||||||
|
* @deprecated Use getAuthenticatingNamespaceObjectNode() instead
|
||||||
|
* @return Node
|
||||||
|
*/
|
||||||
|
public function getAuthenticatingNamespaceObject() : ?Node {
|
||||||
|
return $this->getObject($this->assertAuthenticatingNamespaceAndGetId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the object node that describes the namespace
|
||||||
|
* provided with the "auth_ns" configuration option.
|
||||||
|
*
|
||||||
|
* @return Node
|
||||||
|
*/
|
||||||
|
public function getAuthenticatingNamespaceObjectNode() : ?Node {
|
||||||
|
return $this->getObject($this->assertAuthenticatingNamespaceAndGetId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the CloudObject that describes the namespace
|
||||||
|
* provided with the "auth_ns" configuration option.
|
||||||
|
*
|
||||||
|
* @return CloudObject
|
||||||
|
*/
|
||||||
|
public function getAuthenticatingNamespaceCloudObject() : ?CloudObject {
|
||||||
|
return $this->getCloudObject($this->assertAuthenticatingNamespaceAndGetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
80
CloudObjects/SDK/ObjectRetrieverFacade.php
Normal file
80
CloudObjects/SDK/ObjectRetrieverFacade.php
Normal file
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
63
CloudObjects/SDK/TestHelpers/InMemoryLogger.php
Normal file
63
CloudObjects/SDK/TestHelpers/InMemoryLogger.php
Normal 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 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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,8 +220,8 @@ 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->getAuthenticatingNamespaceObjectNode();
|
||||||
|
|
||||||
$this->reader = new NodeReader([
|
$this->reader = new NodeReader([
|
||||||
'prefixes' => [
|
'prefixes' => [
|
||||||
@@ -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);
|
||||||
|
|||||||
23
CloudObjects/SDK/functions.php
Normal file
23
CloudObjects/SDK/functions.php
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
63
README.md
63
README.md
@@ -2,67 +2,18 @@
|
|||||||
|
|
||||||
[](https://packagist.org/packages/cloudobjects/sdk) [](https://packagist.org/packages/cloudobjects/sdk)
|
[](https://packagist.org/packages/cloudobjects/sdk) [](https://packagist.org/packages/cloudobjects/sdk)
|
||||||
|
|
||||||
[](https://app.buddy.works/cloudobjects/php-sdk/repository/branch/main)
|
[](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
|
||||||
|
|
||||||
The PHP SDK is licensed under Mozilla Public License (see LICENSE file).
|
The PHP SDK is licensed under Mozilla Public License (see LICENSE file).
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
"name": "cloudobjects/sdk",
|
"name": "cloudobjects/sdk",
|
||||||
"description": "CloudObjects SDK for PHP for working with COIDs and object descriptions from CloudObjects.",
|
"description": "CloudObjects SDK for PHP for working with COIDs and object descriptions from CloudObjects.",
|
||||||
"keywords": ["cloudobjects", "sdk"],
|
"keywords": ["cloudobjects", "sdk"],
|
||||||
"homepage": "https://github.com/CloudObjects/CloudObjects-PHP-SDK",
|
"homepage": "https://codeberg.org/CloudObjects/CloudObjects-PHP-SDK",
|
||||||
"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": "^3.2",
|
"kevinrob/guzzle-cache-middleware": "^7.0.0",
|
||||||
"webmozart/assert": "^1.6"
|
"webmozart/assert": "^1.6",
|
||||||
|
"psr/simple-cache": "^3.0"
|
||||||
},
|
},
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
@@ -21,19 +21,22 @@
|
|||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {
|
"psr-0": {
|
||||||
"CloudObjects\\SDK" : ""
|
"CloudObjects\\SDK" : ""
|
||||||
}
|
},
|
||||||
|
"files": [
|
||||||
|
"CloudObjects/SDK/functions.php"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"require-dev" : {
|
"require-dev" : {
|
||||||
"phpunit/phpunit": ">=4.8.0,<5.0",
|
"phpunit/phpunit": "^10",
|
||||||
"symfony/http-foundation" : ">=4.0",
|
"symfony/http-foundation" : ">=4.0",
|
||||||
"symfony/psr-http-message-bridge" : ">=1.1.0",
|
"symfony/psr-http-message-bridge" : ">=1.1.0",
|
||||||
"nyholm/psr7" : "~1.5.1",
|
"nyholm/psr7" : "~1.5.1",
|
||||||
"defuse/php-encryption" : "^2.2"
|
"defuse/php-encryption" : "^2.2"
|
||||||
},
|
},
|
||||||
"suggest" : {
|
"suggest" : {
|
||||||
"symfony/http-foundation" : "Required to use parseSymfonyRequest() in AccountContext.",
|
"symfony/http-foundation" : "Required to use fromSymfonyRequest() in AccountContext.",
|
||||||
"symfony/psr-http-message-bridge" : "Required to use parseSymfonyRequest() in AccountContext.",
|
"symfony/psr-http-message-bridge" : "Required to use fromSymfonyRequest() in AccountContext.",
|
||||||
"nyholm/psr7" : "Required to use parseSymfonyRequest() in AccountContext.",
|
"nyholm/psr7" : "Required to use fromSymfonyRequest() in AccountContext.",
|
||||||
"defuse/php-encryption": "Required to use CryptoHelper"
|
"defuse/php-encryption": "Required to use CryptoHelper"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2276
composer.lock
generated
2276
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<phpunit backupGlobals="false"
|
<phpunit backupGlobals="false"
|
||||||
backupStaticAttributes="false"
|
|
||||||
colors="true"
|
colors="true"
|
||||||
convertErrorsToExceptions="true"
|
|
||||||
convertNoticesToExceptions="true"
|
|
||||||
convertWarningsToExceptions="true"
|
|
||||||
processIsolation="false"
|
processIsolation="false"
|
||||||
stopOnFailure="false"
|
stopOnFailure="false"
|
||||||
syntaxCheck="false"
|
|
||||||
bootstrap="./tests/bootstrap.php">
|
bootstrap="./tests/bootstrap.php">
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite name="OfflineTests">
|
<testsuite name="OfflineTests">
|
||||||
|
|||||||
5
run-docker.sh
Normal file
5
run-docker.sh
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
docker run -d -v .:/root --name cloudobjects-sdk-test cloudobjects/php-build-base:8.3
|
||||||
|
docker exec cloudobjects-sdk-test bash -c "cd /root && composer install"
|
||||||
|
docker exec cloudobjects-sdk-test bash -c "cd /root && vendor/bin/phpunit"
|
||||||
|
docker stop cloudobjects-sdk-test
|
||||||
|
docker rm cloudobjects-sdk-test
|
||||||
@@ -8,7 +8,7 @@ namespace CloudObjects\SDK\AccountGateway;
|
|||||||
|
|
||||||
use ML\IRI\IRI;
|
use ML\IRI\IRI;
|
||||||
|
|
||||||
class AAUIDParserTest extends \PHPUnit_Framework_TestCase {
|
class AAUIDParserTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
public function testValidAccountAAUID() {
|
public function testValidAccountAAUID() {
|
||||||
$aauid = new IRI('aauid:abcd1234abcd1234');
|
$aauid = new IRI('aauid:abcd1234abcd1234');
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace CloudObjects\SDK\AccountGateway;
|
|||||||
use GuzzleHttp\Psr7\Request as GuzzlePsrRequest;
|
use GuzzleHttp\Psr7\Request as GuzzlePsrRequest;
|
||||||
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
|
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
|
||||||
|
|
||||||
class AccountContextParseTest extends \PHPUnit_Framework_TestCase {
|
class AccountContextParseTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
public function testParsePsrRequest() {
|
public function testParsePsrRequest() {
|
||||||
$request = new GuzzlePsrRequest('GET', '/', [
|
$request = new GuzzlePsrRequest('GET', '/', [
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ namespace CloudObjects\SDK\AccountGateway;
|
|||||||
|
|
||||||
use ML\IRI\IRI;
|
use ML\IRI\IRI;
|
||||||
|
|
||||||
class AccountContextTest extends \PHPUnit_Framework_TestCase {
|
class AccountContextTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
private $context;
|
private $context;
|
||||||
|
|
||||||
protected function setUp() {
|
protected function setUp(): void {
|
||||||
$this->context = new AccountContext(new IRI('aauid:aaaabbbbccccdddd'), 'DUMMY');
|
$this->context = new AccountContext(new IRI('aauid:aaaabbbbccccdddd'), 'DUMMY');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,123 +8,141 @@ namespace CloudObjects\SDK;
|
|||||||
|
|
||||||
use ML\IRI\IRI;
|
use ML\IRI\IRI;
|
||||||
|
|
||||||
class COIDParserTest extends \PHPUnit_Framework_TestCase {
|
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));
|
||||||
}
|
|
||||||
|
|
||||||
public function testInvalidRootCOID() {
|
$coid = new IRI('coid://subdomain.example.com');
|
||||||
$coid = new IRI('coid://example');
|
$this->assertEquals(COIDParser::COID_ROOT, COIDParser::getType($coid));
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
$coid = new IRI('coid://exämple.com');
|
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
$coid = new IRI('coid://ex&mple.com');
|
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testInvalidCOID() {
|
$coid = new IRI('coid://anotherlevel.subdomain.example.com');
|
||||||
$coid = new IRI('http://example.com');
|
$this->assertEquals(COIDParser::COID_ROOT, COIDParser::getType($coid));
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
}
|
||||||
$coid = new IRI('example.com');
|
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
$coid = new IRI('COID://example.com');
|
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
$coid = new IRI('Coid://example.com');
|
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
$coid = new IRI('coid://EXAMPLE.COM');
|
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
$coid = new IRI('coid://exAMPle.CoM');
|
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testUnversionedCOID() {
|
public function testInvalidRootCOID() {
|
||||||
$coid = new IRI('coid://example.com/Example');
|
$coid = new IRI('coid://example');
|
||||||
$this->assertEquals(COIDParser::COID_UNVERSIONED, COIDParser::getType($coid));
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
}
|
|
||||||
|
|
||||||
public function testInvalidUnversionedCOID() {
|
$coid = new IRI('coid://exämple.com');
|
||||||
$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');
|
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testVersionedCOID() {
|
$coid = new IRI('coid://ex&mple.com');
|
||||||
$coid = new IRI('coid://example.com/Example/1.0');
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
$this->assertEquals(COIDParser::COID_VERSIONED, COIDParser::getType($coid));
|
}
|
||||||
$coid = new IRI('coid://example.com/Example/alpha');
|
|
||||||
$this->assertEquals(COIDParser::COID_VERSIONED, COIDParser::getType($coid));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testInvalidVersionedCOID() {
|
public function testInvalidCOID() {
|
||||||
$coid = new IRI('coid://example.com/Example/1.$');
|
$coid = new IRI('http://example.com');
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
}
|
|
||||||
|
|
||||||
public function testVersionWildcardCOID() {
|
$coid = new IRI('example.com');
|
||||||
$coid = new IRI('coid://example.com/Example/^1.0');
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
$this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid));
|
|
||||||
$coid = new IRI('coid://example.com/Example/~1.0');
|
|
||||||
$this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid));
|
|
||||||
$coid = new IRI('coid://example.com/Example/1.*');
|
|
||||||
$this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testInvalidVersionWildcardCOID() {
|
$coid = new IRI('COID://example.com');
|
||||||
$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.*');
|
|
||||||
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIRICaseSensitivity() {
|
$coid = new IRI('Coid://example.com');
|
||||||
$coid1 = new IRI('coid://example.com/example/1.0');
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
$coid2 = new IRI('coid://example.com/Example/1.0');
|
|
||||||
$this->assertFalse($coid1->equals($coid2));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testRootFromString() {
|
$coid = new IRI('coid://EXAMPLE.COM');
|
||||||
$coid1 = new IRI('coid://example.com');
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
$coid2 = COIDParser::fromString('coid://example.com');
|
|
||||||
$coid3 = COIDParser::fromString('example.com');
|
$coid = new IRI('coid://exAMPle.CoM');
|
||||||
$this->assertTrue($coid1->equals($coid2));
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
$this->assertTrue($coid1->equals($coid3));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public function testUnversionedFromString() {
|
public function testUnversionedCOID() {
|
||||||
$coid1 = new IRI('coid://example.com/Example');
|
$coid = new IRI('coid://subdomain.example.com/Example');
|
||||||
$coid2 = COIDParser::fromString('coid://example.com/Example');
|
$this->assertEquals(COIDParser::COID_UNVERSIONED, COIDParser::getType($coid));
|
||||||
$coid3 = COIDParser::fromString('example.com/Example');
|
}
|
||||||
$this->assertTrue($coid1->equals($coid2));
|
|
||||||
$this->assertTrue($coid1->equals($coid3));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testVersionedFromString() {
|
public function testInvalidUnversionedCOID() {
|
||||||
$coid1 = new IRI('coid://example.com/Example/1.0');
|
$coid = new IRI('coid://example.com/Exümple');
|
||||||
$coid2 = COIDParser::fromString('coid://example.com/Example/1.0');
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
$coid3 = COIDParser::fromString('example.com/Example/1.0');
|
|
||||||
$this->assertTrue($coid1->equals($coid2));
|
|
||||||
$this->assertTrue($coid1->equals($coid3));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testNormalizeRootFromString() {
|
$coid = new IRI('coid://example.com/Examp%e');
|
||||||
$coid1 = new IRI('coid://example.com');
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
$coid2 = COIDParser::fromString('COID://example.com');
|
}
|
||||||
$coid3 = COIDParser::fromString('ExAmple.COM');
|
|
||||||
$this->assertTrue($coid1->equals($coid2));
|
|
||||||
$this->assertTrue($coid1->equals($coid3));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testNormalizeNonRootFromString() {
|
public function testVersionedCOID() {
|
||||||
$coid1 = new IRI('coid://example.com/Example');
|
$coid = new IRI('coid://anotherlevel.subdomain.example.com/Example/1.0');
|
||||||
$coid2 = COIDParser::fromString('COID://example.com/Example');
|
$this->assertEquals(COIDParser::COID_VERSIONED, COIDParser::getType($coid));
|
||||||
$coid3 = COIDParser::fromString('ExAmple.COM/Example');
|
|
||||||
$coid4 = COIDParser::fromString('ExAmple.COM/EXample');
|
$coid = new IRI('coid://subdomain.example.com/Example/alpha');
|
||||||
$this->assertTrue($coid1->equals($coid2));
|
$this->assertEquals(COIDParser::COID_VERSIONED, COIDParser::getType($coid));
|
||||||
$this->assertTrue($coid1->equals($coid3));
|
}
|
||||||
$this->assertFalse($coid1->equals($coid4));
|
|
||||||
}
|
public function testInvalidVersionedCOID() {
|
||||||
|
$coid = new IRI('coid://example.com/Example/1.$');
|
||||||
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testVersionWildcardCOID() {
|
||||||
|
$coid = new IRI('coid://example.com/Example/^1.0');
|
||||||
|
$this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid));
|
||||||
|
|
||||||
|
$coid = new IRI('coid://example.com/Example/~1.0');
|
||||||
|
$this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid));
|
||||||
|
|
||||||
|
$coid = new IRI('coid://example.com/Example/1.*');
|
||||||
|
$this->assertEquals(COIDParser::COID_VERSION_WILDCARD, COIDParser::getType($coid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidVersionWildcardCOID() {
|
||||||
|
$coid = new IRI('coid://example.com/Example/^1.*');
|
||||||
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
|
|
||||||
|
$coid = new IRI('coid://example.com/Example/1.a.*');
|
||||||
|
$this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIRICaseSensitivity() {
|
||||||
|
$coid1 = new IRI('coid://example.com/example/1.0');
|
||||||
|
$coid2 = new IRI('coid://example.com/Example/1.0');
|
||||||
|
$this->assertFalse($coid1->equals($coid2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRootFromString() {
|
||||||
|
$coid1 = new IRI('coid://example.com');
|
||||||
|
$coid2 = COIDParser::fromString('coid://example.com');
|
||||||
|
$coid3 = COIDParser::fromString('example.com');
|
||||||
|
$this->assertTrue($coid1->equals($coid2));
|
||||||
|
$this->assertTrue($coid1->equals($coid3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnversionedFromString() {
|
||||||
|
$coid1 = new IRI('coid://example.com/Example');
|
||||||
|
$coid2 = COIDParser::fromString('coid://example.com/Example');
|
||||||
|
$coid3 = COIDParser::fromString('example.com/Example');
|
||||||
|
$this->assertTrue($coid1->equals($coid2));
|
||||||
|
$this->assertTrue($coid1->equals($coid3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testVersionedFromString() {
|
||||||
|
$coid1 = new IRI('coid://example.com/Example/1.0');
|
||||||
|
$coid2 = COIDParser::fromString('coid://example.com/Example/1.0');
|
||||||
|
$coid3 = COIDParser::fromString('example.com/Example/1.0');
|
||||||
|
$this->assertTrue($coid1->equals($coid2));
|
||||||
|
$this->assertTrue($coid1->equals($coid3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNormalizeRootFromString() {
|
||||||
|
$coid1 = new IRI('coid://example.com');
|
||||||
|
$coid2 = COIDParser::fromString('COID://example.com');
|
||||||
|
$coid3 = COIDParser::fromString('ExAmple.COM');
|
||||||
|
$this->assertTrue($coid1->equals($coid2));
|
||||||
|
$this->assertTrue($coid1->equals($coid3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNormalizeNonRootFromString() {
|
||||||
|
$coid1 = new IRI('coid://example.com/Example');
|
||||||
|
$coid2 = COIDParser::fromString('COID://example.com/Example');
|
||||||
|
$coid3 = COIDParser::fromString('ExAmple.COM/Example');
|
||||||
|
$coid4 = COIDParser::fromString('ExAmple.COM/EXample');
|
||||||
|
$this->assertTrue($coid1->equals($coid2));
|
||||||
|
$this->assertTrue($coid1->equals($coid3));
|
||||||
|
$this->assertFalse($coid1->equals($coid4));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use GuzzleHttp\Client, GuzzleHttp\Handler\MockHandler,
|
|||||||
GuzzleHttp\HandlerStack, GuzzleHttp\Psr7\Response;
|
GuzzleHttp\HandlerStack, GuzzleHttp\Psr7\Response;
|
||||||
use CloudObjects\SDK\ObjectRetriever;
|
use CloudObjects\SDK\ObjectRetriever;
|
||||||
|
|
||||||
class CryptoHelperTest extends \PHPUnit_Framework_TestCase {
|
class CryptoHelperTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
private $retriever;
|
private $retriever;
|
||||||
private $graph;
|
private $graph;
|
||||||
@@ -22,7 +22,7 @@ class CryptoHelperTest extends \PHPUnit_Framework_TestCase {
|
|||||||
$this->retriever->setClient(new Client(['handler' => $handler]));
|
$this->retriever->setClient(new Client(['handler' => $handler]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUp() {
|
protected function setUp(): void {
|
||||||
$this->retriever = new ObjectRetriever([
|
$this->retriever = new ObjectRetriever([
|
||||||
'auth_ns' => 'test.cloudobjects.io',
|
'auth_ns' => 'test.cloudobjects.io',
|
||||||
'auth_secret' => 'TEST'
|
'auth_secret' => 'TEST'
|
||||||
|
|||||||
63
tests/OfflineTests/FunctionsTest.php
Normal file
63
tests/OfflineTests/FunctionsTest.php
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -10,12 +10,12 @@ use InvalidArgumentException;
|
|||||||
use ML\JsonLD\JsonLD;
|
use ML\JsonLD\JsonLD;
|
||||||
use CloudObjects\SDK\ObjectRetriever;
|
use CloudObjects\SDK\ObjectRetriever;
|
||||||
|
|
||||||
class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
|
class SchemaValidatorTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
private $schemaValidator;
|
private $schemaValidator;
|
||||||
private $graph;
|
private $graph;
|
||||||
|
|
||||||
public function setUp() {
|
protected function setUp(): void {
|
||||||
$this->schemaValidator = new SchemaValidator(new ObjectRetriever);
|
$this->schemaValidator = new SchemaValidator(new ObjectRetriever);
|
||||||
$this->graph = JsonLD::getDocument('{}')->getGraph();
|
$this->graph = JsonLD::getDocument('{}')->getGraph();
|
||||||
}
|
}
|
||||||
@@ -24,10 +24,11 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
|
|||||||
$node = $this->graph->createNode();
|
$node = $this->graph->createNode();
|
||||||
$node->setType($this->graph->createNode('coid://json.co-n.net/String'));
|
$node->setType($this->graph->createNode('coid://json.co-n.net/String'));
|
||||||
$this->schemaValidator->validateAgainstNode("Test", $node);
|
$this->schemaValidator->validateAgainstNode("Test", $node);
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNotString() {
|
public function testNotString() {
|
||||||
$this->setExpectedException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$node = $this->graph->createNode();
|
$node = $this->graph->createNode();
|
||||||
$node->setType($this->graph->createNode('coid://json.co-n.net/String'));
|
$node->setType($this->graph->createNode('coid://json.co-n.net/String'));
|
||||||
@@ -38,10 +39,11 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
|
|||||||
$node = $this->graph->createNode();
|
$node = $this->graph->createNode();
|
||||||
$node->setType($this->graph->createNode('coid://json.co-n.net/Number'));
|
$node->setType($this->graph->createNode('coid://json.co-n.net/Number'));
|
||||||
$this->schemaValidator->validateAgainstNode(3.5, $node);
|
$this->schemaValidator->validateAgainstNode(3.5, $node);
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNotNumber() {
|
public function testNotNumber() {
|
||||||
$this->setExpectedException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$node = $this->graph->createNode();
|
$node = $this->graph->createNode();
|
||||||
$node->setType($this->graph->createNode('coid://json.co-n.net/Number'));
|
$node->setType($this->graph->createNode('coid://json.co-n.net/Number'));
|
||||||
@@ -52,10 +54,11 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
|
|||||||
$node = $this->graph->createNode();
|
$node = $this->graph->createNode();
|
||||||
$node->setType($this->graph->createNode('coid://json.co-n.net/Integer'));
|
$node->setType($this->graph->createNode('coid://json.co-n.net/Integer'));
|
||||||
$this->schemaValidator->validateAgainstNode(12, $node);
|
$this->schemaValidator->validateAgainstNode(12, $node);
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNotInteger() {
|
public function testNotInteger() {
|
||||||
$this->setExpectedException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$node = $this->graph->createNode();
|
$node = $this->graph->createNode();
|
||||||
$node->setType($this->graph->createNode('coid://json.co-n.net/Integer'));
|
$node->setType($this->graph->createNode('coid://json.co-n.net/Integer'));
|
||||||
@@ -66,10 +69,11 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
|
|||||||
$node = $this->graph->createNode();
|
$node = $this->graph->createNode();
|
||||||
$node->setType($this->graph->createNode('coid://json.co-n.net/Array'));
|
$node->setType($this->graph->createNode('coid://json.co-n.net/Array'));
|
||||||
$this->schemaValidator->validateAgainstNode([ 1, 2, "foo" ], $node);
|
$this->schemaValidator->validateAgainstNode([ 1, 2, "foo" ], $node);
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNotArray() {
|
public function testNotArray() {
|
||||||
$this->setExpectedException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$node = $this->graph->createNode();
|
$node = $this->graph->createNode();
|
||||||
$node->setType($this->graph->createNode('coid://json.co-n.net/Array'));
|
$node->setType($this->graph->createNode('coid://json.co-n.net/Array'));
|
||||||
@@ -83,10 +87,11 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
|
|||||||
'a' => 'A',
|
'a' => 'A',
|
||||||
'b' => 'B'
|
'b' => 'B'
|
||||||
], $node);
|
], $node);
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNotObject() {
|
public function testNotObject() {
|
||||||
$this->setExpectedException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$node = $this->graph->createNode();
|
$node = $this->graph->createNode();
|
||||||
$node->setType($this->graph->createNode('coid://json.co-n.net/Object'));
|
$node->setType($this->graph->createNode('coid://json.co-n.net/Object'));
|
||||||
@@ -105,10 +110,11 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
|
|||||||
'a' => 'A',
|
'a' => 'A',
|
||||||
'b' => 'B'
|
'b' => 'B'
|
||||||
], $node);
|
], $node);
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testObjectWithPropertyTypeError() {
|
public function testObjectWithPropertyTypeError() {
|
||||||
$this->setExpectedException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$stringNode = $this->graph->createNode();
|
$stringNode = $this->graph->createNode();
|
||||||
$stringNode->setProperty('coid://json.co-n.net/hasKey', 'a');
|
$stringNode->setProperty('coid://json.co-n.net/hasKey', 'a');
|
||||||
@@ -136,10 +142,11 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
|
|||||||
'a' => 'A',
|
'a' => 'A',
|
||||||
'b' => 'B'
|
'b' => 'B'
|
||||||
], $node);
|
], $node);
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testObjectWithRequiredPropertyTypeError() {
|
public function testObjectWithRequiredPropertyTypeError() {
|
||||||
$this->setExpectedException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$stringNode = $this->graph->createNode();
|
$stringNode = $this->graph->createNode();
|
||||||
$stringNode->setProperty('coid://json.co-n.net/hasKey', 'a');
|
$stringNode->setProperty('coid://json.co-n.net/hasKey', 'a');
|
||||||
@@ -156,7 +163,7 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testObjectWithRequiredPropertyMissing() {
|
public function testObjectWithRequiredPropertyMissing() {
|
||||||
$this->setExpectedException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$stringNode = $this->graph->createNode();
|
$stringNode = $this->graph->createNode();
|
||||||
$stringNode->setProperty('coid://json.co-n.net/hasKey', 'a');
|
$stringNode->setProperty('coid://json.co-n.net/hasKey', 'a');
|
||||||
|
|||||||
@@ -7,150 +7,189 @@
|
|||||||
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;
|
||||||
|
|
||||||
class NodeReaderMockTest extends \PHPUnit_Framework_TestCase {
|
class NodeReaderMockTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
private $retriever;
|
private $retriever;
|
||||||
private $reader;
|
private $reader;
|
||||||
|
|
||||||
private function setMockResponse(Response $response) {
|
private function setMockResponse(Response $response) {
|
||||||
$mock = new MockHandler([$response]);
|
$mock = new MockHandler([$response]);
|
||||||
$handler = HandlerStack::create($mock);
|
$handler = HandlerStack::create($mock);
|
||||||
$this->retriever->setClient(new Client(['handler' => $handler]));
|
$this->retriever->setClient(new Client(['handler' => $handler]));
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
protected function setUp(): void {
|
||||||
$this->retriever = new ObjectRetriever;
|
$this->retriever = new ObjectRetriever;
|
||||||
$this->reader = new NodeReader([
|
$this->reader = new NodeReader([
|
||||||
'prefixes' => [
|
'prefixes' => [
|
||||||
'co' => 'coid://cloudobjects.io/',
|
'co' => 'coid://cloudobjects.io/',
|
||||||
'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'));
|
||||||
$this->assertFalse($this->reader->hasType($object, 'coid://cloudobjects.io/MemberRole'));
|
$this->assertFalse($this->reader->hasType($object, 'coid://cloudobjects.io/MemberRole'));
|
||||||
$this->assertFalse($this->reader->hasType($object, 'co:MemberRole'));
|
$this->assertFalse($this->reader->hasType($object, 'co:MemberRole'));
|
||||||
}
|
}
|
||||||
|
|
||||||
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'));
|
||||||
}
|
}
|
||||||
|
|
||||||
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'));
|
||||||
|
|
||||||
$this->assertNull($this->reader->getFirstValueString($object, 'coid://cloudobjects.io/makesTriplesVisibleTo'));
|
$this->assertNull($this->reader->getFirstValueString($object, 'coid://cloudobjects.io/makesTriplesVisibleTo'));
|
||||||
$this->assertNull($this->reader->getFirstValueString($object, 'co:makesTriplesVisibleTo'));
|
$this->assertNull($this->reader->getFirstValueString($object, 'co:makesTriplesVisibleTo'));
|
||||||
|
|
||||||
$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'));
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetFirstValueIRI1() {
|
$object = $this->retriever->getCloudObject($coid);
|
||||||
$coid = new IRI('coid://cloudobjects.io');
|
|
||||||
$this->useRootResourceMock();
|
$this->assertEquals('CloudObjects', $object->getString('http://www.w3.org/2000/01/rdf-schema#label'));
|
||||||
$object = $this->retriever->getObject($coid);
|
$this->assertEquals('CloudObjects', $object->getString('rdfs:label'));
|
||||||
|
|
||||||
$this->assertInstanceOf('ML\IRI\IRI', $this->reader->getFirstValueIRI($object, 'coid://cloudobjects.io/isVisibleTo'));
|
$this->assertNull($object->getString('coid://cloudobjects.io/makesTriplesVisibleTo'));
|
||||||
$this->assertInstanceOf('ML\IRI\IRI', $this->reader->getFirstValueIRI($object, 'co:isVisibleTo'));
|
$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() {
|
||||||
|
$coid = new IRI('coid://cloudobjects.io');
|
||||||
|
$this->useRootResourceMock();
|
||||||
|
$object = $this->retriever->getObjectNode($coid);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(IRI::class, $this->reader->getFirstValueIRI($object, 'coid://cloudobjects.io/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'));
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetFirstValueNode1() {
|
$object = $this->retriever->getCloudObject($coid);
|
||||||
$coid = new IRI('coid://cloudobjects.io');
|
|
||||||
$this->useRootResourceMock();
|
|
||||||
$object = $this->retriever->getObject($coid);
|
|
||||||
|
|
||||||
$this->assertInstanceOf('ML\JsonLD\Node', $this->reader->getFirstValueNode($object, 'coid://cloudobjects.io/isVisibleTo'));
|
$this->assertInstanceOf(IRI::class, $object->getIRI('coid://cloudobjects.io/isVisibleTo'));
|
||||||
$this->assertInstanceOf('ML\JsonLD\Node', $this->reader->getFirstValueNode($object, 'co: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() {
|
||||||
|
$coid = new IRI('coid://cloudobjects.io');
|
||||||
|
$this->useRootResourceMock();
|
||||||
|
$object = $this->retriever->getObjectNode($coid);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Node::class, $this->reader->getFirstValueNode($object, 'coid://cloudobjects.io/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());
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetAllValuesString1() {
|
$object = $this->retriever->getCloudObject($coid);
|
||||||
$coid = new IRI('coid://cloudobjects.io');
|
|
||||||
$this->useRootResourceMock();
|
$this->assertInstanceOf(Node::class, $object->getNode('coid://cloudobjects.io/isVisibleTo'));
|
||||||
$object = $this->retriever->getObject($coid);
|
$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 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() {
|
||||||
|
$coid = new IRI('coid://cloudobjects.io');
|
||||||
|
$this->useRootResourceMock();
|
||||||
|
$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'));
|
||||||
|
|
||||||
$this->assertEquals('CloudObjects', $this->reader->getAllValuesString($object, 'http://www.w3.org/2000/01/rdf-schema#label')[0]);
|
$this->assertEquals('CloudObjects', $this->reader->getAllValuesString($object, 'http://www.w3.org/2000/01/rdf-schema#label')[0]);
|
||||||
$this->assertEquals('CloudObjects', $this->reader->getAllValuesString($object, 'rdfs:label')[0]);
|
$this->assertEquals('CloudObjects', $this->reader->getAllValuesString($object, 'rdfs:label')[0]);
|
||||||
|
|
||||||
$this->assertCount(0, $this->reader->getAllValuesString($object, 'coid://cloudobjects.io/makesTriplesVisibleTo'));
|
$this->assertCount(0, $this->reader->getAllValuesString($object, 'coid://cloudobjects.io/makesTriplesVisibleTo'));
|
||||||
$this->assertCount(0, $this->reader->getAllValuesString($object, 'co:makesTriplesVisibleTo'));
|
$this->assertCount(0, $this->reader->getAllValuesString($object, 'co:makesTriplesVisibleTo'));
|
||||||
|
|
||||||
$this->assertCount(2, $this->reader->getAllValuesString($object, '@type'));
|
$this->assertCount(2, $this->reader->getAllValuesString($object, '@type'));
|
||||||
}
|
}
|
||||||
|
|
||||||
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'));
|
||||||
|
|
||||||
$this->assertCount(1, $this->reader->getAllValuesIRI($object, 'coid://cloudobjects.io/isVisibleTo'));
|
$this->assertCount(1, $this->reader->getAllValuesIRI($object, 'coid://cloudobjects.io/isVisibleTo'));
|
||||||
$this->assertCount(1, $this->reader->getAllValuesIRI($object, 'co:isVisibleTo'));
|
$this->assertCount(1, $this->reader->getAllValuesIRI($object, 'co:isVisibleTo'));
|
||||||
|
|
||||||
$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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
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'));
|
||||||
|
|
||||||
$this->assertCount(1, $this->reader->getAllValuesNode($object, 'coid://cloudobjects.io/isVisibleTo'));
|
$this->assertCount(1, $this->reader->getAllValuesNode($object, 'coid://cloudobjects.io/isVisibleTo'));
|
||||||
$this->assertCount(1, $this->reader->getAllValuesNode($object, 'co:isVisibleTo'));
|
$this->assertCount(1, $this->reader->getAllValuesNode($object, 'co:isVisibleTo'));
|
||||||
|
|
||||||
$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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
76
tests/OfflineTests/ObjectRetrieverFacadeTest.php
Normal file
76
tests/OfflineTests/ObjectRetrieverFacadeTest.php
Normal file
@@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,33 +8,46 @@ namespace CloudObjects\SDK;
|
|||||||
|
|
||||||
use ML\IRI\IRI;
|
use ML\IRI\IRI;
|
||||||
use GuzzleHttp\Client, GuzzleHttp\Handler\MockHandler,
|
use GuzzleHttp\Client, GuzzleHttp\Handler\MockHandler,
|
||||||
GuzzleHttp\HandlerStack, GuzzleHttp\Psr7\Response;
|
GuzzleHttp\HandlerStack, GuzzleHttp\Psr7\Response;
|
||||||
|
|
||||||
class ObjectRetrieverMockTest extends \PHPUnit_Framework_TestCase {
|
class ObjectRetrieverMockTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
private $retriever;
|
private $retriever;
|
||||||
|
|
||||||
private function setMockResponse(Response $response) {
|
private function setMockResponse(Response $response) {
|
||||||
$mock = new MockHandler([$response]);
|
$mock = new MockHandler([$response]);
|
||||||
$handler = HandlerStack::create($mock);
|
$handler = HandlerStack::create($mock);
|
||||||
$this->retriever->setClient(new Client(['handler' => $handler]));
|
$this->retriever->setClient(new Client(['handler' => $handler]));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setUp() {
|
protected function setUp(): void {
|
||||||
$this->retriever = new ObjectRetriever;
|
$this->retriever = new ObjectRetriever;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetRootResource() {
|
public function testGetRootResource() {
|
||||||
$this->setMockResponse(new Response(200,
|
$this->setMockResponse(new Response(200,
|
||||||
['Content-Type' => 'application/ld+json'],
|
['Content-Type' => 'application/ld+json'],
|
||||||
'{"@context":{"cloudobjects":"coid:\/\/cloudobjects.io\/","rdf":"http:\/\/www.w3.org\/1999\/02\/22-rdf-syntax-ns#","rdfs":"http:\/\/www.w3.org\/2000\/01\/rdf-schema#"},"@id":"coid:\/\/cloudobjects.io","@type":"cloudobjects:Namespace","cloudobjects:hasPublicListing":"true","cloudobjects:revision":"1-325baa62b76105f56dc09386f5a2ec91","rdfs:comment":"The CloudObjects namespace defines the essential objects.","rdfs:label":"CloudObjects"}'));
|
'{"@context":{"cloudobjects":"coid:\/\/cloudobjects.io\/","rdf":"http:\/\/www.w3.org\/1999\/02\/22-rdf-syntax-ns#","rdfs":"http:\/\/www.w3.org\/2000\/01\/rdf-schema#"},"@id":"coid:\/\/cloudobjects.io","@type":"cloudobjects:Namespace","cloudobjects:hasPublicListing":"true","cloudobjects:revision":"1-325baa62b76105f56dc09386f5a2ec91","rdfs:comment":"The CloudObjects namespace defines the essential objects.","rdfs:label":"CloudObjects"}'
|
||||||
|
));
|
||||||
|
|
||||||
$coid = new IRI('coid://cloudobjects.io');
|
$coid = new IRI('coid://cloudobjects.io');
|
||||||
$object = $this->retriever->getObject($coid);
|
|
||||||
$this->assertNotNull($object);
|
// Test node interface first
|
||||||
$this->assertEquals((string)$coid, $object->getID());
|
$object = $this->retriever->getObjectNode($coid);
|
||||||
$this->assertNotNull($object->getProperty('http://www.w3.org/2000/01/rdf-schema#label'));
|
$this->assertNotNull($object);
|
||||||
$this->assertEquals('CloudObjects', $object->getProperty('http://www.w3.org/2000/01/rdf-schema#label')->getValue());
|
$this->assertEquals((string)$coid, $object->getId());
|
||||||
}
|
$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->assertNull($object->getProperty('urn:example:nonexistingvalue'));
|
||||||
|
|
||||||
|
// Test CloudObject interface
|
||||||
|
$object = $this->retriever->getCloudObject($coid);
|
||||||
|
$this->assertNotNull($object);
|
||||||
|
$this->assertEquals((string)$coid, $object->getAsNode()->getId());
|
||||||
|
$this->assertEquals($coid, $object->getCOID());
|
||||||
|
$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->assertNull($object->getString('urn:example:nonexistingvalue'));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ use InvalidArgumentException;
|
|||||||
use ML\IRI\IRI;
|
use ML\IRI\IRI;
|
||||||
use CloudObjects\SDK\ObjectRetriever;
|
use CloudObjects\SDK\ObjectRetriever;
|
||||||
|
|
||||||
class SchemaValidatorPublicTest extends \PHPUnit_Framework_TestCase {
|
class SchemaValidatorPublicTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
private $schemaValidator;
|
private $schemaValidator;
|
||||||
|
|
||||||
public function setUp() {
|
protected function setUp(): void {
|
||||||
$this->schemaValidator = new SchemaValidator(new ObjectRetriever);
|
$this->schemaValidator = new SchemaValidator(new ObjectRetriever);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,10 +24,11 @@ class SchemaValidatorPublicTest extends \PHPUnit_Framework_TestCase {
|
|||||||
'region' => 'Hessen',
|
'region' => 'Hessen',
|
||||||
'country-name' => 'Germany'
|
'country-name' => 'Germany'
|
||||||
], new IRI('coid://json.co-n.net/Address'));
|
], new IRI('coid://json.co-n.net/Address'));
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNotAddress() {
|
public function testNotAddress() {
|
||||||
$this->setExpectedException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$this->schemaValidator->validateAgainstCOID([
|
$this->schemaValidator->validateAgainstCOID([
|
||||||
'region' => 'Hessen',
|
'region' => 'Hessen',
|
||||||
|
|||||||
47
tests/OnlineTests/ObjectRetrieverCacheTest.php
Normal file
47
tests/OnlineTests/ObjectRetrieverCacheTest.php
Normal 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,11 +8,11 @@ namespace CloudObjects\SDK;
|
|||||||
|
|
||||||
use ML\IRI\IRI;
|
use ML\IRI\IRI;
|
||||||
|
|
||||||
class ObjectRetrieverTest extends \PHPUnit_Framework_TestCase {
|
class ObjectRetrieverPublicTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
private $retriever;
|
private $retriever;
|
||||||
|
|
||||||
protected function setUp() {
|
protected function setUp(): void {
|
||||||
$this->retriever = new ObjectRetriever;
|
$this->retriever = new ObjectRetriever;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,11 +26,23 @@ class ObjectRetrieverTest 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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user