Completed
Push — master ( dd29e5...bcddca )
by Joas
14:52
created

ServerContainer::getAppContainer()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 13
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 21
rs 8.7624
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 *
7
 * @license AGPL-3.0
8
 *
9
 * This code is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License, version 3,
11
 * as published by the Free Software Foundation.
12
 *
13
 * This program 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 License, version 3,
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
20
 *
21
 */
22
23
namespace OC;
24
25
26
use OC\AppFramework\App;
27
use OC\AppFramework\DependencyInjection\DIContainer;
28
use OC\AppFramework\Utility\SimpleContainer;
29
use OCP\AppFramework\QueryException;
30
31
/**
32
 * Class ServerContainer
33
 *
34
 * @package OC
35
 */
36
class ServerContainer extends SimpleContainer {
37
	/** @var DIContainer[] */
38
	protected $appContainers;
39
40
	/** @var string[] */
41
	protected $hasNoAppContainer;
42
43
	/** @var string[] */
44
	protected $namespaces;
45
46
	/**
47
	 * ServerContainer constructor.
48
	 */
49
	public function __construct() {
50
		parent::__construct();
51
		$this->appContainers = [];
52
		$this->namespaces = [];
53
		$this->hasNoAppContainer = [];
54
	}
55
56
	/**
57
	 * @param string $appName
58
	 * @param string $appNamespace
59
	 */
60
	public function registerNamespace($appName, $appNamespace) {
61
		// Cut of OCA\ and lowercase
62
		$appNamespace = strtolower(substr($appNamespace, strrpos($appNamespace, '\\') + 1));
63
		$this->namespaces[$appNamespace] = $appName;
64
	}
65
66
	/**
67
	 * @param string $appName
68
	 * @param DIContainer $container
69
	 */
70
	public function registerAppContainer($appName, DIContainer $container) {
71
		$this->appContainers[strtolower(App::buildAppNamespace($appName, ''))] = $container;
72
	}
73
74
	/**
75
	 * @param string $namespace
76
	 * @param string $sensitiveNamespace
77
	 * @return DIContainer
78
	 * @throws QueryException
79
	 */
80
	protected function getAppContainer($namespace, $sensitiveNamespace) {
81
		if (isset($this->appContainers[$namespace])) {
82
			return $this->appContainers[$namespace];
83
		}
84
85
		if (isset($this->namespaces[$namespace])) {
86
			if (!isset($this->hasNoAppContainer[$namespace])) {
87
				$applicationClassName = 'OCA\\' . $sensitiveNamespace . '\\AppInfo\\Application';
88
				if (class_exists($applicationClassName)) {
89
					new $applicationClassName();
90
					if (isset($this->appContainers[$namespace])) {
91
						return $this->appContainers[$namespace];
92
					}
93
				}
94
				$this->hasNoAppContainer[$namespace] = true;
95
			}
96
97
			return new DIContainer($this->namespaces[$namespace]);
98
		}
99
		throw new QueryException();
100
	}
101
102
	/**
103
	 * @param string $name name of the service to query for
104
	 * @return mixed registered service for the given $name
105
	 * @throws QueryException if the query could not be resolved
106
	 */
107
	public function query($name) {
108
		$name = $this->sanitizeName($name);
109
110
		// In case the service starts with OCA\ we try to find the service in
111
		// the apps container first.
112
		if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
113
			$segments = explode('\\', $name);
114
			try {
115
				$appContainer = $this->getAppContainer(strtolower($segments[1]), $segments[1]);
116
				return $appContainer->queryNoFallback($name);
117
			} catch (QueryException $e) {
118
				// Didn't find the service or the respective app container,
119
				// ignore it and fall back to the core container.
120
			}
121
		} else if (strpos($name, 'OC\\Settings\\') === 0 && substr_count($name, '\\') >= 3) {
122
			$segments = explode('\\', $name);
123
			try {
124
				$appContainer = $this->getAppContainer(strtolower($segments[1]));
125
				return $appContainer->queryNoFallback($name);
126
			} catch (QueryException $e) {
127
				// Didn't find the service or the respective app container,
128
				// ignore it and fall back to the core container.
129
			}
130
		}
131
132
		return parent::query($name);
133
	}
134
}
135