Project

General

Profile

Bug #5625 » groupmanager.lib.php

Yoselyn Castillo, 13/11/2012 21:27

 
1
<?php
2
/* For licensing terms, see /license.txt */
3
/**
4
 *
5
 * @package chamilo.library
6
 */
7
/**
8
 * Code
9
 */
10
require_once 'fileManage.lib.php';
11
require_once 'fileUpload.lib.php';
12
require_once 'document.lib.php';
13

    
14
/**
15
 * This library contains some functions for group-management.
16
 * @author Bart Mollet
17
 * @package chamilo.library
18
 * @todo Add $course_code parameter to all functions. So this GroupManager can
19
 * be used outside a session.
20
 */
21
class GroupManager {
22
    //- VIRTUAL_COURSE_CATEGORY: in this category groups are created based on the virtual  course of a course 
23
    CONST VIRTUAL_COURSE_CATEGORY = 1;
24
    
25
    //DEFAULT_GROUP_CATEGORY: When group categories aren't available (platform-setting),  all groups are created in this 'dummy'-category
26
    CONST DEFAULT_GROUP_CATEGORY = 2;
27
    
28
    /**
29
     * infinite
30
     */
31
    CONST INFINITE  = 99999;
32
    /**
33
     * No limit on the number of users in a group
34
     */
35
    CONST MEMBER_PER_GROUP_NO_LIMIT = 0;
36
    /**
37
     * No limit on the number of groups per user
38
     */
39
    CONST GROUP_PER_MEMBER_NO_LIMIT = 0;
40
    /**
41
     * The tools of a group can have 3 states
42
     * - not available
43
     * - public
44
     * - private
45
     */
46
    CONST TOOL_NOT_AVAILABLE = 0;
47
    CONST TOOL_PUBLIC = 1;
48
    CONST TOOL_PRIVATE = 2;
49
    /**
50
     * Constants for the available group tools
51
     */
52
    CONST GROUP_TOOL_FORUM = 0;
53
    CONST GROUP_TOOL_DOCUMENTS = 1;
54
    CONST GROUP_TOOL_CALENDAR = 2;
55
    CONST GROUP_TOOL_ANNOUNCEMENT = 3;
56
    CONST GROUP_TOOL_WORK = 4;
57
    CONST GROUP_TOOL_WIKI = 5;
58
    CONST GROUP_TOOL_CHAT = 6;
59
    
60
	//GROUP FUNCTIONS
61
	private function __construct() {		
62
	}
63
    
64
    public static function get_groups() {
65
        $table_group 		= Database :: get_course_table(TABLE_GROUP);
66
        $course_id          = api_get_course_int_id();
67
        
68
        $sql = "SELECT * FROM $table_group WHERE c_id = $course_id ";
69
        $result = Database::query($sql);
70
        return Database::store_result($result, 'ASSOC');            
71
    }
72
    
73
	/**
74
	 * Get list of groups for current course.
75
	 * @param int $category The id of the category from which the groups are
76
	 * requested
77
	 * @param string $course_code Default is current course
78
	 * @return array An array with all information about the groups.
79
	 */
80
	public static function get_group_list ($category = null, $course_code = null) {		
81
		$my_user_id = api_get_user_id();		
82
	
83
		$course_info 		= api_get_course_info($course_code);		
84
		$course_id 			= $course_info['real_id'];		
85
		$table_group_user 	= Database :: get_course_table(TABLE_GROUP_USER);
86
		$table_group 		= Database :: get_course_table(TABLE_GROUP);
87

    
88
		//condition for the session
89
		$session_id = api_get_session_id();
90
		$my_status_of_user_in_course = CourseManager::get_user_in_course_status($my_user_id, $course_info['code']);		
91

    
92
		$is_student_in_session = false;
93
		if (is_null($my_status_of_user_in_course) || $my_status_of_user_in_course=='') {//into session
94
			if ($session_id>0) {
95
				$is_student_in_session=true;
96
			}
97
		}
98

    
99
		//COURSEMANAGER or STUDENT
100
		if ($my_status_of_user_in_course == COURSEMANAGER || api_is_allowed_to_edit(null, true) || api_is_drh()) {
101
			$sql = "SELECT g.id ,
102
						g.name ,
103
						g.description ,
104
						g.category_id,
105
						g.max_student maximum_number_of_members,
106
						g.secret_directory,
107
						g.self_registration_allowed,
108
						g.self_unregistration_allowed,
109
						g.session_id,
110
						ug.user_id is_member						
111
					FROM $table_group g
112
					LEFT JOIN $table_group_user ug
113
					ON (ug.group_id = g.id AND ug.user_id = '".api_get_user_id()."' AND ug.c_id = $course_id AND g.c_id = $course_id)";
114
		} elseif ($my_status_of_user_in_course==STUDENT || $is_student_in_session  ===true || $_SESSION['studentview'] == 'studentview') {
115
			$sql = "SELECT g.id,
116
						g.name,
117
						g.description,
118
						g.category_id,
119
						g.max_student maximum_number_of_members,
120
						g.secret_directory,
121
						g.self_registration_allowed,
122
						g.self_unregistration_allowed,
123
						g.session_id,
124
						ug.user_id is_member						
125
					FROM $table_group g
126
					LEFT JOIN $table_group_user ug
127
					ON (ug.group_id = g.id AND ug.user_id = '".api_get_user_id()."' AND ug.c_id = $course_id AND g.c_id = $course_id)";			
128
		}
129
				
130
		$sql .= " WHERE 1=1 ";
131
		
132
		if ($category != null) {
133
			$sql .= "  AND  g.category_id = '".Database::escape_string($category)."' ";
134
			$session_condition = api_get_session_condition($session_id);
135
			if(!empty($session_condition))
136
				$sql .= $session_condition;
137
		} else {
138
			$session_condition = api_get_session_condition($session_id, true);
139
		}
140
	
141
		$sql .= " AND g.c_id = $course_id ";
142
		
143
		if(!empty($session_condition))
144
			$sql .= $session_condition;
145
		$sql .= " GROUP BY g.id ORDER BY UPPER(g.name)";
146

    
147
		if (!api_is_anonymous()) {
148
			$groupList = Database::query($sql);
149
		} else {
150
			return array();
151
		}
152

    
153
		$groups = array();
154
		$thisGroup= array();
155
        while ($thisGroup = Database::fetch_array($groupList)) {
156
            $thisGroup['number_of_members'] = count(GroupManager::get_subscribed_users($thisGroup['id']));
157
            
158
            if ($thisGroup['session_id']!=0) {
159
                $sql_session = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).' WHERE id='.$thisGroup['session_id'];
160
                $rs_session = Database::query($sql_session);
161
                if (Database::num_rows($rs_session)>0) {
162
                    $thisGroup['session_name'] = Database::result($rs_session,0,0);
163
                } else {
164
                    //the session has probably been removed, so the group is now orphaned
165
                }
166
            }
167
            $groups[] = $thisGroup;
168
		}
169
		return $groups;
170
	}
171
    
172
	/**
173
	 * Create a group
174
	 * @param string $name The name for this group
175
	 * @param int $tutor The user-id of the group's tutor
176
	 * @param int $places How many people can subscribe to the new group
177
	 */
178
	public static function create_group ($name, $category_id, $tutor, $places) {
179
		global $_course;		
180
        $table_group = Database :: get_course_table(TABLE_GROUP);
181
        
182
        $session_id = api_get_session_id();
183
        $course_id  = api_get_course_int_id();
184
       	$currentCourseRepository = $_course['path'];
185
		
186
		$category = self :: get_category($category_id);
187

    
188
		if (intval($places) == 0) {
189
			//if the amount of users per group is not filled in, use the setting from the category
190
			$places = $category['max_student'];
191
		} else {
192
            if ($places > $category['max_student'] && $category['max_student'] != 0) {
193
                $places = $category['max_student'];
194
            } 
195
        } 
196
         
197
		 $sql = "INSERT INTO ".$table_group." SET
198
				c_id = $course_id , 
199
				category_id='".Database::escape_string($category_id)."', 
200
				max_student = '".$places."', 
201
				doc_state = '".$category['doc_state']."',
202
				calendar_state = '".$category['calendar_state']."', 
203
				work_state = '".$category['work_state']."', 
204
				announcements_state = '".$category['announcements_state']."', 
205
				forum_state = '".$category['forum_state']."', 
206
				wiki_state = '".$category['wiki_state']."', 
207
				chat_state = '".$category['chat_state']."', 
208
				self_registration_allowed = '".$category['self_reg_allowed']."',  
209
				self_unregistration_allowed = '".$category['self_unreg_allowed']."', 
210
				session_id='".Database::escape_string($session_id)."'";
211
		Database::query($sql);
212
		$lastId = Database::insert_id();
213
        
214
        if ($lastId) {
215
            $desired_dir_name= '/'.replace_dangerous_char($name,'strict').'_groupdocs';
216
            $my_path = api_get_path(SYS_COURSE_PATH).$currentCourseRepository.'/document';
217
            $unique_name = create_unexisting_directory($_course, api_get_user_id(), $session_id, $lastId, NULL, $my_path, $desired_dir_name);               
218
       
219
            /* Stores the directory path into the group table */
220
            $sql = "UPDATE ".$table_group." SET name = '".Database::escape_string($name)."', secret_directory = '".$unique_name."' 
221
                    WHERE c_id = $course_id AND id ='".$lastId."'";
222

    
223
            Database::query($sql);
224

    
225
            // create a forum if needed
226
            if ($category['forum_state'] >= 0) {
227
                require_once api_get_path(SYS_CODE_PATH).'forum/forumconfig.inc.php';
228
                require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
229

    
230
                $forum_categories = get_forum_categories();
231
                
232
                $values = array();
233
                $values['forum_title'] = $name;                
234
                $values['group_id'] = $lastId;
235
                
236
                $counter = 0;
237
                foreach ($forum_categories as $key=>$value) {
238
                    if ($counter==0) {
239
                        $forum_category_id = $key;
240
                    }
241
                    $counter++;
242
                }
243
                // A sanity check.
244
                if (empty($forum_category_id)) {
245
                    $forum_category_id = 0;
246
                }
247
                $values['forum_category'] = $forum_category_id;
248
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
249
                $values['students_can_edit_group']['students_can_edit'] = 0;
250
                $values['approval_direct_group']['approval_direct'] = 0;
251
                $values['allow_attachments_group']['allow_attachments'] = 1;
252
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
253
                $values['default_view_type_group']['default_view_type']=api_get_setting('default_forum_view');
254
                $values['group_forum'] = $lastId;
255
                if ($category['forum_state'] == '1') {
256
                    $values['public_private_group_forum_group']['public_private_group_forum']='public';
257
                } elseif  ($category['forum_state'] == '2') {
258
                    $values['public_private_group_forum_group']['public_private_group_forum']='private';
259
                } elseif  ($category['forum_state'] == '0') {
260
                    $values['public_private_group_forum_group']['public_private_group_forum']='unavailable';
261
                }
262
                store_forum($values);
263
            }
264
        }
265
     
266
		return $lastId;
267
	}
