Example #1
0
 /**
  * Returns true or false depending on if the event falls in the specified
  * time-range. This is used for filtering purposes.
  *
  * The rules used to determine if an event falls within the specified
  * time-range is based on the CalDAV specification.
  *
  * @param DateTime $start
  * @param DateTime $end
  * @return bool
  */
 public function isInTimeRange(DateTime $start, DateTime $end)
 {
     if ($this->RRULE) {
         $it = new Sabre_VObject_RecurrenceIterator($this);
         $it->fastForward($start);
         // We fast-forwarded to a spot where the end-time of the
         // recurrence instance exceeded the start of the requested
         // time-range.
         //
         // If the starttime of the recurrence did not exceed the
         // end of the time range as well, we have a match.
         return $it->getDTStart() < $end && $it->getDTEnd() > $start;
     }
     $effectiveStart = $this->DTSTART->getDateTime();
     if (isset($this->DTEND)) {
         // The DTEND property is considered non inclusive. So for a 3 day
         // event in july, dtstart and dtend would have to be July 1st and
         // July 4th respectively.
         //
         // See:
         // http://tools.ietf.org/html/rfc5545#page-54
         $effectiveEnd = $this->DTEND->getDateTime();
     } elseif (isset($this->DURATION)) {
         $effectiveEnd = clone $effectiveStart;
         $effectiveEnd->add(Sabre_VObject_DateTimeParser::parseDuration($this->DURATION));
     } elseif ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) {
         $effectiveEnd = clone $effectiveStart;
         $effectiveEnd->modify('+1 day');
     } else {
         $effectiveEnd = clone $effectiveStart;
     }
     return $start <= $effectiveEnd && $end > $effectiveStart;
 }
Example #2
0
 /**
  * Returns true or false depending on if the event falls in the specified
  * time-range. This is used for filtering purposes.
  *
  * The rules used to determine if an event falls within the specified
  * time-range is based on the CalDAV specification.
  *
  * @param DateTime $start
  * @param DateTime $end
  * @return bool
  */
 public function isInTimeRange(DateTime $start, DateTime $end)
 {
     if ($this->RRULE) {
         $it = new Sabre_VObject_RecurrenceIterator($this);
         $it->fastForward($start);
         // We fast-forwarded to a spot where the end-time of the
         // recurrence instance exceeded the start of the requested
         // time-range.
         //
         // If the starttime of the recurrence did not exceed the
         // end of the time range as well, we have a match.
         return $it->getDTStart() < $end && $it->getDTEnd() > $start;
     }
     $effectiveStart = $this->DTSTART->getDateTime();
     if (isset($this->DTEND)) {
         $effectiveEnd = $this->DTEND->getDateTime();
         // If this was an all-day event, we should just increase the
         // end-date by 1. Otherwise the event will last until the second
         // the date changed, by increasing this by 1 day the event lasts
         // all of the last day as well.
         if ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) {
             $effectiveEnd->modify('+1 day');
         }
     } elseif (isset($this->DURATION)) {
         $effectiveEnd = clone $effectiveStart;
         $effectiveEnd->add(Sabre_VObject_DateTimeParser::parseDuration($this->DURATION));
     } elseif ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) {
         $effectiveEnd = clone $effectiveStart;
         $effectiveEnd->modify('+1 day');
     } else {
         $effectiveEnd = clone $effectiveStart;
     }
     return $start <= $effectiveEnd && $end > $effectiveStart;
 }
Example #3
0
 /**
  * Returns true or false depending on if the event falls in the specified 
  * time-range. This is used for filtering purposes. 
  *
  * The rules used to determine if an event falls within the specified 
  * time-range is based on the CalDAV specification.
  *
  * @param DateTime $start
  * @param DateTime $end 
  * @return bool 
  */
 public function isInTimeRange(DateTime $start, DateTime $end)
 {
     $dtstart = isset($this->DTSTART) ? $this->DTSTART->getDateTime() : null;
     $duration = isset($this->DURATION) ? Sabre_VObject_DateTimeParser::parseDuration($this->DURATION) : null;
     $due = isset($this->DUE) ? $this->DUE->getDateTime() : null;
     $completed = isset($this->COMPLETED) ? $this->COMPLETED->getDateTime() : null;
     $created = isset($this->CREATED) ? $this->CREATED->getDateTime() : null;
     if ($dtstart) {
         if ($duration) {
             $effectiveEnd = clone $dtstart;
             $effectiveEnd->add($duration);
             return $start <= $effectiveEnd && $end > $dtstart;
         } elseif ($due) {
             return ($start < $due || $start <= $dtstart) && ($end > $dtstart || $end >= $due);
         } else {
             return $start <= $dtstart && $end > $dtstart;
         }
     }
     if ($due) {
         return $start < $due && $end >= $due;
     }
     if ($completed && $created) {
         return ($start <= $created || $start <= $completed) && ($end >= $created || $end >= $completed);
     }
     if ($completed) {
         return $start <= $completed && $end >= $completed;
     }
     if ($created) {
         return $end > $created;
     }
     return true;
 }
Example #4
0
 /**
  * Returns true or false depending on if the event falls in the specified
  * time-range. This is used for filtering purposes.
  *
  * The rules used to determine if an event falls within the specified
  * time-range is based on the CalDAV specification.
  *
  * @param DateTime $start
  * @param DateTime $end
  * @return bool
  */
 public function isInTimeRange(DateTime $start, DateTime $end)
 {
     $effectiveTrigger = $this->getEffectiveTriggerTime();
     if (isset($this->DURATION)) {
         $duration = Sabre_VObject_DateTimeParser::parseDuration($this->DURATION);
         $repeat = (string) $this->repeat;
         if (!$repeat) {
             $repeat = 1;
         }
         $period = new DatePeriod($effectiveTrigger, $duration, (int) $repeat);
         foreach ($period as $occurrence) {
             if ($start <= $occurrence && $end > $occurrence) {
                 return true;
             }
         }
         return false;
     } else {
         return $start <= $effectiveTrigger && $end > $effectiveTrigger;
     }
 }
