Passed
Push — master ( 919a84...b58d4f )
by Christoph
16:54 queued 17s
created

DIContainer::queryNoFallback()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 11
c 1
b 0
f 0
nc 5
nop 1
dl 0
loc 15
rs 8.8333
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bernhard Posselt <[email protected]>
7
 * @author Bjoern Schiessle <[email protected]>
8
 * @author Christoph Wurst <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author Jörn Friedrich Dreyer <[email protected]>
11
 * @author Lukas Reschke <[email protected]>
12
 * @author Morris Jobke <[email protected]>
13
 * @author Robin McCorkell <[email protected]>
14
 * @author Roeland Jago Douma <[email protected]>
15
 * @author Sebastian Wessalowski <[email protected]>
16
 * @author Thomas Müller <[email protected]>
17
 * @author Thomas Tanghus <[email protected]>
18
 *
19
 * @license AGPL-3.0
20
 *
21
 * This code is free software: you can redistribute it and/or modify
22
 * it under the terms of the GNU Affero General Public License, version 3,
23
 * as published by the Free Software Foundation.
24
 *
25
 * This program is distributed in the hope that it will be useful,
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
 * GNU Affero General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU Affero General Public License, version 3,
31
 * along with this program. If not, see <http://www.gnu.org/licenses/>
32
 *
33
 */
34
namespace OC\AppFramework\DependencyInjection;
35
36
use OC;
37
use OC\AppFramework\Http;
38
use OC\AppFramework\Http\Dispatcher;
39
use OC\AppFramework\Http\Output;
40
use OC\AppFramework\Middleware\MiddlewareDispatcher;
41
use OC\AppFramework\Middleware\OCSMiddleware;
42
use OC\AppFramework\Middleware\Security\CORSMiddleware;
43
use OC\AppFramework\Middleware\Security\RateLimitingMiddleware;
44
use OC\AppFramework\Middleware\Security\SecurityMiddleware;
45
use OC\AppFramework\Middleware\SessionMiddleware;
46
use OC\AppFramework\ScopedPsrLogger;
47
use OC\AppFramework\Utility\SimpleContainer;
48
use OC\Core\Middleware\TwoFactorMiddleware;
49
use OC\Diagnostics\EventLogger;
50
use OC\Log\PsrLoggerAdapter;
51
use OC\ServerContainer;
52
use OC\Settings\AuthorizedGroupMapper;
53
use OCA\WorkflowEngine\Manager;
54
use OCP\AppFramework\Http\IOutput;
55
use OCP\AppFramework\IAppContainer;
56
use OCP\AppFramework\QueryException;
57
use OCP\AppFramework\Services\IAppConfig;
58
use OCP\AppFramework\Services\IInitialState;
59
use OCP\AppFramework\Utility\IControllerMethodReflector;
60
use OCP\AppFramework\Utility\ITimeFactory;
61
use OCP\Files\Folder;
62
use OCP\Files\IAppData;
63
use OCP\Group\ISubAdmin;
64
use OCP\IConfig;
65
use OCP\IDBConnection;
66
use OCP\IInitialStateService;
67
use OCP\IL10N;
68
use OCP\ILogger;
69
use OCP\INavigationManager;
70
use OCP\IRequest;
71
use OCP\IServerContainer;
72
use OCP\ISession;
73
use OCP\IURLGenerator;
74
use OCP\IUserSession;
75
use Psr\Container\ContainerInterface;
76
use Psr\Log\LoggerInterface;
77
78
/**
79
 * @deprecated 20.0.0
80
 */
