Passed
Push — master ( fa02f2...bc9f14 )
by
unknown
02:45
created

GrommunioSyncState::getCurrentToken()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 11
rs 10
1
<?php
2
3
/*
4
 * SPDX-License-Identifier: AGPL-3.0-only
5
 * SPDX-FileCopyrightText: Copyright 2016 - 2018 Kopano b.v.
6
 * SPDX-FileCopyrightText: Copyright 2020-2024 grommunio GmbH
7
 *
8
 * Class for handling sync state.
9
 */
10
11
namespace grommunio\DAV;
12
13
class GrommunioSyncState {
14
	private $db;
15
	private $logger;
16
17
	/**
18
	 * Constructor.
19
	 *
20
	 * @param GLogger $logger
21
	 * @param string  $dbstring
22
	 */
23
	public function __construct($logger, $dbstring) {
24
		$this->logger = $logger;
25
		$this->logger->trace("Using db %s", $dbstring);
26
		$this->db = new \PDO($dbstring);
27
28
		$query = "CREATE TABLE IF NOT EXISTS gdav_sync_state (
29
		          id VARCHAR(255), folderid VARCHAR(255), value TEXT,
30
		          PRIMARY KEY (id, folderid));
31
		          CREATE TABLE IF NOT EXISTS gdav_sync_appttsref (
32
		          sourcekey VARCHAR(255), folderid VARCHAR(255), appttsref VARCHAR(255),
33
		          PRIMARY KEY (sourcekey, folderid));
34
		          CREATE INDEX IF NOT EXISTS idx_appttsref ON gdav_sync_appttsref(appttsref);
35
		          CREATE TABLE IF NOT EXISTS gdav_sync_state_current (
36
		          folderid VARCHAR(255) PRIMARY KEY, token VARCHAR(255));";
37
38
		$this->db->exec($query);
39
	}
40
41
	/**
42
	 * Fetch state information for a folderId (e.g. calenderId) and an id (uuid).
43
	 *
44
	 * @param string $folderid
45
	 * @param string $id
46
	 *
47
	 * @return null|string
48
	 */
49
	public function getState($folderid, $id) {
50
		$query = "SELECT value FROM gdav_sync_state WHERE folderid = :folderid AND id = :id";
51
		$statement = $this->db->prepare($query);
52
		$statement->bindParam(":folderid", $folderid);
53
		$statement->bindParam(":id", $id);
54
		$statement->execute();
55
		$result = $statement->fetch();
56
		if (!$result) {
57
			return null;
58
		}
59
60
		return $result['value'];
61
	}
62
63
	/**
64
	 * Set state information for a folderId (e.g. calenderId) and an id (uuid).
65
	 * The state information is the sync token for ICS.
66
	 *
67
	 * @param string $folderid
68
	 * @param string $id
69
	 * @param string $value
70
	 */
71
	public function setState($folderid, $id, $value) {
72
		$query = "REPLACE INTO gdav_sync_state (id, folderid, value) VALUES(:id, :folderid, :value)";
73
		$statement = $this->db->prepare($query);
74
		$statement->bindParam(":folderid", $folderid);
75
		$statement->bindParam(":id", $id);
76
		$statement->bindParam(":value", $value);
77
		$statement->execute();
78
79
		$this->setCurrentToken($folderid, $id);
80
	}
81
82
	/**
83
	 * Returns the latest sync token assigned to the folder.
84
	 *
85
	 * @param string $folderid
86
	 *
87
	 * @return null|string
88
	 */
89
	public function getCurrentToken($folderid) {
90
		$query = "SELECT token FROM gdav_sync_state_current WHERE folderid = :folderid";
91
		$statement = $this->db->prepare($query);
92
		$statement->bindParam(":folderid", $folderid);
93
		$statement->execute();
94
		$result = $statement->fetch();
95
		if (!$result) {
96
			return null;
97
		}
98
99
		return $result['token'];
100
	}
101
102
	/**
103
	 * Persists the current sync token for the folder.
104
	 *
105
	 * @param string      $folderid
106
	 * @param null|string $token
107
	 */
108
	private function setCurrentToken($folderid, $token) {
109
		if ($token === null) {
110
			return;
111
		}
112
113
		$query = "REPLACE INTO gdav_sync_state_current (folderid, token) VALUES (:folderid, :token)";
114
		$statement = $this->db->prepare($query);
115
		$statement->bindParam(":folderid", $folderid);
116
		$statement->bindParam(":token", $token);
117
		$statement->execute();
118
	}
119
120
	/**
121
	 * Set the APPTTSREF (custom URL) for a folderId and source key.
122
	 * This is needed for detecting the URL of deleted items reported by ICS.
123
	 *
124
	 * @param string $folderid
125
	 * @param string $sourcekey
126
	 * @param string $appttsref
127
	 */
128
	public function rememberAppttsref($folderid, $sourcekey, $appttsref) {
129
		$query = "REPLACE INTO gdav_sync_appttsref (folderid, sourcekey, appttsref) VALUES(:folderid, :sourcekey, :appttsref)";
130
		$statement = $this->db->prepare($query);
131
		$statement->bindParam(":folderid", $folderid);
132
		$statement->bindParam(":sourcekey", $sourcekey);
133
		$statement->bindParam(":appttsref", $appttsref);
134
		$statement->execute();
135
	}
136
137
	/**
138
	 * Get the APPTTSREF (custom URL) for a folderId and source key.
139
	 * This is needed for detecting the URL of deleted items reported by ICS.
140
	 *
141
	 * @param string $folderid
142
	 * @param string $sourcekey
143
	 *
144
	 * @return null|string
145
	 */
146
	public function getAppttsref($folderid, $sourcekey) {
147
		$query = "SELECT appttsref FROM gdav_sync_appttsref WHERE folderid = :folderid AND sourcekey = :sourcekey";
148
		$statement = $this->db->prepare($query);
149
		$statement->bindParam(":folderid", $folderid);
150
		$statement->bindParam(":sourcekey", $sourcekey);
151
		$statement->execute();
152
		$result = $statement->fetch();
153
		if (!$result) {
154
			return null;
155
		}
156
157
		return $result['appttsref'];
158
	}
159
160
	/**
161
	 * Get the sourcekey from the saved APPTTSREF (custom URL) and a folderId.
162
	 * This is the last resort when searching for an item in the store fails.
163
	 *
164
	 * @param string $folderid
165
	 * @param string $appttsref
166
	 *
167
	 * @return null|string
168
	 */
169
	public function getSourcekey($folderid, $appttsref) {
170
		$query = "SELECT sourcekey FROM gdav_sync_appttsref WHERE folderid = :folderid AND appttsref = :appttsref";
171
		$statement = $this->db->prepare($query);
172
		$statement->bindParam(":folderid", $folderid);
173
		$statement->bindParam(":appttsref", $appttsref);
174
		$statement->execute();
175
		$result = $statement->fetch();
176
		if (!$result) {
177
			return null;
178
		}
179
180
		return $result['sourcekey'];
181
	}
182
}
183