Kufrik/app/Model/Sdf/SdfCompactExporter.php

107 lines
3.3 KiB
PHP

<?php
namespace App\Model\Sdf;
use Nette\Utils\FileSystem;
use Nette\Utils\Json;
class SdfCompactExporter
{
public function __construct(
private string $scriptPath,
private string $sdfPassword
) {
}
/**
* Přečte SQL Compact .sdf a vrátí tabulky jako pole.
*
* @return array{uzivatel: array, zakaznik: array, faktura: array, polozka: array, platba: array}
*/
public function export(string $sdfPath): array
{
if (!is_file($sdfPath)) {
throw new \RuntimeException('SDF soubor nebyl nalezen.');
}
if (!is_file($this->scriptPath)) {
throw new \RuntimeException('Exportní skript bin/sdf-export.ps1 chybí.');
}
$workDir = dirname($sdfPath) . DIRECTORY_SEPARATOR . 'export-' . bin2hex(random_bytes(4));
FileSystem::createDir($workDir);
$outFile = $workDir . DIRECTORY_SEPARATOR . 'export.json';
try {
$this->runPowershell($sdfPath, $outFile);
$raw = FileSystem::read($outFile);
$data = Json::decode($raw, forceArrays: true);
if (!is_array($data)) {
throw new \RuntimeException('Export SDF nevrátil platná data.');
}
return [
'uzivatel' => $data['uzivatel'] ?? [],
'zakaznik' => $data['zakaznik'] ?? [],
'faktura' => $data['faktura'] ?? [],
'polozka' => $data['polozka'] ?? [],
'platba' => $data['platba'] ?? [],
];
} finally {
FileSystem::delete($workDir);
}
}
private function runPowershell(string $sdfPath, string $outFile): void
{
$powershell = $this->findPowershell();
$cmd = sprintf(
'%s -NoProfile -NonInteractive -ExecutionPolicy Bypass -File %s -SdfPath %s -OutFile %s -Password %s',
$this->winArg($powershell),
$this->winArg($this->scriptPath),
$this->winArg($sdfPath),
$this->winArg($outFile),
$this->winArg($this->sdfPassword)
);
$descriptor = [
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
];
$process = proc_open($cmd, $descriptor, $pipes, null, null, ['bypass_shell' => false]);
if (!is_resource($process)) {
throw new \RuntimeException('Nepodařilo se spustit PowerShell pro čtení SDF.');
}
$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$code = proc_close($process);
if ($code !== 0 || !is_file($outFile)) {
$detail = trim($stderr . "\n" . $stdout);
throw new \RuntimeException('Export SDF selhal' . ($detail !== '' ? ': ' . $detail : '.'));
}
}
private function findPowershell(): string
{
$candidates = [
getenv('SystemRoot') . '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe',
'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe',
];
foreach ($candidates as $path) {
if ($path && is_file($path)) {
return $path;
}
}
return 'powershell.exe';
}
private function winArg(string $value): string
{
return '"' . str_replace('"', '\\"', $value) . '"';
}
}