Commit 50b0e02f authored by swentel's avatar swentel

Issue #3166194: store activities

parent 7c4ebff5
......@@ -17,14 +17,14 @@ use Drupal\Component\Annotation\Plugin;
class ActivityPubObject extends Plugin {
/**
* The widget plugin id.
* The plugin id.
*
* @var string
*/
public $id;
/**
* The human-readable name of the widget plugin.
* The human-readable name of the plugin.
*
* @var \Drupal\Core\Annotation\Translation
*
......@@ -42,7 +42,7 @@ class ActivityPubObject extends Plugin {
public $description;
/**
* Class used to retrieve derivative definitions of the facet_manager.
* Class used to retrieve derivative definitions.
*
* @var string
*/
......
......@@ -66,6 +66,7 @@ class FollowController extends BaseController {
try {
// TODO paging
$page = $request->get('page');
if (!isset($page)) {
$data = $this->getCollectionInfo($user, $activitypub_actor, $type);
......
......@@ -50,7 +50,6 @@ class InboxController extends BaseController {
*/
public function inbox(Request $request, UserInterface $user, ActivitypubActorInterface $activitypub_actor) {
$status = 400;
$user = $activitypub_actor->getOwner();
try {
$payload = Util::decodeJson((string)$request->getContent());
......
......@@ -3,14 +3,42 @@
namespace Drupal\activitypub\Controller;
use Drupal\activitypub\Entity\ActivitypubActorInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\activitypub\Services\ActivityPubKeysInterface;
use Drupal\activitypub\Services\ActivityPubUtilityInterface;
use Drupal\activitypub\Services\Object\ObjectPluginManager;
use Drupal\Core\Url;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
class OutboxController extends BaseController {
/**
* The ActivityPub object plugin manager.
*
* @var \Drupal\activitypub\Services\Object\ObjectPluginManager
*/
protected $objectPluginManager;
/**
* Outbox constructor
*
* @param \Drupal\activitypub\Services\Object\ObjectPluginManager $objectPluginManager
*/
public function __construct(ObjectPluginManager $objectPluginManager) {
$this->objectPluginManager = $objectPluginManager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.activitypub.object')
);
}
/**
* Outbox routing callback.
*
......@@ -87,12 +115,20 @@ class OutboxController extends BaseController {
'id' => Url::fromRoute('activitypub.outbox', ['user' => $user->id(), 'activitypub_actor' => $activitypub_actor->getName()], ['absolute' => TRUE, 'query' => ['page' => $page]])->toString(),
];
// TODO paging.
$items = [];
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface[] $activities */
$conditions = ['uid' => $activitypub_actor->getOwnerId()];
$activities = $this->entityTypeManager()->getStorage('activitypub_activity')->loadByProperties($conditions);
$storage = $this->entityTypeManager()->getStorage('activitypub_activity');
$ids = $storage->getQuery()
->condition('uid', $activitypub_actor->getOwnerId())
->sort('id', 'DESC')
->execute();
$activities = $storage->loadMultiple($ids);
foreach ($activities as $activity) {
$items[] = $activity->getType();
/** @var \Drupal\activitypub\Entity\ActivityPubObjectMappingInterface $activityPubObjectMapping */
$activityPubObjectMapping = $this->entityTypeManager()->getStorage('activitypub_object_mapping')->load($activity->getType());
$entity = $this->entityTypeManager()->getStorage($activity->getTargetEntityTypeId())->load($activity->getTargetEntityId());
$items[] = $activity->generateActivity($activityPubObjectMapping, $this->objectPluginManager, $entity);
}
$data['orderedItems'] = $items;
......
......@@ -2,7 +2,9 @@
namespace Drupal\activitypub\Entity;
use Drupal\activitypub\Services\Object\ObjectPluginManager;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
......@@ -80,6 +82,29 @@ class ActivityPubActivity extends ContentEntityBase implements ActivityPubActivi
return $this->get('target')->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 generateActivity(ActivityPubObjectMappingInterface $activityPubMapping, ObjectPluginManager $objectPluginManager, EntityInterface $entity) {
/** @var \Drupal\activitypub\Services\Object\ObjectPluginInterface $object */
$object = $objectPluginManager->createInstance($activityPubMapping->getActivityPubPlugin());
return $object->generate($this, $activityPubMapping, $entity);
}
/**
* {@inheritdoc}
*/
......@@ -111,6 +136,13 @@ class ActivityPubActivity extends ContentEntityBase implements ActivityPubActivi
->setLabel(t('Object'))
->setSetting('max_length', 255);
$fields['entity_type_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Entity Type'))
->setSetting('max_length', 255);
$fields['entity_id'] = BaseFieldDefinition::create('integer')
->setLabel(t('Entity ID'));
$fields['status'] = BaseFieldDefinition::create('boolean')
->setLabel(new TranslatableMarkup('Status'))
->setDefaultValue(TRUE);
......
......@@ -2,7 +2,9 @@
namespace Drupal\activitypub\Entity;
use Drupal\activitypub\Services\Object\ObjectPluginManager;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\user\EntityOwnerInterface;
/**
......@@ -41,4 +43,29 @@ interface ActivityPubActivityInterface extends ContentEntityInterface, EntityOwn
*/
public function getTarget();
/**
* Returns the target Entity Type.
*
* @return string
*/
public function getTargetEntityTypeId();
/**
* Return the target entity id.
*
* @return integer
*/
public function getTargetEntityId();
/**
* Generate the activity.
*
* @param \Drupal\activitypub\Entity\ActivityPubObjectMappingInterface $activityPubMapping
* @param \Drupal\activitypub\Services\Object\ObjectPluginManager $objectPluginManager
* @param \Drupal\Core\Entity\EntityInterface $entity
*
* @return array
*/
public function generateActivity(ActivityPubObjectMappingInterface $activityPubMapping, ObjectPluginManager $objectPluginManager, EntityInterface $entity);
}
......@@ -117,10 +117,26 @@ class ActivityPubObjectMapping extends ConfigEntityBase implements ActivityPubOb
/**
* {@inheritdoc}
*/
public function getActivityPubObject() {
public function getPluginAndObject() {
return $this->object;
}
/**
* {@inheritdoc}
*/
public function getActivityPubPlugin() {
$ex = explode('::', $this->object);
return $ex[0];
}
/**
* {@inheritdoc}
*/
public function getActivityPubObject() {
$ex = explode('::', $this->object);
return $ex[1];
}
/**
* {@inheritdoc}
*/
......
......@@ -16,6 +16,20 @@ interface ActivityPubObjectMappingInterface extends ConfigEntityInterface {
*/
public function getActivityPubActivity();
/**
* Returns the ActivityPub plugin and object.
*
* @return string
*/
public function getPluginAndObject();
/**
* Returns the Plugin.
*
* @return string
*/
public function getActivityPubPlugin();
/**
* Returns the ActivityPub object.
*
......
......@@ -133,7 +133,7 @@ class ActivityPubObjectMappingForm extends EntityForm {
$form['object'] = [
'#type' => 'select',
'#title' => $this->t('ActivityPub object'),
'#default_value' => $this->entity->getActivityPubObject(),
'#default_value' => $this->entity->getPluginAndObject(),
'#options' => $activitypub_object_options,
'#ajax' => [
'trigger_as' => ['name' => 'mapping_configure'],
......@@ -166,7 +166,7 @@ class ActivityPubObjectMappingForm extends EntityForm {
];
$bundle = $form_state->getValue('target_bundle') ?: $this->entity->getTargetBundle();
$object = $form_state->getValue('object') ?: $this->entity->getActivityPubObject();
$object = $form_state->getValue('object') ?: $this->entity->getPluginAndObject();
if (!empty($bundle) && !empty($object)) {
......
......@@ -2,7 +2,11 @@
namespace Drupal\activitypub\Plugin\activitypub\object;
use ActivityPhp\Type;
use Drupal\activitypub\Entity\ActivityPubActivityInterface;
use Drupal\activitypub\Entity\ActivityPubObjectMappingInterface;
use Drupal\activitypub\Services\Object\ObjectPluginBase;
use Drupal\Core\Entity\EntityInterface;
/**
* The ActivityPub core types.
......@@ -19,8 +23,7 @@ class CoreTypes extends ObjectPluginBase {
*/
public function getObjects() {
return [
'Article', 'Audio', 'Document', 'Event', 'Image', 'Mention', 'Note',
'Page', 'Place', 'Profile', 'Relationship', 'Tombstone', 'Video'
'Article', 'Note',
];
}
......@@ -32,8 +35,32 @@ class CoreTypes extends ObjectPluginBase {
'published',
'content',
'inReplyTo',
'attachment',
];
}
/**
* {@inheritdoc}
*/
public function generate(ActivityPubActivityInterface $activity, ActivityPubObjectMappingInterface $objectMapping, EntityInterface $entity) {
$attributes = [
'type' => $objectMapping->getActivityPubObject(),
'id' => $entity->toUrl('canonical', ['absolute' => TRUE])->toString(),
];
foreach ($objectMapping->getFieldMapping() as $mapping) {
if (!empty($mapping['field_name'])) {
if ($entity->hasField($mapping['field_name']) && ($value = $entity->get($mapping['field_name'])->getValue())) {
if ($v = $this->getValue($mapping['property'], $value)) {
$attributes[$mapping['property']] = $v;
}
}
}
}
$type = Type::create($attributes);
$activity = Type::create(['type' => $objectMapping->getActivityPubActivity(), 'object' => $type->toArray()]);
return $activity->toArray();
}
}
......@@ -2,6 +2,7 @@
namespace Drupal\activitypub\Services;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
......@@ -14,6 +15,9 @@ use Drupal\user\EntityOwnerInterface;
class ActivityPubFormAlter implements ActivityPubFormAlterInterface {
use StringTranslationTrait;
use DependencySerializationTrait {
__sleep as traitSleep;
}
/**
* The ActivityPub Actor storage.
......@@ -55,7 +59,7 @@ class ActivityPubFormAlter implements ActivityPubFormAlterInterface {
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $current_user;
protected $currentUser;
/**
* ActivityPubFormAlter constructor
......@@ -78,7 +82,7 @@ class ActivityPubFormAlter implements ActivityPubFormAlterInterface {
$this->activityStorage = $entity_type_manager->getStorage('activitypub_activity');
$this->activityPubKeys = $activityPubKeys;
$this->activityPubUtility = $activityPubUtility;
$this->current_user = $current_user;
$this->currentUser = $current_user;
}
/**
......@@ -231,7 +235,7 @@ class ActivityPubFormAlter implements ActivityPubFormAlterInterface {
*/
public function addActivityPubOutboxFormElement(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
$actor = $this->actorStorage->loadActorByEntityIdAndType($this->current_user->id(), 'person');
$actor = $this->actorStorage->loadActorByEntityIdAndType($this->currentUser->id(), 'person');
if (!$actor) {
return;
}
......@@ -275,18 +279,13 @@ class ActivityPubFormAlter implements ActivityPubFormAlterInterface {
$entity = $form_state->getFormObject()->getEntity();
if (method_exists($entity, 'isPublished') && $entity->isPublished() && ($map = $form_state->getValue('activitypub_mapping'))) {
/** @var \Drupal\activitypub\Entity\ActivityPubObjectMappingInterface $mapping */
$mapping = $this->objectMapStorage->load($map);
$actor = $this->actorStorage->loadActorByEntityIdAndType($this->current_user->id(), 'person');
$values = [
'status' => TRUE,
'collection' => 'outbox',
'type' => $mapping->getActivityPubObject(),
'actor' => $this->activityPubUtility->getActivityPubURL($actor),
'target' => '',
'object' => '',
'uid' => $this->current_user->id(),
'type' => $map,
'uid' => $this->currentUser->id(),
'entity_type_id' => $entity->getEntityTypeId(),
'entity_id' => $entity->id(),
];
$activity = $this->activityStorage->create($values);
$activity->save();
......
......@@ -23,15 +23,50 @@ abstract class ObjectPluginBase extends PluginBase implements ObjectPluginInterf
*/
public function getActivities() {
return [
'Create', 'Like', 'Follow'
'Create', 'Like'
];
}
/**
* Get value for a property.
*
* @param $property
* @param $value
*
* @return array|mixed|null
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function getvalue($property, $value) {
$return = NULL;
switch ($property) {
case 'published':
$return = \Drupal::service('date.formatter')->format($value[0]['value'], 'custom', 'Y-m-d\TH:i:s\Z');
break;
case 'content':
$return = $value[0]['value'];
break;
case 'inReplyTo':
$return = $value[0]['uri'];
break;
case 'attachment':
$file = \Drupal::entityTypeManager()->getStorage('file')->load($value[0]['target_id']);
$return = [
'type' => 'Image',
'url' => file_create_url($file->getFileUri()),
];
break;
}
return $return;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return ['show_numbers' => FALSE];
return [];
}
/**
......
......@@ -2,8 +2,11 @@
namespace Drupal\activitypub\Services\Object;
use Drupal\activitypub\Entity\ActivityPubActivityInterface;
use Drupal\activitypub\Entity\ActivityPubObjectMappingInterface;
use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Core\Entity\EntityInterface;
/**
* Provides an interface describing the activitypub objects.
......@@ -36,4 +39,15 @@ interface ObjectPluginInterface extends ConfigurableInterface, DependentPluginIn
*/
public function getProperties($object);
/**
* Generate the activity.
*
* @param \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity
* @param \Drupal\activitypub\Entity\ActivityPubObjectMappingInterface $objectMapping
* @param \Drupal\Core\Entity\EntityInterface $entity
*
* @return array
*/
public function generate(ActivityPubActivityInterface $activity, ActivityPubObjectMappingInterface $objectMapping, EntityInterface $entity);
}
......@@ -170,9 +170,9 @@ abstract class ActivityPubTestBase extends BrowserTestBase {
'target_bundle' => $bundle,
'target_entity_type_id' => 'node',
'activity' => $activity,
'object' => $object,
'object' => 'activitypub_core_types::' . $object,
'label' => $bundle . ' - ' . $object,
'id' => $bundle . '_' . strtolower($object),
'id' => 'map',
'field_mapping' => [
[
'field_name' => 'published',
......
......@@ -51,7 +51,7 @@ class OutboxTest extends ActivityPubTestBase {
$edit = [
'title[0][value]' => 'Page one',
'body[0][value]' => 'Hello world!',
'activitypub_mapping' => 'page_note',
'activitypub_mapping' => 'map',
];
$this->drupalPostForm(NULL, $edit, 'Save');
$assert_session->addressEquals('node/1');
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment