PluginProbe
Elementor Website Builder – more than just a page builder / 3.25.8
Elementor Website Builder – more than just a page builder v3.25.8
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / includes / widgets / star-rating.php

star-rating.php in Elementor Website Builder – more than just a page builder 3.25.8, at includes/widgets/star-rating.php

550 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit; // Exit if accessed directly.
6 }
7
8 use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
9 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
10
11 /**
12 * Elementor star rating widget.
13 *
14 * Elementor widget that displays star rating.
15 *
16 * @since 2.3.0
17 */
18 class Widget_Star_Rating extends Widget_Base {
19
20 /**
21 * Get widget name.
22 *
23 * Retrieve star rating widget name.
24 *
25 * @since 2.3.0
26 * @access public
27 *
28 * @return string Widget name.
29 */
30 public function get_name() {
31 return 'star-rating';
32 }
33
34 /**
35 * Get widget title.
36 *
37 * Retrieve star rating widget title.
38 *
39 * @since 2.3.0
40 * @access public
41 *
42 * @return string Widget title.
43 */
44 public function get_title() {
45 return esc_html__( 'Star Rating', 'elementor' );
46 }
47
48 /**
49 * Get widget icon.
50 *
51 * Retrieve star rating widget icon.
52 *
53 * @since 2.3.0
54 * @access public
55 *
56 * @return string Widget icon.
57 */
58 public function get_icon() {
59 return 'eicon-rating';
60 }
61
62 /**
63 * Get widget keywords.
64 *
65 * Retrieve the list of keywords the widget belongs to.
66 *
67 * @since 2.3.0
68 * @access public
69 *
70 * @return array Widget keywords.
71 */
72 public function get_keywords() {
73 return [ 'star', 'rating', 'rate', 'review' ];
74 }
75
76 protected function is_dynamic_content(): bool {
77 return false;
78 }
79
80 /**
81 * Get style dependencies.
82 *
83 * Retrieve the list of style dependencies the widget requires.
84 *
85 * @since 3.24.0
86 * @access public
87 *
88 * @return array Widget style dependencies.
89 */
90 public function get_style_depends(): array {
91 return [ 'widget-star-rating' ];
92 }
93
94 /**
95 * Hide widget from panel.
96 *
97 * Hide the star rating widget from the panel.
98 *
99 * @since 3.17.0
100 * @return bool
101 */
102 public function show_in_panel(): bool {
103 return false;
104 }
105
106 /**
107 * Register star rating widget controls.
108 *
109 * Adds different input fields to allow the user to change and customize the widget settings.
110 *
111 * @since 3.1.0
112 * @access protected
113 */
114 protected function register_controls() {
115 $this->start_controls_section(
116 'section_rating',
117 [
118 'label' => esc_html__( 'Star Rating', 'elementor' ),
119 ]
120 );
121
122 if ( Plugin::$instance->widgets_manager->get_widget_types( 'rating' ) ) {
123 $this->add_deprecation_message(
124 '3.17.0',
125 esc_html__(
126 'You are currently editing a Star Rating widget in its old version. Drag a new Rating widget onto your page to use a newer version, providing better capabilities.',
127 'elementor'
128 ),
129 'rating'
130 );
131 }
132
133 $this->add_control(
134 'rating_scale',
135 [
136 'label' => esc_html__( 'Rating Scale', 'elementor' ),
137 'type' => Controls_Manager::SELECT,
138 'options' => [
139 '5' => '0-5',
140 '10' => '0-10',
141 ],
142 'default' => '5',
143 ]
144 );
145
146 $this->add_control(
147 'rating',
148 [
149 'label' => esc_html__( 'Rating', 'elementor' ),
150 'type' => Controls_Manager::NUMBER,
151 'min' => 0,
152 'max' => 10,
153 'step' => 0.1,
154 'default' => 5,
155 'dynamic' => [
156 'active' => true,
157 ],
158 ]
159 );
160
161 $this->add_control(
162 'star_style',
163 [
164 'label' => esc_html__( 'Icon', 'elementor' ),
165 'type' => Controls_Manager::SELECT,
166 'options' => [
167 'star_fontawesome' => 'Font Awesome',
168 'star_unicode' => 'Unicode',
169 ],
170 'default' => 'star_fontawesome',
171 'render_type' => 'template',
172 'prefix_class' => 'elementor--star-style-',
173 'separator' => 'before',
174 ]
175 );
176
177 $this->add_control(
178 'unmarked_star_style',
179 [
180 'label' => esc_html__( 'Unmarked Style', 'elementor' ),
181 'type' => Controls_Manager::CHOOSE,
182 'options' => [
183 'solid' => [
184 'title' => esc_html__( 'Solid', 'elementor' ),
185 'icon' => 'eicon-star',
186 ],
187 'outline' => [
188 'title' => esc_html__( 'Outline', 'elementor' ),
189 'icon' => 'eicon-star-o',
190 ],
191 ],
192 'default' => 'solid',
193 ]
194 );
195
196 $this->add_control(
197 'title',
198 [
199 'label' => esc_html__( 'Title', 'elementor' ),
200 'type' => Controls_Manager::TEXT,
201 'separator' => 'before',
202 'dynamic' => [
203 'active' => true,
204 ],
205 ]
206 );
207
208 $this->add_responsive_control(
209 'align',
210 [
211 'label' => esc_html__( 'Alignment', 'elementor' ),
212 'type' => Controls_Manager::CHOOSE,
213 'options' => [
214 'left' => [
215 'title' => esc_html__( 'Left', 'elementor' ),
216 'icon' => 'eicon-text-align-left',
217 ],
218 'center' => [
219 'title' => esc_html__( 'Center', 'elementor' ),
220 'icon' => 'eicon-text-align-center',
221 ],
222 'right' => [
223 'title' => esc_html__( 'Right', 'elementor' ),
224 'icon' => 'eicon-text-align-right',
225 ],
226 'justify' => [
227 'title' => esc_html__( 'Justified', 'elementor' ),
228 'icon' => 'eicon-text-align-justify',
229 ],
230 ],
231 'prefix_class' => 'elementor-star-rating%s--align-',
232 'selectors' => [
233 '{{WRAPPER}}' => 'text-align: {{VALUE}}',
234 ],
235 ]
236 );
237
238 $this->end_controls_section();
239
240 $this->start_controls_section(
241 'section_title_style',
242 [
243 'label' => esc_html__( 'Title', 'elementor' ),
244 'tab' => Controls_Manager::TAB_STYLE,
245 'condition' => [
246 'title!' => '',
247 ],
248 ]
249 );
250
251 $this->add_control(
252 'title_color',
253 [
254 'label' => esc_html__( 'Text Color', 'elementor' ),
255 'type' => Controls_Manager::COLOR,
256 'global' => [
257 'default' => Global_Colors::COLOR_TEXT,
258 ],
259 'selectors' => [
260 '{{WRAPPER}} .elementor-star-rating__title' => 'color: {{VALUE}}',
261 ],
262 ]
263 );
264
265 $this->add_group_control(
266 Group_Control_Typography::get_type(),
267 [
268 'name' => 'title_typography',
269 'selector' => '{{WRAPPER}} .elementor-star-rating__title',
270 'global' => [
271 'default' => Global_Typography::TYPOGRAPHY_TEXT,
272 ],
273 ]
274 );
275
276 $this->add_group_control(
277 Group_Control_Text_Shadow::get_type(),
278 [
279 'name' => 'title_shadow',
280 'selector' => '{{WRAPPER}} .elementor-star-rating__title',
281 ]
282 );
283
284 $this->add_responsive_control(
285 'title_gap',
286 [
287 'label' => esc_html__( 'Gap', 'elementor' ),
288 'type' => Controls_Manager::SLIDER,
289 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
290 'range' => [
291 'px' => [
292 'max' => 50,
293 ],
294 'em' => [
295 'min' => 0,
296 'max' => 5,
297 ],
298 'rem' => [
299 'min' => 0,
300 'max' => 5,
301 ],
302 ],
303 'selectors' => [
304 'body:not(.rtl) {{WRAPPER}}:not(.elementor-star-rating--align-justify) .elementor-star-rating__title' => 'margin-right: {{SIZE}}{{UNIT}}',
305 'body.rtl {{WRAPPER}}:not(.elementor-star-rating--align-justify) .elementor-star-rating__title' => 'margin-left: {{SIZE}}{{UNIT}}',
306 ],
307 ]
308 );
309
310 $this->end_controls_section();
311
312 $this->start_controls_section(
313 'section_stars_style',
314 [
315 'label' => esc_html__( 'Stars', 'elementor' ),
316 'tab' => Controls_Manager::TAB_STYLE,
317 ]
318 );
319
320 $this->add_responsive_control(
321 'icon_size',
322 [
323 'label' => esc_html__( 'Size', 'elementor' ),
324 'type' => Controls_Manager::SLIDER,
325 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
326 'range' => [
327 'px' => [
328 'max' => 100,
329 ],
330 'em' => [
331 'min' => 0,
332 'max' => 10,
333 ],
334 'rem' => [
335 'min' => 0,
336 'max' => 10,
337 ],
338 ],
339 'selectors' => [
340 '{{WRAPPER}} .elementor-star-rating' => 'font-size: {{SIZE}}{{UNIT}}',
341 ],
342 ]
343 );
344
345 $this->add_responsive_control(
346 'icon_space',
347 [
348 'label' => esc_html__( 'Spacing', 'elementor' ),
349 'type' => Controls_Manager::SLIDER,
350 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
351 'range' => [
352 'px' => [
353 'max' => 50,
354 ],
355 'em' => [
356 'min' => 0,
357 'max' => 5,
358 ],
359 'rem' => [
360 'min' => 0,
361 'max' => 5,
362 ],
363 ],
364 'selectors' => [
365 'body:not(.rtl) {{WRAPPER}} .elementor-star-rating i:not(:last-of-type)' => 'margin-right: {{SIZE}}{{UNIT}}',
366 'body.rtl {{WRAPPER}} .elementor-star-rating i:not(:last-of-type)' => 'margin-left: {{SIZE}}{{UNIT}}',
367 ],
368 ]
369 );
370
371 $this->add_control(
372 'stars_color',
373 [
374 'label' => esc_html__( 'Color', 'elementor' ),
375 'type' => Controls_Manager::COLOR,
376 'selectors' => [
377 '{{WRAPPER}} .elementor-star-rating i:before' => 'color: {{VALUE}}',
378 ],
379 'separator' => 'before',
380 ]
381 );
382
383 $this->add_control(
384 'stars_unmarked_color',
385 [
386 'label' => esc_html__( 'Unmarked Color', 'elementor' ),
387 'type' => Controls_Manager::COLOR,
388 'selectors' => [
389 '{{WRAPPER}} .elementor-star-rating i' => 'color: {{VALUE}}',
390 ],
391 ]
392 );
393
394 $this->end_controls_section();
395 }
396
397 /**
398 * @since 2.3.0
399 * @access protected
400 */
401 protected function get_rating() {
402 $settings = $this->get_settings_for_display();
403 $rating_scale = (int) $settings['rating_scale'];
404 $rating = (float) $settings['rating'] > $rating_scale ? $rating_scale : $settings['rating'];
405
406 return [ $rating, $rating_scale ];
407 }
408
409 /**
410 * Print the actual stars and calculate their filling.
411 *
412 * Rating type is float to allow stars-count to be a fraction.
413 * Floored-rating type is int, to represent the rounded-down stars count.
414 * In the `for` loop, the index type is float to allow comparing with the rating value.
415 *
416 * @since 2.3.0
417 * @access protected
418 */
419 protected function render_stars( $icon ) {
420 $rating_data = $this->get_rating();
421 $rating = (float) $rating_data[0];
422 $floored_rating = floor( $rating );
423 $stars_html = '';
424
425 for ( $stars = 1.0; $stars <= $rating_data[1]; $stars++ ) {
426 if ( $stars <= $floored_rating ) {
427 $stars_html .= '<i class="elementor-star-full">' . $icon . '</i>';
428 } elseif ( $floored_rating + 1 === $stars && $rating !== $floored_rating ) {
429 $stars_html .= '<i class="elementor-star-' . ( $rating - $floored_rating ) * 10 . '">' . $icon . '</i>';
430 } else {
431 $stars_html .= '<i class="elementor-star-empty">' . $icon . '</i>';
432 }
433 }
434
435 return $stars_html;
436 }
437
438 /**
439 * @since 2.3.0
440 * @access protected
441 */
442 protected function render() {
443 $settings = $this->get_settings_for_display();
444 $rating_data = $this->get_rating();
445 $textual_rating = $rating_data[0] . '/' . $rating_data[1];
446 $icon = '&#xE934;';
447
448 if ( 'star_fontawesome' === $settings['star_style'] ) {
449 if ( 'outline' === $settings['unmarked_star_style'] ) {
450 $icon = '&#xE933;';
451 }
452 } elseif ( 'star_unicode' === $settings['star_style'] ) {
453 $icon = '&#9733;';
454
455 if ( 'outline' === $settings['unmarked_star_style'] ) {
456 $icon = '&#9734;';
457 }
458 }
459
460 $this->add_render_attribute( 'icon_wrapper', [
461 'class' => 'elementor-star-rating',
462 'title' => $textual_rating,
463 'itemtype' => 'http://schema.org/Rating',
464 'itemscope' => '',
465 'itemprop' => 'reviewRating',
466 ] );
467
468 $schema_rating = '<span itemprop="ratingValue" class="elementor-screen-only">' . $textual_rating . '</span>';
469 $stars_element = '<div ' . $this->get_render_attribute_string( 'icon_wrapper' ) . '>' . $this->render_stars( $icon ) . ' ' . $schema_rating . '</div>';
470 ?>
471
472 <div class="elementor-star-rating__wrapper">
473 <?php if ( ! Utils::is_empty( $settings['title'] ) ) : ?>
474 <div class="elementor-star-rating__title"><?php echo esc_html( $settings['title'] ); ?></div>
475 <?php endif;
476 // PHPCS - $stars_element contains an HTML string that cannot be escaped. ?>
477 <?php echo $stars_element; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
478 </div>
479 <?php
480 }
481
482 /**
483 * @since 2.9.0
484 * @access protected
485 */
486 protected function content_template() {
487 ?>
488 <#
489 var getRating = function() {
490 var ratingScale = parseInt( settings.rating_scale, 10 ),
491 rating = settings.rating > ratingScale ? ratingScale : settings.rating;
492
493 return [ rating, ratingScale ];
494 },
495 ratingData = getRating(),
496 rating = ratingData[0],
497 textualRating = ratingData[0] + '/' + ratingData[1],
498 renderStars = function( icon ) {
499 var starsHtml = '',
500 flooredRating = Math.floor( rating );
501
502 for ( var stars = 1; stars <= ratingData[1]; stars++ ) {
503 if ( stars <= flooredRating ) {
504 starsHtml += '<i class="elementor-star-full">' + icon + '</i>';
505 } else if ( flooredRating + 1 === stars && rating !== flooredRating ) {
506 starsHtml += '<i class="elementor-star-' + ( rating - flooredRating ).toFixed( 1 ) * 10 + '">' + icon + '</i>';
507 } else {
508 starsHtml += '<i class="elementor-star-empty">' + icon + '</i>';
509 }
510 }
511
512 return starsHtml;
513 },
514 icon = '&#xE934;';
515
516 if ( 'star_fontawesome' === settings.star_style ) {
517 if ( 'outline' === settings.unmarked_star_style ) {
518 icon = '&#xE933;';
519 }
520 } else if ( 'star_unicode' === settings.star_style ) {
521 icon = '&#9733;';
522
523 if ( 'outline' === settings.unmarked_star_style ) {
524 icon = '&#9734;';
525 }
526 }
527
528 view.addRenderAttribute( 'iconWrapper', 'class', 'elementor-star-rating' );
529 view.addRenderAttribute( 'iconWrapper', 'itemtype', 'http://schema.org/Rating' );
530 view.addRenderAttribute( 'iconWrapper', 'title', textualRating );
531 view.addRenderAttribute( 'iconWrapper', 'itemscope', '' );
532 view.addRenderAttribute( 'iconWrapper', 'itemprop', 'reviewRating' );
533
534 var stars = renderStars( icon );
535 #>
536
537 <div class="elementor-star-rating__wrapper">
538 <# if ( ! _.isEmpty( settings.title ) ) { #>
539 <div class="elementor-star-rating__title">{{ settings.title }}</div>
540 <# } #>
541 <div {{{ view.getRenderAttributeString( 'iconWrapper' ) }}} >
542 {{{ stars }}}
543 <span itemprop="ratingValue" class="elementor-screen-only">{{ textualRating }}</span>
544 </div>
545 </div>
546
547 <?php
548 }
549 }
550