Resolved merge conflicts with upstream/master

pull/5217/head
christianbeeznst 2 years ago
commit f6cb80e25b
  1. 4
      assets/css/app.scss
  2. 2
      assets/css/scss/_skill.scss
  3. 14
      assets/css/scss/atoms/_buttons.scss
  4. 3
      assets/css/scss/atoms/_checkbox.scss
  5. 16
      assets/css/scss/atoms/_dropdown.scss
  6. 2
      assets/vue/components/basecomponents/BaseInputText.vue
  7. 16
      assets/vue/components/basecomponents/BaseToolbar.vue
  8. 1
      assets/vue/components/basecomponents/ChamiloIcons.js
  9. 12
      assets/vue/components/ccalendarevent/CCalendarEventInfo.vue
  10. 38
      assets/vue/composables/calendar/calendarEvent.js
  11. 2
      assets/vue/router/index.js
  12. 19
      assets/vue/views/ccalendarevent/CCalendarEventList.vue
  13. 4
      public/documentation/legacy/changelog.html
  14. 4
      public/main/admin/access_url_add_users_to_url.php
  15. 2
      public/main/admin/access_url_check_user_session.php
  16. 4
      public/main/admin/add_users_to_usergroup.php
  17. 8
      public/main/admin/dashboard_add_users_to_user.php
  18. 4
      public/main/admin/user_edit.php
  19. 15
      public/main/admin/user_list.php
  20. 2
      public/main/admin/user_list_consent.php
  21. 2
      public/main/cron/request_removal_reminder.php
  22. 2
      public/main/inc/ajax/exercise.ajax.php
  23. 2
      public/main/inc/lib/SkillModel.php
  24. 4
      public/main/inc/lib/TicketManager.php
  25. 2
      public/main/inc/lib/access_url_edit_users_to_url_functions.lib.php
  26. 6
      public/main/inc/lib/api.lib.php
  27. 10
      public/main/inc/lib/course.lib.php
  28. 2
      public/main/inc/lib/exercise.lib.php
  29. 2
      public/main/inc/lib/groupmanager.lib.php
  30. 6
      public/main/inc/lib/myspace.lib.php
  31. 14
      public/main/inc/lib/online.inc.php
  32. 8
      public/main/inc/lib/sessionmanager.lib.php
  33. 22
      public/main/inc/lib/statistics.lib.php
  34. 2
      public/main/inc/lib/sub_language.class.php
  35. 2
      public/main/inc/lib/tracking.lib.php
  36. 2
      public/main/inc/lib/urlmanager.lib.php
  37. 6
      public/main/inc/lib/usergroup.lib.php
  38. 4
      public/main/inc/lib/usermanager.lib.php
  39. 2
      public/main/inc/lib/zombie/zombie_manager.class.php
  40. 648
      public/main/template/default/skill/skill_wheel.html.twig
  41. 26
      public/main/user/add_users_to_session.php
  42. 4
      public/main/user/resume_session.php
  43. 16
      public/main/user/subscribe_user.php
  44. 4
      public/main/user/user.php
  45. 10
      public/main/user/user_export.php
  46. 5
      src/CoreBundle/ApiResource/AbstractResource.php
  47. 18
      src/CoreBundle/ApiResource/CalendarEvent.php
  48. 2
      src/CoreBundle/Component/Utils/StateIcon.php
  49. 86
      src/CoreBundle/DataProvider/Extension/CCalendarEventExtension.php
  50. 8
      src/CoreBundle/DataTransformer/CalendarEventTransformer.php
  51. 59
      src/CoreBundle/Entity/Skill.php
  52. 9
      src/CoreBundle/Entity/User.php
  53. 2
      src/CoreBundle/Repository/Node/UserRepository.php
  54. 32
      src/CoreBundle/Repository/Node/UsergroupRepository.php
  55. 201
      src/CoreBundle/Repository/SkillRepository.php
  56. 2
      src/CoreBundle/Resources/views/Layout/skill_layout.html.twig
  57. 59
      src/CoreBundle/ServiceHelper/CidReqHelper.php
  58. 20
      src/CourseBundle/Entity/CCalendarEvent.php

@ -220,6 +220,10 @@
@import "scss/index.scss";
.field > small.p-error {
@apply text-error;
}
// tabs
.tab-content {
> .tab-pane {

@ -470,3 +470,5 @@
display: inline-block;
}
}

