[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\JsonLdNode;
|
||||
use stdClass;
|
||||
|
||||
interface DereferencerInterface
|
||||
{
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
public function dereference( $iri );
|
||||
|
@ -2,27 +2,42 @@
|
||||
|
||||
namespace ActivityPub\JsonLd;
|
||||
|
||||
use ActivityPub\JsonLd\Dereferencer\DereferencerInterface;
|
||||
use ActivityPub\JsonLd\Exceptions\PropertyNotDefinedException;
|
||||
use ArrayAccess;
|
||||
use InvalidArgumentException;
|
||||
use ML\JsonLD\Graph;
|
||||
use ML\JsonLD\JsonLD;
|
||||
use ML\JsonLD\Node;
|
||||
use ML\JsonLD\Value;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class JsonLdNode
|
||||
* @package ActivityPub\JsonLd
|
||||
*
|
||||
* A representation of a node in a JSON-LD graph. Supports lazy-loading linked nodes and persisting RDF triples to
|
||||
* a storage backend.
|
||||
* A representation of a node in a JSON-LD graph. Supports lazy-loading linked nodes.
|
||||
*/
|
||||
class JsonLdNode implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* The internal representation of the node.
|
||||
* The Node within $this->graph that represents this JsonLdNode.
|
||||
* @var 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.
|
||||
* @var array|\stdClass|string
|
||||
@ -30,20 +45,31 @@ class JsonLdNode implements ArrayAccess
|
||||
private $context;
|
||||
|
||||
/**
|
||||
* JsonLdNode constructor.
|
||||
* @param \stdClass $jsonLd The JSON-LD input as a stdClass.
|
||||
* @param string $context This node's JSON-LD context.
|
||||
* The dereferencer, used to dereference foreign nodes based on their IRIs.
|
||||
* @var DereferencerInterface
|
||||
*/
|
||||
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 );
|
||||
$graph = $doc->getGraph();
|
||||
$id = empty( $doc->getIri() ) ? '_:b0' : $doc->getIri();
|
||||
$this->node = $graph->getNode( $id );
|
||||
if ( is_null( $this->node ) ) {
|
||||
$this->node = $graph->createNode();
|
||||
}
|
||||
$this->factory = $factory;
|
||||
$this->dereferencer = $dereferencer;
|
||||
$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();
|
||||
} else if ( is_array( $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 );
|
||||
}
|
||||
// TODO handle lazy-loading linked nodes here
|
||||
// also, figure out what to do about as:items -- the vocab says it should be a node but the JsonLD lib
|
||||
return $this->factory->newNode( $property );
|
||||
}
|
||||
}
|
||||
// TODO 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...
|
||||
}
|
||||
|
||||
@ -132,12 +169,18 @@ class JsonLdNode implements ArrayAccess
|
||||
public function setProperty( $name, $value )
|
||||
{
|
||||
$expandedName = $this->expand_name( $name );
|
||||
if ( $value instanceof \stdClass || is_array( $value ) ) {
|
||||
// TODO handle adding a new linked node here
|
||||
// should instantiate a new JsonLdNode and recursively call __set
|
||||
if ( is_array( $value ) ) {
|
||||
$this->clearProperty( $expandedName );
|
||||
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 ) {
|
||||
// TODO handle adding a new linked node here
|
||||
// by getting the \ML\JsonLD\Node instance from the $value and calling $this->node->addPropertyValue()
|
||||
$this->setProperty( $expandedName, $value->asObject() );
|
||||
} else {
|
||||
$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
|
||||
* overwriting them.
|
||||
* @param string $name
|
||||
* @param string|\stdClass|array $value
|
||||
* @param string|stdClass $value
|
||||
*/
|
||||
public function addPropertyValue( $name, $value )
|
||||
{
|
||||
$expandedName = $this->expand_name( $name );
|
||||
if ( $value instanceof \stdClass || is_array( $value ) ) {
|
||||
// TODO handle adding a new linked node here
|
||||
// should instantiate a new JsonLdNode and recursively call __set
|
||||
if ( is_array( $value ) ) {
|
||||
$err = "Can't add array value to a property. To add multiple values call addPropertyValue multiple times or use setProperty";
|
||||
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 ) {
|
||||
// TODO handle adding a new linked node here
|
||||
// by getting the \ML\JsonLD\Node instance from the $value and calling $this->node->addPropertyValue()
|
||||
$this->addPropertyValue( $expandedName, $value->asObject() );
|
||||
} else {
|
||||
$this->node->addPropertyValue( $expandedName, $value );
|
||||
}
|
||||
@ -184,6 +231,11 @@ class JsonLdNode implements ArrayAccess
|
||||
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.
|
||||
* @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