Back to index

d-push  2.0
Public Member Functions | Static Public Member Functions | Public Attributes
Recurrence Class Reference

Recurrence. More...

Inheritance diagram for Recurrence:
Inheritance graph
[legend]
Collaboration diagram for Recurrence:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 Recurrence ($store, $message)
 Constructor.
 createException ($exception_props, $base_date, $delete=false, $exception_recips=array(), $copy_attach_from=false)
 Create an exception.
 modifyException ($exception_props, $base_date, $exception_recips=array(), $copy_attach_from=false)
 Modifies an existing exception, but only updates the given properties NOTE: You can't remove properites from an exception, only add new ones.
 isValidExceptionDate ($basedate, $start)
 isValidReminderTime ($basedate, $reminderminutes, $startdate)
 Check to see if the exception proposed at a certain basedate is allowed concerning reminder times:
 setRecurrence ($tz, $recur)
 getOccurrenceStart ($basedate)
 getOccurrenceEnd ($basedate)
 getOccurenceStart ($basedate)
 getOccurenceEnd ($basedate)
 getNextReminderTime ($timestamp)
 This function returns the next remindertime starting from $timestamp When no next reminder exists, false is returned.
 saveRecurrencePattern ()
 Generates and stores recurrence pattern string to recurring_pattern property.
 deleteException ($base_date)
 createExceptionAttachment ($exception_props, $exception_recips=array(), $copy_attach_from=false)
 Function which saves the exception data in an attachment.
 deleteExceptionAttachment ($base_date)
 Function which deletes the attachment of an exception.
 deleteAttachments ()
 Function which deletes all attachments of a message.
 getExceptionAttachment ($base_date)
 Get an exception attachment based on its basedate.
 processOccurrenceItem (&$items, $start, $end, $basedate, $startocc, $endocc, $tz, $reminderonly)
 processOccurrenceItem, adds an item to a list of occurrences, but only if the following criteria are met:
 processExceptionItems (&$items, $start, $end)
 processExceptionItem, adds an all exception item to a list of occurrences, without any constraint on timeframe
 isException ($basedate)
 Function which verifies if on the given date an exception, delete or change, occurs.
 isDeleteException ($basedate)
 Returns TRUE if there is a DELETE exception on the given base date.
 getChangeException ($basedate)
 Returns the exception if there is a CHANGE exception on the given base date, or FALSE otherwise.
 isSameDay ($date1, $date2)
 Function to see if two dates are on the same day.
 getExceptionProperties ($exception)
 Function to get all properties of a single changed exception.
 setExceptionRecipients ($message, $exception_recips, $copy_orig_recips=true)
 Function which sets recipients for an exception.
 setDeltaExceptionRecipients ($exception, $exception_recips, $copy_orig_recips)
 Function which applies the provided delta for recipients changes to the exception.
 setAllExceptionRecipients ($message, $exception_recips)
 Function which applies the provided recipients to the exception, also checks for deleted recipients.
 getAllExceptions ()
 Function returns basedates of all changed occurrences.
 addOrganizer ($messageProps, &$recipients, $isException=false)
 Function which adds organizer to recipient list which is passed.
 BaseRecurrence ($store, $message)
 Constructor.
 getRecurrence ()
 getFullRecurrenceBlob ()
 parseRecurrence ($rdata)
 Function for parsing the Recurrence value of a Calendar item.
 saveRecurrence ()
 Saves the recurrence data to the recurrence property.
 recurDataToUnixData ($rdate)
 Function which converts a recurrence date timestamp to an unix date timestamp.
 unixDataToRecurData ($date)
 Function which converts an unix date timestamp to recurrence date timestamp.
 GetTZOffset ($ts)
 gmtime() doesn't exist in standard PHP, so we have to implement it ourselves
 gmtime ($time)
 gmtime() doesn't exist in standard PHP, so we have to implement it ourselves
 isLeapYear ($year)
 getMonthInSeconds ($year, $month)
 getDateByYearMonthWeekDayHour ($year, $month, $week, $day, $hour)
 Function to get a date by Year Nr, Month Nr, Week Nr, Day Nr, and hour.
 getTimezone ($tz, $date)
 getTimezone gives the timezone offset (in minutes) of the given local date/time according to the given TZ info
 getWeekNr ($date)
 getWeekNr() returns the week nr of the month (ie first week of february is 1)
 parseTimezone ($data)
 parseTimezone parses the timezone as specified in named property 0x8233 in Outlook calendar messages.
 getTimezoneData ($tz)
 createTimezone ($tz)
 createTimezone creates the timezone as specified in the named property 0x8233 see also parseTimezone() $tz is an array with the timezone data
 toGMT ($tz, $date)
 toGMT returns a timestamp in GMT time for the time and timezone given
 fromGMT ($tz, $date)
 fromGMT returns a timestamp in the local timezone given from the GMT time given
 dayStartOf ($date)
 Function to get timestamp of the beginning of the day of the timestamp given.
 monthStartOf ($date)
 Function to get timestamp of the beginning of the month of the timestamp given.
 yearStartOf ($date)
 Function to get timestamp of the beginning of the year of the timestamp given.
 getItems ($start, $end, $limit=0, $remindersonly=false)
 Function which returns the items in a given interval.
 sortStarttime ($a, $b)
 daysInMonth ($date, $months)
 daysInMonth
 monthOfYear ($minutes)
 sortExceptionStart ($a, $b)

Static Public Member Functions

static getCalendarItems ($store, $calendar, $viewstart, $viewend, $propsrequested)
 Note: Static function, more like a utility function.

Public Attributes

 $recipprops
 $store
 $message
 $messageprops
 $proptags
 $recur
 $tz

Detailed Description

Recurrence.

Author:
Steve Hardy steve.nosp@m.@zar.nosp@m.afa.c.nosp@m.om
Michel de Ron miche.nosp@m.l@za.nosp@m.rafa..nosp@m.com

Definition at line 58 of file class.recurrence.php.


Member Function Documentation

Recurrence::addOrganizer ( messageProps,
&$  recipients,
isException = false 
)

Function which adds organizer to recipient list which is passed.

This function also checks if it has organizer.

Parameters:
array$messagePropsmessage properties
array$recipientsrecipients list of message.
boolean$isExceptiontrue if we are processing recipient of exception

Definition at line 1237 of file class.recurrence.php.

                                                                                {

            $hasOrganizer = false;
            // Check if meeting already has an organizer.
            foreach ($recipients as $key => $recipient){
                if (isset($recipient[PR_RECIPIENT_FLAGS]) && $recipient[PR_RECIPIENT_FLAGS] == (recipSendable | recipOrganizer)) {
                    $hasOrganizer = true;
                } else if ($isException && !isset($recipient[PR_RECIPIENT_FLAGS])){
                    // Recipients for an occurrence
                    $recipients[$key][PR_RECIPIENT_FLAGS] = recipSendable | recipExceptionalResponse;
                }
            }

            if (!$hasOrganizer){
                // Create organizer.
                $organizer = array();
                $organizer[PR_ENTRYID] = $messageProps[PR_SENT_REPRESENTING_ENTRYID];
                $organizer[PR_DISPLAY_NAME] = $messageProps[PR_SENT_REPRESENTING_NAME];
                $organizer[PR_EMAIL_ADDRESS] = $messageProps[PR_SENT_REPRESENTING_EMAIL_ADDRESS];
                $organizer[PR_RECIPIENT_TYPE] = MAPI_TO;
                $organizer[PR_RECIPIENT_DISPLAY_NAME] = $messageProps[PR_SENT_REPRESENTING_NAME];
                $organizer[PR_ADDRTYPE] = empty($messageProps[PR_SENT_REPRESENTING_ADDRTYPE])?'SMTP':$messageProps[PR_SENT_REPRESENTING_ADDRTYPE];
                $organizer[PR_RECIPIENT_TRACKSTATUS] = olRecipientTrackStatusNone;
                $organizer[PR_RECIPIENT_FLAGS] = recipSendable | recipOrganizer;

                // Add organizer to recipients list.
                array_unshift($recipients, $organizer);
            }
        }

Here is the caller graph for this function:

BaseRecurrence::BaseRecurrence ( store,
message 
) [inherited]

Constructor.

Parameters:
resource$storeMAPI Message Store Object
resource$messagethe MAPI (appointment) message
array$propertiesthe list of MAPI properties the message has.

