1

I have an open / closed script that I'd like to be placed in 3 separate areas of my page: The header, the footer and on a mobile menu panel when responsive.

I can get it to work fine in the header, but the minute I try to call it again (normally or via a shortcode) it wreaks havoc - causing strange layout changes or blank mobile panels.

I can't figure out what is causing this to happen, despite trying everything in the book (returning variables and calling those etc.)

This is setup as a function within Wordpress child theme's Functions.php file:

function open_closed_message() {

    date_default_timezone_set('America/Toronto');
    $date = new DateTime;
    echo date("D m/d/y  h:i:s ",time());

    $times = array(
        'mon' => '9:00 AM - 9:00 PM',
        'tue' => '9:00 AM - 9:00 PM',
        'wed' => '9:00 AM - 9:00 PM',
        'thu' => '9:00 AM - 9:00 PM',
        'fri' => '9:00 AM - 9:00 PM',
        'sat' => '11:00 AM - 6:00 PM',
        'sun' => 'closed'
    );

    function compileHours($times, $timestamp) {
        $times = $times[strtolower(date('D',$timestamp))];
        if(!strpos($times, '-')) return array();
        $hours = explode(",", $times);
        $hours = array_map('explode', array_pad(array(),count($hours),'-'), $hours);
        $hours = array_map('array_map', array_pad(array(),count($hours),'strtotime'),         $hours, array_pad(array(),count($hours),array_pad(array(),2,$timestamp)));
        end($hours);
        if ($hours[key($hours)][0] > $hours[key($hours)][1]) $hours[key($hours)][1] =         strtotime('+1 day', $hours[key($hours)][1]);
        return $hours;
    }

    function isOpen($now, $times) {
        $open = 0; // time until closing in seconds or 0 if closed
        // merge opening hours of today and the day before
        $hours = array_merge(compileHours($times,         strtotime('yesterday',$now)),compileHours($times, $now)); 

        foreach ($hours as $h) {
            if ($now >= $h[0] and $now < $h[1]) {
                $open = $h[1] - $now;
                return $open;
            } 
        }
        return $open;
    }

    $now = time();
    $open = isOpen($now, $times);

    if ($open == 0) {
        echo "Closed - Sorry, we are not making deliveries.";
    } 
    elseif ($open <= 1800) {
        $tomorrow = strtotime('tomorrow', $now);
        if (date('N', $tomorrow) == 7) {
            $tomorrow = strtotime('next monday', $now);
        }
        $day = strtolower(date('D', $tomorrow));
        $tomorrow = date('l', $tomorrow);
        $opentime = preg_replace('/^(\d+:\d+ [AP]M).*/', '$1', $times[$day]);
        echo "Finishing up current orders. We re-open $tomorrow at $opentime";
    }
    else {
        echo "Open - Yes, we are making deliveries.";
    }
}

All help is extremely appreciated as I have been trying to wrap my brain around this for hours.

2
  • so there is actually no error (500 error). just breaks the layout, then there's nothing to debug on the code above, its how to apply it in the layout. just make sure the text is in its proper place so that it doesn't break your html structure / markup Commented Mar 18, 2020 at 4:02
  • Check this stackoverflow.com/questions/39818420/… Commented Mar 18, 2020 at 4:12

1 Answer 1

2

Ok, so to make it short. Nesting functions is a dirty business. Your error goes as follows: You trigger the parent function. When this runs, it registers the nested functions. Which is why the first time you have no problem. However, when you run the parent for a second time, php will error saying that the nested functions already exists because its trying to register them again.

If you must preserve your code you can check if the function has already been registered.

