ajax availability calendar help

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

Look in classes/class_calendar.php

Code: Select all

public $day_closed					= array("Saturday", "Sunday"); 	// If you don't want any 'closed' days, remove the day so it becomes: = array();
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

You would probably want to convert $booking_start_time and $booking_end_time to arrays of values, either one entry per day, or one entry per exception day plus one default. You would then also need to change where the arrays are referenced to reflect your new array structure.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

I would leave most of the functionality as is. booking_start_time and booking_end_time are fine. You could add an exceptions array, indexed by day, with start and end times for those specific days. When you're building the booking form, check if the current day is specified in the exceptions and override booking_start_time and booking_end_time with those values. Otherwise, do nothing.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

Yes, absolutely.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

Without even worrying about writing new code yet, look through the class you're modifying to see the flow and think about what steps you'd want to take to allow for these exceptions. You've got them defined, how do you use them? Where?
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

make_calendar takes a booking date as a parameter and chains all the class methods together. Once we know what day we're booking for, we can check if that's in the exception array. Does that help?
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

Here are the modifications I've made. Can you see what I'm doing and how it works?

Code: Select all

<?php


class booking_diary {


    // Mysqli connection
    function __construct($link) {
        $this->link = $link;    
    }

    // Settings you can change:


    // Time Related Variables
    public $booking_start_time          = "09:00";          // The time of the first slot in 24 hour H:M format  
    public $booking_end_time            = "19:00";          // The time of the last slot in 24 hour H:M format  
    public $booking_frequency           = 30;               // The slot frequency per hour, expressed in minutes.   

    // Allowing for days to have different business hours. Indexed by day name
    // to match conventions set forth by $day_closed
    protected $booking_exceptions = [
        'Saturday' => [
            'start_time' => "09:00",
            'end_time' => "12:00",
        ],
    ];

    // Day Related Variables

    public $day_format                  = 1;                // Day format of the table header.  Possible values (1, 2, 3)   
    // 1 = Show First digit, eg: "M"
    // 2 = Show First 3 letters, eg: "Mon"
    // 3 = Full Day, eg: "Monday"

    public $day_closed                  = array("Sunday");  // If you don't want any 'closed' days, remove the day so it becomes: = array();
    public $day_closed_text             = "CLOSED";         // If you don't want any any 'closed' remove the text so it becomes: = "";

    // Cost Related Variables
    public $cost_per_slot               = 20.00;            // The cost per slot
    public $cost_currency_tag           = "$";      // The currency tag in HTML such as &euro; &pound; &yen;


    //  DO NOT EDIT BELOW THIS LINE

    public $day_order                   = array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday");
    public $day, $month, $year, $selected_date, $back, $back_month, $back_year, $forward, $forward_month, $forward_year, $bookings, $count, $days, $is_slot_booked_today;


    /*========================================================================================================================================================*/


    function make_calendar($selected_date, $back, $forward, $day, $month, $year) {

        // $day, $month and $year are the $_GET variables in the URL
        $this->day = $day;    
        $this->month = $month;
        $this->year = $year;

        // $back and $forward are Unix Timestamps of the previous / next month, used to give the back arrow the correct month and year 
        $this->selected_date = $selected_date;       
        $this->back = $back;
        $this->back_month = date("m", $back);
        $this->back_year = date("Y", $back); // Minus one month back arrow

        $this->forward = $forward;
        $this->forward_month = date("m", $forward);
        $this->forward_year = date("Y", $forward); // Add one month forward arrow    

        // Now that we know the day we're booking for, check its hours
        $this->getBusinessHours();
        // Make the booking array
        $this->make_booking_array($year, $month);

    }

    // Overwrite start/end properties if today has special hours
    protected function getBusinessHours() {
        $date = new \DateTime("{$this->year}-{$this->month}-{$this->day}");
        $day = $date->format('l');

        if (array_key_exists($day, $this->booking_exceptions)) {
            $this->booking_start_time = $this->booking_exceptions[$day]['start_time'];
            $this->booking_end_time = $this->booking_exceptions[$day]['end_time'];
        }
    }
    //...
    // Everything else is the same
} // Close Class

?>
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

ianhaney wrote:I don't get what this part is doing

Code: Select all

// Now that we know the day we're booking for, check its hours
        $this->getBusinessHours();
It's calling the function getBusinessHours.
ianhaney wrote:I don't get what this part is doing

Code: Select all

