picture of Mark Musone
One of the latest crazes on the 'net has recently been online calendars. with the MCAL library and PHP, writing calendar applications is now easy and fully functional. The MCAL library is very similar to the c-client IMAP library. It offers a common simple interface for accessing calendars that can be stored in many different formats, both local and remote formats are supported.
In this tutorial, we will use the mstore calendar driver. The mstore calendar driver uses a local file storage format. Another driver that can be used is the ICAP driver, which allows access to remote calendar stores.
One things that makes the MCAL library very different than other libraries is that it does not just handle "simple" calendaring. It is a feature rich calendaring library that handles dates from year 1 to year 9999, incorporating the Gregorian calendar and extrapolating back. This calendaring obviously contains events and many event objects. (It essentially uses icalendar objects and properties).
Some of MCAL's supported object features are:
Enough about the capabilities, lets get coding!
The first thing we'll probably want to do is pull up a users calendar and display the month view, and the event titles for any of their scheduled events:
To do this, we only need to use just a couple of mcal functions. The first is mcal_open. mcal_open takes in a calendar string, a username and a password.
In this case, we are using:
<?php mcal_open("{/mstore}","username","password"); ?>
Calendar address strings are currently of the following form:
{servername/protocol}<username>calendar
This is the contents broken down:
Most of these parts can also be left out. For example:
In our case, we are using the mstore driver, (since it's a local filesystem, no hostname is necessary)
This function will return a calendar stream upon success.
The other function we will use is:
<?php mcal_days_in_month($month,$leap_year); ?>
This simply returns the number of days in a given month, taking into account if it is a leap year or not.
To find out what day of the week the first of the month is, because we need to display the first on the correct weekday when we go to display the calendar, we use:
<?php $startday=mcal_day_of_week($year,$month,1); ?>
The next function is where the majority of the work is done:
<?php $events=mcal_list_events($stream,$year,$month,1,$year,$month,$days); ?>
This function takes in a stream, and beginning and end dates. It returns a list of event ID's for every event that is scheduled between the two dates.
Once we have this list of ID's, we need to loop through the events and find their actual dates. while we are at it, we might as well store the title of the events since we will be printing them out in the month view also:

<?php

for($x=0$x<count($events); $x++) {
    
$event=mcal_fetch_event($stream,$events[$x]);
    
$start=$event->start;
    
$date_array[$start->mday]=$date_array[$start->mday] . "<br>$event->title";
}

?>
Now that we have all the date and event information, the rest is simple. We just loop through all the dates, printing out the information we need.
Following is the complete file, index.php3:
<html><head><title>Calendar</title></head><body><center>

<?php

$montharray
=array("","January","February","March","April","May","June","July","August","September","October","November","December");

$current_date=getdate();

if(empty(
$month)) {
    
$month=$current_date["mon"];
}
if(empty(
$year)) {
    
$year=$current_date["year"];
}

$stream=mcal_open("{/mstore}","musone","hi");
$days=mcal_days_in_month($month,mcal_is_leap_year($year));
$startday=mcal_day_of_week($year,$month,1);

$events=mcal_list_events($stream,$year,$month,1,$year,$month,$days);

for(
$x=0;$x<count($events);$x++) {
    
$event=mcal_fetch_event($stream,$events[$x]);
    
$start=$event->start;
    
$date_array[$start->mday]=$date_array[$start->mday] . "<br>$event->title";
}
?>

<a href="<?php echo $PHP_SELF?>?month=<?php echo $month-1?>">&lt;</a>
<b><?php echo $montharray[$month] - $year?></b>
<a href="<?php echo $PHP_SELF?>?month=<?php echo $month+1?>">&gt;</a>
<table border=1>
<tr><th>Sun</th><th>Mon</th><th>Tue</th><th>Web</th><th>Thu</th><th>Fri</th><th>Sat</th></tr>
<?php
    
for($i=0;$i<$startday;$i++) {
        echo 
"<td></td>";
    }
    
$dayofweek=$startday;
    for(
$i=1;$i<=$days;$i++) {
        if ((
$dayofweek == 0) && ($dayofweek !=0)) {
            
printf("</tr>\n<tr>");
        }
        echo 
"<td height=100 width=100>";
        echo 
"<A href=\"addevent.php3?month=$month&year=$year&day=$i\">$i";
        echo 
"</a>";
        if (
$date_array[$i]) {
            echo 
"<A href=\"viewevent.php3?month=$month&year=$year&day=$i\">";
            echo 
"$date_array[$i]</a>";
        }
        echo 
"</td>";
        
$dayofweek++;
    }
?>
</tr></table>
</center></body></html>
Note, one thing we are doing is allowing people to add events by clicking on and day in the calendar. If there is an event scheduled, it prints out the title, and by clicking on the title, it displays all of the events information.
to display an events information, we use the same technique as the above, but just pull up the events for that one day, and print out all information.
viewevent.php3 consists of:

<?php

$stream
=mcal_open("{/mstore}","musone","hi");
$events=mcal_list_events($stream,$year,$month,$day,$year,$month,$day);

for(
$x=0$x<count($events); $x++) {
    
$event=mcal_fetch_event($stream,$events[$x]);
    
$start=$event->start;
    
$end=$event->end;
    echo 
"Event: $event->id<br>";
    echo 
"Start: ";
    echo 
"$start->year";
    echo 
"$start->month";
    echo 
"$start->mday";
    echo 
"$start->hour";
    echo 
"$start->min";
    echo 
"$start->sec <br>";

    echo 
"End:";
    echo 
"$end->year";
    echo 
"$end->month";
    echo 
"$end->mday";
    echo 
"$end->hour";
    echo 
"$end->min";
    echo 
"$end->sec <br>";

    echo 
"Title: $event->title <br>";
    echo 
"Category: $event->category <br>";
    echo 
"Description: $event->description <br>";
}
?>
<a href="index.php3?month=<?php echo $month?>&year=<?php echo $year?>">Back</a>
To add an event, it's just as simple, first we print out a form, addevent.php3:
<form action="addeventaction.php3">

<center>Adding event for <?php echo $month?>/<?php echo $day?>/<?php echo $year?></center><br>
Title:<input type="text" name="title"><br>
Category:<input type="text" name="category"><br>
Description<br>
<textarea cols=40 rows=10 name="description"></textarea><br>
<input type="hidden" name="year" value="<?php echo $year?>">
<input type="hidden" name="month" value="<?php echo $month?>">
<input type="hidden" name="day" value="<?php echo $day?>">
<input type="submit">
To do the actual adding of the event after the form is submitted, we use a couple of new functions. Every calendar stream has an internal event structure. This event structure is used for storing and retreiving events.
So we simply set the internal event structure with the proper information using the mcal_event_set functions.
Finally, we simply call mcal_store_event. This function takes the current event and adds it to the calendar store.
addeventaction.php3:

<?php

$stream
=mcal_open("{/mstore}","musone","hi");
mcal_event_set_title($stream,$title);
mcal_event_set_description($stream,$description);
mcal_event_set_category($stream,$category);
mcal_event_set_start($stream,$year,$month,$day);
mcal_store_event($stream);
Header("Location: index.php3?month=$month&year=$year");

?>
--Mark