Failed Conditions
Branch facadeless (c66f0a)
by Atanas
02:01
created

src/Application/Application.php (18 issues)

1
<?php
2
/**
3
 * @package   WPEmerge
4
 * @author    Atanas Angelov <[email protected]>
5
 * @copyright 2017-2019 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 Closure;
13
use Pimple\Container;
14
use WPEmerge\Controllers\ControllersServiceProvider;
15
use WPEmerge\Csrf\CsrfServiceProvider;
16
use WPEmerge\Exceptions\ConfigurationException;
17
use WPEmerge\Exceptions\ExceptionsServiceProvider;
18
use WPEmerge\Flash\FlashServiceProvider;
19
use WPEmerge\Input\OldInputServiceProvider;
20
use WPEmerge\Kernels\KernelsServiceProvider;
21
use WPEmerge\Requests\Request;
22
use WPEmerge\Requests\RequestsServiceProvider;
23
use WPEmerge\Responses\ResponsesServiceProvider;
24
use WPEmerge\Routing\RoutingServiceProvider;
25
use WPEmerge\ServiceProviders\ServiceProviderInterface;
26
use WPEmerge\Support\Arr;
27
use WPEmerge\View\ViewServiceProvider;
28
29
/**
30
 * Main communication channel with the application.
31
 */