// Overwrite start/end properties if today has special hours
    protected function getBusinessHours() {
        $date = new \DateTime("{$this->year}-{$this->month}-{$this->day}");
        $day = $date->format('l');

        if (array_key_exists($day, $this->booking_exceptions)) {
            $this->booking_start_time = $this->booking_exceptions[$day]['start_time'];
            $this->booking_end_time = $this->booking_exceptions[$day]['end_time'];
        }
    }
Is that calling the function to get it displayed in the calendar?
The booking_start_time and booking_end_time properties are hardcoded and are being used to generate the available bookings. The above method creates a DateTime object based on the date passed to make_calendar (which stores it as instance properties). We use that object to get the name of the day (Monday, Tuesday, etc). This isn't necessarily the best approach, but it is consistent with other configuration settings in the class. Finally, it checks if that day name exists as a key in the booking_exceptions array and, if it does, sets the start and end times to those specified in the exceptions array.
ianhaney wrote:Also what is the difference between public and protected?
Public properties and methods can be accessed from anywhere. Protected properties and methods can be accessed from within the class or its children. Private properties and methods can only be accessed from within the class.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

Are you using an old version of PHP? Or does Dreamweaver think you are? Short array syntax was introduced in 5.4, way back in March, 2012.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

Old version of Dreamweaver, perhaps? Alternately, check if PHP version can be specified in the settings.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

I wouldn't worry too much about it. The editor's wrong, the code is fine, and that's simple enough to confirm.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

I would actually consider taking a different approach to it. You're not overriding the standard business hours per se, you're adding a set of specific dates to the closed array. It currently expects days of the week, though, and you want specific dates, so you may want to add a separate property to handle those. Also, we're not concerned about modifying the booking form here; we want the day to be marked as closed and the booking form to be entirely unavailable.

I have made some changes below. // ... indicates parts of the class I have trimmed for brevity; they are still very much required for things to run. Gives this a look and see if you understand how it works and why. We can discuss further once you've gone over it.

Code: Select all

<?php

class booking_diary {

    // Mysqli connection
    function __construct($link) {
        $this->link = $link;    
    }

    // Settings you can change:


    // Time Related Variables
    public $booking_start_time          = "09:00";          // The time of the first slot in 24 hour H:M format  
    public $booking_end_time            = "19:00";          // The time of the last slot in 24 hour H:M format  
    public $booking_frequency           = 30;               // The slot frequency per hour, expressed in minutes.   

    // Allowing for days to have different business hours. Indexed by day name
    // to match conventions set forth by $day_closed
    protected $booking_exceptions = [
        'Saturday' => [
            'start_time' => "09:00",
            'end_time' => "12:00",
        ],
    ];

    // Holidays are another exception; business is closed but on a specific date
    // rather than on a day of the week
    protected $holidays = [
        '01-01',
        '24-12',
        '25-12',
        '31-12',
    ];

    // Day Related Variables

    public $day_format                  = 1;                // Day format of the table header.  Possible values (1, 2, 3)   
    // 1 = Show First digit, eg: "M"
    // 2 = Show First 3 letters, eg: "Mon"
    // 3 = Full Day, eg: "Monday"

    public $day_closed                  = array("Sunday");  // If you don't want any 'closed' days, remove the day so it becomes: = array();
    public $day_closed_text             = "CLOSED";         // If you don't want any any 'closed' remove the text so it becomes: = "";

    // ...

    function make_calendar($selected_date, $back, $forward, $day, $month, $year) {

        // $day, $month and $year are the $_GET variables in the URL
        $this->day = $day;    
        $this->month = $month;
        $this->year = $year;

        // $back and $forward are Unix Timestamps of the previous / next month, used to give the back arrow the correct month and year 
        $this->selected_date = $selected_date;       
        $this->back = $back;
        $this->back_month = date("m", $back);
        $this->back_year = date("Y", $back); // Minus one month back arrow

        $this->forward = $forward;
        $this->forward_month = date("m", $forward);
        $this->forward_year = date("Y", $forward); // Add one month forward arrow    

        $this->getBusinessHours();
        // Make the booking array
        $this->make_booking_array($year, $month);

    }

    // Overwrite start/end properties if today has special hours
    protected function getBusinessHours() {
        $date = new \DateTime("{$this->year}-{$this->month}-{$this->day}");
        $day = $date->format('l');

        if (array_key_exists($day, $this->booking_exceptions)) {
            $this->booking_start_time = $this->booking_exceptions[$day]['start_time'];
            $this->booking_end_time = $this->booking_exceptions[$day]['end_time'];
        }
    }

    // ...

