groupmanager.lib.php 104 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CourseBundle\Entity\CGroupRelUser;
  4. /**
  5. * This library contains some functions for group-management.
  6. * @author Bart Mollet
  7. * @package chamilo.library
  8. * @todo Add $course_code parameter to all functions. So this GroupManager can
  9. * be used outside a session.
  10. */
  11. class GroupManager
  12. {
  13. /* VIRTUAL_COURSE_CATEGORY:
  14. in this category groups are created based on the virtual course of a course*/
  15. const VIRTUAL_COURSE_CATEGORY = 1;
  16. /* DEFAULT_GROUP_CATEGORY:
  17. When group categories aren't available (platform-setting),
  18. all groups are created in this 'dummy'-category*/
  19. const DEFAULT_GROUP_CATEGORY = 2;
  20. /**
  21. * infinite
  22. */
  23. const INFINITE = 99999;
  24. /**
  25. * No limit on the number of users in a group
  26. */
  27. const MEMBER_PER_GROUP_NO_LIMIT = 0;
  28. /**
  29. * No limit on the number of groups per user
  30. */
  31. const GROUP_PER_MEMBER_NO_LIMIT = 0;
  32. /**
  33. * The tools of a group can have 3 states
  34. * - not available
  35. * - public
  36. * - private
  37. */
  38. const TOOL_NOT_AVAILABLE = 0;
  39. const TOOL_PUBLIC = 1;
  40. const TOOL_PRIVATE = 2;
  41. /**
  42. * Constants for the available group tools
  43. */
  44. const GROUP_TOOL_FORUM = 0;
  45. const GROUP_TOOL_DOCUMENTS = 1;
  46. const GROUP_TOOL_CALENDAR = 2;
  47. const GROUP_TOOL_ANNOUNCEMENT = 3;
  48. const GROUP_TOOL_WORK = 4;
  49. const GROUP_TOOL_WIKI = 5;
  50. const GROUP_TOOL_CHAT = 6;
  51. /**
  52. *
  53. */
  54. public function __construct()
  55. {
  56. }
  57. /**
  58. * @return array
  59. */
  60. public static function get_groups($courseId = null)
  61. {
  62. $table_group = Database::get_course_table(TABLE_GROUP);
  63. $courseId = !empty($courseId) ? (int) $courseId : api_get_course_int_id();
  64. $sql = "SELECT * FROM $table_group WHERE c_id = $courseId ";
  65. $result = Database::query($sql);
  66. return Database::store_result($result, 'ASSOC');
  67. }
  68. /**
  69. * Get list of groups for current course.
  70. * @param int $categoryId The id of the category from which the groups are
  71. * requested
  72. * @param string $course_code Default is current course
  73. * @return array An array with all information about the groups.
  74. */
  75. public static function get_group_list($categoryId = null, $course_code = null, $status = null)
  76. {
  77. $course_info = api_get_course_info($course_code);
  78. if (empty($course_info)) {
  79. return [];
  80. }
  81. $session_id = api_get_session_id();
  82. $course_id = $course_info['real_id'];
  83. $table_group = Database::get_course_table(TABLE_GROUP);
  84. $sql = "SELECT
  85. g.id,
  86. g.iid,
  87. g.name,
  88. g.description,
  89. g.category_id,
  90. g.max_student maximum_number_of_members,
  91. g.secret_directory,
  92. g.self_registration_allowed,
  93. g.self_unregistration_allowed,
  94. g.session_id,
  95. g.status
  96. FROM $table_group g
  97. WHERE 1 = 1 ";
  98. if (!is_null($categoryId)) {
  99. $sql .= " AND g.category_id = '".intval($categoryId)."' ";
  100. $session_condition = api_get_session_condition($session_id);
  101. if (!empty($session_condition)) {
  102. $sql .= $session_condition;
  103. }
  104. } else {
  105. $session_condition = api_get_session_condition($session_id, true);
  106. }
  107. if (!is_null($status)) {
  108. $sql .= " AND g.status = '".intval($status)."' ";
  109. }
  110. $sql .= " AND g.c_id = $course_id ";
  111. if (!empty($session_condition)) {
  112. $sql .= $session_condition;
  113. }
  114. $sql .= "ORDER BY UPPER(g.name)";
  115. $groupList = Database::query($sql);
  116. $groups = array();
  117. while ($thisGroup = Database::fetch_array($groupList)) {
  118. $thisGroup['number_of_members'] = count(self::get_subscribed_users($thisGroup));
  119. if ($thisGroup['session_id'] != 0) {
  120. $sql = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).'
  121. WHERE id='.$thisGroup['session_id'];
  122. $rs_session = Database::query($sql);
  123. if (Database::num_rows($rs_session) > 0) {
  124. $thisGroup['session_name'] = Database::result($rs_session, 0, 0);
  125. }
  126. }
  127. $groups[] = $thisGroup;
  128. }
  129. return $groups;
  130. }
  131. /**
  132. * Create a group
  133. * @param string $name The name for this group
  134. * @param int $category_id
  135. * @param int $tutor The user-id of the group's tutor
  136. * @param int $places How many people can subscribe to the new group
  137. */
  138. public static function create_group($name, $category_id, $tutor, $places)
  139. {
  140. $_course = api_get_course_info();
  141. $session_id = api_get_session_id();
  142. $course_id = $_course['real_id'];
  143. $currentCourseRepository = $_course['path'];
  144. $category = self::get_category($category_id);
  145. $places = intval($places);
  146. if ($category) {
  147. if ($places == 0) {
  148. //if the amount of users per group is not filled in, use the setting from the category
  149. $places = $category['max_student'];
  150. } else {
  151. if ($places > $category['max_student'] && $category['max_student'] != 0) {
  152. $places = $category['max_student'];
  153. }
  154. }
  155. $docState = $category['doc_state'];
  156. $calendarState = $category['calendar_state'];
  157. $workState = $category['work_state'];
  158. $anonuncementState = $category['announcements_state'];
  159. $forumState = $category['forum_state'];
  160. $wikiState = $category['wiki_state'];
  161. $chatState = $category['chat_state'];
  162. $selfRegAllowed = $category['self_reg_allowed'];
  163. $selfUnregAllwoed = $category['self_unreg_allowed'];
  164. } else {
  165. $docState = self::TOOL_PRIVATE;
  166. $calendarState = self::TOOL_PRIVATE;
  167. $workState = self::TOOL_PRIVATE;
  168. $anonuncementState = self::TOOL_PRIVATE;
  169. $forumState = self::TOOL_PRIVATE;
  170. $wikiState = self::TOOL_PRIVATE;
  171. $chatState = self::TOOL_PRIVATE;
  172. $selfRegAllowed = 0;
  173. $selfUnregAllwoed = 0;
  174. }
  175. $table_group = Database::get_course_table(TABLE_GROUP);
  176. $sql = "INSERT INTO $table_group SET
  177. c_id = $course_id,
  178. status = 1,
  179. category_id='".Database::escape_string($category_id)."',
  180. max_student = '".$places."',
  181. doc_state = '".$docState."',
  182. calendar_state = '".$calendarState."',
  183. work_state = '".$workState."',
  184. announcements_state = '".$anonuncementState."',
  185. forum_state = '".$forumState."',
  186. wiki_state = '".$wikiState."',
  187. chat_state = '".$chatState."',
  188. self_registration_allowed = '".$selfRegAllowed."',
  189. self_unregistration_allowed = '".$selfUnregAllwoed."',
  190. session_id='".intval($session_id)."'";
  191. Database::query($sql);
  192. $lastId = Database::insert_id();
  193. if ($lastId) {
  194. $sql = "UPDATE $table_group SET id = iid WHERE iid = $lastId";
  195. Database::query($sql);
  196. $desired_dir_name = '/'.api_replace_dangerous_char($name).'_groupdocs';
  197. $my_path = api_get_path(SYS_COURSE_PATH).$currentCourseRepository.'/document';
  198. $newFolderData = create_unexisting_directory(
  199. $_course,
  200. api_get_user_id(),
  201. $session_id,
  202. $lastId,
  203. null,
  204. $my_path,
  205. $desired_dir_name,
  206. null,
  207. 1
  208. );
  209. $unique_name = $newFolderData['path'];
  210. /* Stores the directory path into the group table */
  211. $sql = "UPDATE $table_group SET
  212. name = '".Database::escape_string($name)."',
  213. secret_directory = '".$unique_name."'
  214. WHERE c_id = $course_id AND id ='".$lastId."'";
  215. Database::query($sql);
  216. // create a forum if needed
  217. if ($forumState >= 0) {
  218. require_once api_get_path(SYS_CODE_PATH).'forum/forumconfig.inc.php';
  219. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  220. $forum_categories = get_forum_categories();
  221. if (empty($forum_categories)) {
  222. $categoryParam = array(
  223. 'forum_category_title' => get_lang('GroupForums'),
  224. );
  225. store_forumcategory($categoryParam);
  226. $forum_categories = get_forum_categories();
  227. }
  228. $counter = 0;
  229. foreach ($forum_categories as $key => $value) {
  230. if ($counter == 0) {
  231. $forum_category_id = $key;
  232. }
  233. $counter++;
  234. }
  235. // A sanity check.
  236. if (empty($forum_category_id)) {
  237. $forum_category_id = 0;
  238. }
  239. $values = array();
  240. $values['forum_title'] = $name;
  241. $values['group_id'] = $lastId;
  242. $values['forum_category'] = $forum_category_id;
  243. $values['allow_anonymous_group']['allow_anonymous'] = 0;
  244. $values['students_can_edit_group']['students_can_edit'] = 0;
  245. $values['approval_direct_group']['approval_direct'] = 0;
  246. $values['allow_attachments_group']['allow_attachments'] = 1;
  247. $values['allow_new_threads_group']['allow_new_threads'] = 1;
  248. $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
  249. $values['group_forum'] = $lastId;
  250. if ($forumState == '1') {
  251. $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
  252. } elseif ($forumState == '2') {
  253. $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
  254. } elseif ($forumState == '0') {
  255. $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
  256. }
  257. store_forum($values);
  258. }
  259. }
  260. return $lastId;
  261. }
  262. /**
  263. * Create subgroups.
  264. * This function creates new groups based on an existing group. It will
  265. * create the specified number of groups and fill those groups with users
  266. * from the base group
  267. * @param int $group_id The group from which subgroups have to be created.
  268. * @param int $number_of_groups The number of groups that have to be created
  269. */
  270. public static function create_subgroups($group_id, $number_of_groups)
  271. {
  272. $course_id = api_get_course_int_id();
  273. $table_group = Database::get_course_table(TABLE_GROUP);
  274. $category_id = self::create_category(
  275. get_lang('Subgroups'),
  276. '',
  277. self::TOOL_PRIVATE,
  278. self::TOOL_PRIVATE,
  279. 0,
  280. 0,
  281. 1,
  282. 1
  283. );
  284. $users = self::get_users($group_id);
  285. $group_ids = array();
  286. for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
  287. $group_ids[] = self::create_group(
  288. get_lang('Subgroup').' '.$group_nr,
  289. $category_id,
  290. 0,
  291. 0
  292. );
  293. }
  294. $members = array();
  295. foreach ($users as $index => $user_id) {
  296. $groupId = $group_ids[$index % $number_of_groups];
  297. $groupInfo = self::get_group_properties($groupId);
  298. self::subscribe_users(
  299. $user_id,
  300. $groupInfo
  301. );
  302. $members[$group_ids[$groupId]]++;
  303. }
  304. foreach ($members as $group_id => $places) {
  305. $sql = "UPDATE $table_group SET max_student = $places
  306. WHERE c_id = $course_id AND id = $group_id";
  307. Database::query($sql);
  308. }
  309. }
  310. /**
  311. * Create a group for every class subscribed to the current course
  312. * @param int $category_id The category in which the groups should be created
  313. * @return array
  314. */
  315. public static function create_class_groups($category_id)
  316. {
  317. $options['where'] = array(" usergroup.course_id = ? " => api_get_course_int_id());
  318. $obj = new UserGroup();
  319. $classes = $obj->getUserGroupInCourse($options);
  320. $group_ids = array();
  321. foreach ($classes as $class) {
  322. $users_ids = $obj->get_users_by_usergroup($class['id']);
  323. $group_id = self::create_group(
  324. $class['name'],
  325. $category_id,
  326. 0,
  327. count($users_ids)
  328. );
  329. $groupInfo = self::get_group_properties($group_id);
  330. self::subscribe_users($users_ids, $groupInfo);
  331. $group_ids[] = $group_id;
  332. }
  333. return $group_ids;
  334. }
  335. /**
  336. * Deletes groups and their data.
  337. * @author Christophe Gesche <christophe.gesche@claroline.net>
  338. * @author Hugues Peeters <hugues.peeters@claroline.net>
  339. * @author Bart Mollet
  340. * @param array $groupInfo iid
  341. * @param string $course_code Default is current course
  342. * @return integer - number of groups deleted.
  343. */
  344. public static function delete_groups($groupInfo, $course_code = null)
  345. {
  346. $course_info = api_get_course_info($course_code);
  347. $course_id = $course_info['real_id'];
  348. // Database table definitions
  349. $group_table = Database::get_course_table(TABLE_GROUP);
  350. $forum_table = Database::get_course_table(TABLE_FORUM);
  351. $groupInfo = self::get_group_properties($groupInfo['iid'], true);
  352. if ($groupInfo) {
  353. $groupIid = $groupInfo['iid'];
  354. $groupId = $groupInfo['id'];
  355. $directory = $groupInfo['secret_directory'];
  356. // Unsubscribe all users
  357. self::unsubscribe_all_users($groupInfo);
  358. self::unsubscribe_all_tutors($groupInfo);
  359. // move group-documents to garbage
  360. $source_directory = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory;
  361. // File to renamed
  362. $destination_dir = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory.'_DELETED_'.$groupInfo['id'];
  363. if (!empty($directory)) {
  364. //Deleting from document tool
  365. DocumentManager::delete_document(
  366. $course_info,
  367. $directory,
  368. $source_directory
  369. );
  370. if (file_exists($source_directory)) {
  371. if (api_get_setting('permanently_remove_deleted_files') === 'true') {
  372. // Delete
  373. my_delete($source_directory);
  374. } else {
  375. // Rename
  376. rename($source_directory, $destination_dir);
  377. }
  378. }
  379. }
  380. $sql = "DELETE FROM $forum_table
  381. WHERE c_id = $course_id AND forum_of_group = $groupId ";
  382. Database::query($sql);
  383. // Delete item properties of this group.
  384. $itemPropertyTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
  385. $sql = "DELETE FROM $itemPropertyTable
  386. WHERE c_id = $course_id AND to_group_id = $groupId ";
  387. Database::query($sql);
  388. // delete the groups
  389. $sql = "DELETE FROM $group_table
  390. WHERE c_id = $course_id AND iid = $groupIid ";
  391. Database::query($sql);
  392. }
  393. return true;
  394. }
  395. /**
  396. * Get group properties
  397. * @param int $group_id The group from which properties are requested.
  398. * @param bool $useIid
  399. * @return array All properties. Array-keys are:
  400. * name, tutor_id, description, maximum_number_of_students,
  401. * directory and visibility of tools
  402. */
  403. public static function get_group_properties($group_id, $useIid = false)
  404. {
  405. $course_id = api_get_course_int_id();
  406. if (empty($group_id) || !is_integer(intval($group_id))) {
  407. return null;
  408. }
  409. $table_group = Database::get_course_table(TABLE_GROUP);
  410. $sql = "SELECT * FROM $table_group
  411. WHERE c_id = $course_id AND id = ".intval($group_id);
  412. if ($useIid) {
  413. $sql = "SELECT * FROM $table_group
  414. WHERE c_id = $course_id AND iid = ".intval($group_id);
  415. }
  416. $db_result = Database::query($sql);
  417. $db_object = Database::fetch_object($db_result);
  418. $result = array();
  419. if ($db_object) {
  420. $result['id'] = $db_object->id;
  421. $result['iid'] = $db_object->iid;
  422. $result['name'] = $db_object->name;
  423. $result['status'] = $db_object->status;
  424. $result['description'] = $db_object->description;
  425. $result['maximum_number_of_students'] = $db_object->max_student;
  426. $result['max_student'] = $db_object->max_student;
  427. $result['doc_state'] = $db_object->doc_state;
  428. $result['work_state'] = $db_object->work_state;
  429. $result['calendar_state'] = $db_object->calendar_state;
  430. $result['announcements_state'] = $db_object->announcements_state;
  431. $result['forum_state'] = $db_object->forum_state;
  432. $result['wiki_state'] = $db_object->wiki_state;
  433. $result['chat_state'] = $db_object->chat_state;
  434. $result['directory'] = $db_object->secret_directory;
  435. $result['self_registration_allowed'] = $db_object->self_registration_allowed;
  436. $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
  437. $result['count_users'] = count(
  438. self::get_subscribed_users($result)
  439. );
  440. $result['count_tutor'] = count(
  441. self::get_subscribed_tutors($result)
  442. );
  443. $result['count_all'] = $result['count_users'] + $result['count_tutor'];
  444. }
  445. return $result;
  446. }
  447. /**
  448. * @param string $name
  449. * @param string $courseCode
  450. * @return array
  451. */
  452. public static function getGroupByName($name, $courseCode = null)
  453. {
  454. $name = trim($name);
  455. if (empty($name)) {
  456. return array();
  457. }
  458. $course_info = api_get_course_info($courseCode);
  459. $course_id = $course_info['real_id'];
  460. $name = Database::escape_string($name);
  461. $table_group = Database::get_course_table(TABLE_GROUP);
  462. $sql = "SELECT * FROM $table_group
  463. WHERE c_id = $course_id AND name = '$name'
  464. LIMIT 1";
  465. $res = Database::query($sql);
  466. $group = array();
  467. if (Database::num_rows($res)) {
  468. $group = Database::fetch_array($res, 'ASSOC');
  469. }
  470. return $group;
  471. }
  472. /**
  473. * @param int $courseId
  474. * @param int $categoryId
  475. * @param string $name
  476. * @return array
  477. */
  478. public static function getGroupListFilterByName($name, $categoryId, $courseId)
  479. {
  480. $name = trim($name);
  481. if (empty($name)) {
  482. return array();
  483. }
  484. $name = Database::escape_string($name);
  485. $courseId = intval($courseId);
  486. $table_group = Database::get_course_table(TABLE_GROUP);
  487. $sql = "SELECT * FROM $table_group
  488. WHERE c_id = $courseId AND name LIKE '%$name%'";
  489. if (!empty($categoryId)) {
  490. $categoryId = intval($categoryId);
  491. $sql .= " AND category_id = $categoryId";
  492. }
  493. $sql .= " ORDER BY name";
  494. $result = Database::query($sql);
  495. return Database::store_result($result, 'ASSOC');
  496. }
  497. /**
  498. * Set group properties
  499. * Changes the group's properties.
  500. * @param int Group Id
  501. * @param string Group name
  502. * @param string Group description
  503. * @param int Max number of students in group
  504. * @param int Document tool's visibility (0=none,1=private,2=public)
  505. * @param int Work tool's visibility (0=none,1=private,2=public)
  506. * @param int Calendar tool's visibility (0=none,1=private,2=public)
  507. * @param int Announcement tool's visibility (0=none,1=private,2=public)
  508. * @param int Forum tool's visibility (0=none,1=private,2=public)
  509. * @param int Wiki tool's visibility (0=none,1=private,2=public)
  510. * @param int Chat tool's visibility (0=none,1=private,2=public)
  511. * @param bool Whether self registration is allowed or not
  512. * @param bool Whether self unregistration is allowed or not
  513. * @param int $categoryId
  514. * @return bool TRUE if properties are successfully changed, false otherwise
  515. */
  516. public static function set_group_properties(
  517. $group_id,
  518. $name,
  519. $description,
  520. $maximum_number_of_students,
  521. $doc_state,
  522. $work_state,
  523. $calendar_state,
  524. $announcements_state,
  525. $forum_state,
  526. $wiki_state,
  527. $chat_state,
  528. $self_registration_allowed,
  529. $self_unregistration_allowed,
  530. $categoryId = null
  531. ) {
  532. $table_group = Database::get_course_table(TABLE_GROUP);
  533. $table_forum = Database::get_course_table(TABLE_FORUM);
  534. $categoryId = intval($categoryId);
  535. $group_id = intval($group_id);
  536. $course_id = api_get_course_int_id();
  537. $sql = "UPDATE ".$table_group." SET
  538. name='".Database::escape_string(trim($name))."',
  539. doc_state = '".Database::escape_string($doc_state)."',
  540. work_state = '".Database::escape_string($work_state)."',
  541. calendar_state = '".Database::escape_string($calendar_state)."',
  542. announcements_state = '".Database::escape_string($announcements_state)."',
  543. forum_state = '".Database::escape_string($forum_state)."',
  544. wiki_state = '".Database::escape_string($wiki_state)."',
  545. chat_state = '".Database::escape_string($chat_state)."',
  546. description ='".Database::escape_string(trim($description))."',
  547. max_student = '".Database::escape_string($maximum_number_of_students)."',
  548. self_registration_allowed = '".Database::escape_string($self_registration_allowed)."',
  549. self_unregistration_allowed = '".Database::escape_string($self_unregistration_allowed)."',
  550. category_id = ".intval($categoryId)."
  551. WHERE c_id = $course_id AND id=".$group_id;
  552. $result = Database::query($sql);
  553. /* Here we are updating a field in the table forum_forum that perhaps
  554. duplicates the table group_info.forum_state cvargas*/
  555. $forum_state = (int) $forum_state;
  556. $sql2 = "UPDATE ".$table_forum." SET ";
  557. if ($forum_state === 1) {
  558. $sql2 .= " forum_group_public_private='public' ";
  559. } elseif ($forum_state === 2) {
  560. $sql2 .= " forum_group_public_private='private' ";
  561. } elseif ($forum_state === 0) {
  562. $sql2 .= " forum_group_public_private='unavailable' ";
  563. }
  564. $sql2 .= " WHERE c_id = $course_id AND forum_of_group=".$group_id;
  565. Database::query($sql2);
  566. return $result;
  567. }
  568. /**
  569. * Get the total number of groups for the current course.
  570. * @return int The number of groups for the current course.
  571. */
  572. public static function get_number_of_groups()
  573. {
  574. $course_id = api_get_course_int_id();
  575. $table_group = Database::get_course_table(TABLE_GROUP);
  576. $sql = "SELECT COUNT(id) AS number_of_groups
  577. FROM $table_group
  578. WHERE c_id = $course_id ";
  579. $res = Database::query($sql);
  580. $obj = Database::fetch_object($res);
  581. return $obj->number_of_groups;
  582. }
  583. /**
  584. * Get all categories
  585. * @param string $course_code The course (default = current course)
  586. * @return array
  587. */
  588. public static function get_categories($course_code = null)
  589. {
  590. $course_info = api_get_course_info($course_code);
  591. $course_id = $course_info['real_id'];
  592. $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
  593. $sql = "SELECT * FROM $table_group_cat
  594. WHERE c_id = $course_id
  595. ORDER BY display_order";
  596. $res = Database::query($sql);
  597. $cats = array();
  598. while ($cat = Database::fetch_array($res)) {
  599. $cats[] = $cat;
  600. }
  601. return $cats;
  602. }
  603. /**
  604. * Get a group category
  605. * @param int $id The category id
  606. * @param string $course_code The course (default = current course)
  607. * @return array
  608. */
  609. public static function get_category($id, $course_code = null)
  610. {
  611. if (empty($id)) {
  612. return array();
  613. }
  614. $course_info = api_get_course_info($course_code);
  615. $course_id = $course_info['real_id'];
  616. $id = intval($id);
  617. $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
  618. $sql = "SELECT * FROM $table_group_cat
  619. WHERE c_id = $course_id AND id = $id
  620. LIMIT 1";
  621. $res = Database::query($sql);
  622. return Database::fetch_array($res);
  623. }
  624. /**
  625. * Get a group category
  626. * @param string $title
  627. * @param string $course_code The course (default = current course)
  628. * @return array
  629. */
  630. public static function getCategoryByTitle($title, $course_code = null)
  631. {
  632. $title = trim($title);
  633. if (empty($title)) {
  634. return array();
  635. }
  636. $course_info = api_get_course_info($course_code);
  637. $course_id = $course_info['real_id'];
  638. $title = Database::escape_string($title);
  639. $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
  640. $sql = "SELECT * FROM $table_group_cat
  641. WHERE c_id = $course_id AND title = '$title'
  642. LIMIT 1";
  643. $res = Database::query($sql);
  644. $category = array();
  645. if (Database::num_rows($res)) {
  646. $category = Database::fetch_array($res, 'ASSOC');
  647. }
  648. return $category;
  649. }
  650. /**
  651. * Get the unique category of a given group
  652. * @param int $group_id The iid of the group
  653. * @param string $course_code The course in which the group is (default =
  654. * current course)
  655. * @return array The category
  656. */
  657. public static function get_category_from_group($group_id, $course_code = null)
  658. {
  659. $table_group = Database::get_course_table(TABLE_GROUP);
  660. $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
  661. $group_id = intval($group_id);
  662. if (empty($group_id)) {
  663. return array();
  664. }
  665. $course_info = api_get_course_info($course_code);
  666. if (empty($course_info)) {
  667. return false;
  668. }
  669. $course_id = $course_info['real_id'];
  670. $sql = "SELECT gc.* FROM $table_group_cat gc, $table_group g
  671. WHERE
  672. gc.c_id = $course_id AND
  673. g.c_id = $course_id AND
  674. gc.id = g.category_id AND
  675. g.iid = $group_id
  676. LIMIT 1";
  677. $res = Database::query($sql);
  678. $cat = array();
  679. if (Database::num_rows($res)) {
  680. $cat = Database::fetch_array($res);
  681. }
  682. return $cat;
  683. }
  684. /**
  685. * Delete a group category
  686. * @param int $cat_id The id of the category to delete
  687. * @param string $course_code The code in which the category should be
  688. * deleted (default = current course)
  689. */
  690. public static function delete_category($cat_id, $course_code = null)
  691. {
  692. $course_info = api_get_course_info($course_code);
  693. $course_id = $course_info['real_id'];
  694. $table_group = Database::get_course_table(TABLE_GROUP);
  695. $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
  696. $cat_id = intval($cat_id);
  697. $sql = "SELECT iid FROM $table_group
  698. WHERE c_id = $course_id AND category_id='".$cat_id."'";
  699. $res = Database::query($sql);
  700. if (Database::num_rows($res) > 0) {
  701. while ($group = Database::fetch_object($res)) {
  702. $groupInfo = self::get_group_properties($group->iid, true);
  703. self::delete_groups($groupInfo, $course_code);
  704. }
  705. }
  706. $sql = "DELETE FROM $table_group_cat
  707. WHERE c_id = $course_id AND id='".$cat_id."'";
  708. Database::query($sql);
  709. }
  710. /**
  711. * Create group category
  712. * @param string $title The title of the new category
  713. * @param string $description The description of the new category
  714. * @param int $doc_state
  715. * @param int $work_state
  716. * @param int $calendar_state
  717. * @param int $announcements_state
  718. * @param int $forum_state
  719. * @param int $wiki_state
  720. * @param int $chat_state
  721. * @param int $self_registration_allowed
  722. * @param int $self_unregistration_allowed
  723. * @param int $maximum_number_of_students
  724. * @param int $groups_per_user
  725. * @return mixed
  726. */
  727. public static function create_category(
  728. $title,
  729. $description,
  730. $doc_state,
  731. $work_state,
  732. $calendar_state,
  733. $announcements_state,
  734. $forum_state,
  735. $wiki_state,
  736. $chat_state = 1,
  737. $self_registration_allowed = 0,
  738. $self_unregistration_allowed = 0,
  739. $maximum_number_of_students = 8,
  740. $groups_per_user = 0
  741. ) {
  742. if (empty($title)) {
  743. return false;
  744. }
  745. $table_group_category = Database::get_course_table(TABLE_GROUP_CATEGORY);
  746. $course_id = api_get_course_int_id();
  747. $sql = "SELECT MAX(display_order)+1 as new_order
  748. FROM $table_group_category
  749. WHERE c_id = $course_id ";
  750. $res = Database::query($sql);
  751. $obj = Database::fetch_object($res);
  752. if (!isset($obj->new_order)) {
  753. $obj->new_order = 1;
  754. }
  755. $params = [
  756. 'c_id' => $course_id,
  757. 'title' => $title,
  758. 'display_order' => $obj->new_order,
  759. 'description' => $description,
  760. 'doc_state' => $doc_state,
  761. 'work_state' => $work_state,
  762. 'calendar_state' => $calendar_state,
  763. 'announcements_state' => $announcements_state,
  764. 'forum_state' => $forum_state,
  765. 'wiki_state' => $wiki_state,
  766. 'chat_state' => $chat_state,
  767. 'groups_per_user' => $groups_per_user,
  768. 'self_reg_allowed' => $self_registration_allowed,
  769. 'self_unreg_allowed' => $self_unregistration_allowed,
  770. 'max_student' => $maximum_number_of_students
  771. ];
  772. $categoryId = Database::insert($table_group_category, $params);
  773. if ($categoryId) {
  774. $sql = "UPDATE $table_group_category SET id = iid
  775. WHERE iid = $categoryId";
  776. Database::query($sql);
  777. return $categoryId;
  778. }
  779. return false;
  780. }
  781. /**
  782. * Update group category
  783. *
  784. * @param int $id
  785. * @param string $title
  786. * @param string $description
  787. * @param $doc_state
  788. * @param $work_state
  789. * @param $calendar_state
  790. * @param $announcements_state
  791. * @param $forum_state
  792. * @param $wiki_state
  793. * @param $chat_state
  794. * @param $self_registration_allowed
  795. * @param $self_unregistration_allowed
  796. * @param $maximum_number_of_students
  797. * @param $groups_per_user
  798. */
  799. public static function update_category(
  800. $id,
  801. $title,
  802. $description,
  803. $doc_state,
  804. $work_state,
  805. $calendar_state,
  806. $announcements_state,
  807. $forum_state,
  808. $wiki_state,
  809. $chat_state,
  810. $self_registration_allowed,
  811. $self_unregistration_allowed,
  812. $maximum_number_of_students,
  813. $groups_per_user
  814. ) {
  815. $table_group_category = Database::get_course_table(TABLE_GROUP_CATEGORY);
  816. $id = intval($id);
  817. $course_id = api_get_course_int_id();
  818. $sql = "UPDATE ".$table_group_category." SET
  819. title='".Database::escape_string($title)."',
  820. description='".Database::escape_string($description)."',
  821. doc_state = '".Database::escape_string($doc_state)."',
  822. work_state = '".Database::escape_string($work_state)."',
  823. calendar_state = '".Database::escape_string($calendar_state)."',
  824. announcements_state = '".Database::escape_string($announcements_state)."',
  825. forum_state = '".Database::escape_string($forum_state)."',
  826. wiki_state = '".Database::escape_string($wiki_state)."',
  827. chat_state = '".Database::escape_string($chat_state)."',
  828. groups_per_user = '".Database::escape_string($groups_per_user)."',
  829. self_reg_allowed = '".Database::escape_string($self_registration_allowed)."',
  830. self_unreg_allowed = '".Database::escape_string($self_unregistration_allowed)."',
  831. max_student = ".intval($maximum_number_of_students)."
  832. WHERE c_id = $course_id AND id = $id";
  833. Database::query($sql);
  834. // Updating all groups inside this category
  835. $groups = self::get_group_list($id);
  836. if (!empty($groups)) {
  837. foreach ($groups as $group) {
  838. self::set_group_properties(
  839. $group['id'],
  840. $group['name'],
  841. $group['description'],
  842. $maximum_number_of_students,
  843. $doc_state,
  844. $work_state,
  845. $calendar_state,
  846. $announcements_state,
  847. $forum_state,
  848. $wiki_state,
  849. $chat_state,
  850. $self_registration_allowed,
  851. $self_unregistration_allowed,
  852. $id
  853. );
  854. }
  855. }
  856. }
  857. /**
  858. * Returns the number of groups of the user with the greatest number of
  859. * subscriptions in the given category
  860. */
  861. public static function get_current_max_groups_per_user($category_id = null, $course_code = null)
  862. {
  863. $course_info = api_get_course_info($course_code);
  864. $group_table = Database::get_course_table(TABLE_GROUP);
  865. $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
  866. $sql = 'SELECT COUNT(gu.group_id) AS current_max
  867. FROM '.$group_user_table.' gu, '.$group_table.' g
  868. WHERE g.c_id = '.$course_info['real_id'].'
  869. AND gu.c_id = g.c_id
  870. AND gu.group_id = g.iid ';
  871. if ($category_id != null) {
  872. $category_id = intval($category_id);
  873. $sql .= ' AND g.category_id = '.$category_id;
  874. }
  875. $sql .= ' GROUP BY gu.user_id ORDER BY current_max DESC LIMIT 1';
  876. $res = Database::query($sql);
  877. $obj = Database::fetch_object($res);
  878. return $obj->current_max;
  879. }
  880. /**
  881. * Swaps the display-order of two categories
  882. * @param int $id1 The id of the first category
  883. * @param int $id2 The id of the second category
  884. */
  885. public static function swap_category_order($id1, $id2)
  886. {
  887. $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
  888. $id1 = intval($id1);
  889. $id2 = intval($id2);
  890. $course_id = api_get_course_int_id();
  891. $sql = "SELECT id, display_order FROM $table_group_cat
  892. WHERE id IN ($id1,$id2) AND c_id = $course_id ";
  893. $res = Database::query($sql);
  894. $cat1 = Database::fetch_object($res);
  895. $cat2 = Database::fetch_object($res);
  896. if ($cat1 && $cat2) {
  897. $sql = "UPDATE $table_group_cat SET display_order=$cat2->display_order
  898. WHERE id = $cat1->id AND c_id = $course_id ";
  899. Database::query($sql);
  900. $sql = "UPDATE $table_group_cat SET display_order=$cat1->display_order
  901. WHERE id = $cat2->id AND c_id = $course_id ";
  902. Database::query($sql);
  903. }
  904. }
  905. /**
  906. * Get all users from a given group
  907. * @param int $group_id The group
  908. * @param bool $load_extra_info
  909. * @param int $start
  910. * @param int $limit
  911. * @param bool $getCount
  912. * @param int $courseId
  913. * @return array list of user id
  914. */
  915. public static function get_users(
  916. $group_id,
  917. $load_extra_info = false,
  918. $start = null,
  919. $limit = null,
  920. $getCount = false,
  921. $courseId = null,
  922. $column = null,
  923. $direction = null
  924. ) {
  925. $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
  926. $groupTable = Database::get_course_table(TABLE_GROUP);
  927. $user_table = Database::get_main_table(TABLE_MAIN_USER);
  928. $group_id = intval($group_id);
  929. if (empty($courseId)) {
  930. $courseId = api_get_course_int_id();
  931. } else {
  932. $courseId = intval($courseId);
  933. }
  934. $select = " SELECT u.id, firstname, lastname ";
  935. if ($getCount) {
  936. $select = " SELECT count(u.id) count";
  937. }
  938. $sql = "$select
  939. FROM $group_user_table gu
  940. INNER JOIN $groupTable g
  941. ON (gu.group_id = g.id and g.c_id = gu.c_id)
  942. INNER JOIN $user_table u
  943. ON (u.id = gu.user_id)
  944. WHERE
  945. gu.c_id = $courseId AND
  946. g.id = $group_id";
  947. if (!empty($column) && !empty($direction)) {
  948. $column = Database::escape_string($column, null, false);
  949. $direction = ($direction == 'ASC' ? 'ASC' : 'DESC');
  950. $sql .= " ORDER BY $column $direction";
  951. }
  952. if (!empty($start) && !empty($limit)) {
  953. $start = intval($start);
  954. $limit = intval($limit);
  955. $sql .= " LIMIT $start, $limit";
  956. }
  957. $res = Database::query($sql);
  958. $users = array();
  959. while ($obj = Database::fetch_object($res)) {
  960. if ($getCount) {
  961. return $obj->count;
  962. break;
  963. }
  964. if ($load_extra_info) {
  965. $users[] = api_get_user_info($obj->user_id);
  966. } else {
  967. $users[] = $obj->user_id;
  968. }
  969. }
  970. return $users;
  971. }
  972. /**
  973. * @param int $group_id id
  974. * @return array
  975. */
  976. public static function getStudentsAndTutors($group_id)
  977. {
  978. $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
  979. $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
  980. $groupTable = Database::get_course_table(TABLE_GROUP);
  981. $course_id = api_get_course_int_id();
  982. $group_id = intval($group_id);
  983. $sql = "SELECT user_id
  984. FROM $group_user_table gu
  985. INNER JOIN $groupTable g
  986. ON (gu.group_id = g.iid and g.c_id = gu.c_id)
  987. WHERE gu.c_id = $course_id AND g.id = $group_id";
  988. $res = Database::query($sql);
  989. $users = array();
  990. while ($obj = Database::fetch_object($res)) {
  991. $users[] = api_get_user_info($obj->user_id);
  992. }
  993. $sql = "SELECT user_id
  994. FROM $tutor_user_table gu
  995. INNER JOIN $groupTable g
  996. ON (gu.group_id = g.id and g.c_id = gu.c_id)
  997. WHERE gu.c_id = $course_id AND g.id = $group_id";
  998. $res = Database::query($sql);
  999. while ($obj = Database::fetch_object($res)) {
  1000. $users[] = api_get_user_info($obj->user_id);
  1001. }
  1002. return $users;
  1003. }
  1004. /**
  1005. * Get only tutors from a group
  1006. * @param array $groupInfo
  1007. * @return array
  1008. */
  1009. public static function getTutors($groupInfo)
  1010. {
  1011. $groupTable = Database::get_course_table(TABLE_GROUP);
  1012. $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
  1013. $course_id = api_get_course_int_id();
  1014. $group_id = intval($groupInfo['iid']);
  1015. $sql = "SELECT user_id
  1016. FROM $tutor_user_table gu
  1017. INNER JOIN $groupTable g
  1018. ON (gu.group_id = g.id and g.c_id = gu.c_id)
  1019. WHERE gu.c_id = $course_id AND g.iid = $group_id";
  1020. $res = Database::query($sql);
  1021. $users = array();
  1022. while ($obj = Database::fetch_object($res)) {
  1023. $users[] = api_get_user_info($obj->user_id);
  1024. }
  1025. return $users;
  1026. }
  1027. /**
  1028. * Get only students from a group (not tutors)
  1029. * @param int $group_id iid
  1030. * @return array
  1031. */
  1032. public static function getStudents($group_id)
  1033. {
  1034. $em = Database::getManager();
  1035. $subscriptions = $em
  1036. ->createQuery('
  1037. SELECT gu
  1038. FROM ChamiloCourseBundle:CGroupRelUser gu
  1039. INNER JOIN ChamiloCourseBundle:CGroupInfo g
  1040. WITH gu.groupId = g.iid AND g.cId = gu.cId
  1041. WHERE gu.cId = :course AND g.id = :group
  1042. ')
  1043. ->setParameters([
  1044. 'course' => api_get_course_int_id(),
  1045. 'group' => intval($group_id)
  1046. ])
  1047. ->getResult();
  1048. $users = [];
  1049. /** @var CGroupRelUser $subscription */
  1050. foreach ($subscriptions as $subscription) {
  1051. $users[] = api_get_user_info($subscription->getUserId());
  1052. }
  1053. return $users;
  1054. }
  1055. /**
  1056. * Returns users belonging to any of the group
  1057. *
  1058. * @param array $groups list of group ids
  1059. * @return array list of user ids
  1060. */
  1061. public static function get_groups_users($groups = array())
  1062. {
  1063. $result = array();
  1064. $tbl_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1065. $course_id = api_get_course_int_id();
  1066. $groups = array_map('intval', $groups);
  1067. // protect individual elements with surrounding quotes
  1068. $groups = implode(', ', $groups);
  1069. $sql = "SELECT DISTINCT user_id
  1070. FROM $tbl_group_user gu
  1071. WHERE c_id = $course_id AND gu.group_id IN ($groups)";
  1072. $rs = Database::query($sql);
  1073. while ($row = Database::fetch_array($rs)) {
  1074. $result[] = $row['user_id'];
  1075. }
  1076. return $result;
  1077. }
  1078. /**
  1079. * Fill the groups with students.
  1080. * The algorithm takes care to first fill the groups with the least # of users.
  1081. * Analysis
  1082. * There was a problem with the "ALL" setting.
  1083. * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
  1084. * and in both cased the query does not work as expected.
  1085. * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
  1086. * Better solution: that's up to you.
  1087. *
  1088. * Note
  1089. * Throughout Dokeos there is some confusion about "course id" and "course code"
  1090. * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
  1091. * However, there is also a integer course_id that uniquely identifies the course.
  1092. * ywarnier:> Now the course_id has been removed (25/1/2005)
  1093. * The databases are als very inconsistent in this.
  1094. *
  1095. * @param array $groupInfo
  1096. * @author Chrisptophe Gesche <christophe.geshe@claroline.net>,
  1097. * Hugues Peeters <hugues.peeters@claroline.net> - original version
  1098. * @author Roan Embrechts - virtual course support, code cleaning
  1099. * @author Bart Mollet - code cleaning, use other GroupManager-functions
  1100. * @return void
  1101. */
  1102. public static function fill_groups($groupInfo)
  1103. {
  1104. $_course = api_get_course_info();
  1105. $groupIid = $groupInfo['iid'];
  1106. $groupId = $groupInfo['id'];
  1107. $category = self::get_category_from_group($groupIid);
  1108. $groups_per_user = isset($category['groups_per_user']) ? $category['groups_per_user'] : self::GROUP_PER_MEMBER_NO_LIMIT;
  1109. $group_table = Database::get_course_table(TABLE_GROUP);
  1110. $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
  1111. $session_id = api_get_session_id();
  1112. $complete_user_list = CourseManager::get_real_and_linked_user_list(
  1113. $_course['code'],
  1114. true,
  1115. $session_id
  1116. );
  1117. $number_groups_per_user = $groups_per_user == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $groups_per_user;
  1118. /*
  1119. * Retrieve all the groups where enrollment is still allowed
  1120. * (reverse) ordered by the number of place available
  1121. */
  1122. $course_id = api_get_course_int_id();
  1123. $sql = "SELECT g.id gid, g.iid, g.max_student-count(ug.user_id) nbPlaces, g.max_student
  1124. FROM $group_table g
  1125. LEFT JOIN $group_user_table ug ON
  1126. g.c_id = $course_id AND
  1127. ug.c_id = $course_id AND
  1128. g.id = ug.group_id
  1129. WHERE
  1130. g.id = $groupId
  1131. GROUP BY (g.iid)
  1132. HAVING (nbPlaces > 0 OR g.max_student = ".self::MEMBER_PER_GROUP_NO_LIMIT.")
  1133. ORDER BY nbPlaces DESC";
  1134. $sql_result = Database::query($sql);
  1135. $group_available_place = array();
  1136. while ($group = Database::fetch_array($sql_result, 'ASSOC')) {
  1137. $group_available_place[$group['iid']] = $group['nbPlaces'];
  1138. }
  1139. /*
  1140. * Retrieve course users (reverse) ordered by the number
  1141. * of group they are already enrolled
  1142. */
  1143. for ($i = 0; $i < count($complete_user_list); $i++) {
  1144. //find # of groups the user is enrolled in
  1145. $number_of_groups = self::user_in_number_of_groups(
  1146. $complete_user_list[$i]["user_id"],
  1147. isset($category['id']) ? $category['id'] : null
  1148. );
  1149. //add # of groups to user list
  1150. $complete_user_list[$i]['number_groups_left'] = $number_groups_per_user - $number_of_groups;
  1151. }
  1152. //first sort by user_id to filter out duplicates
  1153. $complete_user_list = TableSort::sort_table($complete_user_list, 'user_id');
  1154. $complete_user_list = self::filter_duplicates($complete_user_list, 'user_id');
  1155. $complete_user_list = self::filter_only_students($complete_user_list);
  1156. //now sort by # of group left
  1157. $complete_user_list = TableSort::sort_table($complete_user_list, 'number_groups_left', SORT_DESC);
  1158. $userToken = array();
  1159. foreach ($complete_user_list as $this_user) {
  1160. if ($this_user['number_groups_left'] > 0) {
  1161. $userToken[$this_user['user_id']] = $this_user['number_groups_left'];
  1162. }
  1163. }
  1164. $changed = true;
  1165. while ($changed) {
  1166. $changed = false;
  1167. reset($group_available_place);
  1168. arsort($group_available_place);
  1169. reset($userToken);
  1170. arsort($userToken);
  1171. foreach ($group_available_place as $groupIid => $place) {
  1172. foreach ($userToken as $user_id => $places) {
  1173. $groupInfo = self::get_group_properties($groupIid, true);
  1174. if (self::can_user_subscribe($user_id, $groupInfo)) {
  1175. self::subscribe_users($user_id, $groupInfo);
  1176. $group_available_place[$groupIid]--;
  1177. unset($userToken[$user_id]);
  1178. $changed = true;
  1179. break;
  1180. }
  1181. }
  1182. if ($changed) {
  1183. break;
  1184. }
  1185. }
  1186. }
  1187. }
  1188. /**
  1189. * Get the number of students in a group.
  1190. * @param int $group_id id
  1191. * @return int Number of students in the given group.
  1192. */
  1193. public static function number_of_students($group_id, $course_id = null)
  1194. {
  1195. $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1196. $group_id = intval($group_id);
  1197. if (empty($course_id)) {
  1198. $course_id = api_get_course_int_id();
  1199. } else {
  1200. $course_id = intval($course_id);
  1201. }
  1202. $sql = "SELECT COUNT(*) AS number_of_students
  1203. FROM $table_group_user
  1204. WHERE c_id = $course_id AND group_id = $group_id";
  1205. $result = Database::query($sql);
  1206. $db_object = Database::fetch_object($result);
  1207. return $db_object->number_of_students;
  1208. }
  1209. /**
  1210. * Maximum number of students in a group
  1211. * @param int $group_id iid
  1212. * @return int Maximum number of students in the given group.
  1213. */
  1214. public static function maximum_number_of_students($group_id)
  1215. {
  1216. $table_group = Database::get_course_table(TABLE_GROUP);
  1217. $group_id = intval($group_id);
  1218. $course_id = api_get_course_int_id();
  1219. $sql = "SELECT max_student FROM $table_group WHERE c_id = $course_id AND iid = $group_id";
  1220. $db_result = Database::query($sql);
  1221. $db_object = Database::fetch_object($db_result);
  1222. if ($db_object->max_student == 0) {
  1223. return self::INFINITE;
  1224. }
  1225. return $db_object->max_student;
  1226. }
  1227. /**
  1228. * Number of groups of a user
  1229. * @param int $user_id
  1230. * @return int The number of groups the user is subscribed in.
  1231. */
  1232. public static function user_in_number_of_groups($user_id, $cat_id = null)
  1233. {
  1234. $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1235. $table_group = Database::get_course_table(TABLE_GROUP);
  1236. $user_id = intval($user_id);
  1237. $cat_id = intval($cat_id);
  1238. $course_id = api_get_course_int_id();
  1239. $cat_condition = '';
  1240. if (!empty($cat_id)) {
  1241. $cat_condition = " AND g.category_id = $cat_id ";
  1242. }
  1243. $sql = "SELECT COUNT(*) AS number_of_groups
  1244. FROM $table_group_user gu, $table_group g
  1245. WHERE
  1246. gu.c_id = $course_id AND
  1247. g.c_id = $course_id AND
  1248. gu.user_id = $user_id AND
  1249. g.iid = gu.group_id
  1250. $cat_condition";
  1251. $result = Database::query($sql);
  1252. $db_object = Database::fetch_object($result);
  1253. return $db_object->number_of_groups;
  1254. }
  1255. /**
  1256. * Is sef-registration allowed?
  1257. * @param int $user_id
  1258. * @param array $groupInfo
  1259. * @return bool TRUE if self-registration is allowed in the given group.
  1260. */
  1261. public static function is_self_registration_allowed($user_id, $groupInfo)
  1262. {
  1263. $course_id = api_get_course_int_id();
  1264. if (!$user_id > 0) {
  1265. return false;
  1266. }
  1267. $groupIid = $groupInfo['iid'];
  1268. $table_group = Database::get_course_table(TABLE_GROUP);
  1269. if (isset($groupIid)) {
  1270. $sql = "SELECT status, self_registration_allowed
  1271. FROM $table_group
  1272. WHERE c_id = $course_id AND iid = $groupIid";
  1273. $result = Database::query($sql);
  1274. $group = Database::fetch_object($result);
  1275. if ($group->status == 0 || $group->self_registration_allowed != 1) {
  1276. return false;
  1277. }
  1278. return self::can_user_subscribe($user_id, $groupInfo);
  1279. } else {
  1280. return false;
  1281. }
  1282. }
  1283. /**
  1284. * Is sef-unregistration allowed?
  1285. * @param int $user_id
  1286. * @param array $groupInfo
  1287. * @return bool TRUE if self-unregistration is allowed in the given group.
  1288. */
  1289. public static function is_self_unregistration_allowed($user_id, $groupInfo)
  1290. {
  1291. if (!$user_id > 0 || empty($groupInfo)) {
  1292. return false;
  1293. }
  1294. $groupIid = $groupInfo['iid'];
  1295. $table_group = Database::get_course_table(TABLE_GROUP);
  1296. $course_id = api_get_course_int_id();
  1297. $sql = "SELECT status, self_unregistration_allowed
  1298. FROM $table_group
  1299. WHERE c_id = $course_id AND iid = $groupIid";
  1300. $result = Database::query($sql);
  1301. $group = Database::fetch_object($result);
  1302. if ($group->status == 0 || $group->self_unregistration_allowed != 1) {
  1303. return false;
  1304. }
  1305. return self::is_subscribed($user_id, $groupInfo);
  1306. }
  1307. /**
  1308. * Is user subscribed in group?
  1309. * @param int $user_id
  1310. * @param array $groupInfo
  1311. * @return bool TRUE if given user is subscribed in given group
  1312. */
  1313. public static function is_subscribed($user_id, $groupInfo)
  1314. {
  1315. $course_id = api_get_course_int_id();
  1316. if (empty($user_id) || empty($groupInfo) || empty($course_id)) {
  1317. return false;
  1318. }
  1319. $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1320. $group_id = intval($groupInfo['id']);
  1321. $user_id = intval($user_id);
  1322. $sql = "SELECT 1 FROM $table_group_user
  1323. WHERE
  1324. c_id = $course_id AND
  1325. group_id = $group_id AND
  1326. user_id = $user_id
  1327. ";
  1328. $result = Database::query($sql);
  1329. return Database::num_rows($result) > 0;
  1330. }
  1331. /**
  1332. * Can a user subscribe to a specified group in a course
  1333. * @param int $user_id
  1334. * @param array $groupInfo
  1335. * @param bool $checkMaxNumberStudents
  1336. *
  1337. * @return bool TRUE if given user can be subscribed in given group
  1338. */
  1339. public static function can_user_subscribe($user_id, $groupInfo, $checkMaxNumberStudents = true)
  1340. {
  1341. $group_id = $groupInfo['id'];
  1342. $groupIid = $groupInfo['iid'];
  1343. if ($checkMaxNumberStudents) {
  1344. $category = self::get_category_from_group($groupIid);
  1345. if ($category) {
  1346. if ($category['groups_per_user'] == self::GROUP_PER_MEMBER_NO_LIMIT) {
  1347. $category['groups_per_user'] = self::INFINITE;
  1348. }
  1349. $result = self:: user_in_number_of_groups($user_id, $category['id']) < $category['groups_per_user'];
  1350. if ($result == false) {
  1351. return false;
  1352. }
  1353. }
  1354. $result = self::number_of_students($group_id) < self:: maximum_number_of_students($groupIid);
  1355. if ($result == false) {
  1356. return false;
  1357. }
  1358. }
  1359. $result = self::is_tutor_of_group($user_id, $groupInfo);
  1360. if ($result) {
  1361. return false;
  1362. }
  1363. $result = self::is_subscribed($user_id, $groupInfo);
  1364. if ($result) {
  1365. return false;
  1366. }
  1367. return true;
  1368. }
  1369. /**
  1370. * Get all subscribed users (members) from a group
  1371. * @param array $groupInfo
  1372. * @return array An array with information of all users from the given group.
  1373. * (user_id, firstname, lastname, email)
  1374. */
  1375. public static function get_subscribed_users($groupInfo)
  1376. {
  1377. $table_user = Database::get_main_table(TABLE_MAIN_USER);
  1378. $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1379. $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
  1380. $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
  1381. if ($orderListByOfficialCode === 'true') {
  1382. $order_clause = " ORDER BY u.official_code, u.firstname, u.lastname";
  1383. }
  1384. $group_id = intval($groupInfo['id']);
  1385. if (empty($group_id)) {
  1386. return array();
  1387. }
  1388. $course_id = api_get_course_int_id();
  1389. $sql = "SELECT
  1390. ug.id,
  1391. u.user_id,
  1392. u.lastname,
  1393. u.firstname,
  1394. u.email,
  1395. u.username
  1396. FROM $table_user u
  1397. INNER JOIN $table_group_user ug
  1398. ON (ug.user_id = u.user_id)
  1399. WHERE ug.c_id = $course_id AND
  1400. ug.group_id = $group_id
  1401. $order_clause";
  1402. $db_result = Database::query($sql);
  1403. $users = array();
  1404. while ($user = Database::fetch_object($db_result)) {
  1405. $users[$user->user_id] = array(
  1406. 'user_id' => $user->user_id,
  1407. 'firstname' => $user->firstname,
  1408. 'lastname' => $user->lastname,
  1409. 'email' => $user->email,
  1410. 'username' => $user->username
  1411. );
  1412. }
  1413. return $users;
  1414. }
  1415. /**
  1416. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1417. * Get all subscribed tutors of a group
  1418. * @param array $groupInfo
  1419. * @return array An array with information of all users from the given group.
  1420. * (user_id, firstname, lastname, email)
  1421. */
  1422. public static function get_subscribed_tutors($groupInfo, $id_only = false)
  1423. {
  1424. $table_user = Database::get_main_table(TABLE_MAIN_USER);
  1425. $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
  1426. $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
  1427. $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
  1428. if ($orderListByOfficialCode === 'true') {
  1429. $order_clause = " ORDER BY u.official_code, u.firstname, u.lastname";
  1430. }
  1431. $group_id = intval($groupInfo['id']);
  1432. $course_id = api_get_course_int_id();
  1433. $sql = "SELECT tg.id, u.user_id, u.lastname, u.firstname, u.email
  1434. FROM $table_user u, $table_group_tutor tg
  1435. WHERE
  1436. tg.c_id = $course_id AND
  1437. tg.group_id = $group_id AND
  1438. tg.user_id = u.user_id
  1439. $order_clause
  1440. ";
  1441. $db_result = Database::query($sql);
  1442. $users = array();
  1443. while ($user = Database::fetch_object($db_result)) {
  1444. if (!$id_only) {
  1445. $member['user_id'] = $user->user_id;
  1446. $member['firstname'] = $user->firstname;
  1447. $member['lastname'] = $user->lastname;
  1448. $member['email'] = $user->email;
  1449. $users[] = $member;
  1450. } else {
  1451. $users[] = $user->user_id;
  1452. }
  1453. }
  1454. return $users;
  1455. }
  1456. /**
  1457. * Subscribe user(s) to a specified group in current course (as a student)
  1458. * @param mixed $user_ids Can be an array with user-id's or a single user-id
  1459. * @param array $groupInfo
  1460. * @param int $course_id
  1461. * @return bool TRUE if successful
  1462. */
  1463. public static function subscribe_users($user_ids, $groupInfo, $course_id = null)
  1464. {
  1465. $user_ids = is_array($user_ids) ? $user_ids : array($user_ids);
  1466. $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
  1467. $group_id = $groupInfo['id'];
  1468. $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1469. if (!empty($user_ids)) {
  1470. foreach ($user_ids as $user_id) {
  1471. if (self::can_user_subscribe($user_id, $groupInfo)) {
  1472. $user_id = intval($user_id);
  1473. $sql = "INSERT INTO ".$table_group_user." (c_id, user_id, group_id)
  1474. VALUES ('$course_id', '".$user_id."', '".$group_id."')";
  1475. Database::query($sql);
  1476. }
  1477. }
  1478. }
  1479. return true;
  1480. }
  1481. /**
  1482. * Subscribe tutor(s) to a specified group in current course
  1483. * @param mixed $user_ids Can be an array with user-id's or a single user-id
  1484. * @param int $group_id id
  1485. * @param int $course_id
  1486. *
  1487. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1488. * @see subscribe_users. This function is almost an exact copy of that function.
  1489. * @return bool TRUE if successful
  1490. */
  1491. public static function subscribe_tutors($user_ids, $groupInfo, $course_id = null)
  1492. {
  1493. $user_ids = is_array($user_ids) ? $user_ids : array($user_ids);
  1494. $result = true;
  1495. $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
  1496. $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
  1497. $groupId = (int) $groupInfo['id'];
  1498. foreach ($user_ids as $user_id) {
  1499. $user_id = intval($user_id);
  1500. if (self::can_user_subscribe($user_id, $groupInfo, false)) {
  1501. $sql = "INSERT INTO ".$table_group_tutor." (c_id, user_id, group_id)
  1502. VALUES ('$course_id', '".$user_id."', '".$groupId."')";
  1503. $result = Database::query($sql);
  1504. }
  1505. }
  1506. return $result;
  1507. }
  1508. /**
  1509. * Unsubscribe user(s) from a specified group in current course
  1510. * @param mixed $user_ids Can be an array with user-id's or a single user-id
  1511. * @param array $groupInfo
  1512. * @return bool TRUE if successful
  1513. */
  1514. public static function unsubscribe_users($user_ids, $groupInfo)
  1515. {
  1516. $user_ids = is_array($user_ids) ? $user_ids : array($user_ids);
  1517. $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1518. $group_id = intval($groupInfo['id']);
  1519. $course_id = api_get_course_int_id();
  1520. $sql = 'DELETE FROM '.$table_group_user.'
  1521. WHERE
  1522. c_id = '.$course_id.' AND
  1523. group_id = '.$group_id.' AND
  1524. user_id IN ('.implode(',', $user_ids).')
  1525. ';
  1526. Database::query($sql);
  1527. }
  1528. /**
  1529. * Unsubscribe all users from one or more groups
  1530. * @param array $groupInfo
  1531. * @return bool TRUE if successful
  1532. */
  1533. public static function unsubscribe_all_users($groupInfo)
  1534. {
  1535. $course_id = api_get_course_int_id();
  1536. $groupId = (int) $groupInfo['id'];
  1537. if (empty($course_id) || empty($groupId)) {
  1538. return false;
  1539. }
  1540. $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1541. $sql = "DELETE FROM $table_group_user
  1542. WHERE
  1543. group_id = $groupId AND
  1544. c_id = $course_id";
  1545. $result = Database::query($sql);
  1546. return $result;
  1547. }
  1548. /**
  1549. * Unsubscribe all tutors from one or more groups
  1550. * @param int $groupId iid
  1551. * @see unsubscribe_all_users. This function is almost an exact copy of that function.
  1552. * @return bool TRUE if successful
  1553. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1554. */
  1555. public static function unsubscribe_all_tutors($groupId)
  1556. {
  1557. $courseId = api_get_course_int_id();
  1558. $groupId = (int) $groupId;
  1559. if (empty($courseId) || empty($groupId)) {
  1560. return false;
  1561. }
  1562. if (!empty($groupId) > 0) {
  1563. $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
  1564. $sql = "DELETE FROM $table_group_tutor
  1565. WHERE group_id = $groupId AND c_id = $courseId";
  1566. $result = Database::query($sql);
  1567. return $result;
  1568. }
  1569. return true;
  1570. }
  1571. /**
  1572. * Is the user a tutor of this group?
  1573. * @param int $user_id the id of the user
  1574. * @param array $groupInfo
  1575. * @return boolean true/false
  1576. * @todo use the function user_has_access that includes this function
  1577. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1578. */
  1579. public static function is_tutor_of_group($user_id, $groupInfo)
  1580. {
  1581. if (empty($groupInfo)) {
  1582. return false;
  1583. }
  1584. $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
  1585. $user_id = intval($user_id);
  1586. $group_id = intval($groupInfo['id']);
  1587. $course_id = api_get_course_int_id();
  1588. $sql = "SELECT * FROM $table_group_tutor
  1589. WHERE
  1590. c_id = $course_id AND
  1591. user_id = $user_id AND
  1592. group_id = $group_id";
  1593. $result = Database::query($sql);
  1594. if (Database::num_rows($result) > 0) {
  1595. return true;
  1596. } else {
  1597. return false;
  1598. }
  1599. }
  1600. /**
  1601. * Is the user part of this group? This can be a tutor or a normal member
  1602. * you should use this function if the access to a tool or functionality is
  1603. * restricted to the people who are actually in the group
  1604. * before you had to check if the user was
  1605. * 1. a member of the group OR
  1606. * 2. a tutor of the group. This function combines both
  1607. * @param int $user_id the id of the user
  1608. * @param array $groupInfo
  1609. * @return boolean true/false
  1610. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1611. */
  1612. public static function is_user_in_group($user_id, $groupInfo)
  1613. {
  1614. $member = self::is_subscribed($user_id, $groupInfo);
  1615. $tutor = self::is_tutor_of_group($user_id, $groupInfo);
  1616. if ($member || $tutor) {
  1617. return true;
  1618. } else {
  1619. return false;
  1620. }
  1621. }
  1622. /**
  1623. * Get all group's from a given course in which a given user is unsubscribed
  1624. * @author Patrick Cool
  1625. * @param int $course_id retrieve the groups for
  1626. * @param int $user_id the ID of the user you want to know all its group memberships
  1627. * @return array
  1628. */
  1629. public static function get_group_ids($course_id, $user_id)
  1630. {
  1631. $groups = array();
  1632. $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
  1633. $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
  1634. $user_id = intval($user_id);
  1635. $course_id = intval($course_id);
  1636. $sql = "SELECT group_id FROM $tbl_group
  1637. WHERE c_id = $course_id AND user_id = '$user_id'";
  1638. $result = Database::query($sql);
  1639. if ($result) {
  1640. while ($row = Database::fetch_array($result)) {
  1641. $groups[] = $row['group_id'];
  1642. }
  1643. }
  1644. //Also loading if i'm the tutor
  1645. $sql = "SELECT group_id FROM $tbl_group_tutor
  1646. WHERE c_id = $course_id AND user_id = '$user_id'";
  1647. $result = Database::query($sql);
  1648. if ($result) {
  1649. while ($row = Database::fetch_array($result)) {
  1650. $groups[] = $row['group_id'];
  1651. }
  1652. }
  1653. if (!empty($groups)) {
  1654. array_filter($groups);
  1655. }
  1656. return $groups;
  1657. }
  1658. /**
  1659. * Filter out duplicates in a multidimensional array
  1660. * by comparing field $compare_field.
  1661. *
  1662. * @param array $user_array_in List of users (must be sorted).
  1663. * @param string $compare_field The field to be compared
  1664. * @return array
  1665. */
  1666. public static function filter_duplicates($user_array_in, $compare_field)
  1667. {
  1668. $total_number = count($user_array_in);
  1669. $user_array_out[0] = $user_array_in[0];
  1670. $count_out = 0;
  1671. for ($count_in = 1; $count_in < $total_number; $count_in++) {
  1672. if ($user_array_in[$count_in][$compare_field] != $user_array_out[$count_out][$compare_field]) {
  1673. $count_out++;
  1674. $user_array_out[$count_out] = $user_array_in[$count_in];
  1675. }
  1676. }
  1677. return $user_array_out;
  1678. }
  1679. /**
  1680. * Remove all users that are not students and all users who have tutor status
  1681. * from the list.
  1682. * @param array $user_array_in
  1683. * @return array
  1684. */
  1685. public static function filter_only_students($user_array_in)
  1686. {
  1687. $user_array_out = array();
  1688. foreach ($user_array_in as $this_user) {
  1689. if (api_get_session_id()) {
  1690. if ($this_user['status_session'] == 0) {
  1691. $user_array_out[] = $this_user;
  1692. }
  1693. } else {
  1694. if ($this_user['status_rel'] == STUDENT) {
  1695. $user_array_out[] = $this_user;
  1696. }
  1697. }
  1698. }
  1699. return $user_array_out;
  1700. }
  1701. /**
  1702. * Check if a user has access to a certain group tool
  1703. * @param int $user_id The user id
  1704. * @param int $group_id The group iid
  1705. * @param string $tool The tool to check the access rights. This should be
  1706. * one of constants: GROUP_TOOL_DOCUMENTS
  1707. * @return bool True if the given user has access to the given tool in the
  1708. * given course.
  1709. */
  1710. public static function user_has_access($user_id, $group_id, $tool)
  1711. {
  1712. // Admin have access everywhere
  1713. if (api_is_platform_admin()) {
  1714. return true;
  1715. }
  1716. // Course admin also have access to everything
  1717. if (api_is_allowed_to_edit()) {
  1718. return true;
  1719. }
  1720. switch ($tool) {
  1721. case self::GROUP_TOOL_FORUM:
  1722. $key = 'forum_state';
  1723. break;
  1724. case self::GROUP_TOOL_DOCUMENTS:
  1725. $key = 'doc_state';
  1726. break;
  1727. case self::GROUP_TOOL_CALENDAR:
  1728. $key = 'calendar_state';
  1729. break;
  1730. case self::GROUP_TOOL_ANNOUNCEMENT:
  1731. $key = 'announcements_state';
  1732. break;
  1733. case self::GROUP_TOOL_WORK:
  1734. $key = 'work_state';
  1735. break;
  1736. case self::GROUP_TOOL_WIKI:
  1737. $key = 'wiki_state';
  1738. break;
  1739. case self::GROUP_TOOL_CHAT:
  1740. $key = 'chat_state';
  1741. break;
  1742. default:
  1743. return false;
  1744. }
  1745. // Check group properties
  1746. $groupInfo = self::get_group_properties($group_id, true);
  1747. if (empty($groupInfo)) {
  1748. return false;
  1749. }
  1750. if ($groupInfo['status'] == 0) {
  1751. return false;
  1752. }
  1753. if (!isset($groupInfo[$key])) {
  1754. return false;
  1755. }
  1756. if (api_is_allowed_to_edit(false, true)) {
  1757. return true;
  1758. }
  1759. $status = $groupInfo[$key];
  1760. switch ($status) {
  1761. case self::TOOL_NOT_AVAILABLE:
  1762. return false;
  1763. break;
  1764. case self::TOOL_PUBLIC:
  1765. return true;
  1766. break;
  1767. case self::TOOL_PRIVATE:
  1768. $userIsInGroup = self::is_user_in_group($user_id, $groupInfo);
  1769. if ($userIsInGroup) {
  1770. return true;
  1771. }
  1772. break;
  1773. }
  1774. return false;
  1775. }
  1776. /**
  1777. * @param int $userId
  1778. * @param array $groupInfo
  1779. * @param int $sessionId
  1780. *
  1781. * @return bool
  1782. */
  1783. public static function userHasAccessToBrowse($userId, $groupInfo, $sessionId = 0)
  1784. {
  1785. if (empty($groupInfo)) {
  1786. return false;
  1787. }
  1788. if (api_is_platform_admin()) {
  1789. return true;
  1790. }
  1791. if (api_is_allowed_to_edit(false, true)) {
  1792. return true;
  1793. }
  1794. $groupId = $groupInfo['iid'];
  1795. $tutors = self::get_subscribed_tutors($groupInfo, true);
  1796. if (in_array($userId, $tutors)) {
  1797. return true;
  1798. }
  1799. if ($groupInfo['status'] == 0) {
  1800. return false;
  1801. }
  1802. if (
  1803. self::user_has_access($userId, $groupId, self::GROUP_TOOL_FORUM) ||
  1804. self::user_has_access($userId, $groupId, self::GROUP_TOOL_DOCUMENTS) ||
  1805. self::user_has_access($userId, $groupId, self::GROUP_TOOL_CALENDAR) ||
  1806. self::user_has_access($userId, $groupId, self::GROUP_TOOL_ANNOUNCEMENT) ||
  1807. self::user_has_access($userId, $groupId, self::GROUP_TOOL_WORK) ||
  1808. self::user_has_access($userId, $groupId, self::GROUP_TOOL_WIKI) ||
  1809. self::user_has_access($userId, $groupId, self::GROUP_TOOL_CHAT)
  1810. ) {
  1811. return true;
  1812. }
  1813. if (api_is_course_coach() && $groupInfo['session_id'] == $sessionId) {
  1814. return true;
  1815. }
  1816. return false;
  1817. }
  1818. /**
  1819. * Get all groups where a specific user is subscribed
  1820. * @param int $user_id
  1821. * @return array
  1822. */
  1823. public static function get_user_group_name($user_id)
  1824. {
  1825. $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1826. $table_group = Database::get_course_table(TABLE_GROUP);
  1827. $user_id = intval($user_id);
  1828. $course_id = api_get_course_int_id();
  1829. $sql = "SELECT name
  1830. FROM $table_group g
  1831. INNER JOIN $table_group_user gu
  1832. ON (gu.group_id = g.iid)
  1833. WHERE
  1834. gu.c_id= $course_id AND
  1835. g.c_id= $course_id AND
  1836. gu.user_id = $user_id";
  1837. $res = Database::query($sql);
  1838. $groups = array();
  1839. while ($group = Database::fetch_array($res)) {
  1840. $groups[] .= $group['name'];
  1841. }
  1842. return $groups;
  1843. }
  1844. /**
  1845. * Get all groups where a specific user is subscribed
  1846. * @param int $user_id
  1847. * @return array
  1848. */
  1849. public static function getAllGroupPerUserSubscription($user_id)
  1850. {
  1851. $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
  1852. $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
  1853. $table_group = Database::get_course_table(TABLE_GROUP);
  1854. $user_id = intval($user_id);
  1855. $course_id = api_get_course_int_id();
  1856. $sql = "SELECT DISTINCT g.*
  1857. FROM $table_group g
  1858. LEFT JOIN $table_group_user gu
  1859. ON (gu.group_id = g.iid AND g.c_id = gu.c_id)
  1860. LEFT JOIN $table_tutor_user tu
  1861. ON (tu.group_id = g.iid AND g.c_id = tu.c_id)
  1862. WHERE
  1863. g.c_id = $course_id AND
  1864. (gu.user_id = $user_id OR tu.user_id = $user_id) ";
  1865. $res = Database::query($sql);
  1866. $groups = array();
  1867. while ($group = Database::fetch_array($res, 'ASSOC')) {
  1868. $groups[] = $group;
  1869. }
  1870. return $groups;
  1871. }
  1872. /**
  1873. *
  1874. * See : fill_groups
  1875. * Fill the groups with students.
  1876. *
  1877. * note : optimize fill_groups_list <--> fill_groups
  1878. * @param array $groupInfo
  1879. * @return array|bool
  1880. */
  1881. public static function fill_groups_list($groupInfo)
  1882. {
  1883. if (empty($groupInfo)) {
  1884. return [];
  1885. }
  1886. $groupIid = (int) $groupInfo['iid'];
  1887. $groupId = (int) $groupInfo['id'];
  1888. $_course = api_get_course_info();
  1889. if (empty($_course) || empty($groupId)) {
  1890. return [];
  1891. }
  1892. $category = self::get_category_from_group($groupIid);
  1893. $number_groups_per_user = self::GROUP_PER_MEMBER_NO_LIMIT;
  1894. $categoryId = 0;
  1895. if ($category) {
  1896. $groups_per_user = $category['groups_per_user'];
  1897. $number_groups_per_user = ($groups_per_user == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $groups_per_user);
  1898. $categoryId = $category['id'];
  1899. }
  1900. $session_id = api_get_session_id();
  1901. $complete_user_list = CourseManager::get_real_and_linked_user_list(
  1902. $_course['code'],
  1903. true,
  1904. $session_id
  1905. );
  1906. /*
  1907. * Retrieve course users (reverse) ordered by the number
  1908. * of group they are already enrolled
  1909. */
  1910. for ($i = 0; $i < count($complete_user_list); $i++) {
  1911. // find # of groups the user is enrolled in
  1912. $number_of_groups = self:: user_in_number_of_groups(
  1913. $complete_user_list[$i]['user_id'],
  1914. $categoryId
  1915. );
  1916. // add # of groups to user list
  1917. $complete_user_list[$i]['number_groups_left'] = $number_groups_per_user - $number_of_groups;
  1918. }
  1919. //first sort by user_id to filter out duplicates
  1920. $complete_user_list = TableSort::sort_table($complete_user_list, 'user_id');
  1921. $complete_user_list = self::filter_duplicates($complete_user_list, 'user_id');
  1922. //now sort by # of group left
  1923. $complete_user_list = TableSort::sort_table($complete_user_list, 'number_groups_left', SORT_DESC);
  1924. return $complete_user_list;
  1925. }
  1926. /**
  1927. * @param array $group_list
  1928. * @param int $category_id
  1929. *
  1930. * @return string
  1931. */
  1932. public static function process_groups($group_list, $category_id = null)
  1933. {
  1934. global $charset;
  1935. $category_id = intval($category_id);
  1936. $totalRegistered = 0;
  1937. $group_data = array();
  1938. $user_info = api_get_user_info();
  1939. $session_id = api_get_session_id();
  1940. $user_id = $user_info['user_id'];
  1941. $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
  1942. foreach ($group_list as $this_group) {
  1943. // Validation when belongs to a session
  1944. $session_img = api_get_session_image($this_group['session_id'], $user_info['status']);
  1945. // All the tutors of this group
  1946. $tutorsids_of_group = self::get_subscribed_tutors($this_group, true);
  1947. $isMember = self::is_subscribed($user_id, $this_group);
  1948. // Create a new table-row
  1949. $row = array();
  1950. // Checkbox
  1951. if (api_is_allowed_to_edit(false, true) && count($group_list) > 1) {
  1952. $row[] = $this_group['id'];
  1953. }
  1954. if (self::userHasAccessToBrowse($user_id, $this_group, $session_id)) {
  1955. // Group name
  1956. $groupNameClass = null;
  1957. if ($this_group['status'] == 0) {
  1958. $groupNameClass = 'muted';
  1959. }
  1960. $group_name = '<a class="'.$groupNameClass.'" href="group_space.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'">'.
  1961. Security::remove_XSS($this_group['name']).'</a> ';
  1962. if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
  1963. $group_name .= Display::label(get_lang('OneMyGroups'), 'success');
  1964. } elseif ($isMember) {
  1965. $group_name .= Display::label(get_lang('MyGroup'), 'success');
  1966. }
  1967. if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
  1968. $group_name .= ' ('.$this_group['session_name'].')';
  1969. }
  1970. $group_name .= $session_img;
  1971. $row[] = $group_name.'<br />'.stripslashes(trim($this_group['description']));
  1972. } else {
  1973. if ($hideGroup === 'true') {
  1974. continue;
  1975. }
  1976. $row[] = $this_group['name'].'<br />'.stripslashes(trim($this_group['description']));
  1977. }
  1978. // Tutor name
  1979. $tutor_info = null;
  1980. if (count($tutorsids_of_group) > 0) {
  1981. foreach ($tutorsids_of_group as $tutor_id) {
  1982. $tutor = api_get_user_info($tutor_id);
  1983. $username = api_htmlentities(sprintf(get_lang('LoginX'), $tutor['username']), ENT_QUOTES);
  1984. if (api_get_setting('show_email_addresses') === 'true') {
  1985. $tutor_info .= Display::tag(
  1986. 'span',
  1987. Display::encrypted_mailto_link($tutor['mail'], api_get_person_name($tutor['firstName'], $tutor['lastName'])),
  1988. array('title'=>$username)
  1989. ).', ';
  1990. } else {
  1991. if (api_is_allowed_to_edit()) {
  1992. $tutor_info .= Display::tag(
  1993. 'span',
  1994. Display::encrypted_mailto_link($tutor['mail'], api_get_person_name($tutor['firstName'], $tutor['lastName'])),
  1995. array('title'=>$username)
  1996. ).', ';
  1997. } else {
  1998. $tutor_info .= Display::tag(
  1999. 'span',
  2000. api_get_person_name($tutor['firstName'], $tutor['lastName']),
  2001. array('title'=>$username)
  2002. ).', ';
  2003. }
  2004. }
  2005. }
  2006. }
  2007. $tutor_info = api_substr($tutor_info, 0, api_strlen($tutor_info) - 2);
  2008. $row[] = $tutor_info;
  2009. // Max number of members in group
  2010. $max_members = $this_group['maximum_number_of_members'] == self::MEMBER_PER_GROUP_NO_LIMIT ? ' ' : ' / '.$this_group['maximum_number_of_members'];
  2011. // Number of members in group
  2012. $row[] = $this_group['number_of_members'].$max_members;
  2013. // Self-registration / unregistration
  2014. if (!api_is_allowed_to_edit(false, true)) {
  2015. if (self::is_self_registration_allowed($user_id, $this_group)) {
  2016. $row[] = '<a class = "btn btn-default" href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_reg&group_id='.$this_group['id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfRegInf').'</a>';
  2017. } elseif (self::is_self_unregistration_allowed($user_id, $this_group)) {
  2018. $row[] = '<a class = "btn btn-default" href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_unreg&group_id='.$this_group['id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfUnRegInf').'</a>';
  2019. } else {
  2020. $row[] = '-';
  2021. }
  2022. }
  2023. $url = api_get_path(WEB_CODE_PATH).'group/';
  2024. // Edit-links
  2025. if (api_is_allowed_to_edit(false, true) &&
  2026. !(api_is_course_coach() && intval($this_group['session_id']) != $session_id)
  2027. ) {
  2028. $edit_actions = '<a href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'" title="'.get_lang('Edit').'">'.
  2029. Display::return_icon('edit.png', get_lang('EditGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
  2030. if ($this_group['status'] == 1) {
  2031. $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_invisible&id='.$this_group['id'].'" title="'.get_lang('Hide').'">'.
  2032. Display::return_icon('visible.png', get_lang('Hide'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
  2033. } else {
  2034. $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_visible&id='.$this_group['id'].'" title="'.get_lang('Show').'">'.
  2035. Display::return_icon('invisible.png', get_lang('Show'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
  2036. }
  2037. $edit_actions .= '<a href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'" title="'.get_lang('GroupMembers').'">'.
  2038. Display::return_icon('user.png', get_lang('GroupMembers'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
  2039. $edit_actions .= '<a href="'.$url.'group_overview.php?action=export&type=xls&'.api_get_cidreq(true, false).'&id='.$this_group['id'].'" title="'.get_lang('ExportUsers').'">'.
  2040. Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
  2041. $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('FillGroup').'">'.
  2042. Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
  2043. $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'">'.
  2044. Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
  2045. $row[] = $edit_actions;
  2046. }
  2047. if (!empty($this_group['nbMember'])) {
  2048. $totalRegistered = $totalRegistered + $this_group['nbMember'];
  2049. }
  2050. $group_data[] = $row;
  2051. } // end loop
  2052. // If no groups then don't show the table (only for students)
  2053. if (!api_is_allowed_to_edit(true, false)) {
  2054. if (empty($group_data)) {
  2055. return '';
  2056. }
  2057. }
  2058. $table = new SortableTableFromArrayConfig(
  2059. $group_data,
  2060. 1,
  2061. 20,
  2062. 'group_category_'.$category_id
  2063. );
  2064. $table->set_additional_parameters(array('category' => $category_id));
  2065. $column = 0;
  2066. if (api_is_allowed_to_edit(false, true) and count($group_list) > 1) {
  2067. $table->set_header($column++, '', false);
  2068. }
  2069. $table->set_header($column++, get_lang('Groups'));
  2070. $table->set_header($column++, get_lang('GroupTutor'));
  2071. $table->set_header($column++, get_lang('Registered'), false);
  2072. if (!api_is_allowed_to_edit(false, true)) {
  2073. // If self-registration allowed
  2074. $table->set_header($column++, get_lang('GroupSelfRegistration'), false);
  2075. }
  2076. if (api_is_allowed_to_edit(false, true)) {
  2077. // Only for course administrator
  2078. $table->set_header($column++, get_lang('Modify'), false);
  2079. $form_actions = array();
  2080. $form_actions['fill_selected'] = get_lang('FillGroup');
  2081. $form_actions['empty_selected'] = get_lang('EmptyGroup');
  2082. $form_actions['delete_selected'] = get_lang('Delete');
  2083. if (count($group_list) > 1) {
  2084. $table->set_form_actions($form_actions, 'group');
  2085. }
  2086. }
  2087. return $table->return_table();
  2088. }
  2089. /**
  2090. * @param array $groupData
  2091. * @param bool $deleteNotInArray
  2092. * @return array
  2093. */
  2094. public static function importCategoriesAndGroupsFromArray($groupData, $deleteNotInArray = false)
  2095. {
  2096. $result = array();
  2097. $elementsFound = array(
  2098. 'categories' => array(),
  2099. 'groups' => array()
  2100. );
  2101. $courseCode = api_get_course_id();
  2102. $sessionId = api_get_session_id();
  2103. $groupCategories = self::get_categories();
  2104. if (empty($groupCategories)) {
  2105. $result['error'][] = get_lang('CreateACategory');
  2106. return $result;
  2107. }
  2108. foreach ($groupData as $data) {
  2109. $isCategory = empty($data['group']) ? true : false;
  2110. if ($isCategory) {
  2111. $categoryInfo = self::getCategoryByTitle($data['category']);
  2112. $categoryId = $categoryInfo['id'];
  2113. if (!empty($categoryInfo)) {
  2114. // Update
  2115. self::update_category(
  2116. $categoryId,
  2117. $data['category'],
  2118. $data['description'],
  2119. $data['doc_state'],
  2120. $data['work_state'],
  2121. $data['calendar_state'],
  2122. $data['announcements_state'],
  2123. $data['forum_state'],
  2124. $data['wiki_state'],
  2125. $data['chat_state'],
  2126. $data['self_reg_allowed'],
  2127. $data['self_unreg_allowed'],
  2128. $data['max_student'],
  2129. $data['groups_per_user']
  2130. );
  2131. $data['category_id'] = $categoryId;
  2132. $result['updated']['category'][] = $data;
  2133. } else {
  2134. // Add
  2135. $categoryId = self::create_category(
  2136. $data['category'],
  2137. $data['description'],
  2138. $data['doc_state'],
  2139. $data['work_state'],
  2140. $data['calendar_state'],
  2141. $data['announcements_state'],
  2142. $data['forum_state'],
  2143. $data['wiki_state'],
  2144. $data['chat_state'],
  2145. $data['self_reg_allowed'],
  2146. $data['self_unreg_allowed'],
  2147. $data['max_student'],
  2148. $data['groups_per_user']
  2149. );
  2150. if ($categoryId) {
  2151. $data['category_id'] = $categoryId;
  2152. $result['added']['category'][] = $data;
  2153. }
  2154. }
  2155. $elementsFound['categories'][] = $categoryId;
  2156. } else {
  2157. $groupInfo = self::getGroupByName($data['group']);
  2158. $categoryInfo = self::getCategoryByTitle($data['category']);
  2159. $categoryId = null;
  2160. if (!empty($categoryInfo)) {
  2161. $categoryId = $categoryInfo['id'];
  2162. } else {
  2163. if (!empty($groupCategories) && isset($groupCategories[0])) {
  2164. $defaultGroupCategory = $groupCategories[0];
  2165. $categoryId = $defaultGroupCategory['id'];
  2166. }
  2167. }
  2168. if (empty($groupInfo)) {
  2169. // Add
  2170. $groupId = self::create_group(
  2171. $data['group'],
  2172. $categoryId,
  2173. null,
  2174. $data['max_student']
  2175. );
  2176. if ($groupId) {
  2177. self::set_group_properties(
  2178. $groupId,
  2179. $data['group'],
  2180. $data['description'],
  2181. $data['max_student'],
  2182. $data['doc_state'],
  2183. $data['work_state'],
  2184. $data['calendar_state'],
  2185. $data['announcements_state'],
  2186. $data['forum_state'],
  2187. $data['wiki_state'],
  2188. $data['chat_state'],
  2189. $data['self_reg_allowed'],
  2190. $data['self_unreg_allowed'],
  2191. $categoryId
  2192. );
  2193. $data['group_id'] = $groupId;
  2194. $result['added']['group'][] = $data;
  2195. }
  2196. $groupInfo = self::get_group_properties($groupId, true);
  2197. } else {
  2198. // Update
  2199. $groupId = $groupInfo['id'];
  2200. self::set_group_properties(
  2201. $groupId,
  2202. $data['group'],
  2203. $data['description'],
  2204. $data['max_student'],
  2205. $data['doc_state'],
  2206. $data['work_state'],
  2207. $data['calendar_state'],
  2208. $data['announcements_state'],
  2209. $data['forum_state'],
  2210. $data['wiki_state'],
  2211. $data['chat_state'],
  2212. $data['self_reg_allowed'],
  2213. $data['self_unreg_allowed'],
  2214. $categoryId
  2215. );
  2216. $data['group_id'] = $groupId;
  2217. $result['updated']['group'][] = $data;
  2218. $groupInfo = self::get_group_properties($groupId);
  2219. }
  2220. $students = isset($data['students']) ? explode(',', $data['students']) : [];
  2221. if (!empty($students)) {
  2222. $studentUserIdList = array();
  2223. foreach ($students as $student) {
  2224. $userInfo = api_get_user_info_from_username($student);
  2225. if (!$userInfo) {
  2226. continue;
  2227. }
  2228. if (
  2229. !CourseManager::is_user_subscribed_in_course(
  2230. $userInfo['user_id'],
  2231. $courseCode,
  2232. !empty($sessionId),
  2233. $sessionId
  2234. )
  2235. ) {
  2236. Display::addFlash(
  2237. Display::return_message(
  2238. sprintf(get_lang('StudentXIsNotSubscribedToCourse'), $userInfo['complete_name']),
  2239. 'warning'
  2240. )
  2241. );
  2242. continue;
  2243. }
  2244. $studentUserIdList[] = $userInfo['user_id'];
  2245. }
  2246. self::subscribe_users($studentUserIdList, $groupInfo);
  2247. }
  2248. $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
  2249. if (!empty($tutors)) {
  2250. $tutorIdList = array();
  2251. foreach ($tutors as $tutor) {
  2252. $userInfo = api_get_user_info_from_username($tutor);
  2253. if (!$userInfo) {
  2254. continue;
  2255. }
  2256. if (
  2257. !CourseManager::is_user_subscribed_in_course(
  2258. $userInfo['user_id'],
  2259. $courseCode,
  2260. !empty($sessionId),
  2261. $sessionId
  2262. )
  2263. ) {
  2264. Display::addFlash(
  2265. Display::return_message(
  2266. sprintf(get_lang('TutorXIsNotSubscribedToCourse'), $userInfo['complete_name']),
  2267. 'warning'
  2268. )
  2269. );
  2270. continue;
  2271. }
  2272. $tutorIdList[] = $userInfo['user_id'];
  2273. }
  2274. self::subscribe_tutors($tutorIdList, $groupInfo);
  2275. }
  2276. $elementsFound['groups'][] = $groupId;
  2277. }
  2278. }
  2279. if ($deleteNotInArray) {
  2280. // Check categories
  2281. $categories = self::get_categories();
  2282. foreach ($categories as $category) {
  2283. if (!in_array($category['id'], $elementsFound['categories'])) {
  2284. self::delete_category($category['id']);
  2285. $category['category'] = $category['title'];
  2286. $result['deleted']['category'][] = $category;
  2287. }
  2288. }
  2289. $groups = self::get_groups();
  2290. foreach ($groups as $group) {
  2291. if (!in_array($group['iid'], $elementsFound['groups'])) {
  2292. self::delete_groups($group);
  2293. $group['group'] = $group['name'];
  2294. $result['deleted']['group'][] = $group;
  2295. }
  2296. }
  2297. }
  2298. return $result;
  2299. }
  2300. /**
  2301. * Export all categories/group from a course to an array.
  2302. * This function works only in a context of a course.
  2303. * @param int $groupId
  2304. * @param bool $loadUsers
  2305. * @return array
  2306. */
  2307. public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
  2308. {
  2309. $data = array();
  2310. $data[] = array(
  2311. 'category',
  2312. 'group',
  2313. 'description',
  2314. 'announcements_state',
  2315. 'calendar_state',
  2316. 'chat_state',
  2317. 'doc_state',
  2318. 'forum_state',
  2319. 'work_state',
  2320. 'wiki_state',
  2321. 'max_student',
  2322. 'self_reg_allowed',
  2323. 'self_unreg_allowed',
  2324. 'groups_per_user'
  2325. );
  2326. $count = 1;
  2327. if ($loadUsers) {
  2328. $data[0][] = 'students';
  2329. $data[0][] = 'tutors';
  2330. }
  2331. if ($loadUsers == false) {
  2332. $categories = self::get_categories();
  2333. foreach ($categories as $categoryInfo) {
  2334. $data[$count] = array(
  2335. $categoryInfo['title'],
  2336. null,
  2337. $categoryInfo['description'],
  2338. $categoryInfo['announcements_state'],
  2339. $categoryInfo['calendar_state'],
  2340. $categoryInfo['chat_state'],
  2341. $categoryInfo['doc_state'],
  2342. $categoryInfo['forum_state'],
  2343. $categoryInfo['work_state'],
  2344. $categoryInfo['wiki_state'],
  2345. $categoryInfo['max_student'],
  2346. $categoryInfo['self_reg_allowed'],
  2347. $categoryInfo['self_unreg_allowed'],
  2348. $categoryInfo['groups_per_user']
  2349. );
  2350. $count++;
  2351. }
  2352. }
  2353. $groups = self::get_group_list();
  2354. foreach ($groups as $groupInfo) {
  2355. $categoryTitle = null;
  2356. $categoryInfo = self::get_category($groupInfo['category_id']);
  2357. $groupSettings = self::get_group_properties($groupInfo['id']);
  2358. if (!empty($categoryInfo)) {
  2359. $categoryTitle = $categoryInfo['title'];
  2360. }
  2361. $users = self::getStudents($groupInfo['iid']);
  2362. $userList = array();
  2363. foreach ($users as $user) {
  2364. $user = api_get_user_info($user['user_id']);
  2365. $userList[] = $user['username'];
  2366. }
  2367. $tutors = self::getTutors($groupInfo);
  2368. $tutorList = array();
  2369. foreach ($tutors as $user) {
  2370. $user = api_get_user_info($user['user_id']);
  2371. $tutorList[] = $user['username'];
  2372. }
  2373. $userListToString = null;
  2374. if (!empty($userList)) {
  2375. $userListToString = implode(',', $userList);
  2376. }
  2377. $tutorListToString = null;
  2378. if (!empty($tutorList)) {
  2379. $tutorListToString = implode(',', $tutorList);
  2380. }
  2381. $data[$count] = array(
  2382. $categoryTitle,
  2383. $groupSettings['name'],
  2384. $groupSettings['description'],
  2385. $groupSettings['announcements_state'],
  2386. $groupSettings['calendar_state'],
  2387. $groupSettings['chat_state'],
  2388. $groupSettings['doc_state'],
  2389. $groupSettings['forum_state'],
  2390. $groupSettings['work_state'],
  2391. $groupSettings['wiki_state'],
  2392. $groupSettings['maximum_number_of_students'],
  2393. $groupSettings['self_registration_allowed'],
  2394. $groupSettings['self_unregistration_allowed'],
  2395. null
  2396. );
  2397. if ($loadUsers) {
  2398. $data[$count][] = $userListToString;
  2399. $data[$count][] = $tutorListToString;
  2400. }
  2401. if (!empty($groupId)) {
  2402. if ($groupId == $groupInfo['id']) {
  2403. break;
  2404. }
  2405. }
  2406. $count++;
  2407. }
  2408. return $data;
  2409. }
  2410. /**
  2411. * @param string $default
  2412. */
  2413. public static function getSettingBar($default)
  2414. {
  2415. $activeSettings = null;
  2416. $activeTutor = null;
  2417. $activeMember = null;
  2418. switch ($default) {
  2419. case 'settings':
  2420. $activeSettings = 'active';
  2421. break;
  2422. case'tutor':
  2423. $activeTutor = 'active';
  2424. break;
  2425. case 'member':
  2426. $activeMember = 'active';
  2427. break;
  2428. }
  2429. $url = api_get_path(WEB_CODE_PATH).'group/%s?'.api_get_cidreq();
  2430. echo '
  2431. <ul class="toolbar-groups nav nav-tabs">
  2432. <li class="'.$activeSettings.'">
  2433. <a href="'.sprintf($url, 'settings.php').'">
  2434. '.Display::return_icon('settings.png').' '.get_lang('Settings').'
  2435. </a>
  2436. </li>
  2437. <li class="'.$activeMember.'">
  2438. <a href="'.sprintf($url, 'member_settings.php').'">
  2439. '.Display::return_icon('user.png').' '.get_lang('GroupMembers').'
  2440. </a>
  2441. </li>
  2442. <li class="'.$activeTutor.'">
  2443. <a href="'.sprintf($url, 'tutor_settings.php').'">
  2444. '.Display::return_icon('teacher.png').' '.get_lang('GroupTutors').'
  2445. </a>
  2446. </li>
  2447. </ul>';
  2448. }
  2449. /**
  2450. * @param int $courseId
  2451. * @param string $keyword
  2452. * @return string
  2453. */
  2454. public static function getOverview($courseId, $keyword = null)
  2455. {
  2456. $content = null;
  2457. $categories = self::get_categories();
  2458. if (!empty($categories)) {
  2459. foreach ($categories as $category) {
  2460. if (api_get_setting('allow_group_categories') == 'true') {
  2461. $content .= '<h2>'.$category['title'].'</h2>';
  2462. }
  2463. if (!empty($keyword)) {
  2464. $groups = self::getGroupListFilterByName($keyword, $category['id'], $courseId);
  2465. } else {
  2466. $groups = self::get_group_list($category['id']);
  2467. }
  2468. if (empty($groups)) {
  2469. $groups = self::get_group_list();
  2470. }
  2471. $content .= '<ul>';
  2472. if (!empty($groups)) {
  2473. foreach ($groups as $group) {
  2474. $content .= '<li>';
  2475. $content .= Display::tag('h3', Security::remove_XSS($group['name']));
  2476. $users = self::getTutors($group);
  2477. if (!empty($users)) {
  2478. $content .= '<ul>';
  2479. $content .= "<li>".Display::tag('h4', get_lang('Tutors'))."</li><ul>";
  2480. foreach ($users as $user) {
  2481. $user_info = api_get_user_info($user['user_id']);
  2482. $content .= '<li title="'.$user_info['username'].'">'.
  2483. $user_info['complete_name_with_username'].
  2484. '</li>';
  2485. }
  2486. $content .= '</ul>';
  2487. $content .= '</ul>';
  2488. }
  2489. $users = self::getStudents($group['iid']);
  2490. if (!empty($users)) {
  2491. $content .= '<ul>';
  2492. $content .= "<li>".Display::tag('h4', get_lang('Students'))."</li><ul>";
  2493. foreach ($users as $user) {
  2494. $user_info = api_get_user_info($user['user_id']);
  2495. $content .= '<li title="'.$user_info['username'].'">'.
  2496. $user_info['complete_name_with_username'].
  2497. '</li>';
  2498. }
  2499. $content .= '</ul>';
  2500. $content .= '</ul>';
  2501. }
  2502. $content .= '</li>';
  2503. }
  2504. }
  2505. $content .= '</ul>';
  2506. }
  2507. }
  2508. return $content;
  2509. }
  2510. /**
  2511. * Returns the search form
  2512. * @return string
  2513. */
  2514. public static function getSearchForm()
  2515. {
  2516. $url = api_get_path(WEB_CODE_PATH).'group/group_overview.php?'.api_get_cidreq();
  2517. $form = new FormValidator(
  2518. 'search_groups',
  2519. 'get',
  2520. $url,
  2521. null,
  2522. array('class' => 'form-search'),
  2523. FormValidator::LAYOUT_INLINE
  2524. );
  2525. $form->addElement('text', 'keyword');
  2526. $form->addButtonSearch();
  2527. return $form->toHtml();
  2528. }
  2529. /**
  2530. * @param int $groupId
  2531. * @param int $status
  2532. */
  2533. public static function setStatus($groupId, $status)
  2534. {
  2535. $groupInfo = self::get_group_properties($groupId);
  2536. $courseId = api_get_course_int_id();
  2537. if (!empty($groupInfo)) {
  2538. $table = Database::get_course_table(TABLE_GROUP);
  2539. $params = array(
  2540. 'status' => intval($status)
  2541. );
  2542. Database::update(
  2543. $table,
  2544. $params,
  2545. array('c_id = ? AND id = ?' => array($courseId, $groupId))
  2546. );
  2547. }
  2548. }
  2549. /**
  2550. * @param int $groupId
  2551. */
  2552. public static function setVisible($groupId)
  2553. {
  2554. self::setStatus($groupId, 1);
  2555. }
  2556. /**
  2557. * @param int $groupId
  2558. */
  2559. public static function setInvisible($groupId)
  2560. {
  2561. self::setStatus($groupId, 0);
  2562. }
  2563. }