81
class DIContainer extends SimpleContainer implements IAppContainer {
0 ignored issues
show
Deprecated Code introduced by
The interface OCP\AppFramework\IAppContainer has been deprecated: 20.0.0 ( Ignorable by Annotation )

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

81
class DIContainer extends SimpleContainer implements /** @scrutinizer ignore-deprecated */ IAppContainer {

This interface has been deprecated. The supplier of the interface has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.

Loading history...
82
	private string $appName;
83
84
	/**
85
	 * @var array
86
	 */
87
	private $middleWares = [];
88
89
	/** @var ServerContainer */
90
	private $server;
91
92
	/**
93
	 * Put your class dependencies in here
94
	 * @param string $appName the name of the app
95
	 * @param array $urlParams
96
	 * @param ServerContainer|null $server
97
	 */
98
	public function __construct(string $appName, array $urlParams = [], ServerContainer $server = null) {
99
		parent::__construct();
100
		$this->appName = $appName;
101
		$this['appName'] = $appName;
102
		$this['urlParams'] = $urlParams;
103
104
		$this->registerAlias('Request', IRequest::class);
105
106
		/** @var \OC\ServerContainer $server */
107
		if ($server === null) {
108
			$server = \OC::$server;
109
		}
110
		$this->server = $server;
111
		$this->server->registerAppContainer($appName, $this);
112
113
		// aliases
114
		/** @deprecated inject $appName */
115
		$this->registerAlias('AppName', 'appName');
116
		/** @deprecated inject $webRoot*/
117
		$this->registerAlias('WebRoot', 'webRoot');
118
		/** @deprecated inject $userId */
119
		$this->registerAlias('UserId', 'userId');
120
121
		/**
122
		 * Core services
123
		 */
124
		$this->registerService(IOutput::class, function () {
125
			return new Output($this->getServer()->getWebRoot());
126
		});
127
128
		$this->registerService(Folder::class, function () {
129
			return $this->getServer()->getUserFolder();
130
		});
131
132
		$this->registerService(IAppData::class, function (ContainerInterface $c) {
133
			return $this->getServer()->getAppDataDir($c->get('AppName'));
0 ignored issues
show
Bug introduced by
The method getAppDataDir() does not exist on OCP\IServerContainer. Since it exists in all sub-types, consider adding an abstract or default implementation to OCP\IServerContainer. ( Ignorable by Annotation )

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

133
			return $this->getServer()->/** @scrutinizer ignore-call */ getAppDataDir($c->get('AppName'));
Loading history...
134
		});
135
136
		$this->registerService(IL10N::class, function (ContainerInterface $c) {
137
			return $this->getServer()->getL10N($c->get('AppName'));
138
		});
139
140
		// Log wrappers
141
		$this->registerService(LoggerInterface::class, function (ContainerInterface $c) {
142
			return new ScopedPsrLogger(
143
				$c->get(PsrLoggerAdapter::class),
144
				$c->get('AppName')
145
			);
146
		});
147
		$this->registerService(ILogger::class, function (ContainerInterface $c) {
148
			return new OC\AppFramework\Logger($this->server->query(ILogger::class), $c->get('AppName'));
0 ignored issues
show
Deprecated Code introduced by
The class OC\AppFramework\Logger has been deprecated. ( Ignorable by Annotation )

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

148
			return /** @scrutinizer ignore-deprecated */ new OC\AppFramework\Logger($this->server->query(ILogger::class), $c->get('AppName'));
Loading history...
149
		});
150
151
		$this->registerService(IServerContainer::class, function () {
152
			return $this->getServer();
153
		});
154
		$this->registerAlias('ServerContainer', IServerContainer::class);
155
156
		$this->registerService(\OCP\WorkflowEngine\IManager::class, function (ContainerInterface $c) {
157
			return $c->get(Manager::class);
158
		});
159
160
		$this->registerService(ContainerInterface::class, function (ContainerInterface $c) {
161
			return $c;
162
		});
163
		$this->registerAlias(IAppContainer::class, ContainerInterface::class);
164
165
		// commonly used attributes
166
		$this->registerService('userId', function (ContainerInterface $c) {
167
			return $c->get(IUserSession::class)->getSession()->get('user_id');
168
		});
169
170
		$this->registerService('webRoot', function (ContainerInterface $c) {
171
			return $c->get(IServerContainer::class)->getWebRoot();
172
		});
173
174
		$this->registerService('OC_Defaults', function (ContainerInterface $c) {
175
			return $c->get(IServerContainer::class)->getThemingDefaults();
176
		});
177
178
		$this->registerService('Protocol', function (ContainerInterface $c) {
179
			/** @var \OC\Server $server */
180
			$server = $c->get(IServerContainer::class);
181
			$protocol = $server->getRequest()->getHttpProtocol();
182
			return new Http($_SERVER, $protocol);
183
		});
184
185
		$this->registerService('Dispatcher', function (ContainerInterface $c) {
186
			return new Dispatcher(
187
				$c->get('Protocol'),
188
				$c->get(MiddlewareDispatcher::class),
189
				$c->get(IControllerMethodReflector::class),
190
				$c->get(IRequest::class),
191
				$c->get(IConfig::class),
192
				$c->get(IDBConnection::class),
193
				$c->get(LoggerInterface::class),
194
				$c->get(EventLogger::class),
195
				$c,
196
			);
197
		});
198
199
		/**
200
		 * App Framework default arguments
201
		 */
202
		$this->registerParameter('corsMethods', 'PUT, POST, GET, DELETE, PATCH');
203
		$this->registerParameter('corsAllowedHeaders', 'Authorization, Content-Type, Accept');
204
		$this->registerParameter('corsMaxAge', 1728000);
205
206
		/**
207
		 * Middleware
208
		 */
209
		$this->registerAlias('MiddlewareDispatcher', MiddlewareDispatcher::class);
210
		$this->registerService(MiddlewareDispatcher::class, function (ContainerInterface $c) {
211
			$server = $this->getServer();
212
213
			$dispatcher = new MiddlewareDispatcher();
214
215
			$dispatcher->registerMiddleware(
216
				$c->get(OC\AppFramework\Middleware\CompressionMiddleware::class)
217
			);
218
219
			$dispatcher->registerMiddleware($c->get(OC\AppFramework\Middleware\NotModifiedMiddleware::class));
220
221
			$dispatcher->registerMiddleware(
222
				$c->get(OC\AppFramework\Middleware\Security\ReloadExecutionMiddleware::class)
223
			);
224
225
			$dispatcher->registerMiddleware(
226
				new OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware(
227
					$c->get(IRequest::class),
228
					$c->get(IControllerMethodReflector::class)
229
				)
230
			);
231
			$dispatcher->registerMiddleware(
232
				new CORSMiddleware(
233
					$c->get(IRequest::class),
234
					$c->get(IControllerMethodReflector::class),
235
					$c->get(IUserSession::class),
236
					$c->get(OC\Security\Bruteforce\Throttler::class)
237
				)
238
			);
239
			$dispatcher->registerMiddleware(
240
				new OCSMiddleware(
241
					$c->get(IRequest::class)
242
				)
243
			);
244
245
246
247
			$securityMiddleware = new SecurityMiddleware(
248
				$c->get(IRequest::class),
249
				$c->get(IControllerMethodReflector::class),
250
				$c->get(INavigationManager::class),
251
				$c->get(IURLGenerator::class),
252
				$server->get(LoggerInterface::class),
253
				$c->get('AppName'),
254
				$server->getUserSession()->isLoggedIn(),
255
				$this->getUserId() !== null && $server->getGroupManager()->isAdmin($this->getUserId()),
256
				$server->getUserSession()->getUser() !== null && $server->query(ISubAdmin::class)->isSubAdmin($server->getUserSession()->getUser()),
257
				$server->getAppManager(),
258
				$server->getL10N('lib'),
259
				$c->get(AuthorizedGroupMapper::class),
260
				$server->get(IUserSession::class)
261
			);
262
			$dispatcher->registerMiddleware($securityMiddleware);
263
			$dispatcher->registerMiddleware(
264
				new OC\AppFramework\Middleware\Security\CSPMiddleware(
265
					$server->query(OC\Security\CSP\ContentSecurityPolicyManager::class),
266
					$server->query(OC\Security\CSP\ContentSecurityPolicyNonceManager::class),
267
					$server->query(OC\Security\CSRF\CsrfTokenManager::class)
268
				)
269
			);
270
			$dispatcher->registerMiddleware(
271
				$server->query(OC\AppFramework\Middleware\Security\FeaturePolicyMiddleware::class)
272
			);
273
			$dispatcher->registerMiddleware(
274
				new OC\AppFramework\Middleware\Security\PasswordConfirmationMiddleware(
275
					$c->get(IControllerMethodReflector::class),
276
					$c->get(ISession::class),
277
					$c->get(IUserSession::class),
278
					$c->get(ITimeFactory::class)
279
				)
280
			);
281
			$dispatcher->registerMiddleware(
282
				new TwoFactorMiddleware(
283
					$c->get(OC\Authentication\TwoFactorAuth\Manager::class),
284
					$c->get(IUserSession::class),
285
					$c->get(ISession::class),
286
					$c->get(IURLGenerator::class),
287
					$c->get(IControllerMethodReflector::class),
288
					$c->get(IRequest::class)
289
				)
290
			);
291
			$dispatcher->registerMiddleware(
292
				new OC\AppFramework\Middleware\Security\BruteForceMiddleware(
293
					$c->get(IControllerMethodReflector::class),
294
					$c->get(OC\Security\Bruteforce\Throttler::class),
295
					$c->get(IRequest::class)
296
				)
297
			);
298
			$dispatcher->registerMiddleware(
299
				new RateLimitingMiddleware(
300
					$c->get(IRequest::class),
301
					$c->get(IUserSession::class),
302
					$c->get(IControllerMethodReflector::class),
303
					$c->get(OC\Security\RateLimiting\Limiter::class)
304
				)
305
			);
306
			$dispatcher->registerMiddleware(
307
				new OC\AppFramework\Middleware\PublicShare\PublicShareMiddleware(
308
					$c->get(IRequest::class),
309
					$c->get(ISession::class),
310
					$c->get(\OCP\IConfig::class),
311
					$c->get(OC\Security\Bruteforce\Throttler::class)
312
				)
313
			);
314
			$dispatcher->registerMiddleware(
315
				$c->get(\OC\AppFramework\Middleware\AdditionalScriptsMiddleware::class)
316
			);
317
318
			/** @var \OC\AppFramework\Bootstrap\Coordinator $coordinator */
319
			$coordinator = $c->get(\OC\AppFramework\Bootstrap\Coordinator::class);
320
			$registrationContext = $coordinator->getRegistrationContext();
321
			if ($registrationContext !== null) {
322
				$appId = $this->getAppName();
323
				foreach ($registrationContext->getMiddlewareRegistrations() as $middlewareRegistration) {
324
					if ($middlewareRegistration->getAppId() === $appId) {
325
						$dispatcher->registerMiddleware($c->get($middlewareRegistration->getService()));
326
					}
327
				}
328
			}
329
			foreach ($this->middleWares as $middleWare) {
330
				$dispatcher->registerMiddleware($c->get($middleWare));
331
			}
332
333
			$dispatcher->registerMiddleware(
334
				new SessionMiddleware(
335
					$c->get(IControllerMethodReflector::class),
336
					$c->get(ISession::class)
337
				)
338
			);
339
			return $dispatcher;
340
		});
341
342
		$this->registerService(IAppConfig::class, function (ContainerInterface $c) {
343
			return new OC\AppFramework\Services\AppConfig(
344
				$c->get(IConfig::class),
345
				$c->get('AppName')
346
			);
347
		});
348
		$this->registerService(IInitialState::class, function (ContainerInterface $c) {
349
			return new OC\AppFramework\Services\InitialState(
350
				$c->get(IInitialStateService::class),
351
				$c->get('AppName')
352
			);
353
		});
354
	}
355
356
	/**
357
	 * @return \OCP\IServerContainer
358
	 */
359
	public function getServer() {
360
		return $this->server;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->server returns the type OC\ServerContainer which is incompatible with the documented return type OCP\IServerContainer.
Loading history...
361
	}
362
363
	/**
364
	 * @param string $middleWare
365
	 * @return boolean|null
366
	 */
367
	public function registerMiddleWare($middleWare) {
368
		if (in_array($middleWare, $this->middleWares, true) !== false) {
369
			return false;
370
		}
371
		$this->middleWares[] = $middleWare;
372
	}
373
374
	/**
375
	 * used to return the appname of the set application
376
	 * @return string the name of your application
377
	 */
378
	public function getAppName() {
379
		return $this->query('AppName');
380
	}
381
382
	/**
383
	 * @deprecated use IUserSession->isLoggedIn()
384
	 * @return boolean
385
	 */
386
	public function isLoggedIn() {
387
		return \OC::$server->getUserSession()->isLoggedIn();
388
	}
389
390
	/**
391
	 * @deprecated use IGroupManager->isAdmin($userId)
392
	 * @return boolean
393
	 */
394
	public function isAdminUser() {
395
		$uid = $this->getUserId();
396
		return \OC_User::isAdminUser($uid);
397
	}
398
399
	private function getUserId() {
400
		return $this->getServer()->getSession()->get('user_id');
401
	}
402
403
	/**
404
	 * @deprecated use the ILogger instead
405
	 * @param string $message
406
	 * @param string $level
407
	 * @return mixed
408
	 */
409
	public function log($message, $level) {
410
		switch ($level) {
411
			case 'debug':
412
				$level = ILogger::DEBUG;
0 ignored issues
show
Deprecated Code introduced by
The constant OCP\ILogger::DEBUG has been deprecated: 20.0.0 ( Ignorable by Annotation )

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

412
				$level = /** @scrutinizer ignore-deprecated */ ILogger::DEBUG;

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
413
				break;
414
			case 'info':
415
				$level = ILogger::INFO;
0 ignored issues
show
Deprecated Code introduced by
The constant OCP\ILogger::INFO has been deprecated: 20.0.0 ( Ignorable by Annotation )

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

415
				$level = /** @scrutinizer ignore-deprecated */ ILogger::INFO;

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
416
				break;
417
			case 'warn':
418
				$level = ILogger::WARN;
0 ignored issues
show
Deprecated Code introduced by
The constant OCP\ILogger::WARN has been deprecated: 20.0.0 ( Ignorable by Annotation )

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

418
				$level = /** @scrutinizer ignore-deprecated */ ILogger::WARN;

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
419
				break;
420
			case 'fatal':
421
				$level = ILogger::FATAL;
0 ignored issues
show
Deprecated Code introduced by
The constant OCP\ILogger::FATAL has been deprecated: 20.0.0 ( Ignorable by Annotation )

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

421
				$level = /** @scrutinizer ignore-deprecated */ ILogger::FATAL;

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
422
				break;
423
			default:
424
				$level = ILogger::ERROR;
0 ignored issues
show
Deprecated Code introduced by
The constant OCP\ILogger::ERROR has been deprecated: 20.0.0 ( Ignorable by Annotation )

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

424
				$level = /** @scrutinizer ignore-deprecated */ ILogger::ERROR;

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
425
				break;
426
		}
427
		\OCP\Util::writeLog($this->getAppName(), $message, $level);
428
	}
429
430
	/**
431
	 * Register a capability
432
	 *
433
	 * @param string $serviceName e.g. 'OCA\Files\Capabilities'
434
	 */
435
	public function registerCapability($serviceName) {
436
		$this->query('OC\CapabilitiesManager')->registerCapability(function () use ($serviceName) {
437
			return $this->query($serviceName);
438
		});
439
	}
440
441
	public function has($id): bool {
442
		if (parent::has($id)) {
443
			return true;
444
		}
445
446
		if ($this->server->has($id, true)) {
447
			return true;
448
		}
449
450
		return false;
451
	}
452
453
	public function query(string $name, bool $autoload = true) {
454
		if ($name === 'AppName' || $name === 'appName') {
455
			return $this->appName;
456
		}
457
458
		$isServerClass = str_starts_with($name, 'OCP\\') || str_starts_with($name, 'OC\\');
459
		if ($isServerClass && !$this->has($name)) {
460
			return $this->getServer()->query($name, $autoload);
461
		}
462
463
		try {
464
			return $this->queryNoFallback($name);
465
		} catch (QueryException $firstException) {
466
			try {
467
				return $this->getServer()->query($name, $autoload);
468
			} catch (QueryException $secondException) {
469
				if ($firstException->getCode() === 1) {
470
					throw $secondException;
471
				}
472
				throw $firstException;
473
			}
474
		}
475
	}
476
477
	/**
478
	 * @param string $name
479
	 * @return mixed
480
	 * @throws QueryException if the query could not be resolved
481
	 */
482
	public function queryNoFallback($name) {
483
		$name = $this->sanitizeName($name);
484
485
		if ($this->offsetExists($name)) {
486
			return parent::query($name);
487
		} elseif ($this->appName === 'settings' && str_starts_with($name, 'OC\\Settings\\')) {
488
			return parent::query($name);
489
		} elseif ($this->appName === 'core' && str_starts_with($name, 'OC\\Core\\')) {
490
			return parent::query($name);
491
		} elseif (str_starts_with($name, \OC\AppFramework\App::buildAppNamespace($this->appName) . '\\')) {
492
			return parent::query($name);
493
		}
494
495
		throw new QueryException('Could not resolve ' . $name . '!' .
0 ignored issues
show
Deprecated Code introduced by
The class OCP\AppFramework\QueryException has been deprecated: 20.0.0 catch \Psr\Container\ContainerExceptionInterface ( Ignorable by Annotation )

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

495
		throw /** @scrutinizer ignore-deprecated */ new QueryException('Could not resolve ' . $name . '!' .
Loading history...
496
			' Class can not be instantiated', 1);
497
	}
498
}
499