activitypub-1.0.x-dev/src/Entity/ActivityPubActivity.php
src/Entity/ActivityPubActivity.php
<?php
namespace Drupal\activitypub\Entity;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityPublishedTrait;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\user\EntityOwnerTrait;
/**
* Defines the ActivityPub activity entity class.
*
* @ContentEntityType(
* id = "activitypub_activity",
* label = @Translation("ActivityPub activity"),
* label_collection = @Translation("ActivityPub activities"),
* label_singular = @Translation("ActivityPub activity"),
* label_plural = @Translation("ActivityPub activities"),
* label_count = @PluralTranslation(
* singular = "@count ActivityPub activity",
* plural = "@count ActivityPub activities",
* ),
* persistent_cache = FALSE,
* handlers = {
* "access" = "Drupal\activitypub\Entity\ActivityPubActivityAccessControlHandler",
* "storage" = "Drupal\activitypub\Entity\Storage\ActivityPubActivityStorage",
* "storage_schema" = "Drupal\activitypub\Entity\Storage\ActivityPubActivityStorageSchema",
* "list_builder" = "Drupal\activitypub\Entity\ActivityPubActivityListBuilder",
* "views_data" = "Drupal\activitypub\Entity\ActivityPubActivityViewsData",
* "route_provider" = {
* "html" = "Drupal\activitypub\Entity\ActivityPubActivityRouteProvider",
* },
* "form" = {
* "default" = "Drupal\activitypub\Form\ActivityPubActivityForm",
* "add" = "Drupal\activitypub\Form\ActivityPubActivityForm",
* "edit" = "Drupal\activitypub\Form\ActivityPubActivityForm",
* "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm"
* },
* },
* base_table = "activitypub_activity",
* entity_keys = {
* "id" = "id",
* "label" = "id",
* "uuid" = "uuid",
* "owner" = "uid",
* "published" = "status"
* },
* links = {
* "canonical" = "/activitypub/{activitypub_activity}",
* "add-form" = "/activitypub/add",
* "edit-form" = "/activitypub/{activitypub_activity}/edit",
* "delete-form" = "/activitypub/{activitypub_activity}/delete",
* "queue" = "/activitypub/{activitypub_activity}/queue",
* "undo" = "/activitypub/{activitypub_activity}/undo"
* }
* )
*/
class ActivityPubActivity extends ContentEntityBase implements ActivityPubActivityInterface {
use EntityOwnerTrait;
use EntityPublishedTrait;
/**
* The object plugin manager.
*
* @var \Drupal\activitypub\Services\Type\TypePluginManager
*/
protected $typePluginManager;
/**
* {@inheritdoc}
*/
public function getTypePluginManager() {
if (!isset($this->typePluginManager)) {
$this->typePluginManager = \Drupal::service('plugin.manager.activitypub.type');
}
return $this->typePluginManager;
}
/**
* {@inheritdoc}
*
* When a new activitypub actor entity is created, set the uid entity
* reference to the current user as the creator of the entity.
*/
public static function preCreate(EntityStorageInterface $storage_controller, array &$values) {
parent::preCreate($storage_controller, $values);
$values += ['uid' => \Drupal::currentUser()->id()];
}
/**
* {@inheritdoc}
*/
public function getCreatedTime() {
return $this->get('created')->value;
}
/**
* {@inheritdoc}
*/
public function isProcessed() {
return (bool) $this->get('processed')->value;
}
/**
* {@inheritdoc}
*/
public function isQueued() {
return (bool) $this->get('queued')->value;
}
/**
* {@inheritdoc}
*/
public function getCollection() {
return $this->get('collection')->value;
}
/**
* {@inheritdoc}
*/
public function getExternalId() {
return $this->get('external_id')->value;
}
/**
* {@inheritdoc}
*/
public function getType() {
return $this->get('type')->value;
}
/**
* {@inheritdoc}
*/
public function getObject() {
return $this->get('object')->value;
}
/**
* {@inheritdoc}
*/
public function getReply() {
return $this->get('reply')->value;
}
/**
* {@inheritdoc}
*/
public function getConfigID() {
return $this->get('config_id')->value;
}
/**
* {@inheritdoc}
*/
public function getActor() {
return $this->get('actor')->value;
}
/**
* {@inheritdoc}
*/
public function getTargetEntityTypeId() {
return $this->get('entity_type_id')->value;
}
/**
* {@inheritdoc}
*/
public function getTargetEntityId() {
return $this->get('entity_id')->value;
}
/**
* {@inheritdoc}
*/
public function getPayLoad() {
return $this->get('payload')->value;
}
/**
* {@inheritdoc}
*/
public function getContext() {
return $this->get('context')->value;
}
/**
* {@inheritdoc}
*/
public function getToRaw() {
return $this->get('to')->value;
}
/**
* {@inheritdoc}
*/
public function getTo() {
$to = [];
foreach (explode("\n", $this->getToRaw() ?: '') as $t) {
$t = trim($t);
if (!empty($t)) {
$to[] = $t;
}
}
return $to;
}
/**
* {@inheritdoc}
*/
public function getVisibility() {
return $this->get('visibility')->value;
}
/**
* {@inheritdoc}
*/
public function isRead() {
return (bool) $this->get('is_read')->value;
}
/**
* {@inheritdoc}
*/
public function isMuted() {
return (bool) $this->get('mute')->value;
}
/**
* {@inheritdoc}
*/
public function isPublic() {
return $this->get('visibility')->value == self::VISIBILITY_PUBLIC;
}
/**
* {@inheritdoc}
*/
public function isFollowers() {
return $this->get('visibility')->value == self::VISIBILITY_FOLLOWERS;
}
/**
* {@inheritdoc}
*/
public function isUnlisted() {
return $this->get('visibility')->value == self::VISIBILITY_UNLISTED;
}
/**
* {@inheritdoc}
*/
public function isPrivate() {
return $this->get('visibility')->value == self::VISIBILITY_PRIVATE;
}
/**
* {@inheritdoc}
*/
public function canUseSharedInbox() {
return $this->isPublic() || $this->isFollowers();
}
/**
* {@inheritdoc}
*/
public function setTo($to) {
$this->set('to', $to);
return $this;
}
/**
* {@inheritdoc}
*/
public function setVisibility(int $visibility) {
$this->set('visibility', $visibility);
return $this;
}
/**
* {@inheritdoc}
*/
public function setPublic() {
$this->set('visibility', self::VISIBILITY_PUBLIC);
return $this;
}
/**
* {@inheritdoc}
*/
public function setFollowers() {
$this->set('visibility', self::VISIBILITY_FOLLOWERS);
return $this;
}
/**
* {@inheritdoc}
*/
public function setUnlisted() {
$this->set('visibility', self::VISIBILITY_UNLISTED);
return $this;
}
/**
* {@inheritdoc}
*/
public function setPrivate() {
$this->set('visibility', self::VISIBILITY_PRIVATE);
return $this;
}
/**
* {@inheritdoc}
*/
public function mute() {
$this->set('mute', 1);
return $this;
}
/**
* {@inheritdoc}
*/
public function unMute() {
$this->set('mute', 0);
return $this;
}
/**
* {@inheritdoc}
*/
public function buildActivity() {
$activityPubType = NULL;
if ($this->getConfigID()) {
/** @var \Drupal\activitypub\Entity\ActivityPubTypeInterface $activityPubType */
$activityPubType = $this->entityTypeManager()->getStorage('activitypub_type')->load($this->getConfigID());
}
// No config type found, we can not build anything.
if (!$activityPubType || !$activityPubType->isEnabled()) {
return [];
}
// Add entity.
$entity = NULL;
if ($this->getTargetEntityTypeId() && $this->getTargetEntityId()) {
$entity = $this->entityTypeManager()->getStorage($this->getTargetEntityTypeId())->load($this->getTargetEntityId());
}
/** @var \Drupal\activitypub\Services\Type\TypePluginInterface $object */
$object = $this->getTypePluginManager()->createInstance($activityPubType->getPlugin()['id'], $activityPubType->getPlugin()['configuration']);
return $object->build($this, $entity);
}
/**
* {@inheritdoc}
*/
public function doInboxProcess($type = NULL) {
/** @var \Drupal\activitypub\Entity\ActivityPubTypeInterface $activityPubType */
$id = !isset($type) ? $this->getConfigID() : $type;
$activityPubType = $this->entityTypeManager()->getStorage('activitypub_type')->load($id);
// No config type found, we can not process anything.
if (!$activityPubType || !$activityPubType->isEnabled()) {
return FALSE;
}
// Add entity.
$entity = NULL;
if ($this->getTargetEntityTypeId() && $this->getTargetEntityId()) {
$entity = $this->entityTypeManager()->getStorage($this->getTargetEntityTypeId())->load($this->getTargetEntityId());
}
/** @var \Drupal\activitypub\Services\Type\TypePluginInterface $object */
$object = $this->getTypePluginManager()->createInstance($activityPubType->getPlugin()['id'], $activityPubType->getPlugin()['configuration']);
return $object->doInboxProcess($this, $entity);
}
/**
* {@inheritdoc}
*/
public function canBeQueued() {
$canBeQueued = FALSE;
if ($this->getCollection() == ActivityPubActivityInterface::OUTBOX && !$this->isProcessed()) {
$canBeQueued = TRUE;
}
elseif ($this->getCollection() == ActivityPubActivityInterface::INBOX && !$this->isQueued() && $this->typeIsEnabled('context') && ($this->getReply() || in_array($this->getType(), ['Like', 'Announce']))) {
$canBeQueued = TRUE;
}
return $canBeQueued;
}
/**
* {@inheritdoc}
*/
public function canBeUndone() {
$canBeUndone = FALSE;
if ($this->getCollection() == ActivityPubActivityInterface::OUTBOX && $this->getType() == 'Follow' && $this->isPublished()) {
$canBeUndone = TRUE;
}
return $canBeUndone;
}
/**
* Returns whether a type is enabled or not.
*
* @param $type
*
* @return bool
*/
public function typeIsEnabled($type) {
try {
/** @var \Drupal\activitypub\Entity\ActivityPubTypeInterface $activityPubType */
$activityPubType = $this->entityTypeManager()->getStorage('activitypub_type')->load($type);
if ($activityPubType && $activityPubType->isEnabled()) {
return TRUE;
}
}
catch (\Exception $ignored) {}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function preInboxSave(&$doSave) {
foreach (array_keys($this->getTypePluginManager()->getDefinitions()) as $plugin_id) {
/** @var \Drupal\activitypub\Services\Type\TypePluginInterface $object */
$object = $this->getTypePluginManager()->createInstance($plugin_id);
$object->onActivityInboxPreSave($this,$doSave);
}
}
/**
* {@inheritdoc}
*/
public function preOutboxSave(EntityInterface $entity, ActivityPubTypeInterface $activityPubType, &$doSave) {
foreach (array_keys($this->getTypePluginManager()->getDefinitions()) as $plugin_id) {
/** @var \Drupal\activitypub\Services\Type\TypePluginInterface $object */
$object = $this->getTypePluginManager()->createInstance($plugin_id);
$object->onActivityOutboxPreSave($this, $entity, $activityPubType, $doSave);
}
}
/**
* {@inheritdoc}
*/
public function onEntityDelete(EntityInterface $entity) {
foreach (array_keys($this->getTypePluginManager()->getDefinitions()) as $plugin_id) {
/** @var \Drupal\activitypub\Services\Type\TypePluginInterface $object */
$object = $this->getTypePluginManager()->createInstance($plugin_id);
$object->onEntityDelete($this, $entity);
}
}
/**
* {@inheritdoc}
*/
public function delete() {
parent::delete();
foreach (array_keys($this->getTypePluginManager()->getDefinitions()) as $plugin_id) {
/** @var \Drupal\activitypub\Services\Type\TypePluginInterface $object */
$object = $this->getTypePluginManager()->createInstance($plugin_id);
$object->onActivityDelete($this);
}
}
/**
* {@inheritdoc}
*/
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
foreach (array_keys($this->getTypePluginManager()->getDefinitions()) as $plugin_id) {
/** @var \Drupal\activitypub\Services\Type\TypePluginInterface $object */
$object = $this->getTypePluginManager()->createInstance($plugin_id);
$object->onActivityPostSave($this, $update);
}
}
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields += static::ownerBaseFieldDefinitions($entity_type);
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created'))
->setDescription(t('The time that the activity was created.'));
$fields['collection'] = BaseFieldDefinition::create('string')
->setLabel(t('Collection'))
->setRequired(TRUE)
->setSetting('max_length', 40);
$fields['external_id'] = BaseFieldDefinition::create('string')
->setLabel(t('External ID'))
->setSetting('max_length', 128);
$fields['type'] = BaseFieldDefinition::create('string')
->setLabel(t('Type'))
->setSetting('max_length', 128);
$fields['actor'] = BaseFieldDefinition::create('string')
->setLabel(t('Actor'))
->setSetting('max_length', 128);
$fields['object'] = BaseFieldDefinition::create('string')
->setLabel(t('Object'))
->setSetting('max_length', 128);
$fields['reply'] = BaseFieldDefinition::create('string')
->setLabel(t('Reply'))
->setSetting('max_length', 128);
$fields['config_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Config ID'))
->setSetting('max_length', 128);
$fields['entity_type_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Entity Type'))
->setSetting('max_length', 128);
$fields['entity_id'] = BaseFieldDefinition::create('integer')
->setLabel(t('Entity ID'));
$fields['processed'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Processed'))
->setDefaultValue(FALSE);
$fields['queued'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Queued'))
->setDefaultValue(FALSE);
$fields['status'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Status'))
->setDefaultValue(TRUE);
$fields['payload'] = BaseFieldDefinition::create('string_long')
->setLabel('Payload');
$fields['context'] = BaseFieldDefinition::create('string_long')
->setLabel('Context');
$fields['to'] = BaseFieldDefinition::create('string_long')
->setLabel(t('To'));
$fields['is_read'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Read'))
->setDefaultValue(0);
$fields['visibility'] = BaseFieldDefinition::create('integer')
->setLabel(t('Post privacy'))
->setDefaultValue(1);
$fields['mute'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Mute'))
->setDefaultValue(0);
return $fields;
}
}
