source: trunk/zpush/lib/core/syncparameters.php @ 7589

Revision 7589, 14.0 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      :   syncparameters.php
4* Project   :   Z-Push
5* Descr     :   Transportation container for
6*               requested content parameters and information
7*               about the container and states
8*
9* Created   :   11.04.2011
10*
11* Copyright 2007 - 2012 Zarafa Deutschland GmbH
12*
13* This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU Affero General Public License, version 3,
15* as published by the Free Software Foundation with the following additional
16* term according to sec. 7:
17*
18* According to sec. 7 of the GNU Affero General Public License, version 3,
19* the terms of the AGPL are supplemented with the following terms:
20*
21* "Zarafa" is a registered trademark of Zarafa B.V.
22* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
23* The licensing of the Program under the AGPL does not imply a trademark license.
24* Therefore any rights, title and interest in our trademarks remain entirely with us.
25*
26* However, if you propagate an unmodified version of the Program you are
27* allowed to use the term "Z-Push" to indicate that you distribute the Program.
28* Furthermore you may use our trademarks where it is necessary to indicate
29* the intended purpose of a product or service provided you use it in accordance
30* with honest practices in industrial or commercial matters.
31* If you want to propagate modified versions of the Program under the name "Z-Push",
32* you may only do so if you have a written permission by Zarafa Deutschland GmbH
33* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
34*
35* This program is distributed in the hope that it will be useful,
36* but WITHOUT ANY WARRANTY; without even the implied warranty of
37* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38* GNU Affero General Public License for more details.
39*
40* You should have received a copy of the GNU Affero General Public License
41* along with this program.  If not, see <http://www.gnu.org/licenses/>.
42*
43* Consult LICENSE file for details
44************************************************/
45
46class SyncParameters extends StateObject {
47    const DEFAULTOPTIONS = "DEFAULT";
48    const EMAILOPTIONS = "EMAIL";
49    const CALENDAROPTIONS = "CALENDAR";
50    const CONTACTOPTIONS = "CONTACTS";
51    const NOTEOPTIONS = "NOTES";
52    const TASKOPTIONS = "TASKS";
53    const SMSOPTIONS = "SMS";
54
55    private $synckeyChanged = false;
56    private $currentCPO = self::DEFAULTOPTIONS;
57
58    protected $unsetdata = array(
59                                    'uuid' => false,
60                                    'uuidcounter' => false,
61                                    'uuidnewcounter' => false,
62                                    'folderid' => false,
63                                    'referencelifetime' => 10,
64                                    'lastsynctime' => false,
65                                    'referencepolicykey' => true,
66                                    'pingableflag' => false,
67                                    'contentclass' => false,
68                                    'deletesasmoves' => false,
69                                    'conversationmode' => false,
70                                    'windowsize' => 5,
71                                    'contentparameters' => array()
72                                );
73
74    /**
75     * SyncParameters constructor
76     */
77    public function SyncParameters() {
78        // initialize ContentParameters for the current option
79        $this->checkCPO();
80    }
81
82
83    /**
84     * SyncKey methods
85     *
86     * The current and next synckey is saved as uuid and counter
87     * so partial and ping can access the latest states.
88     */
89
90    /**
91     * Returns the latest SyncKey of this folder
92     *
93     * @access public
94     * @return string/boolean       false if no uuid/counter available
95     */
96    public function GetSyncKey() {
97        if (isset($this->uuid) && isset($this->uuidCounter))
98            return StateManager::BuildStateKey($this->uuid, $this->uuidCounter);
99
100        return false;
101    }
102
103    /**
104     * Sets the the current synckey.
105     * This is done by parsing it and saving uuid and counter.
106     * By setting the current key, the "next" key is obsolete
107     *
108     * @param string    $synckey
109     *
110     * @access public
111     * @return boolean
112     */
113    public function SetSyncKey($synckey) {
114        list($this->uuid, $this->uuidCounter) = StateManager::ParseStateKey($synckey);
115
116        // remove newSyncKey
117        unset($this->uuidNewCounter);
118
119        return true;
120    }
121
122    /**
123     * Indicates if this folder has a synckey
124     *
125     * @access public
126     * @return booleans
127     */
128    public function HasSyncKey() {
129        return (isset($this->uuid) && isset($this->uuidCounter));
130    }
131
132    /**
133     * Sets the the next synckey.
134     * This is done by parsing it and saving uuid and next counter.
135     * if the folder has no synckey until now (new sync), the next counter becomes current asl well.
136     *
137     * @param string    $synckey
138     *
139     * @access public
140     * @throws FatalException       if the uuids of current and next do not match
141     * @return boolean
142     */
143    public function SetNewSyncKey($synckey) {
144        list($uuid, $uuidNewCounter) = StateManager::ParseStateKey($synckey);
145        if (!$this->HasSyncKey()) {
146            $this->uuid = $uuid;
147            $this->uuidCounter = $uuidNewCounter;
148        }
149        else if ($uuid !== $this->uuid)
150            throw new FatalException("SyncParameters->SetNewSyncKey(): new SyncKey must have the same UUID as current SyncKey");
151
152        $this->uuidNewCounter = $uuidNewCounter;
153        $this->synckeyChanged = true;
154    }
155
156    /**
157     * Returns the next synckey
158     *
159     * @access public
160     * @return string/boolean       returns false if uuid or counter are not available
161     */
162    public function GetNewSyncKey() {
163        if (isset($this->uuid) && isset($this->uuidNewCounter))
164            return StateManager::BuildStateKey($this->uuid, $this->uuidNewCounter);
165
166        return false;
167    }
168
169    /**
170     * Indicates if the folder has a next synckey
171     *
172     * @access public
173     * @return boolean
174     */
175    public function HasNewSyncKey() {
176        return (isset($this->uuid) && isset($this->uuidNewCounter));
177    }
178
179    /**
180     * Return the latest synckey.
181     * When this is called the new key becomes the current key (if a new key is available).
182     * The current key is then returned.
183     *
184     * @access public
185     * @return string
186     */
187    public function GetLatestSyncKey() {
188        // New becomes old
189        if ($this->HasUuidNewCounter()) {
190            $this->uuidCounter = $this->uuidNewCounter;
191            unset($this->uuidNewCounter);
192        }
193
194        ZLog::Write(LOGLEVEL_DEBUG, sprintf("SyncParameters->GetLastestSyncKey(): '%s'", $this->GetSyncKey()));
195        return $this->GetSyncKey();
196    }
197
198    /**
199     * Removes the saved SyncKey of this folder
200     *
201     * @access public
202     * @return boolean
203     */
204    public function RemoveSyncKey() {
205        if (isset($this->uuid))
206            unset($this->uuid);
207
208        if (isset($this->uuidCounter))
209            unset($this->uuidCounter);
210
211        if (isset($this->uuidNewCounter))
212            unset($this->uuidNewCounter);
213
214        ZLog::Write(LOGLEVEL_DEBUG, "SyncParameters->RemoveSyncKey(): saved sync key removed");
215        return true;
216    }
217
218
219    /**
220     * CPO methods
221     *
222     * A sync request can have several options blocks. Each block is saved into an own CPO object
223     *
224     */
225
226    /**
227     * Returns the a specified CPO
228     *
229     * @param string    $options    (opt) If not specified, the default Options (CPO) will be used
230     *                              Valid option SyncParameters::SMSOPTIONS (string "SMS")
231     *
232     * @access public
233     * @return ContentParameters object
234     */
235    public function GetCPO($options = self::DEFAULTOPTIONS) {
236        $options = strtoupper($options);
237        $this->isValidType($options);
238        $options = $this->normalizeType($options);
239
240        $this->checkCPO($options);
241
242        // copy contentclass and conversationmode to the CPO
243        $this->contentParameters[$options]->SetContentClass($this->contentclass);
244        $this->contentParameters[$options]->SetConversationMode($this->conversationmode);
245
246        return $this->contentParameters[$options];
247    }
248
249    /**
250     * Use the submitted CPO type for next setters/getters
251     *
252     * @param string    $options    (opt) If not specified, the default Options (CPO) will be used
253     *                              Valid option SyncParameters::SMSOPTIONS (string "SMS")
254     *
255     * @access public
256     * @return
257     */
258    public function UseCPO($options = self::DEFAULTOPTIONS) {
259        $options = strtoupper($options);
260        $this->isValidType($options);
261
262        // remove potential old default CPO if available
263        if (isset($this->contentParameters[self::DEFAULTOPTIONS]) && $options != self::DEFAULTOPTIONS && $options !== self::SMSOPTIONS) {
264            $a = $this->contentParameters;
265            unset($a[self::DEFAULTOPTIONS]);
266            $this->contentParameters = $a;
267            ZLog::Write(LOGLEVEL_DEBUG, "SyncParameters->UseCPO(): removed existing DEFAULT CPO as it is obsolete");
268        }
269
270        ZLOG::Write(LOGLEVEL_DEBUG, sprintf("SyncParameters->UseCPO('%s')", $options));
271        $this->currentCPO = $options;
272        $this->checkCPO($this->currentCPO);
273    }
274
275    /**
276     * Checks if a CPO is correctly inicialized and inicializes it if necessary
277     *
278     * @param string    $options    (opt) If not specified, the default Options (CPO) will be used
279     *                              Valid option SyncParameters::SMSOPTIONS (string "SMS")
280     *
281     * @access private
282     * @return boolean
283     */
284    private function checkCPO($options = self::DEFAULTOPTIONS) {
285        $this->isValidType($options);
286
287        if (!isset($this->contentParameters[$options])) {
288            $a = $this->contentParameters;
289            $a[$options] = new ContentParameters();
290            $this->contentParameters = $a;
291        }
292
293        return true;
294    }
295
296    /**
297     * Checks if the requested option type is available
298     *
299     * @param string $options   CPO type
300     *
301     * @access private
302     * @return boolean
303     * @throws FatalNotImplementedException
304     */
305     private function isValidType($options) {
306         if ($options !== self::DEFAULTOPTIONS &&
307                        $options !== self::EMAILOPTIONS &&
308                        $options !== self::CALENDAROPTIONS &&
309                        $options !== self::CONTACTOPTIONS &&
310                        $options !== self::NOTEOPTIONS &&
311                        $options !== self::TASKOPTIONS &&
312                        $options !== self::SMSOPTIONS)
313            throw new FatalNotImplementedException(sprintf("SyncParameters->isAllowedType('%s') ContentParameters is invalid. Such type is not available.", $options));
314
315        return true;
316    }
317
318    /**
319     * Normalizes the requested option type and returns it as
320     * default option if no default is available
321     *
322     * @param string $options   CPO type
323     *
324     * @access private
325     * @return string
326     * @throws FatalNotImplementedException
327     */
328     private function normalizeType($options) {
329        // return the requested CPO as it is defined
330        if (isset($this->contentParameters[$options]))
331            return $options;
332
333        $returnCPO = $options;
334        // return email, calendar, contact or note CPO as default CPO if there no explicit default CPO defined
335        if ($options == self::DEFAULTOPTIONS && !isset($this->contentParameters[self::DEFAULTOPTIONS])) {
336
337            if (isset($this->contentParameters[self::EMAILOPTIONS]))
338                $returnCPO = self::EMAILOPTIONS;
339            elseif (isset($this->contentParameters[self::CALENDAROPTIONS]))
340                $returnCPO = self::CALENDAROPTIONS;
341            elseif (isset($this->contentParameters[self::CONTACTOPTIONS]))
342                $returnCPO = self::CONTACTOPTIONS;
343            elseif (isset($this->contentParameters[self::NOTEOPTIONS]))
344                $returnCPO = self::NOTEOPTIONS;
345            elseif (isset($this->contentParameters[self::TASKOPTIONS]))
346                $returnCPO = self::TASKOPTIONS;
347
348            if ($returnCPO != $options)
349                ZLog::Write(LOGLEVEL_DEBUG, sprintf("SyncParameters->normalizeType(): using %s for requested %s", $returnCPO, $options));
350            return $returnCPO;
351        }
352        // something unexpected happened, just return default, empty in the worst case
353        else {
354            ZLog::Write(LOGLEVEL_WARN, "SyncParameters->normalizeType(): no DEFAULT CPO available, creating empty CPO");
355            $this->checkCPO(self::DEFAULTOPTIONS);
356            return self::DEFAULTOPTIONS;
357        }
358    }
359
360
361    /**
362     * PHP magic to implement any getter, setter, has and delete operations
363     * on an instance variable.
364     *
365     * NOTICE: All magic getters and setters of this object which are not defined in the unsetdata array are passed to the current CPO.
366     *
367     * Methods like e.g. "SetVariableName($x)" and "GetVariableName()" are supported
368     *
369     * @access public
370     * @return mixed
371     */
372    public function __call($name, $arguments) {
373        $lowname = strtolower($name);
374        $operator = substr($lowname, 0,3);
375        $var = substr($lowname,3);
376
377        if (array_key_exists($var, $this->unsetdata)) {
378            return parent::__call($name, $arguments);
379        }
380
381        return $this->contentParameters[$this->currentCPO]->__call($name, $arguments);
382    }
383
384
385    /**
386     * un/serialization methods
387     */
388
389    /**
390     * Called before the StateObject is serialized
391     *
392     * @access protected
393     * @return boolean
394     */
395    protected function preSerialize() {
396        parent::preSerialize();
397
398        if ($this->changed === true && $this->synckeyChanged)
399            $this->lastsynctime = time();
400
401        return true;
402    }
403
404    /**
405     * Called after the StateObject was unserialized
406     *
407     * @access protected
408     * @return boolean
409     */
410    protected function postUnserialize() {
411        // init with default options
412        $this->UseCPO();
413
414        return true;
415    }
416}
417?>
Note: See TracBrowser for help on using the repository browser.