146 lines
4.7 KiB
PHP
146 lines
4.7 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use Illuminate\Database\Eloquent\Builder;
|
||
use Illuminate\Support\Facades\DB;
|
||
use App\DevExtreme\FilterHelper; // Mevcut FilterHelper'ı kullanacağız
|
||
|
||
class QueryBuilderService
|
||
{
|
||
/**
|
||
* DevExtreme LoadOptions formatındaki parametreleri sorguya uygular.
|
||
*
|
||
* @param Builder|\Illuminate\Database\Query\Builder $query
|
||
* @param array|string|null $filter JSON string veya array
|
||
* @param array|string|null $sort JSON string veya array
|
||
* @param int|null $skip
|
||
* @param int|null $take
|
||
* @return Builder|\Illuminate\Database\Query\Builder
|
||
*/
|
||
public function apply($query, $filter = null, $sort = null, $skip = null, $take = null)
|
||
{
|
||
// JSON string gelirse array'e çevir
|
||
if (is_string($filter)) {
|
||
$filter = json_decode($filter, true);
|
||
}
|
||
|
||
if (is_string($sort)) {
|
||
$sort = json_decode($sort, true);
|
||
}
|
||
|
||
// Filtreleme (Mevcut DevExtreme/FilterHelper veya özel mantık)
|
||
if (!empty($filter)) {
|
||
// Eğer projenizdeki FilterHelper statik ise doğrudan çağırabiliriz.
|
||
// Değilse burada custom bir recursive parser yazıyorum.
|
||
$this->applyFilterRecursive($query, $filter);
|
||
}
|
||
|
||
// Sıralama
|
||
if (!empty($sort)) {
|
||
foreach ($sort as $s) {
|
||
$selector = $s['selector'];
|
||
$desc = (isset($s['desc']) && $s['desc'] === true) ? 'desc' : 'asc';
|
||
$query->orderBy($selector, $desc);
|
||
}
|
||
}
|
||
|
||
// Sayfalama
|
||
if (!is_null($skip)) {
|
||
$query->skip($skip);
|
||
}
|
||
|
||
if (!is_null($take)) {
|
||
$query->take($take);
|
||
}
|
||
|
||
return $query;
|
||
}
|
||
|
||
/**
|
||
* Recursive Filter Parser
|
||
* DevExtreme formatı: ["field", "=", "value"] veya ["and", ["f1", "=", "v1"], ["f2", "=", "v2"]]
|
||
*/
|
||
protected function applyFilterRecursive($query, $filter)
|
||
{
|
||
// Grup koşulu mu? İlk eleman "and" veya "or" ise grup olarak işle (2+ filtre birleşimi)
|
||
$firstIsLogic = isset($filter[0]) && is_string($filter[0])
|
||
&& in_array(strtolower($filter[0]), ['and', 'or'], true);
|
||
if ($firstIsLogic && count($filter) >= 2) {
|
||
$this->applyFilterGroup($query, $filter);
|
||
return;
|
||
}
|
||
|
||
// Tekil koşul: ["field", "op", "value"] -> tam 3 eleman, ikinci operatör
|
||
if (isset($filter[0], $filter[1], $filter[2]) && count($filter) === 3
|
||
&& is_string($filter[0]) && is_string($filter[1])) {
|
||
$this->addCondition($query, $filter[0], $filter[1], $filter[2]);
|
||
return;
|
||
}
|
||
|
||
// Eski format: [ [..], "and", [..] ] (operatör ortada)
|
||
$this->applyFilterGroup($query, $filter);
|
||
}
|
||
|
||
/**
|
||
* Grup filtre: ["and", cond1, cond2] veya [cond1, "and", cond2]
|
||
*/
|
||
protected function applyFilterGroup($query, $filter)
|
||
{
|
||
$query->where(function ($subQuery) use ($filter) {
|
||
$logic = 'and'; // Varsayılan bağlaç
|
||
|
||
foreach ($filter as $item) {
|
||
if (is_string($item)) {
|
||
// "and" veya "or" bağlacı
|
||
$logic = strtolower($item);
|
||
continue;
|
||
}
|
||
|
||
if (is_array($item)) {
|
||
if ($logic === 'or') {
|
||
$subQuery->orWhere(function ($q) use ($item) {
|
||
$this->applyFilterRecursive($q, $item);
|
||
});
|
||
} else {
|
||
$subQuery->where(function ($q) use ($item) {
|
||
$this->applyFilterRecursive($q, $item);
|
||
});
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
protected function addCondition($query, $field, $operator, $value)
|
||
{
|
||
switch ($operator) {
|
||
case 'contains':
|
||
$query->where($field, 'like', '%' . $value . '%');
|
||
break;
|
||
case 'notcontains':
|
||
$query->where($field, 'not like', '%' . $value . '%');
|
||
break;
|
||
case 'startswith':
|
||
$query->where($field, 'like', $value . '%');
|
||
break;
|
||
case 'endswith':
|
||
$query->where($field, 'like', '%' . $value);
|
||
break;
|
||
case '=':
|
||
case '<>':
|
||
case '>':
|
||
case '>=':
|
||
case '<':
|
||
case '<=':
|
||
$query->where($field, $operator, $value);
|
||
break;
|
||
default:
|
||
// Desteklenmeyen operatörler için varsayılan davranış
|
||
$query->where($field, '=', $value);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|