2021-12-30 00:51:12 +00:00
< ? php
declare ( strict_types = 1 );
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
// }}}
/**
* Collections Controller for GNU social
*
* @ package GNUsocial
* @ category Plugin
*
* @ author Phablulo < phablulo @ gmail . com >
* @ copyright 2018 - 2019 , 2021 Free Software Foundation , Inc http :// www . fsf . org
* @ license https :// www . gnu . org / licenses / agpl . html GNU AGPL v3 or later
*/
2022-01-02 20:04:52 +00:00
namespace Component\Collection\Util\Controller ;
2021-12-30 00:51:12 +00:00
2022-03-27 15:19:09 +01:00
use App\Core\DB ;
2021-12-30 00:51:12 +00:00
use App\Core\Form ;
2022-01-02 20:04:52 +00:00
use function App\Core\I18n\_m ;
2021-12-30 00:51:12 +00:00
use App\Entity\LocalUser ;
use App\Util\Common ;
use App\Util\Exception\RedirectException ;
use Symfony\Component\Form\Extension\Core\Type\SubmitType ;
use Symfony\Component\Form\Extension\Core\Type\TextType ;
2022-10-19 22:39:17 +01:00
use Symfony\Component\Form\FormView ;
2021-12-30 00:51:12 +00:00
use Symfony\Component\HttpFoundation\Request ;
2022-10-19 22:39:17 +01:00
/**
2022-10-19 22:39:17 +01:00
* @ template T of object
*
* @ extends FeedController < T >
2022-10-19 22:39:17 +01:00
*/
2022-01-02 20:04:52 +00:00
abstract class MetaCollectionController extends FeedController
2021-12-30 00:51:12 +00:00
{
2022-02-26 14:09:41 +00:00
protected const SLUG = 'collectionsEntry' ;
protected const PLURAL_SLUG = 'collectionsList' ;
protected string $page_title = 'Collections' ;
2021-12-30 00:51:12 +00:00
abstract public function getCollectionUrl ( int $owner_id , string $owner_nickname , int $collection_id ) : string ;
2022-10-19 22:39:17 +01:00
/**
* @ return T []
*/
abstract public function getCollectionItems ( int $owner_id , int $collection_id ) : array ;
/**
* @ return T []
*/
2022-01-02 20:04:52 +00:00
abstract public function getCollectionsByActorId ( int $owner_id ) : array ;
2021-12-30 00:51:12 +00:00
2022-10-19 22:39:17 +01:00
/**
* @ return T A collection
*/
abstract public function getCollectionBy ( int $owner_id , int $collection_id ) : object ;
abstract public function createCollection ( int $owner_id , string $name ) : bool ;
/**
2022-10-19 22:39:17 +01:00
* @ return ControllerResultType
2022-10-19 22:39:17 +01:00
*/
2022-01-02 20:04:52 +00:00
public function collectionsViewByActorNickname ( Request $request , string $nickname ) : array
2021-12-30 00:51:12 +00:00
{
$user = DB :: findOneBy ( LocalUser :: class , [ 'nickname' => $nickname ]);
2022-01-02 20:04:52 +00:00
return self :: collectionsView ( $request , $user -> getId (), $nickname );
2021-12-30 00:51:12 +00:00
}
2022-10-19 22:39:17 +01:00
/**
2022-10-19 22:39:17 +01:00
* @ return ControllerResultType
2022-10-19 22:39:17 +01:00
*/
2022-01-02 20:04:52 +00:00
public function collectionsViewByActorId ( Request $request , int $id ) : array
2021-12-30 00:51:12 +00:00
{
2022-01-02 20:04:52 +00:00
return self :: collectionsView ( $request , $id , null );
2021-12-30 00:51:12 +00:00
}
/**
* Generate Collections page
*
* @ param int $id actor id
* @ param ? string $nickname actor nickname
*
2022-10-19 22:39:17 +01:00
* @ return ControllerResultType twig template options
2021-12-30 00:51:12 +00:00
*/
2022-01-02 20:04:52 +00:00
public function collectionsView ( Request $request , int $id , ? string $nickname ) : array
2021-12-30 00:51:12 +00:00
{
2022-01-02 20:04:52 +00:00
$collections = $this -> getCollectionsByActorId ( $id );
2021-12-30 00:51:12 +00:00
2022-02-26 14:09:41 +00:00
$create_title = _m ( 'Create a ' . mb_strtolower ( preg_replace ( '/([a-z0-9])([A-Z])/' , '$1 $2' , static :: SLUG )));
$collections_title = _m ( 'The ' . mb_strtolower ( preg_replace ( '/([a-z0-9])([A-Z])/' , '$1 $2' , static :: PLURAL_SLUG )));
2021-12-30 00:51:12 +00:00
// create collection form
$create = null ;
if ( Common :: user () ? -> getId () === $id ) {
$create = Form :: create ([
[ 'name' , TextType :: class , [
2022-01-02 18:40:09 +00:00
'label' => $create_title ,
2021-12-30 00:51:12 +00:00
'attr' => [
'placeholder' => _m ( 'Name' ),
'required' => 'required' ,
],
'data' => '' ,
]],
[ 'add_collection' , SubmitType :: class , [
2022-01-02 18:40:09 +00:00
'label' => $create_title ,
2021-12-30 00:51:12 +00:00
'attr' => [
2022-01-02 18:40:09 +00:00
'title' => $create_title ,
2021-12-30 00:51:12 +00:00
],
]],
]);
$create -> handleRequest ( $request );
if ( $create -> isSubmitted () && $create -> isValid ()) {
$this -> createCollection ( $id , $create -> getData ()[ 'name' ]);
DB :: flush ();
throw new RedirectException ();
}
}
// We need to inject some functions in twig,
// but I don't want to create an environment for this
// as twig docs suggest in https://twig.symfony.com/doc/2.x/advanced.html#functions.
//
// Instead, I'm using an anonymous class to encapsulate
// the functions and passing that class to the template.
2022-02-26 14:09:41 +00:00
// This is suggested at https://web.archive.org/web/20220226132328/https://stackoverflow.com/questions/3595727/twig-pass-function-into-template/50364502
$fn = new class ( $id , $nickname , $request , $this , static :: SLUG ) {
2022-10-19 22:39:17 +01:00
public function __construct ( private int $id , private string $nickname , private Request $request , private object $parent , private string $slug )
2021-12-30 00:51:12 +00:00
{
}
2022-01-04 21:58:49 +00:00
// there's already an injected function called path,
2021-12-30 00:51:12 +00:00
// that maps to Router::url(name, args), but since
// I want to preserve nicknames, I think it's better
// to use that getUrl function
2022-10-19 22:39:17 +01:00
public function getUrl ( int $cid ) : string
2021-12-30 00:51:12 +00:00
{
2022-10-19 22:39:17 +01:00
return $this -> parent -> getCollectionUrl ( $this -> id , $this -> nickname , $cid );
2021-12-30 00:51:12 +00:00
}
// There are many collections in this page and we need two
// forms for each one of them: one form to edit the collection's
// name and another to remove the collection.
// creating the edit form
2022-10-19 22:39:17 +01:00
public function editForm ( object $collection ) : FormView
2021-12-30 00:51:12 +00:00
{
$edit = Form :: create ([
[ 'name' , TextType :: class , [
'attr' => [
'placeholder' => 'New name' ,
'required' => 'required' ,
],
'data' => '' ,
]],
[ 'update_' . $collection -> getId (), SubmitType :: class , [
'label' => _m ( 'Save' ),
'attr' => [
'title' => _m ( 'Save' ),
],
]],
]);
$edit -> handleRequest ( $this -> request );
if ( $edit -> isSubmitted () && $edit -> isValid ()) {
2022-10-19 22:39:17 +01:00
$this -> parent -> setCollectionName ( $this -> id , $this -> nickname , $collection , $edit -> getData ()[ 'name' ]);
2021-12-30 00:51:12 +00:00
DB :: flush ();
throw new RedirectException ();
}
return $edit -> createView ();
}
// creating the remove form
2022-10-19 22:39:17 +01:00
public function rmForm ( object $collection ) : FormView
2021-12-30 00:51:12 +00:00
{
$rm = Form :: create ([
[ 'remove_' . $collection -> getId (), SubmitType :: class , [
'label' => _m ( 'Delete ' . $this -> slug ),
'attr' => [
'title' => _m ( 'Delete ' . $this -> slug ),
'class' => 'danger' ,
],
]],
]);
$rm -> handleRequest ( $this -> request );
if ( $rm -> isSubmitted ()) {
2022-10-19 22:39:17 +01:00
$this -> parent -> removeCollection ( $this -> id , $this -> nickname , $collection );
2021-12-30 00:51:12 +00:00
DB :: flush ();
throw new RedirectException ();
}
return $rm -> createView ();
}
};
return [
2022-01-02 20:04:52 +00:00
'_template' => 'collection/meta_collections.html.twig' ,
2021-12-30 00:51:12 +00:00
'page_title' => $this -> page_title ,
2022-01-02 18:40:09 +00:00
'list_title' => $collections_title ,
2021-12-30 00:51:12 +00:00
'add_collection' => $create ? -> createView (),
'fn' => $fn ,
'collections' => $collections ,
];
}
2022-10-19 22:39:17 +01:00
/**
* @ return ControllerResultType
*/
2022-01-02 18:40:09 +00:00
public function collectionsEntryViewNotesByNickname ( Request $request , string $nickname , int $cid ) : array
2021-12-30 00:51:12 +00:00
{
$user = DB :: findOneBy ( LocalUser :: class , [ 'nickname' => $nickname ]);
2022-01-02 18:40:09 +00:00
return self :: collectionsEntryViewNotesByActorId ( $request , $user -> getId (), $cid );
2021-12-30 00:51:12 +00:00
}
2022-10-19 22:39:17 +01:00
/**
* @ return ControllerResultType
*/
2022-01-02 18:40:09 +00:00
public function collectionsEntryViewNotesByActorId ( Request $request , int $id , int $cid ) : array
2021-12-30 00:51:12 +00:00
{
$collection = $this -> getCollectionBy ( $id , $cid );
$vars = $this -> getCollectionItems ( $id , $cid );
return array_merge ([
2022-01-02 18:40:09 +00:00
'_template' => 'collections/collection_entry_view.html.twig' ,
2021-12-30 00:51:12 +00:00
'page_title' => $collection -> getName (),
], $vars );
}
}