PluginProbe ʕ •ᴥ•ʔ
Author Website Templates – Create Writer, Author & Publisher Websites Easily / 1.1.5
Author Website Templates – Create Writer, Author & Publisher Websites Easily v1.1.5
trunk 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9
author-website-templates / build / blocks / author-pro / book-page-review-section / render.php
author-website-templates / build / blocks / author-pro / book-page-review-section Last commit date
block.json 5 months ago index.asset.php 5 months ago index.js 5 months ago render.php 5 months ago view.asset.php 5 months ago view.js 5 months ago
render.php
302 lines
1 <?php
2 /**
3 * Render Book Page Reviews [Author Pro] Block
4 */
5
6 $block_id = isset($attributes['blockId']) ? $attributes['blockId'] : '';
7 if (empty($block_id)) {
8 $block_id = 'awt-book-reviews-' . uniqid();
9 }
10
11 $anchor = isset($attributes['anchor']) ? $attributes['anchor'] : '';
12 $element_id = !empty($anchor) ? $anchor : $block_id;
13
14 $section_title = !empty($attributes['sectionTitle']) ? $attributes['sectionTitle'] : 'Customer Reviews';
15 $form_title = !empty($attributes['formTitle']) ? $attributes['formTitle'] : 'Write a Review';
16 $submit_btn_text = !empty($attributes['submitBtnText']) ? $attributes['submitBtnText'] : 'Submit Review';
17
18 $book_id = get_the_ID();
19 $is_editor = defined('REST_REQUEST') && REST_REQUEST === true;
20
21 // If in editor, preview with a real book if possible
22 if ($is_editor && get_post_type($book_id) !== 'book') {
23 $min_query = new WP_Query([
24 'post_type' => 'book',
25 'posts_per_page' => 1,
26 'post_status' => 'publish'
27 ]);
28 if ($min_query->have_posts()) {
29 $min_query->the_post();
30 $book_id = get_the_ID();
31 wp_reset_postdata();
32 }
33 }
34
35 // 1. Fetch Reviews
36 $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
37 $args = array(
38 'post_type' => 'book_reviews',
39 'posts_per_page' => 5,
40 'paged' => $paged,
41 'meta_query' => array(
42 array(
43 'key' => '_rswpbs_reviewed_book',
44 'value' => $book_id,
45 'compare' => '='
46 )
47 )
48 );
49 $reviews_query = new WP_Query($args);
50 $total_reviews = $reviews_query->found_posts;
51
52 // 2. Calculate Stats (All time)
53 // Separate query for ALL reviews to calculate stats correctly
54 $stats_args = $args;
55 $stats_args['posts_per_page'] = -1;
56 $stats_args['paged'] = 1;
57 $all_reviews = get_posts($stats_args);
58
59 $total_rating_sum = 0;
60 $star_counts = [5 => 0, 4 => 0, 3 => 0, 2 => 0, 1 => 0];
61
62 foreach ($all_reviews as $review) {
63 $rating = get_post_meta($review->ID, '_rswpbs_rating', true);
64 $rating = intval($rating);
65 if ($rating >= 1 && $rating <= 5) {
66 $total_rating_sum += $rating;
67 $star_counts[$rating]++;
68 }
69 }
70
71 $avg_rating = ($total_reviews > 0) ? round($total_rating_sum / count($all_reviews), 1) : 0; // Use count of fetched posts for accuracy
72
73 // Helper to render stars
74 function awt_render_stars($rating) {
75 $html = '';
76
77 for ($i = 1; $i <= 5; $i++) {
78 $color_class = ($i <= $rating) ? 'text-yellow-400' : 'text-gray-300';
79
80 $html .= '
81 <svg
82 xmlns="http://www.w3.org/2000/svg"
83 viewBox="0 0 640 640"
84 class="w-4 h-4 inline-block ' . esc_attr($color_class) . '"
85 fill="currentColor"
86 aria-hidden="true"
87 >
88 <path d="M341.5 45.1C337.4 37.1 329.1 32 320.1 32C311.1 32 302.8 37.1 298.7 45.1L225.1 189.3L65.2 214.7C56.3 216.1 48.9 222.4 46.1 231C43.3 239.6 45.6 249 51.9 255.4L166.3 369.9L141.1 529.8C139.7 538.7 143.4 547.7 150.7 553C158 558.3 167.6 559.1 175.7 555L320.1 481.6L464.4 555C472.4 559.1 482.1 558.3 489.4 553C496.7 547.7 500.4 538.8 499 529.8L473.7 369.9L588.1 255.4C594.5 249 596.7 239.6 593.9 231C591.1 222.4 583.8 216.1 574.8 214.7L415 189.3L341.5 45.1z"/>
89 </svg>';
90 }
91
92 return $html;
93 }
94
95
96 $wrapper_attributes = get_block_wrapper_attributes([
97 'class' => 'awt-book-reviews',
98 'id' => $element_id,
99 ]);
100 ?>
101
102 <section class="py-20 bg-white" <?php echo $wrapper_attributes; ?>>
103 <div class="awt-container">
104 <div class="grid grid-cols-1 lg:grid-cols-12 gap-12">
105
106 <!-- Left Column: Stats -->
107 <div class="lg:col-span-4">
108 <!-- Summary Card -->
109 <div class="bg-paper p-8 rounded-xl border border-gray-100 text-center mb-8">
110 <div class="text-5xl font-bold text-primary mb-2"><?php echo esc_html($avg_rating); ?></div>
111 <div class="flex justify-center gap-1 text-yellow-400 mb-2">
112 <?php echo awt_render_stars(round($avg_rating)); ?>
113 </div>
114 <p class="text-secondary text-sm">Based on <?php echo esc_html($total_reviews); ?> reviews</p>
115 </div>
116
117 <!-- Progress Bars -->
118 <div class="space-y-3 mb-8">
119 <?php for ($star = 5; $star >= 1; $star--) :
120 $count = $star_counts[$star];
121 $percent = ($total_reviews > 0) ? ($count / $total_reviews) * 100 : 0;
122 ?>
123 <div class="flex items-center text-sm">
124 <span class="w-12 text-secondary font-medium"><?php echo $star; ?> Star</span>
125 <div class="flex-1 h-2 bg-gray-100 rounded-full mx-3 overflow-hidden">
126 <div class="h-full bg-yellow-400 rounded-full" style="width: <?php echo esc_attr($percent); ?>%"></div>
127 </div>
128 <span class="w-8 text-right text-gray-400 text-xs"><?php echo round($percent); ?>%</span>
129 </div>
130 <?php endfor; ?>
131 </div>
132
133 <!-- CTA Box -->
134 <div class="bg-primary text-white p-6 rounded-xl relative overflow-hidden">
135 <div class="relative z-10">
136 <h3 class="font-serif font-bold text-xl mb-2">Share your thoughts</h3>
137 <p class="text-white/80 text-sm mb-6">If you've read this book, we'd love to hear what you think!</p>
138 <a href="#write-review" class="block w-full py-3 bg-white text-primary text-center font-bold rounded-lg hover:bg-accent hover:text-white transition">Write a Review</a>
139 </div>
140 <!-- Decorative Circles in CSS/Class similar to ref if needed, strictly keeping structure simple as requested -->
141 </div>
142 </div>
143
144 <!-- Right Column: Review List -->
145 <div class="lg:col-span-8">
146 <div class="flex justify-between items-center mb-8 pb-4 border-b border-gray-100">
147 <h2 class="font-serif font-bold text-2xl text-primary"><?php echo esc_html($section_title); ?></h2>
148
149 <!-- Sorting Dropdown (Optional visual only for now) -->
150 <div class="relative">
151 <select class="appearance-none bg-white border border-gray-200 rounded-lg py-2 pl-4 pr-10 text-sm font-medium text-secondary focus:outline-none focus:border-accent">
152 <option>Most Recent</option>
153 <option>Highest Rated</option>
154 <option>Lowest Rated</option>
155 </select>
156 <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-500">
157 <svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/></svg>
158 </div>
159 </div>
160 </div>
161
162 <?php if ($reviews_query->have_posts()) : ?>
163 <div class="space-y-8 mb-12">
164 <?php while ($reviews_query->have_posts()) : $reviews_query->the_post();
165 $reviewer_email = get_post_meta(get_the_ID(), '_rswpbs_reviewer_email', true);
166 $reviewer_name = get_post_meta(get_the_ID(), '_rswpbs_reviewer_name', true);
167 $rating = get_post_meta(get_the_ID(), '_rswpbs_rating', true);
168 $avatar_url = get_avatar_url($reviewer_email, ['default' => 'mp']);
169 ?>
170 <div class="flex gap-4 mb-8">
171 <div class="flex-shrink-0">
172 <img src="<?php echo esc_url($avatar_url); ?>" alt="<?php echo esc_attr($reviewer_name); ?>" class="w-12 h-12 rounded-full object-cover border border-gray-100">
173 </div>
174 <div class="flex-grow">
175 <div class="flex justify-between items-start mb-2">
176 <div>
177 <h4 class="font-bold text-primary"><?php echo esc_html($reviewer_name); ?></h4>
178 <div class="text-xs text-gray-400"><?php echo get_the_date(); ?></div>
179 </div>
180 <div class="flex text-yellow-400 text-xs gap-0.5">
181 <?php echo awt_render_stars(intval($rating)); ?>
182 </div>
183 </div>
184 <h5 class="font-bold text-sm text-primary mb-2"><?php the_title(); ?></h5>
185 <div class="text-secondary text-sm leading-relaxed">
186 <?php the_content(); ?>
187 <!-- Using the_content() or excerpt depending on need. The ref request asked for content. -->
188 </div>
189 </div>
190 </div>
191 <?php endwhile; wp_reset_postdata(); ?>
192 </div>
193
194 <!-- Pagination -->
195 <div class="flex justify-center gap-2 mb-12">
196 <?php
197 $prev_icon = '
198 <svg xmlns="http://www.w3.org/2000/svg"
199 viewBox="0 0 640 640"
200 class="w-4 h-4"
201 fill="currentColor"
202 aria-hidden="true">
203 <path d="M169.4 297.4C156.9 309.9 156.9 330.2 169.4 342.7L361.4 534.7C373.9 547.2 394.2 547.2 406.7 534.7C419.2 522.2 419.2 501.9 406.7 489.4L237.3 320L406.6 150.6C419.1 138.1 419.1 117.8 406.6 105.3C394.1 92.8 373.8 92.8 361.3 105.3L169.3 297.3z"/>
204 </svg>';
205
206 $next_icon = '
207 <svg xmlns="http://www.w3.org/2000/svg"
208 viewBox="0 0 640 640"
209 class="w-4 h-4"
210 fill="currentColor"
211 aria-hidden="true">
212 <path d="M471.1 297.4C483.6 309.9 483.6 330.2 471.1 342.7L279.1 534.7C266.6 547.2 246.3 547.2 233.8 534.7C221.3 522.2 221.3 501.9 233.8 489.4L403.2 320L233.9 150.6C221.4 138.1 221.4 117.8 233.9 105.3C246.4 92.8 266.7 92.8 279.2 105.3L471.2 297.3z"/>
213 </svg>';
214
215 $pagination = paginate_links(array(
216 'base' => str_replace(999999999, '%#%', esc_url(get_pagenum_link(999999999))),
217 'format' => '?paged=%#%',
218 'current' => max(1, get_query_var('paged')),
219 'total' => $reviews_query->max_num_pages,
220 'prev_text' => $prev_icon,
221 'next_text' => $next_icon,
222 'type' => 'array',
223 ));
224
225
226 if( is_array( $pagination ) ) {
227 foreach ( $pagination as $page ) {
228 // Add tailwind classes to pagination links logic if needed,
229 // but standard WP output is usually sufficient with theme styles,
230 // or we can wrapper it.
231 // For now echoing simple links.
232 echo '<span class="px-4 py-2 border border-gray-200 rounded hover:bg-gray-50 text-sm font-medium text-secondary transition cursor-pointer">' . $page . '</span>';
233 }
234 }
235 ?>
236 </div>
237
238 <?php else : ?>
239 <p class="text-gray-500 italic mb-12">No reviews yet. Be the first to review!</p>
240 <?php endif; ?>
241
242 <!-- Submission Form -->
243 <div id="write-review" class="pt-12 border-t border-gray-100">
244 <h3 class="font-serif font-bold text-2xl text-primary mb-6"><?php echo esc_html($form_title); ?></h3>
245
246 <form id="rswpbs-review-form" action="" method="post" class="space-y-6">
247 <?php
248 // AJAX Action and Nonce for RS WP Books Showcase
249 // Note: The plugin must handle this action.
250 wp_nonce_field( 'rswpbs_submit_review', '_rswpbs_submit_review_nonce' );
251 ?>
252 <input type="hidden" name="action" value="rswpbs_submit_review_form">
253 <input type="hidden" name="current_post_id" value="<?php echo esc_attr($book_id); ?>">
254 <input type="hidden" name="rating" value="5">
255
256 <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
257 <div>
258 <label class="block text-sm font-bold text-primary mb-2">Name *</label>
259 <input type="text" name="reviewer_name" required class="w-full px-4 py-3 bg-paper border border-gray-200 rounded-lg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition">
260 </div>
261 <div>
262 <label class="block text-sm font-bold text-primary mb-2">Email *</label>
263 <input type="email" name="reviewer_email" required class="w-full px-4 py-3 bg-paper border border-gray-200 rounded-lg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition">
264 </div>
265 </div>
266
267 <div>
268 <label class="block text-sm font-bold text-primary mb-2">Rating *</label>
269 <div class="flex gap-1 text-2xl awt-star-rating-select">
270 <?php for ($i = 1; $i <= 5; $i++) : ?>
271 <svg
272 class="awt-star-icon w-6 h-6 cursor-pointer text-gray-300 hover:scale-110 transition-transform duration-200"
273 data-rating="<?php echo $i; ?>"
274 fill="currentColor"
275 xmlns="http://www.w3.org/2000/svg"
276 viewBox="0 0 640 640">
277 <path d="M341.5 45.1C337.4 37.1 329.1 32 320.1 32C311.1 32 302.8 37.1 298.7 45.1L225.1 189.3L65.2 214.7C56.3 216.1 48.9 222.4 46.1 231C43.3 239.6 45.6 249 51.9 255.4L166.3 369.9L141.1 529.8C139.7 538.7 143.4 547.7 150.7 553C158 558.3 167.6 559.1 175.7 555L320.1 481.6L464.4 555C472.4 559.1 482.1 558.3 489.4 553C496.7 547.7 500.4 538.8 499 529.8L473.7 369.9L588.1 255.4C594.5 249 596.7 239.6 593.9 231C591.1 222.4 583.8 216.1 574.8 214.7L415 189.3L341.5 45.1z"/>
278 </svg>
279 <?php endfor; ?>
280 </div>
281 </div>
282
283 <div>
284 <label class="block text-sm font-bold text-primary mb-2">Review Title *</label>
285 <input type="text" name="review_title" required class="w-full px-4 py-3 bg-paper border border-gray-200 rounded-lg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition">
286 </div>
287
288 <div>
289 <label class="block text-sm font-bold text-primary mb-2">Your Review *</label>
290 <textarea name="reviewer_comment" rows="5" required class="w-full px-4 py-3 bg-paper border border-gray-200 rounded-lg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition"></textarea>
291 </div>
292
293 <button type="submit" class="px-8 py-3 bg-accent text-white font-bold rounded-lg hover:border-orange-700 hover:bg-orange-700 transition shadow-lg shadow-orange-500/20">
294 <?php echo esc_html($submit_btn_text); ?>
295 </button>
296 </form>
297 </div>
298 </div>
299 </div>
300 </div>
301 </section>
302