Elementor Business Hours Widget
February 11, 2025 · AI Conversations
—
## **Step 1: Register the Custom Widget**
Create a new Elementor widget in your custom plugin or theme’s `functions.php`.
### **File Structure**
wp-content/plugins/elementor-custom-widget/
│── elementor-custom-widget.php
│── includes/
│ ├── widgets/
│ │ ├── business-hours-widget.php
### **1. Create the Main Plugin File**
Create `elementor-custom-widget.php` in `wp-content/plugins/elementor-custom-widget/`:
<?php
/**
* Plugin Name: Elementor Custom Business Hours Widget
* Description: Custom Elementor widget to display business hours and check if open.
* Version: 1.0
* Author: Neeraj Tiwari
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
// Register Custom Widget
function register_custom_business_hours_widget( $widgets_manager ) {
require_once( __DIR__ . '/includes/widgets/business-hours-widget.php' );
$widgets_manager->register( new Elementor_Business_Hours_Widget() );
}
add_action( 'elementor/widgets/register', 'register_custom_business_hours_widget' );
—
## **Step 2: Create the Widget Class**
Create `business-hours-widget.php` inside `includes/widgets/`:
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
class Elementor_Business_Hours_Widget extends ElementorWidget_Base {
public function get_name() {
return 'business_hours';
}
public function get_title() {
return __( 'Business Hours', 'elementor-custom-widget' );
}
public function get_icon() {
return 'eicon-clock';
}
public function get_categories() {
return [ 'general' ];
}
protected function register_controls() {
$this->start_controls_section(
'content_section',
[
'label' => __( 'Business Hours', 'elementor-custom-widget' ),
'tab' => ElementorControls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'week_days',
[
'label' => __( 'Week Days & Hours', 'elementor-custom-widget' ),
'type' => ElementorControls_Manager::REPEATER,
'fields' => [
[
'name' => 'day',
'label' => __( 'Day', 'elementor-custom-widget' ),
'type' => ElementorControls_Manager::SELECT,
'options' => [
'Monday' => __( 'Monday', 'elementor-custom-widget' ),
'Tuesday' => __( 'Tuesday', 'elementor-custom-widget' ),
'Wednesday' => __( 'Wednesday', 'elementor-custom-widget' ),
'Thursday' => __( 'Thursday', 'elementor-custom-widget' ),
'Friday' => __( 'Friday', 'elementor-custom-widget' ),
'Saturday' => __( 'Saturday', 'elementor-custom-widget' ),
'Sunday' => __( 'Sunday', 'elementor-custom-widget' ),
],
'default' => 'Monday',
],
[
'name' => 'opening_time',
'label' => __( 'Opening Time', 'elementor-custom-widget' ),
'type' => ElementorControls_Manager::TIME,
'default' => '09:00',
],
[
'name' => 'closing_time',
'label' => __( 'Closing Time', 'elementor-custom-widget' ),
'type' => ElementorControls_Manager::TIME,
'default' => '18:00',
],
],
'title_field' => '{{{ day }}} ({{{ opening_time }}} - {{{ closing_time }}})',
]
);
$this->end_controls_section();
}
protected function render() {
$settings = $this->get_settings_for_display();
$week_days = $settings['week_days'];
date_default_timezone_set(get_option('timezone_string') ?: 'UTC'); // Use WP timezone
$current_day = date('l');
$current_time = date('H:i');
$is_open = false;
$open_message = '';
foreach ($week_days as $day) {
if ($day['day'] === $current_day) {
if ($current_time >= $day['opening_time'] && $current_time <= $day['closing_time']) {
$is_open = true;
break;
}
}
}
echo '<div class="business-hours-widget">';
echo '<ul>';
foreach ($week_days as $day) {
echo '<li>' . esc_html($day['day']) . ': ' . esc_html($day['opening_time']) . ' - ' . esc_html($day['closing_time']) . '</li>';
}
echo '</ul>';
echo '<p class="business-status">' . ($is_open ? '<span style="color:green;">We are Open</span>' : '<span style="color:red;">We are Closed</span>') . '</p>';
echo '</div>';
}
}
—
## **Step 3: Activate the Plugin**
– Go to **WordPress Admin > Plugins**.
– Find **Elementor Custom Business Hours Widget** and activate it.
– Add the widget to any Elementor page.
—
### **Final Output**
– Displays a list of business hours.
– Automatically detects the current day and time.
– Shows "We are Open" or "We are Closed" based on current time.
Would you like any additional styling or features, such as different layouts or conditional messages?
—
## **📂 File Structure**
wp-content/plugins/elementor-business-hours/
│── elementor-business-hours.php
│── includes/
│ ├── widgets/
│ │ ├── business-hours-widget.php
│ ├── templates/
│ │ ├── business-hours-template.php
—
## **1️⃣ Main Plugin File (`elementor-business-hours.php`)**
This file registers the Elementor widget.
<?php
/**
* Plugin Name: Elementor Business Hours Widget
* Description: Custom Elementor widget to display business hours.
* Version: 1.0
* Author: Neeraj Tiwari
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
// Define plugin path
define( 'EBH_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
// Register Custom Widget
function register_elementor_business_hours_widget( $widgets_manager ) {
require_once( EBH_PLUGIN_PATH . 'includes/widgets/business-hours-widget.php' );
$widgets_manager->register( new Elementor_Business_Hours_Widget() );
}
add_action( 'elementor/widgets/register', 'register_elementor_business_hours_widget' );
—
## **2️⃣ Widget File (`includes/widgets/business-hours-widget.php`)**
This file defines the Elementor widget.
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
class Elementor_Business_Hours_Widget extends ElementorWidget_Base {
public function get_name() {
return 'business_hours';
}
public function get_title() {
return __( 'Business Hours', 'elementor-business-hours' );
}
public function get_icon() {
return 'eicon-clock';
}
public function get_categories() {
return [ 'general' ];
}
protected function register_controls() {
$this->start_controls_section(
'content_section',
[
'label' => __( 'Business Hours', 'elementor-business-hours' ),
'tab' => ElementorControls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'week_days',
[
'label' => __( 'Week Days & Hours', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::REPEATER,
'fields' => [
[
'name' => 'day',
'label' => __( 'Day', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::SELECT,
'options' => [
'Monday' => __( 'Monday', 'elementor-business-hours' ),
'Tuesday' => __( 'Tuesday', 'elementor-business-hours' ),
'Wednesday' => __( 'Wednesday', 'elementor-business-hours' ),
'Thursday' => __( 'Thursday', 'elementor-business-hours' ),
'Friday' => __( 'Friday', 'elementor-business-hours' ),
'Saturday' => __( 'Saturday', 'elementor-business-hours' ),
'Sunday' => __( 'Sunday', 'elementor-business-hours' ),
],
'default' => 'Monday',
],
[
'name' => 'opening_time',
'label' => __( 'Opening Time', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::TIME,
'default' => '09:00',
],
[
'name' => 'closing_time',
'label' => __( 'Closing Time', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::TIME,
'default' => '18:00',
],
],
'title_field' => '{{{ day }}} ({{{ opening_time }}} - {{{ closing_time }}})',
]
);
$this->end_controls_section();
}
protected function render() {
$settings = $this->get_settings_for_display();
$week_days = $settings['week_days'];
// Pass data to template
include( EBH_PLUGIN_PATH . 'includes/templates/business-hours-template.php' );
}
}
—
## **3️⃣ Template File (`includes/templates/business-hours-template.php`)**
This file handles the front-end display.
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
date_default_timezone_set(get_option('timezone_string') ?: 'UTC'); // Use WP timezone
$current_day = date('l');
$current_time = date('H:i');
$is_open = false;
foreach ($week_days as $day) {
if ($day['day'] === $current_day) {
if ($current_time >= $day['opening_time'] && $current_time <= $day['closing_time']) {
$is_open = true;
break;
}
}
}
?>
<div class="business-hours-widget">
<ul>
<?php foreach ($week_days as $day): ?>
<li><?php echo esc_html($day['day']) . ': ' . esc_html($day['opening_time']) . ' - ' . esc_html($day['closing_time']); ?></li>
<?php endforeach; ?>
</ul>
<p class="business-status">
<?php echo $is_open ? '<span style="color:green;">We are Open</span>' : '<span style="color:red;">We are Closed</span>'; ?>
</p>
</div>
—
## **🎯 Features & Benefits**
✅ **Widget & Template Separation**: Business logic stays in `business-hours-widget.php`, while the template is in `business-hours-template.php`.
✅ **Easy Maintenance**: The template can be edited separately without modifying the widget logic.
✅ **Dynamic Opening Status**: Checks the user's current time and updates the status dynamically.
Would you like to add custom styling or additional features like highlighting the current day? 🚀
### ✅ **Fix: Ensure Proper Time Formatting**
Modify the way we handle time comparison by explicitly formatting the opening and closing times.
#### **Updated Code for `business-hours-template.php`**
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
date_default_timezone_set(get_option('timezone_string') ?: 'UTC'); // Use WordPress timezone
$current_day = date('l');
$current_time = strtotime(date('H:i')); // Convert current time to timestamp
$is_open = false;
foreach ($week_days as $day) {
$opening_time = isset($day['opening_time']) ? strtotime($day['opening_time']) : null;
$closing_time = isset($day['closing_time']) ? strtotime($day['closing_time']) : null;
if ($day['day'] === $current_day && $opening_time && $closing_time) {
if ($current_time >= $opening_time && $current_time <= $closing_time) {
$is_open = true;
break;
}
}
}
?>
<div class="business-hours-widget">
<ul>
<?php foreach ($week_days as $day): ?>
<li>
<?php echo esc_html($day['day']) . ': ' . esc_html($day['opening_time']) . ' - ' . esc_html($day['closing_time']); ?>
</li>
<?php endforeach; ?>
</ul>
<p class="business-status">
<?php echo $is_open ? '<span style="color:green;">We are Open</span>' : '<span style="color:red;">We are Closed</span>'; ?>
</p>
</div>
—
### 🔍 **What Was Wrong?**
1. `TIME` control values might not be directly comparable with `date('H:i')` because of formatting differences.
2. Using `strtotime()` ensures both values are converted to timestamps before comparison.
Now your business hours widget will correctly determine whether the store is open based on the user's local time. 🚀 Let me know if you need further tweaks!
—
### ✅ **Fix: Use `TEXT` Instead of `TIME`**
Since Elementor lacks a direct `TIME` control, we can use `Controls_Manager::TEXT` and validate user input to ensure it's formatted as `HH:MM`.
#### **Update `business-hours-widget.php`**
protected function register_controls() {
$this->start_controls_section(
'content_section',
[
'label' => __( 'Business Hours', 'elementor-business-hours' ),
'tab' => ElementorControls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'week_days',
[
'label' => __( 'Week Days & Hours', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::REPEATER,
'fields' => [
[
'name' => 'day',
'label' => __( 'Day', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::SELECT,
'options' => [
'Monday' => __( 'Monday', 'elementor-business-hours' ),
'Tuesday' => __( 'Tuesday', 'elementor-business-hours' ),
'Wednesday' => __( 'Wednesday', 'elementor-business-hours' ),
'Thursday' => __( 'Thursday', 'elementor-business-hours' ),
'Friday' => __( 'Friday', 'elementor-business-hours' ),
'Saturday' => __( 'Saturday', 'elementor-business-hours' ),
'Sunday' => __( 'Sunday', 'elementor-business-hours' ),
],
'default' => 'Monday',
],
[
'name' => 'opening_time',
'label' => __( 'Opening Time (HH:MM)', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::TEXT,
'default' => '09:00',
'description' => __( 'Enter time in 24-hour format (HH:MM)', 'elementor-business-hours' ),
],
[
'name' => 'closing_time',
'label' => __( 'Closing Time (HH:MM)', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::TEXT,
'default' => '18:00',
'description' => __( 'Enter time in 24-hour format (HH:MM)', 'elementor-business-hours' ),
],
],
'title_field' => '{{{ day }}} ({{{ opening_time }}} - {{{ closing_time }}})',
]
);
$this->end_controls_section();
}
—
### ✅ **Update `business-hours-template.php`**
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
date_default_timezone_set(get_option('timezone_string') ?: 'UTC'); // Use WordPress timezone
$current_day = date('l');
$current_time = strtotime(date('H:i')); // Convert current time to timestamp
$is_open = false;
foreach ($week_days as $day) {
// Validate time format to prevent errors
$opening_time = isset($day['opening_time']) ? date('H:i', strtotime($day['opening_time'])) : null;
$closing_time = isset($day['closing_time']) ? date('H:i', strtotime($day['closing_time'])) : null;
if ($day['day'] === $current_day && $opening_time && $closing_time) {
if ($current_time >= strtotime($opening_time) && $current_time <= strtotime($closing_time)) {
$is_open = true;
break;
}
}
}
?>
<div class="business-hours-widget">
<ul>
<?php foreach ($week_days as $day): ?>
<li>
<?php echo esc_html($day['day']) . ': ' . esc_html($day['opening_time']) . ' - ' . esc_html($day['closing_time']); ?>
</li>
<?php endforeach; ?>
</ul>
<p class="business-status">
<?php echo $is_open ? '<span style="color:green;">We are Open</span>' : '<span style="color:red;">We are Closed</span>'; ?>
</p>
</div>
—
### **🎯 What's Fixed?**
✔ **Replaced `TIME` control with `TEXT` control**
✔ **Ensured proper validation & formatting for `HH:MM` format**
✔ **No more undefined errors in Elementor!**
🚀 Now your Elementor widget will work perfectly. Let me know if you need enhancements! 🎉
—
### ✅ **Updated Widget with Time Dropdown**
This version uses **Elementor's `SELECT` control** for **Opening and Closing Hours**.
#### **🔹 Update `business-hours-widget.php`**
protected function register_controls() {
$this->start_controls_section(
'content_section',
[
'label' => __( 'Business Hours', 'elementor-business-hours' ),
'tab' => ElementorControls_Manager::TAB_CONTENT,
]
);
// Generate time slots in 30-minute intervals
$time_slots = [];
for ($i = 0; $i < 24; $i++) {
for ($j = 0; $j < 60; $j += 30) {
$time = sprintf('%02d:%02d', $i, $j);
$time_slots[$time] = $time;
}
}
$this->add_control(
'week_days',
[
'label' => __( 'Week Days & Hours', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::REPEATER,
'fields' => [
[
'name' => 'day',
'label' => __( 'Day', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::SELECT,
'options' => [
'Monday' => __( 'Monday', 'elementor-business-hours' ),
'Tuesday' => __( 'Tuesday', 'elementor-business-hours' ),
'Wednesday' => __( 'Wednesday', 'elementor-business-hours' ),
'Thursday' => __( 'Thursday', 'elementor-business-hours' ),
'Friday' => __( 'Friday', 'elementor-business-hours' ),
'Saturday' => __( 'Saturday', 'elementor-business-hours' ),
'Sunday' => __( 'Sunday', 'elementor-business-hours' ),
],
'default' => 'Monday',
],
[
'name' => 'opening_time',
'label' => __( 'Opening Time', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::SELECT,
'options' => $time_slots, // Dropdown options
'default' => '09:00',
],
[
'name' => 'closing_time',
'label' => __( 'Closing Time', 'elementor-business-hours' ),
'type' => ElementorControls_Manager::SELECT,
'options' => $time_slots, // Dropdown options
'default' => '18:00',
],
],
'title_field' => '{{{ day }}} ({{{ opening_time }}} - {{{ closing_time }}})',
]
);
$this->end_controls_section();
}
—
### ✅ **Update `business-hours-template.php`**
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
date_default_timezone_set(get_option('timezone_string') ?: 'UTC'); // Use WordPress timezone
$current_day = date('l');
$current_time = strtotime(date('H:i')); // Convert current time to timestamp
$is_open = false;
foreach ($week_days as $day) {
$opening_time = isset($day['opening_time']) ? strtotime($day['opening_time']) : null;
$closing_time = isset($day['closing_time']) ? strtotime($day['closing_time']) : null;
if ($day['day'] === $current_day && $opening_time && $closing_time) {
if ($current_time >= $opening_time && $current_time <= $closing_time) {
$is_open = true;
break;
}
}
}
?>
<div class="business-hours-widget">
<ul>
<?php foreach ($week_days as $day): ?>
<li>
<?php echo esc_html($day['day']) . ': ' . esc_html($day['opening_time']) . ' - ' . esc_html($day['closing_time']); ?>
</li>
<?php endforeach; ?>
</ul>
<p class="business-status">
<?php echo $is_open ? '<span style="color:green;">We are Open</span>' : '<span style="color:red;">We are Closed</span>'; ?>
</p>
</div>
—
### 🎯 **What's New & Fixed?**
✔ **Dropdown instead of manual text input** (prevents invalid times).
✔ **Predefined 30-minute intervals** (e.g., `09:00`, `09:30`, `10:00`).
✔ **Improved time comparison** using `strtotime()`.
Now users can **select** opening and closing times instead of typing them. 🚀 Let me know if you need adjustments! 🎉
—
### ✅ **Method 1: Using `end()` Function** (Best for Simple Cases)
foreach ($week_days as $day) {
$is_last = ($day === end($week_days)); // Check if it's the last item
echo esc_html($day['day']) . ($is_last ? ' (Last Item)' : '') . '<br>';
}
🔹 `end($week_days)` moves the internal pointer to the last element and returns it.
—
### ✅ **Method 2: Using `count()` with `foreach`**
$total = count($week_days);
$index = 0;
foreach ($week_days as $day) {
$is_last = (++$index === $total);
echo esc_html($day['day']) . ($is_last ? ' (Last Item)' : '') . '<br>';
}
🔹 This method is **efficient** when iterating over an array while tracking its index.
—
### ✅ **Method 3: Using `array_key_last()` (PHP 7.3+)**
$last_key = array_key_last($week_days);
foreach ($week_days as $key => $day) {
$is_last = ($key === $last_key);
echo esc_html($day['day']) . ($is_last ? ' (Last Item)' : '') . '<br>';
}
🔹 `array_key_last($week_days)` returns the last **key** in an associative or indexed array.
—
### **🎯 Best Approach?**
– ✅ **For PHP 7.3+**, use `array_key_last()`
– ✅ **For simple checks**, use `end()`
– ✅ **For numeric iteration**, use `count()`
—
Now your Elementor widget can **detect the last item in the loop** easily! 🚀 Let me know if you need tweaks. 🎉