From 2b9f70f89f7aa4fdff7e107792b084513997607a Mon Sep 17 00:00:00 2001 From: Eliseu Amaro Date: Sat, 5 Feb 2022 16:15:34 +0000 Subject: [PATCH] [PLUGINS][BlogCollections] Entities and base plugin and controller done --- .../AttachmentCollections.php | 21 ++-- .../Controller/AttachmentCollections.php | 2 +- .../Entity/AttachmentCollectionEntry.php | 18 +-- plugins/BlogCollections/BlogCollections.php | 109 ++++++++++++++++++ .../Controller/BlogCollections.php | 83 +++++++++++++ .../BlogCollections/Entity/BlogCollection.php | 97 ++++++++++++++++ .../Entity/BlogCollectionEntry.php | 98 ++++++++++++++++ 7 files changed, 408 insertions(+), 20 deletions(-) create mode 100644 plugins/BlogCollections/BlogCollections.php create mode 100644 plugins/BlogCollections/Controller/BlogCollections.php create mode 100644 plugins/BlogCollections/Entity/BlogCollection.php create mode 100644 plugins/BlogCollections/Entity/BlogCollectionEntry.php diff --git a/plugins/AttachmentCollections/AttachmentCollections.php b/plugins/AttachmentCollections/AttachmentCollections.php index 484ed90177..6bdc5862f7 100644 --- a/plugins/AttachmentCollections/AttachmentCollections.php +++ b/plugins/AttachmentCollections/AttachmentCollections.php @@ -60,9 +60,9 @@ class AttachmentCollections extends Plugin ]); DB::persist($col); DB::persist(AttachmentCollectionEntry::create([ - 'attachment_id' => $vars['vars']['attachment_id'], - 'note_id' => $vars['vars']['note_id'], - 'collection_id' => $col->getId(), + 'attachment_id' => $vars['vars']['attachment_id'], + 'note_id' => $vars['vars']['note_id'], + 'attachment_collection_id' => $col->getId(), ])); } protected function removeItem(Actor $owner, array $vars, array $items, array $collections) @@ -70,7 +70,7 @@ class AttachmentCollections extends Plugin return DB::dql(<<<'EOF' DELETE FROM \Plugin\AttachmentCollections\Entity\AttachmentCollectionEntry AS entry WHERE entry.attachment_id = :attach_id AND entry.note_id = :note_id - AND entry.collection_id IN ( + AND entry.attachment_collection_id IN ( SELECT album.id FROM \Plugin\AttachmentCollections\Entity\AttachmentCollection AS album WHERE album.actor_id = :user_id AND album.id IN (:ids) @@ -89,9 +89,9 @@ class AttachmentCollections extends Plugin // prevent user from putting something in a collection (s)he doesn't own: if (\in_array($id, $collections)) { DB::persist(AttachmentCollectionEntry::create([ - 'attachment_id' => $vars['vars']['attachment_id'], - 'note_id' => $vars['vars']['note_id'], - 'collection_id' => $id, + 'attachment_id' => $vars['vars']['attachment_id'], + 'note_id' => $vars['vars']['note_id'], + 'attachment_collection_id' => $id, ])); } } @@ -101,6 +101,7 @@ class AttachmentCollections extends Plugin { return $vars['path'] === 'note_attachment_show'; } + protected function getCollectionsBy(Actor $owner, ?array $vars = null, bool $ids_only = false): array { if (\is_null($vars)) { @@ -108,9 +109,9 @@ class AttachmentCollections extends Plugin } else { $res = DB::dql( <<<'EOF' - SELECT entry.collection_id FROM \Plugin\AttachmentCollections\Entity\AttachmentCollectionEntry AS entry + SELECT entry.attachment_collection_id FROM \Plugin\AttachmentCollections\Entity\AttachmentCollectionEntry AS entry INNER JOIN \Plugin\AttachmentCollections\Entity\AttachmentCollection AS attachment_collection - WITH attachment_collection.id = entry.collection_id + WITH attachment_collection.id = entry.attachment_collection_id WHERE entry.attachment_id = :attach_id AND entry.note_id = :note_id AND attachment_collection.actor_id = :id EOF, [ @@ -123,7 +124,7 @@ class AttachmentCollections extends Plugin if (!$ids_only) { return $res; } - return array_map(fn ($x) => $x['collection_id'], $res); + return array_map(fn ($x) => $x['attachment_collection_id'], $res); } public function onAddRoute(RouteLoader $r): bool diff --git a/plugins/AttachmentCollections/Controller/AttachmentCollections.php b/plugins/AttachmentCollections/Controller/AttachmentCollections.php index 1fb33a64c5..91aa4ac258 100644 --- a/plugins/AttachmentCollections/Controller/AttachmentCollections.php +++ b/plugins/AttachmentCollections/Controller/AttachmentCollections.php @@ -59,7 +59,7 @@ class AttachmentCollections extends MetaCollectionController WITH entry.attachment_id = attach.id LEFT JOIN \App\Entity\Note AS notice WITH entry.note_id = notice.id - WHERE entry.collection_id = :cid + WHERE entry.attachment_collection_id = :cid EOF, ['cid' => $collection_id], ); diff --git a/plugins/AttachmentCollections/Entity/AttachmentCollectionEntry.php b/plugins/AttachmentCollections/Entity/AttachmentCollectionEntry.php index 1a75e626ba..8497c9be21 100644 --- a/plugins/AttachmentCollections/Entity/AttachmentCollectionEntry.php +++ b/plugins/AttachmentCollections/Entity/AttachmentCollectionEntry.php @@ -14,7 +14,7 @@ class AttachmentCollectionEntry extends Entity private int $id; private int $note_id; private int $attachment_id; - private int $collection_id; + private int $attachment_collection_id; public function setId(int $id): self { @@ -49,15 +49,15 @@ class AttachmentCollectionEntry extends Entity return $this->attachment_id; } - public function setCollectionId(int $collection_id): self + public function setAttachmentCollectionId(int $attachment_collection_id): self { - $this->collection_id = $collection_id; + $this->attachment_collection_id = $attachment_collection_id; return $this; } - public function getCollectionId(): int + public function getAttachmentCollectionId(): int { - return $this->collection_id; + return $this->attachment_collection_id; } // @codeCoverageIgnoreEnd @@ -68,10 +68,10 @@ class AttachmentCollectionEntry extends Entity return [ 'name' => 'attachment_collection_entry', 'fields' => [ - 'id' => ['type' => 'serial', 'not null' => true, 'description' => 'unique identifier'], - 'note_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Note.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'foreign key to note table'], - 'attachment_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Attachment.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'foreign key to attachment table'], - 'collection_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Collection.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'foreign key to collection table'], + 'id' => ['type' => 'serial', 'not null' => true, 'description' => 'unique identifier'], + 'note_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Note.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'foreign key to note table'], + 'attachment_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Attachment.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'foreign key to attachment table'], + 'attachment_collection_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'AttachmentCollection.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'foreign key to collection table'], ], 'primary key' => ['id'], ]; diff --git a/plugins/BlogCollections/BlogCollections.php b/plugins/BlogCollections/BlogCollections.php new file mode 100644 index 0000000000..e93e3f6118 --- /dev/null +++ b/plugins/BlogCollections/BlogCollections.php @@ -0,0 +1,109 @@ +. + +// }}} + +namespace Plugin\BlogCollections; + +use App\Core\DB\DB; +use App\Core\Modules\Plugin; +use App\Entity\Actor; +use Component\Collection\Util\MetaCollectionTrait; +use Plugin\BlogCollections\Entity\BlogCollection; +use Plugin\BlogCollections\Entity\BlogCollectionEntry; +use Symfony\Component\HttpFoundation\Request; + +class BlogCollections extends Plugin +{ + use MetaCollectionTrait; + + protected function createCollection(Actor $owner, array $vars, string $name) + { + $column = BlogCollection::create([ + 'name' => $name, + 'actor_id' => $owner->getId(), + ]); + DB::persist($column); + DB::persist(BlogCollectionEntry::create(args: [ + 'note_id' => $vars['vars']['note_id'], + 'blog_collection_id' => $column->getId(), + ])); + } + + protected function removeItem(Actor $owner, array $vars, array $items, array $collections) + { + return DB::dql(<<<'EOF' + DELETE FROM \Plugin\BlogCollections\Entity\BlogCollectionEntry AS entry + WHERE entry.note_id = :note_id + AND entry.blog_collection_id IN ( + SELECT blog.id FROM \Plugin\BlogCollections\Entity\BlogCollection AS blog + WHERE blog.actor_id = :user_id + AND blog.id IN (:ids) + ) + EOF, [ + 'note_id' => $vars['vars']['note_id'], + 'user_id' => $owner->getId(), + 'ids' => $items, + ]); + } + + protected function addItem(Actor $owner, array $vars, array $items, array $collections) + { + foreach ($items as $id) { + // prevent user from putting something in a collection (s)he doesn't own: + if (\in_array($id, $collections)) { + DB::persist(BlogCollectionEntry::create(args: [ + 'note_id' => $vars['vars']['note_id'], + 'blog_collection_id' => $id, + ])); + } + } + } + + protected function shouldAddToRightPanel(Actor $user, $vars, Request $request): bool + { + // TODO: Implement shouldAddToRightPanel() method. + return $vars['path'] === 'note_view'; + } + + protected function getCollectionsBy(Actor $owner, ?array $vars = null, bool $ids_only = false): array + { + if (\is_null($vars)) { + $res = DB::findBy(BlogCollection::class, ['actor_id' => $owner->getId()]); + } else { + $res = DB::dql( + <<<'EOF' + SELECT entry.blog_collection_id FROM \Plugin\BlogCollections\Entity\BlogCollectionEntry AS entry + INNER JOIN \Plugin\BlogCollections\Entity\BlogCollection AS blog_collection + WITH blog_collection.id = entry.attachment_collection_id + WHERE entry.note_id = :note_id AND blog_collection.actor_id = :id + EOF, + [ + 'id' => $owner->getId(), + 'note_id' => $vars['vars']['note_id'], + ], + ); + } + if (!$ids_only) { + return $res; + } + return array_map(fn ($x) => $x['blog_collection_id'], $res); + } +} diff --git a/plugins/BlogCollections/Controller/BlogCollections.php b/plugins/BlogCollections/Controller/BlogCollections.php new file mode 100644 index 0000000000..8999676a6a --- /dev/null +++ b/plugins/BlogCollections/Controller/BlogCollections.php @@ -0,0 +1,83 @@ +. + +// }}} + +namespace Plugin\BlogCollections\Controller; + +use App\Core\DB\DB; +use App\Core\Router\Router; +use Component\Collection\Util\Controller\MetaCollectionController; +use Plugin\BlogCollections\Entity\BlogCollection; + +class BlogCollections extends MetaCollectionController +{ + public function getCollectionUrl(int $owner_id, string $owner_nickname, int $collection_id): string + { + if (\is_null($owner_nickname)) { + return Router::url( + 'collection_notes_view_by_actor_id', + ['id' => $owner_id, 'cid' => $collection_id], + ); + } + return Router::url( + 'collection_notes_view_by_nickname', + ['nickname' => $owner_nickname, 'cid' => $collection_id], + ); + } + + public function getCollectionItems(int $owner_id, $collection_id): array + { + [$notes] = DB::dql( + <<<'EOF' + SELECT notice FROM \Plugin\BlogCollections\Entity\BlogCollectionEntry AS entry + LEFT JOIN \App\Entity\Actor AS actor + WITH entry.actor_id = :owner_id + LEFT JOIN \App\Entity\Note AS notice + WITH entry.note_id = notice.id + WHERE entry.blog_collection_id = :collection_id + EOF, + ['collection_id' => $collection_id, 'owner_id' => $owner_id], + ); + return [ + '_template' => 'BlogCollections/collection_entry_view.html.twig', + 'bare_notes' => array_values($notes), + ]; + } + + public function getCollectionsByActorId(int $owner_id): array + { + return DB::findBy(BlogCollection::class, ['actor_id' => $owner_id], order_by: ['id' => 'desc']); + } + + public function getCollectionBy(int $owner_id, int $collection_id) + { + return DB::findOneBy(BlogCollection::class, ['id' => $collection_id]); + } + + public function createCollection(int $owner_id, string $name) + { + DB::persist(BlogCollection::create([ + 'name' => $name, + 'actor_id' => $owner_id, + ])); + } +} diff --git a/plugins/BlogCollections/Entity/BlogCollection.php b/plugins/BlogCollections/Entity/BlogCollection.php new file mode 100644 index 0000000000..c5b494a8fa --- /dev/null +++ b/plugins/BlogCollections/Entity/BlogCollection.php @@ -0,0 +1,97 @@ +. + +// }}} + +namespace Plugin\BlogCollections\Entity; + +use App\Core\Entity; + +/** + * BlogCollection Entity + * + * @package GNUsocial + * @category BlogCollectionsPlugin + * + * @author Eliseu Amaro + * @copyright 2022 Free Software Foundation, Inc http://www.fsf.org + * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later + */ +class BlogCollection extends Entity +{ + // {{{ Autocode + // @codeCoverageIgnoreStart + private int $id; + private string $name; + private int $actor_id; + + public function setId(int $id): self + { + $this->id = $id; + return $this; + } + + public function getId(): int + { + return $this->id; + } + + public function setName(string $name): self + { + $this->name = mb_substr($name, 0, 255); + return $this; + } + + public function getName(): string + { + return $this->name; + } + + public function setActorId(int $actor_id): self + { + $this->actor_id = $actor_id; + return $this; + } + + public function getActorId(): int + { + return $this->actor_id; + } + + // @codeCoverageIgnoreEnd + // }}} Autocode + + public static function schemaDef(): array + { + return [ + 'name' => 'blog_collection', + 'fields' => [ + 'id' => ['type' => 'serial', 'not null' => true, 'description' => 'Unique Blog identifier'], + 'name' => ['type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'A Blog Collection name, used to categorize Blog entries'], + 'actor_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'one to many', 'not null' => true, 'description' => 'Foreign key to actor table, the original author of this Collection'], + ], + 'primary key' => ['id'], + 'foreign keys' => [ + 'actor_id_to_id_fkey' => ['actor', ['actor_id' => 'id']], + ], + ]; + } +} diff --git a/plugins/BlogCollections/Entity/BlogCollectionEntry.php b/plugins/BlogCollections/Entity/BlogCollectionEntry.php new file mode 100644 index 0000000000..f50afa5926 --- /dev/null +++ b/plugins/BlogCollections/Entity/BlogCollectionEntry.php @@ -0,0 +1,98 @@ +. + +// }}} + +namespace Plugin\BlogCollections\Entity; + +use App\Core\Entity; + +/** + * BlogCollectionEntry Entity + * + * @package GNUsocial + * @category BlogCollectionsPlugin + * + * @author Eliseu Amaro + * @copyright 2022 Free Software Foundation, Inc http://www.fsf.org + * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later + */ +class BlogCollectionEntry extends Entity +{ + // {{{ Autocode + // @codeCoverageIgnoreStart + private int $id; + private int $note_id; + private int $blog_collection_id; + + public function setId(int $id): self + { + $this->id = $id; + return $this; + } + + public function getId(): int + { + return $this->id; + } + + public function setNoteId(int $note_id): self + { + $this->note_id = $note_id; + return $this; + } + + public function getNoteId(): int + { + return $this->note_id; + } + + public function setBlogCollectionId(int $blog_collection_id): self + { + $this->blog_collection_id = $blog_collection_id; + return $this; + } + + public function getBlogCollectionId(): int + { + return $this->blog_collection_id; + } + + // @codeCoverageIgnoreEnd + // }}} Autocode + + public static function schemaDef(): array + { + return [ + 'name' => 'blog_collection_entry', + 'fields' => [ + 'id' => ['type' => 'serial', 'not null' => true, 'description' => 'unique identifier'], + 'note_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Note.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'Foreign key to note table, since a Blog entry is really just a Note with a higher text limit'], + 'blog_collection_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'BlogCollection.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'Foreign key to blog_collection table, indicates what category/collection this Blog entry is a part of'], + ], + 'primary key' => ['id'], + 'foreign keys' => [ + 'note_id_to_id_fkey' => ['note', ['note_id' => 'id']], + 'blog_collection_id_to_id_fkey' => ['blog_collection', ['blog_collection_id' => 'id']], + ], + ]; + } +}