PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.5.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.5.0
2.5.0 2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 All 34 releases
← All changes | vendor/wpfluent/framework/src/WPFluent/Foundation/ComponentBinder.php +180 -80 1.5.0 → 2.5.0 View file →
@@ -2,20 +2,25 @@
2 2
3 3 namespace FluentBooking\Framework\Foundation;
4 4
5 5 use FluentBooking\Framework\Support\Arr;
6 -use FluentBooking\Framework\Support\Str;
7 6 use FluentBooking\Framework\View\View;
7 +use FluentBooking\Framework\Cache\Cache;
8 8 use FluentBooking\Framework\Http\URL;
9 +use FluentBooking\Framework\Http\UrlGenerator;
10 +use FluentBooking\Framework\Support\Mail;
11 +use FluentBooking\Framework\Support\Pipeline;
9 12 use FluentBooking\Framework\Http\Router;
10 -use FluentBooking\Framework\Support\Facade;
11 -use FluentBooking\Framework\Support\Pipeline;
12 13 use FluentBooking\Framework\Http\Request\Request;
13 14 use FluentBooking\Framework\Http\Response\Response;
14 15 use FluentBooking\Framework\Events\Dispatcher;
16 +use FluentBooking\Framework\Encryption\Encrypter;
15 17 use FluentBooking\Framework\Database\Orm\Model;
16 18 use FluentBooking\Framework\Validator\Validator;
17 19 use FluentBooking\Framework\Foundation\RequestGuard;
20 +use FluentBooking\Framework\Foundation\Exceptions\ExceptionHandler;
21 +use FluentBooking\Framework\Database\DatabaseManager;
22 +use FluentBooking\Framework\Database\DatabaseTransactionsManager;
18 23 use FluentBooking\Framework\Database\ConnectionResolver;
19 24 use FluentBooking\Framework\Database\Query\WPDBConnection;
20 25 use FluentBooking\Framework\Pagination\AbstractCursorPaginator;
21 26 use FluentBooking\Framework\Pagination\AbstractPaginator;
@@ -24,8 +29,10 @@
24 29 use WpOrg\Requests\Exception\Http\Status401;
25 30
26 31 class ComponentBinder
27 32 {
33 + use Concerns\DynamicFacadeTrait;
34 +
28 35 /**
29 36 * The application instance
30 37 * @var \FluentBooking\Framework\Foundation\Application
31 38 */
@@ -35,18 +42,22 @@
35 42 * List of bindings
36 43 * @var array
37 44 */
38 45 protected $bindables = [
46 + 'Cache',
39 47 'Request',
40 48 'Response',
41 49 'Validator',
42 50 'View',
43 51 'Events',
52 + 'Encrypter',
44 53 'DB',
45 54 'URL',
46 55 'Router',
56 + 'Mail',
47 57 'Paginator',
48 58 'Pipeline',
59 + 'ExceptionHandler',
49 60 ];
50 61
51 62 /**
52 63 * Construct the binder
@@ -76,8 +87,19 @@
76 87
77 88 $this->registerResolvingEvent($this->app);
78 89 }
79 90
91 + public function resolveDatabaseTransactionsManager()
92 + {
93 + if (!$this->app->bound('db.transactions')) {
94 + $this->app->singleton('db.transactions', function ($app) {
95 + return new DatabaseTransactionsManager;
96 + });
97 + }
98 +
99 + return $this->app->make('db.transactions');
100 + }
101 +
80 102 /**
81 103 * Register resolving event into the container.
82 104 * @param \FluentBooking\Framework\Foundation\Application $app
83 105 * @return null
@@ -84,94 +106,46 @@
84 106 */
85 107 protected function registerResolvingEvent($app)
86 108 {
87 109 $app->resolving(RequestGuard::class, function($request) use ($app) {
110 +
111 + $request->setRequestInstance($app->request);
88 112
89 113 if (method_exists($request, 'authorize')) {
90 114 if(!$request->authorize()) throw new Status401;
91 115 }
92 116
93 - $request->merge($request->beforeValidation());
117 + $request->merge((array) $request->beforeValidation());
94 118 $request->validate();
95 119 $request->merge((array) $request->afterValidation(
96 - $app->make('validator')
120 + $request->getValidator()
97 121 ));
98 122 });
99 123 }
100 124
101 125 /**
102 - * Register the dynamic facade resolver.
103 - * @param \FluentBooking\Framework\Foundation\Application $app
126 + * Bind the cache instance into the container.
104 127 * @return null
105 128 */
106 - protected function registerFacadeResolver($app)
129 + protected function bindCache()
107 130 {
108 - Facade::setFacadeApplication($app);
109 -
110 - spl_autoload_register(function($class) use ($app) {
111 -
112 - $ns = substr(($fqn = __NAMESPACE__), 0, strpos($fqn, '\\'));
113 -
114 - if (Str::contains($class, ($facade = $ns.'\Facade'))) {
115 -
116 - $this->createFacadeFor($facade, $class, $app);
117 - }
131 + $this->app->singleton(Cache::class, function ($app) {
132 + return Cache::init();
118 133 });
119 - }
120 134
121 - /**
122 - * Create a facade resolver class dynamically
123 - * @param string $facade
124 - * @param string $class
125 - * @param \FluentBooking\Framework\Foundation\Application $app
126 - * @return null
127 - */
128 - protected function createFacadeFor($facade, $class, $app)
129 - {
130 - $facadeAccessor = $this->resolveFacadeAccessor($facade, $class, $app);
131 -
132 - $anonymousClass = new class($facadeAccessor) extends Facade {
133 -
134 - protected static $facadeAccessor;
135 -
136 - public function __construct($facadeAccessor) {
137 - static::$facadeAccessor = $facadeAccessor;
138 - }
139 -
140 - protected static function getFacadeAccessor() {
141 - return static::$facadeAccessor;
142 - }
143 - };
144 -
145 - class_alias(get_class($anonymousClass), $class, true);
135 + $this->app->alias(Cache::class, 'cache');
146 136 }
147 137
148 138 /**
149 - * Resolve the binding name.
150 - * @param string $facade
151 - * @param string $class
152 - * @param \FluentBooking\Framework\Foundation\Application $app
153 - * @return string
154 - */
155 - protected function resolveFacadeAccessor($facade, $class,$app)
156 - {
157 - $name = strtolower(trim(str_replace($facade, '', $class), '\\'));
158 -
159 - if ($name == 'route') $name = 'router';
160 -
161 - if ($app->bound($name)) {
162 - return $name;
163 - }
164 - }
165 -
166 - /**
167 139 * Bind the request instance into the container.
168 140 * @return null
169 141 */
170 142 protected function bindRequest()
171 143 {
172 - $this->app->singleton(Request::class, function ($app) {
173 - return new Request($app, $_GET, $_POST, $_FILES);
144 + $method = $this->getBindingMethod('singleton');
145 +
146 + $this->app->$method(Request::class, function ($app) {
147 + return $this->resolveRequest($app);
174 148 });
175 149
176 150 $this->app->alias(Request::class, 'request');
177 151
@@ -183,9 +157,11 @@
183 157 * @return null
184 158 */
185 159 protected function bindResponse()
186 160 {
187 - $this->app->singleton(Response::class, function($app) {
161 + $method = $this->getBindingMethod('singleton');
162 +
163 + $this->app->$method(Response::class, function($app) {
188 164 return new Response($app);
189 165 });
190 166
191 167 $this->app->alias(Response::class, 'response');
@@ -193,8 +169,23 @@
193 169 $this->addBackwardCompatibleAlias(Response::class);
194 170 }
195 171
196 172 /**
173 + * Get the binding method to bind a component.
174 + * In the testing environment, we use bind
175 + * method instead of singleton method.
176 + *
177 + * @param string $original
178 + * @return string
179 + */
180 + protected function getBindingMethod($original)
181 + {
182 + return str_starts_with(
183 + $this->app->env(), 'testing'
184 + ) ? 'bind' : $original;
185 + }
186 +
187 + /**
197 188 * Bind the request validator into the container.
198 189 * @return null
199 190 */
200 191 protected function bindValidator()
@@ -225,9 +216,11 @@
225 216 */
226 217 protected function bindEvents()
227 218 {
228 219 $this->app->singleton(Dispatcher::class, function($app) {
229 - return new Dispatcher($app);
220 + return (new Dispatcher($app))->setTransactionManagerResolver(
221 + fn () => $this->resolveDatabaseTransactionsManager()
222 + );
230 223 });
231 224
232 225 $this->app->alias(Dispatcher::class, 'events');
233 226 }
@@ -232,33 +225,60 @@
232 225 $this->app->alias(Dispatcher::class, 'events');
233 226 }
234 227
235 228 /**
229 + * Bind the encrypter instance into the container.
230 + * @return null
231 + */
232 + protected function bindEncrypter()
233 + {
234 + $this->app->singleton(Encrypter::class, function($app) {
235 + return new Encrypter($app->config->get('app.key'));
236 + });
237 +
238 + $this->app->alias(Encrypter::class, 'encrypter');
239 + $this->app->alias(Encrypter::class, 'crypt');
240 + }
241 +
242 + /**
236 243 * Bind the db (query builder) instance into the container.
237 244 * @return null
238 245 */
239 246 protected function bindDB()
240 247 {
241 - $this->app->singleton('db', function($app) {
242 - return new WPDBConnection(
243 - $GLOBALS['wpdb'], $app->config->get('database')
244 - );
245 - });
248 + $connection = new WPDBConnection($GLOBALS['wpdb']);
246 249
250 + $resolver = new ConnectionResolver([
251 + 'mysql' => $connection,
252 + 'sqlite' => $connection,
253 + ]);
254 +
255 + $resolver->setDefaultConnection('mysql');
256 +
257 + $resolver->connection()->setTransactionManager(
258 + $this->resolveDatabaseTransactionsManager()
259 + );
260 +
261 + Model::setConnectionResolver($resolver);
262 +
247 263 Model::setEventDispatcher($this->app['events']);
248 -
249 - Model::setConnectionResolver(new ConnectionResolver);
264 +
265 + $this->app->singletonIf('db', function($app) use ($resolver) {
266 + return new DatabaseManager($resolver);
267 + });
250 268 }
251 269
252 270 /**
253 - * Bind the URL instance into the container.
271 + * Bind the Url instance into the container.
254 272 * @return null
255 273 */
256 - protected function bindURL()
274 + protected function bindUrl()
257 275 {
258 - $this->app->bind('url', function($app) {
259 - return new URL;
276 + $this->app->bind(URL::class, function($app) {
277 + return new URL('', new UrlGenerator($app));
260 278 });
279 +
280 + $this->app->alias(URL::class, 'url');
261 281 }
262 282
263 283 /**
264 284 * Bind the router instance into the container.
@@ -265,14 +285,29 @@
265 285 * @return null
266 286 */
267 287 protected function bindRouter()
268 288 {
269 - $this->app->singleton('router', function($app) {
289 + $this->app->singleton(Router::class, function($app) {
270 290 return new Router($app);
271 291 });
292 +
293 + $this->app->alias(Router::class, 'router');
272 294 }
273 295
274 296 /**
297 + * Bind the mail instance into the container.
298 + * @return null
299 + */
300 + protected function bindMail()
301 + {
302 + $this->app->bind(Mail::class, function($app) {
303 + return new Mail();
304 + });
305 +
306 + $this->app->alias(Mail::class, 'mail');
307 + }
308 +
309 + /**
275 310 * Bind the paginator instance into the container.
276 311 * @return null
277 312 */
278 313 protected function bindPaginator()
@@ -309,12 +344,31 @@
309 344 $this->app->bind(Pipeline::class, function ($app) {
310 345 return new Pipeline($app);
311 346 });
312 347
313 - $this->app->alias(Pipeline::class, 'pipeline');
348 + $this->app->alias(Pipeline::class, 'pipeline');
314 349 }
315 350
316 351 /**
352 + * Bind the exception-handler registry into the container.
353 + *
354 + * Default is the bare `Foundation\Exceptions\ExceptionHandler` (no
355 + * renderables registered). Plugins override by re-binding their own
356 + * subclass to the same key from `boot/bindings.php` BEFORE the first
357 + * request hits Route.
358 + *
359 + * @return null
360 + */
361 + protected function bindExceptionHandler()
362 + {
363 + $this->app->singleton(ExceptionHandler::class, function ($app) {
364 + return new ExceptionHandler();
365 + });
366 +
367 + $this->app->alias(ExceptionHandler::class, 'exception.handler');
368 + }
369 +
370 + /**
317 371 * Load other bindings the developers might
318 372 * have added in the application level.
319 373 *
320 374 * @param \FluentBooking\Framework\Foundation\Application $app
@@ -343,9 +397,9 @@
343 397 }
344 398 }
345 399
346 400 /**
347 - * Adds new alias to maintain ther backward compatibility.
401 + * Adds new alias to maintain the backward compatibility.
348 402 *
349 403 * @param string $class
350 404 * @return void
351 405 */
@@ -374,6 +428,52 @@
374 428 unset($pieces[$index]);
375 429 }
376 430
377 431 return implode('\\', $pieces);
432 + }
433 +
434 + /**
435 + * Resolve the appropriate request instance.
436 + *
437 + * @param $app
438 + * @return Request|object (Anonymous Class)
439 + */
440 + protected function resolveRequest($app)
441 + {
442 + return new Request($app, $_GET, $_POST);
443 + }
444 +
445 + /**
446 + * Check if the request is of the plugin.
447 + *
448 + * @return boolean
449 + */
450 + protected function isRequestOfPlugin()
451 + {
452 + if (str_starts_with($this->app->env(), 'testing')) {
453 + return true;
454 + }
455 +
456 + $slug = $this->app->config->get('app.slug');
457 +
458 + if (get_option('permalink_structure')) {
459 + $route = $_SERVER['REQUEST_URI'] ?? '';
460 + } else {
461 + $route = $_GET['rest_route'] ?? '';
462 + }
463 +
464 + $parsedUrl = parse_url($route);
465 +
466 + $path = $parsedUrl['path'] ?? '';
467 +
468 + $path = str_replace('/wp-json', '', $path);
469 +
470 + if (is_admin()) {
471 + $page = $_GET['page'] ?? '';
472 + if ($slug === $page) {
473 + $path = $page;
474 + }
475 + }
476 +
477 + return str_starts_with(ltrim($path, '/'), $slug);
378 478 }
379 479 }