3) ? '%A' : '%a'; // Days of the week $days = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); if (Calendar::$start_monday === TRUE) { // Push Sunday to the end of the days array_push($days, array_shift($days)); } if (strpos(Kohana::config('locale.language.0'), 'en') !== 0) { // This is a bit awkward, but it works properly and is reliable foreach ($days as $i => $day) { // Convert the English names to i18n names $days[$i] = strftime($format, strtotime($day)); } } if (is_int($length) OR ctype_digit($length)) { foreach ($days as $i => $day) { // Shorten the days to the expected length $days[$i] = utf8::substr($day, 0, $length); } } return $days; } /** * Create a new Calendar instance. A month and year can be specified. * By default, the current month and year are used. * * @param integer month number * @param integer year number * @return object */ public static function factory($month = NULL, $year = NULL) { return new Calendar($month, $year); } /** * Create a new Calendar instance. A month and year can be specified. * By default, the current month and year are used. * * @param integer month number * @param integer year number * @return void */ public function __construct($month = NULL, $year = NULL) { empty($month) and $month = date('n'); // Current month empty($year) and $year = date('Y'); // Current year // Set the month and year $this->month = (int) $month; $this->year = (int) $year; if (Calendar::$start_monday === TRUE) { // Week starts on Monday $this->week_start = 1; } } /** * Allows fetching the current month and year. * * @param string key to get * @return mixed */ public function __get($key) { if ($key === 'month' OR $key === 'year') { return $this->$key; } } /** * Calendar_Event factory method. * * @param string unique name for the event * @return object Calendar_Event */ public function event($name = NULL) { return new Calendar_Event($this); } /** * Calendar_Event factory method. * * @chainable * @param string standard event type * @return object */ public function standard($name) { switch ($name) { case 'today': // Add an event for the current day $this->attach($this->event()->condition('timestamp', strtotime('today'))->add_class('today')); break; case 'prev-next': // Add an event for padding days $this->attach($this->event()->condition('current', FALSE)->add_class('prev-next')); break; case 'holidays': // Base event $event = $this->event()->condition('current', TRUE)->add_class('holiday'); // Attach New Years $holiday = clone $event; $this->attach($holiday->condition('month', 1)->condition('day', 1)); // Attach Valentine's Day $holiday = clone $event; $this->attach($holiday->condition('month', 2)->condition('day', 14)); // Attach St. Patrick's Day $holiday = clone $event; $this->attach($holiday->condition('month', 3)->condition('day', 17)); // Attach Easter $holiday = clone $event; $this->attach($holiday->condition('easter', TRUE)); // Attach Memorial Day $holiday = clone $event; $this->attach($holiday->condition('month', 5)->condition('day_of_week', 1)->condition('last_occurrence', TRUE)); // Attach Independance Day $holiday = clone $event; $this->attach($holiday->condition('month', 7)->condition('day', 4)); // Attach Labor Day $holiday = clone $event; $this->attach($holiday->condition('month', 9)->condition('day_of_week', 1)->condition('occurrence', 1)); // Attach Halloween $holiday = clone $event; $this->attach($holiday->condition('month', 10)->condition('day', 31)); // Attach Thanksgiving $holiday = clone $event; $this->attach($holiday->condition('month', 11)->condition('day_of_week', 4)->condition('occurrence', 4)); // Attach Christmas $holiday = clone $event; $this->attach($holiday->condition('month', 12)->condition('day', 25)); break; case 'weekends': // Weekend events $this->attach($this->event()->condition('weekend', TRUE)->add_class('weekend')); break; } return $this; } /** * Returns an array for use with a view. The array contains an array for * each week. Each week contains 7 arrays, with a day number and status: * TRUE if the day is in the month, FALSE if it is padding. * * @return array */ public function weeks() { // First day of the month as a timestamp $first = mktime(1, 0, 0, $this->month, 1, $this->year); // Total number of days in this month $total = (int) date('t', $first); // Last day of the month as a timestamp $last = mktime(1, 0, 0, $this->month, $total, $this->year); // Make the month and week empty arrays $month = $week = array(); // Number of days added. When this reaches 7, start a new week $days = 0; $week_number = 1; if (($w = (int) date('w', $first) - $this->week_start) < 0) { $w = 6; } if ($w > 0) { // Number of days in the previous month $n = (int) date('t', mktime(1, 0, 0, $this->month - 1, 1, $this->year)); // i = number of day, t = number of days to pad for ($i = $n - $w + 1, $t = $w; $t > 0; $t--, $i++) { // Notify the listeners $this->notify(array($this->month - 1, $i, $this->year, $week_number, FALSE)); // Add previous month padding days $week[] = array($i, FALSE, $this->observed_data); $days++; } } // i = number of day for ($i = 1; $i <= $total; $i++) { if ($days % 7 === 0) { // Start a new week $month[] = $week; $week = array(); $week_number++; } // Notify the listeners $this->notify(array($this->month, $i, $this->year, $week_number, TRUE)); // Add days to this month $week[] = array($i, TRUE, $this->observed_data); $days++; } if (($w = (int) date('w', $last) - $this->week_start) < 0) { $w = 6; } if ($w >= 0) { // i = number of day, t = number of days to pad for ($i = 1, $t = 6 - $w; $t > 0; $t--, $i++) { // Notify the listeners $this->notify(array($this->month + 1, $i, $this->year, $week_number, FALSE)); // Add next month padding days $week[] = array($i, FALSE, $this->observed_data); } } if ( ! empty($week)) { // Append the remaining days $month[] = $week; } return $month; } /** * Adds new data from an observer. All event data contains and array of CSS * classes and an array of output messages. * * @param array observer data. * @return void */ public function add_data(array $data) { // Add new classes $this->observed_data['classes'] += $data['classes']; if ( ! empty($data['output'])) { // Only add output if it's not empty $this->observed_data['output'][] = $data['output']; } } /** * Resets the observed data and sends a notify to all attached events. * * @param array UNIX timestamp * @return void */ public function notify($data) { // Reset observed data $this->observed_data = array ( 'classes' => array(), 'output' => array(), ); // Send a notify parent::notify($data); } /** * Convert the calendar to HTML using the kohana_calendar view. * * @return string */ public function render() { $view = new View('kohana_calendar', array ( 'month' => $this->month, 'year' => $this->year, 'weeks' => $this->weeks(), )); return $view->render(); } /** * Magically convert this object to a string, the rendered calendar. * * @return string */ public function __toString() { return $this->render(); } } // End Calendar