Skip to content

Commit f90fc8b

Browse files
authored
Merge pull request #6352 from christianbeeznest/ras-22643
Admin: Implement advanced MultiURL management for courses - refs BT#22643
2 parents 56ef210 + 72d934c commit f90fc8b

11 files changed

+1167
-1029
lines changed
Lines changed: 122 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
<?php
22
/* For licensing terms, see /license.txt */
3+
34
/**
4-
* This script allows platform admins to add users to urls.
5-
* It displays a list of users and a list of courses;
6-
* you can select multiple users and courses and then click on.
7-
*
8-
* @author Julio Montoya <[email protected]>
5+
* This script allows platform admins to add courses to multiple URLs.
96
*/
107

118
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
@@ -24,121 +21,148 @@
2421
$first_letter_course = '';
2522
$courses = [];
2623
$url_list = [];
27-
$users = [];
24+
2825
$tbl_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
2926
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
3027

31-
/* Header */
32-
$tool_name = get_lang('Add courses to an URL');
28+
$tool_name = get_lang('Add courses to URLs');
3329
$interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('Administration')];
3430
$interbreadcrumb[] = ['url' => 'access_urls.php', 'name' => get_lang('Multiple access URL / Branding')];
3531

3632
Display::display_header($tool_name);
3733

38-
echo Display::toolbarAction(
39-
'url',
40-
[
41-
Display::url(
42-
Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Edit courses of an URL')),
43-
api_get_path(WEB_CODE_PATH).'admin/access_url_edit_courses_to_url.php'
44-
),
45-
]
34+
echo '<div class="flex gap-2 items-center mb-4 mt-4">';
35+
echo Display::url(
36+
Display::getMdiIcon(ActionIcon::BACK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Back to URL list')),
37+
api_get_path(WEB_CODE_PATH).'admin/access_urls.php'
4638
);
47-
39+
echo Display::url(
40+
Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Edit courses of an URL')),
41+
api_get_path(WEB_CODE_PATH).'admin/access_url_edit_courses_to_url.php'
42+
);
43+
echo '</div>';
4844
Display::page_subheader2($tool_name);
49-
45+
?>
46+
<h2 class="text-xl font-semibold text-gray-800 mt-6 mb-2">
47+
<?php echo $tool_name; ?>
48+
</h2>
49+
<?php
50+
echo Display::return_message(get_lang("This page allows you to massively assign or remove the assignment of courses to/from many URLs in one single action. Assigning and removing courses to/from URLs can have a high impact on access for users and data stored about users' progress. Please use carefully."), 'warning');
5051
if (isset($_POST['form_sent']) && $_POST['form_sent']) {
51-
$form_sent = $_POST['form_sent'];
5252
$courses = is_array($_POST['course_list']) ? $_POST['course_list'] : [];
5353
$url_list = is_array($_POST['url_list']) ? $_POST['url_list'] : [];
54-
$first_letter_course = $_POST['first_letter_course'];
54+
$first_letter_course = $_POST['first_letter_course'] ?? '';
55+
56+
$sql = "SELECT id, url FROM $tbl_access_url WHERE active = 1 ORDER BY url";
57+
$db_urls = Database::store_result(Database::query($sql));
5558

56-
foreach ($users as $key => $value) {
57-
$users[$key] = intval($value);
59+
if (in_array('__all__', $url_list)) {
60+
$url_list = array_column($db_urls, 'id');
5861
}
5962

60-
if (1 == $form_sent) {
61-
if (0 == count($courses) || 0 == count($url_list)) {
62-
echo Display::return_message(get_lang('At least one course and one URL'), 'error');
63-
} else {
64-
UrlManager::add_courses_to_urls($courses, $url_list);
65-
echo Display::return_message(get_lang('Course registered to the URL'), 'confirm');
66-
}
63+
if (isset($_POST['add'])) {
64+
UrlManager::add_courses_to_urls($courses, $url_list);
65+
echo Display::return_message(get_lang('Course registered to the URL'), 'confirm');
66+
} elseif (isset($_POST['remove'])) {
67+
UrlManager::remove_courses_from_urls($courses, $url_list);
68+
echo Display::return_message(get_lang('Course unregistered from the URL'), 'confirm');
6769
}
70+
} else {
71+
$sql = "SELECT id, url FROM $tbl_access_url WHERE active = 1 ORDER BY url";
72+
$db_urls = Database::store_result(Database::query($sql));
6873
}
6974

7075
$first_letter_course_lower = Database::escape_string(api_strtolower($first_letter_course));
76+
$sql = "SELECT id, code, title FROM $tbl_course
77+
WHERE title LIKE '".$first_letter_course_lower."%'
78+
ORDER BY title, code DESC";
79+
$db_courses = Database::store_result(Database::query($sql));
80+
?>
7181

72-
$sql = "SELECT code, title FROM $tbl_course
73-
WHERE
74-
title LIKE '".$first_letter_course_lower."%' OR
75-
title LIKE '".$first_letter_course_lower."%'
76-
ORDER BY title, code DESC ";
82+
<form
83+
name="formulaire"
84+
method="post"
85+
action="<?php echo api_get_self(); ?>"
86+
class="space-y-6"
87+
onsubmit="return confirmSubmission(event)"
88+
>
89+
<input type="hidden" name="form_sent" value="1"/>
90+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
91+
<div>
92+
<label class="block text-sm font-bold text-gray-90 mb-2"><?php echo get_lang('Course list'); ?></label>
93+
<input type="text" id="courseFilter" onkeyup="filterSelect('courseFilter', 'courseSelect')" placeholder="<?php echo get_lang('Search course'); ?>"
94+
class="mb-2 w-full rounded-md border border-gray-25 p-2 text-sm focus:outline-none">
95+
<select name="course_list[]" id="courseSelect" multiple size="20"
96+
class="w-full h-[400px] rounded-md border border-gray-25 p-2 text-sm focus:outline-none">
97+
<?php foreach ($db_courses as $course): ?>
98+
<option value="<?php echo $course['code']; ?>" <?php if (in_array($course['code'], $courses)) echo 'selected'; ?>>
99+
<?php echo $course['title'].' ('.$course['code'].')'; ?>
100+
</option>
101+
<?php endforeach; ?>
102+
</select>
103+
</div>
104+
105+
<div>
106+
<label class="block text-sm font-bold text-gray-90 mb-2"><?php echo get_lang('URL list'); ?></label>
107+
<input type="text" id="urlFilter" onkeyup="filterSelect('urlFilter', 'urlSelect')" placeholder="<?php echo get_lang('Search URL'); ?>"
108+
class="mb-2 w-full rounded-md border border-gray-25 p-2 text-sm focus:outline-none">
109+
<select name="url_list[]" id="urlSelect" multiple size="20"
110+
class="w-full h-[400px] rounded-md border border-gray-25 p-2 text-sm focus:outline-none">
111+
<option value="__all__"><?php echo get_lang('Select all URLs'); ?></option>
112+
<?php foreach ($db_urls as $url_obj): ?>
113+
<option value="<?php echo $url_obj['id']; ?>" <?php if (in_array($url_obj['id'], $url_list)) echo 'selected'; ?>>
114+
<?php echo $url_obj['url']; ?>
115+
</option>
116+
<?php endforeach; ?>
117+
</select>
118+
</div>
119+
</div>
120+
<div class="flex justify-center gap-4 mt-6 flex-wrap">
121+
<button
122+
type="submit"
123+
name="add"
124+
class="rounded-lg px-6 py-2 shadow focus:outline-none focus:ring btn--info"
125+
>
126+
<?php echo get_lang('Add courses to selected URLs'); ?>
127+
</button>
128+
129+
<button
130+
type="submit"
131+
name="remove"
132+
class="rounded-lg px-6 py-2 shadow focus:outline-none focus:ring"
133+
style="background: rgb(var(--color-danger-base)); color: rgb(var(--color-danger-button-text));"
134+
>
135+
<?php echo get_lang('Remove courses from selected URLs'); ?>
136+
</button>
137+
</div>
138+
</form>
77139

78-
$result = Database::query($sql);
79-
$db_courses = Database::store_result($result);
80-
unset($result);
140+
<script>
141+
function filterSelect(inputId, selectId) {
142+
const input = document.getElementById(inputId);
143+
const filter = input.value.toLowerCase();
144+
const select = document.getElementById(selectId);
145+
const options = select.options;
81146

82-
$sql = "SELECT id, url FROM $tbl_access_url WHERE active = 1 ORDER BY url";
83-
$result = Database::query($sql);
84-
$db_urls = Database::store_result($result);
85-
unset($result);
86-
?>
147+
for (let i = 0; i < options.length; i++) {
148+
const txt = options[i].text.toLowerCase();
149+
options[i].style.display = txt.includes(filter) ? '' : 'none';
150+
}
151+
}
87152

88-
<form name="formulaire" method="post" action="<?php echo api_get_self(); ?>" style="margin:0px;">
89-
<input type="hidden" name="form_sent" value="1"/>
90-
<table border="0" cellpadding="5" cellspacing="0" width="100%">
91-
<tr>
92-
<td width="40%" align="center">
93-
<b><?php echo get_lang('Course list'); ?></b>
94-
<br/><br/>
95-
<?php echo get_lang('First letter (code)'); ?> :
96-
<select name="first_letter_course" onchange="javascript:document.formulaire.form_sent.value='2'; document.formulaire.submit();">
97-
<option value="">--</option>
98-
<?php
99-
echo Display:: get_alphabet_options($first_letter_course);
100-
echo Display:: get_numeric_options(0, 9, $first_letter_course);
101-
?>
102-
</select>
103-
</td>
104-
<td width="20%">&nbsp;</td>
105-
<td width="40%" align="center">
106-
<b><?php echo get_lang('URL list'); ?> :</b>
107-
</td>
108-
</tr>
109-
<tr>
110-
<td width="40%" align="center">
111-
<select name="course_list[]" multiple="multiple" size="20" style="width:400px;">
112-
<?php foreach ($db_courses as $course) {
113-
?>
114-
<option value="<?php echo $course['code']; ?>" <?php if (in_array($course['code'], $courses)) {
115-
echo 'selected="selected"';
116-
} ?>>
117-
<?php echo $course['title'].' ('.$course['code'].')'; ?>
118-
</option>
119-
<?php
120-
} ?>
121-
</select>
122-
</td>
123-
<td width="20%" valign="middle" align="center">
124-
<button type="submit" class="add"> <?php echo get_lang('Add courses to that URL'); ?> </button>
125-
</td>
126-
<td width="40%" align="center">
127-
<select name="url_list[]" multiple="multiple" size="20" style="width:300px;">
128-
<?php foreach ($db_urls as $url_obj) {
129-
?>
130-
<option value="<?php echo $url_obj['id']; ?>" <?php if (in_array($url_obj['id'], $url_list)) {
131-
echo 'selected="selected"';
132-
} ?>>
133-
<?php echo $url_obj['url']; ?>
134-
</option>
135-
<?php
136-
} ?>
137-
</select>
138-
</td>
139-
</tr>
140-
</table>
141-
</form>
142-
<?php
153+
function confirmSubmission(event) {
154+
const form = event.target;
155+
const addClicked = form.querySelector('[name="add"]').matches(':focus');
156+
const removeClicked = form.querySelector('[name="remove"]').matches(':focus');
157+
158+
if (addClicked) {
159+
return confirm("<?php echo get_lang('Are you sure you want to add the selected courses to the selected URLs?'); ?>");
160+
}
161+
if (removeClicked) {
162+
return confirm("<?php echo get_lang('Are you sure you want to remove the selected courses from the selected URLs?'); ?>");
163+
}
164+
return true;
165+
}
166+
</script>
143167

144-
Display :: display_footer();
168+
<?php Display::display_footer(); ?>

0 commit comments

Comments
 (0)