PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.35
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.35
2.1.0 2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 1.41 All 42 releases
fluent-boards / vendor / wpfluent / framework / src / WPFluent / Foundation / Application.php

Application.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.35, at vendor/wpfluent/framework/src/WPFluent/Foundation/Application.php

404 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBoards\Framework\Foundation;
4
5 use InvalidArgumentException;
6 use FluentBoards\Framework\Support\Arr;
7 use FluentBoards\Framework\Foundation\Config;
8 use FluentBoards\Framework\Container\Container;
9 use FluentBoards\Framework\Foundation\ComponentBinder;
10 use FluentBoards\Framework\Foundation\FoundationTrait;
11 use FluentBoards\Framework\Foundation\AsyncRequestTrait;
12
13 class Application extends Container
14 {
15 use FoundationTrait,
16 AsyncRequestTrait;
17
18 /**
19 * Main plugin file's absolute path
20 * @var string
21 */
22 protected $file = null;
23
24 /**
25 * Plugin's base url
26 * @var string
27 */
28 protected $baseUrl = null;
29
30 /**
31 * Plugin's base path
32 * @var string
33 */
34 protected $basePath = null;
35
36 /**
37 * Default namespace for hook's handlers
38 * @var string
39 */
40 protected $handlerNamespace = null;
41
42 /**
43 * Default namespace for controllers
44 * @var string
45 */
46 protected $controllerNamespace = null;
47
48 /**
49 * Default namespace for policy handlers
50 * @var string
51 */
52 protected $permissionNamespace = null;
53
54 /**
55 * Composer JSON
56 * @var null|array
57 */
58 protected static $composer = null;
59
60 /**
61 * Construct the application instance
62 *
63 * @param string $file The main plugin file's absolute path
64 * @return null
65 */
66 public function __construct($file = null)
67 {
68 $this->init($file);
69 $this->setAppLevelNamespace();
70 $this->bootstrapApplication();
71 }
72
73 /**
74 * Init the application instance
75 *
76 * @param string $file The main plugin file's absolute path
77 *
78 * @return null
79 */
80 protected function init($file)
81 {
82 $this['__pluginfile__'] = $this->file = $file;
83 $this->basePath = plugin_dir_path($this->file);
84 $this->baseUrl = plugin_dir_url($this->file);
85 }
86
87 /**
88 * Set the default application level namespaces to resolve
89 * the controllers, policies and various hook handlers.
90 *
91 * @return null
92 */
93 protected function setAppLevelNamespace()
94 {
95 $composer = $this->getComposer();
96
97 $psr4 = array_flip($composer['autoload']['psr-4']);
98
99 $this->policyNamespace = $psr4['app/'] . 'Http\Policies';
100
101 $this->handlerNamespace = $psr4['app/'] . 'Hooks\Handlers';
102
103 $this->controllerNamespace = $psr4['app/'] . 'Http\Controllers';
104
105 $this['__namespace__'] = $composer['extra']['wpfluent']['namespace']['current'];
106 }
107
108 /**
109 * Get the composer data as an array
110 *
111 * @param string $section Specific key
112 *
113 * @return array partial or full composer data array
114 */
115 public function getComposer($section = null)
116 {
117 if (is_null(static::$composer)) {
118 static::$composer = json_decode(
119 file_get_contents($this->basePath . 'composer.json'), true
120 );
121 }
122
123 return $section ? Arr::get(static::$composer, $section) : static::$composer;
124 }
125
126 /**
127 * Bootstrap the application.
128 *
129 * @return null
130 */
131 protected function bootstrapApplication()
132 {
133 $this->bindAppInstance();
134 $this->bindPathsAndUrls();
135 $this->loadConfigIfExists();
136 $this->registerTextdomain();
137 $this->bindCoreComponents();
138 $this->requireCommonFiles($this);
139 $this->registerAsyncActions();
140 $this->addRestApiInitAction($this);
141 }
142
143 /**
144 * Bind application instance in the container.
145 *
146 * @return null
147 */
148 protected function bindAppInstance()
149 {
150 App::setInstance($this);
151 $this->instance('app', $this);
152 $this->instance(__CLASS__, $this);
153 $this->instance('endpoints', []);
154 }
155
156 /**
157 * Bind the paths and urls
158 *
159 * @return null
160 */
161 protected function bindPathsAndUrls()
162 {
163 $this->bindUrls();
164 $this->basePaths();
165 }
166
167 /**
168 * Bind urls
169 *
170 * @return null
171 */
172 protected function bindUrls()
173 {
174 $this['url.assets'] = $this->baseUrl . 'assets/';
175 }
176
177 /**
178 * Bind paths
179 *
180 * @return null
181 */
182 protected function basePaths()
183 {
184 $this['path'] = $this->basePath;
185 $this['path.app'] = $this->basePath . 'app/';
186 $this['path.hooks'] = $this['path.app'] . 'Hooks/';
187 $this['path.http'] = $this['path.app'] . 'Http/';
188 $this['path.controllers'] = $this['path.http'] . 'Controllers/';
189 $this['path.config'] = $this->basePath . 'config/';
190 $this['path.assets'] = $this->basePath . 'assets/';
191 $this['path.resources'] = $this->basePath . 'resources/';
192 $this['path.views'] = $this['path.app'] . 'Views/';
193 }
194
195 /**
196 * Load application's config and set
197 * the data in the Config instance.
198 *
199 * @return null
200 */
201 protected function loadConfigIfExists()
202 {
203 $data = [];
204
205 if (is_dir($this['path.config'])) {
206 foreach (glob($this['path.config'] . '*.php') as $file) {
207 $data[basename($file, '.php')] = require($file);
208 }
209 }
210
211 $this->instance('config', new Config($data));
212 }
213
214 /**
215 * Register plugin's text domain
216 *
217 * @return null
218 */
219 protected function registerTextdomain()
220 {
221 $this->addAction('init', function() {
222 load_plugin_textdomain(
223 $this->config->get('app.text_domain'), false, $this->textDomainPath()
224 );
225 });
226 }
227
228 /**
229 * Resolve the text domain path.
230 *
231 * @return null
232 */
233 protected function textDomainPath()
234 {
235 return basename($this['path']) . $this->config->get('app.domain_path');
236 }
237
238 /**
239 * Bind the components of the framework into the container so
240 * they'll be available throughout the application life cycle.
241 *
242 * @return null
243 */
244 protected function bindCoreComponents()
245 {
246 (new ComponentBinder($this))->bindComponents();
247 }
248
249 /**
250 * Load (include) the files where hooks are registered.
251 *
252 * @param self $app
253 *
254 * @return null
255 */
256 protected function requireCommonFiles($app)
257 {
258 $this->addFilter(
259 'rest_pre_serve_request', [$this, 'preServeRequest'], 10, 4
260 );
261
262 require_once $this->basePath . 'app/Hooks/actions.php';
263 require_once $this->basePath . 'app/Hooks/filters.php';
264
265 if (file_exists($includes = $this->basePath . 'app/Hooks/includes.php')) {
266 require_once $includes;
267 }
268 }
269
270 /**
271 * Handler for rest_pre_serve_request filter.
272 *
273 * @param bool $served (default: false)
274 * @param \WP_Rest_Response $result
275 * @param \WP_Rest_Request $request
276 * @param \WP_Rest_Server $server
277 * @return bool (false to intercept, otherwise true)
278 */
279 public function preServeRequest($served, $result, $request, $server)
280 {
281 if ($result->get_status() === 404) {
282 $route = $request->get_route();
283 $slug = $this->config->get('app.slug');
284
285 if ($this->isRequestOfPlugin($route, $slug)) {
286 if ($this->isRequestForEndpoints($route)) {
287 status_header(200);
288 $result->set_status(200);
289 $result->set_data($this->endpoints);
290 } else {
291 $result->set_data(
292 $this->customizeNotFoundResponse(
293 $result, $request
294 )
295 );
296 }
297 }
298 }
299
300 return $served;
301 }
302
303 /**
304 * Determines whether the request is madse by plugin.
305 *
306 * @param string $route (Rest route|Full URL)
307 * @param string $slug (Plugin's slug)
308 * @return bool
309 */
310 public function isRequestOfPlugin($route = '', $slug = '')
311 {
312 return str_contains(
313 $route ?: $this->request->url(),
314 $slug ?: $this->config->get('app.slug')
315 );
316 }
317
318 /**
319 * Determines if the request is made for endpoints.
320 *
321 * @param string $route (Rest route|Full URL)
322
323 * @return bool
324 */
325 protected function isRequestForEndpoints($route)
326 {
327 return str_ends_with($route, '__endpoints');
328 }
329
330 /**
331 * Prepare a custom not found response.
332 *
333 * @param \WP_Rest_Response $result
334 * @param \WP_Rest_Request $request
335 *
336 * @return array
337 */
338 public function customizeNotFoundResponse($result, $request)
339 {
340 $response = $result->get_data();
341
342 if ($this->env() === 'dev') {
343 $response['data']['wpfluent'] = [
344 'env' => $this->env(),
345 'method' => $request->get_method(),
346 'request_url' => $this->request->url(),
347 'route_params' => $request->get_url_params(),
348 'query_params' => $request->get_query_params(),
349 'body_params' => $request->get_body_params(),
350 ];
351 } else {
352 $response['data']['wpfluent'] = [
353 'env' => $this->env()
354 ];
355 }
356
357 return $response;
358 }
359
360
361 /**
362 * Register the rest api init actions and routes
363 *
364 * @param self $app
365 */
366 protected function addRestApiInitAction($app)
367 {
368 $this->addAction('rest_api_init', function($wpRestServer) use ($app) {
369 try {
370 $this->registerRestRoutes($app->router);
371 } catch (InvalidArgumentException $e) {
372 return $app->response->json([
373 'message' => $e->getMessage()
374 ], $e->getCode() ?: 500);
375 }
376 });
377 }
378
379 /**
380 * Register rest routes.
381 *
382 * @param \FluentBoards\Framework\Http\Router $router
383 *
384 * @return null
385 */
386 protected function registerRestRoutes($router)
387 {
388 $router->registerRoutes(
389 $this->requireRouteFile($router)
390 );
391 }
392
393 /**
394 * Load (include) routes
395 *
396 * @param \FluentBoards\Framework\Http\Router $router
397 * @return null
398 */
399 protected function requireRouteFile($router)
400 {
401 require_once $this['path.http'] . 'Routes/routes.php';
402 }
403 }
404