PluginProbe
Elementor Website Builder – more than just a page builder / 3.4.0-dev9
Elementor Website Builder – more than just a page builder v3.4.0-dev9
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.4.0-dev9, at includes/widgets/star-rating.php

485 lines 11.9 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 /**
77 * Register star rating widget controls.
78 *
79 * Adds different input fields to allow the user to change and customize the widget settings.
80 *
81 * @since 3.1.0
82 * @access protected
83 */
84 protected function register_controls() {
85 $this->start_controls_section(
86 'section_rating',
87 [
88 'label' => esc_html__( 'Rating', 'elementor' ),
89 ]
90 );
91
92 $this->add_control(
93 'rating_scale',
94 [
95 'label' => esc_html__( 'Rating Scale', 'elementor' ),
96 'type' => Controls_Manager::SELECT,
97 'options' => [
98 '5' => '0-5',
99 '10' => '0-10',
100 ],
101 'default' => '5',
102 ]
103 );
104
105 $this->add_control(
106 'rating',
107 [
108 'label' => esc_html__( 'Rating', 'elementor' ),
109 'type' => Controls_Manager::NUMBER,
110 'min' => 0,
111 'max' => 10,
112 'step' => 0.1,
113 'default' => 5,
114 'dynamic' => [
115 'active' => true,
116 ],
117 ]
118 );
119
120 $this->add_control(
121 'star_style',
122 [
123 'label' => esc_html__( 'Icon', 'elementor' ),
124 'type' => Controls_Manager::SELECT,
125 'options' => [
126 'star_fontawesome' => 'Font Awesome',
127 'star_unicode' => 'Unicode',
128 ],
129 'default' => 'star_fontawesome',
130 'render_type' => 'template',
131 'prefix_class' => 'elementor--star-style-',
132 'separator' => 'before',
133 ]
134 );
135
136 $this->add_control(
137 'unmarked_star_style',
138 [
139 'label' => esc_html__( 'Unmarked Style', 'elementor' ),
140 'type' => Controls_Manager::CHOOSE,
141 'options' => [
142 'solid' => [
143 'title' => esc_html__( 'Solid', 'elementor' ),
144 'icon' => 'eicon-star',
145 ],
146 'outline' => [
147 'title' => esc_html__( 'Outline', 'elementor' ),
148 'icon' => 'eicon-star-o',
149 ],
150 ],
151 'default' => 'solid',
152 ]
153 );
154
155 $this->add_control(
156 'title',
157 [
158 'label' => esc_html__( 'Title', 'elementor' ),
159 'type' => Controls_Manager::TEXT,
160 'separator' => 'before',
161 'dynamic' => [
162 'active' => true,
163 ],
164 ]
165 );
166
167 $this->add_responsive_control(
168 'align',
169 [
170 'label' => esc_html__( 'Alignment', 'elementor' ),
171 'type' => Controls_Manager::CHOOSE,
172 'options' => [
173 'left' => [
174 'title' => esc_html__( 'Left', 'elementor' ),
175 'icon' => 'eicon-text-align-left',
176 ],
177 'center' => [
178 'title' => esc_html__( 'Center', 'elementor' ),
179 'icon' => 'eicon-text-align-center',
180 ],
181 'right' => [
182 'title' => esc_html__( 'Right', 'elementor' ),
183 'icon' => 'eicon-text-align-right',
184 ],
185 'justify' => [
186 'title' => esc_html__( 'Justified', 'elementor' ),
187 'icon' => 'eicon-text-align-justify',
188 ],
189 ],
190 'prefix_class' => 'elementor-star-rating%s--align-',
191 'selectors' => [
192 '{{WRAPPER}}' => 'text-align: {{VALUE}}',
193 ],
194 ]
195 );
196
197 $this->end_controls_section();
198
199 $this->start_controls_section(
200 'section_title_style',
201 [
202 'label' => esc_html__( 'Title', 'elementor' ),
203 'tab' => Controls_Manager::TAB_STYLE,
204 'condition' => [
205 'title!' => '',
206 ],
207 ]
208 );
209
210 $this->add_control(
211 'title_color',
212 [
213 'label' => esc_html__( 'Text Color', 'elementor' ),
214 'type' => Controls_Manager::COLOR,
215 'global' => [
216 'default' => Global_Colors::COLOR_TEXT,
217 ],
218 'selectors' => [
219 '{{WRAPPER}} .elementor-star-rating__title' => 'color: {{VALUE}}',
220 ],
221 ]
222 );
223
224 $this->add_group_control(
225 Group_Control_Typography::get_type(),
226 [
227 'name' => 'title_typography',
228 'selector' => '{{WRAPPER}} .elementor-star-rating__title',
229 'global' => [
230 'default' => Global_Typography::TYPOGRAPHY_TEXT,
231 ],
232 ]
233 );
234
235 $this->add_group_control(
236 Group_Control_Text_Shadow::get_type(),
237 [
238 'name' => 'title_shadow',
239 'selector' => '{{WRAPPER}} .elementor-star-rating__title',
240 ]
241 );
242
243 $this->add_responsive_control(
244 'title_gap',
245 [
246 'label' => esc_html__( 'Gap', 'elementor' ),
247 'type' => Controls_Manager::SLIDER,
248 'range' => [
249 'px' => [
250 'min' => 0,
251 'max' => 50,
252 ],
253 ],
254 'selectors' => [
255 'body:not(.rtl) {{WRAPPER}}:not(.elementor-star-rating--align-justify) .elementor-star-rating__title' => 'margin-right: {{SIZE}}{{UNIT}}',
256 'body.rtl {{WRAPPER}}:not(.elementor-star-rating--align-justify) .elementor-star-rating__title' => 'margin-left: {{SIZE}}{{UNIT}}',
257 ],
258 ]
259 );
260
261 $this->end_controls_section();
262
263 $this->start_controls_section(
264 'section_stars_style',
265 [
266 'label' => esc_html__( 'Stars', 'elementor' ),
267 'tab' => Controls_Manager::TAB_STYLE,
268 ]
269 );
270
271 $this->add_responsive_control(
272 'icon_size',
273 [
274 'label' => esc_html__( 'Size', 'elementor' ),
275 'type' => Controls_Manager::SLIDER,
276 'range' => [
277 'px' => [
278 'min' => 0,
279 'max' => 100,
280 ],
281 ],
282 'selectors' => [
283 '{{WRAPPER}} .elementor-star-rating' => 'font-size: {{SIZE}}{{UNIT}}',
284 ],
285 ]
286 );
287
288 $this->add_responsive_control(
289 'icon_space',
290 [
291 'label' => esc_html__( 'Spacing', 'elementor' ),
292 'type' => Controls_Manager::SLIDER,
293 'range' => [
294 'px' => [
295 'min' => 0,
296 'max' => 50,
297 ],
298 ],
299 'selectors' => [
300 'body:not(.rtl) {{WRAPPER}} .elementor-star-rating i:not(:last-of-type)' => 'margin-right: {{SIZE}}{{UNIT}}',
301 'body.rtl {{WRAPPER}} .elementor-star-rating i:not(:last-of-type)' => 'margin-left: {{SIZE}}{{UNIT}}',
302 ],
303 ]
304 );
305
306 $this->add_control(
307 'stars_color',
308 [
309 'label' => esc_html__( 'Color', 'elementor' ),
310 'type' => Controls_Manager::COLOR,
311 'selectors' => [
312 '{{WRAPPER}} .elementor-star-rating i:before' => 'color: {{VALUE}}',
313 ],
314 'separator' => 'before',
315 ]
316 );
317
318 $this->add_control(
319 'stars_unmarked_color',
320 [
321 'label' => esc_html__( 'Unmarked Color', 'elementor' ),
322 'type' => Controls_Manager::COLOR,
323 'selectors' => [
324 '{{WRAPPER}} .elementor-star-rating i' => 'color: {{VALUE}}',
325 ],
326 ]
327 );
328
329 $this->end_controls_section();
330 }
331
332 /**
333 * @since 2.3.0
334 * @access protected
335 */
336 protected function get_rating() {
337 $settings = $this->get_settings_for_display();
338 $rating_scale = (int) $settings['rating_scale'];
339 $rating = (float) $settings['rating'] > $rating_scale ? $rating_scale : $settings['rating'];
340
341 return [ $rating, $rating_scale ];
342 }
343
344 /**
345 * Print the actual stars and calculate their filling.
346 *
347 * Rating type is float to allow stars-count to be a fraction.
348 * Floored-rating type is int, to represent the rounded-down stars count.
349 * In the `for` loop, the index type is float to allow comparing with the rating value.
350 *
351 * @since 2.3.0
352 * @access protected
353 */
354 protected function render_stars( $icon ) {
355 $rating_data = $this->get_rating();
356 $rating = (float) $rating_data[0];
357 $floored_rating = floor( $rating );
358 $stars_html = '';
359
360 for ( $stars = 1.0; $stars <= $rating_data[1]; $stars++ ) {
361 if ( $stars <= $floored_rating ) {
362 $stars_html .= '<i class="elementor-star-full">' . $icon . '</i>';
363 } elseif ( $floored_rating + 1 === $stars && $rating !== $floored_rating ) {
364 $stars_html .= '<i class="elementor-star-' . ( $rating - $floored_rating ) * 10 . '">' . $icon . '</i>';
365 } else {
366 $stars_html .= '<i class="elementor-star-empty">' . $icon . '</i>';
367 }
368 }
369
370 return $stars_html;
371 }
372
373 /**
374 * @since 2.3.0
375 * @access protected
376 */
377 protected function render() {
378 $settings = $this->get_settings_for_display();
379 $rating_data = $this->get_rating();
380 $textual_rating = $rating_data[0] . '/' . $rating_data[1];
381 $icon = '&#xE934;';
382
383 if ( 'star_fontawesome' === $settings['star_style'] ) {
384 if ( 'outline' === $settings['unmarked_star_style'] ) {
385 $icon = '&#xE933;';
386 }
387 } elseif ( 'star_unicode' === $settings['star_style'] ) {
388 $icon = '&#9733;';
389
390 if ( 'outline' === $settings['unmarked_star_style'] ) {
391 $icon = '&#9734;';
392 }
393 }
394
395 $this->add_render_attribute( 'icon_wrapper', [
396 'class' => 'elementor-star-rating',
397 'title' => $textual_rating,
398 'itemtype' => 'http://schema.org/Rating',
399 'itemscope' => '',
400 'itemprop' => 'reviewRating',
401 ] );
402
403 $schema_rating = '<span itemprop="ratingValue" class="elementor-screen-only">' . $textual_rating . '</span>';
404 $stars_element = '<div ' . $this->get_render_attribute_string( 'icon_wrapper' ) . '>' . $this->render_stars( $icon ) . ' ' . $schema_rating . '</div>';
405 ?>
406
407 <div class="elementor-star-rating__wrapper">
408 <?php if ( ! Utils::is_empty( $settings['title'] ) ) : ?>
409 <div class="elementor-star-rating__title"><?php echo esc_html( $settings['title'] ); ?></div>
410 <?php endif;
411 // PHPCS - $stars_element contains an HTML string that cannot be escaped. ?>
412 <?php echo $stars_element; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
413 </div>
414 <?php
415 }
416
417 /**
418 * @since 2.9.0
419 * @access protected
420 */
421 protected function content_template() {
422 ?>
423 <#
424 var getRating = function() {
425 var ratingScale = parseInt( settings.rating_scale, 10 ),
426 rating = settings.rating > ratingScale ? ratingScale : settings.rating;
427
428 return [ rating, ratingScale ];
429 },
430 ratingData = getRating(),
431 rating = ratingData[0],
432 textualRating = ratingData[0] + '/' + ratingData[1],
433 renderStars = function( icon ) {
434 var starsHtml = '',
435 flooredRating = Math.floor( rating );
436
437 for ( var stars = 1; stars <= ratingData[1]; stars++ ) {
438 if ( stars <= flooredRating ) {
439 starsHtml += '<i class="elementor-star-full">' + icon + '</i>';
440 } else if ( flooredRating + 1 === stars && rating !== flooredRating ) {
441 starsHtml += '<i class="elementor-star-' + ( rating - flooredRating ).toFixed( 1 ) * 10 + '">' + icon + '</i>';
442 } else {
443 starsHtml += '<i class="elementor-star-empty">' + icon + '</i>';
444 }
445 }
446
447 return starsHtml;
448 },
449 icon = '&#xE934;';
450
451 if ( 'star_fontawesome' === settings.star_style ) {
452 if ( 'outline' === settings.unmarked_star_style ) {
453 icon = '&#xE933;';
454 }
455 } else if ( 'star_unicode' === settings.star_style ) {
456 icon = '&#9733;';
457
458 if ( 'outline' === settings.unmarked_star_style ) {
459 icon = '&#9734;';
460 }
461 }
462
463 view.addRenderAttribute( 'iconWrapper', 'class', 'elementor-star-rating' );
464 view.addRenderAttribute( 'iconWrapper', 'itemtype', 'http://schema.org/Rating' );
465 view.addRenderAttribute( 'iconWrapper', 'title', textualRating );
466 view.addRenderAttribute( 'iconWrapper', 'itemscope', '' );
467 view.addRenderAttribute( 'iconWrapper', 'itemprop', 'reviewRating' );
468
469 var stars = renderStars( icon );
470 #>
471
472 <div class="elementor-star-rating__wrapper">
473 <# if ( ! _.isEmpty( settings.title ) ) { #>
474 <div class="elementor-star-rating__title">{{ settings.title }}</div>
475 <# } #>
476 <div {{{ view.getRenderAttributeString( 'iconWrapper' ) }}} >
477 {{{ stars }}}
478 <span itemprop="ratingValue" class="elementor-screen-only">{{ textualRating }}</span>
479 </div>
480 </div>
481
482 <?php
483 }
484 }
485