The Calendar_Decorator is provided to allow you to attach functionality to existing Calendar objects without needing to subclass them. This helps in a number of situations, such as allowing results from, say, a database query to be rendered in the calendar or to modify the values returned from Calendar methods (perhaps converting a numeric month into its textual name).
Some concrete decorators are provided with PEAR::Calendar, to address what may be common problems you encounter in using the library. These are not designed to suit everyone but instead focus on solving a more narrow problem domain. They will only be parsed by the PHP engine should you explicitly include them in your code. An example of why decorators can be useful:
<?php
require_once 'Calendar/Day.php';
require_once 'Calendar/Decorator.php';
class WorkingDay extends Calendar_Decorator {
function WorkingDay(& $Calendar) {
parent::Calendar_Decorator($Calendar);
}
// Overides the default fetch method of the calendar object
function fetch() {
if ($Hour = parent::fetch()) {
// Recursive fetch, return only hours between 8am and 6pm
if ($Hour->thisHour() < 8 || $Hour->thisHour() > 18) {
return $this->fetch();
} else {
return $Hour;
}
} else {
// Make sure to return FALSE when the real fetch returned nothing
// or you will get an infinite loop
return FALSE;
}
}
}
// Create a normal day and build the hours
$Day = new Calendar_Day(date('Y'), date('n'), date('d'));
$Day->build();
// Create the decorator, passing it the normal day
$WorkingDay = new WorkingDay($Day);
// Only hours in a working day are displayed...
while ($Hour = $WorkingDay->fetch()) {
echo $Hour->thisHour().'<br />';
}
?>
The base class Calendar_Decorator "mirrors" the combined API of all the subclasses of Calendar. It accepts a Calendar object to its constructor then "takes over" the API allowing you to make calls through it rather than directly to the original calendar object. The Calendar_Decorator simply routes calls through to the calendar object it is decorating and returns values where appropriate.
One important use of decorators is to help "inject" data into the loop which renders the calendar. This helps with fetching data from some sort of "event" table in a database. When passing a selection array to any build() method, the selected date objects will replace the default built objects, allowing you to get them back as inside the fetch() loop, using the isSelected() method. You'll find an example of this in the PEAR::Calendar download. It should always be possible to fetch the event data you need with a single database query...
PEAR::Calendar already provides a few decorators:
Calendar_Decorator_Textual
Decorator to help with fetching textual representations of months and days of the week. It has
Calendar_Decorator_Uri
Decorator to help with building HTML links for navigating the calendar.
Calendar_Decorator_Weekday
Decorator for fetching the day of the week.
Calendar_Decorator_Wrapper
Decorator to help with wrapping built children in another decorator.
This decorator defines a few methods that can be useful to handle month and day names:
monthNames($format
='long')
Returns an array with month names; the format of returned months
depends on the format
parameter
(one, two, short or long)
weekdayNames($format
='long')
Returns an array with day names; the format of returned days
depends on the format
parameter
(one, two, short or long)
prevMonthName($format
='long')
Returns textual representation of the previous month of the decorated calendar object
thisMonthName($format
='long')
Returns textual representation of the month of the decorated calendar object
nextMonthName($format
='long')
Returns textual representation of the next month of the decorated calendar object
prevDayName($format
='long')
Returns textual representation of the previous day of the decorated calendar object
thisDayName($format
='long')
Returns textual representation of the day of the decorated calendar object
nextDayName($format
='long')
Returns textual representation of the next day of the decorated calendar object
orderedWeekdays($format
='long')
Returns the days of the week using the order defined in the decorated calendar object. Only useful for Calendar_Month_Weekdays, Calendar_Month_Weeks and Calendar_Week. Otherwise the returned array will begin on Sunday.
Methods defined by this decorator:
setFragments($y, $m=null, $d=null, $h=null, $i=null, $s=null)
Set the names of the URI vars for each date element
setSeparator($separator
)
Set the fragments separator, for instance '/' (default: &).
setScalar(boolean $state
=TRUE)
Puts Uri decorator into "scalar mode" - URI variable names are not returned
prev($method
)
Gets the URI string for the previous calendar unit (year, month, week or day etc)
this($method
)
Gets the URI string for the current calendar unit (year, month, week or day etc)
next($method
)
Gets the URI string for the next calendar unit (year, month, week or day etc)
A simple usage example:
<?php
$Day = new Calendar_Day(2003, 10, 23);
$Uri = & new Calendar_Decorator_Uri($Day);
$Uri->setFragments('year', 'month', 'day');
echo $Uri->prev('day');
// Displays year=2003&month=10&day=22
?>
Methods defined by this decorator:
setFirstDay($firstDay)
Sets the first day of the week (0 = Sunday, 1 = Monday [default] etc)
prevWeekDay($format='int')
Returns the previous weekday, formatted according the $format
parameter (int, array, object, timestamp)
thisWeekDay($format='int')
Returns the current weekday, formatted according the $format
parameter (int, array, object, timestamp)
nextWeekDay($format='int')
Returns the next weekday, formatted according the $format
parameter (int, array, object, timestamp)
Example:
<?php
$Day = new Calendar_Day(2003, 10, 23);
$Weekday = & new Calendar_Decorator_Weekday($Day);
$Weekday->setFirstDay(0); // Set first day of week to Sunday (default Mon)
echo $Weekday->thisWeekDay(); // Displays 5 - fifth day of week relative to Sun
?>
<?php
require_once 'Calendar/Month.php';
require_once 'Calendar/Decorator.php'; // Not really needed but added to help this make sense
require_once 'Calendar/Decorator/Wrapper.php';
class MyBoldDecorator extends Calendar_Decorator
{
function MyBoldDecorator(&$Calendar)
{
parent::Calendar_Decorator($Calendar);
}
function thisDay()
{
return '<b>'.parent::thisDay().'</b>';
}
}
$Month = new Calendar_Month(date('Y'), date('n'));
$Wrapper = & new Calendar_Decorator_Wrapper($Month);
$Wrapper->build();
echo '<h2>The Wrapper decorator</h2>';
echo '<i>Day numbers are rendered in bold</i><br /> <br />';
while ($DecoratedDay = $Wrapper->fetch('MyBoldDecorator')) {
echo $DecoratedDay->thisDay().'<br />';
}
?>