Initial Kohana install
[speedfreak] / Server / system / libraries / Calendar.php
diff --git a/Server/system/libraries/Calendar.php b/Server/system/libraries/Calendar.php
new file mode 100644 (file)
index 0000000..193a6fb
--- /dev/null
@@ -0,0 +1,362 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Calendar creation library.
+ *
+ * $Id: Calendar.php 3769 2008-12-15 00:48:56Z zombor $
+ *
+ * @package    Calendar
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Calendar_Core extends Event_Subject {
+
+       // Start the calendar on Sunday by default
+       public static $start_monday = FALSE;
+
+       // Month and year to use for calendaring
+       protected $month;
+       protected $year;
+
+       // Week starts on Sunday
+       protected $week_start = 0;
+
+       // Observed data
+       protected $observed_data;
+
+       /**
+        * Returns an array of the names of the days, using the current locale.
+        *
+        * @param   integer  left of day names
+        * @return  array
+        */
+       public static function days($length = TRUE)
+       {
+               // strftime day format
+               $format = ($length > 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
\ No newline at end of file