Passed
Push — master ( 7698ad...f746d3 )
by Morris
15:22
created

Manager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 4
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 * @copyright Copyright (c) 2016 Joas Schilling <[email protected]>
5
 *
6
 * @author Björn Schießle <[email protected]>
7
 * @author Joas Schilling <[email protected]>
8
 * @author Roeland Jago Douma <[email protected]>
9
 * @author Thomas Müller <[email protected]>
10
 *
11
 * @license AGPL-3.0
12
 *
13
 * This code is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Affero General Public License, version 3,
15
 * as published by the Free Software Foundation.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License, version 3,
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
24
 *
25
 */
26
namespace OC\Activity;
27
28
29
use OCP\Activity\IConsumer;
30
use OCP\Activity\IEvent;
31
use OCP\Activity\IFilter;
32
use OCP\Activity\IManager;
33
use OCP\Activity\IProvider;
34
use OCP\Activity\ISetting;
35
use OCP\IConfig;
36
use OCP\IRequest;
37
use OCP\IUser;
38
use OCP\IUserSession;
39
use OCP\RichObjectStrings\IValidator;
40
41
class Manager implements IManager {
42
	/** @var IRequest */
43
	protected $request;
44
45
	/** @var IUserSession */
46
	protected $session;
47
48
	/** @var IConfig */
49
	protected $config;
50
51
	/** @var IValidator */
52
	protected $validator;
53
54
	/** @var string */
55
	protected $formattingObjectType;
56
57
	/** @var int */
58
	protected $formattingObjectId;
59
60
	/** @var bool */
61
	protected $requirePNG;
62
63
	/** @var string */
64
	protected $currentUserId;
65
66
	public function __construct(IRequest $request,
67
								IUserSession $session,
68
								IConfig $config,
69
								IValidator $validator) {
70
		$this->request = $request;
71
		$this->session = $session;
72
		$this->config = $config;
73
		$this->validator = $validator;
74
	}
75
76
	/** @var \Closure[] */
77
	private $consumersClosures = array();
78
79
	/** @var IConsumer[] */
80
	private $consumers = array();
81
82
	/**
83
	 * @return \OCP\Activity\IConsumer[]
84
	 */
85
	protected function getConsumers(): array {
86
		if (!empty($this->consumers)) {
87
			return $this->consumers;
88
		}
89
90
		$this->consumers = [];
91
		foreach($this->consumersClosures as $consumer) {
92
			$c = $consumer();
93
			if ($c instanceof IConsumer) {
94
				$this->consumers[] = $c;
95
			} else {
96
				throw new \InvalidArgumentException('The given consumer does not implement the \OCP\Activity\IConsumer interface');
97
			}
98
		}
99
100
		return $this->consumers;
101
	}
102
103
	/**
104
	 * Generates a new IEvent object
105
	 *
106
	 * Make sure to call at least the following methods before sending it to the
107
	 * app with via the publish() method:
108
	 *  - setApp()
109
	 *  - setType()
110
	 *  - setAffectedUser()
111
	 *  - setSubject()
112
	 *
113
	 * @return IEvent
114
	 */
115
	public function generateEvent(): IEvent {
116
		return new Event($this->validator);
117
	}
118
119
	/**
120
	 * Publish an event to the activity consumers
121
	 *
122
	 * Make sure to call at least the following methods before sending an Event:
123
	 *  - setApp()
124
	 *  - setType()
125
	 *  - setAffectedUser()
126
	 *  - setSubject()
127
	 *
128
	 * @param IEvent $event
129
	 * @throws \BadMethodCallException if required values have not been set
130
	 */
131
	public function publish(IEvent $event): void {
132
		if ($event->getAuthor() === '') {
133
			if ($this->session->getUser() instanceof IUser) {
134
				$event->setAuthor($this->session->getUser()->getUID());
135
			}
136
		}
137
138
		if (!$event->getTimestamp()) {
139
			$event->setTimestamp(time());
140
		}
141
142
		if (!$event->isValid()) {
143
			throw new \BadMethodCallException('The given event is invalid');
144
		}
145
146
		foreach ($this->getConsumers() as $c) {
147
			$c->receive($event);
148
		}
149
	}
150
151
	/**
152
	 * In order to improve lazy loading a closure can be registered which will be called in case
153
	 * activity consumers are actually requested
154
	 *
155
	 * $callable has to return an instance of OCA\Activity\IConsumer
156
	 *
157
	 * @param \Closure $callable
158
	 */
159
	public function registerConsumer(\Closure $callable): void {
160
		$this->consumersClosures[] = $callable;
161
		$this->consumers = [];
162
	}
163
164
	/** @var string[] */
165
	protected $filterClasses = [];
166
167
	/** @var IFilter[] */
168
	protected $filters = [];
169
170
	/**
171
	 * @param string $filter Class must implement OCA\Activity\IFilter
172
	 * @return void
173
	 */
174
	public function registerFilter(string $filter): void {
175
		$this->filterClasses[$filter] = false;
176
	}
177
178
	/**
179
	 * @return IFilter[]
180
	 * @throws \InvalidArgumentException
181
	 */
182
	public function getFilters(): array {
183
		foreach ($this->filterClasses as $class => $false) {
184
			/** @var IFilter $filter */
185
			$filter = \OC::$server->query($class);
186
187
			if (!$filter instanceof IFilter) {
188
				throw new \InvalidArgumentException('Invalid activity filter registered');
189
			}
190
191
			$this->filters[$filter->getIdentifier()] = $filter;
192
193
			unset($this->filterClasses[$class]);
194
		}
195
		return $this->filters;
196
	}
197
198
	/**
199
	 * @param string $id
200
	 * @return IFilter
201
	 * @throws \InvalidArgumentException when the filter was not found
202
	 * @since 11.0.0
203
	 */
204
	public function getFilterById(string $id): IFilter {
205
		$filters = $this->getFilters();
206
207
		if (isset($filters[$id])) {
208
			return $filters[$id];
209
		}
210
211
		throw new \InvalidArgumentException('Requested filter does not exist');
212
	}
213
214
	/** @var string[] */
215
	protected $providerClasses = [];
216
217
	/** @var IProvider[] */
218
	protected $providers = [];
219
220
	/**
221
	 * @param string $provider Class must implement OCA\Activity\IProvider
222
	 * @return void
223
	 */
224
	public function registerProvider(string $provider): void {
225
		$this->providerClasses[$provider] = false;
226
	}
227
228
	/**
229
	 * @return IProvider[]
230
	 * @throws \InvalidArgumentException
231
	 */
232
	public function getProviders(): array {
233
		foreach ($this->providerClasses as $class => $false) {
234
			/** @var IProvider $provider */
235
			$provider = \OC::$server->query($class);
236
237
			if (!$provider instanceof IProvider) {
238
				throw new \InvalidArgumentException('Invalid activity provider registered');
239
			}
240
241
			$this->providers[] = $provider;
242
243
			unset($this->providerClasses[$class]);
244
		}
245
		return $this->providers;
246
	}
247
248
	/** @var string[] */
249
	protected $settingsClasses = [];
250
251
	/** @var ISetting[] */
252
	protected $settings = [];
253
254
	/**
255
	 * @param string $setting Class must implement OCA\Activity\ISetting
256
	 * @return void
257
	 */
258
	public function registerSetting(string $setting): void {
259
		$this->settingsClasses[$setting] = false;
260
	}
261
262
	/**
263
	 * @return ISetting[]
264
	 * @throws \InvalidArgumentException
265
	 */
266
	public function getSettings(): array {
267
		foreach ($this->settingsClasses as $class => $false) {
268
			/** @var ISetting $setting */
269
			$setting = \OC::$server->query($class);
270
271
			if (!$setting instanceof ISetting) {
272
				throw new \InvalidArgumentException('Invalid activity filter registered');
273
			}
274
275
			$this->settings[$setting->getIdentifier()] = $setting;
276
277
			unset($this->settingsClasses[$class]);
278
		}
279
		return $this->settings;
280
	}
281
282
	/**
283
	 * @param string $id
284
	 * @return ISetting
285
	 * @throws \InvalidArgumentException when the setting was not found
286
	 * @since 11.0.0
287
	 */
288
	public function getSettingById(string $id): ISetting {
289
		$settings = $this->getSettings();
290
291
		if (isset($settings[$id])) {
292
			return $settings[$id];
293
		}
294
295
		throw new \InvalidArgumentException('Requested setting does not exist');
296
	}
297
298
299
	/**
300
	 * @param string $type
301
	 * @param int $id
302
	 */
303
	public function setFormattingObject(string $type, int $id): void {
304
		$this->formattingObjectType = $type;
305
		$this->formattingObjectId = $id;
306
	}
307
308
	/**
309
	 * @return bool
310
	 */
311
	public function isFormattingFilteredObject(): bool {
312
		return $this->formattingObjectType !== null && $this->formattingObjectId !== null
313
			&& $this->formattingObjectType === $this->request->getParam('object_type')
314
			&& $this->formattingObjectId === (int) $this->request->getParam('object_id');
315
	}
316
317
	/**
318
	 * @param bool $status Set to true, when parsing events should not use SVG icons
319
	 */
320
	public function setRequirePNG(bool $status): void {
321
		$this->requirePNG = $status;
322
	}
323
324
	/**
325
	 * @return bool
326
	 */
327
	public function getRequirePNG(): bool {
328
		return $this->requirePNG;
329
	}
330
331
	/**
332
	 * Set the user we need to use
333
	 *
334
	 * @param string|null $currentUserId
335
	 * @throws \UnexpectedValueException If the user is invalid
336
	 */
337
	public function setCurrentUserId(string $currentUserId = null): void {
338
		if (!is_string($currentUserId) && $currentUserId !== null) {
0 ignored issues
show
introduced by
The condition $currentUserId !== null is always false.
Loading history...
339
			throw new \UnexpectedValueException('The given current user is invalid');
340
		}
341
		$this->currentUserId = $currentUserId;
342
	}
343
344
	/**
345
	 * Get the user we need to use
346
	 *
347
	 * Either the user is logged in, or we try to get it from the token
348
	 *
349
	 * @return string
350
	 * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique
351
	 */
352
	public function getCurrentUserId(): string {
353
		if ($this->currentUserId !== null) {
354
			return $this->currentUserId;
355
		}
356
357
		if (!$this->session->isLoggedIn()) {
358
			return $this->getUserFromToken();
359
		}
360
361
		return $this->session->getUser()->getUID();
362
	}
363
364
	/**
365
	 * Get the user for the token
366
	 *
367
	 * @return string
368
	 * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique
369
	 */
370
	protected function getUserFromToken(): string {
371
		$token = (string) $this->request->getParam('token', '');
372
		if (strlen($token) !== 30) {
373
			throw new \UnexpectedValueException('The token is invalid');
374
		}
375
376
		$users = $this->config->getUsersForUserValue('activity', 'rsstoken', $token);
377
378
		if (count($users) !== 1) {
379
			// No unique user found
380
			throw new \UnexpectedValueException('The token is invalid');
381
		}
382
383
		// Token found login as that user
384
		return array_shift($users);
385
	}
386
387
}
388