← All changes
|
vendor/wpfluent/framework/src/WPFluent/Http/Route.php
+89
-8
2.2.0
→
2.5.0
View file →
| @@ -19,8 +19,10 @@ | ||
| 19 | 19 | use FluentBooking\Framework\Http\SubstituteParameters; |
| 20 | 20 | use FluentBooking\Framework\Http\Middleware\RateLimiter; |
| 21 | 21 | use FluentBooking\Framework\Validator\ValidationException; |
| 22 | 22 | use FluentBooking\Framework\Database\Orm\ModelNotFoundException; |
| 23 | +use FluentBooking\Framework\Foundation\Exceptions\HttpException; | |
| 24 | +use FluentBooking\Framework\Foundation\Exceptions\ExceptionHandler; | |
| 23 | 25 | use FluentBooking\Framework\Http\Response\Response as WPFluentResponse; |
| 24 | 26 | |
| 25 | 27 | class Route |
| 26 | 28 | { |
| @@ -203,9 +205,8 @@ | ||
| 203 | 205 | |
| 204 | 206 | /** |
| 205 | 207 | * Map the route to be used in front-end. |
| 206 | 208 | * |
| 207 | - * @param mixed $handler | |
| 208 | 209 | * @return self |
| 209 | 210 | */ |
| 210 | 211 | public function preparefrontendHandlers() |
| 211 | 212 | { |
| @@ -909,16 +910,72 @@ | ||
| 909 | 910 | } catch (ModelNotFoundException $e) { |
| 910 | 911 | return $this->app->response->sendError([ |
| 911 | 912 | 'message' => $e->getMessage() |
| 912 | 913 | ], 404); |
| 914 | + } catch (HttpException $e) { | |
| 915 | + return $this->renderHttpException($e); | |
| 913 | 916 | } catch (Throwable $e) { |
| 914 | - return $this->handleUnknownException( | |
| 915 | - $e, $this->response ? $this->response->get_headers() : [] | |
| 916 | - ); | |
| 917 | + $headers = $this->response ? $this->response->get_headers() : []; | |
| 918 | + | |
| 919 | + // Consult the plugin's ExceptionHandler registry BEFORE the | |
| 920 | + // production sanitizer. A registered renderable may return | |
| 921 | + // either an HttpException (rendered with full status + safe | |
| 922 | + // message) or a WP_REST_Response (returned verbatim). Null / | |
| 923 | + // no-match falls through to handleUnknownException — the | |
| 924 | + // sanitization default is preserved for any exception not | |
| 925 | + // explicitly opted in. | |
| 926 | + if ($mapped = $this->mapToHandlerResponse($e)) { | |
| 927 | + return $mapped; | |
| 928 | + } | |
| 929 | + | |
| 930 | + return $this->handleUnknownException($e, $headers); | |
| 917 | 931 | } |
| 918 | 932 | } |
| 919 | 933 | |
| 920 | 934 | /** |
| 935 | + * Run the bound `ExceptionHandler` over `$e` and convert its result | |
| 936 | + * to a `WP_REST_Response`, or `null` if the handler has nothing for | |
| 937 | + * this exception (in which case the caller falls through to the | |
| 938 | + * sanitizer). | |
| 939 | + * | |
| 940 | + * Returns an `HttpException` result through `renderHttpException()` | |
| 941 | + * so observability + headers + the `{code, message, data}` shape | |
| 942 | + * stay consistent with the dedicated `HttpException` catch arm. | |
| 943 | + * A `WP_REST_Response` is returned verbatim — the renderer claimed | |
| 944 | + * full control over the response shape; we still fire | |
| 945 | + * `fluent_exception` so observability listeners see the original | |
| 946 | + * exception. | |
| 947 | + * | |
| 948 | + * @param \Throwable $e | |
| 949 | + * @return \WP_REST_Response|null | |
| 950 | + */ | |
| 951 | + protected function mapToHandlerResponse(Throwable $e) | |
| 952 | + { | |
| 953 | + if (!$this->app->bound(ExceptionHandler::class)) { | |
| 954 | + return null; | |
| 955 | + } | |
| 956 | + | |
| 957 | + $handler = $this->app->make(ExceptionHandler::class); | |
| 958 | + | |
| 959 | + if (!$handler instanceof ExceptionHandler) { | |
| 960 | + return null; | |
| 961 | + } | |
| 962 | + | |
| 963 | + $result = $handler->render($e, $this->app); | |
| 964 | + | |
| 965 | + if ($result instanceof HttpException) { | |
| 966 | + return $this->renderHttpException($result); | |
| 967 | + } | |
| 968 | + | |
| 969 | + if ($result instanceof WP_REST_Response) { | |
| 970 | + $this->fireExceptionEvent($e); | |
| 971 | + return $result; | |
| 972 | + } | |
| 973 | + | |
| 974 | + return null; | |
| 975 | + } | |
| 976 | + | |
| 977 | + /** | |
| 921 | 978 | * Handle response from route. |
| 922 | 979 | * |
| 923 | 980 | * @param \WP_REST_Response $response |
| 924 | 981 | * @return \WP_REST_Response |
| @@ -983,8 +1040,30 @@ | ||
| 983 | 1040 | ], $e->getCode() ?: 500, $headers); |
| 984 | 1041 | } |
| 985 | 1042 | |
| 986 | 1043 | /** |
| 1044 | + * Render an HttpException to a sanitization-free response. | |
| 1045 | + * | |
| 1046 | + * HttpException is the opt-in contract for "I authored this message, | |
| 1047 | + * it is safe to ship to the client". Bypasses handleUnknownException's | |
| 1048 | + * production sanitization but still fires fluent_exception for | |
| 1049 | + * observability so listeners see every thrown HttpException. | |
| 1050 | + * | |
| 1051 | + * @param HttpException $e | |
| 1052 | + * @return \WP_REST_Response | |
| 1053 | + */ | |
| 1054 | + protected function renderHttpException(HttpException $e) | |
| 1055 | + { | |
| 1056 | + $this->fireExceptionEvent($e); | |
| 1057 | + | |
| 1058 | + return $this->app->response->sendError([ | |
| 1059 | + 'code' => $e->getErrorCode(), | |
| 1060 | + 'message' => $e->getMessage(), | |
| 1061 | + 'data' => $e->getData(), | |
| 1062 | + ], $e->getStatusCode(), $e->getHeaders()); | |
| 1063 | + } | |
| 1064 | + | |
| 1065 | + /** | |
| 987 | 1066 | * Dispatch the route action. |
| 988 | 1067 | * |
| 989 | 1068 | * @return \WP_REST_Response |
| 990 | 1069 | */ |
| @@ -1269,9 +1348,11 @@ | ||
| 1269 | 1348 | * @return array |
| 1270 | 1349 | */ |
| 1271 | 1350 | protected function collectMiddleWare($type = 'before') |
| 1272 | 1351 | { |
| 1273 | - $middleware = $this->app['config']->get('middleware', []); | |
| 1352 | + $middleware = $this->app->bound('http.middleware') | |
| 1353 | + ? $this->app['http.middleware'] | |
| 1354 | + : []; | |
| 1274 | 1355 | |
| 1275 | 1356 | $callableMiddleware = Arr::get($middleware, "global.{$type}", []); |
| 1276 | 1357 | |
| 1277 | 1358 | $routeArray = []; |
| @@ -1300,9 +1381,9 @@ | ||
| 1300 | 1381 | if (isset($handler)) { |
| 1301 | 1382 | $this->addMiddlewareInTheStack($callableMiddleware, $handler); |
| 1302 | 1383 | } else { |
| 1303 | 1384 | if (isset($key)) { |
| 1304 | - $mpath = 'config.middleware.route.' . $type; | |
| 1385 | + $mpath = 'app/Http/middleware.php route.' . $type; | |
| 1305 | 1386 | $msg = "No middleware is assigned for the key: {$key} in {$mpath} array."; |
| 1306 | 1387 | } else { |
| 1307 | 1388 | $msg = "Could't resolve middleware."; |
| 1308 | 1389 | } |
| @@ -1467,10 +1548,10 @@ | ||
| 1467 | 1548 | * @return boolean |
| 1468 | 1549 | */ |
| 1469 | 1550 | protected function isPolicyHandlerParseable($policyHandler) |
| 1470 | 1551 | { |
| 1471 | - return (strpos($policyHandler, '@') === true | |
| 1472 | - || strpos($policyHandler, '::') === true); | |
| 1552 | + return (strpos($policyHandler, '@') !== false | |
| 1553 | + || strpos($policyHandler, '::') !== false); | |
| 1473 | 1554 | } |
| 1474 | 1555 | |
| 1475 | 1556 | /** |
| 1476 | 1557 | * Default/Fallback policy handler for the route |