    function make_cells($table = '') {

        echo "<tr>";

        foreach($this->days as $i => $r) { // Loop through the date array

            $j = $i + 1; $tag = 0;

            $dm = null;
            if ($r['dayname'] !== 'blank') {
                $day = str_pad($r['daynumber'], 2, '0', STR_PAD_LEFT);
                $dm = "{$day}-{$this->month}";
            }

            // If the the current day is found in the day_closed array, bookings are not allowed on this day  
            // OR if the current date is in the holidays array
            if (in_array($r['dayname'], $this->day_closed) || ($dm && in_array($dm, $this->holidays))) {            
                echo "\r\n<td width='21' valign='top' class='closed'>" . $this->day_closed_text . "</td>";      
                $tag = 1;
            }


            // Past days are greyed out
            if (mktime(0, 0, 0, $this->month, sprintf("%02s", $r['daynumber']) + 1, $this->year) < strtotime("now") && $tag != 1) {     

                echo "\r\n<td width='21' valign='top' class='past'>";           
                // Output day number 
                if($r['daynumber'] != 'blank') echo $r['daynumber']; 

                echo "</td>";       
                $tag = 1;
            }


            // If the element is set as 'blank', insert blank day
            if($r['dayname'] == 'blank' && $tag != 1) {     
                echo "\r\n<td width='21' valign='top' class='unavailable'></td>";   
                $tag = 1;
            }


            // Now check the booking array $this->booking to see whether we have a booking on this day              
            $current_day = $this->year . '-' . $this->month . '-' . sprintf("%02s", $r['daynumber']);

            if(isset($this->bookings_per_day[$current_day]) && $tag == 0) {

                $current_day_slots_booked = count($this->bookings_per_day[$current_day]);

                if($current_day_slots_booked < $this->slots_per_day) {

                    echo "\r\n<td width='21' valign='top'>
                        <a href='calendar.php?month=" .  $this->month . "&year=" .  $this->year . "&day=" . sprintf("%02s", $r['daynumber']) . "' class='part_booked' title='This day is part booked'>" . 
                        $r['daynumber'] . "</a></td>"; 
                    $tag = 1;

                } else {

                    echo "\r\n<td width='21' valign='top'>
                        <a href='calendar.php?month=" .  $this->month . "&year=" .  $this->year . "&day=" . sprintf("%02s", $r['daynumber']) . "' class='fully_booked' title='This day is fully booked'>" . 
                        $r['daynumber'] . "</a></td>"; 
                    $tag = 1;           

                } // Close else 

            } // Close if


            if($tag == 0) {

                echo "\r\n<td width='21' valign='top'>
                    <a href='calendar.php?month=" .  $this->month . "&year=" .  $this->year . "&day=" . sprintf("%02s", $r['daynumber']) . "' class='green' title='Please click to view bookings'>" . 
                    $r['daynumber'] . "</a></td>";          

            }

            // The modulus function below ($j % 7 == 0) adds a <tr> tag to every seventh cell + 1;
            if($j % 7 == 0 && $i >1) {
                echo "\r\n</tr>\r\n<tr>"; // Use modulus to give us a <tr> after every seven <td> cells
            }       

        }       

        echo "</tr></table></div><!-- Close outer_calendar DIV -->";

        if(isset($_GET['year']))
            $this->basket();

        echo "</div><!-- Close LHS DIV -->";

        // Check booked slots for selected date and only show the booking form if there are available slots 
        $current_day = $this->year . '-' . $this->month . '-' . $this->day; 
        $slots_selected_day = 0;

        if(isset($this->bookings_per_day[$current_day]))
            $slots_selected_day = count($this->bookings_per_day[$current_day]);

        if($this->day != 0 && $slots_selected_day < $this->slots_per_day) { 
            $this->booking_form();
        }


    } // Close function

    // ...

} // Close Class
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

It needs to be day-month, or you need to change the holidays array to be month-day. There's a mismatch.

Code: Select all

$dm = null;
if ($r['dayname'] !== 'blank') {
    $day = str_pad($r['daynumber'], 2, '0', STR_PAD_LEFT);
    $dm = "{$this->month}-{$day}";
} 
$r is an array containing the day name and the date (day number). I am prepending a 0 to the days so you'll get 01-01 rather than 1-01
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

Code: Select all

$dm = "{$this->day}-{$month}";
Should be

Code: Select all

$dm = "{$day}-{$this->month}";
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: ajax availability calendar help

Post by Celauran »

You're also missing the check for if $dm is in the holidays array.

Code: Select all

            if(in_array($r['dayname'], $this->day_closed)) {
needs to be

Code: Select all

            if(in_array($r['dayname'], $this->day_closed) || ($dm && in_array($dm, $this->holidays))) {
Do you see why? Do you see what the above is doing?
Post Reply