summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Rehnelt <noreply@maennchen1.de>2026-10-04 16:14:50 +0200
committerRoger Rehnelt <noreply@maennchen1.de>2026-10-04 16:21:21 +0200
commit40e3d1614cea93b734d568f4eebf20eb8954fa9b (patch)
treeb1c5f2a7c33105bd09d683d781d53e7f81769587
parentc24b6746c27a7e81a9819ef523dec8f64a90f9a6 (diff)
Produktbewertungen: Sterne und Bewertungen im Shop
Sterne mit Schnitt unter dem Produktnamen und in den Kacheln, Liste mit Hinweis zur Echtheit unter dem Produkt, Link zum Bewerten im Kundenkonto. Ohne das Modul bleibt die Anzeige wie bisher. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--views/blocks/product-list.phtml2
-rw-r--r--views/mods/mod_productview/productview.phtml6
-rw-r--r--views/mods/mod_reviews/account_row.phtml18
-rw-r--r--views/mods/mod_reviews/list.phtml57
-rw-r--r--views/mods/mod_reviews/rating.phtml13
-rw-r--r--views/mods/mod_reviews/settings_edit.phtml8
-rw-r--r--views/mods/mod_reviews/wpsg_reviews.css32
7 files changed, 134 insertions, 2 deletions
diff --git a/views/blocks/product-list.phtml b/views/blocks/product-list.phtml
index be33534..feb186f 100644
--- a/views/blocks/product-list.phtml
+++ b/views/blocks/product-list.phtml
@@ -36,6 +36,8 @@
<?php $h = 'h'.intval($arBlock['titleLevel']??3); ?><<?php echo $h; ?> class="wpsg-product-list__title"><a href="<?php echo esc_url($p['url']); ?>"><?php echo esc_html($name); ?></a></<?php echo $h; ?>>
+ <?php /* Sterne nur mit dem Modul Produktbewertungen, aus freigegebenen Bewertungen */ if ($this->hasMod('wpsg_mod_reviews')) echo $this->callMod('wpsg_mod_reviews', 'renderSummary', [$product_id, 'wpsg-product-list__rating']); ?>
+
<?php if ($this->canDisplayPrice()) { $price = $oProduct->getPrice($product_id); ?>
<div class="wpsg-product-list__price">
<?php if ($this->hasMod('wpsg_mod_productvariants') && $this->callMod('wpsg_mod_productvariants', 'isVariantsProduct', [$product_id])) { ?>
diff --git a/views/mods/mod_productview/productview.phtml b/views/mods/mod_productview/productview.phtml
index 0319b84..12cbeef 100644
--- a/views/mods/mod_productview/productview.phtml
+++ b/views/mods/mod_productview/productview.phtml
@@ -83,9 +83,11 @@
<p class="wpsg-pv__detailname"><?php echo esc_html($detailname); ?></p>
<?php } ?>
- <?php $rating = floatval($oProduct->getRating()); if ($rating > 0) { ?>
+ <?php if ($this->hasMod('wpsg_mod_reviews')) { /* Mit dem Modul Produktbewertungen nur freigegebene Bewertungen, sonst die Sterne am Produkt (doc/bewertungen.md, Entscheidung 1) */ ?>
+ <?php echo $this->callMod('wpsg_mod_reviews', 'renderSummary', [$product_id, 'wpsg-pv__rating']); ?>
+ <?php } else { $rating = floatval($oProduct->getRating()); if ($rating > 0) { ?>
<p class="wpsg-pv__rating" title="<?php echo esc_attr(wpsg_translate(__('#1# von 5 Sternen', 'wpsg'), wpsg_ff($rating, '', true))); ?>"><span aria-hidden="true"><?php echo str_repeat('★', intval(round($rating))).str_repeat('☆', 5 - intval(round($rating))); ?></span><span class="screen-reader-text"><?php echo esc_html(wpsg_translate(__('#1# von 5 Sternen', 'wpsg'), wpsg_ff($rating, '', true))); ?></span></p>
- <?php } ?>
+ <?php } } ?>
<?php if ($oProduct->canDisplayPrice()) { $price = $oProduct->getPrice(); $oldPrice = $oProduct->getOldPrice(); ?>
<p class="wpsg-pv__price">
diff --git a/views/mods/mod_reviews/account_row.phtml b/views/mods/mod_reviews/account_row.phtml
new file mode 100644
index 0000000..67395de
--- /dev/null
+++ b/views/mods/mod_reviews/account_row.phtml
@@ -0,0 +1,18 @@
+<?php
+ /**
+ * Kundenkonto, Zeile unter einer Bestellposition: Link zum Bewerten (Modul Produktbewertungen)
+ * @version 4.6.1
+ */
+ defined('ABSPATH') || exit;
+
+ $v = $this->view['wpsg_mod_reviews']['account'];
+?>
+<tr class="wpsg-review-account">
+ <td colspan="2">
+ <?php if ($v['url'] !== '') { ?>
+ <a class="wpsg-review-account__link" href="<?php echo esc_url($v['url']); ?>"><?php echo esc_html__('Produkt bewerten', 'wpsg'); ?><span class="screen-reader-text"><?php echo esc_html(': '.$v['name']); ?></span></a>
+ <?php } else { ?>
+ <span class="wpsg-review-account__done"><?php echo esc_html__('Bewertung abgegeben', 'wpsg'); ?></span>
+ <?php } ?>
+ </td>
+</tr>
diff --git a/views/mods/mod_reviews/list.phtml b/views/mods/mod_reviews/list.phtml
new file mode 100644
index 0000000..1080b5f
--- /dev/null
+++ b/views/mods/mod_reviews/list.phtml
@@ -0,0 +1,57 @@
+<?php
+ /**
+ * Freigegebene Bewertungen unter dem Produkt (Modul Produktbewertungen)
+ *
+ * Mit Hinweis zur Echtheit (§ 5b Abs. 3 UWG). „Verifizierter Kauf“ steht nur an Bewertungen über den Link einer
+ * Bestellung (doc/bewertungen.md).
+ * @version 4.6.1
+ */
+ defined('ABSPATH') || exit;
+
+ $v = $this->view['wpsg_mod_reviews']['list'];
+ $section_id = 'wpsg-reviews-'.intval($v['product_id']);
+?>
+<section class="wpsg-reviews<?php if ($v['wide']) echo ' alignwide'; ?>" id="<?php echo esc_attr($section_id); ?>" aria-labelledby="<?php echo esc_attr($section_id.'-title'); ?>">
+
+ <h2 class="wpsg-reviews__title" id="<?php echo esc_attr($section_id.'-title'); ?>"><?php echo esc_html__('Bewertungen', 'wpsg'); ?></h2>
+
+ <?php echo $v['summary']; ?>
+
+ <p class="wpsg-reviews__hint"><?php echo nl2br(esc_html($v['hint'])); ?></p>
+
+ <ol class="wpsg-reviews__list">
+ <?php foreach ($v['reviews'] as $review) { ?>
+ <li class="wpsg-review">
+
+ <?php echo $review['rating']; ?>
+
+ <?php if ($review['title'] !== '') { ?>
+ <h3 class="wpsg-review__title"><?php echo esc_html($review['title']); ?></h3>
+ <?php } ?>
+
+ <p class="wpsg-review__meta">
+ <span class="wpsg-review__author"><?php echo esc_html($review['name']); ?></span>
+ <time class="wpsg-review__date" datetime="<?php echo esc_attr($review['datetime']); ?>"><?php echo esc_html($review['date']); ?></time>
+ <?php if ($review['verified']) { ?><span class="wpsg-review__verified"><?php echo esc_html__('Verifizierter Kauf', 'wpsg'); ?></span><?php } ?>
+ </p>
+
+ <?php if ($review['text'] !== '') { ?>
+ <div class="wpsg-review__text"><?php echo nl2br(esc_html($review['text'])); ?></div>
+ <?php } ?>
+
+ <?php if ($review['reply'] !== '') { ?>
+ <div class="wpsg-review__reply">
+ <p class="wpsg-review__reply-title"><?php echo esc_html__('Antwort des Shops', 'wpsg'); ?></p>
+ <div><?php echo nl2br(esc_html($review['reply'])); ?></div>
+ </div>
+ <?php } ?>
+
+ </li>
+ <?php } ?>
+ </ol>
+
+ <?php if ($v['more_url'] !== '') { ?>
+ <p class="wpsg-reviews__more"><a href="<?php echo esc_url($v['more_url']); ?>"><?php /* translators: %s: Anzahl der Bewertungen */ echo esc_html(sprintf(__('Alle %s Bewertungen anzeigen', 'wpsg'), number_format_i18n($v['count']))); ?></a></p>
+ <?php } ?>
+
+</section>
diff --git a/views/mods/mod_reviews/rating.phtml b/views/mods/mod_reviews/rating.phtml
new file mode 100644
index 0000000..5aa665b
--- /dev/null
+++ b/views/mods/mod_reviews/rating.phtml
@@ -0,0 +1,13 @@
+<?php
+ /**
+ * Sterne mit Schnitt und Anzahl (Modul Produktbewertungen)
+ *
+ * Die Sternzeichen sind aria-hidden, den Wert sagt der Text. Modus full: Text sichtbar; compact: sichtbar „4,5 (12)“,
+ * der ganze Text für Screenreader; single: nur Sterne, der Text für Screenreader.
+ * @version 4.6.1
+ */
+ defined('ABSPATH') || exit;
+
+ $r = $this->view['wpsg_mod_reviews']['rating'];
+?>
+<p class="wpsg-rating<?php if ($r['class'] !== '') echo ' '.esc_attr($r['class']); ?>"><span class="wpsg-rating__stars" aria-hidden="true"><span class="wpsg-rating__empty">★★★★★</span><span class="wpsg-rating__fill" style="width:<?php echo intval($r['percent']); ?>%">★★★★★</span></span><?php if ($r['mode'] === 'full') { ?> <span class="wpsg-rating__text"><?php echo esc_html($r['text']); ?></span><?php } else if ($r['mode'] === 'compact') { ?> <span class="wpsg-rating__text" aria-hidden="true"><?php echo esc_html($r['short']); ?></span><span class="screen-reader-text"><?php echo esc_html($r['text']); ?></span><?php } else { ?><span class="screen-reader-text"><?php echo esc_html($r['text']); ?></span><?php } ?></p>
diff --git a/views/mods/mod_reviews/settings_edit.phtml b/views/mods/mod_reviews/settings_edit.phtml
index ddfd423..7ee9555 100644
--- a/views/mods/mod_reviews/settings_edit.phtml
+++ b/views/mods/mod_reviews/settings_edit.phtml
@@ -18,3 +18,11 @@
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')); ?>
+<?php echo wpsg_drawForm_Textarea('wpsg_mod_reviews_hint', __('Hinweis zur Echtheit der Bewertungen', 'wpsg'), (string)$this->get_option('wpsg_mod_reviews_hint')); ?>
+<div class="form-group form-group-sm">
+ <div class="col-sm-6 col-sm-offset-6">
+ <p class="description"><?php echo esc_html__('Steht über den Bewertungen. Leer lassen für diesen Text, der zu Ihren Einstellungen passt:', 'wpsg'); ?></p>
+ <p class="description"><em><?php echo esc_html($this->view['wpsg_mod_reviews']['default_hint']); ?></em></p>
+ </div>
+ <div class="clearfix wpsg_clear"></div>
+</div>
diff --git a/views/mods/mod_reviews/wpsg_reviews.css b/views/mods/mod_reviews/wpsg_reviews.css
new file mode 100644
index 0000000..bb36a70
--- /dev/null
+++ b/views/mods/mod_reviews/wpsg_reviews.css
@@ -0,0 +1,32 @@
+/**
+ * Modul Produktbewertungen: Sterne, Liste unter dem Produkt, Kundenkonto
+ *
+ * Farben über --wpsg-*, mit Rückfall für den Modus „klassisch“. Eigene Farbe der Sterne: --wpsg-color-rating.
+ */
+
+.wpsg-rating { display:flex; flex-wrap:wrap; align-items:center; gap:0.15em 0.5em; margin:0.25em 0 0.5em; font-size:var(--wpsg-font-size-small, 0.875em); line-height:1.4; }
+.wpsg-rating__stars { position:relative; display:inline-block; flex:none; line-height:1; font-size:1.15em; letter-spacing:0.05em; white-space:nowrap; }
+.wpsg-rating__empty { color:var(--wpsg-color-rating-empty, rgba(127, 127, 127, 0.45)); }
+.wpsg-rating__fill { position:absolute; top:0; left:0; overflow:hidden; white-space:nowrap; color:var(--wpsg-color-rating, #b07800); }
+.wpsg-rating .screen-reader-text { position:absolute !important; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden; clip:rect(0, 0, 0, 0); clip-path:inset(50%); white-space:nowrap; border:0; }
+
+.wpsg-rating--product { margin:0.25em 0 0.75em; }
+
+.wpsg-reviews { margin-block:2em; padding-top:1.5em; border-top:1px solid var(--wpsg-color-line, rgba(127, 127, 127, 0.35)); }
+.wpsg-reviews__title { margin:0 0 0.5em; }
+.wpsg-reviews__summary { font-size:1em; }
+.wpsg-reviews__hint { margin:0 0 1.5em; font-size:var(--wpsg-font-size-small, 0.875em); opacity:var(--wpsg-muted-opacity, 0.8); }
+.wpsg-reviews__list { margin:0; padding:0; list-style:none; }
+.wpsg-review { margin:0; padding:1.25em 0; border-top:1px solid var(--wpsg-color-line-soft, rgba(127, 127, 127, 0.2)); overflow-wrap:anywhere; }
+.wpsg-review:first-child { border-top:0; padding-top:0; }
+.wpsg-review__rating { margin:0 0 0.25em; }
+.wpsg-review__title { margin:0 0 0.25em; font-size:1.05em; }
+.wpsg-review__meta { display:flex; flex-wrap:wrap; gap:0 0.75em; margin:0 0 0.5em; font-size:var(--wpsg-font-size-small, 0.875em); }
+.wpsg-review__author { font-weight:600; }
+.wpsg-review__verified::before { content:"✓\00a0"; color:var(--wpsg-color-success, #1e7a2d); }
+.wpsg-review__text { margin:0; }
+.wpsg-review__reply { margin:0.75em 0 0; padding:0.75em 1em; border-left:3px solid var(--wpsg-color-line, rgba(127, 127, 127, 0.35)); background:var(--wpsg-color-surface, rgba(127, 127, 127, 0.08)); }
+.wpsg-review__reply-title { margin:0 0 0.25em; font-weight:600; font-size:var(--wpsg-font-size-small, 0.875em); }
+.wpsg-reviews__more { margin:1em 0 0; }
+
+.wpsg-review-account td { padding-top:0; }