Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
82.35% covered (warning)
82.35%
28 / 34
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
BaseController
82.35% covered (warning)
82.35%
28 / 34
25.00% covered (danger)
25.00%
1 / 4
12.79
0.00% covered (danger)
0.00%
0 / 1
 __invoke
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
3
 getExceptionContext
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 readResponse
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 createJsonResponse
76.92% covered (warning)
76.92%
10 / 13
0.00% covered (danger)
0.00%
0 / 1
7.60
1<?php
2
3declare(strict_types=1);
4
5namespace BO\Zmscitizenapi;
6
7use BO\Zmscitizenapi\Services\Core\ExceptionService;
8use BO\Zmscitizenapi\Services\Core\ValidationService;
9use BO\Zmscitizenapi\Services\Core\ZmsApiFacadeService;
10use Psr\Http\Message\RequestInterface;
11use Psr\Http\Message\ResponseInterface;
12use BO\Zmscitizenapi\Localization\ErrorMessages;
13
14abstract class BaseController extends \BO\Slim\Controller
15{
16    protected ?string $language = null;
17    public function __invoke(RequestInterface $request, ResponseInterface $response, array $args): ResponseInterface
18    {
19        try {
20            $request = $this->initRequest($request);
21            $this->language = $request->getAttribute('language');
22            ValidationService::setLanguageContext($this->language);
23            ExceptionService::setLanguageContext($this->language);
24            ZmsApiFacadeService::setLanguageContext($this->language);
25            $noCacheResponse = \BO\Slim\Render::withLastModified($response, time(), '0');
26            return $this->readResponse($request, $noCacheResponse, $args);
27        } catch (\RuntimeException $e) {
28        // Extract error details from the exception message
29            [$errorCode, $errorMessage] = explode(': ', $e->getMessage(), 2);
30            return $this->createJsonResponse($response, [
31                'errors' => [
32                    [
33                        'errorCode' => $errorCode,
34                        'errorMessage' => $errorMessage,
35                        'statusCode' => $e->getCode()
36                    ]
37                ]
38            ], $e->getCode() ?: 500);
39        }
40    }
41
42    protected function getExceptionContext(): string
43    {
44        $className = (new \ReflectionClass($this))->getShortName();
45        return str_replace('Controller', '', $className);
46    }
47
48    /**
49     * Hook method for handling responses in child controllers.
50     * Child classes should override this method to implement their specific response logic.
51     *
52     * @param RequestInterface $request The HTTP request
53     * @param ResponseInterface $response The HTTP response
54     * @param array $args Route parameters
55     * @return ResponseInterface The modified response
56     */
57    public function readResponse(RequestInterface $request, ResponseInterface $response, array $args): ResponseInterface
58    {
59        return parent::__invoke($request, $response, $args);
60    }
61
62    protected function createJsonResponse(ResponseInterface $response, array $content, int $statusCode): ResponseInterface
63    {
64        if ($statusCode < 100 || $statusCode > 599) {
65            throw new \InvalidArgumentException('Invalid HTTP status code');
66        }
67
68        $response = $response->withStatus($statusCode)
69            ->withHeader('Content-Type', 'application/json; charset=utf-8');
70        if (isset($content['errors'])) {
71            foreach ($content['errors'] as &$error) {
72                if (isset($error['errorCode'])) {
73                    $error = ErrorMessages::get($error['errorCode'], $this->language);
74                }
75            }
76        }
77
78        try {
79            $json = json_encode($content, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
80        } catch (\JsonException $e) {
81            throw new \RuntimeException('Failed to encode JSON response: ' . $e->getMessage(), 0, $e);
82        }
83
84        $response->getBody()->write($json);
85        return $response;
86    }
87}