diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d6465f..7992ff6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/spec/v2.0.0.ht --- +## [2.17.0] — 2026-07-09 + +### ✨ Added +- **Datei per Link ODER Upload** (Datenbereitstellung): Das Zugriffs-URL-Feld heißt jetzt + „Ergänzen Sie den Link zu Ihrem Datensatz oder laden Sie die Datei in die Mediathek hoch". Wer eine + Datei über die Mediathek-Box hochlädt, muss die URL **nicht** mehr eintippen — Zugriffs-URL und + Format werden beim Speichern automatisch aus der Datei übernommen. Pflichtprüfung ist erfüllt, + sobald **entweder** ein Link eingetragen **oder** eine Datei hochgeladen wurde. +- **„Auf dem Datenatlas Zivilgesellschaft veröffentlichen"** (optional): Im letzten Wizard-Schritt + (Vorschau) verlinkt ein Button auf [datenatlas-zivilgesellschaft.de](https://datenatlas-zivilgesellschaft.de). + +--- + ## [2.16.0] — 2026-07-08 ### ✨ Changed diff --git a/README.md b/README.md index 8ced30d..16cfd90 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ![PHP Version](https://img.shields.io/badge/PHP-%3E%3D%208.1-8892BF?style=flat-square&logo=php&logoColor=white) ![WordPress](https://img.shields.io/badge/WordPress-compatible-21759B?style=flat-square&logo=wordpress&logoColor=white) ![DCAT-AP](https://img.shields.io/badge/DCAT--AP-3.0-brightgreen?style=flat-square) -![Version](https://img.shields.io/badge/Version-2.16.0-brightgreen?style=flat-square) +![Version](https://img.shields.io/badge/Version-2.17.0-brightgreen?style=flat-square) ![PRs Welcome](https://img.shields.io/badge/PRs-willkommen-brightgreen?style=flat-square) 📖 [Dokumentation](DOCUMENTATION.md) · 📐 [Technische Spezifikation](TECHNICAL-SPEC.md) · 📝 [Changelog](CHANGELOG.md) · 🛡️ [Security](SECURITY.md) · ⚖️ [Lizenz](LICENSE) diff --git a/assets/css/admin.css b/assets/css/admin.css index 54f2d00..8df5bba 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -857,3 +857,17 @@ color: #a0a5aa; font-style: italic; } + +/* ========================================================================= + Datenatlas Zivilgesellschaft — Veröffentlichen-Abschnitt (Tab 5) + ========================================================================= */ + +.odw-datenatlas-publish { + margin-top: 20px; + padding-top: 16px; + border-top: 1px solid var(--odw-color-border, #c3c4c7); +} + +.odw-datenatlas-publish h4 { + font-size: 14px; +} diff --git a/includes/class-admin.php b/includes/class-admin.php index 42f9cd3..d82387a 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -544,10 +544,29 @@ public static function save_file_attachment( int $post_id, \WP_Post $post ): voi update_post_meta( $post_id, '_odw_file_id', $file_id ); if ( $file_id > 0 ) { + $ext = ''; $file_path = get_attached_file( $file_id ); if ( $file_path && file_exists( $file_path ) ) { update_post_meta( $post_id, '_odw_file_size', (int) filesize( $file_path ) ); - update_post_meta( $post_id, '_odw_file_format', strtoupper( (string) pathinfo( $file_path, PATHINFO_EXTENSION ) ) ); + $ext = strtoupper( (string) pathinfo( $file_path, PATHINFO_EXTENSION ) ); + update_post_meta( $post_id, '_odw_file_format', $ext ); + } + + // A media-library upload doubles as the distribution: derive the + // access URL (and format) from the file when the user did not enter + // them manually, so they never have to type the URL twice. + if ( '' === trim( (string) get_post_meta( $post_id, '_odw_access_url', true ) ) ) { + $attachment_url = wp_get_attachment_url( $file_id ); + if ( $attachment_url ) { + update_post_meta( $post_id, '_odw_access_url', esc_url_raw( $attachment_url ) ); + } + } + + if ( '' !== $ext + && '' === trim( (string) get_post_meta( $post_id, '_odw_format', true ) ) + && array() !== ODW_Fields::get_format_meta( $ext ) + ) { + update_post_meta( $post_id, '_odw_format', $ext ); } } else { delete_post_meta( $post_id, '_odw_file_size' ); diff --git a/includes/class-fields.php b/includes/class-fields.php index d76c038..9d7776d 100644 --- a/includes/class-fields.php +++ b/includes/class-fields.php @@ -126,11 +126,10 @@ private static function register_required_fields(): void { ->add_tab( __( '3 — Datenbereitstellung', 'open-data-wizard' ), array( - Field::make( 'text', 'odw_access_url', __( 'Wo kann ich die Datei herunterladen?', 'open-data-wizard' ) ) - ->set_required( true ) + Field::make( 'text', 'odw_access_url', __( 'Ergänzen Sie den Link zu Ihrem Datensatz oder laden Sie die Datei in die Mediathek hoch', 'open-data-wizard' ) ) ->set_attribute( 'placeholder', 'https://beispiel.de/daten/datei.csv' ) ->set_attribute( 'type', 'url' ) - ->set_help_text( __( 'ZUGRIFFS-URL (dcat:accessURL)', 'open-data-wizard' ) . "\n\n" . __( 'Beispiel: https://beispiel.de/daten/datei.csv', 'open-data-wizard' ) ), + ->set_help_text( __( 'ZUGRIFFS-URL (dcat:accessURL)', 'open-data-wizard' ) . "\n\n" . __( 'Zwei Wege — einer genügt: Tragen Sie hier den Link zu Ihrer Datei ein ODER laden Sie die Datei in der Box „Download-Datei (Mediathek)" hoch. Bei einem Upload wird die URL beim Speichern automatisch übernommen; dieses Feld können Sie dann leer lassen.', 'open-data-wizard' ) ), Field::make( 'select', 'odw_format', __( 'In welchem Format ist die Datei?', 'open-data-wizard' ) ) ->add_options( self::get_format_options() ) @@ -416,6 +415,16 @@ private static function register_required_fields(): void { array( Field::make( 'html', 'odw_preview_html' ) ->set_html( self::get_preview_html() ), + + Field::make( 'html', 'odw_datenatlas_publish' ) + ->set_html( + '
' + . '

