PageRenderTime 38ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/system/libraries/Calendar.php

https://github.com/Toushi/flow
PHP | 361 lines | 180 code | 53 blank | 128 comment | 17 complexity | e6dbe4c4e87abd5eb396921c47162edf MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Calendar creation library.
  4. *
  5. * $Id: Calendar.php 3279 2008-08-06 14:41:49Z Shadowhand $
  6. *
  7. * @package Calendar
  8. * @author Kohana Team
  9. * @copyright (c) 2007-2008 Kohana Team
  10. * @license http://kohanaphp.com/license.html
  11. */
  12. class Calendar_Core extends Event_Subject {
  13. // Start the calendar on Sunday by default
  14. public static $start_monday = FALSE;
  15. // Month and year to use for calendaring
  16. protected $month;
  17. protected $year;
  18. // Week starts on Sunday
  19. protected $week_start = 0;
  20. // Observed data
  21. protected $observed_data;
  22. /**
  23. * Returns an array of the names of the days, using the current locale.
  24. *
  25. * @param boolean return short names
  26. * @return array
  27. */
  28. public static function days($short = FALSE)
  29. {
  30. // strftime day format
  31. $format = ($short == TRUE) ? '%a' : '%A';
  32. // Days of the week
  33. $days = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
  34. if (Calendar::$start_monday === TRUE)
  35. {
  36. // Push Sunday to the end of the days
  37. array_push($days, array_shift($days));
  38. }
  39. if (strpos(Kohana::config('locale.language.0'), 'en') !== 0)
  40. {
  41. // This is a bit awkward, but it works properly and is reliable
  42. foreach ($days as $i => $day)
  43. {
  44. // Convert the English names to i18n names
  45. $days[$i] = strftime($format, strtotime($day));
  46. }
  47. }
  48. elseif ($short == TRUE)
  49. {
  50. foreach ($days as $i => $day)
  51. {
  52. // Shorten the day names to 3 letters
  53. $days[$i] = substr($day, 0, 3);
  54. }
  55. }
  56. return $days;
  57. }
  58. /**
  59. * Create a new Calendar instance. A month and year can be specified.
  60. * By default, the current month and year are used.
  61. *
  62. * @param integer month number
  63. * @param integer year number
  64. * @return object
  65. */
  66. public static function factory($month = NULL, $year = NULL)
  67. {
  68. return new Calendar($month, $year);
  69. }
  70. /**
  71. * Create a new Calendar instance. A month and year can be specified.
  72. * By default, the current month and year are used.
  73. *
  74. * @param integer month number
  75. * @param integer year number
  76. * @return void
  77. */
  78. public function __construct($month = NULL, $year = NULL)
  79. {
  80. empty($month) and $month = date('n'); // Current month
  81. empty($year) and $year = date('Y'); // Current year
  82. // Set the month and year
  83. $this->month = (int) $month;
  84. $this->year = (int) $year;
  85. if (Calendar::$start_monday === TRUE)
  86. {
  87. // Week starts on Monday
  88. $this->week_start = 1;
  89. }
  90. }
  91. /**
  92. * Allows fetching the current month and year.
  93. *
  94. * @param string key to get
  95. * @return mixed
  96. */
  97. public function __get($key)
  98. {
  99. if ($key === 'month' OR $key === 'year')
  100. {
  101. return $this->$key;
  102. }
  103. }
  104. /**
  105. * Calendar_Event factory method.
  106. *
  107. * @param string unique name for the event
  108. * @return object Calendar_Event
  109. */
  110. public function event($name = NULL)
  111. {
  112. return new Calendar_Event($this);
  113. }
  114. /**
  115. * Calendar_Event factory method.
  116. *
  117. * @chainable
  118. * @param string standard event type
  119. * @return object
  120. */
  121. public function standard($name)
  122. {
  123. switch ($name)
  124. {
  125. case 'today':
  126. // Add an event for the current day
  127. $this->attach($this->event()->condition('timestamp', strtotime('today'))->add_class('today'));
  128. break;
  129. case 'prev-next':
  130. // Add an event for padding days
  131. $this->attach($this->event()->condition('current', FALSE)->add_class('prev-next'));
  132. break;
  133. case 'holidays':
  134. // Base event
  135. $event = $this->event()->condition('current', TRUE)->add_class('holiday');
  136. // Attach New Years
  137. $holiday = clone $event;
  138. $this->attach($holiday->condition('month', 1)->condition('day', 1));
  139. // Attach Valentine's Day
  140. $holiday = clone $event;
  141. $this->attach($holiday->condition('month', 2)->condition('day', 14));
  142. // Attach St. Patrick's Day
  143. $holiday = clone $event;
  144. $this->attach($holiday->condition('month', 3)->condition('day', 17));
  145. // Attach Easter
  146. $holiday = clone $event;
  147. $this->attach($holiday->condition('easter', TRUE));
  148. // Attach Memorial Day
  149. $holiday = clone $event;
  150. $this->attach($holiday->condition('month', 5)->condition('day_of_week', 1)->condition('last_occurrence', TRUE));
  151. // Attach Independance Day
  152. $holiday = clone $event;
  153. $this->attach($holiday->condition('month', 7)->condition('day', 4));
  154. // Attach Labor Day
  155. $holiday = clone $event;
  156. $this->attach($holiday->condition('month', 9)->condition('day_of_week', 1)->condition('occurrence', 1));
  157. // Attach Halloween
  158. $holiday = clone $event;
  159. $this->attach($holiday->condition('month', 10)->condition('day', 31));
  160. // Attach Thanksgiving
  161. $holiday = clone $event;
  162. $this->attach($holiday->condition('month', 11)->condition('day_of_week', 4)->condition('occurrence', 4));
  163. // Attach Christmas
  164. $holiday = clone $event;
  165. $this->attach($holiday->condition('month', 12)->condition('day', 25));
  166. break;
  167. case 'weekends':
  168. // Weekend events
  169. $this->attach($this->event()->condition('weekend', TRUE)->add_class('weekend'));
  170. break;
  171. }
  172. return $this;
  173. }
  174. /**
  175. * Returns an array for use with a view. The array contains an array for
  176. * each week. Each week contains 7 arrays, with a day number and status:
  177. * TRUE if the day is in the month, FALSE if it is padding.
  178. *
  179. * @return array
  180. */
  181. public function weeks()
  182. {
  183. // First day of the month as a timestamp
  184. $first = mktime(1, 0, 0, $this->month, 1, $this->year);
  185. // Total number of days in this month
  186. $total = (int) date('t', $first);
  187. // Last day of the month as a timestamp
  188. $last = mktime(1, 0, 0, $this->month, $total, $this->year);
  189. // Make the month and week empty arrays
  190. $month = $week = array();
  191. // Number of days added. When this reaches 7, start a new week
  192. $days = 0;
  193. $week_number = 1;
  194. if (($w = (int) date('w', $first) - $this->week_start) < 0)
  195. {
  196. $w = 6;
  197. }
  198. if ($w > 0)
  199. {
  200. // Number of days in the previous month
  201. $n = (int) date('t', mktime(1, 0, 0, $this->month - 1, 1, $this->year));
  202. // i = number of day, t = number of days to pad
  203. for ($i = $n - $w + 1, $t = $w; $t > 0; $t--, $i++)
  204. {
  205. // Notify the listeners
  206. $this->notify(array($this->month - 1, $i, $this->year, $week_number, FALSE));
  207. // Add previous month padding days
  208. $week[] = array($i, FALSE, $this->observed_data);
  209. $days++;
  210. }
  211. }
  212. // i = number of day
  213. for ($i = 1; $i <= $total; $i++)
  214. {
  215. if ($days % 7 === 0)
  216. {
  217. // Start a new week
  218. $month[] = $week;
  219. $week = array();
  220. $week_number++;
  221. }
  222. // Notify the listeners
  223. $this->notify(array($this->month, $i, $this->year, $week_number, TRUE));
  224. // Add days to this month
  225. $week[] = array($i, TRUE, $this->observed_data);
  226. $days++;
  227. }
  228. if (($w = (int) date('w', $last) - $this->week_start) < 0)
  229. {
  230. $w = 6;
  231. }
  232. if ($w >= 0)
  233. {
  234. // i = number of day, t = number of days to pad
  235. for ($i = 1, $t = 6 - $w; $t > 0; $t--, $i++)
  236. {
  237. // Notify the listeners
  238. $this->notify(array($this->month + 1, $i, $this->year, $week_number, FALSE));
  239. // Add next month padding days
  240. $week[] = array($i, FALSE, $this->observed_data);
  241. }
  242. }
  243. if ( ! empty($week))
  244. {
  245. // Append the remaining days
  246. $month[] = $week;
  247. }
  248. return $month;
  249. }
  250. /**
  251. * Adds new data from an observer. All event data contains and array of CSS
  252. * classes and an array of output messages.
  253. *
  254. * @param array observer data.
  255. * @return void
  256. */
  257. public function add_data(array $data)
  258. {
  259. // Add new classes
  260. $this->observed_data['classes'] += $data['classes'];
  261. if ( ! empty($data['output']))
  262. {
  263. // Only add output if it's not empty
  264. $this->observed_data['output'][] = $data['output'];
  265. }
  266. }
  267. /**
  268. * Resets the observed data and sends a notify to all attached events.
  269. *
  270. * @param array UNIX timestamp
  271. * @return void
  272. */
  273. public function notify($data)
  274. {
  275. // Reset observed data
  276. $this->observed_data = array
  277. (
  278. 'classes' => array(),
  279. 'output' => array(),
  280. );
  281. // Send a notify
  282. parent::notify($data);
  283. }
  284. /**
  285. * Convert the calendar to HTML using the kohana_calendar view.
  286. *
  287. * @return string
  288. */
  289. public function render()
  290. {
  291. $view = new View('kohana_calendar', array
  292. (
  293. 'month' => $this->month,
  294. 'year' => $this->year,
  295. 'weeks' => $this->weeks(),
  296. ));
  297. return $view->render();
  298. }
  299. /**
  300. * Magically convert this object to a string, the rendered calendar.
  301. *
  302. * @return string
  303. */
  304. public function __toString()
  305. {
  306. return $this->render();
  307. }
  308. } // End Calendar