Skip to content

Commit 285d65d

Browse files
authored
Merge pull request #11 from kettasoft/refactor/engines-clause-refactor
Refactor Engines to rely on ClauseFactory/Clause
2 parents 973b3dd + 38cf501 commit 285d65d

File tree

10 files changed

+253
-130
lines changed

10 files changed

+253
-130
lines changed

config/filterable.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,16 @@
214214
*/
215215
'strict' => true,
216216

217+
/*
218+
|--------------------------------------------------------------------------
219+
| Egnore empty values
220+
|--------------------------------------------------------------------------
221+
|
222+
| If 'true' filters with null or empty string values will be ignored.
223+
|
224+
*/
225+
'ignore_empty_values' => false,
226+
217227
/*
218228
|--------------------------------------------------------------------------
219229
| Allowed Fields

src/Engines/Expression.php

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@
22

33
namespace Kettasoft\Filterable\Engines;
44

5+
use Kettasoft\Filterable\Support\Payload;
56
use Kettasoft\Filterable\Traits\FieldNormalizer;
67
use Illuminate\Contracts\Database\Eloquent\Builder;
78
use Kettasoft\Filterable\Engines\Foundation\Clause;
89
use Kettasoft\Filterable\Engines\Foundation\Engine;
910
use Kettasoft\Filterable\Support\ConditionNormalizer;
1011
use Kettasoft\Filterable\Support\ValidateTableColumns;
1112
use Kettasoft\Filterable\Engines\Foundation\ClauseApplier;
13+
use Kettasoft\Filterable\Engines\Foundation\ClauseFactory;
1214
use Kettasoft\Filterable\Engines\Foundation\Enums\Operators;
1315
use Kettasoft\Filterable\Engines\Foundation\Appliers\Applier;
1416
use Kettasoft\Filterable\Exceptions\InvalidOperatorException;
1517
use Kettasoft\Filterable\Exceptions\NotAllowedFieldException;
18+
use Kettasoft\Filterable\Engines\Foundation\Parsers\Dissector;
1619

1720
class Expression extends Engine
1821
{
@@ -36,20 +39,16 @@ public function execute(Builder $builder)
3639
// Normalize the condition to [ operator => value ].
3740
$condition = ConditionNormalizer::normalize($condition, $this->defaultOperator());
3841

39-
$clause = Clause::make($this->getResources(), $field, $condition)->strict($this->isStrict());
42+
$dissector = Dissector::parse($condition, $this->defaultOperator());
4043

41-
if (! $clause->isAllowedField() && ! $clause->isRelational()) {
42-
if ($this->isStrict()) {
43-
throw new NotAllowedFieldException($field);
44-
}
44+
$clause = (new ClauseFactory($this))->make(
45+
new Payload($field, $dissector->operator, $dissector->value, null)
46+
);
4547

48+
if (! $clause->validated) {
4649
continue; // skip disallowed field
4750
}
4851

49-
if ($clause->isEmptyValue() && config('filterable.engines.expression.egnore_empty_values', false)) {
50-
continue;
51-
}
52-
5352
return Applier::apply(new ClauseApplier($clause), $builder);
5453
}
5554

@@ -94,6 +93,11 @@ public function defaultOperator(): string
9493
return config('filterable.engines.expression.default_operator', 'eq');
9594
}
9695

96+
public function isIgnoredEmptyValuesFromConfig(): bool
97+
{
98+
return config('filterable.engines.expression.ignore_empty_values', false);
99+
}
100+
97101
/**
98102
* Get engine name.
99103
* @return string

src/Engines/Foundation/Clause.php

Lines changed: 22 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,11 @@
66
use Illuminate\Database\Eloquent\Builder;
77
use Illuminate\Contracts\Support\Jsonable;
88
use Illuminate\Contracts\Support\Arrayable;
9-
use Kettasoft\Filterable\Foundation\Resources;
10-
use Kettasoft\Filterable\Engines\Foundation\Mapper;
11-
use Kettasoft\Filterable\Support\ValidateTableColumns;
129
use Kettasoft\Filterable\Engines\Foundation\Parsers\Dissector;
13-
use Kettasoft\Filterable\Engines\Foundation\Mappers\OperatorMapper;
1410
use Kettasoft\Filterable\Engines\Foundation\Resolvers\RelationResolver;
1511

1612
class Clause implements Arrayable, Jsonable
1713
{
18-
/**
19-
* Current registered engine.
20-
* @var Resources
21-
*/
22-
public Resources $resources;
2314

2415
/**
2516
* Original field.
@@ -40,43 +31,33 @@ class Clause implements Arrayable, Jsonable
4031
public readonly string|null $value;
4132

4233
/**
43-
* Dissector instance.
44-
* @var Dissector
45-
*/
46-
public readonly Dissector $dissector;
47-
48-
/**
49-
* Strict mode.
34+
* Check if the clause is validated.
5035
* @var bool
5136
*/
52-
protected bool $strict = false;
37+
public bool $validated = false;
5338

