281 lines
8.1 KiB
PHP
281 lines
8.1 KiB
PHP
<?php
|
||
|
||
/**
|
||
* Excel dosyasını PDF'e dönüştüren fonksiyon
|
||
*
|
||
* @param string $xlsx Excel dosyasının tam yolu
|
||
* @param string $pdf_dir PDF çıktısının kaydedileceği dizin
|
||
* @param array $options Ek seçenekler (timeout, log_level vb.)
|
||
* @return array Dönüşüm sonucu bilgileri
|
||
* @throws Exception Hata durumunda
|
||
*/
|
||
function xlsx_to_pdf($xlsx, $pdf_dir, $options = []) {
|
||
|
||
// PDF cache bypass: Dizin içerisinde mevcut aynı isimli PDF varsa siliyoruz ve tekrardan oluşturacak
|
||
$pdf_output_path = rtrim($pdf_dir, '/\\') . DIRECTORY_SEPARATOR . basename(pathinfo($xlsx, PATHINFO_FILENAME)) . '.pdf';
|
||
if (file_exists($pdf_output_path)) {
|
||
@unlink($pdf_output_path);
|
||
}
|
||
|
||
|
||
// Varsayılan seçenekler
|
||
$defaults = [
|
||
'timeout' => 300, // 5 dakika timeout
|
||
'log_level' => 'info',
|
||
'create_backup' => true,
|
||
'validate_input' => true,
|
||
'cleanup_temp' => true
|
||
];
|
||
|
||
$options = array_merge($defaults, $options);
|
||
|
||
try {
|
||
// Giriş parametrelerini doğrula
|
||
if ($options['validate_input']) {
|
||
validate_xlsx_to_pdf_inputs($xlsx, $pdf_dir);
|
||
}
|
||
|
||
// Çıktı dizinini oluştur
|
||
create_output_directory($pdf_dir);
|
||
|
||
// LibreOffice komutunu hazırla
|
||
$command = build_libreoffice_command($xlsx, $pdf_dir);
|
||
|
||
// Komutu çalıştır
|
||
$result = execute_conversion_command($command, $options['timeout']);
|
||
|
||
// Sonucu işle
|
||
$output = process_conversion_output($result);
|
||
|
||
// Başarı logu
|
||
log_conversion_success($xlsx, $pdf_dir, $output);
|
||
|
||
return [
|
||
'success' => true,
|
||
'output_file' => $output,
|
||
'message' => 'Dönüşüm başarıyla tamamlandı',
|
||
'timestamp' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
} catch (Exception $e) {
|
||
// Hata logu
|
||
log_conversion_error($xlsx, $pdf_dir, $e->getMessage());
|
||
|
||
return [
|
||
'success' => false,
|
||
'error' => $e->getMessage(),
|
||
'timestamp' => date('Y-m-d H:i:s')
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Giriş parametrelerini doğrular
|
||
*/
|
||
function validate_xlsx_to_pdf_inputs($xlsx, $pdf_dir) {
|
||
// Excel dosyasının varlığını kontrol et
|
||
if (!file_exists($xlsx)) {
|
||
throw new Exception("Excel dosyası bulunamadı: {$xlsx}");
|
||
}
|
||
|
||
// Excel dosyasının okunabilir olduğunu kontrol et
|
||
if (!is_readable($xlsx)) {
|
||
throw new Exception("Excel dosyası okunamıyor: {$xlsx}");
|
||
}
|
||
|
||
// Dosya uzantısını kontrol et
|
||
$extension = strtolower(pathinfo($xlsx, PATHINFO_EXTENSION));
|
||
if (!in_array($extension, ['xlsx', 'xls'])) {
|
||
throw new Exception("Geçersiz dosya formatı. Sadece .xlsx ve .xls dosyaları desteklenir.");
|
||
}
|
||
|
||
// PDF dizininin yazılabilir olduğunu kontrol et
|
||
if (file_exists($pdf_dir) && !is_writable($pdf_dir)) {
|
||
throw new Exception("PDF çıktı dizini yazılabilir değil: {$pdf_dir}");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Çıktı dizinini oluşturur
|
||
*/
|
||
function create_output_directory($pdf_dir) {
|
||
if (!is_dir($pdf_dir)) {
|
||
if (!mkdir($pdf_dir, 0755, true)) {
|
||
throw new Exception("PDF çıktı dizini oluşturulamadı: {$pdf_dir}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* LibreOffice komutunu oluşturur
|
||
*/
|
||
function build_libreoffice_command($xlsx, $pdf_dir) {
|
||
// Güvenli komut oluşturma
|
||
$xlsx_escaped = escapeshellarg($xlsx);
|
||
$pdf_dir_escaped = escapeshellarg($pdf_dir);
|
||
|
||
// LibreOffice komutunu oluştur (environment variable'ları export ile set et)
|
||
$command = sprintf(
|
||
'export LANG=en_US.UTF-8 && sudo -u root libreoffice --headless --convert-to pdf --outdir %s %s 2>&1',
|
||
$pdf_dir_escaped,
|
||
$xlsx_escaped
|
||
);
|
||
|
||
return $command;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* Dönüşüm komutunu çalıştırır
|
||
*/
|
||
function execute_conversion_command($command, $timeout) {
|
||
// Basit shell_exec kullanarak komutu çalıştır (proc_open ile environment variable sorunu var)
|
||
$output = shell_exec($command);
|
||
|
||
// Hata kontrolü - shell_exec null dönerse komut çalışmamış demektir
|
||
if ($output === null) {
|
||
throw new Exception("LibreOffice komutu çalıştırılamadı. Komut: " . $command);
|
||
}
|
||
|
||
// LibreOffice çıktısında hata var mı kontrol et
|
||
if (strpos($output, 'Error') !== false || strpos($output, 'error') !== false) {
|
||
throw new Exception("LibreOffice dönüşüm hatası: " . trim($output));
|
||
}
|
||
|
||
// Çıktı boş mu kontrol et
|
||
if (empty(trim($output))) {
|
||
throw new Exception("LibreOffice çıktısı boş. Komut başarısız olmuş olabilir.");
|
||
}
|
||
|
||
return $output;
|
||
}
|
||
|
||
|
||
/**
|
||
* Dönüşüm çıktısını işler
|
||
*/
|
||
function process_conversion_output($shell_output) {
|
||
// Çıktıyı temizle
|
||
$output = extract_between_markers_pdf($shell_output);
|
||
|
||
if (is_null($output)) {
|
||
$output = trim($shell_output);
|
||
}
|
||
|
||
return $output;
|
||
}
|
||
|
||
/**
|
||
* Başarılı dönüşüm logu
|
||
*/
|
||
function log_conversion_success($xlsx, $pdf_dir, $output) {
|
||
$log_message = sprintf(
|
||
"[SUCCESS] Excel to PDF conversion completed - File: %s, Output: %s, Result: %s",
|
||
$xlsx,
|
||
$pdf_dir,
|
||
$output
|
||
);
|
||
|
||
error_log($log_message);
|
||
}
|
||
|
||
/**
|
||
* Dönüşüm hatası logu
|
||
*/
|
||
function log_conversion_error($xlsx, $pdf_dir, $error_message) {
|
||
$log_message = sprintf(
|
||
"[ERROR] Excel to PDF conversion failed - File: %s, Output: %s, Error: %s",
|
||
$xlsx,
|
||
$pdf_dir,
|
||
$error_message
|
||
);
|
||
|
||
error_log($log_message);
|
||
}
|
||
|
||
/**
|
||
* PDF marker'ları arasındaki içeriği çıkarır
|
||
*
|
||
* @param string $input_str LibreOffice çıktısı
|
||
* @return string|null Çıkarılan içeriği veya null
|
||
*/
|
||
function extract_between_markers_pdf($input_str) {
|
||
// PDF export marker'ları arasındaki içeriği bul
|
||
// Excel dosyaları Writer olarak algılanabilir, bu yüzden her iki filter'ı da kontrol et
|
||
$patterns = [
|
||
'/->\s*(.*?)\s*using filter : calc_pdf_Export/', // Calc (spreadsheet) için
|
||
'/->\s*(.*?)\s*using filter : writer_pdf_Export/', // Writer (document) için
|
||
'/convert\s+(.*?)\s+as\s+a\s+(.*?)\s+->\s+(.*?)\s+using filter : (.*?)_Export/' // Genel pattern
|
||
];
|
||
|
||
foreach ($patterns as $pattern) {
|
||
if (preg_match($pattern, $input_str, $matches)) {
|
||
// İlk pattern için dosya yolu, ikinci için de dosya yolu, üçüncü için tam çıktı
|
||
if (count($patterns) === 3 && $pattern === $patterns[2]) {
|
||
return trim($matches[3]); // PDF dosya yolu
|
||
}
|
||
return trim($matches[1]); // Dosya yolu
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Eski fonksiyon için geriye uyumluluk
|
||
* @deprecated Bu fonksiyon artık kullanılmamalı, xlsx_to_pdf() kullanın
|
||
*/
|
||
function xlsx_to_pdf_legacy($xlsx, $pdf_dir) {
|
||
trigger_error(
|
||
'xlsx_to_pdf_legacy() fonksiyonu deprecated. xlsx_to_pdf() kullanın.',
|
||
E_USER_DEPRECATED
|
||
);
|
||
|
||
$result = xlsx_to_pdf($xlsx, $pdf_dir);
|
||
|
||
if ($result['success']) {
|
||
return $result['output_file'];
|
||
}
|
||
|
||
return $result['error'];
|
||
}
|
||
|
||
function xlsx_to_pdf2($xlsx, $pdf_dir) {
|
||
// Ensure the LANG environment variable is set
|
||
putenv('LANG=ru_RU.UTF-8');
|
||
|
||
// Ensure the output directory exists
|
||
if (!is_dir($pdf_dir)) {
|
||
mkdir($pdf_dir, 0777, true);
|
||
}
|
||
// Construct the command
|
||
$command = "sudo -u root libreoffice --headless --convert-to pdf --outdir '" . ($pdf_dir) . "' '" . ($xlsx) . "' ";
|
||
// Execute the command
|
||
$shellOutput = shell_exec("$command 2>&1");
|
||
$output = extract_between_markers_pdf($shellOutput);
|
||
if(is_null($output)) {
|
||
$output = $shellOutput;
|
||
}
|
||
return $output;
|
||
}
|
||
|
||
function extract_between_markers_pdf2($input_str) {
|
||
// Define the regular expression pattern to match the content between the markers
|
||
$pattern = '/->\s*(.*?)\s*using filter : calc_pdf_Export/';
|
||
|
||
// Perform the regex match
|
||
if (preg_match($pattern, $input_str, $matches)) {
|
||
// Return the matched content
|
||
return $matches[1];
|
||
}
|
||
|
||
// Return null if no match is found
|
||
return null;
|
||
}
|
||
|