From 7d8819a3daa373bd4db3fe1f62cf9312797b0fae Mon Sep 17 00:00:00 2001 From: Hugo Sales Date: Tue, 9 Nov 2021 23:37:46 +0000 Subject: [PATCH] [DB][CONTROLLER][Network][ENTITY][Note] Fix Note::getAllNotes --- src/Core/DB/DB.php | 15 +++++++----- src/Entity/Note.php | 56 ++++++++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/Core/DB/DB.php b/src/Core/DB/DB.php index 91cabbc72f..cd000f7200 100644 --- a/src/Core/DB/DB.php +++ b/src/Core/DB/DB.php @@ -43,6 +43,7 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Query; use Doctrine\ORM\Query\ResultSetMappingBuilder; +use Exception; use Functional as F; /** @@ -114,10 +115,12 @@ class DB * from table aliases to class names. Replaces '{select}' in * $query with the appropriate select list */ - public static function sql(string $query// , array $entities - , array $params = [], ) + public static function sql(string $query, array $params = []) { - $rsm = new ResultSetMappingBuilder(self::$em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT); + if ($_ENV['APP_ENV'] === 'dev' && str_starts_with($query, 'select *')) { + throw new Exception('Cannot use `select *`, use `select {select}` (see ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT)'); + } + $rsmb = new ResultSetMappingBuilder(self::$em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT); $matches = []; preg_match_all(self::$table_entity_pattern, $query, $matches); $entities = []; @@ -125,10 +128,10 @@ class DB $entities[$alias] = self::$table_map[$table]; } foreach ($entities as $alias => $entity) { - $rsm->addRootEntityFromClassMetadata($entity, $alias); + $rsmb->addRootEntityFromClassMetadata($entity, $alias); } - $query = preg_replace('/{select}/', $rsm->generateSelectClause(), $query); - $q = self::$em->createNativeQuery($query, $rsm); + $query = preg_replace('/{select}/', $rsmb->generateSelectClause(), $query); + $q = self::$em->createNativeQuery($query, $rsmb); foreach ($params as $k => $v) { $q->setParameter($k, $v); } diff --git a/src/Entity/Note.php b/src/Entity/Note.php index 749eb623cc..f54d2f57c5 100644 --- a/src/Entity/Note.php +++ b/src/Entity/Note.php @@ -255,11 +255,11 @@ class Note extends Entity { return DB::sql( <<<'EOF' - select * from note n - where (n.scope & :notescope) <> 0 + select {select} from note n + where (n.scope & :scope) <> 0 order by n.created DESC EOF, - ['notescope' => $note_scope], + ['scope' => $note_scope], ); } @@ -267,9 +267,11 @@ class Note extends Entity { return Cache::get('note-attachments-' . $this->id, function () { return DB::dql( - 'select att from App\Entity\Attachment att ' - . 'join App\Entity\AttachmentToNote atn with atn.attachment_id = att.id ' - . 'where atn.note_id = :note_id', + <<<'EOF' + select att from attachment att + join attachment_to_note atn with atn.attachment_id = att.id + where atn.note_id = :note_id + EOF, ['note_id' => $this->id], ); }); @@ -279,9 +281,11 @@ class Note extends Entity { return Cache::get('note-links-' . $this->id, function () { return DB::dql( - 'select l from App\Entity\Link l ' - . 'join App\Entity\NoteToLink ntl with ntl.link_id = l.id ' - . 'where ntl.note_id = :note_id', + <<<'EOF' + select l from link l + join note_to_link ntl with ntl.link_id = l.id + where ntl.note_id = :note_id + EOF, ['note_id' => $this->id], ); }); @@ -297,8 +301,10 @@ class Note extends Entity if (!empty($this->reply_to)) { return Cache::get('note-reply-to-' . $this->id, function () { return DB::dql( - 'select g from App\Entity\Note n join ' - . 'App\Entity\Actor g with n.actor_id = g.id where n.reply_to = :reply', + <<<'EOF' + select g from note n join + actor g with n.actor_id = g.id where n.reply_to = :reply + EOF, ['reply' => $this->reply_to], )[0]->getNickname(); }); @@ -318,10 +324,12 @@ class Note extends Entity ($scope->subscriber && 0 != DB::count('subscription', ['subscriber' => $a->getId(), 'subscribed' => $this->actor_id])) || ($scope->addressee && 0 != DB::count('notification', ['activity_id' => $this->id, 'actor_id' => $a->getId()])) || ($scope->group && [] != DB::dql( - 'select m from group_member m ' - . 'join group_inbox i with m.group_id = i.group_id ' - . 'join note n with i.activity_id = n.id ' - . 'where n.id = :note_id and m.actor_id = :actor_id', + <<<'EOF' + select m from group_member m + join group_inbox i with m.group_id = i.group_id + join note n with i.activity_id = n.id + where n.id = :note_id and m.actor_id = :actor_id + EOF, ['note_id' => $this->id, 'actor_id' => $a->getId()], )) )); @@ -350,21 +358,21 @@ class Note extends Entity 'is_local' => ['type' => 'bool', 'description' => 'was this note generated by a local actor'], 'source' => ['type' => 'varchar', 'foreign key' => true, 'length' => 32, 'target' => 'NoteSource.code', 'multiplicity' => 'many to one', 'description' => 'fkey to source of note, like "web", "im", or "clientname"'], 'conversation' => ['type' => 'int', 'foreign key' => true, 'target' => 'Conversation.id', 'multiplicity' => 'one to one', 'description' => 'the local conversation id'], -// 'repeat_of' => ['type' => 'int', 'foreign key' => true, 'target' => 'Note.id', 'multiplicity' => 'one to one', 'description' => 'note this is a repeat of'], - 'scope' => ['type' => 'int', 'not null' => true, 'default' => VisibilityScope::PUBLIC, 'description' => 'bit map for distribution scope; 0 = everywhere; 1 = this server only; 2 = addressees; 4 = groups; 8 = subscribers; 16 = messages; null = default'], - 'url' => ['type' => 'text', 'description' => 'Permalink to Note'], - 'language' => ['type' => 'int', 'foreign key' => true, 'target' => 'Language.id', 'multiplicity' => 'one to many', 'description' => 'The language for this note'], - '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'], + // 'repeat_of' => ['type' => 'int', 'foreign key' => true, 'target' => 'Note.id', 'multiplicity' => 'one to one', 'description' => 'note this is a repeat of'], + 'scope' => ['type' => 'int', 'not null' => true, 'default' => VisibilityScope::PUBLIC, 'description' => 'bit map for distribution scope; 0 = everywhere; 1 = this server only; 2 = addressees; 4 = groups; 8 = subscribers; 16 = messages; null = default'], + 'url' => ['type' => 'text', 'description' => 'Permalink to Note'], + 'language' => ['type' => 'int', 'foreign key' => true, 'target' => 'Language.id', 'multiplicity' => 'one to many', 'description' => 'The language for this note'], + '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' => ['id'], 'indexes' => [ 'note_created_id_is_local_idx' => ['created', 'is_local'], 'note_actor_created_idx' => ['actor_id', 'created'], 'note_is_local_created_actor_idx' => ['is_local', 'created', 'actor_id'], - 'note_repeat_of_created_idx' => ['repeat_of', 'created'], - 'note_conversation_created_idx' => ['conversation', 'created'], - 'note_reply_to_idx' => ['reply_to'], + // 'note_repeat_of_created_idx' => ['repeat_of', 'created'], + 'note_conversation_created_idx' => ['conversation', 'created'], + 'note_reply_to_idx' => ['reply_to'], ], 'fulltext indexes' => ['notice_fulltext_idx' => ['content']], // TODO make this configurable ];