5439
/**
5540
* Clause constructor.
5641
* @param \Kettasoft\Filterable\Foundation\Resources $resources
5742
* @param mixed $field
5843
* @param mixed $dissector
5944
*/
60-
public function __construct(Resources $resources, $field, $dissector)
45+
public function __construct($field, $operator, $value)
6146
{
62-
$this->resources = $resources;
6347
$this->field = $field;
64-
$this->dissector = Dissector::parse($dissector, 'eq');
65-
66-
$this->operator = $this->dissector->operator;
67-
$this->value = $this->dissector->value;
48+
$this->operator = $operator;
49+
$this->value = $value;
6850
}
6951

7052
/**
7153
* Create Dissector instance.
72-
* @param \Kettasoft\Filterable\Foundation\Resources $resources
7354
* @param mixed $field
7455
* @param mixed $dissector
7556
* @return Clause
7657
*/
77-
public static function make(Resources $resources, $field, $dissector)
58+
public static function make($field, $operator, $value)
7859
{
79-
return new self($resources, $field, $dissector);
60+
return new self($field, $operator, $value);
8061
}
8162

8263
/**
@@ -87,9 +68,10 @@ public function isRelational(): bool
8768
return is_string($this->field) && str_contains($this->field, '.');
8869
}
8970

90-
public function isEmptyValue(): bool
71+
public function setStatus(bool $status)
9172
{
92-
return empty($this->value) || is_null($this->value);
73+
$this->validated = $status;
74+
return $this;
9375
}
9476

9577
/**
@@ -105,73 +87,22 @@ public function getOriginalField()
10587
*/
10688
public function getValue()
10789
{
108-
$sanitizers = $this->resources->sanitizers;
109-
110-
$value = $this->getOriginalValue();
111-
112-
if (count($sanitizers)) {
113-
foreach ($sanitizers as $sanitizer) {
114-
$value = $sanitizer->handle($this->getOriginalField(), $value);
115-
}
116-
}
117-
118-
return $value;
90+
return $this->value;
11991
}
12092

121-
/**
122-
* @inheritDoc
123-
*/
124-
public function getOriginalValue()
93+
public function relation($bag)
12594
{
126-
return $this->dissector->value;
95+
$instance = new RelationResolver($bag, $this->field);
96+
return $instance;
12797
}
12898

129-
/**
130-
* @inheritDoc
131-
*/
132-
public function getOperator()
99+
public function apply(Builder $builder)
133100
{
134-
$instance = $this->resources->operators;
135-
136-
return Mapper::run(
137-
OperatorMapper::init($instance, $this->strict),
138-
$this->operator
101+
return $builder->where(
102+
$this->field,
103+
$this->operator,
104+
$this->value
139105
);
140-
// return $instance->get($this->operator, $instance->get($instance->default));
141-
}
142-
143-
/**
144-
* @inheritDoc
145-
*/
146-
public function getDatabaseColumnName()
147-
{
148-
return $this->resources->fieldMap->get($this->field, $this->field);
149-
}
150-
151-
/**
152-
* Check if the field is allowed.
153-
* @return bool
154-
*/
155-
public function isAllowedField(): bool
156-
{
157-
return $this->resources->fields->has($this->field);
158-
}
159-
160-
public function validateTableColumn()
161-
{
162-
// return ValidateTableColumns::validate($this->engine->getContext()->getBuilder(), $this->getDatabaseColumnName());
163-
}
164-
165-
public function strict($enable = true): self
166-
{
167-
$this->strict = $enable;
168-
return $this;
169-
}
170-
171-
public function relation($bag)
172-
{
173-
$instance = new RelationResolver($bag, $this->field);
174-
return $instance;
175106
}
176107

177108
/**
@@ -180,9 +111,9 @@ public function relation($bag)
180111
public function toArray(): array
181112
{
182113
return [
183-
'field' => $this->getDatabaseColumnName(),
184-
'operator' => $this->getOperator(),
185-
'value' => $this->getValue()
114+
'field' => $this->field,
115+
'operator' => $this->operator,
116+
'value' => $this->value
186117
];
187118
}
188119

src/Engines/Foundation/ClauseApplier.php

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ public function __construct(protected Clause $clause) {}
2020
*/
2121
public function apply(Builder $builder): Builder
2222
{
23-
if (! $this->clause->isAllowedField() && ! $this->clause->isRelational()) {
24-
return $builder;
25-
}
23+
// if ($this->clause->isRelational()) {
24+
// return $builder;
25+
// }
2626

2727
if ($this->clause->isRelational()) {
2828
return $this->applyRelational($builder);
@@ -38,11 +38,7 @@ public function apply(Builder $builder): Builder
3838
*/
3939
protected function applyDirect(Builder $builder)
4040
{
41-
return $builder->where(
42-
$this->clause->getDatabaseColumnName(),
43-
$this->clause->getOperator(),
44-
$this->clause->getValue()
45-
);
41+
return $builder->where($this->clause->field, $this->clause->operator, $this->clause->value);
4642
}
4743

4844
/**
@@ -52,9 +48,10 @@ protected function applyDirect(Builder $builder)
5248
*/
5349
protected function applyRelational(Builder $builder)
5450
{
55-
return $this->clause->relation($this->clause->resources->relations)->resolve(
56-
$builder,
57-
$this->clause
58-
);
51+
[$relation, $field] = explode('.', $this->clause->field, 2);
52+
53+
return $builder->whereHas($relation, function ($query) use ($field) {
54+
$query->where($field, $this->clause->operator, $this->clause->value);
55+
});
5956
}
6057
}

0 commit comments

Comments
 (0)