forked from GNUsocial/gnu-social
		
	[COMPONENT][Posting] DB::Flush after Notification and fix minor issues with In targets
This commit is contained in:
		| @@ -89,11 +89,14 @@ class Notification extends Component | ||||
|                 } | ||||
|                 if (Event::handle('NewNotificationShould', [$activity, $target]) === Event::next) { | ||||
|                     // 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(), | ||||
|                         'target_id'   => $target->getId(), | ||||
|                         'reason'      => $reason, | ||||
|                     ])); | ||||
|                     ]))); | ||||
|                 } | ||||
|             } else { | ||||
|                 // 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_id = $user->getId(); | ||||
|  | ||||
|         $placeholder_strings = ['How are you feeling?', 'Have something to share?', 'How was your day?']; | ||||
|         Event::handle('PostingPlaceHolderString', [&$placeholder_strings]); | ||||
| @@ -97,6 +96,8 @@ class Posting extends Component | ||||
|  | ||||
|         $form_params = []; | ||||
|         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]]; | ||||
|         } | ||||
|  | ||||
| @@ -145,13 +146,15 @@ class Posting extends Component | ||||
|                     $extra_args   = []; | ||||
|                     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( | ||||
|                         actor: $user->getActor(), | ||||
|                         content: $data['content'], | ||||
|                         content_type: $content_type, | ||||
|                         language: $data['language'], | ||||
|                         locale: $data['language'], | ||||
|                         scope: VisibilityScope::from($data['visibility']), | ||||
|                         target: $data['in'] ?? $context_actor, | ||||
|                         target: $target ?? null, // @phpstan-ignore-line | ||||
|                         reply_to_id: $data['reply_to_id'], | ||||
|                         attachments: $data['attachments'], | ||||
|                         process_note_content_extra_args: $extra_args, | ||||
| @@ -199,9 +202,9 @@ class Posting extends Component | ||||
|         Actor $actor, | ||||
|         ?string $content, | ||||
|         string $content_type, | ||||
|         ?string $language = null, | ||||
|         ?string $locale = null, | ||||
|         ?VisibilityScope $scope = null, | ||||
|         null|int|Actor $target = null, | ||||
|         null|Actor|int $target = null, | ||||
|         ?int $reply_to_id = null, | ||||
|         array $attachments = [], | ||||
|         array $processed_attachments = [], | ||||
| @@ -212,7 +215,7 @@ class Posting extends Component | ||||
|         $rendered = null; | ||||
|         $mentions = []; | ||||
|         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([ | ||||
| @@ -220,7 +223,7 @@ class Posting extends Component | ||||
|             'content'      => $content, | ||||
|             'content_type' => $content_type, | ||||
|             '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, | ||||
|             'scope'        => $scope, | ||||
|             'reply_to'     => $reply_to_id, | ||||
| @@ -265,9 +268,8 @@ class Posting extends Component | ||||
|             'source'      => 'web', | ||||
|         ]); | ||||
|         DB::persist($activity); | ||||
|  | ||||
|         if (!\is_null($target)) { | ||||
|             $target     = is_numeric($target) ? Actor::getById((int) $target) : $target; | ||||
|             $target     = \is_int($target) ? Actor::getById($target) : $target; | ||||
|             $mentions[] = [ | ||||
|                 'mentioned'       => [$target], | ||||
|                 '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()))); | ||||
|  | ||||
|         // Flush before notification | ||||
|         DB::flush(); | ||||
|  | ||||
|         if ($notify) { | ||||
|             Event::handle('NewNotification', [$actor, $activity, ['object' => $mention_ids], _m('{nickname} created a note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return $note; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -23,6 +23,7 @@ namespace Plugin\RepeatNote; | ||||
|  | ||||
| use App\Core\DB\DB; | ||||
| use App\Core\Event; | ||||
| use function App\Core\I18n\_m; | ||||
| use App\Core\Modules\NoteHandlerPlugin; | ||||
| use App\Core\Router\RouteLoader; | ||||
| use App\Core\Router\Router; | ||||
| @@ -38,9 +39,8 @@ use Component\Language\Entity\Language; | ||||
| use Component\Posting\Posting; | ||||
| use DateTime; | ||||
| use Plugin\RepeatNote\Entity\NoteRepeat as RepeatEntity; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use function App\Core\I18n\_m; | ||||
| use const SORT_REGULAR; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| 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 | ||||
|     { | ||||
|         $repeat_entity = DB::findBy('note_repeat', [ | ||||
|                 'actor_id' => $actor_id, | ||||
|                 'note_id' => $note->getId(), | ||||
|             ])[ 0 ] ?? null; | ||||
|             'actor_id' => $actor_id, | ||||
|             'note_id'  => $note->getId(), | ||||
|         ])[0] ?? null; | ||||
|  | ||||
|         if (!\is_null($repeat_entity)) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         // If it's a repeat, the reply_to should be to the original, conversation ought to be the same | ||||
|         $original_note_id = $note->getId(); | ||||
|         $extra_args[ 'reply_to' ] = $original_note_id; | ||||
|         $original_note_id       = $note->getId(); | ||||
|         $extra_args['reply_to'] = $original_note_id; | ||||
|  | ||||
|         $attachments = $note->getAttachmentsWithTitle(); | ||||
|         foreach ($attachments as $attachment) { | ||||
| @@ -88,25 +88,25 @@ class RepeatNote extends NoteHandlerPlugin | ||||
|             actor: Actor::getById($actor_id), | ||||
|             content: $note->getContent(), | ||||
|             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(), | ||||
|             process_note_content_extra_args: $extra_args, | ||||
|             notify: false, | ||||
|         ); | ||||
|  | ||||
|         DB::persist(RepeatEntity::create([ | ||||
|             'note_id' => $repeat->getId(), | ||||
|             'actor_id' => $actor_id, | ||||
|             'note_id'   => $repeat->getId(), | ||||
|             'actor_id'  => $actor_id, | ||||
|             'repeat_of' => $original_note_id, | ||||
|         ])); | ||||
|  | ||||
|         // Log an activity | ||||
|         $repeat_activity = Activity::create([ | ||||
|             'actor_id' => $actor_id, | ||||
|             'verb' => 'repeat', | ||||
|             'actor_id'    => $actor_id, | ||||
|             'verb'        => 'repeat', | ||||
|             'object_type' => 'note', | ||||
|             'object_id' => $note->getId(), | ||||
|             'source' => $source, | ||||
|             'object_id'   => $note->getId(), | ||||
|             'source'      => $source, | ||||
|         ]); | ||||
|         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 | ||||
|     { | ||||
|         $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 | ||||
|             // Find previous repeat activity | ||||
|             $already_repeated_activity = DB::findBy(Activity::class, [ | ||||
|                     'actor_id' => $actor_id, | ||||
|                     'verb' => 'repeat', | ||||
|                     'object_type' => 'note', | ||||
|                     'object_id' => $already_repeated->getRepeatOf(), | ||||
|                 ])[ 0 ] ?? null; | ||||
|                 'actor_id'    => $actor_id, | ||||
|                 'verb'        => 'repeat', | ||||
|                 'object_type' => 'note', | ||||
|                 'object_id'   => $already_repeated->getRepeatOf(), | ||||
|             ])[0] ?? null; | ||||
|  | ||||
|             // 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(); | ||||
|  | ||||
|             // 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 | ||||
|             $undo_repeat_activity = Activity::create([ | ||||
|                 'actor_id' => $actor_id, | ||||
|                 'verb' => 'undo', | ||||
|                 'actor_id'    => $actor_id, | ||||
|                 'verb'        => 'undo', | ||||
|                 'object_type' => 'activity', | ||||
|                 'object_id' => $already_repeated_activity->getId(), | ||||
|                 'source' => $source, | ||||
|                 'object_id'   => $already_repeated_activity->getId(), | ||||
|                 'source'      => $source, | ||||
|             ]); | ||||
|             DB::persist($undo_repeat_activity); | ||||
|  | ||||
| @@ -162,17 +162,17 @@ class RepeatNote extends NoteHandlerPlugin | ||||
|         } else { | ||||
|             // Either was undoed already | ||||
|             if (!\is_null($already_repeated_activity = DB::findBy('activity', [ | ||||
|                     'actor_id' => $actor_id, | ||||
|                     'verb' => 'repeat', | ||||
|                     'object_type' => 'note', | ||||
|                     'object_id' => $note_id, | ||||
|                 ])[ 0 ] ?? null)) { | ||||
|                 'actor_id' => $actor_id, | ||||
|                 'verb' => 'repeat', | ||||
|                 'object_type' => 'note', | ||||
|                 'object_id' => $note_id, | ||||
|             ])[0] ?? null)) { | ||||
|                 return DB::findBy('activity', [ | ||||
|                         'actor_id' => $actor_id, | ||||
|                         'verb' => 'undo', | ||||
|                         'object_type' => 'activity', | ||||
|                         'object_id' => $already_repeated_activity->getId(), | ||||
|                     ])[ 0 ] ?? null; // null if not undoed | ||||
|                     'actor_id'    => $actor_id, | ||||
|                     'verb'        => 'undo', | ||||
|                     'object_type' => 'activity', | ||||
|                     'object_id'   => $already_repeated_activity->getId(), | ||||
|                 ])[0] ?? null; // null if not undoed | ||||
|             } else { | ||||
|                 // or it's an attempt to undo something that wasn't repeated in the first place, | ||||
|                 return null; | ||||
| @@ -190,7 +190,7 @@ class RepeatNote extends NoteHandlerPlugin | ||||
|         // it's pretty cool | ||||
|         if (str_starts_with($request->get('_route'), 'actor_view_')) { | ||||
|             $notes = array_map( | ||||
|                 fn(Note $note) => RepeatEntity::isNoteRepeat($note) | ||||
|                 fn (Note $note) => RepeatEntity::isNoteRepeat($note) | ||||
|                     ? Note::getById(RepeatEntity::getByPK($note->getId())->getRepeatOf()) | ||||
|                     : $note, | ||||
|                 $notes, | ||||
| @@ -199,7 +199,7 @@ class RepeatNote extends NoteHandlerPlugin | ||||
|         } | ||||
|  | ||||
|         // 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; | ||||
|     } | ||||
|  | ||||
| @@ -218,13 +218,13 @@ class RepeatNote extends NoteHandlerPlugin | ||||
|  | ||||
|         // If note is repeated, "is_repeated" is 1, 0 otherwise. | ||||
|         $is_repeat = ($note_repeat = DB::findBy('note_repeat', [ | ||||
|             'actor_id' => $user->getId(), | ||||
|             'actor_id'  => $user->getId(), | ||||
|             'repeat_of' => $note->getId(), | ||||
|         ])) !== [] ? 1 : 0; | ||||
|  | ||||
|         // Generating URL for repeat action route | ||||
|         $args = ['note_id' => $is_repeat === 0 ? $note->getId() : $note_repeat[ 0 ]->getRepeatOf()]; | ||||
|         $type = Router::ABSOLUTE_PATH; | ||||
|         $args              = ['note_id' => $is_repeat === 0 ? $note->getId() : $note_repeat[0]->getRepeatOf()]; | ||||
|         $type              = Router::ABSOLUTE_PATH; | ||||
|         $repeat_action_url = $is_repeat | ||||
|             ? Router::url('repeat_remove', $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'; | ||||
|         $repeat_action = [ | ||||
|             'url' => $repeat_action_url, | ||||
|             'title' => $is_repeat ? 'Remove this repeat' : 'Repeat this note!', | ||||
|             'url'     => $repeat_action_url, | ||||
|             'title'   => $is_repeat ? 'Remove this repeat' : 'Repeat this note!', | ||||
|             'classes' => "button-container repeat-button-container {$extra_classes}", | ||||
|             'note_id' => 'repeat-button-container-' . $note->getId(), | ||||
|         ]; | ||||
| @@ -261,12 +261,12 @@ class RepeatNote extends NoteHandlerPlugin | ||||
|         $check_user = !\is_null(Common::user()); | ||||
|  | ||||
|         // The current Note being rendered | ||||
|         $note = $vars[ 'note' ]; | ||||
|         $note = $vars['note']; | ||||
|  | ||||
|         // Will have actors array, and action string | ||||
|         // Actors are the subjects, action is the verb (in the final phrase) | ||||
|         $repeat_actors = []; | ||||
|         $note_repeats = RepeatEntity::getNoteRepeats($note); | ||||
|         $note_repeats  = RepeatEntity::getNoteRepeats($note); | ||||
|  | ||||
|         // Get actors who repeated the note | ||||
|         foreach ($note_repeats as $repeat) { | ||||
| @@ -278,7 +278,7 @@ class RepeatNote extends NoteHandlerPlugin | ||||
|  | ||||
|         // Filter out multiple replies from the same actor | ||||
|         $repeat_actors = array_unique($repeat_actors, SORT_REGULAR); | ||||
|         $result[] = ['actors' => $repeat_actors, 'action' => 'repeated']; | ||||
|         $result[]      = ['actors' => $repeat_actors, 'action' => 'repeated']; | ||||
|  | ||||
|         return Event::next; | ||||
|     } | ||||
| @@ -286,11 +286,6 @@ class RepeatNote extends NoteHandlerPlugin | ||||
|     /** | ||||
|      * Deletes every repeat entity that is related to a deleted Note in its | ||||
|      * respective table | ||||
|      * | ||||
|      * @param \App\Entity\Note  $note | ||||
|      * @param \App\Entity\Actor $actor | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function onNoteDeleteRelated(Note &$note, Actor $actor): bool | ||||
|     { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user