| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Extra library for groups and groupings. 4 * 5 * @copyright © 2006 The Open University 6 * @author J.White AT open.ac.uk, Petr Skoda (skodak) 7 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License 8 * @package groups 9 */ 10 11 /* 12 * INTERNAL FUNCTIONS - to be used by moodle core only 13 * require_once $CFG->dirroot.'/group/lib.php' must be used 14 */ 15 16 /** 17 * Adds a specified user to a group 18 * @param int $userid The user id 19 * @param int $groupid The group id 20 * @return boolean True if user added successfully or the user is already a 21 * member of the group, false otherwise. 22 */ 23 function groups_add_member($groupid, $userid) { 24 if (!groups_group_exists($groupid)) { 25 return false; 26 } 27 28 if (groups_is_member($groupid, $userid)) { 29 return true; 30 } 31 32 $member = new object(); 33 $member->groupid = $groupid; 34 $member->userid = $userid; 35 $member->timeadded = time(); 36 37 if (!insert_record('groups_members', $member)) { 38 return false; 39 } 40 41 //update group info 42 set_field('groups', 'timemodified', $member->timeadded, 'id', $groupid); 43 44 //trigger groups events 45 $eventdata = new object(); 46 $eventdata->groupid = $groupid; 47 $eventdata->userid = $userid; 48 events_trigger('groups_member_added', $eventdata); 49 50 return true; 51 } 52 53 /** 54 * Deletes the link between the specified user and group. 55 * @param int $groupid The group to delete the user from 56 * @param int $userid The user to delete 57 * @return boolean True if deletion was successful, false otherwise 58 */ 59 function groups_remove_member($groupid, $userid) { 60 if (!groups_group_exists($groupid)) { 61 return false; 62 } 63 64 if (!groups_is_member($groupid, $userid)) { 65 return true; 66 } 67 68 if (!delete_records('groups_members', 'groupid', $groupid, 'userid', $userid)) { 69 return false; 70 } 71 //update group info 72 set_field('groups', 'timemodified', time(), 'id', $groupid); 73 74 //trigger groups events 75 $eventdata = new object(); 76 $eventdata->groupid = $groupid; 77 $eventdata->userid = $userid; 78 events_trigger('groups_member_removed', $eventdata); 79 80 return true; 81 } 82 83 /** 84 * Add a new group 85 * @param object $data group properties (with magic quotes) 86 * @param object $um upload manager with group picture 87 * @return id of group or false if error 88 */ 89 function groups_create_group($data, $um=false) { 90 global $CFG; 91 require_once("$CFG->libdir/gdlib.php"); 92 93 $data->timecreated = time(); 94 $data->timemodified = $data->timecreated; 95 $data->name = trim($data->name); 96 $id = insert_record('groups', $data); 97 98 if ($id) { 99 $data->id = $id; 100 if ($um) { 101 //update image 102 if (save_profile_image($id, $um, 'groups')) { 103 set_field('groups', 'picture', 1, 'id', $id); 104 } 105 $data->picture = 1; 106 } 107 108 //trigger groups events 109 events_trigger('groups_group_created', stripslashes_recursive($data)); 110 } 111 112 return $id; 113 } 114 115 /** 116 * Add a new grouping 117 * @param object $data grouping properties (with magic quotes) 118 * @return id of grouping or false if error 119 */ 120 function groups_create_grouping($data) { 121 global $CFG; 122 123 $data->timecreated = time(); 124 $data->timemodified = $data->timecreated; 125 $data->name = trim($data->name); 126 127 $id = insert_record('groupings', $data); 128 129 if ($id) { 130 //trigger groups events 131 $data->id = $id; 132 events_trigger('groups_grouping_created', stripslashes_recursive($data)); 133 } 134 135 return $id; 136 } 137 138 /** 139 * Update group 140 * @param object $data group properties (with magic quotes) 141 * @param object $um upload manager with group picture 142 * @return boolean success 143 */ 144 function groups_update_group($data, $um=false) { 145 global $CFG; 146 require_once("$CFG->libdir/gdlib.php"); 147 148 $data->timemodified = time(); 149 $data->name = trim($data->name); 150 $result = update_record('groups', $data); 151 152 if ($result) { 153 if ($um) { 154 //update image 155 if (save_profile_image($data->id, $um, 'groups')) { 156 set_field('groups', 'picture', 1, 'id', $data->id); 157 $data->picture = 1; 158 } 159 } 160 161 //trigger groups events 162 events_trigger('groups_group_updated', stripslashes_recursive($data)); 163 } 164 165 return $result; 166 } 167 168 /** 169 * Update grouping 170 * @param object $data grouping properties (with magic quotes) 171 * @return boolean success 172 */ 173 function groups_update_grouping($data) { 174 global $CFG; 175 $data->timemodified = time(); 176 $data->name = trim($data->name); 177 $result = update_record('groupings', $data); 178 if ($result) { 179 //trigger groups events 180 events_trigger('groups_grouping_updated', stripslashes_recursive($data)); 181 } 182 return $result; 183 } 184 185 /** 186 * Delete a group best effort, first removing members and links with courses and groupings. 187 * Removes group avatar too. 188 * @param mixed $grouporid The id of group to delete or full group object 189 * @return boolean True if deletion was successful, false otherwise 190 */ 191 function groups_delete_group($grouporid) { 192 global $CFG; 193 require_once($CFG->libdir.'/gdlib.php'); 194 195 if (is_object($grouporid)) { 196 $groupid = $grouporid->id; 197 $group = $grouporid; 198 } else { 199 $groupid = $grouporid; 200 if (!$group = get_record('groups', 'id', $groupid)) { 201 return false; 202 } 203 } 204 205 // delete group calendar events 206 delete_records('event', 'groupid', $groupid); 207 //first delete usage in groupings_groups 208 delete_records('groupings_groups', 'groupid', $groupid); 209 //delete members 210 delete_records('groups_members', 'groupid', $groupid); 211 //then imge 212 delete_profile_image($groupid, 'groups'); 213 //group itself last 214 $result = delete_records('groups', 'id', $groupid); 215 216 if ($result) { 217 //trigger groups events 218 events_trigger('groups_group_deleted', $group); 219 } 220 221 return $result; 222 } 223 224 /** 225 * Delete grouping 226 * @param int $groupingid 227 * @return bool success 228 */ 229 function groups_delete_grouping($groupingorid) { 230 if (is_object($groupingorid)) { 231 $groupingid = $groupingorid->id; 232 $grouping = $groupingorid; 233 } else { 234 $groupingid = $groupingorid; 235 if (!$grouping = get_record('groupings', 'id', $groupingorid)) { 236 return false; 237 } 238 } 239 240 //first delete usage in groupings_groups 241 delete_records('groupings_groups', 'groupingid', $groupingid); 242 // remove the default groupingid from course 243 set_field('course', 'defaultgroupingid', 0, 'defaultgroupingid', $groupingid); 244 // remove the groupingid from all course modules 245 set_field('course_modules', 'groupingid', 0, 'groupingid', $groupingid); 246 //group itself last 247 $result = delete_records('groupings', 'id', $groupingid); 248 249 if ($result) { 250 //trigger groups events 251 events_trigger('groups_grouping_deleted', $grouping); 252 } 253 254 return $result; 255 } 256 257 /** 258 * Remove all users (or one user) from all groups in course 259 * @param int $courseid 260 * @param int $userid 0 means all users 261 * @param bool $showfeedback 262 * @return bool success 263 */ 264 function groups_delete_group_members($courseid, $userid=0, $showfeedback=false) { 265 global $CFG; 266 267 if (is_bool($userid)) { 268 debugging('Incorrect userid function parameter'); 269 return false; 270 } 271 272 if ($userid) { 273 $usersql = "AND userid = $userid"; 274 } else { 275 $usersql = ""; 276 } 277 278 $groupssql = "SELECT id FROM {$CFG->prefix}groups g WHERE g.courseid = $courseid"; 279 delete_records_select('groups_members', "groupid IN ($groupssql) $usersql"); 280 281 //trigger groups events 282 $eventdata = new object(); 283 $eventdata->courseid = $courseid; 284 $eventdata->userid = $userid; 285 events_trigger('groups_members_removed', $eventdata); 286 287 if ($showfeedback) { 288 notify(get_string('deleted').' groups_members'); 289 } 290 291 return true; 292 } 293 294 /** 295 * Remove all groups from all groupings in course 296 * @param int $courseid 297 * @param bool $showfeedback 298 * @return bool success 299 */ 300 function groups_delete_groupings_groups($courseid, $showfeedback=false) { 301 global $CFG; 302 303 $groupssql = "SELECT id FROM {$CFG->prefix}groups g WHERE g.courseid = $courseid"; 304 delete_records_select('groupings_groups', "groupid IN ($groupssql)"); 305 306 //trigger groups events 307 events_trigger('groups_groupings_groups_removed', $courseid); 308 309 if ($showfeedback) { 310 notify(get_string('deleted').' groupings_groups'); 311 } 312 313 return true; 314 } 315 316 /** 317 * Delete all groups from course 318 * @param int $courseid 319 * @param bool $showfeedback 320 * @return bool success 321 */ 322 function groups_delete_groups($courseid, $showfeedback=false) { 323 global $CFG; 324 require_once($CFG->libdir.'/gdlib.php'); 325 326 $groupssql = "SELECT id FROM {$CFG->prefix}groups g WHERE g.courseid = $courseid"; 327 328 // delete any uses of groups 329 groups_delete_groupings_groups($courseid, $showfeedback); 330 groups_delete_group_members($courseid, 0, $showfeedback); 331 332 // delete group pictures 333 if ($groups = get_records('groups', 'courseid', $courseid)) { 334 foreach($groups as $group) { 335 delete_profile_image($group->id, 'groups'); 336 } 337 } 338 339 // delete group calendar events 340 delete_records_select('event', "groupid IN ($groupssql)"); 341 342 delete_records('groups', 'courseid', $courseid); 343 344 //trigger groups events 345 events_trigger('groups_groups_deleted', $courseid); 346 347 if ($showfeedback) { 348 notify(get_string('deleted').' groups'); 349 } 350 351 return true; 352 } 353 354 /** 355 * Delete all groupings from course 356 * @param int $courseid 357 * @param bool $showfeedback 358 * @return bool success 359 */ 360 function groups_delete_groupings($courseid, $showfeedback=false) { 361 global $CFG; 362 363 // delete any uses of groupings 364 $sql = "DELETE FROM {$CFG->prefix}groupings_groups 365 WHERE groupingid in (SELECT id FROM {$CFG->prefix}groupings g WHERE g.courseid = $courseid)"; 366 execute_sql($sql, false); 367 368 // remove the default groupingid from course 369 set_field('course', 'defaultgroupingid', 0, 'id', $courseid); 370 // remove the groupingid from all course modules 371 set_field('course_modules', 'groupingid', 0, 'course', $courseid); 372 373 delete_records('groupings', 'courseid', $courseid); 374 375 //trigger groups events 376 events_trigger('groups_groupings_deleted', $courseid); 377 378 if ($showfeedback) { 379 notify(get_string('deleted').' groupings'); 380 } 381 382 return true; 383 } 384 385 /* =================================== */ 386 /* various functions used by groups UI */ 387 /* =================================== */ 388 389 /** 390 * Gets the users for a course who are not in a specified group, and returns 391 * them in an array organised by role. For the array format, see 392 * groups_get_members_by_role. 393 * @param int $groupid The id of the group 394 * @param string searchtext similar to searchtext in role assign, search 395 * @return array An array of role id or '*' => information about that role 396 * including a list of users 397 */ 398 function groups_get_users_not_in_group_by_role($courseid, $groupid, $searchtext='', $sort = 'u.lastname ASC') { 399 400 global $CFG; 401 $context = get_context_instance(CONTEXT_COURSE, $courseid); 402 403 if ($searchtext !== '') { // Search for a subset of remaining users 404 $LIKE = sql_ilike(); 405 $FULLNAME = sql_fullname(); 406 $wheresearch = " AND u.id IN (SELECT id FROM {$CFG->prefix}user WHERE $FULLNAME $LIKE '%$searchtext%' OR email $LIKE '%$searchtext%' )"; 407 } else { 408 $wheresearch = ''; 409 } 410 411 /// Get list of allowed roles 412 if(!($validroleids=groups_get_possible_roles($context))) { 413 return; 414 } 415 $roleids = '('.implode(',', $validroleids).')'; 416 417 /// Construct the main SQL 418 $select = " SELECT r.id AS roleid,r.shortname AS roleshortname,r.name AS rolename, 419 u.id AS userid, u.firstname, u.lastname"; 420 $from = " FROM {$CFG->prefix}user u 421 INNER JOIN {$CFG->prefix}role_assignments ra ON ra.userid = u.id 422 INNER JOIN {$CFG->prefix}role r ON r.id = ra.roleid"; 423 424 $where = " WHERE ra.contextid ".get_related_contexts_string($context)." 425 AND u.deleted = 0 426 AND ra.roleid in $roleids 427 AND u.id NOT IN (SELECT userid 428 FROM {$CFG->prefix}groups_members 429 WHERE groupid = $groupid) 430 $wheresearch"; 431 $orderby = " ORDER BY $sort"; 432 433 return groups_calculate_role_people(get_recordset_sql( 434 $select.$from.$where.$orderby),$context); 435 } 436 437 438 /** 439 * Obtains a list of the possible roles that group members might come from, 440 * on a course. Generally this includes all the roles who would have 441 * course:view on that course, except the doanything roles. 442 * @param object $context Context of course 443 * @return Array of role ID integers, or false if error/none. 444 */ 445 function groups_get_possible_roles($context) { 446 $capability = 'moodle/course:view'; 447 $doanything = false; 448 449 // find all possible "student" roles 450 if ($possibleroles = get_roles_with_capability($capability, CAP_ALLOW, $context)) { 451 if (!$doanything) { 452 if (!$sitecontext = get_context_instance(CONTEXT_SYSTEM)) { 453 return false; // Something is seriously wrong 454 } 455 $doanythingroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $sitecontext); 456 } 457 458 $validroleids = array(); 459 foreach ($possibleroles as $possiblerole) { 460 if (!$doanything) { 461 if (isset($doanythingroles[$possiblerole->id])) { // We don't want these included 462 continue; 463 } 464 } 465 if ($caps = role_context_capabilities($possiblerole->id, $context, $capability)) { // resolved list 466 if (isset($caps[$capability]) && $caps[$capability] > 0) { // resolved capability > 0 467 $validroleids[] = $possiblerole->id; 468 } 469 } 470 } 471 if (empty($validroleids)) { 472 return false; 473 } 474 return $validroleids; 475 } else { 476 return false; // No need to continue, since no roles have this capability set 477 } 478 } 479 480 481 /** 482 * Gets potential group members for grouping 483 * @param int $courseid The id of the course 484 * @param int $roleid The role to select users from 485 * @param string $orderby The colum to sort users by 486 * @return array An array of the users 487 */ 488 function groups_get_potential_members($courseid, $roleid = null, $orderby = 'lastname,firstname') { 489 global $CFG; 490 491 $context = get_context_instance(CONTEXT_COURSE, $courseid); 492 $sitecontext = get_context_instance(CONTEXT_SYSTEM); 493 $rolenames = array(); 494 $avoidroles = array(); 495 496 if ($roles = get_roles_used_in_context($context, true)) { 497 498 $canviewroles = get_roles_with_capability('moodle/course:view', CAP_ALLOW, $context); 499 $doanythingroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $sitecontext); 500 501 foreach ($roles as $role) { 502 if (!isset($canviewroles[$role->id])) { // Avoid this role (eg course creator) 503 $avoidroles[] = $role->id; 504 unset($roles[$role->id]); 505 continue; 506 } 507 if (isset($doanythingroles[$role->id])) { // Avoid this role (ie admin) 508 $avoidroles[] = $role->id; 509 unset($roles[$role->id]); 510 continue; 511 } 512 $rolenames[$role->id] = strip_tags(role_get_name($role, $context)); // Used in menus etc later on 513 } 514 } 515 516 $select = 'SELECT u.id, u.username, u.firstname, u.lastname, u.idnumber '; 517 $from = "FROM {$CFG->prefix}user u INNER JOIN 518 {$CFG->prefix}role_assignments r on u.id=r.userid "; 519 520 if ($avoidroles) { 521 $adminroles = 'AND r.roleid NOT IN ('; 522 $adminroles .= implode(',', $avoidroles); 523 $adminroles .= ')'; 524 } else { 525 $adminroles = ''; 526 } 527 528 // we are looking for all users with this role assigned in this context or higher 529 if ($usercontexts = get_parent_contexts($context)) { 530 $listofcontexts = '('.implode(',', $usercontexts).')'; 531 } else { 532 $listofcontexts = '('.$sitecontext->id.')'; // must be site 533 } 534 535 if ($roleid) { 536 $selectrole = " AND r.roleid = $roleid "; 537 } else { 538 $selectrole = " "; 539 } 540 541 $where = "WHERE (r.contextid = $context->id OR r.contextid in $listofcontexts) 542 AND u.deleted = 0 $selectrole 543 AND u.username != 'guest' 544 $adminroles "; 545 $order = "ORDER BY $orderby "; 546 547 return(get_records_sql($select.$from.$where.$order)); 548 549 } 550 551 /** 552 * Parse a group name for characters to replace 553 * @param string $format The format a group name will follow 554 * @param int $groupnumber The number of the group to be used in the parsed format string 555 * @return string the parsed format string 556 */ 557 function groups_parse_name($format, $groupnumber) { 558 if (strstr($format, '@') !== false) { // Convert $groupnumber to a character series 559 $letter = 'A'; 560 for($i=0; $i<$groupnumber; $i++) { 561 $letter++; 562 } 563 $str = str_replace('@', $letter, $format); 564 } else { 565 $str = str_replace('#', $groupnumber+1, $format); 566 } 567 return($str); 568 } 569 570 /** 571 * Assigns group into grouping 572 * @param int groupingid 573 * @param int groupid 574 * @return bool success 575 */ 576 function groups_assign_grouping($groupingid, $groupid) { 577 if (record_exists('groupings_groups', 'groupingid', $groupingid, 'groupid', $groupid)) { 578 return true; 579 } 580 $assign = new object(); 581 $assign->groupingid = $groupingid; 582 $assign->groupid = $groupid; 583 $assign->timeadded = time(); 584 return (bool)insert_record('groupings_groups', $assign); 585 } 586 587 /** 588 * Unassigns group grom grouping 589 * @param int groupingid 590 * @param int groupid 591 * @return bool success 592 */ 593 function groups_unassign_grouping($groupingid, $groupid) { 594 return delete_records('groupings_groups', 'groupingid', $groupingid, 'groupid', $groupid); 595 } 596 597 /** 598 * Lists users in a group based on their role on the course. 599 * Returns false if there's an error or there are no users in the group. 600 * Otherwise returns an array of role ID => role data, where role data includes: 601 * (role) $id, $shortname, $name 602 * $users: array of objects for each user which include the specified fields 603 * Users who do not have a role are stored in the returned array with key '-' 604 * and pseudo-role details (including a name, 'No role'). Users with multiple 605 * roles, same deal with key '*' and name 'Multiple roles'. You can find out 606 * which roles each has by looking in the $roles array of the user object. 607 * @param int $groupid 608 * @param int $courseid Course ID (should match the group's course) 609 * @param string $fields List of fields from user table prefixed with u, default 'u.*' 610 * @param string $sort SQL ORDER BY clause, default 'u.lastname ASC' 611 * @return array Complex array as described above 612 */ 613 function groups_get_members_by_role($groupid, $courseid, $fields='u.*', $sort='u.lastname ASC') { 614 global $CFG; 615 616 // Retrieve information about all users and their roles on the course or 617 // parent ('related') contexts 618 $context=get_context_instance(CONTEXT_COURSE,$courseid); 619 $rs=get_recordset_sql($crap="SELECT r.id AS roleid,r.shortname AS roleshortname,r.name AS rolename, 620 u.id AS userid,$fields 621 FROM {$CFG->prefix}groups_members gm 622 INNER JOIN {$CFG->prefix}user u ON u.id = gm.userid 623 INNER JOIN {$CFG->prefix}role_assignments ra 624 ON ra.userid = u.id 625 INNER JOIN {$CFG->prefix}role r ON r.id = ra.roleid 626 WHERE gm.groupid='$groupid' 627 AND ra.contextid ".get_related_contexts_string($context)." 628 ORDER BY r.sortorder,$sort"); 629 630 return groups_calculate_role_people($rs,$context); 631 } 632 633 /** 634 * Internal function used by groups_get_members_by_role to handle the 635 * results of a database query that includes a list of users and possible 636 * roles on a course. 637 * 638 * @param object $rs The record set (may be false) 639 * @param object $context of course 640 * @return array As described in groups_get_members_by_role 641 */ 642 function groups_calculate_role_people($rs,$context) { 643 global $CFG; 644 if(!$rs) { 645 return false; 646 } 647 648 $roles = get_records_menu('role', null, 'name', 'id, name'); 649 $aliasnames = role_fix_names($roles, $context); 650 651 // Array of all involved roles 652 $roles=array(); 653 // Array of all retrieved users 654 $users=array(); 655 // Fill arrays 656 while($rec=rs_fetch_next_record($rs)) { 657 // Create information about user if this is a new one 658 if(!array_key_exists($rec->userid,$users)) { 659 // User data includes all the optional fields, but not any of the 660 // stuff we added to get the role details 661 $userdata=clone($rec); 662 unset($userdata->roleid); 663 unset($userdata->roleshortname); 664 unset($userdata->rolename); 665 unset($userdata->userid); 666 $userdata->id=$rec->userid; 667 668 // Make an array to hold the list of roles for this user 669 $userdata->roles=array(); 670 $users[$rec->userid]=$userdata; 671 } 672 // If user has a role... 673 if(!is_null($rec->roleid)) { 674 // Create information about role if this is a new one 675 if(!array_key_exists($rec->roleid,$roles)) { 676 $roledata=new StdClass; 677 $roledata->id=$rec->roleid; 678 $roledata->shortname=$rec->roleshortname; 679 if(array_key_exists($rec->roleid,$aliasnames)) { 680 $roledata->name=$aliasnames[$rec->roleid]; 681 } else { 682 $roledata->name=$rec->rolename; 683 } 684 $roledata->users=array(); 685 $roles[$roledata->id]=$roledata; 686 } 687 // Record that user has role 688 $users[$rec->userid]->roles[] = $roles[$rec->roleid]; 689 } 690 } 691 rs_close($rs); 692 693 // Return false if there weren't any users 694 if(count($users)==0) { 695 return false; 696 } 697 698 // Add pseudo-role for multiple roles 699 $roledata=new StdClass; 700 $roledata->name=get_string('multipleroles','role'); 701 $roledata->users=array(); 702 $roles['*']=$roledata; 703 704 // Now we rearrange the data to store users by role 705 foreach($users as $userid=>$userdata) { 706 $rolecount=count($userdata->roles); 707 if($rolecount==0) { 708 debugging("Unexpected: user $userid is missing roles"); 709 } else if($rolecount>1) { 710 $roleid='*'; 711 } else { 712 $roleid=$userdata->roles[0]->id; 713 } 714 $roles[$roleid]->users[$userid]=$userdata; 715 } 716 717 // Delete roles not used 718 foreach($roles as $key=>$roledata) { 719 if(count($roledata->users)===0) { 720 unset($roles[$key]); 721 } 722 } 723 724 // Return list of roles containing their users 725 return $roles; 726 } 727 728 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |