extended firefly import options, cleaned up language usage in code, new README in english, changed license references
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
co-authored by
Copilot
parent
90dc37cafc
commit
a6ed05a38a
+180
-39
@@ -18,7 +18,7 @@ use UbsCsvTransformer\ConfigurationLoader;
|
||||
use UbsCsvTransformer\FireflyImporter;
|
||||
|
||||
// ============================================================================
|
||||
// CLI-Argument-Verarbeitung
|
||||
// CLI argument processing
|
||||
// ============================================================================
|
||||
|
||||
$argc = $_SERVER['argc'] ?? 0;
|
||||
@@ -29,10 +29,10 @@ if ($argc < 2) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Debug-Modus aktivierbar
|
||||
// Debug mode can be enabled
|
||||
$debug = in_array('--debug', $argv) || in_array('-d', $argv);
|
||||
|
||||
// Extrahiere Kommando
|
||||
// Extract command
|
||||
$command = $argv[1];
|
||||
|
||||
try {
|
||||
@@ -54,11 +54,26 @@ try {
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Zeige Hilfe und Verwendungsanleitung
|
||||
* Returns true when the active shell locale is German (de_*)
|
||||
*/
|
||||
function isGermanLocale(): bool
|
||||
{
|
||||
foreach (['LANG', 'LC_ALL', 'LC_MESSAGES', 'LANGUAGE'] as $var) {
|
||||
$val = getenv($var);
|
||||
if ($val !== false && $val !== '') {
|
||||
return str_starts_with(strtolower($val), 'de');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show help and usage instructions
|
||||
*/
|
||||
function showHelp(): void
|
||||
{
|
||||
echo <<<'HELP'
|
||||
if (isGermanLocale()) {
|
||||
echo <<<'HELP_DE'
|
||||
╔════════════════════════════════════════════════════════════════════════════╗
|
||||
║ Firefly Import Preprocessor - Kommandozeilen-Tool ║
|
||||
║ ║
|
||||
@@ -170,26 +185,150 @@ KONFIGURATION:
|
||||
|
||||
DOKUMENTATION:
|
||||
|
||||
Siehe README.md und UBS_Transformer_Guide.md für vollständige Dokumentation
|
||||
Siehe README.md für vollständige Dokumentation
|
||||
|
||||
LIZENZ:
|
||||
|
||||
MIT License
|
||||
GPL 3
|
||||
|
||||
HELP;
|
||||
HELP_DE;
|
||||
return;
|
||||
}
|
||||
|
||||
echo <<<'HELP_EN'
|
||||
╔════════════════════════════════════════════════════════════════════════════╗
|
||||
║ Firefly Import Preprocessor - Command Line Tool ║
|
||||
║ ║
|
||||
║ A lightweight PHP 8 tool for transforming UBS E-Banking exports ║
|
||||
║ into a Firefly III compatible format. ║
|
||||
╚════════════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
USAGE:
|
||||
transformer [command] [options]
|
||||
|
||||
COMMANDS:
|
||||
|
||||
test [input] [config] [options]
|
||||
Tests the transformation with a limited number of rows
|
||||
Options:
|
||||
--rows=N Process only N rows (default: 10)
|
||||
--output=FILE, -o Also write result to file
|
||||
Example:
|
||||
transformer test ubs-export.csv config.json --rows=5
|
||||
transformer test ubs-export.csv config.json -o test-output.csv
|
||||
|
||||
transform [input] [config] [options]
|
||||
Transforms a complete CSV file
|
||||
Options:
|
||||
--output=FILE, -o Output path (default: input-transformed.csv)
|
||||
--no-import Do not automatically import into Firefly III
|
||||
Example:
|
||||
transformer transform ubs-export.csv config.json
|
||||
transformer transform ubs-export.csv config.json -o import.csv
|
||||
|
||||
validate [config] [options]
|
||||
Validates the configuration file
|
||||
Options:
|
||||
--strict Strict validation (recommended)
|
||||
Example:
|
||||
transformer validate config.json
|
||||
transformer validate config.json --strict
|
||||
|
||||
auto-import [config] [options]
|
||||
Monitors source directory and processes new files
|
||||
Options:
|
||||
--watch Continuous monitoring (daemon mode)
|
||||
--interval=SEC Check interval in seconds (default: 60)
|
||||
--dry-run Show what would be done (no actual processing)
|
||||
Example:
|
||||
transformer auto-import config.json
|
||||
transformer auto-import config.json --watch --interval=30
|
||||
|
||||
help, -h, --help
|
||||
Show this help
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--debug, -d Enable debug mode (detailed output)
|
||||
|
||||
INSTALLATION:
|
||||
|
||||
1. PHP 8.1+ must be installed
|
||||
php --version
|
||||
|
||||
2. Autoloader setup (choose one):
|
||||
Option A: With Composer (recommended)
|
||||
composer install
|
||||
Option B: Manual - files in directory structure:
|
||||
ff-imp-preprocessor/
|
||||
├── bin/transformer.php
|
||||
├── src/*.php
|
||||
└── config/config.json
|
||||
|
||||
3. Make executable:
|
||||
chmod +x bin/transformer.php
|
||||
|
||||
4. Adjust configuration:
|
||||
cp config/config.example.json config/config.json
|
||||
nano config/config.json
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
# Test transformation (first 5 rows)
|
||||
./bin/transformer test data/ubs-export.csv config/config.json --rows=5
|
||||
|
||||
# Full transformation
|
||||
./bin/transformer transform data/ubs-export.csv config/config.json \
|
||||
--output=output/firefly-import.csv
|
||||
|
||||
# Validate configuration
|
||||
./bin/transformer validate config/config.json --strict
|
||||
|
||||
# Start auto-import with monitoring
|
||||
./bin/transformer auto-import config/config.json --watch
|
||||
|
||||
# Process only next file
|
||||
./bin/transformer auto-import config/config.json
|
||||
|
||||
CONFIGURATION:
|
||||
|
||||
The config.json must have the following structure:
|
||||
{
|
||||
"metadata": { "extractionRules": {...} },
|
||||
"csvStructure": { "delimiter": ";", ... },
|
||||
"columnTransformations": { ... },
|
||||
"fireflyImport": { "apiUrl": "...", "apiKey": "..." },
|
||||
"directories": {
|
||||
"source": "./import/source",
|
||||
"output": "./import/output",
|
||||
"archive": "./import/archive",
|
||||
"error": "./import/error"
|
||||
}
|
||||
}
|
||||
|
||||
DOCUMENTATION:
|
||||
|
||||
See README.md for full documentation
|
||||
|
||||
LICENSE:
|
||||
|
||||
GPL 3
|
||||
|
||||
HELP_EN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expandiert ~ zu absolutem Home-Verzeichnis und löst relative Pfade auf
|
||||
* Expands ~ to absolute home directory and resolves relative paths
|
||||
*/
|
||||
function expandPath(string $path): string
|
||||
{
|
||||
if (str_starts_with($path, '~/') || $path === '~') {
|
||||
$home = getenv('HOME') ?: posix_getpwuid(posix_getuid())['dir'];
|
||||
$path = $home . substr($path, 1);
|
||||
$homeEnv = getenv('HOME');
|
||||
$pwInfo = posix_getpwuid(posix_getuid());
|
||||
$home = $homeEnv !== false && $homeEnv !== '' ? $homeEnv : ($pwInfo !== false ? $pwInfo['dir'] : '~');
|
||||
$path = $home . substr($path, 1);
|
||||
}
|
||||
|
||||
// Relative Pfade gegen cwd auflösen (ohne realpath, damit nicht-existierende Dirs erlaubt sind)
|
||||
// Resolve relative paths against cwd (without realpath, so non-existent dirs are allowed)
|
||||
if (!str_starts_with($path, '/')) {
|
||||
$path = getcwd() . '/' . $path;
|
||||
}
|
||||
@@ -198,7 +337,7 @@ function expandPath(string $path): string
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse CLI-Optionen in assoziatives Array
|
||||
* Parses CLI options into an associative array
|
||||
*/
|
||||
function parseOptions(array $argv, int $startIndex = 0): array
|
||||
{
|
||||
@@ -217,9 +356,9 @@ function parseOptions(array $argv, int $startIndex = 0): array
|
||||
}
|
||||
|
||||
/**
|
||||
* Teste Transformation mit begrenzter Zeilenzahl
|
||||
* Tests transformation with a limited number of rows
|
||||
*/
|
||||
function handleTest($argc, $argv): void
|
||||
function handleTest(int $argc, array $argv): void
|
||||
{
|
||||
if ($argc < 4) {
|
||||
throw new Exception("Usage: transformer test [input-file] [config-file] [options]");
|
||||
@@ -234,10 +373,10 @@ function handleTest($argc, $argv): void
|
||||
$outputFile = $options['output'] ?? $options['o'] ?? null;
|
||||
|
||||
if (!file_exists($inputFile)) {
|
||||
throw new Exception("Input-Datei nicht gefunden: $inputFile");
|
||||
throw new Exception("Input file not found: $inputFile");
|
||||
}
|
||||
if (!file_exists($configFile)) {
|
||||
throw new Exception("Konfigurationsdatei nicht gefunden: $configFile");
|
||||
throw new Exception("Configuration file not found: $configFile");
|
||||
}
|
||||
|
||||
echo "\n📊 TEST-MODUS: Verarbeite max. $maxRows Zeilen\n";
|
||||
@@ -292,9 +431,9 @@ function handleTest($argc, $argv): void
|
||||
}
|
||||
|
||||
/**
|
||||
* Transformiere komplette CSV-Datei
|
||||
* Transforms a complete CSV file
|
||||
*/
|
||||
function handleTransform($argc, $argv): void
|
||||
function handleTransform(int $argc, array $argv): void
|
||||
{
|
||||
if ($argc < 4) {
|
||||
throw new Exception("Usage: transformer transform [input-file] [config-file] [options]");
|
||||
@@ -308,10 +447,10 @@ function handleTransform($argc, $argv): void
|
||||
$outputFile = $options['output'] ?? $options['o'] ?? null;
|
||||
|
||||
if (!file_exists($inputFile)) {
|
||||
throw new Exception("Input-Datei nicht gefunden: $inputFile");
|
||||
throw new Exception("Input file not found: $inputFile");
|
||||
}
|
||||
if (!file_exists($configFile)) {
|
||||
throw new Exception("Konfigurationsdatei nicht gefunden: $configFile");
|
||||
throw new Exception("Configuration file not found: $configFile");
|
||||
}
|
||||
|
||||
echo "\n🚀 TRANSFORMATION STARTEN\n";
|
||||
@@ -320,7 +459,7 @@ function handleTransform($argc, $argv): void
|
||||
$configLoader = new ConfigurationLoader($configFile);
|
||||
$configLoader->load();
|
||||
|
||||
// --output überschreibt Zielverzeichnis und Dateiname aus der Konfiguration
|
||||
// --output overrides target directory and filename from configuration
|
||||
if ($outputFile !== null) {
|
||||
$outputFile = expandPath($outputFile);
|
||||
$configLoader->set('directories.output', dirname($outputFile));
|
||||
@@ -338,9 +477,9 @@ function handleTransform($argc, $argv): void
|
||||
}
|
||||
|
||||
/**
|
||||
* Validiere Konfigurationsdatei
|
||||
* Validates the configuration file
|
||||
*/
|
||||
function handleValidate($argc, $argv): void
|
||||
function handleValidate(int $argc, array $argv): void
|
||||
{
|
||||
if ($argc < 3) {
|
||||
throw new Exception("Usage: transformer validate [config-file] [options]");
|
||||
@@ -351,7 +490,7 @@ function handleValidate($argc, $argv): void
|
||||
$strict = isset($options['strict']);
|
||||
|
||||
if (!file_exists($configFile)) {
|
||||
throw new Exception("Konfigurationsdatei nicht gefunden: $configFile");
|
||||
throw new Exception("Configuration file not found: $configFile");
|
||||
}
|
||||
|
||||
echo "\n✔️ KONFIGURATION VALIDIEREN\n";
|
||||
@@ -362,7 +501,7 @@ function handleValidate($argc, $argv): void
|
||||
try {
|
||||
$config = $configLoader->load();
|
||||
|
||||
// Basis-Validierung
|
||||
// Basic validation
|
||||
echo "✅ JSON-Format valide\n";
|
||||
|
||||
$required = ['metadata', 'csvStructure', 'columnTransformations'];
|
||||
@@ -377,7 +516,7 @@ function handleValidate($argc, $argv): void
|
||||
}
|
||||
}
|
||||
|
||||
// Firefly-Validierung
|
||||
// Firefly validation
|
||||
if (isset($config['fireflyImport'])) {
|
||||
echo "✅ Firefly III Konfiguration vorhanden\n";
|
||||
if (empty($config['fireflyImport']['apiUrl'])) {
|
||||
@@ -396,7 +535,7 @@ function handleValidate($argc, $argv): void
|
||||
echo "⚠️ Firefly III Konfiguration nicht vorhanden (optional)\n";
|
||||
}
|
||||
|
||||
// Verzeichnisse-Validierung
|
||||
// Directory validation
|
||||
if (isset($config['directories'])) {
|
||||
echo "✅ Verzeichnisse konfiguriert\n";
|
||||
$dirs = ['source', 'output', 'archive', 'error'];
|
||||
@@ -416,14 +555,14 @@ function handleValidate($argc, $argv): void
|
||||
echo "\n⚠️ Konfiguration hat Warnungen aber ist funktional\n\n";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Validierungsfehler: " . $e->getMessage());
|
||||
throw new Exception("Validation error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-Import mit Verzeichnis-Überwachung
|
||||
* Auto-import with directory monitoring
|
||||
*/
|
||||
function handleAutoImport($argc, $argv): void
|
||||
function handleAutoImport(int $argc, array $argv): void
|
||||
{
|
||||
if ($argc < 3) {
|
||||
throw new Exception("Usage: transformer auto-import [config-file] [options]");
|
||||
@@ -434,7 +573,7 @@ function handleAutoImport($argc, $argv): void
|
||||
$debug = isset($options['debug']) || isset($options['d']);
|
||||
|
||||
if (!file_exists($configFile)) {
|
||||
throw new Exception("Konfigurationsdatei nicht gefunden: $configFile");
|
||||
throw new Exception("Configuration file not found: $configFile");
|
||||
}
|
||||
|
||||
$configLoader = new ConfigurationLoader($configFile);
|
||||
@@ -448,7 +587,7 @@ function handleAutoImport($argc, $argv): void
|
||||
$watch = isset($options['watch']);
|
||||
$interval = isset($options['interval']) ? (int)$options['interval'] : 60;
|
||||
|
||||
// Verzeichnisse erstellen
|
||||
// Create directories
|
||||
foreach ([$sourceDir, $outputDir, $archiveDir, $errorDir] as $dir) {
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0755, true);
|
||||
@@ -476,7 +615,9 @@ function handleAutoImport($argc, $argv): void
|
||||
|
||||
if ($watch) {
|
||||
echo "⏳ Drücke Ctrl+C zum Beenden.\n\n";
|
||||
while (true) {
|
||||
$running = true;
|
||||
/** @phpstan-ignore while.alwaysTrue (intentional infinite loop — terminated only via Ctrl+C / SIGINT) */
|
||||
while ($running) {
|
||||
processImportDirectory($sourceDir, $outputDir, $archiveDir, $errorDir, $config, $configFile, $dryRun, $debug);
|
||||
sleep($interval);
|
||||
}
|
||||
@@ -486,9 +627,9 @@ function handleAutoImport($argc, $argv): void
|
||||
}
|
||||
|
||||
/**
|
||||
* Verarbeite Verzeichnis mit CSV-Dateien
|
||||
* Processes directory containing CSV files
|
||||
*/
|
||||
function processImportDirectory($sourceDir, $outputDir, $archiveDir, $errorDir, $config, $configFile, $dryRun = false, $debug = false): void
|
||||
function processImportDirectory(string $sourceDir, string $outputDir, string $archiveDir, string $errorDir, array $config, string $configFile, bool $dryRun = false, bool $debug = false): void
|
||||
{
|
||||
if (!is_dir($sourceDir)) {
|
||||
return;
|
||||
@@ -516,10 +657,10 @@ function processImportDirectory($sourceDir, $outputDir, $archiveDir, $errorDir,
|
||||
$result = $engine->transform($file);
|
||||
$outputFile = $result['outputFile'] ?? $outputFile;
|
||||
|
||||
// Archiviere Original-Datei
|
||||
// Archive original file
|
||||
$archiveFile = $archiveDir . '/' . $basename;
|
||||
if (!rename($file, $archiveFile)) {
|
||||
throw new Exception("Konnte nicht archivieren");
|
||||
throw new Exception("Could not archive file");
|
||||
}
|
||||
|
||||
// Firefly Import
|
||||
@@ -534,7 +675,7 @@ function processImportDirectory($sourceDir, $outputDir, $archiveDir, $errorDir,
|
||||
echo "❌ " . $e->getMessage() . "\n";
|
||||
|
||||
if (!$dryRun) {
|
||||
// Verschiebe zu Error-Verzeichnis
|
||||
// Move to error directory
|
||||
$errorFile = $errorDir . '/' . $basename;
|
||||
@rename($file, $errorFile);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user