Completed
Push — 5.6 ( 679697...f4d50c )
by Jeroen
16:35 queued 10:49
created

SearchService::search()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 3.009

Importance

Changes 0
Metric Value
dl 0
loc 37
ccs 18
cts 20
cp 0.9
rs 9.328
c 0
b 0
f 0
cc 3
nc 4
nop 0
crap 3.009
1
<?php
2
3
namespace Kunstmaan\NodeSearchBundle\Services;
4
5
use Elastica\Aggregation\Terms;
6
use Kunstmaan\NodeBundle\Helper\RenderContext;
7
use Kunstmaan\NodeSearchBundle\PagerFanta\Adapter\SearcherRequestAdapter;
8
use Kunstmaan\NodeSearchBundle\Search\AbstractElasticaSearcher;
9
use Pagerfanta\Exception\NotValidCurrentPageException;
10
use Pagerfanta\Pagerfanta;
11
use Symfony\Component\DependencyInjection\Container;
12
use Symfony\Component\DependencyInjection\ContainerInterface;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\HttpFoundation\RequestStack;
15
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
16
17
/**
18
 * Class SearchService
19
 */
20
class SearchService
21
{
22
    /**
23
     * @var RenderContext
24
     */
25
    protected $renderContext;
26
27
    /**
28
     * @var Container
29
     */
30
    protected $container;
31
32
    /**
33
     * @var RequestStack
34
     */
35
    protected $requestStack;
36
37
    /**
38
     * @var int
39
     */
40
    protected $defaultPerPage;
41
42
    /**
43
     * @var array
44
     */
45
    private $searchers;
46
47
    /**
48
     * @param int $defaultPerPage
49
     */
50 2
    public function __construct(ContainerInterface $container, RequestStack $requestStack, $defaultPerPage = 10, array $searchers = [])
51
    {
52 2
        $this->container = $container;
0 ignored issues
show
Documentation Bug introduced by
$container is of type object<Symfony\Component...ion\ContainerInterface>, but the property $container was declared to be of type object<Symfony\Component...ncyInjection\Container>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
53 2
        $this->requestStack = $requestStack;
54 2
        $this->defaultPerPage = $defaultPerPage;
55 2
        $this->renderContext = new RenderContext();
56 2
        $this->searchers = $searchers;
57 2
    }
58
59
    /**
60
     * @param int $defaultPerPage
61
     */
62
    public function setDefaultPerPage($defaultPerPage)
63
    {
64
        $this->defaultPerPage = $defaultPerPage;
65
    }
66
67
    /**
68
     * @return RenderContext
69
     */
70
    public function getRenderContext()
71
    {
72
        return $this->renderContext;
73
    }
74
75
    /**
76
     * @param RenderContext $renderContext
77
     */
78
    public function setRenderContext($renderContext)
79
    {
80
        $this->renderContext = $renderContext;
81
    }
82
83
    /**
84
     * @return int
85
     */
86 1
    public function getDefaultPerPage()
87
    {
88 1
        return $this->defaultPerPage;
89
    }
90
91
    /**
92
     * @return Container
93
     */
94
    public function getContainer()
95
    {
96
        return $this->container;
97
    }
98
99
    /**
100
     * @param Container $container
101
     */
102
    public function setContainer($container)
103
    {
104
        $this->container = $container;
105
    }
106
107
    /**
108
     * @return Request
0 ignored issues
show
Documentation introduced by
Should the return type not be Request|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
109
     */
110
    public function getRequest()
111
    {
112
        return $this->requestStack->getCurrentRequest();
113
    }
114
115
    /**
116
     * @return Pagerfanta
117
     */
118 2
    public function search()
119
    {
120 2
        $request = $this->requestStack->getCurrentRequest();
121
122
        // Retrieve the current page number from the URL, if not present of lower than 1, set it to 1
123 2
        $entity = $request->attributes->get('_entity');
124
125 2
        $pageNumber = $this->getRequestedPage($request);
126
127 2
        $searcher = $this->searchers[$entity->getSearcher()] ?? null;
128 2
        if (null === $searcher) {
129 2
            $searcher = $this->container->get($entity->getSearcher());
130
131 1
            @trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
132 1
                sprintf(
133 1
                    'Getting the node searcher "%s" from the container is deprecated in KunstmaanNodeSearchBundle 5.2 and will be removed in KunstmaanNodeSearchBundle 6.0. Tag your searcher service with the "kunstmaan_node_search.node_searcher" tag to add a searcher.',
134 1
                    $entity->getSearcher()
135
                ),
136 1
                E_USER_DEPRECATED
137
            );
138
        }
139
140 1
        $this->applySearchParams($searcher, $request, $this->renderContext);
141
142 1
        $adapter = new SearcherRequestAdapter($searcher);
143 1
        $pagerfanta = new Pagerfanta($adapter);
144
145
        try {
146
            $pagerfanta
147 1
                ->setMaxPerPage($this->getDefaultPerPage())
148 1
                ->setCurrentPage($pageNumber);
149
        } catch (NotValidCurrentPageException $e) {
150
            throw new NotFoundHttpException();
151
        }
152
153 1
        return $pagerfanta;
154
    }
155
156 1
    protected function applySearchParams(AbstractElasticaSearcher $searcher, Request $request, RenderContext $context)
157
    {
158
        // Retrieve the search parameters
159 1
        $queryString = trim($request->query->get('query'));
160 1
        $queryType = $request->query->get('type');
161 1
        $lang = $request->getLocale();
162
163 1
        $context['q_query'] = $queryString;
164 1
        $context['q_type'] = $queryType;
165
166
        $searcher
167 1
            ->setData($this->sanitizeSearchQuery($queryString))
168 1
            ->setContentType($queryType)
169 1
            ->setLanguage($lang);
170
171 1
        $query = $searcher->getQuery();
172
173
        // Aggregations
174 1
        $termsAggregation = new Terms('type');
175 1
        $termsAggregation->setField('type');
176
177 1
        $query->addAggregation($termsAggregation);
178 1
    }
179
180
    /**
181
     * Currently we just search for a complete match...
182
     *
183
     * @param string $query
184
     *
185
     * @return string
186
     */
187 1
    protected function sanitizeSearchQuery($query)
188
    {
189 1
        return '"' . $query . '"';
190
    }
191
192
    /**
193
     * @return int
194
     */
195 2
    private function getRequestedPage(Request $request)
196
    {
197 2
        $pageNumber = $request->query->getInt('page', 1);
198 2
        if (!$pageNumber || $pageNumber < 1) {
199
            $pageNumber = 1;
200
        }
201
202 2
        return $pageNumber;
203
    }
204
}
205