function open_closed_message() {

    date_default_timezone_set('America/Toronto');
    $date = new DateTime;
    echo date("D m/d/y  h:i:s ",time());

    $times = array(
        'mon' => '9:00 AM - 9:00 PM',
        'tue' => '9:00 AM - 9:00 PM',
        'wed' => '9:00 AM - 9:00 PM',
        'thu' => '9:00 AM - 9:00 PM',
        'fri' => '9:00 AM - 9:00 PM',
        'sat' => '11:00 AM - 6:00 PM',
        'sun' => 'closed'
    );
// Check if function exists
if (!function_exists('compileHours')) {
    function compileHours($times, $timestamp) {
        $times = $times[strtolower(date('D',$timestamp))];
        if(!strpos($times, '-')) return array();
        $hours = explode(",", $times);
        $hours = array_map('explode', array_pad(array(),count($hours),'-'), $hours);
        $hours = array_map('array_map', array_pad(array(),count($hours),'strtotime'),         $hours, array_pad(array(),count($hours),array_pad(array(),2,$timestamp)));
        end($hours);
        if ($hours[key($hours)][0] > $hours[key($hours)][1]) $hours[key($hours)][1] =         strtotime('+1 day', $hours[key($hours)][1]);
        return $hours;
    }
}

// Check if function exists
if (!function_exists('isOpen')) {
    function isOpen($now, $times) {
        $open = 0; // time until closing in seconds or 0 if closed
        // merge opening hours of today and the day before
        $hours = array_merge(compileHours($times,         strtotime('yesterday',$now)),compileHours($times, $now)); 

        foreach ($hours as $h) {
            if ($now >= $h[0] and $now < $h[1]) {
                $open = $h[1] - $now;
                return $open;
            } 
        }
        return $open;
    }
}

    $now = time();
    $open = isOpen($now, $times);

    if ($open == 0) {
        echo "Closed - Sorry, we are not making deliveries.";
    } 
    elseif ($open <= 1800) {
        $tomorrow = strtotime('tomorrow', $now);
        if (date('N', $tomorrow) == 7) {
            $tomorrow = strtotime('next monday', $now);
        }
        $day = strtolower(date('D', $tomorrow));
        $tomorrow = date('l', $tomorrow);
        $opentime = preg_replace('/^(\d+:\d+ [AP]M).*/', '$1', $times[$day]);
        echo "Finishing up current orders. We re-open $tomorrow at $opentime";
    }
    else {
        echo "Open - Yes, we are making deliveries.";
    }
}

or you can make a class. which would be wayyyyyyyy better

class open_closed_message{

    public $date;

    public $times;

    public function __construct(){
        date_default_timezone_set('America/Toronto');
        $this->date = new DateTime;

        $this->times = [
            'mon' => '9:00 AM - 9:00 PM',
            'tue' => '9:00 AM - 9:00 PM',
            'wed' => '9:00 AM - 9:00 PM',
            'thu' => '9:00 AM - 9:00 PM',
            'fri' => '9:00 AM - 9:00 PM',
            'sat' => '11:00 AM - 6:00 PM',
            'sun' => 'closed'
        ];
    }

    public function message(){
        echo date("D m/d/y  h:i:s ",time());

        $now = time();
        $open = $this->isOpen($now, $this->times);

        if ($open == 0) {
            echo "Closed - Sorry, we are not making deliveries.";
        } elseif ($open <= 1800) {
            $tomorrow = strtotime('tomorrow', $now);
            if (date('N', $tomorrow) == 7) {
                $tomorrow = strtotime('next monday', $now);
            }
            $day = strtolower(date('D', $tomorrow));
            $tomorrow = date('l', $tomorrow);
            $opentime = preg_replace('/^(\d+:\d+ [AP]M).*/', '$1', $this->times[$day]);
            echo "Finishing up current orders. We re-open $tomorrow at $opentime";
        }
        else {
            echo "Open - Yes, we are making deliveries.";
        }
    }

    private function compileHours($times, $timestamp){
        $times = $times[strtolower(date('D',$timestamp))];
        if(!strpos($times, '-')) return array();
        $hours = explode(",", $times);
        $hours = array_map('explode', array_pad(array(),count($hours),'-'), $hours);
        $hours = array_map('array_map', array_pad(array(),count($hours),'strtotime'),         $hours, array_pad(array(),count($hours),array_pad(array(),2,$timestamp)));
        end($hours);
        if ($hours[key($hours)][0] > $hours[key($hours)][1]) $hours[key($hours)][1] =         strtotime('+1 day', $hours[key($hours)][1]);
        return $hours;
    }

    private function isOpen($now, $times) {
        $open = 0; // time until closing in seconds or 0 if closed
        // merge opening hours of today and the day before
        $hours = array_merge(compileHours($times,         strtotime('yesterday',$now)),compileHours($times, $now));

        foreach ($hours as $h) {
            if ($now >= $h[0] and $now < $h[1]) {
                $open = $h[1] - $now;
                return $open;
            }
        }
        return $open;
    }
}

run Class

$openClose = new open_closed_message();

run method

$openClose->message();
Sign up to request clarification or add additional context in comments.

1 Comment

This worked perfectly, thank you so much! I didn't end up using the class because I wasn't sure how to properly call the functions within it (forgive me, I'm not a guru with this stuff). Could you quickly explain how, once the class is built, I can call it to execute the same way I would a function?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.