diff options
| author | Roger Rehnelt <noreply@maennchen1.de> | 2026-10-04 15:44:05 +0200 |
|---|---|---|
| committer | Roger Rehnelt <noreply@maennchen1.de> | 2026-10-04 15:44:05 +0200 |
| commit | 9f73ac8d79ae3050e0162f3c48e78518df21a09b (patch) | |
| tree | 3c138747735226cea115c05fa209634bc49bad9b | |
| parent | b592f99d16f124a889e50c2727a8f5a41d9b473f (diff) | |
Produktbewertungen: Modul mit persönlichem Link, Formular und Freigabe
Käufer bewerten je Bestellposition über einen Link von der Abschlussseite; das Backend gibt frei, lehnt ab und antwortet. Noch ohne Anzeige im Shop.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | views/mods/mod_reviews/admin_index.phtml | 81 | ||||
| -rw-r--r-- | views/mods/mod_reviews/order_done.phtml | 15 | ||||
| -rw-r--r-- | views/mods/mod_reviews/page.phtml | 75 | ||||
| -rw-r--r-- | views/mods/mod_reviews/settings_edit.phtml | 20 |
4 files changed, 191 insertions, 0 deletions
diff --git a/views/mods/mod_reviews/admin_index.phtml b/views/mods/mod_reviews/admin_index.phtml new file mode 100644 index 0000000..7ee6661 --- /dev/null +++ b/views/mods/mod_reviews/admin_index.phtml @@ -0,0 +1,81 @@ +<?php + /** + * Backend: Bewertungen prüfen, freigeben, ablehnen, beantworten + * @version 4.6.1 + */ + defined('ABSPATH') || exit; + + $admin = $this->view['wpsg_mod_reviews']['admin']; + $arTabs = [ + wpsg_review::STATUS_PENDING => __('Zu prüfen', 'wpsg'), + wpsg_review::STATUS_APPROVED => __('Veröffentlicht', 'wpsg'), + wpsg_review::STATUS_REJECTED => __('Abgelehnt', 'wpsg') + ]; + $base = admin_url('admin.php?page=wpsg-Reviews'); +?> +<div class="wrap wpsg-reviews-admin"> + + <h1><?php echo esc_html__('Bewertungen', 'wpsg'); ?></h1> + + <?php echo $this->writeBackendMessage(); ?> + + <nav class="nav-tab-wrapper" aria-label="<?php echo esc_attr__('Bewertungen nach Status', 'wpsg'); ?>"> + <?php foreach ($arTabs as $status => $label) { ?> + <a href="<?php echo esc_url(add_query_arg('status', $status, $base)); ?>" class="nav-tab<?php echo (($admin['status'] === $status)?' nav-tab-active':''); ?>"<?php if ($admin['status'] === $status) { ?> aria-current="page"<?php } ?>><?php echo esc_html($label); ?> (<?php echo intval($admin['count'][$status]??0); ?>)</a> + <?php } ?> + </nav> + + <?php if (sizeof($admin['reviews']) === 0) { ?> + + <p><?php echo esc_html__('Keine Bewertungen.', 'wpsg'); ?></p> + + <?php } else { ?> + + <table class="widefat striped"> + <thead> + <tr> + <th scope="col"><?php echo esc_html__('Produkt', 'wpsg'); ?></th> + <th scope="col"><?php echo esc_html__('Sterne', 'wpsg'); ?></th> + <th scope="col"><?php echo esc_html__('Bewertung', 'wpsg'); ?></th> + <th scope="col"><?php echo esc_html__('Name', 'wpsg'); ?></th> + <th scope="col"><?php echo esc_html__('Abgegeben', 'wpsg'); ?></th> + <th scope="col"><?php echo esc_html__('Aktion', 'wpsg'); ?></th> + </tr> + </thead> + <tbody> + <?php foreach ($admin['reviews'] as $review) { $review_id = intval($review['id']); ?> + <tr> + <td><?php echo esc_html($review['product']); ?><br /> + <small><?php echo ((intval($review['verified']) === 1)?esc_html__('Verifizierter Kauf', 'wpsg'):esc_html__('Ohne Kaufnachweis (übernommen)', 'wpsg')); ?></small></td> + <td><span aria-hidden="true"><?php echo str_repeat('★', intval($review['stars'])).str_repeat('☆', 5 - intval($review['stars'])); ?></span> + <span class="screen-reader-text"><?php echo esc_html(wpsg_translate(__('#1# von 5 Sternen', 'wpsg'), intval($review['stars']))); ?></span></td> + <td><?php if ((string)$review['title'] !== '') { ?><strong><?php echo esc_html($review['title']); ?></strong><br /><?php } ?> + <?php echo nl2br(esc_html((string)$review['text'])); ?> + <?php if ((string)$review['reply'] !== '') { ?><p><em><?php echo esc_html__('Ihre Antwort:', 'wpsg'); ?></em> <?php echo nl2br(esc_html((string)$review['reply'])); ?></p><?php } ?></td> + <td><?php echo esc_html($review['display_name']); ?></td> + <td><?php echo esc_html((string)$review['submitted']); ?></td> + <td> + <?php foreach (['approve' => __('Freigeben', 'wpsg'), 'reject' => __('Ablehnen', 'wpsg'), 'delete' => __('Löschen', 'wpsg')] as $action => $label) { ?> + <?php if (($action === 'approve' && $review['status'] === wpsg_review::STATUS_APPROVED) || ($action === 'reject' && $review['status'] === wpsg_review::STATUS_REJECTED)) continue; ?> + <form method="post" class="wpsg-reviews-admin__action"> + <?php wp_nonce_field('wpsg_reviews_moderate'); ?> + <input type="hidden" name="review_id" value="<?php echo $review_id; ?>" /> + <button type="submit" name="wpsg_review_action" value="<?php echo esc_attr($action); ?>" class="button<?php echo (($action === 'approve')?' button-primary':''); ?>"<?php if ($action === 'delete') { ?> onclick="return confirm('<?php echo esc_js(__('Bewertung endgültig löschen?', 'wpsg')); ?>');"<?php } ?>><?php echo esc_html($label); ?></button> + </form> + <?php } ?> + <form method="post" class="wpsg-reviews-admin__reply"> + <?php wp_nonce_field('wpsg_reviews_moderate'); ?> + <input type="hidden" name="review_id" value="<?php echo $review_id; ?>" /> + <label for="wpsg_review_reply_<?php echo $review_id; ?>"><?php echo esc_html__('Öffentliche Antwort', 'wpsg'); ?></label> + <textarea id="wpsg_review_reply_<?php echo $review_id; ?>" name="reply" rows="2"><?php echo esc_textarea((string)$review['reply']); ?></textarea> + <button type="submit" name="wpsg_review_action" value="reply" class="button"><?php echo esc_html__('Antwort speichern', 'wpsg'); ?></button> + </form> + </td> + </tr> + <?php } ?> + </tbody> + </table> + + <?php } ?> + +</div> diff --git a/views/mods/mod_reviews/order_done.phtml b/views/mods/mod_reviews/order_done.phtml new file mode 100644 index 0000000..00af294 --- /dev/null +++ b/views/mods/mod_reviews/order_done.phtml @@ -0,0 +1,15 @@ +<?php + /** + * Abschlussseite: persönliche Links zum Bewerten der bestellten Produkte + * @version 4.6.1 + */ + defined('ABSPATH') || exit; +?> +<div class="wpsg-reviews-invite"> + <p><?php echo esc_html__('Sobald Ihre Bestellung bei Ihnen ist, können Sie die Produkte über diese persönlichen Links bewerten. Bewahren Sie sie auf, etwa als Lesezeichen:', 'wpsg'); ?></p> + <ul> + <?php foreach ((array)$this->view['wpsg_mod_reviews']['done'] as $review) { ?> + <li><a href="<?php echo esc_url($review['url']); ?>"><?php echo esc_html(wpsg_translate(__('#1# bewerten', 'wpsg'), $review['name'])); ?></a></li> + <?php } ?> + </ul> +</div> diff --git a/views/mods/mod_reviews/page.phtml b/views/mods/mod_reviews/page.phtml new file mode 100644 index 0000000..788c4bd --- /dev/null +++ b/views/mods/mod_reviews/page.phtml @@ -0,0 +1,75 @@ +<?php + /** + * Seite „Bewertung abgeben“: Formular zum persönlichen Link + * @version 4.6.1 + */ + defined('ABSPATH') || exit; + + $page = $this->view['wpsg_mod_reviews']['page']; +?> +<div class="wpsg wpsg-review-page"> + + <?php if ($page['thanks']) { ?> + + <p class="wpsg-review-page__message" role="status"><?php echo esc_html((($page['status']??'') === wpsg_review::STATUS_APPROVED)?__('Vielen Dank für Ihre Bewertung. Sie ist jetzt veröffentlicht.', 'wpsg'):__('Vielen Dank für Ihre Bewertung. Sie erscheint, sobald wir sie freigegeben haben.', 'wpsg')); ?></p> + + <?php } else if ($page['state'] === 'invalid') { ?> + + <p class="wpsg-review-page__message"><?php echo esc_html__('Dieser Link ist ungültig. Bitte verwenden Sie den vollständigen Link aus Ihrer Bestellung.', 'wpsg'); ?></p> + + <?php } else if ($page['state'] === 'done') { ?> + + <p class="wpsg-review-page__message"><?php echo esc_html(wpsg_translate(__('Sie haben „#1#“ bereits bewertet. Vielen Dank!', 'wpsg'), $page['product'])); ?></p> + + <?php } else if ($page['state'] === 'early') { ?> + + <p class="wpsg-review-page__message"><?php echo esc_html(wpsg_translate(__('Sie können „#1#“ bewerten, sobald Ihre Bestellung bei Ihnen ist. Der Link bleibt gültig.', 'wpsg'), $page['product'])); ?></p> + + <?php } else { $errors = $page['errors']; $data = $page['data']; ?> + + <h2 class="wpsg-review-page__title"><?php echo esc_html(wpsg_translate(__('„#1#“ bewerten', 'wpsg'), $page['product'])); ?></h2> + + <?php if (sizeof($errors) > 0) { ?> + <div class="wpsg-review-page__errors" role="alert"> + <ul><?php foreach ($errors as $error) { ?><li><?php echo esc_html($error); ?></li><?php } ?></ul> + </div> + <?php } ?> + + <form method="post" action="<?php echo esc_url(add_query_arg(wpsg_mod_reviews::PARAM, $page['token'], get_permalink())); ?>" class="wpsg-review-form" novalidate> + + <?php wp_nonce_field('wpsg_review_submit_'.$page['review_id']); ?> + <input type="hidden" name="<?php echo esc_attr(wpsg_mod_reviews::PARAM); ?>" value="<?php echo esc_attr($page['token']); ?>" /> + + <fieldset class="wpsg-review-form__stars"<?php if (isset($errors['stars'])) { ?> aria-invalid="true"<?php } ?>> + <legend><?php echo esc_html__('Ihre Bewertung', 'wpsg'); ?> <span class="wpsg_required">*</span></legend> + <?php for ($i = 5; $i >= 1; $i--) { ?> + <label><input type="radio" name="wpsg_review[stars]" value="<?php echo $i; ?>" <?php checked(intval($data['stars']), $i); ?> required /> <span aria-hidden="true"><?php echo str_repeat('★', $i).str_repeat('☆', 5 - $i); ?></span> <span class="wpsg-review-form__stars-text"><?php echo esc_html(wpsg_translate(_n('#1# Stern', '#1# Sterne', $i, 'wpsg'), $i)); ?></span></label> + <?php } ?> + </fieldset> + + <p> + <label for="wpsg_review_title"><?php echo esc_html__('Überschrift', 'wpsg'); ?></label> + <input type="text" id="wpsg_review_title" name="wpsg_review[title]" maxlength="<?php echo intval(wpsg_review::MAX_TITLE); ?>" value="<?php echo esc_attr((string)$data['title']); ?>" /> + </p> + + <p> + <label for="wpsg_review_text"><?php echo esc_html__('Ihre Erfahrung', 'wpsg'); ?></label> + <textarea id="wpsg_review_text" name="wpsg_review[text]" rows="6" maxlength="<?php echo intval(wpsg_review::MAX_TEXT); ?>"><?php echo esc_textarea((string)$data['text']); ?></textarea> + </p> + + <p> + <label for="wpsg_review_name"><?php echo esc_html__('Anzeigename', 'wpsg'); ?> <span class="wpsg_required">*</span></label> + <input type="text" id="wpsg_review_name" name="wpsg_review[display_name]" maxlength="<?php echo intval(wpsg_review::MAX_NAME); ?>" autocomplete="nickname" value="<?php echo esc_attr((string)$data['display_name']); ?>" required<?php if (isset($errors['display_name'])) { ?> aria-invalid="true"<?php } ?> /> + </p> + + <p> + <label><input type="checkbox" name="wpsg_review[consent]" value="1" <?php checked((string)$data['consent'], '1'); ?> required<?php if (isset($errors['consent'])) { ?> aria-invalid="true"<?php } ?> /> <?php echo esc_html__('Ich bin einverstanden, dass meine Bewertung mit dem Anzeigenamen auf dieser Website veröffentlicht wird. Ich kann das jederzeit widerrufen.', 'wpsg'); ?> <span class="wpsg_required">*</span></label> + </p> + + <p><button type="submit" name="wpsg_review_submit" value="1" class="wpsg_button<?php echo wpsg_button_class(); ?>"><?php echo esc_html__('Bewertung absenden', 'wpsg'); ?></button></p> + + </form> + + <?php } ?> + +</div> diff --git a/views/mods/mod_reviews/settings_edit.phtml b/views/mods/mod_reviews/settings_edit.phtml new file mode 100644 index 0000000..ddfd423 --- /dev/null +++ b/views/mods/mod_reviews/settings_edit.phtml @@ -0,0 +1,20 @@ +<?php + /** + * Einstellungen des Moduls Produktbewertungen + * @version 4.6.1 + */ + defined('ABSPATH') || exit; + + $arStatus = []; + foreach ([wpsg_ShopController::STATUS_ZAHLUNGAKZEPTIERT, wpsg_ShopController::STATUS_RECHNUNGGESCHRIEBEN, wpsg_ShopController::STATUS_WAREVERSENDET, wpsg_ShopController::STATUS_ZUGESTELLT] as $status) { + + if (isset($this->view['wpsg_mod_reviews']['status'][$status])) $arStatus[$status] = $this->view['wpsg_mod_reviews']['status'][$status]; + + } +?> +<?php echo wpsg_drawForm_Select('wpsg_page_review', __('Seite „Bewertung abgeben“', 'wpsg'), $this->view['wpsg_mod_reviews']['pages'], $this->get_option('wpsg_page_review')); ?> +<?php echo wpsg_drawForm_Select('wpsg_mod_reviews_from_status', __('Bewerten möglich ab Status', 'wpsg'), $arStatus, $this->get_option('wpsg_mod_reviews_from_status')); ?> +<?php echo wpsg_drawForm_Select('wpsg_mod_reviews_approval', __('Neue Bewertungen', 'wpsg'), [ + wpsg_mod_reviews::APPROVAL_MANUAL => __('Vor der Veröffentlichung prüfen', 'wpsg'), + wpsg_mod_reviews::APPROVAL_AUTO => __('Sofort veröffentlichen', 'wpsg') +], $this->get_option('wpsg_mod_reviews_approval')); ?> |