268
	/**
269
	 * Create subgroups.
270
	 * This function creates new groups based on an existing group. It will
271
	 * create the specified number of groups and fill those groups with users
272
	 * from the base group
273
	 * @param int $group_id The group from which subgroups have to be created.
274
	 * @param int $number_of_groups The number of groups that have to be created
275
	 */
276
	public static function create_subgroups ($group_id, $number_of_groups) {
277
		$course_id = api_get_course_int_id();
278
		$table_group = Database :: get_course_table(TABLE_GROUP);
279
		$category_id = self :: create_category('Subgroups', '', GroupManager::TOOL_PRIVATE, GroupManager::TOOL_PRIVATE, 0, 0, 1, 1);
280
		$users = self :: get_users($group_id);
281
		$group_ids = array ();
282

    
283
		for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr ++)
284
		{
285
			$group_ids[] = self :: create_group('SUBGROUP '.$group_nr, $category_id, 0, 0);
286
		}
287
		$members = array ();
288
		foreach ($users as $index => $user_id) {
289
			self :: subscribe_users($user_id, $group_ids[$index % $number_of_groups]);
290
			$members[$group_ids[$index % $number_of_groups]]++;
291
		}
292
		foreach ($members as $group_id => $places) {
293
			$sql = "UPDATE $table_group SET max_student = $places WHERE c_id = $course_id  AND id = $group_id";
294
			Database::query($sql);
295
		}
296
	}
297
	/**
298
	 * Create groups from all virtual courses in the given course.
299
	 */
300
	public static function create_groups_from_virtual_courses() {
301
		self :: delete_category(self::VIRTUAL_COURSE_CATEGORY);
302
		$id = self :: create_category(get_lang('GroupsFromVirtualCourses'), '', GroupManager::TOOL_NOT_AVAILABLE, GroupManager::TOOL_NOT_AVAILABLE, 0, 0, 1, 1);
303
		$table_group_cat = Database :: get_course_table(TABLE_GROUP_CATEGORY);
304
        $course_id = api_get_course_int_id();
305
        
306
		$sql = "UPDATE ".$table_group_cat." SET id=".self::VIRTUAL_COURSE_CATEGORY." WHERE c_id = $course_id AND id=$id";
307
		Database::query($sql);
308
		$course = api_get_course_info();
309
		$course['code'] = $course['sysCode'];
310
		$course['title'] = $course['name'];
311
		$virtual_courses = CourseManager :: get_virtual_courses_linked_to_real_course($course['sysCode']);
312
		$group_courses = $virtual_courses;
313
		$group_courses[] = $course;
314
		$ids = array ();
315
		foreach ($group_courses as $index => $group_course) {
316
			$users = CourseManager :: get_user_list_from_course_code($group_course['code']);
317
			$members = array ();
318
			foreach ($users as $index => $user) {
319
				if ($user['status'] == 5 && $user['tutor_id'] == 0) {
320
					$members[] = $user['user_id'];
321
				}
322
			}
323
			$id = self :: create_group($group_course['code'], self::VIRTUAL_COURSE_CATEGORY, 0, count($members));
324
			self :: subscribe_users($members, $id);
325
			$ids[] = $id;
326
		}
327
		return $ids;
328
	}
329
	/**
330
	 * Create a group for every class subscribed to the current course
331
	 * @param int $category_id The category in which the groups should be
332
	 * created
333
	 */
334
	public static function create_class_groups ($category_id) {
335
		global $_course;
336
        $options['where'] = array(" usergroup.course_id = ? " =>  api_get_real_course_id());
337
        $obj = new UserGroup();	 
338
        $classes = $obj->get_usergroup_in_course($options);		
339
		$group_ids = array();
340
		foreach($classes as $index => $class)
341
		{
342
		    $users_ids = $obj->get_users_by_usergroup($class['id']);
343
			$group_id = self::create_group($class['name'],$category_id,0,count($users_ids));
344
			self::subscribe_users($users_ids,$group_id);
345
			$group_ids[] = $group_id;
346
		}
347
		return $group_ids;
348
	}
349

    
350
	/**
351
	 * deletes groups and their data.
352
	 * @author Christophe Gesche <christophe.gesche@claroline.net>
353
	 * @author Hugues Peeters <hugues.peeters@claroline.net>
354
	 * @author Bart Mollet
355
	 * @param  mixed   $groupIdList - group(s) to delete. It can be a single id
356
	 *                                (int) or a list of id (array).
357
	 * @param string $course_code Default is current course
358
	 * @return integer              - number of groups deleted.
359
	 */
360
	public static function delete_groups($group_ids, $course_code = null) {		
361
		$course_info = api_get_course_info($course_code);
362
		$course_id	 = $course_info['real_id'];   
363

    
364
		// Database table definitions
365
		$group_table 			= Database :: get_course_table(TABLE_GROUP);
366
		$forum_table 			= Database :: get_course_table(TABLE_FORUM);
367
				
368
		$group_ids = is_array($group_ids) ? $group_ids : array ($group_ids);
369
		$group_ids = array_map('intval',$group_ids);
370

    
371
		if (api_is_course_coach()) { 
372
		    //a coach can only delete courses from his session
373
			for($i=0 ; $i<count($group_ids) ; $i++) {
374
				if(!api_is_element_in_the_session(TOOL_GROUP,$group_ids[$i])) {
375
					array_splice($group_ids,$i,1);
376
					$i--;
377
				}
378
			}
379
			if(count($group_ids)==0)
380
				return 0;
381
		}
382

    
383
		// Unsubscribe all users
384
		self :: unsubscribe_all_users($group_ids);
385
		$sql = "SELECT id, secret_directory, session_id FROM $group_table WHERE c_id = $course_id AND id IN (".implode(' , ', $group_ids).")";
386
		$db_result = Database::query($sql);
387
		$forum_ids = array ();
388

    
389
		while ($group = Database::fetch_object($db_result)) {
390
			// move group-documents to garbage
391
			//$source_directory = api_get_path(SYS_COURSE_PATH).$course['path']."/group/".$group->secret_directory;
392
			$source_directory = api_get_path(SYS_COURSE_PATH).$course['path']."/document".$group->secret_directory;
393
			//File to renamed
394
			$destination_dir = api_get_path(SYS_COURSE_PATH).$course['path']."/document".$group->secret_directory.'_DELETED_'.$group->id;
395

    
396
			if (!empty($group->secret_directory)) {
397
				//Deleting from document tool
398
				DocumentManager::delete_document($course, $group->secret_directory, $source_directory);
399

    
400
				if (file_exists($source_directory)) {
401
					if (api_get_setting('permanently_remove_deleted_files') == 'true') {
402
						//Delete
403
						 my_delete($source_directory);
404
					} else {
405
						//Rename
406
						rename($source_directory, $destination_dir);
407
					}
408
				}
409
			}
410
			//$forum_ids[] = $group->forum_id;
411
		}
412

    
413
		// delete the groups
414
		$sql = "DELETE FROM ".$group_table." WHERE c_id = $course_id AND id IN ('".implode("' , '", $group_ids)."')";
415
		Database::query($sql);
416

    
417
		$sql2 = "DELETE FROM ".$forum_table." WHERE c_id = $course_id AND forum_of_group IN ('".implode("' , '", $group_ids)."')";
418
		Database::query($sql2);
419

    
420
		return Database::affected_rows();
421
	}
422

    
423
	/**
424
	 * Get group properties
425
	 * @param int $group_id The group from which properties are requested.
426
	 * @return array All properties. Array-keys are name, tutor_id, description, maximum_number_of_students, directory and visibility of tools
427
	 */
428
	public static function get_group_properties($group_id) {
429
	    $course_id = api_get_course_int_id();
430
		if (empty($group_id) or !is_integer(intval($group_id)) ) {
431
			return null;
432
		}
433
        $result = array();
434
        
435
		$table_group = Database :: get_course_table(TABLE_GROUP);
436
		$sql = "SELECT * FROM $table_group WHERE c_id = $course_id AND id = ".intval($group_id);
437
		$db_result = Database::query($sql);
438
        $db_object = Database::fetch_object($db_result);
439
        
440
        $result['id'] 							= $db_object->id;
441
        $result['name'] 						= $db_object->name;
442
        $result['tutor_id'] 					= isset($db_object->tutor_id)?$db_object->tutor_id:null;
443
        $result['description']					= $db_object->description;
444
        $result['maximum_number_of_students'] 	= $db_object->max_student;
445
        $result['doc_state'] 					= $db_object->doc_state;
446
        $result['work_state'] 					= $db_object->work_state;
447
        $result['calendar_state'] 				= $db_object->calendar_state;
448
        $result['announcements_state'] 			= $db_object->announcements_state;
449
        $result['forum_state'] 					= $db_object->forum_state;
450
        $result['wiki_state'] 					= $db_object->wiki_state;
451
        $result['chat_state'] 					= $db_object->chat_state;
452
        $result['directory'] 					= $db_object->secret_directory;
453
        $result['self_registration_allowed'] 	= $db_object->self_registration_allowed;
454
        $result['self_unregistration_allowed'] 	= $db_object->self_unregistration_allowed;
455
        
456
        $result['count_users'] 	= count(self::get_subscribed_users($group_id));
457
        $result['count_tutor'] 	= count(self::get_subscribed_tutors($group_id));
458
        $result['count_all'] = $result['count_users'] + $result['count_tutor'];
459
        
460
		return $result;
461
	}
462
	/**
463
	 * Set group properties
464
	 * Changes the group's properties.
465
	 * @param int		Group Id
466
	 * @param string 	Group name
467
	 * @param string	Group description
468
	 * @param int		Max number of students in group
469
	 * @param int		Document tool's visibility (0=none,1=private,2=public)
470
	 * @param int		Work tool's visibility (0=none,1=private,2=public)
471
	 * @param int		Calendar tool's visibility (0=none,1=private,2=public)
472
	 * @param int		Announcement tool's visibility (0=none,1=private,2=public)
473
	 * @param int		Forum tool's visibility (0=none,1=private,2=public)
474
	 * @param int		Wiki tool's visibility (0=none,1=private,2=public)
475
	 * @param int		Chat tool's visibility (0=none,1=private,2=public)
476
	 * @param bool 		Whether self registration is allowed or not
477
	 * @param bool 		Whether self unregistration is allowed or not
478
	 * @return bool 	TRUE if properties are successfully changed, false otherwise
479
	 */
