activitypub-1.0.x-dev/src/Plugin/activitypub/type/Core.php
src/Plugin/activitypub/type/Core.php
<?php
namespace Drupal\activitypub\Plugin\activitypub\type;
use Drupal\activitypub\Entity\ActivityPubActivityInterface;
use Drupal\activitypub\Entity\ActivityPubTypeInterface;
use Drupal\activitypub\Services\Type\TypePluginBase;
use Drupal\Core\Entity\EntityInterface;
/**
* The ActivityPub core plugin.
*
* @ActivityPubType(
* id = "activitypub_core",
* label = @Translation("Core functionality")
* )
*/
class Core extends TypePluginBase {
/**
* {@inheritdoc}
*/
public function isExposed() {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function onActivityOutboxPreSave(ActivityPubActivityInterface $activity, EntityInterface $entity, ActivityPubTypeInterface $activityPubType, &$doSave) {
if (method_exists($entity, 'isPublished') && !$entity->isPublished()) {
$doSave = FALSE;
// Scheduler integration.
if (isset($entity->publish_on) && !empty($entity->publish_on)) {
$doSave = TRUE;
$activity->setUnpublished();
}
}
// Private activities can be saved.
if ($activity->isPrivate()) {
$doSave = TRUE;
}
}
/**
* {@inheritdoc}
*/
public function onActivityInboxPreSave(ActivityPubActivityInterface $activity, &$doSave) {
// Check update.
if ($activity->getType() == 'Update') {
$this->updateExistingActivity($activity);
$doSave = FALSE;
return;
}
// Check if we have an existing activity. Properties to match on: Type,
// actor and external id.
$conditions = [
'type' => $activity->getType(),
'actor' => $activity->getActor(),
'external_id' => $activity->getExternalId(),
];
if ($this->entityTypeManager->getStorage('activitypub_activity')->getActivityCount($conditions) > 0) {
$doSave = FALSE;
return;
}
// Types like Announce, Like, Follow will populate reference to local
// content or users. There might be others, but we can add those later.
if (in_array($activity->getType(), ["Like", "Announce", "Follow"])) {
if ($entity = $this->getEntityFromUrl($activity->getObject())) {
$activity->set('entity_id', $entity->id());
$activity->set('entity_type_id', $entity->getEntityTypeId());
}
}
// Private activity.
$payload = @json_decode($activity->getPayLoad(), TRUE);
if ($activity->getType() == 'Create' && empty($payload['cc'])) {
$followers_url = $activity->getActor() . '/followers';
if (in_array($followers_url, $payload['to'])) {
$activity->setFollowers();
}
elseif (!in_array(ActivityPubActivityInterface::PUBLIC_URL, $payload['to']) && !in_array($followers_url, $payload['to'])) {
$activity->setPrivate();
}
}
}
/**
* Update existing activity.
*
* @param \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function updateExistingActivity(ActivityPubActivityInterface $activity) {
$conditions = [
'type' => 'Create',
'actor' => $activity->getActor(),
'object' => $activity->getObject(),
'external_id' => $activity->getExternalId(),
'collection' => ActivityPubActivityInterface::INBOX,
];
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActivityStorage $storage */
$storage = $this->entityTypeManager->getStorage('activitypub_activity');
$activities = $storage->getActivities($conditions);
if (count($activities) === 1) {
$activity_to_update = array_shift($activities);
$activity_to_update->set('payload', $activity->getPayLoad());
try {
$activity_to_update->save();
}
catch (\Exception $e) {
$this->logger->error('Error updating existing activity: @message', ['@message' => $e->getMessage()]);
}
}
}
}