' . esc_html__( 'Auf dem Datenatlas Zivilgesellschaft veröffentlichen', 'open-data-wizard' ) . '

' + . '

' . esc_html__( 'Optional: Machen Sie diesen Datensatz zusätzlich auf dem Datenatlas Zivilgesellschaft auffindbar.', 'open-data-wizard' ) . '

' + . '' + . esc_html__( 'Zum Datenatlas Zivilgesellschaft', 'open-data-wizard' ) . ' ↗' + . '
' + ), ) ); } diff --git a/includes/class-validation.php b/includes/class-validation.php index ed1ab3d..1fd217b 100644 --- a/includes/class-validation.php +++ b/includes/class-validation.php @@ -162,7 +162,21 @@ private static function has_valid_distribution( int $post_id, array $cf_input ): // Fall back to existing meta. $access_url = (string) carbon_get_post_meta( $post_id, 'odw_access_url' ); - return ! empty( $access_url ) && self::is_valid_url( $access_url ); + if ( ! empty( $access_url ) && self::is_valid_url( $access_url ) ) { + return true; + } + + // A media-library upload also counts as a valid distribution — its access + // URL is derived from the file on save (see ODW_Admin::save_file_attachment). + $file_id = (int) get_post_meta( $post_id, '_odw_file_id', true ); + if ( 0 === $file_id + && isset( $_POST['_odw_file_id'], $_POST['odw_file_upload_nonce'] ) + && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['odw_file_upload_nonce'] ) ), 'odw_save_file_attachment' ) + ) { + $file_id = absint( wp_unslash( $_POST['_odw_file_id'] ) ); + } + + return $file_id > 0; } /** diff --git a/open-data-wizard.php b/open-data-wizard.php index abfa7ee..9c39374 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.16.0 + * Version: 2.17.0 * Requires at least: 6.4 * Requires PHP: 8.1 * Author: nozilla @@ -26,7 +26,7 @@ exit; } -define( 'ODW_VERSION', '2.16.0' ); +define( 'ODW_VERSION', '2.17.0' ); define( 'ODW_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'ODW_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); define( 'ODW_PLUGIN_FILE', __FILE__ );