Failed Conditions
Branch refactor/kernels (4c6e24)
by Atanas
01:47
created

src/Application/Application.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * @package   WPEmerge
4
 * @author    Atanas Angelov <[email protected]>
5
 * @copyright 2018 Atanas Angelov
6
 * @license   https://www.gnu.org/licenses/gpl-2.0.html GPL-2.0
7
 * @link      https://wpemerge.com/
8
 */
9
10
namespace WPEmerge\Application;
11
12
use Pimple\Container;
13
use Psr\Http\Message\ResponseInterface;
14
use WPEmerge\Controllers\ControllersServiceProvider;
15
use WPEmerge\Csrf\CsrfServiceProvider;
16
use WPEmerge\Exceptions\ConfigurationException;
17
use WPEmerge\Exceptions\ExceptionsServiceProvider;
18
use WPEmerge\Facades\Route;
19
use WPEmerge\Flash\FlashServiceProvider;
20
use WPEmerge\Input\OldInputServiceProvider;
21
use WPEmerge\Kernels\KernelsServiceProvider;
22
use WPEmerge\Requests\RequestsServiceProvider;
23
use WPEmerge\Responses\ResponsesServiceProvider;
24
use WPEmerge\Routing\RoutingServiceProvider;
25
use WPEmerge\ServiceProviders\ServiceProviderInterface;
26
use WPEmerge\Support\AliasLoader;
27
use WPEmerge\View\ViewServiceProvider;
28
29
/**
30
 * Main communication channel with the application.
31
 */