480
	public static function set_group_properties ($group_id, $name, $description, $maximum_number_of_students, $doc_state, $work_state, $calendar_state, $announcements_state, $forum_state, $wiki_state, $chat_state, $self_registration_allowed, $self_unregistration_allowed) {
481
		$table_group = Database :: get_course_table(TABLE_GROUP);
482
		$table_forum = Database :: get_course_table(TABLE_FORUM);
483
		//$forum_id = get_forums_of_group($group_id);
484
		$group_id = Database::escape_string($group_id);
485
        $category = self::get_category_from_group($group_id);
486
        if ($maximum_number_of_students > $category['max_student'] && $category['max_student'] != 0) {
487
            $maximum_number_of_students = $category['max_student'];
488
        }
489
        $course_id = api_get_course_int_id();
490
        
491
		$sql = "UPDATE ".$table_group."
492
					SET name='".Database::escape_string(trim($name))."',
493
					doc_state = '".Database::escape_string($doc_state)."',
494
					work_state = '".Database::escape_string($work_state)."',
495
					calendar_state = '".Database::escape_string($calendar_state)."',
496
					announcements_state = '".Database::escape_string($announcements_state)."',
497
					forum_state = '".Database::escape_string($forum_state)."',
498
					wiki_state = '".Database::escape_string($wiki_state)."',
499
					chat_state = '".Database::escape_string($chat_state)."',
500
					description='".Database::escape_string(trim($description))."',
501
					max_student=".Database::escape_string($maximum_number_of_students).",
502
					self_registration_allowed='".Database::escape_string($self_registration_allowed)."',
503
					self_unregistration_allowed='".Database::escape_string($self_unregistration_allowed)."'
504
					WHERE c_id = $course_id AND id=".$group_id;
505
		$result = Database::query($sql);
506
		//Here we are updating a field in the table forum_forum that perhaps duplicates the table group_info.forum_state cvargas
507
		$forum_state = (int) $forum_state;
508
		$sql2 = "UPDATE ".$table_forum." SET ";
509
		if ($forum_state===1) {
510
			$sql2 .= " forum_group_public_private='public' ";
511
		} elseif ($forum_state===2) {
512
			$sql2 .= " forum_group_public_private='private' ";
513
		} elseif ($forum_state===0) {
514
			$sql2 .= " forum_group_public_private='unavailable' ";
515
		}
516
		$sql2 .=" WHERE c_id = 	$course_id AND forum_of_group=".$group_id;
517
		$result2 = Database::query($sql2);
518
		return $result;
519
	}
520
	/**
521
	 * Get the total number of groups for the current course.
522
	 * @return int The number of groups for the current course.
523
	 */
524
	public static function get_number_of_groups() {
525
		$course_id = api_get_course_int_id();
526
		$table_group = Database :: get_course_table(TABLE_GROUP);
527
		$res = Database::query("SELECT COUNT(id) AS number_of_groups FROM $table_group WHERE c_id = $course_id ");
528
		$obj = Database::fetch_object($res);
529
		return $obj->number_of_groups;
530
	}
531

    
532
	//GROUPCATEGORY FUNCTIONS
533
	  
534
	/**
535
	 * Get all categories
536
	 * @param string $course_code The cours (default = current course)
537
	 */
538
	public static function get_categories ($course_code = null) {
539
		$course_info = api_get_course_info($course_code);
540
		$course_id	 = $course_info['real_id'];
541
		$table_group_cat = Database :: get_course_table(TABLE_GROUP_CATEGORY);
542
		$sql = "SELECT * FROM $table_group_cat WHERE c_id = $course_id ORDER BY display_order";
543
		$res = Database::query($sql);
544
		$cats = array ();
545
		while ($cat = Database::fetch_array($res)) {
546
			$cats[] = $cat;
547
		}
548
		return $cats;
549
	}
550
	/**
551
	 * Get a group category
552
	 * @param int $id The category id
553
	 * @param string $course_code The course (default = current course)
554
	 */
555
	public static function get_category ($id, $course_code = null) {
556
        if (empty($id)) {
557
            return array();
558
        }
559
		$course_info = api_get_course_info($course_code);
560
		$course_id	 = $course_info['real_id'];		
561
		$id = Database::escape_string($id);        
562
		$table_group_cat = Database :: get_course_table(TABLE_GROUP_CATEGORY);
563
		$sql = "SELECT * FROM $table_group_cat WHERE c_id = $course_id AND id = $id LIMIT 1";
564
		$res = Database::query($sql);
565
		return Database::fetch_array($res);
566
	}
567
	/**
568
	 * Get the unique category of a given group
569
	 * @param int $group_id The id of the group
570
	 * @param string $course_code The course in which the group is (default =
571
	 * current course)
572
	 * @return array The category
573
	 */
574
	public static function get_category_from_group ($group_id, $course_code = null) {	
575
		$table_group 		= Database :: get_course_table(TABLE_GROUP);
576
		$table_group_cat 	= Database :: get_course_table(TABLE_GROUP_CATEGORY);
577
        
578
        if (empty($group_id)) {
579
            return array();
580
        }
581
		
582
		$course_info = api_get_course_info($course_code);
583
		$course_id	 = $course_info['real_id'];
584
		
585
		$group_id = Database::escape_string($group_id);
586
		$sql = "SELECT gc.* FROM $table_group_cat gc, $table_group g 
587
				WHERE 	gc.c_id = $course_id AND 
588
						g.c_id = $course_id AND
589
						gc.id = g.category_id AND g.id= $group_id LIMIT 1";
590
		$res = Database::query($sql);
591
        $cat = array();
592
        if (Database::num_rows($res)) {
593
            $cat = Database::fetch_array($res);
594
        }
595
		return $cat;
596
	}
597
	/**
598
	 * Delete a group category
599
	 * @param int $cat_id The id of the category to delete
600
	 * @param string $course_code The code in which the category should be
601
	 * deleted (default = current course)
602
	 */
603
	public static function delete_category ($cat_id, $course_code = null) {
604
		$course_info = api_get_course_info($course_code);
605
		$course_id	 = $course_info['real_id'];
606
		
607
		$table_group 		= Database :: get_course_table(TABLE_GROUP);
608
		$table_group_cat 	= Database :: get_course_table(TABLE_GROUP_CATEGORY);
609
		$cat_id 			= Database::escape_string($cat_id);
610
		$sql = "SELECT id FROM $table_group WHERE c_id = $course_id AND category_id='".$cat_id."'";
611
		$res = Database::query($sql);
612
		if (Database::num_rows($res) > 0) {
613
			$groups_to_delete = array ();
614
			while ($group = Database::fetch_object($res)) {
615
				$groups_to_delete[] = $group->id;
616
			}
617
			self :: delete_groups($groups_to_delete);
618
		}
619
		$sql = "DELETE FROM $table_group_cat WHERE c_id = $course_id  AND id='".$cat_id."'";
620
		Database::query($sql);
621
	}
622
	/**
623
	 * Create group category
624
	 * @param string $title The title of the new category
625
	 * @param string $description The description of the new category
626
	 * @param bool $self_registration_allowed
627
	 * @param bool $self_unregistration_allowed
628
	 * @param int $max_number_of_students
629
	 * @param int $groups_per_user
630
	 */
631
	public static function create_category ($title, $description, $doc_state, $work_state, $calendar_state, $announcements_state, $forum_state, $wiki_state,
632
											$chat_state = 1, $self_registration_allowed = 0, $self_unregistration_allowed = 0, $maximum_number_of_students = 8, $groups_per_user = 0) {
633
		$table_group_category = Database :: get_course_table(TABLE_GROUP_CATEGORY);
634
		
635
		$course_id = api_get_course_int_id();
636
		
637
		$sql = "SELECT MAX(display_order)+1 as new_order FROM $table_group_category WHERE c_id = $course_id ";
638
		$res = Database::query($sql);
639
		$obj = Database::fetch_object($res);
640
		if (!isset ($obj->new_order)) {
641
			$obj->new_order = 1;
642
		}
643
		$sql = "INSERT INTO ".$table_group_category." SET
644
					c_id =  $course_id , 
645
					title='".Database::escape_string($title)."',
646
					display_order ='".$obj->new_order."',
647
					description='".Database::escape_string($description)."',
648
					doc_state = '".Database::escape_string($doc_state)."',
649
					work_state = '".Database::escape_string($work_state)."',
650
					calendar_state = '".Database::escape_string($calendar_state)."',
651
              		announcements_state = '".Database::escape_string($announcements_state)."',
652
              		forum_state = '".Database::escape_string($forum_state)."',
653
					wiki_state = '".Database::escape_string($wiki_state)."',
654
					chat_state = '".Database::escape_string($chat_state)."',
655
					groups_per_user   = '".Database::escape_string($groups_per_user)."',
656
					self_reg_allowed = '".Database::escape_string($self_registration_allowed)."',
657
					self_unreg_allowed = '".Database::escape_string($self_unregistration_allowed)."',
658
					max_student = '".Database::escape_string($maximum_number_of_students)."' ";
659
		Database::query($sql);
660
		$id = Database::insert_id();
661
		if ($id == self::VIRTUAL_COURSE_CATEGORY) {
662
			$sql = "UPDATE  ".$table_group_category." SET id = ". ($id +1)." WHERE c_id = $course_id AND id = $id";
663
			Database::query($sql);
664
			return $id +1;
665
		}
666
		return $id;
667
	}
668

    
669
	/**
670
	 * Update group category
671
	 * @param int $id The id of the category
672
	 * @param string $title The title of the new category
673
	 * @param string $description The description of the new category
674
	 * @param bool $self_registration_allowed
675
	 * @param bool $self_unregistration_allowed
676
	 * @param int $max_number_of_students
677
	 * @param int $groups_per_user
678
	 */
679
	public static function update_category ($id, $title, $description, $doc_state, $work_state, $calendar_state, $announcements_state, $forum_state, $wiki_state, $chat_state, $self_registration_allowed, $self_unregistration_allowed, $maximum_number_of_students, $groups_per_user) {
680
		$table_group_category = Database :: get_course_table(TABLE_GROUP_CATEGORY);
681
		$id = Database::escape_string($id);
682
		
683
		$course_id = api_get_course_int_id();
684
		
685
		$sql = "UPDATE ".$table_group_category."
686
				SET title='".Database::escape_string($title)."',
687
				description='".Database::escape_string($description)."',
688
				doc_state = '".Database::escape_string($doc_state)."',
689
				work_state = '".Database::escape_string($work_state)."',
690
            	calendar_state = '".Database::escape_string($calendar_state)."',
691
            	announcements_state = '".Database::escape_string($announcements_state)."',
692
            	forum_state = '".Database::escape_string($forum_state)."',
693
				wiki_state = '".Database::escape_string($wiki_state)."',
694
				chat_state = '".Database::escape_string($chat_state)."',
695
				groups_per_user   = ".Database::escape_string($groups_per_user).",
696
				self_reg_allowed = '".Database::escape_string($self_registration_allowed)."',
697
				self_unreg_allowed = '".Database::escape_string($self_unregistration_allowed)."',
698
				max_student = ".Database::escape_string($maximum_number_of_students)."
699
				WHERE c_id = $course_id AND id=$id";
700
		Database::query($sql);
701
	}