Example #5
0
 /**
  * This method is responsible for parsing the request and generating the
  * response for the CALDAV:free-busy-query REPORT.
  *
  * @param DOMNode $dom
  * @return void
  */
 protected function freeBusyQueryReport(DOMNode $dom)
 {
     $start = null;
     $end = null;
     foreach ($dom->firstChild->childNodes as $childNode) {
         $clark = Sabre_DAV_XMLUtil::toClarkNotation($childNode);
         if ($clark == '{' . self::NS_CALDAV . '}time-range') {
             $start = $childNode->getAttribute('start');
             $end = $childNode->getAttribute('end');
             break;
         }
     }
     if ($start) {
         $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
     }
     if ($end) {
         $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
     }
     if (!$start && !$end) {
         throw new Sabre_DAV_Exception_BadRequest('The freebusy report must have a time-range filter');
     }
     $acl = $this->server->getPlugin('acl');
     if (!$acl) {
         throw new Sabre_DAV_Exception('The ACL plugin must be loaded for free-busy queries to work');
     }
     $uri = $this->server->getRequestUri();
     $acl->checkPrivileges($uri, '{' . self::NS_CALDAV . '}read-free-busy');
     $calendar = $this->server->tree->getNodeForPath($uri);
     if (!$calendar instanceof Sabre_CalDAV_ICalendar) {
         throw new Sabre_DAV_Exception_NotImplemented('The free-busy-query REPORT is only implemented on calendars');
     }
     $objects = array_map(function ($child) {
         $obj = $child->get();
         if (is_resource($obj)) {
             $obj = stream_get_contents($obj);
         }
         return $obj;
     }, $calendar->getChildren());
     $generator = new Sabre_VObject_FreeBusyGenerator();
     $generator->setObjects($objects);
     $generator->setTimeRange($start, $end);
     $result = $generator->getResult();
     $result = $result->serialize();
     $this->server->httpResponse->sendStatus(200);
     $this->server->httpResponse->setHeader('Content-Type', 'text/calendar');
     $this->server->httpResponse->setHeader('Content-Length', strlen($result));
     $this->server->httpResponse->sendBody($result);
 }
/**
 * @param wdcal_local $localization
 * @param string $baseurl
 * @param int $calendar_id
 * @param int $uri
 * @return string
 */
