Passed
Push — master ( 5c8d6a...421765 )
by Atanas
01:51
created

Framework::resolve()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
ccs 5
cts 5
cp 1
crap 2
1
<?php
2
3
namespace Obsidian\Framework;
4
5
use ReflectionException;
6
use ReflectionMethod;
7
use Exception;
8
use Pimple\Container;
9
use Psr\Http\Message\ResponseInterface;
10
use Obsidian\Response;
11
use Obsidian\Support\Facade;
12
use Obsidian\Support\AliasLoader;
13
use Obsidian\Routing\RoutingServiceProvider;
14
use Obsidian\Flash\FlashServiceProvider;
15
use Obsidian\Input\OldInputServiceProvider;
16
use Obsidian\Templating\TemplatingServiceProvider;
17
use Obsidian\Controllers\ControllersServiceProvider;
18
19
/**
20
 * Main communication channel with the framework
21
 */
22
class Framework {
23
	/**
24
	 * Flag whether the framework has been booted
25
	 *
26
	 * @var boolean
27
	 */
28
	protected $booted = false;
29
30
	/**
31
	 * IoC container
32
	 *
33
	 * @var Container
34
	 */
35
	protected $container = null;
36
37
	/**
38
	 * Array of framework service providers
39
	 *
40
	 * @var string[]
41
	 */
42
	protected $service_proviers = [
43
		RoutingServiceProvider::class,
44
		FlashServiceProvider::class,
45
		OldInputServiceProvider::class,
46
		TemplatingServiceProvider::class,
47
		ControllersServiceProvider::class,
48
	];
49
50
	/**
51
	 * Constructor
52
	 *
53
	 * @param Container $container
54
	 */
55
	public function __construct( Container $container ) {
56
		$this->container = $container;
57
	}
58
59
	/**
60
	 * Get whether WordPress is in debug mode
61
	 *
62
	 * @return boolean
63
	 */
64 1
	public function debugging() {
65 1
		$debugging = ( defined( 'WP_DEBUG' ) && WP_DEBUG );
66 1
		$debugging = apply_filters( 'obsidian.debug', $debugging );
67 1
		return $debugging;
68
	}
69
70
	/**
71
	 * Get whether the framework has been booted
72
	 *
73
	 * @return boolean
74
	 */
75 1
	public function isBooted() {
76 1
		return $this->booted;
77
	}
78
79
	/**
80
	 * Throw an exception if the framework has not been booted
81
	 *
82
	 * @codeCoverageIgnore
83
	 * @throws Exception
84
	 * @return void
85
	 */
86
	protected function verifyBoot() {
87
		if ( ! $this->isBooted() ) {
88
			throw new Exception( static::class . ' must be booted first.' );
89
		}
90
	}
91
92
	/**
93
	 * Get the IoC container instance
94
	 *
95
	 * @return Container
96
	 */
97 1
	public function getContainer() {
98 1
		return $this->container;
99
	}
100
101
	/**
102
	 * Boot the framework
103
	 * WordPress's 'after_setup_theme' action is a good place to call this
104
	 *
105
	 * @codeCoverageIgnore
106
	 * @param  array     $config
107
	 * @throws Exception
108
	 * @return void
109
	 */
110
	public function boot( $config = [] ) {
111
		if ( $this->isBooted() ) {
112
			throw new Exception( static::class . ' already booted.' );
113
		}
114
115
		do_action( 'obsidian.booting' );
116
117
		$container = $this->getContainer();
118
		$this->loadConfig( $container, $config );
119
		$this->loadServiceProviders( $container );
120
		$this->booted = true;
121
122
		do_action( 'obsidian.booted' );
123
	}
124
125
	/**
126
	 * Load config into the service container
127
	 *
128
	 * @codeCoverageIgnore
129
	 * @param  Container $container
130
	 * @param  array     $config
131
	 * @return void
132
	 */
133
	protected function loadConfig( Container $container, $config ) {
134
		$container = $this->getContainer();
135
		$container['framework.config'] = array_merge( [
136
			'providers' => [],
137
		], $config );
138
	}
139
140
	/**
141
	 * Register and boot all service providers
142
	 *
143
	 * @codeCoverageIgnore
144
	 * @param  Container $container
145
	 * @return void
146
	 */
147
	protected function loadServiceProviders( Container $container ) {
148
		$container['framework.service_providers'] = array_merge(
149
			$this->service_proviers,
150
			$container['framework.config']['providers']
151
		);
152
153
		$container['framework.service_providers'] = apply_filters(
154
			'obsidian.service_providers',
155
			$container['framework.service_providers']
156
		);
157
158
		$service_providers = array_map( function( $service_provider ) {
159
			return new $service_provider();
160
		}, $container['framework.service_providers'] );
161
162
		$this->registerServiceProviders( $service_providers, $container );
163
		$this->bootServiceProviders( $service_providers, $container );
164
	}
165
166
	/**
167
	 * Register all service providers
168
	 *
169
	 * @codeCoverageIgnore
170
	 * @param  \Obsidian\ServiceProviders\ServiceProviderInterface[] $service_providers
171
	 * @param  Container                                             $container
172
	 * @return void
173
	 */
174
	protected function registerServiceProviders( $service_providers, Container $container ) {
175
		foreach ( $service_providers as $provider ) {
176
			$provider->register( $container );
177
		}
178
	}
179
180
	/**
181
	 * Boot all service providers
182
	 *
183
	 * @codeCoverageIgnore
184
	 * @param  \Obsidian\ServiceProviders\ServiceProviderInterface[] $service_providers
185
	 * @param  Container                                             $container
186
	 * @return void
187
	 */
188
	protected function bootServiceProviders( $service_providers, Container $container ) {
189
		foreach ( $service_providers as $provider ) {
190
			$provider->boot( $container );
191
		}
192
	}
193
194
	/**
195
	 * Register a facade class
196
	 *
197
	 * @param  string $alias
198
	 * @param  string $facade_class
199
	 * @return void
200
	 */
201 1
	public function facade( $alias, $facade_class ) {
202 1
		AliasLoader::getInstance()->alias( $alias, $facade_class );
203 1
	}
204
205
	/**
206
	 * Resolve a dependency from the IoC container
207
	 *
208
	 * @param  string   $key
209
	 * @return mixed|null
210
	 */
211 2
	public function resolve( $key ) {
212 2
		$this->verifyBoot();
213
214 2
		if ( ! isset( $this->getContainer()[ $key ] ) ) {
215 1
			return null;
216
		}
217
218 1
		return $this->getContainer()[ $key ];
219
	}
220
221
	/**
222
	 * Create and return a class instance
223
	 *
224
	 * @param  string $class
225
	 * @return object
226
	 */
227 2
	public function instantiate( $class ) {
228 2
		$this->verifyBoot();
229
230 2
		$instance = $this->resolve( $class );
231
232 2
		if ( $instance === null ) {
233 1
			$instance = new $class();
234 1
		}
235
236 2
		return $instance;
237
	}
238
239
	/**
240
	 * Send output based on a response object
241
	 *
242
	 * @codeCoverageIgnore
243
	 * @param  ResponseInterface $response
244
	 * @return void
245
	 */
246
	public function respond( ResponseInterface $response ) {
247
		Response::respond( $response );
248
	}
249
}
250