Delete orphaned nodes and test update()

This commit is contained in:
Jeremy Dormitzer 2018-12-08 19:12:08 -05:00
parent a9f18c7396
commit 8e5706aff1
4 changed files with 282 additions and 4 deletions

View File

@ -21,7 +21,7 @@ class ActivityPubObject
/**
* This object's fields
* @OneToMany(targetEntity="Field", mappedBy="object")
* @OneToMany(targetEntity="Field", mappedBy="object", cascade={"persist", "remove"})
* @var Field[] An ArrayCollection of Fields
*/
protected $fields;
@ -144,6 +144,21 @@ class ActivityPubObject
return $this->lastUpdated;
}
/**
* Returns true if the object contains a field with key $name
*
* @return boolean
*/
public function hasField( string $name )
{
foreach( $this->getFields() as $field ) {
if ( $field->getName() === $name ) {
return true;
}
}
return false;
}
/**
* Adds a new field on the object
*

View File

@ -113,7 +113,7 @@ class Field
$this->object= $object;
}
protected function setTargetObject( ActivityPubObject $targetObject )
public function setTargetObject( ActivityPubObject $targetObject )
{
$this->value = null;
$targetObject->addReferencingField( $this );
@ -164,7 +164,17 @@ class Field
}
/**
* Returns either the value or the target object of the field, depending on which was set
* Returns the target object of the field or null if there isn't one
*
* @return ActivityPubObject|null
*/
public function getTargetObject()
{
return $this->targetObject;
}
/**
* Returns the value or the target object of the field, depending on which was set
*
* @return string|ActivityPubObject
*/

View File