702

    
703

    
704
	/**
705
	 * Returns the number of groups of the user with the greatest number of
706
	 * subscribtions in the given category
707
	 */
708
	public static function get_current_max_groups_per_user ($category_id = null, $course_code = null) {		
709
		$course_info = api_get_course_info ($course_code);
710
		$group_table = Database :: get_course_table(TABLE_GROUP);
711
		$group_user_table = Database :: get_course_table(TABLE_GROUP_USER);
712
		$sql = 'SELECT COUNT(gu.group_id) AS current_max FROM '.$group_user_table.' gu, '.$group_table.' g 
713
				WHERE g.c_id = '.$course_info['real_id'].' AND gu.group_id = g.id ';
714
		if ($category_id != null) {
715
			$category_id = Database::escape_string($category_id);
716
			$sql .= ' AND g.category_id = '.$category_id;
717
		}
718
		$sql .= ' GROUP BY gu.user_id ORDER BY current_max DESC LIMIT 1';
719
		$res = Database::query($sql);
720
		$obj = Database::fetch_object($res);
721
		return $obj->current_max;
722
	}
723
	
724
	/**
725
	 * Swaps the display-order of two categories
726
	 * @param int $id1 The id of the first category
727
	 * @param int $id2 The id of the second category
728
	 */
729
	public static function swap_category_order ($id1, $id2) {
730
		$table_group_cat = Database :: get_course_table(TABLE_GROUP_CATEGORY);
731
		$id1 = Database::escape_string($id1);
732
		$id2 = Database::escape_string($id2);
733
		
734
		$course_id = api_get_course_int_id();
735
		
736

    
737
		$sql = "SELECT id,display_order FROM $table_group_cat WHERE id IN ($id1,$id2) AND c_id = $course_id ";
738
		$res = Database::query($sql);
739
		$cat1 = Database::fetch_object($res);
740
		$cat2 = Database::fetch_object($res);
741
		$sql = "UPDATE $table_group_cat SET display_order=$cat2->display_order WHERE id = $cat1->id AND c_id = $course_id ";
742
		Database::query($sql);
743
		$sql = "UPDATE $table_group_cat SET display_order=$cat1->display_order WHERE id = $cat2->id AND c_id = $course_id ";
744
		Database::query($sql);
745
	}
746
    
747
	//GROUP USERS FUNCTIONS
748
	
749
	/**
750
	 * Get all users from a given group
751
	 * @param int $group_id The group
752
         * @return array list of user id
753
	 */
754
	public static function get_users($group_id, $load_extra_info = false) {
755
		$group_user_table = Database :: get_course_table(TABLE_GROUP_USER);
756
		$group_id = Database::escape_string($group_id);
757
		$course_id = api_get_course_int_id();
758
		$sql = "SELECT user_id FROM $group_user_table WHERE c_id = $course_id AND group_id = $group_id";
759
		$res = Database::query($sql);
760
		$users = array ();
761
		while ($obj = Database::fetch_object($res)) {
762
            if ($load_extra_info) {
763
                $users[] = api_get_user_info($obj->user_id);
764
            } else {
765
                $users[] = $obj->user_id;
766
            }
767
		}
768
		return $users;
769
	}
770
    
771
    public static function get_members_and_tutors($group_id) {
772
        $group_user_table = Database :: get_course_table(TABLE_GROUP_USER);
773
        $tutor_user_table = Database :: get_course_table(TABLE_GROUP_TUTOR);
774
        $course_id = api_get_course_int_id();
775
		$group_id = intval($group_id);		
776
		$sql = "SELECT user_id FROM $group_user_table WHERE c_id = $course_id AND group_id = $group_id";
777
		$res = Database::query($sql);
778
		$users = array();
779
        
780
		while ($obj = Database::fetch_object($res)) {            
781
            $users[] = api_get_user_info($obj->user_id);            
782
		}
783
        
784
        $sql = "SELECT user_id FROM $tutor_user_table WHERE c_id = $course_id AND group_id = $group_id";
785
		$res = Database::query($sql);		
786
		while ($obj = Database::fetch_object($res)) {            
787
            $users[] = api_get_user_info($obj->user_id);            
788
		}        
789
		return $users;        
790
    }
791
        
792
    /**
793
        * Returns users belonging to any of the group 
794
        * 
795
        * @param array $groups list of group ids
796
        * @return array list of user ids
797
        */
798
    public static function get_groups_users($groups = array()) {
799
        $result = array();
800
        $tbl_group_user = Database::get_course_table(TABLE_GROUP_USER); 
801
        $course_id = api_get_course_int_id();
802

    
803
        $groups = array_map('intval', $groups);
804
        $groups = implode(', ', $groups);	//protect individual elements with surrounding quotes
805
        $sql = "SELECT DISTINCT user_id
806
                FROM $tbl_group_user gu
807
                WHERE c_id = $course_id AND gu.group_id IN ($groups)";
808
        $rs = Database::query($sql);
809
        while ($row = Database::fetch_array($rs)) {
810
            $result[] = $row['user_id']; 
811
        }
812
        return $result;
813
    }
814

    
815
	/**
816
	 * Fill the groups with students.
817
	 * The algorithm takes care to first fill the groups with the least # of users.
818
	 *	Analysis
819
	 *	There was a problem with the "ALL" setting.
820
	 *	When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
821
	 *	and in both cased the query does not work as expected.
822
	 *	Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
823
	 *	Better solution: that's up to you.
824
	 *
825
	 *	Note
826
	 *	Throughout Dokeos there is some confusion about "course id" and "course code"
827
	 *	The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
828
	 *	However, there is also a integer course_id that uniquely identifies the course.
829
	 *	ywarnier:> Now the course_id has been removed (25/1/2005)
830
	 *	The databases are als very inconsistent in this.
831
	 *
832
	 * @author Chrisptophe Gesche <christophe.geshe@claroline.net>,
833
	 *         Hugues Peeters     <hugues.peeters@claroline.net> - original version
834
	 * @author Roan Embrechts - virtual course support, code cleaning
835
	 * @author Bart Mollet - code cleaning, use other GroupManager-functions
836
	 * @return void
837
	 */
838
	public static function fill_groups ($group_ids) {
839
        global $_course;
840
        
841
		$group_ids = is_array($group_ids) ? $group_ids : array ($group_ids);
842
		$group_ids = array_map('intval', $group_ids);
843
        
844
		if (api_is_course_coach()) {
845
			for ($i=0 ; $i< count($group_ids) ; $i++) {
846
				if (!api_is_element_in_the_session(TOOL_GROUP, $group_ids[$i])){
847
					array_splice($group_ids,$i,1);
848
					$i--;
849
				}
850
			}
851
			if (count($group_ids)==0) {
852
				return false;                
853
            }
854
		}
855
     		
856
		$category 			= self::get_category_from_group($group_ids[0]);
857
        
858
		$groups_per_user 	= $category['groups_per_user'];		
859
		$group_table 		= Database :: get_course_table(TABLE_GROUP);
860
		$group_user_table 	= Database :: get_course_table(TABLE_GROUP_USER);
861
		$session_id 		= api_get_session_id();
862
		
863
		$complete_user_list = CourseManager :: get_real_and_linked_user_list($_course['code'], true, $session_id);				        
864
        $number_groups_per_user = ($groups_per_user == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $groups_per_user);
865
        
866
		/*
867
		 * Retrieve all the groups where enrollment is still allowed
868
		 * (reverse) ordered by the number of place available
869
		 */
870
        
871
        $course_id = api_get_course_int_id();        
872
		$sql = "SELECT g.id gid, g.max_student-count(ug.user_id) nbPlaces, g.max_student
873
				FROM ".$group_table." g
874
				LEFT JOIN  ".$group_user_table." ug ON  
875
                    g.c_id = $course_id AND ug.c_id = $course_id  AND g.id = ug.group_id
876
				WHERE 					
877
					g.id IN (".implode(',', $group_ids).")
878
				GROUP BY (g.id)
879
				HAVING (nbPlaces > 0 OR g.max_student = ".GroupManager::MEMBER_PER_GROUP_NO_LIMIT.")
880
				ORDER BY nbPlaces DESC";
881
		$sql_result = Database::query($sql);
882
		$group_available_place = array ();
883
		while ($group = Database::fetch_array($sql_result, 'ASSOC')) {
884
			$group_available_place[$group['gid']] = $group['nbPlaces'];
885
		}
886
		
887
		/*
888
		 * Retrieve course users (reverse) ordered by the number
889
		 * of group they are already enrolled
890
		 */
891
		for ($i = 0; $i < count($complete_user_list); $i ++) {
892
			//find # of groups the user is enrolled in
893
			$number_of_groups = self :: user_in_number_of_groups($complete_user_list[$i]["user_id"], $category['id']);            
894
			//add # of groups to user list
895
			$complete_user_list[$i]['number_groups_left'] = $number_groups_per_user - $number_of_groups;
896
		}
897
		
898
		//first sort by user_id to filter out duplicates
899
		$complete_user_list = TableSort :: sort_table($complete_user_list, 'user_id');		
900
		$complete_user_list = self :: filter_duplicates($complete_user_list, 'user_id');		
901
		$complete_user_list = self :: filter_only_students($complete_user_list);
902
				
903
		//now sort by # of group left
904
		$complete_user_list = TableSort :: sort_table($complete_user_list, 'number_groups_left', SORT_DESC);
905
		$userToken = array ();
906
		foreach ($complete_user_list as $this_user) {
907
			if ($this_user['number_groups_left'] > 0) {
908
				$userToken[$this_user['user_id']] = $this_user['number_groups_left'];
909
			}
910
		}
911
        
912
		$changed = true;
913
		while ($changed) {
914
			$changed = false;
915
			reset($group_available_place);
916
			arsort($group_available_place);
917
			reset($userToken);
918
			arsort($userToken);
919
            
920
			foreach ($group_available_place as $group_id => $place) {
921
				foreach ($userToken as $user_id => $places) {					
922
					if (self :: can_user_subscribe($user_id, $group_id)) {
923

    
924
						self :: subscribe_users($user_id, $group_id);
925
						$group_available_place[$group_id]--;
926
						//$userToken[$user_id]--;
927
                        unset($userToken[$user_id]);
928
						$changed = true;
929
						break;
930
					}
931
				}
932
				if ($changed) {
933
					break;
934
				}
935
			}
936
		}
937
	}
