Back to index

d-push  2.0
class.freebusypublish.php
Go to the documentation of this file.
00001 <?php
00002 /*
00003  * Copyright 2005 - 2012  Zarafa B.V.
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU Affero General Public License, version 3,
00007  * as published by the Free Software Foundation with the following additional
00008  * term according to sec. 7:
00009  *
00010  * According to sec. 7 of the GNU Affero General Public License, version
00011  * 3, the terms of the AGPL are supplemented with the following terms:
00012  *
00013  * "Zarafa" is a registered trademark of Zarafa B.V. The licensing of
00014  * the Program under the AGPL does not imply a trademark license.
00015  * Therefore any rights, title and interest in our trademarks remain
00016  * entirely with us.
00017  *
00018  * However, if you propagate an unmodified version of the Program you are
00019  * allowed to use the term "Zarafa" to indicate that you distribute the
00020  * Program. Furthermore you may use our trademarks where it is necessary
00021  * to indicate the intended purpose of a product or service provided you
00022  * use it in accordance with honest practices in industrial or commercial
00023  * matters.  If you want to propagate modified versions of the Program
00024  * under the name "Zarafa" or "Zarafa Server", you may only do so if you
00025  * have a written permission by Zarafa B.V. (to acquire a permission
00026  * please contact Zarafa at trademark@zarafa.com).
00027  *
00028  * The interactive user interface of the software displays an attribution
00029  * notice containing the term "Zarafa" and/or the logo of Zarafa.
00030  * Interactive user interfaces of unmodified and modified versions must
00031  * display Appropriate Legal Notices according to sec. 5 of the GNU
00032  * Affero General Public License, version 3, when you propagate
00033  * unmodified or modified versions of the Program. In accordance with
00034  * sec. 7 b) of the GNU Affero General Public License, version 3, these
00035  * Appropriate Legal Notices must retain the logo of Zarafa or display
00036  * the words "Initial Development by Zarafa" if the display of the logo
00037  * is not reasonably feasible for technical reasons. The use of the logo
00038  * of Zarafa in Legal Notices is allowed for unmodified and modified
00039  * versions of the software.
00040  *
00041  * This program is distributed in the hope that it will be useful,
00042  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00043  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00044  * GNU Affero General Public License for more details.
00045  *
00046  * You should have received a copy of the GNU Affero General Public License
00047  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00048  *
00049  */
00050 
00051 
00052 include_once('backend/zarafa/mapi/class.recurrence.php');
00053 
00054 class FreeBusyPublish {
00055 
00056     var $session;
00057     var $calendar;
00058     var $entryid;
00059     var $starttime;
00060     var $length;
00061     var $store;
00062     var $proptags;
00063 
00073     function FreeBusyPublish($session, $store, $calendar, $entryid)
00074     {
00075         $properties["entryid"] = PR_ENTRYID;
00076         $properties["parent_entryid"] = PR_PARENT_ENTRYID;
00077         $properties["message_class"] = PR_MESSAGE_CLASS;
00078         $properties["icon_index"] = PR_ICON_INDEX;
00079         $properties["subject"] = PR_SUBJECT;
00080         $properties["display_to"] = PR_DISPLAY_TO;
00081         $properties["importance"] = PR_IMPORTANCE;
00082         $properties["sensitivity"] = PR_SENSITIVITY;
00083         $properties["startdate"] = "PT_SYSTIME:PSETID_Appointment:0x820d";
00084         $properties["duedate"] = "PT_SYSTIME:PSETID_Appointment:0x820e";
00085         $properties["recurring"] = "PT_BOOLEAN:PSETID_Appointment:0x8223";
00086         $properties["recurring_data"] = "PT_BINARY:PSETID_Appointment:0x8216";
00087         $properties["busystatus"] = "PT_LONG:PSETID_Appointment:0x8205";
00088         $properties["label"] = "PT_LONG:PSETID_Appointment:0x8214";
00089         $properties["alldayevent"] = "PT_BOOLEAN:PSETID_Appointment:0x8215";
00090         $properties["private"] = "PT_BOOLEAN:PSETID_Common:0x8506";
00091         $properties["meeting"] = "PT_LONG:PSETID_Appointment:0x8217";
00092         $properties["startdate_recurring"] = "PT_SYSTIME:PSETID_Appointment:0x8235";
00093         $properties["enddate_recurring"] = "PT_SYSTIME:PSETID_Appointment:0x8236";
00094         $properties["location"] = "PT_STRING8:PSETID_Appointment:0x8208";
00095         $properties["duration"] = "PT_LONG:PSETID_Appointment:0x8213";
00096         $properties["responsestatus"] = "PT_LONG:PSETID_Appointment:0x8218";
00097         $properties["reminder"] = "PT_BOOLEAN:PSETID_Common:0x8503";
00098         $properties["reminder_minutes"] = "PT_LONG:PSETID_Common:0x8501";
00099         $properties["contacts"] = "PT_MV_STRING8:PSETID_Common:0x853a";
00100         $properties["contacts_string"] = "PT_STRING8:PSETID_Common:0x8586";
00101         $properties["categories"] = "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords";
00102         $properties["reminder_time"] = "PT_SYSTIME:PSETID_Common:0x8502";
00103         $properties["commonstart"] = "PT_SYSTIME:PSETID_Common:0x8516";
00104         $properties["commonend"] = "PT_SYSTIME:PSETID_Common:0x8517";
00105         $properties["basedate"] = "PT_SYSTIME:PSETID_Appointment:0x8228";
00106         $properties["timezone_data"] = "PT_BINARY:PSETID_Appointment:0x8233";
00107         $this->proptags = getPropIdsFromStrings($store, $properties);
00108 
00109         $this->session = $session;
00110         $this->calendar = $calendar;
00111         $this->entryid = $entryid;
00112         $this->store = $store;
00113     }
00114 
00120     function publishFB($starttime, $length) {
00121         $start = $starttime;
00122         $end = $starttime + $length;
00123 
00124         // Get all the items in the calendar that we need
00125 
00126         $calendaritems = Array();
00127 
00128         $restrict = Array(RES_OR,
00129                              Array(
00130                                    // OR
00131                                    // (item[start] >= start && item[start] <= end)
00132                                    Array(RES_AND,
00133                                          Array(
00134                                                Array(RES_PROPERTY,
00135                                                      Array(RELOP => RELOP_GE,
00136                                                            ULPROPTAG => $this->proptags["startdate"],
00137                                                            VALUE => $start
00138                                                            )
00139                                                      ),
00140                                                Array(RES_PROPERTY,
00141                                                      Array(RELOP => RELOP_LE,
00142                                                            ULPROPTAG => $this->proptags["startdate"],
00143                                                            VALUE => $end
00144                                                            )
00145                                                      )
00146                                                )
00147                                          ),
00148                                    // OR
00149                                    // (item[end]   >= start && item[end]   <= end)
00150                                    Array(RES_AND,
00151                                          Array(
00152                                                Array(RES_PROPERTY,
00153                                                      Array(RELOP => RELOP_GE,
00154                                                            ULPROPTAG => $this->proptags["duedate"],
00155                                                            VALUE => $start
00156                                                            )
00157                                                      ),
00158                                                Array(RES_PROPERTY,
00159                                                      Array(RELOP => RELOP_LE,
00160                                                            ULPROPTAG => $this->proptags["duedate"],
00161                                                            VALUE => $end
00162                                                            )
00163                                                      )
00164                                                )
00165                                          ),
00166                                    // OR
00167                                    // (item[start] <  start && item[end]   >  end)
00168                                    Array(RES_AND,
00169                                          Array(
00170                                                Array(RES_PROPERTY,
00171                                                      Array(RELOP => RELOP_LT,
00172                                                            ULPROPTAG => $this->proptags["startdate"],
00173                                                            VALUE => $start
00174                                                            )
00175                                                      ),
00176                                                Array(RES_PROPERTY,
00177                                                      Array(RELOP => RELOP_GT,
00178                                                            ULPROPTAG => $this->proptags["duedate"],
00179                                                            VALUE => $end
00180                                                            )
00181                                                      )
00182                                                )
00183                                          ),
00184                                    // OR
00185                                    Array(RES_OR,
00186                                          Array(
00187                                                // OR
00188                                                // (EXIST(ecurrence_enddate_property) && item[isRecurring] == true && item[end] >= start)
00189                                                Array(RES_AND,
00190                                                      Array(
00191                                                            Array(RES_EXIST,
00192                                                                  Array(ULPROPTAG => $this->proptags["enddate_recurring"],
00193                                                                        )
00194                                                                  ),
00195                                                            Array(RES_PROPERTY,
00196                                                                  Array(RELOP => RELOP_EQ,
00197                                                                        ULPROPTAG => $this->proptags["recurring"],
00198                                                                        VALUE => true
00199                                                                        )
00200                                                                  ),
00201                                                            Array(RES_PROPERTY,
00202                                                                  Array(RELOP => RELOP_GE,
00203                                                                        ULPROPTAG => $this->proptags["enddate_recurring"],
00204                                                                        VALUE => $start
00205                                                                        )
00206                                                                  )
00207                                                            )
00208                                                      ),
00209                                                // OR
00210                                                // (!EXIST(ecurrence_enddate_property) && item[isRecurring] == true && item[start] <= end)
00211                                                Array(RES_AND,
00212                                                      Array(
00213                                                            Array(RES_NOT,
00214                                                                  Array(
00215                                                                        Array(RES_EXIST,
00216                                                                              Array(ULPROPTAG => $this->proptags["enddate_recurring"]
00217                                                                                    )
00218                                                                              )
00219                                                                        )
00220                                                                  ),
00221                                                            Array(RES_PROPERTY,
00222                                                                  Array(RELOP => RELOP_LE,
00223                                                                        ULPROPTAG => $this->proptags["startdate"],
00224                                                                        VALUE => $end
00225                                                                        )
00226                                                                  ),
00227                                                            Array(RES_PROPERTY,
00228                                                                  Array(RELOP => RELOP_EQ,
00229                                                                        ULPROPTAG => $this->proptags["recurring"],
00230                                                                        VALUE => true
00231                                                                        )
00232                                                                  )
00233                                                            )
00234                                                      )
00235                                                )
00236                                          ) // EXISTS OR
00237                                    )
00238                              );        // global OR
00239 
00240         $contents = mapi_folder_getcontentstable($this->calendar);
00241         mapi_table_restrict($contents, $restrict);
00242 
00243         while(1) {
00244             $rows = mapi_table_queryrows($contents, array_values($this->proptags), 0, 50);
00245 
00246             if(!is_array($rows))
00247                 break;
00248 
00249             if(empty($rows))
00250                 break;
00251 
00252             foreach ($rows as $row) {
00253                 $occurrences = Array();
00254                 if(isset($row[$this->proptags['recurring']]) && $row[$this->proptags['recurring']]) {
00255                     $recur = new Recurrence($this->store, $row);
00256 
00257                     $occurrences = $recur->getItems($starttime, $starttime + $length);
00258                 } else {
00259                     $occurrences[] = $row;
00260                 }
00261 
00262                 $calendaritems = array_merge($calendaritems, $occurrences);
00263             }
00264         }
00265 
00266         // $calendaritems now contains all the calendar items in the specified time
00267         // frame. We now need to merge these into a flat array of begin/end/status
00268         // objects. This also filters out all the 'free' items (status 0)
00269 
00270         $freebusy = $this->mergeItemsFB($calendaritems);
00271 
00272         // $freebusy now contains the start, end and status of all items, merged.
00273 
00274         // Get the FB interface
00275         try {
00276             $fbsupport = mapi_freebusysupport_open($this->session, $this->store);
00277         } catch (MAPIException $e) {
00278             if($e->getCode() == MAPI_E_NOT_FOUND) {
00279                 $e->setHandled();
00280                 if(function_exists("dump")) {
00281                     dump("Error in opening freebusysupport object.");
00282                 }
00283             }
00284         }
00285 
00286         // Open updater for this user
00287         if(isset($fbsupport)) {
00288             $updaters = mapi_freebusysupport_loadupdate($fbsupport, Array($this->entryid));
00289 
00290             $updater = $updaters[0];
00291 
00292             // Send the data
00293             mapi_freebusyupdate_reset($updater);
00294             mapi_freebusyupdate_publish($updater, $freebusy);
00295             mapi_freebusyupdate_savechanges($updater, $start-24*60*60, $end);
00296 
00297             // We're finished
00298             mapi_freebusysupport_close($fbsupport);
00299         }
00300     }
00301 
00305     function cmp($a, $b)
00306     {
00307         if ($a["time"] == $b["time"]) {
00308             if($a["type"] < $b["type"])
00309                 return 1;
00310             if($a["type"] > $b["type"])
00311                 return -1;
00312             return 0;
00313         }
00314         return ($a["time"] > $b["time"] ? 1 : -1);
00315     }
00316 
00321     function mergeItemsFB($items)
00322     {
00323         $merged = Array();
00324         $timestamps = Array();
00325         $csubj = Array();
00326         $cbusy = Array();
00327         $level = 0;
00328         $laststart = null;
00329 
00330         foreach($items as $item)
00331         {
00332             $ts["type"] = 0;
00333             $ts["time"] = $item[$this->proptags["startdate"]];
00334             $ts["subject"] = $item[PR_SUBJECT];
00335             $ts["status"] = $item[$this->proptags["busystatus"]];
00336             $timestamps[] = $ts;
00337 
00338             $ts["type"] = 1;
00339             $ts["time"] = $item[$this->proptags["duedate"]];
00340             $ts["subject"] = $item[PR_SUBJECT];
00341             $ts["status"] = $item[$this->proptags["busystatus"]];
00342             $timestamps[] = $ts;
00343         }
00344 
00345         usort($timestamps, Array($this, "cmp"));
00346         $laststart = 0; // seb added
00347 
00348         foreach($timestamps as $ts)
00349         {
00350             switch ($ts["type"])
00351             {
00352                 case 0: // Start
00353                     if ($level != 0 && $laststart != $ts["time"])
00354                     {
00355                         $newitem["start"] = $laststart;
00356                         $newitem["end"] = $ts["time"];
00357                         $newitem["subject"] = join(",", $csubj);
00358                         $newitem["status"] = !empty($cbusy) ? max($cbusy) : 0;
00359                         if($newitem["status"] > 0)
00360                             $merged[] = $newitem;
00361                     }
00362 
00363                     $level++;
00364 
00365                     $csubj[] = $ts["subject"];
00366                     $cbusy[] = $ts["status"];
00367 
00368                     $laststart = $ts["time"];
00369                     break;
00370                 case 1: // End
00371                     if ($laststart != $ts["time"])
00372                     {
00373                         $newitem["start"] = $laststart;
00374                         $newitem["end"] = $ts["time"];
00375                         $newitem["subject"] = join(",", $csubj);
00376                         $newitem["status"] = !empty($cbusy) ? max($cbusy) : 0;
00377                         if($newitem["status"] > 0)
00378                             $merged[] = $newitem;
00379                     }
00380 
00381                     $level--;
00382 
00383                     array_splice($csubj, array_search($ts["subject"], $csubj, 1), 1);
00384                     array_splice($cbusy, array_search($ts["status"], $cbusy, 1), 1);
00385 
00386                     $laststart = $ts["time"];
00387                     break;
00388             }
00389         }
00390 
00391         return $merged;
00392     }
00393 
00394 }
00395 ?>