1 | <?php |
---|
2 | /* |
---|
3 | * Copyright 2005 - 2012 Zarafa B.V. |
---|
4 | * |
---|
5 | * This program is free software: you can redistribute it and/or modify |
---|
6 | * it under the terms of the GNU Affero General Public License, version 3, |
---|
7 | * as published by the Free Software Foundation with the following additional |
---|
8 | * term according to sec. 7: |
---|
9 | * |
---|
10 | * According to sec. 7 of the GNU Affero General Public License, version |
---|
11 | * 3, the terms of the AGPL are supplemented with the following terms: |
---|
12 | * |
---|
13 | * "Zarafa" is a registered trademark of Zarafa B.V. The licensing of |
---|
14 | * the Program under the AGPL does not imply a trademark license. |
---|
15 | * Therefore any rights, title and interest in our trademarks remain |
---|
16 | * entirely with us. |
---|
17 | * |
---|
18 | * However, if you propagate an unmodified version of the Program you are |
---|
19 | * allowed to use the term "Zarafa" to indicate that you distribute the |
---|
20 | * Program. Furthermore you may use our trademarks where it is necessary |
---|
21 | * to indicate the intended purpose of a product or service provided you |
---|
22 | * use it in accordance with honest practices in industrial or commercial |
---|
23 | * matters. If you want to propagate modified versions of the Program |
---|
24 | * under the name "Zarafa" or "Zarafa Server", you may only do so if you |
---|
25 | * have a written permission by Zarafa B.V. (to acquire a permission |
---|
26 | * please contact Zarafa at trademark@zarafa.com). |
---|
27 | * |
---|
28 | * The interactive user interface of the software displays an attribution |
---|
29 | * notice containing the term "Zarafa" and/or the logo of Zarafa. |
---|
30 | * Interactive user interfaces of unmodified and modified versions must |
---|
31 | * display Appropriate Legal Notices according to sec. 5 of the GNU |
---|
32 | * Affero General Public License, version 3, when you propagate |
---|
33 | * unmodified or modified versions of the Program. In accordance with |
---|
34 | * sec. 7 b) of the GNU Affero General Public License, version 3, these |
---|
35 | * Appropriate Legal Notices must retain the logo of Zarafa or display |
---|
36 | * the words "Initial Development by Zarafa" if the display of the logo |
---|
37 | * is not reasonably feasible for technical reasons. The use of the logo |
---|
38 | * of Zarafa in Legal Notices is allowed for unmodified and modified |
---|
39 | * versions of the software. |
---|
40 | * |
---|
41 | * This program is distributed in the hope that it will be useful, |
---|
42 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
43 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
44 | * GNU Affero General Public License for more details. |
---|
45 | * |
---|
46 | * You should have received a copy of the GNU Affero General Public License |
---|
47 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
48 | * |
---|
49 | */ |
---|
50 | |
---|
51 | |
---|
52 | require_once("backend/zarafa/mapi/class.baserecurrence.php"); |
---|
53 | |
---|
54 | class TaskRecurrence extends BaseRecurrence |
---|
55 | { |
---|
56 | /** |
---|
57 | * Timezone info which is always false for task |
---|
58 | */ |
---|
59 | var $tz = false; |
---|
60 | |
---|
61 | function TaskRecurrence($store, $message) |
---|
62 | { |
---|
63 | $this->store = $store; |
---|
64 | $this->message = $message; |
---|
65 | |
---|
66 | $properties = array(); |
---|
67 | $properties["entryid"] = PR_ENTRYID; |
---|
68 | $properties["parent_entryid"] = PR_PARENT_ENTRYID; |
---|
69 | $properties["icon_index"] = PR_ICON_INDEX; |
---|
70 | $properties["message_class"] = PR_MESSAGE_CLASS; |
---|
71 | $properties["message_flags"] = PR_MESSAGE_FLAGS; |
---|
72 | $properties["subject"] = PR_SUBJECT; |
---|
73 | $properties["importance"] = PR_IMPORTANCE; |
---|
74 | $properties["sensitivity"] = PR_SENSITIVITY; |
---|
75 | $properties["last_modification_time"] = PR_LAST_MODIFICATION_TIME; |
---|
76 | $properties["status"] = "PT_LONG:PSETID_Task:0x8101"; |
---|
77 | $properties["percent_complete"] = "PT_DOUBLE:PSETID_Task:0x8102"; |
---|
78 | $properties["startdate"] = "PT_SYSTIME:PSETID_Task:0x8104"; |
---|
79 | $properties["duedate"] = "PT_SYSTIME:PSETID_Task:0x8105"; |
---|
80 | $properties["reset_reminder"] = "PT_BOOLEAN:PSETID_Task:0x8107"; |
---|
81 | $properties["dead_occurrence"] = "PT_BOOLEAN:PSETID_Task:0x8109"; |
---|
82 | $properties["datecompleted"] = "PT_SYSTIME:PSETID_Task:0x810f"; |
---|
83 | $properties["recurring_data"] = "PT_BINARY:PSETID_Task:0x8116"; |
---|
84 | $properties["actualwork"] = "PT_LONG:PSETID_Task:0x8110"; |
---|
85 | $properties["totalwork"] = "PT_LONG:PSETID_Task:0x8111"; |
---|
86 | $properties["complete"] = "PT_BOOLEAN:PSETID_Task:0x811c"; |
---|
87 | $properties["task_f_creator"] = "PT_BOOLEAN:PSETID_Task:0x811e"; |
---|
88 | $properties["owner"] = "PT_STRING8:PSETID_Task:0x811f"; |
---|
89 | $properties["recurring"] = "PT_BOOLEAN:PSETID_Task:0x8126"; |
---|
90 | |
---|
91 | $properties["reminder_minutes"] = "PT_LONG:PSETID_Common:0x8501"; |
---|
92 | $properties["reminder_time"] = "PT_SYSTIME:PSETID_Common:0x8502"; |
---|
93 | $properties["reminder"] = "PT_BOOLEAN:PSETID_Common:0x8503"; |
---|
94 | |
---|
95 | $properties["private"] = "PT_BOOLEAN:PSETID_Common:0x8506"; |
---|
96 | $properties["contacts"] = "PT_MV_STRING8:PSETID_Common:0x853a"; |
---|
97 | $properties["contacts_string"] = "PT_STRING8:PSETID_Common:0x8586"; |
---|
98 | $properties["categories"] = "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords"; |
---|
99 | |
---|
100 | $properties["commonstart"] = "PT_SYSTIME:PSETID_Common:0x8516"; |
---|
101 | $properties["commonend"] = "PT_SYSTIME:PSETID_Common:0x8517"; |
---|
102 | $properties["commonassign"] = "PT_LONG:PSETID_Common:0x8518"; |
---|
103 | $properties["flagdueby"] = "PT_SYSTIME:PSETID_Common:0x8560"; |
---|
104 | $properties["side_effects"] = "PT_LONG:PSETID_Common:0x8510"; |
---|
105 | $properties["reminder"] = "PT_BOOLEAN:PSETID_Common:0x8503"; |
---|
106 | $properties["reminder_minutes"] = "PT_LONG:PSETID_Common:0x8501"; |
---|
107 | |
---|
108 | $this->proptags = getPropIdsFromStrings($store, $properties); |
---|
109 | |
---|
110 | parent::BaseRecurrence($store, $message, $properties); |
---|
111 | } |
---|
112 | |
---|
113 | /** |
---|
114 | * Function which saves recurrence and also regenerates task if necessary. |
---|
115 | *@param array $recur new recurrence properties |
---|
116 | *@return array of properties of regenerated task else false |
---|
117 | */ |
---|
118 | function setRecurrence(&$recur) |
---|
119 | { |
---|
120 | $this->recur = $recur; |
---|
121 | $this->action =& $recur; |
---|
122 | |
---|
123 | if(!isset($this->recur["changed_occurences"])) |
---|
124 | $this->recur["changed_occurences"] = Array(); |
---|
125 | |
---|
126 | if(!isset($this->recur["deleted_occurences"])) |
---|
127 | $this->recur["deleted_occurences"] = Array(); |
---|
128 | |
---|
129 | if (!isset($this->recur['startocc'])) $this->recur['startocc'] = 0; |
---|
130 | if (!isset($this->recur['endocc'])) $this->recur['endocc'] = 0; |
---|
131 | |
---|
132 | // Save recurrence because we need proper startrecurrdate and endrecurrdate |
---|
133 | $this->saveRecurrence(); |
---|
134 | |
---|
135 | // Update $this->recur with proper startrecurrdate and endrecurrdate updated after saveing recurrence |
---|
136 | $msgProps = mapi_getprops($this->message, array($this->proptags['recurring_data'])); |
---|
137 | $recurring_data = $this->parseRecurrence($msgProps[$this->proptags['recurring_data']]); |
---|
138 | foreach($recurring_data as $key => $value) { |
---|
139 | $this->recur[$key] = $value; |
---|
140 | } |
---|
141 | |
---|
142 | $this->setFirstOccurrence(); |
---|
143 | |
---|
144 | // Let's see if next occurrence has to be generated |
---|
145 | return $this->moveToNextOccurrence(); |
---|
146 | } |
---|
147 | |
---|
148 | /** |
---|
149 | * Sets task object to first occurrence if startdate/duedate of task object is different from first occurrence |
---|
150 | */ |
---|
151 | function setFirstOccurrence() |
---|
152 | { |
---|
153 | // Check if it is already the first occurrence |
---|
154 | if($this->action['start'] == $this->recur["start"]){ |
---|
155 | return; |
---|
156 | }else{ |
---|
157 | $items = $this->getNextOccurrence(); |
---|
158 | |
---|
159 | $props = array(); |
---|
160 | $props[$this->proptags['startdate']] = $items[$this->proptags['startdate']]; |
---|
161 | $props[$this->proptags['commonstart']] = $items[$this->proptags['startdate']]; |
---|
162 | |
---|
163 | $props[$this->proptags['duedate']] = $items[$this->proptags['duedate']]; |
---|
164 | $props[$this->proptags['commonend']] = $items[$this->proptags['duedate']]; |
---|
165 | |
---|
166 | mapi_setprops($this->message, $props); |
---|
167 | } |
---|
168 | } |
---|
169 | |
---|
170 | /** |
---|
171 | * Function which creates new task as current occurrence and moves the |
---|
172 | * existing task to next occurrence. |
---|
173 | * |
---|
174 | *@param array $recur $action from client |
---|
175 | *@return boolean if moving to next occurrence succeed then it returns |
---|
176 | * properties of either newly created task or existing task ELSE |
---|
177 | * false because that was last occurrence |
---|
178 | */ |
---|
179 | function moveToNextOccurrence() |
---|
180 | { |
---|
181 | $result = false; |
---|
182 | /** |
---|
183 | * Every recurring task should have a 'duedate'. If a recurring task is created with no start/end date |
---|
184 | * then we create first two occurrence separately and for first occurrence recurrence has ended. |
---|
185 | */ |
---|
186 | if ((empty($this->action['startdate']) && empty($this->action['duedate'])) |
---|
187 | || ($this->action['complete'] == 1) || (isset($this->action['deleteOccurrence']) && $this->action['deleteOccurrence'])){ |
---|
188 | |
---|
189 | $nextOccurrence = $this->getNextOccurrence(); |
---|
190 | $result = mapi_getprops($this->message, array(PR_ENTRYID, PR_PARENT_ENTRYID, PR_STORE_ENTRYID)); |
---|
191 | |
---|
192 | $props = array(); |
---|
193 | if ($nextOccurrence) { |
---|
194 | if (!isset($this->action['deleteOccurrence'])) { |
---|
195 | // Create current occurrence as separate task |
---|
196 | $result = $this->regenerateTask($this->action['complete']); |
---|
197 | } |
---|
198 | |
---|
199 | // Set reminder for next occurrence |
---|
200 | $this->setReminder($nextOccurrence); |
---|
201 | |
---|
202 | // Update properties for next occurrence |
---|
203 | $this->action['duedate'] = $props[$this->proptags['duedate']] = $nextOccurrence[$this->proptags['duedate']]; |
---|
204 | $this->action['commonend'] = $props[$this->proptags['commonend']] = $nextOccurrence[$this->proptags['duedate']]; |
---|
205 | |
---|
206 | $this->action['startdate'] = $props[$this->proptags['startdate']] = $nextOccurrence[$this->proptags['startdate']]; |
---|
207 | $this->action['commonstart'] = $props[$this->proptags['commonstart']] = $nextOccurrence[$this->proptags['startdate']]; |
---|
208 | |
---|
209 | // If current task as been mark as 'Complete' then next occurrence should be uncomplete. |
---|
210 | if (isset($this->action['complete']) && $this->action['complete'] == 1) { |
---|
211 | $this->action['status'] = $props[$this->proptags["status"]] = olTaskNotStarted; |
---|
212 | $this->action['complete'] = $props[$this->proptags["complete"]] = false; |
---|
213 | $this->action['percent_complete'] = $props[$this->proptags["percent_complete"]] = 0; |
---|
214 | } |
---|
215 | |
---|
216 | $props[$this->proptags["dead_occurrence"]] = false; |
---|
217 | } else { |
---|
218 | if (isset($this->action['deleteOccurrence']) && $this->action['deleteOccurrence']) |
---|
219 | return false; |
---|
220 | |
---|
221 | // Didn't get next occurrence, probably this is the last one, so recurrence ends here |
---|
222 | $props[$this->proptags["dead_occurrence"]] = true; |
---|
223 | $props[$this->proptags["datecompleted"]] = $this->action['datecompleted']; |
---|
224 | $props[$this->proptags["task_f_creator"]] = true; |
---|
225 | |
---|
226 | //OL props |
---|
227 | $props[$this->proptags["side_effects"]] = 1296; |
---|
228 | $props[$this->proptags["icon_index"]] = 1280; |
---|
229 | } |
---|
230 | |
---|
231 | mapi_setprops($this->message, $props); |
---|
232 | } |
---|
233 | |
---|
234 | return $result; |
---|
235 | } |
---|
236 | |
---|
237 | /** |
---|
238 | * Function which return properties of next occurrence |
---|
239 | *@return array startdate/enddate of next occurrence |
---|
240 | */ |
---|
241 | function getNextOccurrence() |
---|
242 | { |
---|
243 | if ($this->recur) { |
---|
244 | $items = array(); |
---|
245 | |
---|
246 | //@TODO: fix start of range |
---|
247 | $start = isset($this->messageprops[$this->proptags["duedate"]]) ? $this->messageprops[$this->proptags["duedate"]] : $this->action['start']; |
---|
248 | $dayend = ($this->recur['term'] == 0x23) ? 0x7fffffff : $this->dayStartOf($this->recur["end"]); |
---|
249 | |
---|
250 | // Fix recur object |
---|
251 | $this->recur['startocc'] = 0; |
---|
252 | $this->recur['endocc'] = 0; |
---|
253 | |
---|
254 | // Retrieve next occurrence |
---|
255 | $items = $this->getItems($start, $dayend, 1); |
---|
256 | |
---|
257 | return !empty($items) ? $items[0] : false; |
---|
258 | } |
---|
259 | } |
---|
260 | |
---|
261 | /** |
---|
262 | * Function which clones current occurrence and sets appropriate properties. |
---|
263 | * The original recurring item is moved to next occurrence. |
---|
264 | *@param boolean $markComplete true if existing occurrence has to be mark complete else false. |
---|
265 | */ |
---|
266 | function regenerateTask($markComplete) |
---|
267 | { |
---|
268 | // Get all properties |
---|
269 | $taskItemProps = mapi_getprops($this->message); |
---|
270 | |
---|
271 | if (isset($this->action["subject"])) $taskItemProps[$this->proptags["subject"]] = $this->action["subject"]; |
---|
272 | if (isset($this->action["importance"])) $taskItemProps[$this->proptags["importance"]] = $this->action["importance"]; |
---|
273 | if (isset($this->action["startdate"])) { |
---|
274 | $taskItemProps[$this->proptags["startdate"]] = $this->action["startdate"]; |
---|
275 | $taskItemProps[$this->proptags["commonstart"]] = $this->action["startdate"]; |
---|
276 | } |
---|
277 | if (isset($this->action["duedate"])) { |
---|
278 | $taskItemProps[$this->proptags["duedate"]] = $this->action["duedate"]; |
---|
279 | $taskItemProps[$this->proptags["commonend"]] = $this->action["duedate"]; |
---|
280 | } |
---|
281 | |
---|
282 | $folder = mapi_msgstore_openentry($this->store, $taskItemProps[PR_PARENT_ENTRYID]); |
---|
283 | $newMessage = mapi_folder_createmessage($folder); |
---|
284 | |
---|
285 | $taskItemProps[$this->proptags["status"]] = $markComplete ? olTaskComplete : olTaskNotStarted; |
---|
286 | $taskItemProps[$this->proptags["complete"]] = $markComplete; |
---|
287 | $taskItemProps[$this->proptags["percent_complete"]] = $markComplete ? 1 : 0; |
---|
288 | |
---|
289 | // This occurrence has been marked as 'Complete' so disable reminder |
---|
290 | if ($markComplete) { |
---|
291 | $taskItemProps[$this->proptags["reset_reminder"]] = false; |
---|
292 | $taskItemProps[$this->proptags["reminder"]] = false; |
---|
293 | $taskItemProps[$this->proptags["datecompleted"]] = $this->action["datecompleted"]; |
---|
294 | |
---|
295 | unset($this->action[$this->proptags['datecompleted']]); |
---|
296 | } |
---|
297 | |
---|
298 | // Recurrence ends for this item |
---|
299 | $taskItemProps[$this->proptags["dead_occurrence"]] = true; |
---|
300 | $taskItemProps[$this->proptags["task_f_creator"]] = true; |
---|
301 | |
---|
302 | //OL props |
---|
303 | $taskItemProps[$this->proptags["side_effects"]] = 1296; |
---|
304 | $taskItemProps[$this->proptags["icon_index"]] = 1280; |
---|
305 | |
---|
306 | // Copy recipients |
---|
307 | $recipienttable = mapi_message_getrecipienttable($this->message); |
---|
308 | $recipients = mapi_table_queryallrows($recipienttable, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_RECIPIENT_ENTRYID, PR_RECIPIENT_TYPE, PR_SEND_INTERNET_ENCODING, PR_SEND_RICH_INFO, PR_RECIPIENT_DISPLAY_NAME, PR_ADDRTYPE, PR_DISPLAY_TYPE, PR_RECIPIENT_TRACKSTATUS, PR_RECIPIENT_TRACKSTATUS_TIME, PR_RECIPIENT_FLAGS, PR_ROWID)); |
---|
309 | |
---|
310 | $copy_to_recipientTable = mapi_message_getrecipienttable($newMessage); |
---|
311 | $copy_to_recipientRows = mapi_table_queryallrows($copy_to_recipientTable, array(PR_ROWID)); |
---|
312 | foreach($copy_to_recipientRows as $recipient) { |
---|
313 | mapi_message_modifyrecipients($newMessage, MODRECIP_REMOVE, array($recipient)); |
---|
314 | } |
---|
315 | mapi_message_modifyrecipients($newMessage, MODRECIP_ADD, $recipients); |
---|
316 | |
---|
317 | // Copy attachments |
---|
318 | $attachmentTable = mapi_message_getattachmenttable($this->message); |
---|
319 | if($attachmentTable) { |
---|
320 | $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)); |
---|
321 | |
---|
322 | foreach($attachments as $attach_props){ |
---|
323 | $attach_old = mapi_message_openattach($this->message, (int) $attach_props[PR_ATTACH_NUM]); |
---|
324 | $attach_newResourceMsg = mapi_message_createattach($newMessage); |
---|
325 | |
---|
326 | mapi_copyto($attach_old, array(), array(), $attach_newResourceMsg, 0); |
---|
327 | mapi_savechanges($attach_newResourceMsg); |
---|
328 | } |
---|
329 | } |
---|
330 | |
---|
331 | mapi_setprops($newMessage, $taskItemProps); |
---|
332 | mapi_savechanges($newMessage); |
---|
333 | |
---|
334 | // Update body of original message |
---|
335 | $msgbody = mapi_message_openproperty($this->message, PR_BODY); |
---|
336 | $msgbody = trim($this->windows1252_to_utf8($msgbody), "\0"); |
---|
337 | $separator = "------------\r\n"; |
---|
338 | |
---|
339 | if (!empty($msgbody) && strrpos($msgbody, $separator) === false) { |
---|
340 | $msgbody = $separator . $msgbody; |
---|
341 | $stream = mapi_openpropertytostream($this->message, PR_BODY, MAPI_CREATE | MAPI_MODIFY); |
---|
342 | mapi_stream_setsize($stream, strlen($msgbody)); |
---|
343 | mapi_stream_write($stream, $msgbody); |
---|
344 | mapi_stream_commit($stream); |
---|
345 | } |
---|
346 | |
---|
347 | // We need these properties to notify client |
---|
348 | return mapi_getprops($newMessage, array(PR_ENTRYID, PR_PARENT_ENTRYID, PR_STORE_ENTRYID)); |
---|
349 | } |
---|
350 | |
---|
351 | /** |
---|
352 | * processOccurrenceItem, adds an item to a list of occurrences, but only if the |
---|
353 | * resulting occurrence starts or ends in the interval <$start, $end> |
---|
354 | * @param array $items reference to the array to be added to |
---|
355 | * @param date $start start of timeframe in GMT TIME |
---|
356 | * @param date $end end of timeframe in GMT TIME |
---|
357 | * @param date $basedate (hour/sec/min assumed to be 00:00:00) in LOCAL TIME OF THE OCCURRENCE |
---|
358 | */ |
---|
359 | function processOccurrenceItem(&$items, $start, $end, $now) |
---|
360 | { |
---|
361 | if ($now > $start) { |
---|
362 | $newItem = array(); |
---|
363 | $newItem[$this->proptags['startdate']] = $now; |
---|
364 | |
---|
365 | // If startdate and enddate are set on task, then slide enddate according to duration |
---|
366 | if (isset($this->messageprops[$this->proptags["startdate"]]) && isset($this->messageprops[$this->proptags["duedate"]])) { |
---|
367 | $newItem[$this->proptags['duedate']] = $newItem[$this->proptags['startdate']] + ($this->messageprops[$this->proptags["duedate"]] - $this->messageprops[$this->proptags["startdate"]]); |
---|
368 | } else { |
---|
369 | $newItem[$this->proptags['duedate']] = $newItem[$this->proptags['startdate']]; |
---|
370 | } |
---|
371 | |
---|
372 | $items[] = $newItem; |
---|
373 | } |
---|
374 | } |
---|
375 | |
---|
376 | /** |
---|
377 | * Function which marks existing occurrence to 'Complete' |
---|
378 | *@param array $recur array action from client |
---|
379 | *@return array of properties of regenerated task else false |
---|
380 | */ |
---|
381 | function markOccurrenceComplete(&$recur) |
---|
382 | { |
---|
383 | // Fix timezone object |
---|
384 | $this->tz = false; |
---|
385 | $this->action =& $recur; |
---|
386 | $dead_occurrence = isset($this->messageprops[$this->proptags['dead_occurrence']]) ? $this->messageprops[$this->proptags['dead_occurrence']] : false; |
---|
387 | |
---|
388 | if (!$dead_occurrence) { |
---|
389 | return $this->moveToNextOccurrence(); |
---|
390 | } |
---|
391 | |
---|
392 | return false; |
---|
393 | } |
---|
394 | |
---|
395 | /** |
---|
396 | * Function which sets reminder on recurring task after existing occurrence has been deleted or marked complete. |
---|
397 | *@param array $nextOccurrence properties of next occurrence |
---|
398 | */ |
---|
399 | function setReminder($nextOccurrence) |
---|
400 | { |
---|
401 | $props = array(); |
---|
402 | if ($nextOccurrence) { |
---|
403 | // Check if reminder is reset. Default is 'false' |
---|
404 | $reset_reminder = isset($this->messageprops[$this->proptags['reset_reminder']]) ? $this->messageprops[$this->proptags['reset_reminder']] : false; |
---|
405 | $reminder = $this->messageprops[$this->proptags['reminder']]; |
---|
406 | |
---|
407 | // Either reminder was already set OR reminder was set but was dismissed bty user |
---|
408 | if ($reminder || $reset_reminder) { |
---|
409 | // Reminder can be set at any time either before or after the duedate, so get duration between the reminder time and duedate |
---|
410 | $reminder_time = isset($this->messageprops[$this->proptags['reminder_time']]) ? $this->messageprops[$this->proptags['reminder_time']] : 0; |
---|
411 | $reminder_difference = isset($this->messageprops[$this->proptags['duedate']]) ? $this->messageprops[$this->proptags['duedate']] : 0; |
---|
412 | $reminder_difference = $reminder_difference - $reminder_time; |
---|
413 | |
---|
414 | // Apply duration to next calculated duedate |
---|
415 | $next_reminder_time = $nextOccurrence[$this->proptags['duedate']] - $reminder_difference; |
---|
416 | |
---|
417 | $props[$this->proptags['reminder_time']] = $next_reminder_time; |
---|
418 | $props[$this->proptags['flagdueby']] = $next_reminder_time; |
---|
419 | $this->action['reminder'] = $props[$this->proptags['reminder']] = true; |
---|
420 | } |
---|
421 | } else { |
---|
422 | // Didn't get next occurrence, probably this is the last occurrence |
---|
423 | $props[$this->proptags['reminder']] = false; |
---|
424 | $props[$this->proptags['reset_reminder']] = false; |
---|
425 | } |
---|
426 | |
---|
427 | if (!empty($props)) |
---|
428 | mapi_setprops($this->message, $props); |
---|
429 | } |
---|
430 | |
---|
431 | /** |
---|
432 | * Function which recurring task to next occurrence. |
---|
433 | * It simply doesn't regenerate task |
---|
434 | @param array $action |
---|
435 | */ |
---|
436 | function deleteOccurrence($action) |
---|
437 | { |
---|
438 | $this->tz = false; |
---|
439 | $this->action = $action; |
---|
440 | $result = $this->moveToNextOccurrence(); |
---|
441 | |
---|
442 | mapi_savechanges($this->message); |
---|
443 | |
---|
444 | return $result; |
---|
445 | } |
---|
446 | |
---|
447 | /** |
---|
448 | * Convert from windows-1252 encoded string to UTF-8 string |
---|
449 | * |
---|
450 | * The same conversion rules as utf8_to_windows1252 apply. |
---|
451 | * |
---|
452 | * @param string $string the Windows-1252 string to convert |
---|
453 | * @return string UTF-8 representation of the string |
---|
454 | */ |
---|
455 | function windows1252_to_utf8($string) |
---|
456 | { |
---|
457 | if (function_exists("iconv")){ |
---|
458 | return iconv("Windows-1252", "UTF-8//TRANSLIT", $string); |
---|
459 | }else{ |
---|
460 | return utf8_encode($string); // no euro support here |
---|
461 | } |
---|
462 | } |
---|
463 | } |
---|
464 | ?> |
---|