Passed
Push — master ( 19f1cc...65465b )
by Christoph
37:37 queued 22:17
created
apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php 2 patches
Indentation   +400 added lines, -400 removed lines patch added patch discarded remove patch
@@ -37,404 +37,404 @@
 block discarded – undo
37 37
 
38 38
 class UpdateCalendarResourcesRoomsBackgroundJob extends TimedJob {
39 39
 
40
-	/** @var IResourceManager */
41
-	private $resourceManager;
42
-
43
-	/** @var IRoomManager */
44
-	private $roomManager;
45
-
46
-	/** @var IDBConnection */
47
-	private $dbConnection;
48
-
49
-	/** @var CalDavBackend */
50
-	private $calDavBackend;
51
-
52
-	/**
53
-	 * UpdateCalendarResourcesRoomsBackgroundJob constructor.
54
-	 *
55
-	 * @param IResourceManager $resourceManager
56
-	 * @param IRoomManager $roomManager
57
-	 * @param IDBConnection $dbConnection
58
-	 * @param CalDavBackend $calDavBackend
59
-	 */
60
-	public function __construct(IResourceManager $resourceManager,
61
-								IRoomManager $roomManager,
62
-								IDBConnection $dbConnection,
63
-								CalDavBackend $calDavBackend) {
64
-		$this->resourceManager = $resourceManager;
65
-		$this->roomManager = $roomManager;
66
-		$this->dbConnection = $dbConnection;
67
-		$this->calDavBackend = $calDavBackend;
68
-
69
-		// run once an hour
70
-		$this->setInterval(60 * 60);
71
-	}
72
-
73
-	/**
74
-	 * @param $argument
75
-	 */
76
-	public function run($argument):void {
77
-		$this->runForBackend(
78
-			$this->resourceManager,
79
-			'calendar_resources',
80
-			'calendar_resources_md',
81
-			'resource_id',
82
-			'principals/calendar-resources'
83
-		);
84
-		$this->runForBackend(
85
-			$this->roomManager,
86
-			'calendar_rooms',
87
-			'calendar_rooms_md',
88
-			'room_id',
89
-			'principals/calendar-rooms'
90
-		);
91
-	}
92
-
93
-	/**
94
-	 * Run background-job for one specific backendManager
95
-	 * either ResourceManager or RoomManager
96
-	 *
97
-	 * @param IResourceManager|IRoomManager $backendManager
98
-	 * @param string $dbTable
99
-	 * @param string $dbTableMetadata
100
-	 * @param string $foreignKey
101
-	 * @param string $principalPrefix
102
-	 */
103
-	private function runForBackend($backendManager,
104
-								   string $dbTable,
105
-								   string $dbTableMetadata,
106
-								   string $foreignKey,
107
-								   string $principalPrefix):void {
108
-		$backends = $backendManager->getBackends();
109
-
110
-		foreach ($backends as $backend) {
111
-			$backendId = $backend->getBackendIdentifier();
112
-
113
-			try {
114
-				if ($backend instanceof IResourceBackend) {
115
-					$list = $backend->listAllResources();
116
-				} else {
117
-					$list = $backend->listAllRooms();
118
-				}
119
-			} catch (BackendTemporarilyUnavailableException $ex) {
120
-				continue;
121
-			}
122
-
123
-			$cachedList = $this->getAllCachedByBackend($dbTable, $backendId);
124
-			$newIds = array_diff($list, $cachedList);
125
-			$deletedIds = array_diff($cachedList, $list);
126
-			$editedIds = array_intersect($list, $cachedList);
127
-
128
-			foreach ($newIds as $newId) {
129
-				try {
130
-					if ($backend instanceof IResourceBackend) {
131
-						$resource = $backend->getResource($newId);
132
-					} else {
133
-						$resource = $backend->getRoom($newId);
134
-					}
135
-
136
-					$metadata = [];
137
-					if ($resource instanceof IMetadataProvider) {
138
-						$metadata = $this->getAllMetadataOfBackend($resource);
139
-					}
140
-				} catch (BackendTemporarilyUnavailableException $ex) {
141
-					continue;
142
-				}
143
-
144
-				$id = $this->addToCache($dbTable, $backendId, $resource);
145
-				$this->addMetadataToCache($dbTableMetadata, $foreignKey, $id, $metadata);
146
-				// we don't create the calendar here, it is created lazily
147
-				// when an event is actually scheduled with this resource / room
148
-			}
149
-
150
-			foreach ($deletedIds as $deletedId) {
151
-				$id = $this->getIdForBackendAndResource($dbTable, $backendId, $deletedId);
152
-				$this->deleteFromCache($dbTable, $id);
153
-				$this->deleteMetadataFromCache($dbTableMetadata, $foreignKey, $id);
154
-
155
-				$principalName = implode('-', [$backendId, $deletedId]);
156
-				$this->deleteCalendarDataForResource($principalPrefix, $principalName);
157
-			}
158
-
159
-			foreach ($editedIds as $editedId) {
160
-				$id = $this->getIdForBackendAndResource($dbTable, $backendId, $editedId);
161
-
162
-				try {
163
-					if ($backend instanceof IResourceBackend) {
164
-						$resource = $backend->getResource($editedId);
165
-					} else {
166
-						$resource = $backend->getRoom($editedId);
167
-					}
168
-
169
-					$metadata = [];
170
-					if ($resource instanceof IMetadataProvider) {
171
-						$metadata = $this->getAllMetadataOfBackend($resource);
172
-					}
173
-				} catch (BackendTemporarilyUnavailableException $ex) {
174
-					continue;
175
-				}
176
-
177
-				$this->updateCache($dbTable, $id, $resource);
178
-
179
-				if ($resource instanceof IMetadataProvider) {
180
-					$cachedMetadata = $this->getAllMetadataOfCache($dbTableMetadata, $foreignKey, $id);
181
-					$this->updateMetadataCache($dbTableMetadata, $foreignKey, $id, $metadata, $cachedMetadata);
182
-				}
183
-			}
184
-		}
185
-	}
186
-
187
-	/**
188
-	 * add entry to cache that exists remotely but not yet in cache
189
-	 *
190
-	 * @param string $table
191
-	 * @param string $backendId
192
-	 * @param IResource|IRoom $remote
193
-	 * @return int Insert id
194
-	 */
195
-	private function addToCache(string $table,
196
-								string $backendId,
197
-								$remote):int {
198
-		$query = $this->dbConnection->getQueryBuilder();
199
-		$query->insert($table)
200
-			->values([
201
-				'backend_id' => $query->createNamedParameter($backendId),
202
-				'resource_id' => $query->createNamedParameter($remote->getId()),
203
-				'email' => $query->createNamedParameter($remote->getEMail()),
204
-				'displayname' => $query->createNamedParameter($remote->getDisplayName()),
205
-				'group_restrictions' => $query->createNamedParameter(
206
-					$this->serializeGroupRestrictions(
207
-						$remote->getGroupRestrictions()
208
-					))
209
-			])
210
-			->execute();
211
-		return $query->getLastInsertId();
212
-	}
213
-
214
-	/**
215
-	 * @param string $table
216
-	 * @param string $foreignKey
217
-	 * @param int $foreignId
218
-	 * @param array $metadata
219
-	 */
220
-	private function addMetadataToCache(string $table,
221
-										string $foreignKey,
222
-										int $foreignId,
223
-										array $metadata):void {
224
-		foreach ($metadata as $key => $value) {
225
-			$query = $this->dbConnection->getQueryBuilder();
226
-			$query->insert($table)
227
-				->values([
228
-					$foreignKey => $query->createNamedParameter($foreignId),
229
-					'key' => $query->createNamedParameter($key),
230
-					'value' => $query->createNamedParameter($value),
231
-				])
232
-				->execute();
233
-		}
234
-	}
235
-
236
-	/**
237
-	 * delete entry from cache that does not exist anymore remotely
238
-	 *
239
-	 * @param string $table
240
-	 * @param int $id
241
-	 */
242
-	private function deleteFromCache(string $table,
243
-									 int $id):void {
244
-		$query = $this->dbConnection->getQueryBuilder();
245
-		$query->delete($table)
246
-			->where($query->expr()->eq('id', $query->createNamedParameter($id)))
247
-			->execute();
248
-	}
249
-
250
-	/**
251
-	 * @param string $table
252
-	 * @param string $foreignKey
253
-	 * @param int $id
254
-	 */
255
-	private function deleteMetadataFromCache(string $table,
256
-											 string $foreignKey,
257
-											 int $id):void {
258
-		$query = $this->dbConnection->getQueryBuilder();
259
-		$query->delete($table)
260
-			->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id)))
261
-			->execute();
262
-	}
263
-
264
-	/**
265
-	 * update an existing entry in cache
266
-	 *
267
-	 * @param string $table
268
-	 * @param int $id
269
-	 * @param IResource|IRoom $remote
270
-	 */
271
-	private function updateCache(string $table,
272
-								 int $id,
273
-								 $remote):void {
274
-		$query = $this->dbConnection->getQueryBuilder();
275
-		$query->update($table)
276
-			->set('email', $query->createNamedParameter($remote->getEMail()))
277
-			->set('displayname', $query->createNamedParameter($remote->getDisplayName()))
278
-			->set('group_restrictions', $query->createNamedParameter(
279
-				$this->serializeGroupRestrictions(
280
-					$remote->getGroupRestrictions()
281
-				)))
282
-			->where($query->expr()->eq('id', $query->createNamedParameter($id)))
283
-			->execute();
284
-	}
285
-
286
-	/**
287
-	 * @param string $dbTable
288
-	 * @param string $foreignKey
289
-	 * @param int $id
290
-	 * @param array $metadata
291
-	 * @param array $cachedMetadata
292
-	 */
293
-	private function updateMetadataCache(string $dbTable,
294
-										 string $foreignKey,
295
-										 int $id,
296
-										 array $metadata,
297
-										 array $cachedMetadata):void {
298
-		$newMetadata = array_diff_key($metadata, $cachedMetadata);
299
-		$deletedMetadata = array_diff_key($cachedMetadata, $metadata);
300
-
301
-		foreach ($newMetadata as $key => $value) {
302
-			$query = $this->dbConnection->getQueryBuilder();
303
-			$query->insert($dbTable)
304
-				->values([
305
-					$foreignKey => $query->createNamedParameter($id),
306
-					'key' => $query->createNamedParameter($key),
307
-					'value' => $query->createNamedParameter($value),
308
-				])
309
-				->execute();
310
-		}
311
-
312
-		foreach ($deletedMetadata as $key => $value) {
313
-			$query = $this->dbConnection->getQueryBuilder();
314
-			$query->delete($dbTable)
315
-				->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id)))
316
-				->andWhere($query->expr()->eq('key', $query->createNamedParameter($key)))
317
-				->execute();
318
-		}
319
-
320
-		$existingKeys = array_keys(array_intersect_key($metadata, $cachedMetadata));
321
-		foreach ($existingKeys as $existingKey) {
322
-			if ($metadata[$existingKey] !== $cachedMetadata[$existingKey]) {
323
-				$query = $this->dbConnection->getQueryBuilder();
324
-				$query->update($dbTable)
325
-					->set('value', $query->createNamedParameter($metadata[$existingKey]))
326
-					->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id)))
327
-					->andWhere($query->expr()->eq('key', $query->createNamedParameter($existingKey)))
328
-					->execute();
329
-			}
330
-		}
331
-	}
332
-
333
-	/**
334
-	 * serialize array of group restrictions to store them in database
335
-	 *
336
-	 * @param array $groups
337
-	 * @return string
338
-	 */
339
-	private function serializeGroupRestrictions(array $groups):string {
340
-		return \json_encode($groups);
341
-	}
342
-
343
-	/**
344
-	 * Gets all metadata of a backend
345
-	 *
346
-	 * @param IResource|IRoom $resource
347
-	 * @return array
348
-	 */
349
-	private function getAllMetadataOfBackend($resource):array {
350
-		if (!($resource instanceof IMetadataProvider)) {
351
-			return [];
352
-		}
353
-
354
-		$keys = $resource->getAllAvailableMetadataKeys();
355
-		$metadata = [];
356
-		foreach ($keys as $key) {
357
-			$metadata[$key] = $resource->getMetadataForKey($key);
358
-		}
359
-
360
-		return $metadata;
361
-	}
362
-
363
-	/**
364
-	 * @param string $table
365
-	 * @param string $foreignKey
366
-	 * @param int $id
367
-	 * @return array
368
-	 */
369
-	private function getAllMetadataOfCache(string $table,
370
-										   string $foreignKey,
371
-										   int $id):array {
372
-		$query = $this->dbConnection->getQueryBuilder();
373
-		$query->select(['key', 'value'])
374
-			->from($table)
375
-			->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id)));
376
-		$stmt = $query->execute();
377
-		$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
378
-
379
-		$metadata = [];
380
-		foreach ($rows as $row) {
381
-			$metadata[$row['key']] = $row['value'];
382
-		}
383
-
384
-		return $metadata;
385
-	}
386
-
387
-	/**
388
-	 * Gets all cached rooms / resources by backend
389
-	 *
390
-	 * @param $tableName
391
-	 * @param $backendId
392
-	 * @return array
393
-	 */
394
-	private function getAllCachedByBackend(string $tableName,
395
-										   string $backendId):array {
396
-		$query = $this->dbConnection->getQueryBuilder();
397
-		$query->select('resource_id')
398
-			->from($tableName)
399
-			->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)));
400
-		$stmt = $query->execute();
401
-
402
-		return array_map(function ($row): string {
403
-			return $row['resource_id'];
404
-		}, $stmt->fetchAll());
405
-	}
406
-
407
-	/**
408
-	 * @param $principalPrefix
409
-	 * @param $principalUri
410
-	 */
411
-	private function deleteCalendarDataForResource(string $principalPrefix,
412
-												   string $principalUri):void {
413
-		$calendar = $this->calDavBackend->getCalendarByUri(
414
-			implode('/', [$principalPrefix, $principalUri]),
415
-			CalDavBackend::RESOURCE_BOOKING_CALENDAR_URI);
416
-
417
-		if ($calendar !== null) {
418
-			$this->calDavBackend->deleteCalendar($calendar['id']);
419
-		}
420
-	}
421
-
422
-	/**
423
-	 * @param $table
424
-	 * @param $backendId
425
-	 * @param $resourceId
426
-	 * @return int
427
-	 */
428
-	private function getIdForBackendAndResource(string $table,
429
-												string $backendId,
430
-												string $resourceId):int {
431
-		$query = $this->dbConnection->getQueryBuilder();
432
-		$query->select('id')
433
-			->from($table)
434
-			->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
435
-			->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
436
-		$stmt = $query->execute();
437
-
438
-		return $stmt->fetch()['id'];
439
-	}
40
+    /** @var IResourceManager */
41
+    private $resourceManager;
42
+
43
+    /** @var IRoomManager */
44
+    private $roomManager;
45
+
46
+    /** @var IDBConnection */
47
+    private $dbConnection;
48
+
49
+    /** @var CalDavBackend */
50
+    private $calDavBackend;
51
+
52
+    /**
53
+     * UpdateCalendarResourcesRoomsBackgroundJob constructor.
54
+     *
55
+     * @param IResourceManager $resourceManager
56
+     * @param IRoomManager $roomManager
57
+     * @param IDBConnection $dbConnection
58
+     * @param CalDavBackend $calDavBackend
59
+     */
60
+    public function __construct(IResourceManager $resourceManager,
61
+                                IRoomManager $roomManager,
62
+                                IDBConnection $dbConnection,
63
+                                CalDavBackend $calDavBackend) {
64
+        $this->resourceManager = $resourceManager;
65
+        $this->roomManager = $roomManager;
66
+        $this->dbConnection = $dbConnection;
67
+        $this->calDavBackend = $calDavBackend;
68
+
69
+        // run once an hour
70
+        $this->setInterval(60 * 60);
71
+    }
72
+
73
+    /**
74
+     * @param $argument
75
+     */
76
+    public function run($argument):void {
77
+        $this->runForBackend(
78
+            $this->resourceManager,
79
+            'calendar_resources',
80
+            'calendar_resources_md',
81
+            'resource_id',
82
+            'principals/calendar-resources'
83
+        );
84
+        $this->runForBackend(
85
+            $this->roomManager,
86
+            'calendar_rooms',
87
+            'calendar_rooms_md',
88
+            'room_id',
89
+            'principals/calendar-rooms'
90
+        );
91
+    }
92
+
93
+    /**
94
+     * Run background-job for one specific backendManager
95
+     * either ResourceManager or RoomManager
96
+     *
97
+     * @param IResourceManager|IRoomManager $backendManager
98
+     * @param string $dbTable
99
+     * @param string $dbTableMetadata
100
+     * @param string $foreignKey
101
+     * @param string $principalPrefix
102
+     */
103
+    private function runForBackend($backendManager,
104
+                                    string $dbTable,
105
+                                    string $dbTableMetadata,
106
+                                    string $foreignKey,
107
+                                    string $principalPrefix):void {
108
+        $backends = $backendManager->getBackends();
109
+
110
+        foreach ($backends as $backend) {
111
+            $backendId = $backend->getBackendIdentifier();
112
+
113
+            try {
114
+                if ($backend instanceof IResourceBackend) {
115
+                    $list = $backend->listAllResources();
116
+                } else {
117
+                    $list = $backend->listAllRooms();
118
+                }
119
+            } catch (BackendTemporarilyUnavailableException $ex) {
120
+                continue;
121
+            }
122
+
123
+            $cachedList = $this->getAllCachedByBackend($dbTable, $backendId);
124
+            $newIds = array_diff($list, $cachedList);
125
+            $deletedIds = array_diff($cachedList, $list);
126
+            $editedIds = array_intersect($list, $cachedList);
127
+
128
+            foreach ($newIds as $newId) {
129
+                try {
130
+                    if ($backend instanceof IResourceBackend) {
131
+                        $resource = $backend->getResource($newId);
132
+                    } else {
133
+                        $resource = $backend->getRoom($newId);
134
+                    }
135
+
136
+                    $metadata = [];
137
+                    if ($resource instanceof IMetadataProvider) {
138
+                        $metadata = $this->getAllMetadataOfBackend($resource);
139
+                    }
140
+                } catch (BackendTemporarilyUnavailableException $ex) {
141
+                    continue;
142
+                }
143
+
144
+                $id = $this->addToCache($dbTable, $backendId, $resource);
145
+                $this->addMetadataToCache($dbTableMetadata, $foreignKey, $id, $metadata);
146
+                // we don't create the calendar here, it is created lazily
147
+                // when an event is actually scheduled with this resource / room
148
+            }
149
+
150
+            foreach ($deletedIds as $deletedId) {
151
+                $id = $this->getIdForBackendAndResource($dbTable, $backendId, $deletedId);
152
+                $this->deleteFromCache($dbTable, $id);
153
+                $this->deleteMetadataFromCache($dbTableMetadata, $foreignKey, $id);
154
+
155
+                $principalName = implode('-', [$backendId, $deletedId]);
156
+                $this->deleteCalendarDataForResource($principalPrefix, $principalName);
157
+            }
158
+
159
+            foreach ($editedIds as $editedId) {
160
+                $id = $this->getIdForBackendAndResource($dbTable, $backendId, $editedId);
161
+
162
+                try {
163
+                    if ($backend instanceof IResourceBackend) {
164
+                        $resource = $backend->getResource($editedId);
165
+                    } else {
166
+                        $resource = $backend->getRoom($editedId);
167
+                    }
168
+
169
+                    $metadata = [];
170
+                    if ($resource instanceof IMetadataProvider) {
171
+                        $metadata = $this->getAllMetadataOfBackend($resource);
172
+                    }
173
+                } catch (BackendTemporarilyUnavailableException $ex) {
174
+                    continue;
175
+                }
176
+
177
+                $this->updateCache($dbTable, $id, $resource);
178
+
179
+                if ($resource instanceof IMetadataProvider) {
180
+                    $cachedMetadata = $this->getAllMetadataOfCache($dbTableMetadata, $foreignKey, $id);
181
+                    $this->updateMetadataCache($dbTableMetadata, $foreignKey, $id, $metadata, $cachedMetadata);
182
+                }
183
+            }
184
+        }
185
+    }
186
+
187
+    /**
188
+     * add entry to cache that exists remotely but not yet in cache
189
+     *
190
+     * @param string $table
191
+     * @param string $backendId
192
+     * @param IResource|IRoom $remote
193
+     * @return int Insert id
194
+     */
195
+    private function addToCache(string $table,
196
+                                string $backendId,
197
+                                $remote):int {
198
+        $query = $this->dbConnection->getQueryBuilder();
199
+        $query->insert($table)
200
+            ->values([
201
+                'backend_id' => $query->createNamedParameter($backendId),
202
+                'resource_id' => $query->createNamedParameter($remote->getId()),
203
+                'email' => $query->createNamedParameter($remote->getEMail()),
204
+                'displayname' => $query->createNamedParameter($remote->getDisplayName()),
205
+                'group_restrictions' => $query->createNamedParameter(
206
+                    $this->serializeGroupRestrictions(
207
+                        $remote->getGroupRestrictions()
208
+                    ))
209
+            ])
210
+            ->execute();
211
+        return $query->getLastInsertId();
212
+    }
213
+
214
+    /**
215
+     * @param string $table
216
+     * @param string $foreignKey
217
+     * @param int $foreignId
218
+     * @param array $metadata
219
+     */
220
+    private function addMetadataToCache(string $table,
221
+                                        string $foreignKey,
222
+                                        int $foreignId,
223
+                                        array $metadata):void {
224
+        foreach ($metadata as $key => $value) {
225
+            $query = $this->dbConnection->getQueryBuilder();
226
+            $query->insert($table)
227
+                ->values([
228
+                    $foreignKey => $query->createNamedParameter($foreignId),
229
+                    'key' => $query->createNamedParameter($key),
230
+                    'value' => $query->createNamedParameter($value),
231
+                ])
232
+                ->execute();
233
+        }
234
+    }
235
+
236
+    /**
237
+     * delete entry from cache that does not exist anymore remotely
238
+     *
239
+     * @param string $table
240
+     * @param int $id
241
+     */
242
+    private function deleteFromCache(string $table,
243
+                                        int $id):void {
244
+        $query = $this->dbConnection->getQueryBuilder();
245
+        $query->delete($table)
246
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id)))
247
+            ->execute();
248
+    }
249
+
250
+    /**
251
+     * @param string $table
252
+     * @param string $foreignKey
253
+     * @param int $id
254
+     */
255
+    private function deleteMetadataFromCache(string $table,
256
+                                                string $foreignKey,
257
+                                                int $id):void {
258
+        $query = $this->dbConnection->getQueryBuilder();
259
+        $query->delete($table)
260
+            ->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id)))
261
+            ->execute();
262
+    }
263
+
264
+    /**
265
+     * update an existing entry in cache
266
+     *
267
+     * @param string $table
268
+     * @param int $id
269
+     * @param IResource|IRoom $remote
270
+     */
271
+    private function updateCache(string $table,
272
+                                    int $id,
273
+                                    $remote):void {
274
+        $query = $this->dbConnection->getQueryBuilder();
275
+        $query->update($table)
276
+            ->set('email', $query->createNamedParameter($remote->getEMail()))
277
+            ->set('displayname', $query->createNamedParameter($remote->getDisplayName()))
278
+            ->set('group_restrictions', $query->createNamedParameter(
279
+                $this->serializeGroupRestrictions(
280
+                    $remote->getGroupRestrictions()
281
+                )))
282
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id)))
283
+            ->execute();
284
+    }
285
+
286
+    /**
287
+     * @param string $dbTable
288
+     * @param string $foreignKey
289
+     * @param int $id
290
+     * @param array $metadata
291
+     * @param array $cachedMetadata
292
+     */
293
+    private function updateMetadataCache(string $dbTable,
294
+                                            string $foreignKey,
295
+                                            int $id,
296
+                                            array $metadata,
297
+                                            array $cachedMetadata):void {
298
+        $newMetadata = array_diff_key($metadata, $cachedMetadata);
299
+        $deletedMetadata = array_diff_key($cachedMetadata, $metadata);
300
+
301
+        foreach ($newMetadata as $key => $value) {
302
+            $query = $this->dbConnection->getQueryBuilder();
303
+            $query->insert($dbTable)
304
+                ->values([
305
+                    $foreignKey => $query->createNamedParameter($id),
306
+                    'key' => $query->createNamedParameter($key),
307
+                    'value' => $query->createNamedParameter($value),
308
+                ])
309
+                ->execute();
310
+        }
311
+
312
+        foreach ($deletedMetadata as $key => $value) {
313
+            $query = $this->dbConnection->getQueryBuilder();
314
+            $query->delete($dbTable)
315
+                ->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id)))
316
+                ->andWhere($query->expr()->eq('key', $query->createNamedParameter($key)))
317
+                ->execute();
318
+        }
319
+
320
+        $existingKeys = array_keys(array_intersect_key($metadata, $cachedMetadata));
321
+        foreach ($existingKeys as $existingKey) {
322
+            if ($metadata[$existingKey] !== $cachedMetadata[$existingKey]) {
323
+                $query = $this->dbConnection->getQueryBuilder();
324
+                $query->update($dbTable)
325
+                    ->set('value', $query->createNamedParameter($metadata[$existingKey]))
326
+                    ->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id)))
327
+                    ->andWhere($query->expr()->eq('key', $query->createNamedParameter($existingKey)))
328
+                    ->execute();
329
+            }
330
+        }
331
+    }
332
+
333
+    /**
334
+     * serialize array of group restrictions to store them in database
335
+     *
336
+     * @param array $groups
337
+     * @return string
338
+     */
339
+    private function serializeGroupRestrictions(array $groups):string {
340
+        return \json_encode($groups);
341
+    }
342
+
343
+    /**
344
+     * Gets all metadata of a backend
345
+     *
346
+     * @param IResource|IRoom $resource
347
+     * @return array
348
+     */
349
+    private function getAllMetadataOfBackend($resource):array {
350
+        if (!($resource instanceof IMetadataProvider)) {
351
+            return [];
352
+        }
353
+
354
+        $keys = $resource->getAllAvailableMetadataKeys();
355
+        $metadata = [];
356
+        foreach ($keys as $key) {
357
+            $metadata[$key] = $resource->getMetadataForKey($key);
358
+        }
359
+
360
+        return $metadata;
361
+    }
362
+
363
+    /**
364
+     * @param string $table
365
+     * @param string $foreignKey
366
+     * @param int $id
367
+     * @return array
368
+     */
369
+    private function getAllMetadataOfCache(string $table,
370
+                                            string $foreignKey,
371
+                                            int $id):array {
372
+        $query = $this->dbConnection->getQueryBuilder();
373
+        $query->select(['key', 'value'])
374
+            ->from($table)
375
+            ->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id)));
376
+        $stmt = $query->execute();
377
+        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
378
+
379
+        $metadata = [];
380
+        foreach ($rows as $row) {
381
+            $metadata[$row['key']] = $row['value'];
382
+        }
383
+
384
+        return $metadata;
385
+    }
386
+
387
+    /**
388
+     * Gets all cached rooms / resources by backend
389
+     *
390
+     * @param $tableName
391
+     * @param $backendId
392
+     * @return array
393
+     */
394
+    private function getAllCachedByBackend(string $tableName,
395
+                                            string $backendId):array {
396
+        $query = $this->dbConnection->getQueryBuilder();
397
+        $query->select('resource_id')
398
+            ->from($tableName)
399
+            ->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)));
400
+        $stmt = $query->execute();
401
+
402
+        return array_map(function ($row): string {
403
+            return $row['resource_id'];
404
+        }, $stmt->fetchAll());
405
+    }
406
+
407
+    /**
408
+     * @param $principalPrefix
409
+     * @param $principalUri
410
+     */
411
+    private function deleteCalendarDataForResource(string $principalPrefix,
412
+                                                    string $principalUri):void {
413
+        $calendar = $this->calDavBackend->getCalendarByUri(
414
+            implode('/', [$principalPrefix, $principalUri]),
415
+            CalDavBackend::RESOURCE_BOOKING_CALENDAR_URI);
416
+
417
+        if ($calendar !== null) {
418
+            $this->calDavBackend->deleteCalendar($calendar['id']);
419
+        }
420
+    }
421
+
422
+    /**
423
+     * @param $table
424
+     * @param $backendId
425
+     * @param $resourceId
426
+     * @return int
427
+     */
428
+    private function getIdForBackendAndResource(string $table,
429
+                                                string $backendId,
430
+                                                string $resourceId):int {
431
+        $query = $this->dbConnection->getQueryBuilder();
432
+        $query->select('id')
433
+            ->from($table)
434
+            ->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
435
+            ->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
436
+        $stmt = $query->execute();
437
+
438
+        return $stmt->fetch()['id'];
439
+    }
440 440
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -399,7 +399,7 @@
 block discarded – undo
