refactoring of filters
This commit is contained in:
@@ -12,7 +12,6 @@
|
||||
export let inModal;
|
||||
export let modalUrl;
|
||||
export let graph;
|
||||
|
||||
let filter = {
|
||||
label: "",
|
||||
operator: "",
|
||||
@@ -58,9 +57,11 @@
|
||||
const filterRecord = extractFilterRecord(graph, value);
|
||||
|
||||
function extractFilterRecord(graph, value) {
|
||||
|
||||
if (!filter.isReference) {
|
||||
return null;
|
||||
}
|
||||
console.log(graph)
|
||||
return graph.records.find(r => r.id === value);
|
||||
}
|
||||
|
||||
@@ -82,7 +83,7 @@
|
||||
{#if filter.isReference && filterRecord}
|
||||
{filter.label} is {previewTitle(channel.schemas, filterRecord)}
|
||||
{:else}
|
||||
{filter.label} {operators.find((o) => o.name === filter.operator)?.symbol ?? ""} {value}
|
||||
{filter.label} {operators.find((o) => o.name === filter.operator)?.symbol ?? ""} {operators.find((o) => o.name === filter.operator)?.hasValue ? value : ""}
|
||||
{/if}
|
||||
|
||||
<button
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
export let inModal;
|
||||
export let modalUrl;
|
||||
|
||||
|
||||
let dropdown;
|
||||
let search = "";
|
||||
let systemFieldsFiltered = systemFields;
|
||||
@@ -70,6 +69,13 @@
|
||||
activeOperator = operators.find(o => o.name === "eq")
|
||||
}
|
||||
|
||||
function selectOperator(e, operator) {
|
||||
activeOperator = operator;
|
||||
if (!operator.hasValue) {
|
||||
applyFilter(e)
|
||||
}
|
||||
}
|
||||
|
||||
function applyFilter(e) {
|
||||
e.preventDefault();
|
||||
let filterPrefix = "";
|
||||
@@ -146,7 +152,7 @@
|
||||
<div class="selected-filter">field: {activeField.label}</div>
|
||||
|
||||
{#each activeOperators as operator}
|
||||
<button class="dropdown-item button" on:click={e => activeOperator = operator }>
|
||||
<button class="dropdown-item button" on:click={e => selectOperator(e,operator)}>
|
||||
{operator.label}
|
||||
</button>
|
||||
{/each}
|
||||
@@ -214,8 +220,8 @@
|
||||
required
|
||||
/>
|
||||
|
||||
<button class="button applied-filter">
|
||||
Submit
|
||||
<button class="button applied-filter">
|
||||
Submit
|
||||
</button>
|
||||
|
||||
</form>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<h2 class="mb-5">Enter Lucent</h2>
|
||||
|
||||
<form hx-post="/lucent/login" >
|
||||
@csrf
|
||||
<p>Submit your email address and you will receive a <b>login link</b> to your email</p>
|
||||
<p>Don't forget to check your spam folder</p>
|
||||
<div class="mt-5 mb-3">
|
||||
|
||||
@@ -8,7 +8,7 @@ use Lucent\Account\AccountService;
|
||||
use Lucent\Account\AuthService;
|
||||
use Lucent\Channel\ChannelService;
|
||||
use Lucent\LucentException;
|
||||
use Lucent\Query\Operator;
|
||||
use Lucent\Query\Operator\OperatorRegistry;
|
||||
use Lucent\Query\Query;
|
||||
use Lucent\Record\InputData\EdgeInputData;
|
||||
use Lucent\Record\InputData\RecordInputData;
|
||||
@@ -25,13 +25,14 @@ use function Lucent\Response\ok;
|
||||
class RecordController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly RecordService $recordService,
|
||||
private readonly AccountService $accountService,
|
||||
private readonly AuthService $authService,
|
||||
private readonly ChannelService $channelService,
|
||||
private readonly Svelte $svelte,
|
||||
private readonly Query $query,
|
||||
private readonly Manager $recordManager
|
||||
private readonly RecordService $recordService,
|
||||
private readonly AccountService $accountService,
|
||||
private readonly AuthService $authService,
|
||||
private readonly ChannelService $channelService,
|
||||
private readonly Svelte $svelte,
|
||||
private readonly Query $query,
|
||||
private readonly Manager $recordManager,
|
||||
private readonly OperatorRegistry $operatorRegistry
|
||||
)
|
||||
{
|
||||
}
|
||||
@@ -79,7 +80,6 @@ class RecordController extends Controller
|
||||
|
||||
$records = $graph->getRootRecords()->toArray();
|
||||
|
||||
|
||||
$data = [
|
||||
"schemas" => $this->channelService->channel->schemas,
|
||||
"schema" => $schema,
|
||||
@@ -87,7 +87,7 @@ class RecordController extends Controller
|
||||
"records" => $records,
|
||||
"graph" => toArray($graph),
|
||||
"systemFields" => array_values(System::list()),
|
||||
"operators" => array_values(Operator::list()),
|
||||
"operators" => $this->operatorRegistry->all(),
|
||||
"sortParam" => $sort,
|
||||
"sortField" => $schema->fields->merge(array_values(System::list()))->firstWhere(fn($field) => $field->name === $sort || "-" . $field->name === $sort || "data." . $field->name === $sort || "-data." . $field->name === $sort),
|
||||
"limit" => $limit,
|
||||
@@ -302,7 +302,7 @@ class RecordController extends Controller
|
||||
id: $request->input("record.id"),
|
||||
data: $request->input("record.data"),
|
||||
status: Status::from($request->input("record.status")),
|
||||
edges: array_map(EdgeInputData::fromArray(...), $request->input("edges") ?? []),
|
||||
edges: array_map(EdgeInputData::fromArray(...), $request->input("edges") ?? []),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
class BuilderConverter
|
||||
{
|
||||
public function for(Argument $argument): IBuilderConverter
|
||||
{
|
||||
return new ($argument->operator->converter)($argument);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class Equals implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->where($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): string
|
||||
{
|
||||
return trim($this->argument->value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class EqualsFalse implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->where($this->argument->field, false);
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere($this->argument->field, false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class EqualsNumber implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
|
||||
return $builder->where($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): int|float
|
||||
{
|
||||
$value = trim($this->argument->value);
|
||||
return str_contains($value, ".") ? floatval($value) : intval($value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class EqualsTrue implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->where($this->argument->field, true);
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere($this->argument->field, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class Exists implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNot($this->argument->field, "")->whereNotNull($this->argument->field);
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNot($this->argument->field, "")->whereNotNull($this->argument->field);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class Filter implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereJsonContains($this->argument->field, [$this->argument->value]);
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereJsonContains($this->argument->field, [$this->argument->value]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class GreaterThan implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
|
||||
return $builder->where($this->argument->field, ">", $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere($this->argument->field, ">", $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): int|float
|
||||
{
|
||||
$value = trim($this->argument->value);
|
||||
if (is_numeric($value)) {
|
||||
return str_contains($value, ".") ? floatval($value) : intval($value);
|
||||
}
|
||||
return $value;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class GreaterThanEquals implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
|
||||
return $builder->where($this->argument->field, ">=", $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere($this->argument->field, ">=", $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): int|float
|
||||
{
|
||||
$value = trim($this->argument->value);
|
||||
if (is_numeric($value)) {
|
||||
return str_contains($value, ".") ? floatval($value) : intval($value);
|
||||
}
|
||||
return $value;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
interface IBuilderConverter
|
||||
{
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder;
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class In implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereIn($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereIn($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): array
|
||||
{
|
||||
$value = $this->argument->value;
|
||||
if (is_string($value)) {
|
||||
$value = explode(",", $value);
|
||||
}
|
||||
return array_map(fn($v) => trim($v), $value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class InNum implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereIn($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereIn($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): array
|
||||
{
|
||||
$value = $this->argument->value;
|
||||
if (is_string($value)) {
|
||||
$value = explode(",", $value);
|
||||
}
|
||||
return array_map(fn($v) => $this->formatNumber($v), $value);
|
||||
}
|
||||
|
||||
private function formatNumber(string $value): float|int
|
||||
{
|
||||
$value = trim($value);
|
||||
return str_contains($value, ".") ? floatval($value) : intval($value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class IsNull implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNull($this->argument->field);
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereNull($this->argument->field);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class LessThan implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
|
||||
return $builder->where($this->argument->field, "<", $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere($this->argument->field, "<", $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): int|float
|
||||
{
|
||||
$value = trim($this->argument->value);
|
||||
if (is_numeric($value)) {
|
||||
return str_contains($value, ".") ? floatval($value) : intval($value);
|
||||
}
|
||||
return $value;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class LessThanEquals implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
|
||||
return $builder->where($this->argument->field, "<=", $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere($this->argument->field, "<=", $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): int|float
|
||||
{
|
||||
$value = trim($this->argument->value);
|
||||
if (is_numeric($value)) {
|
||||
return str_contains($value, ".") ? floatval($value) : intval($value);
|
||||
}
|
||||
return $value;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class NotEquals implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNot($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereNot($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): string
|
||||
{
|
||||
return trim($this->argument->value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class NotEqualsFalse implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNot($this->argument->field, false);
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereNot($this->argument->field, false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class NotEqualsNumber implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNot($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereNot($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): int|float
|
||||
{
|
||||
$value = trim($this->argument->value);
|
||||
return str_contains($value, ".") ? floatval($value) : intval($value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class NotEqualsTrue implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNot($this->argument->field, true);
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereNot($this->argument->field, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class NotExists implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->where(fn($b) => $b->where($this->argument->field, "")->orWhereNull($this->argument->field));
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere(fn($b) => $b->where($this->argument->field, "")->orWhereNull($this->argument->field));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class NotIn implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNotIn($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereNotIn($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): array
|
||||
{
|
||||
$value = $this->argument->value;
|
||||
if (is_string($value)) {
|
||||
$value = explode(",", $value);
|
||||
}
|
||||
return array_map(fn($v) => trim($v), $value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class NotInNum implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNotIn($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereNotIn($this->argument->field, $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): array
|
||||
{
|
||||
$value = $this->argument->value;
|
||||
if (is_string($value)) {
|
||||
$value = explode(",", $value);
|
||||
}
|
||||
return array_map(fn($v) => $this->formatNumber($v), $value);
|
||||
}
|
||||
|
||||
private function formatNumber(string $value): float|int
|
||||
{
|
||||
$value = trim($value);
|
||||
return str_contains($value, ".") ? floatval($value) : intval($value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class NotNull implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->whereNotNull($this->argument->field);
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhereNotNull($this->argument->field);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\BuilderConverter;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
readonly class Regex implements IBuilderConverter
|
||||
{
|
||||
|
||||
public function __construct(private Argument $argument)
|
||||
{
|
||||
}
|
||||
|
||||
public function toAndQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
|
||||
return $builder->where($this->argument->field, "like", $this->formatValue());
|
||||
}
|
||||
|
||||
public function toOrQueryBuilder(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orWhere($this->argument->field, "like", $this->formatValue());
|
||||
}
|
||||
|
||||
private function formatValue(): string
|
||||
{
|
||||
return "%" . strtolower(trim($this->argument->value)) . "%";
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,15 @@
|
||||
|
||||
namespace Lucent\Query\Filter;
|
||||
|
||||
use Lucent\Query\Operator\Operator;
|
||||
|
||||
class Argument
|
||||
{
|
||||
public function __construct(
|
||||
public string $field,
|
||||
public string $operator,
|
||||
public mixed $value,
|
||||
){}
|
||||
public string $field,
|
||||
public Operator $operator,
|
||||
public mixed $value,
|
||||
)
|
||||
{
|
||||
}
|
||||
}
|
||||
+16
-139
@@ -5,19 +5,26 @@ namespace Lucent\Query;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Lucent\Query\BuilderConverter\BuilderConverter;
|
||||
use Lucent\Query\Filter\AndFilter;
|
||||
use Lucent\Query\Filter\Argument;
|
||||
use Lucent\Query\Filter\Filter;
|
||||
use Lucent\Query\Filter\OrFilter;
|
||||
use Lucent\Query\Operator\In;
|
||||
use Lucent\Query\Operator\OperatorDetector;
|
||||
use function explode;
|
||||
|
||||
final class FilterParser
|
||||
{
|
||||
|
||||
public function __construct(public Application $app)
|
||||
public function __construct(
|
||||
public Application $app,
|
||||
public BuilderConverter $builderConverter,
|
||||
public OperatorDetector $operatorDetector,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @return array<Argument>
|
||||
@@ -25,105 +32,11 @@ final class FilterParser
|
||||
private function formatArguments(array $arguments): array
|
||||
{
|
||||
return collect($arguments)->reduce(function ($c, $v, $k) {
|
||||
$c[] = $this->formatArgument($v, $k);
|
||||
$c[] = $this->operatorDetector->detect($v, $k);
|
||||
return $c;
|
||||
}, []);
|
||||
}
|
||||
|
||||
private function formatArgument(mixed $value, string $filter): Argument
|
||||
{
|
||||
|
||||
$operator = $this->detectOperator($filter);
|
||||
|
||||
$field = $this->detectField($filter, $operator);
|
||||
$formattedValue = match ($operator) {
|
||||
"eq" => $this->formatText($value),
|
||||
"ne" => $this->formatText($value),
|
||||
"eqnum" => $this->formatNumber($value),
|
||||
"nenum" => $this->formatNumber($value),
|
||||
"object" => $this->formatText($value),
|
||||
"in" => $this->formatListString($value),
|
||||
"nin" => $this->formatListString($value),
|
||||
"innum" => $this->formatListNum($value),
|
||||
"ninnum" => $this->formatListNum($value),
|
||||
"eqtrue" => true,
|
||||
"eqfalse" => false,
|
||||
"netrue" => true,
|
||||
"nefalse" => false,
|
||||
"regex" => "%" . strtolower($value) . "%",
|
||||
"gt" => is_numeric($value) ? floatval($value) : $value,
|
||||
"gte" => is_numeric($value) ? floatval($value) : $value,
|
||||
"lt" => is_numeric($value) ? floatval($value) : $value,
|
||||
"lte" => is_numeric($value) ? floatval($value) : $value,
|
||||
"null" => null,
|
||||
"nnull" => null,
|
||||
"exists" => true,
|
||||
"nexists" => false,
|
||||
default => $value,
|
||||
};
|
||||
|
||||
$matchedOperator = Operator::list()[$operator];
|
||||
return new Argument(
|
||||
field: str_replace(".", "->", $field),
|
||||
operator: $matchedOperator->db,
|
||||
value: $formattedValue
|
||||
);
|
||||
}
|
||||
|
||||
private function formatText(string $value): string
|
||||
{
|
||||
return trim($value);
|
||||
}
|
||||
|
||||
private function formatNumber(string $value): float
|
||||
{
|
||||
return floatval($value);
|
||||
}
|
||||
|
||||
|
||||
private function formatListString(mixed $value): array
|
||||
{
|
||||
if (is_string($value)) {
|
||||
$value = explode(",", $value);
|
||||
}
|
||||
|
||||
return array_map(fn($v) => $this->formatText($v), $value);
|
||||
}
|
||||
|
||||
private function formatListNum(mixed $value): array
|
||||
{
|
||||
if (\is_string($value)) {
|
||||
$value = explode(",", $value);
|
||||
}
|
||||
|
||||
return \array_map(fn($v) => $this->formatNumber($v), $value);
|
||||
}
|
||||
|
||||
|
||||
private function detectOperator(string $filter): string
|
||||
{
|
||||
$exploded = \explode("_", $filter);
|
||||
$candidate = end($exploded);
|
||||
$operatorsListNames = collect(Operator::list())->map(fn($o) => $o->name)->toArray();
|
||||
|
||||
if (\in_array($candidate, $operatorsListNames)) {
|
||||
return $candidate;
|
||||
}
|
||||
return 'eq';
|
||||
}
|
||||
|
||||
private function detectField(string $filter, string $operator): string
|
||||
{
|
||||
|
||||
$exploded = explode("_", $filter);
|
||||
$candidate = array_pop($exploded);
|
||||
if ($candidate === $operator) {
|
||||
return implode("_", $exploded);
|
||||
}
|
||||
return $filter;
|
||||
}
|
||||
|
||||
|
||||
private function formatReferences(array $referenceArguments): Argument
|
||||
{
|
||||
$subqueries = collect($referenceArguments)->reduce(function ($c, $v, $k) {
|
||||
@@ -151,7 +64,7 @@ final class FilterParser
|
||||
|
||||
return new Argument(
|
||||
field: "id",
|
||||
operator: "in",
|
||||
operator: In::make(),
|
||||
value: $sourceIds
|
||||
);
|
||||
|
||||
@@ -174,7 +87,6 @@ final class FilterParser
|
||||
private function parseArguments(Filter $arguments): array
|
||||
{
|
||||
[$normalArguments, $referenceArguments] = $this->separateMainFromReferenceArguments($arguments);
|
||||
|
||||
$formattedArguments = $this->formatArguments($normalArguments);
|
||||
if (!empty($referenceArguments)) {
|
||||
$formattedArguments[] = $this->formatReferences($referenceArguments);
|
||||
@@ -198,26 +110,8 @@ final class FilterParser
|
||||
*/
|
||||
private function parseAnd(Builder $builder, array $arguments): Builder
|
||||
{
|
||||
foreach ($arguments as $argument) {
|
||||
if ($argument->operator == "in") {
|
||||
$builder->whereIn($argument->field, $argument->value);
|
||||
} else if ($argument->operator == "nin") {
|
||||
$builder->whereNotIn($argument->field, $argument->value);
|
||||
} else if ($argument->operator == "exists") {
|
||||
$builder->where($argument->field, "!=", "");
|
||||
$builder->where($argument->field, "!=", null);
|
||||
} elseif ($argument->operator == "filter") {
|
||||
$builder->whereJsonContains($argument->field, [$argument->value]);
|
||||
// target result
|
||||
// filter[data.previousNames_object]=previousNames&filter[previousNames.name_eq]=alpha&filter[previousNames.id_eqnum]=24
|
||||
// $query->whereJsonContains("data->previousNames", [["name" => "alpha", "id" => 24]]);
|
||||
// $query->whereJsonContains($filter["field"], [$objectFilters]);
|
||||
} else {
|
||||
$builder->where($argument->field, $argument->operator, $argument->value);
|
||||
}
|
||||
}
|
||||
|
||||
return $builder;
|
||||
return collect($arguments)
|
||||
->reduce(fn($cBuilder, Argument $arg) => $this->builderConverter->for($arg)->toAndQueryBuilder($cBuilder), $builder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,27 +119,10 @@ final class FilterParser
|
||||
*/
|
||||
private function parseOr(Builder $builder, array $arguments): Builder
|
||||
{
|
||||
$builder->where(function (Builder $orBuilder) use ($arguments) {
|
||||
foreach ($arguments as $argument) {
|
||||
if ($argument->operator == "in") {
|
||||
$orBuilder->orWhereIn($argument->field, $argument->value);
|
||||
} else if ($argument->operator == "nin") {
|
||||
$orBuilder->orWhereNotIn($argument->field, $argument->value);
|
||||
} else if ($argument->operator == "exists") {
|
||||
$orBuilder->where($argument->field, "!=", "");
|
||||
$orBuilder->where($argument->field, "!=", null);
|
||||
} elseif ($argument->operator == "filter") {
|
||||
$orBuilder->whereJsonContains($argument->field, [$argument->value]);
|
||||
// target result
|
||||
// filter[data.previousNames_object]=previousNames&filter[previousNames.name_eq]=alpha&filter[previousNames.id_eqnum]=24
|
||||
// $query->whereJsonContains("data->previousNames", [["name" => "alpha", "id" => 24]]);
|
||||
// $query->whereJsonContains($filter["field"], [$objectFilters]);
|
||||
} else {
|
||||
$orBuilder->orWhere($argument->field, $argument->operator, $argument->value);
|
||||
}
|
||||
}
|
||||
return $builder->where(function (Builder $orBuilder) use ($arguments) {
|
||||
return collect($arguments)
|
||||
->reduce(fn($cBuilder, Argument $arg) => $this->builderConverter->for($arg)->toOrQueryBuilder($cBuilder), $orBuilder);
|
||||
});
|
||||
return $builder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query;
|
||||
|
||||
|
||||
final class Operator
|
||||
{
|
||||
/**
|
||||
* @psalm-param string[] $uis
|
||||
*/
|
||||
public function __construct(
|
||||
public string $name,
|
||||
public string $label,
|
||||
public string $symbol,
|
||||
public string $db,
|
||||
public array $uis,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, Operator>
|
||||
*/
|
||||
public static function list(): array
|
||||
{
|
||||
|
||||
return [
|
||||
"regex" => new Operator(
|
||||
name: "regex",
|
||||
label: "Search",
|
||||
symbol: "~",
|
||||
db: 'like',
|
||||
uis: ["id", "text", "textarea", "url", "color", "date", "datetime"],
|
||||
),
|
||||
"eq" => new Operator(
|
||||
name: "eq",
|
||||
label: "Equals",
|
||||
symbol: "is",
|
||||
db: '=',
|
||||
uis: ["id", "text", "textarea", "url", "color", "date", "datetime", "reference"],
|
||||
),
|
||||
"ne" => new Operator(
|
||||
name: "ne",
|
||||
label: "Not Equals",
|
||||
symbol: "is not",
|
||||
db: '!=',
|
||||
uis: ["id", "text", "textarea", "url", "color", "date", "datetime"],
|
||||
),
|
||||
"eqnum" => new Operator(
|
||||
name: "eqnum",
|
||||
label: "Equals number",
|
||||
symbol: "is",
|
||||
db: '=',
|
||||
uis: ["number"],
|
||||
),
|
||||
"neqnum" => new Operator(
|
||||
name: "nenum",
|
||||
label: "Not Equals number",
|
||||
symbol: "is not",
|
||||
db: '$ne',
|
||||
uis: ["number"],
|
||||
),
|
||||
"filter" => new Operator(
|
||||
name: "filter",
|
||||
label: "Equals Object",
|
||||
symbol: "is",
|
||||
db: 'filter',
|
||||
uis: [],
|
||||
),
|
||||
"eqtrue" => new Operator(
|
||||
name: "eqtrue",
|
||||
label: "Equals true",
|
||||
symbol: "is",
|
||||
db: '=',
|
||||
uis: ["checkbox"],
|
||||
),
|
||||
"eqfalse" => new Operator(
|
||||
name: "eqfalse",
|
||||
label: "Equals false",
|
||||
symbol: "is not",
|
||||
db: '=',
|
||||
uis: ["checkbox"],
|
||||
),
|
||||
"netrue" => new Operator(
|
||||
name: "netrue",
|
||||
label: "Not equals true",
|
||||
symbol: "!=",
|
||||
db: '$ne',
|
||||
uis: ["checkbox"],
|
||||
),
|
||||
"nefalse" => new Operator(
|
||||
name: "nefalse",
|
||||
label: "Not equals false",
|
||||
symbol: "!=",
|
||||
db: '$ne',
|
||||
uis: ["checkbox"],
|
||||
),
|
||||
"in" => new Operator(
|
||||
name: "in",
|
||||
label: "In list",
|
||||
symbol: "in",
|
||||
db: 'in',
|
||||
uis: ["id", "text", "textarea", "url", "color", "date", "datetime"],
|
||||
),
|
||||
"innum" => new Operator(
|
||||
name: "innum",
|
||||
label: "In list of numbers",
|
||||
symbol: "in",
|
||||
db: '$in',
|
||||
uis: ["number"],
|
||||
),
|
||||
"nin" => new Operator(
|
||||
name: "nin",
|
||||
label: "Not in list",
|
||||
symbol: "not in",
|
||||
db: 'nin',
|
||||
uis: ["id", "text", "textarea", "url", "color", "date", "datetime"],
|
||||
),
|
||||
"ninnum" => new Operator(
|
||||
name: "ninnum",
|
||||
label: "Not In list of numbers",
|
||||
symbol: "not in",
|
||||
db: '$nin',
|
||||
uis: ["number"],
|
||||
),
|
||||
"lt" => new Operator(
|
||||
name: "lt",
|
||||
label: "Less than",
|
||||
symbol: "<",
|
||||
db: '<',
|
||||
uis: ["number", "date", "datetime"],
|
||||
),
|
||||
"lte" => new Operator(
|
||||
name: "lte",
|
||||
label: "Less than equals",
|
||||
symbol: "<=",
|
||||
db: '<=',
|
||||
uis: ["number", "date", "datetime"],
|
||||
),
|
||||
"gt" => new Operator(
|
||||
name: "gt",
|
||||
label: "Greater than",
|
||||
symbol: ">",
|
||||
db: '>',
|
||||
uis: ["number", "date", "datetime"],
|
||||
),
|
||||
"gte" => new Operator(
|
||||
name: "gte",
|
||||
label: "Greater than equals",
|
||||
symbol: ">=",
|
||||
db: '>=',
|
||||
uis: ["number", "date", "datetime"],
|
||||
),
|
||||
"null" => new Operator(
|
||||
name: "null",
|
||||
label: "Is null",
|
||||
symbol: "=",
|
||||
db: '$eq',
|
||||
uis: ["*"],
|
||||
),
|
||||
"nnull" => new Operator(
|
||||
name: "nnull",
|
||||
label: "Not null",
|
||||
symbol: "!=",
|
||||
db: '$ne',
|
||||
uis: ["*"],
|
||||
),
|
||||
"exists" => new Operator(
|
||||
name: "exists",
|
||||
label: "Exists",
|
||||
symbol: "exists",
|
||||
db: 'exists',
|
||||
uis: ["*"],
|
||||
),
|
||||
"nexists" => new Operator(
|
||||
name: "nexists",
|
||||
label: "Not exists",
|
||||
symbol: "not exists",
|
||||
db: '$exists',
|
||||
uis: ["*"],
|
||||
),
|
||||
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class Equals extends Operator
|
||||
{
|
||||
|
||||
public string $name = "eq";
|
||||
public string $label = "Equals";
|
||||
public string $symbol = "is";
|
||||
public array $uis = ["id", "text", "textarea", "url", "color", "date", "datetime", "reference"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\Equals::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class EqualsFalse extends Operator
|
||||
{
|
||||
|
||||
public string $name = "eqfalse";
|
||||
public string $label = "Equals False";
|
||||
public string $symbol = "is";
|
||||
public array $uis = ["checkbox"];
|
||||
public bool $hasValue = false;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\EqualsFalse::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class EqualsNumber extends Operator
|
||||
{
|
||||
|
||||
public string $name = "eqnum";
|
||||
public string $label = "Equals Number";
|
||||
public string $symbol = "is";
|
||||
public array $uis = ["number"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\EqualsNumber::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class EqualsTrue extends Operator
|
||||
{
|
||||
|
||||
public string $name = "eqtrue";
|
||||
public string $label = "Equals True";
|
||||
public string $symbol = "is";
|
||||
public array $uis = ["checkbox"];
|
||||
public bool $hasValue = false;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\EqualsTrue::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class Exists extends Operator
|
||||
{
|
||||
|
||||
public string $name = "exists";
|
||||
public string $label = "Exists";
|
||||
public string $symbol = "exists";
|
||||
public array $uis = ["*"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\Exists::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class Filter extends Operator
|
||||
{
|
||||
public string $name = "filter";
|
||||
public string $label = "Equals Object";
|
||||
public string $symbol = "is";
|
||||
public array $uis = [];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\Filter::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class GreaterThan extends Operator
|
||||
{
|
||||
|
||||
public string $name = "gt";
|
||||
public string $label = "Greater than";
|
||||
public string $symbol = ">";
|
||||
public array $uis = ["number", "date", "datetime"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\GreaterThan::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class GreaterThanEquals extends Operator
|
||||
{
|
||||
|
||||
public string $name = "gte";
|
||||
public string $label = "Greater than equals";
|
||||
public string $symbol = ">";
|
||||
public array $uis = ["number", "date", "datetime"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\GreaterThanEquals::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class In extends Operator
|
||||
{
|
||||
public string $name = "in";
|
||||
public string $label = "In list";
|
||||
public string $symbol = "in";
|
||||
public array $uis = ["id", "text", "textarea", "url", "color", "date", "datetime"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\In::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class InNum extends Operator
|
||||
{
|
||||
public string $name = "innum";
|
||||
public string $label = "In number list";
|
||||
public string $symbol = "in";
|
||||
public array $uis = ["number"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\NotInNum::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class IsNull extends Operator
|
||||
{
|
||||
|
||||
public string $name = "null";
|
||||
public string $label = "Is Null";
|
||||
public string $symbol = "is null";
|
||||
public array $uis = ["*"];
|
||||
public bool $hasValue = false;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\IsNull::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class LessThan extends Operator
|
||||
{
|
||||
|
||||
public string $name = "lt";
|
||||
public string $label = "Less than";
|
||||
public string $symbol = ">";
|
||||
public array $uis = ["number", "date", "datetime"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\LessThan::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class LessThanEquals extends Operator
|
||||
{
|
||||
|
||||
public string $name = "lte";
|
||||
public string $label = "Less than equals";
|
||||
public string $symbol = ">";
|
||||
public array $uis = ["number", "date", "datetime"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\LessThanEquals::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class NotEquals extends Operator
|
||||
{
|
||||
|
||||
public string $name = "ne";
|
||||
public string $label = "Not Equals";
|
||||
public string $symbol = "is not";
|
||||
public array $uis = ["id", "text", "textarea", "url", "color", "date", "datetime", "reference"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\NotEquals::class;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class NotEqualsFalse extends Operator
|
||||
{
|
||||
|
||||
public string $name = "nefalse";
|
||||
public string $label = "Not Equals False";
|
||||
public string $symbol = "is";
|
||||
public array $uis = ["checkbox"];
|
||||
public bool $hasValue = false;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\NotEqualsFalse::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class NotEqualsNumber extends Operator
|
||||
{
|
||||
|
||||
public string $name = "neqnum";
|
||||
public string $label = "Not Equals Number";
|
||||
public string $symbol = "is";
|
||||
public array $uis = ["number"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\NotEqualsNumber::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class NotEqualsTrue extends Operator
|
||||
{
|
||||
|
||||
public string $name = "netrue";
|
||||
public string $label = "Not Equals True";
|
||||
public string $symbol = "is";
|
||||
public array $uis = ["checkbox"];
|
||||
public bool $hasValue = false;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\NotEqualsTrue::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class NotExists extends Operator
|
||||
{
|
||||
|
||||
public string $name = "nexists";
|
||||
public string $label = "Not Exists";
|
||||
public string $symbol = "not exists";
|
||||
public array $uis = ["*"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\NotExists::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class NotIn extends Operator
|
||||
{
|
||||
public string $name = "nin";
|
||||
public string $label = "Not in list";
|
||||
public string $symbol = "in";
|
||||
public array $uis = ["id", "text", "textarea", "url", "color", "date", "datetime"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\NotIn::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class NotInNum extends Operator
|
||||
{
|
||||
public string $name = "ninnum";
|
||||
public string $label = "Not in number list";
|
||||
public string $symbol = "not in";
|
||||
public array $uis = ["number"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\InNum::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class NotNull extends Operator
|
||||
{
|
||||
|
||||
public string $name = "nnull";
|
||||
public string $label = "Is not Null";
|
||||
public string $symbol = "is not null";
|
||||
public array $uis = ["*"];
|
||||
public bool $hasValue = false;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\NotNull::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
|
||||
abstract class Operator
|
||||
{
|
||||
public string $name;
|
||||
public string $label;
|
||||
public string $symbol;
|
||||
public array $uis;
|
||||
public bool $hasValue;
|
||||
/**
|
||||
* @var class-string
|
||||
*/
|
||||
public string $converter;
|
||||
|
||||
public static function make(): Operator
|
||||
{
|
||||
return new static();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
use Lucent\Query\Filter\Argument;
|
||||
|
||||
class OperatorDetector
|
||||
{
|
||||
public function __construct(
|
||||
public OperatorRegistry $operatorRegistry
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function detect(mixed $value, string $filter): Argument
|
||||
{
|
||||
$operator = $this->detectOperator($filter);
|
||||
$field = $this->detectField($filter, $operator->name);
|
||||
return new Argument(
|
||||
field: str_replace(".", "->", $field),
|
||||
operator: $operator,
|
||||
value: $value
|
||||
);
|
||||
}
|
||||
|
||||
private function detectOperator(string $filter): Operator
|
||||
{
|
||||
$exploded = explode("_", $filter);
|
||||
$candidate = end($exploded);
|
||||
return $this->operatorRegistry->matchByName($candidate);
|
||||
}
|
||||
|
||||
private function detectField(string $filter, string $operator): string
|
||||
{
|
||||
$exploded = explode("_", $filter);
|
||||
$candidate = array_pop($exploded);
|
||||
if ($candidate === $operator) {
|
||||
return implode("_", $exploded);
|
||||
}
|
||||
return $filter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
|
||||
final class OperatorRegistry
|
||||
{
|
||||
/**
|
||||
* @return list<Operator>
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
return [
|
||||
new Equals(),
|
||||
new NotEquals(),
|
||||
new EqualsNumber(),
|
||||
new NotEqualsNumber(),
|
||||
new EqualsTrue(),
|
||||
new EqualsFalse(),
|
||||
new NotEqualsFalse(),
|
||||
new NotEqualsTrue(),
|
||||
new Regex(),
|
||||
new In(),
|
||||
new NotIn(),
|
||||
new InNum(),
|
||||
new NotInNum(),
|
||||
new GreaterThan(),
|
||||
new GreaterThanEquals(),
|
||||
new LessThan(),
|
||||
new LessThanEquals(),
|
||||
new IsNull(),
|
||||
new NotNull(),
|
||||
new Exists(),
|
||||
new NotExists(),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
public function matchByName(string $name): Operator
|
||||
{
|
||||
$operator = collect($this->all())->where('name', $name)->first();
|
||||
if (empty($operator)) {
|
||||
return new Equals();
|
||||
}
|
||||
return $operator;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Query\Operator;
|
||||
|
||||
class Regex extends Operator
|
||||
{
|
||||
|
||||
public string $name = "regex";
|
||||
public string $label = "Search";
|
||||
public string $symbol = "~";
|
||||
public array $uis = ["id", "text", "textarea", "url", "color", "date", "datetime"];
|
||||
public bool $hasValue = true;
|
||||
public string $converter = \Lucent\Query\BuilderConverter\Regex::class;
|
||||
|
||||
}
|
||||
+2
-3
@@ -161,7 +161,7 @@ final class Query
|
||||
|
||||
private function findNotLinked(Builder $query): Builder
|
||||
{
|
||||
if(empty($this->options->notLinked)){
|
||||
if (empty($this->options->notLinked)) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
@@ -169,8 +169,7 @@ final class Query
|
||||
$query
|
||||
->select("records.*")
|
||||
->join('edges', 'records.id', '=', 'edges.target', 'left outer')
|
||||
->whereNull("edges.target")
|
||||
;
|
||||
->whereNull("edges.target");
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user