@ -40,11 +40,11 @@
}
&--plain {
@apply bg-gray-90 text-white mr-1.5;
@apply bg-gray-30 text-white mr-1.5;
&:hover,
&:focus {
@apply bg-black;
@apply bg-gray-90;
}
}
@ -53,7 +53,7 @@
&:hover,
&:focus {
@apply bg-gray-90 border-gray-90 text-white;
@apply bg-gray-30 border-gray-30 text-white;
}
}
@ -165,7 +165,7 @@ $border-color_12: #9333EA;
$textColor: 'white';
@if('warning' == $color) {
$textColor: 'gray-90';
$textColor: 'gray-30';
}
@apply bg-#{$color} text-#{$textColor};
@ -194,7 +194,7 @@ $border-color_12: #9333EA;
@if ('warning' == $color) {
@apply bg-#{$color} border-#{$color} text-gray-90;
} @else if('black' == $color) {
@apply bg-gray-90 border-gray-90 text-white;
@apply bg-gray-30 border-gray-30 text-white;
} @else {
@apply bg-#{$color} border-#{$color} text-white;
}
@ -321,7 +321,7 @@ $border-color_12: #9333EA;
// plain button
.p-button.p-button-plain {
@include filled-style('gray-90', 'black');
@include filled-style('gray-30', 'black');
&.p-button-outlined {
@include outlined-style('black');
@ -334,7 +334,7 @@ $border-color_12: #9333EA;
.p-buttonset.p-button-plain {
> .p-button {
@include filled-style('gray-90', 'black');
@include filled-style('gray-30', 'black');
&.p-button-outlined {
@include outlined-style('black');

@ -32,3 +32,6 @@
}
}
.p-checkbox .p-checkbox-box {
@apply invisible;
}

@ -1,4 +1,4 @@
.p-dropdown {
.p-dropdown, .p-multiselect {
@apply border border-support-3 bg-white rounded-lg transition w-full duration-200
hover:border-primary hover:text-gray-90 hover:outline-0 hover:outline-none;
@ -29,7 +29,7 @@
}
}
.p-dropdown-panel {
.p-dropdown-panel, .multi-select-panel {
@apply bg-white rounded-lg text-gray-90 shadow-lg;
.p-dropdown-header {
@ -89,3 +89,15 @@
}
}
.multi-select-panel {
@apply border border-gray-300 shadow-md rounded-md p-2;
}
.multi-select-panel .p-checkbox {
@apply mr-1;
}
.p-multiselect-label {
@apply py-2;
}

@ -7,6 +7,7 @@
:class="{ 'p-invalid': isInvalid }"
:aria-label="label"
type="text"
:required="required"
@update:model-value="$emit('update:modelValue', $event)"
/>
<label
@ -54,6 +55,7 @@ const props = defineProps({
required: false,
default: false,
},
required: Boolean,
})
defineEmits(["update:modelValue"])

@ -1,7 +1,10 @@
<template>
<Toolbar :class="toolbarClass">
<template #start>
<slot></slot>
<template v-slot:start>
<slot name="start"></slot>
</template>
<template v-slot:end>
<slot name="end"></slot>
</template>
</Toolbar>
</template>
@ -21,6 +24,13 @@ const toolbarClass = computed(() => {
if (props.showTopBorder) {
return "pt-5 border-t border-b";
}
return "";
return "p-toolbar";
});
</script>
<style scoped>
.p-toolbar {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
</style>

@ -118,4 +118,5 @@ export const chamiloIconToClass = {
"map-search": "mdi mdi-map-search-outline",
"join-group": "mdi mdi-account-multiple-plus",
"add-topic": "mdi mdi-forum-outline",
'badge-account': "mdi mdi-badge-account-horizontal",
};

@ -1,5 +1,5 @@
<template>
<div class="flex flex-col gap-4">
<div class="flex flex-col space-y-4">
<h5 v-text="event.title" />
<p v-text="abbreviatedDatetime(event.startDate)" />
@ -13,11 +13,7 @@
<div v-html="event.content" />
<div
v-if="event.resourceLinkListFromEntity && event.resourceLinkListFromEntity.length"
aria-invalid="spelling"
@click="window.alert('asdfsadf')"
>
<div v-if="allowCollectiveInvitations && type.invitation === event.invitationType">
<h6 v-t="'Invitees'" />
<ShowLinks
@ -30,10 +26,12 @@
<script setup>
import { useFormatDate } from "../../composables/formatDate"
import ShowLinks from "../resource_links/ShowLinks"
import { useCalendarInvitations } from "../../composables/calendar/calendarInvitations"
import { type } from "../../constants/entity/ccalendarevent"
const { abbreviatedDatetime } = useFormatDate()
const { allowCollectiveInvitations } = useCalendarInvitations()
// eslint-disable-next-line no-undef
defineProps({

@ -0,0 +1,38 @@
import { type } from "../../constants/entity/ccalendarevent"
export function useCalendarEvent() {
return {
findUserLink,
isEditableByUser,
}
}
/**
* @param {Object} event
* @param {number} userId
* @returns {Object|undefined}
*/
function findUserLink(event, userId) {
return event.resourceLinkListFromEntity.find((linkEntity) => linkEntity.user.id === userId)
}
/**
* @param {Object} event
* @param {number} userId
* @returns {boolean}
*/
function isEditableByUser(event, userId) {
if (event.resourceNode.creator.id === userId) {
return true
}
if (type.invitation === event.invitationType && event.collective) {
const userLink = findUserLink(event, userId)
if (userLink) {
return true
}
}
return false
}

@ -12,6 +12,7 @@ import toolIntroRoutes from "./ctoolintro"
import pageRoutes from "./page"
import socialNetworkRoutes from "./social"
import termsRoutes from "./terms"
import skillsRoutes from "./skill"
//import courseCategoryRoutes from './coursecategory';
import documents from "./documents"
@ -140,6 +141,7 @@ const router = createRouter({
component: MySessionListUpcoming,
meta: { requiresAuth: true },
},
skillsRoutes,
termsRoutes,
socialNetworkRoutes,
catalogueCourses,

@ -61,7 +61,7 @@
@click="confirmDelete"
/>
<BaseButton
v-if="isEventEditable"
v-if="allowToEdit"
:label="t('Edit')"
type="secondary"
@click="dialog = true"
@ -129,6 +129,7 @@ import { useLocale, useParentLocale } from "../../composables/locale"
import { storeToRefs } from "pinia"
import CalendarSectionHeader from "../../components/ccalendarevent/CalendarSectionHeader.vue"
import { useCalendarActionButtons } from "../../composables/calendar/calendarActionButtons"
import { useCalendarEvent } from "../../composables/calendar/calendarEvent"
const store = useStore()
const confirm = useConfirm()
@ -140,10 +141,12 @@ const { abbreviatedDatetime } = useFormatDate()
const { showAddButton } = useCalendarActionButtons()
const { isEditableByUser } = useCalendarEvent()
const item = ref({})
const dialog = ref(false)
const dialogShow = ref(false)
const isEventEditable = ref(false)
const allowToEdit = ref(false)
const currentUser = computed(() => store.getters["security/getUser"])
const { t } = useI18n()
@ -244,17 +247,7 @@ const calendarOptions = ref({
item.value["endDate"] = event.end
item.value["parentResourceNodeId"] = event.extendedProps.resourceNode.creator.id
isEventEditable.value = item.value["parentResourceNodeId"] === currentUser.value["id"]
if (!isEventEditable.value && event.extendedProps.collective && event.extendedProps.resourceLinkListFromEntity) {
const resourceLink = event.extendedProps.resourceLinkListFromEntity.find(
(linkEntity) => linkEntity.user.id === currentUser.value.id,
)
if (resourceLink) {
isEventEditable.value = true
}
}
allowToEdit.value = isEditableByUser(item.value, currentUser.value.id)
dialogShow.value = true
},

@ -299,7 +299,7 @@
<li>[2018-08-06] (<a href="https://github.com/chamilo/chamilo-lms/commit/6cd142ffd650e7fe5aadce7fb56a1318653114cc">6cd142ff</a> - <a href="https://github.com/chamilo/chamilo-lms/issues/2555">GH#2555</a>) Privacy: If user sends remove account request, delete the remove legal request</li>
<li>[2018-08-06] (<a href="https://github.com/chamilo/chamilo-lms/commit/531e4505434e0d8cd718fbc5517f56c30846bb4d">531e4505</a> - <a href="https://github.com/chamilo/chamilo-lms/issues/2555">GH#2555</a>) Privacy: Add "erase account" extra fields</li>
<li>[2018-08-06] (<a href="https://github.com/chamilo/chamilo-lms/commit/ecb18907a7fec22402411aa873382a4bd06cb07d">ecb18907</a>) Internal: Maintenance: Remove use of Course::unserialize() when exporting/importing course bk</li>
<li>[2018-08-06] (<a href="https://github.com/chamilo/chamilo-lms/commit/0683b23602b5fd0505e4d96442f573095c299597">0683b236</a>) Internal: Create the main.language.js file even if we're in CLI</li>
<li>[2018-08-06] (<a href="https://github.com/chamilo/chamilo-lms/commit/0683b23602b5fd0505e4d96442f573095c299597">0683b236</a>) Internal: Create the main.languageService.js file even if we're in CLI</li>
<li>[2018-08-03] (<a href="https://github.com/chamilo/chamilo-lms/commit/c2b4f937520fe843f757b78bd77e88c10c091527">c2b4f937</a> - <a href="https://github.com/chamilo/chamilo-lms/issues/2616">GH#2616</a>) Quiz: Fix empty lines appearing when no question details set to appear</li>
<li>[2018-08-03] (<a href="https://github.com/chamilo/chamilo-lms/commit/3400f430a5a70bbd49c261affe5288330abf2291">3400f430</a> - <a href="https://github.com/chamilo/chamilo-lms/issues/2572">GH#2572</a>) Learnpath: Quiz: Fix issue preventing save buttons for individual questions and end of test when quizzes are included into learning paths on Apple devices</li>
<li>[2018-08-03] (<a href="https://github.com/chamilo/chamilo-lms/commit/618c56cd90e1f00fac11df9cb0c35dd4c68539da">618c56cd</a> - <a href="https://github.com/chamilo/chamilo-lms/issues/2555">GH#2555</a>) Privacy: Add "Delete legal agreement" button</li>
@ -314,7 +314,7 @@
<li>[2018-08-02] (<a href="https://github.com/chamilo/chamilo-lms/commit/6413516bfd53050deb97eb0425ec5392d4281883">6413516b</a>) Internal: Improve language terms scanning script - re-enable die() call to avoid non-authorized execution</li>
<li>[2018-08-02] (<a href="https://github.com/chamilo/chamilo-lms/commit/c1478e829702662c89003967764df4b1691305a1">c1478e82</a>) Internal: Improve language terms scanning script</li>
<li>[2018-08-02] (<a href="https://github.com/chamilo/chamilo-lms/commit/992b79c624a8f524a4fb33a139befb0e1c7f10d1">992b79c6</a>) Template: Fix missing get_lang call for LightBlue in skill wheel</li>
<li>[2018-08-02] (<a href="https://github.com/chamilo/chamilo-lms/commit/7a6691647c213b1b950b622de685710b2220a4a8">7a669164</a>) Internal: Add error checking before writing web/build/main.language.js</li>
<li>[2018-08-02] (<a href="https://github.com/chamilo/chamilo-lms/commit/7a6691647c213b1b950b622de685710b2220a4a8">7a669164</a>) Internal: Add error checking before writing web/build/main.languageService.js</li>
<li>[2018-08-02] (<a href="https://github.com/chamilo/chamilo-lms/commit/13676a5dcbbe59e51304dd7eb6ba971726965942">13676a5d</a> - <a href="https://github.com/chamilo/chamilo-lms/issues/2574">GH#2574</a>) Install: Use "SET SESSION sql_mode" to avoid issues with bin/doctrine.php when we don't have global DB privileges</li>
<li>[2018-08-02] (<a href="https://github.com/chamilo/chamilo-lms/commit/dd29d0f3126e5d62bd1d3aea646e10766a752766">dd29d0f3</a>) Internal: Remove TEACHER case from get_status_from_code(): TEACHER constant doesn't exist.</li>
<li>[2018-08-02] (<a href="https://github.com/chamilo/chamilo-lms/commit/6075671b780dd703ab4e03a6e33771d83f97198f">6075671b</a>) Quiz: Add link to user profile in test results header table</li>

@ -66,7 +66,7 @@ if ($_POST['form_sent']) {
/* Display GUI */
if (empty($first_letter_user)) {
$sql = "SELECT count(*) as nb_users FROM $tbl_user WHERE active <> -1";
$sql = "SELECT count(*) as nb_users FROM $tbl_user WHERE active <> ".USER_SOFT_DELETED;
$result = Database::query($sql);
$num_row = Database::fetch_array($result);
if ($num_row['nb_users'] > 1000) {
@ -81,7 +81,7 @@ $first_letter_user_lower = Database::escape_string(api_strtolower($first_letter_
$target_name = api_sort_by_first_name() ? 'firstname' : 'lastname';
$target_name = 'lastname';
$sql = "SELECT user_id,lastname,firstname,username FROM $tbl_user
WHERE active <> -1 AND ".$target_name." LIKE '".$first_letter_user_lower."%' OR ".$target_name." LIKE '".$first_letter_user_lower."%'
WHERE active <> ".USER_SOFT_DELETED." AND ".$target_name." LIKE '".$first_letter_user_lower."%' OR ".$target_name." LIKE '".$first_letter_user_lower."%'
ORDER BY ".(count($users) > 0 ? '(user_id IN('.implode(',', $users).')) DESC,' : '').' '.$target_name;
$result = Database::query($sql);
$db_users = Database::store_result($result);

@ -78,7 +78,7 @@ foreach ($session_list as $session_item) {
ON u.id = su.user_id AND su.relation_type <> ".Session::DRH."
LEFT OUTER JOIN $table_access_url_user uu
ON (uu.user_id = u.id)
WHERE su.session_id = $session_id AND $access_where AND u.active <> -1
WHERE su.session_id = $session_id AND $access_where AND u.active <> ".USER_SOFT_DELETED."
$order_clause";
$result = Database::query($sql);

@ -143,7 +143,7 @@ if (isset($_GET['action']) && 'export' === $_GET['action']) {
['UserName', 'ClassName'],
];
foreach ($users as $user) {
$data[] = [$user['username'], $groupInfo['name']];
$data[] = [$user['username'], $groupInfo['title']];
}
$filename = 'export_user_class_'.api_get_local_time();
Export::arrayToCsv($data, $filename);
@ -345,7 +345,7 @@ echo Display::toolbarAction('add_users', [$actions]);
echo '<div id="advanced_search_options" style="display:none">';
$searchForm->display();
echo '</div>';
echo Display::page_header($tool_name.': '.$data['name']);
echo Display::page_header($tool_name.': '.$data['title']);
?>
<form name="formulaire" method="post" action="<?php echo api_get_self(); ?>?id=<?php echo $id; if (!empty($_GET['add'])) {

@ -103,7 +103,7 @@ function search_users($needle, $type = 'multiple')
$sql = "SELECT user.id as user_id, username, lastname, firstname
FROM $tbl_user user
LEFT JOIN $tbl_access_url_rel_user au ON (au.user_id = user.id)
WHERE user.active <> -1 AND
WHERE user.active <> ".USER_SOFT_DELETED." AND
".(api_sort_by_first_name() ? 'firstname' : 'lastname')." LIKE '$needle%' AND
status NOT IN(".DRH.', '.SESSIONADMIN.', '.STUDENT_BOSS.") AND
user.id NOT IN ($user_anonymous, $current_user_id, $user_id)
@ -114,7 +114,7 @@ function search_users($needle, $type = 'multiple')
} else {
$sql = "SELECT id as user_id, username, lastname, firstname
FROM $tbl_user user
WHERE user.active <> -1 AND
WHERE user.active <> ".USER_SOFT_DELETED." AND
".(api_sort_by_first_name() ? 'firstname' : 'lastname')." LIKE '$needle%' AND
status NOT IN(".DRH.', '.SESSIONADMIN.', '.STUDENT_BOSS.") AND
id NOT IN ($user_anonymous, $current_user_id, $user_id)
@ -132,7 +132,7 @@ function search_users($needle, $type = 'multiple')
$sql = 'SELECT user.id as user_id, username, lastname, firstname
FROM '.$tbl_user.' user
INNER JOIN '.$tbl_user_rel_access_url.' url_user ON (url_user.user_id=user.id)
WHERE user.active <> -1 AND
WHERE user.active <> '.USER_SOFT_DELETED.' AND
access_url_id = '.$access_url_id.' AND
(
username LIKE "'.$needle.'%" OR
@ -400,7 +400,7 @@ if (api_is_multiple_url_enabled()) {
FROM $tbl_user user
LEFT JOIN $tbl_access_url_rel_user au
ON (au.user_id = user.id)
WHERE user.active <> -1 AND
WHERE user.active <> ".USER_SOFT_DELETED." AND
$without_assigned_users
user.id NOT IN ($user_anonymous, $current_user_id, $user_id) AND
status NOT IN(".DRH.', '.SESSIONADMIN.', '.ANONYMOUS.") $search_user AND

@ -436,9 +436,9 @@ if ($form->validate()) {
}
if (isset($user['active'])) {
$active = $user_data['platform_admin'] ? 1 : intval($user['active']);
$active = $user_data['platform_admin'] ? USER_ACTIVE : intval($user['active']);
} else {
$active = -1;
$active = USER_SOFT_DELETED;
}
//If the user is set to admin the status will be overwrite by COURSEMANAGER = 1

@ -384,9 +384,9 @@ function prepare_user_sql_query(bool $getCount, bool $showDeletedUsers = false):
}
if ($showDeletedUsers) {
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active = -1' : ' AND u.active = -1';
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active = '.USER_SOFT_DELETED : ' AND u.active = '.USER_SOFT_DELETED;
} else {
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> -1' : ' AND u.active <> -1';
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> '.USER_SOFT_DELETED : ' AND u.active <> '.USER_SOFT_DELETED;
}
return $sql;
@ -865,23 +865,26 @@ function active_filter(int $active, string $params, array $row): string
$action = 'Unlock';
$image = StateIcon::WARNING;
if ('1' == $active) {
if (USER_ACTIVE == $active) {
$action = 'Lock';
$image = StateIcon::COMPLETE;
} elseif ('-1' == $active) {
} elseif (USER_INACTIVE_AUTOMATIC == $active) {
$action = 'edit';
$image = StateIcon::EXPIRED;
} elseif (USER_SOFT_DELETED == $active) {
$action = 'soft_deleted';
$image = StateIcon::REJECT;
}
$result = '';
if ('edit' === $action) {
if (in_array($action, ['edit', 'soft_deleted'])) {
$result = Display::getMdiIcon(
$image,
'ch-tool-icon',
null,
ICON_SIZE_TINY,
get_lang('Account expired')
'edit' === $action ? get_lang('Account expired') : get_lang('Account is removed temporally')
);
} elseif ($row['0'] != $_user['user_id']) {
// you cannot lock yourself out otherwise you could disable all the

@ -173,7 +173,7 @@ function prepare_user_sql_query($getCount)
$sql .= " AND url_rel_user.access_url_id = ".api_get_current_access_url_id();
}
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> -1' : ' AND u.active <> -1';
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> '.USER_SOFT_DELETED : ' AND u.active <> '.USER_SOFT_DELETED;
return $sql;
}

@ -41,7 +41,7 @@ foreach ($urlList as $url) {
v.value = 1
) ";
$sql .= " WHERE 1 = 1 AND u.active <> -1 ";
$sql .= " WHERE 1 = 1 AND u.active <> ".USER_SOFT_DELETED;
if (api_get_multiple_access_url()) {
$sql .= " AND url_rel_user.access_url_id = ".api_get_current_access_url_id();

@ -237,7 +237,7 @@ switch ($action) {
GROUP BY exe_user_id
) as aa
ON aa.exe_user_id = u.id
WHERE u.active <> -1
WHERE u.active <> ".USER_SOFT_DELETED."
ORDER BY `$sidx` $sord
LIMIT $start, $limit";

@ -1243,7 +1243,7 @@ class SkillModel extends Model
ON (s.id = su.skill_id)
INNER JOIN {$this->table_user} u
ON u.id = su.user_id, (SELECT @rownum:=0) r
WHERE 1=1 AND u.active <> -1 $where_condition
WHERE 1=1 AND u.active <> ".USER_SOFT_DELETED." $where_condition
GROUP BY username
ORDER BY skills_acquired desc
LIMIT $start , $limit) AS T1, (SELECT @rownum:=0) r";

@ -1281,7 +1281,7 @@ class TicketManager
FROM $table_support_messages message
INNER JOIN $table_main_user user
ON (message.sys_insert_user_id = user.id)
WHERE user.active <> -1 AND
WHERE user.active <> ".USER_SOFT_DELETED." AND
message.ticket_id = '$ticketId' ";
$result = Database::query($sql);
$ticket['messages'] = [];
@ -1812,7 +1812,7 @@ class TicketManager
}
}
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE user.active <> -1' : ' AND user.active <> -1';
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE user.active <> '.USER_SOFT_DELETED : ' AND user.active <> '.USER_SOFT_DELETED;
$sql .= " LIMIT $from,$number_of_items";
$result = Database::query($sql);

@ -39,7 +39,7 @@ class AccessUrlEditUsersToUrl
$order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname, username' : ' ORDER BY lastname, firstname, username';
$sql = 'SELECT u.id as user_id, username, lastname, firstname
FROM '.$tbl_user.' u
WHERE u.active <> -1 AND
WHERE u.active <> '.USER_SOFT_DELETED.' AND
(
username LIKE "'.$needle.'%" OR
firstname LIKE "'.$needle.'%" OR

@ -662,6 +662,12 @@ define('SE_DOCTYPE_EXERCISE_QUESTION', 1);
define('XAPIAN_PREFIX_COURSEID', 'C');
define('XAPIAN_PREFIX_TOOLID', 'O');
// User active field constants
define('USER_ACTIVE', 1);
define('USER_INACTIVE', 0);
define('USER_INACTIVE_AUTOMATIC', -1);
define('USER_SOFT_DELETED', -2);
/**
* Returns a path to a certain resource within Chamilo.
*

@ -1375,7 +1375,7 @@ class CourseManager
$sqlInjectJoins
";
$where[] = ' session_course_user.c_id IS NOT NULL ';
$where[] = ' user.active <> -1 ';
$where[] = ' user.active <> '.USER_SOFT_DELETED.' ';
// 2 = coach
// 0 = student
@ -1452,7 +1452,7 @@ class CourseManager
}
}
$sql .= " WHERE user.active <> -1 AND
$sql .= " WHERE user.active <> ".USER_SOFT_DELETED." AND
$filter_by_status_condition
".implode(' OR ', $where);
@ -1759,7 +1759,7 @@ class CourseManager
$sql .= " LEFT JOIN $tblUrlUser au ON (au.user_id = user.id) ";
}
$sql .= ' WHERE user.active <> -1 AND '.implode(' OR ', $where);
$sql .= ' WHERE user.active <> '.USER_SOFT_DELETED.' AND '.implode(' OR ', $where);
if ($multiple_access_url) {
$current_access_url_id = api_get_current_access_url_id();
@ -1881,7 +1881,7 @@ class CourseManager
FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
INNER JOIN $userTable u
ON cu.user_id = u.id
WHERE u.active <> -1 AND c_id = $courseId AND cu.status = ".STUDENT;
WHERE u.active <> ".USER_SOFT_DELETED." AND c_id = $courseId AND cu.status = ".STUDENT;
if (!$includeInvitedUsers) {
$sql .= " AND u.status != ".INVITEE;
@ -1924,7 +1924,7 @@ class CourseManager
$joinSession
INNER JOIN $userTable u
ON scu.user_id = u.id
WHERE u.active <> -1 AND scu.c_id = $courseId AND scu.status = ".SessionEntity::STUDENT;
WHERE u.active <> ".USER_SOFT_DELETED." AND scu.c_id = $courseId AND scu.status = ".SessionEntity::STUDENT;
if (!empty($date_from) && !empty($date_to)) {
$date_from = Database::escape_string($date_from);

@ -2094,7 +2094,7 @@ HOTSPOT;
";
}
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE user.active <> -1' : ' AND user.active <> -1';
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE user.active <> '.USER_SOFT_DELETED : ' AND user.active <> '.USER_SOFT_DELETED;
if (empty($sql)) {
return false;

@ -1133,7 +1133,7 @@ class GroupManager
ON (gu.group_id = g.iid)
INNER JOIN $user_table u
ON (u.id = gu.user_id)
WHERE u.active <> -1 AND
WHERE u.active <> ".USER_SOFT_DELETED." AND
g.iid = $group_id";
if (!empty($column) && !empty($direction)) {

@ -518,7 +518,7 @@ class MySpace
MAX(login_date) as login_date
FROM $tbl_user u, $tbl_session_course_user scu, $tbl_track_login
WHERE
u.active <> -1 AND scu.user_id = u.id AND scu.status=".SessionEntity::COURSE_COACH." AND login_user_id=u.id
u.active <> ".USER_SOFT_DELETED." AND scu.user_id = u.id AND scu.status=".SessionEntity::COURSE_COACH." AND login_user_id=u.id
GROUP BY user_id ";
if (api_is_multiple_url_enabled()) {
@ -1958,7 +1958,7 @@ class MySpace
FROM $tbl_user AS u
INNER JOIN $tbl_session_rel_course_rel_user AS scu
ON u.id = scu.user_id
WHERE u.active <> -1 AND scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
WHERE u.active <> ".USER_SOFT_DELETED." AND scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
$result_users = Database::query($sql);
$time_spent = 0;
$progress = 0;
@ -2138,7 +2138,7 @@ class MySpace
FROM $tbl_user AS u
INNER JOIN $tbl_session_rel_course_rel_user AS scu
ON u.id = scu.user_id
WHERE u.active <> -1 AND scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
WHERE u.active <> ".USER_SOFT_DELETED." AND scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
$result_users = Database::query($sql);
$time_spent = 0;
$progress = 0;

@ -316,7 +316,7 @@ function who_is_online(
$query = "SELECT DISTINCT login_user_id, login_date
FROM ".$track_online_table." e
INNER JOIN ".$table_user." u ON (u.id = e.login_user_id)
WHERE u.active <> -1 AND u.status != ".ANONYMOUS." AND login_date >= '".$current_date."'
WHERE u.active <> ".USER_SOFT_DELETED." AND u.status != ".ANONYMOUS." AND login_date >= '".$current_date."'
ORDER BY `$column` $direction
LIMIT $from, $number_of_items";
}
@ -341,7 +341,7 @@ function who_is_online(
FROM ".$track_online_table." track
INNER JOIN ".$table_user." u
ON (u.id=track.login_user_id)
WHERE u.active <> -1 AND u.status != ".ANONYMOUS." AND track.access_url_id = $access_url_id AND
WHERE u.active <> ".USER_SOFT_DELETED." AND u.status != ".ANONYMOUS." AND track.access_url_id = $access_url_id AND
login_date >= '".$current_date."'
ORDER BY `$column` $direction
LIMIT $from, $number_of_items";
@ -400,7 +400,7 @@ function who_is_online_count($time_limit = null, $friends = false)
$query = "SELECT count(login_id) as count
FROM $track_online_table track INNER JOIN $table_user u
ON (u.id=track.login_user_id)
WHERE u.active <> -1 AND u.status != ".ANONYMOUS." AND login_date >= '$current_date' ";
WHERE u.active <> ".USER_SOFT_DELETED." AND u.status != ".ANONYMOUS." AND login_date >= '$current_date' ";
}
if (api_get_multiple_access_url()) {
@ -421,7 +421,7 @@ function who_is_online_count($time_limit = null, $friends = false)
$query = "SELECT count(login_id) as count FROM $track_online_table track
INNER JOIN $table_user u ON (u.id=track.login_user_id)
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
u.status != ".ANONYMOUS." AND
track.access_url_id = $access_url_id AND
login_date >= '$current_date' ";
@ -489,7 +489,7 @@ function who_is_online_in_this_course($from, $number_of_items, $uid, $time_limit
ON (o.login_user_id = u.id)
$urlJoin
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
u.status <> '".ANONYMOUS."' AND
o.c_id = $courseId AND
o.login_date >= '$current_date'
@ -547,7 +547,7 @@ function who_is_online_in_this_course_count(
ON (login_user_id = u.id)
$urlJoin
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
u.status <> '".ANONYMOUS."' AND
c_id = $courseId AND
login_date >= '$current_date'
@ -597,7 +597,7 @@ function whoIsOnlineInThisSessionCount($timeLimit, $sessionId)
ON (login_user_id = u.id)
$urlJoin
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
u.status <> '".ANONYMOUS."' AND
session_id = $sessionId AND
login_date >= '$current_date'

@ -447,7 +447,7 @@ class SessionManager
}
}
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> -1' : ' AND u.active <> -1';
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> '.USER_SOFT_DELETED : ' AND u.active <> '.USER_SOFT_DELETED;
$result_rows = Database::query($sql);
$row = Database::fetch_array($result_rows);
@ -4370,7 +4370,7 @@ class SessionManager
$sql .= " WHERE (au.access_url_id = $urlId OR au.access_url_id is null )";
}
$sql .= ' AND u.active <> -1 ORDER BY su.relation_type, ';
$sql .= ' AND u.active <> '.USER_SOFT_DELETED.' ORDER BY su.relation_type, ';
$sql .= api_sort_by_first_name() ? ' u.firstname, u.lastname' : ' u.lastname, u.firstname';
$result = Database::query($sql);
@ -6166,7 +6166,7 @@ class SessionManager
$sessionConditions = '';
$courseConditions = '';
$userConditions = ' AND u.active <> -1 ';
$userConditions = ' AND u.active <> '.USER_SOFT_DELETED.' ';
if (isset($active)) {
$active = (int) $active;
@ -7948,7 +7948,7 @@ class SessionManager
'getFullname'
);
} else {
$sql = "SELECT COUNT(1) FROM $tbl_user WHERE active <> -1 AND status = 1";
$sql = "SELECT COUNT(1) FROM $tbl_user WHERE active <> ".USER_SOFT_DELETED." AND status = 1";
$rs = Database::query($sql);
$countUsers = (int) Database::result($rs, 0, '0');

@ -143,7 +143,7 @@ class Statistics
$sql = "SELECT COUNT(DISTINCT(u.id)) AS number
FROM $user_table as u, $access_url_rel_user_table as url
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
u.id = url.user_id AND
access_url_id = $urlId
$status_filter $active_filter";
@ -163,7 +163,7 @@ class Statistics
} else {
$sql = "SELECT COUNT(DISTINCT(id)) AS number
FROM $user_table
WHERE 1 = 1 AND active <> -1 AND $status_filter $active_filter";
WHERE 1 = 1 AND active <> ".USER_SOFT_DELETED." AND $status_filter $active_filter";
if (isset($categoryCode)) {
$categoryCode = Database::escape_string($categoryCode);
$status_filter = isset($status) ? ' AND status = '.intval($status) : '';
@ -233,14 +233,14 @@ class Statistics
if (api_is_multiple_url_enabled()) {
$sql = "SELECT count(default_id) AS total_number_of_items
FROM $track_e_default, $table_user user, $access_url_rel_user_table url
WHERE user.active <> -1 AND
WHERE user.active <> ".USER_SOFT_DELETED." AND
default_user_id = user.id AND
user.id=url.user_id AND
access_url_id = '".$urlId."'";
} else {
$sql = "SELECT count(default_id) AS total_number_of_items
FROM $track_e_default, $table_user user
WHERE user.active <> -1 AND default_user_id = user.id ";
WHERE user.active <> ".USER_SOFT_DELETED." AND default_user_id = user.id ";
}
if (!empty($courseId)) {
@ -325,7 +325,7 @@ class Statistics
user.id as col6,
default_date as col7
FROM $track_e_default track_default, $table_user user
WHERE user.active <> -1 AND track_default.default_user_id = user.id ";
WHERE user.active <> ".USER_SOFT_DELETED." AND track_default.default_user_id = user.id ";
}
if (!empty($_GET['keyword'])) {
@ -867,7 +867,7 @@ class Statistics
$sql = "SELECT COUNT(*) AS n FROM $user_table as u $table ".
"WHERE LENGTH(picture_uri) > 0 $url_condition2";
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> -1' : ' AND u.active <> -1';
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> '.USER_SOFT_DELETED : ' AND u.active <> '.USER_SOFT_DELETED;
$res = Database::query($sql);
$count2 = Database::fetch_object($res);
@ -1048,14 +1048,14 @@ class Statistics
if (api_is_multiple_url_enabled()) {
$sql = "SELECT lastname, firstname, username, COUNT($field) AS count_message
FROM $access_url_rel_user_table as url, $message_table m
LEFT JOIN $user_table u ON m.$field = u.id AND u.active <> -1
LEFT JOIN $user_table u ON m.$field = u.id AND u.active <> ".USER_SOFT_DELETED."
WHERE url.user_id = m.$field AND access_url_id='".$urlId."'
GROUP BY m.$field
ORDER BY count_message DESC ";
} else {
$sql = "SELECT lastname, firstname, username, COUNT($field) AS count_message
FROM $message_table m
LEFT JOIN $user_table u ON m.$field = u.id AND u.active <> -1
LEFT JOIN $user_table u ON m.$field = u.id AND u.active <> ".USER_SOFT_DELETED."
GROUP BY m.$field ORDER BY count_message DESC ";
}
$res = Database::query($sql);
@ -1088,7 +1088,7 @@ class Statistics
$sql = "SELECT lastname, firstname, username, COUNT(friend_user_id) AS count_friend
FROM $access_url_rel_user_table as url, $user_friend_table uf
LEFT JOIN $user_table u
ON (uf.user_id = u.id) AND u.active <> -1
ON (uf.user_id = u.id) AND u.active <> ".USER_SOFT_DELETED."
WHERE
uf.relation_type <> '".UserRelUser::USER_RELATION_TYPE_RRHH."' AND
uf.user_id = url.user_id AND
@ -1099,7 +1099,7 @@ class Statistics
$sql = "SELECT lastname, firstname, username, COUNT(friend_user_id) AS count_friend
FROM $user_friend_table uf
LEFT JOIN $user_table u
ON (uf.user_id = u.id) AND u.active <> -1
ON (uf.user_id = u.id) AND u.active <> ".USER_SOFT_DELETED."
WHERE uf.relation_type <> '".UserRelUser::USER_RELATION_TYPE_RRHH."'
GROUP BY uf.user_id
ORDER BY count_friend DESC ";
@ -1472,7 +1472,7 @@ class Statistics
INNER JOIN $tblLogin l
ON u.id = l.login_user_id
$urlJoin
WHERE u.active <> -1 AND l.login_date BETWEEN '$startDate' AND '$endDate'
WHERE u.active <> ".USER_SOFT_DELETED." AND l.login_date BETWEEN '$startDate' AND '$endDate'
$urlWhere
GROUP BY u.id";

@ -278,7 +278,7 @@ class SubLanguageManager
$language_info = self::get_all_information_of_language($language_id);
$table = Database::get_main_table(TABLE_MAIN_USER);
$sql = 'SELECT count(*) AS count FROM '.$table.'
WHERE locale ="'.Database::escape_string($language_info['english_name']).'" AND active <> -1';
WHERE locale ="'.Database::escape_string($language_info['english_name']).'" AND active <> '.USER_SOFT_DELETED;
$rs = Database::query($sql);
if (Database::num_rows($rs) > 0 && Database::result($rs, '0', 'count') >= 1) {
return true;

@ -6490,7 +6490,7 @@ class Tracking
// Now fill users data
$sqlUsers = "SELECT id as user_id, username, lastname, firstname
FROM $tuser
WHERE active <> -1 AND id IN (".implode(',', $userIds).")";
WHERE active <> ".USER_SOFT_DELETED." AND id IN (".implode(',', $userIds).")";
$resUsers = Database::query($sqlUsers);
while ($rowUser = Database::fetch_assoc($resUsers)) {
$users[$rowUser['user_id']] = $rowUser;

@ -225,7 +225,7 @@ class UrlManager
public static function get_url_rel_user_data($urlId = 0, $order_by = null)
{
$urlId = (int) $urlId;
$where = ' WHERE u.active <> -1 ';
$where = ' WHERE u.active <> '.USER_SOFT_DELETED.' ';
$table_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$tbl_user = Database::get_main_table(TABLE_MAIN_USER);
if (!empty($urlId)) {

@ -1763,7 +1763,7 @@ class UserGroupModel extends Model
$sql = "SELECT u.* FROM $this->table_user u
INNER JOIN $this->usergroup_rel_user_table c
ON c.user_id = u.id
WHERE u.active <> -1 AND c.usergroup_id = $id"
WHERE u.active <> ".USER_SOFT_DELETED." AND c.usergroup_id = $id"
;
if (!empty($orderBy)) {
$orderBy = Database::escape_string($orderBy);
@ -2475,7 +2475,7 @@ class UserGroupModel extends Model
INNER JOIN $table_group_rel_user gu
ON (gu.user_id = u.id)
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
gu.usergroup_id= $group_id
$where_relation_condition
ORDER BY relation_type, firstname
@ -2520,7 +2520,7 @@ class UserGroupModel extends Model
FROM $tbl_user u
INNER JOIN $table_group_rel_user gu
ON (gu.user_id = u.id)
WHERE u.active <> -1 AND gu.usergroup_id= $group_id
WHERE u.active <> ".USER_SOFT_DELETED." AND gu.usergroup_id= $group_id
ORDER BY relation_type, firstname";
$result = Database::query($sql);

@ -1028,7 +1028,7 @@ class UserManager
$change_active = 0;
$isUserActive = $user->isActive();
if ($active != -1) {
if ($active != USER_SOFT_DELETED) {
if ($isUserActive != $active) {
$change_active = 1;
}
@ -3894,7 +3894,7 @@ class UserManager
INNER JOIN $table_user u
ON (u.id=admin.user_id)";
}
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> -1' : ' AND u.active <> -1';
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> '.USER_SOFT_DELETED : ' AND u.active <> '.USER_SOFT_DELETED;
$result = Database::query($sql);
$return = [];
if (Database::num_rows($result) > 0) {

@ -86,7 +86,7 @@ class ZombieManager
$sql .= ' AND user.active = 1';
}
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE user.active <> -1' : ' AND user.active <> -1';
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE user.active <> '.USER_SOFT_DELETED : ' AND user.active <> '.USER_SOFT_DELETED;
$sql .= " ORDER BY `$column` $direction";
if (!is_null($from) && !is_null($count)) {
$count = (int) $count;

@ -1,648 +0,0 @@
{% import '@ChamiloCore/Macros/box.html.twig' as display %}
{% autoescape false %}
<script>
/* Skill search input in the left menu */
function check_skills_sidebar() {
//Selecting only selected skills
$("#skill_id option").each(function () {
var skill_id = $(this).val();
if (skill_id != "") {
$.ajax({
url: "{{ url }}&a=skill_exists",
data: "skill_id=" + skill_id,
async: false,
success: function (return_value) {
if (return_value == 0) {
alert("{{ 'There is no such skill'|trans }}");
//Deleting select option tag
//$("#skill_id option[value="+skill_id+"]").remove();
$("#skill_id").empty();
//Deleting holder
$("#skill_search .holder li").each(function () {
if ($(this).attr("rel") == skill_id) {
$(this).remove();
}
});
} else {
$("#skill_id option[value=" + skill_id + "]").remove();
//Deleting holder
$("#skill_search .holder li").each(function () {
if ($(this).attr("rel") == skill_id) {
$(this).remove();
}
});
if ($('#skill_to_select_id_' + skill_id).length == 0) {
skill_info = get_skill_info(skill_id);
li = fill_skill_search_li(skill_id, skill_info.title);
$("#skill_holder").append(li);
}
}
}
});
}
});
}
function fill_skill_search_li(skill_id, skill_name, checked) {
var checked_condition = '',
activeCondition = '',
iconClassCondition = 'fa fa-square-o fa-fw';
if (checked) {
checked_condition = 'checked=checked';
activeCondition = 'active';
iconClassCondition = 'fa fa-check-square-o fa-fw';
}
return '\
<tr>\n\
<td>' + skill_name + '</td>\n\
<td class="text-right">\n\
<div class="btn-group btn-group-sm" data-toggle="buttons">\n\
<label class="btn btn--plain ' + activeCondition + '" aria-label="{{ 'Select'|trans }}" title="{{ 'Select to search'|trans }}">\n\
<input id="skill_to_select_id_' + skill_id + '" data-id="' + skill_id + '" name="' + skill_name + '" class="skill_to_select" type="checkbox" autocomplete="off" ' + checked_condition + '>\n\
<span class="' + iconClassCondition + '" aria-hidden="true"></span>\n\
</label>\n\
<button class="btn btn--plain load_wheel" aria-label="{{ 'Search'|trans }}" title="{{ 'Place on the wheel'|trans }}" data-id="' + skill_id + '">\n\
<span class="fa fa-crosshairs fa-fw" aria-hidden="true"></span>\n\
</button>\n\
</div>\n\
</td>\n\
</tr>';
}
function check_skills_edit_form() {
//selecting only selected parents
$("#parent_id option:selected").each(function () {
var skill_id = $(this).val();
if (skill_id != "") {
$.ajax({
async: false,
url: "{{ url }}&a=skill_exists",
data: "skill_id=" + skill_id,
success: function (return_value) {
if (return_value == 0) {
alert("{{ 'SkillDoesNotExist'|trans }}");
//Deleting select option tag
$("#parent_id").find('option').remove();
//Deleting holder
$("#skill_row .holder li").each(function () {
if ($(this).attr("rel") == skill_id) {
$(this).remove();
}
});
} else {
$("#parent_id").empty();
$("#skill_edit_holder").find('li').remove();
//Deleting holder
$("#skill_row .holder li").each(function () {
if ($(this).attr("rel") == skill_id) {
$(this).remove();
}
});
skill = get_skill_info(skill_id);
$("#skill_edit_holder").append('<li class="bit-box" id="skill_option_' + skill_id + '"> ' + skill.title + '</li>');
$("#parent_id").append('<option class="selected" selected="selected" value="' + skill_id + '"></option>');
}
}
});
}
});
}
function check_gradebook() {
//selecting only selected users
$("#gradebook_id option:selected").each(function () {
var gradebook_id = $(this).val();
if (gradebook_id != "") {
$.ajax({
url: "{{ url }}&a=gradebook_exists",
data: "gradebook_id=" + gradebook_id,
success: function (return_value) {
if (return_value == 0) {
alert("{{ 'GradebookDoesNotExist'|trans }}");
//Deleting select option tag
$("#gradebook_id option[value=" + gradebook_id + "]").remove();
//Deleting holder
$("#gradebook_row .holder li").each(function () {
if ($(this).attr("rel") == gradebook_id) {
$(this).remove();
}
});
} else {
//Deleting holder
$("#gradebook_row .holder li").each(function () {
if ($(this).attr("rel") == gradebook_id) {
$(this).remove();
}
});
if ($('#gradebook_item_' + gradebook_id).length == 0) {
gradebook = get_gradebook_info(gradebook_id);
if (gradebook) {
$("#gradebook_holder").append('<li id="gradebook_item_' + gradebook_id + '" class="bit-box"> ' + gradebook.title +
' <a rel="' + gradebook_id + '" class="closebutton" href="#"></a></li>');
}
}
}
}
});
}
});
}
function delete_gradebook_from_skill(skill_id, gradebook_id) {
$.ajax({
url: url + '&a=delete_gradebook_from_skill&skill_id=' + skill_id + '&gradebook_id=' + gradebook_id,
async: false,
success: function (result) {
//if (result == 1) {
$('#gradebook_item_' + gradebook_id).remove();
$("#gradebook_id option").each(function () {
if ($(this).attr("value") == gradebook_id) {
$(this).remove();
}
});
//}
}
});
}
function return_skill_list_from_profile_search() {
var skill_list = {};
if ($("#profile_search li").length != 0) {
$("#profile_search li").each(function (index) {
id = $(this).attr("id").split('_')[3];
if (id) {
skill_list[index] = id;
}
});
}
return skill_list;
}
function submit_profile_search_form() {
$("#skill_wheel").remove();
var skill_list = return_skill_list_from_profile_search();
if (skill_list.length != 0) {
skill_list = {'skill_id': skill_list};
skill_params = $.param(skill_list);
$.ajax({
url: url + '&a=profile_matches&' + skill_params,
async: false,
success: function (html) {
//users = jQuery.parseJSON(users);
$('#wheel_container').html(html);
}
});
}
//return skill;
}
function add_skill_in_profile_list(skill_id, skill_name) {
if ($('#profile_match_item_' + skill_id).length == 0) {
$('#profile_search').append('<li class="bit-box" id="profile_match_item_' + skill_id + '">' + skill_name +
' <a rel="' + skill_id + '" class="closebutton" href="#"></a> </li>');
} else {
$('#profile_match_item_' + skill_id).remove();
}
toogle_save_profile_form();
}
function toogle_save_profile_form() {
//Hiding showing the save this search
if ($('#profile_search li').length == 0) {
$('#profile-options-container').hide();
} else {
$('#profile-options-container').show();
}
}
$(function() {
/* Skill search */
// Tool tip (in exercises)
var tip_options = {
placement: 'right'
}
$('.tooltip_skill').tooltip(tip_options);
/* Skill item list onclick */
$("#skill_holder").on("change", "input.skill_to_select", function () {
var self = $(this);
skill_id = self.data('id') || 0;
skill_name = self.attr('name');
add_skill_in_profile_list(skill_id, skill_name);
if (this.checked) {
self.next('.fa').replaceWith('<span class="fa fa-check-square-o fa-fw" aria-hidden="true"></span>');
} else {
self.next('.fa').replaceWith('<span class="fa fa-square-o fa-fw" aria-hidden="true"></span>');
}
});
/* URL link when searching skills */
$("#skill_holder").on("click", "button.load_wheel", function (e) {
e.preventDefault();
skill_id = $(this).data('id') || 0;
skill_to_load_from_get = 0;
load_nodes(skill_id, main_depth);
});
/* URL link when searching skills */
$("a.load_root").on("click", function (e) {
e.preventDefault();
skill_id = $(this).attr('rel');
skill_to_load_from_get = 0;
load_nodes(skill_id, main_depth);
});
/* Profile matcher */
/* Submit button */
$("#search_profile_form").submit(function () {
submit_profile_search_form();
return false;
});
$("form#save_profile_form_button").on('submit', function (e) {
e.preventDefault();
var profileId = parseInt($('input[name="profile_id"]').val());
var getProfileInfo = $.getJSON(
'{{ url }}',
{
a: 'get_profile',
profile_id: profileId
}
);
$.when(getProfileInfo).done(function (profileInfo) {
$("#name_profile").val(profileInfo.title);
$("#description_profile").val(profileInfo.description);
$('#frm-save-profile').modal('show');
});
});
/* Close button in profile matcher items */
$("#profile_search").on("click", "a.closebutton", function () {
skill_id = $(this).attr('rel');
$('input[id=skill_to_select_id_' + skill_id + ']').attr('checked', false);
$('#profile_match_item_' + skill_id).remove();
submit_profile_search_form();
toogle_save_profile_form();
});
// Fill saved profiles list
update_my_saved_profiles();
/* Click in profile */
$("#saved_profiles").on("click", "button.skill-wheel-load-profile", function (e) {
e.preventDefault();
profile_id = $(this).data('id') || 0;
$('input[name="profile_id"]').val(profile_id);
$.ajax({
url: '{{ url }}&a=get_skills_by_profile&profile_id=' + profile_id,
success: function (json) {
$('#profile_search').empty();
$('#skill_holder').empty();
skill_list = $.parseJSON(json);
$.each(skill_list, function (index, skill_id) {
skill_info = get_skill_info(skill_id);
li = fill_skill_search_li(skill_id, skill_info.title, 1);
$("#skill_holder").append(li);
add_skill_in_profile_list(skill_id, skill_info.title);
});
submit_profile_search_form();
}
});
});
$("#saved_profiles").on('click', 'button.skill-wheel-delete-profile', function (e) {
e.preventDefault();
var self = $(this),
profileId = self.data('id') || 0;
$.getJSON('{{ url }}&a=delete_profile', {
profile: profileId
}, function (response) {
if (response.status) {
update_my_saved_profiles();
}
});
});
/* Wheel skill popup form */
/* Close button in gradebook select */
$("#gradebook_holder").on("click", "a.closebutton", function () {
gradebook_id = $(this).attr('rel');
skill_id = $('input[name="id"]').attr('value');
delete_gradebook_from_skill(skill_id, gradebook_id);
});
$("#skill_id").select2({
ajax: {
url: '{{ url }}&a=find_skills',
processResults: function (data) {
return {
results: data.items
};
}
},
cache: false,
placeholder: '{{ 'Enter the skill name to search'|trans }}'
}).on('change', function () {
check_skills_sidebar();
});
load_nodes(0, main_depth);
function update_my_saved_profiles() {
$.ajax({
url: '{{ url }}&a=get_saved_profiles',
success: function (data) {
$("#saved_profiles").html(data);
}
});
}
/* change background color */
$('#skill-change-background-options li a').on('click', function (e) {
e.preventDefault();
var newBackgroundColor = $(this).data('color') || '#FFF';
$("#page-back").css("background", newBackgroundColor);
});
/* Generated random colour */
/*
function colour(d) {
if (d.children) {
// There is a maximum of two children!
var colours = d.children.map(colour),
a = d3.hsl(colours[0]),
b = d3.hsl(colours[1]);
// L*a*b* might be better here...
return d3.hsl((a.h + b.h) / 2, a.s * 1.2, a.levels_to_show / 1.2);
}
return d.colour || "#fff";
}*/
$('#form-button-edit').on('click', function (e) {
e.preventDefault();
if (SkillWheel.currentSkill === null) {
return;
}
window.location.href = "{{ url('legacy_main', {'name': 'skills/skill_edit.php?id=' }) }}" + SkillWheel.currentSkill.id;
});
$('#form-button-create-child').on('click', function (e) {
e.preventDefault();
if (SkillWheel.currentSkill === null) {
return;
}
window.location.href = "{{ url('legacy_main', {'name': 'skills/skill_create.php?parent=' }) }}" + SkillWheel.currentSkill.id;
});
$('#form-button-add-to-profile').on('click', function (e) {
e.preventDefault();
if (SkillWheel.currentSkill === null) {
return;
}
add_skill_in_profile_list(SkillWheel.currentSkill.id, SkillWheel.currentSkill.title);
});
$('#frm-save-profile').on('hidden.bs.modal', function () {
$("#name_profile").val('');
$("#description_profile").val('');
$('input[name="profile_id"]').val(0);
});
$('#form-button-save-profile').on('click', function (e) {
e.preventDefault();
var saveProfile = $.ajax(
'{{ url }}',
{
data: {
a: 'save_profile',
name: $("#name_profile").val(),
description: $("#description_profile").val(),
skill_id: return_skill_list_from_profile_search(),
profile: $('input[name="profile_id"]').val()
}
}
);
$.when(saveProfile).done(function (response) {
if (parseInt(response) === 1) {
update_my_saved_profiles();
alert("{{ "Saved" | trans }}");
} else {
alert("{{ "Error" | trans }}");
}
$('#frm-save-profile').modal('hide');
});
});
$(".facebook-auto").css("width","100%");
$(".facebook-auto ul").css("width","100%");
$("ul.holder").css("width","100%");
});
</script>
<div id="page-back" class="page-skill">
<div class="container-fluid">
<div class="row">
<div class="col-md-3 skill-options">
<div class="skill-home">
<a class="btn btn-large btn-block btn--primary" href="{{ url('courses') }}">
<em class="fa fa-home"></em> {{ "Return to the course list"|trans }}
</a>
</div>
<div class="card">
<div class="card-body">
<div id="saved_profiles"></div>
<h4 class="page-header">{{ 'What skills are you looking for?'|trans }}</h4>
<div class="search-skill">
<form id="skill_search" class="form-search">
<select id="skill_id" name="skill_id" style="width: 100%;" multiple></select>
<table id="skill_holder" class="table table-condensed"></table>
</form>
</div>
<div class="search-profile-skill">
<ul id="profile_search" class="holder holder_simple hide"></ul>
<form id="search_profile_form" class="form-search">
<button class="btn btn--plain btn-block" type="submit">
<em class="fa fa-search"></em> {{ "Search profile matches"|trans }}
</button>
</form>
<h4 class="page-header">{{ 'Is this what you were looking for?'|trans }}</h4>
<form id="save_profile_form_button" class="form-search">
<button class="btn btn--plain btn-block" type="submit">
<em class="fa fa-floppy-o"></em> {{ "Save this search"|trans }}
</button>
</form>
</div>
<hr>
<p>
<a class="btn btn-block btn--primary load_root" rel="0" href="#">
<em class="fa fa-eye"></em> {{ "View skills wheel"|trans }}
</a>
</p>
</div>
</div>
<div class="accordion" id="wheel-second-accordion" role="tablist" aria-multiselectable="true">
<div class="card">
<div class="card-header" role="tab" id="wheel-legend-heading">
<h4 class="card-title">
<a role="button" data-toggle="collapse" data-parent="#wheel-second-accordion"
href="#wheel-legend-collapse" aria-expanded="true" aria-controls="wheel-legend-collapse">
{{ "Legend"|trans }}
</a>
</h4>
</div>
<div id="wheel-legend-collapse" class="collapse in" role="tabpanel" aria-labelledby="wheel-legend-heading">
<div class="card-body">
<ul class="fa-ul">
<li>
<em class="fa fa-li fa-square skill-legend-basic"></em> {{ "Basic skills"|trans }}
</li>
<li>
<em class="fa fa-li fa-square skill-legend-add"></em> {{ "Skills you can learn"|trans }}
</li>
<li>
<em class="fa fa-li fa-square skill-legend-search"></em> {{ "Skills searched for"|trans }}
</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header" role="tab" id="wheel-display-heading">
<h4 class="card-title">
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#wheel-second-accordion"
href="#wheel-display-collapse" aria-expanded="false" aria-controls="wheel-display-collapse">
{{ 'Display options' | trans }}
</a>
</h4>
</div>
<div id="wheel-display-collapse" class="collapse" role="tabpanel" aria-labelledby="wheel-display-heading">
<div class="card-body">
<p>{{ 'Choose a background color' | trans }}</p>
<ul class="list-unstyled" id="skill-change-background-options">
<li><a href="#" data-color="#FFFFFF">{{ 'White' | trans }}</a></li>
<li><a href="#" data-color="#000000">{{ 'Black' | trans }}</a></li>
<li><a href="#" data-color="#A9E2F3">{{ 'Light blue' }}</a></li>
<li><a href="#" data-color="#848484">{{ 'Gray' | trans }}</a></li>
<li><a href="#" data-color="#F7F8E0">{{ 'Corn' | trans }}</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div id="wheel_container" class="col-md-9">
<div id="skill_wheel">
<img src="">
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="frm-skill" tabindex="-1" role="dialog" aria-labelledby="form-skill-title" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="{{ "Close" | trans }}">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title" id="form-skill-title">{{ "Skill" | trans }}</h4>
</div>
<div class="modal-body">
{{ dialogForm }}
</div>
<div class="modal-footer">
<button id="form-button-edit" class="btn btn--primary">
<em class="fa fa-edit"></em> {{ "Edit" | trans }}
</button>
<button id="form-button-create-child" class="btn btn--primary">
<em class="fa fa-plus"></em> {{ "Create child skill" | trans }}
</button>
<button id="form-button-add-to-profile" class="btn btn--primary">
<em class="fa fa-check"></em> {{ "Add skill to profile search" | trans }}
</button>
<button type="button" class="btn btn--primary" data-dismiss="modal">
<em class="fa fa-close"></em> {{ "Close" | trans }}
</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="frm-save-profile" tabindex="-1" role="dialog" aria-labelledby="form-save-profile-title" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="{{ "Close" | trans }}">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title" id="form-save-profile-title">
{{ "Skill profile" | trans }}
</h4>
</div>
<div class="modal-body">
{{ save_profile_form }}
</div>
<div class="modal-footer">
<button id="form-button-save-profile" class="btn btn--primary">
<em class="fa fa-save"></em> {{ "Save" | trans }}
</button>
<button type="button" class="btn btn--primary" data-dismiss="modal">
<em class="fa fa-close"></em> {{ "Close" | trans }}
</button>
</div>
</div>
</div>
</div>
{% endautoescape %}

@ -117,7 +117,7 @@ if ('true' === $allowTutors) {
// search users where username or firstname or lastname begins likes $needle
$sql = 'SELECT user.user_id, username, lastname, firstname
FROM '.$tbl_user.' user
WHERE user.active <> -1 AND (username LIKE "'.$needle.'%" OR firstname LIKE "'.$needle.'%"
WHERE user.active <> '.USER_SOFT_DELETED.' AND (username LIKE "'.$needle.'%" OR firstname LIKE "'.$needle.'%"
OR lastname LIKE "'.$needle.'%") AND user.status<>6 AND user.status<>'.DRH.''.
$order_clause.
' LIMIT 11';
@ -125,7 +125,7 @@ if ('true' === $allowTutors) {
case 'multiple':
$sql = 'SELECT user.user_id, username, lastname, firstname
FROM '.$tbl_user.' user
WHERE user.active <> -1 AND '.(api_sort_by_first_name() ? 'firstname' : 'lastname').'
WHERE user.active <> '.USER_SOFT_DELETED.' AND '.(api_sort_by_first_name() ? 'firstname' : 'lastname').'
LIKE "'.$needle.'%" AND
user.status<>'.DRH.' AND
user.status<>6 '.$cond_user_id.
@ -136,7 +136,7 @@ if ('true' === $allowTutors) {
FROM '.$tbl_user.' user
LEFT OUTER JOIN '.$tbl_session_rel_user.' s ON (s.user_id = user.user_id)
WHERE
user.active <> -1 AND
user.active <> '.USER_SOFT_DELETED.' AND
s.user_id IS NULL AND
user.status <>'.DRH.' AND
user.status <> 6 '.$cond_user_id.
@ -155,7 +155,7 @@ if ('true' === $allowTutors) {
INNER JOIN '.$tbl_user_rel_access_url.' url_user
ON (url_user.user_id=user.user_id)
WHERE
user.active <> -1 AND
user.active <> '.USER_SOFT_DELETED.' AND
access_url_id = '.$access_url_id.' AND
(username LIKE "'.$needle.'%" OR firstname LIKE "'.$needle.'%" OR lastname LIKE "'.$needle.'%") AND
user.status<>6 AND
@ -168,7 +168,7 @@ if ('true' === $allowTutors) {
FROM '.$tbl_user.' user
INNER JOIN '.$tbl_user_rel_access_url.' url_user
ON (url_user.user_id=user.user_id)
WHERE user.active <> -1 AND access_url_id = '.$access_url_id.' AND
WHERE user.active <> '.USER_SOFT_DELETED.' AND access_url_id = '.$access_url_id.' AND
'.(api_sort_by_first_name() ? 'firstname' : 'lastname').' LIKE "'.$needle.'%" AND user.status<>'.DRH.' AND user.status<>6 '.$cond_user_id.
$order_clause;
break;
@ -180,7 +180,7 @@ if ('true' === $allowTutors) {
INNER JOIN '.$tbl_user_rel_access_url.' url_user
ON (url_user.user_id=user.user_id)
WHERE
user.active <> -1 AND
user.active <> '.USER_SOFT_DELETED.' AND
access_url_id = '.$access_url_id.' AND
s.user_id IS null AND
user.status<>'.DRH.' AND
@ -299,7 +299,7 @@ if ('true' === $allowTutors) {
$tbl_session_rel_user.user_id = u.id AND
$tbl_session_rel_user.relation_type = ".Session::STUDENT." AND
$tbl_session_rel_user.session_id = ".intval($id_session)."
WHERE u.active <> -1 AND u.status <> ".DRH." AND u.status<>6 $order_clause";
WHERE u.active <> ".USER_SOFT_DELETED." AND u.status <> ".DRH." AND u.status<>6 $order_clause";
if (api_is_multiple_url_enabled()) {
$tbl_user_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
@ -314,7 +314,7 @@ if ('true' === $allowTutors) {
$tbl_session_rel_user.session_id = ".intval($id_session)."
INNER JOIN $tbl_user_rel_access_url url_user
ON (url_user.user_id=u.user_id)
WHERE u.active <> -1 AND access_url_id = $access_url_id AND u.status<>".DRH." AND u.status<>6
WHERE u.active <> ".USER_SOFT_DELETED." AND access_url_id = $access_url_id AND u.status<>".DRH." AND u.status<>6
$order_clause";
}
}
@ -385,7 +385,7 @@ if ('true' === $allowTutors) {
ON $tbl_session_rel_user.user_id = u.id AND
$tbl_session_rel_user.session_id = '$id_session' AND
$tbl_session_rel_user.relation_type = ".Session::STUDENT."
$where_filter AND u.status<>".DRH." AND u.status<>6 AND u.active <> -1
$where_filter AND u.status<>".DRH." AND u.status<>6 AND u.active <> ".USER_SOFT_DELETED."
$order_clause";
} else {
$sql = "SELECT u.id as user_id, lastname, firstname, username, session_id
@ -394,7 +394,7 @@ if ('true' === $allowTutors) {
ON $tbl_session_rel_user.user_id = u.id AND
$tbl_session_rel_user.session_id = '$id_session' AND
$tbl_session_rel_user.relation_type = ".Session::STUDENT."
WHERE u.status <> ".DRH." AND u.status<>6 AND u.active <> -1
WHERE u.status <> ".DRH." AND u.status<>6 AND u.active <> ".USER_SOFT_DELETED."
$order_clause";
}
@ -410,7 +410,7 @@ if ('true' === $allowTutors) {
$tbl_session_rel_user.session_id = '$id_session' AND
$tbl_session_rel_user.relation_type = ".Session::STUDENT."
INNER JOIN $tbl_user_rel_access_url url_user ON (url_user.user_id=u.user_id)
WHERE access_url_id = $access_url_id $where_filter AND u.status<>".DRH." AND u.status<>6 AND u.active <> -1
WHERE access_url_id = $access_url_id $where_filter AND u.status<>".DRH." AND u.status<>6 AND u.active <> ".USER_SOFT_DELETED."
$order_clause";
}
}
@ -438,7 +438,7 @@ if ('true' === $allowTutors) {
$tbl_session_rel_user.user_id = u.id AND
$tbl_session_rel_user.session_id = '$id_session' AND
$tbl_session_rel_user.relation_type = ".Session::STUDENT."
WHERE u.active <> -1 AND u.status <> ".DRH." AND u.status<>6 $order_clause";
WHERE u.active <> ".USER_SOFT_DELETED." AND u.status <> ".DRH." AND u.status<>6 $order_clause";
if (api_is_multiple_url_enabled()) {
$tbl_user_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
@ -452,7 +452,7 @@ if ('true' === $allowTutors) {
$tbl_session_rel_user.session_id = '$id_session' AND
$tbl_session_rel_user.relation_type = ".Session::STUDENT."
INNER JOIN $tbl_user_rel_access_url url_user ON (url_user.user_id=u.user_id)
WHERE u.active <> -1 AND access_url_id = $access_url_id AND u.status<>".DRH." AND u.status<>6
WHERE u.active <> ".USER_SOFT_DELETED." AND access_url_id = $access_url_id AND u.status<>".DRH." AND u.status<>6
$order_clause";
}
}

@ -230,14 +230,14 @@ if ('true' === $allowTutors) {
INNER JOIN $tbl_session_rel_user su
ON u.id = su.user_id AND su.relation_type = ".Session::STUDENT."
LEFT OUTER JOIN $table_access_url_user uu ON (uu.user_id = u.id)
WHERE u.active <> -1 AND su.session_id = $id_session AND (access_url_id = $url_id OR access_url_id is null )
WHERE u.active <> ".USER_SOFT_DELETED." AND su.session_id = $id_session AND (access_url_id = $url_id OR access_url_id is null )
$order_clause";
} else {
$sql = "SELECT u.id as user_id, lastname, firstname, username
FROM $tbl_user u
INNER JOIN $tbl_session_rel_user su
ON u.id = su.user_id AND su.relation_type = ".Session::STUDENT."
AND su.session_id = ".$id_session." WHERE u.active <> -1 ".$order_clause;
AND su.session_id = ".$id_session." WHERE u.active <> ".USER_SOFT_DELETED.$order_clause;
}
$result = Database::query($sql);

@ -253,7 +253,7 @@ function get_number_of_users()
c_id = $courseId AND
session_id = $sessionId
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
cu.user_id IS NULL
$teacherRoleFilter AND
(u.official_code <> 'ADMIN' OR u.official_code IS NULL) ";
@ -271,7 +271,7 @@ function get_number_of_users()
INNER JOIN $tbl_url_rel_user as url_rel_user
ON (url_rel_user.user_id = u.id)
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
cu.user_id IS NULL AND
access_url_id = $url_access_id
$teacherRoleFilter AND
@ -285,7 +285,7 @@ function get_number_of_users()
LEFT JOIN $course_user_table cu
ON u.id = cu.user_id and c_id = $courseId
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
cu.user_id IS NULL
$teacherRoleFilter ";
@ -301,7 +301,7 @@ function get_number_of_users()
INNER JOIN $tbl_url_rel_user as url_rel_user
ON (url_rel_user.user_id = u.id)
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
cu.user_id IS NULL
$teacherRoleFilter AND
access_url_id = $url_access_id ";
@ -319,7 +319,7 @@ function get_number_of_users()
c_id = $courseId AND
session_id = $sessionId
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
cu.user_id IS NULL
$studentRoleFilter AND
(u.official_code <> 'ADMIN' OR u.official_code IS NULL) ";
@ -338,7 +338,7 @@ function get_number_of_users()
INNER JOIN $tbl_url_rel_user as url_rel_user
ON (url_rel_user.user_id = u.id)
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
cu.user_id IS NULL
$studentRoleFilter AND
access_url_id = $url_access_id AND
@ -422,7 +422,7 @@ function get_number_of_users()
$users_of_course[] = $course_user['user_id'];
}
}
$sql .= " AND u.status <> ".ANONYMOUS." AND u.active <> -1 ";
$sql .= " AND u.status <> ".ANONYMOUS." AND u.active <> ".USER_SOFT_DELETED." ";
$res = Database::query($sql);
$count_user = 0;
@ -710,7 +710,7 @@ function get_user_data($from, $number_of_items, $column, $direction)
}
}
$sql .= " AND u.status != ".ANONYMOUS." AND u.active <> -1 ";
$sql .= " AND u.status != ".ANONYMOUS." AND u.active <> ".USER_SOFT_DELETED." ";
$column = (int) $column;
$direction = !in_array(strtolower(trim($direction)), ['asc', 'desc']) ? 'asc' : $direction;
// Sorting and pagination (used by the sortable table)

@ -233,7 +233,7 @@ if (isset($_GET['action'])) {
$sql .= ' , '.Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER).' au ';
}
$sql .= "
WHERE user.active <> -1 AND c_id = $courseId
WHERE user.active <> ".USER_SOFT_DELETED." AND c_id = $courseId
AND session_course_user.user_id = user.id
AND session_id = $sessionId
";
@ -321,7 +321,7 @@ if (isset($_GET['action'])) {
$sql .= ' , '.Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER).' au ';
}
$sql .= " WHERE
user.active <> -1 AND
user.active <> ".USER_SOFT_DELETED." AND
c_id = '$courseId' AND
course_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
course_user.user_id = user.id ";

@ -77,7 +77,7 @@ if (strlen($course_code) > 0) {
ON (u.id = cu.user_id)
$extraUrlJoin
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
cu.c_id = $courseId AND
cu.relation_type<>".COURSE_RELATION_TYPE_RRHH."
$extraUrlCondition
@ -89,7 +89,7 @@ if (strlen($course_code) > 0) {
ON (u.id = scu.user_id)
$extraUrlJoin
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
scu.c_id = $courseSessionId AND
scu.session_id = $sessionId
$extraUrlCondition
@ -101,7 +101,7 @@ if (strlen($course_code) > 0) {
ON (u.id = su.user_id)
$extraUrlJoin
WHERE
u.active <> -1 AND
u.active <> ".USER_SOFT_DELETED." AND
su.session_id = $sessionId
$extraUrlCondition
ORDER BY lastname,firstname";
@ -114,11 +114,11 @@ if (strlen($course_code) > 0) {
$sql .= " FROM $userTable u
INNER JOIN $tbl_user_rel_access_url as user_rel_url
ON (u.id = user_rel_url.user_id)
WHERE u.active <> -1 AND access_url_id = $access_url_id
WHERE u.active <> ".USER_SOFT_DELETED." AND access_url_id = $access_url_id
ORDER BY lastname,firstname";
}
} else {
$sql .= " FROM $userTable u WHERE u.active <> -1 ORDER BY lastname,firstname";
$sql .= " FROM $userTable u WHERE u.active <> ".USER_SOFT_DELETED." ORDER BY lastname,firstname";
}
$filename = 'export_users_'.api_get_local_time();
}

@ -14,4 +14,9 @@ abstract class AbstractResource
'ctool:read',
])]
public ?string $illustrationUrl = null;
#[Groups([
'calendar_event:read',
])]
public ?array $resourceLinkListFromEntity = null;
}

@ -7,10 +7,11 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\ApiResource;
use Chamilo\CoreBundle\Entity\ResourceNode;
use Chamilo\CourseBundle\Entity\CCalendarEvent;
use DateTime;
use Symfony\Component\Serializer\Annotation\Groups;
class CalendarEvent
class CalendarEvent extends AbstractResource
{
public function __construct(
#[Groups(['calendar_event:read'])]
@ -28,6 +29,19 @@ class CalendarEvent
#[Groups(['calendar_event:read'])]
public ?string $url = null,
#[Groups(['calendar_event:read'])]
public ?string $invitationType = null,
#[Groups(['calendar_event:read'])]
public bool $collective = false,
#[Groups(['calendar_event:read'])]
public int $subscriptionVisibility = CCalendarEvent::SUBSCRIPTION_VISIBILITY_NO,
#[Groups(['calendar_event:read'])]
public ?int $subscriptionItemId = null,
#[Groups(['calendar_event:read'])]
public int $maxAttendees = 0,
#[Groups(['calendar_event:read'])]
public ?ResourceNode $resourceNode = null,
) {}
?array $resourceLinkListFromEntity = null,
) {
$this->resourceLinkListFromEntity = $resourceLinkListFromEntity;
}
}

@ -60,4 +60,6 @@ enum StateIcon: string
case ONLINE = 'account-check';
// Offline (for a user)
case OFFLINE = 'account-off';
// Soft deleted (for a user)
case REJECT = 'cancel';
}

@ -7,23 +7,25 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\DataProvider\Extension;
use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
// use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface;
// use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Entity\Usergroup;
use Chamilo\CoreBundle\ServiceHelper\CidReqHelper;
use Chamilo\CoreBundle\Settings\SettingsManager;
use Chamilo\CourseBundle\Entity\CCalendarEvent;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Security;
use UserGroupModel;
final class CCalendarEventExtension implements QueryCollectionExtensionInterface // , QueryItemExtensionInterface
final class CCalendarEventExtension implements QueryCollectionExtensionInterface
{
use CourseLinkExtensionTrait;
public function __construct(
private readonly Security $security,
private readonly RequestStack $requestStack
private readonly CidReqHelper $cidReqHelper,
private readonly SettingsManager $settingsManager,
) {}
public function applyToCollection(
@ -42,8 +44,19 @@ final class CCalendarEventExtension implements QueryCollectionExtensionInterface
return;
}
/** @var User $user */
$courseId = $this->cidReqHelper->getCourseId();
$sessionId = $this->cidReqHelper->getSessionId();
$groupId = $this->cidReqHelper->getGroupId();
/** @var ?User $user */
$user = $this->security->getUser();
$inCourseBase = !empty($courseId);
$inSession = !empty($sessionId);
$inCourseSession = $inCourseBase && $inSession;
$inPersonalList = !$inCourseBase && !$inCourseSession;
$alias = $qb->getRootAliases()[0];
$qb
@ -51,27 +64,54 @@ final class CCalendarEventExtension implements QueryCollectionExtensionInterface
->leftJoin('node.resourceLinks', 'resource_links')
;
$request = $this->requestStack->getCurrentRequest();
$courseId = $request->query->getInt('cid');
$sessionId = $request->query->getInt('sid');
$groupId = $request->query->getInt('gid');
if ($inPersonalList && $user) {
$this->addPersonalCalendarConditions($qb, $user);
}
}
$inCourseBase = !empty($courseId);
$inSession = !empty($sessionId);
$inCourseSession = $inCourseBase && $inSession;
private function addPersonalCalendarConditions(QueryBuilder $qb, User $user): void
{
$qb
->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('resource_links.user', ':user'),
$qb->expr()->eq('node.creator', ':user')
)
)
->setParameter('user', $user->getId())
;
$inPersonalList = !$inCourseBase && !$inCourseSession;
if ('true' === $this->settingsManager->getSetting('agenda.agenda_event_subscriptions')) {
$this->addSubscriptionsConditions($qb, $user);
}
}
private function addSubscriptionsConditions(QueryBuilder $qb, User $user): void
{
$groupList = (new UserGroupModel())->getUserGroupListByUser($user->getId(), Usergroup::NORMAL_CLASS);
$groupIdList = $groupList ? array_column($groupList, 'id') : [];
if ($inPersonalList) {
$qb
->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('resource_links.user', ':user'),
$qb->expr()->eq('node.creator', ':user')
)
$alias = $qb->getRootAliases()[0];
$expr = $qb->expr()->orX(
$qb->expr()->eq("$alias.subscriptionVisibility", ':visibility_all'),
);
if ($groupIdList) {
$expr->add(
$qb->expr()->orX(
$qb->expr()->eq("$alias.subscriptionVisibility", ':visibility_class'),
$qb->expr()->in("$alias.subscriptionItemId", ':item_id_list')
)
->setParameter('user', $user->getId())
;
);
$qb->setParameter('visibility_class', CCalendarEvent::SUBSCRIPTION_VISIBILITY_CLASS);
$qb->setParameter('item_id_list', $groupIdList);
}
$qb
->orWhere($expr)
->setParameter(':visibility_all', CCalendarEvent::SUBSCRIPTION_VISIBILITY_ALL)
;
}
}

@ -38,6 +38,8 @@ class CalendarEventTransformer implements DataTransformerInterface
{
\assert($object instanceof CCalendarEvent);
$object->setResourceLinkListFromEntity();
return new CalendarEvent(
'calendar_event_'.$object->getIid(),
$object->getTitle(),
@ -46,7 +48,13 @@ class CalendarEventTransformer implements DataTransformerInterface
$object->getEndDate(),
$object->isAllDay(),
null,
$object->getInvitationType(),
$object->isCollective(),
$object->getSubscriptionVisibility(),
$object->getSubscriptionItemId(),
$object->getMaxAttendees(),
$object->getResourceNode(),
$object->getResourceLinkListFromEntity(),
);
}

@ -9,8 +9,15 @@ namespace Chamilo\CoreBundle\Entity;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use Chamilo\CoreBundle\DataProvider\SkillDataProvider;
use Chamilo\CoreBundle\Dto\SkillInputDto;
use Chamilo\CoreBundle\Repository\SkillRepository;
use Chamilo\CoreBundle\State\SkillPostProcessor;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
@ -20,7 +27,55 @@ use Stringable;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
#[ApiResource(security: 'is_granted(\'ROLE_ADMIN\')', normalizationContext: ['groups' => ['skill:read']])]
#[ApiResource(
operations: [
new GetCollection(
uriTemplate: '/skills/options',
normalizationContext: ['groups' => ['skill:read']],
security: "is_granted('ROLE_USER')",
name: 'get_skill_options',
provider: SkillDataProvider::class
),
new GetCollection(
uriTemplate: '/skills/gradebook/options',
normalizationContext: ['groups' => ['skill:read']],
security: "is_granted('ROLE_USER')",
name: 'get_skill_gradebook_options',
provider: SkillDataProvider::class
),
new GetCollection(
uriTemplate: '/skills/all',
normalizationContext: ['groups' => ['skill:read']],
security: "is_granted('ROLE_USER')",
name: 'get_all_skills',
provider: SkillDataProvider::class
),
new GetCollection(
uriTemplate: '/skills/user/{user_id}',
normalizationContext: ['groups' => ['skill:read']],
security: "is_granted('ROLE_USER')",
name: 'get_skills_by_user',
provider: SkillDataProvider::class
),
new Post(
securityPostDenormalize: "is_granted('ROLE_USER')",
input: SkillInputDto::class,
processor: SkillPostProcessor::class
),
new Get(
security: "is_granted('ROLE_USER')"
),
new Delete(security: "is_granted('DELETE', object)"),
new Put(security: "is_granted('EDIT', object)"),
],
normalizationContext: [
'groups' => ['skill:read'],
],
denormalizationContext: [
'groups' => ['skill:write'],
],
security: "is_granted('ROLE_USER')",
)]
#[ApiFilter(SearchFilter::class, properties: ['issuedSkills.user' => 'exact'])]
#[ORM\Table(name: 'skill')]
#[ORM\Entity(repositoryClass: SkillRepository::class)]
@ -79,6 +134,7 @@ class Skill implements Stringable
#[ORM\Column(name: 'description', type: 'text', nullable: false)]
protected string $description;
#[Assert\NotNull]
#[Groups(['skill:read', 'skill:write'])]
#[ORM\Column(name: 'access_url_id', type: 'integer', nullable: false)]
protected int $accessUrlId;
#[Groups(['skill:read', 'skill_rel_user:read'])]
@ -87,6 +143,7 @@ class Skill implements Stringable
#[ORM\ManyToOne(targetEntity: Asset::class, cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(name: 'asset_id', referencedColumnName: 'id')]
protected ?Asset $asset = null;
#[Groups(['skill:read', 'skill:write'])]
#[ORM\Column(name: 'criteria', type: 'text', nullable: true)]
protected ?string $criteria = null;
#[ORM\Column(name: 'status', type: 'integer', nullable: false, options: ['default' => 1])]

@ -93,6 +93,12 @@ class User implements UserInterface, EquatableInterface, ResourceInterface, Reso
public const STUDENT = 5;
public const ANONYMOUS = 6;*/
// User active field constants
public const ACTIVE = 1;
public const INACTIVE = 0;
public const INACTIVE_AUTOMATIC = -1;
public const SOFT_DELETED = -2;
#[Groups(['user_json:read'])]
#[ORM\OneToOne(targetEntity: ResourceNode::class, cascade: ['persist'])]
#[ORM\JoinColumn(name: 'resource_node_id', onDelete: 'CASCADE')]
@ -931,7 +937,8 @@ class User implements UserInterface, EquatableInterface, ResourceInterface, Reso
}*/
/**
* Get a bool on whether the user is active or not. Active can be "-1" which means pre-deleted, and is returned as false (not active)
* Get a bool on whether the user is active or not. Active can be "-1" which means pre-deleted, and is returned as false (not active).
*
* @return bool True if active = 1, false in any other case (0 = inactive, -1 = predeleted)
*/
public function getIsActive(): bool

@ -159,7 +159,7 @@ class UserRepository extends ResourceRepository implements PasswordUpgraderInter
$em->remove($user);
} else {
$user->setActive(-1);
$user->setActive(User::SOFT_DELETED);
$em->persist($user);
}

@ -10,6 +10,7 @@ use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Entity\Usergroup;
use Chamilo\CoreBundle\Entity\UsergroupRelUser;
use Chamilo\CoreBundle\Repository\ResourceRepository;
use Chamilo\CoreBundle\ServiceHelper\AccessUrlHelper;
use Doctrine\Persistence\ManagerRegistry;
use Exception;
@ -17,7 +18,8 @@ class UsergroupRepository extends ResourceRepository
{
public function __construct(
ManagerRegistry $registry,
private readonly IllustrationRepository $illustrationRepository
private readonly IllustrationRepository $illustrationRepository,
private readonly AccessUrlHelper $accessUrlHelper,
) {
parent::__construct($registry, Usergroup::class);
}
@ -47,11 +49,12 @@ class UsergroupRepository extends ResourceRepository
}
}
if ($this->getUseMultipleUrl()) {
$urlId = $this->getCurrentAccessUrlId();
if ($this->accessUrlHelper->isMultipleEnabled()) {
$accessUrl = $this->accessUrlHelper->getCurrent();
$qb->innerJoin('g.urls', 'u')
->andWhere('u.accessUrl = :urlId')
->setParameter('urlId', $urlId)
->setParameter('urlId', $accessUrl->getId())
;
}
@ -85,11 +88,12 @@ class UsergroupRepository extends ResourceRepository
->setMaxResults($limit)
;
if ($this->getUseMultipleUrl()) {
$urlId = $this->getCurrentAccessUrlId();
if ($this->accessUrlHelper->isMultipleEnabled()) {
$accessUrl = $this->accessUrlHelper->getCurrent();
$qb->innerJoin('g.urls', 'u')
->andWhere('u.accessUrl = :urlId')
->setParameter('urlId', $urlId)
->setParameter('urlId', $accessUrl->getId())
;
}
@ -120,11 +124,12 @@ class UsergroupRepository extends ResourceRepository
->setMaxResults($limit)
;
if ($this->getUseMultipleUrl()) {
$urlId = $this->getCurrentAccessUrlId();
if ($this->accessUrlHelper->isMultipleEnabled()) {
$accessUrl = $this->accessUrlHelper->getCurrent();
$qb->innerJoin('g.urls', 'u')
->andWhere('u.accessUrl = :urlId')
->setParameter('urlId', $urlId)
->setParameter('urlId', $accessUrl->getId())
;
}
@ -306,11 +311,12 @@ class UsergroupRepository extends ResourceRepository
$qb->select('g.id, g.title, g.description, g.url, g.picture');
}
if ($this->getUseMultipleUrl()) {
$urlId = $this->getCurrentAccessUrlId();
if ($this->accessUrlHelper->isMultipleEnabled()) {
$accessUrl = $this->accessUrlHelper->getCurrent();
$qb->innerJoin('g.accessUrls', 'a', 'WITH', 'g.id = a.usergroup')
->andWhere('a.accessUrl = :urlId')
->setParameter('urlId', $urlId)
->setParameter('urlId', $accessUrl->getId())
;
}

@ -6,9 +6,14 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\Repository;
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
use Chamilo\CoreBundle\Entity\Asset;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\GradebookCategory;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\Skill;
use Chamilo\CoreBundle\Entity\SkillRelGradebook;
use Chamilo\CoreBundle\Entity\SkillRelSkill;
use Chamilo\CoreBundle\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Collections\Criteria;
@ -20,9 +25,12 @@ use Doctrine\Persistence\ManagerRegistry;
*/
class SkillRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
private $assetRepository;
public function __construct(ManagerRegistry $registry, AssetRepository $assetRepository)
{
parent::__construct($registry, Skill::class);
$this->assetRepository = $assetRepository;
}
public function deleteAsset(Skill $skill): void
@ -87,4 +95,195 @@ class SkillRepository extends ServiceEntityRepository
return $qb->getQuery()->getOneOrNullResult();
}
public function getAllSkills($loadUserData = false, $userId = null, $id = null, $parentId = null): array
{
$qb = $this->createQueryBuilder('s');
// Filtrar por ID específico si se proporciona
if (null !== $id) {
$qb->andWhere('s.id = :id')
->setParameter('id', $id);
}
// Filtrar por habilidades relacionadas con un usuario específico si se proporciona
if ($loadUserData && null !== $userId) {
$qb->innerJoin('s.issuedSkills', 'isu')
->andWhere('isu.user = :userId')
->setParameter('userId', $userId);
}
// Filtrar por padre si se proporciona
if (null !== $parentId) {
$qb->innerJoin('s.skills', 'ss', 'WITH', 'ss.parent = :parentId')
->setParameter('parentId', $parentId);
}
// Ordenar por algún criterio si es necesario
$qb->orderBy('s.id', 'ASC');
$query = $qb->getQuery();
$skills = $query->getResult();
// Convertir cada Skill en un array de detalles
$skillsWithDetails = array_map(function ($skill) {
return $this->getSkillDetails($skill); // Asume que getSkillDetails está definido y funciona como se espera
}, $skills);
return $skillsWithDetails;
}
public function getSkillDetails(Skill $skill): array
{
$assetUrl = '/img/icons/64/badges-default.png';
if ($skill->getAsset()) {
$assetUrl = $this->assetRepository->getAssetUrl($skill->getAsset());
}
$skillDetails = [
'id' => $skill->getId(),
'title' => $this->translateName($skill->getTitle()),
'shortCode' => $this->translateCode($skill->getShortCode()),
'description' => $skill->getDescription(),
'icon' => $assetUrl,
];
$skillDetails['parents'] = $this->getSkillParents($skill);
$skillDetails['gradebooks'] = $this->getGradebooksBySkill($skill);
return $skillDetails;
}
public function getParentOptions(): array
{
$qb = $this->createQueryBuilder('s');
$qb->select('s.id', 's.title')
->where('s.status = :status')
->setParameter('status', Skill::STATUS_ENABLED);
return $qb->getQuery()->getArrayResult();
}
public function getGradebookOptions(): array
{
$gradebookRepo = $this->getEntityManager()->getRepository(GradebookCategory::class);
$qb = $gradebookRepo->createQueryBuilder('g');
$qb->select('g.id', 'g.title');
return $qb->getQuery()->getArrayResult();
}
public function addSkill(array $params): ?Skill
{
$em = $this->getEntityManager();
$skill = new Skill();
$skill->setTitle($params['title'])
->setShortCode($params['short_code'] ?? '')
->setDescription($params['description'] ?? '')
->setCriteria($params['criteria'] ?? '')
->setAccessUrlId($params['access_url_id'])
->setIcon($params['icon'] ?? '');
$em->persist($skill);
// Relate with parent skills
if (!empty($params['parent_id'])) {
foreach ($params['parent_id'] as $parentId) {
$parentSkill = $this->find($parentId);
if ($parentSkill) {
$skillRelSkill = new SkillRelSkill();
$skillRelSkill->setSkill($skill)
->setParent($parentSkill)
->setLevel($params['level'] ?? 0)
->setRelationType($params['relation_type'] ?? 0);
$em->persist($skillRelSkill);
}
}
}
// Relate with Gradebooks
if (!empty($params['gradebook_id'])) {
foreach ($params['gradebook_id'] as $gradebookId) {
$gradebook = $em->getRepository(GradebookCategory::class)->find($gradebookId);
if ($gradebook) {
$skillRelGradebook = new SkillRelGradebook();
$skillRelGradebook->setGradeBookCategory($gradebook)
->setSkill($skill);
$em->persist($skillRelGradebook);
}
}
}
$em->flush();
return $skill;
}
/**
* Translates a skill name into the current user's language, if a translation is available.
*/
private function translateName(string $name): string
{
$variable = ChamiloApi::getLanguageVar($name, 'Skill');
return $GLOBALS[$variable] ?? $name;
}
/**
* Translates a skill code into the current user's language, if a translation is available.
*
* This is useful for displaying skill codes in a user-friendly manner, especially when they have specific meanings or abbreviations that may not be immediately clear to all users.
*/
private function translateCode(string $code): string
{
if (empty($code)) {
return '';
}
$variable = ChamiloApi::getLanguageVar($code, 'SkillCode');
return $GLOBALS[$variable] ?? $code;
}
/**
* Retrieves the parent skills of a specific skill.
*/
private function getSkillParents(Skill $skill): array
{
$parents = [];
$currentSkill = $skill;
// While the current skill has a parent, keep looking up the hierarchy
while ($currentSkillRelSkill = $this->getEntityManager()->getRepository(SkillRelSkill::class)->findOneBy(['skill' => $currentSkill])) {
$parentSkill = $currentSkillRelSkill->getParent();
if ($parentSkill) {
$parents[] = $parentSkill;
$currentSkill = $parentSkill; // Move to the next level in the hierarchy
} else {
break; // No more parents
}
}
return $parents;
}
/**
* Fetches gradebook categories associated with a given skill.
*/
private function getGradebooksBySkill(Skill $skill): array
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('g')
->from(GradebookCategory::class, 'g')
->innerJoin(SkillRelGradebook::class, 'sg', 'WITH', 'g.id = sg.gradeBookCategory')
->where('sg.skill = :skill')
->setParameter('skill', $skill);
return $qb->getQuery()->getResult();
}
}

@ -4,7 +4,7 @@
{# topbar #}
{# {% include "@ChamiloCore/Layout/topbar.html.twig" %}#}
{% include 'default/skill/skill_wheel.js.html.twig' %}
{% include 'default/skill/skill_wheel.html.twig' %}
{% include 'default/skill/skill_wheel2.html.twig' %}
{% autoescape false %}
<section id="content-scorm">
{{ content }}

@ -0,0 +1,59 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\ServiceHelper;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\EventListener\CourseListener;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
* @see CourseListener::onKernelRequest()
*/
class CidReqHelper
{
public function __construct(
private readonly RequestStack $requestStack,
) {}
private function getRequest(): ?Request
{
return $this->requestStack->getCurrentRequest();
}
private function getSessionHandler(): SessionInterface
{
return $this->getRequest()->getSession();
}
public function getSessionId(): ?int
{
return $this->getSessionHandler()->get('sid');
}
public function getSessionEntity(): ?Session
{
return $this->getSessionHandler()->get('session');
}
public function getCourseId()
{
return $this->getSessionHandler()->get('cid');
}
public function getCourseEntity(): ?Course
{
return $this->getSessionHandler()->get('course');
}
public function getGroupId(): ?int
{
return $this->getSessionHandler()->get('gid');
}
}

@ -84,21 +84,21 @@ class CCalendarEvent extends AbstractResource implements ResourceInterface, Stri
#[ORM\GeneratedValue]
protected ?int $iid = null;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Groups(['calendar_event:write'])]
#[Assert\NotBlank]
#[ORM\Column(name: 'title', type: 'string', length: 255, nullable: false)]
protected string $title;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Groups(['calendar_event:write'])]
#[Assert\NotBlank]
#[ORM\Column(name: 'content', type: 'text', nullable: true)]
protected ?string $content = null;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Groups(['calendar_event:write'])]
#[ORM\Column(name: 'start_date', type: 'datetime', nullable: true)]
protected ?DateTime $startDate = null;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Groups(['calendar_event:write'])]
#[ORM\Column(name: 'end_date', type: 'datetime', nullable: true)]
protected ?DateTime $endDate = null;
@ -143,24 +143,24 @@ class CCalendarEvent extends AbstractResource implements ResourceInterface, Stri
#[ORM\OneToMany(mappedBy: 'event', targetEntity: CCalendarEventAttachment::class, cascade: ['persist', 'remove'])]
protected Collection $attachments;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Groups(['calendar_event:write'])]
#[ORM\Column(name: 'invitation_type', type: 'string', nullable: true)]
protected ?string $invitationType = null;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Groups(['calendar_event:write'])]
#[Assert\NotNull]
#[ORM\Column(name: 'collective', type: 'boolean')]
protected bool $collective = false;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Groups(['calendar_event:write'])]
#[ORM\Column(name: 'subscription_visibility', type: 'integer')]
protected int $subscriptionVisibility = self::SUBSCRIPTION_VISIBILITY_NO;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Groups(['calendar_event:write'])]
#[ORM\Column(name: 'subscription_item_id', type: 'integer', nullable: true)]
protected ?int $subscriptionItemId = null;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Groups(['calendar_event:write'])]
#[ORM\Column(name: 'max_attendees', type: 'integer')]
protected int $maxAttendees = 0;
@ -385,7 +385,7 @@ class CCalendarEvent extends AbstractResource implements ResourceInterface, Stri
return $this;
}
public function getInvitationType(): string
public function getInvitationType(): ?string
{
return $this->invitationType;
}

Loading…
Cancel
Save