İlk temizlik tamamlandı bir önceki projeden

This commit is contained in:
Ümit Tunç
2026-04-28 21:14:25 +03:00
commit f80443aec0
10000 changed files with 959965 additions and 0 deletions
+644
View File
@@ -0,0 +1,644 @@
<?php
namespace App\DevExtreme;
use App\DevExtreme\SummaryContext;
class AggregateHelper {
const MIN_OP = "MIN";
const MAX_OP = "MAX";
const AVG_OP = "AVG";
const COUNT_OP = "COUNT";
const SUM_OP = "SUM";
const AS_OP = "AS";
const GENERATED_FIELD_PREFIX = "dx_";
private static function _RecalculateGroupCountAndSummary(&$dataItem, $groupInfo) {
if ($groupInfo["groupIndex"] <= $groupInfo["groupCount"] - 3) {
$items = $dataItem["items"];
foreach ($items as $item) {
$grInfo = $groupInfo;
$grInfo["groupIndex"]++;
self::_RecalculateGroupCountAndSummary($item, $grInfo);
}
}
if (isset($groupInfo["summaryTypes"]) && $groupInfo["groupIndex"] < $groupInfo["groupCount"] - 2) {
$result = array();
$items = $dataItem["items"];
$itemsCount = count($items);
foreach ($items as $index => $item) {
$currentSummaries = $item["summary"];
if ($index == 0) {
foreach ($currentSummaries as $summaryItem) {
$result[] = $summaryItem;
}
continue;
}
foreach ($groupInfo["summaryTypes"] as $si => $stItem) {
if ($stItem == self::MIN_OP) {
if ($result[$si] > $currentSummaries[$si]) {
$result[$si] = $currentSummaries[$si];
}
continue;
}
if ($stItem == self::MAX_OP) {
if ($result[$si] < $currentSummaries[$si]) {
$result[$si] = $currentSummaries[$si];
}
continue;
}
$result[$si] += $currentSummaries[$si];
}
}
foreach ($groupInfo["summaryTypes"] as $si => $stItem) {
if ($stItem == self::AVG_OP) {
$result[$si] /= $itemsCount;
}
}
$dataItem["summary"] = $result;
}
}
private static function _GetNewDataItem($row, $groupInfo) {
$dataItem = array();
$dataFieldCount = count($groupInfo["dataFieldNames"]);
for ($index = 0; $index < $dataFieldCount; $index++) {
$dataItem[$groupInfo["dataFieldNames"][$index]] = $row[$groupInfo["groupCount"] + $index];
}
return $dataItem;
}
private static function _GetNewGroupItem($row, $groupInfo, $explicitKey = null) {
$groupIndexOffset = $groupInfo["lastGroupExpanded"] ? 1 : 2;
// Direkt row değerini al, explode kullanma
$item = $explicitKey !== null ? $explicitKey : (isset($row[$groupInfo["groupIndex"]]) ? trim($row[$groupInfo["groupIndex"]]) : null);
$groupItem = array();
$groupItem["key"] = ($item === "" || $item === null) ? null : $item;
$groupItem["items"] = $groupInfo["groupIndex"] < $groupInfo["groupCount"] - $groupIndexOffset ? array() :
($groupInfo["lastGroupExpanded"] ? array() : NULL);
if ($groupInfo["groupIndex"] == $groupInfo["groupCount"] - $groupIndexOffset) {
if (isset($groupInfo["summaryTypes"])) {
$summaries = array();
$endIndex = $groupInfo["groupIndex"] + count($groupInfo["summaryTypes"]) + 1;
for ($index = $groupInfo["groupCount"]; $index <= $endIndex; $index++) {
$summaries[] = $row[$index];
}
$groupItem["summary"] = $summaries;
}
if (!$groupInfo["lastGroupExpanded"]) {
$groupItem["count"] = $row[$groupInfo["groupIndex"] + 1];
}
else {
$groupItem["items"][] = self::_GetNewDataItem($row, $groupInfo);
}
}
return $groupItem;
}
private static function _GroupData($row, &$resultItems, $groupInfo) {
$itemsCount = count($resultItems);
if (!isset($row) && !$itemsCount) {
return;
}
$currentItem = NULL;
$groupIndexOffset = $groupInfo["lastGroupExpanded"] ? 1 : 2;
// Eğer bu bir tarih filtresi ise, özel yönetim yapalım
$dateSequenceInfo = self::_getDateSequence($groupInfo);
if ($dateSequenceInfo['isDateSequence']) {
// Tarih sırası algılandı, özel tarih işleme mantığını kullan
self::_processDateSequence($row, $resultItems, $groupInfo, $dateSequenceInfo);
return;
}
// Standart (tarih olmayan) gruplamalar için normal akış
$currentKey = isset($row[$groupInfo["groupIndex"]]) ? trim($row[$groupInfo["groupIndex"]]) : null;
// Comma separation logic
if (isset($groupInfo["processCommas"]) && $groupInfo["processCommas"] === true &&
$currentKey !== null && strpos($currentKey, ',') !== false) {
$keys = explode(',', $currentKey);
foreach ($keys as $key) {
self::_processGroupDataItem($row, $resultItems, $groupInfo, trim($key));
}
return;
}
// Standart grup işlemlerini yapan yardımcı fonksiyon
self::_processGroupDataItem($row, $resultItems, $groupInfo, $currentKey);
}
// Standart grup işlemlerini yapan yardımcı fonksiyon
private static function _processGroupDataItem($row, &$resultItems, $groupInfo, $explicitKey = null) {
$currentKey = $explicitKey;
if ($currentKey === "") {
$currentKey = null;
}
$groupIndexOffset = $groupInfo["lastGroupExpanded"] ? 1 : 2;
// Eğer bu key zaten varsa, ilgili item'ı kullan
$keyExists = false;
$currentItem = null;
foreach($resultItems as $index => $item) {
if(isset($item["key"]) && (trim($item["key"]) === trim($currentKey) ||
($item["key"] === null && ($currentKey === null || $currentKey === "")))) {
$keyExists = true;
$currentItem = &$resultItems[$index];
break;
}
}
if (!$keyExists) {
$currentItem = self::_GetNewGroupItem($row, $groupInfo, $currentKey);
$resultItems[] = &$currentItem;
} else {
// MERGE LOGIC for leaf groups
if ($groupInfo["groupIndex"] == $groupInfo["groupCount"] - $groupIndexOffset) {
// Update count
if (isset($currentItem["count"])) {
$currentItem["count"] += $row[$groupInfo["groupIndex"] + 1];
}
// Update summaries if needed
if (isset($currentItem["summary"]) && isset($groupInfo["summaryTypes"])) {
$newSummaries = array();
$endIndex = $groupInfo["groupIndex"] + count($groupInfo["summaryTypes"]) + 1;
for ($index = $groupInfo["groupCount"]; $index <= $endIndex; $index++) {
$newSummaries[] = $row[$index];
}
foreach ($groupInfo["summaryTypes"] as $si => $stItem) {
if ($stItem == self::MIN_OP) {
if ($currentItem["summary"][$si] > $newSummaries[$si]) $currentItem["summary"][$si] = $newSummaries[$si];
} else if ($stItem == self::MAX_OP) {
if ($currentItem["summary"][$si] < $newSummaries[$si]) $currentItem["summary"][$si] = $newSummaries[$si];
} else if ($stItem == self::SUM_OP || $stItem == self::COUNT_OP) {
$currentItem["summary"][$si] += $newSummaries[$si];
} else if ($stItem == self::AVG_OP) {
$count1 = isset($currentItem["count"]) ? $currentItem["count"] : 1;
$count2 = isset($row[$groupInfo["groupIndex"] + 1]) ? $row[$groupInfo["groupIndex"] + 1] : 1;
if (($count1 + $count2) > 0)
$currentItem["summary"][$si] = (($currentItem["summary"][$si] * $count1) + ($newSummaries[$si] * $count2)) / ($count1 + $count2);
else
$currentItem["summary"][$si] = ($currentItem["summary"][$si] + $newSummaries[$si]) / 2;
}
}
}
// If expanded, append items
if ($groupInfo["lastGroupExpanded"]) {
$currentItem["items"][] = self::_GetNewDataItem($row, $groupInfo);
}
}
}
if ($groupInfo["groupIndex"] < $groupInfo["groupCount"] - $groupIndexOffset) {
$groupInfo["groupIndex"]++;
self::_GroupData($row, $currentItem["items"], $groupInfo);
}
}
// Tarih dizisini tanımla ve işle
private static function _getDateSequence($groupInfo) {
// Tarih sırası bilgisi
$result = [
'isDateSequence' => false,
'sequence' => []
];
if (!isset($groupInfo["groupNames"]) || count($groupInfo["groupNames"]) < 2) {
return $result;
}
$dateFields = [];
// Tüm tarih alanlarını tespit et
foreach ($groupInfo["groupNames"] as $index => $name) {
if (strpos($name, 'dx_') !== 0) {
continue;
}
$type = '';
if (strpos($name, '_year') !== false) {
$type = 'year';
} else if (strpos($name, '_month') !== false) {
$type = 'month';
} else if (strpos($name, '_day') !== false) {
$type = 'day';
} else {
continue;
}
$dateFields[] = [
'index' => $index,
'type' => $type,
'name' => $name
];
}
// Eğer en az 2 tarih alanı varsa, tarih sırası oluştur
if (count($dateFields) >= 2) {
// Yıl, ay, gün sırasına göre sırala
usort($dateFields, function($a, $b) {
$order = ['year' => 0, 'month' => 1, 'day' => 2];
return $order[$a['type']] - $order[$b['type']];
});
$result['isDateSequence'] = true;
$result['sequence'] = $dateFields;
}
return $result;
}
// Tarih dizisini doğru bir şekilde işle
private static function _processDateSequence($row, &$resultItems, $groupInfo, $dateSequenceInfo) {
$groupIndexOffset = $groupInfo["lastGroupExpanded"] ? 1 : 2;
$sequence = $dateSequenceInfo['sequence'];
// İlk seviye için gruplama yap (genellikle yıl)
$firstLevelIndex = $sequence[0]['index'];
$firstLevelType = $sequence[0]['type'];
$currentKey = isset($row[$firstLevelIndex]) ? trim($row[$firstLevelIndex]) : null;
if ($currentKey === "") {
$currentKey = null;
}
// İlk seviyede (yıl) item ara
$yearItem = null;
foreach($resultItems as &$item) {
if(isset($item["key"]) && (trim($item["key"]) === trim($currentKey) ||
($item["key"] === null && ($currentKey === null || $currentKey === "")))) {
$yearItem = &$item;
break;
}
}
// Yıl item'ı yoksa oluştur
if ($yearItem === null) {
// Özel yıl item'ı oluştur
$tempGroupInfo = $groupInfo;
$tempGroupInfo["groupIndex"] = $firstLevelIndex;
$yearItem = self::_GetNewGroupItem($row, $tempGroupInfo);
$yearItem["dateLevel"] = $firstLevelType;
$resultItems[] = &$yearItem;
}
// İkinci seviye için (genellikle ay)
if (count($sequence) > 1) {
$secondLevelIndex = $sequence[1]['index'];
$secondLevelType = $sequence[1]['type'];
$secondKey = isset($row[$secondLevelIndex]) ? trim($row[$secondLevelIndex]) : null;
if ($secondKey === "") {
$secondKey = null;
}
// İkinci seviyede (ay) item ara
$monthItem = null;
foreach($yearItem["items"] as &$item) {
if(isset($item["key"]) && (trim($item["key"]) === trim($secondKey) ||
($item["key"] === null && ($secondKey === null || $secondKey === "")))) {
$monthItem = &$item;
break;
}
}
// Ay item'ı yoksa oluştur
if ($monthItem === null) {
// Özel ay item'ı oluştur
$tempGroupInfo = $groupInfo;
$tempGroupInfo["groupIndex"] = $secondLevelIndex;
$monthItem = self::_GetNewGroupItem($row, $tempGroupInfo);
$monthItem["dateLevel"] = $secondLevelType;
$yearItem["items"][] = &$monthItem;
}
// Üçüncü seviye için (genellikle gün)
if (count($sequence) > 2) {
$thirdLevelIndex = $sequence[2]['index'];
$thirdLevelType = $sequence[2]['type'];
$thirdKey = isset($row[$thirdLevelIndex]) ? trim($row[$thirdLevelIndex]) : null;
if ($thirdKey === "") {
$thirdKey = null;
}
// Üçüncü seviyede (gün) item ara
$dayItem = null;
foreach($monthItem["items"] as &$item) {
if(isset($item["key"]) && (trim($item["key"]) === trim($thirdKey) ||
($item["key"] === null && ($thirdKey === null || $thirdKey === "")))) {
$dayItem = &$item;
break;
}
}
// Gün item'ı yoksa oluştur
if ($dayItem === null) {
// Özel gün item'ı oluştur
$tempGroupInfo = $groupInfo;
$tempGroupInfo["groupIndex"] = $thirdLevelIndex;
$dayItem = self::_GetNewGroupItem($row, $tempGroupInfo);
$dayItem["dateLevel"] = $thirdLevelType;
$monthItem["items"][] = &$dayItem;
}
// Veriler için
if ($groupInfo["lastGroupExpanded"]) {
$dataItem = self::_GetNewDataItem($row, $groupInfo);
$dayItem["items"][] = $dataItem;
}
} else if ($groupInfo["lastGroupExpanded"]) {
// İki seviye varsa (sadece yıl ve ay), veriyi ay seviyesinde göster
$dataItem = self::_GetNewDataItem($row, $groupInfo);
$monthItem["items"][] = $dataItem;
}
} else if ($groupInfo["lastGroupExpanded"]) {
// Tek seviye varsa (sadece yıl), veriyi yıl seviyesinde göster
$dataItem = self::_GetNewDataItem($row, $groupInfo);
$yearItem["items"][] = $dataItem;
}
}
public static function GetGroupedDataFromQuery($queryResult, $groupSettings) {
$result = array();
$row = NULL;
$groupSummaryTypes = NULL;
$dataFieldNames = NULL;
$startSummaryFieldIndex = NULL;
$endSummaryFieldIndex = NULL;
if ($groupSettings["lastGroupExpanded"]) {
$queryFields = $queryResult->fetch_fields();
$dataFieldNames = array();
for ($i = $groupSettings["groupCount"]; $i < count($queryFields); $i++) {
$dataFieldNames[] = $queryFields[$i]->name;
}
}
if (isset($groupSettings["summaryTypes"])) {
$groupSummaryTypes = $groupSettings["summaryTypes"];
$startSummaryFieldIndex = $groupSettings["groupCount"] - 1;
$endSummaryFieldIndex = $startSummaryFieldIndex + count($groupSummaryTypes);
}
// Grup isimlerini al (tarih filtreleri için gerekli)
$groupNames = array();
if (isset($groupSettings["groupNames"])) {
$groupNames = $groupSettings["groupNames"];
} elseif ($queryResult && $queryResult->field_count > 0) {
$fields = $queryResult->fetch_fields();
for ($i = 0; $i < $groupSettings["groupCount"]; $i++) {
if (isset($fields[$i])) {
$groupNames[] = $fields[$i]->name;
}
}
// Sonuçlar için yeniden başa dönmek gerek
$queryResult->data_seek(0);
}
// Tarih alanlarını sıralamak için düzenleme (yıl, ay, gün)
$dateGroupIndices = self::getDateGroupIndices($groupNames);
$groupInfo = array(
"groupCount" => $groupSettings["groupCount"],
"groupIndex" => 0,
"summaryTypes" => $groupSummaryTypes,
"lastGroupExpanded" => $groupSettings["lastGroupExpanded"],
"dataFieldNames" => $dataFieldNames,
"processCommas" => isset($groupSettings["processCommas"]) ? $groupSettings["processCommas"] : true,
"groupNames" => $groupNames,
"dateGroupIndices" => $dateGroupIndices
);
while ($row = $queryResult->fetch_array(MYSQLI_NUM)) {
if (isset($startSummaryFieldIndex)) {
for ($i = $startSummaryFieldIndex; $i <= $endSummaryFieldIndex; $i++) {
$row[$i] = Utils::StringToNumber($row[$i]);
}
}
self::_GroupData($row, $result, $groupInfo);
}
if (!$groupSettings["lastGroupExpanded"]) {
self::_GroupData($row, $result, $groupInfo);
}
else {
if (isset($groupSettings["skip"]) && $groupSettings["skip"] >= 0 &&
isset($groupSettings["take"]) && $groupSettings["take"] >= 0) {
$result = array_slice($result, $groupSettings["skip"], $groupSettings["take"]);
}
}
return $result;
}
private static function getDateGroupIndices($groupNames) {
$yearIndex = -1;
$monthIndex = -1;
$dayIndex = -1;
foreach ($groupNames as $index => $name) {
if (strpos($name, 'dx_') === 0) {
if (strpos($name, '_year') !== false) {
$yearIndex = $index;
} else if (strpos($name, '_month') !== false) {
$monthIndex = $index;
} else if (strpos($name, '_day') !== false) {
$dayIndex = $index;
}
}
}
return [
'year' => $yearIndex,
'month' => $monthIndex,
'day' => $dayIndex
];
}
public static function IsLastGroupExpanded($items) {
$result = true;
$itemsCount = count($items);
if ($itemsCount > 0) {
$lastItem = $items[$itemsCount - 1];
if (gettype($lastItem) === "object") {
$result = isset($lastItem->isExpanded) ? $lastItem->isExpanded === true : true;
}
else {
$result = true;
}
}
return $result;
}
public static function GetFieldSetBySelectors($items) {
$group = "";
$sort = "";
$select = "";
foreach ($items as $item) {
$groupField = NULL;
$sortField = NULL;
$selectField = NULL;
$desc = false;
if (is_string($item) && strlen($item = trim($item))) {
$selectField = $groupField = $sortField = Utils::QuoteStringValue($item);
}
else if (gettype($item) === "object" && isset($item->selector)) {
$quoteSelector = Utils::QuoteStringValue($item->selector);
$desc = isset($item->desc) ? $item->desc : false;
// Tarih gruplamalarını düzenle
if (isset($item->groupInterval)) {
if (is_int($item->groupInterval)) {
$groupField = Utils::QuoteStringValue(sprintf("%s%s_%d", self::GENERATED_FIELD_PREFIX, $item->selector, $item->groupInterval));
$selectField = sprintf("(%s - (%s %% %d)) %s %s",
$quoteSelector,
$quoteSelector,
$item->groupInterval,
self::AS_OP,
$groupField);
}
else {
// Tarih gruplamalarını düzgün şekilde yap
$interval = strtolower($item->groupInterval);
$groupField = Utils::QuoteStringValue(sprintf("%s%s_%s", self::GENERATED_FIELD_PREFIX, $item->selector, $interval));
if ($interval == 'year') {
$selectField = sprintf("YEAR(%s) %s %s",
$quoteSelector,
self::AS_OP,
$groupField);
}
else if ($interval == 'month') {
$selectField = sprintf("MONTH(%s) %s %s",
$quoteSelector,
self::AS_OP,
$groupField);
}
else if ($interval == 'day') {
$selectField = sprintf("DAY(%s) %s %s",
$quoteSelector,
self::AS_OP,
$groupField);
}
else if ($interval == 'dayofweek') {
$selectField = sprintf("DAYOFWEEK(%s) - 1 %s %s",
$quoteSelector,
self::AS_OP,
$groupField);
}
else {
$selectField = sprintf("%s(%s) %s %s",
strtoupper($interval),
$quoteSelector,
self::AS_OP,
$groupField);
}
}
$sortField = $groupField;
}
else {
$selectField = $groupField = $sortField = $quoteSelector;
}
}
if (isset($selectField)) {
$select .= (strlen($select) > 0 ? ", ".$selectField : $selectField);
}
if (isset($groupField)) {
$group .= (strlen($group) > 0 ? ", ".$groupField : $groupField);
}
if (isset($sortField)) {
$sort .= (strlen($sort) > 0 ? ", ".$sortField : $sortField).
($desc ? " DESC" : "");
}
}
return array(
"group" => $group,
"sort" => $sort,
"select" => $select
);
}
private static function _IsSummaryTypeValid($summaryType) {
return in_array($summaryType, array(self::MIN_OP, self::MAX_OP, self::AVG_OP, self::COUNT_OP, self::SUM_OP));
}
public static function GetSummaryInfo($expression, $tableName = null) {
$result = array();
$fields = "";
$summaryTypes = array();
foreach ($expression as $index => $item) {
if (gettype($item) === "object" && isset($item->summaryType)) {
$summaryType = strtoupper(trim($item->summaryType));
if (!self::_IsSummaryTypeValid($summaryType)) {
continue;
}
$summaryTypes[] = $summaryType;
$selector = (isset($item->selector) && is_string($item->selector)) ? $item->selector : null;
$quotedSelector = isset($selector) ? Utils::QuoteStringValue($selector) : "1";
if (self::shouldApplyWeldedFilter($tableName, $item, $summaryType)) {
$quotedSelector = self::applyWeldedFilterExpression($quotedSelector, $summaryType);
}
$fields .= sprintf("%s(%s) %s %sf%d",
strlen($fields) > 0 ? ", ".$summaryType : $summaryType,
$quotedSelector,
self::AS_OP,
self::GENERATED_FIELD_PREFIX,
$index);
}
}
$result["fields"] = $fields;
$result["summaryTypes"] = $summaryTypes;
return $result;
}
private static function shouldApplyWeldedFilter($tableName, $item, $summaryType) {
if ($tableName !== 'weld_logs') {
return false;
}
$hasExplicitFlag = isset($item->weldedOnly) && $item->weldedOnly;
$forceByContext = SummaryContext::shouldExcludeMechanical();
if (!$hasExplicitFlag && !$forceByContext) {
return false;
}
return in_array($summaryType, [self::SUM_OP, self::AVG_OP]);
}
private static function getMechanicalTypesList() {
static $cachedList = null;
if ($cachedList !== null) {
return $cachedList;
}
if (function_exists('get_mechanical_joint_types')) {
$types = get_mechanical_joint_types();
} else {
$types = ['BJ', 'FJ', 'TH', 'CJ'];
}
$escaped = array_map(function($type) {
$normalized = strtoupper(trim($type));
return "'" . addslashes($normalized) . "'";
}, $types);
$cachedList = implode(",", $escaped);
if ($cachedList === '') {
$cachedList = "''";
}
return $cachedList;
}
private static function applyWeldedFilterExpression($quotedSelector, $summaryType) {
$mechanicalList = self::getMechanicalTypesList();
$typeColumnExpr = "UPPER(TRIM(COALESCE(`type_of_welds`, '')))";
$thenValue = $summaryType === self::AVG_OP ? "NULL" : "0";
return sprintf(
"CASE WHEN %s IN (%s) THEN %s ELSE %s END",
$typeColumnExpr,
$mechanicalList,
$thenValue,
$quotedSelector
);
}
}
+157
View File
@@ -0,0 +1,157 @@
<?php
namespace App\DevExtreme;
class DataSourceLoader {
public static function Load($dbSet, $params, $module = null) {
$result = NULL;
if (isset($dbSet) && get_class($dbSet) == "App\DevExtreme\DbSet" && isset($params) && is_array($params)) {
// Check if distinctColumn parameter is provided (for header filter unique values)
// distinctColumn can come as string (from GET) or already parsed
$distinctColumn = null;
if (isset($params["distinctColumn"])) {
$distinctColumn = $params["distinctColumn"];
// If it's a JSON string, decode it
if (is_string($distinctColumn) && (substr($distinctColumn, 0, 1) === '[' || substr($distinctColumn, 0, 1) === '{')) {
$decoded = json_decode($distinctColumn, true);
if ($decoded !== null) {
$distinctColumn = $decoded;
}
}
// Log for debugging
error_log("DataSourceLoader: distinctColumn parameter received: " . var_export($distinctColumn, true) . " (type: " . gettype($distinctColumn) . ")");
}
if (!empty($distinctColumn) && is_string($distinctColumn)) {
// Apply filters first
$dbSet->Filter(Utils::GetItemValueOrDefault($params, "filter"));
if ($module === 'weldlog-employer-view' && $dbSet->getTableName() === 'weld_logs') {
self::ApplyEmployerViewFilters($dbSet);
}
// Get distinct values
error_log("DataSourceLoader: Getting distinct values for column: " . $distinctColumn . " in table: " . $dbSet->getTableName());
$distinctValues = $dbSet->GetDistinctValues($distinctColumn);
if ($dbSet->GetLastError() !== NULL) {
error_log("GetDistinctValues error: " . $dbSet->GetLastError());
// Return error response instead of NULL
$result = array();
$result["data"] = array();
$result["hasBlanks"] = false;
$result["error"] = $dbSet->GetLastError();
return $result;
}
error_log("DataSourceLoader: Found " . count($distinctValues) . " distinct values");
// Check for blanks
$hasBlanks = $dbSet->HasBlanks($distinctColumn);
if ($dbSet->GetLastError() !== NULL) {
error_log("HasBlanks error: " . $dbSet->GetLastError());
// Continue even if HasBlanks fails
}
// Format response for header filter
$result = array();
$result["data"] = array_map(function($value) {
return array("value" => $value, "text" => $value);
}, $distinctValues);
$result["hasBlanks"] = $hasBlanks;
return $result;
}
// Normal data loading
$dbSet->Select(Utils::GetItemValueOrDefault($params, "select"))
->Filter(Utils::GetItemValueOrDefault($params, "filter"));
if ($module === 'weldlog-employer-view' && $dbSet->getTableName() === 'weld_logs') {
self::ApplyEmployerViewFilters($dbSet);
}
$totalSummary = $dbSet->GetTotalSummary(Utils::GetItemValueOrDefault($params, "totalSummary"),
Utils::GetItemValueOrDefault($params, "filter"));
if ($dbSet->GetLastError() !== NULL) {
error_log("GetTotalSummary error: " . $dbSet->GetLastError());
return $result;
}
$totalCount = (isset($params["requireTotalCount"]) && $params["requireTotalCount"] === true)
? $dbSet->GetCount() : NULL;
if ($dbSet->GetLastError() !== NULL) {
return $result;
}
$dbSet->Sort(Utils::GetItemValueOrDefault($params, "sort"));
$groupCount = NULL;
$skip = Utils::GetItemValueOrDefault($params, "skip");
$take = Utils::GetItemValueOrDefault($params, "take");
if (isset($params["group"])) {
$groupExpression = $params["group"];
$groupSummary = Utils::GetItemValueOrDefault($params, "groupSummary");
$dbSet->Group($groupExpression, $groupSummary, $skip, $take);
if (isset($params["requireGroupCount"]) && $params["requireGroupCount"] === true) {
$groupCount = $dbSet->GetGroupCount();
}
}
else {
$dbSet->SkipTake($skip, $take);
}
$result = array();
$result["data"] = $dbSet->AsArray();
if ($dbSet->GetLastError() !== NULL) {
return $result;
}
if (isset($totalCount)) {
$result["totalCount"] = $totalCount;
}
if (isset($totalSummary)) {
$result["summary"] = $totalSummary;
}
if (isset($groupCount)) {
$result["groupCount"] = $groupCount;
}
}
else {
throw new \Exception("Invalid params");
}
return $result;
}
/**
* Apply employer view specific filters to weld_logs table
* Filters:
* 1. Exclude records with repair_status = 'Repair' in repair_logs
* 2. Exclude records with NDT results other than 'Accept / Годен' or empty/null
*/
private static function ApplyEmployerViewFilters($dbSet) {
$weldLogsTable = $dbSet->getTableName();
$repairFilter = "NOT EXISTS (
SELECT 1 FROM repair_logs
WHERE repair_logs.iso_number = {$weldLogsTable}.iso_number
AND repair_logs.new_joint_no = {$weldLogsTable}.no_of_the_joint_as_per_as_built_survey
AND repair_logs.repair_status = 'Repair'
)";
$ndtFields = [
'vt_result',
'rt_result',
'ut_result',
'pt_result',
'mt_result',
'pmi_result',
'ferrite_result',
'ht_result'
];
$ndtFilters = [];
foreach ($ndtFields as $field) {
$ndtFilters[] = "({$weldLogsTable}.{$field} IN ('Accept / Годен', '') OR {$weldLogsTable}.{$field} IS NULL)";
}
$ndtFilter = implode(' AND ', $ndtFilters);
$combinedFilter = "({$repairFilter}) AND ({$ndtFilter})";
$dbSet->AddCustomWhere($combinedFilter);
}
}
+624
View File
@@ -0,0 +1,624 @@
<?php
namespace App\DevExtreme;
class DbSet {
private static $SELECT_OP = "SELECT";
private static $FROM_OP = "FROM";
private static $WHERE_OP = "WHERE";
private static $ORDER_OP = "ORDER BY";
private static $GROUP_OP = "GROUP BY";
private static $ALL_FIELDS = "*";
private static $LIMIT_OP = "LIMIT";
private static $INSERT_OP = "INSERT INTO";
private static $VALUES_OP = "VALUES";
private static $UPDATE_OP = "UPDATE";
private static $SET_OP = "SET";
private static $DELETE_OP = "DELETE";
private static $MAX_ROW_INDEX = 2147483647;
private $dbTableName;
private $tableNameIndex = 0;
private $lastWrappedTableName;
private $resultQuery;
private $mySQL;
private $lastError;
private $groupSettings;
private $customWhereClause = null;
public function __construct($mySQL, $table) {
if (!is_a($mySQL, "\mysqli") || !isset($table)) {
throw new \Exception("Invalid params");
}
$this->mySQL = $mySQL;
$this->dbTableName = $table;
$this->resultQuery = sprintf("%s %s %s %s",
self::$SELECT_OP,
self::$ALL_FIELDS,
self::$FROM_OP,
$this->dbTableName);
}
public function GetLastError() {
return $this->lastError;
}
public function getTableName() {
return $this->dbTableName;
}
private function _WrapQuery() {
$this->tableNameIndex++;
$this->lastWrappedTableName = "{$this->dbTableName}_{$this->tableNameIndex}";
$this->resultQuery = sprintf("%s %s %s (%s) %s %s",
self::$SELECT_OP,
self::$ALL_FIELDS,
self::$FROM_OP,
$this->resultQuery,
AggregateHelper::AS_OP,
$this->lastWrappedTableName);
}
private function _PrepareQueryForLastOperator($operator) {
$operator = trim($operator);
$lastOperatorPos = strrpos($this->resultQuery, " ".$operator." ");
if ($lastOperatorPos !== false) {
$lastBracketPos = strrpos($this->resultQuery, ")");
if (($lastBracketPos !== false && $lastOperatorPos > $lastBracketPos) || ($lastBracketPos === false)) {
$this->_WrapQuery();
}
}
}
public function Select($expression) {
Utils::EscapeExpressionValues($this->mySQL, $expression);
$this->_SelectImpl($expression);
return $this;
}
private function _SelectImpl($expression, $needQuotes = true) {
if (isset($expression)) {
$fields = "";
if (is_string($expression)) {
$expression = explode(",", $expression);
}
if (is_array($expression)) {
foreach ($expression as $field) {
$fields .= (strlen($fields) ? ", " : "").($needQuotes ? Utils::QuoteStringValue(trim($field)) : trim($field));
}
}
if (strlen($fields)) {
$allFieldOperatorPos = strpos($this->resultQuery, self::$ALL_FIELDS);
if ($allFieldOperatorPos == 7) {
$this->resultQuery = substr_replace($this->resultQuery, $fields, 7, strlen(self::$ALL_FIELDS));
}
else {
$this->_WrapQuery();
$this->_SelectImpl($expression);
}
}
}
}
public function Filter($expression) {
Utils::EscapeExpressionValues($this->mySQL, $expression);
if (isset($expression) && is_array($expression)) {
$result = FilterHelper::GetSqlExprByArray($expression);
if (strlen($result)) {
$this->_PrepareQueryForLastOperator(self::$WHERE_OP);
$this->resultQuery .= sprintf(" %s %s",
self::$WHERE_OP,
$result);
}
}
return $this;
}
/**
* Add custom raw SQL WHERE clause
* This is used for complex filters that cannot be expressed via FilterHelper
* @param string $rawWhereClause Raw SQL WHERE clause (without WHERE keyword)
* @return $this
*/
public function AddCustomWhere($rawWhereClause) {
if (isset($rawWhereClause) && strlen(trim($rawWhereClause)) > 0) {
$this->_PrepareQueryForLastOperator(self::$WHERE_OP);
if (stripos($this->resultQuery, " " . self::$WHERE_OP . " ") !== false) {
$this->resultQuery .= sprintf(" AND (%s)",
trim($rawWhereClause));
if ($this->customWhereClause === null) {
$this->customWhereClause = trim($rawWhereClause);
} else {
$this->customWhereClause .= " AND (" . trim($rawWhereClause) . ")";
}
} else {
$this->resultQuery .= sprintf(" %s %s",
self::$WHERE_OP,
trim($rawWhereClause));
$this->customWhereClause = trim($rawWhereClause);
}
}
return $this;
}
public function Sort($expression) {
Utils::EscapeExpressionValues($this->mySQL, $expression);
if (isset($expression)) {
$result = "";
if (is_string($expression)) {
$result = trim($expression);
}
if (is_array($expression)) {
$fieldSet = AggregateHelper::GetFieldSetBySelectors($expression);
$result = $fieldSet["sort"];
}
if (strlen($result)) {
$this->_PrepareQueryForLastOperator(self::$ORDER_OP);
$this->resultQuery .= sprintf(" %s %s",
self::$ORDER_OP,
$result);
}
}
return $this;
}
public function SkipTake($skip, $take) {
$skip = (!isset($skip) || !is_int($skip) ? 0 : $skip);
$take = (!isset($take) || !is_int($take) ? self::$MAX_ROW_INDEX : $take);
if ($skip != 0 || $take != 0) {
$this->_PrepareQueryForLastOperator(self::$LIMIT_OP);
$this->resultQuery .= sprintf(" %s %0.0f, %0.0f",
self::$LIMIT_OP,
$skip,
$take);
}
return $this;
}
/**
* Extract WHERE clause from resultQuery
* @return string WHERE clause without WHERE keyword, or empty string
*/
private function _ExtractWhereClause() {
$whereClause = "";
$wherePos = stripos($this->resultQuery, " " . self::$WHERE_OP . " ");
if ($wherePos !== false) {
$afterWhere = substr($this->resultQuery, $wherePos + strlen(" " . self::$WHERE_OP . " "));
// Find the end of WHERE clause by looking for ORDER BY, GROUP BY, or LIMIT
// Use regex to find the first occurrence of these keywords
$endPattern = '/\s+(ORDER\s+BY|GROUP\s+BY|LIMIT)\s+/i';
if (preg_match($endPattern, $afterWhere, $matches, PREG_OFFSET_CAPTURE)) {
$whereClause = trim(substr($afterWhere, 0, $matches[0][1]));
} else {
$whereClause = trim($afterWhere);
}
}
return $whereClause;
}
/**
* Get distinct values for a specific column
* @param string $columnName Column name to get distinct values from
* @return array Array of distinct values
*/
public function GetDistinctValues($columnName) {
$result = array();
if ($this->mySQL && isset($columnName) && strlen($columnName) > 0) {
Utils::EscapeExpressionValues($this->mySQL, $columnName);
$quotedColumn = Utils::QuoteStringValue($columnName);
// Build the distinct query - use WHERE clause from resultQuery if exists
$distinctQuery = sprintf("%s DISTINCT %s %s %s",
self::$SELECT_OP,
$quotedColumn,
self::$FROM_OP,
$this->dbTableName);
// Extract WHERE clause from resultQuery (after WHERE keyword)
$whereClause = "";
$wherePos = stripos($this->resultQuery, " " . self::$WHERE_OP . " ");
if ($wherePos !== false) {
// Get everything after WHERE
$afterWhere = substr($this->resultQuery, $wherePos + strlen(" " . self::$WHERE_OP . " "));
// Remove ORDER BY, GROUP BY, LIMIT if they exist (find first occurrence)
$endPattern = '/\s+(ORDER\s+BY|GROUP\s+BY|LIMIT)\s+/i';
if (preg_match($endPattern, $afterWhere, $matches, PREG_OFFSET_CAPTURE)) {
$whereClause = trim(substr($afterWhere, 0, $matches[0][1]));
} else {
$whereClause = trim($afterWhere);
}
if (strlen($whereClause) > 0) {
$distinctQuery .= " " . self::$WHERE_OP . " " . $whereClause;
}
}
// Also add customWhereClause if exists (from AddCustomWhere)
if ($this->customWhereClause !== null) {
if (strlen($whereClause) > 0) {
$distinctQuery .= " AND (" . $this->customWhereClause . ")";
} else {
$distinctQuery .= " " . self::$WHERE_OP . " " . $this->customWhereClause;
}
}
// Add ORDER BY for sorted results
$distinctQuery .= sprintf(" %s %s",
self::$ORDER_OP,
$quotedColumn);
// Limit results to prevent memory issues with very large distinct value sets
// If there's a WHERE clause (filtered), we can return more results
// If no filter, limit to first 1000 to prevent UI freezing
$hasFilter = ($wherePos !== false && strlen($whereClause) > 0) || ($this->customWhereClause !== null);
if (!$hasFilter) {
$distinctQuery .= sprintf(" %s 1000",
self::$LIMIT_OP);
}
$this->lastError = NULL;
$sanitizedQuery = $this->_sanitizeDateValues($distinctQuery);
// Debug: Log the query for troubleshooting
error_log("GetDistinctValues SQL: " . $sanitizedQuery);
error_log("GetDistinctValues resultQuery: " . $this->resultQuery);
$queryResult = $this->mySQL->query($sanitizedQuery);
if (!$queryResult) {
$this->lastError = $this->mySQL->error;
error_log("GetDistinctValues query error: " . $this->lastError);
}
else {
while ($row = $queryResult->fetch_array(MYSQLI_NUM)) {
$value = $row[0];
if ($value !== null && $value !== '') {
$result[] = $value;
}
}
$queryResult->close();
error_log("GetDistinctValues found " . count($result) . " distinct values");
}
}
return $result;
}
/**
* Check if there are blank (NULL or empty) values for a specific column
* @param string $columnName Column name to check
* @return bool True if blanks exist, false otherwise
*/
public function HasBlanks($columnName) {
$result = false;
if ($this->mySQL && isset($columnName) && strlen($columnName) > 0) {
Utils::EscapeExpressionValues($this->mySQL, $columnName);
$quotedColumn = Utils::QuoteStringValue($columnName);
// Build the blank check query
$blankQuery = sprintf("%s COUNT(1) %s %s",
self::$SELECT_OP,
self::$FROM_OP,
$this->dbTableName);
// Extract WHERE clause from resultQuery
$wherePos = stripos($this->resultQuery, " " . self::$WHERE_OP . " ");
$blankCondition = sprintf("(%s IS NULL OR %s = '')",
$quotedColumn,
$quotedColumn);
if ($wherePos !== false) {
// Get everything after WHERE
$afterWhere = substr($this->resultQuery, $wherePos + strlen(" " . self::$WHERE_OP . " "));
// Remove ORDER BY, GROUP BY, LIMIT if they exist
$endPattern = '/\s+(ORDER\s+BY|GROUP\s+BY|LIMIT)\s+/i';
if (preg_match($endPattern, $afterWhere, $matches, PREG_OFFSET_CAPTURE)) {
$whereClause = trim(substr($afterWhere, 0, $matches[0][1]));
} else {
$whereClause = trim($afterWhere);
}
if (strlen($whereClause) > 0) {
$blankQuery .= " " . self::$WHERE_OP . " " . $whereClause . " AND " . $blankCondition;
} else {
$blankQuery .= " " . self::$WHERE_OP . " " . $blankCondition;
}
} else {
// No WHERE clause, add blank condition
$blankQuery .= " " . self::$WHERE_OP . " " . $blankCondition;
}
$this->lastError = NULL;
$sanitizedQuery = $this->_sanitizeDateValues($blankQuery);
$queryResult = $this->mySQL->query($sanitizedQuery);
if (!$queryResult) {
$this->lastError = $this->mySQL->error;
}
else if ($queryResult->num_rows > 0) {
$row = $queryResult->fetch_array(MYSQLI_NUM);
$result = Utils::StringToNumber($row[0]) > 0;
$queryResult->close();
}
}
return $result;
}
private function _CreateGroupCountQuery($firstGroupField, $skip = NULL, $take = NULL) {
$groupCount = $this->groupSettings["groupCount"];
$lastGroupExpanded = $this->groupSettings["lastGroupExpanded"];
if (!$lastGroupExpanded) {
if ($groupCount === 2) {
$this->groupSettings["groupItemCountQuery"] = sprintf("%s COUNT(1) %s (%s) AS %s_%d",
self::$SELECT_OP,
self::$FROM_OP,
$this->resultQuery,
$this->dbTableName,
$this->tableNameIndex + 1);
if (isset($skip) || isset($take)) {
$this->SkipTake($skip, $take);
}
}
}
else {
$groupQuery = sprintf("%s COUNT(1) %s %s %s %s",
self::$SELECT_OP,
self::$FROM_OP,
$this->dbTableName,
self::$GROUP_OP,
$firstGroupField);
$this->groupSettings["groupItemCountQuery"] = sprintf("%s COUNT(1) %s (%s) AS %s_%d",
self::$SELECT_OP,
self::$FROM_OP,
$groupQuery,
$this->dbTableName,
$this->tableNameIndex + 1);
if (isset($skip) || isset($take)) {
$this->groupSettings["skip"] = isset($skip) ? Utils::StringToNumber($skip) : 0;
$this->groupSettings["take"] = isset($take) ? Utils::StringToNumber($take) : 0;
}
}
}
public function Group($expression, $groupSummary = NULL, $skip = NULL, $take = NULL) {
Utils::EscapeExpressionValues($this->mySQL, $expression);
Utils::EscapeExpressionValues($this->mySQL, $groupSummary);
$this->groupSettings = NULL;
if (isset($expression)) {
$groupFields = "";
$sortFields = "";
$selectFields = "";
$lastGroupExpanded = true;
$groupCount = 0;
if (is_string($expression)) {
$selectFields = $sortFields = $groupFields = trim($expression);
$groupCount = count(explode(",", $expression));
}
if (is_array($expression)) {
$groupCount = count($expression);
$fieldSet = AggregateHelper::GetFieldSetBySelectors($expression);
$groupFields = $fieldSet["group"];
$selectFields = $fieldSet["select"];
$sortFields = $fieldSet["sort"];
$lastGroupExpanded = AggregateHelper::IsLastGroupExpanded($expression);
}
if ($groupCount > 0) {
if (!$lastGroupExpanded) {
$groupSummaryData = isset($groupSummary) && is_array($groupSummary) ? AggregateHelper::GetSummaryInfo($groupSummary, $this->dbTableName) : NULL;
$selectExpression = sprintf("%s, %s(1)%s",
strlen($selectFields) ? $selectFields : $groupFields,
AggregateHelper::COUNT_OP,
(isset($groupSummaryData) && isset($groupSummaryData["fields"]) && strlen($groupSummaryData["fields"]) ?
", ".$groupSummaryData["fields"] : ""));
$groupCount++;
$this->_WrapQuery();
$this->_SelectImpl($selectExpression, false);
$this->resultQuery .= sprintf(" %s %s",
self::$GROUP_OP,
$groupFields);
$this->Sort($sortFields);
}
else {
$this->_WrapQuery();
$selectExpression = "{$selectFields}, {$this->lastWrappedTableName}.*";
$this->_SelectImpl($selectExpression, false);
$this->resultQuery .= sprintf(" %s %s",
self::$ORDER_OP,
$sortFields);
}
$lastGroupExpanded = true;
$this->groupSettings = array();
$this->groupSettings["groupCount"] = $groupCount;
$this->groupSettings["lastGroupExpanded"] = $lastGroupExpanded;
$this->groupSettings["summaryTypes"] = !$lastGroupExpanded ? $groupSummaryData["summaryTypes"] : NULL;
$firstGroupField = explode(",", $groupFields)[0];
$this->_CreateGroupCountQuery($firstGroupField, $skip, $take);
}
}
return $this;
}
public function GetTotalSummary($expression, $filterExpression = NULL) {
Utils::EscapeExpressionValues($this->mySQL, $expression);
Utils::EscapeExpressionValues($this->mySQL, $filterExpression);
$result = NULL;
if (isset($expression) && is_array($expression)) {
$summaryInfo = AggregateHelper::GetSummaryInfo($expression, $this->dbTableName);
$fields = $summaryInfo["fields"];
if (strlen($fields) > 0) {
$filter = "";
if (isset($filterExpression)) {
if (is_string($filterExpression)) {
$filter = trim($filterExpression);
}
if (is_array($filterExpression)) {
$filter = FilterHelper::GetSqlExprByArray($filterExpression);
}
}
$combinedFilter = "";
if (strlen($filter) > 0 && $this->customWhereClause !== null) {
$combinedFilter = "(" . $filter . ") AND (" . $this->customWhereClause . ")";
} else if (strlen($filter) > 0) {
$combinedFilter = $filter;
} else if ($this->customWhereClause !== null) {
$combinedFilter = $this->customWhereClause;
}
$totalSummaryQuery = sprintf("%s %s %s %s %s",
self::$SELECT_OP,
$fields,
self::$FROM_OP,
$this->dbTableName,
strlen($combinedFilter) > 0 ? self::$WHERE_OP." ".$combinedFilter : "");
$this->lastError = NULL;
$queryResult = $this->mySQL->query($totalSummaryQuery);
if (!$queryResult) {
$this->lastError = $this->mySQL->error;
}
else if ($queryResult->num_rows > 0) {
$result = $queryResult->fetch_array(MYSQLI_NUM);
foreach ($result as $i => $item) {
$result[$i] = Utils::StringToNumber($item);
}
}
if ($queryResult !== false) {
$queryResult->close();
}
}
}
return $result;
}
public function GetGroupCount() {
$result = 0;
if ($this->mySQL && isset($this->groupSettings) && isset($this->groupSettings["groupItemCountQuery"])) {
$this->lastError = NULL;
$queryResult = $this->mySQL->query($this->groupSettings["groupItemCountQuery"]);
if (!$queryResult) {
$this->lastError = $this->mySQL->error;
}
else if ($queryResult->num_rows > 0) {
$row = $queryResult->fetch_array(MYSQLI_NUM);
$result = Utils::StringToNumber($row[0]);
}
if ($queryResult !== false) {
$queryResult->close();
}
}
return $result;
}
public function GetCount() {
$result = 0;
if ($this->mySQL) {
$countQuery = sprintf("%s %s(1) %s (%s) %s %s_%d",
self::$SELECT_OP,
AggregateHelper::COUNT_OP,
self::$FROM_OP,
$this->resultQuery,
AggregateHelper::AS_OP,
$this->dbTableName,
$this->tableNameIndex + 1);
$this->lastError = NULL;
$countQuery = $this->_sanitizeDateValues($countQuery);
$queryResult = $this->mySQL->query($countQuery);
if (!$queryResult) {
$this->lastError = $this->mySQL->error;
}
else if ($queryResult->num_rows > 0) {
$row = $queryResult->fetch_array(MYSQLI_NUM);
$result = Utils::StringToNumber($row[0]);
}
if ($queryResult !== false) {
$queryResult->close();
}
}
return $result;
}
private function _sanitizeDateValues($query) {
return preg_replace("/'0NaN-NaN-NaN'|'\d*NaN-NaN-NaN'/", "NULL", $query);
}
public function AsArray() {
$result = NULL;
if ($this->mySQL) {
$this->lastError = NULL;
$sanitizedQuery = $this->_sanitizeDateValues($this->resultQuery);
$queryResult = $this->mySQL->query($sanitizedQuery);
if (!$queryResult) {
$this->lastError = $this->mySQL->error;
}
else {
if (isset($this->groupSettings)) {
$result = AggregateHelper::GetGroupedDataFromQuery($queryResult, $this->groupSettings);
}
else {
$result = $queryResult->fetch_all(MYSQLI_ASSOC);
}
$queryResult->close();
}
}
return $result;
}
public function Insert($values) {
Utils::EscapeExpressionValues($this->mySQL, $values);
$result = NULL;
if (isset($values) && is_array($values)) {
$fields = "";
$fieldValues = "";
foreach ($values as $prop => $value) {
$fields .= (strlen($fields) ? ", " : "").Utils::QuoteStringValue($prop);
$fieldValues .= (strlen($fieldValues) ? ", " : "").Utils::QuoteStringValue($value, false);
}
if (strlen($fields) > 0) {
$queryString = sprintf("%s %s (%s) %s(%s)",
self::$INSERT_OP,
$this->dbTableName,
$fields,
self::$VALUES_OP,
$fieldValues);
$this->lastError = NULL;
if ($this->mySQL->query($queryString) == true) {
$result = $this->mySQL->affected_rows;
}
else {
$this->lastError = $this->mySQL->error;
}
}
}
return $result;
}
public function Update($key, $values) {
Utils::EscapeExpressionValues($this->mySQL, $key);
Utils::EscapeExpressionValues($this->mySQL, $values);
$result = NULL;
if (isset($key) && is_array($key) && isset($values) && is_array($values)) {
$fields = "";
foreach ($values as $prop => $value) {
$templ = strlen($fields) == 0 ? "%s = %s" : ", %s = %s";
$fields .= sprintf($templ,
Utils::QuoteStringValue($prop),
Utils::QuoteStringValue($value, false));
}
if (strlen($fields) > 0) {
$queryString = sprintf("%s %s %s %s %s %s",
self::$UPDATE_OP,
$this->dbTableName,
self::$SET_OP,
$fields,
self::$WHERE_OP,
FilterHelper::GetSqlExprByKey($key));
$this->lastError = NULL;
if ($this->mySQL->query($queryString) == true) {
$result = $this->mySQL->affected_rows;
}
else {
$this->lastError = $this->mySQL->error;
}
}
}
return $result;
}
public function Delete($key) {
Utils::EscapeExpressionValues($this->mySQL, $key);
$result = NULL;
if (isset($key) && is_array($key)) {
$queryString = sprintf("%s %s %s %s %s",
self::$DELETE_OP,
self::$FROM_OP,
$this->dbTableName,
self::$WHERE_OP,
FilterHelper::GetSqlExprByKey($key));
$this->lastError = NULL;
if ($this->mySQL->query($queryString) == true) {
$result = $this->mySQL->affected_rows;
}
else {
$this->lastError = $this->mySQL->error;
}
}
return $result;
}
}
+242
View File
@@ -0,0 +1,242 @@
<?php
namespace App\DevExtreme;
class FilterHelper {
private static $AND_OP = "AND";
private static $OR_OP = "OR";
private static $LIKE_OP = "LIKE";
private static $NOT_OP = "NOT";
private static $IS_OP = "IS";
private static function _GetSqlFieldName($field) {
$fieldParts = explode(".", $field);
$result = "";
$fieldName = Utils::QuoteStringValue(trim($fieldParts[0]));
if (count($fieldParts) == 2) {
$dateProperty = trim($fieldParts[1]);
$sqlDateFunction = "";
$fieldPattern = "";
switch ($dateProperty) {
case "year":
case "month":
case "day": {
$sqlDateFunction = strtoupper($dateProperty);
$fieldPattern = "%s(%s)";
break;
}
case "dayOfWeek": {
$sqlDateFunction = strtoupper($dateProperty);
$fieldPattern = "%s(%s) - 1";
break;
}
default: {
throw new \Exception("The \"".$dateProperty."\" command is not supported");
}
}
$result = sprintf($fieldPattern, $sqlDateFunction, $fieldName);
}
else {
$result = $fieldName;
}
return $result;
}
private static function _GetSimpleSqlExpr($expression) {
$result = "";
$itemsCount = count($expression);
$fieldName = self::_GetSqlFieldName(trim($expression[0]));
// Known operators list
$knownOperators = ['=', '<>', '>', '>=', '<', '<=', 'startswith', 'endswith', 'contains', 'notcontains', 'in', '==='];
if ($itemsCount == 2) {
$val = $expression[1];
$valLower = is_string($val) ? strtolower(trim($val)) : '';
// Check if second element is an operator (means searching for empty values)
if (in_array($valLower, $knownOperators)) {
// This is an operator without value - treat as empty value search
switch ($valLower) {
case 'contains':
case 'startswith':
case 'endswith':
case '=':
// Search for NULL or empty string
$result = sprintf("(%s IS NULL OR %s = '')", $fieldName, $fieldName);
break;
case '<>':
case 'notcontains':
// Search for NOT NULL and NOT empty
$result = sprintf("(%s IS NOT NULL AND %s != '')", $fieldName, $fieldName);
break;
default:
// For other operators, just check IS NULL
$result = sprintf("%s IS NULL", $fieldName);
break;
}
} elseif ($val === "(Empty)" || $val === "(Boş)" || $val === "") {
$result = sprintf("%s IS NULL", $fieldName);
} else {
$result = sprintf("%s = %s", $fieldName, Utils::QuoteStringValue($val, false));
}
}
else if ($itemsCount == 3) {
$clause = strtolower(trim($expression[1]));
$val = $expression[2];
if ($val === "(Empty)" || $val === "(Boş)" || $val === "" || is_null($val)) {
switch ($clause) {
case "=":
case "contains":
case "startswith":
case "endswith": {
// Hem NULL hem empty string için kontrol
if(strpos($fieldName, 'date') !== false) {
$result = sprintf("(%s IS NULL)", $fieldName);
} else {
$result = sprintf("(%s IS NULL OR %s = '')", $fieldName, $fieldName);
}
return $result;
}
case "<>":
case "notcontains": {
// Ne NULL ne de empty string
$result = sprintf("(%s IS NOT NULL AND %s != '')", $fieldName, $fieldName);
return $result;
}
}
}
else {
switch ($clause) {
case "===": {
// Exact match - DO NOT split comma-separated values
$result = sprintf("%s = %s", $fieldName, Utils::QuoteStringValue($val, false));
return $result;
}
case "=": {
// Exact match - treat comma-separated values as single entity
$pattern = "%s %s %s";
$val = Utils::QuoteStringValue($val, false);
break;
}
case "<>": {
$pattern = "%s %s %s";
$val = Utils::QuoteStringValue($val, false);
break;
}
case ">":
case ">=":
case "<":
case "<=": {
$pattern = "%s %s %s";
$val = Utils::QuoteStringValue($val, false);
break;
}
case "startswith": {
$pattern = "%s %s '%s%%'";
$clause = self::$LIKE_OP;
$val = addcslashes($val, "%_");
break;
}
case "endswith": {
$pattern = "%s %s '%%%s'";
$val = addcslashes($val, "%_");
$clause = self::$LIKE_OP;
break;
}
case "contains": {
$pattern = "%s %s '%%%s%%'";
$val = addcslashes($val, "%_");
$clause = self::$LIKE_OP;
break;
}
case "notcontains": {
$pattern = "%s %s '%%%s%%'";
$val = addcslashes($val, "%_");
$clause = sprintf("%s %s", self::$NOT_OP, self::$LIKE_OP);
break;
}
case "noneof": {
if (is_array($val) && count($val) > 0) {
$quotedValues = array_map(function($v) {
return Utils::QuoteStringValue($v, false);
}, $val);
$result = sprintf("%s NOT IN (%s)", $fieldName, implode(", ", $quotedValues));
return $result;
}
$pattern = "%s <> %s";
$val = Utils::QuoteStringValue($val, false);
break;
}
case "anyof":
case "in": {
if (is_array($val) && count($val) > 0) {
$quotedValues = array_map(function($v) {
return Utils::QuoteStringValue($v, false);
}, $val);
$result = sprintf("%s IN (%s)", $fieldName, implode(", ", $quotedValues));
return $result;
}
// Fall through to default if not array
}
default: {
$clause = $clause ?: "=";
$pattern = "%s %s %s";
if(!is_array($val)) {
$val = Utils::QuoteStringValue($val, false);
}
}
}
}
if(isset($pattern)) {
$result = sprintf($pattern, $fieldName, $clause, $val);
$result = str_replace(" = ''", " is null", $result);
} else {
$result = ""; // Should not happen with new default logic but safe fallback
}
}
return $result;
}
public static function GetSqlExprByArray($expression) {
$result = "(";
$prevItemWasArray = false;
foreach ($expression as $index => $item) {
if (is_string($item)) {
$prevItemWasArray = false;
if ($index == 0) {
if ($item == "!") {
$result .= sprintf("%s ", self::$NOT_OP);
continue;
}
$result .= (isset($expression) && is_array($expression)) ? self::_GetSimpleSqlExpr($expression) : "";
break;
}
$strItem = strtoupper(trim($item));
if ($strItem == self::$AND_OP || $strItem == self::$OR_OP) {
$result .= sprintf(" %s ", $strItem);
}
continue;
}
if (is_array($item)) {
if ($prevItemWasArray) {
$result .= sprintf(" %s ", self::$AND_OP);
}
$result .= self::GetSqlExprByArray($item);
$prevItemWasArray = true;
}
}
$result .= ")";
return $result;
}
public static function GetSqlExprByKey($key) {
$result = "";
foreach ($key as $prop => $value) {
$templ = strlen($result) == 0 ?
"%s = %s" :
" ".self::$AND_OP." %s = %s";
$result .= sprintf($templ,
Utils::QuoteStringValue($prop),
Utils::QuoteStringValue($value, false));
}
return $result;
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App\DevExtreme;
class LoadHelper {
public static function LoadModule($className) {
$namespaceNamePos = strpos($className, __NAMESPACE__);
if ($namespaceNamePos === 0) {
$subFolderPath = substr($className, $namespaceNamePos + strlen(__NAMESPACE__));
$filePath = __DIR__.str_replace("\\", DIRECTORY_SEPARATOR, $subFolderPath).".php";
require_once($filePath);
}
}
}
+19
View File
@@ -0,0 +1,19 @@
<?php
namespace App\DevExtreme;
class SummaryContext
{
protected static bool $excludeMechanical = false;
public static function setExcludeMechanical(bool $flag): void
{
self::$excludeMechanical = $flag;
}
public static function shouldExcludeMechanical(): bool
{
return self::$excludeMechanical;
}
}
+66
View File
@@ -0,0 +1,66 @@
<?php
namespace App\DevExtreme;
class Utils {
private static $NULL_VAL = "NULL";
private static $FORBIDDEN_CHARACTERS = array(
"`", "\"", "'", "~", "!", "@", "#", "\$",
"%", "=", "[", "]", "\\", "/" , "|", "^",
"&", "*", "(", ")", "+", "<", ">", ",", "{",
"}", "?", ":", ";", "\r", "\n"
);
public static function StringToNumber($str) {
$currentLocale = localeconv();
$decimalPoint = $currentLocale["decimal_point"];
$result = strpos($str, $decimalPoint) === false ? intval($str) : floatval($str);
return $result;
}
public static function EscapeExpressionValues($mySql, &$expression = NULL) {
if (isset($expression)) {
if (is_string($expression)) {
$expression = $mySql->real_escape_string($expression);
}
else if (is_array($expression)) {
foreach ($expression as &$arr_value) {
self::EscapeExpressionValues($mySql, $arr_value);
}
unset($arr_value);
}
else if (gettype($expression) === "object") {
foreach ($expression as $prop => $value) {
self::EscapeExpressionValues($mySql, $expression->$prop);
}
}
}
}
public static function QuoteStringValue($value, $isFieldName = true) {
if (!$isFieldName) {
$value = self::_ConvertDateTimeToMySQLValue($value);
} else {
$value = str_replace(self::$FORBIDDEN_CHARACTERS, "", $value);
}
$resultPattern = $isFieldName ? "`%s`" : (is_bool($value) || is_null($value) ? "%s" : "'%s'");
$stringValue = is_bool($value) ? ($value ? "1" : "0") : (is_null($value) ? self::$NULL_VAL : strval($value));
$result = sprintf($resultPattern, $stringValue);
return $result;
}
public static function GetItemValueOrDefault($params, $key, $defaultValue = NULL) {
return isset($params[$key]) ? $params[$key] : $defaultValue;
}
private static function _ConvertDatePartToISOValue($date) {
$dateParts = explode("/", $date);
return sprintf("%s-%s-%s", $dateParts[2], $dateParts[0], $dateParts[1]);
}
private static function _ConvertDateTimeToMySQLValue($strValue) {
$result = $strValue;
if (preg_match("/^\d{1,2}\/\d{1,2}\/\d{4}$/", $strValue) === 1) {
$result = self::_ConvertDatePartToISOValue($strValue);
}
else if (preg_match("/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}\.\d{3}$/", $strValue) === 1) {
$spacePos = strpos($strValue, " ");
$datePart = substr($strValue, 0, $spacePos);
$timePart = substr($strValue, $spacePos + 1);
$result = sprintf("%s %s", self::_ConvertDatePartToISOValue($datePart), $timePart);
}
return $result;
}
}