938

    
939

    
940
	/**
941
	 * Get the number of students in a group.
942
	 * @param int $group_id
943
	 * @return int Number of students in the given group.
944
	 */
945
	public static function number_of_students ($group_id, $course_id = null) {
946
		$table_group_user = Database :: get_course_table(TABLE_GROUP_USER);
947
		$group_id = Database::escape_string($group_id);
948
        if (empty($course_id)) {
949
            $course_id = api_get_course_int_id();
950
        } else {
951
            $course_id = intval($course_id);
952
        }
953
		$sql = "SELECT  COUNT(*) AS number_of_students FROM $table_group_user WHERE c_id = $course_id AND group_id = $group_id";
954
		$db_result = Database::query($sql);
955
		$db_object = Database::fetch_object($db_result);
956
		return $db_object->number_of_students;
957
	}
958
	/**
959
	 * Maximum number of students in a group
960
	 * @param int $group_id
961
	 * @return int Maximum number of students in the given group.
962
	 */
963
	public static function maximum_number_of_students ($group_id) {
964
		$table_group = Database :: get_course_table(TABLE_GROUP);
965
		$group_id = Database::escape_string($group_id);
966
		$course_id = api_get_course_int_id();
967
		$db_result = Database::query("SELECT max_student FROM $table_group WHERE c_id = $course_id AND id = $group_id");
968
		$db_object = Database::fetch_object($db_result);
969
		if ($db_object->max_student == 0) {
970
			return self::INFINITE;
971
		}
972
		return $db_object->max_student;
973
	}
974
	/**
975
	 * Number of groups of a user
976
	 * @param int $user_id
977
	 * @return int The number of groups the user is subscribed in.
978
	 */
979
	public static function user_in_number_of_groups ($user_id, $cat_id = null) {
980
		$table_group_user 	= Database :: get_course_table(TABLE_GROUP_USER);
981
		$table_group 		= Database :: get_course_table(TABLE_GROUP);
982
		$user_id 			= Database::escape_string($user_id);
983
		$cat_id 			= Database::escape_string($cat_id);
984
		
985
		$course_id = api_get_course_int_id();
986
		$cat_condition = '';
987
        if (!empty($cat_id)) {
988
            $cat_condition = " AND g.category_id =  $cat_id ";
989
        }
990
            
991
		$sql = "SELECT  COUNT(*) AS number_of_groups FROM $table_group_user gu, $table_group g 
992
				WHERE 	gu.c_id 	= $course_id AND
993
						g.c_id 		= $course_id AND
994
						gu.user_id 	= $user_id AND 
995
						g.id 		= gu.group_id  $cat_condition";
996
		$db_result = Database::query($sql);
997
		$db_object = Database::fetch_object($db_result);
998
		return $db_object->number_of_groups;
999
	}
1000
	/**
1001
	 * Is sef-registration allowed?
1002
	 * @param int $user_id
1003
	 * @param int $group_id
1004
	 * @return bool TRUE if self-registration is allowed in the given group.
1005
	 */
1006
	public static function is_self_registration_allowed ($user_id, $group_id) {
1007
		$course_id = api_get_course_int_id();
1008
		if (!$user_id > 0)
1009
			return false;
1010
		$table_group = Database :: get_course_table(TABLE_GROUP);
1011
		$group_id= intval($group_id);
1012
		if (isset($group_id)) {			
1013
			$sql = "SELECT  self_registration_allowed FROM $table_group WHERE c_id = $course_id AND id = $group_id";
1014
			$db_result = Database::query($sql);
1015
			$db_object = Database::fetch_object($db_result);
1016
		    return $db_object->self_registration_allowed == 1 && self :: can_user_subscribe($user_id, $group_id);
1017
		} else {
1018
			return false;
1019
		}
1020
	}
1021
	/**
1022
	 * Is sef-unregistration allowed?
1023
	 * @param int $user_id
1024
	 * @param int $group_id
1025
	 * @return bool TRUE if self-unregistration is allowed in the given group.
1026
	 */
1027
	public static function is_self_unregistration_allowed ($user_id, $group_id) {
1028
		if (!$user_id > 0)
1029
			return false;
1030
		$table_group = Database :: get_course_table(TABLE_GROUP);
1031
		$group_id = Database::escape_string($group_id);
1032
		$course_id = api_get_course_int_id();
1033
		$db_result = Database::query('SELECT  self_unregistration_allowed FROM '.$table_group.' WHERE c_id = '.$course_id.' AND id = '.$group_id);
1034
		$db_object = Database::fetch_object($db_result);
1035
		return $db_object->self_unregistration_allowed == 1 && self :: can_user_unsubscribe($user_id, $group_id);
1036
	}
1037
	/**
1038
	 * Is user subscribed in group?
1039
	 * @param int $user_id
1040
	 * @param int $group_id
1041
	 * @return bool TRUE if given user is subscribed in given group
1042
	 */
1043
	public static function is_subscribed ($user_id, $group_id) {
1044
		if(empty($user_id) or empty($group_id)){return false;}
1045
		$table_group_user = Database :: get_course_table(TABLE_GROUP_USER);
1046
		$group_id = Database::escape_string($group_id);
1047
		$user_id = Database::escape_string($user_id);
1048
		$course_id = api_get_course_int_id();
1049
		$sql = 'SELECT 1 FROM '.$table_group_user.' WHERE c_id = '.$course_id.' AND group_id = '.$group_id.' AND user_id = '.$user_id;
1050
		$db_result = Database::query($sql);
1051
		return Database::num_rows($db_result) > 0;
1052
	}
1053
	/**
1054
	 * Can a user subscribe to a specified group in a course
1055
	 * @param int $user_id
1056
	 * @param int $group_id
1057
	 * @return bool TRUE if given user  can be subscribed in given group
1058
	 */
1059
	public static function can_user_subscribe ($user_id, $group_id) {
1060
		global $_course;
1061
		$course_code = $_course['sysCode'];
1062
		$category = self :: get_category_from_group($group_id);
1063
		$result = CourseManager :: is_user_subscribed_in_real_or_linked_course($user_id, $course_code);
1064
		$result = !self :: is_subscribed($user_id, $group_id);
1065
		$result &= (self :: number_of_students($group_id) < self :: maximum_number_of_students($group_id));
1066
		if ($category['groups_per_user'] == self::GROUP_PER_MEMBER_NO_LIMIT) {
1067
			$category['groups_per_user'] = self::INFINITE;
1068
		}
1069
		$result &= (self :: user_in_number_of_groups($user_id, $category['id']) < $category['groups_per_user']);
1070
		$result &= !self :: is_tutor_of_group($user_id, $group_id);
1071
		return $result;
1072
	}
1073
    
1074
	/**
1075
	 * Can a user unsubscribe to a specified group in a course
1076
	 * @param int $user_id
1077
	 * @param int $group_id
1078
	 * @return bool TRUE if given user  can be unsubscribed from given group
1079
	 * @internal for now, same as GroupManager::is_subscribed($user_id,$group_id)
1080
	 */
1081
	public static function can_user_unsubscribe ($user_id, $group_id) {
1082
		$result = self :: is_subscribed($user_id, $group_id);
1083
		return $result;
1084
	}
1085
    
1086
	/**
1087
	 * Get all subscribed users from a group
1088
	 * @param int $group_id
1089
	 * @return array An array with information of all users from the given group.
1090
	 *               (user_id, firstname, lastname, email)
1091
	 */
1092
	public static function get_subscribed_users($group_id) {
1093
		$table_user = Database :: get_main_table(TABLE_MAIN_USER);
1094
		$table_group_user = Database :: get_course_table(TABLE_GROUP_USER);
1095
		$order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1096
        if (empty($group_id)) {
1097
            return array();
1098
        }
1099
		$group_id = intval($group_id);
1100
		$course_id = api_get_course_int_id();
1101
		
1102
		$sql = "SELECT ug.id, u.user_id, u.lastname, u.firstname, u.email, u.username 
1103
				FROM  $table_user u INNER JOIN $table_group_user ug ON (ug.user_id = u.user_id)
1104
				WHERE ug.c_id = $course_id AND
1105
					  ug.group_id = $group_id 
1106
                $order_clause";
1107
		$db_result = Database::query($sql);
1108
		$users = array();
1109
		while ($user = Database::fetch_object($db_result)) {
1110
			$member['user_id']   = $user->user_id;
1111
			$member['firstname'] = $user->firstname;
1112
			$member['lastname']  = $user->lastname;
1113
			$member['email']     = $user->email;
1114
            $member['username']  = $user->username;
1115
			$users[$member['user_id']] = $member;
1116
		}
1117
		return $users;
1118
	}
1119

    
1120
	/**
1121
	 * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
1122
	 * Get all subscribed tutors of a group
1123
	 * @param int $group_id
1124
	 * @return array An array with information of all users from the given group.
1125
	 *               (user_id, firstname, lastname, email)
1126
	 */
1127
	public static function get_subscribed_tutors ($group_id,$id_only=false) {
1128
		$table_user = Database :: get_main_table(TABLE_MAIN_USER);
1129
		$table_group_tutor = Database :: get_course_table(TABLE_GROUP_TUTOR);
1130
		$order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1131
		$group_id = Database::escape_string($group_id);
1132
		$course_id = api_get_course_int_id();
1133
		
1134
		$sql = "SELECT tg.id, u.user_id, u.lastname, u.firstname, u.email
1135
			FROM ".$table_user." u, ".$table_group_tutor." tg
1136
			WHERE 	tg.c_id = $course_id AND 
1137
					tg.group_id='".$group_id."' AND 
1138
					tg.user_id=u.user_id".$order_clause;
1139
		$db_result = Database::query($sql);
1140
		$users = array ();
1141
		while ($user = Database::fetch_object($db_result)) {
1142
			if (!$id_only) {
1143
				$member['user_id'] = $user->user_id;
1144
				$member['firstname'] = $user->firstname;
1145
				$member['lastname'] = $user->lastname;
1146
				$member['email'] = $user->email;
1147
				$users[] = $member;
1148
			} else {
1149
				$users[]=$user->user_id;
1150
			}
1151
		}
1152
		return $users;
1153
	}
1154
	/**
1155
	 * Subscribe user(s) to a specified group in current course
1156
	 * @param mixed $user_ids Can be an array with user-id's or a single user-id
1157
	 * @param int $group_id
1158
	 * @return bool TRUE if successfull
1159
	 */
