Completed
Push — max-version-9.0-791d122c ( 791d12 )
by Thomas
26:14
created

Scanner::scan()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 21
rs 8.7624
cc 5
eloc 14
nc 10
nop 1
1
<?php
2
/**
3
 * ownCloud - Calendar App
4
 *
5
 * @author Georg Ehrke
6
 * @copyright 2014 Georg Ehrke <[email protected]>
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
10
 * License as published by the Free Software Foundation; either
11
 * version 3 of the License, or any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public
19
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
namespace OCA\Calendar\Cache\Calendar;
23
24
use OCA\Calendar\Backend\DoesNotExistException;
25
use OCA\Calendar\Backend\MultipleObjectsReturnedException;
26
use OCA\Calendar\Backend\TemporarilyNotAvailableException;
27
use OCA\Calendar\CorruptDataException;
28
use OCA\Calendar\IBackend;
29
use OCA\Calendar\IBackendCollection;
30
use OCA\Calendar\ICalendar;
31
32
use OCA\Calendar\Utility\CalendarUtility;
33
use OCP\ILogger;
34
35
use OCP\AppFramework\Db\DoesNotExistException as DoesNotExistMapperException;
36
use OCP\AppFramework\Db\MultipleObjectsReturnedException as MultipleObjectsReturnedMapperException;
37
38
class Scanner {
39
40
	/**
41
	 * @var IBackendCollection
42
	 */
43
	protected $backends;
44
45
46
	/**
47
	 * @var \OCA\Calendar\Cache\Calendar\Cache
48
	 */
49
	protected $cache;
50
51
52
	/**
53
	 * @var ILogger
54
	 */
55
	protected $logger;
56
57
58
	/**
59
	 * @param IBackendCollection $backends
60
	 * @param ILogger $logger
61
	 */
62
	public function __construct(IBackendCollection $backends, ILogger $logger) {
63
		$this->backends = $backends;
64
		$this->cache = $backends->getCache();
65
		$this->logger = $logger;
66
	}
67
68
69
	/**
70
	 * @param string $backendId
71
	 * @param string $privateUri
72
	 * @param string $userId
73
	 * @param ICalendar $usersCalendar
74
	 * @return mixed
75
	 */
76
	public function scanCalendar($backendId, $privateUri, $userId, ICalendar &$usersCalendar=null) {
77
		$backend = $this->backends->find($backendId);
78
79
		if (!($backend instanceof IBackend)) {
80
			$this->logger->debug('Backend \'' . $backendId . '\' not found');
81
			return null;
82
		}
83
84
		$calendar = $this->getRemoteAndDeleteIfNecessary($backend, $privateUri, $userId);
85
		if (!$calendar) {
86
			return null;
87
		}
88
89
		$cachedCalendar = $this->getCached($backendId, $privateUri, $userId);
90
		if ($cachedCalendar) {
91
			if ($usersCalendar) {
92
				$calendar = $this->resetUnsupportedProperties($backend, $calendar, $usersCalendar);
93
			} else {
94
				$calendar = $this->resetUnsupportedProperties($backend, $calendar, $cachedCalendar);
95
			}
96
97
			$cachedCalendar->overwriteWith($calendar);
98
99
			$this->updateCache($cachedCalendar);
100
		} else {
101
			CalendarUtility::generateURI($calendar, function($newUri) use ($calendar) {
102
				return $this->cache->doesExist($newUri, $calendar->getUserId());
103
			}, true);
104
			$calendar = $this->addToCache($calendar);
105
			if ($usersCalendar) {
106
				$usersCalendar->setId($calendar->getId());
107
			}
108
		}
109
	}
110
111
112
	/**
113
	 * @param IBackend $backend
114
	 * @param string $privateUri
115
	 * @param string $userId
116
	 * @return null|ICalendar
117
	 */
118
	protected function getRemoteAndDeleteIfNecessary(IBackend $backend, $privateUri, $userId) {
119
		$calendarAPI = $backend->getCalendarAPI();
120
		$msg = 'CalendarManager \'' . $backend->getId() . '\'::';
121
		$msg .= '\'' . $privateUri . '\' of \'' . $userId . '\'';
122
123
		try {
124
			return $calendarAPI->find($privateUri, $userId);
125
		} catch(DoesNotExistException $ex) {
126
			$msg .= 'is not available, deleting from cache';
127
			$this->logger->debug($msg);
128
129
			$this->removeFromCache($backend->getId(), $privateUri, $userId);
130
			return null;
131
		} catch(MultipleObjectsReturnedException $ex) {
132
			$msg .= 'available multiple times (please check backend!) ';
133
			$msg .= 'deleting from cache';
134
			$this->logger->debug($msg);
135
136
			$this->removeFromCache($backend->getId(), $privateUri, $userId);
137
			return null;
138
		} catch(TemporarilyNotAvailableException $ex) {
139
			$msg .= 'temporarily not available, skipping for now';
140
			$this->logger->debug($msg);
141
142
			return null;
143
		} catch(CorruptDataException $ex) {
144
			$msg .= 'is corrupted on backend, deleting from cache';
145
			$this->logger->debug($msg);
146
147
			$this->removeFromCache($backend->getId(), $privateUri, $userId);
148
			return null;
149
		}
150
	}
