Implement and test CollectionsService::removeItem

This commit is contained in:
Jeremy Dormitzer 2019-03-03 12:37:10 -05:00
parent 4e02319ffa
commit 94c9ee417b
3 changed files with 202 additions and 3 deletions

View File

@ -96,7 +96,7 @@ class Field
} }
$field = new Field( $time ); $field = new Field( $time );
$field->setObject( $object, $time ); $field->setObject( $object, $time );
$field->setName( $name ); $field->setName( $name, $time );
$field->setValue( $value, $time ); $field->setValue( $value, $time );
return $field; return $field;
} }
@ -121,7 +121,7 @@ class Field
} }
$field = new Field( $time ); $field = new Field( $time );
$field->setObject( $object, $time ); $field->setObject( $object, $time );
$field->setName( $name ); $field->setName( $name, $time );
$field->setTargetObject( $targetObject, $time ); $field->setTargetObject( $targetObject, $time );
return $field; return $field;
} }
@ -218,9 +218,13 @@ class Field
return $this->name; return $this->name;
} }
protected function setName( $name ) public function setName( $name, DateTime $time = null )
{ {
if ( ! $time ) {
$time = new DateTime( "now" );
}
$this->name = $name; $this->name = $name;
$this->setLastUpdated( $time );
} }
/** /**

View File

@ -262,6 +262,9 @@ class CollectionsService
*/ */
public function addItem( ActivityPubObject $collection, $item ) public function addItem( ActivityPubObject $collection, $item )
{ {
if ( ! in_array( $collection['type'], array( 'Collection', 'OrderedCollection') ) ) {
return;
}
if ( $collection['type'] === 'Collection' ) { if ( $collection['type'] === 'Collection' ) {
$itemsFieldName = 'items'; $itemsFieldName = 'items';
} else if ( $collection['type'] === 'OrderedCollection' ) { } else if ( $collection['type'] === 'OrderedCollection' ) {
@ -323,5 +326,56 @@ class CollectionsService
$this->entityManager->persist( $collection ); $this->entityManager->persist( $collection );
$this->entityManager->flush(); $this->entityManager->flush();
} }
/**
* Remove the item with id $itemId from $collection, if such an item is present in the collection
*
* This is O(n) with the size of the collection.
*
* @param ActivityPubObject $collection
* @param string $itemId
*/
public function removeItem( ActivityPubObject $collection, $itemId )
{
if ( ! in_array( $collection['type'], array( 'Collection', 'OrderedCollection' ) ) ) {
return;
}
if ( $collection['type'] === 'Collection' ) {
$itemsFieldName = 'items';
} else if ( $collection['type'] === 'OrderedCollection' ) {
$itemsFieldName = 'orderedItems';
}
if ( ! $collection->hasField( $itemsFieldName ) ) {
return;
}
$itemsObj = $collection[$itemsFieldName];
foreach ( $itemsObj->getFields() as $arrayField ) {
if ( $arrayField->hasTargetObject() &&
$arrayField->getTargetObject()->getFieldValue( 'id' ) === $itemId ) {
$foundItemField = $arrayField;
$foundItemIndex = intval( $arrayField->getName() );
break;
}
}
if ( ! isset( $foundItemField ) ) {
return;
}
$itemsObj->removeField(
$foundItemField, $this->dateTimeProvider->getTime( 'collections-service.remove' )
);
$this->entityManager->persist( $itemsObj );
$this->entityManager->remove( $foundItemField );
while ( $itemsObj->hasField( $foundItemIndex + 1) ) {
$nextItemField = $itemsObj->getField( $foundItemIndex + 1 );
$nextItemField->setName(
$foundItemIndex, $this->dateTimeProvider->getTime( 'collections-service.remove' )
);
$this->entityManager->persist( $nextItemField );
$foundItemIndex = $foundItemIndex + 1;
}
$collection->setLastUpdated( $this->dateTimeProvider->getTime( 'collections-service.remove' ) );
$this->entityManager->persist( $collection );
$this->entityManager->flush();
}
} }

