/** * Deletes the link between the specified user and group. * @param int $groupid The group to delete the user from * @param int $userid The user to delete * @return boolean True if deletion was successful, false otherwise */ function groups_remove_member($groupid, $userid) { if (!groups_group_exists($groupid)) { return false; } if (!groups_is_member($groupid, $userid)) { return true; } if (!delete_records('groups_members', 'groupid', $groupid, 'userid', $userid)) { return false; } //update group info set_field('groups', 'timemodified', time(), 'id', $groupid); return true; }
/** * Deletes the link between the specified user and group. * @param int $groupid The group to delete the user from * @param int $userid The user to delete * @return boolean True if deletion was successful, false otherwise */ function groups_remove_member($groupid, $userid) { if (!groups_group_exists($groupid)) { return false; } if (!groups_is_member($groupid, $userid)) { return true; } if (!delete_records('groups_members', 'groupid', $groupid, 'userid', $userid)) { return false; } //update group info set_field('groups', 'timemodified', time(), 'id', $groupid); //trigger groups events $eventdata = new object(); $eventdata->groupid = $groupid; $eventdata->userid = $userid; events_trigger('groups_member_removed', $eventdata); return true; }
/** * Deletes the link between the specified user and group. * @param int $groupid The group to delete the user from * @param int $userid The user to delete * @return boolean True if deletion was successful, false otherwise */ function groups_remove_member($groupid, $userid) { global $DB; if (!$DB->record_exists('user', array('id' => $userid))) { throw new moodle_exception('useriddoesntexist'); } if (!groups_group_exists($groupid)) { throw new moodle_exception('cannotaddmembergroupiddoesntexist'); } if (!groups_is_member($groupid, $userid)) { return true; } $DB->delete_records('groups_members', array('groupid' => $groupid, 'userid' => $userid)); //update group info $DB->set_field('groups', 'timemodified', time(), array('id' => $groupid)); //trigger groups events $eventdata = new object(); $eventdata->groupid = $groupid; $eventdata->userid = $userid; events_trigger('groups_member_removed', $eventdata); return true; }
/** * Performs the report function. * * @param array $formdata the form data * @param int $type the report type * @param string $saveto File to save the pdf report to. * @return bool False on failure * @uses $CFG, $DB */ function report_ncccscensus_generate_report($formdata, $type = REPORT_NCCCSCENSUS_ACTION_VIEW, $saveto = false) { global $CFG, $DB; require_once $CFG->libdir . '/moodlelib.php'; $reportname = 'report_ncccscensus'; $cid = $formdata->id; // In case the form is hacked, set a default startdate to today at midnight. if (empty($formdata->startdate)) { $formdata->startdate = usergetmidnight(time(), get_user_timezone()); } // In case the form is hacked, set a default enddate to today at midnight. if (empty($formdata->enddate)) { $formdata->enddate = $formdata->startdate; } // Advance enddate to tomorrow's midnight. $formdata->enddate += DAYSECS - 1; // This flag determines if we should display grouped users or not. $nogroups = isset($formdata->disablegroups) ? true : false; if ($nogroups) { $group = false; } else { // If group specified, do some validation. $group = isset($formdata->group) ? $formdata->group : false; // In case the form is hacked, the group could be invalid. if ($group === false || $group < 0) { throw new report_ncccscensus_exception('cannotfindgroup'); } if ($group > 0) { // Validate the group ID. if (!groups_group_exists($group)) { throw new report_ncccscensus_exception('cannotfindgroup'); } // Validate the group ID with respect to the course ID. $groupdata = groups_get_course_data($cid); $groupfound = false; foreach ($groupdata->groups as $groupobject) { if ($groupobject->id == $group) { $groupfound = true; break; } } if (!$groupfound) { throw new report_ncccscensus_exception('invalidgroupid'); } // User could still hack form to view a group that they don't have the capability to see. $context = context_course::instance($cid); if (has_capability('moodle/site:accessallgroups', $context)) { $userid = 0; } else { if (has_capability('moodle/course:managegroups', $context)) { $userid = $USER->id; } else { $userid = false; } } if ($userid === false) { throw new report_ncccscensus_exception('invalidgroupid'); } if ($userid != 0) { $grouprecs = groups_get_all_groups($course->id, $userid, 0, 'g.id, g.name'); $groupnotfound = true; foreach ($grouprecs as $grouprec) { if ($grouprec->id == $group) { $groupnotfound = false; break; } } if ($groupnotfound) { throw new report_ncccscensus_exception('invalidgroupid'); } } } } $users = array(); if ($nogroups) { $users = report_ncccscensus_get_users($cid, REPORT_NCCCSCENSUS_EXCLUDE_GROUP_MEMBERS); } else { if ($group > 0) { $users = report_ncccscensus_get_users($cid, $group); } else { $users = report_ncccscensus_get_users($cid); } } $results = report_ncccscensus_build_grades_array($cid, $users, $formdata->startdate, $formdata->enddate); if (empty($results)) { return false; } if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW) { $headers = array('student' => get_string('studentfullnamehtml', $reportname)); $showstudentid = report_ncccscensus_check_field_status('showstudentid', 'html'); } else { if ($type == REPORT_NCCCSCENSUS_ACTION_CSV) { $headers = array('student' => get_string('studentfullnamecsv', $reportname)); $showstudentid = report_ncccscensus_check_field_status('showstudentid', 'csv'); } else { $headers = array('student' => get_string('studentfullnamepdf', $reportname)); $showstudentid = report_ncccscensus_check_field_status('showstudentid', 'pdf'); } } if ($showstudentid) { $headers['studentid'] = get_string('studentid', $reportname); } $headers['activity'] = get_string('activityname', $reportname); $headers['module'] = get_string('activitymodule', $reportname); $headers['status'] = get_string('submissionstatus', $reportname); $headers['datesubmitted'] = get_string('submissiondate', $reportname); $headers['grade'] = get_string('grade', $reportname); $headers['gradedate'] = get_string('gradedate', $reportname); $context = context_course::instance($cid); $namesarrayview = array(); $namesarraypdf = array(); $instructors = ' - '; $viewlink = ': <a href="' . $CFG->wwwroot . '/user/view.php?id='; if (!empty($CFG->coursecontact)) { $coursecontactroles = explode(',', $CFG->coursecontact); sort($coursecontactroles); // If a user has multiple roles, we do not want to show user multiple times as a contact. $teachers = array(); foreach ($coursecontactroles as $roleid) { $roleid = (int) $roleid; if ($users = get_role_users($roleid, $context, true)) { $role = $DB->get_record('role', array('id' => $roleid)); $rolename = format_string(role_get_name($role, $context)); foreach ($users as $teacher) { // The $teachers array tracks whether a user is already a course contact. if (!isset($teachers[$teacher->id])) { $teachers[$teacher->id] = true; $fullname = fullname($teacher, has_capability('moodle/site:viewfullnames', $context)); $namesarrayview[] = $rolename . $viewlink . $teacher->id . '&course=' . SITEID . '">' . $fullname . '</a>'; $namesarraycsv[] = $rolename . ': ' . $fullname; $namesarraypdf[] = $rolename . ': ' . $fullname; } } } } } if ($type != REPORT_NCCCSCENSUS_ACTION_PDF) { if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW) { // Create legend for HTML view. $legend = new html_table(); $legend->head = array(get_string('legend', $reportname)); $legend->headspan = array(2); $legendrow1colour = new html_table_cell(); $legendrow1colour->style = 'width: 50px; background-color: ' . get_config('report_ncccscensus', 'gradeoverridecolour'); $legendrow1[] = $legendrow1colour; $legendrow1[] = get_string('legendgradeoverride', $reportname); $legendrow2colour = new html_table_cell(); $legendrow2colour->style = 'width: 50px; background-color: ' . get_config('report_ncccscensus', 'gradenogradecolour'); $legendrow2[] = $legendrow2colour; $legendrow2[] = get_string('legendnograde', $reportname); $legend->data = array($legendrow1, $legendrow2); $legendalign = array('center', 'left'); $legend->align = $legendalign; } $table = new html_table(); $table->head = $headers; $align = array('left'); $numheaders = count($headers); for ($i = 1; $i < $numheaders; $i++) { $align[] = 'center'; } $table->align = $align; $table->data = array(); foreach ($results as $result) { $datum = array(); $datum[] = $result->student; if ($showstudentid) { $datum[] = $result->studentid; } $datum[] = $result->activity; $datum[] = $result->module; $status = $result->status; $grade = $result->grade; if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW && $grade == get_string('nograde', $reportname)) { $specialstatus = new html_table_cell($status); $specialstatus->style = 'background-color: ' . get_config('report_ncccscensus', 'gradenogradecolour'); $status = $specialstatus; } else { if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW && $result->overridden) { $specialstatus = new html_table_cell($status); $specialstatus->style = 'background-color: ' . get_config('report_ncccscensus', 'gradeoverridecolour'); $status = $specialstatus; } } $datum[] = $status; $datum[] = $result->submitdate; if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW && $grade == get_string('nograde', $reportname)) { $nograde = new html_table_cell($grade); $nograde->style = 'background-color: ' . get_config('report_ncccscensus', 'gradenogradecolour'); $grade = $nograde; } else { if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW && $result->overridden) { $overriddengrade = new html_table_cell($grade); $overriddengrade->style = 'background-color: ' . get_config('report_ncccscensus', 'gradeoverridecolour'); $grade = $overriddengrade; } } $datum[] = $grade; $datum[] = $result->date; $table->data[] = $datum; } } $course = $DB->get_record('course', array('id' => $cid)); if ($group > 0) { $groupname = groups_get_group_name($group); } $datestring = 'n/j/y'; $reportrange = date($datestring, $formdata->startdate) . ' - ' . date($datestring, $formdata->enddate); if ($type != REPORT_NCCCSCENSUS_ACTION_VIEW) { $date = usergetdate(time(), get_user_timezone()); $filename = 'CensusRpt2_'; $filename .= date('MdY_Hi', mktime($date['hours'], $date['minutes'], 0, $date['mon'], $date['mday'], $date['year'])); } if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW) { if (report_ncccscensus_check_field_status('showcoursename', 'html')) { echo '<b>' . get_string('coursetitle', $reportname) . ':</b> ' . $course->fullname . '<br>'; } if (report_ncccscensus_check_field_status('showcoursecode', 'html')) { echo '<b>' . get_string('coursecode', $reportname) . ':</b> ' . $course->shortname . '<br>'; } // Only show course ID if present. if (report_ncccscensus_check_field_status('showcourseid', 'html') && $course->idnumber !== '') { echo '<b>' . get_string('courseid', $reportname) . ':</b> ' . $course->idnumber . '<br>'; } if (report_ncccscensus_check_field_status('showteachername', 'html')) { if (!empty($namesarrayview)) { $instructors = implode(', ', $namesarrayview); echo '<b>' . get_string('instructor', $reportname) . ':</b> ' . $instructors . '<br>'; } } echo '<b>' . get_string('reportrange', $reportname) . ':</b> ' . $reportrange . '<br>'; if (isset($groupname)) { echo '<b>' . get_string('section', $reportname) . ':</b> ' . $groupname . '<br>'; } else { echo '<b>' . get_string('section', $reportname) . ':</b> ' . get_string('allgroupspdf', $reportname) . '<br>'; } echo '<br>'; echo html_writer::table($table); echo '<div id="studentfootnote" style="font-size:10px;">' . get_string('studentfootnote', $reportname) . '</div>'; echo '<br>'; echo html_writer::table($legend); echo '<br><div align="center"><a href="' . $CFG->wwwroot . '/report/ncccscensus/index.php?id=' . $formdata->id . '">'; echo get_string('backtoreport', 'report_ncccscensus') . '</a></div>'; } else { if ($type == REPORT_NCCCSCENSUS_ACTION_PDF) { $topheaders = array(); $topheaders['student'] = get_string('student', $reportname); $topheaders['activity'] = get_string('activity', $reportname); $topheaders['submission'] = get_string('submission', $reportname); $topheaders['grade'] = get_string('grade', $reportname); $bottomheaders = array(); $bottomheaders['student'] = array('fullname' => get_string('studentfullnamepdf', $reportname)); $showstudentid = report_ncccscensus_check_field_status('showstudentid', 'pdf'); if ($showstudentid) { $bottomheaders['student']['id'] = get_string('studentidpdf', $reportname); } $bottomheaders['activity'] = array('name' => get_string('activityname', $reportname), 'module' => get_string('activitymodule', $reportname)); $bottomheaders['submission'] = array('status' => get_string('submissionstatus', $reportname), 'date' => get_string('submissiondate', $reportname)); $bottomheaders['grade'] = array('grade' => get_string('grade', $reportname), 'date' => get_string('gradedatepdf', $reportname)); require_once 'report.class.php'; $censusreport = new report(); $censusreport->topheaders = $topheaders; $censusreport->bottomheaders = $bottomheaders; $censusreport->data = array(); foreach ($results as $result) { $fieldarray = array(); $fieldarray['studentfullname'] = $result->student; if ($showstudentid) { $fieldarray['studentid'] = $result->studentid; } $fieldarray['activityname'] = $result->activity; $fieldarray['activitymodule'] = $result->module; $fieldarray['submissionstatus'] = $result->status; $fieldarray['submissiondate'] = $result->submitdate; $fieldarray['gradegrade'] = $result->grade; $fieldarray['gradedate'] = $result->date; $censusreport->data[] = array('data' => $fieldarray, 'override' => $result->overridden != 0 ? true : false, 'nograde' => $result->grade == get_string('nograde', $reportname) ? true : false); } $censusreport->filename = $filename . '.pdf'; if (report_ncccscensus_check_field_status('showcoursename', 'pdf')) { $censusreport->top[] = array(get_string('coursetitlepdf', $reportname) . ':', $course->fullname); } if (report_ncccscensus_check_field_status('showcoursecode', 'pdf')) { $censusreport->top[] = array(get_string('coursecodepdf', $reportname) . ':', $course->shortname); } if (report_ncccscensus_check_field_status('showcourseid', 'pdf') && $course->idnumber !== '') { $censusreport->top[] = array(get_string('courseid', $reportname) . ':', $course->idnumber); } if (report_ncccscensus_check_field_status('showteachername', 'pdf')) { if (!empty($namesarrayview)) { $instructors = implode(', ', $namesarrayview); } $censusreport->top[] = array(get_string('instructor', $reportname) . ':', strip_tags($instructors)); } $censusreport->top[] = array(get_string('reportrangepdf', $reportname) . ':', $reportrange); if (isset($groupname)) { $censusreport->top[] = array(get_string('group', $reportname) . ':', $groupname); } else { if ($group !== false) { $censusreport->top[] = array(get_string('group', $reportname) . ':', get_string('allgroupspdf', $reportname)); } } if (report_ncccscensus_check_field_status('showsignatureline', 'pdf')) { $censusreport->signatureline = true; } if (report_ncccscensus_check_field_status('showdateline', 'pdf')) { $censusreport->dateline = true; } if ($footermessage = get_config('report_ncccscensus', 'footermessage')) { $censusreport->bottom .= $footermessage; } $censusreport->download($saveto); return true; } else { if ($type == REPORT_NCCCSCENSUS_ACTION_CSV) { if (!empty($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) { header('Expires: 0'); header('Cache-Control: private, pre-check=0, post-check=0, max-age=0, must-revalidate'); header('Connection: Keep-Alive'); header('Content-Language: ' . current_language()); header('Keep-Alive: timeout=5, max=100'); header('Pragma: no-cache'); header('Pragma: expires'); header('Expires: Mon, 20 Aug 1969 09:23:00 GMT'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); } header('Content-Transfer-Encoding: ascii'); header('Content-Disposition: attachment; filename=' . $filename . '.csv'); header('Content-Type: text/comma-separated-values'); $output = fopen('php://output', 'w'); fputcsv($output, array(get_string('ncccscensusreport_title', 'report_ncccscensus'))); fputcsv($output, array()); if (report_ncccscensus_check_field_status('showcoursename', 'csv')) { fputcsv($output, array(get_string('coursetitle', $reportname), $course->fullname)); } if (report_ncccscensus_check_field_status('showcoursecode', 'csv')) { fputcsv($output, array(get_string('coursecode', $reportname), $course->shortname)); } if (report_ncccscensus_check_field_status('showcourseid', 'csv') && $course->idnumber !== '') { fputcsv($output, array(get_string('courseid', $reportname), $course->idnumber)); } if (!empty($namesarrayview) && report_ncccscensus_check_field_status('showteachername', 'csv')) { fputcsv($output, array_merge(array(get_string('instructor', $reportname)), $namesarraycsv)); } fputcsv($output, array(get_string('reportrange', $reportname), $reportrange)); if (isset($groupname)) { fputcsv($output, array(get_string('section', $reportname), $groupname)); } else { fputcsv($output, array(get_string('section', $reportname), get_string('allgroups', $reportname))); } fputcsv($output, array()); fputcsv($output, $table->head); foreach ($table->data as $row) { fputcsv($output, $row); } $showsignatureline = report_ncccscensus_check_field_status('showsignatureline', 'csv'); $showdateline = report_ncccscensus_check_field_status('showdateline', 'csv'); if ($showsignatureline || $showdateline) { fputcsv($output, array()); if ($showsignatureline) { fputcsv($output, array(get_string('certified', $reportname))); fputcsv($output, array(get_string('signature', $reportname) . get_string('underscores', $reportname))); } if ($showdateline) { fputcsv($output, array(get_string('date') . get_string('underscores', 'report_ncccscensus'))); } } fclose($output); } } } }
function calendar_add_event_allowed($event) { global $USER; // can not be using guest account if (empty($USER->id) or $USER->username == 'guest') { return false; } $sitecontext = get_context_instance(CONTEXT_SYSTEM); // if user has manageentries at site level, always return true if (has_capability('moodle/calendar:manageentries', $sitecontext)) { return true; } switch ($event->type) { case 'course': return has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, $event->courseid)); case 'group': if (!groups_group_exists($event->groupid)) { //TODO:check. return false; } // this is ok because if you have this capability at course level, you should be able // to edit group calendar too // there is no need to check membership, because if you have this capability // you will have a role in this group context return has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_GROUP, $event->groupid)); case 'user': if ($event->userid == $USER->id) { return has_capability('moodle/calendar:manageownentries', $sitecontext); } //there is no 'break;' intentionally //there is no 'break;' intentionally case 'site': return has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, SITEID)); default: return false; } }
/** * Function to be run periodically according to the moodle cron * Finds all posts that have yet to be mailed out, and mails them * out to all subscribers * @return void */ function forum_cron() { global $CFG, $USER; $cronuser = clone $USER; $site = get_site(); // all users that are subscribed to any post that needs sending $users = array(); // status arrays $mailcount = array(); $errorcount = array(); // caches $discussions = array(); $forums = array(); $courses = array(); $coursemodules = array(); $subscribedusers = array(); // Posts older than 2 days will not be mailed. This is to avoid the problem where // cron has not been running for a long time, and then suddenly people are flooded // with mail from the past few weeks or months $timenow = time(); $endtime = $timenow - $CFG->maxeditingtime; $starttime = $endtime - 48 * 3600; // Two days earlier if ($posts = forum_get_unmailed_posts($starttime, $endtime, $timenow)) { // Mark them all now as being mailed. It's unlikely but possible there // might be an error later so that a post is NOT actually mailed out, // but since mail isn't crucial, we can accept this risk. Doing it now // prevents the risk of duplicated mails, which is a worse problem. if (!forum_mark_old_posts_as_mailed($endtime)) { mtrace('Errors occurred while trying to mark some posts as being mailed.'); return false; // Don't continue trying to mail them, in case we are in a cron loop } // checking post validity, and adding users to loop through later foreach ($posts as $pid => $post) { $discussionid = $post->discussion; if (!isset($discussions[$discussionid])) { if ($discussion = get_record('forum_discussions', 'id', $post->discussion)) { $discussions[$discussionid] = $discussion; } else { mtrace('Could not find discussion ' . $discussionid); unset($posts[$pid]); continue; } } $forumid = $discussions[$discussionid]->forum; if (!isset($forums[$forumid])) { if ($forum = get_record('forum', 'id', $forumid)) { $forums[$forumid] = $forum; } else { mtrace('Could not find forum ' . $forumid); unset($posts[$pid]); continue; } } $courseid = $forums[$forumid]->course; if (!isset($courses[$courseid])) { if ($course = get_record('course', 'id', $courseid)) { $courses[$courseid] = $course; } else { mtrace('Could not find course ' . $courseid); unset($posts[$pid]); continue; } } if (!isset($coursemodules[$forumid])) { if ($cm = get_coursemodule_from_instance('forum', $forumid, $courseid)) { $coursemodules[$forumid] = $cm; } else { mtrace('Could not course module for forum ' . $forumid); unset($posts[$pid]); continue; } } // caching subscribed users of each forum if (!isset($subscribedusers[$forumid])) { if ($subusers = forum_subscribed_users($courses[$courseid], $forums[$forumid], 0, false)) { foreach ($subusers as $postuser) { // do not try to mail users with stopped email if ($postuser->emailstop) { if (!empty($CFG->forum_logblocked)) { add_to_log(SITEID, 'forum', 'mail blocked', '', '', 0, $postuser->id); } continue; } // this user is subscribed to this forum $subscribedusers[$forumid][$postuser->id] = $postuser->id; // this user is a user we have to process later $users[$postuser->id] = $postuser; } unset($subusers); // release memory } } $mailcount[$pid] = 0; $errorcount[$pid] = 0; } } if ($users && $posts) { $urlinfo = parse_url($CFG->wwwroot); $hostname = $urlinfo['host']; foreach ($users as $userto) { @set_time_limit(120); // terminate if processing of any account takes longer than 2 minutes // set this so that the capabilities are cached, and environment matches receiving user $USER = $userto; mtrace('Processing user ' . $userto->id); // init caches $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); $userto->enrolledin = array(); // reset the caches foreach ($coursemodules as $forumid => $unused) { $coursemodules[$forumid]->cache = new object(); $coursemodules[$forumid]->cache->caps = array(); unset($coursemodules[$forumid]->uservisible); } foreach ($posts as $pid => $post) { // Set up the environment for the post, discussion, forum, course $discussion = $discussions[$post->discussion]; $forum = $forums[$discussion->forum]; $course = $courses[$forum->course]; $cm =& $coursemodules[$forum->id]; // Do some checks to see if we can bail out now if (!isset($subscribedusers[$forum->id][$userto->id])) { continue; // user does not subscribe to this forum } // Verify user is enrollend in course - if not do not send any email if (!isset($userto->enrolledin[$course->id])) { $userto->enrolledin[$course->id] = has_capability('moodle/course:view', get_context_instance(CONTEXT_COURSE, $course->id)); } if (!$userto->enrolledin[$course->id]) { // oops - this user should not receive anything from this course continue; } // Get info about the sending user if (array_key_exists($post->userid, $users)) { // we might know him/her already $userfrom = $users[$post->userid]; } else { if ($userfrom = get_record('user', 'id', $post->userid)) { $users[$userfrom->id] = $userfrom; // fetch only once, we can add it to user list, it will be skipped anyway } else { mtrace('Could not find user ' . $post->userid); continue; } } // setup global $COURSE properly - needed for roles and languages course_setup($course); // More environment // Fill caches if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $userto->canpost[$discussion->id] = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); $users[$userfrom->id]->groups = array(); } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; } // Make sure groups allow this user to see this email if ($discussion->groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used if (!groups_group_exists($discussion->groupid)) { // Can't find group continue; // Be safe and don't send it to anyone } if (!groups_is_member($discussion->groupid) and !has_capability('moodle/site:accessallgroups', $modcontext)) { // do not send posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS continue; } } // Make sure we're allowed to see it... if (!forum_user_can_see_post($forum, $discussion, $post, NULL, $cm)) { mtrace('user ' . $userto->id . ' can not see ' . $post->id); continue; } // OK so we need to send the email. // Does the user want this post in a digest? If so postpone it for now. if ($userto->maildigest > 0) { // This user wants the mails to be in digest form $queue = new object(); $queue->userid = $userto->id; $queue->discussionid = $discussion->id; $queue->postid = $post->id; $queue->timemodified = $post->created; if (!insert_record('forum_queue', $queue)) { mtrace("Error: mod/forum/cron.php: Could not queue for digest mail for id {$post->id} to user {$userto->id} ({$userto->email}) .. not trying again."); } continue; } // Prepare to actually send the post now, and build up the content $cleanforumname = str_replace('"', "'", strip_tags(format_string($forum->name))); $userfrom->customheaders = array('Precedence: Bulk', 'List-Id: "' . $cleanforumname . '" <moodleforum' . $forum->id . '@' . $hostname . '>', 'List-Help: ' . $CFG->wwwroot . '/mod/forum/view.php?f=' . $forum->id, 'Message-ID: <moodlepost' . $post->id . '@' . $hostname . '>', 'In-Reply-To: <moodlepost' . $post->parent . '@' . $hostname . '>', 'References: <moodlepost' . $post->parent . '@' . $hostname . '>', 'X-Course-Id: ' . $course->id, 'X-Course-Name: ' . format_string($course->fullname, true)); $postsubject = "{$course->shortname}: " . format_string($post->subject, true); $posttext = forum_make_mail_text($course, $forum, $discussion, $post, $userfrom, $userto); $posthtml = forum_make_mail_html($course, $forum, $discussion, $post, $userfrom, $userto); // Send the post now! mtrace('Sending ', ''); if (!($mailresult = email_to_user($userto, $userfrom, $postsubject, $posttext, $posthtml, '', '', $CFG->forum_replytouser))) { mtrace("Error: mod/forum/cron.php: Could not send out mail for id {$post->id} to user {$userto->id}" . " ({$userto->email}) .. not trying again."); add_to_log($course->id, 'forum', 'mail error', "discuss.php?d={$discussion->id}#p{$post->id}", substr(format_string($post->subject, true), 0, 30), $cm->id, $userto->id); $errorcount[$post->id]++; } else { if ($mailresult === 'emailstop') { // should not be reached anymore - see check above } else { $mailcount[$post->id]++; // Mark post as read if forum_usermarksread is set off if (!$CFG->forum_usermarksread) { $userto->markposts[$post->id] = $post->id; } } } mtrace('post ' . $post->id . ': ' . $post->subject); } // mark processed posts as read forum_tp_mark_posts_read($userto, $userto->markposts); } } if ($posts) { foreach ($posts as $post) { mtrace($mailcount[$post->id] . " users were sent post {$post->id}, '{$post->subject}'"); if ($errorcount[$post->id]) { set_field("forum_posts", "mailed", "2", "id", "{$post->id}"); } } } // release some memory unset($subscribedusers); unset($mailcount); unset($errorcount); $USER = clone $cronuser; course_setup(SITEID); $sitetimezone = $CFG->timezone; // Now see if there are any digest mails waiting to be sent, and if we should send them mtrace('Starting digest processing...'); @set_time_limit(300); // terminate if not able to fetch all digests in 5 minutes if (!isset($CFG->digestmailtimelast)) { // To catch the first time set_config('digestmailtimelast', 0); } $timenow = time(); $digesttime = usergetmidnight($timenow, $sitetimezone) + $CFG->digestmailtime * 3600; // Delete any really old ones (normally there shouldn't be any) $weekago = $timenow - 7 * 24 * 3600; delete_records_select('forum_queue', "timemodified < {$weekago}"); mtrace('Cleaned old digest records'); if ($CFG->digestmailtimelast < $digesttime and $timenow > $digesttime) { mtrace('Sending forum digests: ' . userdate($timenow, '', $sitetimezone)); $digestposts_rs = get_recordset_select('forum_queue', "timemodified < {$digesttime}"); if (!rs_EOF($digestposts_rs)) { // We have work to do $usermailcount = 0; //caches - reuse the those filled before too $discussionposts = array(); $userdiscussions = array(); while ($digestpost = rs_fetch_next_record($digestposts_rs)) { if (!isset($users[$digestpost->userid])) { if ($user = get_record('user', 'id', $digestpost->userid)) { $users[$digestpost->userid] = $user; } else { continue; } } $postuser = $users[$digestpost->userid]; if ($postuser->emailstop) { if (!empty($CFG->forum_logblocked)) { add_to_log(SITEID, 'forum', 'mail blocked', '', '', 0, $postuser->id); } continue; } if (!isset($posts[$digestpost->postid])) { if ($post = get_record('forum_posts', 'id', $digestpost->postid)) { $posts[$digestpost->postid] = $post; } else { continue; } } $discussionid = $digestpost->discussionid; if (!isset($discussions[$discussionid])) { if ($discussion = get_record('forum_discussions', 'id', $discussionid)) { $discussions[$discussionid] = $discussion; } else { continue; } } $forumid = $discussions[$discussionid]->forum; if (!isset($forums[$forumid])) { if ($forum = get_record('forum', 'id', $forumid)) { $forums[$forumid] = $forum; } else { continue; } } $courseid = $forums[$forumid]->course; if (!isset($courses[$courseid])) { if ($course = get_record('course', 'id', $courseid)) { $courses[$courseid] = $course; } else { continue; } } if (!isset($coursemodules[$forumid])) { if ($cm = get_coursemodule_from_instance('forum', $forumid, $courseid)) { $coursemodules[$forumid] = $cm; } else { continue; } } $userdiscussions[$digestpost->userid][$digestpost->discussionid] = $digestpost->discussionid; $discussionposts[$digestpost->discussionid][$digestpost->postid] = $digestpost->postid; } rs_close($digestposts_rs); /// Finished iteration, let's close the resultset // Data collected, start sending out emails to each user foreach ($userdiscussions as $userid => $thesediscussions) { @set_time_limit(120); // terminate if processing of any account takes longer than 2 minutes $USER = $cronuser; course_setup(SITEID); // reset cron user language, theme and timezone settings mtrace(get_string('processingdigest', 'forum', $userid), '... '); // First of all delete all the queue entries for this user delete_records_select('forum_queue', "userid = {$userid} AND timemodified < {$digesttime}"); $userto = $users[$userid]; // Override the language and timezone of the "current" user, so that // mail is customised for the receiver. $USER = $userto; course_setup(SITEID); // init caches $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); $postsubject = get_string('digestmailsubject', 'forum', format_string($site->shortname, true)); $headerdata = new object(); $headerdata->sitename = format_string($site->fullname, true); $headerdata->userprefs = $CFG->wwwroot . '/user/edit.php?id=' . $userid . '&course=' . $site->id; $posttext = get_string('digestmailheader', 'forum', $headerdata) . "\n\n"; $headerdata->userprefs = '<a target="_blank" href="' . $headerdata->userprefs . '">' . get_string('digestmailprefs', 'forum') . '</a>'; $posthtml = "<head>"; foreach ($CFG->stylesheets as $stylesheet) { $posthtml .= '<link rel="stylesheet" type="text/css" href="' . $stylesheet . '" />' . "\n"; } $posthtml .= "</head>\n<body id=\"email\">\n"; $posthtml .= '<p>' . get_string('digestmailheader', 'forum', $headerdata) . '</p><br /><hr size="1" noshade="noshade" />'; foreach ($thesediscussions as $discussionid) { @set_time_limit(120); // to be reset for each post $discussion = $discussions[$discussionid]; $forum = $forums[$discussion->forum]; $course = $courses[$forum->course]; $cm = $coursemodules[$forum->id]; //override language course_setup($course); // Fill caches if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $userto->canpost[$discussion->id] = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } $strforums = get_string('forums', 'forum'); $canunsubscribe = !forum_is_forcesubscribed($forum); $canreply = $userto->canpost[$discussion->id]; $posttext .= "\n \n"; $posttext .= '====================================================================='; $posttext .= "\n \n"; $posttext .= "{$course->shortname} -> {$strforums} -> " . format_string($forum->name, true); if ($discussion->name != $forum->name) { $posttext .= " -> " . format_string($discussion->name, true); } $posttext .= "\n"; $posthtml .= "<p><font face=\"sans-serif\">" . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/course/view.php?id={$course->id}\">{$course->shortname}</a> -> " . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/index.php?id={$course->id}\">{$strforums}</a> -> " . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/view.php?f={$forum->id}\">" . format_string($forum->name, true) . "</a>"; if ($discussion->name == $forum->name) { $posthtml .= "</font></p>"; } else { $posthtml .= " -> <a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/discuss.php?d={$discussion->id}\">" . format_string($discussion->name, true) . "</a></font></p>"; } $posthtml .= '<p>'; $postsarray = $discussionposts[$discussionid]; sort($postsarray); foreach ($postsarray as $postid) { $post = $posts[$postid]; if (array_key_exists($post->userid, $users)) { // we might know him/her already $userfrom = $users[$post->userid]; } else { if ($userfrom = get_record('user', 'id', $post->userid)) { $users[$userfrom->id] = $userfrom; // fetch only once, we can add it to user list, it will be skipped anyway } else { mtrace('Could not find user ' . $post->userid); continue; } } if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); $users[$userfrom->id]->groups = array(); } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; } $userfrom->customheaders = array("Precedence: Bulk"); if ($userto->maildigest == 2) { // Subjects only $by = new object(); $by->name = fullname($userfrom); $by->date = userdate($post->modified); $posttext .= "\n" . format_string($post->subject, true) . ' ' . get_string("bynameondate", "forum", $by); $posttext .= "\n---------------------------------------------------------------------"; $by->name = "<a target=\"_blank\" href=\"{$CFG->wwwroot}/user/view.php?id={$userfrom->id}&course={$course->id}\">{$by->name}</a>"; $posthtml .= '<div><a target="_blank" href="' . $CFG->wwwroot . '/mod/forum/discuss.php?d=' . $discussion->id . '#p' . $post->id . '">' . format_string($post->subject, true) . '</a> ' . get_string("bynameondate", "forum", $by) . '</div>'; } else { // The full treatment $posttext .= forum_make_mail_text($course, $forum, $discussion, $post, $userfrom, $userto, true); $posthtml .= forum_make_mail_post($course, $forum, $discussion, $post, $userfrom, $userto, false, $canreply, true, false); // Create an array of postid's for this user to mark as read. if (!$CFG->forum_usermarksread) { $userto->markposts[$post->id] = $post->id; } } } if ($canunsubscribe) { $posthtml .= "\n<div align=\"right\"><font size=\"1\"><a href=\"{$CFG->wwwroot}/mod/forum/subscribe.php?id={$forum->id}\">" . get_string("unsubscribe", "forum") . "</a></font></div>"; } else { $posthtml .= "\n<div align=\"right\"><font size=\"1\">" . get_string("everyoneissubscribed", "forum") . "</font></div>"; } $posthtml .= '<hr size="1" noshade="noshade" /></p>'; } $posthtml .= '</body>'; if ($userto->mailformat != 1) { // This user DOESN'T want to receive HTML $posthtml = ''; } if (!($mailresult = email_to_user($userto, $site->shortname, $postsubject, $posttext, $posthtml, '', '', $CFG->forum_replytouser))) { mtrace("ERROR!"); echo "Error: mod/forum/cron.php: Could not send out digest mail to user {$userto->id} ({$userto->email})... not trying again.\n"; add_to_log($course->id, 'forum', 'mail digest error', '', '', $cm->id, $userto->id); } else { if ($mailresult === 'emailstop') { // should not happen anymore - see check above } else { mtrace("success."); $usermailcount++; // Mark post as read if forum_usermarksread is set off forum_tp_mark_posts_read($userto, $userto->markposts); } } } } /// We have finishied all digest emails, update $CFG->digestmailtimelast set_config('digestmailtimelast', $timenow); } $USER = $cronuser; course_setup(SITEID); // reset cron user language, theme and timezone settings if (!empty($usermailcount)) { mtrace(get_string('digestsentusers', 'forum', $usermailcount)); } if (!empty($CFG->forum_lastreadclean)) { $timenow = time(); if ($CFG->forum_lastreadclean + 24 * 3600 < $timenow) { set_config('forum_lastreadclean', $timenow); mtrace('Removing old forum read tracking info...'); forum_tp_clean_read_records(); } } else { set_config('forum_lastreadclean', time()); } return true; }
function calendar_edit_event_allowed($event) { global $USER; // can not be using guest account if ($USER->username == "guest") { return false; } $sitecontext = get_context_instance(CONTEXT_SYSTEM, SITEID); // if user has manageentries at site level, return true if (has_capability('moodle/calendar:manageentries', $sitecontext)) { return true; } // if groupid is set, it's definitely a group event if ($event->groupid) { //TODO:check. if (!groups_group_exists($event->groupid)) { return false; } // this is ok because if you have this capability at course level, you should be able // to edit group calendar too // there is no need to check membership, because if you have this capability // you will have a role in this group context return has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_GROUP, $event->groupid)); } else { if ($event->courseid) { // if groupid is not set, but course is set, // it's definiely a course event return has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, $event->courseid)); } else { if ($event->userid && $event->userid == $USER->id) { // if course is not set, but userid id set, it's a user event return has_capability('moodle/calendar:manageownentries', $sitecontext); } } } return false; }
/** * Serves the forum attachments. Implements needed access control ;-) * * @param object $course * @param object $cm * @param object $context * @param string $filearea * @param array $args * @param bool $forcedownload * @return bool false if file not found, does not return if found - justsend the file */ function forum_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { global $CFG, $DB; if ($context->contextlevel != CONTEXT_MODULE) { return false; } require_course_login($course, true, $cm); $fileareas = array('attachment', 'post'); if (!in_array($filearea, $fileareas)) { return false; } $postid = (int)array_shift($args); if (!$post = $DB->get_record('forum_posts', array('id'=>$postid))) { return false; } if (!$discussion = $DB->get_record('forum_discussions', array('id'=>$post->discussion))) { return false; } if (!$forum = $DB->get_record('forum', array('id'=>$cm->instance))) { return false; } $fs = get_file_storage(); $relativepath = implode('/', $args); $fullpath = "/$context->id/mod_forum/$filearea/$postid/$relativepath"; if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { return false; } // Make sure groups allow this user to see this file if ($discussion->groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used if (!groups_group_exists($discussion->groupid)) { // Can't find group return false; // Be safe and don't send it to anyone } if (!groups_is_member($discussion->groupid) and !has_capability('moodle/site:accessallgroups', $context)) { // do not send posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS return false; } } // Make sure we're allowed to see it... if (!forum_user_can_see_post($forum, $discussion, $post, NULL, $cm)) { return false; } // finally send the file send_stored_file($file, 0, 0, true); // download MUST be forced - security! }
/** * Utility function for getting a subwiki by group and user, validating that the user can view it. * If the subwiki doesn't exists in DB yet it'll have id -1. * * @param stdClass $wiki The wiki. * @param int $groupid Group ID. 0 means the subwiki doesn't use groups. * @param int $userid User ID. 0 means the subwiki doesn't use users. * @return stdClass Subwiki. If it doesn't exists in DB yet it'll have id -1. If the user can't view the * subwiki this function will return false. * @since Moodle 3.1 * @throws moodle_exception */ function wiki_get_subwiki_by_group_and_user_with_validation($wiki, $groupid, $userid) { global $USER, $DB; // Get subwiki based on group and user. if (!($subwiki = wiki_get_subwiki_by_group($wiki->id, $groupid, $userid))) { // The subwiki doesn't exist. // Validate if user is valid. if ($userid != 0) { $user = core_user::get_user($userid, '*', MUST_EXIST); core_user::require_active_user($user); } // Validate that groupid is valid. if ($groupid != 0 && !groups_group_exists($groupid)) { throw new moodle_exception('cannotfindgroup', 'error'); } // Valid data but subwiki not found. We'll simulate a subwiki object to check if the user would be able to see it // if it existed. If he's able to see it then we'll return an empty array because the subwiki has no pages. $subwiki = new stdClass(); $subwiki->id = -1; $subwiki->wikiid = $wiki->id; $subwiki->userid = $userid; $subwiki->groupid = $groupid; } // Check that the user can view the subwiki. This function checks capabilities. if (!wiki_user_can_view($subwiki, $wiki)) { return false; } return $subwiki; }
/** * This function makes a role-assignment (a role for a user or group in a particular context) * @param $roleid - the role of the id * @param $userid - userid * @param $groupid - group id * @param $contextid - id of the context * @param $timestart - time this assignment becomes effective * @param $timeend - time this assignemnt ceases to be effective * @uses $USER * @return id - new id of the assigment */ function role_assign($roleid, $userid, $groupid, $contextid, $timestart = 0, $timeend = 0, $hidden = 0, $enrol = 'manual', $timemodified = '') { global $USER, $CFG; debugging("Assign roleid {$roleid} userid {$userid} contextid {$contextid}", DEBUG_DEVELOPER); /// Do some data validation if (empty($roleid)) { debugging('Role ID not provided'); return false; } if (empty($userid) && empty($groupid)) { debugging('Either userid or groupid must be provided'); return false; } if ($userid && !record_exists('user', 'id', $userid)) { debugging('User ID ' . intval($userid) . ' does not exist!'); return false; } if ($groupid && !groups_group_exists($groupid)) { debugging('Group ID ' . intval($groupid) . ' does not exist!'); return false; } if (!($context = get_context_instance_by_id($contextid))) { debugging('Context ID ' . intval($contextid) . ' does not exist!'); return false; } if ($timestart and $timeend and $timestart > $timeend) { debugging('The end time can not be earlier than the start time'); return false; } if (!$timemodified) { $timemodified = time(); } /// Check for existing entry if ($userid) { $ra = get_record('role_assignments', 'roleid', $roleid, 'contextid', $context->id, 'userid', $userid); } else { $ra = get_record('role_assignments', 'roleid', $roleid, 'contextid', $context->id, 'groupid', $groupid); } $newra = new object(); if (empty($ra)) { // Create a new entry $newra->roleid = $roleid; $newra->contextid = $context->id; $newra->userid = $userid; $newra->hidden = $hidden; $newra->enrol = $enrol; /// Always round timestart downto 100 secs to help DBs to use their own caching algorithms /// by repeating queries with the same exact parameters in a 100 secs time window $newra->timestart = round($timestart, -2); $newra->timeend = $timeend; $newra->timemodified = $timemodified; $newra->modifierid = empty($USER->id) ? 0 : $USER->id; $success = insert_record('role_assignments', $newra); } else { // We already have one, just update it $newra->id = $ra->id; $newra->hidden = $hidden; $newra->enrol = $enrol; /// Always round timestart downto 100 secs to help DBs to use their own caching algorithms /// by repeating queries with the same exact parameters in a 100 secs time window $newra->timestart = round($timestart, -2); $newra->timeend = $timeend; $newra->timemodified = $timemodified; $newra->modifierid = empty($USER->id) ? 0 : $USER->id; $success = update_record('role_assignments', $newra); } if ($success) { /// Role was assigned, so do some other things /// If the user is the current user, then reload the capabilities too. if (!empty($USER->id) && $USER->id == $userid) { load_all_capabilities(); } /// Ask all the modules if anything needs to be done for this user if ($mods = get_list_of_plugins('mod')) { foreach ($mods as $mod) { include_once $CFG->dirroot . '/mod/' . $mod . '/lib.php'; $functionname = $mod . '_role_assign'; if (function_exists($functionname)) { $functionname($userid, $context, $roleid); } } } } /// now handle metacourse role assignments if in course context if ($success and $context->contextlevel == CONTEXT_COURSE) { if ($parents = get_records('course_meta', 'child_course', $context->instanceid)) { foreach ($parents as $parent) { sync_metacourse($parent->parent_course); } } } return $success; }
function exercise_list_unassessed_student_submissions($exercise, $user) { // list the student submissions not assessed by the teacher global $CFG; $timenow = time(); if (!($course = get_record("course", "id", $exercise->course))) { error("Course is misconfigured"); } if (!($cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id))) { error("Course Module ID was incorrect"); } $table->head = array(get_string("title", "exercise"), get_string("submittedby", "exercise"), get_string("submitted", "exercise"), get_string("action", "exercise"), get_string("comment", "exercise")); $table->align = array("left", "left", "left", "left", "left"); $table->size = array("*", "*", "*", "*", "*"); $table->cellpadding = 2; $table->cellspacing = 0; // get all the submissions, oldest first, youngest last // exercise_get_student_submissions is group aware $groupid = get_current_group($course->id); if ($groupid) { if (!groups_group_exists($groupid)) { error("List unassessed student submissions: group not found"); } print_heading(get_string("studentsubmissionsforassessment", "exercise", $group->name)); } if ($submissions = exercise_get_student_submissions($exercise, "time", $groupid)) { foreach ($submissions as $submission) { // only consider "cold" submissions if ($submission->timecreated < $timenow - $CFG->maxeditingtime) { $comment = ""; // see if student has already submitted $submissionowner = get_record("user", "id", $submission->userid); if (exercise_count_user_submissions($exercise, $submissionowner) == 1) { // it's the student's first submission // see if there are no cold assessments for this submission if (!exercise_count_assessments($submission)) { // now see if the teacher has already assessed this submission $warm = false; if ($assessments = get_records("exercise_assessments", "submissionid", $submission->id)) { foreach ($assessments as $assessment) { if (isteacher($course->id, $assessment->userid)) { if ($assessment->timecreated > $timenow - $CFG->maxeditingtime) { $warm = true; } break; // no need to look further } } } // get their assessment if ($assessments = exercise_get_user_assessments($exercise, $submissionowner)) { foreach ($assessments as $assessment) { $studentassessment = $assessment; break; // there should only be one! } $timegap = get_string("ago", "exercise", format_time($submission->timecreated - $timenow)); if ($submission->late) { $timegap = "<font color=\"red\">" . $timegap . "</font>"; } if ($warm) { // last chance salon $action = "<a href=\"assessments.php?action=teacherassessment&id={$cm->id}&aid={$studentassessment->id}&sid={$submission->id}\">" . get_string("edit", "exercise") . "</a>"; $table->data[] = array(exercise_print_submission_title($exercise, $submission), fullname($submissionowner), $timegap, $action, $comment); } else { $action = "<a href=\"assessments.php?action=teacherassessment&id={$cm->id}&aid={$studentassessment->id}&sid={$submission->id}\">" . get_string("assess", "exercise") . "</a>"; $table->data[] = array(exercise_print_submission_title($exercise, $submission), fullname($submissionowner), $timegap, $action, $comment); } } else { // there's no student assessment, odd!! } } } else { $teacherassessed = false; $warm = false; if ($assessments = get_records("exercise_assessments", "submissionid", $submission->id)) { foreach ($assessments as $assessment) { if (isteacher($course->id, $assessment->userid)) { $teacherassessed = true; if (!($teacher = get_record("user", "id", $assessment->userid))) { error("List unassessed student submissions: teacher record not found"); } $comment = get_string("resubmissionfor", "exercise", fullname($teacher)); if ($assessment->timecreated > $timenow - $CFG->maxeditingtime) { $warm = true; } break; // no need to look further } } } if ($teacherassessed and $warm) { // last chance salon $action = "<a href=\"assessments.php?action=assessresubmission&id={$cm->id}&sid={$submission->id}\">" . get_string("edit", "exercise") . "</a>"; $timegap = get_string("ago", "exercise", format_time($submission->timecreated - $timenow)); if ($submission->late) { $timegap = "<font color=\"red\">" . $timegap . "</font>"; } $table->data[] = array(exercise_print_submission_title($exercise, $submission), fullname($submissionowner), $timegap, $action, $comment); } if (!$teacherassessed) { // no teacher's assessment // find who did the previous assessment if (!($submissions = exercise_get_user_submissions($exercise, $submissionowner))) { error("List unassessed student submissions: submission records not found"); } // get the oldest submission, exercise_get_user_submissions returns that first foreach ($submissions as $tempsubmission) { $prevsubmission = $tempsubmission; break; } // get the teacher's assessment of the student's previous submission if ($assessments = get_records("exercise_assessments", "submissionid", $prevsubmission->id)) { foreach ($assessments as $assessment) { if (isteacher($course->id, $assessment->userid)) { if (!($teacher = get_record("user", "id", $assessment->userid))) { error("List unassessed student submissions: teacher record not found"); } $comment = get_string("resubmissionfor", "exercise", fullname($teacher)); break; // no need to look further } } } $action = "<a href=\"assessments.php?action=assessresubmission&id={$cm->id}&sid={$submission->id}\">" . get_string("assess", "exercise") . "</a>"; $timegap = get_string("ago", "exercise", format_time($submission->timecreated - $timenow)); if ($submission->late) { $timegap = "<font color=\"red\">" . $timegap . "</font>"; } $table->data[] = array(exercise_print_submission_title($exercise, $submission), fullname($submissionowner), $timegap, $action, $comment); } } } } if (isset($table->data)) { print_table($table); } } }
if (!($cm = get_coursemodule_from_instance('chat', $chat->id, $course->id))) { error('Course Module ID was incorrect'); } require_login($course->id, false, $cm); if (isguest()) { error('Guest does not have access to chat rooms'); } if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_MODULE, $cm->id))) { print_header(); notice(get_string("activityiscurrentlyhidden")); } /// Check to see if groups are being used here if ($groupmode = groupmode($course, $cm)) { // Groups are being used if ($groupid = get_and_set_current_group($course, $groupmode, $groupid)) { if (!groups_group_exists($groupid)) { error("That group (id {$groupid}) doesn't exist!"); } $groupname = ': ' . $group->name; } else { $groupname = ': ' . get_string('allparticipants'); } } else { $groupid = 0; $groupname = ''; } $strchat = get_string('modulename', 'chat'); // must be before current_language() in chat_login_user() to force course language!!! if (!($chat_sid = chat_login_user($chat->id, 'sockets', $groupid, $course))) { error('Could not log in to chat room!!'); }
/** * */ public function validation($params) { global $DB, $USER; // Check the component is mod_dataform. if ($params['component'] != 'mod_dataform') { throw new rating_exception('invalidcomponent'); } $ownentry = $params['rateduserid'] == $USER->id; if ($ownentry) { // You can't rate your own entries unless you have the capability. if (!has_capability('dataformfield/ratingmdl:ownrate', $params['context'])) { throw new rating_exception('nopermissiontorate'); } } else { // You can't rate other entries unless you have the capability. if (!has_capability('dataformfield/ratingmdl:anyrate', $params['context'])) { throw new rating_exception('nopermissiontorate'); } } // If the supplied context doesnt match the item's context. if ($params['context']->id != $this->df->context->id) { throw new rating_exception('invalidcontext'); } // Check the ratingarea is entry or activity. if ($params['ratingarea'] != $this->name) { throw new rating_exception('invalidratingarea'); } // Vaildate entry scale and rating range. if ($params['scaleid'] != $this->_scaleid) { throw new rating_exception('invalidscaleid'); } // Upper limit. if ($this->_scaleid < 0) { // Its a custom scale. $scalerecord = $DB->get_record('scale', array('id' => -$this->_scaleid)); if ($scalerecord) { $scalearray = explode(',', $scalerecord->scale); if ($params['rating'] > count($scalearray)) { throw new rating_exception('invalidnum'); } } else { throw new rating_exception('invalidscaleid'); } } else { if ($params['rating'] > $this->_scaleid) { // If its numeric and submitted rating is above maximum. throw new rating_exception('invalidnum'); } } // Lower limit. if ($params['rating'] < 0 and $params['rating'] != RATING_UNSET_RATING) { throw new rating_exception('invalidnum'); } // Make sure groups allow this user to see the item they're rating. $groupid = $this->df->currentgroup; if ($groupid > 0 and $groupmode = groups_get_activity_groupmode($this->df->cm, $this->df->course)) { // Groups are being used. if (!groups_group_exists($groupid)) { // Can't find group. throw new rating_exception('cannotfindgroup'); } if (!groups_is_member($groupid) and !has_capability('moodle/site:accessallgroups', $this->df->context)) { // Do not allow rating of posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS. throw new rating_exception('notmemberofgroup'); } } return true; }
/** * Returns the list of pages from a specific subwiki. * * @param int $wikiid The wiki instance ID. * @param int $groupid The group ID. If not defined, use current group. * @param int $userid The user ID. If not defined, use current user. * @param array $options Several options like sort by, sort direction, ... * @return array Containing a list of warnings and a list of pages. * @since Moodle 3.1 */ public static function get_subwiki_pages($wikiid, $groupid = -1, $userid = 0, $options = array()) { global $USER, $DB; $returnedpages = array(); $warnings = array(); $params = self::validate_parameters(self::get_subwiki_pages_parameters(), array('wikiid' => $wikiid, 'groupid' => $groupid, 'userid' => $userid, 'options' => $options)); // Get wiki instance. if (!($wiki = wiki_get_wiki($params['wikiid']))) { throw new moodle_exception('incorrectwikiid', 'wiki'); } list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki'); $context = context_module::instance($cm->id); self::validate_context($context); // Determine group. $groupmode = groups_get_activity_groupmode($cm); if ($groupmode == NOGROUPS) { $groupid = 0; } else { if ($params['groupid'] == -1) { // Use current group. $groupid = groups_get_activity_group($cm); $groupid = !empty($groupid) ? $groupid : 0; } else { $groupid = $params['groupid']; } } // Determine user. if ($wiki->wikimode == 'collaborative') { // Collaborative wikis don't use userid in subwikis. $userid = 0; } else { if (empty($params['userid'])) { // Use current user. $userid = $USER->id; } else { $userid = $params['userid']; } } // Get subwiki based on group and user. if (!($subwiki = wiki_get_subwiki_by_group($cm->instance, $groupid, $userid))) { // The subwiki doesn't exist. // Validate if user is valid. if ($userid != 0 && $userid != $USER->id && !($user = $DB->get_record('user', array('id' => $userid)))) { throw new moodle_exception('invaliduserid', 'error'); } // Validate that groupid is valid. if ($groupid != 0 && !groups_group_exists($groupid)) { throw new moodle_exception('cannotfindgroup', 'error'); } // Valid data but subwiki not found. We'll simulate a subwiki object to check if the user would be able to see it // if it existed. If he's able to see it then we'll return an empty array because the subwiki has no pages. $subwiki = new stdClass(); $subwiki->wikiid = $wiki->id; $subwiki->userid = $userid; $subwiki->groupid = $groupid; // Check that the user can view the subwiki. This function checks capabilities. if (!wiki_user_can_view($subwiki, $wiki)) { throw new moodle_exception('cannotviewpage', 'wiki'); } } else { // Check that the user can view the subwiki. This function checks capabilities. if (!wiki_user_can_view($subwiki, $wiki)) { throw new moodle_exception('cannotviewpage', 'wiki'); } // Set sort param. $options = $params['options']; if (!empty($options['sortby'])) { if ($options['sortdirection'] != 'ASC' && $options['sortdirection'] != 'DESC') { // Invalid sort direction. Use default. $options['sortdirection'] = 'ASC'; } $sort = $options['sortby'] . ' ' . $options['sortdirection']; } $pages = wiki_get_page_list($subwiki->id, $sort); $caneditpages = wiki_user_can_edit($subwiki); $firstpage = wiki_get_first_page($subwiki->id); foreach ($pages as $page) { $retpage = array('id' => $page->id, 'subwikiid' => $page->subwikiid, 'title' => external_format_string($page->title, $context->id), 'timecreated' => $page->timecreated, 'timemodified' => $page->timemodified, 'timerendered' => $page->timerendered, 'userid' => $page->userid, 'pageviews' => $page->pageviews, 'readonly' => $page->readonly, 'caneditpage' => $caneditpages, 'firstpage' => $page->id == $firstpage->id); if ($options['includecontent']) { // Refresh page cached content if needed. if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) { if ($content = wiki_refresh_cachedcontent($page)) { $page = $content['page']; } } list($retpage['cachedcontent'], $retpage['contentformat']) = external_format_text($page->cachedcontent, FORMAT_HTML, $context->id, 'mod_wiki', 'attachments', $subwiki->id); } $returnedpages[] = $retpage; } } $result = array(); $result['pages'] = $returnedpages; $result['warnings'] = $warnings; return $result; }
/** * This function makes a role-assignment (a role for a user or group in a particular context) * @param $roleid - the role of the id * @param $userid - userid * @param $groupid - group id * @param $contextid - id of the context * @param $timestart - time this assignment becomes effective * @param $timeend - time this assignemnt ceases to be effective * @uses $USER * @return id - new id of the assigment */ function role_assign($roleid, $userid, $groupid, $contextid, $timestart = 0, $timeend = 0, $hidden = 0, $enrol = 'manual', $timemodified = '') { global $USER, $CFG, $DB; /// Do some data validation if (empty($roleid)) { debugging('Role ID not provided'); return false; } if (empty($userid) && empty($groupid)) { debugging('Either userid or groupid must be provided'); return false; } if ($userid && !$DB->record_exists('user', array('id' => $userid))) { debugging('User ID ' . intval($userid) . ' does not exist!'); return false; } if ($groupid && !groups_group_exists($groupid)) { debugging('Group ID ' . intval($groupid) . ' does not exist!'); return false; } if (!($context = get_context_instance_by_id($contextid))) { debugging('Context ID ' . intval($contextid) . ' does not exist!'); return false; } if ($timestart and $timeend and $timestart > $timeend) { debugging('The end time can not be earlier than the start time'); return false; } if (!$timemodified) { $timemodified = time(); } /// Check for existing entry if ($userid) { $ra = $DB->get_record('role_assignments', array('roleid' => $roleid, 'contextid' => $context->id, 'userid' => $userid)); } else { $ra = $DB->get_record('role_assignments', array('roleid' => $roleid, 'contextid' => $context->id, 'groupid' => $groupid)); } if (empty($ra)) { // Create a new entry $ra = new object(); $ra->roleid = $roleid; $ra->contextid = $context->id; $ra->userid = $userid; $ra->hidden = $hidden; $ra->enrol = $enrol; /// Always round timestart downto 100 secs to help DBs to use their own caching algorithms /// by repeating queries with the same exact parameters in a 100 secs time window $ra->timestart = round($timestart, -2); $ra->timeend = $timeend; $ra->timemodified = $timemodified; $ra->modifierid = empty($USER->id) ? 0 : $USER->id; if (!($ra->id = $DB->insert_record('role_assignments', $ra))) { return false; } } else { // We already have one, just update it $ra->id = $ra->id; $ra->hidden = $hidden; $ra->enrol = $enrol; /// Always round timestart downto 100 secs to help DBs to use their own caching algorithms /// by repeating queries with the same exact parameters in a 100 secs time window $ra->timestart = round($timestart, -2); $ra->timeend = $timeend; $ra->timemodified = $timemodified; $ra->modifierid = empty($USER->id) ? 0 : $USER->id; if (!$DB->update_record('role_assignments', $ra)) { return false; } } /// mark context as dirty - modules might use has_capability() in xxx_role_assing() /// again expensive, but needed mark_context_dirty($context->path); if (!empty($USER->id) && $USER->id == $userid) { /// If the user is the current user, then do full reload of capabilities too. load_all_capabilities(); } /// Ask all the modules if anything needs to be done for this user if ($mods = get_list_of_plugins('mod')) { foreach ($mods as $mod) { include_once $CFG->dirroot . '/mod/' . $mod . '/lib.php'; $functionname = $mod . '_role_assign'; if (function_exists($functionname)) { $functionname($userid, $context, $roleid); } } } /// now handle metacourse role assignments if in course context if ($context->contextlevel == CONTEXT_COURSE) { if ($parents = $DB->get_records('course_meta', array('child_course' => $context->instanceid))) { foreach ($parents as $parent) { sync_metacourse($parent->parent_course); } } } events_trigger('role_assigned', $ra); return $ra->id; }
/** * File browsing support for ouwiki module. * @param object $browser * @param object $areas * @param object $course * @param object $cm * @param object $context * @param string $filearea * @param int $itemid * @param string $filepath * @param string $filename * @return file_info instance Representing an actual file or folder (null if not found * or cannot access) */ function ouwiki_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { global $CFG, $DB, $USER; if ($context->contextlevel != CONTEXT_MODULE) { return null; } $fileareas = array('attachment', 'content'); if (!in_array($filearea, $fileareas)) { return null; } if (!has_capability('mod/ouwiki:view', $context)) { return null; } if (!($pageid = $DB->get_field('ouwiki_versions', 'pageid', array('id' => $itemid), IGNORE_MISSING))) { return null; } if (!($subwikiid = $DB->get_field('ouwiki_pages', 'subwikiid', array('id' => $pageid), IGNORE_MISSING))) { return null; } $groupid = $DB->get_field('ouwiki_subwikis', 'groupid', array('id' => $subwikiid), IGNORE_MISSING); // Make sure groups allow this user to see this file if ($groupid) { if (groups_get_activity_groupmode($cm, $course) == SEPARATEGROUPS) { // Groups are being used if (!groups_group_exists($groupid)) { // Can't find group return null; } if (!has_capability('moodle/site:accessallgroups', $context) && !groups_is_member($groupid)) { return null; } } } $userid = $DB->get_field('ouwiki_subwikis', 'userid', array('id' => $subwikiid), IGNORE_MISSING); if ($userid) { if ($userid != $USER->id && !has_capability('mod/ouwiki:viewallindividuals', $context)) { if (has_capability('mod/ouwiki:viewgroupindividuals', $context)) { $params = array($course->id, $userid, $USER->id); $query = "\n FROM\n {groups} gp\n INNER JOIN {groups_members} gm ON gp.id = gm.groupid\n INNER JOIN {groups_members} gms ON gp.id = gms.groupid\n WHERE\n gp.courseid = ? AND gm.userid = ? AND gms.userid = ?"; $count = $DB->count_records_sql("SELECT COUNT(1) {$query}", $params); if ($count == 0) { return null; } } else { return null; } } } $fs = get_file_storage(); $filepath = is_null($filepath) ? '/' : $filepath; $filename = is_null($filename) ? '.' : $filename; if (!($storedfile = $fs->get_file($context->id, 'mod_ouwiki', $filearea, $itemid, $filepath, $filename))) { return null; } $urlbase = $CFG->wwwroot . '/pluginfile.php'; return new file_info_stored($browser, $context, $storedfile, $urlbase, $filearea, $itemid, true, true, false); }
/** * Validates a submitted rating * @param array $params submitted data * context => object the context in which the rated items exists [required] * itemid => int the ID of the object being rated * scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required] * rating => int the submitted rating * rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required] * aggregation => int the aggregation method to apply when calculating grades ie RATING_AGGREGATE_AVERAGE [required] * @return boolean true if the rating is valid. Will throw rating_exception if not */ function data_rating_validate($params) { global $DB, $USER; // Check the component is mod_data if ($params['component'] != 'mod_data') { throw new rating_exception('invalidcomponent'); } // Check the ratingarea is entry (the only rating area in data module) if ($params['ratingarea'] != 'entry') { throw new rating_exception('invalidratingarea'); } // Check the rateduserid is not the current user .. you can't rate your own entries if ($params['rateduserid'] == $USER->id) { throw new rating_exception('nopermissiontorate'); } $datasql = "SELECT d.id as dataid, d.scale, d.course, r.userid as userid, d.approval, r.approved, r.timecreated, d.assesstimestart, d.assesstimefinish, r.groupid FROM {data_records} r JOIN {data} d ON r.dataid = d.id WHERE r.id = :itemid"; $dataparams = array('itemid'=>$params['itemid']); if (!$info = $DB->get_record_sql($datasql, $dataparams)) { //item doesn't exist throw new rating_exception('invaliditemid'); } if ($info->scale != $params['scaleid']) { //the scale being submitted doesnt match the one in the database throw new rating_exception('invalidscaleid'); } //check that the submitted rating is valid for the scale // lower limit if ($params['rating'] < 0 && $params['rating'] != RATING_UNSET_RATING) { throw new rating_exception('invalidnum'); } // upper limit if ($info->scale < 0) { //its a custom scale $scalerecord = $DB->get_record('scale', array('id' => -$info->scale)); if ($scalerecord) { $scalearray = explode(',', $scalerecord->scale); if ($params['rating'] > count($scalearray)) { throw new rating_exception('invalidnum'); } } else { throw new rating_exception('invalidscaleid'); } } else if ($params['rating'] > $info->scale) { //if its numeric and submitted rating is above maximum throw new rating_exception('invalidnum'); } if ($info->approval && !$info->approved) { //database requires approval but this item isnt approved throw new rating_exception('nopermissiontorate'); } // check the item we're rating was created in the assessable time window if (!empty($info->assesstimestart) && !empty($info->assesstimefinish)) { if ($info->timecreated < $info->assesstimestart || $info->timecreated > $info->assesstimefinish) { throw new rating_exception('notavailable'); } } $course = $DB->get_record('course', array('id'=>$info->course), '*', MUST_EXIST); $cm = get_coursemodule_from_instance('data', $info->dataid, $course->id, false, MUST_EXIST); $context = get_context_instance(CONTEXT_MODULE, $cm->id, MUST_EXIST); // if the supplied context doesnt match the item's context if ($context->id != $params['context']->id) { throw new rating_exception('invalidcontext'); } // Make sure groups allow this user to see the item they're rating $groupid = $info->groupid; if ($groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used if (!groups_group_exists($groupid)) { // Can't find group throw new rating_exception('cannotfindgroup');//something is wrong } if (!groups_is_member($groupid) and !has_capability('moodle/site:accessallgroups', $context)) { // do not allow rating of posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS throw new rating_exception('notmemberofgroup'); } } return true; }
/** * Removes all users from the specified group. * @param int $groupid The ID of the group. * @return boolean True for success, false otherwise. */ function groups_remove_all_members($groupid) { if (!groups_group_exists($groupid)) { //Woops, delete group last! return false; } $userids = groups_get_members($groupid); if (!$userids) { return false; } $success = true; foreach ($userids as $id) { $success = $success && groups_db_remove_member($groupid, $id); } $success = $success && groups_db_set_group_modified($groupid); return $success; }
/** * Validates a submitted rating * @param array $params submitted data * context => object the context in which the rated items exists [required] * component => The component for this module - should always be mod_forum [required] * ratingarea => object the context in which the rated items exists [required] * itemid => int the ID of the object being rated [required] * scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required] * rating => int the submitted rating [required] * rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required] * aggregation => int the aggregation method to apply when calculating grades ie RATING_AGGREGATE_AVERAGE [required] * @return boolean true if the rating is valid. Will throw rating_exception if not */ function forum_rating_validate($params) { global $DB, $USER; // Check the component is mod_forum if ($params['component'] != 'mod_forum') { throw new rating_exception('invalidcomponent'); } // Check the ratingarea is post (the only rating area in forum) if ($params['ratingarea'] != 'post') { throw new rating_exception('invalidratingarea'); } // Check the rateduserid is not the current user .. you can't rate your own posts if ($params['rateduserid'] == $USER->id) { throw new rating_exception('nopermissiontorate'); } // Fetch all the related records ... we need to do this anyway to call forum_user_can_see_post $post = $DB->get_record('forum_posts', array('id' => $params['itemid'], 'userid' => $params['rateduserid']), '*', MUST_EXIST); $discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion), '*', MUST_EXIST); $forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST); $course = $DB->get_record('course', array('id' => $forum->course), '*', MUST_EXIST); $cm = get_coursemodule_from_instance('forum', $forum->id, $course->id , false, MUST_EXIST); $context = context_module::instance($cm->id); // Make sure the context provided is the context of the forum if ($context->id != $params['context']->id) { throw new rating_exception('invalidcontext'); } if ($forum->scale != $params['scaleid']) { //the scale being submitted doesnt match the one in the database throw new rating_exception('invalidscaleid'); } // check the item we're rating was created in the assessable time window if (!empty($forum->assesstimestart) && !empty($forum->assesstimefinish)) { if ($post->created < $forum->assesstimestart || $post->created > $forum->assesstimefinish) { throw new rating_exception('notavailable'); } } //check that the submitted rating is valid for the scale // lower limit if ($params['rating'] < 0 && $params['rating'] != RATING_UNSET_RATING) { throw new rating_exception('invalidnum'); } // upper limit if ($forum->scale < 0) { //its a custom scale $scalerecord = $DB->get_record('scale', array('id' => -$forum->scale)); if ($scalerecord) { $scalearray = explode(',', $scalerecord->scale); if ($params['rating'] > count($scalearray)) { throw new rating_exception('invalidnum'); } } else { throw new rating_exception('invalidscaleid'); } } else if ($params['rating'] > $forum->scale) { //if its numeric and submitted rating is above maximum throw new rating_exception('invalidnum'); } // Make sure groups allow this user to see the item they're rating if ($discussion->groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used if (!groups_group_exists($discussion->groupid)) { // Can't find group throw new rating_exception('cannotfindgroup');//something is wrong } if (!groups_is_member($discussion->groupid) and !has_capability('moodle/site:accessallgroups', $context)) { // do not allow rating of posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS throw new rating_exception('notmemberofgroup'); } } // perform some final capability checks if (!forum_user_can_see_post($forum, $discussion, $post, $USER, $cm)) { throw new rating_exception('nopermissiontorate'); } return true; }
function test_delete_group() { $this->assertTrue(groups_delete_group($this->groupid)); $this->assertFalse(groups_group_exists($this->groupid)); }