@ -163,6 +163,10 @@ class ObjectsService
* to update and the value is the field's new value. If the value is
* null, the field will be deleted.
*
* If the update results in an orphaned anonymous node (an ActivityPubObject
* with no 'id' field that no longer has any references to it), then the
* orphaned node will be deleted.
*
* @return ActivityPubObject|null The updated object,
* or null if an object with that id isn't in the DB
*/
@ -176,10 +180,13 @@ class ObjectsService
if ( array_key_exists( $field->getName(), $updatedFields ) ) {
$newValue = $updatedFields[$field->getName()];
if ( is_array( $newValue ) ) {
// Should I handle orphaned nodes here?
$referencedObject = $this->createObject( $newValue );
$oldTargetObject = $field->getTargetObject();
$field->setTargetObject( $referencedObject );
$this->entityManager->persist( $field );
if ( $oldTargetObject && ! $oldTargetObject->hasField( 'id' ) ) {
$this->entityManager->remove( $oldTargetObject );
}
} else if ( ! $newValue ) {
$object->removeField( $field );
$this->entityManager->persist( $object );

View File

@ -835,14 +835,260 @@ class ObjectsServiceTest extends SQLiteTestCase
public function testItUpdatesObjectFieldToNewObject()
{
$fields = array(
'id' => 'https://example.com/notes/1',
'type' => 'Note',
'content' => 'This is a note',
'attributedTo' => array(
'id' => 'https://example.com/actors/1',
),
);
$createTime = self::getNow();
$object = $this->objectsService->createObject( $fields );
$update = array( 'attributedTo' => array(
'id' => 'https://example.com/actors/2',
) );
$updateTime = self::getNow();
$this->objectsService->updateObject( 'https://example.com/notes/1', $update );
$expected = new ArrayDataSet( array(
'objects' => array(
array(
'id' => 1,
'created' => $createTime,
'lastUpdated' => $updateTime
),
array(
'id' => 2,
'created' => $createTime,
'lastUpdated' => $createTime,
),
array(
'id' => 3,
'created' => $updateTime,
'lastUpdated' => $updateTime,
),
),
'fields' => array(
array(
'id' => 1,
'object_id' => 1,
'name' => 'id',
'value' => 'https://example.com/notes/1',
'created' => $createTime,
'lastUpdated' => $createTime,
'targetObject_id' => null,
),
array(
'id' => 2,
'object_id' => 1,
'name' => 'type',
'value' => 'Note',
'created' => $createTime,
'lastUpdated' => $createTime,
'targetObject_id' => null,
),
array(
'id' => 3,
'object_id' => 1,
'name' => 'content',
'value' => 'This is a note',
'created' => $createTime,
'lastUpdated' => $createTime,
'targetObject_id' => null,
),
array(
'id' => 4,
'object_id' => 2,
'name' => 'id',
'value' => 'https://example.com/actors/1',
'created' => $createTime,
'lastUpdated' => $createTime,
'targetObject_id' => null,
),
array(
'id' => 5,
'object_id' => 1,
'name' => 'attributedTo',
'value' => null,
'created' => $createTime,
'lastUpdated' => $updateTime,
'targetObject_id' => 3,
),
array(
'id' => 6,
'object_id' => 3,
'name' => 'id',
'value' => 'https://example.com/actors/2',
'created' => $updateTime,
'lastUpdated' => $updateTime,
'targetObject_id' => null,
),
),
) );
$expectedObjectsTable = $expected->getTable('objects');
$expectedFieldsTable = $expected->getTable('fields');
$objectsQueryTable = $this->getConnection()->createQueryTable(
'objects', 'SELECT * FROM objects'
);
$fieldsQueryTable = $this->getConnection()->createQueryTable(
'fields', 'SELECT * FROM fields'
);
$this->assertTablesEqual( $expectedObjectsTable, $objectsQueryTable );
$this->assertTablesEqual( $expectedFieldsTable, $fieldsQueryTable );
}
public function testItUpdatedObjectFieldArray()
{
$fields = array(
'id' => 'https://example.com/notes/1',
'type' => 'Note',
'content' => 'This is a note',
'likes' => array(
'https://example.com/likes/1',
'https://example.com/likes/2',
),
);
$createTime = self::getNow();
$object = $this->objectsService->createObject( $fields );
$update = array( 'likes' => array(
'https://example.com/likes/3',
'https://example.com/likes/4',
) );
$updateTime = self::getNow();
$this->objectsService->updateObject( 'https://example.com/notes/1', $update );
$expected = new ArrayDataSet( array(
'objects' => array(
array(
'id' => 1,
'created' => $createTime,
'lastUpdated' => $updateTime
),
array(
'id' => 3,
'created' => $updateTime,
'lastUpdated' => $updateTime,
),
),
'fields' => array(
array(
'id' => 1,
'object_id' => 1,
'name' => 'id',
'value' => 'https://example.com/notes/1',
'created' => $createTime,
'lastUpdated' => $createTime,
'targetObject_id' => null,
),
array(
'id' => 2,
'object_id' => 1,
'name' => 'type',
'value' => 'Note',
'created' => $createTime,
'lastUpdated' => $createTime,
'targetObject_id' => null,
),
array(
'id' => 3,
'object_id' => 1,
'name' => 'content',
'value' => 'This is a note',
'created' => $createTime,
'lastUpdated' => $createTime,
'targetObject_id' => null,
),
array(
'id' => 6,
'object_id' => 1,
'name' => 'likes',
'value' => null,
'created' => $createTime,
'lastUpdated' => $updateTime,
'targetObject_id' => 3,
),
array(
'id' => 7,
'object_id' => 3,
'name' => '0',
'value' => 'https://example.com/likes/3',
'created' => $updateTime,
'lastUpdated' => $updateTime,
'targetObject_id' => null,
),
array(
'id' => 8,
'object_id' => 3,
'name' => '1',
'value' => 'https://example.com/likes/4',
'created' => $updateTime,
'lastUpdated' => $updateTime,
'targetObject_id' => null,
),
),
) );
$expectedObjectsTable = $expected->getTable('objects');
$expectedFieldsTable = $expected->getTable('fields');
$objectsQueryTable = $this->getConnection()->createQueryTable(
'objects', 'SELECT * FROM objects'
);
$fieldsQueryTable = $this->getConnection()->createQueryTable(
'fields', 'SELECT * FROM fields'
);
$this->assertTablesEqual( $expectedObjectsTable, $objectsQueryTable );
$this->assertTablesEqual( $expectedFieldsTable, $fieldsQueryTable );
}
public function testItDeletesObjectField()
{
$fields = array(
'id' => 'https://example.com/notes/1',
'type' => 'Note',
'content' => 'This is a note'
);
$createTime = self::getNow();
$object = $this->objectsService->createObject( $fields );
$update = array( 'content' => null );
$updateTime = self::getNow();
$this->objectsService->updateObject( 'https://example.com/notes/1', $update );
$expected = new ArrayDataSet( array(
'objects' => array(
array(
'id' => 1,
'created' => $createTime,
'lastUpdated' => $updateTime
),
),
'fields' => array(
array(
'id' => 1,
'object_id' => 1,
'name' => 'id',
'value' => 'https://example.com/notes/1',
'created' => $createTime,
'lastUpdated' => $createTime,
'targetObject_id' => null,
),
array(
'id' => 2,
'object_id' => 1,
'name' => 'type',
'value' => 'Note',
'created' => $createTime,
'lastUpdated' => $createTime,
'targetObject_id' => null,
),
),
) );
$expectedObjectsTable = $expected->getTable('objects');
$expectedFieldsTable = $expected->getTable('fields');
$objectsQueryTable = $this->getConnection()->createQueryTable(
'objects', 'SELECT * FROM objects'
);
$fieldsQueryTable = $this->getConnection()->createQueryTable(
'fields', 'SELECT * FROM fields'
);
$this->assertTablesEqual( $expectedObjectsTable, $objectsQueryTable );
$this->assertTablesEqual( $expectedFieldsTable, $fieldsQueryTable );
}
}
?>