Skip to content

Commit 9d23b82

Browse files
Internal: Add default error page for undefined URL in multi-URL - refs #6297
Author: @christianbeeznest
1 parent 6cda8c0 commit 9d23b82

File tree

7 files changed

+165
-3
lines changed

7 files changed

+165
-3
lines changed

src/CoreBundle/Controller/ExceptionController.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66

77
namespace Chamilo\CoreBundle\Controller;
88

9+
use Chamilo\CoreBundle\Helpers\AccessUrlHelper;
910
use Exception;
1011
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1112
use Symfony\Component\ErrorHandler\Exception\FlattenException;
1213
use Symfony\Component\HttpFoundation\Request;
1314
use Symfony\Component\HttpFoundation\Response;
1415
use Symfony\Component\HttpKernel\Exception\HttpException;
1516
use Symfony\Component\Routing\Attribute\Route;
17+
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
1618

1719
class ExceptionController extends AbstractController
1820
{
@@ -91,4 +93,33 @@ public function error(Request $request): Response
9193
'exception' => $exception,
9294
]);
9395
}
96+
97+
#[Route(path: '/error/undefined-url', name: 'undefined_url_error')]
98+
public function undefinedUrlError(
99+
Request $request,
100+
UrlGeneratorInterface $urlGenerator,
101+
AccessUrlHelper $accessUrlHelper
102+
): Response {
103+
$host = $request->getHost();
104+
105+
$accessUrl = $accessUrlHelper->getFirstAccessUrl();
106+
$themeHost = rtrim($accessUrl?->getUrl() ?? '', '/');
107+
$themeName = 'chamilo';
108+
109+
$cssUrl = $themeHost . $urlGenerator->generate('theme_asset', [
110+
'name' => $themeName,
111+
'path' => 'colors.css',
112+
], UrlGeneratorInterface::ABSOLUTE_PATH);
113+
114+
$logoUrl = $themeHost . $urlGenerator->generate('theme_asset', [
115+
'name' => $themeName,
116+
'path' => 'images/header-logo.svg',
117+
], UrlGeneratorInterface::ABSOLUTE_PATH);
118+
119+
return $this->render('@ChamiloCore/Exception/undefined_url.html.twig', [
120+
'host' => $host,
121+
'cssUrl' => $cssUrl,
122+
'logoUrl' => $logoUrl,
123+
]);
124+
}
94125
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/* For licensing terms, see /license.txt */
6+
7+
namespace Chamilo\CoreBundle\EventListener;
8+
9+
use Chamilo\CoreBundle\Helpers\AccessUrlHelper;
10+
use Symfony\Component\HttpFoundation\RedirectResponse;
11+
use Symfony\Component\HttpKernel\Event\RequestEvent;
12+
use Symfony\Component\Routing\RouterInterface;
13+
14+
/**
15+
* This event listener checks whether the current request is using a valid, registered AccessUrl.
16+
* If not, it redirects to a custom error page (/error/undefined-url).
17+
*/
18+
class AccessUrlValidationListener
19+
{
20+
public function __construct(
21+
private readonly AccessUrlHelper $accessUrlHelper,
22+
private readonly RouterInterface $router
23+
) {}
24+
25+
public function onKernelRequest(RequestEvent $event): void
26+
{
27+
// Only handle the main request, not subrequests.
28+
if (!$event->isMainRequest()) {
29+
return;
30+
}
31+
32+
$request = $event->getRequest();
33+
$path = $request->getPathInfo();
34+
35+
// Prevent infinite redirection loop to the same error page
36+
if (str_starts_with($path, '/error/undefined-url')) {
37+
return;
38+
}
39+
40+
// Skip validation for static assets and special files
41+
$excludedPrefixes = [
42+
'/build/', // Webpack build assets
43+
'/theme/', // Legacy theme assets
44+
'/favicon.ico', // Favicon
45+
'/robots.txt', // Robots file
46+
'/apple-touch-icon.png', // Mobile shortcut icon
47+
];
48+
49+
foreach ($excludedPrefixes as $prefix) {
50+
if (str_starts_with($path, $prefix)) {
51+
return;
52+
}
53+
}
54+
55+
// Skip validation if multi-URL is not enabled
56+
if (!$this->accessUrlHelper->isMultiple()) {
57+
return;
58+
}
59+
60+
try {
61+
// Try to get the current AccessUrl from the request
62+
$accessUrl = $this->accessUrlHelper->getCurrent();
63+
64+
// If it's null, throw an exception to trigger redirection
65+
if (null === $accessUrl) {
66+
throw new \RuntimeException('AccessUrl not defined');
67+
}
68+
} catch (\Throwable $e) {
69+
// Log host and URI for debugging
70+
$host = $request->getHost();
71+
$uri = $request->getUri();
72+
73+
// Redirect to custom error page
74+
$url = $this->router->generate('undefined_url_error');
75+
$event->setResponse(new RedirectResponse($url));
76+
}
77+
}
78+
}

