source: trunk/zpush/lib/request/getitemestimate.php @ 7589

Revision 7589, 12.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      :   getitemestimate.php
4* Project   :   Z-Push
5* Descr     :   Provides the GETITEMESTIMATE command
6*
7* Created   :   16.02.2012
8*
9* Copyright 2007 - 2012 Zarafa Deutschland GmbH
10*
11* This program is free software: you can redistribute it and/or modify
12* it under the terms of the GNU Affero General Public License, version 3,
13* as published by the Free Software Foundation with the following additional
14* term according to sec. 7:
15*
16* According to sec. 7 of the GNU Affero General Public License, version 3,
17* the terms of the AGPL are supplemented with the following terms:
18*
19* "Zarafa" is a registered trademark of Zarafa B.V.
20* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
21* The licensing of the Program under the AGPL does not imply a trademark license.
22* Therefore any rights, title and interest in our trademarks remain entirely with us.
23*
24* However, if you propagate an unmodified version of the Program you are
25* allowed to use the term "Z-Push" to indicate that you distribute the Program.
26* Furthermore you may use our trademarks where it is necessary to indicate
27* the intended purpose of a product or service provided you use it in accordance
28* with honest practices in industrial or commercial matters.
29* If you want to propagate modified versions of the Program under the name "Z-Push",
30* you may only do so if you have a written permission by Zarafa Deutschland GmbH
31* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
32*
33* This program is distributed in the hope that it will be useful,
34* but WITHOUT ANY WARRANTY; without even the implied warranty of
35* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36* GNU Affero General Public License for more details.
37*
38* You should have received a copy of the GNU Affero General Public License
39* along with this program.  If not, see <http://www.gnu.org/licenses/>.
40*
41* Consult LICENSE file for details
42************************************************/
43
44class GetItemEstimate extends RequestProcessor {
45
46    /**
47     * Handles the GetItemEstimate command
48     * Returns an estimation of how many items will be synchronized at the next sync
49     * This is mostly used to show something in the progress bar
50     *
51     * @param int       $commandCode
52     *
53     * @access public
54     * @return boolean
55     */
56    public function Handle($commandCode) {
57        $sc = new SyncCollections();
58
59        if(!self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_GETITEMESTIMATE))
60            return false;
61
62        if(!self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERS))
63            return false;
64
65        while(self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDER)) {
66            $spa = new SyncParameters();
67            $spastatus = false;
68
69            // read the folder properties
70            while (1) {
71                if(self::$decoder->getElementStartTag(SYNC_SYNCKEY)) {
72                    try {
73                        $spa->SetSyncKey(self::$decoder->getElementContent());
74                    }
75                    catch (StateInvalidException $siex) {
76                        $spastatus = SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED;
77                    }
78
79                    if(!self::$decoder->getElementEndTag())
80                        return false;
81                }
82
83                elseif(self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERID)) {
84                    $spa->SetFolderId( self::$decoder->getElementContent());
85
86                    if(!self::$decoder->getElementEndTag())
87                        return false;
88                }
89
90                // conversation mode requested
91                elseif(self::$decoder->getElementStartTag(SYNC_CONVERSATIONMODE)) {
92                    $spa->SetConversationMode(true);
93                    if(($conversationmode = self::$decoder->getElementContent()) !== false) {
94                        $spa->SetConversationMode((boolean)$conversationmode);
95                        if(!self::$decoder->getElementEndTag())
96                            return false;
97                    }
98                }
99
100                // get items estimate does not necessarily send the folder type
101                elseif(self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERTYPE)) {
102                    $spa->SetContentClass(self::$decoder->getElementContent());
103
104                    if(!self::$decoder->getElementEndTag())
105                        return false;
106                }
107
108                //TODO AS 2.5 and filtertype not set
109                elseif(self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) {
110                    $spa->SetFilterType(self::$decoder->getElementContent());
111
112                    if(!self::$decoder->getElementEndTag())
113                        return false;
114                }
115
116                while(self::$decoder->getElementStartTag(SYNC_OPTIONS)) {
117                    while(1) {
118                        $firstOption = true;
119                        // foldertype definition
120                        if(self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) {
121                            $foldertype = self::$decoder->getElementContent();
122                            ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleGetItemEstimate(): specified options block with foldertype '%s'", $foldertype));
123
124                            // switch the foldertype for the next options
125                            $spa->UseCPO($foldertype);
126
127                            // set to synchronize all changes. The mobile could overwrite this value
128                            $spa->SetFilterType(SYNC_FILTERTYPE_ALL);
129
130                            if(!self::$decoder->getElementEndTag())
131                                return false;
132                        }
133                        // if no foldertype is defined, use default cpo
134                        else if ($firstOption){
135                            $spa->UseCPO();
136                            // set to synchronize all changes. The mobile could overwrite this value
137                            $spa->SetFilterType(SYNC_FILTERTYPE_ALL);
138                        }
139                        $firstOption = false;
140
141                        if(self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) {
142                            $spa->SetFilterType(self::$decoder->getElementContent());
143                            if(!self::$decoder->getElementEndTag())
144                                return false;
145                        }
146
147                        if(self::$decoder->getElementStartTag(SYNC_MAXITEMS)) {
148                            $spa->SetWindowSize($maxitems = self::$decoder->getElementContent());
149                            if(!self::$decoder->getElementEndTag())
150                                return false;
151                        }
152
153                        $e = self::$decoder->peek();
154                        if($e[EN_TYPE] == EN_TYPE_ENDTAG) {
155                            self::$decoder->getElementEndTag();
156                            break;
157                        }
158                    }
159                }
160
161                $e = self::$decoder->peek();
162                if($e[EN_TYPE] == EN_TYPE_ENDTAG) {
163                    self::$decoder->getElementEndTag(); //SYNC_GETITEMESTIMATE_FOLDER
164                    break;
165                }
166            }
167            // Process folder data
168
169            //In AS 14 request only collectionid is sent, without class
170            if (! $spa->HasContentClass() && $spa->HasFolderId()) {
171               try {
172                    $spa->SetContentClass(self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId()));
173                }
174                catch (NoHierarchyCacheAvailableException $nhca) {
175                    $spastatus = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID;
176                }
177            }
178
179            // compatibility mode AS 1.0 - get folderid which was sent during GetHierarchy()
180            if (! $spa->HasFolderId() && $spa->HasContentClass()) {
181                $spa->SetFolderId(self::$deviceManager->GetFolderIdFromCacheByClass($spa->GetContentClass()));
182            }
183
184            // Add collection to SC and load state
185            $sc->AddCollection($spa);
186            if ($spastatus) {
187                // the CPO has a folder id now, so we can set the status
188                $sc->AddParameter($spa, "status", $spastatus);
189            }
190            else {
191                try {
192                    $sc->AddParameter($spa, "state", self::$deviceManager->GetStateManager()->GetSyncState($spa->GetSyncKey()));
193
194                    // if this is an additional folder the backend has to be setup correctly
195                    if (!self::$backend->Setup(ZPush::GetAdditionalSyncFolderStore($spa->GetFolderId())))
196                        throw new StatusException(sprintf("HandleGetItemEstimate() could not Setup() the backend for folder id '%s'", $spa->GetFolderId()), SYNC_GETITEMESTSTATUS_COLLECTIONINVALID);
197                }
198                catch (StateNotFoundException $snfex) {
199                    // ok, the key is invalid. Question is, if the hierarchycache is still ok
200                    //if not, we have to issue SYNC_GETITEMESTSTATUS_COLLECTIONINVALID which triggers a FolderSync
201                    try {
202                        self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId());
203                        // we got here, so the HierarchyCache is ok
204                        $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCKKEYINVALID);
205                    }
206                    catch (NoHierarchyCacheAvailableException $nhca) {
207                        $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID);
208                    }
209
210                    self::$topCollector->AnnounceInformation("StateNotFoundException ". $sc->GetParameter($spa, "status"), true);
211                }
212                catch (StatusException $stex) {
213                    if ($stex->getCode() == SYNC_GETITEMESTSTATUS_COLLECTIONINVALID)
214                        $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID);
215                    else
216                        $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED);
217                    self::$topCollector->AnnounceInformation("StatusException ". $sc->GetParameter($spa, "status"), true);
218                }
219            }
220
221        }
222        if(!self::$decoder->getElementEndTag())
223            return false; //SYNC_GETITEMESTIMATE_FOLDERS
224
225        if(!self::$decoder->getElementEndTag())
226            return false; //SYNC_GETITEMESTIMATE_GETITEMESTIMATE
227
228        self::$encoder->startWBXML();
229        self::$encoder->startTag(SYNC_GETITEMESTIMATE_GETITEMESTIMATE);
230        {
231            $status = SYNC_GETITEMESTSTATUS_SUCCESS;
232            // look for changes in all collections
233
234            try {
235                $sc->CountChanges();
236            }
237            catch (StatusException $ste) {
238                $status = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID;
239            }
240            $changes = $sc->GetChangedFolderIds();
241
242            foreach($sc as $folderid => $spa) {
243                self::$encoder->startTag(SYNC_GETITEMESTIMATE_RESPONSE);
244                {
245                    if ($sc->GetParameter($spa, "status"))
246                        $status = $sc->GetParameter($spa, "status");
247
248                    self::$encoder->startTag(SYNC_GETITEMESTIMATE_STATUS);
249                    self::$encoder->content($status);
250                    self::$encoder->endTag();
251
252                    self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDER);
253                    {
254                        self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDERTYPE);
255                        self::$encoder->content($spa->GetContentClass());
256                        self::$encoder->endTag();
257
258                        self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDERID);
259                        self::$encoder->content($spa->GetFolderId());
260                        self::$encoder->endTag();
261
262                        if (isset($changes[$folderid]) && $changes[$folderid] !== false) {
263                            self::$encoder->startTag(SYNC_GETITEMESTIMATE_ESTIMATE);
264                            self::$encoder->content($changes[$folderid]);
265                            self::$encoder->endTag();
266
267                            if ($changes[$folderid] > 0)
268                                self::$topCollector->AnnounceInformation(sprintf("%s %d changes", $spa->GetContentClass(), $changes[$folderid]), true);
269                        }
270                    }
271                    self::$encoder->endTag();
272                }
273                self::$encoder->endTag();
274            }
275            if (array_sum($changes) == 0)
276                self::$topCollector->AnnounceInformation("No changes found", true);
277        }
278        self::$encoder->endTag();
279
280        return true;
281    }
282}
283?>
Note: See TracBrowser for help on using the repository browser.