32
class Application {
33
	/**
34
	 * Flag whether the application has been bootstrapped.
35
	 *
36
	 * @var boolean
37
	 */
38
	protected $bootstrapped = false;
39
40
	/**
41
	 * IoC container.
42
	 *
43
	 * @var Container
44
	 */
45
	protected $container = null;
46
47
	/**
48
	 * Array of application service providers.
49
	 *
50
	 * @var string[]
51
	 */
52
	protected $service_providers = [
53
		KernelsServiceProvider::class,
54
		ExceptionsServiceProvider::class,
55
		RequestsServiceProvider::class,
56
		ResponsesServiceProvider::class,
57
		RoutingServiceProvider::class,
58
		ViewServiceProvider::class,
59
		ControllersServiceProvider::class,
60
		CsrfServiceProvider::class,
61
		FlashServiceProvider::class,
62
		OldInputServiceProvider::class,
63
	];
64
65
	/**
66
	 * Constructor.
67
	 *
68
	 * @param Container $container
69
	 */
70 1
	public function __construct( Container $container ) {
71 1
		$this->container = $container;
72
73 1
		$config = isset( $container[ WPEMERGE_CONFIG_KEY ] ) ? $container[ WPEMERGE_CONFIG_KEY ] : [];
74 1
		$config = array_merge( [
75 1
			'providers' => [],
76 1
		], $config );
77 1
		$container[ WPEMERGE_CONFIG_KEY ] = $config;
78 1
	}
79
80
	/**
81
	 * Get whether WordPress is in debug mode.
82
	 *
83
	 * @return boolean
84
	 */
85 1
	public function debugging() {
86 1
		$debugging = ( defined( 'WP_DEBUG' ) && WP_DEBUG );
87 1
		$debugging = apply_filters( 'wpemerge.debug', $debugging );
88 1
		return $debugging;
89
	}
90
91
	/**
92
	 * Get whether the application has been bootstrapped.
93
	 *
94
	 * @return boolean
95
	 */
96 1
	public function isBootstrapped() {
97 1
		return $this->bootstrapped;
98
	}
99
100
	/**
101
	 * Throw an exception if the application has not been bootstrapped.
102
	 *
103
	 * @throws ConfigurationException
104
	 * @return void
105
	 */
106 5
	protected function verifyBootstrap() {
107 5
		if ( ! $this->isBootstrapped() ) {
108 1
			throw new ConfigurationException( static::class . ' must be bootstrapped first.' );
109
		}
110 4
	}
111
112
	/**
113
	 * Get the IoC container instance.
114
	 *
115
	 * @return Container
116
	 */
117 1
	public function getContainer() {
118 1
		return $this->container;
119
	}
120
121
	/**
122
	 * Bootstrap the application.
123
	 * WordPress' 'after_setup_theme' action is a good place to call this.
124
	 *
125
	 * @throws ConfigurationException
126
	 * @param  array   $config
127
	 * @param  boolean $run
128
	 * @return void
129
	 */
130 3
	public function bootstrap( $config = [], $run = true ) {
131 3
		if ( $this->isBootstrapped() ) {
132 1
			throw new ConfigurationException( static::class . ' already bootstrapped.' );
133
		}
134
135 3
		$container = $this->getContainer();
136 3
		$this->loadConfig( $container, $config );
137 3
		$this->loadServiceProviders( $container );
138
139 3
		$this->bootstrapped = true;
140
141 3
		if ( $run ) {
142
			$kernel = $this->resolve( WPEMERGE_WORDPRESS_HTTP_KERNEL_KEY );
143
			$kernel->bootstrap();
144
		}
145 3
	}
146
147
	/**
148
	 * Load config into the service container.
149
	 *
150
	 * @codeCoverageIgnore
151
	 * @param  Container $container
152
	 * @param  array     $config
153
	 * @return void
154
	 */
155
	protected function loadConfig( Container $container, $config ) {
156
		$container[ WPEMERGE_CONFIG_KEY ] = array_merge(
157
			$container[ WPEMERGE_CONFIG_KEY ],
158
			$config
159
		);
160
	}
161
162
	/**
163
	 * Register and bootstrap all service providers.
164
	 *
165
	 * @codeCoverageIgnore
166
	 * @param  Container $container
167
	 * @return void
168
	 */
169
	protected function loadServiceProviders( Container $container ) {
170
		$container[ WPEMERGE_SERVICE_PROVIDERS_KEY ] = array_merge(
171
			$this->service_providers,
172
			$container[ WPEMERGE_CONFIG_KEY ]['providers']
173
		);
174
175
		$service_providers = array_map( function ( $service_provider ) {
176
			if ( ! is_subclass_of( $service_provider, ServiceProviderInterface::class ) ) {
177
				throw new ConfigurationException( 'The following class does not implement ServiceProviderInterface: ' . $service_provider );
178
			}
179
180
			return new $service_provider();
181
		}, $container[ WPEMERGE_SERVICE_PROVIDERS_KEY ] );
182
183
		$this->registerServiceProviders( $service_providers, $container );
184
		$this->bootstrapServiceProviders( $service_providers, $container );
185
	}
186
187
	/**
188
	 * Register all service providers.
189
	 *
190
	 * @param  \WPEmerge\ServiceProviders\ServiceProviderInterface[] $service_providers
191
	 * @param  Container                                             $container
192
	 * @return void
193
	 */
194 1
	protected function registerServiceProviders( $service_providers, Container $container ) {
195 1
		foreach ( $service_providers as $provider ) {
196 1
			$provider->register( $container );
197
		}
198 1
	}
199
200
	/**
201
	 * Bootstrap all service providers.
202
	 *
203
	 * @param  \WPEmerge\ServiceProviders\ServiceProviderInterface[] $service_providers
204
	 * @param  Container                                             $container
205
	 * @return void
206
	 */
207 1
	protected function bootstrapServiceProviders( $service_providers, Container $container ) {
208 1
		foreach ( $service_providers as $provider ) {
209 1
			$provider->bootstrap( $container );
210
		}
211 1
	}
212
213
	/**
214
	 * Register a facade class.
215
	 *
216
	 * @param  string $alias
217
	 * @param  string $facade_class
218
	 * @return void
219
	 */
220 1
	public function facade( $alias, $facade_class ) {
221 1
		AliasLoader::getInstance()->alias( $alias, $facade_class );
222 1
	}
223
224
	/**
225
	 * Resolve a dependency from the IoC container.
226
	 *
227
	 * @param  string     $key
228
	 * @return mixed|null
229
	 */
230 2
	public function resolve( $key ) {
231 2
		$this->verifyBootstrap();
232
233 2
		if ( ! isset( $this->getContainer()[ $key ] ) ) {
234 1
			return null;
235
		}
236
237 1
		return $this->getContainer()[ $key ];
238
	}
239
240
	/**
241
	 * Create and return a class instance.
242
	 *
243
	 * @throws ClassNotFoundException
244
	 * @param  string $class
245
	 * @return object
246
	 */
247 3
	public function instantiate( $class ) {
248 3
		$this->verifyBootstrap();
249
250 3
		$instance = $this->resolve( $class );
251
252 3
		if ( $instance === null ) {
253 2
			if ( ! class_exists( $class ) ) {
254 1
				throw new ClassNotFoundException( 'Class not found: ' . $class );
255
			}
256
257 1
			$instance = new $class();
258
		}
259
260 2
		return $instance;
261
	}
262
263
	/**
264
	 * Send output based on a response object.
265
	 *
266
	 * @codeCoverageIgnore
267
	 * @param  ResponseInterface $response
268
	 * @return void
269
	 */
270
	public function respond( ResponseInterface $response ) {
271
		$this->resolve( WPEMERGE_RESPONSE_SERVICE_KEY )->respond( $response );
272
	}
273
274
	/**
275
	 * Load a route definition file, applying middleware to all routes defined within.
276
	 *
277
	 * @codeCoverageIgnore
278
	 * @param  string        $file
279
	 * @param  array<string> $middleware
280
	 * @return void
281
	 */
282
	protected function loadRoutes( $file, $middleware = [] ) {
283
		if ( empty( $file ) ) {
284
			return;
285
		}
286
287
		Route::middleware( $middleware )->group( $file );
0 ignored issues
show
The method middleware() does not exist on WPEmerge\Facades\Route. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

287
		Route::/** @scrutinizer ignore-call */ 
288
         middleware( $middleware )->group( $file );
Loading history...
288
	}
289
290
	/**
291
	 * Load route definition files according to the current request.
292
	 *
293
	 * @codeCoverageIgnore
294
	 * @param  string $web
295
	 * @param  string $admin
296
	 * @param  string $ajax
297
	 * @return void
298
	 */
299
	public function routes( $web = '', $admin = '', $ajax = '' ) {
300
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
301
			$this->loadRoutes( $ajax, ['ajax'] );
302
			return;
303
		}
304
305
		if ( is_admin() ) {
306
			$this->loadRoutes( $admin, ['admin'] );
307
			return;
308
		}
309
310
		$this->loadRoutes( $web, ['web'] );
311
	}
312
}
313