This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace Dkd\PhpCmis; |
||
3 | |||
4 | /* |
||
5 | * This file is part of php-cmis-client. |
||
6 | * |
||
7 | * (c) Dimitri Ebert <[email protected]> |
||
8 | * |
||
9 | * For the full copyright and license information, please view the LICENSE |
||
10 | * file that was distributed with this source code. |
||
11 | */ |
||
12 | |||
13 | use Dkd\PhpCmis\Data\ObjectIdInterface; |
||
14 | use Dkd\PhpCmis\Data\ObjectTypeInterface; |
||
15 | use Dkd\PhpCmis\Definitions\PropertyDefinitionInterface; |
||
16 | use Dkd\PhpCmis\Definitions\TypeDefinitionInterface; |
||
17 | use Dkd\PhpCmis\Exception\CmisInvalidArgumentException; |
||
18 | use Dkd\PhpCmis\Exception\CmisObjectNotFoundException; |
||
19 | |||
20 | /** |
||
21 | * Query Statement |
||
22 | * |
||
23 | * Prepares a query statement based on either a manually supplied |
||
24 | * statement or one generated from supplied property list, type |
||
25 | * list, clause and ordering. |
||
26 | * |
||
27 | * Used with a manual statement: |
||
28 | * |
||
29 | * $statement = new QueryStatement($session, 'SELECT ...'); |
||
30 | * |
||
31 | * Used with property, type lists, clause and ordering: |
||
32 | * |
||
33 | * $statement = new QueryStatement( |
||
34 | * $session, |
||
35 | * NULL, |
||
36 | * array('prop1', 'prop2'), |
||
37 | * array('type1', 'type2'), |
||
38 | * 'prop1 = type1.foobar', |
||
39 | * array('prop1 ASC') |
||
40 | * ); |
||
41 | * |
||
42 | * Note that this is an approximation of the OpenCMIS Java implementation: |
||
43 | * Java allows multiple constructors but PHP does not; allowing additional |
||
44 | * constructor arguments and making the manual statement optional makes it |
||
45 | * possible to construct instances in nearly the same way as in Java. It's |
||
46 | * close, but not exactly the same - however, when used through the public |
||
47 | * APIs (Session->createQueryStatement) there is no difference in behavior. |
||
48 | */ |
||
49 | class QueryStatement implements QueryStatementInterface |
||
50 | { |
||
51 | /** |
||
52 | * @var SessionInterface |
||
53 | */ |
||
54 | protected $session; |
||
55 | |||
56 | /** |
||
57 | * @var string |
||
58 | */ |
||
59 | protected $statement; |
||
60 | |||
61 | /** |
||
62 | * @var array |
||
63 | */ |
||
64 | protected $parametersMap = []; |
||
65 | |||
66 | /** |
||
67 | * Creates a prepared statement for querying the CMIS repository. Requires |
||
68 | * at least the Session as parameter, then accepts either a manual statement |
||
69 | * or a list of property IDs, type IDs, a where clause and orderings which |
||
70 | * will then generate a prepared statement based on those values. |
||
71 | * |
||
72 | * See also main class desciption. |
||
73 | * |
||
74 | * @param SessionInterface $session The initialized Session for communicating |
||
75 | * @param string $statement Optional, manually prepared statement. If provided, |
||
76 | * excludes the use of property list, type list, where clause and ordering. |
||
77 | * @param array $selectPropertyIds An array PropertyDefinitionInterface |
||
78 | * or strings, can be mixed. When strings are provided those can be |
||
79 | * either the actual ID of the property or the query name thereof. |
||
80 | * @param array $fromTypes An array of TypeDefinitionInterface or strings, |
||
81 | * can be mixed. When strings are provided those can be either the |
||
82 | * actual ID of the type, or it can be the query name thereof. If |
||
83 | * an array of arrays is provided, each array is expected to contain |
||
84 | * a TypeDefinition or string as first member and an alias as second. |
||
85 | * @param string|null $whereClause If searching by custom clause, provide here. |
||
86 | * @param array $orderByPropertyIds List of property IDs by which to sort. |
||
87 | * Each value can be either a PropertyDefinitionInterface instance, |
||
88 | * a string (in which case, ID or queryName) or an array of a string |
||
89 | * or PropertyDefinition as first member and ASC or DESC as second. |
||
90 | * E.g. valid strings: "cm:title ASC", "cm:title", "P:cm:title". |
||
91 | * Valid arrays: [PropertyDefinitionInterface, "ASC"], ["cm:title", "ASC"] |
||
92 | * @throws CmisInvalidArgumentException |
||
93 | */ |
||
94 | 120 | public function __construct( |
|
95 | SessionInterface $session, |
||
96 | $statement = null, |
||
97 | array $selectPropertyIds = [], |
||
98 | array $fromTypes = [], |
||
99 | $whereClause = null, |
||
100 | array $orderByPropertyIds = [] |
||
101 | ) { |
||
102 | 120 | $this->session = $session; |
|
103 | 120 | $statementString = trim((string) $statement); |
|
104 | |||
105 | 120 | if (empty($statementString)) { |
|
106 | 26 | if (empty($selectPropertyIds)) { |
|
107 | 3 | throw new CmisInvalidArgumentException( |
|
108 | 3 | 'Statement was empty so property list must not be empty!', |
|
109 | 1441286811 |
||
110 | 3 | ); |
|
111 | } |
||
112 | 23 | if (empty($fromTypes)) { |
|
113 | 1 | throw new CmisInvalidArgumentException( |
|
114 | 1 | 'Statement was empty so types list must not be empty!', |
|
115 | 1441286812 |
||
116 | 1 | ); |
|
117 | } |
||
118 | 22 | $statementString = $this->generateStatementFromPropertiesAndTypesLists( |
|
119 | 22 | $selectPropertyIds, |
|
120 | 22 | $fromTypes, |
|
121 | 22 | $whereClause, |
|
122 | $orderByPropertyIds |
||
123 | 22 | ); |
|
124 | 22 | } else { |
|
125 | 94 | if (!empty($selectPropertyIds)) { |
|
126 | 1 | throw new CmisInvalidArgumentException( |
|
127 | 1 | 'Manual statement cannot be used when properties are used', |
|
128 | 1441286813 |
||
129 | 1 | ); |
|
130 | } |
||
131 | 93 | if (!empty($fromTypes)) { |
|
132 | 1 | throw new CmisInvalidArgumentException( |
|
133 | 1 | 'Manual statement cannot be used when types are used', |
|
134 | 1441286814 |
||
135 | 1 | ); |
|
136 | } |
||
137 | 92 | if (!empty($whereClause)) { |
|
138 | 1 | throw new CmisInvalidArgumentException( |
|
139 | 1 | 'Manual statement cannot be used when clause is used', |
|
140 | 1441286815 |
||
141 | 1 | ); |
|
142 | } |
||
143 | 91 | if (!empty($orderByPropertyIds)) { |
|
144 | 1 | throw new CmisInvalidArgumentException( |
|
145 | 1 | 'Manual statement cannot be used when orderings are used', |
|
146 | 1441286816 |
||
147 | 1 | ); |
|
148 | } |
||
149 | } |
||
150 | |||
151 | 112 | $this->statement = $statementString; |
|
152 | 112 | } |
|
153 | |||
154 | /** |
||
155 | * Generates a statement based on input criteria, with the necessary |
||
156 | * JOINs in place for selecting attributes related to all provided types. |
||
157 | * |
||
158 | * @param array $selectPropertyIds An array PropertyDefinitionInterface |
||
159 | * or strings, can be mixed. When strings are provided those can be |
||
160 | * either the actual ID of the property or the query name thereof. |
||
161 | * @param array $fromTypes An array of TypeDefinitionInterface or strings, |
||
162 | * can be mixed. When strings are provided those can be either the |
||
163 | * actual ID of the type, or it can be the query name thereof. If |
||
164 | * an array of arrays is provided, each array is expected to contain |
||
165 | * a TypeDefinition or string as first member and an alias as second. |
||
166 | * @param string|null $whereClause If searching by custom clause, provide here. |
||
167 | * @param array $orderByPropertyIds List of property IDs by which to sort. |
||
168 | * Each value can be either a PropertyDefinitionInterface instance, |
||
169 | * a string (in which case, ID or queryName) or an array of a string |
||
170 | * or PropertyDefinition as first member and ASC or DESC as second. |
||
171 | * E.g. valid strings: "cm:title ASC", "cm:title", "P:cm:title". |
||
172 | * Valid arrays: [PropertyDefinitionInterface, "ASC"], ["cm:title", "ASC"] |
||
173 | * @return string |
||
174 | */ |
||
175 | 22 | protected function generateStatementFromPropertiesAndTypesLists( |
|
176 | array $selectPropertyIds, |
||
177 | array $fromTypes, |
||
178 | $whereClause, |
||
179 | array $orderByPropertyIds |
||
180 | ) { |
||
181 | 22 | $statementString = 'SELECT ' . $this->generateStatementPropertyList($selectPropertyIds, false); |
|
182 | |||
183 | 22 | $primaryTable = array_shift($fromTypes); |
|
184 | 22 | list ($primaryTableQueryName, $primaryAlias) = $this->getQueryNameAndAliasForType($primaryTable, 'primary'); |
|
185 | |||
186 | 22 | $statementString .= ' FROM ' . $primaryTableQueryName . ' ' . $primaryAlias; |
|
187 | |||
188 | 22 | while (count($fromTypes) > 0) { |
|
189 | 7 | $secondaryTable = array_shift($fromTypes); |
|
190 | /* |
||
191 | * we build an automatic alias here, a simple one-byte ASCII value |
||
192 | * generated based on remaining tables. If 26 tables remain, a "z" |
||
193 | * is generated. If 1 table remains, an "a" is generated. The alias |
||
194 | * is, unfortunately, required for the JOIN to work correctly. It |
||
195 | * only gets used if the type string does not contain an alias. |
||
196 | */ |
||
197 | 7 | $alias = chr(97 + count($fromTypes)); |
|
198 | 7 | list ($secondaryTableQueryName, $alias) = $this->getQueryNameAndAliasForType($secondaryTable, $alias); |
|
199 | 7 | $statementString .= ' JOIN ' . $secondaryTableQueryName . ' AS ' . $alias . |
|
200 | 7 | ' ON ' . $primaryAlias . '.cmis:objectId = ' . $alias . '.cmis:objectId'; |
|
201 | 7 | } |
|
202 | |||
203 | 22 | if (trim((string) $whereClause)) { |
|
204 | 5 | $statementString .= ' WHERE ' . trim($whereClause); |
|
205 | 5 | } |
|
206 | |||
207 | 22 | if (!empty($orderByPropertyIds)) { |
|
208 | 7 | $statementString .= ' ORDER BY ' . $this->generateStatementPropertyList($orderByPropertyIds, true); |
|
209 | 7 | } |
|
210 | 22 | return trim($statementString); |
|
211 | } |
||
212 | |||
213 | /** |
||
214 | * Translates a TypeDefinition or string into a query name for |
||
215 | * that TypeDefinition. Returns the input string as fallback if |
||
216 | * the type could not be resolved. Input may contain an alias, |
||
217 | * if so, we split and preserve the alias but attempt to translate |
||
218 | * the type ID part. |
||
219 | * |
||
220 | * @param mixed $typeDefinitionMixed Input describing the type |
||
221 | * @param string $autoAlias If alias is not provided |
||
222 | * @return array |
||
223 | */ |
||
224 | 23 | protected function getQueryNameAndAliasForType($typeDefinitionMixed, $autoAlias) |
|
225 | { |
||
226 | 23 | $alias = null; |
|
227 | 23 | if (is_array($typeDefinitionMixed)) { |
|
228 | 4 | list ($typeDefinitionMixed, $alias) = $typeDefinitionMixed; |
|
229 | 4 | } |
|
230 | 23 | if ($typeDefinitionMixed instanceof TypeDefinitionInterface) { |
|
231 | 4 | $queryName = $typeDefinitionMixed->getQueryName(); |
|
232 | 23 | } elseif (is_string($typeDefinitionMixed) && strpos($typeDefinitionMixed, ' ')) { |
|
233 | 1 | list ($typeDefinitionMixed, $alias) = explode(' ', $typeDefinitionMixed, 2); |
|
234 | 1 | } |
|
235 | try { |
||
236 | 23 | $queryName = $this->session->getTypeDefinition($typeDefinitionMixed)->getQueryName(); |
|
237 | 23 | } catch (CmisObjectNotFoundException $error) { |
|
238 | 1 | $queryName = $typeDefinitionMixed; |
|
239 | } |
||
240 | 23 | return [$queryName, ($alias ? $alias : $autoAlias)]; |
|
241 | } |
||
242 | |||
243 | /** |
||
244 | * Renders a statement-compatible string of property selections, |
||
245 | * with ordering support if $withOrdering is true. Input properties |
||
246 | * can be an array of strings, an array of PropertyDefinition, or |
||
247 | * when $withOrdering is true, an array of arrays each containing |
||
248 | * a string or PropertyDefinition plus ASC or DESC as second value. |
||
249 | * |
||
250 | * @param array $properties |
||
251 | * @param boolean $withOrdering |
||
252 | * @return string |
||
253 | */ |
||
254 | 22 | protected function generateStatementPropertyList(array $properties, $withOrdering) |
|
255 | { |
||
256 | 22 | $statement = []; |
|
257 | 22 | foreach ($properties as $property) { |
|
258 | 22 | $ordering = ($withOrdering ? 'ASC' : ''); |
|
259 | 22 | if ($withOrdering) { |
|
260 | 7 | if (is_array($property)) { |
|
261 | 1 | list ($property, $ordering) = $property; |
|
262 | 7 | } elseif (is_string($property) && strpos($property, ' ')) { |
|
263 | 4 | list ($property, $ordering) = explode(' ', $property, 2); |
|
264 | 4 | } |
|
265 | 7 | } |
|
266 | 22 | if ($property instanceof PropertyDefinitionInterface) { |
|
267 | 5 | $propertyQueryName = $property->getQueryName(); |
|
268 | 5 | } else { |
|
269 | 20 | $propertyQueryName = $property; |
|
270 | } |
||
271 | 22 | $statement[] = rtrim($propertyQueryName . ' ' . $ordering); |
|
272 | 22 | } |
|
273 | 22 | return implode(', ', $statement); |
|
274 | } |
||
275 | |||
276 | /** |
||
277 | * Executes the query. |
||
278 | * |
||
279 | * @param boolean $searchAllVersions <code>true</code> if all document versions should be included in the search |
||
280 | * results, <code>false</code> if only the latest document versions should be included in the search results |
||
281 | * @param OperationContextInterface|null $context the operation context to use |
||
282 | * @return QueryResultInterface[] |
||
283 | */ |
||
284 | 1 | public function query($searchAllVersions, OperationContextInterface $context = null) |
|
285 | { |
||
286 | 1 | return $this->session->query($this->toQueryString(), $searchAllVersions, $context); |
|
287 | } |
||
288 | |||
289 | /** |
||
290 | * Sets the designated parameter to the given boolean. |
||
291 | * |
||
292 | * @param integer $parameterIndex the parameter index (one-based) |
||
293 | * @param boolean $bool the boolean |
||
294 | */ |
||
295 | 3 | public function setBoolean($parameterIndex, $bool) |
|
296 | { |
||
297 | 3 | $this->setParameter($parameterIndex, $bool === true ? 'TRUE' : 'FALSE'); |
|
298 | 2 | } |
|
299 | |||
300 | /** |
||
301 | * Sets the designated parameter to the given DateTime value. |
||
302 | * |
||
303 | * @param integer $parameterIndex the parameter index (one-based) |
||
304 | * @param \DateTime $dateTime the DateTime value as DateTime object |
||
305 | */ |
||
306 | 3 | public function setDateTime($parameterIndex, \DateTime $dateTime) |
|
307 | { |
||
308 | 3 | $this->setParameter($parameterIndex, $dateTime->format(Constants::QUERY_DATETIMEFORMAT)); |
|
309 | 2 | } |
|
310 | |||
311 | /** |
||
312 | * Sets the designated parameter to the given DateTime value with the prefix 'TIMESTAMP '. |
||
313 | * |
||
314 | * @param integer $parameterIndex the parameter index (one-based) |
||
315 | * @param \DateTime $dateTime the DateTime value as DateTime object |
||
316 | */ |
||
317 | 3 | public function setDateTimeTimestamp($parameterIndex, \DateTime $dateTime) |
|
318 | { |
||
319 | 3 | $this->setParameter($parameterIndex, 'TIMESTAMP ' . $dateTime->format(Constants::QUERY_DATETIMEFORMAT)); |
|
320 | 2 | } |
|
321 | |||
322 | /** |
||
323 | * Sets the designated parameter to the given object ID. |
||
324 | * |
||
325 | * @param integer $parameterIndex the parameter index (one-based) |
||
326 | * @param ObjectIdInterface $id the object ID |
||
327 | */ |
||
328 | 6 | public function setId($parameterIndex, ObjectIdInterface $id) |
|
329 | { |
||
330 | 6 | $this->setParameter($parameterIndex, $this->escape($id->getId())); |
|
331 | 5 | } |
|
332 | |||
333 | /** |
||
334 | * Sets the designated parameter to the given number. |
||
335 | * |
||
336 | * @param integer $parameterIndex the parameter index (one-based) |
||
337 | * @param integer $number the value to be set as number |
||
338 | * @throws CmisInvalidArgumentException If number not of type integer |
||
339 | */ |
||
340 | 5 | public function setNumber($parameterIndex, $number) |
|
341 | { |
||
342 | 5 | if (!is_int($number)) { |
|
343 | 1 | throw new CmisInvalidArgumentException('Number must be of type integer!'); |
|
344 | } |
||
345 | |||
346 | 4 | $this->setParameter($parameterIndex, $number); |
|
347 | 3 | } |
|
348 | |||
349 | /** |
||
350 | * Sets the designated parameter to the query name of the given property. |
||
351 | * |
||
352 | * @param integer $parameterIndex the parameter index (one-based) |
||
353 | * @param PropertyDefinitionInterface $propertyDefinition |
||
354 | * @throws CmisInvalidArgumentException If property has no query name |
||
355 | */ |
||
356 | 4 | public function setProperty($parameterIndex, PropertyDefinitionInterface $propertyDefinition) |
|
357 | { |
||
358 | 4 | $queryName = $propertyDefinition->getQueryName(); |
|
359 | 4 | if (empty($queryName)) { |
|
360 | 1 | throw new CmisInvalidArgumentException('Property has no query name!'); |
|
361 | } |
||
362 | |||
363 | 3 | $this->setParameter($parameterIndex, $this->escape($queryName)); |
|
364 | 2 | } |
|
365 | |||
366 | /** |
||
367 | * Sets the designated parameter to the given string. |
||
368 | * |
||
369 | * @param integer $parameterIndex the parameter index (one-based) |
||
370 | * @param string $string the string |
||
371 | * @throws CmisInvalidArgumentException If given value is not a string |
||
372 | */ |
||
373 | 8 | public function setString($parameterIndex, $string) |
|
374 | { |
||
375 | 8 | if (!is_string($string)) { |
|
376 | 1 | throw new CmisInvalidArgumentException('Parameter string must be of type string!'); |
|
377 | } |
||
378 | |||
379 | 7 | $this->setParameter($parameterIndex, $this->escape($string)); |
|
380 | 6 | } |
|
381 | |||
382 | /** |
||
383 | * Sets the designated parameter to the given string in a CMIS contains statement. |
||
384 | * |
||
385 | * Note that the CMIS specification requires two levels of escaping. The first level escapes ', ", \ characters |
||
386 | * to \', \" and \\. The characters *, ? and - are interpreted as text search operators and are not escaped |
||
387 | * on first level. |
||
388 | * If *, ?, - shall be used as literals, they must be passed escaped with \*, \? and \- to this method. |
||
389 | * |
||
390 | * For all statements in a CONTAINS() clause it is required to isolate those from a query statement. |
||
391 | * Therefore a second level escaping is performed. On the second level grammar ", ', - and \ are escaped with a \. |
||
392 | * See the spec for further details. |
||
393 | * |
||
394 | * Summary (input --> first level escaping --> second level escaping and output): |
||
395 | * * --> * --> * |
||
396 | * ? --> ? --> ? |
||
397 | * - --> - --> - |
||
398 | * \ --> \\ --> \\\\ |
||
399 | * (for any other character following other than * ? -) |
||
400 | * \* --> \* --> \\* |
||
401 | * \? --> \? --> \\? |
||
402 | * \- --> \- --> \\- |
||
403 | * ' --> \' --> \\\' |
||
404 | * " --> \" --> \\\" |
||
405 | * |
||
406 | * @param integer $parameterIndex the parameter index (one-based) |
||
407 | * @param string $string the CONTAINS string |
||
408 | * @throws CmisInvalidArgumentException If given value is not a string |
||
409 | */ |
||
410 | 10 | public function setStringContains($parameterIndex, $string) |
|
411 | { |
||
412 | 10 | if (!is_string($string)) { |
|
413 | 1 | throw new CmisInvalidArgumentException('Parameter string must be of type string!'); |
|
414 | } |
||
415 | |||
416 | 9 | $this->setParameter($parameterIndex, $this->escapeContains($string)); |
|
417 | 8 | } |
|
418 | |||
419 | /** |
||
420 | * Sets the designated parameter to the given string. |
||
421 | * It does not escape backslashes ('\') in front of '%' and '_'. |
||
422 | * |
||
423 | * @param integer $parameterIndex the parameter index (one-based) |
||
424 | * @param $string |
||
425 | * @throws CmisInvalidArgumentException If given value is not a string |
||
426 | */ |
||
427 | 10 | public function setStringLike($parameterIndex, $string) |
|
428 | { |
||
429 | 10 | if (!is_string($string)) { |
|
430 | 1 | throw new CmisInvalidArgumentException('Parameter string must be of type string!'); |
|
431 | } |
||
432 | |||
433 | 9 | $this->setParameter($parameterIndex, $this->escapeLike($string)); |
|
434 | 8 | } |
|
435 | |||
436 | /** |
||
437 | * Sets the designated parameter to the query name of the given type. |
||
438 | * |
||
439 | * @param integer $parameterIndex the parameter index (one-based) |
||
440 | * @param ObjectTypeInterface $type the object type |
||
441 | */ |
||
442 | 3 | public function setType($parameterIndex, ObjectTypeInterface $type) |
|
443 | { |
||
444 | 3 | $this->setParameter($parameterIndex, $this->escape($type->getQueryName())); |
|
445 | 2 | } |
|
446 | |||
447 | /** |
||
448 | * Sets the designated parameter to the given value |
||
449 | * |
||
450 | * @param integer $parameterIndex |
||
451 | * @param mixed $value |
||
452 | * @throws CmisInvalidArgumentException If parameter index is not of type integer |
||
453 | */ |
||
454 | 49 | protected function setParameter($parameterIndex, $value) |
|
455 | { |
||
456 | 49 | if (!is_int($parameterIndex)) { |
|
457 | 10 | throw new CmisInvalidArgumentException('Parameter index must be of type integer!'); |
|
458 | } |
||
459 | |||
460 | 39 | $this->parametersMap[$parameterIndex] = $value; |
|
461 | 39 | } |
|
462 | |||
463 | /** |
||
464 | * Returns the query statement. |
||
465 | * |
||
466 | * @return string the query statement, not null |
||
467 | */ |
||
468 | 4 | public function toQueryString() |
|
469 | { |
||
470 | 4 | $queryString = ''; |
|
471 | 4 | $inString = false; |
|
472 | 4 | $parameterIndex = 0; |
|
473 | 4 | $length = strlen($this->statement); |
|
474 | |||
475 | 4 | for ($i=0; $i < $length; $i++) { |
|
476 | 4 | $char = $this->statement{$i}; |
|
477 | 4 | if ($char === '\'') { |
|
478 | 1 | if ($inString && $this->statement{max(0, $i-1)} === '\\') { |
|
479 | 1 | $inString = true; |
|
480 | 1 | } else { |
|
481 | 1 | $inString = !$inString; |
|
482 | } |
||
483 | 1 | $queryString .= $char; |
|
484 | 4 | } elseif ($char === '?' && !$inString) { |
|
485 | 3 | $parameterIndex ++; |
|
486 | 3 | $queryString .= $this->parametersMap[$parameterIndex]; |
|
487 | 3 | } else { |
|
488 | 4 | $queryString .= $char; |
|
489 | } |
||
490 | 4 | } |
|
491 | |||
492 | 4 | return $queryString; |
|
493 | } |
||
494 | |||
495 | /** |
||
496 | * Escapes string for query |
||
497 | * |
||
498 | * @param $string |
||
499 | * @return string |
||
500 | */ |
||
501 | 29 | protected function escape($string) |
|
502 | { |
||
503 | 29 | return "'" . addcslashes($string, '\'\\') . "'"; |
|
504 | } |
||
505 | |||
506 | /** |
||
507 | * Escapes string, but not escapes backslashes ('\') in front of '%' and '_'. |
||
508 | * |
||
509 | * @param $string |
||
510 | * @return string |
||
511 | */ |
||
512 | 19 | View Code Duplication | protected function escapeLike($string) |
0 ignored issues
–
show
|
|||
513 | { |
||
514 | 19 | $escapedString = addcslashes($string, '\'\\'); |
|
515 | $replace = [ |
||
516 | 19 | '\\\\%' => '\\%', |
|
517 | 19 | '\\\\_' => '\\_', |
|
518 | 19 | ]; |
|
519 | 19 | $escapedString = str_replace(array_keys($replace), array_values($replace), $escapedString); |
|
520 | 19 | return "'" . $escapedString . "'"; |
|
521 | } |
||
522 | |||
523 | /** |
||
524 | * Escapes string, but not escapes backslashes ('\') in front of '*' and '?'. |
||
525 | * |
||
526 | * @param $string |
||
527 | * @return string |
||
528 | */ |
||
529 | 20 | View Code Duplication | protected function escapeContains($string) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
530 | { |
||
531 | 20 | $escapedString = addcslashes($string, '"\'\\'); |
|
532 | $replace = [ |
||
533 | 20 | '\\\\*' => '\*', |
|
534 | 20 | '\\\\?' => '\?', |
|
535 | 20 | ]; |
|
536 | 20 | $escapedString = str_replace(array_keys($replace), array_values($replace), $escapedString); |
|
537 | 20 | return "'" . $escapedString . "'"; |
|
538 | } |
||
539 | } |
||
540 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.