Skip to content

Commit 0453a49

Browse files
Settings: fix MultiURL locked overrides + reset access_url_locked
1 parent de20ccc commit 0453a49

File tree

6 files changed

+881
-274
lines changed

6 files changed

+881
-274
lines changed

public/main/inc/lib/urlmanager.lib.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Chamilo\CoreBundle\Entity\AccessUrlRelSession;
88
use Chamilo\CoreBundle\Entity\AccessUrlRelUser;
99
use Chamilo\CoreBundle\Entity\AccessUrlRelUserGroup;
10+
use Chamilo\CoreBundle\Entity\SettingsCurrent;
1011
use Chamilo\CoreBundle\Entity\UserAuthSource;
1112
use Chamilo\CoreBundle\Framework\Container;
1213
use Doctrine\ORM\NonUniqueResultException;
@@ -98,12 +99,13 @@ public static function delete($id)
9899

99100
/*
100101
* $tableCourseCategory = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
101-
$sql = "DELETE FROM $tableCourseCategory WHERE access_url_id = ".$id;
102-
Database::query($sql);
103-
*/
102+
* $sql = "DELETE FROM $tableCourseCategory WHERE access_url_id = ".$id;
103+
* Database::query($sql);
104+
*/
104105
$em = Container::getEntityManager();
105106

