display(); * function daily($year, $month, $day) { * print "Hello, $year-$month-$day!"; * } */ class Calendar { public $month; public $year; public $limit; public $link_template = "?year=%YEAR%&month=%MONTH%"; /// The template that will be used to create the link to each month page public $date_field; public $query; public $items; //Cache for all the items private $_callback; /// The callback function that the user have to provide - this will be called for every day - from within the day's cell private $_callback_cell_class_provider; private $_month_days; /** * Constructor * Argument: $callback(function) - The user specified callback function that will be called for each day * $year - [OPTIONAL] The year that is to be shown - defaults to current year. * $month - [OPTIONAL] The month that is to be shown - defaults to current month. */ function __construct($callback = '', $year=0, $month=0) { if($callback) $this->setDailyFunction($callback); $this->month= (!empty($_REQUEST['month']))? intval($_REQUEST['month']): $month; //Shows the calendar for this month $this->year = (!empty($_REQUEST['year'])) ? intval($_REQUEST['year']) : $year; // of this year. if(!$this->year) $this->year = date('Y'); //This could be 0 if it the default argument the function - make it current year if(!$this->month) $this->month = date('n'); // Set the limit to which the calendar can go. $this->limit = array( //'from' => array('year'=>2000, 'month'=>1), 'to' => array('year'=>date('Y'), 'month'=>date('n')) //This makes sure that future dates are not shown. ); //Validations if($this->month > 12) $this->month=12; elseif($this->month < 1) $this->month=1; $this->_month_days = array(31,28,31,30,31,30,31,31,30,31,30,31); if($this->year%4 == 0) $this->_month_days[1] = 29; } /** * The function to set the user-specified callback function. * Argument: $callback(function) - The user specified callback function that will be called for each day */ function setDailyFunction($func) { $this->_callback = $func; } /** * The user can use this function to set the class name of any valid date's cell(the td tag of that day). * The string returned by the user function will be added to the class of the cell. */ function setCellClassProvider($func) { $this->_callback_cell_class_provider = $func; } ///////////////////////////////// Controller Helper functions //////////////////////// /** * This field will be treated as the date field in the table. * Argument: $field - the name of the field. * Example: $calendar->setDateField("Duration.from_time"); */ function setDateField($field) { $this->date_field = $field; } /** * This sets the query that will be used for this calendar. * Arguments: $query_main - The first part of the query - the select, From, inner join etc. * $query_where - The condition part of the query. * $query_end - The final part of the query - Order By, Group by, limit etc. * Example: $calendar->setDateField("Duration.from_time"); * $calendar->setQuery("SELECT Task.id,Task.name,Duration.from_time,Duration.to_time " * . " FROM Task INNER JOIN Duration ON Duration.task_id=Task.id ", "Task.status='1'", * " ORDER BY Duration.from_time") */ function setQuery($query_main, $query_where, $query_end) { $this->query = $query_main; if(!trim($query_where)) $query_where = " WHERE "; else { $query_where .= " AND "; if(!preg_match('/^\s*WHERE/i', $query_where)) $query_where = " WHERE " . $query_where; //Prepend the where keyword if its not there. } $filled_month = (($this->month < 10) ? '0' : '') . $this->month; $query_where .= " DATE_FORMAT({$this->date_field}, '%Y-%m')='{$this->year}-$filled_month' "; $this->query = $query_main . $query_where . $query_end; //Now that we have the query, execute it and cache the results... $this->execQuery(); } /** * This function will execute the 'Calender::query' SQL query and cache the results that will be used later. */ function execQuery() { global $sql; $all_items = $sql->getAll($this->query); $date_field = $this->date_field; if(strpos($date_field, '.') !== false) { //There is a . in the field name - so its Table.field - we need just the field name $parts = explode('.', $date_field); $date_field = $parts[1]; } foreach($all_items as $item) { $date_index = date('d', strtotime($item[$date_field])); //The day is the index (its 0 filled) $this->items[$date_index][] = $item; } } function getData($day) { if(isset($this->items[$day])) return $this->items[$day]; else return array(); } //////////////////////////////////////// Private Functions /////////////////////////// /** * This function renders the stuff inside each day's cell. It also calls the user-specified callback function. */ private function _each_day() { static $flag = 0; static $column = 1; static $d = 1; $start_day = date('w',mktime(0,0,0,$this->month,1,$this->year)) + 1;//Get the first day of this month - 0 (for Sunday) through 6 (for Saturday) $curmonth = ($this->month>9) ? $this->month : '0'.$this->month; if($d > $this->_month_days[$this->month-1]) $flag=0;//If the days has overshot the number of days in this month, stop writing else if($column>=$start_day and !$flag) $flag=1;//If the first day of this month has come, start the date writing $class=''; if($d == date('j') and $this->month == date('n') and $this->year == date('Y') and $flag) $class='today'; if(!$flag) $class .= ' overflow-days'; $weekdays = array('saturday', 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday'); $class .= " weekday-" . $weekdays[($column%7)]; //See if the user wants to tag any date with a class - if(is_callable($this->_callback_cell_class_provider) and $flag) { $da = ($d<10) ? "0".$d : $d ; $func = $this->_callback_cell_class_provider; $class .= $func($this->year, $curmonth, $da); } print "