Completed
Push — master ( ec3f5a...0b5e18 )
by Blizzz
26:23 queued 12:08
created

DIContainer::queryNoFallback()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 13
c 0
b 0
f 0
nc 5
nop 1
dl 0
loc 18
rs 8.2222
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Bernhard Posselt <[email protected]>
6
 * @author Christoph Wurst <[email protected]>
7
 * @author Joas Schilling <[email protected]>
8
 * @author Jörn Friedrich Dreyer <[email protected]>
9
 * @author Lukas Reschke <[email protected]>
10
 * @author Morris Jobke <[email protected]>
11
 * @author Robin McCorkell <[email protected]>
12
 * @author Roeland Jago Douma <[email protected]>
13
 * @author Thomas Müller <[email protected]>
14
 * @author Thomas Tanghus <[email protected]>
15
 *
16
 * @license AGPL-3.0
17
 *
18
 * This code is free software: you can redistribute it and/or modify
19
 * it under the terms of the GNU Affero General Public License, version 3,
20
 * as published by the Free Software Foundation.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
 * GNU Affero General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU Affero General Public License, version 3,
28
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
29
 *
30
 */
31
32
33
namespace OC\AppFramework\DependencyInjection;
34
35
use OC;
36
use OC\AppFramework\Core\API;
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\Security\CORSMiddleware;
42
use OC\AppFramework\Middleware\OCSMiddleware;
43
use OC\AppFramework\Middleware\Security\SecurityMiddleware;
44
use OC\AppFramework\Middleware\SessionMiddleware;
45
use OC\AppFramework\Utility\SimpleContainer;
46
use OC\Core\Middleware\TwoFactorMiddleware;
47
use OC\RichObjectStrings\Validator;
48
use OC\ServerContainer;
49
use OCP\AppFramework\Http\IOutput;
50
use OCP\AppFramework\IApi;
51
use OCP\AppFramework\IAppContainer;
52
use OCP\AppFramework\QueryException;
53
use OCP\Files\Folder;
54
use OCP\Files\IAppData;
55
use OCP\IL10N;
56
use OCP\IRequest;
57
use OCP\IServerContainer;
58
use OCP\IUserSession;
59
use OCP\RichObjectStrings\IValidator;
60
use OCP\Util;
61
62
class DIContainer extends SimpleContainer implements IAppContainer {
63
64
	/**
65
	 * @var array
66
	 */
67
	private $middleWares = array();
68
69
	/** @var ServerContainer */
70
	private $server;
71
72
	/**
73
	 * Put your class dependencies in here
74
	 * @param string $appName the name of the app
75
	 * @param array $urlParams
76
	 * @param ServerContainer $server
77
	 */
78
	public function __construct($appName, $urlParams = array(), ServerContainer $server = null){
79
		parent::__construct();
80
		$this['AppName'] = $appName;
81
		$this['urlParams'] = $urlParams;
82
83
		/** @var \OC\ServerContainer $server */
84
		if ($server === null) {
85
			$server = \OC::$server;
86
		}
87
		$this->server = $server;
88
		$this->server->registerAppContainer($appName, $this);
89
90
		// aliases
91
		$this->registerAlias('appName', 'AppName');
92
		$this->registerAlias('webRoot', 'WebRoot');
93
		$this->registerAlias('userId', 'UserId');
94
95
		/**
96
		 * Core services
97
		 */
98
		$this->registerService(IOutput::class, function($c){
0 ignored issues
show
Unused Code introduced by
The parameter $c is not used and could be removed.

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

Loading history...
99
			return new Output($this->getServer()->getWebRoot());
100
		});
101
102
		$this->registerService(Folder::class, function() {
103
			return $this->getServer()->getUserFolder();
104
		});
105
106
		$this->registerService(IAppData::class, function (SimpleContainer $c) {
107
			return $this->getServer()->getAppDataDir($c->query('AppName'));
108
		});
109
110
		$this->registerService(IL10N::class, function($c) {
111
			return $this->getServer()->getL10N($c->query('AppName'));
112
		});
113
114
		$this->registerAlias(\OCP\AppFramework\Utility\IControllerMethodReflector::class, \OC\AppFramework\Utility\ControllerMethodReflector::class);
115
		$this->registerAlias('ControllerMethodReflector', \OCP\AppFramework\Utility\IControllerMethodReflector::class);
116
117
		$this->registerService(IRequest::class, function() {
118
			return $this->getServer()->query(IRequest::class);
119
		});
120
		$this->registerAlias('Request', IRequest::class);
121
122
		$this->registerAlias(\OCP\AppFramework\Utility\ITimeFactory::class, \OC\AppFramework\Utility\TimeFactory::class);
123
		$this->registerAlias('TimeFactory', \OCP\AppFramework\Utility\ITimeFactory::class);
124
125
		$this->registerAlias(\OC\User\Session::class, \OCP\IUserSession::class);
126
127
		$this->registerService(IServerContainer::class, function ($c) {
0 ignored issues
show
Unused Code introduced by
The parameter $c is not used and could be removed.

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

Loading history...
128
			return $this->getServer();
129
		});
130
		$this->registerAlias('ServerContainer', IServerContainer::class);
131
132
		$this->registerService(\OCP\WorkflowEngine\IManager::class, function ($c) {
133
			return $c->query('OCA\WorkflowEngine\Manager');
134
		});
135
136
		$this->registerService(\OCP\AppFramework\IAppContainer::class, function ($c) {
137
			return $c;
138
		});
139
140
		// commonly used attributes
141
		$this->registerService('UserId', function ($c) {
142
			return $c->query('OCP\\IUserSession')->getSession()->get('user_id');
143
		});
144
145
		$this->registerService('WebRoot', function ($c) {
146
			return $c->query('ServerContainer')->getWebRoot();
147
		});
148
149
		$this->registerService('fromMailAddress', function() {
150
			return Util::getDefaultEmailAddress('no-reply');
151
		});
152
153
		$this->registerService('OC_Defaults', function ($c) {
154
			return $c->getServer()->getThemingDefaults();
155
		});
156
157
		$this->registerService('OCP\Encryption\IManager', function ($c) {
0 ignored issues
show
Unused Code introduced by
The parameter $c is not used and could be removed.

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

Loading history...
158
			return $this->getServer()->getEncryptionManager();
159
		});
160
161
		$this->registerService(IValidator::class, function($c) {
162
			return $c->query(Validator::class);
163
		});
164
165
		$this->registerService(\OC\Security\IdentityProof\Manager::class, function ($c) {
0 ignored issues
show
Unused Code introduced by
The parameter $c is not used and could be removed.

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

Loading history...
166
			return new \OC\Security\IdentityProof\Manager(
167
				$this->getServer()->getAppDataDir('identityproof'),
168
				$this->getServer()->getCrypto()
169
			);
170
		});
171
172
173
		/**
174
		 * App Framework APIs
175
		 */
176
		$this->registerService('API', function($c){
177
			$c->query('OCP\\ILogger')->debug(
178
				'Accessing the API class is deprecated! Use the appropriate ' .
179
				'services instead!'
180
			);
181
			return new API($c['AppName']);
0 ignored issues
show
Deprecated Code introduced by
The class OC\AppFramework\Core\API has been deprecated.

This class, trait or interface has been deprecated.

Loading history...
182
		});
183
184
		$this->registerService('Protocol', function($c){
185
			/** @var \OC\Server $server */
186
			$server = $c->query('ServerContainer');
187
			$protocol = $server->getRequest()->getHttpProtocol();
188
			return new Http($_SERVER, $protocol);
189
		});
190
191
		$this->registerService('Dispatcher', function($c) {
192
			return new Dispatcher(
193
				$c['Protocol'],
194
				$c['MiddlewareDispatcher'],
195
				$c['ControllerMethodReflector'],
196
				$c['Request']
197
			);
198
		});
199
200
		/**
201
		 * App Framework default arguments
202
		 */
203
		$this->registerParameter('corsMethods', 'PUT, POST, GET, DELETE, PATCH');
204
		$this->registerParameter('corsAllowedHeaders', 'Authorization, Content-Type, Accept');
205
		$this->registerParameter('corsMaxAge', 1728000);
206
207
		/**
208
		 * Middleware
209
		 */
210
		$app = $this;
211
		$this->registerService('SecurityMiddleware', function($c) use ($app){
212
			/** @var \OC\Server $server */
213
			$server = $app->getServer();
214
215
			return new SecurityMiddleware(
216
				$c['Request'],
217
				$c['ControllerMethodReflector'],
218
				$server->getNavigationManager(),
219
				$server->getURLGenerator(),
220
				$server->getLogger(),
221
				$server->getSession(),
222
				$c['AppName'],
223
				$app->isLoggedIn(),
0 ignored issues
show
Deprecated Code introduced by
The method OC\AppFramework\Dependen...Container::isLoggedIn() has been deprecated with message: use IUserSession->isLoggedIn()

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
224
				$app->isAdminUser(),
0 ignored issues
show
Deprecated Code introduced by
The method OC\AppFramework\Dependen...ontainer::isAdminUser() has been deprecated with message: use IGroupManager->isAdmin($userId)

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
225
				$server->getContentSecurityPolicyManager(),
0 ignored issues
show
Compatibility introduced by
$server->getContentSecurityPolicyManager() of type object<OCP\Security\ICon...tSecurityPolicyManager> is not a sub-type of object<OC\Security\CSP\C...tSecurityPolicyManager>. It seems like you assume a concrete implementation of the interface OCP\Security\IContentSecurityPolicyManager to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
226
				$server->getCsrfTokenManager(),
227
				$server->getContentSecurityPolicyNonceManager(),
228
				$server->getBruteForceThrottler()
229
			);
230
231
		});
232
233
		$this->registerService('CORSMiddleware', function($c) {
234
			return new CORSMiddleware(
235
				$c['Request'],
236
				$c['ControllerMethodReflector'],
237
				$c->query(IUserSession::class),
238
				$c->getServer()->getBruteForceThrottler()
239
			);
240
		});
241
242
		$this->registerService('SessionMiddleware', function($c) use ($app) {
243
			return new SessionMiddleware(
244
				$c['Request'],
245
				$c['ControllerMethodReflector'],
246
				$app->getServer()->getSession()
247
			);
248
		});
249
250
		$this->registerService('TwoFactorMiddleware', function (SimpleContainer $c) use ($app) {
251
			$twoFactorManager = $c->getServer()->getTwoFactorAuthManager();
252
			$userSession = $app->getServer()->getUserSession();
253
			$session = $app->getServer()->getSession();
254
			$urlGenerator = $app->getServer()->getURLGenerator();
255
			$reflector = $c['ControllerMethodReflector'];
256
			$request = $app->getServer()->getRequest();
257
			return new TwoFactorMiddleware($twoFactorManager, $userSession, $session, $urlGenerator, $reflector, $request);
0 ignored issues
show
Compatibility introduced by
$userSession of type object<OCP\IUserSession> is not a sub-type of object<OC\User\Session>. It seems like you assume a concrete implementation of the interface OCP\IUserSession to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
258
		});
259
260
		$this->registerService('OCSMiddleware', function (SimpleContainer $c) {
261
			return new OCSMiddleware(
262
				$c['Request']
263
			);
264
		});
265
266
		$middleWares = &$this->middleWares;
267
		$this->registerService('MiddlewareDispatcher', function($c) use (&$middleWares) {
268
			$dispatcher = new MiddlewareDispatcher();
269
			$dispatcher->registerMiddleware($c['CORSMiddleware']);
270
			$dispatcher->registerMiddleware($c['OCSMiddleware']);
271
			$dispatcher->registerMiddleware($c['SecurityMiddleware']);
272
			$dispatcher->registerMiddleWare($c['TwoFactorMiddleware']);
273
274
			foreach($middleWares as $middleWare) {
275
				$dispatcher->registerMiddleware($c[$middleWare]);
276
			}
277
278
			$dispatcher->registerMiddleware($c['SessionMiddleware']);
279
			return $dispatcher;
280
		});
281
282
	}
283
284
285
	/**
286
	 * @deprecated implements only deprecated methods
287
	 * @return IApi
288
	 */
289
	function getCoreApi()
290
	{
291
		return $this->query('API');
292
	}
293
294
	/**
295
	 * @return \OCP\IServerContainer
296
	 */
297
	function getServer()
298
	{
299
		return $this->server;
300
	}
301
302
	/**
303
	 * @param string $middleWare
304
	 * @return boolean|null
305
	 */
306
	function registerMiddleWare($middleWare) {
307
		array_push($this->middleWares, $middleWare);
308
	}
309
310
	/**
311
	 * used to return the appname of the set application
312
	 * @return string the name of your application
313
	 */
314
	function getAppName() {
315
		return $this->query('AppName');
316
	}
317
318
	/**
319
	 * @deprecated use IUserSession->isLoggedIn()
320
	 * @return boolean
321
	 */
322
	function isLoggedIn() {
323
		return \OC::$server->getUserSession()->isLoggedIn();
324
	}
325
326
	/**
327
	 * @deprecated use IGroupManager->isAdmin($userId)
328
	 * @return boolean
329
	 */
330
	function isAdminUser() {
331
		$uid = $this->getUserId();
332
		return \OC_User::isAdminUser($uid);
333
	}
334
335
	private function getUserId() {
336
		return $this->getServer()->getSession()->get('user_id');
337
	}
338
339
	/**
340
	 * @deprecated use the ILogger instead
341
	 * @param string $message
342
	 * @param string $level
343
	 * @return mixed
344
	 */
345
	function log($message, $level) {
346
		switch($level){
347
			case 'debug':
348
				$level = \OCP\Util::DEBUG;
349
				break;
350
			case 'info':
351
				$level = \OCP\Util::INFO;
352
				break;
353
			case 'warn':
354
				$level = \OCP\Util::WARN;
355
				break;
356
			case 'fatal':
357
				$level = \OCP\Util::FATAL;
358
				break;
359
			default:
360
				$level = \OCP\Util::ERROR;
361
				break;
362
		}
363
		\OCP\Util::writeLog($this->getAppName(), $message, $level);
364
	}
365
366
	/**
367
	 * Register a capability
368
	 *
369
	 * @param string $serviceName e.g. 'OCA\Files\Capabilities'
370
	 */
371
	public function registerCapability($serviceName) {
372
		$this->query('OC\CapabilitiesManager')->registerCapability(function() use ($serviceName) {
373
			return $this->query($serviceName);
374
		});
375
	}
376
377
	/**
378
	 * @param string $name
379
	 * @return mixed
380
	 * @throws QueryException if the query could not be resolved
381
	 */
382
	public function query($name) {
383
		try {
384
			return $this->queryNoFallback($name);
385
		} catch (QueryException $e) {
386
			return $this->getServer()->query($name);
387
		}
388
	}
389
390
	/**
391
	 * @param string $name
392
	 * @return mixed
393
	 * @throws QueryException if the query could not be resolved
394
	 */
395
	public function queryNoFallback($name) {
396
		$name = $this->sanitizeName($name);
397
398
		if ($this->offsetExists($name)) {
399
			return parent::query($name);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (query() instead of queryNoFallback()). Are you sure this is correct? If so, you might want to change this to $this->query().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
400
		} else {
401
			if ($this['AppName'] === 'settings' && strpos($name, 'OC\\Settings\\') === 0) {
402
				return parent::query($name);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (query() instead of queryNoFallback()). Are you sure this is correct? If so, you might want to change this to $this->query().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
403
			} else if ($this['AppName'] === 'core' && strpos($name, 'OC\\Core\\') === 0) {
404
				return parent::query($name);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (query() instead of queryNoFallback()). Are you sure this is correct? If so, you might want to change this to $this->query().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
405
			} else if (strpos($name, \OC\AppFramework\App::buildAppNamespace($this['AppName']) . '\\') === 0) {
406
				return parent::query($name);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (query() instead of queryNoFallback()). Are you sure this is correct? If so, you might want to change this to $this->query().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
407
			}
408
		}
409
410
		throw new QueryException('Could not resolve ' . $name . '!' .
411
			' Class can not be instantiated');
412
	}
413
}
414