function wdcal_getEditPage_str(&$localization, $baseurl, $calendar_id, $uri)
{
    $server = dav_create_server(true, true, false);
    if ($uri > 0) {
        $calendar = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_WRITE);
        if (!$calendar) {
            $calendar = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_READ);
            $calendars = array();
        } else {
            $calendars = dav_get_current_user_calendars($server, DAV_ACL_WRITE);
        }
        if ($calendar == null) {
            return "Calendar not found";
        }
        $obj_uri = Sabre_CalDAV_Backend_Common::loadCalendarobjectById($uri);
        $vObject = dav_get_current_user_calendarobject($server, $calendar, $obj_uri["uri"], DAV_ACL_WRITE);
        $component = dav_get_eventComponent($vObject);
        if ($component == null) {
            return t('Could not open component for editing');
        }
        /** @var Sabre\VObject\Property\DateTime $dtstart  */
        $dtstart = $component->__get("DTSTART");
        $event = array("id" => IntVal($uri), "Summary" => $component->__get("SUMMARY") ? $component->__get("SUMMARY")->value : null, "StartTime" => $dtstart->getDateTime()->getTimeStamp(), "EndTime" => Sabre_CalDAV_Backend_Common::getDtEndTimeStamp($component), "IsAllDayEvent" => strlen($dtstart->value) == 8, "Description" => $component->__get("DESCRIPTION") ? $component->__get("DESCRIPTION")->value : null, "Location" => $component->__get("LOCATION") ? $component->__get("LOCATION")->value : null, "Color" => $component->__get("X-ANIMEXX-COLOR") ? $component->__get("X-ANIMEXX-COLOR")->value : null);
        $exdates = $component->select("EXDATE");
        $recurrentce_exdates = array();
        /** @var Sabre\VObject\Property\MultiDateTime $x */
        foreach ($exdates as $x) {
            /** @var DateTime $y */
            $z = $x->getDateTimes();
            foreach ($z as $y) {
                $recurrentce_exdates[] = $y->getTimeStamp();
            }
        }
        $notifications = array();
        $alarms = $component->select("VALARM");
        foreach ($alarms as $alarm) {
            /** @var Sabre_VObject_Component_VAlarm $alarm */
            $action = $alarm->__get("ACTION")->value;
            $trigger = $alarm->__get("TRIGGER");
            if (isset($trigger['VALUE']) && strtoupper($trigger['VALUE']) !== 'DURATION') {
                notice("The notification of this event cannot be parsed");
                continue;
            }
            /** @var DateInterval $triggerDuration  */
            $triggerDuration = Sabre_VObject_DateTimeParser::parseDuration($trigger);
            $unit = "hour";
            $value = 1;
            if ($triggerDuration->s > 0) {
                $unit = "second";
                $value = $triggerDuration->s + $triggerDuration->i * 60 + $triggerDuration->h * 3600 + $triggerDuration->d * 3600 * 24;
                // @TODO support more than days?
            } elseif ($triggerDuration->i) {
                $unit = "minute";
                $value = $triggerDuration->i + $triggerDuration->h * 60 + $triggerDuration->d * 60 * 24;
            } elseif ($triggerDuration->h) {
                $unit = "hour";
                $value = $triggerDuration->h + $triggerDuration->d * 24;
            } elseif ($triggerDuration->d > 0) {
                $unit = "day";
                $value = $triggerDuration->d;
            }
            $rel = isset($trigger['RELATED']) && strtoupper($trigger['RELATED']) == 'END' ? 'end' : 'start';
            $notifications[] = array("action" => strtolower($action), "rel" => $rel, "trigger_unit" => $unit, "trigger_value" => $value);
        }
        if ($component->select("RRULE")) {
            $recurrence = new Sabre_VObject_RecurrenceIterator($vObject, (string) $component->__get("UID"));
        } else {
            $recurrence = null;
        }
    } elseif (isset($_REQUEST["start"]) && $_REQUEST["start"] > 0) {
        $calendars = dav_get_current_user_calendars($server, DAV_ACL_WRITE);
        //$calendar  = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_WRITE);
        $event = array("id" => 0, "Summary" => $_REQUEST["title"], "StartTime" => InTVal($_REQUEST["start"]), "EndTime" => IntVal($_REQUEST["end"]), "IsAllDayEvent" => $_REQUEST["isallday"], "Description" => "", "Location" => "", "Color" => null);
        if ($_REQUEST["isallday"]) {
            $notifications = array();
        } else {
            $notifications = array(array("action" => "email", "rel" => "start", "trigger_unit" => "hour", "trigger_value" => 1));
        }
        $recurrence = null;
        $recurrentce_exdates = array();
    } else {
        $calendars = dav_get_current_user_calendars($server, DAV_ACL_WRITE);
        //$calendar  = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_WRITE);
        $event = array("id" => 0, "Summary" => "", "StartTime" => time(), "EndTime" => time() + 3600, "IsAllDayEvent" => "0", "Description" => "", "Location" => "", "Color" => null);
        $notifications = array(array("action" => "email", "rel" => "start", "trigger_unit" => "hour", "trigger_value" => 1));
        $recurrence = null;
        $recurrentce_exdates = array();
    }
    $postto = $baseurl . "/dav/wdcal/" . ($uri == 0 ? "new/" : $calendar_id . "/" . $uri . "/edit/");
    $out = "<a href='" . $baseurl . "/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
    $out .= "<form method='POST' action='{$postto}'>\n\t\t<input type='hidden' name='form_security_token' value='" . get_form_security_token('caledit') . "'>\n";
    $out .= "<h2>" . t("Event data") . "</h2>";
    $out .= "<label for='calendar' class='block'>" . t("Calendar") . ":</label><select id='calendar' name='calendar' size='1'>";
    $found = false;
    $cal_col = "aaaaaa";
    foreach ($calendars as $cal) {
        $prop = $cal->getProperties(array("id", DAV_DISPLAYNAME, DAV_CALENDARCOLOR));
        $out .= "<option value='" . $prop["id"] . "' ";
        if ($prop["id"] == $calendar_id) {
            $out .= "selected";
            $cal_col = $prop[DAV_CALENDARCOLOR];
            $found = true;
        } elseif (!$found) {
            $cal_col = $prop[DAV_CALENDARCOLOR];
        }
        $out .= ">" . escape_tags($prop[DAV_DISPLAYNAME]) . "</option>\n";
    }
    $out .= "</select>";
    $out .= "&nbsp; &nbsp; <label class='plain'><input type='checkbox' name='color_override' id='color_override' ";
    if (!is_null($event["Color"])) {
        $out .= "checked";
    }
    $out .= "> " . t("Special color") . ":</label>";
    $out .= "<span id='cal_color_holder' ";
    if (is_null($event["Color"])) {
        $out .= "style='display: none;'";
    }
    $out .= "><input name='color' id='cal_color' value='" . (is_null($event["Color"]) ? "#" . $cal_col : escape_tags($event["Color"])) . "'></span>";
    $out .= "<br>\n";
    $out .= "<label class='block' for='cal_summary'>" . t("Subject") . ":</label>\n\t\t<input name='summary' id='cal_summary' value=\"" . escape_tags($event["Summary"]) . "\"><br>\n";
    $out .= "<label class='block' for='cal_allday'>Is All-Day event:</label><input type='checkbox' name='allday' id='cal_allday' " . ($event["IsAllDayEvent"] ? "checked" : "") . "><br>\n";
    $out .= "<label class='block' for='cal_start_date'>" . t("Starts") . ":</label>";
    $out .= "<input name='start_date' value='" . $localization->dateformat_datepicker_php($event["StartTime"]) . "' id='cal_start_date'>";
    $out .= "<input name='start_time' value='" . date("H:i", $event["StartTime"]) . "' id='cal_start_time'>";
    $out .= "<br>\n";
    $out .= "<label class='block' for='cal_end_date'>" . t("Ends") . ":</label>";
    $out .= "<input name='end_date' value='" . $localization->dateformat_datepicker_php($event["EndTime"]) . "' id='cal_end_date'>";
    $out .= "<input name='end_time' value='" . date("H:i", $event["EndTime"]) . "' id='cal_end_time'>";
    $out .= "<br>\n";
    $out .= "<label class='block' for='cal_location'>" . t("Location") . ":</label><input name='location' id='cal_location' value=\"" . escape_tags($event["Location"]) . "\"><br>\n";
    $out .= "<label class='block' for='event-desc-textarea'>" . t("Description") . ":</label> <textarea id='event-desc-textarea' name='wdcal_desc' style='vertical-align: top; width: 400px; height: 100px;'>" . escape_tags($event["Description"]) . "</textarea>";
    $out .= "<br style='clear: both;'>";
    $out .= "<h2>" . t("Recurrence") . "</h2>";
    $out .= "<label class='block' for='rec_frequency'>" . t("Frequency") . ":</label> <select id='rec_frequency' name='rec_frequency' size='1'>";
    $out .= "<option value=''>" . t("None") . "</option>\n";
    $out .= "<option value='daily' ";
    if ($recurrence && $recurrence->frequency == "daily") {
        $out .= "selected";
    }
    $out .= ">" . t("Daily") . "</option>\n";
    $out .= "<option value='weekly' ";
    if ($recurrence && $recurrence->frequency == "weekly") {
        $out .= "selected";
    }
    $out .= ">" . t("Weekly") . "</option>\n";
    $out .= "<option value='monthly' ";
    if ($recurrence && $recurrence->frequency == "monthly") {
        $out .= "selected";
    }
    $out .= ">" . t("Monthly") . "</option>\n";
    $out .= "<option value='yearly' ";
    if ($recurrence && $recurrence->frequency == "yearly") {
        $out .= "selected";
    }
    $out .= ">" . t("Yearly") . "</option>\n";
    $out .= "</select><br>\n";
    $out .= "<div id='rec_details'>";
    $select = "<select id='rec_interval' name='rec_interval' size='1'>";
    for ($i = 1; $i < 50; $i++) {
        $select .= "<option value='{$i}' ";
        if ($recurrence && $i == $recurrence->interval) {
            $select .= "selected";
        }
        $select .= ">{$i}</option>\n";
    }
    $select .= "</select>";
    $time = "<span class='rec_daily'>" . t("days") . "</span>";
    $time .= "<span class='rec_weekly'>" . t("weeks") . "</span>";
    $time .= "<span class='rec_monthly'>" . t("months") . "</span>";
    $time .= "<span class='rec_yearly'>" . t("years") . "</span>";
    $out .= "<label class='block'>" . t("Interval") . ":</label> " . str_replace(array("%select%", "%time%"), array($select, $time), t("All %select% %time%")) . "<br>";
    $out .= "<div class='rec_daily'>";
    $out .= "<label class='block'>" . t("Days") . ":</label>";
    if ($recurrence && $recurrence->byDay) {
        $byday = $recurrence->byDay;
    } else {
        $byday = array("MO", "TU", "WE", "TH", "FR", "SA", "SU");
    }
    if ($localization->getFirstDayOfWeek() == 0) {
        $out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='SU' ";
        if (in_array("SU", $byday)) {
            $out .= "checked";
        }
        $out .= ">" . t("Sunday") . "</label> &nbsp; ";
    }
    $out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='MO' ";
    if (in_array("MO", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Monday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='TU' ";
    if (in_array("TU", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Tuesday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='WE' ";
    if (in_array("WE", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Wednesday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='TH' ";
    if (in_array("TH", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Thursday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='FR' ";
    if (in_array("FR", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Friday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='SA' ";
    if (in_array("SA", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Saturday") . "</label> &nbsp; ";
    if ($localization->getFirstDayOfWeek() != 0) {
        $out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='SU' ";
        if (in_array("SU", $byday)) {
            $out .= "checked";
        }
        $out .= ">" . t("Sunday") . "</label> &nbsp; ";
    }
    $out .= "</div>";
    $out .= "<div class='rec_weekly'>";
    $out .= "<label class='block'>" . t("Days") . ":</label>";
    if ($recurrence && $recurrence->byDay) {
        $byday = $recurrence->byDay;
    } else {
        $days = array("MO", "TU", "WE", "TH", "FR", "SA", "SU");
        $byday = array($days[date("N", $event["StartTime"]) - 1]);
    }
    if ($localization->getFirstDayOfWeek() == 0) {
        $out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='SU' ";
        if (in_array("SU", $byday)) {
            $out .= "checked";
        }
        $out .= ">" . t("Sunday") . "</label> &nbsp; ";
    }
    $out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='MO' ";
    if (in_array("MO", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Monday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='TU' ";
    if (in_array("TU", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Tuesday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='WE' ";
    if (in_array("WE", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Wednesday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='TH' ";
    if (in_array("TH", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Thursday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='FR' ";
    if (in_array("FR", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Friday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='SA' ";
    if (in_array("SA", $byday)) {
        $out .= "checked";
    }
    $out .= ">" . t("Saturday") . "</label> &nbsp; ";
    if ($localization->getFirstDayOfWeek() != 0) {
        $out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='SU' ";
        if (in_array("SU", $byday)) {
            $out .= "checked";
        }
        $out .= ">" . t("Sunday") . "</label> &nbsp; ";
    }
    $out .= "<br>";
    $out .= "<label class='block'>" . t("First day of week:") . "</label>";
    if ($recurrence && $recurrence->weekStart != "") {
        $wkst = $recurrence->weekStart;
    } else {
        if ($localization->getFirstDayOfWeek() == 0) {
            $wkst = "SU";
        } else {
            $wkst = "MO";
        }
    }
    $out .= "<label class='plain'><input type='radio' name='rec_weekly_wkst' value='SU' ";
    if ($wkst == "SU") {
        $out .= "checked";
    }
    $out .= ">" . t("Sunday") . "</label> &nbsp; ";
    $out .= "<label class='plain'><input type='radio' name='rec_weekly_wkst' value='MO' ";
    if ($wkst == "MO") {
        $out .= "checked";
    }
    $out .= ">" . t("Monday") . "</label><br>\n";
    $out .= "</div>";
    $monthly_rule = "";
    if ($recurrence && ($recurrence->frequency == "monthly" || $recurrence->frequency == "yearly")) {
        if (is_null($recurrence->byDay) && !is_null($recurrence->byMonthDay) && count($recurrence->byMonthDay) == 1) {
            $day = date("j", $event["StartTime"]);
            if ($recurrence->byMonthDay[0] == $day) {
                $monthly_rule = "bymonthday";
            } else {
                $lastday = date("t", $event["StartTime"]);
                if ($recurrence->byMonthDay[0] == -1 * ($lastday - $day + 1)) {
                    $monthly_rule = "bymonthday_neg";
                }
            }
        }
        if (is_null($recurrence->byMonthDay) && !is_null($recurrence->byDay) && count($recurrence->byDay) == 1) {
            $num = IntVal($recurrence->byDay[0]);
            /*
            $dayMap = array(
            	'SU' => 0,
            	'MO' => 1,
            	'TU' => 2,
            	'WE' => 3,
            	'TH' => 4,
            	'FR' => 5,
            	'SA' => 6,
            );
            if ($num == 0) {
            	$num = 1;
            	$weekday = $dayMap[$recurrence->byDay[0]];
            } else {
            	$weekday = $dayMap[substr($recurrence->byDay[0], strlen($num))];
            }
            
            echo $num . " - " . $weekday;
            */
            if ($num > 0) {
                $monthly_rule = "byday";
            }
            if ($num < 0) {
                $monthly_rule = "byday_neg";
            }
        }
        if ($monthly_rule == "") {
            notice("The recurrence of this event cannot be parsed");
        }
    }
    $out .= "<div class='rec_monthly'>";
    $out .= "<label class='block' for='rec_monthly_day'>" . t("Day of month") . ":</label>";
    $out .= "<select id='rec_monthly_day' name='rec_monthly_day' size='1'>";
    $out .= "<option value='bymonthday' ";
    if ($monthly_rule == "bymonthday") {
        $out .= "selected";
    }
    $out .= ">" . t("#num#th of each month") . "</option>\n";
    $out .= "<option value='bymonthday_neg' ";
    if ($monthly_rule == "bymonthday_neg") {
        $out .= "selected";
    }
    $out .= ">" . t("#num#th-last of each month") . "</option>\n";
    $out .= "<option value='byday' ";
    if ($monthly_rule == "byday") {
        $out .= "selected";
    }
    $out .= ">" . t("#num#th #wkday# of each month") . "</option>\n";
    $out .= "<option value='byday_neg' ";
    if ($monthly_rule == "byday_neg") {
        $out .= "selected";
    }
    $out .= ">" . t("#num#th-last #wkday# of each month") . "</option>\n";
    $out .= "</select>";
    $out .= "</div>\n";
    if ($recurrence && $recurrence->frequency == "yearly") {
        if (count($recurrence->byMonth) != 1 || $recurrence->byMonth[0] != date("n", $event["StartTime"])) {
            notice("The recurrence of this event cannot be parsed!");
        }
    }
    $out .= "<div class='rec_yearly'>";
    $out .= "<label class='block'>" . t("Month") . ":</label> <span class='rec_month_name'>#month#</span><br>\n";
    $out .= "<label class='block' for='rec_yearly_day'>" . t("Day of month") . ":</label>";
    $out .= "<select id='rec_yearly_day' name='rec_yearly_day' size='1'>";
    $out .= "<option value='bymonthday' ";
    if ($monthly_rule == "bymonthday") {
        $out .= "selected";
    }
    $out .= ">" . t("#num#th of the given month") . "</option>\n";
    $out .= "<option value='bymonthday_neg' ";
    if ($monthly_rule == "bymonthday_neg") {
        $out .= "selected";
    }
    $out .= ">" . t("#num#th-last of the given month") . "</option>\n";
    $out .= "<option value='byday' ";
    if ($monthly_rule == "byday") {
        $out .= "selected";
    }
    $out .= ">" . t("#num#th #wkday# of the given month") . "</option>\n";
    $out .= "<option value='byday_neg' ";
    if ($monthly_rule == "byday_neg") {
        $out .= "selected";
    }
    $out .= ">" . t("#num#th-last #wkday# of the given month") . "</option>\n";
    $out .= "</select>";
    $out .= "</div>\n";
    if ($recurrence) {
        $until = $recurrence->until;
        $count = $recurrence->count;
        if (is_a($until, "DateTime")) {
            /** @var DateTime $until */
            $rule_type = "date";
            $rule_until_date = $until->getTimestamp();
            $rule_until_count = 1;
        } elseif ($count > 0) {
            $rule_type = "count";
            $rule_until_date = time();
            $rule_until_count = $count;
        } else {
            $rule_type = "infinite";
            $rule_until_date = time();
            $rule_until_count = 1;
        }
    } else {
        $rule_type = "infinite";
        $rule_until_date = time();
        $rule_until_count = 1;
    }
    $out .= "<label class='block' for='rec_until_type'>" . t("Repeat until") . ":</label> ";
    $out .= "<select name='rec_until_type' id='rec_until_type' size='1'>";
    $out .= "<option value='infinite' ";
    if ($rule_type == "infinite") {
        $out .= "selected";
    }
    $out .= ">" . t("Infinite") . "</option>\n";
    $out .= "<option value='date' ";
    if ($rule_type == "date") {
        $out .= "selected";
    }
    $out .= ">" . t("Until the following date") . ":</option>\n";
    $out .= "<option value='count' ";
    if ($rule_type == "count") {
        $out .= "selected";
    }
    $out .= ">" . t("Number of times") . ":</option>\n";
    $out .= "</select>";
    $out .= "<input name='rec_until_date' value='" . $localization->dateformat_datepicker_php($rule_until_date) . "' id='rec_until_date'>";
    $out .= "<input name='rec_until_count' value='{$rule_until_count}' id='rec_until_count'><br>";
    $out .= "<label class='block'>" . t("Exceptions") . ":</label><div class='rec_exceptions'>";
    $out .= "<div class='rec_exceptions_none' ";
    if (count($recurrentce_exdates) > 0) {
        $out .= "style='display: none;'";
    }
    $out .= ">" . t("none") . "</div>";
    $out .= "<div class='rec_exceptions_holder' ";
    if (count($recurrentce_exdates) == 0) {
        $out .= "style='display: none;'";
    }
    $out .= ">";
    foreach ($recurrentce_exdates as $exdate) {
        $out .= "<div data-timestamp='{$exdate}' class='except'><input type='hidden' class='rec_exception' name='rec_exceptions[]' value='{$exdate}'>";
        $out .= "<a href='#' class='exception_remover'>[remove]</a> ";
        $out .= $localization->date_timestamp2localDate($exdate);
        $out .= "</div>\n";
    }
    $out .= "</div><div><a href='#' class='exception_adder'>[add]</a></div>";
    $out .= "</div>\n";
    $out .= "<br>\n";
    $out .= "</div><br>";
    $out .= "<h2>" . t("Notification") . "</h2>";
    if (!$notifications) {
        $notifications = array();
    }
    $notifications["new"] = array("action" => "email", "trigger_value" => 60, "trigger_unit" => "minute", "rel" => "start");
    foreach ($notifications as $index => $noti) {
        $unparsable = false;
        if (!in_array($noti["action"], array("email", "display"))) {
            $unparsable = true;
        }
        $out .= "<div class='noti_holder' ";
        if (!is_numeric($index) && $index == "new") {
            $out .= "style='display: none;' id='noti_new_row'";
        }
        $out .= "><label class='block' for='noti_type_" . $index . "'>" . t("Notify by") . ":</label>";
        $out .= "<select name='noti_type[{$index}]' size='1' id='noti_type_" . $index . "'>";
        $out .= "<option value=''>- " . t("Remove") . " -</option>\n";
        $out .= "<option value='email' ";
        if (!$unparsable && $noti["action"] == "email") {
            $out .= "selected";
        }
        $out .= ">" . t("E-Mail") . "</option>\n";
        $out .= "<option value='display' ";
        if (!$unparsable && $noti["action"] == "display") {
            $out .= "selected";
        }
        $out .= ">" . t("On Friendica / Display") . "</option>\n";
        //$out .= "<option value='other' "; if ($unparsable) $out .= "selected"; $out .= ">- " . t("other (leave it untouched)") . " -</option>\n"; // @TODO
        $out .= "</select><br>";
        $out .= "<label class='block'>" . t("Time") . ":</label>";
        $out .= "<input name='noti_value[{$index}]' size='5' style='width: 5em;' value='" . $noti["trigger_value"] . "'>";
        $out .= "<select name='noti_unit[{$index}]' size='1'>";
        $out .= "<option value='H' ";
        if ($noti["trigger_unit"] == "hour") {
            $out .= "selected";
        }
        $out .= ">" . t("Hours") . "</option>\n";
        $out .= "<option value='M' ";
        if ($noti["trigger_unit"] == "minute") {
            $out .= "selected";
        }
        $out .= ">" . t("Minutes") . "</option>\n";
        $out .= "<option value='S' ";
        if ($noti["trigger_unit"] == "second") {
            $out .= "selected";
        }
        $out .= ">" . t("Seconds") . "</option>\n";
        $out .= "<option value='D' ";
        if ($noti["trigger_unit"] == "day") {
            $out .= "selected";
        }
        $out .= ">" . t("Days") . "</option>\n";
        $out .= "<option value='W' ";
        if ($noti["trigger_unit"] == "week") {
            $out .= "selected";
        }
        $out .= ">" . t("Weeks") . "</option>\n";
        $out .= "</select>";
        $out .= " <label class='plain'>" . t("before the") . " <select name='noti_ref[{$index}]' size='1'>";
        $out .= "<option value='start' ";
        if ($noti["rel"] == "start") {
            $out .= "selected";
        }
        $out .= ">" . t("start of the event") . "</option>\n";
        $out .= "<option value='end' ";
        if ($noti["rel"] == "end") {
            $out .= "selected";
        }
        $out .= ">" . t("end of the event") . "</option>\n";
        $out .= "</select></label>\n";
        $out .= "</div>";
    }
    $out .= "<input type='hidden' name='new_alarm' id='new_alarm' value='0'><div id='new_alarm_adder'><a href='#'>" . t("Add a notification") . "</a></div>";
    $out .= "<script>\$(function() {\n\t\twdcal_edit_init('" . $localization->dateformat_datepicker_js() . "', '{$baseurl}/dav/');\n\t});</script>";
    $out .= "<br><input type='submit' name='save' value='Save'></form>";
    return $out;
}
Example #7
0
/**
 * Parses some information from calendar objects, used for optimized
 * calendar-queries.
 *
 * Blantently copied from Sabre_CalDAV_Backend_PDO
 *
 * Returns an array with the following keys:
 *   * etag
 *   * size
 *   * componentType
 *   * firstOccurence
 *   * lastOccurence
 *
 * @param string $calendarData
 * @return array
 */
function getDenormalizedData($calendarData)
{
    $vObject = Sabre_VObject_Reader::read($calendarData);
    $componentType = null;
    $component = null;
    $firstOccurence = null;
    $lastOccurence = null;
    foreach ($vObject->getComponents() as $component) {
        if ($component->name !== 'VTIMEZONE') {
            $componentType = $component->name;
            break;
        }
    }
    if (!$componentType) {
        throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
    }
    if ($componentType === 'VEVENT') {
        $firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp();
        // Finding the last occurence is a bit harder
        if (!isset($component->RRULE)) {
            if (isset($component->DTEND)) {
                $lastOccurence = $component->DTEND->getDateTime()->getTimeStamp();
            } elseif (isset($component->DURATION)) {
                $endDate = clone $component->DTSTART->getDateTime();
                $endDate->add(Sabre_VObject_DateTimeParser::parse($component->DURATION->value));
                $lastOccurence = $endDate->getTimeStamp();
            } elseif ($component->DTSTART->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
                $endDate = clone $component->DTSTART->getDateTime();
                $endDate->modify('+1 day');
                $lastOccurence = $endDate->getTimeStamp();
            } else {
                $lastOccurence = $firstOccurence;
            }
        } else {
            $it = new Sabre_VObject_RecurrenceIterator($vObject, (string) $component->UID);
            $maxDate = new DateTime(self::MAX_DATE);
            if ($it->isInfinite()) {
                $lastOccurence = $maxDate->getTimeStamp();
            } else {
                $end = $it->getDtEnd();
                while ($it->valid() && $end < $maxDate) {
                    $end = $it->getDtEnd();
                    $it->next();
                }
                $lastOccurence = $end->getTimeStamp();
            }
        }
    }
    return array('etag' => md5($calendarData), 'size' => strlen($calendarData), 'componentType' => $componentType, 'firstOccurence' => $firstOccurence, 'lastOccurence' => $lastOccurence);
}
 /**
  * Parses the CALDAV:expand element
  * 
  * @param DOMElement $parentNode 
  * @return void
  */
 protected function parseExpand(DOMElement $parentNode)
 {
     $start = $parentNode->getAttribute('start');
     if (!$start) {
         throw new Sabre_DAV_Exception_BadRequest('The "start" attribute is required for the CALDAV:expand element');
     }
     $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
     $end = $parentNode->getAttribute('end');
     if (!$end) {
         throw new Sabre_DAV_Exception_BadRequest('The "end" attribute is required for the CALDAV:expand element');
     }
     $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
     if ($end <= $start) {
         throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the expand element.');
     }
     return array('start' => $start, 'end' => $end);
 }
 /**
  * Creates the iterator
  *
  * You should pass a VCALENDAR component, as well as the UID of the event
  * we're going to traverse.
  *
  * @param Sabre_VObject_Component $comp
  */
 public function __construct(Sabre_VObject_Component $vcal, $uid = null)
 {
     if (is_null($uid)) {
         if ($vcal->name === 'VCALENDAR') {
             throw new InvalidArgumentException('If you pass a VCALENDAR object, you must pass a uid argument as well');
         }
         $components = array($vcal);
         $uid = (string) $vcal->uid;
     } else {
         $components = $vcal->select('VEVENT');
     }
     foreach ($components as $component) {
         if ((string) $component->uid == $uid) {
             if (isset($component->{'RECURRENCE-ID'})) {
                 $this->overriddenEvents[$component->DTSTART->getDateTime()->getTimeStamp()] = $component;
                 $this->overriddenDates[] = $component->{'RECURRENCE-ID'}->getDateTime();
             } else {
                 $this->baseEvent = $component;
             }
         }
     }
     if (!$this->baseEvent) {
         throw new InvalidArgumentException('Could not find a base event with uid: ' . $uid);
     }
     $this->startDate = clone $this->baseEvent->DTSTART->getDateTime();
     $this->endDate = null;
     if (isset($this->baseEvent->DTEND)) {
         $this->endDate = clone $this->baseEvent->DTEND->getDateTime();
     } else {
         $this->endDate = clone $this->startDate;
         if (isset($this->baseEvent->DURATION)) {
             $this->endDate->add(Sabre_VObject_DateTimeParser::parse($this->baseEvent->DURATION->value));
         }
     }
     $this->currentDate = clone $this->startDate;
     $rrule = (string) $this->baseEvent->RRULE;
     $parts = explode(';', $rrule);
     foreach ($parts as $part) {
         list($key, $value) = explode('=', $part, 2);
         switch (strtoupper($key)) {
             case 'FREQ':
                 if (!in_array(strtolower($value), array('secondly', 'minutely', 'hourly', 'daily', 'weekly', 'monthly', 'yearly'))) {
                     throw new InvalidArgumentException('Unknown value for FREQ=' . strtoupper($value));
                 }
                 $this->frequency = strtolower($value);
                 break;
             case 'UNTIL':
                 $this->until = Sabre_VObject_DateTimeParser::parse($value);
                 break;
             case 'COUNT':
                 $this->count = (int) $value;
                 break;
             case 'INTERVAL':
                 $this->interval = (int) $value;
                 break;
             case 'BYSECOND':
                 $this->bySecond = explode(',', $value);
                 break;
             case 'BYMINUTE':
                 $this->byMinute = explode(',', $value);
                 break;
             case 'BYHOUR':
                 $this->byHour = explode(',', $value);
                 break;
             case 'BYDAY':
                 $this->byDay = explode(',', strtoupper($value));
                 break;
             case 'BYMONTHDAY':
                 $this->byMonthDay = explode(',', $value);
                 break;
             case 'BYYEARDAY':
                 $this->byYearDay = explode(',', $value);
                 break;
             case 'BYWEEKNO':
                 $this->byWeekNo = explode(',', $value);
                 break;
             case 'BYMONTH':
                 $this->byMonth = explode(',', $value);
                 break;
             case 'BYSETPOS':
                 $this->bySetPos = explode(',', $value);
                 break;
             case 'WKST':
                 $this->weekStart = strtoupper($value);
                 break;
         }
     }
     // Parsing exception dates
     if (isset($this->baseEvent->EXDATE)) {
         foreach ($this->baseEvent->EXDATE as $exDate) {
             foreach (explode(',', (string) $exDate) as $exceptionDate) {
                 $this->exceptionDates[] = Sabre_VObject_DateTimeParser::parse($exceptionDate, $this->startDate->getTimeZone());
             }
         }
     }
 }
 /**
  * Parses the input data and returns a correct VFREEBUSY object, wrapped in
  * a VCALENDAR.
  *
  * @return Sabre_VObject_Component
  */
 public function getResult()
 {
     $busyTimes = array();
     foreach ($this->objects as $object) {
         foreach ($object->getBaseComponents() as $component) {
             switch ($component->name) {
                 case 'VEVENT':
                     $FBTYPE = 'BUSY';
                     if (isset($component->TRANSP) && strtoupper($component->TRANSP) === 'TRANSPARENT') {
                         break;
                     }
                     if (isset($component->STATUS)) {
                         $status = strtoupper($component->STATUS);
                         if ($status === 'CANCELLED') {
                             break;
                         }
                         if ($status === 'TENTATIVE') {
                             $FBTYPE = 'BUSY-TENTATIVE';
                         }
                     }
                     $times = array();
                     if ($component->RRULE) {
                         $iterator = new Sabre_VObject_RecurrenceIterator($object, (string) $component->uid);
                         if ($this->start) {
                             $iterator->fastForward($this->start);
                         }
                         $maxRecurrences = 200;
                         while ($iterator->valid() && --$maxRecurrences) {
                             $startTime = $iterator->getDTStart();
                             if ($this->end && $startTime > $this->end) {
                                 break;
                             }
                             $times[] = array($iterator->getDTStart(), $iterator->getDTEnd());
                             $iterator->next();
                         }
                     } else {
                         $startTime = $component->DTSTART->getDateTime();
                         if ($this->end && $startTime > $this->end) {
                             break;
                         }
                         $endTime = null;
                         if (isset($component->DTEND)) {
                             $endTime = $component->DTEND->getDateTime();
                         } elseif (isset($component->DURATION)) {
                             $duration = Sabre_VObject_DateTimeParser::parseDuration((string) $component->DURATION);
                             $endTime = clone $startTime;
                             $endTime->add($duration);
                         } elseif ($component->DTSTART->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
                             $endTime = clone $startTime;
                             $endTime->modify('+1 day');
                         } else {
                             // The event had no duration (0 seconds)
                             break;
                         }
                         $times[] = array($startTime, $endTime);
                     }
                     foreach ($times as $time) {
                         if ($this->end && $time[0] > $this->end) {
                             break;
                         }
                         if ($this->start && $time[1] < $this->start) {
                             break;
                         }
                         $busyTimes[] = array($time[0], $time[1], $FBTYPE);
                     }
                     break;
                 case 'VFREEBUSY':
                     foreach ($component->FREEBUSY as $freebusy) {
                         $fbType = isset($freebusy['FBTYPE']) ? strtoupper($freebusy['FBTYPE']) : 'BUSY';
                         // Skipping intervals marked as 'free'
                         if ($fbType === 'FREE') {
                             continue;
                         }
                         $values = explode(',', $freebusy);
                         foreach ($values as $value) {
                             list($startTime, $endTime) = explode('/', $value);
                             $startTime = Sabre_VObject_DateTimeParser::parseDateTime($startTime);
                             if (substr($endTime, 0, 1) === 'P' || substr($endTime, 0, 2) === '-P') {
                                 $duration = Sabre_VObject_DateTimeParser::parseDuration($endTime);
                                 $endTime = clone $startTime;
                                 $endTime->add($duration);
                             } else {
                                 $endTime = Sabre_VObject_DateTimeParser::parseDateTime($endTime);
                             }
                             if ($this->start && $this->start > $endTime) {
                                 continue;
                             }
                             if ($this->end && $this->end < $startTime) {
                                 continue;
                             }
                             $busyTimes[] = array($startTime, $endTime, $fbType);
                         }
                     }
                     break;
             }
         }
     }
     if ($this->baseObject) {
         $calendar = $this->baseObject;
     } else {
         $calendar = new Sabre_VObject_Component('VCALENDAR');
         $calendar->version = '2.0';
         $calendar->prodid = '-//SabreDAV//Sabre VObject ' . Sabre_VObject_Version::VERSION . '//EN';
         $calendar->calscale = 'GREGORIAN';
     }
     $vfreebusy = new Sabre_VObject_Component('VFREEBUSY');
     $calendar->add($vfreebusy);
     if ($this->start) {
         $dtstart = new Sabre_VObject_Property_DateTime('DTSTART');
         $dtstart->setDateTime($this->start, Sabre_VObject_Property_DateTime::UTC);
         $vfreebusy->add($dtstart);
     }
     if ($this->end) {
         $dtend = new Sabre_VObject_Property_DateTime('DTEND');
         $dtend->setDateTime($this->start, Sabre_VObject_Property_DateTime::UTC);
         $vfreebusy->add($dtend);
     }
     $dtstamp = new Sabre_VObject_Property_DateTime('DTSTAMP');
     $dtstamp->setDateTime(new DateTime('now'), Sabre_VObject_Property_DateTime::UTC);
     $vfreebusy->add($dtstamp);
     foreach ($busyTimes as $busyTime) {
         $busyTime[0]->setTimeZone(new DateTimeZone('UTC'));
         $busyTime[1]->setTimeZone(new DateTimeZone('UTC'));
         $prop = new Sabre_VObject_Property('FREEBUSY', $busyTime[0]->format('Ymd\\THis\\Z') . '/' . $busyTime[1]->format('Ymd\\THis\\Z'));
         $prop['FBTYPE'] = $busyTime[2];
         $vfreebusy->add($prop);
     }
     return $calendar;
 }
 /**
  * @depends testParseICalendarDate
  * @expectedException Sabre_DAV_Exception_BadRequest
  */
 function testParseICalendarDateBadFormat()
 {
     $dateTime = Sabre_VObject_DateTimeParser::parseDate('20100316T141405');
 }
 /**
  * Validates if a component matches the given time range.
  *
  * This is all based on the rules specified in rfc4791, which are quite
  * complex.
  *
  * @param Sabre_VObject_Node $component
  * @param DateTime $start
  * @param DateTime $end
  * @return bool
  */
 protected function validateTimeRange(Sabre_VObject_Node $component, $start, $end)
 {
     if (is_null($start)) {
         $start = new DateTime('1900-01-01');
     }
     if (is_null($end)) {
         $end = new DateTime('3000-01-01');
     }
     switch ($component->name) {
         case 'VEVENT':
         case 'VTODO':
         case 'VJOURNAL':
             return $component->isInTimeRange($start, $end);
         case 'VFREEBUSY':
             throw new Sabre_DAV_Exception_NotImplemented('time-range filters are currently not supported on ' . $component->name . ' components');
         case 'VALARM':
             $trigger = $component->TRIGGER;
             if (!isset($trigger['TYPE']) || strtoupper($trigger['TYPE']) === 'DURATION') {
                 $triggerDuration = Sabre_VObject_DateTimeParser::parseDuration($component->TRIGGER);
                 $related = isset($trigger['RELATED']) && strtoupper($trigger['RELATED']) == 'END' ? 'END' : 'START';
                 $parentComponent = $component->parent;
                 if ($related === 'START') {
                     $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
                     $effectiveTrigger->add($triggerDuration);
                 } else {
                     if ($parentComponent->name === 'VTODO') {
                         $endProp = 'DUE';
                     } elseif ($parentComponent->name === 'VEVENT') {
                         $endProp = 'DTEND';
                     } else {
                         throw new Sabre_DAV_Exception('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT');
                     }
                     if (isset($parentComponent->{$endProp})) {
                         $effectiveTrigger = clone $parentComponent->{$endProp}->getDateTime();
                         $effectiveTrigger->add($triggerDuration);
                     } elseif (isset($parentComponent->DURATION)) {
                         $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
                         $duration = Sabre_VObject_DateTimeParser::parseDuration($parentComponent->DURATION);
                         $effectiveTrigger->add($duration);
                         $effectiveTrigger->add($triggerDuration);
                     } else {
                         $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
                         $effectiveTrigger->add($triggerDuration);
                     }
                 }
             } else {
                 $effectiveTrigger = $trigger->getDateTime();
             }
             if (isset($component->DURATION)) {
                 $duration = Sabre_VObject_DateTimeParser::parseDuration($component->DURATION);
                 $repeat = (string) $component->repeat;
                 if (!$repeat) {
                     $repeat = 1;
                 }
                 $period = new DatePeriod($effectiveTrigger, $duration, (int) $repeat);
                 foreach ($period as $occurrence) {
                     if ($start <= $occurrence && $end > $occurrence) {
                         return true;
                     }
                 }
                 return false;
             } else {
                 return $start <= $effectiveTrigger && $end > $effectiveTrigger;
             }
             break;
         case 'COMPLETED':
         case 'CREATED':
         case 'DTEND':
         case 'DTSTAMP':
         case 'DTSTART':
         case 'DUE':
         case 'LAST-MODIFIED':
             return $start <= $component->getDateTime() && $end >= $component->getDateTime();
         default:
             throw new Sabre_DAV_Exception_BadRequest('You cannot create a time-range filter on a ' . $component->name . ' component');
     }
 }