MoveItems   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 123
rs 10
c 0
b 0
f 0
wmc 21

1 Method

Rating   Name   Duplication   Size   Complexity  
F Handle() 0 115 21
1
<?php
2
/*
3
 * SPDX-License-Identifier: AGPL-3.0-only
4
 * SPDX-FileCopyrightText: Copyright 2007-2016 Zarafa Deutschland GmbH
5
 * SPDX-FileCopyrightText: Copyright 2020-2022 grommunio GmbH
6
 *
7
 * Provides the MOVEITEMS command
8
 */
9
10
class MoveItems extends RequestProcessor {
11
	/**
12
	 * Handles the MoveItems command.
13
	 *
14
	 * @param int $commandCode
15
	 *
16
	 * @return bool
17
	 */
18
	public function Handle($commandCode) {
19
		if (!self::$decoder->getElementStartTag(SYNC_MOVE_MOVES)) {
20
			return false;
21
		}
22
23
		$moves = [];
24
		while (self::$decoder->getElementStartTag(SYNC_MOVE_MOVE)) {
25
			$move = [];
26
			if (self::$decoder->getElementStartTag(SYNC_MOVE_SRCMSGID)) {
27
				$move["srcmsgid"] = self::$decoder->getElementContent();
28
				if (!self::$decoder->getElementEndTag()) {
29
					break;
30
				}
31
			}
32
			if (self::$decoder->getElementStartTag(SYNC_MOVE_SRCFLDID)) {
33
				$move["srcfldid"] = self::$decoder->getElementContent();
34
				if (!self::$decoder->getElementEndTag()) {
35
					break;
36
				}
37
			}
38
			if (self::$decoder->getElementStartTag(SYNC_MOVE_DSTFLDID)) {
39
				$move["dstfldid"] = self::$decoder->getElementContent();
40
				if (!self::$decoder->getElementEndTag()) {
41
					break;
42
				}
43
			}
44
			array_push($moves, $move);
45
46
			if (!self::$decoder->getElementEndTag()) {
47
				return false;
48
			}
49
		}
50
51
		if (!self::$decoder->getElementEndTag()) {
52
			return false;
53
		}
54
55
		self::$encoder->StartWBXML();
56
57
		self::$encoder->startTag(SYNC_MOVE_MOVES);
58
59
		$operationResults = [];
60
		$operationCounter = 0;
61
		$operationTotal = count($moves);
62
		foreach ($moves as $move) {
63
			++$operationCounter;
64
			self::$encoder->startTag(SYNC_MOVE_RESPONSE);
65
			self::$encoder->startTag(SYNC_MOVE_SRCMSGID);
66
			self::$encoder->content($move["srcmsgid"]);
67
			self::$encoder->endTag();
68
69
			$status = SYNC_MOVEITEMSSTATUS_SUCCESS;
70
			$result = false;
71
72
			try {
73
				$sourceBackendFolderId = self::$deviceManager->GetBackendIdForFolderId($move["srcfldid"]);
74
75
				// if the source folder is an additional folder the backend has to be setup correctly
76
				if (!self::$backend->Setup(GSync::GetAdditionalSyncFolderStore($sourceBackendFolderId))) {
77
					throw new StatusException(sprintf("HandleMoveItems() could not Setup() the backend for folder id %s/%s", $move["srcfldid"], $sourceBackendFolderId), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
78
				}
79
80
				$importer = self::$backend->GetImporter($sourceBackendFolderId);
81
				if ($importer === false) {
82
					throw new StatusException(sprintf("HandleMoveItems() could not get an importer for folder id %s/%s", $move["srcfldid"], $sourceBackendFolderId), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
83
				}
84
85
				// get saved SyncParameters of the source folder
86
				$spa = self::$deviceManager->GetStateManager()->GetSynchedFolderState($move["srcfldid"]);
87
				if (!$spa->HasSyncKey()) {
88
					throw new StatusException(sprintf("MoveItems(): Source folder id '%s' is not fully synchronized. Unable to perform operation.", $move["srcfldid"]), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
89
				}
90
91
				$importer->ConfigContentParameters($spa->GetCPO());
92
93
				$result = $importer->ImportMessageMove($move["srcmsgid"], self::$deviceManager->GetBackendIdForFolderId($move["dstfldid"]));
94
				// We discard the standard importer state for now.
95
			}
96
			catch (StatusException $stex) {
97
				if ($stex->getCode() == SYNC_STATUS_FOLDERHIERARCHYCHANGED) { // same as SYNC_FSSTATUS_CODEUNKNOWN
98
					$status = SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID;
99
				}
100
				else {
101
					$status = $stex->getCode();
102
				}
103
			}
104
105
			if ($operationCounter % 10 == 0) {
106
				self::$topCollector->AnnounceInformation(sprintf("Moved %d objects out of %d", $operationCounter, $operationTotal));
107
			}
108
109
			// save the operation result
110
			if (!isset($operationResults[$status])) {
111
				$operationResults[$status] = 0;
112
			}
113
			++$operationResults[$status];
114
115
			self::$encoder->startTag(SYNC_MOVE_STATUS);
116
			self::$encoder->content($status);
117
			self::$encoder->endTag();
118
119
			self::$encoder->startTag(SYNC_MOVE_DSTMSGID);
120
			self::$encoder->content(($result !== false) ? $result : $move["srcmsgid"]);
121
			self::$encoder->endTag();
122
			self::$encoder->endTag();
123
		}
124
125
		self::$topCollector->AnnounceInformation(sprintf("Moved %d - Codes", $operationTotal), true);
126
		foreach ($operationResults as $status => $occurrences) {
127
			self::$topCollector->AnnounceInformation(sprintf("%dx%d", $occurrences, $status), true);
128
		}
129
130
		self::$encoder->endTag();
131
132
		return true;
133
	}
134
}
135