Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 32 additions & 20 deletions public/main/user/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -481,19 +481,26 @@
}
}

// Global hosting limit: precompute a simple snapshot for UI purposes only.
$globalLimitUsersPerCourse = 0;
$currentUsersForGlobalLimit = 0;
$courseIsFullForGlobalLimit = false;
// Users-per-course limit: precompute a simple snapshot for UI purposes only.
$usersPerCourseLimit = 0;
$currentUsersForCourseLimit = 0;
$courseIsFullForUsersPerCourseLimit = false;

if ($canEdit && 0 === (int) $sessionId) {
// Read the global limit through CourseManager helper to keep logic centralized.
$globalLimitUsersPerCourse = (int) CourseManager::getGlobalUsersPerCourseLimit();
if (method_exists('CourseManager', 'getEffectiveUsersPerCourseLimit')) {
$usersPerCourseLimit = (int) CourseManager::getEffectiveUsersPerCourseLimit($courseId);
} else {
$usersPerCourseLimit = (int) CourseManager::getGlobalUsersPerCourseLimit();
}

if ($usersPerCourseLimit > 0) {
if (method_exists('CourseManager', 'countStudentsForUsersPerCourseLimit')) {
$currentUsersForCourseLimit = (int) CourseManager::countStudentsForUsersPerCourseLimit($courseId);
} else {
$currentUsersForCourseLimit = (int) CourseManager::countUsersForGlobalLimit($courseId);
}

if ($globalLimitUsersPerCourse > 0) {
// Count current users for the limit, excluding HR relation type.
$currentUsersForGlobalLimit = (int) CourseManager::countUsersForGlobalLimit($courseId);
$courseIsFullForGlobalLimit = $currentUsersForGlobalLimit >= $globalLimitUsersPerCourse;
$courseIsFullForUsersPerCourseLimit = $currentUsersForCourseLimit >= $usersPerCourseLimit;
}
}

Expand Down Expand Up @@ -628,10 +635,10 @@

$actionsLeft = '';
if ($canEdit) {
// When the global hosting limit is enabled and already reached (no session),
// When the users-per-course limit is enabled and already reached (no session),
// we hide the "Add" icon to avoid actions that would add more users.
$canShowAddIcon = true;
if (0 === (int) $sessionId && $globalLimitUsersPerCourse > 0 && $courseIsFullForGlobalLimit) {
if (0 === (int) $sessionId && $usersPerCourseLimit > 0 && $courseIsFullForUsersPerCourseLimit) {
$canShowAddIcon = false;
}

Expand Down Expand Up @@ -683,15 +690,20 @@
echo UserManager::getUserSubscriptionTab($selectedTab);
echo Display::toolbarAction('toolbar', [$actionsLeft, $actionsRight]);

// When the course is full according to the global limit (no session),
// When the course is full according to the effective limit (global or BuyCourses),
// show an explicit warning so teachers understand why the Add icon is hidden.
if ($canEdit && 0 === (int) $sessionId && $globalLimitUsersPerCourse > 0 && $courseIsFullForGlobalLimit) {
$msg = sprintf(
get_lang(
'This course already reached the global limit of %d users set by the administrators. To add more users, please ask an administrator to raise this limit or use sessions.'
),
$globalLimitUsersPerCourse
);
if ($canEdit && 0 === (int) $sessionId && $usersPerCourseLimit > 0 && $courseIsFullForUsersPerCourseLimit) {
if (method_exists('CourseManager', 'getUsersPerCourseLimitCancelMessage')) {
$msg = CourseManager::getUsersPerCourseLimitCancelMessage($courseId);
} else {
$msg = sprintf(
get_lang(
'This operation would exceed the limit of %d users allowed for this course.'
),
$usersPerCourseLimit
);
}

echo Display::return_message($msg, 'warning');
}
}
Expand Down
104 changes: 90 additions & 14 deletions public/plugin/BuyCourses/src/buy_course_plugin.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -6246,19 +6246,45 @@ private function saveUserExtraFieldTextValue(int $userId, int $extraFieldId, str
$checkResult = Database::query($checkSql);

if ($checkResult && Database::num_rows($checkResult) > 0) {
Database::query("UPDATE $table
SET $valueColumn = '$escapedValue'
WHERE field_id = $extraFieldId
AND item_id = $userId");
$updateData = [
$valueColumn => $value,
];

if (in_array('updated_at', $this->getExtraFieldValueTimestampColumns(), true)) {
$updateData['updated_at'] = api_get_utc_datetime();
}

Database::update(
$table,
$updateData,
[
'field_id = ? AND item_id = ?' => [$extraFieldId, $userId],
]
);

return;
}

Database::insert($table, [
$insertData = [
'field_id' => $extraFieldId,
'item_id' => $userId,
$valueColumn => $value,
]);
];

$timestampColumns = $this->getExtraFieldValueTimestampColumns();
if (!empty($timestampColumns)) {
$now = api_get_utc_datetime();

if (in_array('created_at', $timestampColumns, true)) {
$insertData['created_at'] = $now;
}

if (in_array('updated_at', $timestampColumns, true)) {
$insertData['updated_at'] = $now;
}
}

Database::insert($table, $insertData);
}

/**
Expand Down Expand Up @@ -9194,6 +9220,35 @@ private function getExtraFieldValueColumn(): string
throw new RuntimeException('No supported value column found in extra_field_values.');
}

/**
* Return timestamp columns available on extra_field_values.
* Some Chamilo 2 installations enforce NOT NULL created_at/updated_at.
*
* @return string[]
*/
private function getExtraFieldValueTimestampColumns(): array
{
static $columns = null;

if (null !== $columns) {
return $columns;
}

$columns = [];
$table = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
$result = Database::query("SHOW COLUMNS FROM $table");

while ($row = Database::fetch_array($result, 'ASSOC')) {
$fieldName = (string) ($row['Field'] ?? '');

if (in_array($fieldName, ['created_at', 'updated_at'], true)) {
$columns[] = $fieldName;
}
}

return $columns;
}

/**
* Return all benefit relations configured for a service.
*/
Expand Down Expand Up @@ -9237,9 +9292,7 @@ public function saveUserExtraFieldJsonValue(int $userId, int $extraFieldId, arra

$table = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
$valueColumn = $this->getExtraFieldValueColumn();
$jsonValue = Database::escape_string(
json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
);
$jsonValue = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

$checkSql = "SELECT id
FROM $table
Expand All @@ -9249,11 +9302,21 @@ public function saveUserExtraFieldJsonValue(int $userId, int $extraFieldId, arra
$checkResult = Database::query($checkSql);

if ($checkResult && Database::num_rows($checkResult) > 0) {
$sql = "UPDATE $table
SET $valueColumn = '$jsonValue'
WHERE field_id = $extraFieldId
AND item_id = $userId";
Database::query($sql);
$updateData = [
$valueColumn => $jsonValue,
];

if (in_array('updated_at', $this->getExtraFieldValueTimestampColumns(), true)) {
$updateData['updated_at'] = api_get_utc_datetime();
}

Database::update(
$table,
$updateData,
[
'field_id = ? AND item_id = ?' => [$extraFieldId, $userId],
]
);

return;
}
Expand All @@ -9264,6 +9327,19 @@ public function saveUserExtraFieldJsonValue(int $userId, int $extraFieldId, arra
$valueColumn => $jsonValue,
];

$timestampColumns = $this->getExtraFieldValueTimestampColumns();
if (!empty($timestampColumns)) {
$now = api_get_utc_datetime();

if (in_array('created_at', $timestampColumns, true)) {
$insertData['created_at'] = $now;
}

if (in_array('updated_at', $timestampColumns, true)) {
$insertData['updated_at'] = $now;
}
}

Database::insert($table, $insertData);
}

Expand Down
2 changes: 1 addition & 1 deletion public/plugin/BuyCourses/view/catalog.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@

{% if service.has_blocking_sale|default(false) %}
<span
class="inline-flex w-full items-center justify-center gap-2 rounded-xl bg-gray-20 px-4 py-2.5 text-sm font-semibold text-gray-50"
class="inline-flex w-full items-center justify-center gap-2 rounded-xl bg-primary/15 px-4 py-2.5 text-sm font-semibold text-primary"
>
<em class="fa fa-check-circle fa-fw"></em>
{{ 'Already purchased'|get_lang }}
Expand Down
2 changes: 1 addition & 1 deletion public/plugin/BuyCourses/view/index_products.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@
</a>

{% if service.has_blocking_sale|default(false) %}
<span class="inline-flex w-full items-center justify-center gap-2 rounded-xl bg-gray-20 px-4 py-2.5 text-sm font-semibold text-gray-50">
<span class="inline-flex w-full items-center justify-center gap-2 rounded-xl bg-primary/15 px-4 py-2.5 text-sm font-semibold text-primary">
<em class="fa fa-check-circle fa-fw"></em>
{{ 'Already purchased'|get_lang }}
</span>
Expand Down
Loading