1<?php
2/***********************************************
3* File      :   hierarchycache.php
4* Project   :   Z-Push
5* Descr     :   HierarchyCache implementation
6*
7* Created   :   18.08.2011
8*
9* Copyright 2007 - 2016 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.
14*
15* This program is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU Affero General Public License for more details.
19*
20* You should have received a copy of the GNU Affero General Public License
21* along with this program.  If not, see <http://www.gnu.org/licenses/>.
22*
23* Consult LICENSE file for details
24************************************************/
25
26class HierarchyCache {
27    private $changed = false;
28    protected $cacheById;
29    private $cacheByIdOld;
30
31    /**
32     * Constructor of the HierarchyCache
33     *
34     * @access public
35     * @return
36     */
37    public function __construct() {
38        $this->cacheById = array();
39        $this->cacheByIdOld = $this->cacheById;
40        $this->changed = true;
41    }
42
43    /**
44     * Indicates if the cache was changed
45     *
46     * @access public
47     * @return boolean
48     */
49    public function IsStateChanged() {
50        return $this->changed;
51    }
52
53    /**
54     * Copy current CacheById to memory
55     *
56     * @access public
57     * @return boolean
58     */
59    public function CopyOldState() {
60        $this->cacheByIdOld = $this->cacheById;
61        return true;
62    }
63
64    /**
65     * Returns the SyncFolder object for a folder id
66     * If $oldstate is set, then the data from the previous state is returned
67     *
68     * @param string    $serverid
69     * @param boolean   $oldstate       (optional) by default false
70     *
71     * @access public
72     * @return SyncObject/boolean       false if not found
73     */
74    public function GetFolder($serverid, $oldState = false) {
75        if (!$oldState && array_key_exists($serverid, $this->cacheById)) {
76            return $this->cacheById[$serverid];
77        }
78        else if ($oldState && array_key_exists($serverid, $this->cacheByIdOld)) {
79            return $this->cacheByIdOld[$serverid];
80        }
81        return false;
82    }
83
84    /**
85     * Adds a folder to the HierarchyCache
86     *
87     * @param SyncObject    $folder
88     *
89     * @access public
90     * @return boolean
91     */
92    public function AddFolder($folder) {
93        ZLog::Write(LOGLEVEL_DEBUG, "HierarchyCache: AddFolder() serverid: {$folder->serverid} displayname: {$folder->displayname}");
94
95        // on update the $folder does most of the times not contain a type
96        // we copy the value in this case to the new $folder object
97        if (isset($this->cacheById[$folder->serverid]) && (!isset($folder->type) || $folder->type == false) && isset($this->cacheById[$folder->serverid]->type)) {
98            $folder->type = $this->cacheById[$folder->serverid]->type;
99            ZLog::Write(LOGLEVEL_DEBUG, sprintf("HierarchyCache: AddFolder() is an update: used type '%s' from old object", $folder->type));
100        }
101
102        // add/update
103        $this->cacheById[$folder->serverid] = $folder;
104        $this->changed = true;
105
106        return true;
107    }
108
109    /**
110     * Removes a folder to the HierarchyCache
111     *
112     * @param string    $serverid           id of folder to be removed
113     *
114     * @access public
115     * @return boolean
116     */
117    public function DelFolder($serverid) {
118        $ftype = $this->GetFolder($serverid);
119
120        ZLog::Write(LOGLEVEL_DEBUG, sprintf("HierarchyCache: DelFolder() serverid: '%s' - type: '%s'", $serverid, $ftype->type));
121        unset($this->cacheById[$serverid]);
122        $this->changed = true;
123        return true;
124    }
125
126    /**
127     * Imports a folder array to the HierarchyCache
128     *
129     * @param array     $folders            folders to the HierarchyCache
130     *
131     * @access public
132     * @return boolean
133     */
134    public function ImportFolders($folders) {
135        if (!is_array($folders))
136            return false;
137
138        $this->cacheById = array();
139
140        foreach ($folders as $folder) {
141            if (!isset($folder->type))
142                continue;
143            $this->AddFolder($folder);
144        }
145        return true;
146    }
147
148    /**
149     * Exports all folders from the HierarchyCache
150     *
151     * @param boolean   $oldstate           (optional) by default false
152     *
153     * @access public
154     * @return array
155     */
156    public function ExportFolders($oldstate = false) {
157        if ($oldstate === false)
158            return $this->cacheById;
159        else
160            return $this->cacheByIdOld;
161    }
162
163    /**
164     * Returns all folder objects which were deleted in this operation
165     *
166     * @access public
167     * @return array        with SyncFolder objects
168     */
169    public function GetDeletedFolders() {
170        // diffing the OldCacheById with CacheById we know if folders were deleted
171        return array_diff_key($this->cacheByIdOld, $this->cacheById);
172    }
173
174    /**
175     * Returns some statistics about the HierarchyCache
176     *
177     * @access public
178     * @return string
179     */
180    public function GetStat() {
181        return sprintf("HierarchyCache is %s - Cached objects: %d", ((isset($this->cacheById))?"up":"down"), ((isset($this->cacheById))?count($this->cacheById):"0"));
182    }
183
184    /**
185     * Removes internal data from the object, so this data can not be exposed.
186     *
187     * @access public
188     * @return boolean
189     */
190    public function StripData() {
191        unset($this->changed);
192        unset($this->cacheByIdOld);
193        foreach ($this->cacheById as $id => $folder) {
194            $folder->StripData();
195        }
196        return true;
197    }
198
199    /**
200     * Returns objects which should be persistent
201     * called before serialization
202     *
203     * @access public
204     * @return array
205     */
206    public function __sleep() {
207        return array("cacheById");
208    }
209
210}
211