src/CoreBundle/Helpers/AuthenticationConfigHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function getAuthSources(?AccessUrl $url)
7171
? $this->parameterBag->get('authentication')
7272
: [];
7373

74-
if (isset($authentication[$urlId->getId()])) {
74+
if ($urlId && isset($authentication[$urlId->getId()])) {
7575
return $authentication[$urlId->getId()];
7676
}
7777

src/CoreBundle/Helpers/SettingsManagerHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public function getOverride(string $name, ?AccessUrl $accessUrl = null): mixed
3131

3232
$accessUrl ??= $this->accessUrlHelper->getCurrent();
3333

34-
if (isset($settingsOverrides[$accessUrl->getId()][$name])) {
34+
if ($accessUrl && isset($settingsOverrides[$accessUrl->getId()][$name])) {
3535
return $settingsOverrides[$accessUrl->getId()][$name];
3636
}
3737

src/CoreBundle/Helpers/ThemeHelper.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Chamilo\CoreBundle\Helpers;
88

9+
use Chamilo\CoreBundle\Entity\AccessUrl;
910
use Chamilo\CoreBundle\Settings\SettingsManager;
1011
use Chamilo\CourseBundle\Settings\SettingsCourseManager;
1112
use League\Flysystem\FilesystemException;
@@ -46,9 +47,12 @@ public function getVisualTheme(): string
4647
return $visualTheme;
4748
}
4849

50+
$visualTheme = null;
4951
$accessUrl = $this->accessUrlHelper->getCurrent();
5052

51-
$visualTheme = $accessUrl->getActiveColorTheme()?->getColorTheme()->getSlug();
53+
if ($accessUrl instanceof AccessUrl) {
54+
$visualTheme = $accessUrl->getActiveColorTheme()?->getColorTheme()->getSlug();
55+
}
5256

5357
if ('true' == $this->settingsManager->getSetting('profile.user_selected_theme')) {
5458
$visualTheme = $this->userHelper->getCurrent()?->getTheme();

src/CoreBundle/Resources/config/services.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,10 @@ services:
146146
arguments:
147147
$registry: '@doctrine'
148148
$em: '@doctrine.orm.entity_manager'
149+
150+
Chamilo\CoreBundle\EventListener\AccessUrlValidationListener:
151+
arguments:
152+
$accessUrlHelper: '@Chamilo\CoreBundle\Helpers\AccessUrlHelper'
153+
$router: '@router'
154+
tags:
155+
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 255 }
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{% extends '@ChamiloCore/Layout/layout_one_col.html.twig' %}
2+
3+
{% block chamilo_head %}
4+
{{ parent() }}
5+
<link rel="stylesheet" href="{{ cssUrl }}">
6+
{% endblock %}
7+
8+
{% block content %}
9+
<div class="text-center my-10">
10+
{% if logoUrl %}
11+
<img
12+
src="{{ logoUrl }}"
13+
alt="Logo"
14+
class="mx-auto h-20 mb-6"
15+
/>
16+
{% endif %}
17+
18+
<div style="background-color: rgb(var(--color-danger-base)); color: rgb(var(--color-danger-button-text));"
19+
class="mx-auto p-6 rounded-lg shadow-md md:w-3/4 lg:w-1/2">
20+
<p style="font-size: 1.5rem; font-weight: bold;" class="mb-4">
21+
{{ 'Oops! URL not registered.'|trans }}
22+
</p>
23+
24+
<p style="font-size: 1.2rem;" class="mb-4">
25+
{{ 'The address "%host%" is not configured in this portal instance.'|trans({'%host%': host}) }}
26+
</p>
27+
28+
<p style="font-size: 1rem;" class="mb-6">
29+
{{ 'If the problem persists, please contact support.'|trans }}
30+
</p>
31+
32+
<a href="/"
33+
class="inline-block px-6 py-2 rounded"
34+
style="
35+
background-color: rgb(var(--color-primary-base));
36+
color: rgb(var(--color-primary-button-alternative-text));
37+
">
38+
{{ 'Go to home page'|trans }}
39+
</a>
40+
</div>
41+
</div>
42+
{% endblock %}

0 commit comments

Comments
 (0)