PluginProbe ʕ •ᴥ•ʔ
Strong Testimonials / 3.3.2
Strong Testimonials v3.3.2
3.3.2 3.3.1 trunk 1.0.1 2.30.9 2.31.10 2.32 2.32.1 2.32.2 2.32.3 2.32.4 2.33 2.34 2.35 2.36 2.37 2.38 2.38.1 2.39 2.39.1 2.39.2 2.39.3 2.40.0 2.40.1 2.40.2 2.40.3 2.40.4 2.40.5 2.40.6 2.40.7 2.41.0 2.41.1 2.50.0 2.50.1 2.50.2 2.50.3 2.50.4 2.51.0 2.51.1 2.51.2 2.51.3 2.51.4 2.51.5 2.51.6 2.51.7 2.51.8 2.51.9 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.20 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.17 3.2.18 3.2.19 3.2.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0
strong-testimonials / includes / class-strong-testimonials-average-shortcode.php
strong-testimonials / includes Last commit date
elementor 1 year ago logs 1 month ago strong-testimonials-beaver-block 1 year ago submodules 8 months ago class-strong-gutemberg.php 1 year ago class-strong-log.php 1 year ago class-strong-mail.php 1 year ago class-strong-testimonials-average-shortcode.php 1 year ago class-strong-testimonials-count-shortcode.php 1 year ago class-strong-testimonials-defaults.php 1 month ago class-strong-testimonials-form.php 1 month ago class-strong-testimonials-order.php 1 year ago class-strong-testimonials-privacy.php 1 year ago class-strong-testimonials-render.php 1 month ago class-strong-testimonials-templates.php 1 year ago class-strong-testimonials-view-shortcode.php 1 week ago class-strong-testimonials-view-widget.php 1 year ago class-strong-view-display.php 1 day ago class-strong-view-form.php 1 day ago class-strong-view-slideshow.php 1 day ago class-strong-view.php 1 day ago class-walker-strong-category-checklist-front.php 1 year ago deprecated.php 1 year ago filters.php 1 month ago functions-activation.php 1 month ago functions-content.php 11 months ago functions-image.php 5 months ago functions-rating.php 1 year ago functions-template-form.php 1 week ago functions-template.php 4 months ago functions-views.php 1 year ago functions.php 1 month ago l10n-polylang.php 1 year ago l10n-wpml.php 1 year ago post-types.php 1 week ago retro.php 1 year ago scripts.php 1 month ago
class-strong-testimonials-average-shortcode.php
422 lines
1 <?php
2 /**
3 * Class Strong_Testimonials_Average_Shortcode
4 *
5 * @since 2.31.0
6 */
7
8 class Strong_Testimonials_Average_Shortcode {
9
10 /**
11 * @var string
12 */
13 public $shortcode = 'testimonial_average_rating';
14
15 public function __construct() {
16 add_shortcode( $this->shortcode, array( $this, 'testimonial_average_rating_shortcode' ) );
17 }
18
19 /**
20 * Return average rating.
21 *
22 * @param $atts
23 * @param null $content
24 * @since 2.31.0
25 * @return string
26 */
27 public function testimonial_average_rating_shortcode( $atts, $content = null ) {
28 $pairs = array(
29 // parts
30 'average' => '',
31 'count' => '',
32 'stars' => '',
33 // style
34 'block' => '',
35 'centered' => '',
36 // HTML
37 'element' => 'div', // span
38 'class' => '', // on wrapper
39 // filters
40 'category' => '',
41 // rounded
42 'rounded' => '',
43 // field
44 'field' => '',
45 // decimals
46 'decimals' => 1,
47 );
48 $pairs = apply_filters( "wpmtst_shortcode_defaults__{$this->shortcode}", $pairs );
49
50 $atts = shortcode_atts( $pairs, normalize_empty_atts( $atts ), $this->shortcode );
51
52 // default parts
53 if ( ! $content ) {
54 $content = '{title} {stars} {summary}';
55 }
56
57 // set parts
58 preg_match_all( '#{(.*?)}#', $content, $parts );
59 /*
60 * Example:
61 *
62 * Array
63 * (
64 * [0] => Array
65 * (
66 * [0] => {title}
67 * [1] => {stars}
68 * [2] => {summary}
69 * )
70 *
71 * [1] => Array
72 * (
73 * [0] => title
74 * [1] => stars
75 * [2] => summary
76 * )
77 * )
78 */
79 $tag_list = $parts[0];
80 $tag_keys = $parts[1];
81 $parts = array_fill_keys( $tag_keys, '' );
82
83 // get posts
84 $args = array(
85 'posts_per_page' => -1,
86 'post_type' => 'wpm-testimonial',
87 'post_status' => 'publish',
88 'suppress_filters' => true,
89 );
90
91 // category
92 if ( $atts['category'] ) {
93 $categories = explode( ',', $atts['category'] );
94 $args['tax_query'] = array(
95 array(
96 'taxonomy' => 'wpm-testimonial-category',
97 'field' => is_numeric( $categories[0] ) ? 'id' : 'slug',
98 'terms' => $categories,
99 ),
100 );
101 }
102
103 $args = apply_filters( 'wpmtst_query_args', $args, $atts );
104 $posts_array = get_posts( $args );
105
106 // get summary
107 $summary = $this->get_summary( $posts_array, $atts['field'], $atts['decimals'] );
108 /*
109 * Example:
110 *
111 * Array
112 * (
113 * [review_count] => 2
114 * [rating_count] => 2
115 * [rating_sum] => 10
116 * [rating_average] => 5
117 * [rating_detail] => Array
118 * (
119 * [5] => 2
120 * [4] => 0
121 * [3] => 0
122 * [2] => 0
123 * [1] => 0
124 * [0] => 0
125 * )
126 * )
127 */
128
129 // Want to build your own HTML? Return any truthy value to short-circuit this shortcode output.
130 $html = apply_filters( 'wpmtst_average_rating_pre_html', '', $atts, $summary );
131 if ( $html ) {
132 return $html;
133 }
134
135 // assemble classes
136 $class_list = array_filter( array_merge( array( 'strong-rating-wrapper', 'average' ), explode( ' ', $atts['class'] ) ) );
137 if ( $atts['block'] ) {
138 $class_list[] = 'block';
139 }
140 if ( $atts['centered'] ) {
141 $class_list[] = 'centered';
142 }
143
144 // round the rating if necessary
145 if ( ! empty( $atts['rounded'] ) ) {
146 $rating_average = number_format( $summary['rating_average'], 0 );
147 } else {
148 $rating_average = number_format( $summary['rating_average'], absint( $atts['decimals'] ) );
149 }
150
151 // title
152 if ( isset( $parts['title'] ) ) {
153 $parts['title'] = sprintf( '<span class="strong-rating-title">%s</span>', esc_html__( 'Average Rating:', 'strong-testimonials' ) );
154 }
155 if ( isset( $parts['title2'] ) ) {
156 /* translators: %s is a number */
157 $count = sprintf( _n( 'Average of %s Rating:', 'Average of %s Ratings:', $summary['rating_count'], 'strong-testimonials' ), $summary['rating_count'] );
158 $parts['title2'] = sprintf( '<span class="strong-rating-title">%s</span>', $count );
159 }
160
161 // stars
162 if ( isset( $parts['stars'] ) ) {
163 $parts['stars'] = $this->print_stars( $rating_average );
164 }
165
166 // average
167 if ( isset( $parts['average'] ) ) {
168 $parts['average'] = sprintf( '<span class="strong-rating-average">%s</span>', $rating_average );
169 }
170
171 // count
172 if ( isset( $parts['count'] ) ) {
173 $parts['count'] = sprintf( '<span class="strong-rating-count">%s</span>', $summary['rating_count'] );
174 }
175
176 // summary phrase
177 if ( isset( $parts['summary'] ) ) {
178
179 /* translators: %s is a number */
180 $average = sprintf( _n( '%s star', '%s stars', $rating_average, 'strong-testimonials' ), $rating_average );
181 /* translators: %s is a number */
182 $count = sprintf( _n( '(based on %s rating)', '(based on %s ratings)', $summary['rating_count'], 'strong-testimonials' ), $summary['rating_count'] );
183 $parts['summary'] = sprintf( '<span class="strong-rating-summary">%s</span>', $average . ' ' . $count );
184 } elseif ( isset( $parts['summary2'] ) ) {
185
186 /* translators: %s is a number */
187 $average = sprintf( _n( '%s star', '%s stars', $rating_average, 'strong-testimonials' ), $rating_average );
188 $parts['summary2'] = sprintf( '<span class="strong-rating-summary">%s</span>', $average );
189 }
190
191 // replace tags
192 foreach ( $tag_list as $key => $tag ) {
193 $content = str_replace( $tag, $parts[ $tag_keys[ $key ] ], $content );
194 }
195
196 $allowed_elements = array( 'span', 'p', 'i', 'div', 'li', 'ul', 'ol', 'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' );
197 $allowed_elements = apply_filters( 'wpmtst_allowed_shortcode_elements', $allowed_elements );
198 $element = in_array( $atts['element'], $allowed_elements, true ) ? esc_attr( $atts['element'] ) : 'div';
199
200 // assemble it.
201 $html = sprintf( '<%s class="%s">%s</%s>', esc_attr( $element ), esc_attr( implode( ' ', $class_list ) ), $content, esc_attr( $element ) );
202
203 wp_enqueue_style( 'wpmtst-rating-display' );
204
205 return apply_filters( 'wpmtst_average_rating_html', $html, $atts, $summary );
206 }
207
208 /**
209 * Calculate and return the average rating.
210 *
211 * @param $posts
212 * @since 1.1.0
213 * @return array|null
214 */
215 public function get_summary( $posts = null, $field = '', $decimals = 1 ) {
216 // Set a placeholder.
217 $average = array(
218 'review_count' => null,
219 'rating_count' => null,
220 'rating_sum' => null,
221 'rating_average' => 0,
222 'rating_detail' => null,
223 );
224
225 if ( $posts ) {
226
227 // initialize totals
228 $review_count = count( $posts );
229 $rating_count = 0;
230 $rating_sum = 0;
231 // initial values for each rating
232 $rating_detail = array_fill_keys( array( 5, 4, 3, 2, 1, 0 ), 0 );
233
234 foreach ( $posts as $post ) {
235 // get rating value
236 $value = $this->get_rating_value( $post, $field );
237 // add to detail array
238 ++$rating_detail[ $value ];
239 // add to count and sum
240 if ( $value ) {
241 $rating_sum += $value;
242 ++$rating_count;
243 }
244 }
245
246 if ( $rating_count ) {
247 $rating_average = number_format( $rating_sum / $rating_count, absint( $decimals ) );
248 if ( 1 === absint( $decimals ) ) {
249 $rating_average = trim( $rating_average, '.0' );
250 }
251 $average = array(
252 'review_count' => number_format( $review_count ),
253 'rating_count' => number_format( $rating_count ),
254 'rating_sum' => number_format( $rating_sum ),
255 'rating_average' => $rating_average,
256 'rating_detail' => $rating_detail,
257 );
258 }
259 }
260
261 return $average;
262 }
263
264 /**
265 * Return the rating value for a single post.
266 *
267 * @param $post
268 * @since 1.1.0
269 * @return int|null
270 */
271 private function get_rating_value( $post, $field = '' ) {
272 if ( ! empty( $field ) ) {
273 if ( 'all' === $field ) {
274 $rating_fields = $this->find_all_rating_field();
275 } else {
276 $rating_fields = $this->find_rating_field( $field );
277 }
278 } else {
279 $rating_fields = $this->find_first_rating_field();
280 }
281 if ( $rating_fields ) {
282 $ratings = array();
283 foreach ( $rating_fields as $rating_field ) {
284 $rating = intval( get_post_meta( $post->ID, $rating_field['name'], true ) );
285 if ( ! $rating ) {
286 $rating = intval( $rating_field['default_display_value'] );
287 }
288 $ratings[] = $rating;
289 }
290 $rating = array_sum( $ratings ) / count( $ratings );
291 } else {
292 $rating = 5;
293 }
294 return $rating;
295 }
296
297 /**
298 * Find the first rating field.
299 *
300 * @since 1.1.0
301 * @return bool|int|string
302 */
303 private function find_first_rating_field() {
304 $fields = wpmtst_get_custom_fields();
305 foreach ( $fields as $key => $field ) {
306 if ( 'rating' === $field['input_type'] ) {
307 return array( $field );
308 }
309 }
310
311 return false;
312 }
313
314 /**
315 * Find specific rating field.
316 *
317 * @return bool|int|string
318 */
319 private function find_rating_field( $rating_field ) {
320 $fields = wpmtst_get_custom_fields();
321 foreach ( $fields as $key => $field ) {
322 if ( 'rating' === $field['input_type'] && $rating_field === $field['name'] ) {
323 return array( $field );
324 }
325 }
326
327 return false;
328 }
329
330 /**
331 * Find all rating field.
332 *
333 * @since 2.41.0
334 * @return bool|int|string
335 */
336 private function find_all_rating_field() {
337 $fields = wpmtst_get_custom_fields();
338 $rating = array();
339 foreach ( $fields as $key => $field ) {
340 if ( 'rating' === $field['input_type'] ) {
341 $rating[] = $field;
342 }
343 }
344
345 if ( ! empty( $rating ) ) {
346 return $rating;
347 }
348
349 return false;
350 }
351
352 /**
353 * Print the stars.
354 *
355 * @param float $rating Average rating.
356 * @param string $wrapper_class The container CSS class.
357 * @since 2.31.0
358 * @return string
359 */
360 public function print_stars( $rating = 0.0, $wrapper_class = 'strong-rating' ) {
361
362 $is_zero = ( 0.0 === (float) $rating ) ? ' current' : '';
363
364 $star_solid = wpmtst_get_star_svg( 'star_solid' );
365 $star_regular = wpmtst_get_star_svg( 'star_regular' );
366 $star_half = wpmtst_get_star_svg( 'star_half' );
367
368 $svg_args = array(
369 'svg' => array(
370 'class' => true,
371 'aria-hidden' => true,
372 'aria-labelledby' => true,
373 'role' => true,
374 'xmlns' => true,
375 'width' => true,
376 'height' => true,
377 'viewbox' => true, // <= Must be lower case!
378 'id' => true,
379 ),
380 'g' => array( 'fill' => true ),
381 'title' => array( 'title' => true ),
382 'path' => array(
383 'd' => true,
384 'fill' => true,
385 ),
386 'style' => array( 'type' => true ),
387 'span' => array(
388 'style' => array(),
389 'class' => array(),
390 ),
391 );
392
393 ob_start();
394 ?>
395 <span class="<?php echo esc_attr( $wrapper_class ); ?>">
396 <span class="star0 star<?php echo esc_attr( $is_zero ); ?>"></span>
397 <?php
398 if ( $is_zero ) {
399 echo str_repeat( '<span class="star" style="display: inline-block;" >' . $star_regular . '</span>', 5 );
400 } else {
401 for ( $i = 1; $i <= 5; $i++ ) {
402 if ( $i <= round( $rating ) ) {
403 $star_icon = $star_solid;
404 } else {
405 $star_icon = $star_regular;
406 }
407
408 if ( ( 0.9 >= $i - $rating ) && ( 0.1 <= $i - $rating ) ) {
409 $star_icon = $star_half;
410 }
411 echo wp_kses( sprintf( '<span class="star" style="display: inline-block;" >%s</span>', $star_icon ), $svg_args );
412 }
413 }
414 ?>
415 </span>
416 <?php
417 $html = apply_filters( 'wpmtst_average_rating_stars_html', ob_get_clean(), $rating );
418
419 return $html;
420 }
421 }
422