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 |