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()]); } } } }