Conditions | 44 |
Paths | > 20000 |
Total Lines | 245 |
Code Lines | 128 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | <?php |
||
18 | public function Handle($commandCode) { |
||
19 | // Parse input |
||
20 | if (!self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_FOLDERSYNC)) { |
||
21 | return false; |
||
22 | } |
||
23 | |||
24 | if (!self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_SYNCKEY)) { |
||
25 | return false; |
||
26 | } |
||
27 | |||
28 | $synckey = self::$decoder->getElementContent(); |
||
29 | |||
30 | if (!self::$decoder->getElementEndTag()) { |
||
31 | return false; |
||
32 | } |
||
33 | |||
34 | // every FolderSync with SyncKey 0 should return the supported AS version & command headers |
||
35 | if ($synckey == "0") { |
||
36 | self::$specialHeaders = []; |
||
37 | self::$specialHeaders[] = GSync::GetSupportedProtocolVersions(); |
||
38 | self::$specialHeaders[] = GSync::GetSupportedCommands(); |
||
39 | } |
||
40 | |||
41 | $status = SYNC_FSSTATUS_SUCCESS; |
||
42 | $newsynckey = $synckey; |
||
43 | |||
44 | try { |
||
45 | $syncstate = self::$deviceManager->GetStateManager()->GetSyncState($synckey); |
||
46 | |||
47 | // We will be saving the sync state under 'newsynckey' |
||
48 | $newsynckey = self::$deviceManager->GetStateManager()->GetNewSyncKey($synckey); |
||
49 | |||
50 | // there are no SyncParameters for the hierarchy, but we use it to save the latest synckeys |
||
51 | $spa = self::$deviceManager->GetStateManager()->GetSynchedFolderState(false); |
||
52 | } |
||
53 | catch (StateNotFoundException $snfex) { |
||
54 | $status = SYNC_FSSTATUS_SYNCKEYERROR; |
||
55 | } |
||
56 | catch (StateInvalidException $sive) { |
||
57 | $status = SYNC_FSSTATUS_SYNCKEYERROR; |
||
58 | } |
||
59 | |||
60 | // The ChangesWrapper caches all imports in-memory, so we can send a change count |
||
61 | // before sending the actual data. |
||
62 | // the HierarchyCache is notified and the changes from the PIM are transmitted to the actual backend |
||
63 | $changesMem = self::$deviceManager->GetHierarchyChangesWrapper(); |
||
64 | |||
65 | // the hierarchyCache should now fully be initialized - check for changes in the additional folders |
||
66 | $changesMem->Config(GSync::GetAdditionalSyncFolders(false), ChangesMemoryWrapper::SYNCHRONIZING); |
||
67 | |||
68 | // reset to default store in backend |
||
69 | self::$backend->Setup(false); |
||
70 | |||
71 | // process incoming changes |
||
72 | if (self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_CHANGES)) { |
||
73 | // Ignore <Count> if present |
||
74 | if (self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_COUNT)) { |
||
75 | self::$decoder->getElementContent(); |
||
76 | if (!self::$decoder->getElementEndTag()) { |
||
77 | return false; |
||
78 | } |
||
79 | } |
||
80 | |||
81 | // Process the changes (either <Add>, <Modify>, or <Remove>) |
||
82 | $element = self::$decoder->getElement(); |
||
83 | |||
84 | if ($element[EN_TYPE] != EN_TYPE_STARTTAG) { |
||
85 | return false; |
||
86 | } |
||
87 | |||
88 | $importer = false; |
||
89 | WBXMLDecoder::ResetInWhile("folderSyncIncomingChange"); |
||
90 | while (WBXMLDecoder::InWhile("folderSyncIncomingChange")) { |
||
91 | $folder = new SyncFolder(); |
||
92 | if (!$folder->Decode(self::$decoder)) { |
||
|
|||
93 | break; |
||
94 | } |
||
95 | |||
96 | // add the backendId to the SyncFolder object |
||
97 | $folder->BackendId = self::$deviceManager->GetBackendIdForFolderId($folder->serverid); |
||
98 | |||
99 | try { |
||
100 | if ($status == SYNC_FSSTATUS_SUCCESS && !$importer) { |
||
101 | // Configure the backends importer with last state |
||
102 | $importer = self::$backend->GetImporter(); |
||
103 | $importer->Config($syncstate); |
||
104 | // the messages from the PIM will be forwarded to the backend |
||
105 | $changesMem->forwardImporter($importer); |
||
106 | } |
||
107 | |||
108 | if ($status == SYNC_FSSTATUS_SUCCESS) { |
||
109 | switch ($element[EN_TAG]) { |
||
110 | case SYNC_ADD: |
||
111 | case SYNC_MODIFY: |
||
112 | $serverid = $changesMem->ImportFolderChange($folder); |
||
113 | break; |
||
114 | |||
115 | case SYNC_REMOVE: |
||
116 | $serverid = $changesMem->ImportFolderDeletion($folder); |
||
117 | break; |
||
118 | } |
||
119 | } |
||
120 | else { |
||
121 | SLog::Write(LOGLEVEL_WARN, sprintf("Request->HandleFolderSync(): ignoring incoming folderchange for folder '%s' as status indicates problem.", $folder->displayname)); |
||
122 | self::$topCollector->AnnounceInformation("Incoming change ignored", true); |
||
123 | } |
||
124 | } |
||
125 | catch (StatusException $stex) { |
||
126 | $status = $stex->getCode(); |
||
127 | } |
||
128 | } |
||
129 | |||
130 | if (!self::$decoder->getElementEndTag()) { |
||
131 | return false; |
||
132 | } |
||
133 | } |
||
134 | // no incoming changes |
||
135 | else { |
||
136 | // check for a potential process loop |
||
137 | if ($synckey != "0" && self::$deviceManager->IsHierarchyFullResyncRequired()) { |
||
138 | $status = SYNC_FSSTATUS_SYNCKEYERROR; |
||
139 | self::$deviceManager->AnnounceProcessStatus(false, $status); |
||
140 | } |
||
141 | } |
||
142 | |||
143 | if (!self::$decoder->getElementEndTag()) { |
||
144 | return false; |
||
145 | } |
||
146 | |||
147 | // We have processed incoming foldersync requests, now send the PIM |
||
148 | // our changes |
||
149 | |||
150 | // Output our WBXML reply now |
||
151 | self::$encoder->StartWBXML(); |
||
152 | |||
153 | self::$encoder->startTag(SYNC_FOLDERHIERARCHY_FOLDERSYNC); |
||
154 | |||
155 | if ($status == SYNC_FSSTATUS_SUCCESS) { |
||
156 | try { |
||
157 | // do nothing if this is an invalid device id (like the 'validate' Androids internal client sends) |
||
158 | if (!Request::IsValidDeviceID()) { |
||
159 | throw new StatusException(sprintf("Request::IsValidDeviceID() indicated that '%s' is not a valid device id", Request::GetDeviceID()), SYNC_FSSTATUS_SERVERERROR); |
||
160 | } |
||
161 | |||
162 | // Changes from backend are sent to the MemImporter and processed for the HierarchyCache. |
||
163 | // The state which is saved is from the backend, as the MemImporter is only a proxy. |
||
164 | $exporter = self::$backend->GetExporter(); |
||
165 | |||
166 | $exporter->Config($syncstate); |
||
167 | $exporter->InitializeExporter($changesMem); |
||
168 | |||
169 | // Stream all changes to the ImportExportChangesMem |
||
170 | $totalChanges = $exporter->GetChangeCount(); |
||
171 | $exported = 0; |
||
172 | $partial = false; |
||
173 | while (is_array($exporter->Synchronize())) { |
||
174 | ++$exported; |
||
175 | |||
176 | if (time() % 4) { |
||
177 | self::$topCollector->AnnounceInformation(sprintf("Exported %d from %d folders", $exported, $totalChanges)); |
||
178 | } |
||
179 | |||
180 | // if partial sync is allowed, stop if this takes too long |
||
181 | if (USE_PARTIAL_FOLDERSYNC && Request::IsRequestTimeoutReached()) { |
||
182 | SLog::Write(LOGLEVEL_WARN, sprintf("Request->HandleFolderSync(): Exporting folders is too slow. In %d seconds only %d from %d changes were processed.", time() - $_SERVER["REQUEST_TIME"], $exported, $totalChanges)); |
||
183 | self::$topCollector->AnnounceInformation(sprintf("Partial export of %d out of %d folders", $exported, $totalChanges), true); |
||
184 | self::$deviceManager->SetFolderSyncComplete(false); |
||
185 | $partial = true; |
||
186 | |||
187 | break; |
||
188 | } |
||
189 | } |
||
190 | |||
191 | // update the foldersync complete flag |
||
192 | if (USE_PARTIAL_FOLDERSYNC && $partial === false && self::$deviceManager->GetFolderSyncComplete() === false) { |
||
193 | // say that we are done with partial syncing |
||
194 | self::$deviceManager->SetFolderSyncComplete(true); |
||
195 | // reset the loop data to prevent any loop detection to kick in now |
||
196 | self::$deviceManager->ClearLoopDetectionData(Request::GetAuthUserString(), Request::GetDeviceID()); |
||
197 | SLog::Write(LOGLEVEL_INFO, "Request->HandleFolderSync(): Chunked exporting of folders completed successfully"); |
||
198 | } |
||
199 | |||
200 | // get the new state from the backend |
||
201 | $newsyncstate = (isset($exporter)) ? $exporter->GetState() : ""; |
||
202 | } |
||
203 | catch (StatusException $stex) { |
||
204 | if ($stex->getCode() == SYNC_FSSTATUS_CODEUNKNOWN) { |
||
205 | $status = SYNC_FSSTATUS_SYNCKEYERROR; |
||
206 | } |
||
207 | else { |
||
208 | $status = $stex->getCode(); |
||
209 | } |
||
210 | } |
||
211 | } |
||
212 | |||
213 | self::$encoder->startTag(SYNC_FOLDERHIERARCHY_STATUS); |
||
214 | self::$encoder->content($status); |
||
215 | self::$encoder->endTag(); |
||
216 | |||
217 | if ($status == SYNC_FSSTATUS_SUCCESS) { |
||
218 | self::$encoder->startTag(SYNC_FOLDERHIERARCHY_SYNCKEY); |
||
219 | $synckey = ($changesMem->IsStateChanged()) ? $newsynckey : $synckey; |
||
220 | self::$encoder->content($synckey); |
||
221 | self::$encoder->endTag(); |
||
222 | |||
223 | // Stream folders directly to the PDA |
||
224 | $streamimporter = new ImportChangesStream(self::$encoder, false); |
||
225 | $changesMem->InitializeExporter($streamimporter); |
||
226 | $changeCount = $changesMem->GetChangeCount(); |
||
227 | |||
228 | self::$encoder->startTag(SYNC_FOLDERHIERARCHY_CHANGES); |
||
229 | |||
230 | self::$encoder->startTag(SYNC_FOLDERHIERARCHY_COUNT); |
||
231 | self::$encoder->content($changeCount); |
||
232 | self::$encoder->endTag(); |
||
233 | while ($changesMem->Synchronize()); |
||
234 | |||
235 | self::$encoder->endTag(); |
||
236 | self::$topCollector->AnnounceInformation(sprintf("Outgoing %d folders", $changeCount), true); |
||
237 | |||
238 | if ($changeCount == 0) { |
||
239 | self::$deviceManager->CheckFolderData(); |
||
240 | } |
||
241 | // everything fine, save the sync state for the next time |
||
242 | if ($synckey == $newsynckey) { |
||
243 | self::$deviceManager->GetStateManager()->SetSyncState($newsynckey, $newsyncstate); |
||
244 | |||
245 | // update SPA & save it |
||
246 | $spa->SetSyncKey($newsynckey); |
||
247 | $spa->SetFolderId(false); |
||
248 | |||
249 | // invalidate all pingable flags |
||
250 | SyncCollections::InvalidatePingableFlags(); |
||
251 | } |
||
252 | // save the SyncParameters if it changed or the reference policy key is not set or different |
||
253 | if ($spa->IsDataChanged() || !$spa->HasReferencePolicyKey() || GSync::GetProvisioningManager()->ProvisioningRequired($spa->GetReferencePolicyKey(), true, false)) { |
||
254 | // saves the SPA (while updating the reference policy key) |
||
255 | $spa->SetLastSynctime(time()); |
||
256 | self::$deviceManager->GetStateManager()->SetSynchedFolderState($spa); |
||
257 | } |
||
258 | } |
||
259 | |||
260 | self::$encoder->endTag(); |
||
261 | |||
262 | return true; |
||
263 | } |
||
265 |
If an expression can have both
false
, andnull
as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.