HEX
Server: nginx/1.24.0
System: Linux DGT-WORDPRESS-VM-SERVER 6.14.0-1017-azure #17~24.04.1-Ubuntu SMP Mon Dec 1 20:10:50 UTC 2025 x86_64
User: ubuntu (1000)
PHP: 8.4.12
Disabled: NONE
Upload Files
File: /mnt/data/dreamssalon-wp/wp-content/plugins/dreamsalon-widgets/widgets/class-home3-hero-section.php
<?php
/**
 * DS Home3 Hero Section Widget
 */

namespace dreamsalonelementor\Widgets;

use Elementor\Widget_Base;
use Elementor\Controls_Manager;
use Elementor\Group_Control_Typography;

if ( ! defined( 'ABSPATH' ) ) { exit; }

class DSHome3HeroSection extends Widget_Base {
    public function get_name() { return 'dreamsalon-home3-hero-section'; }
    public function get_title() { return __( 'Home3 Hero Section', 'dreamsalon_elementor' ); }
    public function get_icon() { return 'eicon-banner'; }
    public function get_categories() { return [ 'dreamsalonelemetortheme' ]; }

    protected function _register_controls() {
        // Content controls
        $this->start_controls_section('section_content', [
            'label' => __( 'Content', 'dreamsalon_elementor' ),
            'tab'   => Controls_Manager::TAB_CONTENT,
        ]);

        // Rating / avatars
        $this->add_control('rating_value', [
            'label' => __( 'Rating Value', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::TEXT,
            'default' => '4.8 / 5.0',
        ]);

        $this->add_control('reviews_text', [
            'label' => __( 'Reviews Text', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::TEXT,
            'default' => 'From 2000+ Reviews',
        ]);

        $this->add_control('reviews_mode', [
            'label' => __( 'Reviews Mode', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::SELECT,
            'options' => [
                'static'  => __( 'Static (use text above)', 'dreamsalon_elementor' ),
               // 'dynamic' => __( 'Dynamic (from service reviews)', 'dreamsalon_elementor' ),
            ],
            'default' => 'static',
        ]);

        $this->add_control('avatars', [
            'label' => __( 'Avatar Images (1)', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::GALLERY,
            'default' => [],
            'description' => __( 'First 1 images will be used.', 'dreamsalon_elementor' ),
        ]);

        // Heading & description
        $this->add_control('heading', [
            'label' => __( 'Heading', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::TEXT,
            'default' => 'Luxury Appointments, Instantly Scheduled',
        ]);

        $this->add_control('heading_highlight_text', [
            'label' => __( 'Highlight Text', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::TEXT,
            'default' => 'Appointments',
        ]);

        $this->add_control('description', [
            'label' => __( 'Description', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::TEXTAREA,
            'default' => 'Discover personalized salon services that enhance your natural beauty, delivered by professionals who understand that every detail matters.',
        ]);

        // Buttons
        $this->add_control('primary_btn_text', [
            'label' => __( 'Primary Button Text', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::TEXT,
            'default' => 'View All Listings',
        ]);

        $this->add_control('primary_btn_url', [
            'label' => __( 'Primary Button URL', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::URL,
            'default' => [ 'url' => '#' ],
        ]);

        $this->add_control('secondary_btn_text', [
            'label' => __( 'Phone', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::TEXT,
            'default' => 'View All Listings',
        ]);

        $this->add_control('secondary_btn_url', [
            'label' => __( 'Phone To Call', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::URL,
            'default' => [ 'url' => '#' ],
        ]);

       
          // Images
        $this->add_control('stat_img', [
            'label' => __( 'Image', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::MEDIA,
            'default' => [ 'url' => get_template_directory_uri() . '/assets/image/smile.png' ],
        ]);

        $this->add_control('stat1_text', [
            'label' => __( 'Stat 1 Text', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::TEXT,
            'default' => 'Total Customers',
        ]);

        

        // Images
        $this->add_control('shape_1', [
            'label' => __( 'Shape 1 Image', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::MEDIA,
            'default' => [ 'url' => get_template_directory_uri() . '/assets/img/home-2/shape-04.svg' ],
        ]);
        $this->add_control('shape_2', [
            'label' => __( 'Shape 2 Image', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::MEDIA,
            'default' => [ 'url' => get_template_directory_uri() . '/assets/img/home-2/shape-05.svg' ],
        ]);
       

        $this->add_control('banner_img1', [
            'label' => __( 'Banner Image 1', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::MEDIA,
            'default' => [ 'url' => get_template_directory_uri() . '/assets/img/home-2/banner-01.jpg' ],
        ]);
        $this->add_control('banner_img2', [
            'label' => __( 'Banner Image 2', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::MEDIA,
            'default' => [ 'url' => get_template_directory_uri() . '/assets/img/home-2/banner-02.jpg' ],
        ]);
        $this->add_control('banner_img3', [
            'label' => __( 'Banner Image 3', 'dreamsalon_elementor' ),
            'type' => Controls_Manager::MEDIA,
            'default' => [ 'url' => get_template_directory_uri() . '/assets/img/home-2/banner-03.jpg' ],
        ]);

        $this->end_controls_section();

        // Style controls
        $this->start_controls_section(
            'section_style',
            [
                'label' => __( 'Style', 'dreamsalon_elementor' ),
                'tab'   => Controls_Manager::TAB_STYLE,
            ]
        );

        // Title
        $this->add_control('title_color', [
            'label' => __( 'Title Color', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .banner-section-two h1' => 'color: {{VALUE}};',
            ],
        ]);
        $this->add_control('title_highlight_color', [
            'label' => __( 'Highlight Color', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .banner-section-two h1 .text-primary' => 'color: {{VALUE}};',
            ],
        ]);
        $this->add_group_control(
            Group_Control_Typography::get_type(),
            [
                'name' => 'title_typography',
                'label' => __( 'Title Typography', 'dreamsalon_elementor' ),
                'selector' => '{{WRAPPER}} .banner-section-two h1',
            ]
        );

        // Description
        $this->add_control('desc_color', [
            'label' => __( 'Description Color', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .banner-section-two .banner-content > p' => 'color: {{VALUE}};',
            ],
        ]);
        $this->add_group_control(
            Group_Control_Typography::get_type(),
            [
                'name' => 'desc_typography',
                'label' => __( 'Description Typography', 'dreamsalon_elementor' ),
                'selector' => '{{WRAPPER}} .banner-section-two .banner-content > p',
            ]
        );

        // Rating / reviews
        $this->add_control('rating_text_color', [
            'label' => __( 'Rating Text Color', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .banner-section-two .user-rating p' => 'color: {{VALUE}};',
            ],
        ]);
        $this->add_control('rating_star_color', [
            'label' => __( 'Rating Star Color', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .banner-section-two .rating i' => 'color: {{VALUE}};',
            ],
        ]);
        $this->add_group_control(
            Group_Control_Typography::get_type(),
            [
                'name' => 'rating_typography',
                'label' => __( 'Rating Typography', 'dreamsalon_elementor' ),
                'selector' => '{{WRAPPER}} .banner-section-two .rating .fw-bold',
            ]
        );

        // Stats
        $this->add_control('stats_number_color', [
            'label' => __( 'Stats Number Color', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .banner-section-two .item-padding h3' => 'color: {{VALUE}};',
            ],
        ]);
        $this->add_group_control(
            Group_Control_Typography::get_type(),
            [
                'name' => 'stats_number_typography',
                'label' => __( 'Stats Number Typography', 'dreamsalon_elementor' ),
                'selector' => '{{WRAPPER}} .banner-section-two .item-padding h3',
            ]
        );
        $this->add_control('stats_text_color', [
            'label' => __( 'Stats Text Color', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .banner-section-two .item-padding .item-text' => 'color: {{VALUE}};',
            ],
        ]);
        $this->add_group_control(
            Group_Control_Typography::get_type(),
            [
                'name' => 'stats_text_typography',
                'label' => __( 'Stats Text Typography', 'dreamsalon_elementor' ),
                'selector' => '{{WRAPPER}} .banner-section-two .item-padding .item-text',
            ]
        );

        // Buttons
        $this->add_group_control(
            Group_Control_Typography::get_type(),
            [
                'name' => 'button_typography',
                'label' => __( 'Button Typography', 'dreamsalon_elementor' ),
                'selector' => '{{WRAPPER}} .banner-section-two .banner-btns .btn',
            ]
        );
        $this->add_control('primary_button_bg', [
            'label' => __( 'Primary Button BG', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .banner-section-two .btn.btn-primary' => 'background-color: {{VALUE}};',
            ],
        ]);
        $this->add_control('secondary_button_bg', [
            'label' => __( 'Secondary Button BG', 'dreamsalon_elementor' ),
            'type'  => Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .banner-section-two .btn.btn-white' => 'background-color: {{VALUE}};',
            ],
        ]);

        $this->end_controls_section();
    }

    protected function render() {
        $s = $this->get_settings_for_display();

        $avatars = [];
        if ( ! empty( $s['avatars'] ) && is_array( $s['avatars'] ) ) {
            $items = array_slice( $s['avatars'], 0, 3 );
            foreach ( $items as $item ) {
                if ( ! empty( $item['url'] ) ) {
                    $avatars[] = $item['url'];
                }
            }
        }

        $rating_value  = ! empty( $s['rating_value'] ) ? $s['rating_value'] : '';
        $reviews_text  = ! empty( $s['reviews_text'] ) ? $s['reviews_text'] : '';
        $heading       = ! empty( $s['heading'] ) ? $s['heading'] : '';
        $highlight_txt = ! empty( $s['heading_highlight_text'] ) ? $s['heading_highlight_text'] : '';
        $description   = ! empty( $s['description'] ) ? $s['description'] : '';

        $primary_btn_text = ! empty( $s['primary_btn_text'] ) ? $s['primary_btn_text'] : '';
        $primary_btn_url  = ! empty( $s['primary_btn_url']['url'] ) ? $s['primary_btn_url']['url'] : '#';
        $secondary_btn_text = ! empty( $s['secondary_btn_text'] ) ? $s['secondary_btn_text'] : '';
        $secondary_btn_url  = ! empty( $s['secondary_btn_url']['url'] ) ? $s['secondary_btn_url']['url'] : '#';

         $stat1_text   = ! empty( $s['stat1_text'] ) ? $s['stat1_text'] : '';
        
        // Dynamic mode: compute stats and rating from service reviews
        if ( isset( $s['reviews_mode'] ) && $s['reviews_mode'] === 'dynamic' ) {
            $total_reviews = 0;
            $avg_rating    = 0;
            $rating_sum    = 0;
            $rating_count  = 0;
            $unique_customers = [];

            if ( class_exists( '\\WP_Comment_Query' ) ) {
                try {
                    // Count total approved comments with rating meta on service posts
                    $count_query   = new \WP_Comment_Query();
                    $total_reviews = (int) $count_query->query([
                        'count'      => true,
                        'status'     => 'approve',
                        'post_type'  => 'service',
                        'meta_query' => [
                            [
                                'key'     => 'rating',
                                'compare' => 'EXISTS',
                            ],
                        ],
                    ]);

                    // Fetch a subset of comments to compute average and avatars/customers
                    $comment_query = new \WP_Comment_Query();
                    $comments      = $comment_query->query([
                        'status'     => 'approve',
                        'post_type'  => 'service',
                        'meta_query' => [
                            [
                                'key'     => 'rating',
                                'compare' => 'EXISTS',
                            ],
                        ],
                        'number' => 500,
                    ]);

                    if ( ! is_wp_error( $comments ) && ! empty( $comments ) ) {
                        $avatar_urls_dynamic = [];

                        foreach ( $comments as $c ) {
                            $rating_val = get_comment_meta( $c->comment_ID, 'rating', true );
                            if ( is_numeric( $rating_val ) ) {
                                $rating_sum   += (float) $rating_val;
                                $rating_count ++;
                            }

                            // Track unique customers by user ID or email
                            $key = 0;
                            if ( ! empty( $c->user_id ) ) {
                                $key = 'user_' . (int) $c->user_id;
                            } elseif ( ! empty( $c->comment_author_email ) ) {
                                $key = 'email_' . strtolower( $c->comment_author_email );
                            }

                            if ( $key && ! isset( $unique_customers[ $key ] ) ) {
                                $unique_customers[ $key ] = true;

                                // Collect up to 3 avatars for display
                                if ( count( $avatar_urls_dynamic ) < 3 ) {
                                    if ( ! empty( $c->user_id ) ) {
                                        $av = get_avatar_url( $c->user_id, [ 'size' => 64 ] );
                                    } else {
                                        $av = get_avatar_url( $c->comment_author_email, [ 'size' => 64 ] );
                                    }
                                    if ( $av ) {
                                        $avatar_urls_dynamic[] = $av;
                                    }
                                }
                            }
                        }

                        if ( $rating_count > 0 ) {
                            $avg_rating = $rating_sum / $rating_count;
                        }

                        // Override gallery avatars with dynamic reviewer avatars if available
                        if ( ! empty( $avatar_urls_dynamic ) ) {
                            $avatars = $avatar_urls_dynamic;
                        }
                    }
                } catch ( \Exception $e ) {
                    $total_reviews = 0;
                }
            }

            // Average rating text like "4.8 / 5.0"
            if ( $avg_rating > 0 ) {
                $rating_value = sprintf( '%.1f / 5.0', $avg_rating );
            }

            // Reviews text from total
            if ( $total_reviews > 0 ) {
                $reviews_text = sprintf(
                    __( 'From %s+ Reviews', 'dreamsalon_elementor' ),
                    number_format_i18n( $total_reviews )
                );
            }
 
           
        }

        $shape_1 = ! empty( $s['shape_1']['url'] ) ? $s['shape_1']['url'] : '';
        $stat_img = ! empty( $s['stat_img']['url'] ) ? $s['stat_img']['url'] : '';
        

        $shape_2 = ! empty( $s['shape_2']['url'] ) ? $s['shape_2']['url'] : '';
 
        $banner_img1 = ! empty( $s['banner_img1']['url'] ) ? $s['banner_img1']['url'] : '';
        $banner_img2 = ! empty( $s['banner_img2']['url'] ) ? $s['banner_img2']['url'] : '';
        $banner_img3 = ! empty( $s['banner_img3']['url'] ) ? $s['banner_img3']['url'] : '';
        ?>

        <!-- Banner Section Two -->
        <section class="banner-section-two z-0">
            <?php if ( $shape_1 ) : ?>
                <img src="<?php echo esc_url( $shape_1 ); ?>" alt="shape" class="start-0 top-0 position-absolute d-lg-flex d-none z-n1 home-5-shape shape-01">
            <?php endif; ?>
            <?php if ( $shape_2 ) : ?>
                <img src="<?php echo esc_url( $shape_2 ); ?>" alt="bg" class="end-0 bottom-0 position-absolute d-lg-flex d-none z-n1 home-5-shape shape-02">
            <?php endif; ?>
            

            <div class="container">
                <div class="row align-items-center">
                    <div class="col-lg-7">
                        <div class="banner-content wow fadeInUp" data-wow-duration="3s">
                           

                            <?php if ( $heading ) : ?>
                                <h1 class="mb-4">
                                    <?php
                                    if ( $highlight_txt && strpos( $heading, $highlight_txt ) !== false ) {
                                        echo wp_kses_post( str_replace( $highlight_txt, '<span class="text-primary text-decoration-underline">' . esc_html( $highlight_txt ) . '</span>', esc_html( $heading ) ) );
                                    } else {
                                        echo esc_html( $heading );
                                    }
                                    ?>
                                </h1>
                            <?php endif; ?>

                            <?php if ( $description ) : ?>
                                <p><?php echo esc_html( $description ); ?></p>
                            <?php endif; ?>

                            <div class="d-flex align-items-center gap-3 flex-wrap banner-btns">
                                <?php if ( $primary_btn_text ) : ?>
                                    <a href="<?php echo esc_url( $primary_btn_url ); ?>" class="btn btn-primary btn-lg d-flex align-items-center rounded-pill">
                                        <?php echo esc_html( $primary_btn_text ); ?><i class="ti ti-chevron-right ms-1"></i>
                                    </a>
                                <?php endif; ?>
                                <?php if ( $secondary_btn_text ) : ?>
                                    <a href="tel:<?php echo esc_html( $secondary_btn_url ); ?>" class="btn btn-white btn-lg d-flex align-items-center rounded-pill">
                                       <i class="ti ti-phone me-1"></i> <?php echo esc_html( $secondary_btn_text ); ?>
                                    </a>
                                <?php endif; ?>
                            </div>


                            <div class="banner3 pt-3 mt-3">
                             <div class="user-rating rounded-pill bg-transparent mb-3 d-inline-flex align-items-center justify-content-center justify-content-sm-between flex-wrap gap-4">
                                
                             <div class="d-flex align-items-center gap-2">
                                  <?php if ( $stat_img ) : ?>
                                      <div class="avatar-list-stacked flex-shrink-0">
                <span class="avatar rounded-circle"> <img src="<?php echo esc_url( $stat_img ); ?>" alt="shape" class="img-fluid rounded-circle"></span>
                </div>
            <?php endif; ?>
                                      
                                    <?php if ( $stat1_text ) : ?>
                                            <p class="fs-14"><?php echo wp_kses_post( $stat1_text ); ?></p>
                                        <?php endif; ?>
                                      
                             </div>
                             <div class="d-flex align-items-center gap-2">
                                    <div class="avatar-list-stacked flex-shrink-0">
                                        <?php foreach ( $avatars as $av ) : ?>
                                            <span class="avatar rounded-circle"><img src="<?php echo esc_url( $av ); ?>" class="img-fluid rounded-circle" alt="avatar"></span>
                                        <?php endforeach; ?>
                                    </div>
                                    <div>
                                        <div class="d-flex align-items-center rating gap-1 fs-14 text-warning">

                                          <?php if ( $rating_value ) : ?>
                                                <p class="fs-14 heading-color fw-bold me-2 mb-0"><?php echo esc_html( $rating_value ); ?></p>
                                            <?php endif; ?>

                                            <i class="ti ti-star-filled filled"></i>
                                            <i class="ti ti-star-filled filled"></i>
                                            <i class="ti ti-star-filled filled"></i>
                                            <i class="ti ti-star-filled filled"></i>
                                            <i class="ti ti-star-filled filled"></i>
                                          
                                        </div>
                                        <?php if ( $reviews_text ) : ?>
                                            <p class="fs-14"><?php echo esc_html( $reviews_text ); ?></p>
                                        <?php endif; ?>
                                    </div>
                                </div>
                            </div>
                            
</div>
                            
                        </div>
                    </div>

                    <div class="col-lg-5">
                        <div class="banner-image">
                            <?php if ( $banner_img1 ) : ?>
                                <img src="<?php echo esc_url( $banner_img1 ); ?>" alt="banner-1" class="banner-img1">
                            <?php endif; ?>
                            <?php if ( $banner_img2 ) : ?>
                                <img src="<?php echo esc_url( $banner_img2 ); ?>" alt="banner-2" class="banner-img2">
                            <?php endif; ?>
                            <?php if ( $banner_img3 ) : ?>
                                <img src="<?php echo esc_url( $banner_img3 ); ?>" alt="banner-3" class="banner-img3">
                            <?php endif; ?>
                        </div>
                    </div>
                </div>
            </div>
        </section>
        <!-- Hero Section Three End -->
        <?php
    }
}