Passed
Push — master ( dca246...fba64a )
by Morris
12:43 queued 12s
created

Coordinator::getRegistrationContext()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
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 2020 Christoph Wurst <[email protected]>
9
 *
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
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
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 */
25
26
namespace OC\AppFramework\Bootstrap;
27
28
use OC\Support\CrashReport\Registry;
29
use OC_App;
30
use OCP\AppFramework\App;
31
use OCP\AppFramework\Bootstrap\IBootstrap;
32
use OCP\AppFramework\QueryException;
33
use OCP\EventDispatcher\IEventDispatcher;
34
use OCP\ILogger;
35
use OCP\IServerContainer;
36
use RuntimeException;
37
use Throwable;
38
use function class_exists;
39
use function class_implements;
40
use function in_array;
41
42
class Coordinator {
43
44
	/** @var IServerContainer */
45
	private $serverContainer;
46
47
	/** @var Registry */
48
	private $registry;
49
50
	/** @var IEventDispatcher */
51
	private $eventDispatcher;
52
53
	/** @var ILogger */
54
	private $logger;
55
56
	/** @var RegistrationContext|null */
57
	private $registrationContext;
58
59
	public function __construct(IServerContainer $container,
60
								Registry $registry,
61
								IEventDispatcher $eventListener,
62
								ILogger $logger) {
63
		$this->serverContainer = $container;
64
		$this->registry = $registry;
65
		$this->eventDispatcher = $eventListener;
66
		$this->logger = $logger;
67
	}
68
69
	public function runRegistration(): void {
70
		if ($this->registrationContext !== null) {
71
			throw new RuntimeException('Registration has already been run');
72
		}
73
74
		$this->registrationContext = new RegistrationContext($this->logger);
75
		$apps = [];
76
		foreach (OC_App::getEnabledApps() as $appId) {
77
			/*
78
			 * First, we have to enable the app's autoloader
79
			 *
80
			 * @todo use $this->appManager->getAppPath($appId) here
81
			 */
82
			$path = OC_App::getAppPath($appId);
0 ignored issues
show
Deprecated Code introduced by
The function OC_App::getAppPath() has been deprecated: 11.0.0 use \OC::$server->getAppManager()->getAppPath() ( Ignorable by Annotation )

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

82
			$path = /** @scrutinizer ignore-deprecated */ OC_App::getAppPath($appId);

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

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

Loading history...
83
			if ($path === false) {
84
				// Ignore
85
				continue;
86
			}
87
			OC_App::registerAutoloading($appId, $path);
88
89
			/*
90
			 * Next we check if there is an application class and it implements
91
			 * the \OCP\AppFramework\Bootstrap\IBootstrap interface
92
			 */
93
			$appNameSpace = App::buildAppNamespace($appId);
94
			$applicationClassName = $appNameSpace . '\\AppInfo\\Application';
95
			if (class_exists($applicationClassName) && in_array(IBootstrap::class, class_implements($applicationClassName), true)) {
96
				try {
97
					/** @var IBootstrap|App $application */
98
					$apps[$appId] = $application = $this->serverContainer->query($applicationClassName);
99
				} catch (QueryException $e) {
100
					// Weird, but ok
101
					continue;
102
				}
103
				try {
104
					$application->register($this->registrationContext->for($appId));
0 ignored issues
show
Bug introduced by
The method register() does not exist on OCP\AppFramework\App. Did you maybe mean registerRoutes()? ( Ignorable by Annotation )

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

104
					$application->/** @scrutinizer ignore-call */ 
105
                   register($this->registrationContext->for($appId));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
105
				} catch (Throwable $e) {
106
					$this->logger->logException($e, [
107
						'message' => 'Error during app service registration: ' . $e->getMessage(),
108
						'level' => ILogger::FATAL,
109
					]);
110
				}
111
			}
112
		}
113
114
		/**
115
		 * Now that all register methods have been called, we can delegate the registrations
116
		 * to the actual services
117
		 */
118
		$this->registrationContext->delegateCapabilityRegistrations($apps);
119
		$this->registrationContext->delegateCrashReporterRegistrations($apps, $this->registry);
120
		$this->registrationContext->delegateEventListenerRegistrations($this->eventDispatcher);
121
		$this->registrationContext->delegateContainerRegistrations($apps);
122
		$this->registrationContext->delegateMiddlewareRegistrations($apps);
123
	}
124
125
	public function getRegistrationContext(): ?RegistrationContext {
126
		return $this->registrationContext;
127
	}
128
129
	public function bootApp(string $appId): void {
130
		$appNameSpace = App::buildAppNamespace($appId);
131
		$applicationClassName = $appNameSpace . '\\AppInfo\\Application';
132
		if (!class_exists($applicationClassName)) {
133
			// Nothing to boot
134
			return;
135
		}
136
137
		/*
138
		 * Now it is time to fetch an instance of the App class. For classes
139
		 * that implement \OCP\AppFramework\Bootstrap\IBootstrap this means
140
		 * the instance was already created for register, but any other
141
		 * (legacy) code will now do their magic via the constructor.
142
		 */
143
		try {
144
			/** @var App $application */
145
			$application = $this->serverContainer->query($applicationClassName);
146
			if ($application instanceof IBootstrap) {
147
				/** @var BootContext $context */
148
				$context = new BootContext($application->getContainer());
149
				$application->boot($context);
150
			}
151
		} catch (QueryException $e) {
152
			$this->logger->logException($e, [
153
				'message' => "Could not boot $appId" . $e->getMessage(),
154
			]);
155
		} catch (Throwable $e) {
156
			$this->logger->logException($e, [
157
				'message' => "Could not boot $appId" . $e->getMessage(),
158
				'level' => ILogger::FATAL,
159
			]);
160
		}
161
	}
162
163
	public function isBootable(string $appId) {
164
		$appNameSpace = App::buildAppNamespace($appId);
165
		$applicationClassName = $appNameSpace . '\\AppInfo\\Application';
166
		return class_exists($applicationClassName) &&
167
			in_array(IBootstrap::class, class_implements($applicationClassName), true);
168
	}
169
}
170