32
abstract class Application {
33
	use HasStaticAliasesTrait {
0 ignored issues
show
The trait WPEmerge\Application\HasStaticAliasesTrait requires the property $aliases which is not provided by WPEmerge\Application\Application.
Loading history...
34
		__construct as __constructTrait;
35
	}
36
37
	/**
38
	 * IoC container.
39
	 *
40
	 * @var Container
41
	 */
42
	protected $container = null;
43
44
	/**
45
	 * Flag whether to intercept and render configuration exceptions.
46
	 *
47
	 * @var boolean
48
	 */
49
	protected $render_configuration_exceptions = true;
50
51
	/**
52
	 * Flag whether the application has been bootstrapped.
53
	 *
54
	 * @var boolean
55
	 */
56
	protected $bootstrapped = false;
57
58
	/**
59
	 * Array of application service providers.
60
	 *
61
	 * @var string[]
62
	 */
63
	protected $service_providers = [
64
		ApplicationServiceProvider::class,
65
		KernelsServiceProvider::class,
66
		ExceptionsServiceProvider::class,
67
		RequestsServiceProvider::class,
68
		ResponsesServiceProvider::class,
69
		RoutingServiceProvider::class,
70
		ViewServiceProvider::class,
71
		ControllersServiceProvider::class,
72
		CsrfServiceProvider::class,
73
		FlashServiceProvider::class,
74
		OldInputServiceProvider::class,
75
	];
76
77
	/**
78
	 * Make a new application instance.
79
	 *
80
	 * @codeCoverageIgnore
81
	 * @return static
82
	 */
83
	public static function make() {
84
		return new static( new Container() );
0 ignored issues
show
The call to WPEmerge\Application\Application::__construct() has too many arguments starting with new Pimple\Container(). ( Ignorable by Annotation )

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

84
		return /** @scrutinizer ignore-call */ new static( new Container() );

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
85
	}
86
87
	/**
88
	 * Constructor.
89
	 *
90
	 * @param Container   $container
91
	 * @param boolean     $render_configuration_exceptions
92
	 */
93 1
	public function __construct( Container $container, $render_configuration_exceptions = true ) {
94 1
		$this->container = $container;
95 1
		$this->container[ WPEMERGE_APPLICATION_KEY ] = $this;
96 1
		$this->render_configuration_exceptions = $render_configuration_exceptions;
97
98 1
		$this->__constructTrait();
0 ignored issues
show
The method __constructTrait() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

98
		$this->/** @scrutinizer ignore-call */ 
99
         __constructTrait();

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...
99 1
	}
100
101
	/**
102
	 * Get whether WordPress is in debug mode.
103
	 *
104
	 * @return boolean
105
	 */
106 1
	public function debugging() {
107 1
		$debugging = ( defined( 'WP_DEBUG' ) && WP_DEBUG );
108 1
		$debugging = apply_filters( 'wpemerge.debug', $debugging );
109 1
		return $debugging;
110
	}
111
112
	/**
113
	 * Get whether the application has been bootstrapped.
114
	 *
115
	 * @return boolean
116
	 */
117 1
	public function isBootstrapped() {
118 1
		return $this->bootstrapped;
0 ignored issues
show
Bug Best Practice introduced by
The property bootstrapped does not exist on WPEmerge\Application\Application. Did you maybe forget to declare it?
Loading history...
119
	}
120
121
	/**
122
	 * Throw an exception if the application has not been bootstrapped.
123
	 *
124
	 * @return void
125
	 */
126 2
	protected function verifyBootstrap() {
127 2
		if ( ! $this->isBootstrapped() ) {
0 ignored issues
show
The method isBootstrapped() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

127
		if ( ! $this->/** @scrutinizer ignore-call */ isBootstrapped() ) {

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...
128 1
			throw new ConfigurationException( static::class . ' must be bootstrapped first.' );
129
		}
130 1
	}
131
132
	/**
133
	 * Get the IoC container instance.
134
	 *
135
	 * @return Container
136
	 */
137 1
	public function getContainer() {
138 1
		return $this->container;
0 ignored issues
show
Bug Best Practice introduced by
The property container does not exist on WPEmerge\Application\Application. Did you maybe forget to declare it?
Loading history...
139
	}
140
141
	/**
142
	 * Bootstrap the application.
143
	 * WordPress' 'after_setup_theme' action is a good place to call this.
144
	 *
145
	 * @param  array   $config
146
	 * @param  boolean $run
147
	 * @return void
148
	 */
149 4
	public function bootstrap( $config = [], $run = true ) {
150 4
		if ( $this->isBootstrapped() ) {
151 1
			throw new ConfigurationException( static::class . ' already bootstrapped.' );
152
		}
153
154 4
		$this->bootstrapped = true;
155
156 4
		$container = $this->getContainer();
0 ignored issues
show
The method getContainer() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

156
		/** @scrutinizer ignore-call */ 
157
  $container = $this->getContainer();

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...
157 4
		$this->loadConfig( $container, $config );
0 ignored issues
show
The method loadConfig() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

157
		$this->/** @scrutinizer ignore-call */ 
158
         loadConfig( $container, $config );

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...
158 4
		$this->loadServiceProviders( $container );
0 ignored issues
show
The method loadServiceProviders() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

158
		$this->/** @scrutinizer ignore-call */ 
159
         loadServiceProviders( $container );

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...
159
160 4
		$this->renderConfigurationExceptions( function () use ( $run ) {
0 ignored issues
show
The method renderConfigurationExceptions() does not exist on WPEmerge\Application\Application. Did you maybe mean render()? ( Ignorable by Annotation )

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

160
		$this->/** @scrutinizer ignore-call */ 
161
         renderConfigurationExceptions( function () use ( $run ) {

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...
161 4
			$this->loadRoutes();
0 ignored issues
show
The method loadRoutes() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

161
			$this->/** @scrutinizer ignore-call */ 
162
          loadRoutes();

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...
162
163 4
			if ( $run ) {
164 1
				$kernel = $this->resolve( WPEMERGE_WORDPRESS_HTTP_KERNEL_KEY );
0 ignored issues
show
The method resolve() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

164
				/** @scrutinizer ignore-call */ 
165
    $kernel = $this->resolve( WPEMERGE_WORDPRESS_HTTP_KERNEL_KEY );

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...
165 1
				$kernel->bootstrap();
166
			}
167 4
		} );
168 4
	}
169
170
	/**
171
	 * Load config into the service container.
172
	 *
173
	 * @codeCoverageIgnore
174
	 * @param  Container $container
175
	 * @param  array     $config
176
	 * @return void
177
	 */
178
	protected function loadConfig( Container $container, $config ) {
179
		$container[ WPEMERGE_CONFIG_KEY ] = $config;
180
	}
181
182
	/**
183
	 * Register and bootstrap all service providers.
184
	 *
185
	 * @codeCoverageIgnore
186
	 * @param  Container $container
187
	 * @return void
188
	 */
189
	protected function loadServiceProviders( Container $container ) {
190
		$container[ WPEMERGE_SERVICE_PROVIDERS_KEY ] = array_merge(
191
			$this->service_providers,
0 ignored issues
show
Bug Best Practice introduced by
The property service_providers does not exist on WPEmerge\Application\Application. Did you maybe forget to declare it?
Loading history...
192
			Arr::get( $container[ WPEMERGE_CONFIG_KEY ], 'providers', [] )
193
		);
194
195
		$service_providers = array_map( function ( $service_provider ) {
196
			if ( ! is_subclass_of( $service_provider, ServiceProviderInterface::class ) ) {
197
				throw new ConfigurationException(
198
					'The following class does not implement ' .
199
					'ServiceProviderInterface: ' . $service_provider
200
				);
201
			}
202
203
			return new $service_provider();
204
		}, $container[ WPEMERGE_SERVICE_PROVIDERS_KEY ] );
205
206
		$this->registerServiceProviders( $service_providers, $container );
0 ignored issues
show
The method registerServiceProviders() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

206
		$this->/** @scrutinizer ignore-call */ 
207
         registerServiceProviders( $service_providers, $container );

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...
207
		$this->bootstrapServiceProviders( $service_providers, $container );
0 ignored issues
show
The method bootstrapServiceProviders() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

207
		$this->/** @scrutinizer ignore-call */ 
208
         bootstrapServiceProviders( $service_providers, $container );

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...
208
	}
209
210
	/**
211
	 * Register all service providers.
212
	 *
213
	 * @param  array<ServiceProviderInterface> $service_providers
214
	 * @param  Container                                                  $container
215
	 * @return void
216
	 */
217 1
	protected function registerServiceProviders( $service_providers, Container $container ) {
218 1
		foreach ( $service_providers as $provider ) {
219 1
			$provider->register( $container );
220
		}
221 1
	}
222
223
	/**
224
	 * Bootstrap all service providers.
225
	 *
226
	 * @param  array<ServiceProviderInterface> $service_providers
227
	 * @param  Container                                                  $container
228
	 * @return void
229
	 */
230 1
	protected function bootstrapServiceProviders( $service_providers, Container $container ) {
231 1
		foreach ( $service_providers as $provider ) {
232 1
			$provider->bootstrap( $container );
233
		}
234 1
	}
235
236
	/**
237
	 * Load route definition files depending on the current request.
238
	 *
239
	 * @codeCoverageIgnore
240
	 * @return void
241
	 */
242
	protected function loadRoutes() {
243
		if ( wp_doing_ajax() ) {
244
			$this->loadRoutesGroup( 'ajax' );
0 ignored issues
show
The method loadRoutesGroup() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

244
			$this->/** @scrutinizer ignore-call */ 
245
          loadRoutesGroup( 'ajax' );

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...
245
			return;
246
		}
247
248
		if ( is_admin() ) {
249
			$this->loadRoutesGroup( 'admin' );
250
			return;
251
		}
252
253
		$this->loadRoutesGroup( 'web' );
254
	}
255
256
	/**
257
	 * Load a route group applying default attributes, if any.
258
	 *
259
	 * @codeCoverageIgnore
260
	 * @param  string $group
261
	 * @return void
262
	 */
263
	protected function loadRoutesGroup( $group ) {
264
		$config = $this->resolve( WPEMERGE_CONFIG_KEY );
265
		$file = Arr::get( $config, 'routes.' . $group . '.definitions', '' );
266
		$attributes = Arr::get( $config, 'routes.' . $group . '.attributes', [] );
267
268
		if ( empty( $file ) ) {
269
			return;
270
		}
271
272
		$middleware = Arr::get( $attributes, 'middleware', [] );
273
274
		if ( ! in_array( $group, $middleware, true ) ) {
275
			$middleware = array_merge( [$group], $middleware );
276
		}
277
278
		$attributes['middleware'] = $middleware;
279
280
		$blueprint = $this->resolve( WPEMERGE_ROUTING_ROUTE_BLUEPRINT_KEY );
281
		$blueprint->attributes( $attributes )->group( $file );
282
	}
283
284
	/**
285
	 * Resolve a dependency from the IoC container.
286
	 *
287
	 * @param  string     $key
288
	 * @return mixed|null
289
	 */
290 2
	public function resolve( $key ) {
291 2
		$this->verifyBootstrap();
0 ignored issues
show
The method verifyBootstrap() does not exist on WPEmerge\Application\Application. ( Ignorable by Annotation )

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

291
		$this->/** @scrutinizer ignore-call */ 
292
         verifyBootstrap();

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...
292
293 2
		if ( ! isset( $this->getContainer()[ $key ] ) ) {
294 1
			return null;
295
		}
296
297 2
		return $this->getContainer()[ $key ];
298
	}
299
300
	/**
301
	 * Catch any configuration exceptions and short-circuit to an error page.
302
	 *
303
	 * @codeCoverageIgnore
304
	 * @param  Closure $action
305
	 * @return void
306
	 */
307
	protected function renderConfigurationExceptions( Closure $action ) {
308
		try {
309
			$action();
310
		} catch ( ConfigurationException $exception ) {
311
			if ( ! $this->render_configuration_exceptions ) {
0 ignored issues
show
Bug Best Practice introduced by
The property render_configuration_exceptions does not exist on WPEmerge\Application\Application. Did you maybe forget to declare it?
Loading history...
312
				throw $exception;
313
			}
314
315
			$request = Request::fromGlobals();
316
			$handler = $this->resolve( WPEMERGE_EXCEPTIONS_CONFIGURATION_ERROR_HANDLER_KEY );
317
318
			add_filter( 'wpemerge.pretty_errors.apply_admin_styles', '__return_false' );
319
320
			$response_service = $this->resolve( WPEMERGE_RESPONSE_SERVICE_KEY );
321
			$response_service->respond( $handler->getResponse( $request, $exception ) );
322
323
			wp_die();
324
		}
325
	}
326
}
327