MetaCollectionController.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php
  2. declare(strict_types = 1);
  3. // {{{ License
  4. // This file is part of GNU social - https://www.gnu.org/software/social
  5. //
  6. // GNU social is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU Affero General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // GNU social is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU Affero General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU Affero General Public License
  17. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
  18. // }}}
  19. /**
  20. * Collections Controller for GNU social
  21. *
  22. * @package GNUsocial
  23. * @category Plugin
  24. *
  25. * @author Phablulo <phablulo@gmail.com>
  26. * @copyright 2018-2019, 2021 Free Software Foundation, Inc http://www.fsf.org
  27. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  28. */
  29. namespace Component\Collection\Util\Controller;
  30. use App\Core\DB\DB;
  31. use App\Core\Form;
  32. use function App\Core\I18n\_m;
  33. use App\Entity\LocalUser;
  34. use App\Util\Common;
  35. use App\Util\Exception\RedirectException;
  36. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  37. use Symfony\Component\Form\Extension\Core\Type\TextType;
  38. use Symfony\Component\HttpFoundation\Request;
  39. abstract class MetaCollectionController extends FeedController
  40. {
  41. protected string $slug = 'collectionsEntry';
  42. protected string $plural_slug = 'collectionsList';
  43. protected string $page_title = 'Collections';
  44. abstract public function getCollectionUrl(int $owner_id, string $owner_nickname, int $collection_id): string;
  45. abstract public function getCollectionItems(int $owner_id, $collection_id): array;
  46. abstract public function getCollectionsByActorId(int $owner_id): array;
  47. abstract public function getCollectionBy(int $owner_id, int $collection_id);
  48. abstract public function createCollection(int $owner_id, string $name);
  49. public function collectionsViewByActorNickname(Request $request, string $nickname): array
  50. {
  51. $user = DB::findOneBy(LocalUser::class, ['nickname' => $nickname]);
  52. return self::collectionsView($request, $user->getId(), $nickname);
  53. }
  54. public function collectionsViewByActorId(Request $request, int $id): array
  55. {
  56. return self::collectionsView($request, $id, null);
  57. }
  58. /**
  59. * Generate Collections page
  60. *
  61. * @param int $id actor id
  62. * @param ?string $nickname actor nickname
  63. *
  64. * @return array twig template options
  65. */
  66. public function collectionsView(Request $request, int $id, ?string $nickname): array
  67. {
  68. $collections = $this->getCollectionsByActorId($id);
  69. $create_title = _m('Create a ' . mb_strtolower(preg_replace('/([a-z0-9])([A-Z])/', '$1 $2', $this->slug)));
  70. $collections_title = _m('The ' . mb_strtolower(preg_replace('/([a-z0-9])([A-Z])/', '$1 $2', $this->plural_slug)));
  71. // create collection form
  72. $create = null;
  73. if (Common::user()?->getId() === $id) {
  74. $create = Form::create([
  75. ['name', TextType::class, [
  76. 'label' => $create_title,
  77. 'attr' => [
  78. 'placeholder' => _m('Name'),
  79. 'required' => 'required',
  80. ],
  81. 'data' => '',
  82. ]],
  83. ['add_collection', SubmitType::class, [
  84. 'label' => $create_title,
  85. 'attr' => [
  86. 'title' => $create_title,
  87. ],
  88. ]],
  89. ]);
  90. $create->handleRequest($request);
  91. if ($create->isSubmitted() && $create->isValid()) {
  92. $this->createCollection($id, $create->getData()['name']);
  93. DB::flush();
  94. throw new RedirectException();
  95. }
  96. }
  97. // We need to inject some functions in twig,
  98. // but I don't want to create an environment for this
  99. // as twig docs suggest in https://twig.symfony.com/doc/2.x/advanced.html#functions.
  100. //
  101. // Instead, I'm using an anonymous class to encapsulate
  102. // the functions and passing that class to the template.
  103. // This is suggested at https://stackoverflow.com/a/50364502.
  104. $fn = new class($id, $nickname, $request, $this, $this->slug) {
  105. private $id;
  106. private $nick;
  107. private $request;
  108. private $parent;
  109. private $slug;
  110. public function __construct($id, $nickname, $request, $parent, $slug)
  111. {
  112. $this->id = $id;
  113. $this->nick = $nickname;
  114. $this->request = $request;
  115. $this->parent = $parent;
  116. $this->slug = $slug;
  117. }
  118. // there's already an injected function called path,
  119. // that maps to Router::url(name, args), but since
  120. // I want to preserve nicknames, I think it's better
  121. // to use that getUrl function
  122. public function getUrl($cid)
  123. {
  124. return $this->parent->getCollectionUrl($this->id, $this->nick, $cid);
  125. }
  126. // There are many collections in this page and we need two
  127. // forms for each one of them: one form to edit the collection's
  128. // name and another to remove the collection.
  129. // creating the edit form
  130. public function editForm($collection)
  131. {
  132. $edit = Form::create([
  133. ['name', TextType::class, [
  134. 'attr' => [
  135. 'placeholder' => 'New name',
  136. 'required' => 'required',
  137. ],
  138. 'data' => '',
  139. ]],
  140. ['update_' . $collection->getId(), SubmitType::class, [
  141. 'label' => _m('Save'),
  142. 'attr' => [
  143. 'title' => _m('Save'),
  144. ],
  145. ]],
  146. ]);
  147. $edit->handleRequest($this->request);
  148. if ($edit->isSubmitted() && $edit->isValid()) {
  149. $this->parent->setCollectionName($this->id, $this->nick, $collection, $edit->getData()['name']);
  150. DB::flush();
  151. throw new RedirectException();
  152. }
  153. return $edit->createView();
  154. }
  155. // creating the remove form
  156. public function rmForm($collection)
  157. {
  158. $rm = Form::create([
  159. ['remove_' . $collection->getId(), SubmitType::class, [
  160. 'label' => _m('Delete ' . $this->slug),
  161. 'attr' => [
  162. 'title' => _m('Delete ' . $this->slug),
  163. 'class' => 'danger',
  164. ],
  165. ]],
  166. ]);
  167. $rm->handleRequest($this->request);
  168. if ($rm->isSubmitted()) {
  169. $this->parent->removeCollection($this->id, $this->nick, $collection);
  170. DB::flush();
  171. throw new RedirectException();
  172. }
  173. return $rm->createView();
  174. }
  175. };
  176. return [
  177. '_template' => 'collection/meta_collections.html.twig',
  178. 'page_title' => $this->page_title,
  179. 'list_title' => $collections_title,
  180. 'add_collection' => $create?->createView(),
  181. 'fn' => $fn,
  182. 'collections' => $collections,
  183. ];
  184. }
  185. public function collectionsEntryViewNotesByNickname(Request $request, string $nickname, int $cid): array
  186. {
  187. $user = DB::findOneBy(LocalUser::class, ['nickname' => $nickname]);
  188. return self::collectionsEntryViewNotesByActorId($request, $user->getId(), $cid);
  189. }
  190. public function collectionsEntryViewNotesByActorId(Request $request, int $id, int $cid): array
  191. {
  192. $collection = $this->getCollectionBy($id, $cid);
  193. $vars = $this->getCollectionItems($id, $cid);
  194. return array_merge([
  195. '_template' => 'collections/collection_entry_view.html.twig',
  196. 'page_title' => $collection->getName(),
  197. ], $vars);
  198. }
  199. }