<?php

/**
 * PDO CalDAV backend
 *
 * This backend is used to store calendar-data in a PDO database, such as 
 * sqlite or MySQL
 * 
 * @package Atmail
 * @subpackage CalDAV
 * @copyright Copyright (C) 2011 Atmail All rights reserved.
 * @author Atmail
 * @license see atmail license
 */
class Atmail_CalDav_Backend_PDO extends Sabre_CalDAV_Backend_PDO {
	function deleteCalendar($calendarId)
	{
		parent::deleteCalendar($calendarId);
		
		$stmt = $this->pdo->prepare('DELETE FROM `calendarDelegates` WHERE calendarid = ?');
        $stmt->execute(array($calendarId));
	}
	private function findTimeRange($filters)
	{
		foreach($filters as $filterkey => $filter)
		{
			if(!is_array($filter)) continue;

			if(array_key_exists('time-range', $filter) && count($filter['time-range']) && strpos(strtoupper($filterkey), 'VEVENT') !== false)
			{
				// found a time range!
				return $filter['time-range'];
			}
			if(array_key_exists('comp-filters', $filter) && count($filter['comp-filters']))
			{
				// filter(s) found
				foreach($filter['comp-filters'] as $compfilter)
				{
					$result = $this->findTimeRange($compfilter);
					if($result === false) return $result;
				}
			}
		}

		return false;
	}

	public function getCalendarObjects($calendarId, $filters = array()) {

		$result = array();
		if(count($filters) && ($range = $this->findTimeRange($filters)) !== false)
		{
			// some filters that we might be able to apply to the sql selection to reduce resource usage
			// for very large datasets
			$startStamp = array_key_exists('start', $range) && is_object($range['start']) ? $range['start']->getTimestamp() : 0;
			$endStamp = array_key_exists('end', $range) && is_object($range['end']) ? $range['end']->getTimestamp() : 4294967295;
			// as the start and end stamps ignore rrules, we must unfortunately select those too
			$stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE (calendarid = ? and start >= ? and end <= ?) or (calendarid = ? and rrule = 1)');
			$stmt->execute(array($calendarId, $startStamp, $endStamp, $calendarId));
			$result = $stmt->fetchAll();
		}
		else
		{
			$stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?');
			$stmt->execute(array($calendarId));
			$result = $stmt->fetchAll();
		}
		return $result;

	}

	public function createCalendarObject($calendarId,$objectUri,$calendarData)
	{
		if (mb_strlen ( $calendarData , 'latin1' ) > $this->calendarObjectSizeLimit)
		{
			throw new Sabre_DAV_Exception('The xml data provided is too large');
		}

		$vObject = Sabre_VObject_Reader::read($calendarData);
		list($start, $end, $recurrence) = Atmail_Dav_Optimizer::optimizeDates($vObject);

		$stmt = $this->pdo->prepare('INSERT INTO `'.$this->calendarObjectTableName.'` (calendarid, uri, calendardata, lastmodified, start, end, rrule) VALUES (?,?,?,?,?,?,?)');
		$stmt->execute(array($calendarId,$objectUri,$calendarData, time(), $start, $end, $recurrence));
		$stmt = $this->pdo->prepare('UPDATE `'.$this->calendarTableName.'` SET ctag = ctag + 1 WHERE id = ?');
		$stmt->execute(array($calendarId));
	}


	public function updateCalendarObject($calendarId,$objectUri,$calendarData) {
		if (mb_strlen ( $calendarData , 'latin1' ) > $this->calendarObjectSizeLimit)
		{
			throw new Sabre_DAV_Exception('The xml data provided is too large');
		}

		$vObject = Sabre_VObject_Reader::read($calendarData);
		list($start, $end, $rrule) = Atmail_Dav_Optimizer::optimizeDates($vObject);

		$stmt = $this->pdo->prepare('UPDATE `'.$this->calendarObjectTableName.'` SET calendardata = ?, lastmodified = ?, start = ?, end = ?, rrule = ? WHERE calendarid = ? AND uri = ?');
		$stmt->execute(array($calendarData,time(),$start, $end, $rrule, $calendarId,$objectUri));
		$stmt = $this->pdo->prepare('UPDATE `'.$this->calendarTableName.'` SET ctag = ctag + 1 WHERE id = ?');
		$stmt->execute(array($calendarId));
	}
}
