Deprecated: Assigning the return value of new by reference is deprecated in /home/bluestat/public_html/source/index.php on line 477
Kalens - Blob - ViewGit - Blue Static
<?php
/*=====================================================================*\
|| ###################################################################
|| # Kalens [#]version[#]
|| # Copyright 2002-[#]year[#] Iris Studios, Inc.
|| #
|| # This program is free software; you can redistribute it and/or modify
|| # it under the terms of the GNU General Public License as published by
|| # the Free Software Foundation; version [#]gpl[#] of the License.
|| #
|| # This program is distributed in the hope that it will be useful, but
|| # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|| # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|| # more details.
|| #
|| # You should have received a copy of the GNU General Public License along
|| # with this program; if not, write to the Free Software Foundation, Inc.,
|| # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|| ###################################################################
\*=====================================================================*/

require_once('./includes/class_calendar_week.php');
require_once('./includes/functions_names.php');

/**
* Monthly Calendar Display
*
* This class is responsible for creating the actual calendar interface display.
* Parts of this class have been adapted from http://www.cascade.org.uk/software/php/calendar/Calendar.txt
*
* @author		Blue Static
* @copyright	Copyright 2002 - [#]year[#], Blue Static
* @version		$Revision$
* @package		Kalens
*
*/
class CalendarMonth
{
	/**
	* Numeric month
	* @var	integer
	*/
	private $month;

	/**
	* Year (four-year)
	* @var	integer
	*/
	private $year;

	/**
	* User-set start day of the week
	* @var	integer
	*/
	private $weekStartDay = DAY_SUNDAY;

	/**
	* Number of days in the month
	* @var	integer
	*/
	private $daysInMonth;

	/**
	* Internal date number that will be displayed *next* getNextDay()
	* @var	integer
	*/
	private $nextDay;

	/**
	* Event list; week number => day => event
	* @var	array
	*/
	private $events = array();

	// ###################################################################
	/**
	* Constructor: set the current date, if zero then use current
	*
	* @param	integer	Month to display
	* @param	integer	Year to display
	*/
	public function __construct($month, $year)
	{
		$this->month = intval(($month == 0 ? date('m') : $month));
		$this->year = intval(($year == 0 ? date('Y') : $year));
	}

	// ###################################################################
	/**
	* Gets the calendar's month
	*
	* @return	integer	Month number
	*/
	public function getMonth()
	{
		return $this->month;
	}

	// ###################################################################
	/**
	* Gets the calendar's year
	*
	* @return	integer	Year (four-digit)
	*/
	public function getYear()
	{
		return $this->year;
	}

	// ###################################################################
	/**
	* Sets the displayed start day of the week
	*
	* @param	integer	Day of the week to start on
	*/
	public function setWeekStartDay($startdow)
	{
		$this->weekStartDay = $startdow;
	}

	// ###################################################################
	/**
	* Calls a series of internal routines to generate all the calendar
	* HTML and process data.
	*/
	public function generate()
	{
		$this->_getDaysInMonth();
		$firstDay = gmdate('w', gmmktime(0, 0, 0, $this->month, 1, $this->year));
		$this->nextDay = FetchWeekDayFromBitfieldDay($this->weekStartDay) + 1 - $firstDay['wday'];
		while ($this->nextDay > 1)
		{
			$this->nextDay -= 7;
		}
		$this->_getEvents();
	}

	// ###################################################################
	/**
	* Returns a CalendarWeek with CalendarDays inside
	*
	* @return	object	A CalendarWeek
	*/
	public function getNextWeek()
	{
		if ($this->nextDay <= $this->daysInMonth)
		{
			$week = new CalendarWeek($this->nextDay, $this->month, $this->year);
			$week->setWeekStartDay($this->weekStartDay);
			$week->setEvents($this->events); // yes, we have extra events but whatever
			$week->generate();
			$this->nextDay += 7;
			return $week;
		}
	}

