Webservice: Add support for social groups/classes through REST API, update return values of usergroup.lib.php methods, fix getDataToExport filters - refs BT#20460

pull/4909/head
Yannick Warnier 2 years ago
commit 2a4008872b
  1. 3
      main/exercise/fill_blanks.class.php
  2. 153
      main/inc/lib/usergroup.lib.php
  3. 255
      main/inc/lib/webservices/Rest.php
  4. 82
      main/webservices/api/v2.php

@ -1384,9 +1384,6 @@ class FillBlanks extends Question
$resultsDisabled = false,
$showTotalScoreAndUserChoices = false
) {
if ($resultsDisabled == RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT_NO_FEEDBACK) {
return '';
}
return self::getHtmlAnswer(
$answer,

@ -720,21 +720,34 @@ class UserGroup extends Model
* 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 @@ class UserGroup extends Model
* @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 @@ class UserGroup extends Model
$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 @@ class UserGroup extends Model
}
}
$sessions = '';
$sessions = [];
// Adding new relationships.
if (!empty($new_items)) {
foreach ($new_items as $session_id) {
@ -977,18 +995,19 @@ class UserGroup extends Model
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 @@ class UserGroup extends Model
$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 @@ class UserGroup extends Model
$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 @@ class UserGroup extends Model
],
]
);
$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 @@ class UserGroup extends Model
}
/**
* Returns whether teachers can access the classes, as per 'allow_teachers_to_classes' setting
*
* @return bool
*/
public function allowTeachers()
@ -1435,21 +1511,25 @@ class UserGroup extends Model
*/
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 @@ class UserGroup extends Model
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 @@ class UserGroup extends Model
}
/**
* 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 @@ class UserGroup extends Model
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)

@ -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 @@ class Rest extends WebService
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 @@ class Rest extends WebService
/**
* @param $userParam
*
* @return array
* @throws Exception
*/
public function addUser($userParam): array
@ -2060,6 +2115,20 @@ class Rest extends WebService
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 @@ class Rest extends WebService
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 @@ class Rest extends WebService
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)];
}
}

@ -865,6 +865,88 @@ try {
$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'));
}

Loading…
Cancel
Save