Completed
Push — master ( f26e19...3fcf5a )
by Florian
05:27
created

SearchControllerTrait::getFacetFormatter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: FlorianMeyer
5
 * Date: 18.01.2018
6
 * Time: 13:04
7
 */
8
9
namespace StingerSoft\EntitySearchBundle\Controller;
10
11
use StingerSoft\EntitySearchBundle\Form\QueryType;
12
use StingerSoft\EntitySearchBundle\Model\Document;
13
use StingerSoft\EntitySearchBundle\Model\PaginatableResultSet;
14
use StingerSoft\EntitySearchBundle\Model\Query;
15
use StingerSoft\EntitySearchBundle\Services\Facet\FacetServiceInterface;
16
use StingerSoft\EntitySearchBundle\Services\Mapping\DocumentToEntityMapperInterface;
17
use StingerSoft\EntitySearchBundle\Services\SearchService;
18
use Symfony\Component\HttpFoundation\JsonResponse;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpFoundation\Session\SessionInterface;
21
22
trait SearchControllerTrait {
23
24
	use AbstractControllerTrait;
25
26
	/**
27
	 *
28
	 * @var SearchService
29
	 */
30
	private $searchService;
31
32
33
	private $availableFacets;
34
35
	private $facetFormatter;
36
37
38
39
	public function searchAction(Request $request) {
40
		if($request->query->get('term', false) !== false) {
41
			$this->setSearchTerm($request->getSession(), $request->query->get('term'));
0 ignored issues
show
Bug introduced by
It seems like $request->getSession() can be null; however, setSearchTerm() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
42
			return $this->redirectToRoute('stinger_soft_entity_search_search');
43
		}
44
45
		$term = $this->getSearchTerm($request->getSession());
0 ignored issues
show
Bug introduced by
It seems like $request->getSession() can be null; however, getSearchTerm() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
46
		$facets = $this->getSearchFacets($request->getSession());
0 ignored issues
show
Bug introduced by
It seems like $request->getSession() can be null; however, getSearchFacets() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
47
		$availableFacets = $this->getAvailableFacets();
48
49
		$query = new Query($term, $facets, array_keys($availableFacets));
50
51
		$facetForm = $this->createForm(QueryType::class, $query, array(
52
			'used_facets' =>  $this->getConfiguredUsedFacets($query->getUsedFacets())
53
		));
54
55
		$facetForm->handleRequest($request);
56
		if($facetForm->isSubmitted()) {
57
			if($facetForm->get('clear')->isClicked()) {
58
				$query->setFacets($this->getDefaultFacets());
59
			}
60
			$this->setSearchTerm($request->getSession(), $query->getSearchTerm());
0 ignored issues
show
Bug introduced by
It seems like $request->getSession() can be null; however, setSearchTerm() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
61
			$this->setSearchFacets($request->getSession(), $query->getFacets());
0 ignored issues
show
Bug introduced by
It seems like $request->getSession() can be null; however, setSearchFacets() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
62
		}
63
		$result = $this->getSearchService()->search($query);
64
65
		$facetForm = $this->createForm(QueryType::class, $query, array(
66
			'result'          => $result,
67
			'used_facets'     => $this->getConfiguredUsedFacets($query->getUsedFacets()),
68
			'facet_formatter' => $this->getFacetFormatter()
69
		));
70
71
		$page = $request->query->get('page', 1);
72
		$results = array();
0 ignored issues
show
Unused Code introduced by
$results is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
73
		if($result instanceof PaginatableResultSet) {
74
			$results = $result->paginate($page, $this->getResultsPerPage());
75
		} else {
76
			$results = $result->getResults(($page - 1) * $this->getResultsPerPage(), $this->getResultsPerPage());
77
		}
78
79
		return $this->render($this->getTemplate(), array(
80
			'results'   => $results,
81
			'resultSet' => $result,
82
			'term'      => $query->getSearchTerm(),
83
			'mapper'    => $this->get(DocumentToEntityMapperInterface::SERVICE_ID),
0 ignored issues
show
Bug introduced by
It seems like get() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
84
			'facetForm' => $facetForm->createView()
85
		));
86
	}
87
88
	protected function getConfiguredUsedFacets(array $queryUsedFacets) {
89
		$availableFacets = $this->getAvailableFacets();
90
		$usedFacets = array();
91
		foreach($queryUsedFacets as $queryUsedFacet) {
92
			$usedFacets[$queryUsedFacet] = $availableFacets[$queryUsedFacet];
93
		}
94
		return $usedFacets;
95
	}
96
97
	/**
98
	 * Maximum number of suggestions which should be provided by the autocomplete action
99
	 *
100
	 * @return integer
101
	 */
102
	protected function getSuggestionCount() {
103
		return 10;
104
	}
105
106
	/**
107
	 * Prefix to store information in the session variable
108
	 *
109
	 * @return string
110
	 */
111
	protected function getSessionPrefix() {
112
		return 'stinger_soft_entity_search';
113
	}
114
115
	/**
116
	 * Number of results which should be displayed per page
117
	 *
118
	 * @return integer
119
	 */
120
	protected function getResultsPerPage() {
121
		return 10;
122
	}
123
124
	protected function getTemplate() {
125
		return 'StingerSoftEntitySearchBundle:Search:results.html.twig';
126
	}
127
128
	protected function getFacetFormatter() {
129
		$this->initFacets();
130
		return $this->facetFormatter;
131
	}
132
133
	/**
134
	 * Returns an array of preselected facets (no facet selected is the default)
135
	 *
136
	 * @return string[string][]
0 ignored issues
show
Documentation introduced by
The doc-type string[string][] could not be parsed: Expected "]" at position 2, but found "string". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
137
	 */
138
	protected function getDefaultFacets() {
139
		$availableFacets = $this->getAvailableFacets();
140
		return array_combine(array_keys($availableFacets), array_fill(0, count($availableFacets), array()));
141
	}
142
143
	/**
144
	 * Returns an array of the available facets which should be offered the user as a filter
145
	 *
146
	 * @return string[]
147
	 */
148
	protected function getAvailableFacets() {
149
		$this->initFacets();
150
		return $this->availableFacets;
151
	}
152
153
154
	protected function initFacets() {
155
		if(!$this->availableFacets) {
156
			$this->availableFacets = array();
157
			$this->facetFormatter = array();
158
159
			$facetServices = $this->getParameter('stinger_soft.entity_search.available_facets');
0 ignored issues
show
Bug introduced by
It seems like getParameter() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
160
			foreach($facetServices as $facetServiceId) {
161
				/** @var FacetServiceInterface $facetService */
162
				$facetService = $this->get($facetServiceId);
0 ignored issues
show
Bug introduced by
It seems like get() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
163
				$this->availableFacets[$facetService->getField()] = $facetService->getFormOptions();
164
				if($facetService->getFacetFormatter()) {
165
					$this->facetFormatter[$facetService->getField()] = $facetService->getFacetFormatter();
166
				}
167
			}
168
		}
169
	}
170
171
	/**
172
	 * Fetches the searched facets from the session object
173
	 *
174
	 * @param SessionInterface $session
175
	 * @return string[string][]
0 ignored issues
show
Documentation introduced by
The doc-type string[string][] could not be parsed: Expected "]" at position 2, but found "string". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
176
	 */
177
	protected function getSearchFacets(SessionInterface $session) {
178
		$facets = $session->get($this->getSessionPrefix() . '_facets', false);
179
		return $facets ? json_decode($facets, true) : $this->getDefaultFacets();
180
	}
181
182
	/**
183
	 * Sets the given search facets in the user's session
184
	 *
185
	 * @param SessionInterface $session
186
	 * @param string[string][] $facets
0 ignored issues
show
Documentation introduced by
The doc-type string[string][] could not be parsed: Expected "]" at position 2, but found "string". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
187
	 */
188
	protected function setSearchFacets(SessionInterface $session, $facets) {
189
		$session->set($this->getSessionPrefix() . '_facets', json_encode($facets));
190
	}
191
192
	/**
193
	 * Fetches the search term from the session object
194
	 *
195
	 * @param SessionInterface $session
196
	 * @return mixed
197
	 */
198
	protected function getSearchTerm(SessionInterface $session) {
199
		return $session->get($this->getSessionPrefix() . '_term', false);
200
	}
201
202
	/**
203
	 * Sets the given search term in the user's session
204
	 *
205
	 * @param SessionInterface $session
206
	 * @param string $term
207
	 */
208
	protected function setSearchTerm(SessionInterface $session, $term) {
209
		$session->set($this->getSessionPrefix() . '_term', $term);
210
	}
211
212
	/**
213
	 * Returns a JSON array of autocompletions for the given term.
214
	 * The term can be provided as a GET or POST paramater with the name <em>term</em>
215
	 *
216
	 * @param Request $request
217
	 * @return \Symfony\Component\HttpFoundation\JsonResponse
218
	 */
219
	public function autocompleteAction(Request $request) {
220
		$term = $request->get('term');
221
		return new JsonResponse($this->getSearchService()->autocomplete($term, $this->getSuggestionCount()));
222
	}
223
224
	/**
225
	 * Provides an online help for the configured search service.
226
	 * If the search service has no online help defined a warning message will be displayed to the user.
227
	 *
228
	 * @param Request $request
229
	 * @return \Symfony\Component\HttpFoundation\Response
230
	 */
231
	public function onlineHelpAction(Request $request) {
232
		$template = $this->getSearchService()->getOnlineHelp($request->getLocale(), $this->getDefaultLocale());
0 ignored issues
show
Bug introduced by
It seems like getDefaultLocale() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
233
		return $this->render($template ?: 'StingerSoftEntitySearchBundle:Help:no_help.html.twig');
234
	}
235
236
	/**
237
	 * Inits and returns the configured search service
238
	 *
239
	 * @return SearchService
240
	 */
241
	protected function getSearchService() {
242
		$this->service = $this->get(SearchService::SERVICE_ID);
0 ignored issues
show
Bug introduced by
The property service does not seem to exist. Did you mean searchService?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Bug introduced by
It seems like get() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
243
		$this->service->setObjectManager($this->getDoctrine()->getManager());
0 ignored issues
show
Bug introduced by
The property service does not seem to exist. Did you mean searchService?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Bug introduced by
It seems like getDoctrine() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
244
		return $this->service;
0 ignored issues
show
Bug introduced by
The property service does not seem to exist. Did you mean searchService?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
245
	}
246
}