View File

@ -63,6 +63,7 @@ class CollectionsServiceDbTest extends SQLiteTestCase
'objects-service.create' => new DateTime( "12:00" ), 'objects-service.create' => new DateTime( "12:00" ),
'objects-service.update' => new DateTime( "12:01" ), 'objects-service.update' => new DateTime( "12:01" ),
'collections-service.add' => new DateTime( "12:03" ), 'collections-service.add' => new DateTime( "12:03" ),
'collections-service.remove' => new DateTime( "12:04" ),
) ); ) );
$this->httpClient = $this->getMock( Client::class ); $this->httpClient = $this->getMock( Client::class );
$this->httpClient->method( 'send' ) $this->httpClient->method( 'send' )
@ -419,6 +420,146 @@ class CollectionsServiceDbTest extends SQLiteTestCase
} }
} }
public function testRemoveItem()
{
$testCases = array(
array(
'id' => 'basicRemoveTest',
'collection' => array(
'id' => 'https://example.com/collections/1',
'type' => 'Collection',
'items' => array(
array( 'id' => 'https://example.com/items/1' ),
array( 'id' => 'https://example.com/items/2' ),
array( 'id' => 'https://example.com/items/3' ),
),
),
'itemIdToRemove' => 'https://example.com/items/2',
'expectedDataSet' => array(
'objects' => array(
array(
'id' => 1,
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'collections-service.remove' ),
),
array(
'id' => 2,
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'collections-service.remove' ),
),
array(
'id' => 3,
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
),
array(
'id' => 4,
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
),
array(
'id' => 5,
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
),
),
'fields' => array(
array(
'id' => 1,
'object_id' => 1,
'name' => 'id',
'value' => 'https://example.com/collections/1',
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
'targetObject_id' => null,
),
array(
'id' => 2,
'object_id' => 1,
'name' => 'type',
'value' => 'Collection',
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
'targetObject_id' => null,
),
array(
'id' => 3,
'object_id' => 3,
'name' => 'id',
'value' => 'https://example.com/items/1',
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
'targetObject_id' => null,
),
array(
'id' => 4,
'object_id' => 2,
'name' => 0,
'value' => null,
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
'targetObject_id' => 3,
),
array(
'id' => 5,
'object_id' => 4,
'name' => 'id',
'value' => 'https://example.com/items/2',
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
'targetObject_id' => null,
),
array(
'id' => 7,
'object_id' => 5,
'name' => 'id',
'value' => 'https://example.com/items/3',
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
'targetObject_id' => null,
),
array(
'id' => 8,
'object_id' => 2,
'name' => 1,
'value' => null,
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'collections-service.remove' ),
'targetObject_id' => 5,
),
array(
'id' => 9,
'object_id' => 1,
'name' => 'items',
'value' => null,
'created' => $this->getTime( 'objects-service.create' ),
'lastUpdated' => $this->getTime( 'objects-service.create' ),
'targetObject_id' => 2,
),
),
),
),
);
foreach ( $testCases as $testCase )
{
$this->setUp();
$collection = $this->objectsService->persist( $testCase['collection'] );
$this->collectionsService->removeItem( $collection, $testCase['itemIdToRemove'] );
$expectedDataSet = new ArrayDataSet( $testCase['expectedDataSet'] );
$expectedObjects = $expectedDataSet->getTable( 'objects' );
$expectedFields = $expectedDataSet->getTable( 'fields' );
$actualObjects = $this->getConnection()->createQueryTable(
'objects', 'SELECT * FROM objects'
);
$actualFields = $this->getConnection()->createQueryTable(
'fields', 'SELECT * FROM fields'
);
$this->assertTablesEqual( $expectedObjects, $actualObjects, "Error on test $testCase[id]");
$this->assertTablesEqual( $expectedFields, $actualFields, "Error on test $testCase[id]");
$this->tearDown();
}
}
/** /**
* Returns the test dataset. * Returns the test dataset.
* *