Back to index

d-push  2.0
exportchangesdiff.php
Go to the documentation of this file.
00001 <?php
00002 /***********************************************
00003 * File      :   exportchangesdiff.php
00004 * Project   :   Z-Push
00005 * Descr     :   IExportChanges implementation using
00006 *               the differential engine
00007 *
00008 * Created   :   02.01.2012
00009 *
00010 * Copyright 2007 - 2012 Zarafa Deutschland GmbH
00011 *
00012 * This program is free software: you can redistribute it and/or modify
00013 * it under the terms of the GNU Affero General Public License, version 3,
00014 * as published by the Free Software Foundation with the following additional
00015 * term according to sec. 7:
00016 *
00017 * According to sec. 7 of the GNU Affero General Public License, version 3,
00018 * the terms of the AGPL are supplemented with the following terms:
00019 *
00020 * "Zarafa" is a registered trademark of Zarafa B.V.
00021 * "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
00022 * The licensing of the Program under the AGPL does not imply a trademark license.
00023 * Therefore any rights, title and interest in our trademarks remain entirely with us.
00024 *
00025 * However, if you propagate an unmodified version of the Program you are
00026 * allowed to use the term "Z-Push" to indicate that you distribute the Program.
00027 * Furthermore you may use our trademarks where it is necessary to indicate
00028 * the intended purpose of a product or service provided you use it in accordance
00029 * with honest practices in industrial or commercial matters.
00030 * If you want to propagate modified versions of the Program under the name "Z-Push",
00031 * you may only do so if you have a written permission by Zarafa Deutschland GmbH
00032 * (to acquire a permission please contact Zarafa at trademark@zarafa.com).
00033 *
00034 * This program is distributed in the hope that it will be useful,
00035 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00036 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00037 * GNU Affero General Public License for more details.
00038 *
00039 * You should have received a copy of the GNU Affero General Public License
00040 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00041 *
00042 * Consult LICENSE file for details
00043 ************************************************/
00044 
00045 class ExportChangesDiff extends DiffState implements IExportChanges{
00046     private $importer;
00047     private $folderid;
00048     private $contentparameters;
00049     private $cutoffdate;
00050     private $changes;
00051     private $step;
00052 
00062     public function ExportChangesDiff($backend, $folderid) {
00063         $this->backend = $backend;
00064         $this->folderid = $folderid;
00065     }
00066 
00076     public function ConfigContentParameters($contentparameters) {
00077         $this->contentparameters = $contentparameters;
00078         $this->cutoffdate = Utils::GetCutOffDate($contentparameters->GetFilterType());
00079     }
00080 
00091     public function InitializeExporter(&$importer) {
00092         $this->changes = array();
00093         $this->step = 0;
00094         $this->importer = $importer;
00095 
00096         if($this->folderid) {
00097             // Get the changes since the last sync
00098             if(!isset($this->syncstate) || !$this->syncstate)
00099                 $this->syncstate = array();
00100 
00101             ZLog::Write(LOGLEVEL_DEBUG,sprintf("ExportChangesDiff->InitializeExporter(): Initializing message diff engine. '%d' messages in state", count($this->syncstate)));
00102 
00103             //do nothing if it is a dummy folder
00104             if ($this->folderid != SYNC_FOLDER_TYPE_DUMMY) {
00105                 // Get our lists - syncstate (old)  and msglist (new)
00106                 $msglist = $this->backend->GetMessageList($this->folderid, $this->cutoffdate);
00107                 // if the folder was deleted, no information is available anymore. A hierarchysync should be executed
00108                 if($msglist === false)
00109                     throw new StatusException("ExportChangesDiff->InitializeExporter(): Error, no message list available from the backend", SYNC_STATUS_FOLDERHIERARCHYCHANGED, null, LOGLEVEL_INFO);
00110 
00111                 $this->changes = $this->getDiffTo($msglist);
00112             }
00113         }
00114         else {
00115             ZLog::Write(LOGLEVEL_DEBUG, "Initializing folder diff engine");
00116 
00117             ZLog::Write(LOGLEVEL_DEBUG, "ExportChangesDiff->InitializeExporter(): Initializing folder diff engine");
00118 
00119             $folderlist = $this->backend->GetFolderList();
00120             if($folderlist === false)
00121                 throw new StatusException("ExportChangesDiff->InitializeExporter(): error, no folders available from the backend", SYNC_FSSTATUS_CODEUNKNOWN, null, LOGLEVEL_WARN);
00122 
00123             if(!isset($this->syncstate) || !$this->syncstate)
00124                 $this->syncstate = array();
00125 
00126             $this->changes = $this->getDiffTo($folderlist);
00127         }
00128 
00129         ZLog::Write(LOGLEVEL_INFO, sprintf("ExportChangesDiff->InitializeExporter(): Found '%d' changes", count($this->changes) ));
00130     }
00131 
00138     public function GetChangeCount() {
00139         return count($this->changes);
00140     }
00141 
00148     public function Synchronize() {
00149         $progress = array();
00150 
00151         // Get one of our stored changes and send it to the importer, store the new state if
00152         // it succeeds
00153         if($this->folderid == false) {
00154             if($this->step < count($this->changes)) {
00155                 $change = $this->changes[$this->step];
00156 
00157                 switch($change["type"]) {
00158                     case "change":
00159                         $folder = $this->backend->GetFolder($change["id"]);
00160                         $stat = $this->backend->StatFolder($change["id"]);
00161 
00162                         if(!$folder)
00163                             return;
00164 
00165                         if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportFolderChange($folder))
00166                             $this->updateState("change", $stat);
00167                         break;
00168                     case "delete":
00169                         if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportFolderDeletion($change["id"]))
00170                             $this->updateState("delete", $change);
00171                         break;
00172                 }
00173 
00174                 $this->step++;
00175 
00176                 $progress = array();
00177                 $progress["steps"] = count($this->changes);
00178                 $progress["progress"] = $this->step;
00179 
00180                 return $progress;
00181             } else {
00182                 return false;
00183             }
00184         }
00185         else {
00186             if($this->step < count($this->changes)) {
00187                 $change = $this->changes[$this->step];
00188 
00189                 switch($change["type"]) {
00190                     case "change":
00191                         // Note: because 'parseMessage' and 'statMessage' are two seperate
00192                         // calls, we have a chance that the message has changed between both
00193                         // calls. This may cause our algorithm to 'double see' changes.
00194 
00195                         $stat = $this->backend->StatMessage($this->folderid, $change["id"]);
00196                         $message = $this->backend->GetMessage($this->folderid, $change["id"], $this->contentparameters);
00197 
00198                         // copy the flag to the message
00199                         $message->flags = (isset($change["flags"])) ? $change["flags"] : 0;
00200 
00201                         if($stat && $message) {
00202                             if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportMessageChange($change["id"], $message) == true)
00203                                 $this->updateState("change", $stat);
00204                         }
00205                         break;
00206                     case "delete":
00207                         if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportMessageDeletion($change["id"]) == true)
00208                             $this->updateState("delete", $change);
00209                         break;
00210                     case "flags":
00211                         if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportMessageReadFlag($change["id"], $change["flags"]) == true)
00212                             $this->updateState("flags", $change);
00213                         break;
00214                     case "move":
00215                         if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportMessageMove($change["id"], $change["parent"]) == true)
00216                             $this->updateState("move", $change);
00217                         break;
00218                 }
00219 
00220                 $this->step++;
00221 
00222                 $progress = array();
00223                 $progress["steps"] = count($this->changes);
00224                 $progress["progress"] = $this->step;
00225 
00226                 return $progress;
00227             } else {
00228                 return false;
00229             }
00230         }
00231     }
00232 }
00233 
00234 ?>