diff options
| author | Roger Rehnelt <noreply@maennchen1.de> | 2026-10-04 16:14:50 +0200 |
|---|---|---|
| committer | Roger Rehnelt <noreply@maennchen1.de> | 2026-10-04 16:21:21 +0200 |
| commit | 40e3d1614cea93b734d568f4eebf20eb8954fa9b (patch) | |
| tree | b1c5f2a7c33105bd09d683d781d53e7f81769587 | |
| parent | c24b6746c27a7e81a9819ef523dec8f64a90f9a6 (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.phtml | 2 | ||||
| -rw-r--r-- | views/mods/mod_productview/productview.phtml | 6 | ||||
| -rw-r--r-- | views/mods/mod_reviews/account_row.phtml | 18 | ||||
| -rw-r--r-- | views/mods/mod_reviews/list.phtml | 57 | ||||
| -rw-r--r-- | views/mods/mod_reviews/rating.phtml | 13 | ||||
| -rw-r--r-- | views/mods/mod_reviews/settings_edit.phtml | 8 | ||||
| -rw-r--r-- | views/mods/mod_reviews/wpsg_reviews.css | 32 |
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; } |
