335 lines
11 KiB
PHP
335 lines
11 KiB
PHP
<?php
|
||
// PHP'nin maksimum çalışma süresini artır
|
||
set_time_limit(0); // Sınırsız çalışma süresi ayarla
|
||
ini_set('memory_limit', '512M'); // Bellek limitini artır
|
||
|
||
use Symfony\Component\Process\Process;
|
||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||
use Illuminate\Support\Facades\Artisan;
|
||
|
||
// .env dosyasından veritabanı bilgilerini alın
|
||
$user = env("DB_USERNAME");
|
||
$password = env("DB_PASSWORD");
|
||
$database = env("DB_DATABASE");
|
||
$delimiter = ";";
|
||
if(!getesit("delimiter", ""))
|
||
{
|
||
$delimiter = get("delimiter");
|
||
}
|
||
|
||
|
||
if(getesit("file_type", "xlsx"))
|
||
{
|
||
$delimiter = "\t";
|
||
}
|
||
|
||
// Eğer veritabanı bilgileri boş gelirse yapılandırma önbelleğini temizle
|
||
if (empty($user) || empty($password) || empty($database)) {
|
||
// Config cache'i temizle
|
||
Artisan::call('config:clear');
|
||
|
||
// Cache temizlendikten sonra tekrar env değerlerini al
|
||
$user = env("DB_USERNAME");
|
||
$password = env("DB_PASSWORD");
|
||
$database = env("DB_DATABASE");
|
||
}
|
||
|
||
$columns = "*";
|
||
// Bu alanlar Excel'de metin olarak kalmalı (ör: 1/1 gibi değerler için)
|
||
$forceStringFields = [
|
||
'quantity_of_iso',
|
||
'outer_diameter_1',
|
||
'outer_diameter_2',
|
||
'wall_thickness_1',
|
||
'wall_thickness_2',
|
||
'total_wdi',
|
||
'total_complated_wdi',
|
||
'total_shop_wdi',
|
||
'total_complated_shop_wdi',
|
||
'total_field_wdi',
|
||
'total_complated_field_wdi',
|
||
'remaining_wdi',
|
||
'fluid_code',
|
||
'diameter',
|
||
];
|
||
|
||
// Bu alanlar decimal değerlerini virgüllü formatta export etmeli
|
||
$forceVirgulFields = [
|
||
'nps_1',
|
||
'nps_2',
|
||
];
|
||
|
||
if(!getesit("columns", ""))
|
||
{
|
||
|
||
$columns = get("columns");
|
||
$columns = base64_decode($columns);
|
||
|
||
// Sütunları virgülle ayır
|
||
$columnsArray = explode(',', $columns);
|
||
|
||
// Sütun adlarını tırnak içine al
|
||
$columnsArray = array_map(function($column) {
|
||
$column = trim($column);
|
||
return "COALESCE(`" . $column . "`, '') $column"; // Sütun adlarını tırnak içine al
|
||
}, $columnsArray);
|
||
|
||
// Tırnak içine alınmış sütunları tekrar virgüllerle birleştir
|
||
$columns = implode(',', $columnsArray);
|
||
|
||
}
|
||
|
||
$tableName = get("table_name");
|
||
$moduleFileName = get("module");
|
||
|
||
// Apply employer view filters for weldlog-employer-view module
|
||
$whereClause = "";
|
||
if($moduleFileName === 'weldlog-employer-view' && $tableName === 'weld_logs') {
|
||
// Filter 1: Exclude records with repair_status = 'Repair' in repair_logs
|
||
$repairFilter = "NOT EXISTS (
|
||
SELECT 1 FROM repair_logs
|
||
WHERE repair_logs.iso_number = weld_logs.iso_number
|
||
AND repair_logs.new_joint_no = weld_logs.no_of_the_joint_as_per_as_built_survey
|
||
AND repair_logs.repair_status = 'Repair'
|
||
)";
|
||
|
||
// Filter 2: Only acceptable NDT results (Accept / Годен, empty, or NULL)
|
||
$ndtFields = [
|
||
'vt_result',
|
||
'rt_result',
|
||
'ut_result',
|
||
'pt_result',
|
||
'mt_result',
|
||
'pmi_result',
|
||
'ferrite_result',
|
||
'ht_result'
|
||
];
|
||
|
||
$ndtFilters = [];
|
||
foreach ($ndtFields as $field) {
|
||
$ndtFilters[] = "({$field} IN ('Accept / Годен', '') OR {$field} IS NULL)";
|
||
}
|
||
|
||
$ndtFilter = implode(' AND ', $ndtFilters);
|
||
|
||
$whereClause = " WHERE ({$repairFilter}) AND ({$ndtFilter})";
|
||
}
|
||
|
||
// Create standardized filename: "ProjectCode_ModuleName_Date_Time"
|
||
$projectNumber = setting('project_number') ?: 'QMS';
|
||
$currentDateTime = now();
|
||
$dateStr = $currentDateTime->format('d.m.Y');
|
||
$timeStr = $currentDateTime->format('H.i');
|
||
$fileName = $projectNumber . '_' . $moduleFileName . '_' . $dateStr . '_' . $timeStr;
|
||
|
||
|
||
// Kayıt yapılacak dosya yolu
|
||
$csvPath = storage_path($fileName . '.csv');
|
||
@unlink($csvPath);
|
||
|
||
// MySQL komutunu tanımlayın (sudo olmadan)
|
||
$query = "SELECT $columns FROM $tableName" . $whereClause;
|
||
|
||
// İsteğe bağlı olarak çok büyük veri setlerinde LIMIT eklemek isteyebilirsiniz
|
||
// Kullanıcı arayüzünden bir limit parametresi alabilir veya varsayılan bir limit belirleyebilirsiniz
|
||
$limit = get("limit", 0); // Varsayılan olarak 0 (tüm veriyi getirir)
|
||
if ($limit > 0) {
|
||
$query .= " LIMIT $limit";
|
||
}
|
||
$query .= ";";
|
||
|
||
// CSV dosyasını başlat
|
||
file_put_contents($csvPath, "\xEF\xBB\xBF"); // UTF-8 BOM
|
||
|
||
// Excel uyumluluğu için tüm alanları tırnak içine al
|
||
$excelCompatible = true;
|
||
|
||
// Doğrudan mysql komutunu çalıştırarak sonuçları CSV formatında alacağız
|
||
$mysqlCmd = "/usr/bin/mysql -u " . escapeshellarg($user) .
|
||
" -p" . escapeshellarg($password) .
|
||
" -D " . escapeshellarg($database) .
|
||
" --default-character-set=utf8mb4" .
|
||
" -B" . // Batch mode (tab-separated)
|
||
" -N" . // No column names
|
||
" -e " . escapeshellarg("SET NAMES utf8mb4; $query") .
|
||
" 2>/dev/null";
|
||
|
||
// mysql komutunu çalıştır ve sonuçları satır satır oku
|
||
$mysqlHandle = popen($mysqlCmd, 'r');
|
||
|
||
// Sütun adlarını ayarlamak için işlem yapalım
|
||
$csvHeaderColumns = [];
|
||
|
||
if(!getesit("columns", "")) {
|
||
// Özel sütun seçimi varsa, bu sütunların adlarını kullan
|
||
$headerColumnsArr = explode(',', base64_decode(get("columns")));
|
||
|
||
// Sütun adlarını temizle (COALESCE ifadelerini kaldır)
|
||
foreach($headerColumnsArr as $colName) {
|
||
$colName = trim($colName);
|
||
// COALESCE(`column`, '') column formatındaysa, sadece column kısmını al
|
||
if(preg_match('/^.*`([^`]+)`.*$/', $colName, $matches)) {
|
||
$csvHeaderColumns[] = $matches[1];
|
||
} else {
|
||
// Değilse doğrudan ismi kullan
|
||
$csvHeaderColumns[] = $colName;
|
||
}
|
||
}
|
||
} else {
|
||
// Tüm sütunları kullanıyorsa, veritabanından al
|
||
$tableInfoCmd = "/usr/bin/mysql -u " . escapeshellarg($user) .
|
||
" -p" . escapeshellarg($password) .
|
||
" -D " . escapeshellarg($database) .
|
||
" --default-character-set=utf8mb4" .
|
||
" -e " . escapeshellarg("SHOW COLUMNS FROM $tableName") .
|
||
" 2>/dev/null";
|
||
|
||
// Sütun adlarını al
|
||
exec($tableInfoCmd, $columnInfoOutput);
|
||
|
||
// İlk satırı atla (başlık satırı)
|
||
for ($i = 1; $i < count($columnInfoOutput); $i++) {
|
||
$parts = preg_split('/\s+/', trim($columnInfoOutput[$i]), 2);
|
||
if (!empty($parts[0])) {
|
||
$csvHeaderColumns[] = $parts[0];
|
||
}
|
||
}
|
||
}
|
||
// Sütun adlarını CSV dosyasına yaz
|
||
if (!empty($csvHeaderColumns)) {
|
||
// CSV formatında tırnak kullanarak başlık satırını oluştur
|
||
// fputcsv ile güvenli CSV header yazma (otomatik escaping)
|
||
$csvFile = fopen($csvPath, 'a');
|
||
fputcsv($csvFile, $csvHeaderColumns, $delimiter, '"');
|
||
fclose($csvFile);
|
||
}
|
||
|
||
// Verileri satır satır oku ve dosyaya yaz
|
||
while (($line = fgets($mysqlHandle)) !== false) {
|
||
// Satırın sonundaki satır sonu karakterini kaldır
|
||
$line = rtrim($line);
|
||
|
||
// Satırı tab karakterlerine göre böl
|
||
$fields = explode("\t", $line);
|
||
|
||
// Tarih formatlarını düzelt ve decimal alanları virgüllü yap
|
||
foreach ($fields as $i => &$field) {
|
||
// Eğer bu alan forceStringFields içindeyse, değeri ="değer" olarak yaz
|
||
if (isset($csvHeaderColumns[$i]) && in_array($csvHeaderColumns[$i], $forceStringFields)) {
|
||
$field = '="' . str_replace('"', '""', $field) . '"';
|
||
}
|
||
// Eğer bu alan forceVirgulFields içindeyse, decimal değerleri virgüllü yap
|
||
elseif (isset($csvHeaderColumns[$i]) && in_array($csvHeaderColumns[$i], $forceVirgulFields)) {
|
||
if (!empty($field) && is_numeric($field) && strpos($field, '.') !== false) {
|
||
$field = str_replace('.', ',', $field);
|
||
}
|
||
} else {
|
||
// Tarih formatını değiştir
|
||
$field = preg_replace_callback(
|
||
'/^(\d{4})-(\d{2})-(\d{2})$/',
|
||
function ($matches) {
|
||
return $matches[3] . '.' . $matches[2] . '.' . $matches[1]; // dd.mm.yyyy formatına
|
||
},
|
||
$field
|
||
);
|
||
}
|
||
}
|
||
|
||
$fields = str_replace("\\\\", "\\", $fields);
|
||
|
||
// fputcsv ile güvenli CSV yazma (otomatik escaping - sütun kaymasını önler)
|
||
$csvFile = fopen($csvPath, 'a');
|
||
fputcsv($csvFile, $fields, $delimiter, '"');
|
||
fclose($csvFile);
|
||
}
|
||
|
||
// mysql process'i kapat
|
||
pclose($mysqlHandle);
|
||
|
||
$fileType = "csv";
|
||
if(getesit("file_type", "xlsx"))
|
||
{
|
||
// XLSX dönüşümü öncesi belleği temizle
|
||
gc_collect_cycles();
|
||
|
||
try {
|
||
// LibreOffice ile CSV'den XLSX'e dönüştürme
|
||
$outputDir = storage_path();
|
||
$outputFilename = "$fileName.xlsx";
|
||
|
||
// LibreOffice için filtreleme seçenekleri:
|
||
// 9 = Tab karakteri ayırıcı olarak kullanıldığını belirt
|
||
// 0 = Metin sınırlayıcı karakteri kullanılmadığını belirt (veya ihtiyaca göre değiştirilebilir)
|
||
// 76 = Karakter seti (UTF-8)
|
||
// 1 = İlk satır başlık
|
||
$shellCmd = "libreoffice --headless --infilter=\"Text - txt - csv (StarCalc):9,0,76,1\" --convert-to xlsx --outdir " .
|
||
escapeshellarg($outputDir) . " " . escapeshellarg($csvPath) . " 2>&1";
|
||
|
||
// Komutu çalıştır
|
||
$output = [];
|
||
$returnCode = 0;
|
||
exec($shellCmd, $output, $returnCode);
|
||
|
||
// Hata kontrolü
|
||
if ($returnCode !== 0) {
|
||
throw new Exception("LibreOffice conversion failed: " . implode("\n", $output));
|
||
}
|
||
|
||
// LibreOffice dönüştürme işlemi tamamlandıktan sonra, dosyanın doğru adını bulalım
|
||
$csvBaseName = basename($csvPath);
|
||
$csvFileNameWithoutExt = pathinfo($csvBaseName, PATHINFO_FILENAME);
|
||
$expectedXlsxPath = $outputDir . '/' . $csvFileNameWithoutExt . '.xlsx';
|
||
|
||
// Eğer beklenen dosya yoksa, orijinal dosya adıyla tekrar deneyelim
|
||
if (!file_exists($expectedXlsxPath)) {
|
||
$expectedXlsxPath = $outputDir . '/' . $fileName . '.xlsx';
|
||
}
|
||
|
||
// Son dosya yolunu saklayalım
|
||
$xlsxOutputPath = $expectedXlsxPath;
|
||
$fileType = "xlsx";
|
||
|
||
} catch (Exception $e) {
|
||
// XLSX dönüşümü başarısız olursa, CSV dosyasını sunalım
|
||
$xlsxResult = ['error' => $e->getMessage()];
|
||
$fileType = "csv";
|
||
}
|
||
}
|
||
|
||
// CSV dosyasını kontrol et - çok büyükse bile LibreOffice ile dönüştürmeyi dene
|
||
$fileSize = filesize($csvPath);
|
||
$maxSize = 100 * 1024 * 1024; // 100MB - LibreOffice daha büyük dosyaları işleyebilir
|
||
|
||
// Çok büyük dosyalar için uyarı logla ama yine de dönüştürmeyi dene
|
||
if ($fileSize > $maxSize && $fileType == "xlsx") {
|
||
// Büyük dosya işleme durumunu loglayabilirsiniz
|
||
error_log("Warning: Processing large file ($fileName.csv) of size " . round($fileSize / (1024 * 1024), 2) . " MB");
|
||
}
|
||
|
||
if(isset($xlsxResult['error']))
|
||
{
|
||
// Hata durumunda CSV dosyasını sun
|
||
error_log("XLSX conversion error: " . $xlsxResult['error']);
|
||
yonlendir(url("storage/$fileName.csv"));
|
||
} else {
|
||
if ($fileType == "xlsx") {
|
||
// Dosya adından storage path kısmını çıkar, sadece relatif yolu ve dosya adını al
|
||
$relativePath = str_replace(storage_path(), '', $xlsxOutputPath);
|
||
// Başındaki slash'ı kaldır
|
||
$relativePath = ltrim($relativePath, '/');
|
||
yonlendir(url("storage/$relativePath"));
|
||
} else {
|
||
yonlendir(url("storage/$fileName.$fileType"));
|
||
}
|
||
}
|
||
|
||
// İşlem tamamlandıktan sonra belleği temizle
|
||
gc_collect_cycles();
|
||
|
||
// Geçici dosyaları temizle
|
||
if ($fileType == "xlsx" && file_exists($csvPath)) {
|
||
@unlink($csvPath); // XLSX oluşturulduysa CSV'yi silebiliriz
|
||
}
|
||
|
||
?>
|