2021-12-10 18:13:28 +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/>.
// }}}
/**
* @ author Hugo Sales < hugo @ hsal . es >
2022-01-01 10:31:10 +00:00
* @ author Eliseu Amaro < mail @ eliseuama . ro >
* @ copyright 2021 - 2022 Free Software Foundation , Inc http :// www . fsf . org
2021-12-10 18:13:28 +00:00
* @ license https :// www . gnu . org / licenses / agpl . html GNU AGPL v3 or later
*/
namespace Component\Conversation\Controller ;
2022-01-03 20:38:45 +00:00
use App\Core\Cache ;
2022-03-27 15:19:09 +01:00
use App\Core\DB ;
2022-01-01 10:31:10 +00:00
use App\Core\Form ;
use function App\Core\I18n\_m ;
2022-01-13 17:47:47 +00:00
use App\Core\Log ;
2022-03-27 16:43:59 +01:00
use App\Core\Router ;
2022-01-03 20:38:45 +00:00
use App\Entity\Note ;
2022-01-01 10:31:10 +00:00
use App\Util\Common ;
2022-01-03 20:38:45 +00:00
use App\Util\Exception\ClientException ;
use App\Util\Exception\NoLoggedInUser ;
use App\Util\Exception\NoSuchNoteException ;
2022-01-01 10:31:10 +00:00
use App\Util\Exception\RedirectException ;
2022-01-03 20:38:45 +00:00
use App\Util\Exception\ServerException ;
2022-02-16 03:01:25 +00:00
use App\Util\HTML\Heading ;
2022-01-02 21:36:57 +00:00
use Component\Collection\Util\Controller\FeedController ;
use Component\Conversation\Entity\ConversationMute ;
2022-01-01 10:31:10 +00:00
use Symfony\Component\Form\Extension\Core\Type\SubmitType ;
2021-12-10 18:13:28 +00:00
use Symfony\Component\HttpFoundation\Request ;
2022-10-19 22:39:17 +01:00
/**
* @ extends FeedController < \App\Entity\Note >
*/
2021-12-10 18:13:28 +00:00
class Conversation extends FeedController
{
2021-12-19 17:43:43 +00:00
/**
2022-01-03 19:24:54 +00:00
* Render conversation page .
2021-12-19 17:43:43 +00:00
*
2022-01-03 19:24:54 +00:00
* @ param int $conversation_id To identify what Conversation is to be rendered
*
* @ throws \App\Util\Exception\ServerException
*
2022-10-19 22:39:17 +01:00
* @ return ControllerResultType Array containing keys : 'notes' ( all known
* notes in the given Conversation ), 'should_format' ( boolean , stating if
* onFormatNoteList events may or not format given notes ), 'page_title'
* ( used as the title header )
2021-12-19 17:43:43 +00:00
*/
2022-01-03 19:24:54 +00:00
public function showConversation ( Request $request , int $conversation_id ) : array
2021-12-10 18:13:28 +00:00
{
2022-02-16 03:01:25 +00:00
$page_title = _m ( 'Conversation' );
2021-12-10 18:13:28 +00:00
return [
2022-02-27 21:14:33 +00:00
'_template' => 'collection/notes.html.twig' ,
'notes' => $this -> query (
query : " note-conversation: { $conversation_id } " ,
note_order_by : [ 'note.created' => 'ASC' , 'note.id' => 'ASC' ],
)[ 'notes' ] ? ? [],
2022-02-16 03:01:25 +00:00
'should_format' => false ,
'page_title' => $page_title ,
'notes_feed_title' => ( new Heading ( 1 , [], $page_title )),
2021-12-10 18:13:28 +00:00
];
}
2022-01-01 10:31:10 +00:00
2022-01-03 20:38:45 +00:00
/**
* Controller for the note reply non - JS page
*
* Leverages the `PostingModifyData` event to add the `reply_to_id` field from the GET variable 'reply_to_id'
*
* @ throws ClientException
* @ throws NoLoggedInUser
* @ throws NoSuchNoteException
* @ throws ServerException
*
2022-10-19 22:39:17 +01:00
* @ return ControllerResultType
2022-01-03 20:38:45 +00:00
*/
public function addReply ( Request $request )
{
$user = Common :: ensureLoggedIn ();
$note_id = $this -> int ( 'reply_to_id' , new ClientException ( _m ( 'Malformed query.' )));
$note = Note :: ensureCanInteract ( Note :: getByPK ( $note_id ), $user );
$conversation_id = $note -> getConversationId ();
return $this -> showConversation ( $request , $conversation_id );
}
2022-01-03 19:24:54 +00:00
/**
* Creates form view for Muting Conversation extra action .
*
* @ param int $conversation_id The Conversation id that this action targets
*
* @ throws \App\Util\Exception\NoLoggedInUser
* @ throws \App\Util\Exception\RedirectException
* @ throws \App\Util\Exception\ServerException
*
2022-10-19 22:39:17 +01:00
* @ return ControllerResultType Array containing templating where the form is to be rendered , and the form itself
2022-01-03 19:24:54 +00:00
*/
2022-01-03 20:38:45 +00:00
public function muteConversation ( Request $request , int $conversation_id )
2022-01-01 10:31:10 +00:00
{
2022-01-03 20:38:45 +00:00
$user = Common :: ensureLoggedIn ();
$is_muted = ConversationMute :: isMuted ( $conversation_id , $user );
$form = Form :: create ([
2022-01-13 17:47:47 +00:00
[ 'mute_conversation' , SubmitType :: class , [ 'label' => $is_muted ? _m ( 'Unmute' ) : _m ( 'Mute' ), 'attr' => [ 'class' => '' ]]],
2022-01-01 10:31:10 +00:00
]);
$form -> handleRequest ( $request );
if ( $form -> isSubmitted () && $form -> isValid ()) {
2022-01-07 21:14:13 +00:00
if ( ! $is_muted ) {
2022-01-03 20:38:45 +00:00
DB :: persist ( ConversationMute :: create ([ 'conversation_id' => $conversation_id , 'actor_id' => $user -> getId ()]));
} else {
DB :: removeBy ( 'conversation_mute' , [ 'conversation_id' => $conversation_id , 'actor_id' => $user -> getId ()]);
}
2022-01-01 10:31:10 +00:00
DB :: flush ();
2022-01-03 20:38:45 +00:00
Cache :: delete ( ConversationMute :: cacheKeys ( $conversation_id , $user -> getId ())[ 'mute' ]);
2022-01-13 17:47:47 +00:00
// Redirect user to where they came from
// Prevent open redirect
if ( ! \is_null ( $from = $this -> string ( 'from' ))) {
if ( Router :: isAbsolute ( $from )) {
Log :: warning ( " Actor { $user -> getId () } attempted to mute conversation { $conversation_id } and then get redirected to another host, or the URL was invalid ( { $from } ) " );
throw new ClientException ( _m ( 'Can not redirect to outside the website from here' ), 400 ); // 400 Bad request (deceptive)
} else {
// TODO anchor on element id
throw new RedirectException ( url : $from );
}
} else {
// If we don't have a URL to return to, go to the instance root
throw new RedirectException ( 'root' );
}
2022-01-01 10:31:10 +00:00
}
return [
'_template' => 'conversation/mute.html.twig' ,
2022-02-27 21:14:33 +00:00
'notes' => $this -> query (
query : " note-conversation: { $conversation_id } " ,
note_order_by : [ 'note.created' => 'ASC' , 'note.id' => 'ASC' ],
)[ 'notes' ] ? ? [],
'is_muted' => $is_muted ,
'form' => $form -> createView (),
2022-01-01 10:31:10 +00:00
];
}
2021-12-10 18:13:28 +00:00
}