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

Revision 7589, 10.7 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      :   importchangesdiff.php
4* Project   :   Z-Push
5* Descr     :   IImportChanges 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 ImportChangesDiff extends DiffState implements IImportChanges {
46    private $folderid;
47
48    /**
49     * Constructor
50     *
51     * @param object        $backend
52     * @param string        $folderid
53     *
54     * @access public
55     * @throws StatusException
56     */
57    public function ImportChangesDiff($backend, $folderid = false) {
58        $this->backend = $backend;
59        $this->folderid = $folderid;
60    }
61
62    /**
63     * Would load objects which are expected to be exported with this state
64     * The DiffBackend implements conflict detection on the fly
65     *
66     * @param ContentParameters         $contentparameters         class of objects
67     * @param string                    $state
68     *
69     * @access public
70     * @return boolean
71     * @throws StatusException
72     */
73    public function LoadConflicts($contentparameters, $state) {
74        // changes are detected on the fly
75        return true;
76    }
77
78    /**
79     * Imports a single message
80     *
81     * @param string        $id
82     * @param SyncObject    $message
83     *
84     * @access public
85     * @return boolean/string - failure / id of message
86     * @throws StatusException
87     */
88    public function ImportMessageChange($id, $message) {
89        //do nothing if it is in a dummy folder
90        if ($this->folderid == SYNC_FOLDER_TYPE_DUMMY)
91            throw new StatusException(sprintf("ImportChangesDiff->ImportMessageChange('%s','%s'): can not be done on a dummy folder", $id, get_class($message)), SYNC_STATUS_SYNCCANNOTBECOMPLETED);
92
93        if($id) {
94            // See if there's a conflict
95            $conflict = $this->isConflict("change", $this->folderid, $id);
96
97            // Update client state if this is an update
98            $change = array();
99            $change["id"] = $id;
100            $change["mod"] = 0; // dummy, will be updated later if the change succeeds
101            $change["parent"] = $this->folderid;
102            $change["flags"] = (isset($message->read)) ? $message->read : 0;
103            $this->updateState("change", $change);
104
105            if($conflict && $this->flags == SYNC_CONFLICT_OVERWRITE_PIM)
106                // in these cases the status SYNC_STATUS_CONFLICTCLIENTSERVEROBJECT should be returned, so the mobile client can inform the end user
107                throw new StatusException(sprintf("ImportChangesDiff->ImportMessageChange('%s','%s'): Conflict detected. Data from PIM will be dropped! Server overwrites PIM. User is informed.", $id, get_class($message)), SYNC_STATUS_CONFLICTCLIENTSERVEROBJECT, null, LOGLEVEL_INFO);
108        }
109
110        $stat = $this->backend->ChangeMessage($this->folderid, $id, $message);
111
112        if(!is_array($stat))
113            throw new StatusException(sprintf("ImportChangesDiff->ImportMessageChange('%s','%s'): unknown error in backend", $id, get_class($message)), SYNC_STATUS_SYNCCANNOTBECOMPLETED);
114
115        // Record the state of the message
116        $this->updateState("change", $stat);
117
118        return $stat["id"];
119    }
120
121    /**
122     * Imports a deletion. This may conflict if the local object has been modified
123     *
124     * @param string        $id
125     * @param SyncObject    $message
126     *
127     * @access public
128     * @return boolean
129     * @throws StatusException
130     */
131    public function ImportMessageDeletion($id) {
132        //do nothing if it is in a dummy folder
133        if ($this->folderid == SYNC_FOLDER_TYPE_DUMMY)
134            throw new StatusException(sprintf("ImportChangesDiff->ImportMessageDeletion('%s'): can not be done on a dummy folder", $id), SYNC_STATUS_SYNCCANNOTBECOMPLETED);
135
136        // See if there's a conflict
137        $conflict = $this->isConflict("delete", $this->folderid, $id);
138
139        // Update client state
140        $change = array();
141        $change["id"] = $id;
142        $this->updateState("delete", $change);
143
144        // If there is a conflict, and the server 'wins', then return without performing the change
145        // this will cause the exporter to 'see' the overriding item as a change, and send it back to the PIM
146        if($conflict && $this->flags == SYNC_CONFLICT_OVERWRITE_PIM) {
147            ZLog::Write(LOGLEVEL_INFO, sprintf("ImportChangesDiff->ImportMessageDeletion('%s'): Conflict detected. Data from PIM will be dropped! Object was deleted.", $id));
148            return false;
149        }
150
151        $stat = $this->backend->DeleteMessage($this->folderid, $id);
152        if(!$stat)
153            throw new StatusException(sprintf("ImportChangesDiff->ImportMessageDeletion('%s'): Unknown error in backend", $id), SYNC_STATUS_OBJECTNOTFOUND);
154
155        return true;
156    }
157
158    /**
159     * Imports a change in 'read' flag
160     * This can never conflict
161     *
162     * @param string        $id
163     * @param int           $flags - read/unread
164     *
165     * @access public
166     * @return boolean
167     * @throws StatusException
168     */
169    public function ImportMessageReadFlag($id, $flags) {
170        //do nothing if it is a dummy folder
171        if ($this->folderid == SYNC_FOLDER_TYPE_DUMMY)
172            throw new StatusException(sprintf("ImportChangesDiff->ImportMessageReadFlag('%s','%s'): can not be done on a dummy folder", $id, $flags), SYNC_STATUS_SYNCCANNOTBECOMPLETED);
173
174        // Update client state
175        $change = array();
176        $change["id"] = $id;
177        $change["flags"] = $flags;
178        $this->updateState("flags", $change);
179
180        $stat = $this->backend->SetReadFlag($this->folderid, $id, $flags);
181        if (!$stat)
182            throw new StatusException(sprintf("ImportChangesDiff->ImportMessageReadFlag('%s','%s'): Error, unable retrieve message from backend", $id, $flags), SYNC_STATUS_OBJECTNOTFOUND);
183
184        return true;
185    }
186
187    /**
188     * Imports a move of a message. This occurs when a user moves an item to another folder
189     *
190     * @param string        $id
191     * @param int           $flags - read/unread
192     *
193     * @access public
194     * @return boolean
195     * @throws StatusException
196     */
197    public function ImportMessageMove($id, $newfolder) {
198        // don't move messages from or to a dummy folder (GetHierarchy compatibility)
199        if ($this->folderid == SYNC_FOLDER_TYPE_DUMMY || $newfolder == SYNC_FOLDER_TYPE_DUMMY)
200            throw new StatusException(sprintf("ImportChangesDiff->ImportMessageMove('%s'): can not be done on a dummy folder", $id), SYNC_MOVEITEMSSTATUS_CANNOTMOVE);
201
202        return $this->backend->MoveMessage($this->folderid, $id, $newfolder);
203    }
204
205
206    /**
207     * Imports a change on a folder
208     *
209     * @param object        $folder     SyncFolder
210     *
211     * @access public
212     * @return string       id of the folder
213     * @throws StatusException
214     */
215    public function ImportFolderChange($folder) {
216        $id = $folder->serverid;
217        $parent = $folder->parentid;
218        $displayname = $folder->displayname;
219        $type = $folder->type;
220
221        //do nothing if it is a dummy folder
222        if ($parent == SYNC_FOLDER_TYPE_DUMMY)
223            throw new StatusException(sprintf("ImportChangesDiff->ImportFolderChange('%s'): can not be done on a dummy folder", $id), SYNC_FSSTATUS_SERVERERROR);
224
225        if($id) {
226            $change = array();
227            $change["id"] = $id;
228            $change["mod"] = $displayname;
229            $change["parent"] = $parent;
230            $change["flags"] = 0;
231            $this->updateState("change", $change);
232        }
233
234        $stat = $this->backend->ChangeFolder($parent, $id, $displayname, $type);
235
236        if($stat)
237            $this->updateState("change", $stat);
238
239        return $stat["id"];
240    }
241
242    /**
243     * Imports a folder deletion
244     *
245     * @param string        $id
246     * @param string        $parent id
247     *
248     * @access public
249     * @return int          SYNC_FOLDERHIERARCHY_STATUS
250     * @throws StatusException
251     */
252    public function ImportFolderDeletion($id, $parent = false) {
253        //do nothing if it is a dummy folder
254        if ($parent == SYNC_FOLDER_TYPE_DUMMY)
255            throw new StatusException(sprintf("ImportChangesDiff->ImportFolderDeletion('%s','%s'): can not be done on a dummy folder", $id, $parent), SYNC_FSSTATUS_SERVERERROR);
256
257        // check the foldertype
258        $folder = $this->backend->GetFolder($id);
259        if (isset($folder->type) && Utils::IsSystemFolder($folder->type))
260            throw new StatusException(sprintf("ImportChangesDiff->ImportFolderDeletion('%s','%s'): Error deleting system/default folder", $id, $parent), SYNC_FSSTATUS_SYSTEMFOLDER);
261
262        $ret = $this->backend->DeleteFolder($id, $parent);
263        if (!$ret)
264            throw new StatusException(sprintf("ImportChangesDiff->ImportFolderDeletion('%s','%s'): can not be done on a dummy folder", $id, $parent), SYNC_FSSTATUS_FOLDERDOESNOTEXIST);
265
266        $change = array();
267        $change["id"] = $id;
268
269        $this->updateState("delete", $change);
270
271        return true;
272    }
273}
274
275?>
Note: See TracBrowser for help on using the repository browser.