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
Bug
introduced
by
![]() |
|||||||
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
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. ![]() |
|||||||
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
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. ![]() |
|||||||
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
|
|||||||
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
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. ![]() |
|||||||
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
|
|||||||
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
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. ![]() |
|||||||
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
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. ![]() |
|||||||
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
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. ![]() |
|||||||
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
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. ![]() |
|||||||
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
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. ![]() |
|||||||
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
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. ![]() |
|||||||
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
|
|||||||
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
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. ![]() |
|||||||
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
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. ![]() |
|||||||
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
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. ![]() |
|||||||
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
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. ![]() |
|||||||
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
|
|||||||
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 |