2021-09-27 18:39:58 +09:00
< ? php
2021-10-10 17:26:18 +09:00
declare ( strict_types = 1 );
2021-09-27 18:39:58 +09:00
// {{{ 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/>.
// }}}
namespace Component\Search\Controller ;
2021-12-08 06:07:37 +09:00
use App\Core\Controller\FeedController ;
2021-09-27 18:39:58 +09:00
use App\Core\DB\DB ;
use App\Core\Event ;
2021-12-10 22:52:18 +09:00
use App\Core\Form ;
use function App\Core\I18n\_m ;
2021-12-08 05:25:28 +09:00
use App\Util\Common ;
2021-12-11 06:19:21 +09:00
use App\Util\Exception\BugFoundException ;
2021-12-10 22:52:18 +09:00
use App\Util\Exception\RedirectException ;
use App\Util\Form\FormFields ;
2021-12-12 02:38:34 +09:00
use App\Util\Formatting ;
2021-12-10 22:52:18 +09:00
use Component\Search as Comp ;
2021-09-27 18:39:58 +09:00
use Component\Search\Util\Parser ;
2021-12-12 02:38:34 +09:00
use Symfony\Component\Form\Extension\Core\Type\CheckboxType ;
2021-12-10 22:52:18 +09:00
use Symfony\Component\Form\Extension\Core\Type\SubmitType ;
use Symfony\Component\Form\Extension\Core\Type\TextType ;
2021-09-27 18:39:58 +09:00
use Symfony\Component\HttpFoundation\Request ;
2021-12-08 06:07:37 +09:00
class Search extends FeedController
2021-09-27 18:39:58 +09:00
{
2021-12-08 05:25:28 +09:00
/**
* Handle a search query
*/
2021-09-27 18:39:58 +09:00
public function handle ( Request $request )
{
2021-12-08 05:25:28 +09:00
$actor = Common :: actor ();
$language = ! \is_null ( $actor ) ? $actor -> getTopLanguage () -> getLocale () : null ;
2021-10-10 13:44:10 +09:00
$q = $this -> string ( 'q' );
2021-12-08 05:25:28 +09:00
[ $note_criteria , $actor_criteria ] = Parser :: parse ( $q , $language );
2021-10-10 13:44:10 +09:00
$note_qb = DB :: createQueryBuilder ();
$actor_qb = DB :: createQueryBuilder ();
2021-12-08 05:25:28 +09:00
$note_qb -> select ( 'note' ) -> from ( 'App\Entity\Note' , 'note' ) -> orderBy ( 'note.created' , 'DESC' );
$actor_qb -> select ( 'actor' ) -> from ( 'App\Entity\Actor' , 'actor' ) -> orderBy ( 'actor.created' , 'DESC' );
2021-12-03 01:37:17 +09:00
Event :: handle ( 'SearchQueryAddJoins' , [ & $note_qb , & $actor_qb ]);
2021-12-09 06:25:48 +09:00
2021-10-10 13:44:10 +09:00
$notes = $actors = [];
2021-10-10 17:26:18 +09:00
if ( ! \is_null ( $note_criteria )) {
2021-10-10 13:44:10 +09:00
$note_qb -> addCriteria ( $note_criteria );
$notes = $note_qb -> getQuery () -> execute ();
2021-12-09 06:25:48 +09:00
}
if ( ! \is_null ( $actor_criteria )) {
2021-10-10 17:26:18 +09:00
$actor_qb -> addCriteria ( $actor_criteria );
$actors = $actor_qb -> getQuery () -> execute ();
2021-10-10 13:44:10 +09:00
}
2021-09-27 18:39:58 +09:00
2021-12-10 22:52:18 +09:00
$search_builder_form = Form :: create ([
2021-12-12 02:38:34 +09:00
[ 'include_actors' , CheckboxType :: class , [ 'required' => false , 'data' => false , 'label' => _m ( 'Include people/actors' )]],
[ 'include_actors_groups' , CheckboxType :: class , [ 'required' => false , 'data' => false , 'label' => _m ( 'Include groups' )]],
[ 'include_actors_lists' , CheckboxType :: class , [ 'required' => false , 'data' => false , 'label' => _m ( 'Include people lists' )]],
[ 'include_actors_people' , CheckboxType :: class , [ 'required' => false , 'data' => false , 'label' => _m ( 'Include people' )]],
[ 'include_actors_businesses' , CheckboxType :: class , [ 'required' => false , 'data' => false , 'label' => _m ( 'Include businesses' )]],
[ 'include_actors_organizations' , CheckboxType :: class , [ 'required' => false , 'data' => false , 'label' => _m ( 'Include organizations' )]],
[ 'include_actors_bots' , CheckboxType :: class , [ 'required' => false , 'data' => false , 'label' => _m ( 'Include bots' )]],
[ 'include_notes' , CheckboxType :: class , [ 'required' => false , 'data' => true , 'label' => _m ( 'Include notes' )]],
[ 'include_notes_text' , CheckboxType :: class , [ 'required' => false , 'data' => true , 'label' => _m ( 'Include text notes' )]],
[ 'include_notes_media' , CheckboxType :: class , [ 'required' => false , 'data' => true , 'label' => _m ( 'Include media notes' )]],
[ 'include_notes_polls' , CheckboxType :: class , [ 'required' => false , 'data' => true , 'label' => _m ( 'Include polls' )]],
[ 'include_notes_bookmarks' , CheckboxType :: class , [ 'required' => false , 'data' => true , 'label' => _m ( 'Include bookmarks' )]],
/* note_langs */ FormFields :: language ( $actor , context_actor : null , label : _m ( 'Search for notes in these languages' ), multiple : true , required : false , use_short_display : false , form_id : 'note_langs' , use_no_selection : true ),
[ 'note_tags' , TextType :: class , [ 'required' => false , 'label' => _m ( 'Include only notes with all the following tags' )]],
/* note_actor_langs */ FormFields :: language ( $actor , context_actor : null , label : _m ( 'Search for notes by people who know these languages' ), multiple : true , required : false , use_short_display : false , form_id : 'note_actor_langs' , use_no_selection : true ),
[ 'note_actor_tags' , TextType :: class , [ 'required' => false , 'label' => _m ( 'Include only notes by people with all the following tags' )]],
/* actor_langs */ FormFields :: language ( $actor , context_actor : null , label : _m ( 'Search for people that know these languages' ), multiple : true , required : false , use_short_display : false , form_id : 'actor_langs' , use_no_selection : true ),
[ 'actor_tags' , TextType :: class , [ 'required' => false , 'label' => _m ( 'Include only people with all the following tags' )]],
2021-12-10 22:52:18 +09:00
[ $form_name = 'search_builder' , SubmitType :: class , [ 'label' => _m ( 'Search' )]],
]);
if ( 'POST' === $request -> getMethod () && $request -> request -> has ( $form_name )) {
$search_builder_form -> handleRequest ( $request );
if ( $search_builder_form -> isSubmitted () && $search_builder_form -> isValid ()) {
2021-12-12 02:38:34 +09:00
$data = $search_builder_form -> getData ();
$query = [];
$include_notes_query = [];
$include_actors_query = [];
$exception = new BugFoundException ( 'Search builder form seems to have new fields the code did not expect' );
2021-12-11 06:19:21 +09:00
foreach ( $data as $key => $value ) {
if ( ! \is_null ( $value ) && ! empty ( $value )) {
if ( str_contains ( $key , 'tags' )) {
$query [] = " { $key } :# { $value } " ;
} elseif ( str_contains ( $key , 'lang' )) {
if ( ! \in_array ( 'null' , $value )) {
$langs = implode ( ',' , $value );
$query [] = " { $key } : { $langs } " ;
}
2021-12-12 02:38:34 +09:00
} elseif ( str_contains ( $key , 'include' )) {
if ( str_contains ( $key , 'notes' )) {
if ( $key === 'include_notes' ) {
if ( ! $data [ $key ]) {
$include_notes_query = null ;
}
} elseif ( $data [ $key ] && ! \is_null ( $include_notes_query )) {
$include_notes_query [] = Formatting :: removePrefix ( $key , 'include_notes_' );
}
} elseif ( str_contains ( $key , 'actors' )) {
if ( $key === 'include_actors' ) {
if ( ! $data [ $key ]) {
$include_actors_query = null ;
}
} elseif ( $data [ $key ] && ! \is_null ( $include_actors_query )) {
$include_actors_query [] = Formatting :: removePrefix ( $key , 'include_actors_' );
}
} else {
throw $exception ;
}
2021-12-11 06:19:21 +09:00
} else {
2021-12-12 02:38:34 +09:00
throw $exception ;
2021-12-11 06:19:21 +09:00
}
}
}
2021-12-12 02:38:34 +09:00
if ( ! \is_null ( $include_notes_query ) && ! empty ( $include_notes_query )) {
$query [] = 'note-types:' . implode ( ',' , $include_notes_query );
}
if ( ! \is_null ( $include_actors_query ) && ! empty ( $include_actors_query )) {
$query [] = 'actor-types:' . implode ( ',' , $include_actors_query );
}
2021-12-11 06:19:21 +09:00
$query = implode ( ' ' , $query );
throw new RedirectException ( 'search' , [ 'q' => $query ]);
2021-12-10 22:52:18 +09:00
}
}
2021-12-08 19:20:37 +09:00
return [
2021-12-10 22:52:18 +09:00
'_template' => 'search/show.html.twig' ,
2021-12-11 19:48:08 +09:00
'search_form' => Comp\Search :: searchForm ( $request , query : $q , add_subscribe : true ),
2021-12-10 22:52:18 +09:00
'search_builder_form' => $search_builder_form -> createView (),
'notes' => $notes ,
'actors' => $actors ,
'page' => 1 , // TODO paginate
2021-12-08 19:20:37 +09:00
];
2021-09-27 18:39:58 +09:00
}
}