399 399
 			->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)));
400 400
 		$stmt = $query->execute();
401 401
 
402
-		return array_map(function ($row): string {
402
+		return array_map(function($row): string {
403 403
 			return $row['resource_id'];
404 404
 		}, $stmt->fetchAll());
405 405
 	}
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php 2 patches
Indentation   +434 added lines, -434 removed lines patch added patch discarded remove patch
@@ -36,438 +36,438 @@
 block discarded – undo
36 36
 
37 37
 abstract class AbstractPrincipalBackend implements BackendInterface {
38 38
 
39
-	/** @var IDBConnection */
40
-	private $db;
41
-
42
-	/** @var IUserSession */
43
-	private $userSession;
44
-
45
-	/** @var IGroupManager */
46
-	private $groupManager;
47
-
48
-	/** @var ILogger */
49
-	private $logger;
50
-
51
-	/** @var ProxyMapper */
52
-	private $proxyMapper;
53
-
54
-	/** @var string */
55
-	private $principalPrefix;
56
-
57
-	/** @var string */
58
-	private $dbTableName;
59
-
60
-	/** @var string */
61
-	private $dbMetaDataTableName;
62
-
63
-	/** @var string */
64
-	private $dbForeignKeyName;
65
-
66
-	/** @var string */
67
-	private $cuType;
68
-
69
-	/**
70
-	 * @param IDBConnection $dbConnection
71
-	 * @param IUserSession $userSession
72
-	 * @param IGroupManager $groupManager
73
-	 * @param ILogger $logger
74
-	 * @param string $principalPrefix
75
-	 * @param string $dbPrefix
76
-	 * @param string $cuType
77
-	 */
78
-	public function __construct(IDBConnection $dbConnection,
79
-								IUserSession $userSession,
80
-								IGroupManager $groupManager,
81
-								ILogger $logger,
82
-								ProxyMapper $proxyMapper,
83
-								string $principalPrefix,
84
-								string $dbPrefix,
85
-								string $cuType) {
86
-		$this->db = $dbConnection;
87
-		$this->userSession = $userSession;
88
-		$this->groupManager = $groupManager;
89
-		$this->logger = $logger;
90
-		$this->proxyMapper = $proxyMapper;
91
-		$this->principalPrefix = $principalPrefix;
92
-		$this->dbTableName = 'calendar_' . $dbPrefix . 's';
93
-		$this->dbMetaDataTableName = $this->dbTableName . '_md';
94
-		$this->dbForeignKeyName = $dbPrefix . '_id';
95
-		$this->cuType = $cuType;
96
-	}
97
-
98
-	use PrincipalProxyTrait;
99
-
100
-	/**
101
-	 * Returns a list of principals based on a prefix.
102
-	 *
103
-	 * This prefix will often contain something like 'principals'. You are only
104
-	 * expected to return principals that are in this base path.
105
-	 *
106
-	 * You are expected to return at least a 'uri' for every user, you can
107
-	 * return any additional properties if you wish so. Common properties are:
108
-	 *   {DAV:}displayname
109
-	 *
110
-	 * @param string $prefixPath
111
-	 * @return string[]
112
-	 */
113
-	public function getPrincipalsByPrefix($prefixPath) {
114
-		$principals = [];
115
-
116
-		if ($prefixPath === $this->principalPrefix) {
117
-			$query = $this->db->getQueryBuilder();
118
-			$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
119
-				->from($this->dbTableName);
120
-			$stmt = $query->execute();
121
-
122
-			$metaDataQuery = $this->db->getQueryBuilder();
123
-			$metaDataQuery->select([$this->dbForeignKeyName, 'key', 'value'])
124
-				->from($this->dbMetaDataTableName);
125
-			$metaDataStmt = $metaDataQuery->execute();
126
-			$metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
127
-
128
-			$metaDataById = [];
129
-			foreach ($metaDataRows as $metaDataRow) {
130
-				if (!isset($metaDataById[$metaDataRow[$this->dbForeignKeyName]])) {
131
-					$metaDataById[$metaDataRow[$this->dbForeignKeyName]] = [];
132
-				}
133
-
134
-				$metaDataById[$metaDataRow[$this->dbForeignKeyName]][$metaDataRow['key']] =
135
-					$metaDataRow['value'];
136
-			}
137
-
138
-			while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
139
-				$id = $row['id'];
140
-
141
-				if (isset($metaDataById[$id])) {
142
-					$principals[] = $this->rowToPrincipal($row, $metaDataById[$id]);
143
-				} else {
144
-					$principals[] = $this->rowToPrincipal($row);
145
-				}
146
-			}
147
-
148
-			$stmt->closeCursor();
149
-		}
150
-
151
-		return $principals;
152
-	}
153
-
154
-	/**
155
-	 * Returns a specific principal, specified by it's path.
156
-	 * The returned structure should be the exact same as from
157
-	 * getPrincipalsByPrefix.
158
-	 *
159
-	 * @param string $path
160
-	 * @return array
161
-	 */
162
-	public function getPrincipalByPath($path) {
163
-		if (strpos($path, $this->principalPrefix) !== 0) {
164
-			return null;
165
-		}
166
-		list(, $name) = \Sabre\Uri\split($path);
167
-
168
-		list($backendId, $resourceId) = explode('-',  $name, 2);
169
-
170
-		$query = $this->db->getQueryBuilder();
171
-		$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
172
-			->from($this->dbTableName)
173
-			->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
174
-			->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
175
-		$stmt = $query->execute();
176
-		$row = $stmt->fetch(\PDO::FETCH_ASSOC);
177
-
178
-		if (!$row) {
179
-			return null;
180
-		}
181
-
182
-		$metaDataQuery = $this->db->getQueryBuilder();
183
-		$metaDataQuery->select(['key', 'value'])
184
-			->from($this->dbMetaDataTableName)
185
-			->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
186
-		$metaDataStmt = $metaDataQuery->execute();
187
-		$metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
188
-		$metadata = [];
189
-
190
-		foreach ($metaDataRows as $metaDataRow) {
191
-			$metadata[$metaDataRow['key']] = $metaDataRow['value'];
192
-		}
193
-
194
-		return $this->rowToPrincipal($row, $metadata);
195
-	}
196
-
197
-	/**
198
-	 * @param int $id
199
-	 * @return array|null
200
-	 */
201
-	public function getPrincipalById($id):?array {
202
-		$query = $this->db->getQueryBuilder();
203
-		$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
204
-			->from($this->dbTableName)
205
-			->where($query->expr()->eq('id', $query->createNamedParameter($id)));
206
-		$stmt = $query->execute();
207
-		$row = $stmt->fetch(\PDO::FETCH_ASSOC);
208
-
209
-		if (!$row) {
210
-			return null;
211
-		}
212
-
213
-		$metaDataQuery = $this->db->getQueryBuilder();
214
-		$metaDataQuery->select(['key', 'value'])
215
-			->from($this->dbMetaDataTableName)
216
-			->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
217
-		$metaDataStmt = $metaDataQuery->execute();
218
-		$metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
219
-		$metadata = [];
220
-
221
-		foreach ($metaDataRows as $metaDataRow) {
222
-			$metadata[$metaDataRow['key']] = $metaDataRow['value'];
223
-		}
224
-
225
-		return $this->rowToPrincipal($row, $metadata);
226
-	}
227
-
228
-	/**
229
-	 * @param string $path
230
-	 * @param PropPatch $propPatch
231
-	 * @return int
232
-	 */
233
-	public function updatePrincipal($path, PropPatch $propPatch) {
234
-		return 0;
235
-	}
236
-
237
-	/**
238
-	 * @param string $prefixPath
239
-	 * @param array $searchProperties
240
-	 * @param string $test
241
-	 * @return array
242
-	 */
243
-	public function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
244
-		$results = [];
245
-		if (\count($searchProperties) === 0) {
246
-			return [];
247
-		}
248
-		if ($prefixPath !== $this->principalPrefix) {
249
-			return [];
250
-		}
251
-
252
-		$user = $this->userSession->getUser();
253
-		if (!$user) {
254
-			return [];
255
-		}
256
-		$usersGroups = $this->groupManager->getUserGroupIds($user);
257
-
258
-		foreach ($searchProperties as $prop => $value) {
259
-			switch ($prop) {
260
-				case '{http://sabredav.org/ns}email-address':
261
-					$query = $this->db->getQueryBuilder();
262
-					$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
263
-						->from($this->dbTableName)
264
-						->where($query->expr()->iLike('email', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
265
-
266
-					$stmt = $query->execute();
267
-					$principals = [];
268
-					while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
269
-						if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
270
-							continue;
271
-						}
272
-						$principals[] = $this->rowToPrincipal($row)['uri'];
273
-					}
274
-					$results[] = $principals;
275
-
276
-					$stmt->closeCursor();
277
-					break;
278
-
279
-				case '{DAV:}displayname':
280
-					$query = $this->db->getQueryBuilder();
281
-					$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
282
-						->from($this->dbTableName)
283
-						->where($query->expr()->iLike('displayname', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
284
-
285
-					$stmt = $query->execute();
286
-					$principals = [];
287
-					while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
288
-						if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
289
-							continue;
290
-						}
291
-						$principals[] = $this->rowToPrincipal($row)['uri'];
292
-					}
293
-					$results[] = $principals;
294
-
295
-					$stmt->closeCursor();
296
-					break;
297
-
298
-				case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
299
-					// If you add support for more search properties that qualify as a user-address,
300
-					// please also add them to the array below
301
-					$results[] = $this->searchPrincipals($this->principalPrefix, [
302
-						'{http://sabredav.org/ns}email-address' => $value,
303
-					], 'anyof');
304
-					break;
305
-
306
-				default:
307
-					$rowsByMetadata = $this->searchPrincipalsByMetadataKey($prop, $value);
308
-					$filteredRows = array_filter($rowsByMetadata, function ($row) use ($usersGroups) {
309
-						return $this->isAllowedToAccessResource($row, $usersGroups);
310
-					});
311
-
312
-					$results[] = array_map(function ($row): string {
313
-						return $row['uri'];
314
-					}, $filteredRows);
315
-
316
-					break;
317
-			}
318
-		}
319
-
320
-		// results is an array of arrays, so this is not the first search result
321
-		// but the results of the first searchProperty
322
-		if (count($results) === 1) {
323
-			return $results[0];
324
-		}
325
-
326
-		switch ($test) {
327
-			case 'anyof':
328
-				return array_values(array_unique(array_merge(...$results)));
329
-
330
-			case 'allof':
331
-			default:
332
-				return array_values(array_intersect(...$results));
333
-		}
334
-	}
335
-
336
-	/**
337
-	 * Searches principals based on their metadata keys.
338
-	 * This allows to search for all principals with a specific key.
339
-	 * e.g.:
340
-	 * '{http://nextcloud.com/ns}room-building-address' => 'ABC Street 123, ...'
341
-	 *
342
-	 * @param $key
343
-	 * @param $value
344
-	 * @return array
345
-	 */
346
-	private function searchPrincipalsByMetadataKey($key, $value):array {
347
-		$query = $this->db->getQueryBuilder();
348
-		$query->select([$this->dbForeignKeyName])
349
-			->from($this->dbMetaDataTableName)
350
-			->where($query->expr()->eq('key', $query->createNamedParameter($key)))
351
-			->andWhere($query->expr()->iLike('value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
352
-		$stmt = $query->execute();
353
-
354
-		$rows = [];
355
-		while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
356
-			$id = $row[$this->dbForeignKeyName];
357
-
358
-			$principalRow = $this->getPrincipalById($id);
359
-			if (!$principalRow) {
360
-				continue;
361
-			}
362
-
363
-			$rows[] = $principalRow;
364
-		}
365
-
366
-		return $rows;
367
-	}
368
-
369
-	/**
370
-	 * @param string $uri
371
-	 * @param string $principalPrefix
372
-	 * @return null|string
373
-	 */
374
-	public function findByUri($uri, $principalPrefix) {
375
-		$user = $this->userSession->getUser();
376
-		if (!$user) {
377
-			return null;
378
-		}
379
-		$usersGroups = $this->groupManager->getUserGroupIds($user);
380
-
381
-		if (strpos($uri, 'mailto:') === 0) {
382
-			$email = substr($uri, 7);
383
-			$query = $this->db->getQueryBuilder();
384
-			$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
385
-				->from($this->dbTableName)
386
-				->where($query->expr()->eq('email', $query->createNamedParameter($email)));
387
-
388
-			$stmt = $query->execute();
389
-			$row = $stmt->fetch(\PDO::FETCH_ASSOC);
390
-
391
-			if (!$row) {
392
-				return null;
393
-			}
394
-			if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
395
-				return null;
396
-			}
397
-
398
-			return $this->rowToPrincipal($row)['uri'];
399
-		}
400
-
401
-		if (strpos($uri, 'principal:') === 0) {
402
-			$path = substr($uri, 10);
403
-			if (strpos($path, $this->principalPrefix) !== 0) {
404
-				return null;
405
-			}
406
-
407
-			list(, $name) = \Sabre\Uri\split($path);
408
-			list($backendId, $resourceId) = explode('-',  $name, 2);
409
-
410
-			$query = $this->db->getQueryBuilder();
411
-			$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
412
-				->from($this->dbTableName)
413
-				->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
414
-				->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
415
-			$stmt = $query->execute();
416
-			$row = $stmt->fetch(\PDO::FETCH_ASSOC);
417
-
418
-			if (!$row) {
419
-				return null;
420
-			}
421
-			if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
422
-				return null;
423
-			}
424
-
425
-			return $this->rowToPrincipal($row)['uri'];
426
-		}
427
-
428
-		return null;
429
-	}
430
-
431
-	/**
432
-	 * convert database row to principal
433
-	 *
434
-	 * @param String[] $row
435
-	 * @param String[] $metadata
436
-	 * @return Array
437
-	 */
438
-	private function rowToPrincipal(array $row, array $metadata = []):array {
439
-		return array_merge([
440
-			'uri' => $this->principalPrefix . '/' . $row['backend_id'] . '-' . $row['resource_id'],
441
-			'{DAV:}displayname' => $row['displayname'],
442
-			'{http://sabredav.org/ns}email-address' => $row['email'],
443
-			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->cuType,
444
-		], $metadata);
445
-	}
446
-
447
-	/**
448
-	 * @param $row
449
-	 * @param $userGroups
450
-	 * @return bool
451
-	 */
452
-	private function isAllowedToAccessResource(array $row, array $userGroups):bool {
453
-		if (!isset($row['group_restrictions']) ||
454
-			$row['group_restrictions'] === null ||
455
-			$row['group_restrictions'] === '') {
456
-			return true;
457
-		}
458
-
459
-		// group restrictions contains something, but not parsable, deny access and log warning
460
-		$json = json_decode($row['group_restrictions']);
461
-		if (!\is_array($json)) {
462
-			$this->logger->info('group_restrictions field could not be parsed for ' . $this->dbTableName . '::' . $row['id'] . ', denying access to resource');
463
-			return false;
464
-		}
465
-
466
-		// empty array => no group restrictions
467
-		if (empty($json)) {
468
-			return true;
469
-		}
470
-
471
-		return !empty(array_intersect($json, $userGroups));
472
-	}
39
+    /** @var IDBConnection */
40
+    private $db;
41
+
42
+    /** @var IUserSession */
43
+    private $userSession;
44
+
45
+    /** @var IGroupManager */
46
+    private $groupManager;
47
+
48
+    /** @var ILogger */
49
+    private $logger;
50
+
51
+    /** @var ProxyMapper */
52
+    private $proxyMapper;
53
+
54
+    /** @var string */
55
+    private $principalPrefix;
56
+
57
+    /** @var string */
58
+    private $dbTableName;
59
+
60
+    /** @var string */
61
+    private $dbMetaDataTableName;
62
+
63
+    /** @var string */
64
+    private $dbForeignKeyName;
65
+
66
+    /** @var string */
67
+    private $cuType;
68
+
69
+    /**
70
+     * @param IDBConnection $dbConnection
71
+     * @param IUserSession $userSession
72
+     * @param IGroupManager $groupManager
73
+     * @param ILogger $logger
74
+     * @param string $principalPrefix
75
+     * @param string $dbPrefix
76
+     * @param string $cuType
77
+     */
78
+    public function __construct(IDBConnection $dbConnection,
79
+                                IUserSession $userSession,
80
+                                IGroupManager $groupManager,
81
+                                ILogger $logger,
82
+                                ProxyMapper $proxyMapper,
83
+                                string $principalPrefix,
84
+                                string $dbPrefix,
85
+                                string $cuType) {
86
+        $this->db = $dbConnection;
87
+        $this->userSession = $userSession;
88
+        $this->groupManager = $groupManager;
89
+        $this->logger = $logger;
90
+        $this->proxyMapper = $proxyMapper;
91
+        $this->principalPrefix = $principalPrefix;
92
+        $this->dbTableName = 'calendar_' . $dbPrefix . 's';
93
+        $this->dbMetaDataTableName = $this->dbTableName . '_md';
94
+        $this->dbForeignKeyName = $dbPrefix . '_id';
95
+        $this->cuType = $cuType;
96
+    }
97
+
98
+    use PrincipalProxyTrait;
99
+
100
+    /**
101
+     * Returns a list of principals based on a prefix.
102
+     *
103
+     * This prefix will often contain something like 'principals'. You are only
104
+     * expected to return principals that are in this base path.
105
+     *
106
+     * You are expected to return at least a 'uri' for every user, you can
107
+     * return any additional properties if you wish so. Common properties are:
108
+     *   {DAV:}displayname
109
+     *
110
+     * @param string $prefixPath
111
+     * @return string[]
112
+     */
113
+    public function getPrincipalsByPrefix($prefixPath) {
114
+        $principals = [];
115
+
116
+        if ($prefixPath === $this->principalPrefix) {
117
+            $query = $this->db->getQueryBuilder();
118
+            $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
119
+                ->from($this->dbTableName);
120
+            $stmt = $query->execute();
121
+
122
+            $metaDataQuery = $this->db->getQueryBuilder();
123
+            $metaDataQuery->select([$this->dbForeignKeyName, 'key', 'value'])
124
+                ->from($this->dbMetaDataTableName);
125
+            $metaDataStmt = $metaDataQuery->execute();
126
+            $metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
127
+
128
+            $metaDataById = [];
129
+            foreach ($metaDataRows as $metaDataRow) {
130
+                if (!isset($metaDataById[$metaDataRow[$this->dbForeignKeyName]])) {
131
+                    $metaDataById[$metaDataRow[$this->dbForeignKeyName]] = [];
132
+                }
133
+
134
+                $metaDataById[$metaDataRow[$this->dbForeignKeyName]][$metaDataRow['key']] =
135
+                    $metaDataRow['value'];
136
+            }
137
+
138
+            while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
139
+                $id = $row['id'];
140
+
141
+                if (isset($metaDataById[$id])) {
142
+                    $principals[] = $this->rowToPrincipal($row, $metaDataById[$id]);
143
+                } else {
144
+                    $principals[] = $this->rowToPrincipal($row);
145
+                }
146
+            }
147
+
148
+            $stmt->closeCursor();
149
+        }
150
+
151
+        return $principals;
152
+    }
153
+
154
+    /**
155
+     * Returns a specific principal, specified by it's path.
156
+     * The returned structure should be the exact same as from
157
+     * getPrincipalsByPrefix.
158
+     *
159
+     * @param string $path
160
+     * @return array
161
+     */
162
+    public function getPrincipalByPath($path) {
163
+        if (strpos($path, $this->principalPrefix) !== 0) {
164
+            return null;
165
+        }
166
+        list(, $name) = \Sabre\Uri\split($path);
167
+
168
+        list($backendId, $resourceId) = explode('-',  $name, 2);
169
+
170
+        $query = $this->db->getQueryBuilder();
171
+        $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
172
+            ->from($this->dbTableName)
173
+            ->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
174
+            ->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
175
+        $stmt = $query->execute();
176
+        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
177
+
178
+        if (!$row) {
179
+            return null;
180
+        }
181
+
182
+        $metaDataQuery = $this->db->getQueryBuilder();
183
+        $metaDataQuery->select(['key', 'value'])
184
+            ->from($this->dbMetaDataTableName)
185
+            ->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
186
+        $metaDataStmt = $metaDataQuery->execute();
187
+        $metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
188
+        $metadata = [];
189
+
190
+        foreach ($metaDataRows as $metaDataRow) {
191
+            $metadata[$metaDataRow['key']] = $metaDataRow['value'];
192
+        }
193
+
194
+        return $this->rowToPrincipal($row, $metadata);
195
+    }
196
+
197
+    /**
198
+     * @param int $id
199
+     * @return array|null
200
+     */
201
+    public function getPrincipalById($id):?array {
202
+        $query = $this->db->getQueryBuilder();
203
+        $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
204
+            ->from($this->dbTableName)
205
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id)));
206
+        $stmt = $query->execute();
207
+        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
208
+
209
+        if (!$row) {
210
+            return null;
211
+        }
212
+
213
+        $metaDataQuery = $this->db->getQueryBuilder();
214
+        $metaDataQuery->select(['key', 'value'])
215
+            ->from($this->dbMetaDataTableName)
216
+            ->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
217
+        $metaDataStmt = $metaDataQuery->execute();
218
+        $metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
219
+        $metadata = [];
220
+
221
+        foreach ($metaDataRows as $metaDataRow) {
222
+            $metadata[$metaDataRow['key']] = $metaDataRow['value'];
223
+        }
224
+
225
+        return $this->rowToPrincipal($row, $metadata);
226
+    }
227
+
228
+    /**
229
+     * @param string $path
230
+     * @param PropPatch $propPatch
231
+     * @return int
232
+     */
233
+    public function updatePrincipal($path, PropPatch $propPatch) {
234
+        return 0;
235
+    }
236
+
237
+    /**
238
+     * @param string $prefixPath
239
+     * @param array $searchProperties
240
+     * @param string $test
241
+     * @return array
242
+     */
243
+    public function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
244
+        $results = [];
245
+        if (\count($searchProperties) === 0) {
246
+            return [];
247
+        }
248
+        if ($prefixPath !== $this->principalPrefix) {
249
+            return [];
250
+        }
251
+
252
+        $user = $this->userSession->getUser();
253
+        if (!$user) {
254
+            return [];
255
+        }
256
+        $usersGroups = $this->groupManager->getUserGroupIds($user);
257
+
258
+        foreach ($searchProperties as $prop => $value) {
259
+            switch ($prop) {
260
+                case '{http://sabredav.org/ns}email-address':
261
+                    $query = $this->db->getQueryBuilder();
262
+                    $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
263
+                        ->from($this->dbTableName)
264
+                        ->where($query->expr()->iLike('email', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
265
+
266
+                    $stmt = $query->execute();
267
+                    $principals = [];
268
+                    while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
269
+                        if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
270
+                            continue;
271
+                        }
272
+                        $principals[] = $this->rowToPrincipal($row)['uri'];
273
+                    }
274
+                    $results[] = $principals;
275
+
276
+                    $stmt->closeCursor();
277
+                    break;
278
+
279
+                case '{DAV:}displayname':
280
+                    $query = $this->db->getQueryBuilder();
281
+                    $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
282
+                        ->from($this->dbTableName)
283
+                        ->where($query->expr()->iLike('displayname', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
284
+
285
+                    $stmt = $query->execute();
286
+                    $principals = [];
287
+                    while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
288
+                        if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
289
+                            continue;
290
+                        }
291
+                        $principals[] = $this->rowToPrincipal($row)['uri'];
292
+                    }
293
+                    $results[] = $principals;
294
+
295
+                    $stmt->closeCursor();
296
+                    break;
297
+
298
+                case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
299
+                    // If you add support for more search properties that qualify as a user-address,
300
+                    // please also add them to the array below
301
+                    $results[] = $this->searchPrincipals($this->principalPrefix, [
302
+                        '{http://sabredav.org/ns}email-address' => $value,
303
+                    ], 'anyof');
304
+                    break;
305
+
306
+                default:
307
+                    $rowsByMetadata = $this->searchPrincipalsByMetadataKey($prop, $value);
308
+                    $filteredRows = array_filter($rowsByMetadata, function ($row) use ($usersGroups) {
309
+                        return $this->isAllowedToAccessResource($row, $usersGroups);
310
+                    });
311
+
312
+                    $results[] = array_map(function ($row): string {
313
+                        return $row['uri'];
314
+                    }, $filteredRows);
315
+
316
+                    break;
317
+            }
318
+        }
319
+
320
+        // results is an array of arrays, so this is not the first search result
321
+        // but the results of the first searchProperty
322
+        if (count($results) === 1) {
323
+            return $results[0];
324
+        }
325
+
326
+        switch ($test) {
327
+            case 'anyof':
328
+                return array_values(array_unique(array_merge(...$results)));
329
+
330
+            case 'allof':
331
+            default:
332
+                return array_values(array_intersect(...$results));
333
+        }
334
+    }
335
+
336
+    /**
337
+     * Searches principals based on their metadata keys.
338
+     * This allows to search for all principals with a specific key.
339
+     * e.g.:
340
+     * '{http://nextcloud.com/ns}room-building-address' => 'ABC Street 123, ...'
341
+     *
342
+     * @param $key
343
+     * @param $value
344
+     * @return array
345
+     */
346
+    private function searchPrincipalsByMetadataKey($key, $value):array {
347
+        $query = $this->db->getQueryBuilder();
348
+        $query->select([$this->dbForeignKeyName])
349
+            ->from($this->dbMetaDataTableName)
350
+            ->where($query->expr()->eq('key', $query->createNamedParameter($key)))
351
+            ->andWhere($query->expr()->iLike('value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
352
+        $stmt = $query->execute();
353
+
354
+        $rows = [];
355
+        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
356
+            $id = $row[$this->dbForeignKeyName];
357
+
358
+            $principalRow = $this->getPrincipalById($id);
359
+            if (!$principalRow) {
360
+                continue;
361
+            }
362
+
363
+            $rows[] = $principalRow;
364
+        }
365
+
366
+        return $rows;
367
+    }
368
+
369
+    /**
370
+     * @param string $uri
371
+     * @param string $principalPrefix
372
+     * @return null|string
373
+     */
374
+    public function findByUri($uri, $principalPrefix) {
375
+        $user = $this->userSession->getUser();
376
+        if (!$user) {
377
+            return null;
378
+        }
379
+        $usersGroups = $this->groupManager->getUserGroupIds($user);
380
+
381
+        if (strpos($uri, 'mailto:') === 0) {
382
+            $email = substr($uri, 7);
383
+            $query = $this->db->getQueryBuilder();
384
+            $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
385
+                ->from($this->dbTableName)
386
+                ->where($query->expr()->eq('email', $query->createNamedParameter($email)));
387
+
388
+            $stmt = $query->execute();
389
+            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
390
+
391
+            if (!$row) {
392
+                return null;
393
+            }
394
+            if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
395
+                return null;
396
+            }
397
+
398
+            return $this->rowToPrincipal($row)['uri'];
399
+        }
400
+
401
+        if (strpos($uri, 'principal:') === 0) {
402
+            $path = substr($uri, 10);
403
+            if (strpos($path, $this->principalPrefix) !== 0) {
404
+                return null;
405
+            }
406
+
407
+            list(, $name) = \Sabre\Uri\split($path);
408
+            list($backendId, $resourceId) = explode('-',  $name, 2);
409
+
410
+            $query = $this->db->getQueryBuilder();
411
+            $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
412
+                ->from($this->dbTableName)
413
+                ->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
414
+                ->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
415
+            $stmt = $query->execute();
416
+            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
417
+
418
+            if (!$row) {
419
+                return null;
420
+            }
421
+            if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
422
+                return null;
423
+            }
424
+
425
+            return $this->rowToPrincipal($row)['uri'];
426
+        }
427
+
428
+        return null;
429
+    }
430
+
431
+    /**
432
+     * convert database row to principal
433
+     *
434
+     * @param String[] $row
435
+     * @param String[] $metadata
436
+     * @return Array
437
+     */
438
+    private function rowToPrincipal(array $row, array $metadata = []):array {
439
+        return array_merge([
440
+            'uri' => $this->principalPrefix . '/' . $row['backend_id'] . '-' . $row['resource_id'],
441
+            '{DAV:}displayname' => $row['displayname'],
442
+            '{http://sabredav.org/ns}email-address' => $row['email'],
443
+            '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->cuType,
444
+        ], $metadata);
445
+    }
446
+
447
+    /**
448
+     * @param $row
449
+     * @param $userGroups
450
+     * @return bool
451
+     */
452
+    private function isAllowedToAccessResource(array $row, array $userGroups):bool {
453
+        if (!isset($row['group_restrictions']) ||
454
+            $row['group_restrictions'] === null ||
455
+            $row['group_restrictions'] === '') {
456
+            return true;
457
+        }
458
+
459
+        // group restrictions contains something, but not parsable, deny access and log warning
460
+        $json = json_decode($row['group_restrictions']);
461
+        if (!\is_array($json)) {
462
+            $this->logger->info('group_restrictions field could not be parsed for ' . $this->dbTableName . '::' . $row['id'] . ', denying access to resource');
463
+            return false;
464
+        }
465
+
466
+        // empty array => no group restrictions
467
+        if (empty($json)) {
468
+            return true;
469
+        }
470
+
471
+        return !empty(array_intersect($json, $userGroups));
472
+    }
473 473
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -89,9 +89,9 @@  discard block
 block discarded – undo
