diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php index 13d0e76ec1..aca5b27209 100644 --- a/lang/en/moodleoverflow.php +++ b/lang/en/moodleoverflow.php @@ -196,6 +196,14 @@ $string['answer'] = '{$a} Answer'; $string['answers'] = '{$a} Answers'; +// Strings for Overview Pages +$string['overviewdiscussions'] = 'Overview of all started discussions'; +$string['overviewposts'] = 'Overview of all posts'; +$string['viewdiscussions'] = 'View started Moodleoverflow discussions'; +$string['viewposts'] = 'View answers to Moodleoverflow discussions'; +$string['showoverviewprofilpage'] = 'Link Overview on Profile Page'; +$string['showoverviewprofilpage_desc'] = 'Show Links to Overview Pages in User Profile Page'; + // Strings for the readtracking.php. $string['markreadfailed'] = 'A post of the discussion could not be marked as read.'; $string['markdiscussionreadsuccessful'] = 'The discussion has been marked as read.'; @@ -465,7 +473,6 @@ $string['your_post_was_rejected_with_reason'] = 'Your post was rejected with the following reason:'; $string['original_post'] = 'Original post'; - // Daily mail message. $string['digestunreadpost'] = 'Course: {$a->linktocourse} -> {$a->linktoforum}, Topic: {$a->linktodiscussion} has {$a->unreadposts} unread posts.'; diff --git a/lib.php b/lib.php index 5ee67061d7..0b900a34b7 100644 --- a/lib.php +++ b/lib.php @@ -552,7 +552,40 @@ function moodleoverflow_extend_settings_navigation(settings_navigation $settings } } } - +/** + * Insert Overview of discussions and post in the Miscellaneous block in the my profile page. + * + * @param tree $tree tree + * @param stdClass $user user + * @param int $iscurrentuser iscurrentuser + */ +function moodleoverflow_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, $iscurrentuser, $course) { + global $DB, $CFG, $USER; + if (isguestuser($user)) { + // Coopy from forum - the guest user cannot post, so it is not possible to view any posts. + // May as well just bail aggressively here. + return false; + } + if (get_config('moodleoverflow', 'showoverviewprofilpage')) { + $viewdiscussionurl = new moodle_url('/mod/moodleoverflow/viewstartingdiscussion.php'); + if (!empty($course)) { + $viewdiscussionurl->param('courseid', $course->id); + } + $discussionnode = new core_user\output\myprofile\node('miscellaneous', 'moodleoverflowdiscussions', + get_string('viewdiscussions', 'moodleoverflow'), null, $viewdiscussionurl); + $tree->add_node($discussionnode); + $viewposturl = new moodle_url('/mod/moodleoverflow/viewcontributingposts.php'); + if (!empty($course)) { + $viewposturl->param('course', $course->id); + } + $postnode = new core_user\output\myprofile\node('miscellaneous', 'moodleoverflowposts', + get_string('viewposts', 'moodleoverflow'), null, $viewposturl); + $tree->add_node($postnode); + return true; + } else { + return false; + } +} /** * Determine the current context if one wa not already specified. * diff --git a/locallib.php b/locallib.php index 71ff6052eb..5bb4aeacbf 100644 --- a/locallib.php +++ b/locallib.php @@ -174,9 +174,6 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - echo $OUTPUT->paging_bar($numberofdiscussions, $page, $perpage, "view.php?id=$cm->id"); } - // Get the number of replies for each discussion. - $replies = moodleoverflow_count_discussion_replies($cm); - // Check whether the moodleoverflow instance can be tracked and is tracked. if ($cantrack = \mod_moodleoverflow\readtracking::moodleoverflow_can_track_moodleoverflows($moodleoverflow)) { $istracked = \mod_moodleoverflow\readtracking::moodleoverflow_is_tracked($moodleoverflow); @@ -213,9 +210,6 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - echo $OUTPUT->paging_bar($numberofdiscussions, $page, $perpage, "view.php?id=$cm->id"); } - // Get the number of replies for each discussion. - $replies = moodleoverflow_count_discussion_replies($cm); - // Check whether the user can subscribe to the discussion. $cansubtodiscussion = false; if ((!is_guest($context, $USER) && isloggedin()) && has_capability('mod/moodleoverflow:viewdiscussion', $context) @@ -230,221 +224,241 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - } // Iterate through every visible discussion. - $i = 0; $preparedarray = array(); foreach ($discussions as $discussion) { - $preparedarray[$i] = array(); + $preparedarray[] = prepare_data_for_discussions($discussion, $istracked, $canreviewposts, $moodleoverflow, $context, $cm); + } - // Handle anonymized discussions. - if ($discussion->userid == 0) { - $discussion->name = get_string('privacy:anonym_discussion_name', 'mod_moodleoverflow'); - } + // Include the renderer. + $renderer = $PAGE->get_renderer('mod_moodleoverflow'); - // Set the amount of replies for every discussion. - if (!empty($replies[$discussion->discussion])) { - $discussion->replies = $replies[$discussion->discussion]->replies; - $discussion->lastpostid = $replies[$discussion->discussion]->lastpostid; - } else { - $discussion->replies = 0; - } + // Collect the needed data being submitted to the template. + $mustachedata = new stdClass(); + $mustachedata->cantrack = $cantrack; + $mustachedata->canviewdiscussions = $canviewdiscussions; + $mustachedata->canreview = $canreviewposts; + $mustachedata->discussions = $preparedarray; + $mustachedata->hasdiscussions = (count($discussions) >= 0) ? true : false; + $mustachedata->istracked = $istracked; + $mustachedata->markallread = $markallread; + $mustachedata->cansubtodiscussion = $cansubtodiscussion; + $mustachedata->canmovetopic = $canmovetopic; + $mustachedata->cannormoveorsub = ((!$canmovetopic) && (!$cansubtodiscussion)); + // Print the template. + echo $renderer->render_discussion_list($mustachedata); + + // Show the paging bar if paging is activated. + if ($page != -1) { + echo $OUTPUT->paging_bar($numberofdiscussions, $page, $perpage, "view.php?id=$cm->id"); + } +} + +/** + * @param array $discussions + * @param bool $istracked + * @param bool $canreviewposts + * @param object $moodleoverflow + * @return array + * @throws coding_exception + * @throws moodle_exception + */ +function prepare_data_for_discussions($discussion, $istracked, $canreviewposts, $moodleoverflow, $context, $cm, $onlystarted = false): stdClass { + global $CFG, $OUTPUT, $USER, $DB; + // Get the number of replies for each discussion. + $replies = moodleoverflow_count_discussion_replies($cm); + // Handle anonymized discussions. + if ($discussion->userid == 0) { + $discussion->name = get_string('privacy:anonym_discussion_name', 'mod_moodleoverflow'); + } - // Set the right text. - $preparedarray[$i]['answertext'] = ($discussion->replies == 1) ? 'answer' : 'answers'; + // Set the amount of replies for every discussion. + if (!empty($replies[$discussion->discussion])) { + $discussion->replies = $replies[$discussion->discussion]->replies; + $discussion->lastpostid = $replies[$discussion->discussion]->lastpostid; + } else { + $discussion->replies = 0; + } - // Set the amount of unread messages for each discussion. - if (!$istracked) { - $discussion->unread = '-'; - } else if (empty($USER)) { + // Set the right text. + $discussion->answertext = ($discussion->replies == 1) ? 'answer' : 'answers'; + // Set the amount of unread messages for each discussion. + if (!$istracked) { + $discussion->unread = '-'; + } else if (empty($USER)) { + $discussion->unread = 0; + } else { + if (empty($unreads[$discussion->discussion])) { $discussion->unread = 0; } else { - if (empty($unreads[$discussion->discussion])) { - $discussion->unread = 0; - } else { - $discussion->unread = $unreads[$discussion->discussion]; - } + $discussion->unread = $unreads[$discussion->discussion]; } + } - // Check if the question owner marked the question as helpful. - $markedhelpful = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, false); - $preparedarray[$i]['starterlink'] = null; - if ($markedhelpful) { - $link = '/mod/moodleoverflow/discussion.php?d='; - $markedhelpful = $markedhelpful[array_key_first($markedhelpful)]; + // Check if the question owner marked the question as helpful. + $markedhelpful = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, false); + $discussion->starterlink = null; + if ($markedhelpful) { + $link = '/mod/moodleoverflow/discussion.php?d='; + $markedhelpful = $markedhelpful[array_key_first($markedhelpful)]; - $preparedarray[$i]['starterlink'] = new moodle_url($link . - $markedhelpful->discussionid . '#p' . $markedhelpful->postid); - } + $discussion->starterlink = new moodle_url($link . + $markedhelpful->discussionid . '#p' . $markedhelpful->postid); + } - // Check if a teacher marked a post as solved. - $markedsolution = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, true); - $preparedarray[$i]['teacherlink'] = null; - if ($markedsolution) { - $link = '/mod/moodleoverflow/discussion.php?d='; - $markedsolution = $markedsolution[array_key_first($markedsolution)]; + // Check if a teacher marked a post as solved. + $markedsolution = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, true); + $discussion->teacherlink = null; + if ($markedsolution) { + $link = '/mod/moodleoverflow/discussion.php?d='; + $markedsolution = $markedsolution[array_key_first($markedsolution)]; - $preparedarray[$i]['teacherlink'] = new moodle_url($link . - $markedsolution->discussionid . '#p' . $markedsolution->postid); - } + $discussion->teacherlink = new moodle_url($link . + $markedsolution->discussionid . '#p' . $markedsolution->postid); + } - // Check if a single post was marked by the question owner and a teacher. - $statusboth = false; - if ($markedhelpful && $markedsolution) { - if ($markedhelpful->postid == $markedsolution->postid) { - $statusboth = true; - } + // Check if a single post was marked by the question owner and a teacher. + $statusboth = false; + if ($markedhelpful && $markedsolution) { + if ($markedhelpful->postid == $markedsolution->postid) { + $statusboth = true; } + } - // Get the amount of votes for the discussion. + // Get the amount of votes for the discussion. + if (!$onlystarted) { $votes = \mod_moodleoverflow\ratings::moodleoverflow_get_ratings_by_discussion($discussion->discussion, $discussion->id); - $votes = $votes->upvotes - $votes->downvotes; - $preparedarray[$i]['votetext'] = ($votes == 1) ? 'vote' : 'votes'; + } else { + $votes = \mod_moodleoverflow\ratings::moodleoverflow_get_ratings_by_discussion($discussion->id, $discussion->firstpost); + } + $votes = $votes->upvotes - $votes->downvotes; + $discussion->votetext = ($votes == 1) ? 'vote' : 'votes'; + $discussion->votes = $votes; - // Use the discussions name instead of the subject of the first post. - $discussion->subject = $discussion->name; + // Use the discussions name instead of the subject of the first post. + $discussion->subject = $discussion->name; - // Format the subjectname and the link to the topic. - $preparedarray[$i]['subjecttext'] = format_string($discussion->subject); - $preparedarray[$i]['subjectlink'] = $CFG->wwwroot . '/mod/moodleoverflow/discussion.php?d=' . $discussion->discussion; + // Format the subjectname and the link to the topic. + $discussion->subjecttext = format_string($discussion->subject); + $discussion->subjectlink = $CFG->wwwroot . '/mod/moodleoverflow/discussion.php?d=' . $discussion->discussion; - // Get information about the user who started the discussion. - $startuser = new stdClass(); - if ($CFG->branch >= 311) { - $startuserfields = \core_user\fields::get_picture_fields(); - } else { - $startuserfields = explode(',', user_picture::fields()); - } + // Get information about the user who started the discussion. + $startuser = new stdClass(); + if ($CFG->branch >= 311) { + $startuserfields = \core_user\fields::get_picture_fields(); + } else { + $startuserfields = explode(',', user_picture::fields()); + } - $startuser = username_load_fields_from_object($startuser, $discussion, null, $startuserfields); - $startuser->id = $discussion->userid; + $startuser = username_load_fields_from_object($startuser, $discussion, null, $startuserfields); + $startuser->id = $discussion->userid; - // Discussion was anonymized. - if ($startuser->id == 0 || $moodleoverflow->anonymous != anonymous::NOT_ANONYMOUS) { - // Get his picture, his name and the link to his profile. - if ($startuser->id == $USER->id) { - $preparedarray[$i]['username'] = get_string('anonym_you', 'mod_moodleoverflow'); - // Needs to be included for reputation to update properly. - $preparedarray[$i]['userlink'] = $CFG->wwwroot . '/user/view.php?id=' . - $discussion->userid . '&course=' . $moodleoverflow->course; + if ($onlystarted) { + $startuser = $DB->get_record('user', array('id' => $discussion->userid)); + } + // Discussion was anonymized. + if ($startuser->id == 0 || $moodleoverflow->anonymous != anonymous::NOT_ANONYMOUS) { + // Get his picture, his name and the link to his profile. + if ($startuser->id == $USER->id) { + $discussion->username = get_string('anonym_you', 'mod_moodleoverflow'); + // Needs to be included for reputation to update properly. + $discussion->userlink = $CFG->wwwroot . '/user/view.php?id=' . + $discussion->userid . '&course=' . $moodleoverflow->course; - } else { - $preparedarray[$i]['username'] = get_string('privacy:anonym_user_name', 'mod_moodleoverflow'); - $preparedarray[$i]['userlink'] = null; - } } else { - // Get his picture, his name and the link to his profile. - $preparedarray[$i]['picture'] = $OUTPUT->user_picture($startuser, array('courseid' => $moodleoverflow->course, - 'link' => false)); - $preparedarray[$i]['username'] = fullname($startuser, has_capability('moodle/site:viewfullnames', $context)); - $preparedarray[$i]['userlink'] = $CFG->wwwroot . '/user/view.php?id=' . - $discussion->userid . '&course=' . $moodleoverflow->course; + $discussion->username = get_string('privacy:anonym_user_name', 'mod_moodleoverflow'); + $discussion->userlink = null; } - - // Get the amount of replies and the link to the discussion. - $preparedarray[$i]['replyamount'] = $discussion->replies; - $preparedarray[$i]['questionunderreview'] = $discussion->reviewed == 0; - - // Are there unread messages? Create a link to them. - $preparedarray[$i]['unreadamount'] = $discussion->unread; - $preparedarray[$i]['unread'] = ($preparedarray[$i]['unreadamount'] > 0) ? true : false; - $preparedarray[$i]['unreadlink'] = $CFG->wwwroot . - '/mod/moodleoverflow/discussion.php?d=' . $discussion->discussion . '#unread'; - $link = '/mod/moodleoverflow/markposts.php?m='; - $preparedarray[$i]['markreadlink'] = $CFG->wwwroot . $link . $moodleoverflow->id . '&d=' . $discussion->discussion; - - // Check the date of the latest post. Just in case the database is not consistent. - $usedate = (empty($discussion->timemodified)) ? $discussion->modified : $discussion->timemodified; - - // Get the name and the link to the profile of the user, that is related to the latest post. - $usermodified = new stdClass(); - $usermodified->id = $discussion->usermodified; - - if ($usermodified->id == 0 || $moodleoverflow->anonymous) { - if ($usermodified->id == $USER->id) { - $preparedarray[$i]['lastpostusername'] = null; - $preparedarray[$i]['lastpostuserlink'] = null; - } else { - $preparedarray[$i]['lastpostusername'] = null; - $preparedarray[$i]['lastpostuserlink'] = null; - } + } else { + // Get his picture, his name and the link to his profile. + $discussion->picture = $OUTPUT->user_picture($startuser, array('courseid' => $moodleoverflow->course, + 'link' => false)); + $discussion->username = fullname($startuser, has_capability('moodle/site:viewfullnames', $context)); + $discussion->userlink = $CFG->wwwroot . '/user/view.php?id=' . + $discussion->userid . '&course=' . $moodleoverflow->course; + } + + // Get the amount of replies and the link to the discussion. + $discussion->replyamount = $discussion->replies; + $discussion->questionunderreview = $discussion->reviewed == 0; + + // Are there unread messages? Create a link to them. + $discussion->unreadamount = $discussion->unread; + $discussion->unread = ($discussion->unreadamount > 0) ? true : false; + $discussion->unreadlink = $CFG->wwwroot . + '/mod/moodleoverflow/discussion.php?d=' . $discussion->discussion . '#unread'; + $link = '/mod/moodleoverflow/markposts.php?m='; + $discussion->markreadlink = $CFG->wwwroot . $link . $moodleoverflow->id . '&d=' . $discussion->discussion; + + // Check the date of the latest post. Just in case the database is not consistent. + $usedate = (empty($discussion->timemodified)) ? $discussion->modified : $discussion->timemodified; + + // Get the name and the link to the profile of the user, that is related to the latest post. + $usermodified = new stdClass(); + $usermodified->id = $discussion->usermodified; + + if ($usermodified->id == 0 || $moodleoverflow->anonymous) { + if ($usermodified->id == $USER->id) { + $discussion->lastpostusername = null; + $discussion->lastpostuserlink = null; } else { - $usermodified = username_load_fields_from_object($usermodified, $discussion, 'um'); - $preparedarray[$i]['lastpostusername'] = fullname($usermodified); - $preparedarray[$i]['lastpostuserlink'] = $CFG->wwwroot . '/user/view.php?id=' . - $discussion->usermodified . '&course=' . $moodleoverflow->course; + $discussion->lastpostusername = null; + $discussion->lastpostuserlink = null; } - - // Get the date of the latest post of the discussion. - $parenturl = (empty($discussion->lastpostid)) ? '' : '&parent=' . $discussion->lastpostid; - $preparedarray[$i]['lastpostdate'] = userdate($usedate, get_string('strftimerecentfull')); - $preparedarray[$i]['lastpostlink'] = $preparedarray[$i]['subjectlink'] . $parenturl; - - // Check whether the discussion is subscribed. - $preparedarray[$i]['discussionsubicon'] = false; - if ((!is_guest($context, $USER) && isloggedin()) && has_capability('mod/moodleoverflow:viewdiscussion', $context)) { - // Discussion subscription. - if (\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $context)) { - $preparedarray[$i]['discussionsubicon'] = \mod_moodleoverflow\subscriptions::get_discussion_subscription_icon( - $moodleoverflow, $context, $discussion->discussion); - } + } else { + $usermodified = username_load_fields_from_object($usermodified, $discussion, 'um'); + if ($onlystarted) { + $usermodified = $DB->get_record('user', array('id' => $discussion->usermodified)); } - - if ($canreviewposts) { - $reviewinfo = review::get_short_review_info_for_discussion($discussion->discussion); - $preparedarray[$i]['needreview'] = $reviewinfo->count; - $preparedarray[$i]['reviewlink'] = (new moodle_url('/mod/moodleoverflow/discussion.php', [ - 'd' => $discussion->discussion - ], 'p' . $reviewinfo->first))->out(false); + $discussion->lastpostusername = fullname($usermodified); + $discussion->lastpostuserlink = $CFG->wwwroot . '/user/view.php?id=' . + $discussion->usermodified . '&course=' . $moodleoverflow->course; + } + + // Get the date of the latest post of the discussion. + $parenturl = (empty($discussion->lastpostid)) ? '' : '&parent=' . $discussion->lastpostid; + $discussion->lastpostdate = userdate($usedate, get_string('strftimerecentfull')); + $discussion->lastpostlink = $discussion->subjectlink . $parenturl; + + // Check whether the discussion is subscribed. + $discussion->discussionsubicon = false; + if ((!is_guest($context, $USER) && isloggedin()) && has_capability('mod/moodleoverflow:viewdiscussion', $context)) { + // Discussion subscription. + if (\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $context)) { + $discussion->discussionsubicon = \mod_moodleoverflow\subscriptions::get_discussion_subscription_icon( + $moodleoverflow, $context, $discussion->discussion); } + } - // Build linktopopup to move a topic. - $linktopopup = $CFG->wwwroot . '/mod/moodleoverflow/view.php?id=' . $cm->id . '&movetopopup=' . $discussion->discussion; - $preparedarray[$i]['linktopopup'] = $linktopopup; - - // Add all created data to an array. - $preparedarray[$i]['markedhelpful'] = $markedhelpful; - $preparedarray[$i]['markedsolution'] = $markedsolution; - $preparedarray[$i]['statusboth'] = $statusboth; - $preparedarray[$i]['votes'] = $votes; + if ($canreviewposts) { + $reviewinfo = review::get_short_review_info_for_discussion($discussion->discussion); + $discussion->needreview = $reviewinfo->count; + $discussion->reviewlink = (new moodle_url('/mod/moodleoverflow/discussion.php', [ + 'd' => $discussion->discussion + ], 'p' . $reviewinfo->first))->out(false); + } - // Did the user rated this post? - $rating = \mod_moodleoverflow\ratings::moodleoverflow_user_rated($discussion->firstpost); + // Build linktopopup to move a topic. + $linktopopup = $CFG->wwwroot . '/mod/moodleoverflow/view.php?id=' . $cm->id . '&movetopopup=' . $discussion->discussion; + $discussion->linktopopup = $linktopopup; - $firstpost = moodleoverflow_get_post_full($discussion->firstpost); + // Add all created data to an array. + $discussion->markedhelpful = $markedhelpful; + $discussion->markedsolution = $markedsolution; + $discussion->statusboth = $statusboth; - $preparedarray[$i]['userupvoted'] = ($rating->rating ?? null) == RATING_UPVOTE; - $preparedarray[$i]['userdownvoted'] = ($rating->rating ?? null) == RATING_DOWNVOTE; - $preparedarray[$i]['canchange'] = \mod_moodleoverflow\ratings::moodleoverflow_user_can_rate($firstpost, $context) && - $startuser->id != $USER->id; - $preparedarray[$i]['postid'] = $discussion->firstpost; + // Did the user rated this post? + $rating = \mod_moodleoverflow\ratings::moodleoverflow_user_rated($discussion->firstpost); - // Go to the next discussion. - $i++; - } + $firstpost = moodleoverflow_get_post_full($discussion->firstpost); - // Include the renderer. - $renderer = $PAGE->get_renderer('mod_moodleoverflow'); + $discussion->userupvoted = ($rating->rating ?? null) == RATING_UPVOTE; + $discussion->userdownvoted = ($rating->rating ?? null) == RATING_DOWNVOTE; + $discussion->canchange = \mod_moodleoverflow\ratings::moodleoverflow_user_can_rate($firstpost, $context) && + $startuser->id != $USER->id; + $discussion->postid = $discussion->firstpost; - // Collect the needed data being submitted to the template. - $mustachedata = new stdClass(); - $mustachedata->cantrack = $cantrack; - $mustachedata->canviewdiscussions = $canviewdiscussions; - $mustachedata->canreview = $canreviewposts; - $mustachedata->discussions = $preparedarray; - $mustachedata->hasdiscussions = (count($discussions) >= 0) ? true : false; - $mustachedata->istracked = $istracked; - $mustachedata->markallread = $markallread; - $mustachedata->cansubtodiscussion = $cansubtodiscussion; - $mustachedata->canmovetopic = $canmovetopic; - $mustachedata->cannormoveorsub = ((!$canmovetopic) && (!$cansubtodiscussion)); - // Print the template. - echo $renderer->render_discussion_list($mustachedata); - - // Show the paging bar if paging is activated. - if ($page != -1) { - echo $OUTPUT->paging_bar($numberofdiscussions, $page, $perpage, "view.php?id=$cm->id"); - } + return $discussion; } - /** * Prints a popup with a menu of other moodleoverflow in the course. * Menu to move a topic to another moodleoverflow forum. @@ -639,6 +653,46 @@ function moodleoverflow_get_discussions_unread($cm) { } } +/** + * Gets the number of unread post for a single discussion. + * @param int $discussionid + * @param $cm + * @return false|mixed + * @throws coding_exception + * @throws dml_exception + */ +function get_discussion_unread($discussionid, $cm) { + global $USER, $DB; + $now = round(time(), -2); + $cutoffdate = $now - (get_config('moodleoverflow', 'oldpostdays') * 24 * 60 * 60); + + $params = [ + 'userid' => $USER->id, + 'cutoffdate' => $cutoffdate, + 'discussionid' => $discussionid + ]; + + $modcontext = context_module::instance($cm->id); + $whereconditions = ['p.modified >= :cutoffdate', 'r.id is NULL', 'd.id = :discussionid']; + + if (!has_capability('mod/moodleoverflow:reviewpost', $modcontext)) { + $whereconditions[] = '(p.reviewed = 1 OR p.userid = :userid2)'; + $params['userid2'] = $USER->id; + } + + $wheresql = join(' AND ', $whereconditions); + + // Define the sql-query. + $sql = "SELECT d.id, COUNT(p.id) AS unread + FROM {moodleoverflow_discussions} d + JOIN {moodleoverflow_posts} p ON p.discussion = d.id + LEFT JOIN {moodleoverflow_read} r ON (r.postid = p.id AND r.userid = :userid) + WHERE $wheresql + GROUP BY d.id"; + + return $DB->get_record_sql($sql, $params); +} + /** * Gets a post with all info ready for moodleoverflow_print_post. * Most of these joins are just to get the forum id. diff --git a/renderer.php b/renderer.php index 905bc3d12d..ed9e6bb81d 100644 --- a/renderer.php +++ b/renderer.php @@ -46,6 +46,16 @@ class mod_moodleoverflow_renderer extends plugin_renderer_base { public function render_discussion_list($data) { return $this->render_from_template('mod_moodleoverflow/discussions', $data); } + /** + * Display the discussion list for the viewstartingdiscussion.php. + * + * @param object $data The prepared variables. + * + * @return string + */ + public function render_discussion_started_list($data) { + return $this->render_from_template('mod_moodleoverflow/discussion_started_list', $data); + } /** * Display the forum list in the view.php if a discussion needs to be moved to another forum. diff --git a/settings.php b/settings.php index 02376d7b9f..941ec44741 100644 --- a/settings.php +++ b/settings.php @@ -97,6 +97,11 @@ $settings->add(new admin_setting_configcheckbox('moodleoverflow/allowreview', get_string('allowreview', 'moodleoverflow'), get_string('allowreview_desc', 'moodleoverflow'), 1)); + // Allow teachers to enable review before publish. + $settings->add(new admin_setting_configcheckbox('moodleoverflow/showoverviewprofilpage', + get_string('showoverviewprofilpage', 'moodleoverflow'), + get_string('showoverviewprofilpage_desc', 'moodleoverflow'), 1)); + $settings->add(new admin_setting_configtext('moodleoverflow/reviewpossibleaftertime', get_string('reviewpossibleaftertime', 'moodleoverflow'), get_string('reviewpossibleaftertime_desc', 'moodleoverflow'), 1800, PARAM_INT)); diff --git a/styles.css b/styles.css index f0c92ff5bf..2adfa93825 100644 --- a/styles.css +++ b/styles.css @@ -12,6 +12,9 @@ /* * The discussionlist in the view.php */ +.moodleoverflowheaderlist { + border-spacing: 0; +} .moodleoverflowheaderlist th.header.replies .iconsmall { margin: 0 .3em; diff --git a/templates/discussion_started_list.mustache b/templates/discussion_started_list.mustache new file mode 100644 index 0000000000..14673f18a3 --- /dev/null +++ b/templates/discussion_started_list.mustache @@ -0,0 +1,149 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template mod_moodleoverflow/discussion_list + + Moodleoverflow discussion_list template. + The purpose of this template is to render a list of discussions for the view.php. + + Example context (json): + { + } +}} + +{{! There are no discussions. Print the string that specifies it. }} +{{^hasdiscussions}} +
+ ( {{#str}} nodiscussions, moodleoverflow {{/str}} ) +
+{{/hasdiscussions}} + +{{! There are discussions. Start to print the table. }} +{{#hasdiscussions}} + + {{#discussions}} +
+
+
+ {{> mod_moodleoverflow/postvoting }} +
+
+ {{# questionunderreview }} + {{#pix}}i/duration, moodle, {{#str}}pending_review, mod_moodleoverflow{{/str}}{{/pix}} + {{/ questionunderreview }} + {{^ questionunderreview }} + {{#markedsolution}} + {{! avoid whitespace + !}}{{# pix}} i/status-solved, moodleoverflow, {{#str}}containsteacherrating, moodleoverflow{{/str}} {{/ pix}}{{! + !}} + {{/markedsolution}} + {{#markedhelpful}} + {{! avoid whitespace + !}}{{# pix}} i/status-helpful, moodleoverflow, {{#str}}containsstarterrating, moodleoverflow{{/str}} {{/ pix}}{{! + !}} + {{/ markedhelpful }} + {{/ questionunderreview }} +
+
+ {{# canreview }} + {{# needreview }} + + {{/ needreview }} + {{/ canreview }} +
+ {{#pix}}i/reply, mod_moodleoverflow {{/pix}}{{ replyamount }} +
+
+ +
+ +
+ {{/discussions}} + +{{/hasdiscussions}} diff --git a/viewcontributingposts.php b/viewcontributingposts.php new file mode 100644 index 0000000000..83086ce397 --- /dev/null +++ b/viewcontributingposts.php @@ -0,0 +1,50 @@ +. + +/** + * Prints a particular instance of moodleoverflow + * + * You can have a rather longer description of the file as well, + * if you like, and it can span multiple lines. + * + * @package mod_moodleoverflow + * @copyright 2017 Kennet Winter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Include config and locallib. +require_once(__DIR__.'/../../config.php'); +global $PAGE, $OUTPUT; +// If invoked from a course show the discussions from the course. +$courseid = optional_param('courseid', 0, PARAM_INT); +$params = array(); + +if ($courseid) { + $params['courseid'] = $courseid; +} + +$PAGE->set_url('/mod/moodleoverflow/viewcontributingposts.php', $params); +require_login(); + +// Systemwide context as all post in moodleoverflows are displayed. +$PAGE->set_context(context_system::instance()); + +$PAGE->set_title(get_string('overviewposts', 'mod_moodleoverflow')); +$PAGE->set_heading(get_string('overviewposts', 'mod_moodleoverflow')); + +echo $OUTPUT->header(); +echo "hello world"; +echo $OUTPUT->footer(); diff --git a/viewstartingdiscussion.php b/viewstartingdiscussion.php new file mode 100644 index 0000000000..c73a8d38be --- /dev/null +++ b/viewstartingdiscussion.php @@ -0,0 +1,97 @@ +. + +/** + * Prints a particular instance of moodleoverflow + * + * You can have a rather longer description of the file as well, + * if you like, and it can span multiple lines. + * + * @package mod_moodleoverflow + * @copyright 2017 Kennet Winter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Include config and locallib. +require_once(__DIR__.'/../../config.php'); +require_once(__DIR__.'/locallib.php'); +use mod_moodleoverflow\readtracking; + +global $PAGE, $OUTPUT, $USER, $DB; +// If invoked from a course show the discussions from the course. +$courseid = optional_param('courseid', 0, PARAM_INT); +$params = array(); +if ($courseid) { + $params['courseid'] = $courseid; +} + +$PAGE->set_url('/mod/moodleoverflow/viewstartingdiscussion.php', $params); +require_login(); + +// Systemwide context as all started discussion in moodleoverflows are displayed. +$PAGE->set_context(context_system::instance()); + +$PAGE->set_title(get_string('overviewdiscussions', 'mod_moodleoverflow')); +$PAGE->set_heading(get_string('overviewdiscussions', 'mod_moodleoverflow')); + +// Get all started discussions (in a course). +$discussions = $DB->get_records('moodleoverflow_discussions', array('userid' => $USER->id)); +// Collect the needed data being submitted to the template. +$discussionswithdetails = array(); +$tracking = new readtracking(); +echo $OUTPUT->header(); + +foreach ($discussions as $discussion) { + $moodleoverflow = $DB->get_record('moodleoverflow', array('id' => $discussion->moodleoverflow)); + $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $discussion->course, + false, MUST_EXIST); + $context = context_module::instance($cm->id); + + $canreviewposts = has_capability('mod/moodleoverflow:reviewpost', $context); + + if (has_capability('mod/moodleoverflow:viewdiscussion', $context)) { + if ($cantrack = \mod_moodleoverflow\readtracking::moodleoverflow_can_track_moodleoverflows($moodleoverflow)) { + $istracked = \mod_moodleoverflow\readtracking::moodleoverflow_is_tracked($moodleoverflow); + } else { + $istracked = false; + } + $discussion->discussion = $discussion->id; + + $firstpost = $DB->get_record('moodleoverflow_posts', array('id' => $discussion->firstpost)); + $discussion->reviewed = $firstpost->reviewed; + $newdiscussion = prepare_data_for_discussions($discussion, $istracked, $canreviewposts, $moodleoverflow, $context, $cm, true); + $newdiscussion->istracked = $istracked; + $newdiscussion->cantrack = $cantrack; + if ($unreadpost = get_discussion_unread($discussion->id, $cm)) { + $newdiscussion->unread = true; + $newdiscussion->unreadamount = $unreadpost->unread; + } + $newdiscussion->cansubtodiscussion = false; + if ((!is_guest($context, $USER) && isloggedin()) && has_capability('mod/moodleoverflow:viewdiscussion', $context) + && \mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $context)) { + $newdiscussion->cansubtodiscussion = true; + } + array_push($discussionswithdetails, $newdiscussion); + } +} +$mustachedata = new stdClass(); +$mustachedata->discussions = $discussionswithdetails; +$mustachedata->hasdiscussions = count($discussionswithdetails) >= 0; + +// Include the renderer. +$renderer = $PAGE->get_renderer('mod_moodleoverflow'); +echo $renderer->render_discussion_started_list($mustachedata); +echo $OUTPUT->footer();