	// ###################################################################
	/**
	* Gets the number of days in the current month
	*/
	private function _getDaysInMonth()
	{
		$this->daysInMonth = gmdate('t', gmmktime(0, 0, 0, $this->month, 1, $this->year));
	}

	// ###################################################################
	/**
	* Gets all the events for the given time range and organizes them all
	*/
	private function _getEvents()
	{
		global $kalens;

		$this->_processRemovedEvents();

		$start = gmmktime(0, 0, 0, $this->month, 1, $this->year);
		$end = gmmktime(23, 59, 59, $this->month, $this->daysInMonth, $this->year);
		$events = $kalens->db->query("
			SELECT * FROM " . TABLE_PREFIX . "event
			WHERE
				(
					(pattern = " . PATTERN_SINGLE . " AND startstamp >= $start AND endstamp <= $end)
					OR
					(pattern = " . PATTERN_RANGED . " AND endstamp >= $start)
					OR
					(pattern & " . PATTERN_RECUR . " AND (endstamp >= $start OR endstamp = 0))
				)" . ((is_array($kalens->userinfo['calendarids']) AND sizeof($kalens->userinfo['calendarids']) > 0) ? "
			AND calendarid IN (" . implode(',', $kalens->userinfo['calendarids']) . ")" : "") . "
			ORDER BY startstamp ASC
		");
		while ($event = $kalens->db->fetch_array($events))
		{
			if ($event['pattern'] == PATTERN_SINGLE)
			{
				$date = gmdate('d', $event['startstamp']);
				$this->events[ intval($date) ]["$event[eventid]"] = $event;
			}
			else if ($event['pattern'] == PATTERN_RANGED)
			{
				$this->_processRangedEvent($event, $event['startstamp']);
			}
			else if ($event['pattern'] & PATTERN_RECUR)
			{
				$this->_processRecurringEvent($event, $event['startstamp']);
			}
		}
	}

	// ###################################################################
	/**
	* Queries the eventremoved table and loads any removed events into
	* the event array.
	*/
	private function _processRemovedEvents()
	{
		global $kalens;

		$start = gmmktime(0, 0, 0, $this->month, 1, $this->year);
		$end = gmmktime(23, 59, 59, $this->month, $this->daysInMonth, $this->year);

		$events = $kalens->db->query("
			SELECT * FROM " . TABLE_PREFIX . "eventremoved
			WHERE startstamp >= $start AND endstamp <= $end" . ((is_array($kalens->userinfo['calendarids']) AND sizeof($kalens->userinfo['calendarids']) > 0) ? "
			AND calendarid IN (" . implode(',', $kalens->userinfo['calendarids']) . ")" : "") . "
			ORDER BY startstamp ASC
		");
		while ($event = $kalens->db->fetch_array($events))
		{
			$date = gmdate('d', $event['startstamp']);
			$this->events[ intval($date) ]["$event[eventid]"] = ($event['removed'] ? true : $event);
		}
	}

	// ###################################################################
	/**
	* Recursively goes through the given event, adding events to the
	* event table.
	*
	* @param	array	Event information
	* @param	integer	Timetamp to add as an event
	*/
	private function _processRangedEvent($event, $stamp)
	{
		if ($stamp <= $event['endstamp'])
		{
			if (intval(gmdate('m', $stamp)) == $this->month AND intval(gmdate('Y', $stamp)) == $this->year)
			{
				$date = gmdate('d', $stamp);
				if (!isset($this->events[ intval($date) ]["$event[eventid]"]))
				{
					$this->events[ intval($date) ]["$event[eventid]"] = $event;
				}
			}
			$this->_processRangedEvent($event, $stamp + SECONDS_DAY);
		}
	}

	// ###################################################################
	/**
	* Recursivelly adds events to the table from a single recurring event
	* based on the repition criteria.
	*
	* @param	array	Event array
	* @param	integer	Next timestamp to add
	*/
	private function _processRecurringEvent($event, $stamp)
	{
		if ($stamp <= $event['endstamp'])
		{
			$month = intval(gmdate('m', $stamp));
			$year = intval(gmdate('Y', $stamp));
			$date = intval(gmdate('d', $stamp));

			if ($event['pattern'] & RECUR_DAY)
			{
				if ($month == $this->month AND $year == $this->year AND !isset($this->events[ intval($date) ]["$event[eventid]"]))
				{
					$this->events["$date"]["$event[eventid]"] = $event;
				}
				$this->_processRecurringEvent($event, $stamp + ($event['occurrence'] * SECONDS_DAY));
			}
			else if ($event['pattern'] & RECUR_WEEK)
			{
				$this->_processWeeklyRecurringEvent($event, $stamp);
			}
			else if ($event['pattern'] & RECUR_MONTH)
			{
				// we don't want the month or year to be greater than the month's
				if (gmmktime(0, 0, 0, $month, 1, $year) > gmmktime(0, 0, 0, $this->month, 1, $this->year))
				{
					return;
				}
				if ($month == $this->month AND $year == $this->year AND !isset($this->events[ intval($date) ]["$event[eventid]"]))
				{
					$this->events["$date"]["$event[eventid]"] = $event;
				}
				$nextMonth = $month + $event['occurrence'];
				$nextYear = gmdate('Y', $stamp);
				if ($nextMonth > 12)
				{
					$nextMonth -= 12;
					$nextYear++;
				}
				$this->_processRecurringEvent($event, gmmktime(0, 0, 0, $nextMonth, gmdate('d', $event['startstamp']), $nextYear));
			}
			else if ($event['pattern'] & RECUR_YEAR)
			{
				// not the right year and we're not getting any younger
				if (gmdate('Y', $stamp) > $this->year)
				{
					return;
				}
				if ($month == $this->month AND $year == $this->year AND !isset($this->events[ intval($date) ]["$event[eventid]"]))
				{
					$this->events["$date"]["$event[eventid]"] = $event;
				}
				$this->_processRecurringEvent($event, $stamp + ($event['occurrence'] * SECONDS_YEAR));
			}
		}
	}

	// ###################################################################
	/**
	* Function to process weekly recuring events by starting at the first
	* day of the month and working each day checking to see if the pattern
	* matches or not and adding events.
	*
	* @param	array	Event information
	* @param	integer	Timestamp to test
	*/
	private function _processWeeklyRecurringEvent($event, $stamp)
	{
		if ($stamp <= $event['endstamp'])
		{
			$dayOfWeek = gmdate('w', $stamp);
			while ($dayOfWeek != 0)
			{
				$stamp -= SECONDS_DAY;
				$dayOfWeek = gmdate('w', $stamp);
			}

			$workStamp = $stamp;

			for ($i = 1; $i <= 7; $i++)
			{
				$workStamp += SECONDS_DAY;
				$month = intval(gmdate('m', $workStamp));
				$year = intval(gmdate('Y', $workStamp));
				$date = intval(gmdate('d', $workStamp));

				$dayBit = FetchBitfieldDayFromWeekDay($i);
				$timeTest = gmmktime(gmdate('H', $event['startstamp']), gmdate('i', $event['startstamp']), gmdate('s', $event['startstamp']), $month, $date, $year);
				if ($event['pattern'] & $dayBit AND $timeTest >= gmmktime(0, 0, 0, $this->month, 1, $this->year) AND $timeTest <= gmmktime(23, 59, 59, $this->month, $this->daysInMonth, $this->year) AND $timeTest >= $event['startstamp'] AND $timeTest <= $event['endstamp'])
				{
					if (!isset($this->events[ intval($date) ]["$event[eventid]"]))
					{
						$this->events["$date"]["$event[eventid]"] = $event;
					}
				}
			}

			$this->_processWeeklyRecurringEvent($event, $stamp + ($event['occurrence'] * 7 * SECONDS_DAY));
		}
	}
}

/*=====================================================================*\
|| ###################################################################
|| # $HeadURL$
|| # $Id$
|| ###################################################################
\*=====================================================================*/
?>