Implement and test AnnounceHandler

This commit is contained in:
Jeremy Dormitzer 2019-03-06 19:43:55 -05:00
parent eb1ed2e332
commit 94a54eab5f
2 changed files with 203 additions and 0 deletions

View File

@ -0,0 +1,78 @@
<?php
namespace ActivityPub\Activities;
use ActivityPub\Entities\ActivityPubObject;
use ActivityPub\Objects\CollectionsService;
use ActivityPub\Objects\ContextProvider;
use ActivityPub\Objects\ObjectsService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class AnnounceHandler implements EventSubscriberInterface
{
/**
* @var ObjectsService
*/
private $objectsService;
/**
* @var CollectionsService
*/
private $collectionsService;
/**
* @var ContextProvider
*/
private $contextProvider;
public static function getSubscribedEvents()
{
return array(
InboxActivityEvent::NAME => 'handleInbox',
);
}
public function __construct( ObjectsService $objectsService,
CollectionsService $collectionsService,
ContextProvider $contextProvider )
{
$this->objectsService = $objectsService;
$this->collectionsService = $collectionsService;
$this->contextProvider = $contextProvider;
}
public function handleInbox( InboxActivityEvent $event )
{
$activity = $event->getActivity();
if ( $activity['type'] !== 'Announce' ) {
return;
}
$objectId = $activity['object'];
if ( is_array( $objectId ) && array_key_exists( 'id', $objectId ) ) {
$objectId = $objectId['id'];
}
if ( ! is_string( $objectId ) ) {
throw new BadRequestHttpException( 'Invalid object' );
}
$object = $this->objectsService->dereference( $objectId );
if ( ! $object->hasField( 'shares' ) ) {
$object = $this->addCollectionToObject( $object, 'shares' );
}
$shares = $object['shares'];
$this->collectionsService->addItem( $shares, $activity );
}
private function addCollectionToObject( ActivityPubObject $object, $collectionName )
{
$updatedObject = $object->asArray();
$updatedObject[$collectionName] = array(
'@context' => $this->contextProvider->getContext(),
'id' => rtrim( $updatedObject['id'], '/' ) . '/' . $collectionName,
'type' => 'Collection',
'items' => array(),
);
return $this->objectsService->update( $object['id'], $updatedObject );
}
}

View File

@ -0,0 +1,125 @@
<?php
namespace ActivityPub\Test\Activities;
use ActivityPub\Activities\AnnounceHandler;
use ActivityPub\Activities\InboxActivityEvent;
use ActivityPub\Objects\CollectionsService;
use ActivityPub\Objects\ContextProvider;
use ActivityPub\Objects\ObjectsService;
use ActivityPub\Test\TestConfig\APTestCase;
use ActivityPub\Test\TestUtils\TestActivityPubObject;
use Symfony\Component\EventDispatcher\EventDispatcher;
class AnnounceHandlerTest extends APTestCase
{
private static function getObjects()
{
return array(
'https://example.com/notes/withshares' => array(
'id' => 'https://example.com/notes/withshares',
'shares' => array(
'type' => 'Collection',
'items' => array(),
),
),
'https://example.com/notes/withoutshares' => array(
'id' => 'https://example.com/notes/withoutshares',
),
);
}
public function testAnnounceHandler()
{
$testCases = array(
array(
'id' => 'basicInboxTest',
'eventName' => InboxActivityEvent::NAME,
'event' => new InboxActivityEvent(
array(
'id' => 'https://elsewhere.com/announces/1',
'type' => 'Announce',
'object' => 'https://example.com/notes/withshares',
),
TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
) ),
self::requestWithAttributes(
'https://example.com/actors/1/inbox',
array(
'actor' => TestActivityPubObject::fromArray( array(
'id' => 'https://elsewhere.com/actors/1',
) ),
)
)
),
'expectedNewShares' => array(
'id' => 'https://elsewhere.com/announces/1',
'type' => 'Announce',
'object' => 'https://example.com/notes/withshares',
)
),
array(
'id' => 'generatesSharesCollectionTest',
'eventName' => InboxActivityEvent::NAME,
'event' => new InboxActivityEvent(
array(
'id' => 'https://elsewhere.com/announces/1',
'type' => 'Announce',
'object' => 'https://example.com/notes/withoutshares',
),
TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
) ),
self::requestWithAttributes(
'https://example.com/actors/1/inbox',
array(
'actor' => TestActivityPubObject::fromArray( array(
'id' => 'https://elsewhere.com/actors/1',
) ),
)
)
),
'expectedNewShares' => array(
'id' => 'https://elsewhere.com/announces/1',
'type' => 'Announce',
'object' => 'https://example.com/notes/withoutshares',
)
),
);
foreach( $testCases as $testCase ) {
$objectsService = $this->getMock( ObjectsService::class );
$objectsService->method( 'dereference')->willReturnCallback( function( $id ) {
$objects = self::getObjects();
if ( array_key_exists( $id, $objects ) ) {
return TestActivityPubObject::fromArray( $objects[$id] );
} else {
return null;
}
});
$objectsService->method( 'update')->willReturnCallback( function( $id, $arr ) {
return TestActivityPubObject::fromArray( $arr );
});
$collectionsService = $this->getMockBuilder( CollectionsService::class )
->disableOriginalConstructor()
->setMethods( array( 'addItem' ) )
->getMock();
if ( array_key_exists( 'expectedNewShares', $testCase ) ) {
$collectionsService->expects( $this->once() )
->method( 'addItem' )
->with(
$this->anything(),
$this->equalTo( $testCase['expectedNewShares'] )
);
} else {
$collectionsService->expects( $this->never() )
->method( 'addItem' );
}
$contextProvider = new ContextProvider();
$announceHandler = new AnnounceHandler( $objectsService, $collectionsService, $contextProvider );
$eventDispatcher = new EventDispatcher();
$eventDispatcher->addSubscriber( $announceHandler );
$eventDispatcher->dispatch( $testCase['eventName'], $testCase['event'] );
}
}
}