Implement UndoHandler; register all activity handlers
This commit is contained in:
parent
6527a29f3d
commit
0a3ce77893
156
src/ActivityEventHandlers/UndoHandler.php
Normal file
156
src/ActivityEventHandlers/UndoHandler.php
Normal file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace ActivityPub\ActivityEventHandlers;
|
||||
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Objects\CollectionsService;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class UndoHandler implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var ObjectsService
|
||||
*/
|
||||
private $objectsService;
|
||||
|
||||
/**
|
||||
* @var CollectionsService
|
||||
*/
|
||||
private $collectionsService;
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
InboxActivityEvent::NAME => 'handleInbox',
|
||||
OutboxActivityEvent::NAME => 'handleOutbox',
|
||||
);
|
||||
}
|
||||
|
||||
public function __construct( ObjectsService $objectsService,
|
||||
CollectionsService $collectionsService )
|
||||
{
|
||||
$this->objectsService = $objectsService;
|
||||
$this->collectionsService = $collectionsService;
|
||||
}
|
||||
|
||||
// make sure actors match for undo activity and its object
|
||||
// Undoing likes: remove from likes/liked collection
|
||||
// Undoing follow: remove from following/followers collection
|
||||
|
||||
public function handleInbox( InboxActivityEvent $event )
|
||||
{
|
||||
$activity = $event->getActivity();
|
||||
if ( $activity['type'] !== 'Undo' ) {
|
||||
return;
|
||||
}
|
||||
$object = $this->getUndoObject( $activity );
|
||||
if ( ! ( $object && $object->hasField( 'type' ) ) ) {
|
||||
return;
|
||||
}
|
||||
if ( ! $this->undoIsValid( $activity, $object ) ) {
|
||||
return;
|
||||
}
|
||||
switch ( $object['type'] ) {
|
||||
case 'Follow':
|
||||
$this->removeFromCollection( $object['object'], 'followers', $object['actor'] );
|
||||
break;
|
||||
case 'Like':
|
||||
$this->removeFromCollection( $object['object'], 'likes', $object['actor'] );
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function handleOutbox( OutboxActivityEvent $event )
|
||||
{
|
||||
$activity = $event->getActivity();
|
||||
if ( $activity['type'] !== 'Undo' ) {
|
||||
return;
|
||||
}
|
||||
$object = $this->getUndoObject( $activity );
|
||||
if ( ! ( $object && $object->hasField( 'type' ) ) ) {
|
||||
return;
|
||||
}
|
||||
if ( ! $this->undoIsValid( $activity, $object ) ) {
|
||||
return;
|
||||
}
|
||||
switch ( $object['type'] ) {
|
||||
case 'Follow':
|
||||
$this->removeFromCollection( $object['actor'], 'following', $object['object'] );
|
||||
break;
|
||||
case 'Like':
|
||||
$this->removeFromCollection( $object['actor'], 'liked', $object['object'] );
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private function undoIsValid( $activity, ActivityPubObject $undoObject )
|
||||
{
|
||||
if ( ! array_key_exists( 'actor', $activity ) ) {
|
||||
return false;
|
||||
}
|
||||
$actorId = $activity['actor'];
|
||||
if ( is_array( $actorId ) && array_key_exists( 'id', $actorId ) ) {
|
||||
$actorId = $actorId['id'];
|
||||
}
|
||||
if ( ! is_string( $actorId ) ) {
|
||||
return false;
|
||||
}
|
||||
$objectActor = $undoObject['actor'];
|
||||
if ( ! $objectActor ) {
|
||||
return false;
|
||||
}
|
||||
return $actorId == $objectActor['id'];
|
||||
}
|
||||
|
||||
private function removeFromCollection( $object, $collectionField, $itemId )
|
||||
{
|
||||
if ( ! ( $object && $object instanceof ActivityPubObject ) ) {
|
||||
return;
|
||||
}
|
||||
if ( ! $object->hasField( $collectionField ) ) {
|
||||
return;
|
||||
}
|
||||
$collection = $object[$collectionField];
|
||||
if ( ! ( $collection && $collection instanceof ActivityPubObject ) ) {
|
||||
return;
|
||||
}
|
||||
if ( ! $itemId ) {
|
||||
return;
|
||||
}
|
||||
if ( $itemId instanceof ActivityPubObject && $itemId->hasField( 'id' ) ) {
|
||||
$itemId = $itemId['id'];
|
||||
} else if ( is_array( $itemId ) && array_key_exists( 'id', $itemId ) ) {
|
||||
$itemId = $itemId['id'];
|
||||
}
|
||||
if ( ! is_string( $itemId ) ) {
|
||||
return;
|
||||
}
|
||||
$this->collectionsService->removeItem( $collection, $itemId );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object of the undo activity as an ActivityPubObject
|
||||
* @param $activity
|
||||
* @return \ActivityPub\Entities\ActivityPubObject|null
|
||||
*/
|
||||
private function getUndoObject( $activity )
|
||||
{
|
||||
$objectId = $activity['object'];
|
||||
if ( is_array( $objectId ) ) {
|
||||
if ( ! array_key_exists( 'id', $objectId ) ) {
|
||||
return null;
|
||||
}
|
||||
$objectId = $objectId['id'];
|
||||
}
|
||||
$object = $this->objectsService->dereference( $objectId );
|
||||
if ( ! $object ) {
|
||||
return null;
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
}
|
@ -6,10 +6,14 @@ namespace ActivityPub;
|
||||
|
||||
use ActivityPub\ActivityEventHandlers\AcceptHandler;
|
||||
use ActivityPub\ActivityEventHandlers\AddHandler;
|
||||
use ActivityPub\ActivityEventHandlers\AnnounceHandler;
|
||||
use ActivityPub\ActivityEventHandlers\CreateHandler;
|
||||
use ActivityPub\ActivityEventHandlers\DeleteHandler;
|
||||
use ActivityPub\ActivityEventHandlers\FollowHandler;
|
||||
use ActivityPub\ActivityEventHandlers\LikeHandler;
|
||||
use ActivityPub\ActivityEventHandlers\NonActivityHandler;
|
||||
use ActivityPub\ActivityEventHandlers\RemoveHandler;
|
||||
use ActivityPub\ActivityEventHandlers\UndoHandler;
|
||||
use ActivityPub\ActivityEventHandlers\UpdateHandler;
|
||||
use ActivityPub\ActivityEventHandlers\ValidationHandler;
|
||||
use ActivityPub\Auth\AuthListener;
|
||||
@ -92,6 +96,10 @@ class ActivityPub
|
||||
$dispatcher->addSubscriber( $this->module->get( FollowHandler::class ) );
|
||||
$dispatcher->addSubscriber( $this->module->get( AcceptHandler::class ) );
|
||||
$dispatcher->addSubscriber( $this->module->get( AddHandler::class ) );
|
||||
$dispatcher->addSubscriber( $this->module->get( RemoveHandler::class ) );
|
||||
$dispatcher->addSubscriber( $this->module->get( LikeHandler::class ) );
|
||||
$dispatcher->addSubscriber( $this->module->get( AnnounceHandler::class ) );
|
||||
$dispatcher->addSubscriber( $this->module->get( UndoHandler::class ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6,10 +6,14 @@ namespace ActivityPub\Config;
|
||||
|
||||
use ActivityPub\ActivityEventHandlers\AcceptHandler;
|
||||
use ActivityPub\ActivityEventHandlers\AddHandler;
|
||||
use ActivityPub\ActivityEventHandlers\AnnounceHandler;
|
||||
use ActivityPub\ActivityEventHandlers\CreateHandler;
|
||||
use ActivityPub\ActivityEventHandlers\DeleteHandler;
|
||||
use ActivityPub\ActivityEventHandlers\FollowHandler;
|
||||
use ActivityPub\ActivityEventHandlers\LikeHandler;
|
||||
use ActivityPub\ActivityEventHandlers\NonActivityHandler;
|
||||
use ActivityPub\ActivityEventHandlers\RemoveHandler;
|
||||
use ActivityPub\ActivityEventHandlers\UndoHandler;
|
||||
use ActivityPub\ActivityEventHandlers\UpdateHandler;
|
||||
use ActivityPub\ActivityEventHandlers\ValidationHandler;
|
||||
use ActivityPub\Auth\AuthListener;
|
||||
@ -154,6 +158,24 @@ class ActivityPubModule
|
||||
$this->injector->register( AddHandler::class, AddHandler::class )
|
||||
->addArgument( new Reference( ObjectsService::class ) )
|
||||
->addArgument( new Reference( CollectionsService::class ) );
|
||||
|
||||
$this->injector->register( RemoveHandler::class, RemoveHandler::class )
|
||||
->addArgument( new Reference( ObjectsService::class ) )
|
||||
->addArgument( new Reference( CollectionsService::class ) );
|
||||
|
||||
$this->injector->register( LikeHandler::class, LikeHandler::class )
|
||||
->addArgument( new Reference( ObjectsService::class ) )
|
||||
->addArgument( new Reference( CollectionsService::class ) )
|
||||
->addArgument( new Reference( ContextProvider::class ) );
|
||||
|
||||
$this->injector->register( AnnounceHandler::class, AnnounceHandler::class )
|
||||
->addArgument( new Reference( ObjectsService::class ) )
|
||||
->addArgument( new Reference( CollectionsService::class ) )
|
||||
->addArgument( new Reference( ContextProvider::class ) );
|
||||
|
||||
$this->injector->register( UndoHandler::class, UndoHandler::class )
|
||||
->addArgument( new Reference( ObjectsService::class ) )
|
||||
->addArgument( new Reference( CollectionsService::class ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user