-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathSearchParser.php
132 lines (110 loc) · 3.67 KB
/
SearchParser.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<?php
declare(strict_types=1);
namespace Asseco\JsonQueryBuilder;
use Asseco\JsonQueryBuilder\Config\ModelConfig;
use Asseco\JsonQueryBuilder\Config\OperatorsConfig;
use Asseco\JsonQueryBuilder\Exceptions\JsonQueryBuilderException;
use Asseco\JsonQueryBuilder\Traits\CleansValues;
use Illuminate\Support\Facades\Config;
class SearchParser implements SearchParserInterface
{
use CleansValues;
/**
* Constant by which values will be split within a single parameter. E.g. parameter=value1;value2.
*/
const VALUE_SEPARATOR = ';';
public string $column;
public array $values;
public string $type;
public string $operator;
private string $argument;
private ModelConfig $modelConfig;
/**
* Search constructor.
*
* @param ModelConfig $modelConfig
* @param OperatorsConfig $operatorsConfig
* @param string $column
* @param string $argument
*
* @throws JsonQueryBuilderException
*/
public function __construct(ModelConfig $modelConfig, OperatorsConfig $operatorsConfig, string $column, string $argument)
{
$this->modelConfig = $modelConfig;
$this->column = $column;
$this->argument = $argument;
$this->checkForForbiddenColumns();
$this->operator = $this->parseOperator($operatorsConfig->getOperators(), $argument);
$arguments = str_replace($this->operator, '', $this->argument);
$this->values = $this->splitValues($arguments);
$this->type = $this->getColumnType();
}
/**
* @param $operators
* @param string $argument
* @return string
*
* @throws JsonQueryBuilderException
*/
protected function parseOperator($operators, string $argument): string
{
foreach ($operators as $operator) {
$argumentHasOperator = strpos($argument, $operator) !== false;
if (!$argumentHasOperator) {
continue;
}
return $operator;
}
throw new JsonQueryBuilderException("No valid callback registered for $argument. Are you missing an operator?");
}
/**
* Split values by a given separator.
*
* Input: val1;val2
*
* Output: val1
* val2
*
* @param string $values
* @return array
*
* @throws JsonQueryBuilderException
*/
protected function splitValues(string $values): array
{
$valueArray = explode(self::VALUE_SEPARATOR, $values);
$cleanedUpValues = $this->cleanValues($valueArray);
if (count($cleanedUpValues) < 1) {
throw new JsonQueryBuilderException("Column '$this->column' is missing a value.");
}
return $cleanedUpValues;
}
/**
* @return string
*
* @throws JsonQueryBuilderException
*/
protected function getColumnType(): string
{
$columns = $this->modelConfig->getModelColumns();
if (!array_key_exists($this->column, $columns)) {
// TODO: integrate recursive column check for related models?
return 'generic';
}
return $columns[$this->column];
}
/**
* Check if global forbidden key is used.
*
* @throws JsonQueryBuilderException
*/
protected function checkForForbiddenColumns()
{
$forbiddenKeys = Config::get('asseco-json-query-builder.global_forbidden_columns');
$forbiddenKeys = $this->modelConfig->getForbidden($forbiddenKeys);
if (in_array($this->column, $forbiddenKeys)) {
throw new JsonQueryBuilderException("Searching by '$this->column' field is forbidden. Check the configuration if this is not a desirable behavior.");
}
}
}