Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.10% covered (success)
93.10%
27 / 29
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ErrorController
93.10% covered (success)
93.10%
27 / 29
66.67% covered (warning)
66.67%
2 / 3
4.01
0.00% covered (danger)
0.00%
0 / 1
 renderBootstrapError
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 internalServerError
84.62% covered (success)
84.62%
11 / 13
0.00% covered (danger)
0.00%
0 / 1
2.01
 renderMinimalError
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * Error Controller (500)
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public License,
7 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
8 * obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * @package   phpMyFAQ
11 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
12 * @copyright 2026 phpMyFAQ Team
13 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
14 * @link      https://www.phpmyfaq.de
15 * @since     2026-01-03
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Controller\Frontend;
21
22use Exception;
23use phpMyFAQ\Translation;
24use Symfony\Component\HttpFoundation\Request;
25use Symfony\Component\HttpFoundation\Response;
26use Twig\Environment;
27use Twig\Loader\FilesystemLoader;
28
29final class ErrorController extends AbstractFrontController
30{
31    /**
32     * Static fallback method for early bootstrap errors
33     * Used when the system is not fully initialized yet
34     *
35     * @param string|null $errorMessage Optional error message to display
36     * @throws Exception
37     */
38    public static function renderBootstrapError(?string $errorMessage = null): Response
39    {
40        $filesystemLoader = new FilesystemLoader((string) PMF_ROOT_DIR . '/assets/templates/error');
41        $twigEnvironment = new Environment($filesystemLoader);
42        $html = $twigEnvironment->render('500.twig', [
43            'errorMessage' => $errorMessage,
44        ]);
45
46        $response = new Response(content: $html, status: Response::HTTP_INTERNAL_SERVER_ERROR);
47        $response->headers->set('Content-Type', 'text/html; charset=utf-8');
48
49        return $response;
50    }
51
52    /**
53     * Renders a 500 Internal Server Error page
54     *
55     * @param string|null $errorMessage Optional error message to display (shown only in debug mode)
56     * @throws Exception
57     */
58    public function internalServerError(Request $request, ?string $errorMessage = null): Response
59    {
60        try {
61            $response = $this->render('500.twig', [
62                ...$this->getHeader($request),
63                'title' => sprintf(
64                    '%s - %s',
65                    Translation::getString(key: 'msgError500'),
66                    $this->configuration->getTitle(),
67                ),
68                'errorMessage' => $errorMessage,
69            ]);
70        } catch (Exception) {
71            $response = $this->renderMinimalError($errorMessage);
72        }
73
74        $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
75
76        return $response;
77    }
78
79    /**
80     * Renders a minimal standalone error page without dependencies
81     *
82     * @param string|null $errorMessage Optional error message to display
83     * @throws Exception
84     */
85    private function renderMinimalError(?string $errorMessage = null): Response
86    {
87        $filesystemLoader = new FilesystemLoader((string) PMF_ROOT_DIR . '/assets/templates/error');
88        $twigEnvironment = new Environment($filesystemLoader);
89        $html = $twigEnvironment->render('500.twig', [
90            'errorMessage' => $errorMessage,
91        ]);
92
93        $response = new Response(content: $html, status: Response::HTTP_INTERNAL_SERVER_ERROR);
94        $response->headers->set('Content-Type', 'text/html; charset=utf-8');
95
96        return $response;
97    }
98}