diff --git a/main/exercise/fill_blanks.class.php b/main/exercise/fill_blanks.class.php index 6153ecb51eb..008f9074ad6 100755 --- a/main/exercise/fill_blanks.class.php +++ b/main/exercise/fill_blanks.class.php @@ -1384,9 +1384,6 @@ public static function getHtmlWrongAnswer( $resultsDisabled = false, $showTotalScoreAndUserChoices = false ) { - if ($resultsDisabled == RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT_NO_FEEDBACK) { - return ''; - } return self::getHtmlAnswer( $answer, diff --git a/main/inc/lib/usergroup.lib.php b/main/inc/lib/usergroup.lib.php index 8fd70726080..d7861322166 100755 --- a/main/inc/lib/usergroup.lib.php +++ b/main/inc/lib/usergroup.lib.php @@ -720,21 +720,34 @@ public function usergroup_was_added_in_course( * Gets a list of session ids by user group. * * @param int $id group id + * @param bool $returnSessionData Whether to return an array with info (true) or just the session ID (false) * * @return array */ - public function get_sessions_by_usergroup($id) + public function get_sessions_by_usergroup($id, $returnSessionData = false) { - $results = Database::select( - 'session_id', - $this->usergroup_rel_session_table, - ['where' => ['usergroup_id = ?' => $id]] - ); + if ($returnSessionData) { + $results = Database::select( + 'g.session_id, s.name, s.description, s.nbr_users, s.nbr_courses', + $this->usergroup_rel_session_table." g, ".$this->session_table." s", + ['where' => ['g.session_id = s.id AND g.usergroup_id = ?' => $id]] + ); + } else { + $results = Database::select( + 'session_id', + $this->usergroup_rel_session_table, + ['where' => ['usergroup_id = ?' => $id]] + ); + } $array = []; if (!empty($results)) { foreach ($results as $row) { - $array[] = $row['session_id']; + if ($returnSessionData) { + $array[$row['session_id']] = $row; + } else { + $array[] = $row['session_id']; + } } } @@ -912,8 +925,10 @@ public function get_usergroup_by_user($userId) * @param int $usergroup_id usergroup id * @param array $list list of session ids * @param bool $deleteCurrentSessions Optional. Empty the session list for the usergroup (class) + * + * @return array List of IDs of the sessions added to the usergroup */ - public function subscribe_sessions_to_usergroup($usergroup_id, $list, $deleteCurrentSessions = true) + public function subscribe_sessions_to_usergroup($usergroup_id, $list, $deleteCurrentSessions = true): array { $current_list = $this->get_sessions_by_usergroup($usergroup_id); $user_list = $this->get_users_by_usergroup($usergroup_id); @@ -921,8 +936,11 @@ public function subscribe_sessions_to_usergroup($usergroup_id, $list, $deleteCur $delete_items = $new_items = []; if (!empty($list)) { foreach ($list as $session_id) { - if (!in_array($session_id, $current_list)) { - $new_items[] = $session_id; + if (SessionManager::isValidId($session_id)) { + // Only if the session IDs given are not bogus + if (!in_array($session_id, $current_list)) { + $new_items[] = $session_id; + } } } } @@ -963,7 +981,7 @@ public function subscribe_sessions_to_usergroup($usergroup_id, $list, $deleteCur } } - $sessions = ''; + $sessions = []; // Adding new relationships. if (!empty($new_items)) { foreach ($new_items as $session_id) { @@ -977,18 +995,19 @@ public function subscribe_sessions_to_usergroup($usergroup_id, $list, $deleteCur null, false ); - $sessions .= $session_id.','; + $sessions[] = $session_id; } } // Add event to system log Event::addEvent( LOG_GROUP_PORTAL_SESSION_SUBSCRIBED, LOG_GROUP_PORTAL_ID, - 'gid: '.$usergroup_id.' - sids: '.substr($sessions, 0, -1), + 'gid: '.$usergroup_id.' - sids: '.implode(',', $sessions), api_get_utc_datetime(), api_get_user_id() ); } + return $sessions; } /** @@ -1024,9 +1043,10 @@ public function subscribe_courses_to_usergroup($usergroup_id, $list, $delete_gro $this->unsubscribe_courses_from_usergroup($usergroup_id, $delete_items); } + + $courses = []; // Adding new relationships if (!empty($new_items)) { - $courses = ''; foreach ($new_items as $course_id) { $course_info = api_get_course_info_by_id($course_id); if ($course_info) { @@ -1088,29 +1108,32 @@ public function subscribe_courses_to_usergroup($usergroup_id, $list, $delete_gro $params ); } - $courses .= $course_id.','; + $courses[] = $course_id; } // Add event to system log Event::addEvent( LOG_GROUP_PORTAL_COURSE_SUBSCRIBED, LOG_GROUP_PORTAL_ID, - 'gid: '.$usergroup_id.' - cids: '.substr($courses, 0, -1), + 'gid: '.$usergroup_id.' - cids: '.implode(',', $courses), api_get_utc_datetime(), api_get_user_id() ); } + + return $courses; } /** + * Unsubscribe a usergroup from a list of courses * @param int $usergroup_id * @param array $delete_items */ public function unsubscribe_courses_from_usergroup($usergroup_id, $delete_items) { + $courses = []; // Deleting items. if (!empty($delete_items)) { $user_list = $this->get_users_by_usergroup($usergroup_id); - $courses = ''; foreach ($delete_items as $course_id) { $course_info = api_get_course_info_by_id($course_id); if ($course_info) { @@ -1133,18 +1156,69 @@ public function unsubscribe_courses_from_usergroup($usergroup_id, $delete_items) ], ] ); - $courses .= $course_id.','; + $courses[] = $course_id; } } // Add event to system log Event::addEvent( LOG_GROUP_PORTAL_COURSE_UNSUBSCRIBED, LOG_GROUP_PORTAL_ID, - 'gid: '.$usergroup_id.' - cids: '.substr($courses, 0, -1), + 'gid: '.$usergroup_id.' - cids: '.implode(',', $courses), + api_get_utc_datetime(), + api_get_user_id() + ); + } + + return $courses; + } + + /** + * Unsubscribe a usergroup from a list of sessions + * @param int $groupId + * @param array $items Session IDs to remove from the group + * @return array The list of session IDs that have been unsubscribed from the group + */ + public function unsubscribeSessionsFromUserGroup($groupId, $items) + { + // Deleting items. + $sessions = []; + if (!empty($items)) { + $users = $this->get_users_by_usergroup($groupId); + foreach ($items as $sessionId) { + if (SessionManager::isValidId($sessionId)) { + if (!api_get_configuration_value('usergroup_do_not_unsubscribe_users_from_session_on_session_unsubscribe')) { + if (!empty($users)) { + foreach ($users as $userId) { + SessionManager::unsubscribe_user_from_session( + $sessionId, + $userId + ); + } + } + } + Database::delete( + $this->usergroup_rel_session_table, + [ + 'usergroup_id = ? AND session_id = ?' => [ + $groupId, + $sessionId, + ], + ] + ); + $sessions[] = $sessionId; + } + } + // Add event to system log + Event::addEvent( + LOG_GROUP_PORTAL_SESSION_UNSUBSCRIBED, + LOG_GROUP_PORTAL_ID, + 'gid: '.$groupId.' - sids: '.implode(',', $sessions), api_get_utc_datetime(), api_get_user_id() ); } + + return $sessions; } /** @@ -1340,6 +1414,8 @@ public function usergroup_exists($name) } /** + * Returns whether teachers can access the classes, as per 'allow_teachers_to_classes' setting + * * @return bool */ public function allowTeachers() @@ -1435,21 +1511,25 @@ public function getUsergroupsPagination($sidx, $sord, $start, $limit, $extraWher */ public function getDataToExport($options = []) { + $and = ''; + if (!empty($options) && !empty($options['where'])) { + $and = ' AND '; + } if ($this->getUseMultipleUrl()) { $urlId = api_get_current_access_url_id(); $from = $this->table." u INNER JOIN {$this->access_url_rel_usergroup} a ON (u.id = a.usergroup_id)"; - $options = ['where' => ['access_url_id = ? ' => $urlId]]; + $options['where'][$and.' access_url_id = ? '] = $urlId; if ($this->allowTeachers()) { - $options['where'] = [' author_id = ? ' => api_get_user_id()]; + $options['where'] = [' AND author_id = ? ' => api_get_user_id()]; } - $classes = Database::select('u.id, name, description', $from, $options); + $classes = Database::select('u.id, name, description, group_type, visibility', $from, $options); } else { if ($this->allowTeachers()) { - $options['where'] = [' author_id = ? ' => api_get_user_id()]; + $options['where'] = [$and.' author_id = ? ' => api_get_user_id()]; } - $classes = Database::select('id, name, description', $this->table, $options); + $classes = Database::select('id, name, description, group_type, visibility', $this->table, $options); } $result = []; @@ -1841,15 +1921,18 @@ public function delete($id) WHERE usergroup_id = $id"; Database::query($sql); - parent::delete($id); + $res = parent::delete($id); // Add event to system log - Event::addEvent( - LOG_GROUP_PORTAL_DELETED, - LOG_GROUP_PORTAL_ID, - 'id: '.$id, - api_get_utc_datetime(), - api_get_user_id() - ); + if ($res) { + Event::addEvent( + LOG_GROUP_PORTAL_DELETED, + LOG_GROUP_PORTAL_ID, + 'id: '.$id, + api_get_utc_datetime(), + api_get_user_id() + ); + } + return $res; } /** @@ -2360,14 +2443,14 @@ public function add_users_to_groups($user_list, $group_list, $relation_type = GR } /** - * Deletes an url and session relationship. + * Deletes the subscription of a user to a usergroup * * @author Julio Montoya * * @param int $userId * @param int $groupId * - * @return bool true if success + * @return bool true on success * */ public function delete_user_rel_group($userId, $groupId) { @@ -2769,7 +2852,7 @@ public function get_all_users_by_group($group_id) return []; } - $sql = "SELECT u.id, u.firstname, u.lastname, relation_type + $sql = "SELECT u.id, u.firstname, u.lastname, gu.relation_type FROM $tbl_user u INNER JOIN $table_group_rel_user gu ON (gu.user_id = u.id) diff --git a/main/inc/lib/webservices/Rest.php b/main/inc/lib/webservices/Rest.php index 99e16d3c670..a5dbb47f799 100644 --- a/main/inc/lib/webservices/Rest.php +++ b/main/inc/lib/webservices/Rest.php @@ -135,6 +135,20 @@ class Rest extends WebService public const GET_TEST_UPDATES_LIST = 'get_test_updates_list'; public const GET_TEST_AVERAGE_RESULTS_LIST = 'get_test_average_results_list'; + public const GET_GROUPS = 'get_groups'; + public const GROUP_EXISTS = 'group_exists'; + public const ADD_GROUP = 'add_group'; + public const DELETE_GROUP = 'delete_group'; + public const GET_GROUP_SUB_USERS = 'get_group_sub_users'; + public const GET_GROUP_SUB_COURSES = 'get_group_sub_courses'; + public const GET_GROUP_SUB_SESSIONS = 'get_group_sub_sessions'; + public const ADD_GROUP_SUB_USER = 'add_group_sub_user'; + public const ADD_GROUP_SUB_COURSE = 'add_group_sub_course'; + public const ADD_GROUP_SUB_SESSION = 'add_group_sub_session'; + public const DELETE_GROUP_SUB_USER = 'delete_group_sub_user'; + public const DELETE_GROUP_SUB_COURSE = 'delete_group_sub_course'; + public const DELETE_GROUP_SUB_SESSION = 'delete_group_sub_session'; + /** * @var Session */ @@ -1688,6 +1702,46 @@ public function getSessionsCampus(int $campusId = 0): array return $shortList; } + /** + * Returns an array of groups with id, group_type, name, description, visibility. + * + * @param array $params An array of parameters to filter the results (currently supports 'type') + * + * @throws Exception + */ + public function getGroups(array $params): array + { + self::protectAdminEndpoint(); + + if ('*' === $params['type']) { + $conditions = []; + } else { + $conditions = ['where' => ['group_type = ?' => $params['type']]]; + } + $userGroup = new UserGroup(); + $groups = $userGroup->getDataToExport($conditions); + $list = []; + /** @var \Chamilo\UserBundle\Entity\Group $item */ + foreach ($groups as $item) { + $listTemp = [ + 'id' => $item['id'], + 'name' => $item['name'], + 'description' => $item['description'], + 'visibility' => $item['visibility'], + 'type' => $item['group_type'], + ]; + if (in_array($item['group_type'], [0, 1])) { + $listTemp['type_name'] = ($item['group_type'] == 0) ? 'class' : 'social'; + } + if (in_array($item['visibility'], [1, 2])) { + $listTemp['visibility_name'] = ($item['visibility'] == 1) ? 'open' : 'closed'; + } + $list[] = $listTemp; + } + + return $list; + } + /** * @throws Exception */ @@ -1802,6 +1856,7 @@ public function addCourse(array $courseParam): array /** * @param $userParam * + * @return array * @throws Exception */ public function addUser($userParam): array @@ -2060,6 +2115,20 @@ public function setMessageRead(int $messageId) MessageManager::update_message_status($this->user->getId(), $messageId, MESSAGE_STATUS_NEW); } + /** + * Add a group + * @param array Params + */ + public function createGroup($params) + { + self::protectAdminEndpoint(); + + $name = $params['name']; + $description = $params['description']; + + + } + /** * Add Campus Virtual. * @@ -2701,6 +2770,19 @@ public function usernameExist($loginname) return false !== api_get_user_info_from_username($loginname); } + /** + * Returns whether a user group name exists. + * + * @param string $name the group name + * + * @return bool whether the group name exists + */ + public function groupExists($name) + { + $userGroup = new UserGroup(); + return false !== $userGroup->usergroup_exists($name); + } + /** * This service roughly matches what the call to MDL's API core_course_get_contents function returns. * @@ -3941,4 +4023,177 @@ private function generateUrl(array $additionalParams = []): string return api_get_self().'?' .http_build_query(array_merge($queryParams, $additionalParams)); } + + /** + * Create a group/class + * + * @param $params + * + * @return array + * @throws Exception + */ + public function addGroup($params): array + { + self::protectAdminEndpoint(); + + if (!empty($params['type'])) { + $params['group_type'] = $params['type']; + } + + // First check wether the login already exists. + $userGroup = new UserGroup(); + if ($userGroup->usergroup_exists($params['name'])) { + throw new Exception($params['name'].' '.get_lang('AlreadyExists')); + } + + $groupId = $userGroup->save($params); + + if (empty($groupId)) { + throw new Exception(get_lang('NotRegistered')); + } + + return [$groupId]; + } + + /** + * Delete a group/class + * + * @param int $id + * + * @return bool + * @throws Exception + */ + public function deleteGroup(int $id): array + { + self::protectAdminEndpoint(); + + if (empty($id)) { + return false; + } + + // First check wether the login already exists. + $userGroup = new UserGroup(); + if (!$userGroup->delete($id)) { + throw new Exception(get_lang('NotDeleted')); + } + + return [$id]; + } + + /** + * Get the list of users subscribed to the given group/class + * @param int $groupId + * @return array The list of users (userID => [firstname, lastname, relation_type] + */ + public function getGroupSubscribedUsers(int $groupId): array + { + $userGroup = new UserGroup(); + + return $userGroup->get_all_users_by_group($groupId); + } + + /** + * Get the list of courses to which the given group/class is subscribed + * @param int $groupId + * @return array The list of courses (ID => [title] + */ + public function getGroupSubscribedCourses(int $groupId): array + { + $userGroup = new UserGroup(); + + return $userGroup->get_courses_by_usergroup($groupId, true); + } + + /** + * Get the list of sessions to which the given group/class is subscribed + * @param int $groupId + * @return array The list of courses (ID => [title] + */ + public function getGroupSubscribedSessions(int $groupId): array + { + $userGroup = new UserGroup(); + + return $userGroup->get_sessions_by_usergroup($groupId, true); + } + + /** + * Add a new user to the given group/class + * @param int $groupId + * @param int $userId + * @param int $relationType (1:admin, 2:reader, etc. See GROUP_USER_PERMISSION_ constants in api.lib.php) + * + * @return array One item array containing true on success, false otherwise + */ + public function addGroupSubscribedUser(int $groupId, int $userId, int $relationType = 2): array + { + $userGroup = new UserGroup(); + + return [$userGroup->add_user_to_group($userId, $groupId, $relationType)]; + } + + /** + * Add a new course to which the given group/class is subscribed + * @param int $groupId + * @param int $courseId + * @return array One item array containing the ID of the course on success, nothing on failure + */ + public function addGroupSubscribedCourse(int $groupId, int $courseId): array + { + $userGroup = new UserGroup(); + + return [$userGroup->subscribe_courses_to_usergroup($groupId, [$courseId], false)]; + } + + /** + * Add a new session to which the given group/class is subscribed + * @param int $groupId + * @param int $sessionId + * @return array One item array containing the ID of the session on success, nothing on failure + */ + public function addGroupSubscribedSession(int $groupId, int $sessionId): array + { + $userGroup = new UserGroup(); + + return [$userGroup->subscribe_sessions_to_usergroup($groupId, [$sessionId] ,false)]; + } + + /** + * Remove a user from the given group/class + * @param int $groupId + * @param int $userId + * + * @return array One item array containing true on success, false otherwise + */ + public function deleteGroupSubscribedUser(int $groupId, int $userId): array + { + $userGroup = new UserGroup(); + + return [$userGroup->delete_user_rel_group($userId, $groupId)]; + } + + /** + * Remove a course to which the given group/class is subscribed + * @param int $groupId + * @param int $courseId + * @return array One item array containing true on success, false otherwise + */ + public function deleteGroupSubscribedCourse(int $groupId, int $courseId): array + { + $userGroup = new UserGroup(); + + return [$userGroup->unsubscribe_courses_from_usergroup($groupId, [$courseId])]; + } + + /** + * Remove a session to which the given group/class is subscribed + * @param int $groupId + * @param int $sessionId + * @return array One item array containing true on success, false otherwise + */ + public function deleteGroupSubscribedSession(int $groupId, int $sessionId): array + { + $userGroup = new UserGroup(); + + return [$userGroup->unsubscribeSessionsFromUserGroup($groupId, [$sessionId] ,false)]; + } } diff --git a/main/webservices/api/v2.php b/main/webservices/api/v2.php index b534082312e..742f9d4240e 100644 --- a/main/webservices/api/v2.php +++ b/main/webservices/api/v2.php @@ -865,6 +865,88 @@ $restApi->getTestAverageResultsList($_POST['ids'], $fields) ); break; + /* groups/classes */ + case Rest::GET_GROUPS: + Event::addEvent(LOG_WS.$action, 'username', $username); + $data = $restApi->getGroups($_POST); + $restResponse->setData($data); + break; + case Rest::GROUP_EXISTS: + Event::addEvent(LOG_WS.$action, 'groupname', $_POST['name']); + $data = $restApi->groupExists($_POST['name']); + $restResponse->setData([$data]); + break; + case Rest::ADD_GROUP: + $data = $restApi->addGroup($_POST); + Event::addEvent(LOG_WS.$action, 'user_id', $data); + $restResponse->setData($data); + break; + case Rest::DELETE_GROUP: + $data = $restApi->deleteGroup($_POST['id']); + Event::addEvent(LOG_WS.$action, 'group_id', $data); + $restResponse->setData($data); + break; + case Rest::GET_GROUP_SUB_USERS: + $data = $restApi->getGroupSubscribedUsers($_POST['id']); + Event::addEvent(LOG_WS.$action, 'group_id', $data); + $restResponse->setData($data); + break; + case Rest::GET_GROUP_SUB_COURSES: + $data = $restApi->getGroupSubscribedCourses($_POST['id']); + Event::addEvent(LOG_WS.$action, 'group_id', $data); + $restResponse->setData($data); + break; + case Rest::GET_GROUP_SUB_SESSIONS: + $data = $restApi->getGroupSubscribedSessions($_POST['id']); + Event::addEvent(LOG_WS.$action, 'group_id', $data); + $restResponse->setData($data); + break; + case Rest::ADD_GROUP_SUB_USER: + $groupId = (int) $_POST['group_id']; + $userId = (int) $_POST['user_id']; + $role = 2; + if (isset($_POST['role'])) { + $role = (int) $_POST['role']; + } + $data = $restApi->addGroupSubscribedUser($groupId, $userId, $role); + Event::addEvent(LOG_WS.$action, 'group_id', $groupId); + $restResponse->setData($data); + break; + case Rest::ADD_GROUP_SUB_COURSE: + $groupId = (int) $_POST['group_id']; + $courseId = (int) $_POST['course_id']; + $data = $restApi->addGroupSubscribedCourse($groupId, $courseId); + Event::addEvent(LOG_WS.$action, 'group_id', $groupId); + $restResponse->setData($data); + break; + case Rest::ADD_GROUP_SUB_SESSION: + $groupId = (int) $_POST['group_id']; + $sessionId = (int) $_POST['session_id']; + $data = $restApi->addGroupSubscribedSession($groupId, $sessionId); + Event::addEvent(LOG_WS.$action, 'group_id', $groupId); + $restResponse->setData($data); + break; + case Rest::DELETE_GROUP_SUB_USER: + $groupId = (int) $_POST['group_id']; + $userId = (int) $_POST['user_id']; + $data = $restApi->deleteGroupSubscribedUser($groupId, $userId); + Event::addEvent(LOG_WS.$action, 'group_id', $groupId); + $restResponse->setData($data); + break; + case Rest::DELETE_GROUP_SUB_COURSE: + $groupId = (int) $_POST['group_id']; + $courseId = (int) $_POST['course_id']; + $data = $restApi->deleteGroupSubscribedCourse($groupId, $courseId); + Event::addEvent(LOG_WS.$action, 'group_id', $groupId); + $restResponse->setData($data); + break; + case Rest::DELETE_GROUP_SUB_SESSION: + $groupId = (int) $_POST['group_id']; + $sessionId = (int) $_POST['session_id']; + $data = $restApi->deleteGroupSubscribedSession($groupId, $sessionId); + Event::addEvent(LOG_WS.$action, 'group_id', $groupId); + $restResponse->setData($data); + break; default: throw new Exception(get_lang('InvalidAction')); }