diff --git a/CHANGELOG.md b/CHANGELOG.md index 857cc5ab..81d229f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,30 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/spec/v2.0.0.ht --- +## [2.42.2] — 2026-09-17 + +Der Batch-Import trennte Schlagworte an Kommas — das Formular tut das ausdrücklich nicht. + +### 🐛 Fixed +- **Import und Formular widersprachen sich bei Schlagworten mit Komma.** Das Formular warnt + seit jeher: „Trennen Sie die Schlagwörter nicht mit Komma" — ein Komma darf Teil eines + Schlagworts sein (z. B. „Berlin, Stadt"). Der Batch-Import spaltete dieselbe Eingabe aber an + Komma **und** Zeilenumbruch. Dieselben Rohdaten ergaben je nach Weg ein anderes Ergebnis, und + ein per Komma geschriebenes Schlagwort landete beim Veröffentlichen unbemerkt als mehrere + `dcat:keyword`-Werte statt einem. Aufgefallen an den eigenen Beispieldateien: `"Demografie, + Statistik"` wurde beim Import zu zwei Schlagworten, im Formular wäre es eines geblieben. Der + Import trennt jetzt wie das Formular ausschließlich an Zeilenumbrüchen; mehrere Zeilen passen + in eine CSV-Zelle, wenn sie in Anführungszeichen steht (Excel/LibreOffice schreiben das beim + Export automatisch so). +- **`samples/import-example.csv` und `.json` gingen mit schlechtem Beispiel voran** — beide + nutzten kommagetrennte Schlagworte. Auf Zeilentrennung umgestellt. + +Tests: ein bestehender Test verlangte die alte, falsche Form (Komma spaltet) und ist jetzt auf +das richtige Verhalten umgestellt; ein neuer Test hält fest, dass ein Komma innerhalb eines +Schlagworts erhalten bleibt. + +--- + ## [2.42.1] — 2026-09-17 Der empfohlene Harvest-Endpunkt lieferte Turtle, das **kein RDF-Parser lesen konnte** — und diff --git a/CLAUDE.md b/CLAUDE.md index 2054e6d5..12b7af7c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -765,7 +765,7 @@ Update **both** locations: - MINOR: New features (backward-compatible) - PATCH: Bug fixes only -Current: **v2.42.1** +Current: **v2.42.2** --- diff --git a/README.md b/README.md index 80445a26..93b8157d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