106107
$relEntities = [
108+
SettingsCurrent::class,
107109
AccessUrlRelCourse::class,
108110
AccessUrlRelSession::class,
109111
AccessUrlRelUserGroup::class,

src/CoreBundle/Controller/Admin/SettingsController.php

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace Chamilo\CoreBundle\Controller\Admin;
88

99
use Chamilo\CoreBundle\Controller\BaseController;
10+
use Chamilo\CoreBundle\Entity\AccessUrl;
1011
use Chamilo\CoreBundle\Entity\SearchEngineField;
1112
use Chamilo\CoreBundle\Entity\SettingsCurrent;
1213
use Chamilo\CoreBundle\Entity\SettingsValueTemplate;
@@ -62,9 +63,14 @@ public function toggleChangeable(Request $request, AccessUrlHelper $accessUrlHel
6263
}
6364

6465
$currentUrl = $accessUrlHelper->getCurrent();
65-
$currentUrlId = $currentUrl->getId();
66+
if (!$currentUrl) {
67+
return $this->json([
68+
'error' => 'Access URL not resolved.',
69+
], 500);
70+
}
71+
72+
$currentUrlId = (int) $currentUrl->getId();
6673

67-
// Only main URL (ID = 1) can toggle the flag.
6874
if (1 !== $currentUrlId) {
6975
return $this->json([
7076
'error' => 'Only the main URL (ID 1) can toggle this setting.',
@@ -79,8 +85,15 @@ public function toggleChangeable(Request $request, AccessUrlHelper $accessUrlHel
7985
], 400);
8086
}
8187

82-
$variable = (string) $payload['variable'];
88+
$variable = trim((string) $payload['variable']);
8389
$status = (int) $payload['status'];
90+
$status = $status === 1 ? 1 : 0;
91+
92+
if ('' === $variable) {
93+
return $this->json([
94+
'error' => 'Invalid variable.',
95+
], 400);
96+
}
8497

8598
$repo = $this->entityManager->getRepository(SettingsCurrent::class);
8699

@@ -143,9 +156,22 @@ public function searchSetting(Request $request, AccessUrlHelper $accessUrlHelper
143156

144157
// Template map for current URL (existing behavior – JSON helper)
145158
$settingsRepo = $this->entityManager->getRepository(SettingsCurrent::class);
146-
$settingsWithTemplate = $settingsRepo->findBy(['url' => $url]);
147159

148-
foreach ($settingsWithTemplate as $s) {
160+
// Build template map: current URL overrides main URL when missing.
161+
$currentUrlId = (int) $url->getId();
162+
$mainUrl = $this->entityManager->getRepository(AccessUrl::class)->find(1);
163+
164+
if ($mainUrl instanceof AccessUrl && 1 !== $currentUrlId) {
165+
$mainRows = $settingsRepo->findBy(['url' => $mainUrl]);
166+
foreach ($mainRows as $s) {
167+
if ($s->getValueTemplate()) {
168+
$templateMap[$s->getVariable()] = $s->getValueTemplate()->getId();
169+
}
170+
}
171+
}
172+
173+
$currentRows = $settingsRepo->findBy(['url' => $url]);
174+
foreach ($currentRows as $s) {
149175
if ($s->getValueTemplate()) {
150176
$templateMap[$s->getVariable()] = $s->getValueTemplate()->getId();
151177
}
@@ -166,7 +192,6 @@ public function searchSetting(Request $request, AccessUrlHelper $accessUrlHelper
166192
}
167193
}
168194

169-
$currentUrlId = $url->getId();
170195
// Only platform admins on the main URL can toggle the MultiURL flag.
171196
$canToggleMultiUrlSetting = $this->isGranted('ROLE_ADMIN') && 1 === $currentUrlId;
172197

@@ -187,14 +212,6 @@ public function searchSetting(Request $request, AccessUrlHelper $accessUrlHelper
187212
]);
188213
}
189214

190-
$settingsRepo = $this->entityManager->getRepository(SettingsCurrent::class);
191-
$settingsWithTemplate = $settingsRepo->findBy(['url' => $url]);
192-
foreach ($settingsWithTemplate as $s) {
193-
if ($s->getValueTemplate()) {
194-
$templateMap[$s->getVariable()] = $s->getValueTemplate()->getId();
195-
}
196-
}
197-
198215
$settingsFromKeyword = $manager->getParametersFromKeywordOrderedByCategory($keyword);
199216
if (!empty($settingsFromKeyword)) {
200217
foreach ($settingsFromKeyword as $category => $parameterList) {
@@ -331,9 +348,20 @@ public function updateSetting(Request $request, AccessUrlHelper $accessUrlHelper
331348
$templateMap = [];
332349
$settingsRepo = $this->entityManager->getRepository(SettingsCurrent::class);
333350

334-
// Template map for current URL (existing behavior – JSON helper)
335-
$settingsWithTemplate = $settingsRepo->findBy(['url' => $url]);
351+
$currentUrlId = (int) $url->getId();
352+
$mainUrl = $this->entityManager->getRepository(AccessUrl::class)->find(1);
336353

354+
// Build template map: fallback to main URL templates when sub-URL has no row for a locked setting.
355+
if ($mainUrl instanceof AccessUrl && 1 !== $currentUrlId) {
356+
$mainRows = $settingsRepo->findBy(['url' => $mainUrl]);
357+
foreach ($mainRows as $s) {
358+
if ($s->getValueTemplate()) {
359+
$templateMap[$s->getVariable()] = $s->getValueTemplate()->getId();
360+
}
361+
}
362+
}
363+
364+
$settingsWithTemplate = $settingsRepo->findBy(['url' => $url]);
337365
foreach ($settingsWithTemplate as $s) {
338366
if ($s->getValueTemplate()) {
339367
$templateMap[$s->getVariable()] = $s->getValueTemplate()->getId();
@@ -359,7 +387,6 @@ public function updateSetting(Request $request, AccessUrlHelper $accessUrlHelper
359387
'server_type' => (string) $manager->getSetting('platform.server_type', true),
360388
];
361389

362-
$currentUrlId = $url->getId();
363390
// Only platform admins on the main URL can toggle the MultiURL flag.
364391
$canToggleMultiUrlSetting = $this->isGranted('ROLE_ADMIN') && 1 === $currentUrlId;
365392

@@ -494,12 +521,6 @@ private function computeOrderedNamespacesByTranslatedLabel(array $schemas, Reque
494521

495522
/**
496523
* Build environment diagnostics for the "search" settings page.
497-
*
498-
* This replicates the legacy Chamilo 1 behaviour:
499-
* - Check Xapian PHP extension
500-
* - Check the index directory and permissions
501-
* - Check custom search fields
502-
* - Check external converters (pdftotext, ps2pdf, ...)
503524
*/
504525
private function buildSearchDiagnostics(SettingsManager $manager): array
505526
{
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/* For licensing terms, see /license.txt */
6+
7+
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
8+
9+
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
10+
use Doctrine\DBAL\Schema\Schema;
11+
12+
final class Version20251213154100 extends AbstractMigrationChamilo
13+
{
14+
public function getDescription(): string
15+
{
16+
return 'Set settings.access_url_locked to 0 for all rows (MultiURL default unlock).';
17+
}
18+
19+
public function up(Schema $schema): void
20+
{
21+
$this->addSql('UPDATE settings SET access_url_locked = 0 WHERE access_url_locked IS NULL OR access_url_locked = 1');
22+
}
23+
24+
public function down(Schema $schema): void
25+
{
26+
// Revert to previous "locked everywhere" behavior (not recommended, but reversible).
27+
$this->addSql('UPDATE settings SET access_url_locked = 1 WHERE access_url_locked = 0');
28+
}
29+
}

src/CoreBundle/Resources/views/Admin/Settings/default.html.twig

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
<hr class="my-6 border-gray-25" />
2121

2222
<div class="row">
23-
<div class="col-md-12">
23+
<div class="col-md-12 w-full max-w-none">
2424
<div class="box box-primary">
25-
<div class="box-body">
26-
{% if namespace == 'ai_helpers' %}
27-
<div class="mb-6 p-5 rounded-lg border border-gray-50 shadow-sm bg-white hover:shadow transition">
25+
<div class="box-body w-full max-w-none">
26+
{% if namespace == 'ai_helpers' %}
27+
<div class="mb-6 p-5 rounded-lg border border-gray-50 shadow-sm bg-white hover:shadow transition" style="width:100%;max-width:none;">
2828
<div class="flex justify-between items-start mb-3 border-l-4 border-primary pl-4">
2929
<h3 class="text-gray-90 text-body-1 font-semibold">
3030
{{ "EU AI Act – Transparency & risk notice"|trans }}
@@ -52,7 +52,7 @@
5252
{% endif %}
5353
{{ form_errors(form) }}
5454
<form
55-
class="form-horizontal"
55+
class="form-horizontal !w-full !max-w-none"
5656
action="{{ path('chamilo_platform_settings', { 'namespace': namespace, 'keyword': keyword } ) }}"
5757
method="post"
5858
novalidate
@@ -73,7 +73,7 @@
7373
{% if isHidden %}
7474
{{ form_widget(field) }}
7575
{% else %}
76-
<div class="mb-6 p-5 rounded-lg border border-gray-50 shadow-sm bg-white hover:shadow transition">
76+
<div class="mb-6 p-5 rounded-lg border border-gray-50 shadow-sm bg-white hover:shadow transition" style="width:100%;max-width:none;">
7777
<div class="flex justify-between items-start mb-3 border-l-4 border-primary pl-4">
7878
<h3 class="text-gray-90 text-body-1 font-semibold">
7979
{{ field.vars.label|trans }}
@@ -372,6 +372,14 @@ sudo systemctl restart apache2
372372

373373
<script>
374374
document.addEventListener('DOMContentLoaded', () => {
375+
const overlay = document.getElementById('jsonTemplateOverlay');
376+
const modal = document.getElementById('jsonTemplateModal');
377+
378+
function closeJsonTemplateModal() {
379+
overlay?.classList.add('hidden');
380+
modal?.classList.add('hidden');
381+
}
382+
375383
document.querySelectorAll('.show-template').forEach(link => {
376384
link.addEventListener('click', (e) => {
377385
e.preventDefault();
@@ -390,19 +398,17 @@ sudo systemctl restart apache2
390398
document.getElementById('jsonTemplateContent').innerText = data.json_example;
391399
}
392400
393-
document.getElementById('jsonTemplateOverlay').classList.remove('hidden');
394-
document.getElementById('jsonTemplateModal').classList.remove('hidden');
401+
overlay?.classList.remove('hidden');
402+
modal?.classList.remove('hidden');
395403
} else {
396404
alert('{{ "Template not found."|trans }}');
397405
}
398406
});
399407
});
400408
});
401409
402-
document.getElementById('closeJsonTemplateModal').addEventListener('click', () => {
403-
document.getElementById('jsonTemplateOverlay').classList.add('hidden');
404-
document.getElementById('jsonTemplateModal').classList.add('hidden');
405-
});
410+
document.getElementById('closeJsonTemplateModal')?.addEventListener('click', closeJsonTemplateModal);
411+
overlay?.addEventListener('click', closeJsonTemplateModal);
406412
407413
// Xapian help modal
408414
const openXapianHelp = document.getElementById('openXapianHelp');
@@ -465,6 +471,7 @@ sudo systemctl restart apache2
465471
});
466472
});
467473
</script>
474+
468475
{% endblock %}
469476
{% block javascripts %}
470477
{% set ns = app.request.get('namespace')|default('') %}

0 commit comments

Comments
 (0)