1160
	public static function subscribe_users ($user_ids, $group_id) {
1161
		$user_ids = is_array($user_ids) ? $user_ids : array ($user_ids);
1162
		$result = true;
1163
		$course_id = api_get_course_int_id();
1164
		$table_group_user = Database :: get_course_table(TABLE_GROUP_USER);
1165
		if (!empty($user_ids)) {
1166
			foreach ($user_ids as $index => $user_id) {			
1167
				$user_id = Database::escape_string($user_id);
1168
				$group_id = Database::escape_string($group_id);
1169
				$sql = "INSERT INTO ".$table_group_user." (c_id, user_id, group_id) VALUES ('$course_id', '".$user_id."', '".$group_id."')";
1170
				$result &= Database::query($sql);
1171
			}
1172
		}
1173
		return $result;
1174
	}
1175

    
1176
	/**
1177
	 * Subscribe tutor(s) to a specified group in current course
1178
	 * @param mixed $user_ids Can be an array with user-id's or a single user-id
1179
	 * @param int $group_id
1180
	 * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
1181
	 * @see subscribe_users. This function is almost an exact copy of that function.
1182
	 * @return bool TRUE if successfull
1183
	 */
1184
	public static function subscribe_tutors ($user_ids, $group_id) {
1185
		$user_ids = is_array($user_ids) ? $user_ids : array ($user_ids);
1186
		$result = true;
1187
		$course_id = api_get_course_int_id();
1188
		$table_group_tutor = Database :: get_course_table(TABLE_GROUP_TUTOR);
1189
		
1190
		foreach ($user_ids as $index => $user_id) {			
1191
			$user_id = Database::escape_string($user_id);
1192
			$group_id = Database::escape_string($group_id);
1193
			$sql = "INSERT INTO ".$table_group_tutor." (c_id, user_id, group_id) VALUES ('$course_id', '".$user_id."', '".$group_id."')";
1194
			$result &= Database::query($sql);
1195
		}
1196
		return $result;
1197
	}
1198

    
1199
	/**
1200
	 * Unsubscribe user(s) from a specified group in current course
1201
	 * @param mixed $user_ids Can be an array with user-id's or a single user-id
1202
	 * @param int $group_id
1203
	 * @return bool TRUE if successfull
1204
	 */
1205
	public static function unsubscribe_users ($user_ids, $group_id) {
1206
		$user_ids = is_array($user_ids) ? $user_ids : array ($user_ids);
1207
		$table_group_user = Database :: get_course_table(TABLE_GROUP_USER);
1208
		$group_id = Database::escape_string($group_id);
1209
		$course_id = api_get_course_int_id();		
1210
		
1211
		$result &= Database::query('DELETE FROM '.$table_group_user.' WHERE c_id = '.$course_id.' AND group_id = '.$group_id.' AND user_id IN ('.implode(',', $user_ids).')');
1212
	}
1213
	/**
1214
	 * Unsubscribe all users from one or more groups
1215
	 * @param mixed $group_id Can be an array with group-id's or a single group-id
1216
	 * @return bool TRUE if successfull
1217
	 */
1218
	public static function unsubscribe_all_users ($group_ids) {
1219
		$course_id = api_get_course_int_id();
1220
		
1221
		$group_ids = is_array($group_ids) ? $group_ids : array ($group_ids);
1222
		$group_ids = array_map('intval',$group_ids);
1223
		if( count($group_ids) > 0) {
1224
			if(api_is_course_coach()) {
1225
				for($i=0 ; $i<count($group_ids) ; $i++) {
1226
					if(!api_is_element_in_the_session(TOOL_GROUP,$group_ids[$i])) {
1227
						array_splice($group_ids,$i,1);
1228
						$i--;
1229
					}
1230
				}
1231
				if(count($group_ids)==0) {
1232
					return false;
1233
				}
1234
			}
1235
			$table_group_user = Database :: get_course_table(TABLE_GROUP_USER);
1236
			$sql = 'DELETE FROM '.$table_group_user.' WHERE group_id IN ('.implode(',', $group_ids).') AND c_id = '.$course_id;
1237
			$result = Database::query($sql);
1238
			return $result;
1239
		}
1240
		return true;
1241
	}
1242
	/**
1243
	 * Unsubscribe all tutors from one or more groups
1244
	 * @param mixed $group_id Can be an array with group-id's or a single group-id
1245
	 * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1246
	 * @return bool TRUE if successfull
1247
	 * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
1248
	 */
1249
	public static function unsubscribe_all_tutors ($group_ids) {
1250
		$course_id = api_get_course_int_id();
1251
		$group_ids = is_array($group_ids) ? $group_ids : array ($group_ids);
1252
		if( count($group_ids) > 0) {
1253
			$table_group_tutor = Database :: get_course_table(TABLE_GROUP_TUTOR);
1254
			$sql = 'DELETE FROM '.$table_group_tutor.' WHERE group_id IN ('.implode(',', $group_ids).') AND c_id = '.$course_id;
1255
			$result = Database::query($sql);
1256
			return $result;
1257
		}
1258
		return true;
1259
	}
1260

    
1261
	/**
1262
	 * Is the user a tutor of this group?
1263
	 * @param $user_id the id of the user
1264
	 * @param $group_id the id of the group
1265
	 * @return boolean true/false
1266
     * @todo use the function user_has_access that includes this function 
1267
	 * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
1268
	 */
1269
	public static function is_tutor_of_group ($user_id,$group_id) {
1270
		global $_course;
1271

    
1272
		$table_group_tutor = Database :: get_course_table(TABLE_GROUP_TUTOR);
1273
		$user_id = Database::escape_string($user_id);
1274
		$group_id = Database::escape_string($group_id);
1275
		$course_id = api_get_course_int_id();
1276
		
1277
		$sql = "SELECT * FROM ".$table_group_tutor." WHERE c_id = $course_id AND user_id='".$user_id."' AND group_id='".$group_id."'";
1278
		$result = Database::query($sql);
1279
		if (Database::num_rows($result)>0) {
1280
			return true;
1281
		} else {
1282
			return false;
1283
		}
1284
	}
1285

    
1286
	/**
1287
	 * Is the user part of this group? This can be a tutor or a normal member
1288
	 * you should use this function if the access to a tool or functionality is restricted to the people who are actually in the group
1289
	 * before you had to check if the user was 1. a member of the group OR 2. a tutor of the group. This function combines both
1290
	 * @param $user_id the id of the user
1291
	 * @param $group_id the id of the group
1292
	 * @return boolean true/false
1293
	 * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
1294
	*/
1295
	public static function is_user_in_group ($user_id, $group_id) {
1296
		$member = self :: is_subscribed($user_id,$group_id);
1297
		$tutor  = self :: is_tutor_of_group($user_id,$group_id);
1298
		if ($member OR $tutor) {
1299
			return true;
1300
		} else {
1301
			return false;
1302
		}
1303
	}
1304

    
1305
	/**
1306
	 * Get all tutors for the current course.
1307
	 * @return array An array with firstname, lastname and user_id for all
1308
	 *               tutors in the current course.
1309
	 * @deprecated this function uses the old tutor implementation
1310
	 */
1311
	public static function get_all_tutors() {
1312
		global $_course;
1313
		$course_user_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
1314
		$user_table = Database :: get_main_table(TABLE_MAIN_USER);
1315
		$sql = "SELECT user.user_id AS user_id, user.lastname AS lastname, user.firstname AS firstname
1316
				FROM ".$user_table." user, ".$course_user_table." cu
1317
				WHERE cu.user_id=user.user_id
1318
				AND cu.tutor_id='1'
1319
				AND cu.course_code='".$_course['sysCode']."'";
1320
		$resultTutor = Database::query($sql);
1321
		$tutors = array ();
1322
		while ($tutor = Database::fetch_array($resultTutor))
1323
		{
1324
			$tutors[] = $tutor;
1325
		}
1326
		return $tutors;
1327
	}
1328

    
1329

    
1330
	/**
1331
	 * Is user a tutor in current course
1332
	 * @param int $user_id
1333
	 * @return bool TRUE if given user is a tutor in the current course.
1334
	 * @deprecated this function uses the old tutor implementation
1335
	 */
1336
	public static function is_tutor ($user_id) {
1337
		global $_course;
1338
		$course_user_table 	= Database::get_main_table(TABLE_MAIN_COURSE_USER);
1339
		$user_id 			= Database::escape_string($user_id);
1340

    
1341
		$sql = "SELECT tutor_id FROM ".$course_user_table."
1342
		        WHERE user_id='".$user_id."' AND course_code='".$_course['code']."'"."AND tutor_id=1";
1343
		$db_result = Database::query($sql);
1344
		$result = (Database::num_rows($db_result) > 0);
1345
		return $result;
1346
	}
1347

    
1348
	/**
1349
	 * Get all group's from a given course in which a given user is unsubscribed
1350
	 * @author  Patrick Cool
1351
	 * @param	 int  course id
1352
	 * retrieve the groups for
1353
	 * @param integer $user_id: the ID of the user you want to know all its
1354
	 * group memberships
1355
	 */
1356
	public static function get_group_ids ($course_id, $user_id) {
1357
		$groups = array();
1358
		$tbl_group 	= Database::get_course_table(TABLE_GROUP_USER);
1359
		$tbl_group_tutor 	= Database::get_course_table(TABLE_GROUP_TUTOR);
1360
		$user_id 	= intval($user_id);
1361
		$course_id 	= intval($course_id);
1362
		
1363
		$sql = "SELECT group_id FROM $tbl_group WHERE c_id = $course_id AND user_id = '$user_id'";
1364
		$groupres = Database::query($sql);
1365
		
1366
		if ($groupres) {
1367
			while ($myrow= Database::fetch_array($groupres))
1368
				$groups[]=$myrow['group_id'];
1369
		}
1370
		
1371
		//Also loading if i'm the tutor
1372
		$sql = "SELECT group_id FROM $tbl_group_tutor WHERE c_id = $course_id AND user_id = '$user_id'";
1373
		$groupres = Database::query($sql);
1374
		if ($groupres) {
1375
			while ($myrow= Database::fetch_array($groupres)) {
1376
				$groups[]=$myrow['group_id'];				
1377
			}
1378
		}
1379
		if (!empty($groups)) {
1380
			 array_filter($groups);
1381
		}		
1382
		return $groups;
1383
	}
1384
    
1385
	/*	
1386
        Group functions - these take virtual/linked courses into account when necessary
1387
	*/
1388
	/**
1389
	*	Get a combined list of all users of the real course $course_code
1390
	*		and all users in virtual courses linked to this course $course_code
1391
	*	Filter user list: remove duplicate users; plus
1392
	*		remove users that
1393
	*		- are already in the current group $group_id;
1394
	*		- do not have student status in these courses;
1395
	*		- are not appointed as tutor (group assistent) for this group;
1396
	*		- have already reached their maximum # of groups in this course.
1397
	*
1398
	*	Originally to get the correct list of users a big SQL statement was used,
1399
	*	but this has become more complicated now there is not just one real course but many virtual courses.
1400
	*	Still, that could have worked as well.
1401
	*
1402
	*	@version 1.1.3
1403
	*	@author Roan Embrechts
1404
	*/