151
152
153
	/**
154
	 * @param string $backendId
155
	 * @param string $privateUri
156
	 * @param string $userId
157
	 * @return null|ICalendar
158
	 */
159
	protected function getCached($backendId, $privateUri, $userId) {
160
		try {
161
			return $this->cache->findByPrivateUri($backendId, $privateUri, $userId);
162
		} catch(DoesNotExistMapperException $ex) {
0 ignored issues
show
Bug introduced by
The class OCP\AppFramework\Db\DoesNotExistException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
163
			return null;
164
		} catch(MultipleObjectsReturnedMapperException $ex) {
0 ignored issues
show
Bug introduced by
The class OCP\AppFramework\Db\Mult...bjectsReturnedException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
165
			//$this->logger->warn($msg); TODO
166
			return null;
167
		}
168
	}
169
170
171
	/**
172
	 * @param ICalendar $calendar
173
	 * @return ICalendar
174
	 */
175
	protected function addToCache(ICalendar $calendar) {
176
		$calendar = $this->cache->insert($calendar);
177
		return $calendar;
178
	}
179
180
181
	/**
182
	 * @param ICalendar $calendar
183
	 */
184
	protected function updateCache(ICalendar $calendar) {
185
		$this->cache->update($calendar);
186
	}
187
188
189
	/**
190
	 * @param string $backendId
191
	 * @param string $privateUri
192
	 * @param string $userId
193
	 */
194
	protected function removeFromCache($backendId, $privateUri, $userId) {
195
		$this->removeFromCache($backendId, $privateUri, $userId);
196
	}
197
198
199
	/**
200
	 * scan all
201
	 * @param string $userId
202
	 */
203
	public function scan($userId) {
204
		$backends = $this->backends->getObjects();
205
		/* @var IBackend $backend */
206
		foreach ($backends as $backend) {
207
			try {
208
				$backendId = $backend->getId();
209
				$calendars = $backend->getCalendarAPI()->listAll($userId);
210
211
				foreach ($calendars as $privateUri) {
212
					try {
213
						$this->scanCalendar($backendId, $privateUri, $userId);
214
					} catch (\Exception $ex) {
215
						$this->logger->debug($ex->getMessage());
216
						continue;
217
					}
218
				}
219
			} catch(\Exception $ex) {
220
				$this->logger->debug($ex->getMessage());
221
			}
222
		}
223
	}
224
225
226
	/**
227
	 * walk over any calendars that are not fully scanned yet and scan them
228
	 */
229
	protected function backgroundScan() {
230
		$scanned = [];
231
		while(($calendar = $this->cache->getIncomplete()) !== false && !in_array($calendar->getId(), $scanned)) {
232
			$this->scanCalendar($calendar->getBackend()->getId(),
233
				$calendar->getPrivateUri(), $calendar->getUserId());
234
			$scanned[] = $calendar->getId();
235
		}
236
	}
237
238
239
	/**
240
	 * @param IBackend $backend
241
	 * @param ICalendar $calendar
242
	 * @param ICalendar $cachedCalendar
243
	 * @return ICalendar
244
	 */
245
	protected function resetUnsupportedProperties(IBackend $backend,
246
											   ICalendar $calendar,
247
											   ICalendar $cachedCalendar) {
248
		$backendAPI = $backend->getBackendAPI();
249
250
		if (!$backendAPI->canStoreColor()) {
251
			$calendar->setColor($cachedCalendar->getColor());
252
		}
253
		if (!$backendAPI->canStoreComponents()) {
254
			$calendar->setComponents($cachedCalendar->getComponents());
255
		}
256
		if (!$backendAPI->canStoreDescription()) {
257
			$calendar->setDescription($cachedCalendar->getDescription());
258
		}
259
		if (!$backendAPI->canStoreDisplayname()) {
260
			$calendar->setDisplayname($cachedCalendar->getDisplayname());
261
		}
262
		if (!$backendAPI->canStoreEnabled()) {
263
			$calendar->setEnabled($cachedCalendar->getEnabled());
264
		}
265
		if (!$backendAPI->canStoreOrder()) {
266
			$calendar->setOrder($cachedCalendar->getOrder());
267
		}
268
269
		return $calendar;
270
	}
271
}