1 | <?php |
||
2 | |||
3 | namespace SilverStripe\FullTextSearch\Search\Criteria; |
||
4 | |||
5 | use SilverStripe\FullTextSearch\Search\Adapters\SearchAdapterInterface; |
||
6 | use SilverStripe\FullTextSearch\Search\Queries\AbstractSearchQueryWriter; |
||
7 | |||
8 | /** |
||
9 | * Class SearchCriteria |
||
10 | * @package SilverStripe\FullTextSearch\Criteria |
||
11 | */ |
||
12 | class SearchCriteria implements SearchCriteriaInterface |
||
13 | { |
||
14 | /** |
||
15 | * @param string |
||
16 | */ |
||
17 | const CONJUNCTION_AND = 'AND'; |
||
18 | |||
19 | /** |
||
20 | * @param string |
||
21 | */ |
||
22 | const CONJUNCTION_OR = 'OR'; |
||
23 | |||
24 | /** |
||
25 | * A collection of SearchCriterion and SearchCriteria. |
||
26 | * |
||
27 | * @var SearchCriteriaInterface[] |
||
28 | */ |
||
29 | protected $clauses = array(); |
||
30 | |||
31 | /** |
||
32 | * The conjunctions used between Criteria (AND/OR). |
||
33 | * |
||
34 | * @var string[] |
||
35 | */ |
||
36 | protected $conjunctions = array(); |
||
37 | |||
38 | /** |
||
39 | * @var SearchAdapterInterface|null |
||
40 | */ |
||
41 | protected $adapter = null; |
||
42 | |||
43 | /** |
||
44 | * You can pass through a string value, Criteria object, or Criterion object for $target. |
||
45 | * |
||
46 | * String value might be "SiteTree_Title" or whatever field in your index that you're trying to target. |
||
47 | * |
||
48 | * If you require complex filtering then you can build your Criteria object first with multiple layers/levels of |
||
49 | * Criteria, and then pass it in here when you're ready. |
||
50 | * |
||
51 | * If you have your own Criterion object that you've created that you want to use, you can also pass that in here. |
||
52 | * |
||
53 | * @param string|SearchCriterion $target |
||
54 | * @param mixed $value |
||
55 | * @param string|null $comparison |
||
56 | * @param AbstractSearchQueryWriter $searchQueryWriter |
||
57 | */ |
||
58 | public function __construct( |
||
59 | $target, |
||
60 | $value = null, |
||
61 | $comparison = null, |
||
62 | AbstractSearchQueryWriter $searchQueryWriter = null |
||
63 | ) { |
||
64 | $this->addClause($this->getCriterionForCondition($target, $value, $comparison, $searchQueryWriter)); |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * Static create method provided so that you can perform method chaining. |
||
69 | * |
||
70 | * @param $target |
||
71 | * @param null $value |
||
0 ignored issues
–
show
Documentation
Bug
introduced
by
Loading history...
|
|||
72 | * @param null $comparison |
||
0 ignored issues
–
show
|
|||
73 | * @param AbstractSearchQueryWriter $searchQueryWriter |
||
74 | * @return SearchCriteria |
||
75 | */ |
||
76 | public static function create( |
||
77 | $target, |
||
78 | $value = null, |
||
79 | $comparison = null, |
||
80 | AbstractSearchQueryWriter $searchQueryWriter = null |
||
81 | ) { |
||
82 | return new SearchCriteria($target, $value, $comparison, $searchQueryWriter); |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * @return null|SearchAdapterInterface |
||
87 | */ |
||
88 | public function getAdapter() |
||
89 | { |
||
90 | return $this->adapter; |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * @param SearchAdapterInterface $adapter |
||
95 | * @return $this |
||
96 | */ |
||
97 | public function setAdapter(SearchAdapterInterface $adapter) |
||
98 | { |
||
99 | $this->adapter = $adapter; |
||
100 | |||
101 | return $this; |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * @param string $ps Current prepared statement. |
||
106 | * @return void |
||
107 | * @throws \Exception |
||
108 | */ |
||
109 | public function appendPreparedStatementTo(&$ps) |
||
110 | { |
||
111 | $adapter = $this->getAdapter(); |
||
112 | |||
113 | if (!$adapter instanceof SearchAdapterInterface) { |
||
114 | throw new \Exception('No adapter has been applied to SearchCriteria'); |
||
115 | } |
||
116 | |||
117 | $ps .= $adapter->getOpenComparisonContainer(); |
||
118 | |||
119 | foreach ($this->getClauses() as $key => $clause) { |
||
120 | $clause->setAdapter($adapter); |
||
121 | $clause->appendPreparedStatementTo($ps); |
||
122 | |||
123 | // There's always one less conjunction then there are clauses. |
||
124 | if ($this->getConjunction($key) !== null) { |
||
125 | $ps .= $adapter->getConjunctionFor($this->getConjunction($key)); |
||
126 | } |
||
127 | } |
||
128 | |||
129 | $ps .= $adapter->getCloseComparisonContainer(); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * @param string|SearchCriteriaInterface $target |
||
134 | * @param mixed $value |
||
135 | * @param string|null $comparison |
||
136 | * @param AbstractSearchQueryWriter $searchQueryWriter |
||
137 | * @return $this |
||
138 | */ |
||
139 | public function addAnd( |
||
140 | $target, |
||
141 | $value = null, |
||
142 | $comparison = null, |
||
143 | AbstractSearchQueryWriter $searchQueryWriter = null |
||
144 | ) { |
||
145 | $criterion = $this->getCriterionForCondition($target, $value, $comparison, $searchQueryWriter); |
||
146 | |||
147 | $this->addConjunction(SearchCriteria::CONJUNCTION_AND); |
||
148 | $this->addClause($criterion); |
||
149 | |||
150 | return $this; |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * @param string|SearchCriteriaInterface $target |
||
155 | * @param mixed $value |
||
156 | * @param string|null $comparison |
||
157 | * @param AbstractSearchQueryWriter $searchQueryWriter |
||
158 | * @return $this |
||
159 | */ |
||
160 | public function addOr( |
||
161 | $target, |
||
162 | $value = null, |
||
163 | $comparison = null, |
||
164 | AbstractSearchQueryWriter $searchQueryWriter = null |
||
165 | ) { |
||
166 | $criterion = $this->getCriterionForCondition($target, $value, $comparison, $searchQueryWriter); |
||
167 | |||
168 | $this->addConjunction(SearchCriteria::CONJUNCTION_OR); |
||
169 | $this->addClause($criterion); |
||
170 | |||
171 | return $this; |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * @param string|SearchCriteriaInterface $target |
||
176 | * @param mixed $value |
||
177 | * @param string $comparison |
||
178 | * @param AbstractSearchQueryWriter $searchQueryWriter |
||
179 | * @return SearchCriteriaInterface |
||
180 | */ |
||
181 | protected function getCriterionForCondition( |
||
182 | $target, |
||
183 | $value, |
||
184 | $comparison, |
||
185 | AbstractSearchQueryWriter $searchQueryWriter = null |
||
186 | ) { |
||
187 | if ($target instanceof SearchCriteriaInterface) { |
||
188 | return $target; |
||
189 | } |
||
190 | |||
191 | return new SearchCriterion($target, $value, $comparison, $searchQueryWriter); |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * @return SearchCriteriaInterface[] |
||
196 | */ |
||
197 | protected function getClauses() |
||
198 | { |
||
199 | return $this->clauses; |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * @param SearchCriteriaInterface $criterion |
||
204 | */ |
||
205 | protected function addClause($criterion) |
||
206 | { |
||
207 | $this->clauses[] = $criterion; |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * @return string[] |
||
212 | */ |
||
213 | protected function getConjunctions() |
||
214 | { |
||
215 | return $this->conjunctions; |
||
216 | } |
||
217 | |||
218 | /** |
||
219 | * @param int $key |
||
220 | * @return string|null |
||
221 | */ |
||
222 | protected function getConjunction($key) |
||
223 | { |
||
224 | $conjunctions = $this->getConjunctions(); |
||
225 | if (!array_key_exists($key, $conjunctions)) { |
||
226 | return null; |
||
227 | } |
||
228 | |||
229 | return $conjunctions[$key]; |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * @param string $conjunction |
||
234 | */ |
||
235 | protected function addConjunction($conjunction) |
||
236 | { |
||
237 | $this->conjunctions[] = $conjunction; |
||
238 | } |
||
239 | } |
||
240 |