1405
	public static function get_complete_list_of_users_that_can_be_added_to_group ($course_code, $group_id) {
1406
		global $_course, $_user;
1407
		$category = self :: get_category_from_group($group_id, $course_code);
1408
		$number_of_groups_limit = $category['groups_per_user'] == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $category['groups_per_user'];
1409
		$real_course_code = $_course['sysCode'];
1410
		$real_course_info = Database :: get_course_info($real_course_code);
1411
		$real_course_user_list = CourseManager :: get_user_list_from_course_code($real_course_code);
1412
		//get list of all virtual courses
1413
		$user_subscribed_course_list = CourseManager :: get_list_of_virtual_courses_for_specific_user_and_real_course($_user['user_id'], $real_course_code);
1414
		//add real course to the list
1415
		$user_subscribed_course_list[] = $real_course_info;
1416
		if (!is_array($user_subscribed_course_list)) {
1417
			return;
1418
        }
1419
		//for all courses...
1420
		foreach ($user_subscribed_course_list as $this_course) {
1421
			$this_course_code = $this_course['code'];
1422
			$course_user_list = CourseManager :: get_user_list_from_course_code($this_course_code);
1423
			//for all users in the course
1424
			foreach ($course_user_list as $this_user) {
1425
				$user_id = $this_user['user_id'];
1426
				$loginname = $this_user['username'];
1427
				$lastname = $this_user['lastname'];
1428
				$firstname = $this_user['firstname'];
1429
				$status = $this_user['status'];
1430
				//$role =  $this_user['role'];
1431
				$tutor_id = $this_user['tutor_id'];
1432
				$full_name = api_get_person_name($firstname, $lastname);
1433
				if ($lastname == "" || $firstname == '') {
1434
					$full_name = $loginname;
1435
                }
1436
				$complete_user['user_id'] = $user_id;
1437
				$complete_user['full_name'] = $full_name;
1438
				$complete_user['firstname'] = $firstname;
1439
				$complete_user['lastname'] = $lastname;
1440
				$complete_user['status'] = $status;
1441
				$complete_user['tutor_id'] = $tutor_id;
1442
				$student_number_of_groups = self :: user_in_number_of_groups($user_id, $category['id']);
1443
				//filter: only add users that have not exceeded their maximum amount of groups
1444
				if ($student_number_of_groups < $number_of_groups_limit) {
1445
					$complete_user_list[] = $complete_user;
1446
				}
1447
			}
1448
		}
1449
		if (is_array($complete_user_list)) {
1450
			//sort once, on array field "full_name"
1451
			$complete_user_list = TableSort :: sort_table($complete_user_list, "full_name");
1452
			//filter out duplicates, based on field "user_id"
1453
			$complete_user_list = self :: filter_duplicates($complete_user_list, "user_id");
1454
			$complete_user_list = self :: filter_users_already_in_group($complete_user_list, $group_id);
1455

    
1456
		}
1457
		return $complete_user_list;
1458
	}
1459
	/**
1460
	*	Filter out duplicates in a multidimensional array
1461
	*	by comparing field $compare_field.
1462
	*
1463
	*	@param $user_array_in list of users (must be sorted).
1464
	*	@param string $compare_field, the field to be compared
1465
	*/
1466
	public static function filter_duplicates ($user_array_in, $compare_field) {
1467
		$total_number = count($user_array_in);
1468
		$user_array_out[0] = $user_array_in[0];
1469
		$count_out = 0;
1470
		for ($count_in = 1; $count_in < $total_number; $count_in ++) {
1471
			if ($user_array_in[$count_in][$compare_field] != $user_array_out[$count_out][$compare_field]) {
1472
				$count_out ++;
1473
				$user_array_out[$count_out] = $user_array_in[$count_in];
1474
			}
1475
		}
1476
		return $user_array_out;
1477
	}
1478
	/**
1479
	*	Filters from the array $user_array_in the users already in the group $group_id.
1480
	*/
1481
	public static function filter_users_already_in_group ($user_array_in, $group_id) {
1482
		foreach ($user_array_in as $this_user) {
1483
			if (!self :: is_subscribed($this_user['user_id'], $group_id)) {				
1484
                $user_array_out[] = $this_user;
1485
			}
1486
		}
1487
		return $user_array_out;
1488
	}
1489
	
1490
	/**
1491
	* Remove all users that are not students and all users who have tutor status
1492
	* from  the list.
1493
	*/
1494
	public static function filter_only_students($user_array_in) {
1495
		$user_array_out = array ();		
1496
		foreach ($user_array_in as $this_user) {			    
1497
			//if ($this_user['status_rel'] == STUDENT && $this_user['tutor_id'] == 0) {
1498
			if (api_get_session_id()) {
1499
				if ($this_user['status_session'] == 0) {
1500
					$user_array_out[] = $this_user;
1501
				}
1502
			} else {
1503
				if ($this_user['status_rel'] == STUDENT) {
1504
					$user_array_out[] = $this_user;
1505
				}
1506
			}
1507
		}
1508
		return $user_array_out;
1509
	}
1510
    
1511
	/**
1512
	 * Check if a user has access to a certain group tool
1513
	 * @param int $user_id The user id
1514
	 * @param int $group_id The group id
1515
	 * @param constant $tool The tool to check the access rights. This should be
1516
	 * one of constants: GROUP_TOOL_DOCUMENTS
1517
	 * @return bool True if the given user has access to the given tool in the
1518
	 * given course.
1519
	 */
1520
	public static function user_has_access($user_id, $group_id, $tool) {
1521
        
1522
        //Admin have access everywhere
1523
        if (api_is_platform_admin()) {
1524
            return true;
1525
        }
1526
        //Course admin also have access to everything
1527
        if (api_is_allowed_to_edit()) {
1528
            return true;
1529
        }
1530
        
1531
		switch ($tool) {
1532
			case self::GROUP_TOOL_FORUM :
1533
				$state_key = 'forum_state';
1534
				break;
1535
			case self::GROUP_TOOL_DOCUMENTS :
1536
				$state_key = 'doc_state';
1537
				break;
1538
			case self::GROUP_TOOL_CALENDAR :
1539
				$state_key = 'calendar_state';
1540
				break;
1541
			case self::GROUP_TOOL_ANNOUNCEMENT :
1542
				$state_key = 'announcements_state';
1543
				break;
1544
			case self::GROUP_TOOL_WORK :
1545
				$state_key = 'work_state';
1546
				break;
1547
			case self::GROUP_TOOL_WIKI :
1548
				$state_key = 'wiki_state';
1549
				break;
1550
			case self::GROUP_TOOL_CHAT :
1551
				$state_key = 'chat_state';
1552
				break;
1553
			default:
1554
				return false;
1555
		}
1556
        
1557
        $user_is_in_group = self :: is_user_in_group($user_id, $group_id);     
1558
        
1559
        //Check group properties
1560
		$group_info = self :: get_group_properties($group_id);
1561
        
1562
        //Check group category if exists
1563
        $category_group_info = self::get_category_from_group($group_id);
1564
        
1565
        if (!empty($category_group_info)) {
1566
            //if exists check the category group status first        
1567
            if ($category_group_info[$state_key] == GroupManager::TOOL_NOT_AVAILABLE) {
1568
                return false;                
1569
            } elseif($category_group_info[$state_key] == GroupManager::TOOL_PRIVATE && !$user_is_in_group) {                
1570
                return false;
1571
            }
1572
        }
1573
        
1574
        //is_user_in_group() is more complete that  the  is_subscribed() function        
1575
        
1576
		if ($group_info[$state_key] == GroupManager::TOOL_NOT_AVAILABLE) {
1577
			return false;
1578
		} elseif ($group_info[$state_key] == self::TOOL_PUBLIC) {
1579
			return true;
1580
		} elseif (api_is_allowed_to_edit(false,true)) {
1581
			return true;
1582
		} elseif($group_info['tutor_id'] == $user_id) { //this tutor implementation was dropped
1583
			return true;		
1584
        } elseif($group_info[$state_key] == GroupManager::TOOL_PRIVATE && !$user_is_in_group) {
1585
            return false;
1586
        } else {		
1587
            return $user_is_in_group;
1588
		}
1589
	}
1590
    
1591
	/**
1592
	 * Get all groups where a specific user is subscribed
1593
	 */
1594
	public static function get_user_group_name ($user_id) {
1595
		$table_group_user   = Database::get_course_table(TABLE_GROUP_USER);
1596
		$table_group        = Database::get_course_table(TABLE_GROUP);
1597
		$user_id            = intval($user_id);
1598
		$course_id          = api_get_course_int_id();
1599
		$sql_groups = "SELECT name FROM $table_group g  INNER JOIN $table_group_user gu 
1600
                       ON (gu.group_id=g.id)
1601
		               WHERE    gu.c_id= $course_id AND 
1602
                                g.c_id= $course_id AND 
1603
                                gu.user_id = $user_id";		               
1604
		$res = Database::query($sql_groups);
1605
		$groups=array();
1606
	    while ($group = Database::fetch_array($res)) {
1607
	    	$groups[] .= $group['name'];
1608
	    }
1609
	    return $groups;
1610
	}
1611
	
1612
    /**
1613
     *   fill_groups_list
1614
     *
1615
     * see : fill_groups
1616
     *       Fill the groups with students.
1617
     *
1618
     * note : 
1619
     *        optimize fill_groups_list <--> fill_groups
1620
     * 
1621
     */