89 89
 		$this->logger = $logger;
90 90
 		$this->proxyMapper = $proxyMapper;
91 91
 		$this->principalPrefix = $principalPrefix;
92
-		$this->dbTableName = 'calendar_' . $dbPrefix . 's';
93
-		$this->dbMetaDataTableName = $this->dbTableName . '_md';
94
-		$this->dbForeignKeyName = $dbPrefix . '_id';
92
+		$this->dbTableName = 'calendar_'.$dbPrefix.'s';
93
+		$this->dbMetaDataTableName = $this->dbTableName.'_md';
94
+		$this->dbForeignKeyName = $dbPrefix.'_id';
95 95
 		$this->cuType = $cuType;
96 96
 	}
97 97
 
@@ -165,7 +165,7 @@  discard block
 block discarded – undo
165 165
 		}
166 166
 		list(, $name) = \Sabre\Uri\split($path);
167 167
 
168
-		list($backendId, $resourceId) = explode('-',  $name, 2);
168
+		list($backendId, $resourceId) = explode('-', $name, 2);
169 169
 
170 170
 		$query = $this->db->getQueryBuilder();
171 171
 		$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
@@ -198,7 +198,7 @@  discard block
 block discarded – undo
198 198
 	 * @param int $id
199 199
 	 * @return array|null
200 200
 	 */
201
-	public function getPrincipalById($id):?array {
201
+	public function getPrincipalById($id): ?array {
202 202
 		$query = $this->db->getQueryBuilder();
203 203
 		$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
204 204
 			->from($this->dbTableName)
@@ -261,7 +261,7 @@  discard block
 block discarded – undo
261 261
 					$query = $this->db->getQueryBuilder();
262 262
 					$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
263 263
 						->from($this->dbTableName)
264
-						->where($query->expr()->iLike('email', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
264
+						->where($query->expr()->iLike('email', $query->createNamedParameter('%'.$this->db->escapeLikeParameter($value).'%')));
265 265
 
266 266
 					$stmt = $query->execute();
267 267
 					$principals = [];
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
 					$query = $this->db->getQueryBuilder();
281 281
 					$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
282 282
 						->from($this->dbTableName)
283
-						->where($query->expr()->iLike('displayname', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
283
+						->where($query->expr()->iLike('displayname', $query->createNamedParameter('%'.$this->db->escapeLikeParameter($value).'%')));
284 284
 
285 285
 					$stmt = $query->execute();
286 286
 					$principals = [];
@@ -305,11 +305,11 @@  discard block
 block discarded – undo
305 305
 
306 306
 				default:
307 307
 					$rowsByMetadata = $this->searchPrincipalsByMetadataKey($prop, $value);
308
-					$filteredRows = array_filter($rowsByMetadata, function ($row) use ($usersGroups) {
308
+					$filteredRows = array_filter($rowsByMetadata, function($row) use ($usersGroups) {
309 309
 						return $this->isAllowedToAccessResource($row, $usersGroups);
310 310
 					});
311 311
 
312
-					$results[] = array_map(function ($row): string {
312
+					$results[] = array_map(function($row): string {
313 313
 						return $row['uri'];
314 314
 					}, $filteredRows);
315 315
 
@@ -348,7 +348,7 @@  discard block
 block discarded – undo
348 348
 		$query->select([$this->dbForeignKeyName])
349 349
 			->from($this->dbMetaDataTableName)
350 350
 			->where($query->expr()->eq('key', $query->createNamedParameter($key)))
351
-			->andWhere($query->expr()->iLike('value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
351
+			->andWhere($query->expr()->iLike('value', $query->createNamedParameter('%'.$this->db->escapeLikeParameter($value).'%')));
352 352
 		$stmt = $query->execute();
353 353
 
354 354
 		$rows = [];
@@ -405,7 +405,7 @@  discard block
 block discarded – undo
405 405
 			}
406 406
 
407 407
 			list(, $name) = \Sabre\Uri\split($path);
408
-			list($backendId, $resourceId) = explode('-',  $name, 2);
408
+			list($backendId, $resourceId) = explode('-', $name, 2);
409 409
 
410 410
 			$query = $this->db->getQueryBuilder();
411 411
 			$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
@@ -437,7 +437,7 @@  discard block
 block discarded – undo
437 437
 	 */
438 438
 	private function rowToPrincipal(array $row, array $metadata = []):array {
439 439
 		return array_merge([
440
-			'uri' => $this->principalPrefix . '/' . $row['backend_id'] . '-' . $row['resource_id'],
440
+			'uri' => $this->principalPrefix.'/'.$row['backend_id'].'-'.$row['resource_id'],
441 441
 			'{DAV:}displayname' => $row['displayname'],
442 442
 			'{http://sabredav.org/ns}email-address' => $row['email'],
443 443
 			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->cuType,
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
 		// group restrictions contains something, but not parsable, deny access and log warning
460 460
 		$json = json_decode($row['group_restrictions']);
461 461
 		if (!\is_array($json)) {
462
-			$this->logger->info('group_restrictions field could not be parsed for ' . $this->dbTableName . '::' . $row['id'] . ', denying access to resource');
462
+			$this->logger->info('group_restrictions field could not be parsed for '.$this->dbTableName.'::'.$row['id'].', denying access to resource');
463 463
 			return false;
464 464
 		}
465 465
 
Please login to merge, or discard this patch.
apps/dav/lib/AppInfo/Application.php 2 patches
Indentation   +320 added lines, -320 removed lines patch added patch discarded remove patch
@@ -81,333 +81,333 @@
 block discarded – undo
81 81
 use function strpos;
82 82
 
83 83
 class Application extends App implements IBootstrap {
84
-	public const APP_ID = 'dav';
84
+    public const APP_ID = 'dav';
85 85
 
86
-	public function __construct() {
87
-		parent::__construct(self::APP_ID);
88
-	}
86
+    public function __construct() {
87
+        parent::__construct(self::APP_ID);
88
+    }
89 89
 
90
-	public function register(IRegistrationContext $context): void {
91
-		$context->registerServiceAlias('CardDAVSyncService', SyncService::class);
92
-		$context->registerService(PhotoCache::class, function (ContainerInterface $c) {
93
-			/** @var IServerContainer $server */
94
-			$server = $c->get(IServerContainer::class);
90
+    public function register(IRegistrationContext $context): void {
91
+        $context->registerServiceAlias('CardDAVSyncService', SyncService::class);
92
+        $context->registerService(PhotoCache::class, function (ContainerInterface $c) {
93
+            /** @var IServerContainer $server */
94
+            $server = $c->get(IServerContainer::class);
95 95
 
96
-			return new PhotoCache(
97
-				$server->getAppDataDir('dav-photocache'),
98
-				$c->get(ILogger::class)
99
-			);
100
-		});
96
+            return new PhotoCache(
97
+                $server->getAppDataDir('dav-photocache'),
98
+                $c->get(ILogger::class)
99
+            );
100
+        });
101 101
 
102
-		/*
102
+        /*
103 103
 		 * Register capabilities
104 104
 		 */
105
-		$context->registerCapability(Capabilities::class);
105
+        $context->registerCapability(Capabilities::class);
106 106
 
107
-		/*
107
+        /*
108 108
 		 * Register Search Providers
109 109
 		 */
110
-		$context->registerSearchProvider(ContactsSearchProvider::class);
111
-		$context->registerSearchProvider(EventsSearchProvider::class);
112
-		$context->registerSearchProvider(TasksSearchProvider::class);
113
-
114
-		/**
115
-		 * Register event listeners
116
-		 */
117
-		$context->registerEventListener(CalendarObjectCreatedEvent::class, CalendarContactInteractionListener::class);
118
-		$context->registerEventListener(CalendarObjectUpdatedEvent::class, CalendarContactInteractionListener::class);
119
-		$context->registerEventListener(CalendarShareUpdatedEvent::class, CalendarContactInteractionListener::class);
120
-	}
121
-
122
-	public function boot(IBootContext $context): void {
123
-		// Load all dav apps
124
-		\OC_App::loadApps(['dav']);
125
-
126
-		$context->injectFn([$this, 'registerHooks']);
127
-		$context->injectFn([$this, 'registerContactsManager']);
128
-		$context->injectFn([$this, 'registerCalendarManager']);
129
-		$context->injectFn([$this, 'registerNotifier']);
130
-		$context->injectFn([$this, 'registerCalendarReminders']);
131
-	}
132
-
133
-	public function registerHooks(HookManager $hm,
134
-								   EventDispatcherInterface $dispatcher,
135
-								   IAppContainer $container,
136
-								   IServerContainer $serverContainer) {
137
-		$hm->setup();
138
-
139
-		// first time login event setup
140
-		$dispatcher->addListener(IUser::class . '::firstLogin', function ($event) use ($hm) {
141
-			if ($event instanceof GenericEvent) {
142
-				$hm->firstLogin($event->getSubject());
143
-			}
144
-		});
145
-
146
-		$birthdayListener = function ($event) use ($container): void {
147
-			if ($event instanceof GenericEvent) {
148
-				/** @var BirthdayService $b */
149
-				$b = $container->query(BirthdayService::class);
150
-				$b->onCardChanged(
151
-					(int) $event->getArgument('addressBookId'),
152
-					(string) $event->getArgument('cardUri'),
153
-					(string) $event->getArgument('cardData')
154
-				);
155
-			}
156
-		};
157
-
158
-		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::createCard', $birthdayListener);
159
-		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $birthdayListener);
160
-		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', function ($event) use ($container) {
161
-			if ($event instanceof GenericEvent) {
162
-				/** @var BirthdayService $b */
163
-				$b = $container->query(BirthdayService::class);
164
-				$b->onCardDeleted(
165
-					(int) $event->getArgument('addressBookId'),
166
-					(string) $event->getArgument('cardUri')
167
-				);
168
-			}
169
-		});
170
-
171
-		$clearPhotoCache = function ($event) use ($container): void {
172
-			if ($event instanceof GenericEvent) {
173
-				/** @var PhotoCache $p */
174
-				$p = $container->query(PhotoCache::class);
175
-				$p->delete(
176
-					$event->getArgument('addressBookId'),
177
-					$event->getArgument('cardUri')
178
-				);
179
-			}
180
-		};
181
-		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $clearPhotoCache);
182
-		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', $clearPhotoCache);
183
-
184
-		$dispatcher->addListener('OC\AccountManager::userUpdated', function (GenericEvent $event) use ($container) {
185
-			$user = $event->getSubject();
186
-			/** @var SyncService $syncService */
187
-			$syncService = $container->query(SyncService::class);
188
-			$syncService->updateUser($user);
189
-		});
190
-
191
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createCalendar', function (GenericEvent $event) use ($container) {
192
-			/** @var Backend $backend */
193
-			$backend = $container->query(Backend::class);
194
-			$backend->onCalendarAdd(
195
-				$event->getArgument('calendarData')
196
-			);
197
-		});
198
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateCalendar', function (GenericEvent $event) use ($container) {
199
-			/** @var Backend $backend */
200
-			$backend = $container->query(Backend::class);
201
-			$backend->onCalendarUpdate(
202
-				$event->getArgument('calendarData'),
203
-				$event->getArgument('shares'),
204
-				$event->getArgument('propertyMutations')
205
-			);
206
-		});
207
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendar', function (GenericEvent $event) use ($container) {
208
-			/** @var Backend $backend */
209
-			$backend = $container->query(Backend::class);
210
-			$backend->onCalendarDelete(
211
-				$event->getArgument('calendarData'),
212
-				$event->getArgument('shares')
213
-			);
214
-
215
-			/** @var ReminderBackend $reminderBackend */
216
-			$reminderBackend = $container->query(ReminderBackend::class);
217
-			$reminderBackend->cleanRemindersForCalendar(
218
-				(int) $event->getArgument('calendarId')
219
-			);
220
-		});
221
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateShares', function (GenericEvent $event) use ($container) {
222
-			/** @var Backend $backend */
223
-			$backend = $container->query(Backend::class);
224
-			$backend->onCalendarUpdateShares(
225
-				$event->getArgument('calendarData'),
226
-				$event->getArgument('shares'),
227
-				$event->getArgument('add'),
228
-				$event->getArgument('remove')
229
-			);
230
-
231
-			// Here we should recalculate if reminders should be sent to new or old sharees
232
-		});
233
-
234
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', function (GenericEvent $event) use ($container) {
235
-			/** @var Backend $backend */
236
-			$backend = $container->query(Backend::class);
237
-			$backend->onCalendarPublication(
238
-				$event->getArgument('calendarData'),
239
-				$event->getArgument('public')
240
-			);
241
-		});
242
-
243
-		$listener = function (GenericEvent $event, $eventName) use ($container): void {
244
-			/** @var Backend $backend */
245
-			$backend = $container->query(Backend::class);
246
-
247
-			$subject = Event::SUBJECT_OBJECT_ADD;
248
-			if ($eventName === '\OCA\DAV\CalDAV\CalDavBackend::updateCalendarObject') {
249
-				$subject = Event::SUBJECT_OBJECT_UPDATE;
250
-			} elseif ($eventName === '\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject') {
251
-				$subject = Event::SUBJECT_OBJECT_DELETE;
252
-			}
253
-			$backend->onTouchCalendarObject(
254
-				$subject,
255
-				$event->getArgument('calendarData'),
256
-				$event->getArgument('shares'),
257
-				$event->getArgument('objectData')
258
-			);
259
-
260
-			/** @var ReminderService $reminderBackend */
261
-			$reminderService = $container->query(ReminderService::class);
262
-
263
-			$reminderService->onTouchCalendarObject(
264
-				$eventName,
265
-				$event->getArgument('objectData')
266
-			);
267
-		};
268
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createCalendarObject', $listener);
269
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateCalendarObject', $listener);
270
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject', $listener);
271
-
272
-		/**
273
-		 * In case the user has set their default calendar to this one
274
-		 */
275
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendar', function (GenericEvent $event) use ($serverContainer) {
276
-			/** @var IConfig $config */
277
-			$config = $serverContainer->getConfig();
278
-			$principalUri = $event->getArgument('calendarData')['principaluri'];
279
-			if (strpos($principalUri, 'principals/users') === 0) {
280
-				list(, $UID) = \Sabre\Uri\split($principalUri);
281
-				$uri = $event->getArgument('calendarData')['uri'];
282
-				if ($config->getUserValue($UID, 'dav', 'defaultCalendar') === $uri) {
283
-					$config->deleteUserValue($UID, 'dav', 'defaultCalendar');
284
-				}
285
-			}
286
-		});
287
-
288
-		$dispatcher->addListener('OCP\Federation\TrustedServerEvent::remove',
289
-			function (GenericEvent $event) {
290
-				/** @var CardDavBackend $cardDavBackend */
291
-				$cardDavBackend = \OC::$server->query(CardDavBackend::class);
292
-				$addressBookUri = $event->getSubject();
293
-				$addressBook = $cardDavBackend->getAddressBooksByUri('principals/system/system', $addressBookUri);
294
-				if (!is_null($addressBook)) {
295
-					$cardDavBackend->deleteAddressBook($addressBook['id']);
296
-				}
297
-			}
298
-		);
299
-
300
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createSubscription',
301
-			function (GenericEvent $event) use ($container, $serverContainer) {
302
-				$jobList = $serverContainer->getJobList();
303
-				$subscriptionData = $event->getArgument('subscriptionData');
304
-
305
-				/**
306
-				 * Initial subscription refetch
307
-				 *
308
-				 * @var RefreshWebcalService $refreshWebcalService
309
-				 */
310
-				$refreshWebcalService = $container->query(RefreshWebcalService::class);
311
-				$refreshWebcalService->refreshSubscription(
312
-					(string) $subscriptionData['principaluri'],
313
-					(string) $subscriptionData['uri']
314
-				);
315
-
316
-				$jobList->add(\OCA\DAV\BackgroundJob\RefreshWebcalJob::class, [
317
-					'principaluri' => $subscriptionData['principaluri'],
318
-					'uri' => $subscriptionData['uri']
319
-				]);
320
-			}
321
-		);
322
-
323
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteSubscription',
324
-			function (GenericEvent $event) use ($container, $serverContainer) {
325
-				$jobList = $serverContainer->getJobList();
326
-				$subscriptionData = $event->getArgument('subscriptionData');
327
-
328
-				$jobList->remove(\OCA\DAV\BackgroundJob\RefreshWebcalJob::class, [
329
-					'principaluri' => $subscriptionData['principaluri'],
330
-					'uri' => $subscriptionData['uri']
331
-				]);
332
-
333
-				/** @var CalDavBackend $calDavBackend */
334
-				$calDavBackend = $container->query(CalDavBackend::class);
335
-				$calDavBackend->purgeAllCachedEventsForSubscription($subscriptionData['id']);
336
-			}
337
-		);
338
-
339
-		$eventHandler = function () use ($container, $serverContainer): void {
340
-			try {
341
-				/** @var UpdateCalendarResourcesRoomsBackgroundJob $job */
342
-				$job = $container->query(UpdateCalendarResourcesRoomsBackgroundJob::class);
343
-				$job->run([]);
344
-				$serverContainer->getJobList()->setLastRun($job);
345
-			} catch (Exception $ex) {
346
-				$serverContainer->getLogger()->logException($ex);
347
-			}
348
-		};
349
-
350
-		$dispatcher->addListener('\OCP\Calendar\Resource\ForceRefreshEvent', $eventHandler);
351
-		$dispatcher->addListener('\OCP\Calendar\Room\ForceRefreshEvent', $eventHandler);
352
-	}
353
-
354
-	public function registerContactsManager(IContactsManager $cm, IAppContainer $container): void {
355
-		$cm->register(function () use ($container, $cm): void {
356
-			$user = \OC::$server->getUserSession()->getUser();
357
-			if (!is_null($user)) {
358
-				$this->setupContactsProvider($cm, $container, $user->getUID());
359
-			} else {
360
-				$this->setupSystemContactsProvider($cm, $container);
361
-			}
362
-		});
363
-	}
364
-
365
-	private function setupContactsProvider(IContactsManager $contactsManager,
366
-										   IAppContainer $container,
367
-										   string $userID): void {
368
-		/** @var ContactsManager $cm */
369
-		$cm = $container->query(ContactsManager::class);
370
-		$urlGenerator = $container->getServer()->getURLGenerator();
371
-		$cm->setupContactsProvider($contactsManager, $userID, $urlGenerator);
372
-	}
373
-
374
-	private function setupSystemContactsProvider(IContactsManager $contactsManager,
375
-												 IAppContainer $container): void {
376
-		/** @var ContactsManager $cm */
377
-		$cm = $container->query(ContactsManager::class);
378
-		$urlGenerator = $container->getServer()->getURLGenerator();
379
-		$cm->setupSystemContactsProvider($contactsManager, $urlGenerator);
380
-	}
381
-
382
-	public function registerCalendarManager(ICalendarManager $calendarManager,
383
-											 IAppContainer $container): void {
384
-		$calendarManager->register(function () use ($container, $calendarManager) {
385
-			$user = \OC::$server->getUserSession()->getUser();
386
-			if ($user !== null) {
387
-				$this->setupCalendarProvider($calendarManager, $container, $user->getUID());
388
-			}
389
-		});
390
-	}
391
-
392
-	private function setupCalendarProvider(ICalendarManager $calendarManager,
393
-										   IAppContainer $container,
394
-										   $userId) {
395
-		$cm = $container->query(CalendarManager::class);
396
-		$cm->setupCalendarProvider($calendarManager, $userId);
397
-	}
398
-
399
-	public function registerNotifier(INotificationManager $manager): void {
400
-		$manager->registerNotifierService(Notifier::class);
401
-	}
402
-
403
-	public function registerCalendarReminders(NotificationProviderManager $manager,
404
-											   ILogger $logger): void {
405
-		try {
406
-			$manager->registerProvider(AudioProvider::class);
407
-			$manager->registerProvider(EmailProvider::class);
408
-			$manager->registerProvider(PushProvider::class);
409
-		} catch (Throwable $ex) {
410
-			$logger->logException($ex);
411
-		}
412
-	}
110
+        $context->registerSearchProvider(ContactsSearchProvider::class);
111
+        $context->registerSearchProvider(EventsSearchProvider::class);
112
+        $context->registerSearchProvider(TasksSearchProvider::class);
113
+
114
+        /**
115
+         * Register event listeners
116
+         */
117
+        $context->registerEventListener(CalendarObjectCreatedEvent::class, CalendarContactInteractionListener::class);
118
+        $context->registerEventListener(CalendarObjectUpdatedEvent::class, CalendarContactInteractionListener::class);
119
+        $context->registerEventListener(CalendarShareUpdatedEvent::class, CalendarContactInteractionListener::class);
120
+    }
121
+
122
+    public function boot(IBootContext $context): void {
123
+        // Load all dav apps
124
+        \OC_App::loadApps(['dav']);
125
+
126
+        $context->injectFn([$this, 'registerHooks']);
127
+        $context->injectFn([$this, 'registerContactsManager']);
128
+        $context->injectFn([$this, 'registerCalendarManager']);
129
+        $context->injectFn([$this, 'registerNotifier']);
130
+        $context->injectFn([$this, 'registerCalendarReminders']);
131
+    }
132
+
133
+    public function registerHooks(HookManager $hm,
134
+                                    EventDispatcherInterface $dispatcher,
135
+                                    IAppContainer $container,
136
+                                    IServerContainer $serverContainer) {
137
+        $hm->setup();
138
+
139
+        // first time login event setup
140
+        $dispatcher->addListener(IUser::class . '::firstLogin', function ($event) use ($hm) {
141
+            if ($event instanceof GenericEvent) {
142
+                $hm->firstLogin($event->getSubject());
143
+            }
144
+        });
145
+
146
+        $birthdayListener = function ($event) use ($container): void {
147
+            if ($event instanceof GenericEvent) {
148
+                /** @var BirthdayService $b */
149
+                $b = $container->query(BirthdayService::class);
150
+                $b->onCardChanged(
151
+                    (int) $event->getArgument('addressBookId'),
152
+                    (string) $event->getArgument('cardUri'),
153
+                    (string) $event->getArgument('cardData')
154
+                );
155
+            }
156
+        };
157
+
158
+        $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::createCard', $birthdayListener);
159
+        $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $birthdayListener);
160
+        $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', function ($event) use ($container) {
161
+            if ($event instanceof GenericEvent) {
162
+                /** @var BirthdayService $b */
163
+                $b = $container->query(BirthdayService::class);
164
+                $b->onCardDeleted(
165
+                    (int) $event->getArgument('addressBookId'),
166
+                    (string) $event->getArgument('cardUri')
167
+                );
168
+            }
169
+        });
170
+
171
+        $clearPhotoCache = function ($event) use ($container): void {
172
+            if ($event instanceof GenericEvent) {
173
+                /** @var PhotoCache $p */
174
+                $p = $container->query(PhotoCache::class);
175
+                $p->delete(
176
+                    $event->getArgument('addressBookId'),
177
+                    $event->getArgument('cardUri')
178
+                );
179
+            }
180
+        };
181
+        $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $clearPhotoCache);
182
+        $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', $clearPhotoCache);
183
+
184
+        $dispatcher->addListener('OC\AccountManager::userUpdated', function (GenericEvent $event) use ($container) {
185
+            $user = $event->getSubject();
186
+            /** @var SyncService $syncService */
187
+            $syncService = $container->query(SyncService::class);
188
+            $syncService->updateUser($user);
189
+        });
190
+
191
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createCalendar', function (GenericEvent $event) use ($container) {
192
+            /** @var Backend $backend */
193
+            $backend = $container->query(Backend::class);
194
+            $backend->onCalendarAdd(
195
+                $event->getArgument('calendarData')
196
+            );
197
+        });
198
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateCalendar', function (GenericEvent $event) use ($container) {
199
+            /** @var Backend $backend */
200
+            $backend = $container->query(Backend::class);
201
+            $backend->onCalendarUpdate(
202
+                $event->getArgument('calendarData'),
203
+                $event->getArgument('shares'),
204
+                $event->getArgument('propertyMutations')
205
+            );
206
+        });
207
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendar', function (GenericEvent $event) use ($container) {
208
+            /** @var Backend $backend */
209
+            $backend = $container->query(Backend::class);
210
+            $backend->onCalendarDelete(
211
+                $event->getArgument('calendarData'),
212
+                $event->getArgument('shares')
213
+            );
214
+
215
+            /** @var ReminderBackend $reminderBackend */
216
+            $reminderBackend = $container->query(ReminderBackend::class);
217
+            $reminderBackend->cleanRemindersForCalendar(
218
+                (int) $event->getArgument('calendarId')
219
+            );
220
+        });
221
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateShares', function (GenericEvent $event) use ($container) {
222
+            /** @var Backend $backend */
223
+            $backend = $container->query(Backend::class);
224
+            $backend->onCalendarUpdateShares(
225
+                $event->getArgument('calendarData'),
226
+                $event->getArgument('shares'),
227
+                $event->getArgument('add'),
228
+                $event->getArgument('remove')
229
+            );
230
+
231
+            // Here we should recalculate if reminders should be sent to new or old sharees
232
+        });
233
+
234
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', function (GenericEvent $event) use ($container) {
235
+            /** @var Backend $backend */
236
+            $backend = $container->query(Backend::class);
237
+            $backend->onCalendarPublication(
238
+                $event->getArgument('calendarData'),
239
+                $event->getArgument('public')
240
+            );
241
+        });
242
+
243
+        $listener = function (GenericEvent $event, $eventName) use ($container): void {
244
+            /** @var Backend $backend */
245
+            $backend = $container->query(Backend::class);
246
+
247
+            $subject = Event::SUBJECT_OBJECT_ADD;
248
+            if ($eventName === '\OCA\DAV\CalDAV\CalDavBackend::updateCalendarObject') {
249
+                $subject = Event::SUBJECT_OBJECT_UPDATE;
250
+            } elseif ($eventName === '\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject') {
251
+                $subject = Event::SUBJECT_OBJECT_DELETE;
252
+            }
253
+            $backend->onTouchCalendarObject(
254
+                $subject,
255
+                $event->getArgument('calendarData'),
256
+                $event->getArgument('shares'),
257
+                $event->getArgument('objectData')
258
+            );
259
+
260
+            /** @var ReminderService $reminderBackend */
261
+            $reminderService = $container->query(ReminderService::class);
262
+
263
+            $reminderService->onTouchCalendarObject(
264
+                $eventName,
265
+                $event->getArgument('objectData')
266
+            );
267
+        };
268
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createCalendarObject', $listener);
269
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateCalendarObject', $listener);
270
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject', $listener);
271
+
272
+        /**
273
+         * In case the user has set their default calendar to this one
274
+         */
275
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendar', function (GenericEvent $event) use ($serverContainer) {
276
+            /** @var IConfig $config */
277
+            $config = $serverContainer->getConfig();
278
+            $principalUri = $event->getArgument('calendarData')['principaluri'];
279
+            if (strpos($principalUri, 'principals/users') === 0) {
280
+                list(, $UID) = \Sabre\Uri\split($principalUri);
281
+                $uri = $event->getArgument('calendarData')['uri'];
282
+                if ($config->getUserValue($UID, 'dav', 'defaultCalendar') === $uri) {
283
+                    $config->deleteUserValue($UID, 'dav', 'defaultCalendar');
284
+                }
285
+            }
286
+        });
287
+
288
+        $dispatcher->addListener('OCP\Federation\TrustedServerEvent::remove',
289
+            function (GenericEvent $event) {
290
+                /** @var CardDavBackend $cardDavBackend */
291
+                $cardDavBackend = \OC::$server->query(CardDavBackend::class);
292
+                $addressBookUri = $event->getSubject();
293
+                $addressBook = $cardDavBackend->getAddressBooksByUri('principals/system/system', $addressBookUri);
294
+                if (!is_null($addressBook)) {
295
+                    $cardDavBackend->deleteAddressBook($addressBook['id']);
296
+                }
297
+            }
298
+        );
299
+
300
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createSubscription',
301
+            function (GenericEvent $event) use ($container, $serverContainer) {
302
+                $jobList = $serverContainer->getJobList();
303
+                $subscriptionData = $event->getArgument('subscriptionData');
304
+
305
+                /**
306
+                 * Initial subscription refetch
307
+                 *
308
+                 * @var RefreshWebcalService $refreshWebcalService
309
+                 */
310
+                $refreshWebcalService = $container->query(RefreshWebcalService::class);
311
+                $refreshWebcalService->refreshSubscription(
312
+                    (string) $subscriptionData['principaluri'],
313
+                    (string) $subscriptionData['uri']
314
+                );
315
+
316
+                $jobList->add(\OCA\DAV\BackgroundJob\RefreshWebcalJob::class, [
317
+                    'principaluri' => $subscriptionData['principaluri'],
318
+                    'uri' => $subscriptionData['uri']
319
+                ]);
320
+            }
321
+        );
322
+
323
+        $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteSubscription',
324
+            function (GenericEvent $event) use ($container, $serverContainer) {
325
+                $jobList = $serverContainer->getJobList();
326
+                $subscriptionData = $event->getArgument('subscriptionData');
327
+
328
+                $jobList->remove(\OCA\DAV\BackgroundJob\RefreshWebcalJob::class, [
329
+                    'principaluri' => $subscriptionData['principaluri'],
330
+                    'uri' => $subscriptionData['uri']
331
+                ]);
332
+
333
+                /** @var CalDavBackend $calDavBackend */
334
+                $calDavBackend = $container->query(CalDavBackend::class);
335
+                $calDavBackend->purgeAllCachedEventsForSubscription($subscriptionData['id']);
336
+            }
337
+        );
338
+
339
+        $eventHandler = function () use ($container, $serverContainer): void {
340
+            try {
341
+                /** @var UpdateCalendarResourcesRoomsBackgroundJob $job */
342
+                $job = $container->query(UpdateCalendarResourcesRoomsBackgroundJob::class);
343
+                $job->run([]);
344
+                $serverContainer->getJobList()->setLastRun($job);
345
+            } catch (Exception $ex) {
346
+                $serverContainer->getLogger()->logException($ex);
347
+            }
348
+        };
349
+
350
+        $dispatcher->addListener('\OCP\Calendar\Resource\ForceRefreshEvent', $eventHandler);
351
+        $dispatcher->addListener('\OCP\Calendar\Room\ForceRefreshEvent', $eventHandler);
352
+    }
353
+
354
+    public function registerContactsManager(IContactsManager $cm, IAppContainer $container): void {
355
+        $cm->register(function () use ($container, $cm): void {
356
+            $user = \OC::$server->getUserSession()->getUser();
357
+            if (!is_null($user)) {
358
+                $this->setupContactsProvider($cm, $container, $user->getUID());
359
+            } else {
360
+                $this->setupSystemContactsProvider($cm, $container);
361
+            }
362
+        });
363
+    }
364
+
365
+    private function setupContactsProvider(IContactsManager $contactsManager,
366
+                                            IAppContainer $container,
367
+                                            string $userID): void {
368
+        /** @var ContactsManager $cm */
369
+        $cm = $container->query(ContactsManager::class);
370
+        $urlGenerator = $container->getServer()->getURLGenerator();
371
+        $cm->setupContactsProvider($contactsManager, $userID, $urlGenerator);
372
+    }
373
+
374
+    private function setupSystemContactsProvider(IContactsManager $contactsManager,
375
+                                                    IAppContainer $container): void {
376
+        /** @var ContactsManager $cm */
377
+        $cm = $container->query(ContactsManager::class);
378
+        $urlGenerator = $container->getServer()->getURLGenerator();
379
+        $cm->setupSystemContactsProvider($contactsManager, $urlGenerator);
380
+    }
381
+
382
+    public function registerCalendarManager(ICalendarManager $calendarManager,
383
+                                                IAppContainer $container): void {
384
+        $calendarManager->register(function () use ($container, $calendarManager) {
385
+            $user = \OC::$server->getUserSession()->getUser();
386
+            if ($user !== null) {
387
+                $this->setupCalendarProvider($calendarManager, $container, $user->getUID());
388
+            }
389
+        });
390
+    }
391
+
392
+    private function setupCalendarProvider(ICalendarManager $calendarManager,
393
+                                            IAppContainer $container,
394
+                                            $userId) {
395
+        $cm = $container->query(CalendarManager::class);
396
+        $cm->setupCalendarProvider($calendarManager, $userId);
397
+    }
398
+
399
+    public function registerNotifier(INotificationManager $manager): void {
400
+        $manager->registerNotifierService(Notifier::class);
401
+    }
402
+
403
+    public function registerCalendarReminders(NotificationProviderManager $manager,
404
+                                                ILogger $logger): void {
405
+        try {
406
+            $manager->registerProvider(AudioProvider::class);
407
+            $manager->registerProvider(EmailProvider::class);
408
+            $manager->registerProvider(PushProvider::class);
409
+        } catch (Throwable $ex) {
410
+            $logger->logException($ex);
411
+        }
412
+    }
413 413
 }
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -89,7 +89,7 @@  discard block
 block discarded – undo
