Files
citrus-cms/app/Services/QueryBuilderService.php
T
2026-04-28 21:14:25 +03:00

146 lines
4.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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;
}
}
}