1622
    public static function fill_groups_list ($group_ids) {
1623
        $group_ids = is_array($group_ids) ? $group_ids : array ($group_ids);
1624
        $group_ids = array_map('intval',$group_ids);
1625
        if (api_is_course_coach()) {
1626
            for($i=0 ; $i<count($group_ids) ; $i++) {
1627
                if(!api_is_element_in_the_session(TOOL_GROUP,$group_ids[$i])) {
1628
                    array_splice($group_ids,$i,1);
1629
                    $i--;
1630
                }
1631
            }
1632
            if (count($group_ids)==0){
1633
                return false;}
1634
        }
1635

    
1636
        global $_course;
1637
        $category = self :: get_category_from_group($group_ids[0]);
1638
        $groups_per_user = $category['groups_per_user'];
1639
        $course_user_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
1640
        $group_table = Database :: get_course_table(TABLE_GROUP);
1641
        $group_user_table = Database :: get_course_table(TABLE_GROUP_USER);
1642
        $session_id = api_get_session_id();
1643
        $complete_user_list = CourseManager :: get_real_and_linked_user_list($_course['sysCode'], true, $session_id);
1644
        $number_groups_per_user = ($groups_per_user == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $groups_per_user);
1645
        $course_id = api_get_course_int_id();
1646
        /*
1647
         * Retrieve all the groups where enrollment is still allowed
1648
         * (reverse) ordered by the number of place available
1649
         */
1650
        $sql = "SELECT g.id gid, g.max_student - count(ug.user_id) nbPlaces, g.max_student
1651
                FROM ".$group_table." g
1652
                LEFT JOIN  ".$group_user_table." ug
1653
                ON    g.id = ug.group_id
1654
                WHERE   g.c_id = $course_id AND 
1655
                        ug.c_id = $course_id AND 
1656
                        g.id IN (".implode(',', $group_ids).")
1657
                GROUP BY (g.id)
1658
                HAVING (nbPlaces > 0 OR g.max_student = ".GroupManager::MEMBER_PER_GROUP_NO_LIMIT.")
1659
                ORDER BY nbPlaces DESC";
1660
        $sql_result = Database::query($sql);
1661
        $group_available_place = array ();
1662
        while ($group = Database::fetch_array($sql_result, 'ASSOC')) {
1663
            $group_available_place[$group['gid']] = $group['nbPlaces'];
1664
        }
1665
        
1666
        /*
1667
         * Retrieve course users (reverse) ordered by the number
1668
         * of group they are already enrolled
1669
         */
1670
        for ($i = 0; $i < count($complete_user_list); $i ++) {
1671

    
1672
            //find # of groups the user is enrolled in
1673
            $number_of_groups = self :: user_in_number_of_groups($complete_user_list[$i]["user_id"],$category['id']);
1674
            //add # of groups to user list
1675
            $complete_user_list[$i]['number_groups_left'] = $number_groups_per_user - $number_of_groups;
1676
        }
1677
        //first sort by user_id to filter out duplicates
1678
        $complete_user_list = TableSort :: sort_table($complete_user_list, 'user_id');
1679
        $complete_user_list = self :: filter_duplicates($complete_user_list, 'user_id');
1680
        //$complete_user_list = self :: filter_only_students($complete_user_list);
1681
        //now sort by # of group left
1682
        $complete_user_list = TableSort :: sort_table($complete_user_list, 'number_groups_left', SORT_DESC);           
1683
        return $complete_user_list;        
1684
    }
1685
    
1686
    static function process_groups($group_list, $category_id = null) {
1687
        global $origin, $charset;
1688
        $category_id = intval($category_id);
1689
        
1690
        $totalRegistered = 0;
1691
        $group_data = array();
1692
        $user_info = api_get_user_info();
1693
        $session_id = api_get_session_id();
1694
        $user_id = $user_info['user_id'];
1695
        
1696
        $orig = isset($origin) ? $origin : null;
1697
        
1698
        foreach ($group_list as $this_group) {
1699

    
1700
            // Validacion when belongs to a session
1701
            $session_img = api_get_session_image($this_group['session_id'], $user_info['status']);
1702

    
1703
            // All the tutors of this group
1704
            $tutorsids_of_group = GroupManager::get_subscribed_tutors($this_group['id'], true);
1705

    
1706
            // Create a new table-row
1707
            $row = array ();
1708
            // Checkbox
1709
            if (api_is_allowed_to_edit(false,true) && count($group_list) > 1) {
1710
                $row[] = $this_group['id'];
1711
            }
1712

    
1713
            // Group name
1714
            if ((api_is_allowed_to_edit(false, true) ||
1715
                    in_array($user_id, $tutorsids_of_group) ||
1716
                    $this_group['is_member'] ||
1717
                    GroupManager::user_has_access($user_id, $this_group['id'], GroupManager::GROUP_TOOL_FORUM) ||
1718
                    GroupManager::user_has_access($user_id, $this_group['id'], GroupManager::GROUP_TOOL_DOCUMENTS) ||
1719
                    GroupManager::user_has_access($user_id, $this_group['id'], GroupManager::GROUP_TOOL_CALENDAR) ||
1720
                    GroupManager::user_has_access($user_id, $this_group['id'], GroupManager::GROUP_TOOL_ANNOUNCEMENT) ||
1721
                    GroupManager::user_has_access($user_id, $this_group['id'], GroupManager::GROUP_TOOL_WORK) ||
1722
                    GroupManager::user_has_access($user_id, $this_group['id'], GroupManager::GROUP_TOOL_WIKI))
1723
                    && !(api_is_course_coach() && intval($this_group['session_id']) != $session_id)) {
1724
                
1725
                $group_name = '<a href="group_space.php?cidReq='.api_get_course_id().'&amp;origin='.$orig.'&amp;gidReq='.$this_group['id'].'">'.Security::remove_XSS($this_group['name']).'</a> ';
1726
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
1727
                    $group_name .= Display::label(get_lang('OneMyGroups'), 'success');
1728
                } elseif ($this_group['is_member']) {
1729
                    $group_name .= Display::label(get_lang('MyGroup'), 'success');
1730
                }
1731
                
1732
                if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
1733
                    $group_name .= ' ('.$this_group['session_name'].')';
1734
                }
1735
                $group_name .= $session_img;
1736
                $row[] = $group_name.'<br />'.stripslashes(trim($this_group['description']));
1737
            } else {
1738
                $row[] = $this_group['name'].'<br />'.stripslashes(trim($this_group['description']));
1739
            }                      
1740

    
1741
            // Tutor name
1742
            $tutor_info = null;
1743

    
1744
            if (count($tutorsids_of_group) > 0) {
1745
                foreach ($tutorsids_of_group as $tutor_id) {
1746
                    $tutor = api_get_user_info($tutor_id);
1747
                    $username = api_htmlentities(sprintf(get_lang('LoginX'), $tutor['username']), ENT_QUOTES);
1748
                    if (api_get_setting('show_email_addresses') == 'true') {
1749
                        $tutor_info .= Display::tag('span', Display::encrypted_mailto_link($tutor['mail'], api_get_person_name($tutor['firstName'], $tutor['lastName'])), array('title'=>$username)).', ';
1750
                    } else {
1751
                        if (api_is_allowed_to_edit()) {
1752
                            $tutor_info .= Display::tag('span', Display::encrypted_mailto_link($tutor['mail'], api_get_person_name($tutor['firstName'], $tutor['lastName'])), array('title'=>$username)).', ';
1753
                        } else {
1754
                            $tutor_info .= Display::tag('span', api_get_person_name($tutor['firstName'], $tutor['lastName']), array('title'=>$username)).', ';
1755
                        }
1756
                    }
1757
                }
1758
            }
1759
            $tutor_info = api_substr($tutor_info, 0, api_strlen($tutor_info) - 2);
1760
            $row[] = $tutor_info;
1761

    
1762
            // Max number of members in group
1763
            $max_members = ($this_group['maximum_number_of_members'] == GroupManager::MEMBER_PER_GROUP_NO_LIMIT ? ' ' : ' / '.$this_group['maximum_number_of_members']);
1764

    
1765
            // Number of members in group
1766
            $row[] = $this_group['number_of_members'].$max_members;
1767

    
1768
            // Self-registration / unregistration
1769
            if (!api_is_allowed_to_edit(false, true)) {
1770
                if (GroupManager :: is_self_registration_allowed($user_id, $this_group['id'])) {
1771
                    $row[] = '<a class = "btn" href="group.php?'.api_get_cidreq().'&category='.$category_id.'&amp;action=self_reg&amp;group_id='.$this_group['id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfRegInf').'</a>';
1772
                } elseif (GroupManager :: is_self_unregistration_allowed($user_id, $this_group['id'])) {
1773
                    $row[] = '<a class = "btn" href="group.php?'.api_get_cidreq().'&category='.$category_id.'&amp;action=self_unreg&amp;group_id='.$this_group['id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfUnRegInf').'</a>';
1774
                } else {
1775
                    $row[] = '-';
1776
                }
1777
            }
1778

    
1779
            // Edit-links
1780
            if (api_is_allowed_to_edit(false, true)  && !(api_is_course_coach() && intval($this_group['session_id']) != $session_id)) {
1781
                $edit_actions = '<a href="group_edit.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('Edit').'">'.Display::return_icon('edit.png', get_lang('EditGroup'),'',ICON_SIZE_SMALL).'</a>&nbsp;';								
1782
                $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&amp;action=empty_one&amp;id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('EmptyGroup').'">'.
1783
                    Display::return_icon('clean.png',get_lang('EmptyGroup'),'',ICON_SIZE_SMALL).'</a>&nbsp;';				
1784
                $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&amp;action=fill_one&amp;id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('FillGroup').'">'.
1785
                    Display::return_icon('fill.png',get_lang('FillGroup'),'',ICON_SIZE_SMALL).'</a>&nbsp;';
1786
                $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&amp;action=delete_one&amp;id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'">'.
1787
                    Display::return_icon('delete.png', get_lang('Delete'),'',ICON_SIZE_SMALL).'</a>&nbsp;';
1788
                $row[] = $edit_actions;
1789
            }
1790
            if (!empty($this_group['nbMember'])) {
1791
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
1792
            }
1793
            $group_data[] = $row;
1794
        } // end loop
1795
        
1796
        if (isset($_GET['show_all'])) {
1797
            $paging_options = array('per_page' => count($group_data));
1798
        } else {
1799
            $paging_options = array ();
1800
        }
1801
        
1802
        $table = new SortableTableFromArrayConfig($group_data, 1, 20, 'group_category_'.$category_id);
1803
        //$my_cat = isset($_GET['category']) ? Security::remove_XSS($_GET['category']) : null;
1804
        $table->set_additional_parameters(array('category' => $category_id));
1805
        $column = 0;
1806
        if (api_is_allowed_to_edit(false, true) and count($group_list) > 1) {
1807
            $table->set_header($column++, '', false);
1808
        }
1809
        $table->set_header($column++, get_lang('Groups'));
1810
        $table->set_header($column++, get_lang('GroupTutor'));
1811
        $table->set_header($column++, get_lang('Registered'), false);
1812

    
1813
        if (!api_is_allowed_to_edit(false, true)) { // If self-registration allowed
1814
            $table->set_header($column++, get_lang('GroupSelfRegistration'), false);
1815
        }        
1816
        if (api_is_allowed_to_edit(false, true)) { // Only for course administrator
1817
            $table->set_header($column++, get_lang('Modify'), false);
1818
            $form_actions = array();
1819
            $form_actions['fill_selected'] = get_lang('FillGroup');
1820
            $form_actions['empty_selected'] = get_lang('EmptyGroup');
1821
            $form_actions['delete_selected'] = get_lang('Delete');
1822
            if (count($group_list) > 1) {
1823
                $table->set_form_actions($form_actions, 'group');
1824
            }
1825
        }
1826
        $table->display();
1827
    }
1828
}
(4-4/6)