Passed
Push — master ( 3a44ca...99013d )
by Julius
13:35 queued 11s
created

RegistrationContext::registerInitialState()

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
nc 1
nop 2
dl 0
loc 2
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @copyright 2020 Christoph Wurst <[email protected]>
7
 *
8
 * @author Christoph Wurst <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author Julius Härtl <[email protected]>
11
 * @author Roeland Jago Douma <[email protected]>
12
 *
13
 * @license GNU AGPL version 3 or any later version
14
 *
15
 * This program is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License as
17
 * published by the Free Software Foundation, either version 3 of the
18
 * License, or (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License
26
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27
 *
28
 */
29
namespace OC\AppFramework\Bootstrap;
30
31
use Closure;
32
use OC\Support\CrashReport\Registry;
33
use OCP\AppFramework\App;
34
use OCP\AppFramework\Bootstrap\IRegistrationContext;
35
use OCP\AppFramework\Middleware;
36
use OCP\AppFramework\Services\InitialStateProvider;
37
use OCP\Authentication\IAlternativeLogin;
38
use OCP\Capabilities\ICapability;
39
use OCP\Dashboard\IManager;
40
use OCP\Dashboard\IWidget;
41
use OCP\EventDispatcher\IEventDispatcher;
42
use OCP\Files\Template\ICustomTemplateProvider;
43
use OCP\Http\WellKnown\IHandler;
44
use OCP\Notification\INotifier;
45
use OCP\Search\IProvider;
46
use OCP\Support\CrashReport\IReporter;
47
use Psr\Log\LoggerInterface;
48
use Throwable;
49
use function array_shift;
50
51
class RegistrationContext {
52
53
	/** @var ServiceRegistration<ICapability>[] */
54
	private $capabilities = [];
55
56
	/** @var ServiceRegistration<IReporter>[] */
57
	private $crashReporters = [];
58
59
	/** @var ServiceRegistration<IWidget>[] */
60
	private $dashboardPanels = [];
61
62
	/** @var ServiceFactoryRegistration[] */
63
	private $services = [];
64
65
	/** @var ServiceAliasRegistration[] */
66
	private $aliases = [];
67
68
	/** @var ParameterRegistration[] */
69
	private $parameters = [];
70
71
	/** @var EventListenerRegistration[] */
72
	private $eventListeners = [];
73
74
	/** @var ServiceRegistration<Middleware>[] */
75
	private $middlewares = [];
76
77
	/** @var ServiceRegistration<IProvider>[] */
78
	private $searchProviders = [];
79
80
	/** @var ServiceRegistration<IAlternativeLogin>[] */
81
	private $alternativeLogins = [];
82
83
	/** @var ServiceRegistration<InitialStateProvider>[] */
84
	private $initialStates = [];
85
86
	/** @var ServiceRegistration<IHandler>[] */
87
	private $wellKnownHandlers = [];
88
89
	/** @var ServiceRegistration<ICustomTemplateProvider>[] */
90
	private $templateProviders = [];
91
92
	/** @var ServiceRegistration<INotifier>[] */
93
	private $notifierServices = [];
94
95
	/** @var ServiceRegistration<\OCP\Authentication\TwoFactorAuth\IProvider>[] */
96
	private $twoFactorProviders = [];
97
98
	/** @var LoggerInterface */
99
	private $logger;
100
101
	public function __construct(LoggerInterface $logger) {
102
		$this->logger = $logger;
103
	}
104
105
	public function for(string $appId): IRegistrationContext {
106
		return new class($appId, $this) implements IRegistrationContext {
107
			/** @var string */
108
			private $appId;
109
110
			/** @var RegistrationContext */
111
			private $context;
112
113
			public function __construct(string $appId, RegistrationContext $context) {
114
				$this->appId = $appId;
115
				$this->context = $context;
116
			}
117
118
			public function registerCapability(string $capability): void {
119
				$this->context->registerCapability(
120
					$this->appId,
121
					$capability
122
				);
123
			}
124
125
			public function registerCrashReporter(string $reporterClass): void {
126
				$this->context->registerCrashReporter(
127
					$this->appId,
128
					$reporterClass
129
				);
130
			}
131
132
			public function registerDashboardWidget(string $widgetClass): void {
133
				$this->context->registerDashboardPanel(
134
					$this->appId,
135
					$widgetClass
136
				);
137
			}
138
139
			public function registerService(string $name, callable $factory, bool $shared = true): void {
140
				$this->context->registerService(
141
					$this->appId,
142
					$name,
143
					$factory,
144
					$shared
145
				);
146
			}
147
148
			public function registerServiceAlias(string $alias, string $target): void {
149
				$this->context->registerServiceAlias(
150
					$this->appId,
151
					$alias,
152
					$target
153
				);
154
			}
155
156
			public function registerParameter(string $name, $value): void {
157
				$this->context->registerParameter(
158
					$this->appId,
159
					$name,
160
					$value
161
				);
162
			}
163
164
			public function registerEventListener(string $event, string $listener, int $priority = 0): void {
165
				$this->context->registerEventListener(
166
					$this->appId,
167
					$event,
168
					$listener,
169
					$priority
170
				);
171
			}
172
173
			public function registerMiddleware(string $class): void {
174
				$this->context->registerMiddleware(
175
					$this->appId,
176
					$class
177
				);
178
			}
179
180
			public function registerSearchProvider(string $class): void {
181
				$this->context->registerSearchProvider(
182
					$this->appId,
183
					$class
184
				);
185
			}
186
187
			public function registerAlternativeLogin(string $class): void {
188
				$this->context->registerAlternativeLogin(
189
					$this->appId,
190
					$class
191
				);
192
			}
193
194
			public function registerInitialStateProvider(string $class): void {
195
				$this->context->registerInitialState(
196
					$this->appId,
197
					$class
198
				);
199
			}
200
201
			public function registerWellKnownHandler(string $class): void {
202
				$this->context->registerWellKnown(
203
					$this->appId,
204
					$class
205
				);
206
			}
207
208
			public function registerTemplateProvider(string $providerClass): void {
209
				$this->context->registerTemplateProvider(
210
					$this->appId,
211
					$providerClass
212
				);
213
			}
214
215
			public function registerNotifierService(string $notifierClass): void {
216
				$this->context->registerNotifierService(
217
					$this->appId,
218
					$notifierClass
219
				);
220
			}
221
222
			public function registerTwoFactorProvider(string $twoFactorProviderClass): void {
223
				$this->context->registerTwoFactorProvider(
224
					$this->appId,
225
					$twoFactorProviderClass
226
				);
227
			}
228
		};
229
	}
230
231
	/**
232
	 * @psalm-param class-string<ICapability> $capability
233
	 */
234
	public function registerCapability(string $appId, string $capability): void {
235
		$this->capabilities[] = new ServiceRegistration($appId, $capability);
236
	}
237
238
	/**
239
	 * @psalm-param class-string<IReporter> $capability
240
	 */
241
	public function registerCrashReporter(string $appId, string $reporterClass): void {
242
		$this->crashReporters[] = new ServiceRegistration($appId, $reporterClass);
243
	}
244
245
	/**
246
	 * @psalm-param class-string<IWidget> $capability
247
	 */
248
	public function registerDashboardPanel(string $appId, string $panelClass): void {
249
		$this->dashboardPanels[] = new ServiceRegistration($appId, $panelClass);
250
	}
251
252
	public function registerService(string $appId, string $name, callable $factory, bool $shared = true): void {
253
		$this->services[] = new ServiceFactoryRegistration($appId, $name, $factory, $shared);
254
	}
255
256
	public function registerServiceAlias(string $appId, string $alias, string $target): void {
257
		$this->aliases[] = new ServiceAliasRegistration($appId, $alias, $target);
258
	}
259
260
	public function registerParameter(string $appId, string $name, $value): void {
261
		$this->parameters[] = new ParameterRegistration($appId, $name, $value);
262
	}
263
264
	public function registerEventListener(string $appId, string $event, string $listener, int $priority = 0): void {
265
		$this->eventListeners[] = new EventListenerRegistration($appId, $event, $listener, $priority);
266
	}
267
268
	/**
269
	 * @psalm-param class-string<Middleware> $class
270
	 */
271
	public function registerMiddleware(string $appId, string $class): void {
272
		$this->middlewares[] = new ServiceRegistration($appId, $class);
273
	}
274
275
	public function registerSearchProvider(string $appId, string $class) {
276
		$this->searchProviders[] = new ServiceRegistration($appId, $class);
277
	}
278
279
	public function registerAlternativeLogin(string $appId, string $class): void {
280
		$this->alternativeLogins[] = new ServiceRegistration($appId, $class);
281
	}
282
283
	public function registerInitialState(string $appId, string $class): void {
284
		$this->initialStates[] = new ServiceRegistration($appId, $class);
285
	}
286
287
	public function registerWellKnown(string $appId, string $class): void {
288
		$this->wellKnownHandlers[] = new ServiceRegistration($appId, $class);
289
	}
290
291
	public function registerTemplateProvider(string $appId, string $class): void {
292
		$this->templateProviders[] = new ServiceRegistration($appId, $class);
293
	}
294
295
	public function registerNotifierService(string $appId, string $class): void {
296
		$this->notifierServices[] = new ServiceRegistration($appId, $class);
297
	}
298
299
	public function registerTwoFactorProvider(string $appId, string $class): void {
300
		$this->twoFactorProviders[] = new ServiceRegistration($appId, $class);
301
	}
302
303
	/**
304
	 * @param App[] $apps
305
	 */
306
	public function delegateCapabilityRegistrations(array $apps): void {
307
		while (($registration = array_shift($this->capabilities)) !== null) {
0 ignored issues
show
Bug introduced by
$this->capabilities of type OC\AppFramework\Bootstrap\ServiceRegistration is incompatible with the type array expected by parameter $array of array_shift(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

307
		while (($registration = array_shift(/** @scrutinizer ignore-type */ $this->capabilities)) !== null) {
Loading history...
308
			$appId = $registration->getAppId();
309
			if (!isset($apps[$appId])) {
310
				// If we land here something really isn't right. But at least we caught the
311
				// notice that is otherwise emitted for the undefined index
312
				$this->logger->error("App $appId not loaded for the capability registration");
313
314
				continue;
315
			}
316
317
			try {
318
				$apps[$appId]
319
					->getContainer()
320
					->registerCapability($registration->getService());
321
			} catch (Throwable $e) {
322
				$this->logger->error("Error during capability registration of $appId: " . $e->getMessage(), [
323
					'exception' => $e,
324
				]);
325
			}
326
		}
327
	}
328
329
	/**
330
	 * @param App[] $apps
331
	 */
332
	public function delegateCrashReporterRegistrations(array $apps, Registry $registry): void {
0 ignored issues
show
Unused Code introduced by
The parameter $apps is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

332
	public function delegateCrashReporterRegistrations(/** @scrutinizer ignore-unused */ array $apps, Registry $registry): void {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
333
		while (($registration = array_shift($this->crashReporters)) !== null) {
0 ignored issues
show
Bug introduced by
$this->crashReporters of type OC\AppFramework\Bootstrap\ServiceRegistration is incompatible with the type array expected by parameter $array of array_shift(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

333
		while (($registration = array_shift(/** @scrutinizer ignore-type */ $this->crashReporters)) !== null) {
Loading history...
334
			try {
335
				$registry->registerLazy($registration->getService());
336
			} catch (Throwable $e) {
337
				$appId = $registration->getAppId();
338
				$this->logger->error("Error during crash reporter registration of $appId: " . $e->getMessage(), [
339
					'exception' => $e,
340
				]);
341
			}
342
		}
343
	}
344
345
	/**
346
	 * @param App[] $apps
347
	 */
348
	public function delegateDashboardPanelRegistrations(array $apps, IManager $dashboardManager): void {
0 ignored issues
show
Unused Code introduced by
The parameter $apps is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

348
	public function delegateDashboardPanelRegistrations(/** @scrutinizer ignore-unused */ array $apps, IManager $dashboardManager): void {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
349
		while (($panel = array_shift($this->dashboardPanels)) !== null) {
0 ignored issues
show
Bug introduced by
$this->dashboardPanels of type OC\AppFramework\Bootstrap\ServiceRegistration is incompatible with the type array expected by parameter $array of array_shift(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

349
		while (($panel = array_shift(/** @scrutinizer ignore-type */ $this->dashboardPanels)) !== null) {
Loading history...
350
			try {
351
				$dashboardManager->lazyRegisterWidget($panel->getService());
352
			} catch (Throwable $e) {
353
				$appId = $panel->getAppId();
354
				$this->logger->error("Error during dashboard registration of $appId: " . $e->getMessage(), [
355
					'exception' => $e,
356
				]);
357
			}
358
		}
359
	}
360
361
	public function delegateEventListenerRegistrations(IEventDispatcher $eventDispatcher): void {
362
		while (($registration = array_shift($this->eventListeners)) !== null) {
363
			try {
364
				$eventDispatcher->addServiceListener(
365
					$registration->getEvent(),
366
					$registration->getService(),
367
					$registration->getPriority()
368
				);
369
			} catch (Throwable $e) {
370
				$appId = $registration->getAppId();
371
				$this->logger->error("Error during event listener registration of $appId: " . $e->getMessage(), [
372
					'exception' => $e,
373
				]);
374
			}
375
		}
376
	}
377
378
	/**
379
	 * @param App[] $apps
380
	 */
381
	public function delegateContainerRegistrations(array $apps): void {
382
		while (($registration = array_shift($this->services)) !== null) {
383
			$appId = $registration->getAppId();
384
			if (!isset($apps[$appId])) {
385
				// If we land here something really isn't right. But at least we caught the
386
				// notice that is otherwise emitted for the undefined index
387
				$this->logger->error("App $appId not loaded for the container service registration");
388
389
				continue;
390
			}
391
392
			try {
393
				/**
394
				 * Register the service and convert the callable into a \Closure if necessary
395
				 */
396
				$apps[$appId]
397
					->getContainer()
398
					->registerService(
399
						$registration->getName(),
400
						Closure::fromCallable($registration->getFactory()),
401
						$registration->isShared()
402
					);
403
			} catch (Throwable $e) {
404
				$this->logger->error("Error during service registration of $appId: " . $e->getMessage(), [
405
					'exception' => $e,
406
				]);
407
			}
408
		}
409
410
		while (($registration = array_shift($this->aliases)) !== null) {
411
			$appId = $registration->getAppId();
412
			if (!isset($apps[$appId])) {
413
				// If we land here something really isn't right. But at least we caught the
414
				// notice that is otherwise emitted for the undefined index
415
				$this->logger->error("App $appId not loaded for the container alias registration");
416
417
				continue;
418
			}
419
420
			try {
421
				$apps[$appId]
422
					->getContainer()
423
					->registerAlias(
424
						$registration->getAlias(),
425
						$registration->getTarget()
426
					);
427
			} catch (Throwable $e) {
428
				$this->logger->error("Error during service alias registration of $appId: " . $e->getMessage(), [
429
					'exception' => $e,
430
				]);
431
			}
432
		}
433
434
		while (($registration = array_shift($this->parameters)) !== null) {
435
			$appId = $registration->getAppId();
436
			if (!isset($apps[$appId])) {
437
				// If we land here something really isn't right. But at least we caught the
438
				// notice that is otherwise emitted for the undefined index
439
				$this->logger->error("App $appId not loaded for the container parameter registration");
440
441
				continue;
442
			}
443
444
			try {
445
				$apps[$appId]
446
					->getContainer()
447
					->registerParameter(
448
						$registration->getName(),
449
						$registration->getValue()
450
					);
451
			} catch (Throwable $e) {
452
				$this->logger->error("Error during service parameter registration of $appId: " . $e->getMessage(), [
453
					'exception' => $e,
454
				]);
455
			}
456
		}
457
	}
458
459
	/**
460
	 * @param App[] $apps
461
	 */
462
	public function delegateMiddlewareRegistrations(array $apps): void {
463
		while (($middleware = array_shift($this->middlewares)) !== null) {
0 ignored issues
show
Bug introduced by
$this->middlewares of type OC\AppFramework\Bootstrap\ServiceRegistration is incompatible with the type array expected by parameter $array of array_shift(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

463
		while (($middleware = array_shift(/** @scrutinizer ignore-type */ $this->middlewares)) !== null) {
Loading history...
464
			$appId = $middleware->getAppId();
465
			if (!isset($apps[$appId])) {
466
				// If we land here something really isn't right. But at least we caught the
467
				// notice that is otherwise emitted for the undefined index
468
				$this->logger->error("App $appId not loaded for the container middleware registration");
469
470
				continue;
471
			}
472
473
			try {
474
				$apps[$appId]
475
					->getContainer()
476
					->registerMiddleWare($middleware->getService());
477
			} catch (Throwable $e) {
478
				$this->logger->error("Error during capability registration of $appId: " . $e->getMessage(), [
479
					'exception' => $e,
480
				]);
481
			}
482
		}
483
	}
484
485
	/**
486
	 * @return ServiceRegistration<IProvider>[]
487
	 */
488
	public function getSearchProviders(): array {
489
		return $this->searchProviders;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->searchProviders returns the type OC\AppFramework\Bootstrap\ServiceRegistration which is incompatible with the type-hinted return array.
Loading history...
490
	}
491
492
	/**
493
	 * @return ServiceRegistration<IAlternativeLogin>[]
494
	 */
495
	public function getAlternativeLogins(): array {
496
		return $this->alternativeLogins;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->alternativeLogins returns the type OC\AppFramework\Bootstrap\ServiceRegistration which is incompatible with the type-hinted return array.
Loading history...
497
	}
498
499
	/**
500
	 * @return ServiceRegistration<InitialStateProvider>[]
501
	 */
502
	public function getInitialStates(): array {
503
		return $this->initialStates;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->initialStates returns the type OC\AppFramework\Bootstrap\ServiceRegistration which is incompatible with the type-hinted return array.
Loading history...
504
	}
505
506
	/**
507
	 * @return ServiceRegistration<IHandler>[]
508
	 */
509
	public function getWellKnownHandlers(): array {
510
		return $this->wellKnownHandlers;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->wellKnownHandlers returns the type OC\AppFramework\Bootstrap\ServiceRegistration which is incompatible with the type-hinted return array.
Loading history...
511
	}
512
513
	/**
514
	 * @return ServiceRegistration<ICustomTemplateProvider>[]
515
	 */
516
	public function getTemplateProviders(): array {
517
		return $this->templateProviders;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->templateProviders returns the type OC\AppFramework\Bootstrap\ServiceRegistration which is incompatible with the type-hinted return array.
Loading history...
518
	}
519
520
	/**
521
	 * @return ServiceRegistration<INotifier>[]
522
	 */
523
	public function getNotifierServices(): array {
524
		return $this->notifierServices;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->notifierServices returns the type OC\AppFramework\Bootstrap\ServiceRegistration which is incompatible with the type-hinted return array.
Loading history...
525
	}
526
527
	/**
528
	 * @return ServiceRegistration<\OCP\Authentication\TwoFactorAuth\IProvider>[]
529
	 */
530
	public function getTwoFactorProviders(): array {
531
		return $this->twoFactorProviders;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->twoFactorProviders returns the type OC\AppFramework\Bootstrap\ServiceRegistration which is incompatible with the type-hinted return array.
Loading history...
532
	}
533
}
534