[WIP] Hack on serialization

This commit is contained in:
Jeremy Dormitzer 2019-05-26 16:29:48 -04:00
parent 113a26f130
commit 36d16f0352
3 changed files with 94 additions and 64 deletions

View File

@ -6,6 +6,7 @@ use ActivityPub\JsonLd\Dereferencer\DereferencerInterface;
use ActivityPub\JsonLd\Exceptions\NodeNotFoundException;
use ActivityPub\JsonLd\Exceptions\PropertyNotDefinedException;
use ActivityPub\JsonLd\TripleStore\TypedRdfTriple;
use ActivityPub\Utils\Util;
use ArrayAccess;
use BadMethodCallException;
use InvalidArgumentException;
@ -136,7 +137,11 @@ class JsonLdNode implements ArrayAccess
{
$expandedName = $this->expandName( $name );
if ( property_exists( $this->expanded, $expandedName ) ) {
return $this->resolveProperty( $expandedName, $this->expanded->$expandedName[0] );
$resolved = $this->resolveProperty( $expandedName, $this->expanded->$expandedName[0] );
if ( is_array( $resolved ) ) {
$resolved = $resolved[0];
}
return $resolved;
}
throw new PropertyNotDefinedException( $name );
}
@ -153,7 +158,11 @@ class JsonLdNode implements ArrayAccess
{
$expandedName = $this->expandName( $name );
if ( property_exists( $this->expanded, $expandedName ) ) {
return $this->resolveProperty( $expandedName, $this->expanded->$expandedName );
$resolved = $this->resolveProperty( $expandedName, $this->expanded->$expandedName );
if ( ! is_array( $resolved ) ) {
$resolved = array( $resolved );
}
return $resolved;
}
throw new PropertyNotDefinedException( $name );
}
@ -181,10 +190,11 @@ class JsonLdNode implements ArrayAccess
private function resolveProperty( $expandedName, &$property )
{
if ( is_array( $property ) ) {
for ( $i = 0; $i < count( $property); $i += 1) {
$names[] = $expandedName;
$properties = [];
foreach ( $property as $subProperty ) {
$properties[] = $this->resolveProperty( $expandedName, $subProperty );
}
return array_map( array( $this, 'resolveProperty'), $names, $property );
return $properties;
} else if ( $property instanceof stdClass && property_exists( $property, '@id') ) {
// Lazy-load if we only have the @id property
$idProp = '@id';
@ -201,6 +211,8 @@ class JsonLdNode implements ArrayAccess
}
return $referencedNode;
} else if ( $property instanceof stdClass && property_exists( $property, '@value' ) ) {
// TODO check for an @type and return an appropriate object type if present, e.g. Datetime for dates or
// number for nonNegativeInteger etc.
$value = '@value';
return $property->$value;
} else if ( $property instanceof stdClass ) {
@ -260,7 +272,7 @@ class JsonLdNode implements ArrayAccess
$referencedNode = $this->graph->getNode( $id );
if ( is_null( $referencedNode ) ) {
$backrefs = array( $expandedName => array( $this ) );
$referencedNode = $this->factory->newNode( $expandedValue, $this->graph, $backrefs );
$this->factory->newNode( $expandedValue, $this->graph, $backrefs );
} else {
$referencedNode->addBackReference( $expandedName, $this );
}
@ -323,7 +335,7 @@ class JsonLdNode implements ArrayAccess
*/
public function isBlankNode()
{
return property_exists( $this->expanded, '@id' );
return ! property_exists( $this->expanded, '@id' );
}
/**
@ -357,40 +369,39 @@ class JsonLdNode implements ArrayAccess
*/
public function toRdfTriples()
{
$cloned = clone $this->expanded;
// First serialize this node
$quads = JsonLD::toRdf( $cloned );
$idProp = '@id';
$valueProp = '@value';
$typeProp = '@type';
$triples = array();
foreach ( $quads as $quad ) {
if ( (string)$quad->getSubject() === $this->getId() ) {
$objectType = null;
if ( $quad->getObject() instanceof Value ) {
$object = $quad->getObject()->getValue();
if ( $quad->getObject() instanceof TypedValue ) {
$objectType = $quad->getObject()->getType();
}
} else {
$objectIri = $quad->getObject();
if ( $objectIri->getScheme() === '_' ) {
// TODO resolve the associated value to force the generation of a UUID, then set $object to the uuid
} else {
$object = (string)$quad->getObject();
}
$objectType = '@id';
}
$triples[] = TypedRdfTriple::create(
(string)$quad->getSubject(), (string)$quad->getProperty(), $object, $objectType
);
}
}
// Then serialize any sub-nodes
foreach ( $this->expanded as $name => $values ) {
if ( $name === '@id' ) {
foreach ( get_object_vars( $this->expanded ) as $attribute => $values ) {
if ( ! is_array( $values ) ) {
// If $values is not an array, this is the @id property
$triples[] = TypedRdfTriple::create( $this->getId(), $attribute, $values );
continue;
}
foreach ( $this->getMany( $name ) as $subNode ) {
if ( $subNode instanceof JsonLdNode ) {
$triples = array_merge( $triples, $subNode->toRdfTriples() );
foreach ( $values as $value ) {
if ( ! is_object( $value ) ) {
// If $value is not an object, this is the @type property
$triples[] = TypedRdfTriple::create( $this->getId(), $attribute, $value );
}
if ( property_exists( $value, '@id' ) ) {
$triples[] = TypedRdfTriple::create( $this->getId(), $attribute, $value->$idProp, '@id' );
} else if ( property_exists( $value, '@value' ) ) {
$jsonLdValue = Value::fromJsonLd( $value );
$triple = TypedRdfTriple::create( $this->getId(), $attribute, $jsonLdValue->getValue() );
if ( $jsonLdValue instanceof TypedValue ) {
$triple->setObjectType( $jsonLdValue->getType() );
}
$triples[] = $triple;
}
}
// Check if we should serialize any child nodes
foreach ( $this->getMany( $attribute ) as $childNode ) {
if ( $childNode instanceof JsonLdNode ) {
// Serialize the child node if it is local, i.e. has a local URI or is anonymous
if ( $childNode->isBlankNode() || Util::isLocalUri( $childNode->getId() ) ) {
$triples = array_merge( $triples, $childNode->toRdfTriples() );
}
}
}
}

View File

@ -4,8 +4,8 @@ namespace ActivityPub\JsonLd\TripleStore;
/**
* A triple represents a single fact in an RDF graph. A triple is made up a subject, a predicate, and an object.
* The object can also have a type, e.g. @id for references to other resources or
* http://www.w3.org/2001/XMLSchema#dateTime for date-time values.
* The object can also have a type, e.g. "@id" for references to other resources or
* "http://www.w3.org/2001/XMLSchema#dateTime" for date-time values.
*
* See https://www.w3.org/TR/rdf11-concepts/#data-model.
*

View File

@ -11,6 +11,7 @@ use ActivityPub\Test\TestConfig\APTestCase;
use ActivityPub\Test\TestUtils\TestUuidProvider;
use ActivityPub\Utils\Logger;
use stdClass;
use Symfony\Component\HttpFoundation\Request;
class JsonLdNodeTest extends APTestCase
{
@ -509,9 +510,8 @@ class JsonLdNodeTest extends APTestCase
array(
TypedRdfTriple::create(
'https://example.org/collections/1',
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
'https://www.w3.org/ns/activitystreams#Collection',
'@id'
'@id',
'https://example.org/collections/1'
),
TypedRdfTriple::create(
'https://example.org/collections/1',
@ -525,6 +525,26 @@ class JsonLdNodeTest extends APTestCase
'https://example.org/collections/1/items/2',
'@id'
),
TypedRdfTriple::create(
'https://example.org/collections/1/items/1',
'@id',
'https://example.org/collections/1/items/1'
),
TypedRdfTriple::create(
'https://example.org/collections/1/items/1',
'@type',
'https://www.w3.org/ns/activitystreams#Note',
),
TypedRdfTriple::create(
'https://example.org/collections/1/items/2',
'@id',
'https://example.org/collections/1/items/2'
),
TypedRdfTriple::create(
'https://example.org/collections/1/items/2',
'@type',
'https://www.w3.org/ns/activitystreams#Note',
),
TypedRdfTriple::create(
'https://example.org/collections/1',
'https://www.w3.org/ns/activitystreams#name',
@ -538,16 +558,9 @@ class JsonLdNodeTest extends APTestCase
'http://www.w3.org/2001/XMLSchema#dateTime'
),
TypedRdfTriple::create(
'https://example.org/collections/1/items/1',
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
'https://www.w3.org/ns/activitystreams#Note',
'@id'
),
TypedRdfTriple::create(
'https://example.org/collections/1/items/2',
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
'https://www.w3.org/ns/activitystreams#Note',
'@id'
'https://example.org/collections/1',
'@type',
'https://www.w3.org/ns/activitystreams#Collection',
),
),
array(
@ -575,25 +588,29 @@ class JsonLdNodeTest extends APTestCase
'publicKeyPem' => 'the_public_key',
)
),
$this->asContext,
array( 'https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1' ),
array(
TypedRdfTriple::create(
'https://example.org/sally',
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
'https://www.w3.org/ns/activitystreams#Actor',
'@id'
'@id',
'https://example.org/sally'
),
TypedRdfTriple::create(
$this->uuids[0],
'https://w3id.org/security#publicKeyPem',
'the_public_key',
'http://www.w3.org/2001/XMLSchema#string'
),
TypedRdfTriple::create(
'https://example.org/sally',
'@type',
'https://www.w3.org/ns/activitystreams#Actor'
),
TypedRdfTriple::create(
'https://example.org/sally',
'https://w3id.org/security/v1#publicKey',
$this->uuids[0]
),
TypedRdfTriple::create(
$this->uuids[0],
'https://w3id.org/security/v1#publicKeyPem',
'the_public_key',
'@id'
),
),
),
);
@ -604,6 +621,8 @@ class JsonLdNodeTest extends APTestCase
*/
public function testToRdfTriple( $inputObj, $context, $expectedTriples, $nodeGraph = array() )
{
$r = Request::create( 'https://example.org' );
$r->overrideGlobals();
$node = $this->makeJsonLdNode( $inputObj, $context, $nodeGraph );
$triples = $node->toRdfTriples();
$this->assertEquals( $expectedTriples, $triples );
@ -616,4 +635,4 @@ class JsonLdNodeTest extends APTestCase
);
return $factory->newNode( $inputObj );
}
}
}