balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

star-rating.php (12145B)


      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 }