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 it's 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;
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'll 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 it's 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...