'Bad Request', 401 => 'Unauthorized', 403 => 'Forbidden', 404 => 'Page Not Found', 409 => 'Conflict', 500 => 'Internal Server Error', ]; protected $allowedStatusCodeList = [ 200, 201, 400, 401, 403, 404, 409, 500 ]; protected $ignorePrintXStatusReasonExceptionClassNameList = [ 'PDOException' ]; public function __construct(\Espo\Core\Utils\Api\Slim $slim) { $this->slim = $slim; } protected function getSlim() { return $this->slim; } public function render($data = null) { if (is_array($data)) { $dataArr = array_values($data); $data = empty($dataArr[0]) ? false : $dataArr[0]; } ob_clean(); echo $data; } public function processError(string $message = 'Error', $statusCode = 500, bool $toPrint = false, $exception = null) { $currentRoute = $this->getSlim()->router()->getCurrentRoute(); if (isset($currentRoute)) { $inputData = $this->getSlim()->request()->getBody(); $inputData = $this->clearPasswords($inputData); $routePattern = $currentRoute->getPattern(); $routeParams = $currentRoute->getParams(); $method = $this->getSlim()->request()->getMethod(); $logMessage = "API ($statusCode) "; $logMessageItemList = []; if ($message) $logMessageItemList[] = $message; $logMessageItemList[] .= "$method " . $_SERVER['REQUEST_URI']; if ($inputData) $logMessageItemList[] = "Input data: " . $inputData; if ($routePattern) $logMessageItemList[] = "Route pattern: ". $routePattern; if (!empty($routeParams)) $logMessageItemList[] = "Route params: ". print_r($routeParams, true); $logMessage .= implode("; ", $logMessageItemList); $GLOBALS['log']->log('debug', $logMessage); } $this->displayError($message, $statusCode, $toPrint, $exception); } public function displayError(string $text, $statusCode = 500, bool $toPrint = false, $exception = null) { $logLevel = 'error'; $messageLineFile = null; if ($exception) { $messageLineFile = 'line: ' . $exception->getLine() . ', file: ' . $exception->getFile(); } if ($exception && !empty($exception->logLevel)) { $logLevel = $exception->logLevel; } $logMessageItemList = []; if ($text) $logMessageItemList[] = "{$text}"; if (!empty($this->slim)) { $logMessageItemList[] = $this->getSlim()->request()->getMethod() . ' ' .$_SERVER['REQUEST_URI']; } if ($messageLineFile) { $logMessageItemList[] = $messageLineFile; } $logMessage = "($statusCode) " . implode("; ", $logMessageItemList); $GLOBALS['log']->log($logLevel, $logMessage); ob_clean(); if (!empty($this->slim)) { $toPrintXStatusReason = true; if ($exception && in_array(get_class($exception), $this->ignorePrintXStatusReasonExceptionClassNameList)) { $toPrintXStatusReason = false; } if (!in_array($statusCode, $this->allowedStatusCodeList)) { $statusCode = 500; } $this->getSlim()->response()->setStatus($statusCode); if ($toPrintXStatusReason) { $this->getSlim()->response()->headers->set('X-Status-Reason', $text); } if ($toPrint) { $status = $this->getCodeDescription($statusCode); $status = isset($status) ? $statusCode.' '.$status : 'HTTP '.$statusCode; if ($text) $text = htmlspecialchars($text); $this->getSlim()->printError($text, $status); } $this->getSlim()->stop(); } else { $GLOBALS['log']->info('Could not get Slim instance. It looks like a direct call (bypass API). URL: '.$_SERVER['REQUEST_URI']); die($text); } } protected function getCodeDescription($statusCode) { if (isset($this->errorDescriptions[$statusCode])) { return $this->errorDescriptions[$statusCode]; } return null; } protected function clearPasswords($inputData) { return preg_replace('/"(.*?password.*?)":".*?"/i', '"$1":"*****"', $inputData); } }