source: trunk/zpush/lib/default/diffbackend/exportchangesdiff.php @ 7589

Revision 7589, 9.1 KB checked in by douglas, 11 years ago (diff)

Ticket #3209 - Integrar módulo de sincronização Z-push ao Expresso

Line 
1<?php
2/***********************************************
3* File      :   exportchangesdiff.php
4* Project   :   Z-Push
5* Descr     :   IExportChanges implementation using
6*               the differential engine
7*
8* Created   :   02.01.2012
9*
10* Copyright 2007 - 2012 Zarafa Deutschland GmbH
11*
12* This program is free software: you can redistribute it and/or modify
13* it under the terms of the GNU Affero General Public License, version 3,
14* as published by the Free Software Foundation with the following additional
15* term according to sec. 7:
16*
17* According to sec. 7 of the GNU Affero General Public License, version 3,
18* the terms of the AGPL are supplemented with the following terms:
19*
20* "Zarafa" is a registered trademark of Zarafa B.V.
21* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
22* The licensing of the Program under the AGPL does not imply a trademark license.
23* Therefore any rights, title and interest in our trademarks remain entirely with us.
24*
25* However, if you propagate an unmodified version of the Program you are
26* allowed to use the term "Z-Push" to indicate that you distribute the Program.
27* Furthermore you may use our trademarks where it is necessary to indicate
28* the intended purpose of a product or service provided you use it in accordance
29* with honest practices in industrial or commercial matters.
30* If you want to propagate modified versions of the Program under the name "Z-Push",
31* you may only do so if you have a written permission by Zarafa Deutschland GmbH
32* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
33*
34* This program is distributed in the hope that it will be useful,
35* but WITHOUT ANY WARRANTY; without even the implied warranty of
36* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37* GNU Affero General Public License for more details.
38*
39* You should have received a copy of the GNU Affero General Public License
40* along with this program.  If not, see <http://www.gnu.org/licenses/>.
41*
42* Consult LICENSE file for details
43************************************************/
44
45class ExportChangesDiff extends DiffState implements IExportChanges{
46    private $importer;
47    private $folderid;
48    private $contentparameters;
49    private $cutoffdate;
50    private $changes;
51    private $step;
52
53    /**
54     * Constructor
55     *
56     * @param object        $backend
57     * @param string        $folderid
58     *
59     * @access public
60     * @throws StatusException
61     */
62    public function ExportChangesDiff($backend, $folderid) {
63        $this->backend = $backend;
64        $this->folderid = $folderid;
65    }
66
67    /**
68     * Configures additional parameters used for content synchronization
69     *
70     * @param ContentParameters         $contentparameters
71     *
72     * @access public
73     * @return boolean
74     * @throws StatusException
75     */
76    public function ConfigContentParameters($contentparameters) {
77        $this->contentparameters = $contentparameters;
78        $this->cutoffdate = Utils::GetCutOffDate($contentparameters->GetFilterType());
79    }
80
81    /**
82     * Sets the importer the exporter will sent it's changes to
83     * and initializes the Exporter
84     *
85     * @param object        &$importer  Implementation of IImportChanges
86     *
87     * @access public
88     * @return boolean
89     * @throws StatusException
90     */
91    public function InitializeExporter(&$importer) {
92        $this->changes = array();
93        $this->step = 0;
94        $this->importer = $importer;
95
96        if($this->folderid) {
97            // Get the changes since the last sync
98            if(!isset($this->syncstate) || !$this->syncstate)
99                $this->syncstate = array();
100
101            ZLog::Write(LOGLEVEL_DEBUG,sprintf("ExportChangesDiff->InitializeExporter(): Initializing message diff engine. '%d' messages in state", count($this->syncstate)));
102
103            //do nothing if it is a dummy folder
104            if ($this->folderid != SYNC_FOLDER_TYPE_DUMMY) {
105                // Get our lists - syncstate (old)  and msglist (new)
106                $msglist = $this->backend->GetMessageList($this->folderid, $this->cutoffdate);
107                // if the folder was deleted, no information is available anymore. A hierarchysync should be executed
108                if($msglist === false)
109                    throw new StatusException("ExportChangesDiff->InitializeExporter(): Error, no message list available from the backend", SYNC_STATUS_FOLDERHIERARCHYCHANGED, null, LOGLEVEL_INFO);
110
111                $this->changes = $this->getDiffTo($msglist);
112            }
113        }
114        else {
115            ZLog::Write(LOGLEVEL_DEBUG, "Initializing folder diff engine");
116
117            ZLog::Write(LOGLEVEL_DEBUG, "ExportChangesDiff->InitializeExporter(): Initializing folder diff engine");
118
119            $folderlist = $this->backend->GetFolderList();
120            if($folderlist === false)
121                throw new StatusException("ExportChangesDiff->InitializeExporter(): error, no folders available from the backend", SYNC_FSSTATUS_CODEUNKNOWN, null, LOGLEVEL_WARN);
122
123            if(!isset($this->syncstate) || !$this->syncstate)
124                $this->syncstate = array();
125
126            $this->changes = $this->getDiffTo($folderlist);
127        }
128
129        ZLog::Write(LOGLEVEL_INFO, sprintf("ExportChangesDiff->InitializeExporter(): Found '%d' changes", count($this->changes) ));
130    }
131
132    /**
133     * Returns the amount of changes to be exported
134     *
135     * @access public
136     * @return int
137     */
138    public function GetChangeCount() {
139        return count($this->changes);
140    }
141
142    /**
143     * Synchronizes a change
144     *
145     * @access public
146     * @return array
147     */
148    public function Synchronize() {
149        $progress = array();
150
151        // Get one of our stored changes and send it to the importer, store the new state if
152        // it succeeds
153        if($this->folderid == false) {
154            if($this->step < count($this->changes)) {
155                $change = $this->changes[$this->step];
156
157                switch($change["type"]) {
158                    case "change":
159                        $folder = $this->backend->GetFolder($change["id"]);
160                        $stat = $this->backend->StatFolder($change["id"]);
161
162                        if(!$folder)
163                            return;
164
165                        if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportFolderChange($folder))
166                            $this->updateState("change", $stat);
167                        break;
168                    case "delete":
169                        if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportFolderDeletion($change["id"]))
170                            $this->updateState("delete", $change);
171                        break;
172                }
173
174                $this->step++;
175
176                $progress = array();
177                $progress["steps"] = count($this->changes);
178                $progress["progress"] = $this->step;
179
180                return $progress;
181            } else {
182                return false;
183            }
184        }
185        else {
186            if($this->step < count($this->changes)) {
187                $change = $this->changes[$this->step];
188
189                switch($change["type"]) {
190                    case "change":
191                        // Note: because 'parseMessage' and 'statMessage' are two seperate
192                        // calls, we have a chance that the message has changed between both
193                        // calls. This may cause our algorithm to 'double see' changes.
194
195                        $stat = $this->backend->StatMessage($this->folderid, $change["id"]);
196                        $message = $this->backend->GetMessage($this->folderid, $change["id"], $this->contentparameters);
197
198                        // copy the flag to the message
199                        $message->flags = (isset($change["flags"])) ? $change["flags"] : 0;
200
201                        if($stat && $message) {
202                            if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportMessageChange($change["id"], $message) == true)
203                                $this->updateState("change", $stat);
204                        }
205                        break;
206                    case "delete":
207                        if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportMessageDeletion($change["id"]) == true)
208                            $this->updateState("delete", $change);
209                        break;
210                    case "flags":
211                        if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportMessageReadFlag($change["id"], $change["flags"]) == true)
212                            $this->updateState("flags", $change);
213                        break;
214                    case "move":
215                        if($this->flags & BACKEND_DISCARD_DATA || $this->importer->ImportMessageMove($change["id"], $change["parent"]) == true)
216                            $this->updateState("move", $change);
217                        break;
218                }
219
220                $this->step++;
221
222                $progress = array();
223                $progress["steps"] = count($this->changes);
224                $progress["progress"] = $this->step;
225
226                return $progress;
227            } else {
228                return false;
229            }
230        }
231    }
232}
233
234?>
Note: See TracBrowser for help on using the repository browser.