From a7ed16c72f5dfd395fcbe5a00971da6637f7718f Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Tue, 1 Sep 2020 18:42:29 +0300 Subject: [PATCH] controller ob_clean and some cs fix --- application/Espo/Core/Api/RouteProcessor.php | 7 ++- .../Espo/Core/ApplicationRunners/Api.php | 8 ++- application/Espo/Core/ControllerManager.php | 61 +++++++++++++------ 3 files changed, 55 insertions(+), 21 deletions(-) diff --git a/application/Espo/Core/Api/RouteProcessor.php b/application/Espo/Core/Api/RouteProcessor.php index 1d24601364..e9f66f9046 100644 --- a/application/Espo/Core/Api/RouteProcessor.php +++ b/application/Espo/Core/Api/RouteProcessor.php @@ -37,6 +37,8 @@ use Espo\Core\{ ControllerManager, }; +use StdClass; + /** * Processes routes. Obtains a controller name, action, body from a request. Then passes them to controller manager. */ @@ -92,8 +94,11 @@ class RouteProcessor if (!$actionName) { $httpMethod = strtolower($requestMethod); + $crudList = $this->config->get('crud') ?? []; + $actionName = $crudList[$httpMethod] ?? null; + if (!$actionName) { throw new Error("No action for method {$httpMethod}."); } @@ -119,7 +124,7 @@ class RouteProcessor is_float($result) || is_array($result) || is_bool($result) || - $result instanceof \StdClass + $result instanceof StdClass ) { $responseContents = Json::encode($result); } diff --git a/application/Espo/Core/ApplicationRunners/Api.php b/application/Espo/Core/ApplicationRunners/Api.php index 676bfa1029..06cbab7488 100644 --- a/application/Espo/Core/ApplicationRunners/Api.php +++ b/application/Espo/Core/ApplicationRunners/Api.php @@ -135,8 +135,14 @@ class Api implements ApplicationRunner } $routeProcessor = $this->injectableFactory->create(RouteProcessor::class); + + ob_start(); + $routeProcessor->process($item['route'], $item['params'], $requestWrapped, $responseWrapped, $args); - } catch (Exception $exception) { + + ob_clean(); + } + catch (Exception $exception) { (new ApiErrorOutput($requestWrapped))->process( $responseWrapped, $exception, false, $item, $args ); diff --git a/application/Espo/Core/ControllerManager.php b/application/Espo/Core/ControllerManager.php index d01ff8fe74..68cc8f5f20 100644 --- a/application/Espo/Core/ControllerManager.php +++ b/application/Espo/Core/ControllerManager.php @@ -29,17 +29,19 @@ namespace Espo\Core; -use Espo\Core\Exceptions\NotFound; -use Espo\Core\Exceptions\BadRequest; - use Espo\Core\{ InjectableFactory, Utils\ClassFinder, Utils\Util, Api\Request, Api\Response, + Exceptions\NotFound, + Exceptions\BadRequest, }; +use ReflectionClass; +use StdClass; + /** * Creates controller instances and processes actions. */ @@ -89,26 +91,12 @@ class ControllerManager ); } + $this->processContentTypeCheck($controller, $primaryActionMethodName, 1); + if (method_exists($controller, $beforeMethodName)) { $controller->$beforeMethodName($params, $data, $request, $response); } - $class = new \ReflectionClass($controller); - $method = $class->getMethod($primaryActionMethodName); - $args = $method->getParameters(); - if (count($args) >= 2) { - if ($args[1]->hasType()) { - $dataClass = $args[1]->getClass(); - if ($dataClass && strtolower($dataClass->getName()) === 'stdclass') { - if (!$data instanceof \StdClass) { - throw new BadRequest( - "{$controllerName} {$requestMethod} {$actionName}: Content-Type should be 'application/json'." - ); - } - } - } - } - $result = $controller->$primaryActionMethodName($params, $data, $request, $response); if (method_exists($controller, $afterMethodName)) { @@ -118,6 +106,41 @@ class ControllerManager return $result; } + protected function processContentTypeCheck(object $controller, string $primaryActionMethodName, int $parameterIndex) + { + $class = new ReflectionClass($controller); + + $method = $class->getMethod($primaryActionMethodName); + + $args = $method->getParameters(); + + if (count($args) <= $parameterIndex) { + return; + } + + $param = $args[$parameterIndex]; + + if (! $param->hasType()) { + return; + } + + $dataClass = $param->getClass(); + + if (!$dataClass) { + return; + } + + if (strtolower($dataClass->getName()) !== strtolower(StdClass::class)) { + return; + } + + if (! $data instanceof StdClass) { + throw new BadRequest( + "{$controllerName} {$requestMethod} {$actionName}: Content-Type should be 'application/json'." + ); + } + } + protected function getControllerClassName(string $name) : string { $className = $this->classFinder->find('Controllers', $name);