SearchController   A
last analyzed

Complexity

Total Complexity 3

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 63
c 2
b 0
f 0
dl 0
loc 109
rs 10
wmc 3

1 Method

Rating   Name   Duplication   Size   Complexity  
B index() 0 104 3
1
<?php
2
3
namespace App\Controller\Search;
4
5
use App\Entity\Image;
6
use Elastica\Collapse\InnerHits as CollapseInnerHits;
7
use Elastica\Query;
8
use Elastica\Query\BoolQuery;
9
use Elastica\Query\InnerHits;
10
use Elastica\Query\MatchQuery;
11
use Elastica\Query\MultiMatch;
12
use Elastica\Query\Nested;
13
use Elastica\Query\QueryString;
14
use FOS\ElasticaBundle\Finder\FinderInterface;
15
use FOS\ElasticaBundle\Finder\PaginatedFinderInterface;
16
use Knp\Component\Pager\PaginatorInterface;
17
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
18
use Symfony\Component\Form\Extension\Core\Type\SearchType;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpFoundation\Response;
21
use Symfony\Component\Routing\Annotation\Route;
22
23
/**
24
 * @Route("/search", name="search_")
25
 *
26
 */
27
class SearchController extends AbstractController
28
{
29
    /**
30
     * @Route("/", name="index", methods={"GET", "POST"})
31
     */
32
    public function index(
33
        Request $request,
34
        //PaginatedFinderInterface $imageFinder,
35
        PaginatedFinderInterface $wanderFinder,
36
        PaginatorInterface $paginator): Response
37
    {
38
        // $finder = $this->container->get('fos_elastica.finder.app');
39
        // TODO: Maybe try combining results from $imageFinder and $wanderFinder?
40
        $queryString = "";
41
42
        $form = $this->createFormBuilder(null, [
43
            'method' => 'GET',
44
            'csrf_protection' => false //
45
            ])
46
            ->add('query', SearchType::class, ['label' => false])
47
            ->getForm();
48
49
        $form->handleRequest($request);
50
        $pagination = null;
51
        if ($form->isSubmitted() && $form->isValid()) {
52
            $data = $form->getData();
53
            $queryString = $data['query'];
54
            // Nested query to find all wanders with images that match
55
            // the text.
56
            $nmm = new MultiMatch();
57
            $nmm->setQuery($queryString);
58
            // TODO By the looks of https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html
59
            // you might be able to just not setFields and it'll default to * and might catch everything
60
            // anyway.
61
            $nmm->setFields([
62
                'images.title',
63
                'images.description',
64
                'images.tags',
65
                'images.autoTags',
66
                'images.textTags']);
67
68
            $nested = new Nested();
69
            $nested->setPath('images');
70
            $nested->setQuery($nmm);
71
72
            $innerHits = new InnerHits();
73
            // We want more than the default three inner hits, as there may be several related
74
            // images on a particular wander, but we don't want to bump things up too high otherwise
75
            // an overly-broad search will bring back way too many images even with pagination of
76
            // the outer results.
77
            $innerHits->setSize(10);
78
            $innerHits->setHighlight(['fields' => [
79
                'images.title' => [
80
                    'number_of_fragments' => 0,
81
                    'no_match_size' => 1024,
82
                    'pre_tags' => ['<mark>'],
83
                    'post_tags' => ['</mark>']
84
                ],
85
                'images.description' => [
86
                    'no_match_size' => 1024,
87
                    'pre_tags' => ['<mark>'],
88
                    'post_tags' => ['</mark>']
89
                ]
90
                // We don't need to highlight tag hits, as they're Elasticsearch keywords and will
91
                // only be found by an exact match on the search term. We highlight them more simply
92
                // just by looking at which ones match $queryString in the twig template.
93
            ]]);
94
            $nested->setInnerHits($innerHits);
95
96
            // Combine that with a normal query to find all wanders that
97
            // themselves match the text
98
            $mm = new MultiMatch();
99
            $mm->setQuery($data['query']);
100
            $mm->setFields(['title', 'description']);
101
102
            $bool = new BoolQuery();
103
            $bool->addShould($nested);
104
            $bool->addShould($mm);
105
106
            // Wrap it with an outer query to add highlighting to the
107
            // Wander-level query.
108
            $searchQuery = new Query();
109
            $searchQuery->setQuery($bool);
110
111
            $searchQuery->setHighlight(['fields' => [
112
                'title' => [
113
                    'number_of_fragments' => 0,
114
                    'no_match_size' => 1024,
115
                    'pre_tags' => ['<mark>'],
116
                    'post_tags' => ['</mark>']
117
                ],
118
                'description' => [
119
                    'no_match_size' => 200,
120
                    'pre_tags' => ['<mark>'],
121
                    'post_tags' => ['</mark>']
122
                ]
123
            ]]);
124
125
            $results = $wanderFinder->createHybridPaginatorAdapter($searchQuery);
126
            $pagination = $paginator->paginate(
127
                $results,
128
                $request->query->getInt('page', 1),
129
                10
130
            );
131
        }
132
        return $this->render('search/index.html.twig', [
133
            'query_string' => $queryString,
134
            'form' => $form->createView(),
135
            'pagination' => $pagination
136
        ]);
137
    }
138
}
139