Definition at line 94 of file class.baserecurrence.php.

        {
            $this->store = $store;

            if(is_array($message)) {
                $this->messageprops = $message;
            } else {
                $this->message = $message;
                $this->messageprops = mapi_getprops($this->message, $this->proptags);
            }

            if(isset($this->messageprops[$this->proptags["recurring_data"]])) {
                // There is a possibility that recurr blob can be more than 255 bytes so get full blob through stream interface
                if (strlen($this->messageprops[$this->proptags["recurring_data"]]) >= 255) {
                    $this->getFullRecurrenceBlob();
                }

                $this->recur = $this->parseRecurrence($this->messageprops[$this->proptags["recurring_data"]]);
            }
            if(isset($this->proptags["timezone_data"]) && isset($this->messageprops[$this->proptags["timezone_data"]])) {
                $this->tz = $this->parseTimezone($this->messageprops[$this->proptags["timezone_data"]]);
            }
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Recurrence::createException ( exception_props,
base_date,
delete = false,
exception_recips = array(),
copy_attach_from = false 
)

Create an exception.

Parameters:
array$exception_propsthe exception properties (same properties as normal recurring items)
date$base_datethe base date of the exception (LOCAL time of non-exception occurrence)
boolean$deletetrue - delete occurrence, false - create new exception or modify existing
array$exception_recipstrue - delete occurrence, false - create new exception or modify existing
mapi_message$copy_attach_frommapi message from which attachments should be copied

Definition at line 153 of file class.recurrence.php.

        {
            $baseday = $this->dayStartOf($base_date);
            $basetime = $baseday + $this->recur["startocc"] * 60;

            // Remove any pre-existing exception on this base date
            if($this->isException($baseday)) {
                $this->deleteException($baseday); // note that deleting an exception is different from creating a deleted exception (deleting an occurrence).
            }

            if(!$delete) {
                if(isset($exception_props[$this->proptags["startdate"]]) && !$this->isValidExceptionDate($base_date, $this->fromGMT($this->tz, $exception_props[$this->proptags["startdate"]]))) {
                    return false;
                }
                // Properties in the attachment are the properties of the base object, plus $exception_props plus the base date
                foreach (array("subject", "location", "label", "reminder", "reminder_minutes", "alldayevent", "busystatus") as $propname) {
                    if(isset($this->messageprops[$this->proptags[$propname]]))
                        $props[$this->proptags[$propname]] = $this->messageprops[$this->proptags[$propname]];
                }

                $props[PR_MESSAGE_CLASS] = "IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}";
                unset($exception_props[PR_MESSAGE_CLASS]);
                unset($exception_props[PR_ICON_INDEX]);
                $props = $exception_props + $props;

                // Basedate in the exception attachment is the GMT time at which the original occurrence would have been
                $props[$this->proptags["basedate"]] = $this->toGMT($this->tz, $basetime);

                if (!isset($exception_props[$this->proptags["startdate"]])) {
                    $props[$this->proptags["startdate"]] = $this->getOccurrenceStart($base_date);
                }

                if (!isset($exception_props[$this->proptags["duedate"]])) {
                    $props[$this->proptags["duedate"]] = $this->getOccurrenceEnd($base_date);
                }

                // synchronize commonstart/commonend with startdate/duedate
                if(isset($props[$this->proptags["startdate"]])) {
                    $props[$this->proptags["commonstart"]] = $props[$this->proptags["startdate"]];
                }

                if(isset($props[$this->proptags["duedate"]])) {
                    $props[$this->proptags["commonend"]] = $props[$this->proptags["duedate"]];
                }

                // Save the data into an attachment
                $this->createExceptionAttachment($props, $exception_recips, $copy_attach_from);

                $changed_item = array();

                $changed_item["basedate"] = $baseday;
                $changed_item["start"] = $this->fromGMT($this->tz, $props[$this->proptags["startdate"]]);
                $changed_item["end"] = $this->fromGMT($this->tz, $props[$this->proptags["duedate"]]);

                if(array_key_exists($this->proptags["subject"], $exception_props)) {
                    $changed_item["subject"] = $exception_props[$this->proptags["subject"]];
                }

                if(array_key_exists($this->proptags["location"], $exception_props)) {
                    $changed_item["location"] = $exception_props[$this->proptags["location"]];
                }

                if(array_key_exists($this->proptags["label"], $exception_props)) {
                    $changed_item["label"] = $exception_props[$this->proptags["label"]];
                }

                if(array_key_exists($this->proptags["reminder"], $exception_props)) {
                    $changed_item["reminder_set"] = $exception_props[$this->proptags["reminder"]];
                }

                if(array_key_exists($this->proptags["reminder_minutes"], $exception_props)) {
                    $changed_item["remind_before"] = $exception_props[$this->proptags["reminder_minutes"]];
                }

                if(array_key_exists($this->proptags["alldayevent"], $exception_props)) {
                    $changed_item["alldayevent"] = $exception_props[$this->proptags["alldayevent"]];
                }

                if(array_key_exists($this->proptags["busystatus"], $exception_props)) {
                    $changed_item["busystatus"] = $exception_props[$this->proptags["busystatus"]];
                }

                // Add the changed occurrence to the list
                array_push($this->recur["changed_occurences"], $changed_item);
            } else {
                // Delete the occurrence by placing it in the deleted occurrences list
                array_push($this->recur["deleted_occurences"], $baseday);
            }

            // Turn on hideattachments, because the attachments in this item are the exceptions
            mapi_setprops($this->message, array ( $this->proptags["hideattachments"] => true ));

            // Save recurrence data to message
            $this->saveRecurrence();

            return true;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Recurrence::createExceptionAttachment ( exception_props,
exception_recips = array(),
copy_attach_from = false 
)

Function which saves the exception data in an attachment.

Parameters:
array$exception_propsthe exception data (like any other MAPI appointment)
array$exception_recipslist of recipients
mapi_message$copy_attach_frommapi message from which attachments should be copied
Returns:
array properties of the exception

Definition at line 729 of file class.recurrence.php.

        {
              // Create new attachment.
              $attachment = mapi_message_createattach($this->message);
              $props = array();
              $props[PR_ATTACHMENT_FLAGS] = 2;
              $props[PR_ATTACHMENT_HIDDEN] = true;
              $props[PR_ATTACHMENT_LINKID] = 0;
              $props[PR_ATTACH_FLAGS] = 0;
              $props[PR_ATTACH_METHOD] = 5;
              $props[PR_DISPLAY_NAME] = "Exception";
              $props[PR_EXCEPTION_STARTTIME] = $this->fromGMT($this->tz, $exception_props[$this->proptags["startdate"]]);
              $props[PR_EXCEPTION_ENDTIME] = $this->fromGMT($this->tz, $exception_props[$this->proptags["duedate"]]);
              mapi_message_setprops($attachment, $props);

            $imessage = mapi_attach_openobj($attachment, MAPI_CREATE | MAPI_MODIFY);

            if ($copy_attach_from) {
                $attachmentTable = mapi_message_getattachmenttable($copy_attach_from);
                if($attachmentTable) {
                    $attachments = mapi_table_queryallrows($attachmentTable, array(PR_ATTACH_NUM, PR_ATTACH_SIZE, PR_ATTACH_LONG_FILENAME, PR_ATTACHMENT_HIDDEN, PR_DISPLAY_NAME, PR_ATTACH_METHOD));

                    foreach($attachments as $attach_props){
                        $attach_old = mapi_message_openattach($copy_attach_from, (int) $attach_props[PR_ATTACH_NUM]);
                        $attach_newResourceMsg = mapi_message_createattach($imessage);
                        mapi_copyto($attach_old, array(), array(), $attach_newResourceMsg, 0);
                        mapi_savechanges($attach_newResourceMsg);
                    }
                }
            }

            $props = $props + $exception_props;

            // FIXME: the following piece of code is written to fix the creation
            // of an exception. This is only a quickfix as it is not yet possible
            // to change an existing exception.
            // remove mv properties when needed
            foreach($props as $propTag=>$propVal){
                if ((mapi_prop_type($propTag) & MV_FLAG) == MV_FLAG && is_null($propVal)){
                    unset($props[$propTag]);
                }
            }

            mapi_message_setprops($imessage, $props);

            $this->setExceptionRecipients($imessage, $exception_recips, true);

            mapi_message_savechanges($imessage);
            mapi_message_savechanges($attachment);
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::createTimezone ( tz) [inherited]

createTimezone creates the timezone as specified in the named property 0x8233 see also parseTimezone() $tz is an array with the timezone data

Definition at line 1570 of file class.baserecurrence.php.

        {
            $data = pack("lxxxxlxxxxlvvxxxxxxxxxxlvvxxxxxx",
                        $tz["timezone"],
                        array_key_exists("timezonedst",$tz)?$tz["timezonedst"]:0,
                        array_key_exists("dstendmonth",$tz)?$tz["dstendmonth"]:0,
                        array_key_exists("dstendweek",$tz)?$tz["dstendweek"]:0,
                        array_key_exists("dstendhour",$tz)?$tz["dstendhour"]:0,
                        array_key_exists("dststartmonth",$tz)?$tz["dststartmonth"]:0,
                        array_key_exists("dststartweek",$tz)?$tz["dststartweek"]:0,
                        array_key_exists("dststarthour",$tz)?$tz["dststarthour"]:0
                    );

            return $data;
        }
BaseRecurrence::daysInMonth ( date,
months 
) [inherited]

daysInMonth

Returns the number of days in the upcoming number of months. If you specify 1 month as $months it will give you the number of days in the month of $date. If you specify more it will also count the days in the upcomming months and add that to the number of days. So if you have a date in march and you specify $months as 2 it will return 61.

Parameters:
Integer$dateSpecified date as timestamp from which you want to know the number of days in the month.
Integer$monthsNumber of months you want to know the number of days in.
Returns:
Integer Number of days in the specified amount of months.

Definition at line 1919 of file class.baserecurrence.php.

                                             {
            $days = 0;

            for($i=0;$i<$months;$i++) {
                $days += date("t", $date + $days * 24 * 60 * 60);
            }

            return $days;
        }

Here is the caller graph for this function:

BaseRecurrence::dayStartOf ( date) [inherited]

Function to get timestamp of the beginning of the day of the timestamp given.

Parameters:
date$date
Returns:
date timestamp referring to same day but at 00:00:00

Definition at line 1611 of file class.baserecurrence.php.

        {
            $time1 = $this->gmtime($date);

            return gmmktime(0, 0, 0, $time1["tm_mon"] + 1, $time1["tm_mday"], $time1["tm_year"] + 1900);
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Function which deletes all attachments of a message.

Definition at line 807 of file class.recurrence.php.

        {
            $attachments = mapi_message_getattachmenttable($this->message);
            $attachTable = mapi_table_queryallrows($attachments, Array(PR_ATTACH_NUM, PR_ATTACHMENT_HIDDEN));

            foreach($attachTable as $attachRow)
            {
                if(isset($attachRow[PR_ATTACHMENT_HIDDEN]) && $attachRow[PR_ATTACHMENT_HIDDEN]) {
                    mapi_message_deleteattach($this->message, $attachRow[PR_ATTACH_NUM]);
                }
            }
        }

Here is the caller graph for this function:

Recurrence::deleteException ( base_date)

Definition at line 697 of file class.recurrence.php.

        {
            // Remove all exceptions on $base_date from the deleted and changed occurrences lists

            // Remove all items in $todelete from deleted_occurences
            $new = Array();

            foreach($this->recur["deleted_occurences"] as $entry) {
                if($entry != $base_date)
                    $new[] = $entry;
            }
            $this->recur["deleted_occurences"] = $new;

            $new = Array();

            foreach($this->recur["changed_occurences"] as $entry) {
                if(!$this->isSameDay($entry["basedate"], $base_date))
                    $new[] = $entry;
                else
                    $this->deleteExceptionAttachment($this->toGMT($this->tz, $base_date + $this->recur["startocc"] * 60));
            }

            $this->recur["changed_occurences"] = $new;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Function which deletes the attachment of an exception.

Parameters:
date$base_datebase date of the attachment. Should be in GMT. The attachment actually saves the real time of the original date, so we have to check whether it's on the same day.

Definition at line 786 of file class.recurrence.php.

        {
            $attachments = mapi_message_getattachmenttable($this->message);
            $attachTable = mapi_table_queryallrows($attachments, Array(PR_ATTACH_NUM));

            foreach($attachTable as $attachRow)
            {
                $tempattach = mapi_message_openattach($this->message, $attachRow[PR_ATTACH_NUM]);
                $exception = mapi_attach_openobj($tempattach);

                  $data = mapi_message_getprops($exception, array($this->proptags["basedate"]));

                  if($this->dayStartOf($this->fromGMT($this->tz, $data[$this->proptags["basedate"]])) == $this->dayStartOf($base_date)) {
                      mapi_message_deleteattach($this->message, $attachRow[PR_ATTACH_NUM]);
                  }
            }
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::fromGMT ( tz,
date 
) [inherited]

fromGMT returns a timestamp in the local timezone given from the GMT time given

Definition at line 1600 of file class.baserecurrence.php.

                                     {
            $offset = $this->getTimezone($tz, $date);

            return $date - $offset * 60;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Function returns basedates of all changed occurrences.

Returns:
array array( 0 => 123459321 )

Definition at line 1216 of file class.recurrence.php.

        {
            $result = false;
            if (!empty($this->recur["changed_occurences"])) {
                $result = array();
                foreach($this->recur["changed_occurences"] as $exception) {
                    $result[] = $exception["basedate"];
                }
                return $result;
            }
            return $result;
        }
static Recurrence::getCalendarItems ( store,
calendar,
viewstart,
viewend,
propsrequested 
) [static]

Note: Static function, more like a utility function.

Gets all the items (including recurring items) in the specified calendar in the given timeframe. Items are included as a whole if they overlap the interval <$start, $end> (non-inclusive). This means that if the interval is <08:00 - 14:00>, the item [6:00 - 8:00> is NOT included, nor is the item [14:00 - 16:00>. However, the item [7:00 - 9:00> is included as a whole, and is NOT capped to [8:00 - 9:00>.

Parameters:
$storeresource The store in which the calendar resides
$calendarresource The calendar to get the items from
$viewstartint Timestamp of beginning of view window
$viewendint Timestamp of end of view window
$propsrequestedarray Array of properties to return
$rowsarray Array of rowdata as if they were returned directly from mapi_table_queryrows. Each recurring item is expanded so that it seems that there are only many single appointments in the table.

Definition at line 543 of file class.recurrence.php.

        {
            return getCalendarItems($store, $calendar, $viewstart, $viewend, $propsrequested);
        }

Returns the exception if there is a CHANGE exception on the given base date, or FALSE otherwise.

Definition at line 970 of file class.recurrence.php.

        {
            // Check if the occurrence is modified on the specified date
            foreach($this->recur["changed_occurences"] as $changed)
            {
                if($this->isSameDay($changed["basedate"], $basedate))
                    return $changed;
            }

            return false;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::getDateByYearMonthWeekDayHour ( year,
month,
week,
day,
hour 
) [inherited]

Function to get a date by Year Nr, Month Nr, Week Nr, Day Nr, and hour.

Parameters:
int$year
int$month
int$week
int$day
int$hour
Returns:
returns the timestamp of the given date, timezone-independant

Definition at line 1474 of file class.baserecurrence.php.

        {
            // get first day of month
            $date = gmmktime(0,0,0,$month,0,$year + 1900);

            // get wday info
            $gmdate = $this->gmtime($date);

            $date -= $gmdate["tm_wday"] * 24 * 60 * 60; // back up to start of week

            $date += $week * 7 * 24 * 60 * 60; // go to correct week nr
            $date += $day * 24 * 60 * 60;
            $date += $hour * 60 * 60;

            $gmdate = $this->gmtime($date);

            // if we are in the next month, then back up a week, because week '5' means
            // 'last week of month'

            if($gmdate["tm_mon"]+1 != $month)
                $date -= 7 * 24 * 60 * 60;

            return $date;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Get an exception attachment based on its basedate.

Definition at line 823 of file class.recurrence.php.

        {
            // Retrieve only embedded messages
            $attach_res = Array(RES_AND,
                            Array(
                                Array(RES_PROPERTY,
                                    Array(RELOP => RELOP_EQ,
                                        ULPROPTAG => PR_ATTACH_METHOD,
                                        VALUE => array(PR_ATTACH_METHOD => 5)
                                    )
                                )
                            )
            );
            $attachments = mapi_message_getattachmenttable($this->message);
            $attachRows = mapi_table_queryallrows($attachments, Array(PR_ATTACH_NUM), $attach_res);

            if(is_array($attachRows)) {
                foreach($attachRows as $attachRow)
                {
                    $tempattach = mapi_message_openattach($this->message, $attachRow[PR_ATTACH_NUM]);
                    $exception = mapi_attach_openobj($tempattach);

                    $data = mapi_message_getprops($exception, array($this->proptags["basedate"]));

                    if($this->isSameDay($this->fromGMT($this->tz,$data[$this->proptags["basedate"]]), $base_date)) {
                        return $tempattach;
                    }
                }
            }

            return false;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Function to get all properties of a single changed exception.

Parameters:
date$datebase date of exception
Returns:
array associative array of properties for the exception, compatible with

Definition at line 1001 of file class.recurrence.php.

        {
            // Exception has same properties as main object, with some properties overridden:
            $item = $this->messageprops;

            // Special properties
            $item["exception"] = true;
            $item["basedate"] = $exception["basedate"]; // note that the basedate is always in local time !

            // MAPI-compatible properties (you can handle an exception as a normal calendar item like this)
            $item[$this->proptags["startdate"]] = $this->toGMT($this->tz, $exception["start"]);
            $item[$this->proptags["duedate"]] = $this->toGMT($this->tz, $exception["end"]);
            $item[$this->proptags["commonstart"]] = $item[$this->proptags["startdate"]];
            $item[$this->proptags["commonend"]] = $item[$this->proptags["duedate"]];

            if(isset($exception["subject"])) {
                $item[$this->proptags["subject"]] = $exception["subject"];
            }

            if(isset($exception["label"])) {
                $item[$this->proptags["label"]] = $exception["label"];
            }

            if(isset($exception["alldayevent"])) {
                $item[$this->proptags["alldayevent"]] = $exception["alldayevent"];
            }

            if(isset($exception["location"])) {
                $item[$this->proptags["location"]] = $exception["location"];
            }

            if(isset($exception["remind_before"])) {
                $item[$this->proptags["reminder_minutes"]] = $exception["remind_before"];
            }

            if(isset($exception["reminder_set"])) {
                $item[$this->proptags["reminder"]] = $exception["reminder_set"];
            }

            if(isset($exception["busystatus"])) {
                $item[$this->proptags["busystatus"]] = $exception["busystatus"];
            }

            return $item;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 123 of file class.baserecurrence.php.

        {
            $message = mapi_msgstore_openentry($this->store, $this->messageprops[PR_ENTRYID]);

            $recurrBlob = '';
            $stream = mapi_openproperty($message, $this->proptags["recurring_data"], IID_IStream, 0, 0);
            $stat = mapi_stream_stat($stream);

            for ($i = 0; $i < $stat['cb']; $i += 1024) {
                $recurrBlob .= mapi_stream_read($stream, 1024);
            }

            if (!empty($recurrBlob)) {
                $this->messageprops[$this->proptags["recurring_data"]] = $recurrBlob;
            }
        }

Here is the caller graph for this function:

BaseRecurrence::getItems ( start,
end,
limit = 0,
remindersonly = false 
) [inherited]

Function which returns the items in a given interval.

This included expansion of the recurrence and processing of exceptions (modified and deleted).

Parameters:
string$entryidthe entryid of the message
array$propsthe properties of the message
date$startstart time of the interval (GMT)
date$endend time of the interval (GMT)

checks weather the next coming day in recurrence pattern is less than or equal to end day of the * recurring item.Also check weather the coming day in recurrence pattern is greater than or equal to start * of recurring pattern, so that appointment that fall under the recurrence range are only displayed.

Definition at line 1652 of file class.baserecurrence.php.

        {
            $items = array();

            if(isset($this->recur)) {

                // Optimization: remindersonly and default reminder is off; since only exceptions with reminder set will match, just look which
                // exceptions are in range and have a reminder set
                if($remindersonly && (!isset($this->messageprops[$this->proptags["reminder"]]) || $this->messageprops[$this->proptags["reminder"]] == false)) {
                    // Sort exceptions by start time
                    uasort($this->recur["changed_occurences"], array($this, "sortExceptionStart"));

                    // Loop through all changed exceptions
                    foreach($this->recur["changed_occurences"] as $exception) {
                        // Check reminder set
                        if(!isset($exception["reminder"]) || $exception["reminder"] == false)
                            continue;

                        // Convert to GMT
                        $occstart = $this->toGMT($this->tz, $exception["start"]); // seb changed $tz to $this->tz
                        $occend = $this->toGMT($this->tz, $exception["end"]); // seb changed $tz to $this->tz

                        // Check range criterium
                        if($occstart > $end || $occend < $start)
                            continue;

                        // OK, add to items.
                        array_push($items, $this->getExceptionProperties($exception));
                        if($limit && (count($items) == $limit))
                            break;
                    }

                    uasort($items, array($this, "sortStarttime"));

                    return $items;
                }

                // From here on, the dates of the occurrences are calculated in local time, so the days we're looking
                // at are calculated from the local time dates of $start and $end

                if ($this->recur['regen'] && isset($this->action['datecompleted'])) {
                    $daystart = $this->dayStartOf($this->action['datecompleted']);
                } else {
                    $daystart = $this->dayStartOf($this->recur["start"]); // start on first day of occurrence
                }

                // Calculate the last day on which we want to be looking at a recurrence; this is either the end of the view
                // or the end of the recurrence, whichever comes first
                if($end > $this->toGMT($this->tz, $this->recur["end"])) {
                    $rangeend = $this->toGMT($this->tz, $this->recur["end"]);
                } else {
                    $rangeend = $end;
                }

                $dayend = $this->dayStartOf($this->fromGMT($this->tz, $rangeend));

                // Loop through the entire recurrence range of dates, and check for each occurrence whether it is in the view range.

                switch($this->recur["type"])
                {
                case 10:
                    // Daily
                    if($this->recur["everyn"] <= 0)
                        $this->recur["everyn"] = 1440;

                    if($this->recur["subtype"] == 0) {
                        // Every Nth day
                        for($now = $daystart; $now <= $dayend && ($limit == 0 || count($items) < $limit); $now += 60 * $this->recur["everyn"]) {
                            $this->processOccurrenceItem($items, $start, $end, $now, $this->recur["startocc"], $this->recur["endocc"], $this->tz, $remindersonly);
                        }
                    } else {
                        // Every workday
                        for($now = $daystart; $now <= $dayend && ($limit == 0 || count($items) < $limit); $now += 60 * 1440)
                        {
                            $nowtime = $this->gmtime($now);
                            if ($nowtime["tm_wday"] > 0 && $nowtime["tm_wday"] < 6) { // only add items in the given timespace
                                $this->processOccurrenceItem($items, $start, $end, $now, $this->recur["startocc"], $this->recur["endocc"], $this->tz, $remindersonly);
                            }
                        }
                    }
                    break;
                case 11:
                    // Weekly
                    if($this->recur["everyn"] <= 0)
                        $this->recur["everyn"] = 1;

                    // If sliding flag is set then move to 'n' weeks
                    if ($this->recur['regen']) $daystart += (60 * 60 * 24 * 7 * $this->recur["everyn"]);

                    for($now = $daystart; $now <= $dayend && ($limit == 0 || count($items) < $limit); $now += (60 * 60 * 24 * 7 * $this->recur["everyn"]))
                    {
                        if ($this->recur['regen']) {
                            $this->processOccurrenceItem($items, $start, $end, $now, $this->recur["startocc"], $this->recur["endocc"], $this->tz, $remindersonly);
                        } else {
                            // Loop through the whole following week to the first occurrence of the week, add each day that is specified
                            for($wday = 0; $wday < 7; $wday++)
                            {
                                $daynow = $now + $wday * 60 * 60 * 24;
                                //checks weather the next coming day in recurring pattern is less than or equal to end day of the recurring item
                                if ($daynow <= $dayend){
                                    $nowtime = $this->gmtime($daynow); // Get the weekday of the current day
                                    if(($this->recur["weekdays"] &(1 << $nowtime["tm_wday"]))) { // Selected ?
                                        $this->processOccurrenceItem($items, $start, $end, $daynow, $this->recur["startocc"], $this->recur["endocc"], $this->tz, $remindersonly);
                                    }
                                }
                            }
                        }
                    }
                    break;
                case 12:
                    // Monthly
                    if($this->recur["everyn"] <= 0)
                        $this->recur["everyn"] = 1;

                    // Loop through all months from start to end of occurrence, starting at beginning of first month
                    for($now = $this->monthStartOf($daystart); $now <= $dayend && ($limit == 0 || count($items) < $limit); $now += $this->daysInMonth($now, $this->recur["everyn"]) * 24 * 60 * 60 )
                    {
                        if(isset($this->recur["monthday"]) &&($this->recur['monthday'] != "undefined") && !$this->recur['regen']) { // Day M of every N months
                            $difference = 1;
                            if ($this->daysInMonth($now, $this->recur["everyn"]) < $this->recur["monthday"]) {
                                $difference = $this->recur["monthday"] - $this->daysInMonth($now, $this->recur["everyn"]) + 1;
                            }
                            $daynow = $now + (($this->recur["monthday"] - $difference) * 24 * 60 * 60);
                            //checks weather the next coming day in recurrence pattern is less than or equal to end day of the recurring item
                            if ($daynow <= $dayend){
                                $this->processOccurrenceItem($items, $start, $end, $daynow, $this->recur["startocc"], $this->recur["endocc"], $this->tz, $remindersonly);
                            }
                        }
                        else if(isset($this->recur["nday"]) && isset($this->recur["weekdays"])) { // Nth [weekday] of every N months
                            // Sanitize input
                            if($this->recur["weekdays"] == 0)
                                $this->recur["weekdays"] = 1;

                            // If nday is not set to the last day in the month
                            if ($this->recur["nday"] < 5) {
                                // keep the track of no. of time correct selection pattern(like 2nd weekday, 4th fiday, etc.)is matched
                                $ndaycounter = 0;
                                // Find matching weekday in this month
                                for($day = 0; $day < $this->daysInMonth($now, 1); $day++)
                                {
                                    $daynow = $now + $day * 60 * 60 * 24;
                                    $nowtime = $this->gmtime($daynow); // Get the weekday of the current day

                                    if($this->recur["weekdays"] & (1 << $nowtime["tm_wday"])) { // Selected ?
                                        $ndaycounter ++;
                                    }
                                    // check the selected pattern is same as asked Nth weekday,If so set the firstday
                                    if($this->recur["nday"] == $ndaycounter){
                                        $firstday = $day;
                                        break;
                                    }
                                }
                                // $firstday is the day of the month on which the asked pattern of nth weekday matches
                                $daynow = $now + $firstday * 60 * 60 * 24;
                            }else{
                                // Find last day in the month ($now is the firstday of the month)
                                $NumDaysInMonth =  $this->daysInMonth($now, 1);
                                $daynow = $now + (($NumDaysInMonth-1) * 24*60*60);

                                $nowtime = $this->gmtime($daynow);
                                while (($this->recur["weekdays"] & (1 << $nowtime["tm_wday"]))==0){
                                    $daynow -= 86400;
                                    $nowtime = $this->gmtime($daynow);
                                }
                            }

                            if ($daynow <= $dayend && $daynow >= $daystart){
                                $this->processOccurrenceItem($items, $start, $end, $daynow, $this->recur["startocc"], $this->recur["endocc"], $this->tz , $remindersonly);
                            }
                        } else if ($this->recur['regen']) {
                            $next_month_start = $now + ($this->daysInMonth($now, 1) * 24 * 60 * 60);
                            $now = $daystart +($this->daysInMonth($next_month_start, $this->recur['everyn']) * 24 * 60 * 60);

                            if ($now <= $dayend) {
                                $this->processOccurrenceItem($items, $daystart, $end, $now, $this->recur["startocc"], $this->recur["endocc"], $this->tz, $remindersonly);
                            }
                        }
                    }
                    break;
                case 13:
                    // Yearly
                    if($this->recur["everyn"] <= 0)
                        $this->recur["everyn"] = 12;

                    for($now = $this->yearStartOf($daystart); $now <= $dayend && ($limit == 0 || count($items) < $limit); $now += $this->daysInMonth($now, $this->recur["everyn"]) * 24 * 60 * 60 )
                    {
                        if(isset($this->recur["monthday"]) && !$this->recur['regen']) { // same as monthly, but in a specific month
                            // recur["month"] is in minutes since the beginning of the year
                            $month = $this->monthOfYear($this->recur["month"]); // $month is now month of year [0..11]
                            $monthday = $this->recur["monthday"]; // $monthday is day of the month [1..31]
                            $monthstart = $now + $this->daysInMonth($now, $month) * 24 * 60 * 60; // $monthstart is the timestamp of the beginning of the month
                            if($monthday > $this->daysInMonth($monthstart, 1))
                                $monthday = $this->daysInMonth($monthstart, 1);    // Cap $monthday on month length (eg 28 feb instead of 29 feb)
                            $daynow = $monthstart + ($monthday-1) * 24 * 60 * 60;
                            $this->processOccurrenceItem($items, $start, $end, $daynow, $this->recur["startocc"], $this->recur["endocc"], $this->tz, $remindersonly);
                        }
                        else if(isset($this->recur["nday"]) && isset($this->recur["weekdays"])) { // Nth [weekday] in month X of every N years

                            // Go the correct month
                            $monthnow = $now + $this->daysInMonth($now, $this->monthOfYear($this->recur["month"])) * 24 * 60 * 60;

                            // Find first matching weekday in this month
                            for($wday = 0; $wday < 7; $wday++)
                            {
                                $daynow = $monthnow + $wday * 60 * 60 * 24;
                                $nowtime = $this->gmtime($daynow); // Get the weekday of the current day

                                if($this->recur["weekdays"] & (1 << $nowtime["tm_wday"])) { // Selected ?
                                    $firstday = $wday;
                                    break;
                                }
                            }

                            // Same as above (monthly)
                            $daynow = $monthnow + ($firstday + ($this->recur["nday"]-1)*7) * 60 * 60 * 24;

                            while($this->monthStartOf($daynow) != $this->monthStartOf($monthnow)) {
                                $daynow -= 7 * 60 * 60 * 24;
                            }

                            $this->processOccurrenceItem($items, $start, $end, $daynow, $this->recur["startocc"], $this->recur["endocc"], $this->tz, $remindersonly);
                        } else if ($this->recur['regen']) {
                            $year_starttime = $this->gmtime($now);
                            $is_next_leapyear = $this->isLeapYear($year_starttime['tm_year'] + 1900 + 1);    // +1 next year
                            $now = $daystart + ($is_next_leapyear ? 31622400 /* Leap year in seconds */ : 31536000 /*year in seconds*/);

                            if ($now <= $dayend) {
                                $this->processOccurrenceItem($items, $daystart, $end, $now, $this->recur["startocc"], $this->recur["endocc"], $this->tz, $remindersonly);
                            }
                        }
                    }
                }
                //to get all exception items
                if (!empty($this->recur['changed_occurences']))
                    $this->processExceptionItems($items, $start, $end);
            }

            // sort items on starttime
            usort($items, array($this, "sortStarttime"));

            // Return the MAPI-compatible list of items for this object
            return $items;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::getMonthInSeconds ( year,
month 
) [inherited]

Definition at line 1451 of file class.baserecurrence.php.

        {
            if( in_array($month, array(1,3,5,7,8,10,12) ) ) {
                $day = 31;
            } else if( in_array($month, array(4,6,9,11) ) ) {
                $day = 30;
            } else {
                $day = 28;
                if( $this->isLeapYear($year) == 1 )
                    $day++;
            }
            return $day * 24 * 60 * 60;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

This function returns the next remindertime starting from $timestamp When no next reminder exists, false is returned.

Note: Before saving this new reminder time (when snoozing), you must check for yourself if this reminder time is earlier than your snooze time, else use your snooze time and not this reminder time.

Get next item from now until forever, but max 1 item with reminder set Note 0x7ff00000 instead of 0x7fffffff because of possible overflow failures when converting to GMT.... Here for getting next 10 occurences assuming that next here we will be able to find nextreminder occurence in 10 occureneces

Loop through all reminder which we get in items variable and check whether the remindertime is greater than timestamp. On the first occurence of greater nextreminder break the loop and return the value to calling function.

Definition at line 494 of file class.recurrence.php.

        {
            $items = $this->getItems($timestamp, 0x7ff00000, 10, true);

            // Initially setting nextreminder to false so when no next reminder exists, false is returned.
            $nextreminder = false;
            for($i = 0, $len = count($items); $i < $len; $i++)
            {
                $item = $items[$i];
                $tempnextreminder = $item[$this->proptags["startdate"]] - ( $item[$this->proptags["reminder_minutes"]] * 60 );

                // If tempnextreminder is greater than timestamp then save it in nextreminder and break from the loop.
                if($tempnextreminder > $timestamp)
                {
                    $nextreminder = $tempnextreminder;
                    break;
                }
            }
            return $nextreminder;
        }

Here is the call graph for this function:

Recurrence::getOccurenceEnd ( basedate)

Definition at line 482 of file class.recurrence.php.

                                             {
            return $this->getOccurrenceEnd($basedate);
        }

Here is the call graph for this function:

Definition at line 479 of file class.recurrence.php.

                                               {
            return $this->getOccurrenceStart($basedate);
        }

Here is the call graph for this function:

Definition at line 472 of file class.recurrence.php.

                                              {
            $daystart = $this->dayStartOf($basedate);
            return $this->toGMT($this->tz, $daystart + $this->recur["endocc"] * 60);
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 467 of file class.recurrence.php.

                                                {
            $daystart = $this->dayStartOf($basedate);
            return $this->toGMT($this->tz, $daystart + $this->recur["startocc"] * 60);
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 118 of file class.baserecurrence.php.

        {
            return $this->recur;
        }
BaseRecurrence::getTimezone ( tz,
date 
) [inherited]

getTimezone gives the timezone offset (in minutes) of the given local date/time according to the given TZ info

Definition at line 1503 of file class.baserecurrence.php.

        {
            // No timezone -> GMT (+0)
            if(!isset($tz["timezone"]))
                return 0;

            $dst = false;
            $gmdate = $this->gmtime($date);

            $dststart = $this->getDateByYearMonthWeekDayHour($gmdate["tm_year"], $tz["dststartmonth"], $tz["dststartweek"], 0, $tz["dststarthour"]);
            $dstend = $this->getDateByYearMonthWeekDayHour($gmdate["tm_year"], $tz["dstendmonth"], $tz["dstendweek"], 0, $tz["dstendhour"]);

            if($dststart <= $dstend) {
                // Northern hemisphere, eg DST is during Mar-Oct
                if($date > $dststart && $date < $dstend) {
                    $dst = true;
                }
            } else {
                // Southern hemisphere, eg DST is during Oct-Mar
                if($date < $dstend || $date > $dststart) {
                    $dst = true;
                }
            }

            if($dst) {
                return $tz["timezone"] + $tz["timezonedst"];
            } else {
                return $tz["timezone"];
            }
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::getTimezoneData ( tz) [inherited]

Definition at line 1558 of file class.baserecurrence.php.

        {
            $data = pack("lllllvvllvlvvlv", $tz["timezone"], 0, $tz["timezonedst"], 0, $tz["dstendmonth"], $tz["dstendweek"], $tz["dstendhour"], 0, 0, 0, $tz["dststartmonth"], $tz["dststartweek"], $tz["dststarthour"], 0 ,0);

            return $data;
        }

Here is the caller graph for this function:

BaseRecurrence::GetTZOffset ( ts) [inherited]

gmtime() doesn't exist in standard PHP, so we have to implement it ourselves

Author:
Steve Hardy

Definition at line 1420 of file class.baserecurrence.php.

        {
            $Offset = date("O", $ts);

            $Parity = $Offset < 0 ? -1 : 1;
            $Offset = $Parity * $Offset;
            $Offset = ($Offset - ($Offset % 100)) / 100 * 60 + $Offset % 100;

            return $Parity * $Offset;
        }

Here is the caller graph for this function:

BaseRecurrence::getWeekNr ( date) [inherited]

getWeekNr() returns the week nr of the month (ie first week of february is 1)

Definition at line 1537 of file class.baserecurrence.php.

        {
            $gmdate = gmtime($date);
            $gmdate["tm_mday"] = 0;
            return strftime("%W", $date) - strftime("%W", gmmktime($gmdate)) + 1;
        }

Here is the call graph for this function:

BaseRecurrence::gmtime ( time) [inherited]

gmtime() doesn't exist in standard PHP, so we have to implement it ourselves

Author:
Steve Hardy
Parameters:
Date$time
Returns:
Date GMT Time

Definition at line 1437 of file class.baserecurrence.php.

        {
            $TZOffset = $this->GetTZOffset($time);

            $t_time = $time - $TZOffset * 60; #Counter adjust for localtime()
            $t_arr = localtime($t_time, 1);

            return $t_arr;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Returns TRUE if there is a DELETE exception on the given base date.

Definition at line 955 of file class.recurrence.php.

        {
            // Check if the occurrence is deleted on the specified date
            foreach($this->recur["deleted_occurences"] as $deleted)
            {
                if($this->isSameDay($deleted, $basedate))
                    return true;
            }

            return false;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Recurrence::isException ( basedate)

Function which verifies if on the given date an exception, delete or change, occurs.

Parameters:
date$datethe date
Returns:
array the exception, true - if an occurrence is deleted on the given date, false - no exception occurs on the given date

Definition at line 941 of file class.recurrence.php.

        {
            if($this->isDeleteException($basedate))
                return true;

            if($this->getChangeException($basedate) != false)
                return true;

            return false;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::isLeapYear ( year) [inherited]

Definition at line 1447 of file class.baserecurrence.php.

                                   {
            return ( $year % 4 == 0 && ($year % 100 != 0 || $year % 400 == 0) );
        }

Here is the caller graph for this function:

Recurrence::isSameDay ( date1,
date2 
)

Function to see if two dates are on the same day.

Parameters:
date$time1date 1
date$time2date 2
Returns:
boolean Returns TRUE when both dates are on the same day

Definition at line 988 of file class.recurrence.php.

        {
            $time1 = $this->gmtime($date1);
            $time2 = $this->gmtime($date2);

            return $time1["tm_mon"] == $time2["tm_mon"] && $time1["tm_year"] == $time2["tm_year"] && $time1["tm_mday"] == $time2["tm_mday"];
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Recurrence::isValidExceptionDate ( basedate,
start 
)

Definition at line 367 of file class.recurrence.php.

        {
            // The way we do this is to look at the days that we're 'moving' the item in the exception. Each
            // of these days may only contain the item that we're modifying. Any other item violates the rules.

            if($this->isException($basedate)) {
                // If we're modifying an exception, we want to look at the days that we're 'moving' compared to where
                // the exception used to be.
                $oldexception = $this->getChangeException($basedate);
                $prevday = $this->dayStartOf($oldexception["start"]);
            } else {
                // If its a new exception, we want to look at the original placement of this item.
                $prevday = $basedate;
            }

            $startday = $this->dayStartOf($start);

            // Get all the occurrences on the days between the basedate (may be reversed)
            if($prevday < $startday)
                $items = $this->getItems($this->toGMT($this->tz, $prevday), $this->toGMT($this->tz, $startday + 24 * 60 * 60));
            else
                $items = $this->getItems($this->toGMT($this->tz, $startday), $this->toGMT($this->tz, $prevday + 24 * 60 * 60));

            // There should now be exactly one item, namely the item that we are modifying. If there are any other items in the range,
            // then we abort the change, since one of the rules has been violated.
            return count($items) == 1;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Recurrence::isValidReminderTime ( basedate,
reminderminutes,
startdate 
)

Check to see if the exception proposed at a certain basedate is allowed concerning reminder times:

Both must be true:

  • reminder time of this item is not before the starttime of the previous recurring item
  • reminder time of the next item is not before the starttime of this item
Parameters:
date$basedatethe base date of the exception (LOCAL time of non-exception occurrence)
string$reminderminutesreminder minutes which is set of the item
date$startdatethe startdate of the selected item
Returns:
boolean if the reminder minutes value valid (FALSE if either of the rules above are FALSE)

Definition at line 407 of file class.recurrence.php.

        {
            $isreminderrangeset = false;

            // get all occurence items before the seleceted items occurence starttime
            $occitems = $this->getItems($this->messageprops[$this->proptags["startdate"]], $this->toGMT($this->tz, $basedate));

            if(!empty($occitems)) {
                // as occitems array is sorted in ascending order of startdate, to get the previous occurence we take the last items in occitems .
                $previousitem_startdate = $occitems[count($occitems) - 1][$this->proptags["startdate"]];

                // if our reminder is set before or equal to the beginning of the previous occurrence, then that's not allowed
                if($startdate - ($reminderminutes*60) <= $previousitem_startdate)
                    return false;
            }

            // Get the endtime of the current occurrence and find the next two occurrences (including the current occurrence)
            $currentOcc = $this->getItems($this->toGMT($this->tz, $basedate), 0x7ff00000, 2, true);

            // If there are another two occurrences, then the first is the current occurrence, and the one after that
            // is the next occurrence.
            if(count($currentOcc) > 1) {
                $next = $currentOcc[1];
                // Get reminder time of the next occurrence.
                $nextOccReminderTime = $next[$this->proptags["startdate"]] - ($next[$this->proptags["reminder_minutes"]] * 60);
                // If the reminder time of the next item is before the start of this item, then that's not allowed
                if($nextOccReminderTime <= $startdate)
                    return false;
            }

            // All was ok
            return true;
        }

Here is the call graph for this function:

Recurrence::modifyException ( exception_props,
base_date,
exception_recips = array(),
copy_attach_from = false 
)

Modifies an existing exception, but only updates the given properties NOTE: You can't remove properites from an exception, only add new ones.

Definition at line 255 of file class.recurrence.php.

        {
            if(isset($exception_props[$this->proptags["startdate"]]) && !$this->isValidExceptionDate($base_date, $this->fromGMT($this->tz, $exception_props[$this->proptags["startdate"]]))) {
                return false;
            }

            $baseday = $this->dayStartOf($base_date);
            $basetime = $baseday + $this->recur["startocc"] * 60;
            $extomodify = false;

            for($i = 0, $len = count($this->recur["changed_occurences"]); $i < $len; $i++) {
                if($this->isSameDay($this->recur["changed_occurences"][$i]["basedate"], $baseday))
                    $extomodify = &$this->recur["changed_occurences"][$i];
            }

            if(!$extomodify)
                return false;

            // remove basedate property as we want to preserve the old value
            // client will send basedate with time part as zero, so discard that value
            unset($exception_props[$this->proptags["basedate"]]);

            if(array_key_exists($this->proptags["startdate"], $exception_props)) {
                $extomodify["start"] = $this->fromGMT($this->tz, $exception_props[$this->proptags["startdate"]]);
            }

            if(array_key_exists($this->proptags["duedate"], $exception_props)) {
                $extomodify["end"] =   $this->fromGMT($this->tz, $exception_props[$this->proptags["duedate"]]);
            }

            if(array_key_exists($this->proptags["subject"], $exception_props)) {
                $extomodify["subject"] = $exception_props[$this->proptags["subject"]];
            }

            if(array_key_exists($this->proptags["location"], $exception_props)) {
                $extomodify["location"] = $exception_props[$this->proptags["location"]];
            }

            if(array_key_exists($this->proptags["label"], $exception_props)) {
                $extomodify["label"] = $exception_props[$this->proptags["label"]];
            }

            if(array_key_exists($this->proptags["reminder"], $exception_props)) {
                $extomodify["reminder_set"] = $exception_props[$this->proptags["reminder"]];
            }

            if(array_key_exists($this->proptags["reminder_minutes"], $exception_props)) {
                $extomodify["remind_before"] = $exception_props[$this->proptags["reminder_minutes"]];
            }

            if(array_key_exists($this->proptags["alldayevent"], $exception_props)) {
                $extomodify["alldayevent"] = $exception_props[$this->proptags["alldayevent"]];
            }

            if(array_key_exists($this->proptags["busystatus"], $exception_props)) {
                $extomodify["busystatus"] = $exception_props[$this->proptags["busystatus"]];
            }

            $exception_props[PR_MESSAGE_CLASS] = "IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}";

            // synchronize commonstart/commonend with startdate/duedate
            if(isset($exception_props[$this->proptags["startdate"]])) {
                $exception_props[$this->proptags["commonstart"]] = $exception_props[$this->proptags["startdate"]];
            }

            if(isset($exception_props[$this->proptags["duedate"]])) {
                $exception_props[$this->proptags["commonend"]] = $exception_props[$this->proptags["duedate"]];
            }

            $attach = $this->getExceptionAttachment($baseday);
            if(!$attach) {
                if ($copy_attach_from) {
                    $this->deleteExceptionAttachment($base_date);
                    $this->createException($exception_props, $base_date, false, $exception_recips, $copy_attach_from);
                } else {
                    $this->createExceptionAttachment($exception_props, $exception_recips, $copy_attach_from);
                }
            } else {
                $message = mapi_attach_openobj($attach, MAPI_MODIFY);

                // Set exception properties on embedded message and save
                mapi_setprops($message, $exception_props);
                $this->setExceptionRecipients($message, $exception_recips, false);
                mapi_savechanges($message);

                // If a new start or duedate is provided, we update the properties 'PR_EXCEPTION_STARTTIME' and 'PR_EXCEPTION_ENDTIME'
                // on the attachment which holds the embedded msg and save everything.
                $props = array();
                if (isset($exception_props[$this->proptags["startdate"]])) {
                    $props[PR_EXCEPTION_STARTTIME] = $this->fromGMT($this->tz, $exception_props[$this->proptags["startdate"]]);
                }
                if (isset($exception_props[$this->proptags["duedate"]])) {
                    $props[PR_EXCEPTION_ENDTIME] = $this->fromGMT($this->tz, $exception_props[$this->proptags["duedate"]]);
                }
                if (!empty($props)) {
                    mapi_setprops($attach, $props);
                }

                mapi_savechanges($attach);
            }

            // Save recurrence data to message
            $this->saveRecurrence();

            return true;
        }

Here is the call graph for this function:

BaseRecurrence::monthOfYear ( minutes) [inherited]

Definition at line 1930 of file class.baserecurrence.php.

                                       {
            $d = gmmktime(0,0,0,1,1,2001); // The year 2001 was a non-leap year, and the minutes provided are always in non-leap-year-minutes

            $d += $minutes*60;

            $dtime = $this->gmtime($d);

            return $dtime["tm_mon"];
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::monthStartOf ( date) [inherited]

Function to get timestamp of the beginning of the month of the timestamp given.

Parameters:
date$date
Returns:
date Timestamp referring to same month but on the first day, and at 00:00:00

Definition at line 1623 of file class.baserecurrence.php.

        {
            $time1 = $this->gmtime($date);

            return gmmktime(0, 0, 0, $time1["tm_mon"] + 1, 1, $time1["tm_year"] + 1900);
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::parseRecurrence ( rdata) [inherited]

Function for parsing the Recurrence value of a Calendar item.

Retrieve it from Named Property 0x8216 as a PT_BINARY and pass the data to this function

Returns a structure containing the data:

type - type of recurrence: day=10, week=11, month=12, year=13 subtype - type of day recurrence: 2=monthday (ie 21st day of month), 3=nday'th weekdays (ie. 2nd Tuesday and Wednesday) start - unix timestamp of first occurrence end - unix timestamp of last occurrence (up to and including), so when start == end -> occurrences = 1 numoccur - occurrences (may be very large when there is no end data)

then, for each type:

Daily: everyn - every [everyn] days in minutes regen - regenerating event (like tasks)

Weekly: everyn - every [everyn] weeks in weeks regen - regenerating event (like tasks) weekdays - bitmask of week days, where each bit is one weekday (weekdays & 1 = Sunday, weekdays & 2 = Monday, etc)

Monthly: everyn - every [everyn] months regen - regenerating event (like tasks)

subtype 2: monthday - on day [monthday] of the month

subtype 3: weekdays - bitmask of week days, where each bit is one weekday (weekdays & 1 = Sunday, weekdays & 2 = Monday, etc) nday - on [nday]'th [weekdays] of the month

Yearly: everyn - every [everyn] months (12, 24, 36, ...) month - in month month regen - regenerating event (like tasks)

subtype 2: monthday - on day [monthday] of the month

subtype 3: weekdays - bitmask of week days, where each bit is one weekday (weekdays & 1 = Sunday, weekdays & 2 = Monday, etc) nday - on [nday]'th [weekdays] of the month [month]

Parameters:
string$rdataBinary string
Returns:
array recurrence data.

We now have $exc_changed, $exc_base_dates and $exc_changed_details We will ignore $exc_changed, as this information is available in $exc_changed_details also. If an item is in $exc_base_dates and NOT in $exc_changed_details, then the item has been deleted.

Definition at line 190 of file class.baserecurrence.php.

        {
            if (strlen($rdata) < 10) {
                return;
            }

            $ret["changed_occurences"] = array();
            $ret["deleted_occurences"] = array();

            $data = unpack("Vconst1/Crtype/Cconst2/Vrtype2", $rdata);

            $ret["type"] = $data["rtype"];
            $ret["subtype"] = $data["rtype2"];
            $rdata = substr($rdata, 10);

            switch ($data["rtype"])
            {
                case 0x0a:
                    // Daily
                    if (strlen($rdata) < 12) {
                        return $ret;
                    }

                    $data = unpack("Vunknown/Veveryn/Vregen", $rdata);
                    $ret["everyn"] = $data["everyn"];
                    $ret["regen"] = $data["regen"];

                    switch($ret["subtype"])
                    {
                        case 0:
                            $rdata = substr($rdata, 12);
                            break;
                        case 1:
                            $rdata = substr($rdata, 16);
                            break;
                    }

                    break;

                case 0x0b:
                    // Weekly
                    if (strlen($rdata) < 16) {
                        return $ret;
                    }

                    $data = unpack("Vconst1/Veveryn/Vregen", $rdata);
                    $rdata = substr($rdata, 12);

                    $ret["everyn"] = $data["everyn"];
                    $ret["regen"] = $data["regen"];
                    $ret["weekdays"] = 0;

                    if ($data["regen"] == 0) {
                        $data = unpack("Vweekdays", $rdata);
                        $rdata = substr($rdata, 4);

                        $ret["weekdays"] = $data["weekdays"];
                    }
                    break;

                case 0x0c:
                    // Monthly
                    if (strlen($rdata) < 16) {
                        return $ret;
                    }

                    $data = unpack("Vconst1/Veveryn/Vregen/Vmonthday", $rdata);

                    $ret["everyn"] = $data["everyn"];
                    $ret["regen"] = $data["regen"];

                    if ($ret["subtype"] == 3) {
                        $ret["weekdays"] = $data["monthday"];
                    } else {
                        $ret["monthday"] = $data["monthday"];
                    }

                    $rdata = substr($rdata, 16);

                    if ($ret["subtype"] == 3) {
                        $data = unpack("Vnday", $rdata);
                        $ret["nday"] = $data["nday"];
                        $rdata = substr($rdata, 4);
                    }
                    break;

                case 0x0d:
                    // Yearly
                    if (strlen($rdata) < 16)
                        return $ret;

                    $data = unpack("Vmonth/Veveryn/Vregen/Vmonthday", $rdata);

                    $ret["month"] = $data["month"];
                    $ret["everyn"] = $data["everyn"];
                    $ret["regen"] = $data["regen"];

                    if ($ret["subtype"] == 3) {
                        $ret["weekdays"] = $data["monthday"];
                    } else {
                        $ret["monthday"] = $data["monthday"];
                    }

                    $rdata = substr($rdata, 16);

                    if ($ret["subtype"] == 3) {
                        $data = unpack("Vnday", $rdata);
                        $ret["nday"] = $data["nday"];
                        $rdata = substr($rdata, 4);
                    }
                    break;
            }

            if (strlen($rdata) < 16) {
                return $ret;
            }

            $data = unpack("Cterm/C3const1/Vnumoccur/Vconst2/Vnumexcept", $rdata);

            $rdata = substr($rdata, 16);

            $ret["term"] = $data["term"];
            $ret["numoccur"] = $data["numoccur"];
            $ret["numexcept"] = $data["numexcept"];

            // exc_base_dates are *all* the base dates that have been either deleted or modified
            $exc_base_dates = array();
            for($i = 0; $i < $ret["numexcept"]; $i++)
            {
                if (strlen($rdata) < 4) {
                    // We shouldn't arrive here, because that implies
                    // numexcept does not match the amount of data
                    // which is available for the exceptions.
                    return $ret;
                }
                $data = unpack("Vbasedate", $rdata);
                $rdata = substr($rdata, 4);
                $exc_base_dates[] = $this->recurDataToUnixData($data["basedate"]);
            }

            if (strlen($rdata) < 4) {
                return $ret;
            }

            $data = unpack("Vnumexceptmod", $rdata);
            $rdata = substr($rdata, 4);

            $ret["numexceptmod"] = $data["numexceptmod"];

            // exc_changed are the base dates of *modified* occurrences. exactly what is modified
            // is in the attachments *and* in the data further down this function.
            $exc_changed = array();
            for($i = 0; $i < $ret["numexceptmod"]; $i++)
            {
                if (strlen($rdata) < 4) {
                    // We shouldn't arrive here, because that implies
                    // numexceptmod does not match the amount of data
                    // which is available for the exceptions.
                    return $ret;
                }
                $data = unpack("Vstartdate", $rdata);
                $rdata = substr($rdata, 4);
                $exc_changed[] = $this->recurDataToUnixData($data["startdate"]);
            }

            if (strlen($rdata) < 8) {
                return $ret;
            }

            $data = unpack("Vstart/Vend", $rdata);
            $rdata = substr($rdata, 8);

            $ret["start"] = $this->recurDataToUnixData($data["start"]);
            $ret["end"] = $this->recurDataToUnixData($data["end"]);

            // this is where task recurrence stop
            if (strlen($rdata) < 16) {
                return $ret;
            }

            $data = unpack("Vreaderversion/Vwriterversion/Vstartmin/Vendmin", $rdata);
            $rdata = substr($rdata, 16);

            $ret["startocc"] = $data["startmin"];
            $ret["endocc"] = $data["endmin"];
            $readerversion = $data["readerversion"];
            $writerversion = $data["writerversion"];

            $data = unpack("vnumber", $rdata);
            $rdata = substr($rdata, 2);

            $nexceptions = $data["number"];
            $exc_changed_details = array();

            // Parse n modified exceptions
            for($i=0;$i<$nexceptions;$i++)
            {
                $item = array();

                // Get exception startdate, enddate and basedate (the date at which the occurrence would have started)
                $data = unpack("Vstartdate/Venddate/Vbasedate", $rdata);
                $rdata = substr($rdata, 12);

                // Convert recurtimestamp to unix timestamp
                $startdate = $this->recurDataToUnixData($data["startdate"]);
                $enddate = $this->recurDataToUnixData($data["enddate"]);
                $basedate = $this->recurDataToUnixData($data["basedate"]);

                // Set the right properties
                $item["basedate"] = $this->dayStartOf($basedate);
                $item["start"] = $startdate;
                $item["end"] = $enddate;

                $data = unpack("vbitmask", $rdata);
                $rdata = substr($rdata, 2);
                $item["bitmask"] = $data["bitmask"]; // save bitmask for extended exceptions

                // Bitmask to verify what properties are changed
                $bitmask = $data["bitmask"];

                // ARO_SUBJECT: 0x0001
                // Look for field: SubjectLength (2b), SubjectLength2 (2b) and Subject
                if(($bitmask &(1 << 0))) {
                    $data = unpack("vnull_length/vlength", $rdata);
                    $rdata = substr($rdata, 4);

                    $length = $data["length"];
                    $item["subject"] = ""; // Normalized subject
                    for($j = 0; $j < $length && strlen($rdata); $j++)
                    {
                        $data = unpack("Cchar", $rdata);
                        $rdata = substr($rdata, 1);

                        $item["subject"] .= chr($data["char"]);
                    }
                }

                // ARO_MEETINGTYPE: 0x0002
                if(($bitmask &(1 << 1))) {
                    $rdata = substr($rdata, 4);
                    // Attendees modified: no data here (only in attachment)
                }

                // ARO_REMINDERDELTA: 0x0004
                // Look for field: ReminderDelta (4b)
                if(($bitmask &(1 << 2))) {
                    $data = unpack("Vremind_before", $rdata);
                    $rdata = substr($rdata, 4);

                    $item["remind_before"] = $data["remind_before"];
                }

                // ARO_REMINDER: 0x0008
                // Look field: ReminderSet (4b)
                if(($bitmask &(1 << 3))) {
                    $data = unpack("Vreminder_set", $rdata);
                    $rdata = substr($rdata, 4);

                    $item["reminder_set"] = $data["reminder_set"];
                }

                // ARO_LOCATION: 0x0010
                // Look for fields: LocationLength (2b), LocationLength2 (2b) and Location
                // Similar to ARO_SUBJECT above.
                if(($bitmask &(1 << 4))) {
                    $data = unpack("vnull_length/vlength", $rdata);
                    $rdata = substr($rdata, 4);

                    $item["location"] = "";

                    $length = $data["length"];
                    $data = substr($rdata, 0, $length);
                    $rdata = substr($rdata, $length);

                    $item["location"] .= $data;
                }

                // ARO_BUSYSTATUS: 0x0020
                // Look for field: BusyStatus (4b)
                if(($bitmask &(1 << 5))) {
                    $data = unpack("Vbusystatus", $rdata);
                    $rdata = substr($rdata, 4);

                    $item["busystatus"] = $data["busystatus"];
                }

                // ARO_ATTACHMENT: 0x0040
                if(($bitmask &(1 << 6))) {
                    // no data: RESERVED
                    $rdata = substr($rdata, 4);
                }

                // ARO_SUBTYPE: 0x0080
                // Look for field: SubType (4b). Determines whether it is an allday event.
                if(($bitmask &(1 << 7))) {
                    $data = unpack("Vallday", $rdata);
                    $rdata = substr($rdata, 4);

                    $item["alldayevent"] = $data["allday"];
                }

                // ARO_APPTCOLOR: 0x0100
                // Look for field: AppointmentColor (4b)
                if(($bitmask &(1 << 8))) {
                    $data = unpack("Vlabel", $rdata);
                    $rdata = substr($rdata, 4);

                    $item["label"] = $data["label"];
                }

                // ARO_EXCEPTIONAL_BODY: 0x0200
                if(($bitmask &(1 << 9))) {
                    // Notes or Attachments modified: no data here (only in attachment)
                }

                array_push($exc_changed_details, $item);
            }

            // Find deleted occurrences
            $deleted_occurences = array();

            foreach($exc_base_dates as $base_date) {
                $found = false;

                foreach($exc_changed_details as $details) {
                    if($details["basedate"] == $base_date) {
                        $found = true;
                        break;
                    }
                }
                if(! $found) {
                    // item was not in exc_changed_details, so it must be deleted
                    $deleted_occurences[] = $base_date;
                }
            }

            $ret["deleted_occurences"] = $deleted_occurences;
            $ret["changed_occurences"] = $exc_changed_details;

            // enough data for normal exception (no extended data)
            if (strlen($rdata) < 16) {
                return $ret;
            }

            $data = unpack("Vreservedsize", $rdata);
            $rdata = substr($rdata, 4 + $data["reservedsize"]);

            for($i=0;$i<$nexceptions;$i++)
            {
                // subject and location in ucs-2 to utf-8
                if ($writerversion >= 0x3009) {
                    $data = unpack("Vsize/Vvalue", $rdata); // size includes sizeof(value)==4
                    $rdata = substr($rdata, 4 + $data["size"]);
                }

                $data = unpack("Vreservedsize", $rdata);
                $rdata = substr($rdata, 4 + $data["reservedsize"]);

                // ARO_SUBJECT(0x01) | ARO_LOCATION(0x10)
                if ($exc_changed_details[$i]["bitmask"] & 0x11) {
                    $data = unpack("Vstart/Vend/Vorig", $rdata);
                    $rdata = substr($rdata, 4 * 3);

                    $exc_changed_details[$i]["ex_start_datetime"] = $data["start"];
                    $exc_changed_details[$i]["ex_end_datetime"] = $data["end"];
                    $exc_changed_details[$i]["ex_orig_date"] = $data["orig"];
                }

                // ARO_SUBJECT
                if ($exc_changed_details[$i]["bitmask"] & 0x01) {
                    // decode ucs2 string to utf-8
                    $data = unpack("vlength", $rdata);
                    $rdata = substr($rdata, 2);
                    $length = $data["length"];
                    $data = substr($rdata, 0, $length * 2);
                    $rdata = substr($rdata, $length * 2);
                    $subject = iconv("UCS-2LE", "UTF-8", $data);
                    // replace subject with unicode subject
                    $exc_changed_details[$i]["subject"] = $subject;
                }

                // ARO_LOCATION
                if ($exc_changed_details[$i]["bitmask"] & 0x10) {
                    // decode ucs2 string to utf-8
                    $data = unpack("vlength", $rdata);
                    $rdata = substr($rdata, 2);
                    $length = $data["length"];
                    $data = substr($rdata, 0, $length * 2);
                    $rdata = substr($rdata, $length * 2);
                    $location = iconv("UCS-2LE", "UTF-8", $data);
                    // replace subject with unicode subject
                    $exc_changed_details[$i]["location"] = $location;
                }

                // ARO_SUBJECT(0x01) | ARO_LOCATION(0x10)
                if ($exc_changed_details[$i]["bitmask"] & 0x11) {
                    $data = unpack("Vreservedsize", $rdata);
                    $rdata = substr($rdata, 4 + $data["reservedsize"]);
                }
            }

            // update with extended data
            $ret["changed_occurences"] = $exc_changed_details;

            return $ret;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::parseTimezone ( data) [inherited]

parseTimezone parses the timezone as specified in named property 0x8233 in Outlook calendar messages.

Returns the timezone in minutes negative offset (GMT +2:00 -> -120)

Definition at line 1549 of file class.baserecurrence.php.

        {
            if(strlen($data) < 48)
                return;

            $tz = unpack("ltimezone/lunk/ltimezonedst/lunk/ldstendmonth/vdstendweek/vdstendhour/lunk/lunk/vunk/ldststartmonth/vdststartweek/vdststarthour/lunk/vunk", $data);
            return $tz;
        }

Here is the caller graph for this function:

Recurrence::processExceptionItems ( &$  items,
start,
end 
)

processExceptionItem, adds an all exception item to a list of occurrences, without any constraint on timeframe

Parameters:
array$itemsreference to the array to be added to
date$startstart of timeframe in GMT TIME
date$endend of timeframe in GMT TIME

Definition at line 916 of file class.recurrence.php.

        {
            $limit = 0;
            foreach($this->recur["changed_occurences"] as $exception) {

                // Convert to GMT
                $occstart = $this->toGMT($this->tz, $exception["start"]);
                $occend = $this->toGMT($this->tz, $exception["end"]);

                // Check range criterium. Exact matches (eg when $occstart == $end), do NOT match since you cannot
                // see any part of the appointment. Partial overlaps DO match.
                if($occstart >= $end || $occend <= $start)
                    continue;

                array_push($items, $this->getExceptionProperties($exception));
                if($limit && (count($items) == $limit))
                    break;
                }
        }

Here is the call graph for this function:

Recurrence::processOccurrenceItem ( &$  items,
start,
end,
basedate,
startocc,
endocc,
tz,
reminderonly 
)

processOccurrenceItem, adds an item to a list of occurrences, but only if the following criteria are met:

  • The resulting occurrence (or exception) starts or ends in the interval <$start, $end>
  • The ocurrence isn't specified as a deleted occurrence
    Parameters:
    array$itemsreference to the array to be added to
    date$startstart of timeframe in GMT TIME
    date$endend of timeframe in GMT TIME
    date$basedate(hour/sec/min assumed to be 00:00:00) in LOCAL TIME OF THE OCCURRENCE
    int$startoccstart of occurrence since beginning of day in minutes
    int$endoccend of occurrence since beginning of day in minutes
    int$tzthe timezone info for this occurrence ( applied to $basedate / $startocc / $endocc )
    bool$reminderonlyIf TRUE, only add the item if the reminder is set

FIRST PART : Check range criterium. Exact matches (eg when $occstart == $end), do NOT match since you cannot see any part of the appointment. Partial overlaps DO match.

SECOND PART : check if occurence is not a zero duration occurrence which starts at 00:00 and ends on 00:00. if it is so, then process the occurrence and send it in response.

Definition at line 869 of file class.recurrence.php.

        {
            $exception = $this->isException($basedate);
            if($exception){
                return false;
            }else{
                $occstart = $basedate + $startocc * 60;
                $occend = $basedate + $endocc * 60;

                // Convert to GMT
                $occstart = $this->toGMT($tz, $occstart);
                $occend = $this->toGMT($tz, $occend);

                if(($occstart  >= $end || $occend <=  $start) && !($occstart == $occend && $occstart == $start))
                    return;

                // Properties for this occurrence are the same as the main object,
                // With these properties overridden
                $newitem = $this->messageprops;
                $newitem[$this->proptags["startdate"]] = $occstart;
                $newitem[$this->proptags["duedate"]] = $occend;
                $newitem[$this->proptags["commonstart"]] = $occstart;
                $newitem[$this->proptags["commonend"]] = $occend;
                $newitem["basedate"] = $basedate;
            }

            // If reminderonly is set, only add reminders
            if($reminderonly && (!isset($newitem[$this->proptags["reminder"]]) || $newitem[$this->proptags["reminder"]] == false))
                return;

            $items[] = $newitem;
        }

Here is the call graph for this function:

BaseRecurrence::recurDataToUnixData ( rdate) [inherited]

Function which converts a recurrence date timestamp to an unix date timestamp.

Author:
Steve Hardy
Parameters:
Int$rdatethe date which will be converted
Returns:
Int the converted date

Definition at line 1400 of file class.baserecurrence.php.

        {
            return ($rdate - 194074560) * 60 ;
        }

Here is the caller graph for this function:

Recurrence::Recurrence ( store,
message 
)

Constructor.

Parameters:
resource$storeMAPI Message Store Object
resource$messagethe MAPI (appointment) message

Definition at line 97 of file class.recurrence.php.

        {

            $properties = array();
            $properties["entryid"] = PR_ENTRYID;
            $properties["parent_entryid"] = PR_PARENT_ENTRYID;
            $properties["message_class"] = PR_MESSAGE_CLASS;
            $properties["icon_index"] = PR_ICON_INDEX;
            $properties["subject"] = PR_SUBJECT;
            $properties["display_to"] = PR_DISPLAY_TO;
            $properties["importance"] = PR_IMPORTANCE;
            $properties["sensitivity"] = PR_SENSITIVITY;
            $properties["startdate"] = "PT_SYSTIME:PSETID_Appointment:0x820d";
            $properties["duedate"] = "PT_SYSTIME:PSETID_Appointment:0x820e";
            $properties["recurring"] = "PT_BOOLEAN:PSETID_Appointment:0x8223";
            $properties["recurring_data"] = "PT_BINARY:PSETID_Appointment:0x8216";
            $properties["busystatus"] = "PT_LONG:PSETID_Appointment:0x8205";
            $properties["label"] = "PT_LONG:PSETID_Appointment:0x8214";
            $properties["alldayevent"] = "PT_BOOLEAN:PSETID_Appointment:0x8215";
            $properties["private"] = "PT_BOOLEAN:PSETID_Common:0x8506";
            $properties["meeting"] = "PT_LONG:PSETID_Appointment:0x8217";
            $properties["startdate_recurring"] = "PT_SYSTIME:PSETID_Appointment:0x8235";
            $properties["enddate_recurring"] = "PT_SYSTIME:PSETID_Appointment:0x8236";
            $properties["recurring_pattern"] = "PT_STRING8:PSETID_Appointment:0x8232";
            $properties["location"] = "PT_STRING8:PSETID_Appointment:0x8208";
            $properties["duration"] = "PT_LONG:PSETID_Appointment:0x8213";
            $properties["responsestatus"] = "PT_LONG:PSETID_Appointment:0x8218";
            $properties["reminder"] = "PT_BOOLEAN:PSETID_Common:0x8503";
            $properties["reminder_minutes"] = "PT_LONG:PSETID_Common:0x8501";
            $properties["recurrencetype"] = "PT_LONG:PSETID_Appointment:0x8231";
            $properties["contacts"] = "PT_MV_STRING8:PSETID_Common:0x853a";
            $properties["contacts_string"] = "PT_STRING8:PSETID_Common:0x8586";
            $properties["categories"] = "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords";
            $properties["reminder_time"] = "PT_SYSTIME:PSETID_Common:0x8502";
            $properties["commonstart"] = "PT_SYSTIME:PSETID_Common:0x8516";
            $properties["commonend"] = "PT_SYSTIME:PSETID_Common:0x8517";
            $properties["basedate"] = "PT_SYSTIME:PSETID_Appointment:0x8228";
            $properties["timezone_data"] = "PT_BINARY:PSETID_Appointment:0x8233";
            $properties["timezone"] = "PT_STRING8:PSETID_Appointment:0x8234";
            $properties["flagdueby"] = "PT_SYSTIME:PSETID_Common:0x8560";
            $properties["side_effects"] = "PT_LONG:PSETID_Common:0x8510";
            $properties["hideattachments"] = "PT_BOOLEAN:PSETID_Common:0x8514";

            $this->proptags = getPropIdsFromStrings($store, $properties);

            parent::BaseRecurrence($store, $message);
        }

Here is the call graph for this function:

Saves the recurrence data to the recurrence property.

Parameters:
array$propertiesthe recurrence data.
Returns:
string binary string

Definition at line 609 of file class.baserecurrence.php.

        {
            // Only save if a message was passed
            if(!isset($this->message))
                return;

            // Abort if no recurrence was set
            if(!isset($this->recur["type"]) && !isset($this->recur["subtype"])) {
                return;
            }

            if(!isset($this->recur["start"]) && !isset($this->recur["end"])) {
                return;
            }

            if(!isset($this->recur["startocc"]) && !isset($this->recur["endocc"])) {
                return;
            }

            $rdata = pack("CCCCCCV", 0x04, 0x30, 0x04, 0x30, (int) $this->recur["type"], 0x20, (int) $this->recur["subtype"]);

            $weekstart = 1; //monday
            $forwardcount = 0;
            $restocc = 0;
            $dayofweek = (int) gmdate("w", (int) $this->recur["start"]); //0 (for Sunday) through 6 (for Saturday)

            $term = (int) $this->recur["type"];
            switch($term)
            {
                case 0x0A:
                    // Daily
                    if(!isset($this->recur["everyn"])) {
                        return;
                    }

                    if($this->recur["subtype"] == 1) {

                        // Daily every workday
                        $rdata .= pack("VVVV", (6 * 24 * 60), 1, 0, 0x3E);
                    } else {
                        // Daily every N days (everyN in minutes)

                        $everyn =  ((int) $this->recur["everyn"]) / 1440;

                        // Calc first occ
                        $firstocc = $this->unixDataToRecurData($this->recur["start"]) % ((int) $this->recur["everyn"]);

                        $rdata .= pack("VVV", $firstocc, (int) $this->recur["everyn"], $this->recur["regen"] ? 1 : 0);
                    }
                    break;
                case 0x0B:
                    // Weekly
                    if(!isset($this->recur["everyn"])) {
                        return;
                    }

                    if (!$this->recur["regen"] && !isset($this->recur["weekdays"])) {
                        return;
                    }

                    // No need to calculate startdate if sliding flag was set.
                    if (!$this->recur['regen']) {
                        // Calculate start date of recurrence

                        // Find the first day that matches one of the weekdays selected
                        $daycount = 0;
                        $dayskip = -1;
                        for($j = 0; $j < 7; $j++) {
                            if(((int) $this->recur["weekdays"]) & (1<<( ($dayofweek+$j)%7)) ) {
                                if($dayskip == -1)
                                    $dayskip = $j;

                                $daycount++;
                            }
                        }

                        // $dayskip is the number of days to skip from the startdate until the first occurrence
                        // $daycount is the number of days per week that an occurrence occurs

                        $weekskip = 0;
                        if(($dayofweek < $weekstart && $dayskip > 0) || ($dayofweek+$dayskip) > 6)
                            $weekskip = 1;

                        // Check if the recurrence ends after a number of occurences, in that case we must calculate the
                        // remaining occurences based on the start of the recurrence.
                        if (((int) $this->recur["term"]) == 0x22) {
                            // $weekskip is the amount of weeks to skip from the startdate before the first occurence
                            // $forwardcount is the maximum number of week occurrences we can go ahead after the first occurrence that
                            // is still inside the recurrence. We subtract one to make sure that the last week is never forwarded over
                            // (eg when numoccur = 2, and daycount = 1)
                            $forwardcount = floor( (int) ($this->recur["numoccur"] -1 ) / $daycount);

                            // $restocc is the number of occurrences left after $forwardcount whole weeks of occurrences, minus one
                            // for the occurrence on the first day
                            $restocc = ((int) $this->recur["numoccur"]) - ($forwardcount*$daycount) - 1;

                            // $forwardcount is now the number of weeks we can go forward and still be inside the recurrence
                            $forwardcount *= (int) $this->recur["everyn"];
                        }

                        // The real start is start + dayskip + weekskip-1 (since dayskip will already bring us into the next week)
                        $this->recur["start"] = ((int) $this->recur["start"]) + ($dayskip * 24*60*60)+ ($weekskip *(((int) $this->recur["everyn"]) - 1) * 7 * 24*60*60);
                    }

                    // Calc first occ
                    $firstocc = ($this->unixDataToRecurData($this->recur["start"]) ) % ( ((int) $this->recur["everyn"]) * 7 * 24 * 60);

                    $firstocc -= (((int) gmdate("w", (int) $this->recur["start"])) - 1) * 24 * 60;

                    if ($this->recur["regen"])
                        $rdata .= pack("VVV", $firstocc, (int) $this->recur["everyn"], 1);
                    else
                        $rdata .= pack("VVVV", $firstocc, (int) $this->recur["everyn"], 0, (int) $this->recur["weekdays"]);
                    break;
                case 0x0C:
                    // Monthly
                case 0x0D:
                    // Yearly
                    if(!isset($this->recur["everyn"])) {
                        return;
                    }
                    if($term == 0x0D /*yearly*/ && !isset($this->recur["month"])) {
                        return;
                    }

                    if($term == 0x0C /*monthly*/) {
                        $everyn = (int) $this->recur["everyn"];
                    }else {
                        $everyn = $this->recur["regen"] ? ((int) $this->recur["everyn"]) * 12 : 12;
                    }

                    // Get montday/month/year of original start
                    $curmonthday = gmdate("j", (int) $this->recur["start"] );
                    $curyear = gmdate("Y", (int) $this->recur["start"] );
                    $curmonth = gmdate("n", (int) $this->recur["start"] );

                    // Check if the recurrence ends after a number of occurences, in that case we must calculate the
                    // remaining occurences based on the start of the recurrence.
                    if (((int) $this->recur["term"]) == 0x22) {
                        // $forwardcount is the number of occurrences we can skip and still be inside the recurrence range (minus
                        // one to make sure there are always at least one occurrence left)
                        $forwardcount = ((((int) $this->recur["numoccur"])-1) * $everyn );
                    }

                    // Get month for yearly on D'th day of month M
                    if($term == 0x0D /*yearly*/) {
                        $selmonth = floor(((int) $this->recur["month"]) / (24 * 60 *29)) + 1; // 1=jan, 2=feb, eg
                    }

                    switch((int) $this->recur["subtype"])
                    {
                        // on D day of every M month
                        case 2:
                            if(!isset($this->recur["monthday"])) {
                                return;
                            }
                            // Recalc startdate

                            // Set on the right begin day

                            // Go the beginning of the month
                            $this->recur["start"] -= ($curmonthday-1) * 24*60*60;
                            // Go the the correct month day
                            $this->recur["start"] += (((int) $this->recur["monthday"])-1) * 24*60*60;

                            // If the previous calculation gave us a start date *before* the original start date, then we need to skip to the next occurrence
                            if ( ($term == 0x0C /*monthly*/ && ((int) $this->recur["monthday"]) < $curmonthday) ||
                                ($term == 0x0D /*yearly*/ &&( $selmonth < $curmonth || ($selmonth == $curmonth && ((int) $this->recur["monthday"]) < $curmonthday)) ))
                            {
                                if($term == 0x0D /*yearly*/)
                                    $count = ($everyn - ($curmonth - $selmonth)); // Yearly, go to next occurrence in 'everyn' months minus difference in first occurence and original date
                                else
                                    $count = $everyn; // Monthly, go to next occurrence in 'everyn' months

                                // Forward by $count months. This is done by getting the number of days in that month and forwarding that many days
                                for($i=0; $i < $count; $i++) {
                                    $this->recur["start"] += $this->getMonthInSeconds($curyear, $curmonth);

                                    if($curmonth == 12) {
                                        $curyear++;
                                        $curmonth = 0;
                                    }
                                    $curmonth++;
                                }
                            }

                            // "start" is now pointing to the first occurrence, except that it will overshoot if the
                            // month in which it occurs has less days than specified as the day of the month. So 31st
                            // of each month will overshoot in february (29 days). We compensate for that by checking
                            // if the day of the month we got is wrong, and then back up to the last day of the previous
                            // month.
                            if(((int) $this->recur["monthday"]) >=28 && ((int) $this->recur["monthday"]) <= 31 &&
                                gmdate("j", ((int) $this->recur["start"])) < ((int) $this->recur["monthday"]))
                            {
                                $this->recur["start"] -= gmdate("j", ((int) $this->recur["start"])) * 24 * 60 *60;
                            }

                            // "start" is now the first occurrence

                            if($term == 0x0C /*monthly*/) {
                                // Calc first occ
                                $monthIndex = ((((12%$everyn) * ((((int) gmdate("Y", $this->recur["start"])) - 1601)%$everyn)) % $everyn) + (((int) gmdate("n", $this->recur["start"])) - 1))%$everyn;

                                $firstocc = 0;
                                for($i=0; $i < $monthIndex; $i++) {
                                    $firstocc+= $this->getMonthInSeconds(1601 + floor($i/12), ($i%12)+1) / 60;
                                }

                                $rdata .= pack("VVVV", $firstocc, $everyn, $this->recur["regen"], (int) $this->recur["monthday"]);
                            } else{
                                // Calc first occ
                                $firstocc = 0;
                                $monthIndex = (int) gmdate("n", $this->recur["start"]);
                                for($i=1; $i < $monthIndex; $i++) {
                                    $firstocc+= $this->getMonthInSeconds(1601 + floor($i/12), $i) / 60;
                                }

                                $rdata .= pack("VVVV", $firstocc, $everyn, $this->recur["regen"], (int) $this->recur["monthday"]);
                            }
                            break;

                        case 3:
                            // monthly: on Nth weekday of every M month
                            // yearly: on Nth weekday of M month
                            if(!isset($this->recur["weekdays"]) && !isset($this->recur["nday"])) {
                                return;
                            }

                            $weekdays = (int) $this->recur["weekdays"];
                            $nday = (int) $this->recur["nday"];

                            // Calc startdate
                            $monthbegindow = (int) $this->recur["start"];

                            if($nday == 5) {
                                // Set date on the last day of the last month
                                $monthbegindow += (gmdate("t", $monthbegindow ) - gmdate("j", $monthbegindow )) * 24 * 60 * 60;
                            }else {
                                // Set on the first day of the month
                                $monthbegindow -= ((gmdate("j", $monthbegindow )-1) * 24 * 60 * 60);
                            }

                            if($term == 0x0D /*yearly*/) {
                                // Set on right month
                                if($selmonth < $curmonth)
                                    $tmp = 12 - $curmonth + $selmonth;
                                else
                                    $tmp = ($selmonth - $curmonth);

                                for($i=0; $i < $tmp; $i++) {
                                    $monthbegindow += $this->getMonthInSeconds($curyear, $curmonth);

                                    if($curmonth == 12) {
                                        $curyear++;
                                        $curmonth = 0;
                                    }
                                    $curmonth++;
                                }

                            }else {
                                // Check or you exist in the right month

                                for($i = 0; $i < 7; $i++) {
                                    if($nday == 5 && (1<<( (gmdate("w", $monthbegindow)-$i)%7) ) & $weekdays) {
                                        $day = gmdate("j", $monthbegindow) - $i;
                                        break;
                                    }else if($nday != 5 && (1<<( (gmdate("w", $monthbegindow )+$i)%7) ) & $weekdays) {
                                        $day = (($nday-1)*7) + ($i+1);
                                        break;
                                    }
                                }

                                // Goto the next X month
                                if(isset($day) && ($day < gmdate("j", (int) $this->recur["start"])) ) {
                                    if($nday == 5) {
                                        $monthbegindow += 24 * 60 * 60;
                                        if($curmonth == 12) {
                                            $curyear++;
                                            $curmonth = 0;
                                        }
                                        $curmonth++;
                                    }

                                    for($i=0; $i < $everyn; $i++) {
                                        $monthbegindow += $this->getMonthInSeconds($curyear, $curmonth);

                                        if($curmonth == 12) {
                                            $curyear++;
                                            $curmonth = 0;
                                        }
                                        $curmonth++;
                                    }

                                    if($nday == 5) {
                                        $monthbegindow -= 24 * 60 * 60;
                                    }
                                }
                            }

                            //FIXME: weekstart?

                            $day = 0;
                            // Set start on the right day
                            for($i = 0; $i < 7; $i++) {
                                if($nday == 5 && (1<<( (gmdate("w", $monthbegindow )-$i)%7) ) & $weekdays) {
                                    $day = $i;
                                    break;
                                }else if($nday != 5 && (1<<( (gmdate("w", $monthbegindow )+$i)%7) ) & $weekdays) {
                                    $day = ($nday - 1) * 7 + ($i+1);
                                    break;
                                }
                            }
                            if($nday == 5)
                                $monthbegindow -= $day * 24 * 60 *60;
                            else
                                $monthbegindow += ($day-1) * 24 * 60 *60;

                            $firstocc = 0;

                            if($term == 0x0C /*monthly*/) {
                                // Calc first occ
                                $monthIndex = ((((12%$everyn) * (((int) gmdate("Y", $this->recur["start"]) - 1601)%$everyn)) % $everyn) + (((int) gmdate("n", $this->recur["start"])) - 1))%$everyn;

                                for($i=0; $i < $monthIndex; $i++) {
                                    $firstocc+= $this->getMonthInSeconds(1601 + floor($i/12), ($i%12)+1) / 60;
                                }

                                $rdata .= pack("VVVVV", $firstocc, $everyn, 0, $weekdays, $nday);
                            } else {
                                // Calc first occ
                                $monthIndex = (int) gmdate("n", $this->recur["start"]);

                                for($i=1; $i < $monthIndex; $i++) {
                                    $firstocc+= $this->getMonthInSeconds(1601 + floor($i/12), $i) / 60;
                                }

                                $rdata .= pack("VVVVV", $firstocc, $everyn, 0, $weekdays, $nday);
                            }
                            break;
                    }
                    break;



            }

            if(!isset($this->recur["term"])) {
                return;
            }

            // Terminate
            $term = (int) $this->recur["term"];
            $rdata .= pack("CCCC", $term, 0x20, 0x00, 0x00);

            switch($term)
            {
                // After the given enddate
                case 0x21:
                    $rdata .= pack("V", 10);
                    break;
                // After a number of times
                case 0x22:
                    if(!isset($this->recur["numoccur"])) {
                        return;
                    }

                    $rdata .= pack("V", (int) $this->recur["numoccur"]);
                    break;
                // Never ends
                case 0x23:
                    $rdata .= pack("V", 0);
                    break;
            }

            // Strange little thing for the recurrence type "every workday"
            if(((int) $this->recur["type"]) == 0x0B && ((int) $this->recur["subtype"]) == 1) {
                $rdata .= pack("V", 1);
            } else { // Other recurrences
                $rdata .= pack("V", 0);
            }

            // Exception data

            // Get all exceptions
            $deleted_items = $this->recur["deleted_occurences"];
            $changed_items = $this->recur["changed_occurences"];

            // Merge deleted and changed items into one list
            $items = $deleted_items;

            foreach($changed_items as $changed_item)
                array_push($items, $changed_item["basedate"]);

            sort($items);

            // Add the merged list in to the rdata
            $rdata .= pack("V", count($items));
            foreach($items as $item)
                $rdata .= pack("V", $this->unixDataToRecurData($item));

            // Loop through the changed exceptions (not deleted)
            $rdata .= pack("V", count($changed_items));
            $items = array();

            foreach($changed_items as $changed_item)
            {
                $items[] = $this->dayStartOf($changed_item["start"]);
            }

            sort($items);

            // Add the changed items list int the rdata
            foreach($items as $item)
                $rdata .= pack("V", $this->unixDataToRecurData($item));

            // Set start date
            $rdata .= pack("V", $this->unixDataToRecurData((int) $this->recur["start"]));

            // Set enddate
            switch($term)
            {
                // After the given enddate
                case 0x21:
                    $rdata .= pack("V", $this->unixDataToRecurData((int) $this->recur["end"]));
                    break;
                // After a number of times
                case 0x22:
                    // @todo: calculate enddate with intval($this->recur["startocc"]) + intval($this->recur["duration"]) > 24 hour
                    $occenddate = (int) $this->recur["start"];

                    switch((int) $this->recur["type"]) {
                        case 0x0A: //daily

                            if($this->recur["subtype"] == 1) {
                                // Daily every workday
                                $restocc = (int) $this->recur["numoccur"];

                                // Get starting weekday
                                $nowtime = $this->gmtime($occenddate);
                                $j = $nowtime["tm_wday"];

                                while(1)
                                {
                                    if(($j%7) > 0 && ($j%7)<6 ) {
                                        $restocc--;
                                    }

                                    $j++;

                                    if($restocc <= 0)
                                        break;

                                    $occenddate += 24*60*60;
                                }

                            } else {
                                // -1 because the first day already counts (from 1-1-1980 to 1-1-1980 is 1 occurrence)
                                $occenddate += (((int) $this->recur["everyn"]) * 60 * (((int) $this->recur["numoccur"]-1)));
                            }
                            break;
                        case 0x0B: //weekly
                            // Needed values
                            // $forwardcount - number of weeks we can skip forward
                            // $restocc - number of remaning occurrences after the week skip

                            // Add the weeks till the last item
                            $occenddate+=($forwardcount*7*24*60*60);

                            $dayofweek = gmdate("w", $occenddate);

                            // Loop through the last occurrences until we have had them all
                            for($j = 1; $restocc>0; $j++)
                            {
                                // Jump to the next week (which may be N weeks away) when going over the week boundary
                                if((($dayofweek+$j)%7) == $weekstart)
                                    $occenddate += (((int) $this->recur["everyn"])-1) * 7 * 24*60*60;

                                // If this is a matching day, once less occurrence to process
                                if(((int) $this->recur["weekdays"]) & (1<<(($dayofweek+$j)%7)) ) {
                                    $restocc--;
                                }

                                // Next day
                                $occenddate += 24*60*60;
                            }

                            break;
                        case 0x0C: //monthly
                        case 0x0D: //yearly

                            $curyear = gmdate("Y", (int) $this->recur["start"] );
                            $curmonth = gmdate("n", (int) $this->recur["start"] );
                            // $forwardcount = months

                            switch((int) $this->recur["subtype"])
                            {
                                case 2: // on D day of every M month
                                    while($forwardcount > 0)
                                    {
                                        $occenddate += $this->getMonthInSeconds($curyear, $curmonth);

                                        if($curmonth >=12) {
                                            $curmonth = 1;
                                            $curyear++;
                                        } else {
                                            $curmonth++;
                                        }
                                        $forwardcount--;
                                    }

                                    // compensation between 28 and 31
                                    if(((int) $this->recur["monthday"]) >=28 && ((int) $this->recur["monthday"]) <= 31 &&
                                        gmdate("j", $occenddate) < ((int) $this->recur["monthday"]))
                                    {
                                        if(gmdate("j", $occenddate) < 28)
                                            $occenddate -= gmdate("j", $occenddate) * 24 * 60 *60;
                                        else
                                            $occenddate += (gmdate("t", $occenddate) - gmdate("j", $occenddate)) * 24 * 60 *60;
                                    }


                                    break;
                                case 3: // on Nth weekday of every M month
                                    $nday = (int) $this->recur["nday"]; //1 tot 5
                                    $weekdays = (int) $this->recur["weekdays"];


                                    while($forwardcount > 0)
                                    {
                                        $occenddate += $this->getMonthInSeconds($curyear, $curmonth);
                                        if($curmonth >=12) {
                                            $curmonth = 1;
                                            $curyear++;
                                        } else {
                                            $curmonth++;
                                        }

                                        $forwardcount--;
                                    }

                                    if($nday == 5) {
                                        // Set date on the last day of the last month
                                        $occenddate += (gmdate("t", $occenddate ) - gmdate("j", $occenddate )) * 24 * 60 * 60;
                                    }else {
                                        // Set date on the first day of the last month
                                        $occenddate -= (gmdate("j", $occenddate )-1) * 24 * 60 * 60;
                                    }

                                    for($i = 0; $i < 7; $i++) {
                                        if( $nday == 5 && (1<<( (gmdate("w", $occenddate)-$i)%7) ) & $weekdays) {
                                            $occenddate -= $i * 24 * 60 * 60;
                                            break;
                                        }else if($nday != 5 && (1<<( (gmdate("w", $occenddate)+$i)%7) ) & $weekdays) {
                                            $occenddate +=  ($i + (($nday-1) *7)) * 24 * 60 * 60;
                                            break;
                                        }
                                    }

                                break; //case 3:
                                }

                            break;

                    }

                    if (defined("PHP_INT_MAX") && $occenddate > PHP_INT_MAX)
                        $occenddate = PHP_INT_MAX;

                    $this->recur["end"] = $occenddate;

                    $rdata .= pack("V", $this->unixDataToRecurData((int) $this->recur["end"]) );
                    break;
                // Never ends
                case 0x23:
                default:
                    $this->recur["end"] = 0x7fffffff; // max date -> 2038
                    $rdata .= pack("V", 0x5AE980DF);
                    break;
            }

            // UTC date
            $utcstart = $this->toGMT($this->tz, (int) $this->recur["start"]);
            $utcend = $this->toGMT($this->tz, (int) $this->recur["end"]);

            //utc date+time
            $utcfirstoccstartdatetime = (isset($this->recur["startocc"])) ? $utcstart + (((int) $this->recur["startocc"])*60) : $utcstart;
            $utcfirstoccenddatetime = (isset($this->recur["endocc"])) ? $utcstart + (((int) $this->recur["endocc"]) * 60) : $utcstart;

            // update reminder time
            mapi_setprops($this->message, Array($this->proptags["reminder_time"] => $utcfirstoccstartdatetime ));

            // update first occurrence date
            mapi_setprops($this->message, Array($this->proptags["startdate"] => $utcfirstoccstartdatetime ));
            mapi_setprops($this->message, Array($this->proptags["duedate"] => $utcfirstoccenddatetime ));
            mapi_setprops($this->message, Array($this->proptags["commonstart"] => $utcfirstoccstartdatetime ));
            mapi_setprops($this->message, Array($this->proptags["commonend"] => $utcfirstoccenddatetime ));

            // Set Outlook properties, if it is an appointment
            if (isset($this->recur["message_class"]) && $this->recur["message_class"] == "IPM.Appointment") {
                // update real begin and real end date
                mapi_setprops($this->message, Array($this->proptags["startdate_recurring"] => $utcstart));
                mapi_setprops($this->message, Array($this->proptags["enddate_recurring"] => $utcend));

                // recurrencetype
                // Strange enough is the property recurrencetype, (type-0x9) and not the CDO recurrencetype
                mapi_setprops($this->message, Array($this->proptags["recurrencetype"] => ((int) $this->recur["type"]) - 0x9));

                // set named prop 'side_effects' to 369, needed for Outlook to ask for single or total recurrence when deleting
                mapi_setprops($this->message, Array($this->proptags["side_effects"] => 369));
            } else {
                mapi_setprops($this->message, Array($this->proptags["side_effects"] => 3441));
            }

            // FlagDueBy is datetime of the first reminder occurrence. Outlook gives on this time a reminder popup dialog
            // Any change of the recurrence (including changing and deleting exceptions) causes the flagdueby to be reset
            // to the 'next' occurrence; this makes sure that deleting the next ocurrence will correctly set the reminder to
            // the occurrence after that. The 'next' occurrence is defined as being the first occurrence that starts at moment X (server time)
            // with the reminder flag set.
            $reminderprops = mapi_getprops($this->message, array($this->proptags["reminder_minutes"]) );
            if(isset($reminderprops[$this->proptags["reminder_minutes"]]) ) {
                $occ = false;
                $occurrences = $this->getItems(time(), 0x7ff00000, 3, true);

                for($i = 0, $len = count($occurrences) ; $i < $len; $i++) {
                    // This will actually also give us appointments that have already started, but not yet ended. Since we want the next
                    // reminder that occurs after time(), we may have to skip the first few entries. We get 3 entries since that is the maximum
                    // number that would be needed (assuming reminder for item X cannot be before the previous occurrence starts). Worst case:
                    // time() is currently after start but before end of item, but reminder of next item has already passed (reminder for next item
                    // can be DURING the previous item, eg daily allday events). In that case, the first and second items must be skipped.

                    if(($occurrences[$i][$this->proptags["startdate"]] - $reminderprops[$this->proptags["reminder_minutes"]] * 60) > time()) {
                        $occ = $occurrences[$i];
                        break;
                    }
                }

                if($occ) {
                    mapi_setprops($this->message, Array($this->proptags["flagdueby"] => $occ[$this->proptags["startdate"]] - ($reminderprops[$this->proptags["reminder_minutes"]] * 60) ));
                } else {
                    // Last reminder passed, no reminders any more.
                    mapi_setprops($this->message, Array($this->proptags["reminder"] => false, $this->proptags["flagdueby"] => 0x7ff00000));
                }
            }

            // Default data
            // Second item (0x08) indicates the Outlook version (see documentation at the bottom of this file for more information)
            $rdata .= pack("VCCCC", 0x00003006, 0x08, 0x30, 0x00, 0x00);

            if(isset($this->recur["startocc"]) && isset($this->recur["endocc"])) {
                // Set start and endtime in minutes
                $rdata .= pack("VV", (int) $this->recur["startocc"], (int) $this->recur["endocc"]);
            }

            // Detailed exception data

            $changed_items = $this->recur["changed_occurences"];

            $rdata .= pack("v", count($changed_items));

            foreach($changed_items as $changed_item)
            {
                // Set start and end time of exception
                $rdata .= pack("V", $this->unixDataToRecurData($changed_item["start"]));
                $rdata .= pack("V", $this->unixDataToRecurData($changed_item["end"]));
                $rdata .= pack("V", $this->unixDataToRecurData($changed_item["basedate"]));

                //Bitmask
                $bitmask = 0;

                // Check for changed strings
                if(isset($changed_item["subject"]))    {
                    $bitmask |= 1 << 0;
                }

                if(isset($changed_item["remind_before"])) {
                    $bitmask |= 1 << 2;
                }

                if(isset($changed_item["reminder_set"])) {
                    $bitmask |= 1 << 3;
                }

                if(isset($changed_item["location"])) {
                    $bitmask |= 1 << 4;
                }

                if(isset($changed_item["busystatus"])) {
                    $bitmask |= 1 << 5;
                }

                if(isset($changed_item["alldayevent"])) {
                    $bitmask |= 1 << 7;
                }

                if(isset($changed_item["label"])) {
                    $bitmask |= 1 << 8;
                }

                $rdata .= pack("v", $bitmask);

                // Set "subject"
                if(isset($changed_item["subject"])) {
                    // convert utf-8 to non-unicode blob string (us-ascii?)
                    $subject = iconv("UTF-8", "windows-1252//TRANSLIT", $changed_item["subject"]);
                    $length = strlen($subject);
                    $rdata .= pack("vv", $length + 1, $length);
                    $rdata .= pack("a".$length, $subject);
                }

                if(isset($changed_item["remind_before"])) {
                    $rdata .= pack("V", $changed_item["remind_before"]);
                }

                if(isset($changed_item["reminder_set"])) {
                    $rdata .= pack("V", $changed_item["reminder_set"]);
                }

                if(isset($changed_item["location"])) {
                    $location = iconv("UTF-8", "windows-1252//TRANSLIT", $changed_item["location"]);
                    $length = strlen($location);
                    $rdata .= pack("vv", $length + 1, $length);
                    $rdata .= pack("a".$length, $location);
                }

                if(isset($changed_item["busystatus"])) {
                    $rdata .= pack("V", $changed_item["busystatus"]);
                }

                if(isset($changed_item["alldayevent"])) {
                    $rdata .= pack("V", $changed_item["alldayevent"]);
                }

                if(isset($changed_item["label"])) {
                    $rdata .= pack("V", $changed_item["label"]);
                }
            }

            $rdata .= pack("V", 0);

            // write extended data
            foreach($changed_items as $changed_item)
            {
                $rdata .= pack("V", 0);
                if(isset($changed_item["subject"]) || isset($changed_item["location"])) {
                    $rdata .= pack("V", $this->unixDataToRecurData($changed_item["start"]));
                    $rdata .= pack("V", $this->unixDataToRecurData($changed_item["end"]));
                    $rdata .= pack("V", $this->unixDataToRecurData($changed_item["basedate"]));
                }

                if(isset($changed_item["subject"])) {
                    $subject = iconv("UTF-8", "UCS-2LE", $changed_item["subject"]);
                    $length = iconv_strlen($subject, "UCS-2LE");
                    $rdata .= pack("v", $length);
                    $rdata .= pack("a".$length*2, $subject);
                }

                if(isset($changed_item["location"])) {
                    $location = iconv("UTF-8", "UCS-2LE", $changed_item["location"]);
                    $length = iconv_strlen($location, "UCS-2LE");
                    $rdata .= pack("v", $length);
                    $rdata .= pack("a".$length*2, $location);
                }

                if(isset($changed_item["subject"]) || isset($changed_item["location"])) {
                    $rdata .= pack("V", 0);
                }
            }

            $rdata .= pack("V", 0);

            // Set props
            mapi_setprops($this->message, Array($this->proptags["recurring_data"] => $rdata, $this->proptags["recurring"] => true));
            if(isset($this->tz) && $this->tz){
                $timezone = "GMT";
                if ($this->tz["timezone"]!=0){
                    // Create user readable timezone information
                    $timezone = sprintf("(GMT %s%02d:%02d)",    (-$this->tz["timezone"]>0 ? "+" : "-"),
                                                            abs($this->tz["timezone"]/60),
                                                            abs($this->tz["timezone"]%60));
                }
                mapi_setprops($this->message, Array($this->proptags["timezone_data"] => $this->getTimezoneData($this->tz),
                                                    $this->proptags["timezone"] => $timezone));
            }
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Generates and stores recurrence pattern string to recurring_pattern property.

Definition at line 557 of file class.recurrence.php.

        {
            // Start formatting the properties in such a way we can apply
            // them directly into the recurrence pattern.
            $type = $this->recur['type'];
            $everyn = $this->recur['everyn'];
            $start = $this->recur['start'];
            $end = $this->recur['end'];
            $term = $this->recur['term'];
            $numocc = isset($this->recur['numoccur']) ? $this->recur['numoccur'] : false;
            $startocc = $this->recur['startocc'];
            $endocc = $this->recur['endocc'];
            $pattern = '';
            $occSingleDayRank = false;
            $occTimeRange = ($startocc != 0 && $endocc != 0);

            switch ($type) {
                // Daily
                case 0x0A:
                    if ($everyn == 1) {
                        $type = _('workday');
                        $occSingleDayRank = true;
                    } else if ($everyn == (24 * 60)) {
                        $type = _('day');
                        $occSingleDayRank = true;
                    } else {
                        $everyn /= (24 * 60);
                        $type = _('days');
                        $occSingleDayRank = false;
                    }
                    break;
                // Weekly
                case 0x0B:
                    if ($everyn == 1) {
                        $type = _('week');
                        $occSingleDayRank = true;
                    } else {
                        $type = _('weeks');
                        $occSingleDayRank = false;
                    }
                    break;
                // Monthly
                case 0x0C:
                    if ($everyn == 1) {
                        $type = _('month');
                        $occSingleDayRank = true;
                    } else {
                        $type = _('months');
                        $occSingleDayRank = false;
                    }
                    break;
                // Yearly
                case 0x0D:
                    if ($everyn <= 12) {
                        $everyn = 1;
                        $type = _('year');
                        $occSingleDayRank = true;
                    } else {
                        $everyn = $everyn / 12;
                        $type = _('years');
                        $occSingleDayRank = false;
                    }
                    break;
            }

            // get timings of the first occurence
            $firstoccstartdate = isset($startocc) ? $start + (((int) $startocc) * 60) : $start;
            $firstoccenddate = isset($endocc) ? $end + (((int) $endocc) * 60) : $end;

            $start = gmdate(_('d-m-Y'), $firstoccstartdate);
            $end = gmdate(_('d-m-Y'), $firstoccenddate);
            $startocc = gmdate(_('G:i'), $firstoccstartdate);
            $endocc = gmdate(_('G:i'), $firstoccenddate);

            // Based on the properties, we need to generate the recurrence pattern string.
            // This is obviously very easy since we can simply concatenate a bunch of strings,
            // however this messes up translations for languages which order their words
            // differently.
            // To improve translation quality we create a series of default strings, in which
            // we only have to fill in the correct variables. The base string is thus selected
            // based on the available properties.
            if ($term == 0x23) {
                // Never ends
                if ($occTimeRange) {
                    if ($occSingleDayRank) {
                        $pattern = sprintf(_('Occurs every %s effective %s from %s to %s.'), $type, $start, $startocc, $endocc);
                    } else {
                        $pattern = sprintf(_('Occurs every %s %s effective %s from %s to %s.'), $everyn, $type, $start, $startocc, $endocc);
                    }
                } else {
                    if ($occSingleDayRank) {
                        $pattern = sprintf(_('Occurs every %s effective %s.'), $type, $start);
                    } else {
                        $pattern = sprintf(_('Occurs every %s %s effective %s.'), $everyn, $type, $start);
                    }
                }
            } else if ($term == 0x22) {
                // After a number of times
                if ($occTimeRange) {
                    if ($occSingleDayRank) {
                        $pattern = sprintf(ngettext('Occurs every %s effective %s for %s occurence from %s to %s.',
                                                'Occurs every %s effective %s for %s occurences from %s to %s.', $numocc), $type, $start, $numocc, $startocc, $endocc);
                    } else {
                        $pattern = sprintf(ngettext('Occurs every %s %s effective %s for %s occurence from %s to %s.',
                                                'Occurs every %s %s effective %s for %s occurences %s to %s.', $numocc), $everyn, $type, $start, $numocc, $startocc, $endocc);
                    }
                } else {
                    if ($occSingleDayRank) {
                        $pattern = sprintf(ngettext('Occurs every %s effective %s for %s occurence.',
                                                     'Occurs every %s effective %s for %s occurences.', $numocc), $type, $start, $numocc);
                    } else {
                        $pattern = sprintf(ngettext('Occurs every %s %s effective %s for %s occurence.',
                                                         'Occurs every %s %s effective %s for %s occurences.', $numocc), $everyn, $type, $start, $numocc);
                    }
                }
            } else if ($term == 0x21) {
                // After the given enddate
                if ($occTimeRange) {
                    if ($occSingleDayRank) {
                        $pattern = sprintf(_('Occurs every %s effective %s until %s from %s to %s.'), $type, $start, $end, $startocc, $endocc);
                    } else {
                        $pattern = sprintf(_('Occurs every %s %s effective %s until %s from %s to %s.'), $everyn, $type, $start, $end, $startocc, $endocc);
                    }
                } else {
                    if ($occSingleDayRank) {
                        $pattern = sprintf(_('Occurs every %s effective %s until %s.'), $type, $start, $end);
                    } else {
                        $pattern = sprintf(_('Occurs every %s %s effective %s until %s.'), $everyn, $type, $start, $end);
                    }
                }
            }

            if(!empty($pattern)) {
                mapi_setprops($this->message, Array($this->proptags["recurring_pattern"] => $pattern ));
            }
        }

Here is the caller graph for this function:

Recurrence::setAllExceptionRecipients ( message,
exception_recips 
)

Function which applies the provided recipients to the exception, also checks for deleted recipients.

The $exception_recips should be an array containing all recipients which must be applied to the exception. This will copy all recipients from the original message and then start filter out all recipients which are not provided by the $exception_recips list.

Parameters:
resource$messageexception attachment of recurring item
array$exception_recipslist of recipients

Definition at line 1137 of file class.recurrence.php.

        {
            $deletedRecipients = array();
            $useMessageRecipients = false;

            $recipientTable = mapi_message_getrecipienttable($message);
            $recipientRows = mapi_table_queryallrows($recipientTable, $this->recipprops);

            if (empty($recipientRows)) {
                $useMessageRecipients = true;
                $recipientTable = mapi_message_getrecipienttable($this->message);
                $recipientRows = mapi_table_queryallrows($recipientTable, $this->recipprops);
            }

            // Add organizer to meeting only if it is not organized.
            $msgprops = mapi_getprops($message, array(PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ADDRTYPE, $this->proptags['responsestatus']));
            if (isset($msgprops[$this->proptags['responsestatus']]) && $msgprops[$this->proptags['responsestatus']] != olResponseOrganized){
                $this->addOrganizer($msgprops, $exception_recips);
            }

            if (!empty($exception_recips)) {
                foreach($recipientRows as $key => $recipient) {
                    $found = false;
                    foreach($exception_recips as $excep_recip) {
                        if ($recipient[PR_SEARCH_KEY] == $excep_recip[PR_SEARCH_KEY])
                            $found = true;
                    }

                    if (!$found) {
                       $foundInDeletedRecipients = false;
                       // Look if the $recipient is in the list of deleted recipients
                       if (!empty($deletedRecipients)) {
                               foreach($deletedRecipients as $recip) {
                                   if ($recip[PR_SEARCH_KEY] == $recipient[PR_SEARCH_KEY]){
                                       $foundInDeletedRecipients = true;
                                       break;
                                   }
                               }
                       }

                       // If recipient is not in list of deleted recipient, add him
                       if (!$foundInDeletedRecipients) {
                            if (!isset($recipient[PR_RECIPIENT_FLAGS]) || $recipient[PR_RECIPIENT_FLAGS] != (recipReserved | recipExceptionalDeleted | recipSendable)) {
                                $recipient[PR_RECIPIENT_FLAGS] = recipSendable | recipExceptionalDeleted;
                            } else {
                                $recipient[PR_RECIPIENT_FLAGS] = recipReserved | recipExceptionalDeleted | recipSendable;
                            }
                            $recipient[PR_RECIPIENT_TRACKSTATUS] = olRecipientTrackStatusNone;    // No Response required
                            $deletedRecipients[] = $recipient;
                        }
                    }

                    // When $message contains a non-empty recipienttable, we must delete the recipients
                    // before re-adding them. However, when $message is doesn't contain any recipients,
                    // we are using the recipient table of the original message ($this->message)
                    // rather then $message. In that case, we don't need to remove the recipients
                    // from the $message, as the recipient table is already empty, and
                    // mapi_message_modifyrecipients() will throw an error.
                    if ($useMessageRecipients === false) {
                        mapi_message_modifyrecipients($message, MODRECIP_REMOVE, array($recipient));
                    }
                }
                $exception_recips = array_merge($exception_recips, $deletedRecipients);
            } else {
                $exception_recips = $recipientRows;
            }

            if (!empty($exception_recips)) {
                // Set the new list of recipients on the exception message, this also removes the existing recipients
                mapi_message_modifyrecipients($message, 0, $exception_recips);
            }
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Recurrence::setDeltaExceptionRecipients ( exception,
exception_recips,
copy_orig_recips 
)

Function which applies the provided delta for recipients changes to the exception.

The $exception_recips should be an array containing the following keys:

  • "add": this contains an array of recipients which must be added
  • "remove": This contains an array of recipients which must be removed
  • "modify": This contains an array of recipients which must be modified
Parameters:
resource$messageexception attachment of recurring item
array$exception_recipslist of recipients
boolean$copy_orig_recipsTrue to copy all recipients which are on the original message to the attachment by default. False if only the $exception_recips changes should be applied.

Definition at line 1085 of file class.recurrence.php.

        {
            // Check if the recipients from the original message should be copied,
            // if so, open the recipient table of the parent message and apply all
            // rows on the target recipient.
            if ($copy_orig_recips === true) {
                $origTable = mapi_message_getrecipienttable($this->message);
                $recipientRows = mapi_table_queryallrows($origTable, $this->recipprops);
                mapi_message_modifyrecipients($exception, MODRECIP_ADD, $recipientRows);
            }

            // Add organizer to meeting only if it is not organized.
            $msgprops = mapi_getprops($exception, array(PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ADDRTYPE, $this->proptags['responsestatus']));
            if (isset($msgprops[$this->proptags['responsestatus']]) && $msgprops[$this->proptags['responsestatus']] != olResponseOrganized){
                $this->addOrganizer($msgprops, $exception_recips['add']);
            }

            // Remove all deleted recipients
            if (isset($exception_recips['remove'])) {
                foreach ($exception_recips['remove'] as &$recip) {
                    if (!isset($recipient[PR_RECIPIENT_FLAGS]) || $recip[PR_RECIPIENT_FLAGS] != (recipReserved | recipExceptionalDeleted | recipSendable)) {
                        $recip[PR_RECIPIENT_FLAGS] = recipSendable | recipExceptionalDeleted;
                    } else {
                        $recip[PR_RECIPIENT_FLAGS] = recipReserved | recipExceptionalDeleted | recipSendable;
                    }
                    $recip[PR_RECIPIENT_TRACKSTATUS] = olResponseNone;        // No Response required
                }
                unset($recip);
                mapi_message_modifyrecipients($exception, MODRECIP_MODIFY, $exception_recips['remove']);
            }

            // Add all new recipients
            if (isset($exception_recips['add'])) {
                mapi_message_modifyrecipients($exception, MODRECIP_ADD, $exception_recips['add']);
            }

            // Modify the existing recipients
            if (isset($exception_recips['modify'])) {
                mapi_message_modifyrecipients($exception, MODRECIP_MODIFY, $exception_recips['modify']);
            }
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Recurrence::setExceptionRecipients ( message,
exception_recips,
copy_orig_recips = true 
)

Function which sets recipients for an exception.

The $exception_recips can be provided in 2 ways:

  • A delta which indicates which recipients must be added, removed or deleted.
  • A complete array of the recipients which should be applied to the message.

The first option is preferred as it will require less work to be executed.

Parameters:
resource$messageexception attachment of recurring item
array$exception_recipslist of recipients
boolean$copy_orig_recipsTrue to copy all recipients which are on the original message to the attachment by default. False if only the $exception_recips changes should be applied.

Definition at line 1062 of file class.recurrence.php.

        {
            if (isset($exception_recips['add']) || isset($exception_recips['remove']) || isset($exception_recips['modify'])) {
                $this->setDeltaExceptionRecipients($message, $exception_recips, $copy_orig_recips);
            } else {
                $this->setAllExceptionRecipients($message, $exception_recips);
            }
        }

Here is the call graph for this function:

Here is the caller graph for this function:

Recurrence::setRecurrence ( tz,
recur 
)

Definition at line 441 of file class.recurrence.php.

        {
            // only reset timezone if specified
            if($tz)
                $this->tz = $tz;

            $this->recur = $recur;

            if(!isset($this->recur["changed_occurences"]))
                $this->recur["changed_occurences"] = Array();

            if(!isset($this->recur["deleted_occurences"]))
                $this->recur["deleted_occurences"] = Array();

            $this->deleteAttachments();
            $this->saveRecurrence();

            // if client has not set the recurring_pattern then we should generate it and save it
            $messageProps = mapi_getprops($this->message, Array($this->proptags["recurring_pattern"]));
            if(empty($messageProps[$this->proptags["recurring_pattern"]])) {
                $this->saveRecurrencePattern();
            }
        }

Here is the call graph for this function:

BaseRecurrence::sortExceptionStart ( a,
b 
) [inherited]

Definition at line 1940 of file class.baserecurrence.php.

        {
            return $a["start"] == $b["start"] ? 0 : ($a["start"]  > $b["start"] ? 1 : -1 );
        }
BaseRecurrence::sortStarttime ( a,
b 
) [inherited]

Definition at line 1899 of file class.baserecurrence.php.

        {
            $aTime = $a[$this->proptags["startdate"]];
            $bTime = $b[$this->proptags["startdate"]];

            return $aTime==$bTime?0:($aTime>$bTime?1:-1);
        }
BaseRecurrence::toGMT ( tz,
date 
) [inherited]

toGMT returns a timestamp in GMT time for the time and timezone given

Definition at line 1589 of file class.baserecurrence.php.

                                   {
            if(!isset($tz['timezone']))
                return $date;
            $offset = $this->getTimezone($tz, $date);

            return $date + $offset * 60;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

BaseRecurrence::unixDataToRecurData ( date) [inherited]

Function which converts an unix date timestamp to recurrence date timestamp.

Author:
Johnny Biemans
Parameters:
Date$datethe date which will be converted
Returns:
Int the converted date in minutes

Definition at line 1411 of file class.baserecurrence.php.

        {
            return ($date / 60) + 194074560;
        }

Here is the caller graph for this function:

BaseRecurrence::yearStartOf ( date) [inherited]

Function to get timestamp of the beginning of the year of the timestamp given.

Parameters:
date$date
Returns:
date Timestamp referring to the same year but on Jan 01, at 00:00:00

Definition at line 1635 of file class.baserecurrence.php.

        {
            $time1 = $this->gmtime($date);

            return gmmktime(0, 0, 0, 1, 1, $time1["tm_year"] + 1900);
        }

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 66 of file class.baserecurrence.php.

Definition at line 71 of file class.baserecurrence.php.

Definition at line 76 of file class.baserecurrence.php.

Definition at line 81 of file class.baserecurrence.php.

Definition at line 61 of file class.baserecurrence.php.

BaseRecurrence::$tz [inherited]

Reimplemented in TaskRecurrence.

Definition at line 86 of file class.baserecurrence.php.


The documentation for this class was generated from the following file: