activitypub-1.0.x-dev/src/Plugin/activitypub/type/StaticTypes.php
src/Plugin/activitypub/type/StaticTypes.php
<?php
namespace Drupal\activitypub\Plugin\activitypub\type;
use Drupal\activitypub\Entity\ActivityPubActivityInterface;
use Drupal\activitypub\Services\Type\TypePluginBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
/**
* The ActivityPub static types.
*
* @ActivityPubType(
* id = "activitypub_static_types",
* label = @Translation("Static types")
* )
*/
class StaticTypes extends TypePluginBase {
/**
* {@inheritdoc}
*/
public function isExposed() {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function onActivityInboxPreSave(ActivityPubActivityInterface $activity, &$doSave) {
// Delete request. If actor and object are not the same, try to find an
// activity with the id.
if ($activity->getType() == 'Delete' && $activity->getCollection() == ActivityPubActivityInterface::INBOX) {
$doSave = FALSE;
if ($activity->getActor() != $activity->getObject()) {
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActivityStorageInterface $storage */
$storage = $this->entityTypeManager->getStorage('activitypub_activity');
foreach ($storage->getActivities(['object' => $activity->getObject(), '!type' => 'Delete']) as $a) {
$a->delete();
}
}
}
// Check if the actor already exists. If so, do not save the activity,
// otherwise, set status to 0.
if ($activity->getType() == 'Follow') {
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActivityStorageInterface $storage */
$storage = $this->entityTypeManager->getStorage('activitypub_activity');
$activities = $storage->getActivityRecords(['type' => 'Follow', 'actor' => $activity->getActor(), 'object' => $activity->getObject(), 'collection' => ActivityPubActivityInterface::INBOX]);
if (!empty($activities)) {
$doSave = FALSE;
}
else {
$activity->set('status', FALSE);
}
}
// Check undo request.
if ($activity->getType() == 'Undo') {
$payload = @json_decode($activity->getPayLoad(), TRUE);
if (isset($payload['object']) && isset($payload['object']['type']) && $payload['object']['type'] == 'Follow') {
$doSave = FALSE;
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActivityStorageInterface $storage */
$storage = $this->entityTypeManager->getStorage('activitypub_activity');
foreach ($storage->getActivities(['type' => 'Follow', 'actor' => $activity->getActor(), 'object' => $activity->getObject()]) as $a) {
$a->delete();
}
foreach ($storage->getActivities(['type' => 'Accept', 'object' => $activity->getActor(), 'actor' => $activity->getObject()]) as $a) {
$a->delete();
}
}
}
}
/**
* {@inheritdoc}
*/
public function onActivityPostSave(ActivityPubActivityInterface $activity, $update = TRUE) {
// Incoming follow request.
if ($activity->getType() == 'Follow' && $activity->getCollection() == ActivityPubActivityInterface::INBOX && !$update) {
$values = [
'uid' => $activity->getOwnerId(),
'collection' => ActivityPubActivityInterface::OUTBOX,
'config_id' => 'accept',
'type' => 'Accept',
'actor' => $activity->getObject(),
'object' => $activity->getActor(),
'external_id' => $activity->getExternalId(),
'status' => 0,
];
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $outboxActivity */
$outboxActivity = $this->entityTypeManager->getStorage('activitypub_activity')->create($values);
$outboxActivity->save();
$this->activityPubProcessClient->createQueueItem($outboxActivity);
}
// Incoming Move request. Remove any follow/accept requests in the inbox and
// outbox and create a new follow request in case you are following the
// original actor.
if ($activity->getType() == 'Move' && $activity->getCollection() == ActivityPubActivityInterface::INBOX && !$update) {
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActivityStorageInterface $storage */
$storage = $this->entityTypeManager->getStorage('activitypub_activity');
/** @var \Drupal\activitypub\Entity\ActivityPubActorInterface $actor */
$actor = $this->entityTypeManager->getStorage('activitypub_actor')->loadActorByEntityIdAndType($activity->getOwnerId(), 'person');
$follows = $storage->getActivities(['type' => ['Follow', 'Accept'], 'object' => $activity->getActor(), 'actor' => $this->activityPubUtility->getActivityPubID($actor)]);
if ($follows) {
foreach ($follows as $f) {
try {
if ($f->getType() == 'Follow') {
$values = [
'uid' => $activity->getOwnerId(),
'collection' => ActivityPubActivityInterface::OUTBOX,
'config_id' => 'follow',
'type' => 'Follow',
'actor' => $this->activityPubUtility->getActivityPubID($actor),
'object' => $activity->getObject(),
'status' => 0,
];
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $outboxActivity */
$outboxActivity = $this->entityTypeManager->getStorage('activitypub_activity')->create($values);
$outboxActivity->save();
}
$f->delete();
}
catch (\Exception $ignored) {}
}
}
$followee = $storage->getActivities(['type' => ['Follow', 'Accept'], 'actor' => $activity->getActor(), 'object' => $this->activityPubUtility->getActivityPubID($actor)]);
if ($followee) {
foreach ($followee as $f) {
try {
$f->delete();
}
catch (\Exception $ignored) {}
}
}
}
// Outgoing follow request.
if ($activity->getType() == 'Follow' && $activity->getCollection() == ActivityPubActivityInterface::OUTBOX && !$update) {
$this->activityPubProcessClient->createQueueItem($activity);
}
// Outgoing accept request.
if ($activity->getType() == 'Accept' && $activity->getCollection() == ActivityPubActivityInterface::OUTBOX && $update && $activity->isProcessed()) {
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActivityStorageInterface $storage */
$storage = $this->entityTypeManager->getStorage('activitypub_activity');
$activities = $storage->getActivities(['type' => 'Follow', 'actor' => $activity->getObject(), 'object' => $activity->getActor(), 'collection' => ActivityPubActivityInterface::INBOX]);
if (!empty($activities)) {
$followActivity = array_shift($activities);
$followActivity->set('status', TRUE);
$followActivity->save();
}
}
// Incoming accept request.
if ($activity->getType() == 'Accept' && $activity->getCollection() == ActivityPubActivityInterface::INBOX && !$update) {
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActivityStorageInterface $storage */
$storage = $this->entityTypeManager->getStorage('activitypub_activity');
$activities = $storage->getActivities(['type' => 'Follow', 'actor' => $activity->getObject(), 'object' => $activity->getActor(), 'collection' => ActivityPubActivityInterface::OUTBOX]);
if (!empty($activities)) {
$followActivity = array_shift($activities);
$followActivity->set('status', TRUE);
$followActivity->save();
}
}
// Undo request.
if ($activity->getType() == 'Undo' && !$update) {
$build = $activity->buildActivity();
if (isset($build['object']) && isset($build['object']['type']) && $build['object']['type'] == 'Follow') {
foreach ($this->entityTypeManager->getStorage('activitypub_activity')->loadByProperties(['type' => 'Follow', 'actor' => $activity->getActor(), 'object' => $activity->getObject()]) as $a) {
$a->delete();
}
foreach ($this->entityTypeManager->getStorage('activitypub_activity')->loadByProperties(['type' => 'Accept', 'object' => $activity->getActor(), 'actor' => $activity->getObject()]) as $a) {
$a->delete();
}
}
}
}
/**
* {@inheritdoc}
*/
public function build(ActivityPubActivityInterface $activity, EntityInterface $entity = NULL) {
$return = [];
// Follow type.
if ($this->getConfiguration()['activity'] == 'Follow') {
$attributes = [
'id' => $this->renderEntityUrl($activity),
'type' => $this->getConfiguration()['activity'],
'actor' => $activity->getActor(),
'object' => $activity->getObject(),
'to' => [$activity->getObject()],
];
$return = $attributes;
}
// Accept type.
if ($this->getConfiguration()['activity'] == 'Accept') {
$attributes = [
'id' => $this->renderEntityUrl($activity),
'type' => $this->getConfiguration()['activity'],
'actor' => $activity->getActor(),
'to' => [$activity->getObject()],
'object' => [
'type' => 'Follow',
'id' => $activity->getExternalId(),
'actor' => $activity->getObject(),
'object' => $activity->getActor(),
]
];
$return = $attributes;
}
// Undo type.
if ($this->getConfiguration()['activity'] == 'Undo') {
$attributes = [
'id' => $this->renderEntityUrl($activity),
'type' => $this->getConfiguration()['activity'],
'actor' => $activity->getActor(),
'to' => [$activity->getObject()],
'object' => [
'type' => 'Follow',
'id' => $activity->getExternalId(),
'actor' => $activity->getActor(),
'object' => $activity->getObject(),
]
];
$return = $attributes;
}
// Delete type.
if ($this->getConfiguration()['activity'] == 'Delete') {
/** @var \Drupal\activitypub\Entity\ActivityPubActorInterface $actor */
$actor = $this->entityTypeManager->getStorage('activitypub_actor')->loadActorByEntityIdAndType($activity->getOwnerId(), 'person');
if (!$activity->isPrivate()) {
$to = array_merge([ActivityPubActivityInterface::PUBLIC_URL], $activity->getTo());
$cc = [$this->renderUrl(Url::fromRoute('activitypub.followers', ['user' => $actor->getOwnerId(), 'activitypub_actor' => $actor->getName()], ['absolute' => TRUE]))];
}
else {
$to = $activity->getTo();
$cc = [];
}
$attributes['to'] = $to;
$attributes['cc'] = $cc;
$id = $this->renderEntityUrl($activity);
$object_id = $activity->getObject();
$attributes = [
'type' => $this->getConfiguration()['activity'],
'actor' => $activity->getActor(),
'to' => $to,
'cc' => $cc,
'id' => $id,
'object' => ['id' => $object_id],
];
$return = $attributes;
}
return $return;
}
/**
* {@inheritdoc}
*/
public function onEntityDelete(ActivityPubActivityInterface $activity, EntityInterface $entity) {
$values = [
'uid' => $activity->getOwnerId(),
'collection' => ActivityPubActivityInterface::OUTBOX,
'config_id' => 'delete',
'type' => 'Delete',
'actor' => $activity->getActor(),
'object' => $this->renderEntityUrl($entity),
'external_id' => $this->renderEntityUrl($activity),
'status' => 0,
'to' => $activity->getTo(),
];
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $outboxActivity */
$outboxActivity = $this->entityTypeManager->getStorage('activitypub_activity')->create($values);
$outboxActivity->save();
$this->activityPubProcessClient->createQueueItem($outboxActivity);
}
}
