[COMPONENT][Notification] Make logic more generic and robust

Fixed various bugs

Some important concepts to bear in mind:

* Notification: Associated with activities, won't be reconstructed
together with objects, can be thought of as transient

* Attention: Associated with objects, will be reconstructed with them, can
be thought as persistent

* Notifications and Attentions have no direct implications.

* Mentions are a specific form of attentions in notes, leads to the creation of Attentions.

Finally,

Potential PHP issue detected and reported: https://github.com/php/php-src/issues/8199
`static::method()` from a non static context (such as a class method) calls `__call`, rather than
the expected `__callStatic`. Can be fixed by using `(static fn() => static::method())()`, but the
usage of the magic method is strictly unnecessary in this case.
This commit is contained in:
2022-03-13 18:23:19 +00:00
parent e1cceac150
commit 888c3798b7
32 changed files with 438 additions and 494 deletions

View File

@@ -43,6 +43,7 @@ use App\Util\Exception\ClientException;
use App\Util\Exception\DuplicateFoundException;
use App\Util\Exception\ServerException;
use Component\Language\Entity\Language;
use Component\Notification\Entity\Attention;
use Component\Posting\Posting;
use DateTime;
use Plugin\RepeatNote\Entity\NoteRepeat as RepeatEntity;
@@ -81,7 +82,7 @@ class RepeatNote extends NoteHandlerPlugin
// Create a new note with the same content as the original
[, $repeat, ] = Posting::storeLocalNote(
actor: Actor::getById($actor_id),
actor: $actor = Actor::getById($actor_id),
content: $note->getContent(),
content_type: $note->getContentType(),
locale: \is_null($lang_id = $note->getLanguageId()) ? null : Language::getById($lang_id)->getLocale(),
@@ -116,6 +117,13 @@ class RepeatNote extends NoteHandlerPlugin
'source' => $source,
]);
DB::persist($repeat_activity);
DB::persist(Attention::create(['object_type' => Activity::schemaName(), 'object_id' => $repeat_activity->getId(), 'target_id' => $note->getActorId()]));
foreach ($actor->getSubscribers() as $subscriber) {
$target_id = $subscriber->getId();
DB::persist(Attention::create(['object_type' => Activity::schemaName(), 'object_id' => $repeat_activity->getId(), 'target_id' => $target_id]));
$effective_attentions[$target_id] = $subscriber;
}
return $repeat_activity;
}
@@ -166,17 +174,24 @@ class RepeatNote extends NoteHandlerPlugin
'source' => $source,
]);
DB::persist($undo_repeat_activity);
DB::persist(Attention::create(['object_type' => Activity::schemaName(), 'object_id' => $undo_repeat_activity->getId(), 'target_id' => Note::getById($note_id)->getActorId()]));
foreach (Actor::getById($actor_id)->getSubscribers() as $subscriber) {
$target_id = $subscriber->getId();
DB::persist(Attention::create(['object_type' => Activity::schemaName(), 'object_id' => $undo_repeat_activity->getId(), 'target_id' => $target_id]));
$effective_attentions[$target_id] = $subscriber;
}
return $undo_repeat_activity;
} else {
// Either was undoed already
if (!\is_null($already_repeated_activity = DB::findOneBy('activity', [
if (!\is_null($already_repeated_activity = DB::findOneBy(Activity::class, [
'actor_id' => $actor_id,
'verb' => 'repeat',
'object_type' => 'note',
'object_id' => $note_id,
], return_null: true))) {
return DB::findOneBy('activity', [
return DB::findOneBy(Activity::class, [
'actor_id' => $actor_id,
'verb' => 'undo',
'object_type' => 'activity',
@@ -376,7 +391,7 @@ class RepeatNote extends NoteHandlerPlugin
} else {
return Event::next;
}
$activity = self::repeatNote($note ?? Note::getById($note_id), $actor->getId(), source: 'ActivityPub');
$activity = self::repeatNote($note, $actor->getId(), source: 'ActivityPub');
} elseif ($type_activity->get('type') === 'Undo') { // Undo Repeat
if ($type_object instanceof \ActivityPhp\Type\AbstractObject) {
$ap_prev_repeat_act = \Plugin\ActivityPub\Util\Model\Activity::fromJson($type_object);
@@ -413,17 +428,17 @@ class RepeatNote extends NoteHandlerPlugin
return Event::stop;
}
public function onActivityPubNewNotification(Actor $sender, Activity $activity, array $ids_already_known = [], ?string $reason = null): bool
public function onActivityPubNewNotification(Actor $sender, Activity $activity, array $targets, ?string $reason = null): bool
{
switch ($activity->getVerb()) {
case 'repeat':
Event::handle('NewNotification', [$sender, $activity, [], _m('{nickname} repeated note {note_id}.', ['{nickname}' => $sender->getNickname(), '{note_id}' => $activity->getObjectId()])]);
Event::handle('NewNotification', [$sender, $activity, $targets, _m('{actor_id} repeated note {note_id}.', ['{actor_id}' => $sender->getId(), '{note_id}' => $activity->getObjectId()])]);
return Event::stop;
case 'undo':
if ($activity->getObjectType() === 'activity') {
$undone_repeat = $activity->getObject();
if ($undone_repeat->getVerb() === 'repeat') {
Event::handle('NewNotification', [$sender, $activity, [], _m('{nickname} unrepeated note {note_id}.', ['{nickname}' => $sender->getNickname(), '{note_id}' => $undone_repeat->getObjectId()])]);
Event::handle('NewNotification', [$sender, $activity, $targets, _m('{actor_id} unrepeated note {note_id}.', ['{actor_id}' => $sender->getId(), '{note_id}' => $undone_repeat->getObjectId()])]);
return Event::stop;
}
}