Lizenz - Version + Version DCAT-AP 3.0 PHP >= 8.1 WordPress 6.4+ @@ -149,7 +149,7 @@ Importiere mehrere Datensätze auf einmal aus CSV oder JSON Dateien. Der Import- - `language` — Sprache (z.B. de, en) - `format` — Dateiformat (z.B. CSV, JSON, PDF) - `issued` — Veröffentlichungsdatum -- `keywords` — Schlagworte (komma-getrennt) +- `keywords` — Schlagworte (eine pro Zeile, wie im Formular — kein Komma als Trenner: In eine CSV-Zelle passen mehrere Zeilen, wenn sie in Anführungszeichen steht) - `byte_size` — Dateigröße in Bytes (nur ganze Zahl; abweichende Werte werden als Fehler markiert) - `attribution` — Namensnennungstext diff --git a/includes/class-batch-import.php b/includes/class-batch-import.php index f4302da4..48a7fe89 100644 --- a/includes/class-batch-import.php +++ b/includes/class-batch-import.php @@ -489,9 +489,18 @@ private static function create_dataset_from_record( array $record, int $row_inde if ( 'byte_size' === $field ) { $value = (string) absint( $value ); } elseif ( 'keywords' === $field ) { - // Schlagworte werden intern zeilengetrennt gespeichert. Import - // erlaubt Komma- ODER Zeilentrennung — beides zu Zeilen normalisieren. - $split = preg_split( '/[\r\n,]+/', self::neutralize_formula( $value ) ); + // Schlagworte werden intern zeilengetrennt gespeichert — genau wie + // im Formular, das ausdrücklich vor Kommas warnt (ein Komma im + // Schlagwort ist zulässig, z. B. „Berlin, Stadt"). Bis v2.42.1 + // spaltete der Import zusätzlich an Kommas: Dieselbe Eingabe ergab + // im Formular ein Schlagwort, im Import zwei — und ein via Komma + // geschriebenes Schlagwort landete im veröffentlichten JSON-LD als + // mehrere `dcat:keyword`-Werte, ohne dass jemand das so eingegeben + // hätte. Nur noch Zeilenumbrüche trennen; ein Komma bleibt Teil des + // Schlagworts. Mehrere Zeilen in einer CSV-Zelle: Feld in + // Anführungszeichen setzen, Zeilenumbrüche darin bleiben erhalten + // (Excel/LibreOffice tun das beim Export automatisch). + $split = preg_split( '/[\r\n]+/', self::neutralize_formula( $value ) ); $parts = array_values( array_filter( array_map( 'trim', is_array( $split ) ? $split : array() ), diff --git a/open-data-wizard.php b/open-data-wizard.php index 58d971e5..daa86f7d 100644 --- a/open-data-wizard.php +++ b/open-data-wizard.php @@ -3,7 +3,7 @@ * Plugin Name: Open Data Wizard * Plugin URI: https://github.com/daimpad/OpenDataWizard * Description: DCAT-AP 3.0 konforme Open Data Metadatenverwaltung für WordPress. Bereitstellung als maschinenlesbarer JSON-LD-Endpoint für offene Daten. - * Version: 2.42.1 + * Version: 2.42.2 * Requires at least: 6.4 * Requires PHP: 8.1 * Author: nozilla @@ -26,7 +26,7 @@ exit; } -define( 'ODW_VERSION', '2.42.1' ); +define( 'ODW_VERSION', '2.42.2' ); define( 'ODW_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'ODW_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); define( 'ODW_PLUGIN_FILE', __FILE__ ); diff --git a/package.json b/package.json index 0976c398..eb90a12d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-data-wizard", - "version": "2.42.1", + "version": "2.42.2", "description": "WordPress plugin for publishing open data as DCAT-AP 3.0 compliant metadata", "author": "Open Data Wizard Team", "license": "GPL-2.0-or-later", diff --git a/samples/import-example.csv b/samples/import-example.csv index 663368d9..54691951 100644 --- a/samples/import-example.csv +++ b/samples/import-example.csv @@ -1,6 +1,13 @@ title,publisher,description,access_url,license,theme,language,format,issued,keywords -"Bevölkerungszahlen 2024","Statistisches Amt","Bevölkerungszahlen nach Stadt und Jahr für 2024","https://example.com/data/population-2024.csv","cc-by","SOCI","de","CSV","2024-01-15","Demografie, Statistik" -"Arbeitslosenquoten 2024","Arbeitsamt","Monatliche Arbeitslosenquoten nach Bundesland","https://example.com/data/unemployment.xlsx","cc0","ECON","de","XLSX","2024-02-01","Beschäftigung, Wirtschaft" -"Schulstandorte","Bildungsministerium","Verzeichnis aller öffentlichen Schulen mit Adressen","https://example.com/data/schools.geojson","cc-by-sa","EDUC","de","GeoJSON","2024-01-01","Schulen, Bildung, Geolocation" -"Breitbandverfügbarkeit","Telekommunikationsbehörde","Verfügbarkeit von Breitbandanbindung nach Postleitzahl","https://example.com/data/broadband.csv","cc0","TECH","de","CSV","2024-03-01","Internet, Infrastruktur" -"Energieverbrauch nach Sektor 2023","Energieamt","Jährlicher Energieverbrauch nach Wirtschaftssektor","https://example.com/data/energy.json","cc-by","ENVI","de","JSON","2023-12-31","Energie, Umwelt, Statistik" +"Bevölkerungszahlen 2024","Statistisches Amt","Bevölkerungszahlen nach Stadt und Jahr für 2024","https://example.com/data/population-2024.csv","cc-by","SOCI","de","CSV","2024-01-15","Demografie +Statistik" +"Arbeitslosenquoten 2024","Arbeitsamt","Monatliche Arbeitslosenquoten nach Bundesland","https://example.com/data/unemployment.xlsx","cc0","ECON","de","XLSX","2024-02-01","Beschäftigung +Wirtschaft" +"Schulstandorte","Bildungsministerium","Verzeichnis aller öffentlichen Schulen mit Adressen","https://example.com/data/schools.geojson","cc-by-sa","EDUC","de","GeoJSON","2024-01-01","Schulen +Bildung +Geolocation" +"Breitbandverfügbarkeit","Telekommunikationsbehörde","Verfügbarkeit von Breitbandanbindung nach Postleitzahl","https://example.com/data/broadband.csv","cc0","TECH","de","CSV","2024-03-01","Internet +Infrastruktur" +"Energieverbrauch nach Sektor 2023","Energieamt","Jährlicher Energieverbrauch nach Wirtschaftssektor","https://example.com/data/energy.json","cc-by","ENVI","de","JSON","2023-12-31","Energie +Umwelt +Statistik" diff --git a/samples/import-example.json b/samples/import-example.json index 180c7cb7..20c91b3a 100644 --- a/samples/import-example.json +++ b/samples/import-example.json @@ -9,7 +9,7 @@ "language": "de", "format": "CSV", "issued": "2024-01-15", - "keywords": "Demografie, Statistik" + "keywords": "Demografie\nStatistik" }, { "title": "Arbeitslosenquoten 2024", @@ -21,7 +21,7 @@ "language": "de", "format": "XLSX", "issued": "2024-02-01", - "keywords": "Beschäftigung, Wirtschaft" + "keywords": "Beschäftigung\nWirtschaft" }, { "title": "Schulstandorte", @@ -33,7 +33,7 @@ "language": "de", "format": "GeoJSON", "issued": "2024-01-01", - "keywords": "Schulen, Bildung, Geolocation" + "keywords": "Schulen\nBildung\nGeolocation" }, { "title": "Breitbandverfügbarkeit", @@ -45,7 +45,7 @@ "language": "de", "format": "CSV", "issued": "2024-03-01", - "keywords": "Internet, Infrastruktur" + "keywords": "Internet\nInfrastruktur" }, { "title": "Energieverbrauch nach Sektor 2023", @@ -57,6 +57,6 @@ "language": "de", "format": "JSON", "issued": "2023-12-31", - "keywords": "Energie, Umwelt, Statistik" + "keywords": "Energie\nUmwelt\nStatistik" } ] diff --git a/tests/test-batch-import.php b/tests/test-batch-import.php index 18dad755..4e397786 100644 --- a/tests/test-batch-import.php +++ b/tests/test-batch-import.php @@ -509,21 +509,40 @@ public function test_import_maps_license_short_code_to_https_uri(): void { } /** - * Keywords may arrive comma- or newline-separated; internally they are - * stored one per line. + * Keywords are stored one per line — only newlines separate them, exactly + * like the form field. Blank lines in between are dropped. */ public function test_import_normalises_keywords_to_one_per_line(): void { $meta = array(); $this->mock_import_environment( $meta ); $record = $this->valid_record( 'Mit Schlagworten' ); - $record['keywords'] = 'Bäume, Umwelt ,, Klima'; + $record['keywords'] = "Bäume\n\nUmwelt\n \nKlima"; ODW_Batch_Import::import_records( array( $record ) ); $this->assertSame( "Bäume\nUmwelt\nKlima", $meta['_odw_keywords'] ); } + /** + * A comma inside a keyword must survive the import — it is not a + * separator here. Until v2.42.1 the import split on commas too, so the + * same value produced one keyword via the form but several via import, + * and a genuinely comma-containing keyword (e.g. „Berlin, Stadt") was + * silently split into two `dcat:keyword` values on publish. + */ + public function test_import_keeps_comma_within_a_single_keyword(): void { + $meta = array(); + $this->mock_import_environment( $meta ); + + $record = $this->valid_record( 'Komma im Schlagwort' ); + $record['keywords'] = 'Demografie, Statistik'; + + ODW_Batch_Import::import_records( array( $record ) ); + + $this->assertSame( 'Demografie, Statistik', $meta['_odw_keywords'] ); + } + /** * A failing wp_insert_post() is counted and reported with its row number * instead of aborting the whole import.