[WIP] Implement interface for lazy-loading foreign nodes
This commit is contained in:
parent
a210752d7f
commit
4913dfdf43
@ -5,13 +5,13 @@ namespace ActivityPub\JsonLd\Dereferencer;
|
|||||||
|
|
||||||
|
|
||||||
use ActivityPub\JsonLd\Exceptions\NodeNotFoundException;
|
use ActivityPub\JsonLd\Exceptions\NodeNotFoundException;
|
||||||
use ActivityPub\JsonLd\JsonLdNode;
|
use stdClass;
|
||||||
|
|
||||||
interface DereferencerInterface
|
interface DereferencerInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string $iri The IRI to dereference.
|
* @param string $iri The IRI to dereference.
|
||||||
* @return JsonLdNode The dereferenced node.
|
* @return stdClass|array The dereferenced node.
|
||||||
* @throws NodeNotFoundException If a node with the IRI could not be found.
|
* @throws NodeNotFoundException If a node with the IRI could not be found.
|
||||||
*/
|
*/
|
||||||
public function dereference( $iri );
|
public function dereference( $iri );
|
||||||
|
@ -2,27 +2,42 @@
|
|||||||
|
|
||||||
namespace ActivityPub\JsonLd;
|
namespace ActivityPub\JsonLd;
|
||||||
|
|
||||||
|
use ActivityPub\JsonLd\Dereferencer\DereferencerInterface;
|
||||||
use ActivityPub\JsonLd\Exceptions\PropertyNotDefinedException;
|
use ActivityPub\JsonLd\Exceptions\PropertyNotDefinedException;
|
||||||
use ArrayAccess;
|
use ArrayAccess;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use ML\JsonLD\Graph;
|
||||||
use ML\JsonLD\JsonLD;
|
use ML\JsonLD\JsonLD;
|
||||||
use ML\JsonLD\Node;
|
use ML\JsonLD\Node;
|
||||||
use ML\JsonLD\Value;
|
use ML\JsonLD\Value;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class JsonLdNode
|
* Class JsonLdNode
|
||||||
* @package ActivityPub\JsonLd
|
* @package ActivityPub\JsonLd
|
||||||
*
|
*
|
||||||
* A representation of a node in a JSON-LD graph. Supports lazy-loading linked nodes and persisting RDF triples to
|
* A representation of a node in a JSON-LD graph. Supports lazy-loading linked nodes.
|
||||||
* a storage backend.
|
|
||||||
*/
|
*/
|
||||||
class JsonLdNode implements ArrayAccess
|
class JsonLdNode implements ArrayAccess
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The internal representation of the node.
|
* The Node within $this->graph that represents this JsonLdNode.
|
||||||
* @var Node
|
* @var Node
|
||||||
*/
|
*/
|
||||||
private $node;
|
private $node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The portion of the JSON-LD graph that this node knows about.
|
||||||
|
* @var Graph
|
||||||
|
*/
|
||||||
|
private $graph;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The factory used to construct this node.
|
||||||
|
* @var JsonLdNodeFactory
|
||||||
|
*/
|
||||||
|
private $factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The JSON-LD context that should be used when getting/setting properties on this node.
|
* The JSON-LD context that should be used when getting/setting properties on this node.
|
||||||
* @var array|\stdClass|string
|
* @var array|\stdClass|string
|
||||||
@ -30,20 +45,31 @@ class JsonLdNode implements ArrayAccess
|
|||||||
private $context;
|
private $context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JsonLdNode constructor.
|
* The dereferencer, used to dereference foreign nodes based on their IRIs.
|
||||||
* @param \stdClass $jsonLd The JSON-LD input as a stdClass.
|
* @var DereferencerInterface
|
||||||
* @param string $context This node's JSON-LD context.
|
|
||||||
*/
|
*/
|
||||||
public function __construct( $jsonLd, $context )
|
private $dereferencer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JsonLdNode constructor.
|
||||||
|
* @param Node|\stdClass $jsonLd The JSON-LD input as a stdClass or an existing \ML\JsonLD\Node instance.
|
||||||
|
* @param string $context This node's JSON-LD context.
|
||||||
|
* @param DereferencerInterface $dereferencer
|
||||||
|
*/
|
||||||
|
public function __construct( $jsonLd, $context, JsonLdNodeFactory $factory, DereferencerInterface $dereferencer )
|
||||||
{
|
{
|
||||||
$doc = JsonLD::getDocument( $jsonLd );
|
$this->factory = $factory;
|
||||||
$graph = $doc->getGraph();
|
$this->dereferencer = $dereferencer;
|
||||||
$id = empty( $doc->getIri() ) ? '_:b0' : $doc->getIri();
|
|
||||||
$this->node = $graph->getNode( $id );
|
|
||||||
if ( is_null( $this->node ) ) {
|
|
||||||
$this->node = $graph->createNode();
|
|
||||||
}
|
|
||||||
$this->context = $context;
|
$this->context = $context;
|
||||||
|
if ( $jsonLd instanceof Node ) {
|
||||||
|
$this->node = $jsonLd;
|
||||||
|
$this->graph = $jsonLd->getGraph();
|
||||||
|
} else {
|
||||||
|
$doc = JsonLD::getDocument( $jsonLd );
|
||||||
|
$this->graph = $doc->getGraph();
|
||||||
|
$nodes = $this->graph->getNodes();
|
||||||
|
$this->node = count( $nodes ) > 0 ? $nodes[0] : $this->graph->createNode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,9 +143,20 @@ class JsonLdNode implements ArrayAccess
|
|||||||
return $property->getValue();
|
return $property->getValue();
|
||||||
} else if ( is_array( $property ) ) {
|
} else if ( is_array( $property ) ) {
|
||||||
return array_map( array( $this, 'resolveProperty' ), $property );
|
return array_map( array( $this, 'resolveProperty' ), $property );
|
||||||
|
} else if ( $property instanceof Node ) {
|
||||||
|
if ( count( $property->getProperties() ) > 0 ) {
|
||||||
|
return $this->factory->newNode( $property );
|
||||||
|
} else {
|
||||||
|
// dereference the node to get its properties, then update $property's props with the retrieved values
|
||||||
|
$dereferenced = $this->dereferencer->dereference( $property->getId() );
|
||||||
|
$newNode = JsonLD::getDocument( $dereferenced )->getGraph()->getNode( $property->getId() );
|
||||||
|
foreach ( $newNode->getProperties() as $name => $value ) {
|
||||||
|
$property->setProperty( $name, $value );
|
||||||
|
}
|
||||||
|
return $this->factory->newNode( $property );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TODO handle lazy-loading linked nodes here
|
// TODO figure out what to do about as:items -- the vocab says it should be a node but the JsonLD lib
|
||||||
// also, figure out what to do about as:items -- the vocab says it should be a node but the JsonLD lib
|
|
||||||
// seems to resolve it to an array if it comes in as an array of string values...
|
// seems to resolve it to an array if it comes in as an array of string values...
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,12 +169,18 @@ class JsonLdNode implements ArrayAccess
|
|||||||
public function setProperty( $name, $value )
|
public function setProperty( $name, $value )
|
||||||
{
|
{
|
||||||
$expandedName = $this->expand_name( $name );
|
$expandedName = $this->expand_name( $name );
|
||||||
if ( $value instanceof \stdClass || is_array( $value ) ) {
|
if ( is_array( $value ) ) {
|
||||||
// TODO handle adding a new linked node here
|
$this->clearProperty( $expandedName );
|
||||||
// should instantiate a new JsonLdNode and recursively call __set
|
foreach ( $value as $v ) {
|
||||||
|
$this->addPropertyValue( $expandedName, $v );
|
||||||
|
}
|
||||||
|
} else if ( $value instanceof stdClass ) {
|
||||||
|
$newDoc = JsonLD::getDocument( $value );
|
||||||
|
$newNodes = $newDoc->getGraph()->getNodes();
|
||||||
|
$newNode = count( $newNodes ) > 0 ? $newNodes[0] : $this->graph->createNode();
|
||||||
|
$this->node->setProperty( $expandedName, $newNode );
|
||||||
} else if ( $value instanceof JsonLdNode ) {
|
} else if ( $value instanceof JsonLdNode ) {
|
||||||
// TODO handle adding a new linked node here
|
$this->setProperty( $expandedName, $value->asObject() );
|
||||||
// by getting the \ML\JsonLD\Node instance from the $value and calling $this->node->addPropertyValue()
|
|
||||||
} else {
|
} else {
|
||||||
$this->node->setProperty( $expandedName, $value );
|
$this->node->setProperty( $expandedName, $value );
|
||||||
}
|
}
|
||||||
@ -159,17 +202,21 @@ class JsonLdNode implements ArrayAccess
|
|||||||
* If the property already exists, the new value is added onto the existing values rather than
|
* If the property already exists, the new value is added onto the existing values rather than
|
||||||
* overwriting them.
|
* overwriting them.
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param string|\stdClass|array $value
|
* @param string|stdClass $value
|
||||||
*/
|
*/
|
||||||
public function addPropertyValue( $name, $value )
|
public function addPropertyValue( $name, $value )
|
||||||
{
|
{
|
||||||
$expandedName = $this->expand_name( $name );
|
$expandedName = $this->expand_name( $name );
|
||||||
if ( $value instanceof \stdClass || is_array( $value ) ) {
|
if ( is_array( $value ) ) {
|
||||||
// TODO handle adding a new linked node here
|
$err = "Can't add array value to a property. To add multiple values call addPropertyValue multiple times or use setProperty";
|
||||||
// should instantiate a new JsonLdNode and recursively call __set
|
throw new InvalidArgumentException( $err );
|
||||||
|
} else if ( $value instanceof stdClass ) {
|
||||||
|
$newDoc = JsonLD::getDocument( $value );
|
||||||
|
$newNodes = $newDoc->getGraph()->getNodes();
|
||||||
|
$newNode = count( $newNodes ) > 0 ? $newNodes[0] : $this->graph->createNode();
|
||||||
|
$this->node->addPropertyValue( $expandedName, $newNode );
|
||||||
} else if ( $value instanceof JsonLdNode ) {
|
} else if ( $value instanceof JsonLdNode ) {
|
||||||
// TODO handle adding a new linked node here
|
$this->addPropertyValue( $expandedName, $value->asObject() );
|
||||||
// by getting the \ML\JsonLD\Node instance from the $value and calling $this->node->addPropertyValue()
|
|
||||||
} else {
|
} else {
|
||||||
$this->node->addPropertyValue( $expandedName, $value );
|
$this->node->addPropertyValue( $expandedName, $value );
|
||||||
}
|
}
|
||||||
@ -184,6 +231,11 @@ class JsonLdNode implements ArrayAccess
|
|||||||
return $this->setProperty( $name, null );
|
return $this->setProperty( $name, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function asObject()
|
||||||
|
{
|
||||||
|
return $this->node->toJsonLd();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves $name to a full IRI given the JSON-LD context of this node.
|
* Resolves $name to a full IRI given the JSON-LD context of this node.
|
||||||
* @param string $name The name of the property to resolve.
|
* @param string $name The name of the property to resolve.
|
||||||
|
41
src/JsonLd/JsonLdNodeFactory.php
Normal file
41
src/JsonLd/JsonLdNodeFactory.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ActivityPub\JsonLd;
|
||||||
|
|
||||||
|
use ActivityPub\JsonLd\Dereferencer\DereferencerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory class for constructing JsonLdNode instances
|
||||||
|
* Class JsonLdNodeFactory
|
||||||
|
* @package ActivityPub\JsonLd
|
||||||
|
*/
|
||||||
|
class JsonLdNodeFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The JSON-LD context to give to new JsonLdNode instances.
|
||||||
|
* @var array|\stdClass|string
|
||||||
|
*/
|
||||||
|
private $context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dereferencer to pass to new JsonLdNode instances.
|
||||||
|
* @var DereferencerInterface
|
||||||
|
*/
|
||||||
|
private $dereferencer;
|
||||||
|
|
||||||
|
public function __construct( $context, DereferencerInterface $dereferencer )
|
||||||
|
{
|
||||||
|
$this->context = $context;
|
||||||
|
$this->dereferencer = $dereferencer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct and return a new JsonLdNode.
|
||||||
|
* @param Node|\stdClass $jsonLd The JSON-LD object input
|
||||||
|
* @return JsonLdNode
|
||||||
|
*/
|
||||||
|
public function newNode( $jsonLd )
|
||||||
|
{
|
||||||
|
return new JsonLdNode( $jsonLd, $this->context, $this, $this->dereferencer );
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user