[COMPONENT][Posting] DB::Flush after Notification and fix minor issues with In targets
This commit is contained in:
parent
9df9c6a19c
commit
ee007befa4
@ -89,11 +89,14 @@ class Notification extends Component
|
|||||||
}
|
}
|
||||||
if (Event::handle('NewNotificationShould', [$activity, $target]) === Event::next) {
|
if (Event::handle('NewNotificationShould', [$activity, $target]) === Event::next) {
|
||||||
// TODO: use https://symfony.com/doc/current/notifier.html
|
// TODO: use https://symfony.com/doc/current/notifier.html
|
||||||
DB::persist(Entity\Notification::create([
|
// XXX: Unideal as in failures the rollback will leave behind a false notification,
|
||||||
|
// but most notifications (all) require flushing the objects first
|
||||||
|
// Should be okay as long as implementors bear this in mind
|
||||||
|
DB::wrapInTransaction(fn() => DB::persist(Entity\Notification::create([
|
||||||
'activity_id' => $activity->getId(),
|
'activity_id' => $activity->getId(),
|
||||||
'target_id' => $target->getId(),
|
'target_id' => $target->getId(),
|
||||||
'reason' => $reason,
|
'reason' => $reason,
|
||||||
]));
|
])));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We have no authority nor responsibility of notifying remote actors of a remote actor's doing
|
// We have no authority nor responsibility of notifying remote actors of a remote actor's doing
|
||||||
|
@ -75,7 +75,6 @@ class Posting extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
$actor = $user->getActor();
|
$actor = $user->getActor();
|
||||||
$actor_id = $user->getId();
|
|
||||||
|
|
||||||
$placeholder_strings = ['How are you feeling?', 'Have something to share?', 'How was your day?'];
|
$placeholder_strings = ['How are you feeling?', 'Have something to share?', 'How was your day?'];
|
||||||
Event::handle('PostingPlaceHolderString', [&$placeholder_strings]);
|
Event::handle('PostingPlaceHolderString', [&$placeholder_strings]);
|
||||||
@ -97,6 +96,8 @@ class Posting extends Component
|
|||||||
|
|
||||||
$form_params = [];
|
$form_params = [];
|
||||||
if (!empty($in_targets)) { // @phpstan-ignore-line
|
if (!empty($in_targets)) { // @phpstan-ignore-line
|
||||||
|
// Add "none" option to the top of choices
|
||||||
|
$in_targets = array_merge([_m('Public') => 'public'], $in_targets);
|
||||||
$form_params[] = ['in', ChoiceType::class, ['label' => _m('In:'), 'multiple' => false, 'expanded' => false, 'choices' => $in_targets]];
|
$form_params[] = ['in', ChoiceType::class, ['label' => _m('In:'), 'multiple' => false, 'expanded' => false, 'choices' => $in_targets]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,13 +146,15 @@ class Posting extends Component
|
|||||||
$extra_args = [];
|
$extra_args = [];
|
||||||
Event::handle('AddExtraArgsToNoteContent', [$request, $actor, $data, &$extra_args, $form_params, $form]);
|
Event::handle('AddExtraArgsToNoteContent', [$request, $actor, $data, &$extra_args, $form_params, $form]);
|
||||||
|
|
||||||
|
$target = !array_key_exists('in', $data) || $data['in'] === 'public' ? $context_actor : null;
|
||||||
|
|
||||||
self::storeLocalNote(
|
self::storeLocalNote(
|
||||||
actor: $user->getActor(),
|
actor: $user->getActor(),
|
||||||
content: $data['content'],
|
content: $data['content'],
|
||||||
content_type: $content_type,
|
content_type: $content_type,
|
||||||
language: $data['language'],
|
locale: $data['language'],
|
||||||
scope: VisibilityScope::from($data['visibility']),
|
scope: VisibilityScope::from($data['visibility']),
|
||||||
target: $data['in'] ?? $context_actor,
|
target: $target ?? null, // @phpstan-ignore-line
|
||||||
reply_to_id: $data['reply_to_id'],
|
reply_to_id: $data['reply_to_id'],
|
||||||
attachments: $data['attachments'],
|
attachments: $data['attachments'],
|
||||||
process_note_content_extra_args: $extra_args,
|
process_note_content_extra_args: $extra_args,
|
||||||
@ -199,9 +202,9 @@ class Posting extends Component
|
|||||||
Actor $actor,
|
Actor $actor,
|
||||||
?string $content,
|
?string $content,
|
||||||
string $content_type,
|
string $content_type,
|
||||||
?string $language = null,
|
?string $locale = null,
|
||||||
?VisibilityScope $scope = null,
|
?VisibilityScope $scope = null,
|
||||||
null|int|Actor $target = null,
|
null|Actor|int $target = null,
|
||||||
?int $reply_to_id = null,
|
?int $reply_to_id = null,
|
||||||
array $attachments = [],
|
array $attachments = [],
|
||||||
array $processed_attachments = [],
|
array $processed_attachments = [],
|
||||||
@ -212,7 +215,7 @@ class Posting extends Component
|
|||||||
$rendered = null;
|
$rendered = null;
|
||||||
$mentions = [];
|
$mentions = [];
|
||||||
if (!empty($content)) {
|
if (!empty($content)) {
|
||||||
Event::handle('RenderNoteContent', [$content, $content_type, &$rendered, $actor, $language, &$mentions]);
|
Event::handle('RenderNoteContent', [$content, $content_type, &$rendered, $actor, $locale, &$mentions]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$note = Note::create([
|
$note = Note::create([
|
||||||
@ -220,7 +223,7 @@ class Posting extends Component
|
|||||||
'content' => $content,
|
'content' => $content,
|
||||||
'content_type' => $content_type,
|
'content_type' => $content_type,
|
||||||
'rendered' => $rendered,
|
'rendered' => $rendered,
|
||||||
'language_id' => !\is_null($language) ? Language::getByLocale($language)->getId() : null,
|
'language_id' => !\is_null($locale) ? Language::getByLocale($locale)->getId() : null,
|
||||||
'is_local' => true,
|
'is_local' => true,
|
||||||
'scope' => $scope,
|
'scope' => $scope,
|
||||||
'reply_to' => $reply_to_id,
|
'reply_to' => $reply_to_id,
|
||||||
@ -265,9 +268,8 @@ class Posting extends Component
|
|||||||
'source' => 'web',
|
'source' => 'web',
|
||||||
]);
|
]);
|
||||||
DB::persist($activity);
|
DB::persist($activity);
|
||||||
|
|
||||||
if (!\is_null($target)) {
|
if (!\is_null($target)) {
|
||||||
$target = is_numeric($target) ? Actor::getById((int) $target) : $target;
|
$target = \is_int($target) ? Actor::getById($target) : $target;
|
||||||
$mentions[] = [
|
$mentions[] = [
|
||||||
'mentioned' => [$target],
|
'mentioned' => [$target],
|
||||||
'type' => match ($target->getType()) {
|
'type' => match ($target->getType()) {
|
||||||
@ -281,12 +283,14 @@ class Posting extends Component
|
|||||||
|
|
||||||
$mention_ids = F\unique(F\flat_map($mentions, fn (array $m) => F\map($m['mentioned'] ?? [], fn (Actor $a) => $a->getId())));
|
$mention_ids = F\unique(F\flat_map($mentions, fn (array $m) => F\map($m['mentioned'] ?? [], fn (Actor $a) => $a->getId())));
|
||||||
|
|
||||||
|
// Flush before notification
|
||||||
DB::flush();
|
DB::flush();
|
||||||
|
|
||||||
if ($notify) {
|
if ($notify) {
|
||||||
Event::handle('NewNotification', [$actor, $activity, ['object' => $mention_ids], _m('{nickname} created a note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]);
|
Event::handle('NewNotification', [$actor, $activity, ['object' => $mention_ids], _m('{nickname} created a note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return $note;
|
return $note;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ namespace Plugin\RepeatNote;
|
|||||||
|
|
||||||
use App\Core\DB\DB;
|
use App\Core\DB\DB;
|
||||||
use App\Core\Event;
|
use App\Core\Event;
|
||||||
|
use function App\Core\I18n\_m;
|
||||||
use App\Core\Modules\NoteHandlerPlugin;
|
use App\Core\Modules\NoteHandlerPlugin;
|
||||||
use App\Core\Router\RouteLoader;
|
use App\Core\Router\RouteLoader;
|
||||||
use App\Core\Router\Router;
|
use App\Core\Router\Router;
|
||||||
@ -38,9 +39,8 @@ use Component\Language\Entity\Language;
|
|||||||
use Component\Posting\Posting;
|
use Component\Posting\Posting;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use Plugin\RepeatNote\Entity\NoteRepeat as RepeatEntity;
|
use Plugin\RepeatNote\Entity\NoteRepeat as RepeatEntity;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use function App\Core\I18n\_m;
|
|
||||||
use const SORT_REGULAR;
|
use const SORT_REGULAR;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
class RepeatNote extends NoteHandlerPlugin
|
class RepeatNote extends NoteHandlerPlugin
|
||||||
{
|
{
|
||||||
@ -64,17 +64,17 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
public static function repeatNote(Note $note, int $actor_id, string $source = 'web'): ?Activity
|
public static function repeatNote(Note $note, int $actor_id, string $source = 'web'): ?Activity
|
||||||
{
|
{
|
||||||
$repeat_entity = DB::findBy('note_repeat', [
|
$repeat_entity = DB::findBy('note_repeat', [
|
||||||
'actor_id' => $actor_id,
|
'actor_id' => $actor_id,
|
||||||
'note_id' => $note->getId(),
|
'note_id' => $note->getId(),
|
||||||
])[ 0 ] ?? null;
|
])[0] ?? null;
|
||||||
|
|
||||||
if (!\is_null($repeat_entity)) {
|
if (!\is_null($repeat_entity)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's a repeat, the reply_to should be to the original, conversation ought to be the same
|
// If it's a repeat, the reply_to should be to the original, conversation ought to be the same
|
||||||
$original_note_id = $note->getId();
|
$original_note_id = $note->getId();
|
||||||
$extra_args[ 'reply_to' ] = $original_note_id;
|
$extra_args['reply_to'] = $original_note_id;
|
||||||
|
|
||||||
$attachments = $note->getAttachmentsWithTitle();
|
$attachments = $note->getAttachmentsWithTitle();
|
||||||
foreach ($attachments as $attachment) {
|
foreach ($attachments as $attachment) {
|
||||||
@ -88,25 +88,25 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
actor: Actor::getById($actor_id),
|
actor: Actor::getById($actor_id),
|
||||||
content: $note->getContent(),
|
content: $note->getContent(),
|
||||||
content_type: $note->getContentType(),
|
content_type: $note->getContentType(),
|
||||||
language: \is_null($lang_id = $note->getLanguageId()) ? null : Language::getById($lang_id)->getLocale(),
|
locale: \is_null($lang_id = $note->getLanguageId()) ? null : Language::getById($lang_id)->getLocale(),
|
||||||
processed_attachments: $note->getAttachmentsWithTitle(),
|
processed_attachments: $note->getAttachmentsWithTitle(),
|
||||||
process_note_content_extra_args: $extra_args,
|
process_note_content_extra_args: $extra_args,
|
||||||
notify: false,
|
notify: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
DB::persist(RepeatEntity::create([
|
DB::persist(RepeatEntity::create([
|
||||||
'note_id' => $repeat->getId(),
|
'note_id' => $repeat->getId(),
|
||||||
'actor_id' => $actor_id,
|
'actor_id' => $actor_id,
|
||||||
'repeat_of' => $original_note_id,
|
'repeat_of' => $original_note_id,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
// Log an activity
|
// Log an activity
|
||||||
$repeat_activity = Activity::create([
|
$repeat_activity = Activity::create([
|
||||||
'actor_id' => $actor_id,
|
'actor_id' => $actor_id,
|
||||||
'verb' => 'repeat',
|
'verb' => 'repeat',
|
||||||
'object_type' => 'note',
|
'object_type' => 'note',
|
||||||
'object_id' => $note->getId(),
|
'object_id' => $note->getId(),
|
||||||
'source' => $source,
|
'source' => $source,
|
||||||
]);
|
]);
|
||||||
DB::persist($repeat_activity);
|
DB::persist($repeat_activity);
|
||||||
|
|
||||||
@ -128,31 +128,31 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
*/
|
*/
|
||||||
public static function unrepeatNote(int $note_id, int $actor_id, string $source = 'web'): ?Activity
|
public static function unrepeatNote(int $note_id, int $actor_id, string $source = 'web'): ?Activity
|
||||||
{
|
{
|
||||||
$already_repeated = DB::findBy(RepeatEntity::class, ['actor_id' => $actor_id, 'repeat_of' => $note_id])[ 0 ] ?? null;
|
$already_repeated = DB::findBy(RepeatEntity::class, ['actor_id' => $actor_id, 'repeat_of' => $note_id])[0] ?? null;
|
||||||
|
|
||||||
if (!\is_null($already_repeated)) { // If it was repeated, then we can undo it
|
if (!\is_null($already_repeated)) { // If it was repeated, then we can undo it
|
||||||
// Find previous repeat activity
|
// Find previous repeat activity
|
||||||
$already_repeated_activity = DB::findBy(Activity::class, [
|
$already_repeated_activity = DB::findBy(Activity::class, [
|
||||||
'actor_id' => $actor_id,
|
'actor_id' => $actor_id,
|
||||||
'verb' => 'repeat',
|
'verb' => 'repeat',
|
||||||
'object_type' => 'note',
|
'object_type' => 'note',
|
||||||
'object_id' => $already_repeated->getRepeatOf(),
|
'object_id' => $already_repeated->getRepeatOf(),
|
||||||
])[ 0 ] ?? null;
|
])[0] ?? null;
|
||||||
|
|
||||||
// Remove the clone note
|
// Remove the clone note
|
||||||
DB::findBy(Note::class, ['id' => $already_repeated->getNoteId()])[ 0 ]->delete(actor: Actor::getById($actor_id));
|
DB::findBy(Note::class, ['id' => $already_repeated->getNoteId()])[0]->delete(actor: Actor::getById($actor_id));
|
||||||
DB::flush();
|
DB::flush();
|
||||||
|
|
||||||
// Remove from the note_repeat table
|
// Remove from the note_repeat table
|
||||||
DB::remove(DB::findBy(RepeatEntity::class, ['note_id' => $already_repeated->getNoteId()])[ 0 ]);
|
DB::remove(DB::findBy(RepeatEntity::class, ['note_id' => $already_repeated->getNoteId()])[0]);
|
||||||
|
|
||||||
// Log an activity
|
// Log an activity
|
||||||
$undo_repeat_activity = Activity::create([
|
$undo_repeat_activity = Activity::create([
|
||||||
'actor_id' => $actor_id,
|
'actor_id' => $actor_id,
|
||||||
'verb' => 'undo',
|
'verb' => 'undo',
|
||||||
'object_type' => 'activity',
|
'object_type' => 'activity',
|
||||||
'object_id' => $already_repeated_activity->getId(),
|
'object_id' => $already_repeated_activity->getId(),
|
||||||
'source' => $source,
|
'source' => $source,
|
||||||
]);
|
]);
|
||||||
DB::persist($undo_repeat_activity);
|
DB::persist($undo_repeat_activity);
|
||||||
|
|
||||||
@ -162,17 +162,17 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
} else {
|
} else {
|
||||||
// Either was undoed already
|
// Either was undoed already
|
||||||
if (!\is_null($already_repeated_activity = DB::findBy('activity', [
|
if (!\is_null($already_repeated_activity = DB::findBy('activity', [
|
||||||
'actor_id' => $actor_id,
|
'actor_id' => $actor_id,
|
||||||
'verb' => 'repeat',
|
'verb' => 'repeat',
|
||||||
'object_type' => 'note',
|
'object_type' => 'note',
|
||||||
'object_id' => $note_id,
|
'object_id' => $note_id,
|
||||||
])[ 0 ] ?? null)) {
|
])[0] ?? null)) {
|
||||||
return DB::findBy('activity', [
|
return DB::findBy('activity', [
|
||||||
'actor_id' => $actor_id,
|
'actor_id' => $actor_id,
|
||||||
'verb' => 'undo',
|
'verb' => 'undo',
|
||||||
'object_type' => 'activity',
|
'object_type' => 'activity',
|
||||||
'object_id' => $already_repeated_activity->getId(),
|
'object_id' => $already_repeated_activity->getId(),
|
||||||
])[ 0 ] ?? null; // null if not undoed
|
])[0] ?? null; // null if not undoed
|
||||||
} else {
|
} else {
|
||||||
// or it's an attempt to undo something that wasn't repeated in the first place,
|
// or it's an attempt to undo something that wasn't repeated in the first place,
|
||||||
return null;
|
return null;
|
||||||
@ -190,7 +190,7 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
// it's pretty cool
|
// it's pretty cool
|
||||||
if (str_starts_with($request->get('_route'), 'actor_view_')) {
|
if (str_starts_with($request->get('_route'), 'actor_view_')) {
|
||||||
$notes = array_map(
|
$notes = array_map(
|
||||||
fn(Note $note) => RepeatEntity::isNoteRepeat($note)
|
fn (Note $note) => RepeatEntity::isNoteRepeat($note)
|
||||||
? Note::getById(RepeatEntity::getByPK($note->getId())->getRepeatOf())
|
? Note::getById(RepeatEntity::getByPK($note->getId())->getRepeatOf())
|
||||||
: $note,
|
: $note,
|
||||||
$notes,
|
$notes,
|
||||||
@ -199,7 +199,7 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter out repeats altogether
|
// Filter out repeats altogether
|
||||||
$notes = array_filter($notes, fn(Note $note) => !RepeatEntity::isNoteRepeat($note));
|
$notes = array_filter($notes, fn (Note $note) => !RepeatEntity::isNoteRepeat($note));
|
||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,13 +218,13 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
|
|
||||||
// If note is repeated, "is_repeated" is 1, 0 otherwise.
|
// If note is repeated, "is_repeated" is 1, 0 otherwise.
|
||||||
$is_repeat = ($note_repeat = DB::findBy('note_repeat', [
|
$is_repeat = ($note_repeat = DB::findBy('note_repeat', [
|
||||||
'actor_id' => $user->getId(),
|
'actor_id' => $user->getId(),
|
||||||
'repeat_of' => $note->getId(),
|
'repeat_of' => $note->getId(),
|
||||||
])) !== [] ? 1 : 0;
|
])) !== [] ? 1 : 0;
|
||||||
|
|
||||||
// Generating URL for repeat action route
|
// Generating URL for repeat action route
|
||||||
$args = ['note_id' => $is_repeat === 0 ? $note->getId() : $note_repeat[ 0 ]->getRepeatOf()];
|
$args = ['note_id' => $is_repeat === 0 ? $note->getId() : $note_repeat[0]->getRepeatOf()];
|
||||||
$type = Router::ABSOLUTE_PATH;
|
$type = Router::ABSOLUTE_PATH;
|
||||||
$repeat_action_url = $is_repeat
|
$repeat_action_url = $is_repeat
|
||||||
? Router::url('repeat_remove', $args, $type)
|
? Router::url('repeat_remove', $args, $type)
|
||||||
: Router::url('repeat_add', $args, $type);
|
: Router::url('repeat_add', $args, $type);
|
||||||
@ -234,8 +234,8 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
|
|
||||||
$extra_classes = $is_repeat ? 'note-actions-set' : 'note-actions-unset';
|
$extra_classes = $is_repeat ? 'note-actions-set' : 'note-actions-unset';
|
||||||
$repeat_action = [
|
$repeat_action = [
|
||||||
'url' => $repeat_action_url,
|
'url' => $repeat_action_url,
|
||||||
'title' => $is_repeat ? 'Remove this repeat' : 'Repeat this note!',
|
'title' => $is_repeat ? 'Remove this repeat' : 'Repeat this note!',
|
||||||
'classes' => "button-container repeat-button-container {$extra_classes}",
|
'classes' => "button-container repeat-button-container {$extra_classes}",
|
||||||
'note_id' => 'repeat-button-container-' . $note->getId(),
|
'note_id' => 'repeat-button-container-' . $note->getId(),
|
||||||
];
|
];
|
||||||
@ -261,12 +261,12 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
$check_user = !\is_null(Common::user());
|
$check_user = !\is_null(Common::user());
|
||||||
|
|
||||||
// The current Note being rendered
|
// The current Note being rendered
|
||||||
$note = $vars[ 'note' ];
|
$note = $vars['note'];
|
||||||
|
|
||||||
// Will have actors array, and action string
|
// Will have actors array, and action string
|
||||||
// Actors are the subjects, action is the verb (in the final phrase)
|
// Actors are the subjects, action is the verb (in the final phrase)
|
||||||
$repeat_actors = [];
|
$repeat_actors = [];
|
||||||
$note_repeats = RepeatEntity::getNoteRepeats($note);
|
$note_repeats = RepeatEntity::getNoteRepeats($note);
|
||||||
|
|
||||||
// Get actors who repeated the note
|
// Get actors who repeated the note
|
||||||
foreach ($note_repeats as $repeat) {
|
foreach ($note_repeats as $repeat) {
|
||||||
@ -278,7 +278,7 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
|
|
||||||
// Filter out multiple replies from the same actor
|
// Filter out multiple replies from the same actor
|
||||||
$repeat_actors = array_unique($repeat_actors, SORT_REGULAR);
|
$repeat_actors = array_unique($repeat_actors, SORT_REGULAR);
|
||||||
$result[] = ['actors' => $repeat_actors, 'action' => 'repeated'];
|
$result[] = ['actors' => $repeat_actors, 'action' => 'repeated'];
|
||||||
|
|
||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
@ -286,11 +286,6 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
/**
|
/**
|
||||||
* Deletes every repeat entity that is related to a deleted Note in its
|
* Deletes every repeat entity that is related to a deleted Note in its
|
||||||
* respective table
|
* respective table
|
||||||
*
|
|
||||||
* @param \App\Entity\Note $note
|
|
||||||
* @param \App\Entity\Actor $actor
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function onNoteDeleteRelated(Note &$note, Actor $actor): bool
|
public function onNoteDeleteRelated(Note &$note, Actor $actor): bool
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user