89 89
 
90 90
 	public function register(IRegistrationContext $context): void {
91 91
 		$context->registerServiceAlias('CardDAVSyncService', SyncService::class);
92
-		$context->registerService(PhotoCache::class, function (ContainerInterface $c) {
92
+		$context->registerService(PhotoCache::class, function(ContainerInterface $c) {
93 93
 			/** @var IServerContainer $server */
94 94
 			$server = $c->get(IServerContainer::class);
95 95
 
@@ -137,13 +137,13 @@  discard block
 block discarded – undo
137 137
 		$hm->setup();
138 138
 
139 139
 		// first time login event setup
140
-		$dispatcher->addListener(IUser::class . '::firstLogin', function ($event) use ($hm) {
140
+		$dispatcher->addListener(IUser::class.'::firstLogin', function($event) use ($hm) {
141 141
 			if ($event instanceof GenericEvent) {
142 142
 				$hm->firstLogin($event->getSubject());
143 143
 			}
144 144
 		});
145 145
 
146
-		$birthdayListener = function ($event) use ($container): void {
146
+		$birthdayListener = function($event) use ($container): void {
147 147
 			if ($event instanceof GenericEvent) {
148 148
 				/** @var BirthdayService $b */
149 149
 				$b = $container->query(BirthdayService::class);
@@ -157,7 +157,7 @@  discard block
 block discarded – undo
157 157
 
158 158
 		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::createCard', $birthdayListener);
159 159
 		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $birthdayListener);
160
-		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', function ($event) use ($container) {
160
+		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', function($event) use ($container) {
161 161
 			if ($event instanceof GenericEvent) {
162 162
 				/** @var BirthdayService $b */
163 163
 				$b = $container->query(BirthdayService::class);
@@ -168,7 +168,7 @@  discard block
 block discarded – undo
168 168
 			}
169 169
 		});
170 170
 
171
-		$clearPhotoCache = function ($event) use ($container): void {
171
+		$clearPhotoCache = function($event) use ($container): void {
172 172
 			if ($event instanceof GenericEvent) {
173 173
 				/** @var PhotoCache $p */
174 174
 				$p = $container->query(PhotoCache::class);
@@ -181,21 +181,21 @@  discard block
 block discarded – undo
181 181
 		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $clearPhotoCache);
182 182
 		$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', $clearPhotoCache);
183 183
 
184
-		$dispatcher->addListener('OC\AccountManager::userUpdated', function (GenericEvent $event) use ($container) {
184
+		$dispatcher->addListener('OC\AccountManager::userUpdated', function(GenericEvent $event) use ($container) {
185 185
 			$user = $event->getSubject();
186 186
 			/** @var SyncService $syncService */
187 187
 			$syncService = $container->query(SyncService::class);
188 188
 			$syncService->updateUser($user);
189 189
 		});
190 190
 
191
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createCalendar', function (GenericEvent $event) use ($container) {
191
+		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createCalendar', function(GenericEvent $event) use ($container) {
192 192
 			/** @var Backend $backend */
193 193
 			$backend = $container->query(Backend::class);
194 194
 			$backend->onCalendarAdd(
195 195
 				$event->getArgument('calendarData')
196 196
 			);
197 197
 		});
198
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateCalendar', function (GenericEvent $event) use ($container) {
198
+		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateCalendar', function(GenericEvent $event) use ($container) {
199 199
 			/** @var Backend $backend */
200 200
 			$backend = $container->query(Backend::class);
201 201
 			$backend->onCalendarUpdate(
@@ -204,7 +204,7 @@  discard block
 block discarded – undo
204 204
 				$event->getArgument('propertyMutations')
205 205
 			);
206 206
 		});
207
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendar', function (GenericEvent $event) use ($container) {
207
+		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendar', function(GenericEvent $event) use ($container) {
208 208
 			/** @var Backend $backend */
209 209
 			$backend = $container->query(Backend::class);
210 210
 			$backend->onCalendarDelete(
@@ -218,7 +218,7 @@  discard block
 block discarded – undo
218 218
 				(int) $event->getArgument('calendarId')
219 219
 			);
220 220
 		});
221
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateShares', function (GenericEvent $event) use ($container) {
221
+		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateShares', function(GenericEvent $event) use ($container) {
222 222
 			/** @var Backend $backend */
223 223
 			$backend = $container->query(Backend::class);
224 224
 			$backend->onCalendarUpdateShares(
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
 			// Here we should recalculate if reminders should be sent to new or old sharees
232 232
 		});
233 233
 
234
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', function (GenericEvent $event) use ($container) {
234
+		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', function(GenericEvent $event) use ($container) {
235 235
 			/** @var Backend $backend */
236 236
 			$backend = $container->query(Backend::class);
237 237
 			$backend->onCalendarPublication(
@@ -240,7 +240,7 @@  discard block
 block discarded – undo
240 240
 			);
241 241
 		});
242 242
 
243
-		$listener = function (GenericEvent $event, $eventName) use ($container): void {
243
+		$listener = function(GenericEvent $event, $eventName) use ($container): void {
244 244
 			/** @var Backend $backend */
245 245
 			$backend = $container->query(Backend::class);
246 246
 
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
 		/**
273 273
 		 * In case the user has set their default calendar to this one
274 274
 		 */
275
-		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendar', function (GenericEvent $event) use ($serverContainer) {
275
+		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendar', function(GenericEvent $event) use ($serverContainer) {
276 276
 			/** @var IConfig $config */
277 277
 			$config = $serverContainer->getConfig();
278 278
 			$principalUri = $event->getArgument('calendarData')['principaluri'];
@@ -286,7 +286,7 @@  discard block
 block discarded – undo
286 286
 		});
287 287
 
288 288
 		$dispatcher->addListener('OCP\Federation\TrustedServerEvent::remove',
289
-			function (GenericEvent $event) {
289
+			function(GenericEvent $event) {
290 290
 				/** @var CardDavBackend $cardDavBackend */
291 291
 				$cardDavBackend = \OC::$server->query(CardDavBackend::class);
292 292
 				$addressBookUri = $event->getSubject();
@@ -298,7 +298,7 @@  discard block
 block discarded – undo
298 298
 		);
299 299
 
300 300
 		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createSubscription',
301
-			function (GenericEvent $event) use ($container, $serverContainer) {
301
+			function(GenericEvent $event) use ($container, $serverContainer) {
302 302
 				$jobList = $serverContainer->getJobList();
303 303
 				$subscriptionData = $event->getArgument('subscriptionData');
304 304
 
@@ -321,7 +321,7 @@  discard block
 block discarded – undo
321 321
 		);
322 322
 
323 323
 		$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteSubscription',
324
-			function (GenericEvent $event) use ($container, $serverContainer) {
324
+			function(GenericEvent $event) use ($container, $serverContainer) {
325 325
 				$jobList = $serverContainer->getJobList();
326 326
 				$subscriptionData = $event->getArgument('subscriptionData');
327 327
 
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
 			}
337 337
 		);
338 338
 
339
-		$eventHandler = function () use ($container, $serverContainer): void {
339
+		$eventHandler = function() use ($container, $serverContainer): void {
340 340
 			try {
341 341
 				/** @var UpdateCalendarResourcesRoomsBackgroundJob $job */
342 342
 				$job = $container->query(UpdateCalendarResourcesRoomsBackgroundJob::class);
@@ -352,7 +352,7 @@  discard block
 block discarded – undo
352 352
 	}
353 353
 
354 354
 	public function registerContactsManager(IContactsManager $cm, IAppContainer $container): void {
355
-		$cm->register(function () use ($container, $cm): void {
355
+		$cm->register(function() use ($container, $cm): void {
356 356
 			$user = \OC::$server->getUserSession()->getUser();
357 357
 			if (!is_null($user)) {
358 358
 				$this->setupContactsProvider($cm, $container, $user->getUID());
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
 
382 382
 	public function registerCalendarManager(ICalendarManager $calendarManager,
383 383
 											 IAppContainer $container): void {
384
-		$calendarManager->register(function () use ($container, $calendarManager) {
384
+		$calendarManager->register(function() use ($container, $calendarManager) {
385 385
 			$user = \OC::$server->getUserSession()->getUser();
386 386
 			if ($user !== null) {
387 387
 				$this->setupCalendarProvider($calendarManager, $container, $user->getUID());
Please login to merge, or discard this patch.
apps/accessibility/lib/Controller/ConfigController.php 2 patches
Indentation   +114 added lines, -114 removed lines patch added patch discarded remove patch
@@ -42,118 +42,118 @@
 block discarded – undo
42 42
 
43 43
 class ConfigController extends OCSController {
44 44
 
45
-	/** @var string */
46
-	protected $appName;
47
-
48
-	/** @var string */
49
-	protected $userId;
50
-
51
-	/** @var string */
52
-	protected $serverRoot;
53
-
54
-	/** @var IConfig */
55
-	private $config;
56
-
57
-	/** @var IUserSession */
58
-	private $userSession;
59
-
60
-	/** @var AccessibilityProvider */
61
-	private $accessibilityProvider;
62
-
63
-	/**
64
-	 * Config constructor.
65
-	 *
66
-	 * @param string $appName
67
-	 * @param IRequest $request
68
-	 * @param IConfig $config
69
-	 * @param IUserSession $userSession
70
-	 * @param AccessibilityProvider $accessibilityProvider
71
-	 */
72
-	public function __construct(string $appName,
73
-								IRequest $request,
74
-								IConfig $config,
75
-								IUserSession $userSession,
76
-								AccessibilityProvider $accessibilityProvider) {
77
-		parent::__construct($appName, $request);
78
-		$this->appName = $appName;
79
-		$this->config = $config;
80
-		$this->userSession = $userSession;
81
-		$this->accessibilityProvider = $accessibilityProvider;
82
-		$this->userId = $userSession->getUser()->getUID();
83
-	}
84
-
85
-	/**
86
-	 * @NoAdminRequired
87
-	 *
88
-	 * Get user accessibility config
89
-	 *
90
-	 * @param string $key theme or font
91
-	 * @return DataResponse
92
-	 */
93
-	public function getConfig(): DataResponse {
94
-		return new DataResponse([
95
-			'highcontrast' => $this->config->getUserValue($this->userId, $this->appName, 'highcontrast', false),
96
-			'theme' => $this->config->getUserValue($this->userId, $this->appName, 'theme', false),
97
-			'font' => $this->config->getUserValue($this->userId, $this->appName, 'font', false)
98
-		]);
99
-	}
100
-
101
-	/**
102
-	 * @NoAdminRequired
103
-	 *
104
-	 * Set theme or font config
105
-	 *
106
-	 * @param string $key theme or font
107
-	 * @return DataResponse
108
-	 * @throws OCSBadRequestException|PreConditionNotMetException
109
-	 */
110
-	public function setConfig(string $key, $value): DataResponse {
111
-		if ($key === 'theme' || $key === 'font' || $key === 'highcontrast') {
112
-			if ($value === false || $value === '') {
113
-				throw new OCSBadRequestException('Invalid value: ' . $value);
114
-			}
115
-
116
-			$themes = $this->accessibilityProvider->getThemes();
117
-			$highcontrast = [$this->accessibilityProvider->getHighContrast()];
118
-			$fonts = $this->accessibilityProvider->getFonts();
119
-
120
-			$availableOptions = array_map(function ($option): string {
121
-				return $option['id'];
122
-			}, array_merge($themes, $highcontrast, $fonts));
123
-
124
-			if (in_array($value, $availableOptions)) {
125
-				$this->config->setUserValue($this->userId, $this->appName, $key, $value);
126
-				return new DataResponse();
127
-			}
128
-
129
-			throw new OCSBadRequestException('Invalid value: ' . $value);
130
-		}
131
-
132
-		throw new OCSBadRequestException('Invalid key: ' . $key);
133
-	}
134
-
135
-	/**
136
-	 * @NoAdminRequired
137
-	 *
138
-	 * Unset theme or font config
139
-	 *
140
-	 * @param string $key theme or font
141
-	 * @return DataResponse
142
-	 * @throws OCSBadRequestException
143
-	 */
144
-	public function deleteConfig(string $key): DataResponse {
145
-		if ($key === 'theme' || $key === 'font' || $key === 'highcontrast') {
146
-			$this->config->deleteUserValue($this->userId, $this->appName, $key);
147
-			$userValues = $this->config->getUserKeys($this->userId, $this->appName);
148
-
149
-			// remove hash if no settings selected
150
-			if (count($userValues) === 1 && $userValues[0] === 'icons-css') {
151
-				$this->config->deleteUserValue($this->userId, $this->appName, 'icons-css');
152
-			}
153
-
154
-			return new DataResponse();
155
-		}
156
-
157
-		throw new OCSBadRequestException('Invalid key: ' . $key);
158
-	}
45
+    /** @var string */
46
+    protected $appName;
47
+
48
+    /** @var string */
49
+    protected $userId;
50
+
51
+    /** @var string */
52
+    protected $serverRoot;
53
+
54
+    /** @var IConfig */
55
+    private $config;
56
+
57
+    /** @var IUserSession */
58
+    private $userSession;
59
+
60
+    /** @var AccessibilityProvider */
61
+    private $accessibilityProvider;
62
+
63
+    /**
64
+     * Config constructor.
65
+     *
66
+     * @param string $appName
67
+     * @param IRequest $request
68
+     * @param IConfig $config
69
+     * @param IUserSession $userSession
70
+     * @param AccessibilityProvider $accessibilityProvider
71
+     */
72
+    public function __construct(string $appName,
73
+                                IRequest $request,
74
+                                IConfig $config,
75
+                                IUserSession $userSession,
76
+                                AccessibilityProvider $accessibilityProvider) {
77
+        parent::__construct($appName, $request);
78
+        $this->appName = $appName;
79
+        $this->config = $config;
80
+        $this->userSession = $userSession;
81
+        $this->accessibilityProvider = $accessibilityProvider;
82
+        $this->userId = $userSession->getUser()->getUID();
83
+    }
84
+
85
+    /**
86
+     * @NoAdminRequired
87
+     *
88
+     * Get user accessibility config
89
+     *
90
+     * @param string $key theme or font
91
+     * @return DataResponse
92
+     */
93
+    public function getConfig(): DataResponse {
94
+        return new DataResponse([
95
+            'highcontrast' => $this->config->getUserValue($this->userId, $this->appName, 'highcontrast', false),
96
+            'theme' => $this->config->getUserValue($this->userId, $this->appName, 'theme', false),
97
+            'font' => $this->config->getUserValue($this->userId, $this->appName, 'font', false)
98
+        ]);
99
+    }
100
+
101
+    /**
102
+     * @NoAdminRequired
103
+     *
104
+     * Set theme or font config
105
+     *
106
+     * @param string $key theme or font
107
+     * @return DataResponse
108
+     * @throws OCSBadRequestException|PreConditionNotMetException
109
+     */
110
+    public function setConfig(string $key, $value): DataResponse {
111
+        if ($key === 'theme' || $key === 'font' || $key === 'highcontrast') {
112
+            if ($value === false || $value === '') {
113
+                throw new OCSBadRequestException('Invalid value: ' . $value);
114
+            }
115
+
116
+            $themes = $this->accessibilityProvider->getThemes();
117
+            $highcontrast = [$this->accessibilityProvider->getHighContrast()];
118
+            $fonts = $this->accessibilityProvider->getFonts();
119
+
120
+            $availableOptions = array_map(function ($option): string {
121
+                return $option['id'];
122
+            }, array_merge($themes, $highcontrast, $fonts));
123
+
124
+            if (in_array($value, $availableOptions)) {
125
+                $this->config->setUserValue($this->userId, $this->appName, $key, $value);
126
+                return new DataResponse();
127
+            }
128
+
129
+            throw new OCSBadRequestException('Invalid value: ' . $value);
130
+        }
131
+
132
+        throw new OCSBadRequestException('Invalid key: ' . $key);
133
+    }
134
+
135
+    /**
136
+     * @NoAdminRequired
137
+     *
138
+     * Unset theme or font config
139
+     *
140
+     * @param string $key theme or font
141
+     * @return DataResponse
142
+     * @throws OCSBadRequestException
143
+     */
144
+    public function deleteConfig(string $key): DataResponse {
145
+        if ($key === 'theme' || $key === 'font' || $key === 'highcontrast') {
146
+            $this->config->deleteUserValue($this->userId, $this->appName, $key);
147
+            $userValues = $this->config->getUserKeys($this->userId, $this->appName);
148
+
149
+            // remove hash if no settings selected
150
+            if (count($userValues) === 1 && $userValues[0] === 'icons-css') {
151
+                $this->config->deleteUserValue($this->userId, $this->appName, 'icons-css');
152
+            }
153
+
154
+            return new DataResponse();
155
+        }
156
+
157
+        throw new OCSBadRequestException('Invalid key: ' . $key);
158
+    }
159 159
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -110,14 +110,14 @@  discard block
 block discarded – undo
110 110
 	public function setConfig(string $key, $value): DataResponse {
111 111
 		if ($key === 'theme' || $key === 'font' || $key === 'highcontrast') {
112 112
 			if ($value === false || $value === '') {
113
-				throw new OCSBadRequestException('Invalid value: ' . $value);
113
+				throw new OCSBadRequestException('Invalid value: '.$value);
114 114
 			}
115 115
 
116 116
 			$themes = $this->accessibilityProvider->getThemes();
117 117
 			$highcontrast = [$this->accessibilityProvider->getHighContrast()];
118 118
 			$fonts = $this->accessibilityProvider->getFonts();
119 119
 
120
-			$availableOptions = array_map(function ($option): string {
120
+			$availableOptions = array_map(function($option): string {
121 121
 				return $option['id'];
122 122
 			}, array_merge($themes, $highcontrast, $fonts));
123 123
 
@@ -126,10 +126,10 @@  discard block
 block discarded – undo
126 126
 				return new DataResponse();
127 127
 			}
128 128
 
129
-			throw new OCSBadRequestException('Invalid value: ' . $value);
129
+			throw new OCSBadRequestException('Invalid value: '.$value);
130 130
 		}
131 131
 
132
-		throw new OCSBadRequestException('Invalid key: ' . $key);
132
+		throw new OCSBadRequestException('Invalid key: '.$key);
133 133
 	}
134 134
 
135 135
 	/**
@@ -154,6 +154,6 @@  discard block
 block discarded – undo
154 154
 			return new DataResponse();
155 155
 		}
156 156
 
157
-		throw new OCSBadRequestException('Invalid key: ' . $key);
157
+		throw new OCSBadRequestException('Invalid key: '.$key);
158 158
 	}
159 159
 }
Please login to merge, or discard this patch.