diff --git a/components/FreeNetwork/Entity/FreeNetworkActorProtocol.php b/components/FreeNetwork/Entity/FreeNetworkActorProtocol.php index 96d847367b..a5ac6e30d4 100644 --- a/components/FreeNetwork/Entity/FreeNetworkActorProtocol.php +++ b/components/FreeNetwork/Entity/FreeNetworkActorProtocol.php @@ -125,7 +125,7 @@ class FreeNetworkActorProtocol extends Entity } else { $attributed_protocol->setProtocol($protocol); } - DB::wrapInTransaction(fn () => DB::persist($attributed_protocol)); + DB::persist($attributed_protocol); } public static function canIActor(string $protocol, int|Actor $actor_id): bool diff --git a/plugins/ActivityPub/ActivityPub.php b/plugins/ActivityPub/ActivityPub.php index 6341db6637..08e99576b3 100644 --- a/plugins/ActivityPub/ActivityPub.php +++ b/plugins/ActivityPub/ActivityPub.php @@ -48,6 +48,7 @@ use App\Util\Common; use App\Util\Exception\BugFoundException; use App\Util\Exception\NoSuchActorException; use App\Util\Nickname; +use Codeception\Coverage\Subscriber\Local; use Component\Collection\Util\Controller\OrderedCollection; use Component\FreeNetwork\Entity\FreeNetworkActorProtocol; use Component\FreeNetwork\Util\Discovery; @@ -148,7 +149,7 @@ class ActivityPub extends Plugin // Is remote? !$actor->getIsLocal() // Is in ActivityPub? - && !\is_null($ap_actor = ActivitypubActor::getByPK(['actor_id' => $actor->getId()])) + && !\is_null($ap_actor = DB::findOneBy(ActivitypubActor::class, ['actor_id' => $actor->getId()], return_null: true)) // We can only provide a full URL (anything else wouldn't make sense) && $type === Router::ABSOLUTE_URL ) { @@ -166,8 +167,8 @@ class ActivityPub extends Plugin { // Are both in AP? if ( - !\is_null($ap_actor = ActivitypubActor::getByPK(['actor_id' => $actor->getId()])) - && !\is_null($ap_other = ActivitypubActor::getByPK(['actor_id' => $other->getId()])) + !\is_null($ap_actor = DB::findOneBy(ActivitypubActor::class, ['actor_id' => $actor->getId()], return_null: true)) + && !\is_null($ap_other = DB::findOneBy(ActivitypubActor::class, ['actor_id' => $other->getId()], return_null: true)) ) { // Are they both in the same server? $canAdmin = parse_url($ap_actor->getUri(), PHP_URL_HOST) === parse_url($ap_other->getUri(), PHP_URL_HOST); @@ -258,7 +259,7 @@ class ActivityPub extends Plugin $to_addr = []; foreach ($targets as $actor) { if (FreeNetworkActorProtocol::canIActor('activitypub', $actor->getId())) { - if (\is_null($ap_target = ActivitypubActor::getByPK(['actor_id' => $actor->getId()]))) { + if (\is_null($ap_target = DB::findOneBy(ActivitypubActor::class, ['actor_id' => $actor->getId()], return_null: true))) { continue; } $to_addr[$ap_target->getInboxSharedUri() ?? $ap_target->getInboxUri()][] = $actor; @@ -405,7 +406,7 @@ class ActivityPub extends Plugin return $object->getUrl(); } else { // Try known remote objects - $known_object = ActivitypubObject::getByPK(['object_type' => 'note', 'object_id' => $object->getId()]); + $known_object = DB::findOneBy(ActivitypubObject::class, ['object_type' => 'note', 'object_id' => $object->getId()], return_null: true); if ($known_object instanceof ActivitypubObject) { return $known_object->getObjectUri(); } else { @@ -418,8 +419,8 @@ class ActivityPub extends Plugin break; case Activity::class: // Try known remote activities - $known_activity = ActivitypubActivity::getByPK(['activity_id' => $object->getId()]); - if ($known_activity instanceof ActivitypubActivity) { + $known_activity = DB::findOneBy(ActivitypubActivity::class, ['activity_id' => $object->getId()], return_null: true); + if (!\is_null($known_activity)) { return $known_activity->getActivityUri(); } else { return Router::url('activity_view', ['id' => $object->getId()], Router::ABSOLUTE_URL); @@ -444,14 +445,14 @@ class ActivityPub extends Plugin public static function getObjectByUri(string $resource, bool $try_online = true) { // Try known object - $known_object = ActivitypubObject::getByPK(['object_uri' => $resource]); - if ($known_object instanceof ActivitypubObject) { + $known_object = DB::findOneBy(ActivitypubObject::class, ['object_uri' => $resource], return_null: true); + if (!\is_null($known_object)) { return $known_object->getObject(); } // Try known activity - $known_activity = ActivitypubActivity::getByPK(['activity_uri' => $resource]); - if ($known_activity instanceof ActivitypubActivity) { + $known_activity = DB::findOneBy(ActivitypubActivity::class, ['activity_uri' => $resource], return_null: true); + if (!\is_null($known_activity)) { return $known_activity->getActivity(); } @@ -477,14 +478,14 @@ class ActivityPub extends Plugin // Try remote if (!$try_online) { - return; + return null; } $response = HTTPClient::get($resource, ['headers' => self::HTTP_CLIENT_HEADERS]); // If it was deleted if ($response->getStatusCode() == 410) { //$obj = Type::create('Tombstone', ['id' => $resource]); - return; + return null; } elseif (!HTTPClient::statusCodeIsOkay($response)) { // If it is unavailable throw new Exception('Non Ok Status Code for given Object id.'); } else { @@ -514,7 +515,7 @@ class ActivityPub extends Plugin // actor_view_id $reuri = '/\/actor\/(\d+)\/?/m'; if (preg_match_all($renick, $str, $matches, PREG_SET_ORDER, 0) === 1) { - return LocalUser::getByPK(['nickname' => $matches[0][1]])->getActor(); + return DB::findOneBy(LocalUser::class, ['nickname' => $matches[0][1]])->getActor(); } elseif (preg_match_all($reuri, $str, $matches, PREG_SET_ORDER, 0) === 1) { return Actor::getById((int) $matches[0][1]); } diff --git a/plugins/ActivityPub/Controller/Inbox.php b/plugins/ActivityPub/Controller/Inbox.php index 3be55a35e4..1697e43c97 100644 --- a/plugins/ActivityPub/Controller/Inbox.php +++ b/plugins/ActivityPub/Controller/Inbox.php @@ -96,9 +96,8 @@ class Inbox extends Controller try { $resource_parts = parse_url($type->get('actor')); if ($resource_parts['host'] !== Common::config('site', 'server')) { - $ap_actor = ActivitypubActor::fromUri($type->get('actor')); + $ap_actor = DB::wrapInTransaction(fn() => ActivitypubActor::fromUri($type->get('actor'))); $actor = Actor::getById($ap_actor->getActorId()); - DB::flush(); } else { throw new Exception('Only remote actors can use this endpoint.'); } @@ -173,8 +172,8 @@ class Inbox extends Controller if (!empty($ap_act->_object_mention_ids)) { $already_known_ids = $ap_act->_object_mention_ids; } - Event::handle('NewNotification', [$actor, $ap_act->getActivity(), $already_known_ids, _m('{nickname} mentioned you.', ['{nickname}' => $actor->getNickname()])]); DB::flush(); + Event::handle('NewNotification', [$actor, $ap_act->getActivity(), $already_known_ids, _m('{nickname} mentioned you.', ['{nickname}' => $actor->getNickname()])]); dd($ap_act, $act = $ap_act->getActivity(), $act->getActor(), $act->getObject()); diff --git a/plugins/ActivityPub/Entity/ActivitypubActor.php b/plugins/ActivityPub/Entity/ActivitypubActor.php index f15368a7f3..c0b83131db 100644 --- a/plugins/ActivityPub/Entity/ActivitypubActor.php +++ b/plugins/ActivityPub/Entity/ActivitypubActor.php @@ -261,7 +261,10 @@ class ActivitypubActor extends Entity 'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'], 'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'], ], - 'primary key' => ['actor_id'], + 'primary key' => ['uri'], + 'unique keys' => [ + 'activitypub_actor_id_ukey' => ['actor_id'], + ], 'foreign keys' => [ 'activitypub_actor_actor_id_fkey' => ['actor', ['actor_id' => 'id']], ], diff --git a/plugins/ActivityPub/Entity/ActivitypubRsa.php b/plugins/ActivityPub/Entity/ActivitypubRsa.php index e873f9e995..3cda1297ba 100644 --- a/plugins/ActivityPub/Entity/ActivitypubRsa.php +++ b/plugins/ActivityPub/Entity/ActivitypubRsa.php @@ -147,7 +147,7 @@ class ActivitypubRsa extends Entity */ public static function getByActor(Actor $gsactor, bool $fetch = true): self { - $apRSA = self::getByPK(['actor_id' => ($actor_id = $gsactor->getId())]); + $apRSA = DB::findOneBy(self::class, ['actor_id' => ($actor_id = $gsactor->getId())], return_null: true); if (\is_null($apRSA)) { // Nonexistent key pair for this profile if ($gsactor->getIsLocal()) { @@ -157,7 +157,7 @@ class ActivitypubRsa extends Entity 'private_key' => $private_key, 'public_key' => $public_key, ]); - DB::wrapInTransaction(fn () => DB::persist($apRSA)); + DB::persist($apRSA); } else { // ASSERT: This should never happen, but try to recover! Log::error('Activitypub_rsa: An impossible thing has happened... Please let the devs know.'); diff --git a/plugins/ActivityPub/Util/Explorer.php b/plugins/ActivityPub/Util/Explorer.php index 19689e1809..b4601bab9a 100644 --- a/plugins/ActivityPub/Util/Explorer.php +++ b/plugins/ActivityPub/Util/Explorer.php @@ -32,6 +32,7 @@ declare(strict_types = 1); namespace Plugin\ActivityPub\Util; +use App\Core\DB\DB; use App\Core\HTTPClient; use App\Core\Log; use App\Util\Exception\NoSuchActorException; @@ -152,8 +153,8 @@ class Explorer // Try standard ActivityPub route // Is this a known filthy little mudblood? - $aprofile = self::get_aprofile_by_url($uri); - if ($aprofile instanceof ActivitypubActor) { + $aprofile = DB::findOneBy(ActivitypubActor::class, ['uri' => $uri], return_null: true); + if (!\is_null($aprofile)) { Log::debug('ActivityPub Explorer: Found a known Aprofile for ' . $uri); // We found something! @@ -216,19 +217,6 @@ class Explorer return false; } - /** - * Get a ActivityPub Profile from it's uri - * - * @param string $v URL - * - * @return ActivitypubActor|bool false if fails | Aprofile object if successful - */ - public static function get_aprofile_by_url(string $v): ActivitypubActor|bool - { - $aprofile = ActivitypubActor::getByPK(['uri' => $v]); - return \is_null($aprofile) ? false : ActivitypubActor::getByPK(['uri' => $v]); - } - /** * Allows the Explorer to transverse a collection of persons. * diff --git a/plugins/ActivityPub/Util/Model/Activity.php b/plugins/ActivityPub/Util/Model/Activity.php index 3dcac6eab2..3771b3013e 100644 --- a/plugins/ActivityPub/Util/Model/Activity.php +++ b/plugins/ActivityPub/Util/Model/Activity.php @@ -34,6 +34,7 @@ namespace Plugin\ActivityPub\Util\Model; use ActivityPhp\Type; use ActivityPhp\Type\AbstractObject; +use App\Core\DB\DB; use App\Core\Event; use App\Core\Router\Router; use App\Entity\Activity as GSActivity; @@ -79,7 +80,7 @@ class Activity extends Model // Ditch known activities if ($type_activity->has('id')) { // We can't dereference a transient activity - $ap_act = ActivitypubActivity::getByPK(['activity_uri' => $type_activity->get('id')]); + $ap_act = DB::findOneBy(ActivitypubActivity::class, ['activity_uri' => $type_activity->get('id')], return_null: true); if (!\is_null($ap_act)) { return $ap_act; } diff --git a/plugins/ActivityPub/Util/Model/Actor.php b/plugins/ActivityPub/Util/Model/Actor.php index 42082bc90c..80c20f0adf 100644 --- a/plugins/ActivityPub/Util/Model/Actor.php +++ b/plugins/ActivityPub/Util/Model/Actor.php @@ -104,49 +104,46 @@ class Actor extends Model } // Actor - $actor_map = [ - 'nickname' => $object->get('preferredUsername'), - 'fullname' => !empty($object->get('name')) ? $object->get('name') : null, - 'created' => new DateTime($object->get('published') ?? 'now'), - 'bio' => $object->get('summary'), - 'is_local' => false, // duh! - 'type' => self::$_as2_actor_type_to_gs_actor_type[$object->get('type')], - 'roles' => $roles, - 'modified' => new DateTime(), - ]; - - $actor = $options['objects']['Actor'] ?? new GSActor(); - - foreach ($actor_map as $prop => $val) { - $set = Formatting::snakeCaseToCamelCase("set_{$prop}"); - $actor->{$set}($val); - } - - if (!isset($options['objects']['Actor'])) { - DB::wrapInTransaction(fn () => DB::persist($actor)); + if (isset($options['objects']['Actor'])) { + $actor = $options['objects']['Actor']; + } else { + $actor_map = [ + 'nickname' => $object->get('preferredUsername'), + 'fullname' => !empty($object->get('name')) ? $object->get('name') : null, + 'created' => new DateTime($object->get('published') ?? 'now'), + 'bio' => $object->get('summary'), + 'is_local' => false, // duh! + 'type' => self::$_as2_actor_type_to_gs_actor_type[$object->get('type')], + 'roles' => $roles, + 'modified' => new DateTime(), + ]; + $actor = GSActor::create($actor_map); + DB::persist($actor); } // ActivityPub Actor - $ap_actor = ActivitypubActor::create([ - 'inbox_uri' => $object->get('inbox'), - 'inbox_shared_uri' => ($object->has('endpoints') && isset($object->get('endpoints')['sharedInbox'])) ? $object->get('endpoints')['sharedInbox'] : null, - 'uri' => $object->get('id'), - 'actor_id' => $actor->getId(), - 'url' => $object->get('url') ?? null, - ], $options['objects']['ActivitypubActor'] ?? null); - - if (!isset($options['objects']['ActivitypubActor'])) { - DB::wrapInTransaction(fn () => DB::persist($ap_actor)); + if (isset($options['objects']['ActivitypubActor'])) { + $ap_actor = $options['objects']['ActivitypubActor']; + } else { + $ap_actor = ActivitypubActor::create([ + 'inbox_uri' => $object->get('inbox'), + 'inbox_shared_uri' => ($object->has('endpoints') && isset($object->get('endpoints')['sharedInbox'])) ? $object->get('endpoints')['sharedInbox'] : null, + 'uri' => $object->get('id'), + 'actor_id' => $actor->getId(), + 'url' => $object->get('url') ?? null, + ], $options['objects']['ActivitypubActor'] ?? null); + DB::persist($ap_actor); } // Public Key - $apRSA = ActivitypubRsa::create([ - 'actor_id' => $actor->getID(), - 'public_key' => ($object->has('publicKey') && isset($object->get('publicKey')['publicKeyPem'])) ? $object->get('publicKey')['publicKeyPem'] : null, - ], $options['objects']['ActivitypubRsa'] ?? null); - - if (!isset($options['objects']['ActivitypubRsa'])) { - DB::wrapInTransaction(fn () => DB::persist($apRSA)); + if (isset($options['objects']['ActivitypubRsa'])) { + $apRSA = $options['objects']['ActivitypubRsa']; + } else { + $apRSA = ActivitypubRsa::create([ + 'actor_id' => $actor->getID(), + 'public_key' => ($object->has('publicKey') && isset($object->get('publicKey')['publicKeyPem'])) ? $object->get('publicKey')['publicKeyPem'] : null, + ], $options['objects']['ActivitypubRsa'] ?? null); + DB::persist($apRSA); } // Avatar @@ -170,14 +167,14 @@ class Actor extends Model if (!\is_null($avatar = DB::findOneBy(\Component\Avatar\Entity\Avatar::class, ['actor_id' => $actor->getId()], return_null: true))) { $avatar->delete(); } - DB::wrapInTransaction(function () use ($attachment, $actor, $object) { + DB::persist($attachment); DB::persist(\Component\Avatar\Entity\Avatar::create([ 'actor_id' => $actor->getId(), 'attachment_id' => $attachment->getId(), 'title' => $object->get('icon')->get('name') ?? null, ])); - }); + Event::handle('AvatarUpdate', [$actor->getId()]); } } @@ -216,7 +213,7 @@ class Actor extends Model $uri = $object->getUri(Router::ABSOLUTE_URL); $attr = [ '@context' => 'https://www.w3.org/ns/activitystreams', - 'type' => ($object->getType() === GSActor::GROUP) ? (LocalGroup::getByPK(['actor_id' => $object->getId()])->getType() === 'organisation' ? 'Organization' : 'Group'): self::$_gs_actor_type_to_as2_actor_type[$object->getType()], + 'type' => ($object->getType() === GSActor::GROUP) ? (DB::findOneBy(LocalGroup::class, ['actor_id' => $object->getId()], return_null: true)?->getType() === 'organisation' ? 'Organization' : 'Group'): self::$_gs_actor_type_to_as2_actor_type[$object->getType()], 'id' => $uri, 'inbox' => Router::url('activitypub_actor_inbox', ['gsactor_id' => $object->getId()], Router::ABSOLUTE_URL), 'outbox' => Router::url('activitypub_actor_outbox', ['gsactor_id' => $object->getId()], Router::ABSOLUTE_URL), diff --git a/plugins/ActivityPub/Util/Model/Note.php b/plugins/ActivityPub/Util/Model/Note.php index 6a74fddb2e..299c55fde6 100644 --- a/plugins/ActivityPub/Util/Model/Note.php +++ b/plugins/ActivityPub/Util/Model/Note.php @@ -188,7 +188,7 @@ class Note extends Model continue; } try { - $actor = ActivityPub::getActorByUri($target); + $actor = ActivityPub::getActorByUri($target); $object_mentions_ids[$actor->getId()] = $target; // If $to is a group and note is unlisted, set note's scope as Group if ($actor->isGroup() && $map['scope'] === 'unlisted') { @@ -209,18 +209,14 @@ class Note extends Model continue; } try { - $actor = ActivityPub::getActorByUri($target); + $actor = ActivityPub::getActorByUri($target); $object_mentions_ids[$actor->getId()] = $target; } catch (Exception $e) { Log::debug('ActivityPub->Model->Note->fromJson->getActorByUri', [$e]); } } - $obj = new GSNote(); - foreach ($map as $prop => $val) { - $set = Formatting::snakeCaseToCamelCase("set_{$prop}"); - $obj->{$set}($val); - } + $obj = GSNote::create($map); // Attachments $processed_attachments = []; @@ -235,7 +231,7 @@ class Note extends Model // Create an attachment for this $temp_file = new TemporaryFile(); $temp_file->write($media); - $filesize = $temp_file->getSize(); + $filesize = $temp_file->getSize(); $max_file_size = Common::getUploadLimit(); if ($max_file_size < $filesize) { throw new ClientException(_m('No file may be larger than {quota} bytes and the file you sent was {size} bytes. ' @@ -258,7 +254,7 @@ class Note extends Model case 'Mention': case 'Group': try { - $actor = ActivityPub::getActorByUri($ap_tag->get('href')); + $actor = ActivityPub::getActorByUri($ap_tag->get('href')); $object_mentions_ids[$actor->getId()] = $ap_tag->get('href'); } catch (Exception $e) { Log::debug('ActivityPub->Model->Note->fromJson->getActorByUri', [$e]); @@ -276,8 +272,8 @@ class Note extends Model } break; case 'Hashtag': - $match = ltrim($ap_tag->get('name'), '#'); - $tag = Tag::extract($match); + $match = ltrim($ap_tag->get('name'), '#'); + $tag = Tag::extract($match); $canonical_tag = $ap_tag->get('canonical') ?? Tag::canonicalTag($tag, \is_null($lang_id = $obj->getLanguageId()) ? null : Language::getById($lang_id)->getLocale()); DB::persist(NoteTag::create([ 'tag' => $tag, @@ -418,7 +414,7 @@ class Note extends Model 'type' => 'Document', 'mediaType' => $attachment->getMimetype(), 'url' => $attachment->getUrl(note: $object, type: Router::ABSOLUTE_URL), - 'name' => AttachmentToNote::getByPK(['attachment_id' => $attachment->getId(), 'note_id' => $object->getId()])->getTitle(), + 'name' => DB::findOneBy(AttachmentToNote::class, ['attachment_id' => $attachment->getId(), 'note_id' => $object->getId()], return_null: true)?->getTitle(), 'width' => $attachment->getWidth(), 'height' => $attachment->getHeight(), ]; diff --git a/plugins/Favourite/Controller/Favourite.php b/plugins/Favourite/Controller/Favourite.php index f2294c6b6d..39d4305ff2 100644 --- a/plugins/Favourite/Controller/Favourite.php +++ b/plugins/Favourite/Controller/Favourite.php @@ -24,7 +24,9 @@ declare(strict_types = 1); namespace Plugin\Favourite\Controller; use App\Core\DB\DB; +use App\Core\Event; use App\Core\Form; +use App\Entity\Actor; use function App\Core\I18n\_m; use App\Core\Log; use App\Core\Router\Router; @@ -72,8 +74,9 @@ class Favourite extends FeedController $form_add_to_favourite->handleRequest($request); if ($form_add_to_favourite->isSubmitted()) { - if (!\is_null(\Plugin\Favourite\Favourite::favourNote(note_id: $id, actor_id: $actor_id))) { + if (!\is_null($activity = \Plugin\Favourite\Favourite::favourNote(note_id: $id, actor_id: $actor_id))) { DB::flush(); + Event::handle('NewNotification', [$actor = Actor::getById($actor_id), $activity, [], _m('{nickname} favoured note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]); } else { throw new ClientException(_m('Note already favoured!')); } @@ -131,8 +134,10 @@ class Favourite extends FeedController $form_remove_favourite->handleRequest($request); if ($form_remove_favourite->isSubmitted()) { - if (!\is_null(\Plugin\Favourite\Favourite::unfavourNote(note_id: $id, actor_id: $actor_id))) { + if (!\is_null($activity = \Plugin\Favourite\Favourite::unfavourNote(note_id: $id, actor_id: $actor_id))) { DB::flush(); + Event::handle('NewNotification', [$actor = Actor::getById($actor_id), $activity, [], _m('{nickname} unfavoured note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]); + } else { throw new ClientException(_m('Note already unfavoured!')); } diff --git a/plugins/Favourite/Favourite.php b/plugins/Favourite/Favourite.php index a456850f55..191cfb3c3e 100644 --- a/plugins/Favourite/Favourite.php +++ b/plugins/Favourite/Favourite.php @@ -81,7 +81,6 @@ class Favourite extends NoteHandlerPlugin ]); DB::persist($activity); - Event::handle('NewNotification', [$actor = Actor::getById($actor_id), $activity, [], _m('{nickname} favoured note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]); } return $activity; } @@ -116,8 +115,6 @@ class Favourite extends NoteHandlerPlugin 'source' => $source, ]); DB::persist($activity); - - Event::handle('NewNotification', [$actor = Actor::getById($actor_id), $activity, [], _m('{nickname} unfavoured note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]); } return $activity; } @@ -287,7 +284,8 @@ class Favourite extends NoteHandlerPlugin if ($type_activity->get('type') === 'Like') { // Favourite if ($type_object instanceof \ActivityPhp\Type\AbstractObject) { if ($type_object->get('type') === 'Note' || $type_object->get('type') === 'Page') { - $note_id = \Plugin\ActivityPub\Util\Model\Note::fromJson($type_object)->getId(); + $note = \Plugin\ActivityPub\Util\Model\Note::fromJson($type_object); + $note_id = $note->getId(); } else { return Event::next; } @@ -315,9 +313,15 @@ class Favourite extends NoteHandlerPlugin } if ($type_activity->get('type') === 'Like') { - $activity = self::favourNote($note_id, $actor->getId(), source: 'ActivityPub'); + if (!\is_null($activity = self::favourNote($note_id, $actor->getId(), source: 'ActivityPub'))) { + DB::flush(); + Event::handle('NewNotification', [$actor, $activity, [], _m('{nickname} favoured note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]); + } } else { - $activity = self::unfavourNote($note_id, $actor->getId(), source: 'ActivityPub'); + if (!\is_null($activity = self::unfavourNote($note_id, $actor->getId(), source: 'ActivityPub'))) { + DB::flush(); + Event::handle('NewNotification', [$actor, $activity, [], _m('{nickname} unfavoured note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]); + } } if (!\is_null($activity)) { // Store ActivityPub Activity diff --git a/plugins/RepeatNote/Controller/Repeat.php b/plugins/RepeatNote/Controller/Repeat.php index 5f30191c9d..c21d103b86 100644 --- a/plugins/RepeatNote/Controller/Repeat.php +++ b/plugins/RepeatNote/Controller/Repeat.php @@ -25,7 +25,9 @@ namespace Plugin\RepeatNote\Controller; use App\Core\Controller; use App\Core\DB\DB; +use App\Core\Event; use App\Core\Form; +use App\Entity\Actor; use function App\Core\I18n\_m; use App\Core\Log; use App\Core\Router\Router; @@ -71,8 +73,10 @@ class Repeat extends Controller $form_add_to_repeat->handleRequest($request); if ($form_add_to_repeat->isSubmitted()) { - \Plugin\RepeatNote\RepeatNote::repeatNote(note: $note, actor_id: $actor_id); + $repeat_activity = \Plugin\RepeatNote\RepeatNote::repeatNote(note: $note, actor_id: $actor_id); DB::flush(); + Event::handle('NewNotification', [$actor = Actor::getById($actor_id), $repeat_activity, [], _m('{nickname} repeated note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $repeat_activity->getObjectId()])]); + // Redirect user to where they came from // Prevent open redirect @@ -127,8 +131,9 @@ class Repeat extends Controller $form_remove_repeat->handleRequest($request); if ($form_remove_repeat->isSubmitted()) { - if (!\is_null(\Plugin\RepeatNote\RepeatNote::unrepeatNote(note_id: $note_id, actor_id: $actor_id))) { + if (!\is_null($undo_repeat_activity = \Plugin\RepeatNote\RepeatNote::unrepeatNote(note_id: $note_id, actor_id: $actor_id))) { DB::flush(); + Event::handle('NewNotification', [$actor = Actor::getById($actor_id), $undo_repeat_activity, [], _m('{nickname} unrepeated note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $note_id])]); } else { throw new ClientException(_m('Note wasn\'t repeated!')); } diff --git a/plugins/RepeatNote/RepeatNote.php b/plugins/RepeatNote/RepeatNote.php index 01aa25785b..c36650b6e3 100644 --- a/plugins/RepeatNote/RepeatNote.php +++ b/plugins/RepeatNote/RepeatNote.php @@ -110,11 +110,6 @@ class RepeatNote extends NoteHandlerPlugin ]); DB::persist($repeat_activity); - // Flush before notification - DB::flush(); - - Event::handle('NewNotification', [$actor = Actor::getById($actor_id), $repeat_activity, [], _m('{nickname} repeated note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $repeat_activity->getObjectId()])]); - return $repeat_activity; } @@ -165,8 +160,6 @@ class RepeatNote extends NoteHandlerPlugin ]); DB::persist($undo_repeat_activity); - Event::handle('NewNotification', [$actor = Actor::getById($actor_id), $undo_repeat_activity, [], _m('{nickname} unrepeated note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $note_id])]); - return $undo_repeat_activity; } else { // Either was undoed already @@ -397,9 +390,15 @@ class RepeatNote extends NoteHandlerPlugin } if ($type_activity->get('type') === 'Announce') { - $activity = self::repeatNote($note ?? Note::getById($note_id), $actor->getId(), source: 'ActivityPub'); + if (!\is_null($activity = self::repeatNote($note ?? Note::getById($note_id), $actor->getId(), source: 'ActivityPub'))) { + DB::flush(); + Event::handle('NewNotification', [$actor, $activity, [], _m('{nickname} repeated note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $activity->getObjectId()])]); + } } else { - $activity = self::unrepeatNote($note_id, $actor->getId(), source: 'ActivityPub'); + if (!\is_null($activity = self::unrepeatNote($note_id, $actor->getId(), source: 'ActivityPub'))) { + DB::flush(); + Event::handle('NewNotification', [$actor, $activity, [], _m('{nickname} unrepeated note {note_id}.', ['{nickname}' => $actor->getNickname(), '{note_id}' => $note_id])]); + } } if (!\is_null($activity)) { // Store ActivityPub Activity diff --git a/src/Core/DB/DB.php b/src/Core/DB/DB.php index d9c9051d3c..ab3d710501 100644 --- a/src/Core/DB/DB.php +++ b/src/Core/DB/DB.php @@ -52,14 +52,22 @@ use Functional as F; * @mixin EntityManager * @template T of Entity * - * @method static ?T find(string $class, array $values) // Finds an Entity by its identifier. - * @method static ?T getReference(string $class, array $values) // Special cases: It's like find but does not load the object if it has not been loaded yet, it only returns a proxy to the object. (https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/unitofwork.html) - * @method static void remove(object $entity) // Removes an entity instance. - * @method static T merge(object $entity) // Merges the state of a detached entity into the persistence context - * @method static void persist(object $entity) // Tells the EntityManager to make an instance managed and persistent. - * @method static bool contains(object $entity) // Determines whether an entity instance is managed in this EntityManager. - * @method static void flush() // Flushes the in-memory state of persisted objects to the database. - * @method mixed wrapInTransaction(callable $func) // Executes a function in a transaction. Warning: suppresses exceptions + * // Finds an Entity by its identifier. You probably want to use DB::findBy instead + * @method static ?T find(string $class, array $values) + * // Special cases: It's like find but does not load the object if it has not been loaded yet, it only returns a proxy to the object. (https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/unitofwork.html) + * @method static ?T getReference(string $class, array $values) + * // Removes an entity instance. + * @method static void remove(object $entity) + * // Merges the state of a detached entity into the persistence context + * @method static T merge(object $entity) + * // Tells the EntityManager to make an instance managed and persistent. + * @method static void persist(object $entity) + * // Determines whether an entity instance is managed in this EntityManager. + * @method static bool contains(object $entity) + * // Flushes the in-memory state of persisted objects to the database. + * @method static void flush() + * // Executes a function in a transaction. Warning: suppresses exceptions. Returns the result of the callable. + * @method mixed wrapInTransaction(callable $func) */ class DB {