Merge branch 'wip-MDL-28615-master-squashed' of git://github.com/samhemelryk/moodle

This commit is contained in:
Aparup Banerjee 2011-10-05 10:54:05 +08:00
commit 73f5ebea0c
5 changed files with 741 additions and 192 deletions

View File

@ -228,11 +228,35 @@ function enrol_check_plugins($user) {
* The courses has to be visible and enrolments has to be active,
* timestart and timeend restrictions are ignored.
*
* This function calls {@see enrol_get_shared_courses()} setting checkexistsonly
* to true.
*
* @param stdClass|int $user1
* @param stdClass|int $user2
* @return bool
*/
function enrol_sharing_course($user1, $user2) {
return enrol_get_shared_courses($user1, $user2, false, true);
}
/**
* Returns any courses shared by the two users
*
* The courses has to be visible and enrolments has to be active,
* timestart and timeend restrictions are ignored.
*
* @global moodle_database $DB
* @param stdClass|int $user1
* @param stdClass|int $user2
* @param bool $preloadcontexts If set to true contexts for the returned courses
* will be preloaded.
* @param bool $checkexistsonly If set to true then this function will return true
* if the users share any courses and false if not.
* @return array|bool An array of courses that both users are enrolled in OR if
* $checkexistsonly set returns true if the users share any courses
* and false if not.
*/
function enrol_get_shared_courses($user1, $user2, $preloadcontexts = false, $checkexistsonly = false) {
global $DB, $CFG;
$user1 = !empty($user1->id) ? $user1->id : $user1;
@ -253,14 +277,33 @@ function enrol_sharing_course($user1, $user2) {
$params['user1'] = $user1;
$params['user2'] = $user2;
$sql = "SELECT DISTINCT 'x'
FROM {enrol} e
JOIN {user_enrolments} ue1 ON (ue1.enrolid = e.id AND ue1.status = :active1 AND ue1.userid = :user1)
JOIN {user_enrolments} ue2 ON (ue2.enrolid = e.id AND ue2.status = :active2 AND ue2.userid = :user2)
JOIN {course} c ON (c.id = e.courseid AND c.visible = 1)
WHERE e.status = :enabled AND e.enrol $plugins";
$ctxselect = '';
$ctxjoin = '';
if ($preloadcontexts) {
list($ctxselect, $ctxjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
}
return $DB->record_exists_sql($sql, $params);
$sql = "SELECT c.* $ctxselect
FROM {course} c
JOIN (
SELECT DISTINCT c.id
FROM {enrol} e
JOIN {user_enrolments} ue1 ON (ue1.enrolid = e.id AND ue1.status = :active1 AND ue1.userid = :user1)
JOIN {user_enrolments} ue2 ON (ue2.enrolid = e.id AND ue2.status = :active2 AND ue2.userid = :user2)
JOIN {course} c ON (c.id = e.courseid AND c.visible = 1)
WHERE e.status = :enabled AND e.enrol $plugins
) ec ON ec.id = c.id
$ctxjoin";
if ($checkexistsonly) {
return $DB->record_exists_sql($sql, $params);
} else {
$courses = $DB->get_records_sql($sql, $params);
if ($preloadcontexts) {
array_map('context_instance_preload', $courses);
}
return $courses;
}
}
/**
@ -1566,4 +1609,4 @@ abstract class enrol_plugin {
public function get_bulk_operations() {
return array();
}
}
}

View File

@ -73,6 +73,7 @@ $string['cannottrack'] = 'Could not stop tracking that forum';
$string['cannotunsubscribe'] = 'Could not unsubscribe you from that forum';
$string['cannotupdatepost'] = 'You can not update this post';
$string['cannotviewpostyet'] = 'You cannot read other students questions in this discussion yet because you haven\'t posted';
$string['cannotviewusersposts'] = 'There are no posts made by this user that you are able to view.';
$string['cleanreadtime'] = 'Mark old posts as read hour';
$string['completiondiscussions'] = 'Student must create discussions:';
$string['completiondiscussionsgroup'] = 'Require discussions';
@ -122,6 +123,7 @@ $string['discussionname'] = 'Discussion name';
$string['discussions'] = 'Discussions';
$string['discussionsstartedby'] = 'Discussions started by {$a}';
$string['discussionsstartedbyrecent'] = 'Discussions recently started by {$a}';
$string['discussionsstartedbyuserincourse'] = 'Discussions started by {$a->fullname} in {$a->coursename}';
$string['discussthistopic'] = 'Discuss this topic';
$string['displayend'] = 'Display end';
$string['displayend_help'] = 'This setting specifies whether a forum post should be hidden after a certain date. Note that administrators can always view forum posts.';
@ -136,6 +138,7 @@ $string['editing'] = 'Editing';
$string['emptymessage'] = 'Something was wrong with your post. Perhaps you left it blank, or the attachment was too big. Your changes have NOT been saved.';
$string['erroremptymessage'] = 'Post message cannot be empty';
$string['erroremptysubject'] = 'Post subject cannot be empty.';
$string['errorenrolmentrequired'] = 'You must be enrolled in this course to access this content';
$string['errorwhiledelete'] = 'An error occurred while deleting record.';
$string['everyonecanchoose'] = 'Everyone can choose to be subscribed';
$string['everyonecannowchoose'] = 'Everyone can now choose to be subscribed';
@ -240,7 +243,8 @@ $string['nameteacher'] = 'Teacher forum';
$string['newforumposts'] = 'New forum posts';
$string['noattachments'] = 'There are no attachments to this post';
$string['nodiscussions'] = 'There are no discussion topics yet in this forum';
$string['nodiscussionsstartedby'] = 'No discussions started by this user';
$string['nodiscussionsstartedby'] = '{$a} has not started any discussions';
$string['nodiscussionsstartedbyyou'] = 'You haven\'t started any discussions yet';
$string['noguestpost'] = 'Sorry, guests are not allowed to post.';
$string['noguesttracking'] = 'Sorry, guests are not allowed to set tracking options.';
$string['nomorepostscontaining'] = 'No more posts containing \'{$a}\' were found';
@ -250,6 +254,8 @@ $string['nopermissiontosubscribe'] = 'You do not have the permission to view for
$string['nopermissiontoview'] = 'You do not have permissions to view this post';
$string['nopostforum'] = 'Sorry, you are not allowed to post to this forum';
$string['noposts'] = 'No posts';
$string['nopostsmadebyuser'] = '{$a} has made no posts';
$string['nopostsmadebyyou'] = 'You haven\'t made any posts';
$string['nopostscontaining'] = 'No posts containing \'{$a}\' were found';
$string['noquestions'] = 'There are no questions yet in this forum';
$string['nosubscribers'] = 'There are no subscribers yet for this forum';
@ -294,6 +300,8 @@ $string['postrating1'] = 'Mostly separate knowing';
$string['postrating2'] = 'Separate and connected';
$string['postrating3'] = 'Mostly connected knowing';
$string['posts'] = 'Posts';
$string['postsmadebyuser'] = 'Posts made by {$a}';
$string['postsmadebyuserincourse'] = 'Posts made by {$a->fullname} in {$a->coursename}';
$string['posttoforum'] = 'Post to forum';
$string['postupdated'] = 'Your post was updated';
$string['potentialsubscribers'] = 'Potential subscribers';

View File

@ -5071,15 +5071,9 @@ function forum_user_can_see_post($forum, $discussion, $post, $user=NULL, $cm=NUL
$user = $USER;
}
if (isset($cm->cache->caps['mod/forum:viewdiscussion'])) {
if (!$cm->cache->caps['mod/forum:viewdiscussion']) {
return false;
}
} else {
$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
if (!has_capability('mod/forum:viewdiscussion', $modcontext, $user->id)) {
return false;
}
$canviewdiscussion = !empty($cm->cache->caps['mod/forum:viewdiscussion']) || has_capability('mod/forum:viewdiscussion', get_context_instance(CONTEXT_MODULE, $cm->id), $user->id);
if (!$canviewdiscussion && !has_all_capabilities(array('moodle/user:viewdetails', 'moodle/user:readuserposts'), get_context_instance(CONTEXT_USER, $post->userid))) {
return false;
}
if (isset($cm->uservisible)) {
@ -7981,3 +7975,386 @@ function forum_page_type_list($pagetype, $parentcontext, $currentcontext) {
);
return $forum_pagetype;
}
/**
* Gets all of the courses where the provided user has posted in a forum.
*
* @global moodle_database $DB The database connection
* @param stdClass $user The user who's posts we are looking for
* @param bool $discussionsonly If true only look for discussions started by the user
* @param bool $includecontexts If set to trye contexts for the courses will be preloaded
* @param int $limitfrom The offset of records to return
* @param int $limitnum The number of records to return
* @return array An array of courses
*/
function forum_get_courses_user_posted_in($user, $discussionsonly = false, $includecontexts = true, $limitfrom = null, $limitnum = null) {
global $DB;
// If we are only after discussions we need only look at the forum_discussions
// table and join to the userid there. If we are looking for posts then we need
// to join to the forum_posts table.
if (!$discussionsonly) {
$joinsql = 'JOIN {forum_discussions} fd ON fd.course = c.id
JOIN {forum_posts} fp ON fp.discussion = fd.id';
$wheresql = 'fp.userid = :userid';
$params = array('userid' => $user->id);
} else {
$joinsql = 'JOIN {forum_discussions} fd ON fd.course = c.id';
$wheresql = 'fd.userid = :userid';
$params = array('userid' => $user->id);
}
// Join to the context table so that we can preload contexts if required.
if ($includecontexts) {
list($ctxselect, $ctxjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
} else {
$ctxselect = '';
$ctxjoin = '';
}
// Now we need to get all of the courses to search.
// All courses where the user has posted within a forum will be returned.
$sql = "SELECT DISTINCT c.* $ctxselect
FROM {course} c
$joinsql
$ctxjoin
WHERE $wheresql";
$courses = $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
if ($includecontexts) {
array_map('context_instance_preload', $courses);
}
return $courses;
}
/**
* Gets all of the forums a user has posted in for one or more courses.
*
* @global moodle_database $DB
* @param stdClass $user
* @param array $courseids An array of courseids to search or if not provided
* all courses the user has posted within
* @param bool $discussionsonly If true then only forums where the user has started
* a discussion will be returned.
* @param int $limitfrom The offset of records to return
* @param int $limitnum The number of records to return
* @return array An array of forums the user has posted within in the provided courses
*/
function forum_get_forums_user_posted_in($user, array $courseids = null, $discussionsonly = false, $limitfrom = null, $limitnum = null) {
global $DB;
$where = array("m.name = 'forum'");
$params = array();
if (!is_null($courseids)) {
list($coursewhere, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, 'courseid');
$where[] = 'f.course '.$coursewhere;
}
if (!$discussionsonly) {
$joinsql = 'JOIN {forum_discussions} fd ON fd.forum = f.id
JOIN {forum_posts} fp ON fp.discussion = fd.id';
$where[] = 'fp.userid = :userid';
} else {
$joinsql = 'JOIN {forum_discussions} fd ON fd.forum = f.id';
$where[] = 'fd.userid = :userid';
}
$params['userid'] = $user->id;
$wheresql = join(' AND ', $where);
$sql = "SELECT DISTINCT f.*, cm.id AS cmid
FROM {forum} f
JOIN {course_modules} cm ON cm.instance = f.id
JOIN {modules} m ON m.id = cm.module
$joinsql
WHERE $wheresql";
$courseforums = $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
return $courseforums;
}
/**
* Returns posts made by the selected user in the requested courses.
*
* This method can be used to return all of the posts made by the requested user
* within the given courses.
* For each course the access of the current user and requested user is checked
* and then for each post access to the post and forum is checked as well.
*
* This function is safe to use with usercapabilities.
*
* @global moodle_database $DB
* @param stdClass $user The user whose posts we want to get
* @param array $courses The courses to search
* @param bool $musthaveaccess If set to true errors will be thrown if the user
* cannot access one or more of the courses to search
* @param bool $discussionsonly If set to true only discussion starting posts
* will be returned.
* @param int $limitfrom The offset of records to return
* @param int $limitnum The number of records to return
* @return stdClass An object the following properties
* ->totalcount: the total number of posts made by the requested user
* that the current user can see.
* ->courses: An array of courses the current user can see that the
* requested user has posted in.
* ->forums: An array of forums relating to the posts returned in the
* property below.
* ->posts: An array containing the posts to show for this request.
*/
function forum_get_posts_by_user($user, array $courses, $musthaveaccess = false, $discussionsonly = false, $limitfrom = 0, $limitnum = 50) {
global $DB, $USER;
$return = new stdClass;
$return->totalcount = 0; // The total number of posts that the current user is able to view
$return->courses = array(); // The courses the current user can access
$return->forums = array(); // The forums that the current user can access that contain posts
$return->posts = array(); // The posts to display
// First up a small sanity check. If there are no courses to check we can
// return immediately, there is obviously nothing to search.
if (empty($courses)) {
return $return;
}
// A couple of quick setups
$isloggedin = isloggedin();
$isguestuser = $isloggedin && isguestuser();
$iscurrentuser = $isloggedin && $USER->id == $user->id;
// Checkout whether or not the current user has capabilities over the requested
// user and if so they have the capabilities required to view the requested
// users content.
$usercontext = get_context_instance(CONTEXT_USER, $user->id, MUST_EXIST);
$hascapsonuser = !$iscurrentuser && $DB->record_exists('role_assignments', array('userid' => $USER->id, 'contextid' => $usercontext->id));
$hascapsonuser = $hascapsonuser && has_all_capabilities(array('moodle/user:viewdetails', 'moodle/user:readuserposts'), $usercontext);
// Before we actually search each course we need to check the user's access to the
// course. If the user doesn't have the appropraite access then we either throw an
// error if a particular course was requested or we just skip over the course.
foreach ($courses as $course) {
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id, MUST_EXIST);
if ($iscurrentuser || $hascapsonuser) {
// If it is the current user, or the current user has capabilities to the
// requested user then all we need to do is check the requested users
// current access to the course.
// Note: There is no need to check group access or anything of the like
// as either the current user is the requested user, or has granted
// capabilities on the requested user. Either way they can see what the
// requested user posted, although its VERY unlikely in the `parent` situation
// that the current user will be able to view the posts in context.
if (!is_viewing($coursecontext, $user) && !is_enrolled($coursecontext, $user)) {
// Need to have full access to a course to see the rest of own info
if ($musthaveaccess) {
print_error('errorenrolmentrequired', 'forum');
}
continue;
}
} else {
// Check whether the current user is enrolled or has access to view the course
// if they don't we immediately have a problem.
if (!can_access_course($coursecontext)) {
if ($musthaveaccess) {
print_error('errorenrolmentrequired', 'forum');
}
continue;
}
// Check whether the requested user is enrolled or has access to view the course
// if they don't we immediately have a problem.
if (!can_access_course($coursecontext, $user)) {
if ($musthaveaccess) {
print_error('notenrolled', 'forum');
}
continue;
}
// If groups are in use and enforced throughout the course then make sure
// we can meet in at least one course level group.
// Note that we check if either the current user or the requested user have
// the capability to access all groups. This is because with that capability
// a user in group A could post in the group B forum. Grrrr.
if (groups_get_course_groupmode($course) == SEPARATEGROUPS && $course->groupmodeforce
&& !has_capability('moodle/site:accessallgroups', $coursecontext) && !has_capability('moodle/site:accessallgroups', $coursecontext, $user->id)) {
// If its the guest user to bad... the guest user cannot access groups
if (!$isloggedin or $isguestuser) {
// do not use require_login() here because we might have already used require_login($course)
if ($musthaveaccess) {
redirect(get_login_url());
}
continue;
}
// Get the groups of the current user
$mygroups = array_keys(groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid, 'g.id, g.name'));
// Get the groups the requested user is a member of
$usergroups = array_keys(groups_get_all_groups($course->id, $user->id, $course->defaultgroupingid, 'g.id, g.name'));
// Check whether they are members of the same group. If they are great.
$intersect = array_intersect($mygroups, $usergroups);
if (empty($intersect)) {
// But they're not... if it was a specific course throw an error otherwise
// just skip this course so that it is not searched.
if ($musthaveaccess) {
print_error("groupnotamember", '', $CFG->wwwroot."/course/view.php?id=$course->id");
}
continue;
}
}
}
// Woo hoo we got this far which means the current user can search this
// this course for the requested user. Although this is only the course accessibility
// handling that is complete, the forum accessibility tests are yet to come.
$return->courses[$course->id] = $course;
}
// No longer beed $courses array - lose it not it may be big
unset($courses);
// Make sure that we have some courses to search
if (empty($return->courses)) {
// If we don't have any courses to search then the reality is that the current
// user doesn't have access to any courses is which the requested user has posted.
// Although we do know at this point that the requested user has posts.
if ($musthaveaccess) {
print_error('permissiondenied');
} else {
return $return;
}
}
// Next step: Collect all of the forums that we will want to search.
// It is important to note that this step isn't actually about searching, it is
// about determining which forums we can search by testing accessibility.
$forums = forum_get_forums_user_posted_in($user, array_keys($return->courses), $discussionsonly);
// Will be used to build the where conditions for the search
$forumsearchwhere = array();
// Will be used to store the where condition params for the search
$forumsearchparams = array();
// Will record forums where the user can freely access everything
$forumsearchfullaccess = array();
// DB caching friendly
$now = round(time(), -2);
// For each course to search we want to find the forums the user has posted in
// and providing the current user can access the forum create a search condition
// for the forum to get the requested users posts.
foreach ($return->courses as $course) {
// Now we need to get the forums
$modinfo = get_fast_modinfo($course);
if (empty($modinfo->instances['forum'])) {
// hmmm, no forums? well at least its easy... skip!
continue;
}
// Iterate
foreach ($modinfo->get_instances_of('forum') as $forumid => $cm) {
if (!$cm->uservisible or !isset($forums[$forumid])) {
continue;
}
// Get the forum in question
$forum = $forums[$forumid];
// This is needed for functionality later on in the forum code....
$forum->cm = $cm;
// Check that either the current user can view the forum, or that the
// current user has capabilities over the requested user and the requested
// user can view the discussion
if (!has_capability('mod/forum:viewdiscussion', $cm->context) && !($hascapsonuser && has_capability('mod/forum:viewdiscussion', $cm->context, $user->id))) {
continue;
}
// This will contain forum specific where clauses
$forumsearchselect = array();
if (!$iscurrentuser && !$hascapsonuser) {
// Make sure we check group access
if (groups_get_activity_groupmode($cm, $course) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $cm->context)) {
$groups = $modinfo->get_groups($cm->groupingid);
$groups[] = -1;
list($groupid_sql, $groupid_params) = $DB->get_in_or_equal($groups, SQL_PARAMS_NAMED, 'grps'.$forumid.'_');
$forumsearchparams = array_merge($forumsearchparams, $groupid_params);
$forumsearchselect[] = "d.groupid $groupid_sql";
}
// hidden timed discussions
if (!empty($CFG->forum_enabletimedposts) && !has_capability('mod/forum:viewhiddentimedposts', $cm->context)) {
$forumsearchselect[] = "(d.userid = :userid{$forumid} OR (d.timestart < :timestart{$forumid} AND (d.timeend = 0 OR d.timeend > :timeend{$forumid})))";
$forumsearchparams['userid'.$forumid] = $user->id;
$forumsearchparams['timestart'.$forumid] = $now;
$forumsearchparams['timeend'.$forumid] = $now;
}
// qanda access
if ($forum->type == 'qanda' && !has_capability('mod/forum:viewqandawithoutposting', $cm->context)) {
// We need to check whether the user has posted in the qanda forum.
$discussionspostedin = forum_discussions_user_has_posted_in($forum->id, $user->id);
if (!empty($discussionspostedin)) {
$forumonlydiscussions = array(); // Holds discussion ids for the discussions the user is allowed to see in this forum.
foreach ($discussionspostedin as $d) {
$forumonlydiscussions[] = $d->id;
}
list($discussionid_sql, $discussionid_params) = $DB->get_in_or_equal($forumonlydiscussions, SQL_PARAMS_NAMED, 'qanda'.$forumid.'_');
$forumsearchparams = array_merge($forumsearchparams, $discussionid_params);
$forumsearchselect[] = "(d.id $discussionid_sql OR p.parent = 0)";
} else {
$forumsearchselect[] = "p.parent = 0";
}
}
if (count($forumsearchselect) > 0) {
$forumsearchwhere[] = "(d.forum = :forum{$forumid} AND ".implode(" AND ", $forumsearchselect).")";
$forumsearchparams['forum'.$forumid] = $forumid;
} else {
$forumsearchfullaccess[] = $forumid;
}
} else {
// The current user/parent can see all of their own posts
$forumsearchfullaccess[] = $forumid;
}
}
}
// If we dont have any search conditions, and we don't have any forums where
// the user has full access then we just return the default.
if (empty($forumsearchwhere) && empty($forumsearchfullaccess)) {
return $return;
}
// Prepare a where condition for the full access forums.
if (count($forumsearchfullaccess) > 0) {
list($fullidsql, $fullidparams) = $DB->get_in_or_equal($forumsearchfullaccess, SQL_PARAMS_NAMED, 'fula');
$forumsearchparams = array_merge($forumsearchparams, $fullidparams);
$forumsearchwhere[] = "(d.forum $fullidsql)";
}
// Prepare SQL to both count and search
$userfields = user_picture::fields('u', null, 'userid');
$countsql = 'SELECT COUNT(*) ';
$selectsql = 'SELECT p.*, d.forum, d.name AS discussionname, '.$userfields.' ';
$wheresql = implode(" OR ", $forumsearchwhere);
if ($discussionsonly) {
if ($wheresql == '') {
$wheresql = 'p.parent = 0';
} else {
$wheresql = 'p.parent = 0 AND ('.$wheresql.')';
}
}
$sql = "FROM {forum_posts} p
JOIN {forum_discussions} d ON d.id = p.discussion
JOIN {user} u ON u.id = p.userid
WHERE ($wheresql)
AND p.userid = :userid ";
$orderby = "ORDER BY p.modified DESC";
$forumsearchparams['userid'] = $user->id;
// Set the total number posts made by the requested user that the current user can see
$return->totalcount = $DB->count_records_sql($countsql.$sql, $forumsearchparams);
// Set the collection of posts that has been requested
$return->posts = $DB->get_records_sql($selectsql.$sql.$orderby, $forumsearchparams, $limitfrom, $limitnum);
// We need to build an array of forums for which posts will be displayed.
// We do this here to save the caller needing to retrieve them themselves before
// printing these forums posts. Given we have the forums already there is
// practically no overhead here.
foreach ($return->posts as $post) {
if (!array_key_exists($post->forum, $return->forums)) {
$return->forums[$post->forum] = $forums[$post->forum];
}
}
return $return;
}

View File

@ -23,194 +23,319 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../../config.php');
require_once('lib.php');
require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once($CFG->dirroot.'/mod/forum/lib.php');
require_once($CFG->dirroot.'/rating/lib.php');
// Course ID
$course = optional_param('course', SITEID, PARAM_INT);
// User ID
$id = optional_param('id', 0, PARAM_INT);
$mode = optional_param('mode', 'posts', PARAM_ALPHA);
$page = optional_param('page', 0, PARAM_INT);
$perpage = optional_param('perpage', 5, PARAM_INT);
$courseid = optional_param('course', null, PARAM_INT); // Limit the posts to just this course
$userid = optional_param('id', $USER->id, PARAM_INT); // User id whose posts we want to view
$mode = optional_param('mode', 'posts', PARAM_ALPHA); // The mode to use. Either posts or discussions
$page = optional_param('page', 0, PARAM_INT); // The page number to display
$perpage = optional_param('perpage', 5, PARAM_INT); // The number of posts to display per page
$url = new moodle_url('/mod/forum/user.php');
if ($course !== SITEID) {
$url->param('course', $course);
if (empty($userid)) {
if (!isloggedin()) {
require_login();
}
$userid = $USER->id;
}
if ($id !== 0) {
$url->param('id', $id);
$discussionsonly = ($mode !== 'posts');
$isspecificcourse = !is_null($courseid);
$iscurrentuser = ($USER->id == $userid);
$url = new moodle_url('/mod/forum/user.php', array('id' => $userid));
if ($isspecificcourse) {
$url->param('course', $courseid);
}
if ($mode !== 'posts') {
$url->param('mode', $mode);
if ($discussionsonly) {
$url->param('mode', 'discussions');
}
$PAGE->set_url($url);
$PAGE->set_pagelayout('standard');
if (empty($id)) { // See your own profile by default
require_login();
$id = $USER->id;
if ($page != 0) {
$url->param('page', $page);
}
if ($perpage != 5) {
$url->param('perpage', $perpage);
}
$user = $DB->get_record("user", array("id" => $id), '*', MUST_EXIST);
$course = $DB->get_record("course", array("id" => $course), '*', MUST_EXIST);
add_to_log(($isspecificcourse)?$courseid:SITEID, "forum", "user report", 'user.php?'.$url->get_query_string(), $userid);
$syscontext = get_context_instance(CONTEXT_SYSTEM);
$usercontext = get_context_instance(CONTEXT_USER, $id);
// do not force parents to enrol
if (!$DB->get_record('role_assignments', array('userid' => $USER->id, 'contextid' => $usercontext->id))) {
require_course_login($course);
} else {
$PAGE->set_course($course);
$user = $DB->get_record("user", array("id" => $userid), '*', MUST_EXIST);
$usercontext = get_context_instance(CONTEXT_USER, $user->id, MUST_EXIST);
// Check if the requested user is the guest user
if (isguestuser($user)) {
// The guest user cannot post, so it is not possible to view any posts.
// May as well just bail aggressively here.
print_error('invaliduserid');
}
// Make sure the user has not been deleted
if ($user->deleted) {
$PAGE->set_title(get_string('userdeleted'));
$PAGE->set_context(get_system_context());
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('userdeleted'));
echo $OUTPUT->heading($PAGE->title);
echo $OUTPUT->footer();
die;
}
add_to_log($course->id, "forum", "user report",
"user.php?course=$course->id&amp;id=$user->id&amp;mode=$mode", "$user->id");
$isloggedin = isloggedin();
$isguestuser = $isloggedin && isguestuser();
$isparent = !$iscurrentuser && $DB->record_exists('role_assignments', array('userid'=>$USER->id, 'contextid'=>$usercontext->id));
$hasparentaccess = $isparent && has_all_capabilities(array('moodle/user:viewdetails', 'moodle/user:readuserposts'), $usercontext);
$strforumposts = get_string('forumposts', 'forum');
$strparticipants = get_string('participants');
$strmode = get_string($mode, 'forum');
$fullname = fullname($user, has_capability('moodle/site:viewfullnames', $syscontext));
$link = null;
if (has_capability('moodle/course:viewparticipants', get_context_instance(CONTEXT_COURSE, $course->id)) || has_capability('moodle/site:viewparticipants', $syscontext)) {
$link = new moodle_url('/user/index.php',array('id'=>$course->id));
}
$PAGE->navigation->extend_for_user($user);
$PAGE->navigation->set_userid_for_parent_checks($id); // see MDL-25805 for reasons and for full commit reference for reversal when fixed.
$PAGE->set_title("$course->shortname: $fullname: $strmode");
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
echo $OUTPUT->heading($fullname);
switch ($mode) {
case 'posts' :
$searchterms = array('userid:'.$user->id);
$extrasql = '';
break;
default:
$searchterms = array('userid:'.$user->id);
$extrasql = 'AND p.parent = 0';
break;
}
echo '<div class="user-content">';
if ($course->id == SITEID) {
$searchcourse = SITEID;
if (empty($CFG->forceloginforprofiles) or (isloggedin() and !isguestuser() and !is_web_crawler())) {
// Search throughout the whole site.
$searchcourse = 0;
}
} else {
// Search only for posts the user made in this course.
$searchcourse = $course->id;
}
// Get the posts.
$posts = forum_search_posts($searchterms, $searchcourse, $page*$perpage, $perpage, $totalcount, $extrasql);
if ($posts) {
require_once($CFG->dirroot.'/rating/lib.php');
$baseurl = new moodle_url('user.php', array('id' => $user->id, 'course' => $course->id, 'mode' => $mode, 'perpage' => $perpage));
echo $OUTPUT->paging_bar($totalcount, $page, $perpage, $baseurl);
$discussions = array();
$forums = array();
//todo Rather than retrieving the ratings for each post individually it would be nice to do them in groups
//however this requires creating arrays of posts with each array containing all of the posts from a particular forum,
//retrieving the ratings then reassembling them all back into a single array sorted by post.modified (descending)
$rm = new rating_manager();
$ratingoptions = new stdClass;
$ratingoptions->component = 'mod_forum';
$ratingoptions->ratingarea = 'post';
foreach ($posts as $post) {
if (!isset($discussions[$post->discussion])) {
if (! $discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion))) {
print_error('invaliddiscussionid', 'forum');
}
$discussions[$post->discussion] = $discussion;
} else {
$discussion = $discussions[$post->discussion];
}
if (!isset($forums[$discussion->forum])) {
$forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST);
$forum->cm = get_coursemodule_from_instance('forum', $forum->id, 0, false, MUST_EXIST);
$forum->context = get_context_instance(CONTEXT_MODULE, $forum->cm->id);
$forums[$discussion->forum] = $forum;
} else {
$forum = $forums[$discussion->forum];
}
$forumurl = new moodle_url('/mod/forum/view.php', array('id' => $forum->cm->id));
$discussionurl = new moodle_url('/mod/forum/discuss.php', array('d' => $discussion->id));
// load ratings
if ($forum->assessed != RATING_AGGREGATE_NONE) {
$ratingoptions->context = $forum->context;
$ratingoptions->items = array($post);
$ratingoptions->aggregate = $forum->assessed;//the aggregation method
$ratingoptions->scaleid = $forum->scale;
$ratingoptions->userid = $user->id;
$ratingoptions->assesstimestart = $forum->assesstimestart;
$ratingoptions->assesstimefinish = $forum->assesstimefinish;
if ($forum->type == 'single' or !$discussion->id) {
$ratingoptions->returnurl = $forumurl;
} else {
$ratingoptions->returnurl = $discussionurl;
}
$updatedpost = $rm->get_ratings($ratingoptions);
//updating the array this way because we're iterating over a collection and updating them one by one
$posts[$updatedpost[0]->id] = $updatedpost[0];
}
$fullsubjects = array();
if ($course->id == SITEID && has_capability('moodle/site:config', $syscontext)) {
$postcoursename = $DB->get_field('course', 'shortname', array('id'=>$forum->course));
$courseurl = new moodle_url('/course/view.php', array('id' => $forum->course));
$fullsubjects[] = html_writer::link($courseurl, $postcoursename);
}
$fullsubjects[] = html_writer::link($forumurl, format_string($forum->name, true));
if ($forum->type != 'single') {
$fullsubjects[] .= html_writer::link($discussionurl, format_string($discussion->name, true));
if ($post->parent != 0) {
$parenturl = new moodle_url('/mod/forum/discuss.php', array('d' => $post->discussion, 'parent' => $post->id));
$fullsubjects[] .= html_writer::link($parenturl, format_string($post->subject, true));
}
}
$post->subject = join(' -> ', $fullsubjects);
$discussionurl->set_anchor('p'.$post->id);
$fulllink = html_writer::link($discussionurl, get_string("postincontext", "forum"));
forum_print_post($post, $discussion, $forum, $forum->cm, $course, false, false, false, $fulllink);
echo "<br />";
}
echo $OUTPUT->paging_bar($totalcount, $page, $perpage, $baseurl);
} else {
if ($mode == 'posts') {
echo $OUTPUT->heading(get_string('noposts', 'forum'));
// Check whether a specific course has been requested
if ($isspecificcourse) {
// Get the requested course and its context
$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
$coursecontext = get_context_instance(CONTEXT_COURSE, $courseid, MUST_EXIST);
// We have a specific course to search, which we will also assume we are within.
if ($hasparentaccess) {
// A `parent` role won't likely have access to the course so we won't attempt
// to enter it. We will however still make them jump through the normal
// login hoops
require_login();
$PAGE->set_context($coursecontext);
$PAGE->set_course($course);
} else {
echo $OUTPUT->heading(get_string('nodiscussionsstartedby', 'forum'));
// Enter the course we are searching
require_login($course);
}
}
echo '</div>';
echo $OUTPUT->footer();
// Get the course ready for access checks
$courses = array($courseid => $course);
} else {
// We are going to search for all of the users posts in all courses!
// a general require login here as we arn't actually within any course.
require_login();
$PAGE->set_context(get_system_context());
// Now we need to get all of the courses to search.
// All courses where the user has posted within a forum will be returned.
$courses = forum_get_courses_user_posted_in($user, $discussionsonly);
}
// Get the posts by the requested user that the current user can access.
$result = forum_get_posts_by_user($user, $courses, $isspecificcourse, $discussionsonly, ($page * $perpage), $perpage);
// Check whether there are not posts to display.
if (empty($result->posts)) {
// Ok no posts to display means that either the user has not posted or there
// are no posts made by the requested user that the current user is able to
// see.
// In either case we need to decide whether we can show personal information
// about the requested user to the current user so we will execute some checks
// First check the obvious, its the current user, a specific course has been
// provided (require_login has been called), or they have a course contact role.
// True to any of those and the current user can see the details of the
// requested user.
$canviewuser = ($iscurrentuser || $isspecificcourse || empty($CFG->forceloginforprofiles) || has_coursecontact_role($userid));
// Next we'll check the caps, if the current user has the view details and a
// specific course has been requested, or if they have the view all details
$canviewuser = ($canviewuser || ($isspecificcourse && has_capability('moodle/user:viewdetails', $coursecontext) || has_capability('moodle/user:viewalldetails', $usercontext)));
// If none of the above was true the next step is to check a shared relation
// through some course
if (!$canviewuser) {
// Get all of the courses that the users have in common
$sharedcourses = enrol_get_shared_courses($USER->id, $user->id, true);
foreach ($sharedcourses as $sharedcourse) {
// Check the view cap within the course context
if (has_capability('moodle/user:viewdetails', get_context_instance(CONTEXT_COURSE, $sharedcourse->id))) {
$canviewuser = true;
break;
}
}
unset($sharedcourses);
}
// Prepare the page title
$pagetitle = get_string('noposts', 'mod_forum');
// Get the page heading
if ($isspecificcourse) {
$pageheading = format_string($course->shortname, true, array('context' => $coursecontext));
} else {
$pageheading = get_string('pluginname', 'mod_forum');
}
// Next we need to set up the loading of the navigation and choose a message
// to display to the current user.
if ($iscurrentuser) {
// No need to extend the navigation it happens automatically for the
// current user.
if ($discussionsonly) {
$notification = get_string('nodiscussionsstartedbyyou', 'forum');
} else {
$notification = get_string('nopostsmadebyyou', 'forum');
}
} else if ($canviewuser) {
$PAGE->navigation->extend_for_user($user);
$PAGE->navigation->set_userid_for_parent_checks($user->id); // see MDL-25805 for reasons and for full commit reference for reversal when fixed.
$fullname = fullname($user);
if ($discussionsonly) {
$notification = get_string('nodiscussionsstartedby', 'forum', $fullname);
} else {
$notification = get_string('nopostsmadebyuser', 'forum', $fullname);
}
} else {
// Don't extend the navigation it would be giving out information that
// the current uesr doesn't have access to.
$notification = get_string('cannotviewusersposts', 'forum');
if ($isspecificcourse) {
$url = new moodle_url('/course/view.php', array('id' => $courseid));
} else {
$url = new moodle_url('/');
}
navigation_node::override_active_url($url);
}
// Display a page letting the user know that there's nothing to display;
$PAGE->set_title($pagetitle);
$PAGE->set_heading($pageheading);
echo $OUTPUT->header();
echo $OUTPUT->heading($pagetitle);
echo $OUTPUT->notification($notification);
if (!$url->compare($PAGE->url)) {
echo $OUTPUT->continue_button($url);
}
echo $OUTPUT->footer();
die;
}
// Post output will contain an entry containing HTML to display each post by the
// time we are done.
$postoutput = array();
$discussions = array();
foreach ($result->posts as $post) {
$discussions[] = $post->discussion;
}
$discussions = $DB->get_records_list('forum_discussions', 'id', array_unique($discussions));
//todo Rather than retrieving the ratings for each post individually it would be nice to do them in groups
//however this requires creating arrays of posts with each array containing all of the posts from a particular forum,
//retrieving the ratings then reassembling them all back into a single array sorted by post.modified (descending)
$rm = new rating_manager();
$ratingoptions = new stdClass;
$ratingoptions->component = 'mod_forum';
$ratingoptions->ratingarea = 'post';
foreach ($result->posts as $post) {
if (!isset($result->forums[$post->forum]) || !isset($discussions[$post->discussion])) {
// Something very VERY dodgy has happened if we end up here
continue;
}
$forum = $result->forums[$post->forum];
$cm = $forum->cm;
$discussion = $discussions[$post->discussion];
$course = $result->courses[$discussion->course];
$forumurl = new moodle_url('/mod/forum/view.php', array('id' => $cm->id));
$discussionurl = new moodle_url('/mod/forum/discuss.php', array('d' => $post->discussion));
// load ratings
if ($forum->assessed != RATING_AGGREGATE_NONE) {
$ratingoptions->context = $cm->context;
$ratingoptions->items = array($post);
$ratingoptions->aggregate = $forum->assessed;//the aggregation method
$ratingoptions->scaleid = $forum->scale;
$ratingoptions->userid = $user->id;
$ratingoptions->assesstimestart = $forum->assesstimestart;
$ratingoptions->assesstimefinish = $forum->assesstimefinish;
if ($forum->type == 'single' or !$post->discussion) {
$ratingoptions->returnurl = $forumurl;
} else {
$ratingoptions->returnurl = $discussionurl;
}
$updatedpost = $rm->get_ratings($ratingoptions);
//updating the array this way because we're iterating over a collection and updating them one by one
$result->posts[$updatedpost[0]->id] = $updatedpost[0];
}
$courseshortname = format_string($course->shortname, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id)));
$forumname = format_string($forum->name, true, array('context' => $cm->context));
$fullsubjects = array();
if (!$isspecificcourse && !$hasparentaccess) {
$fullsubjects[] = html_writer::link(new moodle_url('/course/view.php', array('id' => $course->id)), $courseshortname);
$fullsubjects[] = html_writer::link($forumurl, $forumname);
} else {
$fullsubjects[] = html_writer::tag('span', $courseshortname);
$fullsubjects[] = html_writer::tag('span', $forumname);
}
if ($forum->type != 'single') {
$discussionname = format_string($discussion->name, true, array('context' => $cm->context));
if (!$isspecificcourse && !$hasparentaccess) {
$fullsubjects[] .= html_writer::link($discussionurl, $discussionname);
} else {
$fullsubjects[] .= html_writer::tag('span', $discussionname);
}
if ($post->parent != 0) {
$postname = format_string($post->subject, true, array('context' => $cm->context));
if (!$isspecificcourse && !$hasparentaccess) {
$fullsubjects[] .= html_writer::link(new moodle_url('/mod/forum/discuss.php', array('d' => $post->discussion, 'parent' => $post->id)), $postname);
} else {
$fullsubjects[] .= html_writer::tag('span', $postname);
}
}
}
$post->subject = join(' -> ', $fullsubjects);
// This is really important, if the strings are formatted again all the links
// we've added will be lost.
$post->subjectnoformat = true;
$discussionurl->set_anchor('p'.$post->id);
$fulllink = html_writer::link($discussionurl, get_string("postincontext", "forum"));
$postoutput[] = forum_print_post($post, $discussion, $forum, $cm, $course, false, false, false, $fulllink, '', null, true, null, true);
}
$userfullname = fullname($user);
if ($discussionsonly) {
$inpageheading = get_string('discussionsstartedby', 'mod_forum', $userfullname);
} else {
$inpageheading = get_string('postsmadebyuser', 'mod_forum', $userfullname);
}
if ($isspecificcourse) {
$a = new stdClass;
$a->fullname = $userfullname;
$a->coursename = format_string($course->shortname, true, array('context' => $coursecontext));
$pageheading = $a->coursename;
if ($discussionsonly) {
$pagetitle = get_string('discussionsstartedbyuserincourse', 'mod_forum', $a);
} else {
$pagetitle = get_string('postsmadebyuserincourse', 'mod_forum', $a);
}
} else {
$pagetitle = $inpageheading;
$pageheading = $userfullname;
}
$PAGE->set_title($pagetitle);
$PAGE->set_heading($pagetitle);
$PAGE->navigation->extend_for_user($user);
$PAGE->navigation->set_userid_for_parent_checks($user->id); // see MDL-25805 for reasons and for full commit reference for reversal when fixed.
echo $OUTPUT->header();
echo $OUTPUT->heading($inpageheading);
echo html_writer::start_tag('div', array('class' => 'user-content'));
if (!empty($postoutput)) {
echo $OUTPUT->paging_bar($result->totalcount, $page, $perpage, $url);
foreach ($postoutput as $post) {
echo $post;
echo html_writer::empty_tag('br');
}
echo $OUTPUT->paging_bar($result->totalcount, $page, $perpage, $url);
} else if ($discussionsonly) {
echo $OUTPUT->heading(get_string('nodiscussionsstartedby', 'forum', $userfullname));
} else {
echo $OUTPUT->heading(get_string('noposts', 'forum'));
}
echo html_writer::end_tag('div');
echo $OUTPUT->footer();

View File

@ -58,10 +58,6 @@ if (isguestuser($user)) {
if (!empty($CFG->forceloginforprofiles)) {
require_login(); // we can not log in to course due to the parent hack bellow
if (isguestuser()) {
$SESSION->wantsurl = $PAGE->url->out(false);
redirect(get_login_url());
}
}
$PAGE->set_context($coursecontext);
@ -96,7 +92,7 @@ $fullname = fullname($user, has_capability('moodle/site:viewfullnames', $coursec
/// Now test the actual capabilities and enrolment in course
if ($currentuser) {
// me
if (!is_enrolled($coursecontext) and !is_viewing($coursecontext)) { // Need to have full access to a course to see the rest of own info
if (!is_viewing($coursecontext) && !is_enrolled($coursecontext)) { // Need to have full access to a course to see the rest of own info
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('notenrolled', '', $fullname));
if (!empty($_SERVER['HTTP_REFERER'])) {