From 6253640064aa08d6a5ba7fb51521827e72c0c3c2 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 13 Jun 2024 11:05:15 +0200 Subject: [PATCH 01/17] adapt code to new codechecker version --- classes/output/moodleoverflow_email.php | 4 +- classes/privacy/provider.php | 4 +- grade.php | 1 + lang/en/moodleoverflow.php | 718 +++++++++++------------- lib.php | 14 +- locallib.php | 2 - post.php | 2 - tests/dailymail_test.php | 2 +- tests/generator/lib.php | 2 +- tests/locallib_test.php | 2 +- tests/post_test.php | 2 +- tests/privacy_provider_test.php | 16 +- tests/ratings_test.php | 76 +-- tests/readtracking_test.php | 2 +- tests/review_test.php | 2 +- tests/subscriptions_test.php | 10 +- tests/userstats_test.php | 2 +- 17 files changed, 401 insertions(+), 460 deletions(-) diff --git a/classes/output/moodleoverflow_email.php b/classes/output/moodleoverflow_email.php index 10d57c2797..0dcd61b8bc 100644 --- a/classes/output/moodleoverflow_email.php +++ b/classes/output/moodleoverflow_email.php @@ -73,13 +73,13 @@ class moodleoverflow_email implements \renderable, \templatable { /** * Whether the user can reply to this post. * - * @var boolean $canreply + * @var bool $canreply */ protected $canreply = false; /** * Whether to override forum display when displaying usernames. - * @var boolean $viewfullnames + * @var bool $viewfullnames */ protected $viewfullnames = false; diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index d1bf9e7644..c1df6fe1f0 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -50,7 +50,7 @@ class provider implements * * @return collection the updated collection of metadata items. */ - public static function get_metadata(collection $collection) : collection { + public static function get_metadata(collection $collection): collection { $collection->add_database_table('moodleoverflow_discussions', [ 'name' => 'privacy:metadata:moodleoverflow_discussions:name', @@ -135,7 +135,7 @@ public static function get_metadata(collection $collection) : collection { * * @return contextlist $contextlist The list of contexts used in this plugin. */ - public static function get_contexts_for_userid(int $userid) : contextlist { + public static function get_contexts_for_userid(int $userid): contextlist { // Fetch all Moodleoverflow discussions, moodleoverflow posts, ratings, tracking settings and subscriptions. $sql = "SELECT c.id FROM {context} c diff --git a/grade.php b/grade.php index e2695d9979..ab46489e8b 100644 --- a/grade.php +++ b/grade.php @@ -21,6 +21,7 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once(__DIR__ . "/../../config.php"); require_login(); $id = required_param('id', PARAM_INT); diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php index c256918c8b..092da48beb 100644 --- a/lang/en/moodleoverflow.php +++ b/lang/en/moodleoverflow.php @@ -27,272 +27,337 @@ defined('MOODLE_INTERNAL') || die(); -// Default strings. -$string['modulename'] = 'Moodleoverflow'; -$string['modulenameplural'] = 'Moodleoverflows'; -$string['modulename_help'] = 'The Moodleoverflow module enables participants to use a question-answer forum structure. The forum display is non-chronological as the ordering depends on collaborative voting instead of on time.'; -$string['moodleoverflowfieldset'] = 'Custom example fieldset'; -$string['moodleoverflowname'] = 'Moodleoverflow name'; -$string['moodleoverflow'] = 'Moodleoverflow'; -$string['pluginadministration'] = 'Moodleoverflow administration'; -$string['pluginname'] = 'Moodleoverflow'; - -// Capabilities. -$string['moodleoverflow:addinstance'] = 'Add a new Moodleoverflow instance'; -$string['moodleoverflow:allowforcesubscribe'] = 'Allow forced subscription'; -$string['moodleoverflow:createattachment'] = 'Create attachments'; -$string['moodleoverflow:managesubscriptions'] = 'Manage subscriptions'; - -$string['moodleoverflow:ratehelpful'] = 'Mark a post as helpful'; -$string['moodleoverflow:ratepost'] = 'Rate a post'; -$string['moodleoverflow:deleteanypost'] = 'Delete posts'; -$string['moodleoverflow:deleteownpost'] = 'Delete own posts'; -$string['moodleoverflow:editanypost'] = 'Edit posts'; -$string['moodleoverflow:startdiscussion'] = 'Start a discussion'; -$string['moodleoverflow:replypost'] = 'Reply in discussion'; -$string['moodleoverflow:viewdiscussion'] = 'View discussion'; -$string['moodleoverflow:marksolved'] = 'Mark a post as solution'; -$string['moodleoverflow:reviewpost'] = 'Review (approve or reject) posts'; -$string['nowallsubscribed'] = 'All forums in {$a} are subscribed.'; -$string['nowallunsubscribed'] = 'All forums in {$a} are unsubscribed.'; -$string['moodleoverflow:movetopic'] = 'Move Topic to another Moddleoverflow Forum'; -$string['moodleoverflow:viewanyrating'] = 'View total ratings that anyone received'; - -// Strings for the view.php. -$string['noviewdiscussionspermission'] = 'You do not have the permission to view discussions in this forum'; -$string['lastpost'] = 'Last post'; - -// Strings for the locallib.php. +$string['action_downvote'] = 'Click to downvote'; +$string['action_remove_downvote'] = 'Click to remove downvote'; +$string['action_remove_upvote'] = 'Click to remove upvote'; +$string['action_upvote'] = 'Click to upvote'; $string['addanewdiscussion'] = 'Add a new discussion topic'; -$string['seeuserstats'] = 'View user statistics'; -$string['nodiscussions'] = 'There are no discussion topics yet in this forum.'; -$string['markallread_forum'] = 'Mark all posts as read'; -$string['markallread'] = 'Mark all posts in this discussion as read'; -$string['delete'] = 'Delete'; -$string['parent'] = 'Show parent'; -$string['markread'] = 'Mark read'; -$string['markunread'] = 'Mark unread'; -$string['permalink'] = 'Permalink'; -$string['postbyuser'] = '{$a->post} by {$a->user}'; +$string['addanewreply'] = 'Add a new answer'; +$string['allowanonymous'] = 'Allow anonymous'; +$string['allowanonymous_desc'] = 'Allow teachers to put moodleoverflow forums into anonymous question or full anonymous mode. Once enabled, anonymous forums will stay anonymous, even when this setting is disabled. If you really want to, you can reset anonymity in all forums here.'; +$string['allowcoursereputation'] = 'Sum reputation within a course.'; +$string['allowdisablerating'] = 'Allow teachers to disable rating and reputation'; +$string['allowmultiplemarks'] = 'Multiple marks?'; +$string['allowmultiplemarks_help'] = 'A post can be marked as helpful or solved. Within a discussion, only one post can be marked as helpful/solved. Click the checkbox to mark multiple posts as helpful/solved.'; +$string['allownegativereputation'] = 'Allow negative reputation?'; +$string['allownegativereputation_help'] = 'If set to yes, the users reputation within a course or within a module can be negative. If set to no, the reputation will stop to decrease at zero.'; +$string['allowrating'] = 'Allow post ratings?'; +$string['allowrating_help'] = 'If set to yes, users can up or downvote a post to give the reader an idea of how helpful the post was to other people. If set to no, ratings will be disabled.'; +$string['allowratingchange'] = 'Allow rating changes'; +$string['allowreputation'] = 'Allow user reputation?'; +$string['allowreputation_help'] = 'If set to yes, the users can gain or lose reputation depending on other users voting on their posts. If set to no, user reputation will be disabled.'; +$string['allowreview'] = 'Allow moderated forums'; +$string['allowreview_desc'] = 'Allow teachers to enable that all posts (or only all questions) have to be reviewed by them in order to be published.'; +$string['allsubscribe'] = 'Subscribe to all forums'; +$string['allunsubscribe'] = 'Unsubscribe from all forums'; +$string['alsomarkhelpful'] = "Also mark as helpful"; +$string['alsomarksolved'] = "Also mark as solution"; +$string['amount_unread_posts_in_discussion'] = 'There are {$a} unread posts in this discussion.'; +$string['amount_waiting_for_review'] = '{$a} post(s) need to be reviewed!'; +$string['anonym_you'] = 'Anonymous (You)'; +$string['anonymous'] = 'Anonymous'; +$string['anonymous:everything'] = 'Questioners and answerers (Irreversible!)'; +$string['anonymous:only_questions'] = 'Only questioners (Irreversible!)'; +$string['anonymous_help'] = 'This will hide username from all question (and answers).
WARNING: Once the questions (and answers) are anonymized, this cannot be reversed.
The setting can only be changed to a higher degree of anonymity.'; +$string['answer'] = '{$a} Answer'; +$string['answerer'] = 'Answerer #{$a}'; +$string['answers'] = '{$a} Answers'; +$string['approve'] = 'Approve'; +$string['areaattachment'] = 'Attachments'; +$string['areapost'] = 'Messages'; +$string['attachment'] = 'Attachment'; +$string['attachment_help'] = 'You can optionally attach one or more files to a forum post. If you attach an image, it will be displayed after the message.'; +$string['attachments'] = 'Attachments'; $string['bynameondate'] = 'by {$a->name} ({$a->rating}) - {$a->date}'; $string['bynameondatenorating'] = 'by {$a->name} - {$a->date}'; -$string['deletesure'] = 'Are you sure you want to delete this post?'; -$string['deletesureplural'] = 'Are you sure you want to delete this post and all replies? ({$a} posts)'; -$string['amount_unread_posts_in_discussion'] = 'There are {$a} unread posts in this discussion.'; - -// Strings for the settings.php. +$string['cannotcreatediscussion'] = 'Could not create new discussion'; +$string['cannotdeletepost'] = 'You can\'t delete this post!'; +$string['cannotfindparentpost'] = 'Could not find top parent of post {$a}'; +$string['cannotreply'] = 'You cannot reply to this post'; +$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['cleanreadtime'] = 'Mark old posts as read hour'; +$string['clicktosubscribe'] = 'You are not subscribed to this discussion. Click to subscribe.'; +$string['clicktounsubscribe'] = 'You are subscribed to this discussion. Click to unsubscribe.'; +$string['configallowcoursereputation'] = 'Allow to sum the reputation of all instances of the current course?'; +$string['configallowdisablerating'] = 'Set to \'yes\' if you want to give teachers the ability to disable rating and reputation.'; +$string['configallowratingchange'] = 'Can a user change its ratings?'; +$string['configcleanreadtime'] = 'The hour of the day to clean old posts from the \'read\' table.'; +$string['configforcedreadtracking'] = 'Allows Moodleoverflows to be set to forced read tracking. Will result in decreased performance for some users, particularly on courses with many moodleoverflows and posts. When off, any moodleoverflows previously set to Forced are treated as optional.'; $string['configmanydiscussions'] = 'Maximum number of discussions shown in a Moodleoverflow instance per page'; -$string['manydiscussions'] = 'Discussions per page'; -$string['maxattachmentsize'] = 'Maximum attachment size'; -$string['maxattachmentsize_help'] = 'This setting specifies the largest size of file that can be attached to a forum post.'; -$string['configmaxbytes'] = 'Default maximum size for all forum attachments on the site (subject to course limits and other local settings)'; -$string['maxattachments'] = 'Maximum number of attachments'; -$string['maxattachments_help'] = 'This setting specifies the maximum number of files that can be attached to a forum post.'; $string['configmaxattachments'] = 'Default maximum number of attachments allowed per post.'; -$string['maxeditingtime'] = 'Maximum amount of time during which a post can be edited by its owner (sec)'; +$string['configmaxbytes'] = 'Default maximum size for all forum attachments on the site (subject to course limits and other local settings)'; $string['configmaxeditingtime'] = 'Default maximum seconds are 3600 (= one hour). Regarding editing posts, please also consider the "Review possible after" setting for moderated forums.'; +$string['configmaxmailingtime'] = 'Posts older than this number of hours will not be mailed to the users. This will help to avoid problems where the cron has not been running for a long time.'; $string['configoldpostdays'] = 'Number of days old any post is considered read.'; -$string['oldpostdays'] = 'Read after days'; -$string['trackingoff'] = 'Off'; -$string['trackingon'] = 'Forced'; -$string['trackingoptional'] = 'Optional'; -$string['trackingtype'] = 'Read tracking'; +$string['configpreferteachersmark'] = 'The answer marked as solution by a course owner are prioritized over the answer marked as helpful by the starter of the discussion.'; +$string['configreputationnotnegative'] = 'Prohibits the users reputation being negative.'; +$string['configshowuserstats'] = 'Allow teachers in courses to see statistics summarizing the activity of users in Moodleoverflows.'; $string['configtrackingtype'] = 'Default setting for read tracking.'; -$string['trackmoodleoverflow'] = 'Track unread posts'; $string['configtrackmoodleoverflow'] = 'Set to \'yes\' if you want to track read/unread for each user.'; -$string['forcedreadtracking'] = 'Allow forced read tracking'; -$string['configforcedreadtracking'] = 'Allows Moodleoverflows to be set to forced read tracking. Will result in decreased performance for some users, particularly on courses with many moodleoverflows and posts. When off, any moodleoverflows previously set to Forced are treated as optional.'; -$string['cleanreadtime'] = 'Mark old posts as read hour'; -$string['configcleanreadtime'] = 'The hour of the day to clean old posts from the \'read\' table.'; -$string['allowdisablerating'] = 'Allow teachers to disable rating and reputation'; -$string['configallowdisablerating'] = 'Set to \'yes\' if you want to give teachers the ability to disable rating and reputation.'; - -$string['votescalevote'] = 'Reputation: Vote.'; -$string['configvotescalevote'] = 'The amount of reputation voting gives.'; -$string['votescaledownvote'] = 'Reputation: Downvote'; $string['configvotescaledownvote'] = 'The amount of reputation a downvote for your post gives.'; -$string['votescaleupvote'] = 'Reputation: Upvote'; -$string['configvotescaleupvote'] = 'The amount of reputation an upvote for your post gives.'; -$string['votescalesolved'] = 'Reputation: Solution'; -$string['configvotescalesolved'] = 'The amount of reputation a mark as solution on your post gives.'; -$string['votescalehelpful'] = 'Reputation: Helpful'; $string['configvotescalehelpful'] = 'The amount of reputation a mark as helpful on your post gives.'; -$string['reputationnotnegative'] = 'Reputation just positive?'; -$string['configreputationnotnegative'] = 'Prohibits the users reputation being negative.'; -$string['allowcoursereputation'] = 'Sum reputation within a course.'; -$string['configallowcoursereputation'] = 'Allow to sum the reputation of all instances of the current course?'; -$string['maxmailingtime'] = 'Maximal mailing time'; -$string['configmaxmailingtime'] = 'Posts older than this number of hours will not be mailed to the users. This will help to avoid problems where the cron has not been running for a long time.'; - -// Strings for the post.php. -$string['invalidmoodleoverflowid'] = 'Forum ID was incorrect'; -$string['invalidparentpostid'] = 'Parent post ID was incorrect'; -$string['notpartofdiscussion'] = 'This post is not part of a discussion!'; -$string['noguestpost'] = 'Sorry, guests are not allowed to post.'; -$string['nopostmoodleoverflow'] = 'Sorry, you are not allowed to post to this forum.'; -$string['yourreply'] = 'Your reply'; -$string['re'] = 'Re:'; -$string['invalidpostid'] = 'Invalid post ID - {$a}'; -$string['cannotfindparentpost'] = 'Could not find top parent of post {$a}'; -$string['edit'] = 'Edit'; -$string['cannotreply'] = 'You cannot reply to this post'; -$string['cannotcreatediscussion'] = 'Could not create new discussion'; +$string['configvotescalesolved'] = 'The amount of reputation a mark as solution on your post gives.'; +$string['configvotescaleupvote'] = 'The amount of reputation an upvote for your post gives.'; +$string['configvotescalevote'] = 'The amount of reputation voting gives.'; +$string['confirmsubscribe'] = 'Do you really want to subscribe to forum \'{$a}\'?'; +$string['confirmsubscribediscussion'] = 'Do you really want to subscribe to discussion \'{$a->discussion}\' in forum \'{$a->moodleoverflow}\'?'; +$string['confirmunsubscribe'] = 'Do you really want to unsubscribe from moodleoverflow \'{$a}\'?'; +$string['confirmunsubscribediscussion'] = 'Do you really want to unsubscribe from discussion \'{$a->discussion}\' in moodleoverflow \'{$a->moodleoverflow}\'?'; +$string['containsstarterrating'] = 'Contains a post marked as the most helpful by the questioner'; +$string['containsteacherrating'] = 'Contains a post marked as the solution by a teacher'; $string['couldnotadd'] = 'Could not add your post due to an unknown error'; -$string['postaddedsuccess'] = 'Your post was successfully added.'; -$string['postaddedtimeleft'] = 'You have {$a} to edit it if you want to make any changes.'; -$string['cannotupdatepost'] = 'You can not update this post'; -$string['couldnotupdate'] = 'Could not update your post due to an unknown error'; -$string['editedpostupdated'] = '{$a}\'s post was updated'; -$string['postupdated'] = 'Your post was updated'; -$string['editedby'] = 'Edited by {$a->name} - original submission {$a->date}'; -$string['cannotdeletepost'] = 'You can\'t delete this post!'; $string['couldnotdeletereplies'] = 'Sorry, that cannot be deleted as people have already responded to it'; -$string['errorwhiledelete'] = 'An error occurred while deleting record.'; -$string['couldnotdeletereplies'] = 'Sorry, that cannot be deleted as people have already responded to it'; - -// Strings for the classes/mod_form.php. -$string['subject'] = 'Subject'; -$string['reply'] = 'Comment'; -$string['replyfirst'] = 'Answer'; -$string['message'] = 'Message'; +$string['couldnotupdate'] = 'Could not update your post due to an unknown error'; +$string['coursewidereputation'] = 'Cross module reputation?'; +$string['coursewidereputation_help'] = 'If set to yes, the users reputations of all moodleoverflow modules in this course will be summed.'; +$string['crontask'] = 'Moodleoverflow maintenance jobs'; +$string['delete'] = 'Delete'; +$string['deletesure'] = 'Are you sure you want to delete this post?'; +$string['deletesureplural'] = 'Are you sure you want to delete this post and all replies? ({$a} posts)'; +$string['desc:anonymous'] = 'No names will be displayed.'; +$string['desc:only_questions'] = 'The name of questioners will not be displayed in their question and comments.'; +$string['desc:review_everything'] = 'All questions and answers are going to be reviewed by a teacher before being published.'; +$string['desc:review_questions'] = 'All questions are going to be reviewed by a teacher before being published.'; +$string['digestunreadpost'] = 'Course: {$a->linktocourse} -> {$a->linktoforum}, Topic: {$a->linktodiscussion} has {$a->unreadposts} unread posts.'; +$string['disallowsubscribe'] = 'Subscriptions not allowed'; +$string['discussionlocked'] = 'This discussion has been locked so you can no longer reply to it.'; +$string['discussionname'] = 'Discussion name'; +$string['discussionnownotsubscribed'] = '{$a->name} will NOT be notified of new posts in \'{$a->discussion}\' of \'{$a->moodleoverflow}\''; +$string['discussionnowsubscribed'] = '{$a->name} will be notified of new posts in \'{$a->discussion}\' of \'{$a->moodleoverflow}\''; +$string['discussions'] = 'Discussions'; $string['discussionsubscription'] = 'Discussion subscription'; $string['discussionsubscription_help'] = 'Subscribing to a discussion means you will receive notifications of new posts to that discussion.'; -$string['posttomoodleoverflow'] = 'Post to forum'; -$string['posts'] = 'Posts'; -$string['erroremptysubject'] = 'Post subject cannot be empty.'; +$string['downvotenotchangeable'] = 'Cannot downvote'; +$string['edit'] = 'Edit'; +$string['editedby'] = 'Edited by {$a->name} - original submission {$a->date}'; +$string['editedpostupdated'] = '{$a}\'s post was updated'; +$string['email_rejected_subject'] = '{$a->coursename}: One of your posts has been rejected.'; +$string['email_review_needed_subject'] = 'Review needed in {$a->coursename}: {$a->subject}'; $string['erroremptymessage'] = 'Post message cannot be empty'; -$string['yournewtopic'] = 'Your new discussion topic'; - -// Strings for the classes/ratings.php. -$string['postnotexist'] = 'Requested post does not exist'; +$string['erroremptysubject'] = 'Post subject cannot be empty.'; +$string['errorwhiledelete'] = 'An error occurred while deleting record.'; +$string['eventdiscussioncreated'] = 'Discussion created'; +$string['eventdiscussiondeleted'] = 'Discussion deleted'; +$string['eventdiscussionsubscriptioncreated'] = 'Discussion subscription created'; +$string['eventdiscussionsubscriptiondeleted'] = 'Discussion subscription deleted'; +$string['eventdiscussionviewed'] = 'Discussion viewed'; +$string['eventpostcreated'] = 'Post created'; +$string['eventpostdeleted'] = 'Post deleted'; +$string['eventpostupdated'] = 'Post updated'; +$string['eventratingcreated'] = 'Rating created'; +$string['eventratingdeleted'] = 'Rating deleted'; +$string['eventratingupdated'] = 'Rating updated'; +$string['eventreadtrackingdisabled'] = 'Read tracking disabled'; +$string['eventreadtrackingenabled'] = 'Read tracking enabled'; +$string['eventsubscriptioncreated'] = 'Subscription created'; +$string['eventsubscriptiondeleted'] = 'Subscription deleted'; +$string['everyonecannowchoose'] = 'Everyone can now choose to be subscribed'; +$string['everyoneisnowsubscribed'] = 'Everyone is now subscribed to this forum'; +$string['everyoneissubscribed'] = 'Everyone is subscribed to this forum'; +$string['forcedreadtracking'] = 'Allow forced read tracking'; +$string['generalmoodleoverflows'] = 'Forums in this course'; +$string['give_a_reason'] = 'Give a reason (optional)'; +$string['gotoindex'] = 'Manage preferences'; +$string['grademaxgradeerror'] = 'Maximum grade must be a positive integer different than 0'; +$string['gradesreport'] = 'Grades report'; +$string['gradesupdated'] = 'Grades updated'; +$string['helpamountofactivity'] = 'Each activity like writing a post, starting a discussion or giving a rating gives 1 point'; +$string['hiddenmoodleoverflowpost'] = 'Hidden forum post'; +$string['invaliddiscussionid'] = 'Discussion ID was incorrect'; +$string['invalidforcesubscribe'] = 'Invalid force subscription mode'; +$string['invalidmoodleoverflowid'] = 'Forum ID was incorrect'; +$string['invalidparentpostid'] = 'Parent post ID was incorrect'; +$string['invalidpostid'] = 'Invalid post ID - {$a}'; +$string['invalidratingid'] = 'The submitted rating is neither an upvote nor a downvote.'; +$string['jump_to_next_post_needing_review'] = 'Jump to next post needing to be reviewed.'; +$string['lastpost'] = 'Last post'; +$string['mailindexlink'] = 'Change your forum preferences: {$a}'; +$string['manydiscussions'] = 'Discussions per page'; +$string['markallread'] = 'Mark all posts in this discussion as read'; +$string['markallread_forum'] = 'Mark all posts as read'; +$string['markdiscussionreadsuccessful'] = 'The discussion has been marked as read.'; +$string['markhelpful'] = 'Mark as helpful'; +$string['markmoodleoverflowreadsuccessful'] = 'All posts have been marked as read.'; +$string['marknothelpful'] = 'Not Helpful'; +$string['marknotsolved'] = 'Remove solution mark'; +$string['markread'] = 'Mark read'; +$string['markreadfailed'] = 'A post of the discussion could not be marked as read.'; +$string['marksolved'] = 'Mark as solution'; +$string['markunread'] = 'Mark unread'; +$string['maxattachments'] = 'Maximum number of attachments'; +$string['maxattachments_help'] = 'This setting specifies the maximum number of files that can be attached to a forum post.'; +$string['maxattachmentsize'] = 'Maximum attachment size'; +$string['maxattachmentsize_help'] = 'This setting specifies the largest size of file that can be attached to a forum post.'; +$string['maxeditingtime'] = 'Maximum amount of time during which a post can be edited by its owner (sec)'; +$string['maxmailingtime'] = 'Maximal mailing time'; +$string['message'] = 'Message'; +$string['messageprovider:posts'] = 'Notification of new posts'; +$string['modulename'] = 'Moodleoverflow'; +$string['modulename_help'] = 'The Moodleoverflow module enables participants to use a question-answer forum structure. The forum display is non-chronological as the ordering depends on collaborative voting instead of on time.'; +$string['modulenameplural'] = 'Moodleoverflows'; +$string['moodleoverflow'] = 'Moodleoverflow'; +$string['moodleoverflow:addinstance'] = 'Add a new Moodleoverflow instance'; +$string['moodleoverflow:allowforcesubscribe'] = 'Allow forced subscription'; +$string['moodleoverflow:createattachment'] = 'Create attachments'; +$string['moodleoverflow:deleteanypost'] = 'Delete posts'; +$string['moodleoverflow:deleteownpost'] = 'Delete own posts'; +$string['moodleoverflow:editanypost'] = 'Edit posts'; +$string['moodleoverflow:managesubscriptions'] = 'Manage subscriptions'; +$string['moodleoverflow:marksolved'] = 'Mark a post as solution'; +$string['moodleoverflow:movetopic'] = 'Move Topic to another Moddleoverflow Forum'; +$string['moodleoverflow:ratehelpful'] = 'Mark a post as helpful'; +$string['moodleoverflow:ratepost'] = 'Rate a post'; +$string['moodleoverflow:replypost'] = 'Reply in discussion'; +$string['moodleoverflow:reviewpost'] = 'Review (approve or reject) posts'; +$string['moodleoverflow:startdiscussion'] = 'Start a discussion'; +$string['moodleoverflow:viewanyrating'] = 'View total ratings that anyone received'; +$string['moodleoverflow:viewdiscussion'] = 'View discussion'; +$string['moodleoverflowauthorhidden'] = 'Author (hidden)'; +$string['moodleoverflowbodyhidden'] = 'This post cannot be viewed by you, probably because you have not posted in the discussion, the maximum editing time hasn\'t passed yet, the discussion has not started or the discussion has expired.'; +$string['moodleoverflowfieldset'] = 'Custom example fieldset'; +$string['moodleoverflowname'] = 'Moodleoverflow name'; +$string['moodleoverflows'] = 'Moodleoverflows'; +$string['moodleoverflowsubjecthidden'] = 'Subject (hidden)'; +$string['movetopicicon'] = 'Move this discussion to another moodleoverflow'; +$string['movetopictoforum'] = 'Move discussion to {$a->forumname}'; +$string['nodiscussions'] = 'There are no discussion topics yet in this forum.'; +$string['noguestpost'] = 'Sorry, guests are not allowed to post.'; +$string['noguesttracking'] = 'Sorry, guests are not allowed to set tracking options.'; +$string['noonecansubscribenow'] = 'Subscriptions are now disallowed'; +$string['nopermissiontosubscribe'] = 'You do not have the permission to view subscribers'; +$string['nopostmoodleoverflow'] = 'Sorry, you are not allowed to post to this forum.'; $string['noratemoodleoverflow'] = 'Sorry, you are not allowed to vote in this forum.'; -$string['configallowratingchange'] = 'Can a user change its ratings?'; -$string['allowratingchange'] = 'Allow rating changes'; -$string['configpreferteachersmark'] = 'The answer marked as solution by a course owner are prioritized over the answer marked as helpful by the starter of the discussion.'; -$string['preferteachersmark'] = 'Prefer course owners\' marks?'; $string['noratingchangeallowed'] = 'You are not allowed to change your ratings.'; -$string['invalidratingid'] = 'The submitted rating is neither an upvote nor a downvote.'; +$string['notexists'] = 'Discussion no longer exists'; +$string['nothing'] = 'Nothing'; +$string['notpartofdiscussion'] = 'This post is not part of a discussion!'; +$string['notrackmoodleoverflow'] = 'Don\'t track unread posts'; $string['notstartuser'] = 'Only the user who started the discussion can mark an answer as helpful.'; $string['notteacher'] = 'Only course owners can do this.'; -$string['ratingtoold'] = 'Ratings can only be changed within 30 minutes after the first vote. '; - -// Strings for the discussion.php. -$string['invaliddiscussionid'] = 'Discussion ID was incorrect'; -$string['notexists'] = 'Discussion no longer exists'; -$string['discussionname'] = 'Discussion name'; -$string['discussionlocked'] = 'This discussion has been locked so you can no longer reply to it.'; -$string['hiddenmoodleoverflowpost'] = 'Hidden forum post'; -$string['moodleoverflowsubjecthidden'] = 'Subject (hidden)'; +$string['noviewdiscussionspermission'] = 'You do not have the permission to view discussions in this forum'; +$string['nowallsubscribed'] = 'All forums in {$a} are subscribed.'; +$string['nowallunsubscribed'] = 'All forums in {$a} are unsubscribed.'; +$string['nownotsubscribed'] = '{$a->name} will NOT be notified of new posts in \'{$a->moodleoverflow}\''; +$string['nownottracking'] = '{$a->name} is no longer tracking \'{$a->moodleoverflow}\'.'; +$string['nowsubscribed'] = '{$a->name} will be notified of new posts in \'{$a->moodleoverflow}\''; +$string['nowtracking'] = '{$a->name} is now tracking \'{$a->moodleoverflow}\'.'; +$string['oldpostdays'] = 'Read after days'; +$string['original_post'] = 'Original post'; +$string['parent'] = 'Show parent'; +$string['pending_review'] = 'Pending review'; +$string['pending_review_but_cannot_now'] = 'Pending review, but cannot be approved until {$a} after the creation of this post to allow the author a bit of time to edit it.'; +$string['permalink'] = 'Permalink'; +$string['pluginadministration'] = 'Moodleoverflow administration'; +$string['pluginname'] = 'Moodleoverflow'; +$string['post_was_approved'] = 'The post was approved.'; +$string['post_was_rejected'] = 'The post was rejected.'; +$string['postaddedsuccess'] = 'Your post was successfully added.'; +$string['postaddedtimeleft'] = 'You have {$a} to edit it if you want to make any changes.'; +$string['postbyuser'] = '{$a->post} by {$a->user}'; +$string['postincontext'] = 'See this post in context'; +$string['postmailinfolink'] = 'This is a copy of a message posted in {$a->coursename}. -$string['moodleoverflowauthorhidden'] = 'Author (hidden)'; -$string['moodleoverflowbodyhidden'] = 'This post cannot be viewed by you, probably because you have not posted in the discussion, the maximum editing time hasn\'t passed yet, the discussion has not started or the discussion has expired.'; -$string['addanewreply'] = 'Add a new answer'; -$string['ratingfailed'] = 'Rating failed. Try again.'; +To reply click on this link: {$a->replylink}'; +$string['postmailsubject'] = '{$a->courseshortname}: {$a->subject}'; +$string['postnotexist'] = 'Requested post does not exist'; +$string['posts'] = 'Posts'; +$string['posttomoodleoverflow'] = 'Post to forum'; +$string['postupdated'] = 'Your post was updated'; +$string['preferteachersmark'] = 'Prefer course owners\' marks?'; +$string['privacy:anonym_discussion_name'] = 'Anonymized discussion name'; +$string['privacy:anonym_post_message'] = 'This content has been deleted.'; +$string['privacy:anonym_user_name'] = 'Anonymous'; +$string['privacy:discussionsubscriptionpreference'] = 'You have chosen the following discussion subscription preference for this forum: "{$a->preference}"'; +$string['privacy:grade'] = 'Your grade for this Moodleoverflow forum.'; +$string['privacy:metadata:core_files'] = 'Moodleoverflow stores files which have been uploaded by the user to form part of a forum post.'; +$string['privacy:metadata:moodleoverflow_discuss_subs'] = 'Information about the subscriptions to individual forum discussions. This includes when a user has chosen to subscribe to a discussion or to unsubscribe from one where they would otherwise be subscribed.'; +$string['privacy:metadata:moodleoverflow_discuss_subs:discussion'] = 'The ID of the discussion that was subscribed / unsubscribed.'; +$string['privacy:metadata:moodleoverflow_discuss_subs:preference'] = 'The start time of the subscription.'; +$string['privacy:metadata:moodleoverflow_discuss_subs:userid'] = 'The ID of the user who changed the subscription settings.'; +$string['privacy:metadata:moodleoverflow_discussions'] = 'Information about forum discussions. This includes which discussions a user has started.'; +$string['privacy:metadata:moodleoverflow_discussions:name'] = 'The name of the discussion.'; +$string['privacy:metadata:moodleoverflow_discussions:timemodified'] = 'The time when the discussion (e.g. a post) was last modified.'; +$string['privacy:metadata:moodleoverflow_discussions:userid'] = 'The ID of the user who started the discussion.'; +$string['privacy:metadata:moodleoverflow_discussions:usermodified'] = 'The ID of the last user who modified the discussion'; +$string['privacy:metadata:moodleoverflow_grades'] = 'Information about the grade a user got for his contribution in a forum.'; +$string['privacy:metadata:moodleoverflow_grades:grade'] = 'The grade the user got.'; +$string['privacy:metadata:moodleoverflow_grades:moodleoverflowid'] = 'The ID of the moodleoverflow forum in which he got the grade.'; +$string['privacy:metadata:moodleoverflow_grades:userid'] = 'The ID of the user who got the grade.'; +$string['privacy:metadata:moodleoverflow_posts'] = 'Information about forum posts. This includes data of posts a user has written.'; +$string['privacy:metadata:moodleoverflow_posts:created'] = 'The date this post was created.'; +$string['privacy:metadata:moodleoverflow_posts:discussion'] = 'The ID of the discussion this post is contributing to.'; +$string['privacy:metadata:moodleoverflow_posts:message'] = 'The text of this post.'; +$string['privacy:metadata:moodleoverflow_posts:modified'] = 'The last date this post was modified.'; +$string['privacy:metadata:moodleoverflow_posts:parent'] = 'The ID of the post this post is referring to.'; +$string['privacy:metadata:moodleoverflow_posts:userid'] = 'The ID of the user who submitted this post.'; +$string['privacy:metadata:moodleoverflow_ratings'] = 'Information about ratings of posts. This includes when a user has rated a post and its specific rating.'; +$string['privacy:metadata:moodleoverflow_ratings:discussionid'] = 'The ID of the discussion the rated post is part of.'; +$string['privacy:metadata:moodleoverflow_ratings:firstrated'] = 'The date the rating was submitted.'; +$string['privacy:metadata:moodleoverflow_ratings:lastchanged'] = 'The date the rating was changed the last time.'; +$string['privacy:metadata:moodleoverflow_ratings:moodleoverflowid'] = 'The ID of the Moodleoverflow forum that contains the rated post.'; +$string['privacy:metadata:moodleoverflow_ratings:postid'] = 'The ID of the post that was rated.'; +$string['privacy:metadata:moodleoverflow_ratings:rating'] = 'The submitted rating. 0 = neutral, 1 = negative, 2 = positive, 3 = helpful, 4 = solution'; +$string['privacy:metadata:moodleoverflow_ratings:userid'] = 'The ID of the user who submitted the rating.'; +$string['privacy:metadata:moodleoverflow_read'] = 'Information about read tracking of posts. This includes when posts were read by a user.'; +$string['privacy:metadata:moodleoverflow_read:discussionid'] = 'The ID of the discussion the read post belongs to,'; +$string['privacy:metadata:moodleoverflow_read:firstread'] = 'The date the post was read the first time.'; +$string['privacy:metadata:moodleoverflow_read:lastread'] = 'The date the post was read the last time by the user.'; +$string['privacy:metadata:moodleoverflow_read:postid'] = 'The ID of the post that has been read.'; +$string['privacy:metadata:moodleoverflow_read:userid'] = 'The ID of the user who read the post.'; +$string['privacy:metadata:moodleoverflow_subscriptions'] = 'Information about subscriptions to forums. This includes which forums a user has subscribed.'; +$string['privacy:metadata:moodleoverflow_subscriptions:moodleoverflow'] = 'The ID of the Moodleoverflow forum the user has subscribed.'; +$string['privacy:metadata:moodleoverflow_subscriptions:userid'] = 'The ID of the user who has subscribed a forum.'; +$string['privacy:metadata:moodleoverflow_tracking'] = 'Information about the tracking of forums. This includes which forums a user does not track.'; +$string['privacy:metadata:moodleoverflow_tracking:moodleoverflowid'] = 'The ID of the moodleoverflow forum that is not tracked by the user.'; +$string['privacy:metadata:moodleoverflow_tracking:userid'] = 'The ID of the user who does not track the forum.'; +$string['privacy:postwasread'] = 'This post was first read on {$a->firstread} and most recently read on {$a->lastread}'; +$string['privacy:readtrackingdisabled'] = 'You have chosen to not track which posts that you have read within this forum.'; +$string['privacy:subscribedtoforum'] = 'You are subscribed to this forum.'; +$string['questioner'] = 'Questioner'; +$string['questions'] = 'Questions'; +$string['questions_and_posts'] = 'Questions and answers'; +$string['ratedbystarter'] = 'This post was marked as the most helpful by the questioner'; +$string['ratedbyteacher'] = 'This post was marked as the solution by a teacher'; $string['rateownpost'] = 'You cannot rate your own post.'; -$string['marksolved'] = 'Mark as solution'; -$string['alsomarksolved'] = "Also mark as solution"; -$string['marknotsolved'] = 'Remove solution mark'; -$string['markhelpful'] = 'Mark as helpful'; -$string['alsomarkhelpful'] = "Also mark as helpful"; -$string['marknothelpful'] = 'Not Helpful'; -$string['answer'] = '{$a} Answer'; -$string['answers'] = '{$a} Answers'; - -// 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.'; -$string['markmoodleoverflowreadsuccessful'] = 'All posts have been marked as read.'; -$string['noguesttracking'] = 'Sorry, guests are not allowed to set tracking options.'; +$string['ratingfailed'] = 'Rating failed. Try again.'; +$string['ratingheading'] = 'Rating and reputation'; +$string['ratingpreference'] = 'Display first'; +$string['ratingpreference_help'] = 'Answers can be marked as solution and helpful. This option decides which of these will be pinned as the first answer of the discussion. There are 2 options: -// Strings for the userstats feature. -$string['userstatsupvotes'] = 'Received upvotes'; -$string['userstatsdownvotes'] = 'Received downvotes'; -$string['userstatsforumactivity'] = 'Activity (this forum)'; -$string['userstatsforumreputation'] = 'Reputation (this forum)'; -$string['userstatscourseactivity'] = 'Activity (coursewide)'; -$string['userstatscoursereputation'] = 'Reputation (coursewide)'; -$string['helpamountofactivity'] = 'Each activity like writing a post, starting a discussion or giving a rating gives 1 point'; +* Heplful - A topic starter\'s helpful mark will be pinned at the top of the discussion +* Solved - A teacher\'s solution mark will be pinned at the top of the discussion'; +$string['ratingtoold'] = 'Ratings can only be changed within 30 minutes after the first vote. '; +$string['re'] = 'Re:'; +$string['reject'] = 'Reject'; +$string['reply'] = 'Comment'; +$string['replyfirst'] = 'Answer'; +$string['reputation'] = 'Reputation'; +$string['reputationnotnegative'] = 'Reputation just positive?'; +$string['resetanonymous_warning'] = 'Are you sure? If you are in production, this is most certainly a bad decision because your students and teachers posted their questions and answers, believing they would remain anonymous.

{$a->fullanoncount} forums are currently fully anonymized, and in {$a->questionanoncount} additional forums the questioners are anonymized.

In all these forums, the real names of posters will be displayed again, even in already existing posts!

There is no way of reverting those changes!
'; +$string['review'] = 'Review'; +$string['review_help'] = 'Select what has to be approved by a teacher before being shown to students.'; +$string['review_needed'] = 'Review needed!'; +$string['reviewpossibleaftertime'] = 'Review possible after (secs)'; +$string['reviewpossibleaftertime_desc'] = 'A teacher cannot reject or approve a post until this amount of time (in seconds) after the creation of the post. After a teacher has approved a post, the post cannot be edited by it\'s author anymore, even if still within the maxeditingtime duration.'; +$string['reviewpost'] = 'Review a post'; +$string['scalefactor'] = 'Scale factor'; +$string['scalefactor_help'] = 'The user rating is divided by the scale factor to obtain each user\'s grade. If the resulting grade is greater than the maximum grade, the value is limited to the specified maximum grade'; +$string['scalefactorerror'] = 'Scale factor must be a positive integer different than 0'; +$string['seeuserstats'] = 'View user statistics'; $string['showuserstats'] = 'Show cumulative user statistics'; -$string['configshowuserstats'] = 'Allow teachers in courses to see statistics summarizing the activity of users in Moodleoverflows.'; - -// OTHER. -$string['messageprovider:posts'] = 'Notification of new posts'; -$string['unknownerror'] = 'This is not expected to happen.'; -$string['crontask'] = 'Moodleoverflow maintenance jobs'; -$string['taskcleanreadrecords'] = 'Moodleoverflow maintenance job to clean old read records'; -$string['tasksendmails'] = 'Moodleoverflow maintenance job to send mails'; -$string['tasksenddailymail'] = 'Moodleoverflow job to send a daily mail of unread post'; -$string['nopermissiontosubscribe'] = 'You do not have the permission to view subscribers'; -$string['subscribeenrolledonly'] = 'Sorry, only enrolled users are allowed to subscribe to post notifications.'; -$string['everyonecannowchoose'] = 'Everyone can now choose to be subscribed'; -$string['noonecansubscribenow'] = 'Subscriptions are now disallowed'; -$string['invalidforcesubscribe'] = 'Invalid force subscription mode'; -$string['nownotsubscribed'] = '{$a->name} will NOT be notified of new posts in \'{$a->moodleoverflow}\''; -$string['cannotunsubscribe'] = 'Could not unsubscribe you from that forum'; -$string['discussionnownotsubscribed'] = '{$a->name} will NOT be notified of new posts in \'{$a->discussion}\' of \'{$a->moodleoverflow}\''; -$string['disallowsubscribe'] = 'Subscriptions not allowed'; -$string['noviewdiscussionspermission'] = 'You do not have the permission to view discussions in this forum'; -$string['nowsubscribed'] = '{$a->name} will be notified of new posts in \'{$a->moodleoverflow}\''; -$string['discussionnowsubscribed'] = '{$a->name} will be notified of new posts in \'{$a->discussion}\' of \'{$a->moodleoverflow}\''; -$string['unsubscribe'] = 'Unsubscribe from this forum'; -$string['subscribe'] = 'Subscribe to this forum'; -$string['confirmunsubscribediscussion'] = 'Do you really want to unsubscribe from discussion \'{$a->discussion}\' in moodleoverflow \'{$a->moodleoverflow}\'?'; -$string['confirmunsubscribe'] = 'Do you really want to unsubscribe from moodleoverflow \'{$a}\'?'; -$string['confirmsubscribediscussion'] = 'Do you really want to subscribe to discussion \'{$a->discussion}\' in forum \'{$a->moodleoverflow}\'?'; -$string['confirmsubscribe'] = 'Do you really want to subscribe to forum \'{$a}\'?'; -$string['postmailsubject'] = '{$a->courseshortname}: {$a->subject}'; $string['smallmessage'] = '{$a->user} posted in {$a->moodleoverflowname}'; -$string['moodleoverflows'] = 'Moodleoverflows'; -$string['postmailinfolink'] = 'This is a copy of a message posted in {$a->coursename}. - -To reply click on this link: {$a->replylink}'; -$string['unsubscribelink'] = 'Unsubscribe from this forum: {$a}'; -$string['unsubscribediscussionlink'] = 'Unsubscribe from this discussion: {$a}'; -$string['postincontext'] = 'See this post in context'; -$string['unsubscribediscussion'] = 'Unsubscribe from this discussion'; -$string['nownottracking'] = '{$a->name} is no longer tracking \'{$a->moodleoverflow}\'.'; -$string['nowtracking'] = '{$a->name} is now tracking \'{$a->moodleoverflow}\'.'; -$string['cannottrack'] = 'Could not stop tracking that forum'; -$string['notrackmoodleoverflow'] = 'Don\'t track unread posts'; -$string['trackmoodleoverflow'] = 'Track unread posts'; -$string['discussions'] = 'Discussions'; +$string['starterrating'] = 'Helpful'; +$string['subject'] = 'Subject'; +$string['subscribe'] = 'Subscribe to this forum'; $string['subscribed'] = 'Subscribed'; -$string['unreadposts'] = 'Unread posts'; -$string['unreadpostsnumber'] = '{$a} unread posts'; -$string['unreadpostsone'] = '1 unread post'; -$string['tracking'] = 'Track'; -$string['allsubscribe'] = 'Subscribe to all forums'; -$string['allunsubscribe'] = 'Unsubscribe from all forums'; -$string['generalmoodleoverflows'] = 'Forums in this course'; +$string['subscribeenrolledonly'] = 'Sorry, only enrolled users are allowed to subscribe to post notifications.'; $string['subscribestart'] = 'Send me notifications of new posts in this forum'; $string['subscribestop'] = 'I don\'t want to be notified of new posts in this forum'; -$string['everyoneisnowsubscribed'] = 'Everyone is now subscribed to this forum'; -$string['everyoneissubscribed'] = 'Everyone is subscribed to this forum'; -$string['mailindexlink'] = 'Change your forum preferences: {$a}'; -$string['gotoindex'] = 'Manage preferences'; -$string['areaattachment'] = 'Attachments'; -$string['areapost'] = 'Messages'; - - -// EVENTS. -$string['eventdiscussioncreated'] = 'Discussion created'; -$string['eventdiscussiondeleted'] = 'Discussion deleted'; -$string['eventdiscussionviewed'] = 'Discussion viewed'; -$string['eventratingcreated'] = 'Rating created'; -$string['eventratingupdated'] = 'Rating updated'; -$string['eventratingdeleted'] = 'Rating deleted'; -$string['eventpostcreated'] = 'Post created'; -$string['eventpostupdated'] = 'Post updated'; -$string['eventpostdeleted'] = 'Post deleted'; -$string['eventdiscussionsubscriptioncreated'] = 'Discussion subscription created'; -$string['eventdiscussionsubscriptiondeleted'] = 'Discussion subscription deleted'; -$string['eventsubscriptioncreated'] = 'Subscription created'; -$string['eventsubscriptiondeleted'] = 'Subscription deleted'; -$string['eventreadtrackingdisabled'] = 'Read tracking disabled'; -$string['eventreadtrackingenabled'] = 'Read tracking enabled'; - - -$string['subscriptiontrackingheader'] = 'Subscription and tracking'; +$string['subscriptionauto'] = 'Auto subscription'; +$string['subscriptiondisabled'] = 'Subscription disabled'; +$string['subscriptionforced'] = 'Forced subscription'; $string['subscriptionmode'] = 'Subscription mode'; $string['subscriptionmode_help'] = 'When a participant is subscribed to a forum it means they will receive forum post notifications. There are 4 subscription mode options: @@ -303,11 +368,16 @@ Note: Any subscription mode changes will only affect users who enrol in the course in the future, and not existing users.'; $string['subscriptionoptional'] = 'Optional subscription'; -$string['subscriptionforced'] = 'Forced subscription'; -$string['subscriptionauto'] = 'Auto subscription'; -$string['subscriptiondisabled'] = 'Subscription disabled'; -$string['switchtooptional'] = 'If you switch to the optional subscription, all currently subscribed users will be unsubscribed from this forum!'; +$string['subscriptiontrackingheader'] = 'Subscription and tracking'; $string['switchtoauto'] = 'If you switch to the auto subscription, all enrolled users will be subscribed to this forum!'; +$string['switchtooptional'] = 'If you switch to the optional subscription, all currently subscribed users will be unsubscribed from this forum!'; +$string['taskcleanreadrecords'] = 'Moodleoverflow maintenance job to clean old read records'; +$string['tasksenddailymail'] = 'Moodleoverflow job to send a daily mail of unread post'; +$string['tasksendmails'] = 'Moodleoverflow maintenance job to send mails'; +$string['taskupdategrades'] = 'Moodleoverflow maintenance job to update grades'; +$string['teacherrating'] = 'Solution'; +$string['there_are_no_posts_needing_review'] = 'There are no more posts in this forum that need to be reviewed.'; +$string['tracking'] = 'Track'; $string['trackingoff'] = 'Off'; $string['trackingon'] = 'Forced'; $string['trackingoptional'] = 'Optional'; @@ -317,161 +387,49 @@ If set to optional, tracking is turned on by default but participants can turn tracking off. If \'Allow forced read tracking\' is enabled in the site administration, then a further option is available - forced. This means that tracking is always on.'; -$string['ratingheading'] = 'Rating and reputation'; -$string['starterrating'] = 'Helpful'; -$string['teacherrating'] = 'Solution'; -$string['ratedbystarter'] = 'This post was marked as the most helpful by the questioner'; -$string['ratedbyteacher'] = 'This post was marked as the solution by a teacher'; -$string['containsstarterrating'] = 'Contains a post marked as the most helpful by the questioner'; -$string['containsteacherrating'] = 'Contains a post marked as the solution by a teacher'; -$string['ratingpreference'] = 'Display first'; -$string['ratingpreference_help'] = 'Answers can be marked as solution and helpful. This option decides which of these will be pinned as the first answer of the discussion. There are 2 options: +$string['trackmoodleoverflow'] = 'Track unread posts'; +$string['unknownerror'] = 'This is not expected to happen.'; +$string['unreadposts'] = 'Unread posts'; +$string['unreadpostsnumber'] = '{$a} unread posts'; +$string['unreadpostsone'] = '1 unread post'; +$string['unsubscribe'] = 'Unsubscribe from this forum'; +$string['unsubscribediscussion'] = 'Unsubscribe from this discussion'; +$string['unsubscribediscussionlink'] = 'Unsubscribe from this discussion: {$a}'; +$string['unsubscribelink'] = 'Unsubscribe from this forum: {$a}'; +$string['updategrades'] = 'Update grades'; +$string['upvotenotchangeable'] = 'Cannot upvote'; +$string['userstatscourseactivity'] = 'Activity (coursewide)'; +$string['userstatscoursereputation'] = 'Reputation (coursewide)'; +$string['userstatsdownvotes'] = 'Received downvotes'; +$string['userstatsforumactivity'] = 'Activity (this forum)'; +$string['userstatsforumreputation'] = 'Reputation (this forum)'; +$string['userstatsupvotes'] = 'Received upvotes'; +$string['votescaledownvote'] = 'Reputation: Downvote'; +$string['votescalehelpful'] = 'Reputation: Helpful'; +$string['votescalesolved'] = 'Reputation: Solution'; +$string['votescaleupvote'] = 'Reputation: Upvote'; +$string['votescalevote'] = 'Reputation: Vote.'; +$string['your_post_was_rejected'] = 'Your post was rejected.'; +$string['your_post_was_rejected_with_reason'] = 'Your post was rejected with the following reason:'; +$string['yournewtopic'] = 'Your new discussion topic'; +$string['yourreply'] = 'Your reply'; -* Heplful - A topic starter\'s helpful mark will be pinned at the top of the discussion -* Solved - A teacher\'s solution mark will be pinned at the top of the discussion'; -$string['allowrating'] = 'Allow post ratings?'; -$string['allowrating_help'] = 'If set to yes, users can up or downvote a post to give the reader an idea of how helpful the post was to other people. If set to no, ratings will be disabled.'; -$string['allowreputation'] = 'Allow user reputation?'; -$string['allowreputation_help'] = 'If set to yes, the users can gain or lose reputation depending on other users voting on their posts. If set to no, user reputation will be disabled.'; -$string['allownegativereputation'] = 'Allow negative reputation?'; -$string['allownegativereputation_help'] = 'If set to yes, the users reputation within a course or within a module can be negative. If set to no, the reputation will stop to decrease at zero.'; -$string['coursewidereputation'] = 'Cross module reputation?'; -$string['coursewidereputation_help'] = 'If set to yes, the users reputations of all moodleoverflow modules in this course will be summed.'; -$string['clicktounsubscribe'] = 'You are subscribed to this discussion. Click to unsubscribe.'; -$string['clicktosubscribe'] = 'You are not subscribed to this discussion. Click to subscribe.'; -$string['attachment'] = 'Attachment'; -$string['attachments'] = 'Attachments'; -$string['attachment_help'] = 'You can optionally attach one or more files to a forum post. If you attach an image, it will be displayed after the message.'; -$string['allowmultiplemarks'] = 'Multiple marks?'; -$string['allowmultiplemarks_help'] = 'A post can be marked as helpful or solved. Within a discussion, only one post can be marked as helpful/solved. Click the checkbox to mark multiple posts as helpful/solved.'; -// Templates. -$string['reputation'] = 'Reputation'; -$string['action_remove_upvote'] = 'Click to remove upvote'; -$string['upvotenotchangeable'] = 'Cannot upvote'; -$string['action_upvote'] = 'Click to upvote'; -$string['action_remove_downvote'] = 'Click to remove downvote'; -$string['downvotenotchangeable'] = 'Cannot downvote'; -$string['action_downvote'] = 'Click to downvote'; -$string['movetopicicon'] = 'Move this discussion to another moodleoverflow'; -$string['movetopictoforum'] = 'Move discussion to {$a->forumname}'; -// Privacy. -$string['privacy:metadata:core_files'] = 'Moodleoverflow stores files which have been uploaded by the user to form part of a forum post.'; -$string['privacy:metadata:moodleoverflow_discussions'] = 'Information about forum discussions. This includes which discussions a user has started.'; -$string['privacy:metadata:moodleoverflow_discussions:name'] = 'The name of the discussion.'; -$string['privacy:metadata:moodleoverflow_discussions:userid'] = 'The ID of the user who started the discussion.'; -$string['privacy:metadata:moodleoverflow_discussions:timemodified'] = 'The time when the discussion (e.g. a post) was last modified.'; -$string['privacy:metadata:moodleoverflow_discussions:usermodified'] = 'The ID of the last user who modified the discussion'; -$string['privacy:metadata:moodleoverflow_posts'] = 'Information about forum posts. This includes data of posts a user has written.'; -$string['privacy:metadata:moodleoverflow_posts:discussion'] = 'The ID of the discussion this post is contributing to.'; -$string['privacy:metadata:moodleoverflow_posts:parent'] = 'The ID of the post this post is referring to.'; -$string['privacy:metadata:moodleoverflow_posts:userid'] = 'The ID of the user who submitted this post.'; -$string['privacy:metadata:moodleoverflow_posts:created'] = 'The date this post was created.'; -$string['privacy:metadata:moodleoverflow_posts:modified'] = 'The last date this post was modified.'; -$string['privacy:metadata:moodleoverflow_posts:message'] = 'The text of this post.'; -$string['privacy:metadata:moodleoverflow_read'] = 'Information about read tracking of posts. This includes when posts were read by a user.'; -$string['privacy:metadata:moodleoverflow_read:userid'] = 'The ID of the user who read the post.'; -$string['privacy:metadata:moodleoverflow_read:discussionid'] = 'The ID of the discussion the read post belongs to,'; -$string['privacy:metadata:moodleoverflow_read:postid'] = 'The ID of the post that has been read.'; -$string['privacy:metadata:moodleoverflow_read:firstread'] = 'The date the post was read the first time.'; -$string['privacy:metadata:moodleoverflow_read:lastread'] = 'The date the post was read the last time by the user.'; -$string['privacy:metadata:moodleoverflow_subscriptions'] = 'Information about subscriptions to forums. This includes which forums a user has subscribed.'; -$string['privacy:metadata:moodleoverflow_subscriptions:userid'] = 'The ID of the user who has subscribed a forum.'; -$string['privacy:metadata:moodleoverflow_subscriptions:moodleoverflow'] = 'The ID of the Moodleoverflow forum the user has subscribed.'; -$string['privacy:metadata:moodleoverflow_discuss_subs'] = 'Information about the subscriptions to individual forum discussions. This includes when a user has chosen to subscribe to a discussion or to unsubscribe from one where they would otherwise be subscribed.'; -$string['privacy:metadata:moodleoverflow_discuss_subs:userid'] = 'The ID of the user who changed the subscription settings.'; -$string['privacy:metadata:moodleoverflow_discuss_subs:discussion'] = 'The ID of the discussion that was subscribed / unsubscribed.'; -$string['privacy:metadata:moodleoverflow_discuss_subs:preference'] = 'The start time of the subscription.'; -$string['privacy:metadata:moodleoverflow_ratings'] = 'Information about ratings of posts. This includes when a user has rated a post and its specific rating.'; -$string['privacy:metadata:moodleoverflow_ratings:userid'] = 'The ID of the user who submitted the rating.'; -$string['privacy:metadata:moodleoverflow_ratings:postid'] = 'The ID of the post that was rated.'; -$string['privacy:metadata:moodleoverflow_ratings:discussionid'] = 'The ID of the discussion the rated post is part of.'; -$string['privacy:metadata:moodleoverflow_ratings:moodleoverflowid'] = 'The ID of the Moodleoverflow forum that contains the rated post.'; -$string['privacy:metadata:moodleoverflow_ratings:rating'] = 'The submitted rating. 0 = neutral, 1 = negative, 2 = positive, 3 = helpful, 4 = solution'; -$string['privacy:metadata:moodleoverflow_ratings:firstrated'] = 'The date the rating was submitted.'; -$string['privacy:metadata:moodleoverflow_ratings:lastchanged'] = 'The date the rating was changed the last time.'; -$string['privacy:metadata:moodleoverflow_tracking'] = 'Information about the tracking of forums. This includes which forums a user does not track.'; -$string['privacy:metadata:moodleoverflow_tracking:userid'] = 'The ID of the user who does not track the forum.'; -$string['privacy:metadata:moodleoverflow_tracking:moodleoverflowid'] = 'The ID of the moodleoverflow forum that is not tracked by the user.'; -$string['privacy:metadata:moodleoverflow_grades'] = 'Information about the grade a user got for his contribution in a forum.'; -$string['privacy:metadata:moodleoverflow_grades:userid'] = 'The ID of the user who got the grade.'; -$string['privacy:metadata:moodleoverflow_grades:moodleoverflowid'] = 'The ID of the moodleoverflow forum in which he got the grade.'; -$string['privacy:metadata:moodleoverflow_grades:grade'] = 'The grade the user got.'; -$string['privacy:anonym_discussion_name'] = 'Anonymized discussion name'; -$string['privacy:anonym_post_message'] = 'This content has been deleted.'; -$string['privacy:anonym_user_name'] = 'Anonymous'; -$string['privacy:subscribedtoforum'] = 'You are subscribed to this forum.'; -$string['privacy:discussionsubscriptionpreference'] = 'You have chosen the following discussion subscription preference for this forum: "{$a->preference}"'; -$string['privacy:readtrackingdisabled'] = 'You have chosen to not track which posts that you have read within this forum.'; -$string['privacy:postwasread'] = 'This post was first read on {$a->firstread} and most recently read on {$a->lastread}'; -$string['privacy:grade'] = 'Your grade for this Moodleoverflow forum.'; -$string['scalefactor'] = 'Scale factor'; -$string['scalefactor_help'] = 'The user rating is divided by the scale factor to obtain each user\'s grade. If the resulting grade is greater than the maximum grade, the value is limited to the specified maximum grade'; -$string['scalefactorerror'] = 'Scale factor must be a positive integer different than 0'; -$string['grademaxgradeerror'] = 'Maximum grade must be a positive integer different than 0'; -$string['updategrades'] = 'Update grades'; -$string['gradesreport'] = 'Grades report'; -$string['gradesupdated'] = 'Grades updated'; -$string['taskupdategrades'] = 'Moodleoverflow maintenance job to update grades'; -// Anonymous Feature. -$string['anonymous'] = 'Anonymous'; -$string['anonymous_help'] = 'This will hide username from all question (and answers).
WARNING: Once the questions (and answers) are anonymized, this cannot be reversed.
The setting can only be changed to a higher degree of anonymity.'; -$string['anonymous:only_questions'] = 'Only questioners (Irreversible!)'; -$string['anonymous:everything'] = 'Questioners and answerers (Irreversible!)'; -$string['anonym_you'] = 'Anonymous (You)'; -$string['allowanonymous'] = 'Allow anonymous'; -$string['allowanonymous_desc'] = 'Allow teachers to put moodleoverflow forums into anonymous question or full anonymous mode. Once enabled, anonymous forums will stay anonymous, even when this setting is disabled. If you really want to, you can reset anonymity in all forums here.'; -$string['questioner'] = 'Questioner'; -$string['answerer'] = 'Answerer #{$a}'; -$string['desc:only_questions'] = 'The name of questioners will not be displayed in their question and comments.'; -$string['desc:anonymous'] = 'No names will be displayed.'; -$string['resetanonymous_warning'] = 'Are you sure? If you are in production, this is most certainly a bad decision because your students and teachers posted their questions and answers, believing they would remain anonymous.

{$a->fullanoncount} forums are currently fully anonymized, and in {$a->questionanoncount} additional forums the questioners are anonymized.

In all these forums, the real names of posters will be displayed again, even in already existing posts!

There is no way of reverting those changes!
'; -// Review feature. -$string['review'] = 'Review'; -$string['reviewpost'] = 'Review a post'; -$string['review_help'] = 'Select what has to be approved by a teacher before being shown to students.'; -$string['nothing'] = 'Nothing'; -$string['questions'] = 'Questions'; -$string['questions_and_posts'] = 'Questions and answers'; -$string['desc:review_questions'] = 'All questions are going to be reviewed by a teacher before being published.'; -$string['desc:review_everything'] = 'All questions and answers are going to be reviewed by a teacher before being published.'; -$string['allowreview'] = 'Allow moderated forums'; -$string['allowreview_desc'] = 'Allow teachers to enable that all posts (or only all questions) have to be reviewed by them in order to be published.'; -$string['amount_waiting_for_review'] = '{$a} post(s) need to be reviewed!'; -$string['pending_review'] = 'Pending review'; -$string['post_was_approved'] = 'The post was approved.'; -$string['post_was_rejected'] = 'The post was rejected.'; -$string['jump_to_next_post_needing_review'] = 'Jump to next post needing to be reviewed.'; -$string['there_are_no_posts_needing_review'] = 'There are no more posts in this forum that need to be reviewed.'; -$string['give_a_reason'] = 'Give a reason (optional)'; -$string['approve'] = 'Approve'; -$string['reject'] = 'Reject'; -$string['reviewpossibleaftertime'] = 'Review possible after (secs)'; -$string['reviewpossibleaftertime_desc'] = 'A teacher cannot reject or approve a post until this amount of time (in seconds) after the creation of the post. After a teacher has approved a post, the post cannot be edited by it\'s author anymore, even if still within the maxeditingtime duration.'; -$string['pending_review_but_cannot_now'] = 'Pending review, but cannot be approved until {$a} after the creation of this post to allow the author a bit of time to edit it.'; -$string['review_needed'] = 'Review needed!'; -$string['email_review_needed_subject'] = 'Review needed in {$a->coursename}: {$a->subject}'; -$string['email_rejected_subject'] = '{$a->coursename}: One of your posts has been rejected.'; -$string['your_post_was_rejected'] = 'Your post was rejected.'; -$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 254ddef794..98de9c8765 100644 --- a/lib.php +++ b/lib.php @@ -130,7 +130,7 @@ function moodleoverflow_supports($feature) { * * @return int The id of the newly inserted moodleoverflow record */ -function moodleoverflow_add_instance(stdClass $moodleoverflow, mod_moodleoverflow_mod_form $mform = null) { +function moodleoverflow_add_instance(stdClass $moodleoverflow, ?mod_moodleoverflow_mod_form $mform = null) { global $DB; // Set the current time. @@ -171,12 +171,12 @@ function moodleoverflow_instance_created($context, $moodleoverflow) { * (defined by the form in mod_form.php) this function * will update an existing instance with new data. * - * @param stdClass $moodleoverflow An object from the form in mod_form.php - * @param mod_moodleoverflow_mod_form $mform The form instance itself (if needed) + * @param stdClass $moodleoverflow An object from the form in mod_form.php + * @param mod_moodleoverflow_mod_form|null $mform The form instance itself (if needed) * * @return boolean Success/Fail */ -function moodleoverflow_update_instance(stdClass $moodleoverflow, mod_moodleoverflow_mod_form $mform = null) { +function moodleoverflow_update_instance(stdClass $moodleoverflow, ?mod_moodleoverflow_mod_form $mform = null) { global $DB; $moodleoverflow->timemodified = time(); @@ -476,10 +476,10 @@ function moodleoverflow_pluginfile($course, $cm, $context, $filearea, $args, $fo * This function is called when the context for the page is a moodleoverflow module. This is not called by AJAX * so it is safe to rely on the $PAGE. * - * @param settings_navigation $settingsnav complete settings navigation tree - * @param navigation_node $moodleoverflownode moodleoverflow administration node + * @param settings_navigation $settingsnav complete settings navigation tree + * @param navigation_node|null $moodleoverflownode moodleoverflow administration node */ -function moodleoverflow_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $moodleoverflownode = null) { +function moodleoverflow_extend_settings_navigation(settings_navigation $settingsnav, ?navigation_node $moodleoverflownode = null) { global $CFG, $DB, $PAGE, $USER; // Retrieve the current moodle record. diff --git a/locallib.php b/locallib.php index 360ce7e4db..69102f1c6d 100644 --- a/locallib.php +++ b/locallib.php @@ -46,8 +46,6 @@ function moodleoverflow_get_discussions($cm, $page = -1, $perpage = 0) { global $DB, $CFG, $USER; - // TODO Refactor variable naming. $discussion->id is first post and $discussion->discussion is discussion id? - // User must have the permission to view the discussions. $modcontext = context_module::instance($cm->id); if (!capabilities::has(capabilities::VIEW_DISCUSSION, $modcontext)) { diff --git a/post.php b/post.php index 303ba6223c..58e959b7c0 100644 --- a/post.php +++ b/post.php @@ -22,8 +22,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -// TODO refactor this. For more readability, and to avoid security issues. - // Include config and locallib. use mod_moodleoverflow\anonymous; use mod_moodleoverflow\review; diff --git a/tests/dailymail_test.php b/tests/dailymail_test.php index 3badfa178a..918584043f 100644 --- a/tests/dailymail_test.php +++ b/tests/dailymail_test.php @@ -39,7 +39,7 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class dailymail_test extends \advanced_testcase { +final class dailymail_test extends \advanced_testcase { /** @var \stdClass collection of messages */ private $sink; diff --git a/tests/generator/lib.php b/tests/generator/lib.php index a089878295..aa5bd7a2de 100644 --- a/tests/generator/lib.php +++ b/tests/generator/lib.php @@ -64,7 +64,7 @@ public function reset() { * * @return stdClass */ - public function create_instance($record = null, array $options = null) { + public function create_instance($record = null, ?array $options = null) { // Transform the record. $record = (object) (array) $record; diff --git a/tests/locallib_test.php b/tests/locallib_test.php index 9207c21bf3..30745209a5 100644 --- a/tests/locallib_test.php +++ b/tests/locallib_test.php @@ -36,7 +36,7 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class locallib_test extends advanced_testcase { +final class locallib_test extends advanced_testcase { public function setUp(): void { \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); diff --git a/tests/post_test.php b/tests/post_test.php index b29614c879..2906298ff8 100644 --- a/tests/post_test.php +++ b/tests/post_test.php @@ -33,7 +33,7 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class post_test extends \advanced_testcase { +final class post_test extends \advanced_testcase { /** @var \stdClass test course */ private $course; diff --git a/tests/privacy_provider_test.php b/tests/privacy_provider_test.php index 5b6d7b60a3..706f291340 100644 --- a/tests/privacy_provider_test.php +++ b/tests/privacy_provider_test.php @@ -41,7 +41,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \provider */ -class privacy_provider_test extends \core_privacy\tests\provider_testcase { +final class privacy_provider_test extends \core_privacy\tests\provider_testcase { /** * @var \mod_moodleoverflow_generator Plugin generator */ @@ -586,8 +586,10 @@ public function test_post_attachment_inclusion(): void { /** * Ensure that all user data is deleted from a context. + * + * @return void */ - public function test_all_users_deleted_from_context() { + public function test_all_users_deleted_from_context(): void { global $DB; $fs = get_file_storage(); $course = $this->getDataGenerator()->create_course(); @@ -723,8 +725,10 @@ public function test_all_users_deleted_from_context() { /** * Ensure that all user data is deleted for a specific context. + * + * @return void */ - public function test_delete_data_for_user() { + public function test_delete_data_for_user(): void { global $DB; $fs = get_file_storage(); $course = $this->getDataGenerator()->create_course(); @@ -924,7 +928,7 @@ protected function create_users($course, $count) { * * @return array The users created */ - protected function create_and_enrol_users($course, $count) { + protected function create_and_enrol_users($course, $count): array { $users = []; for ($i = 0; $i < $count; $i++) { $users[$i] = $this->getDataGenerator()->create_user(); @@ -936,8 +940,10 @@ protected function create_and_enrol_users($course, $count) { /** * Ensure that user data for specific users is deleted from a specified context. + * + * @return void */ - public function test_delete_data_for_users() { + public function test_delete_data_for_users(): void { global $DB; $fs = get_file_storage(); diff --git a/tests/ratings_test.php b/tests/ratings_test.php index f0dccc267b..1ebf68fcf9 100644 --- a/tests/ratings_test.php +++ b/tests/ratings_test.php @@ -23,6 +23,7 @@ */ namespace mod_moodleoverflow; use mod_moodleoverflow\ratings; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -37,47 +38,27 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class ratings_test extends \advanced_testcase { - /** @var \stdClass test course */ - private $course; +final class ratings_test extends \advanced_testcase { - /** @var \stdClass coursemodule */ - private $coursemodule; - - /** @var \stdClass test moodleoverflow */ - private $moodleoverflow; - - /** @var \stdClass test teacher */ - private $teacher; - - /** @var \stdClass test user */ - private $user1; - - /** @var \stdClass another test user */ - private $user2; - - /** @var \stdClass a discussion */ - private $discussion; - - /** @var \stdClass a post from the teacher*/ + /** @var stdClass a post from the teacher*/ private $post; - /** @var \stdClass answer from user 1 */ + /** @var stdClass answer from user 1 */ private $answer1; - /** @var \stdClass answer from user 1 */ + /** @var stdClass answer from user 1 */ private $answer2; - /** @var \stdClass answer from user 1 */ + /** @var stdClass answer from user 1 */ private $answer3; - /** @var \stdClass answer from user 2 */ + /** @var stdClass answer from user 2 */ private $answer4; - /** @var \stdClass answer from user 2 */ + /** @var stdClass answer from user 2 */ private $answer5; - /** @var \stdClass answer from user 2 */ + /** @var stdClass answer from user 2 */ private $answer6; /** @var \mod_moodleoverflow_generator $generator */ @@ -296,31 +277,30 @@ public function test_answersorting_onegroup(): void { private function helper_course_set_up() { global $DB; // Create a new course with a moodleoverflow forum. - $this->course = $this->getDataGenerator()->create_course(); - $location = ['course' => $this->course->id]; - $this->moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $location); - $this->coursemodule = get_coursemodule_from_instance('moodleoverflow', $this->moodleoverflow->id); + $course = $this->getDataGenerator()->create_course(); + $location = ['course' => $course->id]; + $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $location); // Create a teacher. - $this->teacher = $this->getDataGenerator()->create_user(['firstname' => 'Tamaro', 'lastname' => 'Walter']); - $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, 'student'); + $teacher = $this->getDataGenerator()->create_user(['firstname' => 'Tamaro', 'lastname' => 'Walter']); + $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'student'); // Create 2 users. - $this->user1 = $this->getDataGenerator()->create_user(['firstname' => 'Ava', 'lastname' => 'Davis']); - $this->getDataGenerator()->enrol_user($this->user1->id, $this->course->id, 'student'); - $this->user2 = $this->getDataGenerator()->create_user(['firstname' => 'Ethan', 'lastname' => 'Brown']); - $this->getDataGenerator()->enrol_user($this->user2->id, $this->course->id, 'student'); + $user1 = $this->getDataGenerator()->create_user(['firstname' => 'Ava', 'lastname' => 'Davis']); + $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student'); + $user2 = $this->getDataGenerator()->create_user(['firstname' => 'Ethan', 'lastname' => 'Brown']); + $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); // Create a discussion, a parent post and six answers. $this->generator = $this->getDataGenerator()->get_plugin_generator('mod_moodleoverflow'); - $this->discussion = $this->generator->post_to_forum($this->moodleoverflow, $this->teacher); - $this->post = $DB->get_record('moodleoverflow_posts', ['id' => $this->discussion[0]->firstpost], '*'); - $this->answer1 = $this->generator->reply_to_post($this->discussion[1], $this->user1, true); - $this->answer2 = $this->generator->reply_to_post($this->discussion[1], $this->user1, true); - $this->answer3 = $this->generator->reply_to_post($this->discussion[1], $this->user1, true); - $this->answer4 = $this->generator->reply_to_post($this->discussion[1], $this->user2, true); - $this->answer5 = $this->generator->reply_to_post($this->discussion[1], $this->user2, true); - $this->answer6 = $this->generator->reply_to_post($this->discussion[1], $this->user2, true); + $discussion = $this->generator->post_to_forum($moodleoverflow, $teacher); + $this->post = $DB->get_record('moodleoverflow_posts', ['id' => $discussion[0]->firstpost], '*'); + $this->answer1 = $this->generator->reply_to_post($discussion[1], $user1, true); + $this->answer2 = $this->generator->reply_to_post($discussion[1], $user1, true); + $this->answer3 = $this->generator->reply_to_post($discussion[1], $user1, true); + $this->answer4 = $this->generator->reply_to_post($discussion[1], $user2, true); + $this->answer5 = $this->generator->reply_to_post($discussion[1], $user2, true); + $this->answer6 = $this->generator->reply_to_post($discussion[1], $user2, true); } @@ -542,10 +522,10 @@ private function create_twogroups($group1, $group2) { * Executing the sort function and comparing the sorted post to the expected order. * @param String $group1 * @param string $group2 - * @param array|null $orderposts + * @param array $orderposts * @return void */ - private function process_groups(String $group1, string $group2, array $orderposts = null) { + private function process_groups(String $group1, string $group2, array $orderposts = []) { $this->create_twogroups($group1, $group2); $posts = [$this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6]; $rightorder = [$this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4]; diff --git a/tests/readtracking_test.php b/tests/readtracking_test.php index 015d7f4403..4d78b9e89e 100644 --- a/tests/readtracking_test.php +++ b/tests/readtracking_test.php @@ -38,7 +38,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \readtracking */ -class readtracking_test extends advanced_testcase { +final class readtracking_test extends advanced_testcase { /** * Test the logic in the moodleoverflow_can_track_moodleoverflows() function. diff --git a/tests/review_test.php b/tests/review_test.php index 9654f7dba8..df81ad3c2f 100644 --- a/tests/review_test.php +++ b/tests/review_test.php @@ -40,7 +40,7 @@ * * @group mod_moodleoverflow */ -class review_test extends \advanced_testcase { +final class review_test extends \advanced_testcase { /** @var \mod_moodleoverflow_generator $generator */ private $generator; diff --git a/tests/subscriptions_test.php b/tests/subscriptions_test.php index 10c4c6b602..7fe9eae71d 100644 --- a/tests/subscriptions_test.php +++ b/tests/subscriptions_test.php @@ -38,7 +38,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \subscriptions */ -class subscriptions_test extends advanced_testcase { +final class subscriptions_test extends advanced_testcase { /** * Test setUp. @@ -1360,7 +1360,7 @@ public function test_moodleoverflow_subscribe_toggle_as_other_repeat_subscriptio * * @return array */ - public function is_subscribable_moodleoverflows() { + public static function is_subscribable_moodleoverflows() { return [ [ 'forcesubscribe' => MOODLEOVERFLOW_DISALLOWSUBSCRIBE, @@ -1382,9 +1382,9 @@ public function is_subscribable_moodleoverflows() { * * @return array */ - public function is_subscribable_provider(): array { + public static function is_subscribable_provider(): array { $data = []; - foreach ($this->is_subscribable_moodleoverflows() as $moodleoverflow) { + foreach (self::is_subscribable_moodleoverflows() as $moodleoverflow) { $data[] = [$moodleoverflow]; } @@ -1440,7 +1440,7 @@ public function test_is_subscribable_is_guest($options): void { * Returns subscription obtions. * @return array */ - public function is_subscribable_loggedin_provider(): array { + public static function is_subscribable_loggedin_provider(): array { return [ [ ['forcesubscribe' => MOODLEOVERFLOW_DISALLOWSUBSCRIBE], diff --git a/tests/userstats_test.php b/tests/userstats_test.php index b6078f1670..080a11dd95 100644 --- a/tests/userstats_test.php +++ b/tests/userstats_test.php @@ -39,7 +39,7 @@ * * @covers \userstats_table */ -class userstats_test extends \advanced_testcase { +final class userstats_test extends \advanced_testcase { /** @var \stdClass test course */ private $course; From 2da4523f00e44ea47575b770411c9d2a2fcb9b10 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 13 Jun 2024 11:50:52 +0200 Subject: [PATCH 02/17] codecleaning --- tests/dailymail_test.php | 5 +++-- tests/review_test.php | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/dailymail_test.php b/tests/dailymail_test.php index 918584043f..5a2f2329b5 100644 --- a/tests/dailymail_test.php +++ b/tests/dailymail_test.php @@ -38,6 +38,8 @@ * @package mod_moodleoverflow * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @covers \mod_moodleoverflow\task\send_daily_mail */ final class dailymail_test extends \advanced_testcase { @@ -59,7 +61,7 @@ final class dailymail_test extends \advanced_testcase { /** @var \stdClass discussion instance */ private $discussion; - /** @var moodleoverflow generator */ + /** @var \component_generator_base moodleoverflow generator */ private $generator; /** @@ -138,7 +140,6 @@ private function helper_run_send_mails() { /** * Test if the task send_daily_mail sends a mail to the user. - * @covers \send_daily_mail::execute */ public function test_mail_delivery(): void { // Create user with maildigest = on. diff --git a/tests/review_test.php b/tests/review_test.php index df81ad3c2f..de3c3978fc 100644 --- a/tests/review_test.php +++ b/tests/review_test.php @@ -39,6 +39,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * * @group mod_moodleoverflow + * @covers \mod_moodleoverflow\review + * @covers \mod_moodleoverflow\task\send_mails */ final class review_test extends \advanced_testcase { From e45fb02c6033f507e2123f968507894c7f69163d Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 13 Jun 2024 14:02:39 +0200 Subject: [PATCH 03/17] WIP: mess detect - unused code --- .../backup_moodleoverflow_stepslib.php | 25 ++++++++----------- classes/capabilities.php | 3 --- classes/manager/mail_manager.php | 5 ++-- classes/ratings.php | 2 -- classes/readtracking.php | 4 +-- classes/subscriptions.php | 5 ++-- classes/tables/userstats_table.php | 1 + lib.php | 5 ++-- post.php | 6 ++--- 9 files changed, 21 insertions(+), 35 deletions(-) diff --git a/backup/moodle2/backup_moodleoverflow_stepslib.php b/backup/moodle2/backup_moodleoverflow_stepslib.php index 8c803d438c..aa56787799 100644 --- a/backup/moodle2/backup_moodleoverflow_stepslib.php +++ b/backup/moodle2/backup_moodleoverflow_stepslib.php @@ -39,16 +39,14 @@ class backup_moodleoverflow_activity_structure_step extends backup_activity_stru * @return backup_nested_element */ protected function define_structure() { - // To know if we are including userinfo. $userinfo = $this->get_setting_value('userinfo'); // Define the root element describing the moodleoverflow instance. $moodleoverflow = new backup_nested_element('moodleoverflow', ['id'], [ - 'name', 'intro', 'introformat', 'maxbytes', 'maxattachments', 'timecreated', 'timemodified', - 'forcesubscribe', 'trackingtype', 'ratingpreference', 'coursewidereputation', 'allowrating', - 'allowreputation', 'allownegativereputation', 'grademaxgrade', 'gradescalefactor', 'gradecat', - 'anonymous', 'allowmultiplemarks', ]); + 'name', 'intro', 'introformat', 'maxbytes', 'maxattachments', 'timecreated', 'timemodified', 'forcesubscribe', + 'trackingtype', 'ratingpreference', 'coursewidereputation', 'allowrating', 'allowreputation', 'allownegativereputation', + 'grademaxgrade', 'gradescalefactor', 'gradecat', 'anonymous', 'allowmultiplemarks', ]); // Define each element separated. $discussions = new backup_nested_element('discussions'); @@ -56,24 +54,20 @@ protected function define_structure() { 'name', 'firstpost', 'userid', 'timestart', 'timemodified', 'usermodified', ]); $posts = new backup_nested_element('posts'); - $post = new backup_nested_element('post', ['id'], [ - 'parent', 'userid', 'created', 'modified', - 'message', 'messageformat', 'attachment', 'mailed', 'reviewed', 'timereviewed', ]); + $post = new backup_nested_element('post', ['id'], ['parent', 'userid', 'created', 'modified', 'message', + 'messageformat', 'attachment', 'mailed', 'reviewed', 'timereviewed', ]); $ratings = new backup_nested_element('ratings'); - $rating = new backup_nested_element('rating', ['id'], [ - 'userid', 'rating', 'firstrated', 'lastchanged', ]); + $rating = new backup_nested_element('rating', ['id'], ['userid', 'rating', 'firstrated', 'lastchanged']); $discussionsubs = new backup_nested_element('discuss_subs'); - $discussionsub = new backup_nested_element('discuss_sub', ['id'], [ - 'userid', 'preference', ]); + $discussionsub = new backup_nested_element('discuss_sub', ['id'], ['userid', 'preference']); $subscriptions = new backup_nested_element('subscriptions'); $subscription = new backup_nested_element('subscription', ['id'], ['userid']); $readposts = new backup_nested_element('readposts'); - $read = new backup_nested_element('read', ['id'], [ - 'userid', 'discussionid', 'postid', 'firstread', 'lastread', ]); + $read = new backup_nested_element('read', ['id'], ['userid', 'discussionid', 'postid', 'firstread', 'lastread']); $grades = new backup_nested_element('grades'); $grade = new backup_nested_element('grade', ['id'], ['userid', 'grade']); @@ -100,6 +94,9 @@ protected function define_structure() { $moodleoverflow->add_child($readposts); $readposts->add_child($read); + $moodleoverflow->add_child($grades); + $grades->add_child($grade); + $moodleoverflow->add_child($tracking); $tracking->add_child($track); diff --git a/classes/capabilities.php b/classes/capabilities.php index 7a6f72eb3d..064d2c76c3 100644 --- a/classes/capabilities.php +++ b/classes/capabilities.php @@ -74,9 +74,6 @@ class capabilities { /** capability review post to be published*/ const REVIEW_POST = 'mod/moodleoverflow:reviewpost'; - /** @var array cache capabilities*/ - private static $cache = []; - /** * Saves the cache from has_capability. * diff --git a/classes/manager/mail_manager.php b/classes/manager/mail_manager.php index 9fc7118b0a..0ee2f1fbb5 100644 --- a/classes/manager/mail_manager.php +++ b/classes/manager/mail_manager.php @@ -65,7 +65,7 @@ class mail_manager { * @return bool */ public static function moodleoverflow_send_mails(): bool { - global $DB, $CFG, $PAGE; + global $DB, $PAGE; // Get the course object of the top level site. $site = get_site(); @@ -129,7 +129,7 @@ public static function moodleoverflow_send_mails(): bool { cron_setup_user($userto); // Reset the caches. - foreach ($coursemodules as $moodleoverflowid => $unused) { + foreach ($coursemodules as $moodleoverflowid) { $coursemodules[$moodleoverflowid]->cache = new stdClass(); $coursemodules[$moodleoverflowid]->cache->caps = []; unset($coursemodules[$moodleoverflowid]->uservisible); @@ -427,7 +427,6 @@ private static function send_post($userto, $post, array &$coursemodules, array & } // Check whether the user is subscribed to the discussion. - $iscm = $coursemodules[$moodleoverflow->id]; $uid = $userto->id; $did = $post->discussion; $issubscribed = subscriptions::is_subscribed($uid, $moodleoverflow, $modulecontext, $did); diff --git a/classes/ratings.php b/classes/ratings.php index 8756545d21..c398b885fd 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -678,8 +678,6 @@ private static function moodleoverflow_check_old_rating($postid, $userid, $oldra * @return bool */ private static function moodleoverflow_can_be_changed($postid, $rating, $userid) { - global $CFG; - // Check if the old read record exists. $old = self::moodleoverflow_check_old_rating($postid, $userid, $rating); if (!$old) { diff --git a/classes/readtracking.php b/classes/readtracking.php index 24d4530498..0905e78fe6 100644 --- a/classes/readtracking.php +++ b/classes/readtracking.php @@ -134,13 +134,11 @@ public static function moodleoverflow_mark_moodleoverflow_read($cm, $userid = nu $discussions = moodleoverflow_get_discussions_unread($cm); // Iterate through all of this discussions. - foreach ($discussions as $discussionid => $amount) { + foreach ($discussions as $discussionid) { // Mark the discussion as read. if (!self::moodleoverflow_mark_discussion_read($discussionid, context_module::instance($cm->id), $userid)) { throw new moodle_exception('markreadfailed', 'moodleoverflow'); - - return false; } } diff --git a/classes/subscriptions.php b/classes/subscriptions.php index 83af4181d2..2063c067f1 100644 --- a/classes/subscriptions.php +++ b/classes/subscriptions.php @@ -216,7 +216,7 @@ public static function fill_subscription_cache($moodleoverflowid, $userid = null $subscriptions = $DB->get_recordset('moodleoverflow_subscriptions', $params, '', 'id, userid'); // Loop through the records. - foreach ($subscriptions as $id => $data) { + foreach ($subscriptions as $data) { // Create a new record if necessary. if (!isset(self::$moodleoverflowcache[$data->userid])) { @@ -985,14 +985,13 @@ public static function moodleoverflow_get_subscribe_link($moodleoverflow, $conte /** * Given a new post, subscribes the user to the thread the post was posted in. * - * @param object $fromform The submitted form * @param \stdClass $moodleoverflow The moodleoverflow record * @param \stdClass $discussion The discussion record * @param \context_module $modulecontext The context of the module * * @return bool */ - public static function moodleoverflow_post_subscription($fromform, $moodleoverflow, $discussion, $modulecontext) { + public static function moodleoverflow_post_subscription($moodleoverflow, $discussion, $modulecontext) { global $USER; // Check for some basic information. diff --git a/classes/tables/userstats_table.php b/classes/tables/userstats_table.php index 677dc7d081..93a771b22e 100644 --- a/classes/tables/userstats_table.php +++ b/classes/tables/userstats_table.php @@ -372,6 +372,7 @@ private function badge_render($number) { public function other_cols($colname, $attempt) { return null; } + /** * Return a student object. * @param \stdClass $user diff --git a/lib.php b/lib.php index 98de9c8765..d596dfb7ac 100644 --- a/lib.php +++ b/lib.php @@ -94,7 +94,6 @@ * @return mixed true if the feature is supported, null if unknown */ function moodleoverflow_supports($feature) { - global $CFG; if (defined('FEATURE_MOD_PURPOSE')) { if ($feature == FEATURE_MOD_PURPOSE) { @@ -230,11 +229,11 @@ function moodleoverflow_refresh_events($courseid = 0) { global $DB; if ($courseid == 0) { - if (!$moodleoverflows = $DB->get_records('moodleoverflow')) { + if (!$DB->get_records('moodleoverflow')) { return true; } } else { - if (!$moodleoverflows = $DB->get_records('moodleoverflow', ['course' => $courseid])) { + if (!$DB->get_records('moodleoverflow', ['course' => $courseid])) { return true; } } diff --git a/post.php b/post.php index 58e959b7c0..3db4edc10f 100644 --- a/post.php +++ b/post.php @@ -687,8 +687,7 @@ $discussion = new \stdClass(); $discussion->id = $fromform->discussion; $discussion->moodleoverflow = $moodleoverflow->id; - \mod_moodleoverflow\subscriptions::moodleoverflow_post_subscription($fromform, - $moodleoverflow, $discussion, $modulecontext); + \mod_moodleoverflow\subscriptions::moodleoverflow_post_subscription($moodleoverflow, $discussion, $modulecontext); // Print a success-message. $message .= '

' . get_string("postaddedsuccess", "moodleoverflow") . '

'; @@ -763,8 +762,7 @@ $event->trigger(); // Subscribe to this thread. $discussion->moodleoverflow = $moodleoverflow->id; - \mod_moodleoverflow\subscriptions::moodleoverflow_post_subscription($fromform, - $moodleoverflow, $discussion, $modulecontext); + \mod_moodleoverflow\subscriptions::moodleoverflow_post_subscription($moodleoverflow, $discussion, $modulecontext); } // Redirect back to te discussion. From 6733fb3ea3b6100f8dddd735b9b5f29d37daa8e2 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 14 Jun 2024 19:56:46 +0200 Subject: [PATCH 04/17] WIP: php mess cleaning --- classes/manager/mail_manager.php | 1 - locallib.php | 4 +- tests/dailymail_test.php | 4 - tests/ratings_test.php | 60 +-- tests/subscriptions_test.php | 747 +++++++++++-------------------- tests/userstats_test.php | 1 - 6 files changed, 287 insertions(+), 530 deletions(-) diff --git a/classes/manager/mail_manager.php b/classes/manager/mail_manager.php index 0ee2f1fbb5..04dbba65e3 100644 --- a/classes/manager/mail_manager.php +++ b/classes/manager/mail_manager.php @@ -86,7 +86,6 @@ public static function moodleoverflow_send_mails(): bool { $moodleoverflows = []; $courses = []; $coursemodules = []; - $subscribedusers = []; // Posts older than x days will not be mailed. // This will avoid problems with the cron not ran for a long time. diff --git a/locallib.php b/locallib.php index 69102f1c6d..299399afe7 100644 --- a/locallib.php +++ b/locallib.php @@ -772,7 +772,7 @@ function moodleoverflow_user_can_see_discussion($moodleoverflow, $discussion, $c } // Retrieve the coursemodule. - if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $moodleoverflow->course)) { + if (!get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $moodleoverflow->course)) { throw new moodle_exception('invalidcoursemodule'); } @@ -1566,7 +1566,7 @@ function moodleoverflow_print_posts_nested($course, &$cm, $moodleoverflow, $disc * @return array */ function get_attachments($post, $cm) { - global $CFG, $OUTPUT; + global $OUTPUT; $attachments = []; if (empty($post->attachment)) { diff --git a/tests/dailymail_test.php b/tests/dailymail_test.php index 5a2f2329b5..f28b52b88e 100644 --- a/tests/dailymail_test.php +++ b/tests/dailymail_test.php @@ -224,10 +224,6 @@ public function test_content_of_mail_delivery(): void { $linktodiscussion = 'discussion[0]->id; - // Assemble text. - $text = 'Course: ' . $linktocourse . ' -> ' . $linktoforum . ', Topic: ' - . $linktodiscussion . ' has ' . $messagecount . ' unread posts.'; - $this->assertStringContainsString($linktocourse, $message); $this->assertStringContainsString($linktoforum, $message); $this->assertStringContainsString($linktodiscussion, $message); diff --git a/tests/ratings_test.php b/tests/ratings_test.php index 1ebf68fcf9..479b133674 100644 --- a/tests/ratings_test.php +++ b/tests/ratings_test.php @@ -61,9 +61,6 @@ final class ratings_test extends \advanced_testcase { /** @var stdClass answer from user 2 */ private $answer6; - /** @var \mod_moodleoverflow_generator $generator */ - private $generator; - /** * Test setUp. */ @@ -77,8 +74,8 @@ public function setUp(): void { */ public function tearDown(): void { // Clear all caches. - \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); - \mod_moodleoverflow\subscriptions::reset_discussion_cache(); + subscriptions::reset_moodleoverflow_cache(); + subscriptions::reset_discussion_cache(); } // Begin of test functions. @@ -163,40 +160,32 @@ public function test_answersorting_twogroups(): void { $this->set_ratingpreferences(0); // Test case 1: helpful and solved post, only solved posts. - $group1 = 'sh'; - $group2 = 's'; - $this->process_groups($group1, $group2); + $this->process_groups('sh', 's'); // Test case 2: helpful and solved post, only helpful posts. - $group2 = 'h'; - $this->process_groups($group1, $group2); + $this->process_groups('sh', 'h'); // Test case 3: helpful and solved post, not-marked posts. - $group2 = 'o'; - $this->process_groups($group1, $group2); + $this->process_groups('sh', 'o'); // Test case 4: only solved posts and only helpful posts with ratingpreferences = 0. - $group1 = 's'; - $group2 = 'h'; $this->set_ratingpreferences(0); $rightorder = [$this->post, $this->answer6, $this->answer5, $this->answer4, $this->answer2, $this->answer1, $this->answer3]; - $this->process_groups($group1, $group2, $rightorder); + $this->process_groups('s', 'h', $rightorder); // Test case 5: only solved posts and only helpful posts with ratingpreferences = 1. $this->set_ratingpreferences(1); - $this->process_groups($group1, $group2); + $this->process_groups('s', 'h'); // Test case 6: only solved posts and not-marked posts. - $group2 = 'o'; - $this->create_twogroups($group1, $group2); + $this->create_twogroups('s', 'o'); $posts = [$this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6]; $rightorder = [$this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4]; $result = $this->postsorderequal(ratings::moodleoverflow_sort_answers_by_ratings($posts), $rightorder); $this->assertEquals(1, $result); // Test case 6: only helpful posts and not-marked posts. - $group1 = 'h'; - $this->process_groups($group1, $group2); + $this->process_groups('h', 'o'); } /** @@ -213,8 +202,7 @@ public function test_answersorting_onegroup(): void { $this->set_ratingpreferences(0); // Test case 1: only solved and helpful posts. - $group = 'sh'; - $this->create_onegroup($group); + $this->create_onegroup('sh'); $posts = [$this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6]; $rightorder = [$this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5]; $result = $this->postsorderequal(ratings::moodleoverflow_sort_answers_by_ratings($posts), $rightorder); @@ -227,8 +215,7 @@ public function test_answersorting_onegroup(): void { $this->assertEquals(1, $result); // Test case 2: only solvedposts. - $group = 's'; - $this->create_onegroup($group); + $this->create_onegroup('s'); $rightorder = [$this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5]; $result = $this->postsorderequal(ratings::moodleoverflow_sort_answers_by_ratings($posts), $rightorder); $this->assertEquals(1, $result); @@ -240,8 +227,7 @@ public function test_answersorting_onegroup(): void { $this->assertEquals(1, $result); // Test case 3: only helpful posts. - $group = 'h'; - $this->create_onegroup($group); + $this->create_onegroup('h'); $rightorder = [$this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5]; $result = $this->postsorderequal(ratings::moodleoverflow_sort_answers_by_ratings($posts), $rightorder); $this->assertEquals(1, $result); @@ -253,8 +239,7 @@ public function test_answersorting_onegroup(): void { $this->assertEquals(1, $result); // Test case 4: only not marked posts. - $group = 'o'; - $this->create_onegroup($group); + $this->create_onegroup('o'); $rightorder = [$this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5]; $result = $this->postsorderequal(ratings::moodleoverflow_sort_answers_by_ratings($posts), $rightorder); $this->assertEquals(1, $result); @@ -292,15 +277,15 @@ private function helper_course_set_up() { $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); // Create a discussion, a parent post and six answers. - $this->generator = $this->getDataGenerator()->get_plugin_generator('mod_moodleoverflow'); - $discussion = $this->generator->post_to_forum($moodleoverflow, $teacher); + $generator = $this->getDataGenerator()->get_plugin_generator('mod_moodleoverflow'); + $discussion = $generator->post_to_forum($moodleoverflow, $teacher); $this->post = $DB->get_record('moodleoverflow_posts', ['id' => $discussion[0]->firstpost], '*'); - $this->answer1 = $this->generator->reply_to_post($discussion[1], $user1, true); - $this->answer2 = $this->generator->reply_to_post($discussion[1], $user1, true); - $this->answer3 = $this->generator->reply_to_post($discussion[1], $user1, true); - $this->answer4 = $this->generator->reply_to_post($discussion[1], $user2, true); - $this->answer5 = $this->generator->reply_to_post($discussion[1], $user2, true); - $this->answer6 = $this->generator->reply_to_post($discussion[1], $user2, true); + $this->answer1 = $generator->reply_to_post($discussion[1], $user1, true); + $this->answer2 = $generator->reply_to_post($discussion[1], $user1, true); + $this->answer3 = $generator->reply_to_post($discussion[1], $user1, true); + $this->answer4 = $generator->reply_to_post($discussion[1], $user2, true); + $this->answer5 = $generator->reply_to_post($discussion[1], $user2, true); + $this->answer6 = $generator->reply_to_post($discussion[1], $user2, true); } @@ -315,7 +300,8 @@ private function postsorderequal($sortedposts, $rightorder) { if (count($sortedposts) != count($rightorder)) { return 0; } - for ($i = 0; $i < count($sortedposts); $i++) { + $numberofposts = count($sortedposts); + for ($i = 0; $i < $numberofposts; $i++) { // Get the current elements. $sortedpost = current($sortedposts); $post = current($rightorder); diff --git a/tests/subscriptions_test.php b/tests/subscriptions_test.php index 7fe9eae71d..4b02a0854c 100644 --- a/tests/subscriptions_test.php +++ b/tests/subscriptions_test.php @@ -45,8 +45,8 @@ final class subscriptions_test extends advanced_testcase { */ public function setUp(): void { // Clear all caches. - \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); - \mod_moodleoverflow\subscriptions::reset_discussion_cache(); + subscriptions::reset_moodleoverflow_cache(); + subscriptions::reset_discussion_cache(); } /** @@ -54,8 +54,8 @@ public function setUp(): void { */ public function tearDown(): void { // Clear all caches. - \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); - \mod_moodleoverflow\subscriptions::reset_discussion_cache(); + subscriptions::reset_moodleoverflow_cache(); + subscriptions::reset_discussion_cache(); } /** @@ -129,34 +129,34 @@ public function test_subscription_modes(): void { $this->setUser($user); // Test the forced subscription. - \mod_moodleoverflow\subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_FORCESUBSCRIBE); + subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_FORCESUBSCRIBE); $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id]); $this->assertEquals(MOODLEOVERFLOW_FORCESUBSCRIBE, - \mod_moodleoverflow\subscriptions::get_subscription_mode($moodleoverflow)); - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_forcesubscribed($moodleoverflow)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $modulecontext)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::subscription_disabled($moodleoverflow)); + subscriptions::get_subscription_mode($moodleoverflow)); + $this->assertTrue(subscriptions::is_forcesubscribed($moodleoverflow)); + $this->assertFalse(subscriptions::is_subscribable($moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::subscription_disabled($moodleoverflow)); // Test the disallowed subscription. - \mod_moodleoverflow\subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_DISALLOWSUBSCRIBE); + subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_DISALLOWSUBSCRIBE); $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id]); - $this->assertTrue(\mod_moodleoverflow\subscriptions::subscription_disabled($moodleoverflow)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $modulecontext)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_forcesubscribed($moodleoverflow)); + $this->assertTrue(subscriptions::subscription_disabled($moodleoverflow)); + $this->assertFalse(subscriptions::is_subscribable($moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::is_forcesubscribed($moodleoverflow)); // Test the initial subscription. - \mod_moodleoverflow\subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_INITIALSUBSCRIBE); + subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_INITIALSUBSCRIBE); $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id]); - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $modulecontext)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::subscription_disabled($moodleoverflow)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_forcesubscribed($moodleoverflow)); + $this->assertTrue(subscriptions::is_subscribable($moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::subscription_disabled($moodleoverflow)); + $this->assertFalse(subscriptions::is_forcesubscribed($moodleoverflow)); // Test the choose subscription. - \mod_moodleoverflow\subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_CHOOSESUBSCRIBE); + subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_CHOOSESUBSCRIBE); $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id]); - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $modulecontext)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::subscription_disabled($moodleoverflow)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_forcesubscribed($moodleoverflow)); + $this->assertTrue(subscriptions::is_subscribable($moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::subscription_disabled($moodleoverflow)); + $this->assertFalse(subscriptions::is_forcesubscribed($moodleoverflow)); } /** @@ -182,7 +182,7 @@ public function test_unsubscribable_moodleoverflows(): void { $this->setUser($user); // Without any subscriptions, there should be nothing returned. - $result = \mod_moodleoverflow\subscriptions::get_unsubscribable_moodleoverflows(); + $result = subscriptions::get_unsubscribable_moodleoverflows(); $this->assertEquals(0, count($result)); // Create the moodleoverflows. @@ -196,15 +196,15 @@ public function test_unsubscribable_moodleoverflows(): void { $this->getDataGenerator()->create_module('moodleoverflow', $options); // At present the user is only subscribed to the initial moodleoverflow. - $result = \mod_moodleoverflow\subscriptions::get_unsubscribable_moodleoverflows(); + $result = subscriptions::get_unsubscribable_moodleoverflows(); $this->assertEquals(1, count($result)); // Ensure that the user is enrolled in all of the moodleoverflows execpt force subscribe. - \mod_moodleoverflow\subscriptions::subscribe_user($user->id, $disallow, $modulecontext); - \mod_moodleoverflow\subscriptions::subscribe_user($user->id, $choose, $modulecontext); + subscriptions::subscribe_user($user->id, $disallow, $modulecontext); + subscriptions::subscribe_user($user->id, $choose, $modulecontext); // At present the user is subscribed to all three moodleoverflows. - $result = \mod_moodleoverflow\subscriptions::get_unsubscribable_moodleoverflows(); + $result = subscriptions::get_unsubscribable_moodleoverflows(); $this->assertEquals(3, count($result)); } @@ -217,16 +217,12 @@ public function test_moodleoverflow_toggle_as_other(): void { // Reset the database after testing. $this->resetAfterTest(true); - // Create a course with a moodleoverflow. + // Create a course with a moodleoverflow. Get the module context and enroll a user in the course as a student. $course = $this->getDataGenerator()->create_course(); $options = ['course' => $course->id]; $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); - - // Get the module context. $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $modulecontext = \context_module::instance($cm->id); - - // Create a user enrolled in the course as a student. list ($author) = $this->helper_create_users($course, 1); // Post a discussion to the moodleoverflow. @@ -236,149 +232,83 @@ public function test_moodleoverflow_toggle_as_other(): void { $discussion->moodleoverflow = $moodleoverflow->id; // Check that the user is currently not subscribed to the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, - $modulecontext)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); // Check that the user is unsubscribed from the discussion too. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, - $modulecontext, $discussion->id)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); + + // Declare the options for the subscription tables. + $discussoptions = ['userid' => $author->id, 'discussion' => $discussion->id]; + $subscriptionoptions = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; // Check thast we have no records in either on the subscription tables. - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(0, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); - // Subscribing to the moodleoverflow should create a record in the subscription table, - // but the moodleoverflow discussion subscriptions table. - \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); + // Subscribing to the moodleoverflow should add a record to the moodleoverflow subscription table. + subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); - // Unsubscribing should remove the record from the moodleoverflow subscription table. - // Do not modify the moodleoverflow discussion subscriptions table. - \mod_moodleoverflow\subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(0, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); + // Unsubscribing should remove the record from the moodleoverflow subscription table. The discussion table stays the same. + subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); - // Enroling the user in the discussion should add one record to the - // moodleoverflow discussion table without modifying the form subscription. - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(0, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); + // Subscribing to the discussion should only add a record to the discussion subscription table. + subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); - // Unsubscribing should remove the record from the moodleoverflow subscriptions - // table and not modify the moodleoverflow discussion subscription table. - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(0, $count); + // Unsubscribing should remove the record from the moodleoverflow subscriptions and modify the discussion subscriptions. + subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); // Resubscribe to the discussion so that we can check the effect of moodleoverflow-level subscriptions. - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(0, $count); + subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); - // Subscribing to the moodleoverflow should have no effect on the moodleoverflow discussion - // subscription table if the user did not request the change himself. - \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); + // Subscribing to the moodleoverflow should have no effect on the discussion subscription. + subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); - // Unsubbing from the moodleoverflow should have no effect on the moodleoverflow - // discussion subscription table if the user did not request the change themself. - \mod_moodleoverflow\subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(0, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); + // Unsubbing from the moodleoverflow should have no effect on the discussion subscription. + subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); - // Subscribing to the moodleoverflow should remove the per-discussion - // subscription preference if the user requested the change themself. - \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext, true); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); + // Subscribing to the moodleoverflow should remove the per-discussion subscription preference if the user wanted the change. + subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext, true); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); // Now unsubscribe from the current discussion whilst being subscribed to the moodleoverflow as a whole. - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); + subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); - // Unsubscribing from the moodleoverflow should remove the per-discussion - // subscription preference if the user requested the change himself. - \mod_moodleoverflow\subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext, true); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(0, $count); - $count = $DB->count_records('moodleoverflow_discuss_subs', [ - 'userid' => $author->id, - 'discussion' => $discussion->id, - ]); - $this->assertEquals(0, $count); + // Unsubscribing from the moodleoverflow should remove per-discussion subscription preference if the user wanted the change. + subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext, true); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); // Subscribe to the discussion. - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(0, $count); - $count = $DB->count_records('moodleoverflow_discuss_subs', [ - 'userid' => $author->id, - 'discussion' => $discussion->id, - ]); - $this->assertEquals(1, $count); + subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); // Subscribe to the moodleoverflow without removing the discussion preferences. - \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); + subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); // Unsubscribe from the discussion should result in a change. - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); + subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); } /** @@ -397,14 +327,14 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_unsub list($author) = $this->helper_create_users($course, 1); // Check that the user is currently not subscribed to the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow)); // Post a discussion to the moodleoverflow. list($discussion, $post) = $this->helper_post_to_moodleoverflow($moodleoverflow, $author); unset($post); // Check that the user is unsubscribed from the discussion too. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow, $discussion)); } @@ -429,21 +359,21 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_subsc // Enrol the user in the moodleoverflow. // If a subscription was added, we get the record ID. - $this->assertIsInt(\mod_moodleoverflow\subscriptions::subscribe_user($author->id, + $this->assertIsInt(subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext)); // If we already have a subscription when subscribing the user, we get a boolean (true). - $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext)); + $this->assertTrue(subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext)); // Check that the user is currently subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); // Post a discussion to the moodleoverflow. list($discussion, $post) = $this->helper_post_to_moodleoverflow($moodleoverflow, $author); unset($post); // Check that the user is subscribed to the discussion too. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion)); } @@ -467,7 +397,7 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_unsub list($author) = $this->helper_create_users($course, 1); // Check that the user is currently not subscribed to the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow)); // Post a discussion to the moodleoverflow. $discussion = new \stdClass(); @@ -476,18 +406,18 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_unsub $discussion->moodleoverflow = $moodleoverflow->id; // Attempting to unsubscribe from the discussion should not make a change. - $this->assertFalse(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, + $this->assertFalse(subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext)); // Then subscribe them to the discussion. - $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, + $this->assertTrue(subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext)); // Check that the user is still unsubscribed from the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow)); // But subscribed to the discussion. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); } @@ -511,10 +441,10 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_subsc list($author) = $this->helper_create_users($course, 2); // Enrol the student in the moodleoverflow. - \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); + subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); // Check that the user is currently subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); // Post a discussion to the moodleoverflow. $discussion = new \stdClass(); @@ -523,13 +453,13 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_subsc $discussion->moodleoverflow = $moodleoverflow->id; // Then unsubscribe them from the discussion. - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); // Check that the user is still subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); // But unsubscribed from the discussion. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); } @@ -538,23 +468,17 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_subsc */ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(): void { global $DB; - // Reset the database after testing. - $this->resetAfterTest(true); + $this->resetAfterTest(); - // Create a course with a moodleoverflow. + // Create a course with a moodleoverflow and enroll two users in the course as students and in the moodleoverflow. $course = $this->getDataGenerator()->create_course(); $options = ['course' => $course->id, 'forcesubscribe' => MOODLEOVERFLOW_CHOOSESUBSCRIBE]; $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); - $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $modulecontext = \context_module::instance($cm->id); - - // Create two users enrolled in the course as students. list($author) = $this->helper_create_users($course, 2); - - // Enrol the student in the moodleoverflow. - \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); + subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext); // Post a discussion to the moodleoverflow. $discussion = new \stdClass(); @@ -562,152 +486,82 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed( unset($post); $discussion->moodleoverflow = $moodleoverflow->id; - // Check that the user is currently subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); - - // Check that the user is initially subscribed to that discussion. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); + // Check that the user is currently subscribed to the moodleoverflow and initially subscribed to that discussion. + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); // An attempt to subscribe again should result in a falsey return to indicate that no change was made. - $this->assertFalse(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, - $discussion, $modulecontext)); + $this->assertFalse(subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext)); - // And there should be no discussion subscriptions (and one moodleoverflow subscription). - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); + // Declare the options for the subscription tables. + $discussoptions = ['userid' => $author->id, 'discussion' => $discussion->id]; + $subscriptionoptions = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - // Then unsubscribe them from the discussion. - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); - - // Check that the user is still subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + // And there should be no discussion subscriptions (and one moodleoverflow subscription). + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); - // An attempt to unsubscribe again should result in a falsey return to indicate that no change was made. - $this->assertFalse(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, - $discussion, $modulecontext)); + // Unsubscribe them from the discussion while still subscribe the moodleoverflow. Attempt to unsubscribe again should fail. + subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext)); // And there should be a discussion subscriptions (and one moodleoverflow subscription). - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); - - // But unsubscribed from the discussion. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); - - // There should be a record in the discussion subscription tracking table. - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); - - // And one in the moodleoverflow subscription tracking table. - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); - - // Now subscribe the user again to the discussion. - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); - - // Check that the user is still subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); - - // And is subscribed to the discussion again. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); - - // And one in the moodleoverflow subscription tracking table. - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); - - // There should be no record in the discussion subscription tracking table. - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); - - // And unsubscribe again. - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); - - // Check that the user is still subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); // But unsubscribed from the discussion. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); - // And one in the moodleoverflow subscription tracking table. - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); + // There should be one record in the discussion and moodleoverflow subscription tracking table. + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); - // There should be a record in the discussion subscription tracking table. - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); + // Now subscribe the user again to the discussion. Now discussion and moodleoverflow should be subscribed. + subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); - // And subscribe the user again to the discussion. - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); + // And one in the moodleoverflow subscription and no record in the discussion tracking table. + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); - // Check that the user is still subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + // And unsubscribe again. Only moodleoverflow should be subscribed. Discussion should be unsubscribed. + subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); - // And is subscribed to the discussion again. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); - - // There should be no record in the discussion subscription tracking table. - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); + // There should be one record in the moodleoverflow and discussion subscription tracking table. + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); - // And one in the forum subscription tracking table. - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); + // And subscribe the user again to the discussion. Both should be subscribed. + subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); - // And unsubscribe again. - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + // There should be no record in the discussion and one in the moodleoverflow subscription tracking table. + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); - // But unsubscribed from the discussion. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); + // And unsubscribe again from the discussion. Only moodleoverflow should be subscribed. + subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); - // Check that the user is still subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); - - // There should be a record in the discussion subscription tracking table. - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); - - // And one in the moodleoverflow subscription tracking table. - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(1, $count); + // There should be a record in the discussion and one in the moodleoverflow subscription tracking table. + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); // Now unsubscribe the user from the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext, - true)); + $this->assertTrue(subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext, true)); // This removes both the moodleoverflow, and the moodleoverflow records. - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); - $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; - $count = $DB->count_records('moodleoverflow_subscriptions', $options); - $this->assertEquals(0, $count); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); // And should have reset the discussion cache value. - $result = \mod_moodleoverflow\subscriptions::fetch_discussion_subscription($moodleoverflow->id, $author->id); + $result = subscriptions::fetch_discussion_subscription($moodleoverflow->id, $author->id); $this->assertIsArray($result); $this->assertFalse(isset($result[$discussion->id])); } @@ -721,20 +575,16 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_unsubscribe // Reset the database after testing. $this->resetAfterTest(true); - // Create a course, with a moodleoverflow. + // Create a course, with a moodleoverflow and get the module context. Create two users enrolled inthe course as students. $course = $this->getDataGenerator()->create_course(); $options = ['course' => $course->id, 'forcesubscribe' => MOODLEOVERFLOW_CHOOSESUBSCRIBE]; $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); - - // Get the module context. $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $modulecontext = \context_module::instance($cm->id); - - // Create two users enrolled in the course as students. list($author) = $this->helper_create_users($course, 2); // Check that the user is currently unsubscribed to the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); // Post a discussion to the moodleoverflow. $discussion = new \stdClass(); @@ -742,54 +592,47 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_unsubscribe unset($post); $discussion->moodleoverflow = $moodleoverflow->id; + // Declare the options for the subscription tables. + $discussoptions = ['userid' => $author->id, 'discussion' => $discussion->id]; + // Check that the user is initially unsubscribed to that discussion. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); // Then subscribe them to the discussion. - $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, - $discussion, $modulecontext)); + $this->assertTrue(subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext)); // An attempt to subscribe again should result in a falsey return to indicate that no change was made. - $this->assertFalse(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, - $discussion, $modulecontext)); + $this->assertFalse(subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext)); // Check that the user is still unsubscribed from the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); // But subscribed to the discussion. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); // There should be a record in the discussion subscription tracking table. - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(1, $count); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); // Now unsubscribe the user again from the discussion. - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); // Check that the user is still unsubscribed from the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); // And is unsubscribed from the discussion again. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); // There should be no record in the discussion subscription tracking table. - $options = ['userid' => $author->id, 'discussion' => $discussion->id]; - $count = $DB->count_records('moodleoverflow_discuss_subs', $options); - $this->assertEquals(0, $count); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); // And subscribe the user again to the discussion. - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); + subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext); // And is subscribed to the discussion again. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); + $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); // Check that the user is still unsubscribed from the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); // There should be a record in the discussion subscription tracking table. $options = ['userid' => $author->id, 'discussion' => $discussion->id]; @@ -797,14 +640,13 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_unsubscribe $this->assertEquals(1, $count); // And unsubscribe again. - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); + subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext); // But unsubscribed from the discussion. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, - $discussion->id)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext, $discussion->id)); // Check that the user is still unsubscribed from the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext)); // There should be no record in the discussion subscription tracking table. $options = ['userid' => $author->id, 'discussion' => $discussion->id]; @@ -822,37 +664,34 @@ public function test_fetch_subscribed_users_subscriptions(): void { // Reset the database after testing. $this->resetAfterTest(true); - // Create a course, with a moodleoverflow. where users are initially subscribed. + // Create a course, with a moodleoverflow. where users are initially subscribed and get the module context. $course = $this->getDataGenerator()->create_course(); $options = ['course' => $course->id, 'forcesubscribe' => MOODLEOVERFLOW_INITIALSUBSCRIBE]; $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); - - // Get the module context. $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $modulecontext = \context_module::instance($cm->id); - // Create some user enrolled in the course as a student. + // Create five user enrolled in the course as a student. $usercount = 5; $users = $this->helper_create_users($course, $usercount); // All users should be subscribed. - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); $this->assertEquals($usercount, count($subscribers)); // Subscribe the guest user too to the moodleoverflow - they should never be returned by this function. $this->getDataGenerator()->enrol_user($CFG->siteguest, $course->id); - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); $this->assertEquals($usercount, count($subscribers)); // Unsubscribe 2 users. - $unsubscribedcount = 2; - for ($i = 0; $i < $unsubscribedcount; $i++) { - \mod_moodleoverflow\subscriptions::unsubscribe_user($users[$i]->id, $moodleoverflow, $modulecontext); + for ($i = 0; $i < 2; $i++) { + subscriptions::unsubscribe_user($users[$i]->id, $moodleoverflow, $modulecontext); } // The subscription count should now take into account those users who have been unsubscribed. - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); - $this->assertEquals($usercount - $unsubscribedcount, count($subscribers)); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); + $this->assertEquals($usercount - 2, count($subscribers)); } /** @@ -877,7 +716,7 @@ public function test_fetch_subscribed_users_forced(): void { $this->helper_create_users($course, $usercount); // All users should be subscribed. - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); $this->assertEquals($usercount, count($subscribers)); } @@ -910,21 +749,19 @@ public function test_fetch_subscribed_users_discussion_subscriptions(): void { $discussion->moodleoverflow = $moodleoverflow->id; // All users should be subscribed. - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); $this->assertEquals($usercount, count($subscribers)); - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, - true); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, true); $this->assertEquals($usercount, count($subscribers)); - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($users[0]->id, $discussion, $modulecontext); + subscriptions::unsubscribe_user_from_discussion($users[0]->id, $discussion, $modulecontext); // All users should be subscribed. - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); $this->assertEquals($usercount, count($subscribers)); // All users should be subscribed. - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, - true); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, true); $this->assertEquals($usercount, count($subscribers)); // Manually insert an extra subscription for one of the users. @@ -936,35 +773,27 @@ public function test_fetch_subscribed_users_discussion_subscriptions(): void { $DB->insert_record('moodleoverflow_discuss_subs', $record); // The discussion count should not have changed. - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); $this->assertEquals($usercount, count($subscribers)); - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, - true); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, true); $this->assertEquals($usercount, count($subscribers)); // Unsubscribe 2 users. - $unsubscribedcount = 2; - for ($i = 0; $i < $unsubscribedcount; $i++) { - \mod_moodleoverflow\subscriptions::unsubscribe_user($users[$i]->id, $moodleoverflow, $modulecontext); - } + subscriptions::unsubscribe_user($users[0]->id, $moodleoverflow, $modulecontext); + subscriptions::unsubscribe_user($users[1]->id, $moodleoverflow, $modulecontext); // The subscription count should now take into account those users who have been unsubscribed. - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); - $this->assertEquals($usercount - $unsubscribedcount, count($subscribers)); - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, - true); - $this->assertEquals($usercount - $unsubscribedcount, count($subscribers)); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); + $this->assertEquals($usercount - 2, count($subscribers)); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, true); + $this->assertEquals($usercount - 2, count($subscribers)); // Now subscribe one of those users back to the discussion. - $subedusers = 1; - for ($i = 0; $i < $subedusers; $i++) { - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($users[$i]->id, $discussion, $modulecontext); - } - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); - $this->assertEquals($usercount - $unsubscribedcount, count($subscribers)); - $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, - true); - $this->assertEquals($usercount - $unsubscribedcount + $subedusers, count($subscribers)); + subscriptions::subscribe_user_to_discussion($users[0]->id, $discussion, $modulecontext); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext); + $this->assertEquals($usercount - 2, count($subscribers)); + $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null, true); + $this->assertEquals($usercount - 1, count($subscribers)); } /** @@ -972,7 +801,6 @@ public function test_fetch_subscribed_users_discussion_subscriptions(): void { */ public function test_force_subscribed_to_moodleoverflow(): void { global $DB; - // Reset database after testing. $this->resetAfterTest(true); @@ -992,7 +820,7 @@ public function test_force_subscribed_to_moodleoverflow(): void { $this->getDataGenerator()->enrol_user($user->id, $course->id, $roleids['student']); // Check that the user is currently subscribed to the moodleoverflow. - $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($user->id, $moodleoverflow, $context)); + $this->assertTrue(subscriptions::is_subscribed($user->id, $moodleoverflow, $context)); assign_capability('mod/moodleoverflow:allowforcesubscribe', CAP_PROHIBIT, $roleids['student'], $context); @@ -1018,17 +846,17 @@ public function test_subscription_cache_prefill(): void { $users = $this->helper_create_users($course, 20); // Reset the subscription cache. - \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); + subscriptions::reset_moodleoverflow_cache(); // Filling the subscription cache should only use a single query, except for Postgres, which delegates actual reading // to Cursors, thus tripling the amount of queries. We intend to test the cache, though, so no worries. - $this->assertNull(\mod_moodleoverflow\subscriptions::fill_subscription_cache($moodleoverflow->id)); + $this->assertNull(subscriptions::fill_subscription_cache($moodleoverflow->id)); $postfillcount = $DB->perf_get_reads(); // Now fetch some subscriptions from that moodleoverflow - these should use // the cache and not perform additional queries. foreach ($users as $user) { - $this->assertTrue(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($moodleoverflow->id, $user->id)); + $this->assertTrue(subscriptions::fetch_subscription_cache($moodleoverflow->id, $user->id)); } $finalcount = $DB->perf_get_reads(); $this->assertEquals($finalcount, $postfillcount); @@ -1053,14 +881,14 @@ public function test_subscription_cache_fill(): void { $users = $this->helper_create_users($course, 20); // Reset the subscription cache. - \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); + subscriptions::reset_moodleoverflow_cache(); // Filling the subscription cache should only use a single query. $startcount = $DB->perf_get_reads(); // Fetch some subscriptions from that moodleoverflow - these should not use the cache and will perform additional queries. foreach ($users as $user) { - $this->assertTrue(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($moodleoverflow->id, $user->id)); + $this->assertTrue(subscriptions::fetch_subscription_cache($moodleoverflow->id, $user->id)); } $finalcount = $DB->perf_get_reads(); $this->assertEquals(20, $finalcount - $startcount); @@ -1080,34 +908,35 @@ public function test_discussion_subscription_cache_fill_for_course(): void { // Create the moodleoverflows. $options = ['course' => $course->id, 'forcesubscribe' => MOODLEOVERFLOW_DISALLOWSUBSCRIBE]; - $disallowmoodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); + $disallowobject = $this->getDataGenerator()->create_module('moodleoverflow', $options); $options = ['course' => $course->id, 'forcesubscribe' => MOODLEOVERFLOW_CHOOSESUBSCRIBE]; - $choosemoodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); + $chooseobject = $this->getDataGenerator()->create_module('moodleoverflow', $options); $options = ['course' => $course->id, 'forcesubscribe' => MOODLEOVERFLOW_INITIALSUBSCRIBE]; - $initialmoodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); + $initialobject = $this->getDataGenerator()->create_module('moodleoverflow', $options); // Create some users and keep a reference to the first user. $users = $this->helper_create_users($course, 20); $user = reset($users); // Reset the subscription caches. - \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); + subscriptions::reset_moodleoverflow_cache(); - $result = \mod_moodleoverflow\subscriptions::fill_subscription_cache_for_course($course->id, $user->id); + $result = subscriptions::fill_subscription_cache_for_course($course->id, $user->id); $this->assertNull($result); $postfillcount = $DB->perf_get_reads(); - $this->assertFalse(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($disallowmoodleoverflow->id, $user->id)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($choosemoodleoverflow->id, $user->id)); - $this->assertTrue(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($initialmoodleoverflow->id, $user->id)); + $this->assertFalse(subscriptions::fetch_subscription_cache($disallowobject->id, $user->id)); + $this->assertFalse(subscriptions::fetch_subscription_cache($chooseobject->id, $user->id)); + $this->assertTrue(subscriptions::fetch_subscription_cache($initialobject->id, $user->id)); $finalcount = $DB->perf_get_reads(); $this->assertEquals(0, $finalcount - $postfillcount); // Test for all users. foreach ($users as $user) { - $result = \mod_moodleoverflow\subscriptions::fill_subscription_cache_for_course($course->id, $user->id); - $this->assertFalse(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($disallowmoodleoverflow->id, $user->id)); - $this->assertFalse(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($choosemoodleoverflow->id, $user->id)); - $this->assertTrue(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($initialmoodleoverflow->id, $user->id)); + $result = subscriptions::fill_subscription_cache_for_course($course->id, $user->id); + $this->assertNull($result); + $this->assertFalse(subscriptions::fetch_subscription_cache($disallowobject->id, $user->id)); + $this->assertFalse(subscriptions::fetch_subscription_cache($chooseobject->id, $user->id)); + $this->assertTrue(subscriptions::fetch_subscription_cache($initialobject->id, $user->id)); } $finalcount = $DB->perf_get_reads(); $reads = $finalcount - $postfillcount; @@ -1162,24 +991,24 @@ public function test_discussion_subscription_cache_prefill(): void { if ($usercount % 2) { continue; } - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion, $modulecontext); + subscriptions::unsubscribe_user_from_discussion($user->id, $data, $modulecontext); $usercount++; } $moodleoverflowcount++; } // Reset the subscription caches. - \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); - \mod_moodleoverflow\subscriptions::reset_discussion_cache(); + subscriptions::reset_moodleoverflow_cache(); + subscriptions::reset_discussion_cache(); // Filling the discussion subscription cache should only use a single query. - $this->assertNull(\mod_moodleoverflow\subscriptions::fill_discussion_subscription_cache($moodleoverflow->id)); + $this->assertNull(subscriptions::fill_discussion_subscription_cache($moodleoverflow->id)); $postfillcount = $DB->perf_get_reads(); // Now fetch some subscriptions from that moodleoverflow - these should use // the cache and not perform additional queries. foreach ($users as $user) { - $result = \mod_moodleoverflow\subscriptions::fetch_discussion_subscription($moodleoverflow->id, $user->id); + $result = subscriptions::fetch_discussion_subscription($moodleoverflow->id, $user->id); $this->assertIsArray($result); } $finalcount = $DB->perf_get_reads(); @@ -1229,22 +1058,22 @@ public function test_discussion_subscription_cache_fill(): void { if ($usercount % 2) { continue; } - \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion, $modulecontext); + subscriptions::unsubscribe_user_from_discussion($user->id, $data, $modulecontext); $usercount++; } $moodleoverflowcount++; } // Reset the subscription caches. - \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); - \mod_moodleoverflow\subscriptions::reset_discussion_cache(); + subscriptions::reset_moodleoverflow_cache(); + subscriptions::reset_discussion_cache(); $startcount = $DB->perf_get_reads(); // Now fetch some subscriptions from that moodleoverflow - these should use // the cache and not perform additional queries. foreach ($users as $user) { - $result = \mod_moodleoverflow\subscriptions::fetch_discussion_subscription($moodleoverflow->id, $user->id); + $result = subscriptions::fetch_discussion_subscription($moodleoverflow->id, $user->id); $this->assertIsArray($result); } $finalcount = $DB->perf_get_reads(); @@ -1268,16 +1097,12 @@ public function test_moodleoverflow_subscribe_toggle_as_other_repeat_subscriptio // Reset the database after testing. $this->resetAfterTest(true); - // Create a course, with a moodleoverflow. + // Create a course, with a moodleoverflow and get the module context. Create a user enrolled in the course as a student. $course = $this->getDataGenerator()->create_course(); $options = ['course' => $course->id, 'forcesubscribe' => MOODLEOVERFLOW_CHOOSESUBSCRIBE]; $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); - - // Get the module context. $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $modulecontext = \context_module::instance($cm->id); - - // Create a user enrolled in the course as a student. list($user) = $this->helper_create_users($course, 1); // Post a discussion to the moodleoverflow. @@ -1286,73 +1111,52 @@ public function test_moodleoverflow_subscribe_toggle_as_other_repeat_subscriptio unset($post); $discussion->moodleoverflow = $moodleoverflow->id; + // Declare the options for the subscription tables. + $discussoptions = ['userid' => $author->id, 'discussion' => $discussion->id]; + $subscriptionoptions = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; + // Confirm that the user is currently not subscribed to the moodleoverflow. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($user->id, $moodleoverflow, $modulecontext)); + $this->assertFalse(subscriptions::is_subscribed($user->id, $moodleoverflow, $modulecontext)); // Confirm that the user is unsubscribed from the discussion too. - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($user->id, $moodleoverflow, $modulecontext, - $discussion->id)); + $this->assertFalse(subscriptions::is_subscribed($user->id, $moodleoverflow, $modulecontext, $discussion->id)); // Confirm that we have no records in either of the subscription tables. - $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', [ - 'userid' => $user->id, - 'moodleoverflow' => $moodleoverflow->id, - ])); - $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', [ - 'userid' => $user->id, - 'discussion' => $discussion->id, - ])); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); // Subscribing to the moodleoverflow should create a record in the subscriptions table, // but not the moodleoverflow discussion subscriptions table. - \mod_moodleoverflow\subscriptions::subscribe_user($user->id, $moodleoverflow, $modulecontext); - $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', [ - 'userid' => $user->id, - 'moodleoverflow' => $moodleoverflow->id, - ])); - $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', [ - 'userid' => $user->id, - 'discussion' => $discussion->id, - ])); + subscriptions::subscribe_user($user->id, $moodleoverflow, $modulecontext); + $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); // Now unsubscribe from the discussion. This should return true. $uid = $user->id; - $this->assertTrue(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext)); + $this->assertTrue(subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext)); // Attempting to unsubscribe again should return false because no change was made. - $this->assertFalse(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext)); + $this->assertFalse(subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext)); // Subscribing to the discussion again should return truthfully as the subscription preference was removed. - $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext)); + $this->assertTrue(subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext)); // Attempting to subscribe again should return false because no change was made. - $this->assertFalse(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext)); + $this->assertFalse(subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext)); // Now unsubscribe from the discussion. This should return true once more. - $this->assertTrue(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext)); + $this->assertTrue(subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext)); // And unsubscribing from the moodleoverflow but not as a request from the user should maintain their preference. - \mod_moodleoverflow\subscriptions::unsubscribe_user($user->id, $moodleoverflow, $modulecontext); + subscriptions::unsubscribe_user($user->id, $moodleoverflow, $modulecontext); - $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', [ - 'userid' => $user->id, - 'moodleoverflow' => $moodleoverflow->id, - ])); - $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', [ - 'userid' => $user->id, - 'discussion' => $discussion->id, - ])); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); // Subscribing to the discussion should return truthfully because a change was made. - $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext)); - $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', [ - 'userid' => $user->id, - 'moodleoverflow' => $moodleoverflow->id, - ])); - $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', [ - 'userid' => $user->id, - 'discussion' => $discussion->id, - ])); + $this->assertTrue(subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext)); + $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', $subscriptionoptions)); + $this->assertEquals(1, $DB->count_records('moodleoverflow_discuss_subs', $discussoptions)); } /** @@ -1361,20 +1165,8 @@ public function test_moodleoverflow_subscribe_toggle_as_other_repeat_subscriptio * @return array */ public static function is_subscribable_moodleoverflows() { - return [ - [ - 'forcesubscribe' => MOODLEOVERFLOW_DISALLOWSUBSCRIBE, - ], - [ - 'forcesubscribe' => MOODLEOVERFLOW_CHOOSESUBSCRIBE, - ], - [ - 'forcesubscribe' => MOODLEOVERFLOW_INITIALSUBSCRIBE, - ], - [ - 'forcesubscribe' => MOODLEOVERFLOW_FORCESUBSCRIBE, - ], - ]; + return [['forcesubscribe' => MOODLEOVERFLOW_DISALLOWSUBSCRIBE], ['forcesubscribe' => MOODLEOVERFLOW_CHOOSESUBSCRIBE], + ['forcesubscribe' => MOODLEOVERFLOW_INITIALSUBSCRIBE], ['forcesubscribe' => MOODLEOVERFLOW_FORCESUBSCRIBE], ]; } /** @@ -1387,7 +1179,6 @@ public static function is_subscribable_provider(): array { foreach (self::is_subscribable_moodleoverflows() as $moodleoverflow) { $data[] = [$moodleoverflow]; } - return $data; } @@ -1407,8 +1198,7 @@ public function test_is_subscribable_logged_out($options): void { $options['course'] = $course->id; $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, - \context_module::instance($moodleoverflow->cmid))); + $this->assertFalse(subscriptions::is_subscribable($moodleoverflow, \context_module::instance($moodleoverflow->cmid))); } /** @@ -1432,8 +1222,7 @@ public function test_is_subscribable_is_guest($options): void { $options['course'] = $course->id; $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); - $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, - \context_module::instance($moodleoverflow->cmid))); + $this->assertFalse(subscriptions::is_subscribable($moodleoverflow, \context_module::instance($moodleoverflow->cmid))); } /** @@ -1442,22 +1231,10 @@ public function test_is_subscribable_is_guest($options): void { */ public static function is_subscribable_loggedin_provider(): array { return [ - [ - ['forcesubscribe' => MOODLEOVERFLOW_DISALLOWSUBSCRIBE], - false, - ], - [ - ['forcesubscribe' => MOODLEOVERFLOW_CHOOSESUBSCRIBE], - true, - ], - [ - ['forcesubscribe' => MOODLEOVERFLOW_INITIALSUBSCRIBE], - true, - ], - [ - ['forcesubscribe' => MOODLEOVERFLOW_FORCESUBSCRIBE], - false, - ], + [['forcesubscribe' => MOODLEOVERFLOW_DISALLOWSUBSCRIBE], false], + [['forcesubscribe' => MOODLEOVERFLOW_CHOOSESUBSCRIBE], true], + [['forcesubscribe' => MOODLEOVERFLOW_INITIALSUBSCRIBE], true], + [['forcesubscribe' => MOODLEOVERFLOW_FORCESUBSCRIBE], false], ]; } @@ -1484,7 +1261,7 @@ public function test_is_subscribable_loggedin($options, $expect): void { $this->getDataGenerator()->enrol_user($user->id, $course->id); $this->setUser($user); - $this->assertEquals($expect, \mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, - \context_module::instance($moodleoverflow->cmid))); + $this->assertEquals($expect, subscriptions::is_subscribable($moodleoverflow, + \context_module::instance($moodleoverflow->cmid))); } } diff --git a/tests/userstats_test.php b/tests/userstats_test.php index 080a11dd95..037b1db1f6 100644 --- a/tests/userstats_test.php +++ b/tests/userstats_test.php @@ -230,7 +230,6 @@ public function test_total_anonymous(): void { // Get the current userstats to compare later. $olduserstats = $this->create_statstable(); - $oldupvotesuser1 = $this->get_specific_userstats($olduserstats, $this->user1, 'receivedupvotes'); $oldactivityuser1 = $this->get_specific_userstats($olduserstats, $this->user1, 'forumactivity'); $oldupvotesuser2 = $this->get_specific_userstats($olduserstats, $this->user2, 'receivedupvotes'); From 36d6129a5a7645287dc6511c819baa5950b759f3 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Tue, 18 Jun 2024 14:52:59 +0200 Subject: [PATCH 05/17] WIP: phpmd for privacy provider test --- tests/privacy_provider_test.php | 252 +++++++++++--------------------- tests/subscriptions_test.php | 4 +- 2 files changed, 91 insertions(+), 165 deletions(-) diff --git a/tests/privacy_provider_test.php b/tests/privacy_provider_test.php index 706f291340..63cd0b3ce0 100644 --- a/tests/privacy_provider_test.php +++ b/tests/privacy_provider_test.php @@ -28,6 +28,7 @@ use core_privacy\local\request\approved_contextlist; use core_privacy\local\request\userlist; +use core_privacy\local\request\writer; use mod_moodleoverflow\privacy\provider; use mod_moodleoverflow\privacy\data_export_helper; @@ -91,7 +92,7 @@ protected function assert_discussion_data($expected, $actual, $userid) { * * @param object $expected The expected data in the post. * @param object $actual The actual data in the post. - * @param \core_privacy\local\request\writer $writer The writer used + * @param writer $writer The writer used */ protected function assert_post_data($expected, $actual, $writer) { // The message should have been passed through the rewriter. @@ -137,7 +138,7 @@ public function test_user_has_never_posted(): void { // Attempting to export data for this context should return nothing either. $this->export_context_data_for_user($user->id, $context, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context); + $writer = writer::with_context($context); // The provider should always export data for any context explicitly asked of it, but there should be no // metadata, files, or discussions. $this->assertEmpty($writer->get_data([get_string('discussions', 'mod_moodleoverflow')])); @@ -159,7 +160,7 @@ public function test_user_has_never_posted_subscribed_to_forum(): void { $context = \context_module::instance($cm->id); // Subscribe the user to the forum. - \mod_moodleoverflow\subscriptions::subscribe_user($user->id, $forum, $context); + subscriptions::subscribe_user($user->id, $forum, $context); // Retrieve all contexts - only this context should be returned. $contextlist = $this->get_contexts_for_userid($user->id, 'mod_moodleoverflow'); @@ -167,7 +168,7 @@ public function test_user_has_never_posted_subscribed_to_forum(): void { $this->assertEquals($context, $contextlist->current()); // Export all of the data for the context. $this->export_context_data_for_user($user->id, $context, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context); + $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $subcontext = data_export_helper::get_subcontext(); // There should be one item of metadata. @@ -195,14 +196,14 @@ public function test_user_has_never_posted_subscribed_to_discussion(): void { $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); $context = \context_module::instance($cm->id); // Subscribe the user to the discussion. - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($user->id, $discussion, $context); + subscriptions::subscribe_user_to_discussion($user->id, $discussion, $context); // Retrieve all contexts - only this context should be returned. $contextlist = $this->get_contexts_for_userid($user->id, 'mod_moodleoverflow'); $this->assertCount(1, $contextlist); $this->assertEquals($context, $contextlist->current()); // Export all of the data for the context. $this->export_context_data_for_user($user->id, $context, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context); + $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); // There should be nothing in the forum. The user is not subscribed there. $forumsubcontext = data_export_helper::get_subcontext(); @@ -233,7 +234,7 @@ public function test_user_has_posted_own_discussion(): void { list($user, $otheruser) = $this->create_users($course, 2); // Post twice - only the second discussion should be included. list($discussion, $post) = $this->generator->post_to_forum($forum, $user); - list($otherdiscussion, $otherpost) = $this->generator->post_to_forum($forum, $otheruser); + list($otherdiscussion) = $this->generator->post_to_forum($forum, $otheruser); $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); $context = \context_module::instance($cm->id); // Retrieve all contexts - only this context should be returned. @@ -243,7 +244,7 @@ public function test_user_has_posted_own_discussion(): void { // Export all of the data for the context. $this->setUser($user); $this->export_context_data_for_user($user->id, $context, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context); + $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); // The other discussion should not have been returned as we did not post in it. $this->assertEmpty($writer->get_data(data_export_helper::get_subcontext($otherdiscussion))); @@ -263,7 +264,7 @@ public function test_user_has_posted_reply(): void { list($user, $otheruser) = $this->create_users($course, 2); // Post twice - only the second discussion should be included. list($discussion, $post) = $this->generator->post_to_forum($forum, $otheruser); - list($otherdiscussion, $otherpost) = $this->generator->post_to_forum($forum, $otheruser); + list($otherdiscussion) = $this->generator->post_to_forum($forum, $otheruser); $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); $context = \context_module::instance($cm->id); // Post a reply to the other person's post. @@ -276,7 +277,7 @@ public function test_user_has_posted_reply(): void { $this->assertEquals($context, $contextlist->current()); // Export all of the data for the context. $this->export_context_data_for_user($user->id, $context, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context); + $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); // Refresh the discussions. $discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $discussion->id]); @@ -288,8 +289,7 @@ public function test_user_has_posted_reply(): void { $this->assertNotEmpty($data); $this->assert_discussion_data($discussion, $data, $user->id); // The reply will be included. - $this->assert_post_data($reply, - $writer->get_data(data_export_helper::get_subcontext($discussion, $reply)), $writer); + $this->assert_post_data($reply, $writer->get_data(data_export_helper::get_subcontext($discussion, $reply)), $writer); } /** @@ -323,7 +323,7 @@ public function test_user_has_rated_others(): void { $this->assertEquals($context, $contextlist->current()); // Export all of the data for the context. $this->export_context_data_for_user($user->id, $context, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context); + $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); // The discussion should not have been returned as we did not post in it. $this->assertEmpty($writer->get_data(data_export_helper::get_subcontext($discussion))); @@ -345,7 +345,7 @@ public function test_user_has_been_rated(): void { 'course' => $course->id, 'scale' => 100, ]); - list($user, $otheruser, $anotheruser) = $this->create_users($course, 3); + list($user, $otheruser) = $this->create_users($course, 3); list($discussion, $post) = $this->generator->post_to_forum($forum, $user); $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); $context = \context_module::instance($cm->id); @@ -366,7 +366,7 @@ public function test_user_has_been_rated(): void { $this->assertEquals($context, $contextlist->current()); // Export all of the data for the context. $this->export_context_data_for_user($user->id, $context, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context); + $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $ratingdata = $writer->get_related_data(data_export_helper::get_subcontext($discussion, $post), 'rating'); @@ -383,11 +383,10 @@ public function test_user_tracking_data(): void { $cmoff = get_coursemodule_from_instance('moodleoverflow', $forumoff->id); $contextoff = \context_module::instance($cmoff->id); $forumon = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); - $cmon = get_coursemodule_from_instance('moodleoverflow', $forumon->id); list($user) = $this->create_users($course, 1); // Set user tracking data. - \mod_moodleoverflow\readtracking::moodleoverflow_stop_tracking($forumoff->id, $user->id); - \mod_moodleoverflow\readtracking::moodleoverflow_start_tracking($forumon->id, $user->id); + readtracking::moodleoverflow_stop_tracking($forumoff->id, $user->id); + readtracking::moodleoverflow_start_tracking($forumon->id, $user->id); // Run as the user under test. $this->setUser($user); // Retrieve all contexts - only the forum tracking reads should be included. @@ -396,8 +395,7 @@ public function test_user_tracking_data(): void { $this->assertEquals($contextoff, $contextlist->current()); // Check export data for each context. $this->export_context_data_for_user($user->id, $contextoff, 'mod_moodleoverflow'); - $this->assertEquals(0, - \core_privacy\local\request\writer::with_context($contextoff)->get_metadata([], 'trackreadpreference')); + $this->assertEquals(0, writer::with_context($contextoff)->get_metadata([], 'trackreadpreference')); } /** @@ -415,9 +413,6 @@ public function test_user_read_posts(): void { $forum3 = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $cm3 = get_coursemodule_from_instance('moodleoverflow', $forum3->id); $context3 = \context_module::instance($cm3->id); - $forum4 = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); - $cm4 = get_coursemodule_from_instance('moodleoverflow', $forum4->id); - $context4 = \context_module::instance($cm4->id); list($author, $user) = $this->create_users($course, 2); list($f1d1, $f1p1) = $this->generator->post_to_forum($forum1, $author); $f1p1reply = $this->generator->post_to_discussion($forum1, $f1d1, $author); @@ -431,101 +426,67 @@ public function test_user_read_posts(): void { $f3p1reply = $this->generator->post_to_discussion($forum3, $f3d1, $author); $f3d1 = $DB->get_record('moodleoverflow_discussions', ['id' => $f3d1->id]); list($f3d2, $f3p2) = $this->generator->post_to_forum($forum3, $author); - list($f4d1, $f4p1) = $this->generator->post_to_forum($forum4, $author); - $f4p1reply = $this->generator->post_to_discussion($forum4, $f4d1, $author); - $f4d1 = $DB->get_record('moodleoverflow_discussions', ['id' => $f4d1->id]); - list($f4d2, $f4p2) = $this->generator->post_to_forum($forum4, $author); + // Insert read info. // User has read post1, but not the reply or second post in forum1. - \mod_moodleoverflow\readtracking::moodleoverflow_add_read_record($user->id, $f1p1->id); + readtracking::moodleoverflow_add_read_record($user->id, $f1p1->id); // User has read post1 and its reply, but not the second post in forum2. - \mod_moodleoverflow\readtracking::moodleoverflow_add_read_record($user->id, $f2p1->id); - \mod_moodleoverflow\readtracking::moodleoverflow_add_read_record($user->id, $f2p1reply->id); + readtracking::moodleoverflow_add_read_record($user->id, $f2p1->id); + readtracking::moodleoverflow_add_read_record($user->id, $f2p1reply->id); // User has read post2 in forum3. - \mod_moodleoverflow\readtracking::moodleoverflow_add_read_record($user->id, $f3p2->id); + readtracking::moodleoverflow_add_read_record($user->id, $f3p2->id); // Nothing has been read in forum4. // Run as the user under test. $this->setUser($user); // Retrieve all contexts - should be three - forum4 has no data. $contextlist = $this->get_contexts_for_userid($user->id, 'mod_moodleoverflow'); $this->assertCount(3, $contextlist); - $contextids = [ - $context1->id, - $context2->id, - $context3->id, - ]; + $contextids = [$context1->id, $context2->id, $context3->id]; sort($contextids); $contextlistids = $contextlist->get_contextids(); sort($contextlistids); $this->assertEquals($contextids, $contextlistids); // Forum 1. $this->export_context_data_for_user($user->id, $context1, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context1); + $writer = writer::with_context($context1); // User has read f1p1. - $readdata = $writer->get_metadata( - data_export_helper::get_subcontext($f1d1, $f1p1), - 'postread' - ); + $readdata = $writer->get_metadata(data_export_helper::get_subcontext($f1d1, $f1p1), 'postread'); $this->assertNotEmpty($readdata); $this->assertTrue(isset($readdata->firstread)); $this->assertTrue(isset($readdata->lastread)); // User has not f1p1reply. - $readdata = $writer->get_metadata( - data_export_helper::get_subcontext($f1d1, $f1p1reply), - 'postread' - ); + $readdata = $writer->get_metadata(data_export_helper::get_subcontext($f1d1, $f1p1reply), 'postread'); $this->assertEmpty($readdata); // User has not f1p2. - $readdata = $writer->get_metadata( - data_export_helper::get_subcontext($f1d2, $f1p2), - 'postread' - ); + $readdata = $writer->get_metadata(data_export_helper::get_subcontext($f1d2, $f1p2), 'postread'); $this->assertEmpty($readdata); // Forum 2. $this->export_context_data_for_user($user->id, $context2, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context2); + $writer = writer::with_context($context2); // User has read f2p1. - $readdata = $writer->get_metadata( - data_export_helper::get_subcontext($f2d1, $f2p1), - 'postread' - ); + $readdata = $writer->get_metadata(data_export_helper::get_subcontext($f2d1, $f2p1), 'postread'); $this->assertNotEmpty($readdata); $this->assertTrue(isset($readdata->firstread)); $this->assertTrue(isset($readdata->lastread)); // User has read f2p1reply. - $readdata = $writer->get_metadata( - data_export_helper::get_subcontext($f2d1, $f2p1reply), - 'postread' - ); + $readdata = $writer->get_metadata(data_export_helper::get_subcontext($f2d1, $f2p1reply), 'postread'); $this->assertNotEmpty($readdata); $this->assertTrue(isset($readdata->firstread)); $this->assertTrue(isset($readdata->lastread)); // User has not read f2p2. - $readdata = $writer->get_metadata( - data_export_helper::get_subcontext($f2d2, $f2p2), - 'postread' - ); + $readdata = $writer->get_metadata(data_export_helper::get_subcontext($f2d2, $f2p2), 'postread'); $this->assertEmpty($readdata); // Forum 3. $this->export_context_data_for_user($user->id, $context3, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context3); + $writer = writer::with_context($context3); // User has not read f3p1. - $readdata = $writer->get_metadata( - data_export_helper::get_subcontext($f3d1, $f3p1), - 'postread' - ); + $readdata = $writer->get_metadata(data_export_helper::get_subcontext($f3d1, $f3p1), 'postread'); $this->assertEmpty($readdata); // User has not read f3p1reply. - $readdata = $writer->get_metadata( - data_export_helper::get_subcontext($f3d1, $f3p1reply), - 'postread' - ); + $readdata = $writer->get_metadata(data_export_helper::get_subcontext($f3d1, $f3p1reply), 'postread'); $this->assertEmpty($readdata); // User has read f3p2. - $readdata = $writer->get_metadata( - data_export_helper::get_subcontext($f3d2, $f3p2), - 'postread' - ); + $readdata = $writer->get_metadata(data_export_helper::get_subcontext($f3d2, $f3p2), 'postread'); $this->assertNotEmpty($readdata); $this->assertTrue(isset($readdata->firstread)); $this->assertTrue(isset($readdata->lastread)); @@ -538,45 +499,34 @@ public function test_post_attachment_inclusion(): void { global $DB; $fs = get_file_storage(); $course = $this->getDataGenerator()->create_course(); - list($author, $otheruser) = $this->create_users($course, 2); - $forum = $this->getDataGenerator()->create_module('moodleoverflow', [ - 'course' => $course->id, - 'scale' => 100, - ]); + list($author) = $this->create_users($course, 2); + $forum = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id, 'scale' => 100]); $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); $context = \context_module::instance($cm->id); // Create a new discussion + post in the forum. list($discussion, $post) = $this->generator->post_to_forum($forum, $author); $discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $discussion->id]); // Add a number of replies. + $this->generator->reply_to_post($post, $author); $reply = $this->generator->reply_to_post($post, $author); - $reply = $this->generator->reply_to_post($post, $author); - $reply = $this->generator->reply_to_post($reply, $author); - $posts[$reply->id] = $reply; + $this->generator->reply_to_post($reply, $author); // Add a fake inline image to the original post. - $createdfile = $fs->create_file_from_string([ - 'contextid' => $context->id, - 'component' => 'mod_moodleoverflow', - 'filearea' => 'attachment', - 'itemid' => $post->id, - 'filepath' => '/', - 'filename' => 'example.jpg', - ], - 'image contents (not really)'); + $createdfile = $fs->create_file_from_string(['contextid' => $context->id, 'component' => 'mod_moodleoverflow', + 'filearea' => 'attachment', 'itemid' => $post->id, 'filepath' => '/', 'filename' => 'example.jpg', ], + 'image contents (not really)'); // Create a second discussion + post in the forum without tags. list($otherdiscussion, $otherpost) = $this->generator->post_to_forum($forum, $author); - $otherdiscussion = $DB->get_record('moodleoverflow_discussions', ['id' => $otherdiscussion->id]); // Add a number of replies. - $reply = $this->generator->reply_to_post($otherpost, $author); - $reply = $this->generator->reply_to_post($otherpost, $author); + $this->generator->reply_to_post($otherpost, $author); + $this->generator->reply_to_post($otherpost, $author); // Run as the user under test. $this->setUser($author); // Retrieve all contexts - should be one. $contextlist = $this->get_contexts_for_userid($author->id, 'mod_moodleoverflow'); $this->assertCount(1, $contextlist); $this->export_context_data_for_user($author->id, $context, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context); + $writer = writer::with_context($context); // The inline file should be on the first forum post. $subcontext = data_export_helper::get_subcontext($discussion, $post); $foundfiles = $writer->get_files($subcontext); @@ -597,10 +547,7 @@ public function test_all_users_deleted_from_context(): void { $forums = []; $contexts = []; for ($i = 0; $i < 2; $i++) { - $forum = $this->getDataGenerator()->create_module('moodleoverflow', [ - 'course' => $course->id, - 'scale' => 100, - ]); + $forum = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id, 'scale' => 100]); $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); $context = \context_module::instance($cm->id); $forums[$forum->id] = $forum; @@ -640,13 +587,11 @@ public function test_all_users_deleted_from_context(): void { foreach ($posts as $post) { $discussion = $discussions[$post->discussion]; $forum = $forums[$discussion->moodleoverflow]; - $context = $contexts[$forum->id]; // Mark the post as being read by user. - \mod_moodleoverflow\readtracking::moodleoverflow_add_read_record($user->id, $post->id); + readtracking::moodleoverflow_add_read_record($user->id, $post->id); // Rate the other users content. if ($post->userid != $user->id) { $ratedposts[$post->id] = $post; - $rating = []; $rating['moodleoverflowid'] = $forum->id; $rating['discussionid'] = $discussion->id; @@ -736,10 +681,7 @@ public function test_delete_data_for_user(): void { $forums = []; $contexts = []; for ($i = 0; $i < 2; $i++) { - $forum = $this->getDataGenerator()->create_module('moodleoverflow', [ - 'course' => $course->id, - 'scale' => 100, - ]); + $forum = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id, 'scale' => 100]); $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); $context = \context_module::instance($cm->id); $forums[$forum->id] = $forum; @@ -759,7 +701,6 @@ public function test_delete_data_for_user(): void { $postsbyforum[$user->id][$context->id] = []; // Add a number of replies. $posts[$post->id] = $post; - $thisforumposts[$post->id] = $post; $postsbyforum[$user->id][$context->id][$post->id] = $post; $reply = $this->generator->reply_to_post($post, $user); $posts[$reply->id] = $reply; @@ -786,20 +727,16 @@ public function test_delete_data_for_user(): void { foreach ($posts as $post) { $discussion = $discussions[$post->discussion]; $forum = $forums[$discussion->moodleoverflow]; - $context = $contexts[$forum->id]; // Mark the post as being read by user1. - \mod_moodleoverflow\readtracking::moodleoverflow_add_read_record($user1->id, $post->id); + readtracking::moodleoverflow_add_read_record($user1->id, $post->id); } // Rate and tag all posts. - $ratedposts = []; foreach ($users as $user) { foreach ($posts as $post) { $discussion = $discussions[$post->discussion]; $forum = $forums[$discussion->moodleoverflow]; - $context = $contexts[$forum->id]; // Rate the other users content. if ($post->userid != $user->id) { - $ratedposts[$post->id] = $post; $rating = []; $rating['moodleoverflowid'] = $forum->id; @@ -967,13 +904,12 @@ public function test_delete_data_for_users(): void { $discussions = []; $posts = []; - $postsbymoodleoverflow = []; + $postsbyforum = []; // Foreach of the 5 users and foreach of the two Moodleoverflows a post and discussion is created. // Additionally, 3 replies to each discussion are created. - // Last but not least the original post gets a fake image and attachement. - $counter = 0; + // Last but not least the original post gets a fake image and attachment. foreach ($users as $user) { - $postsbymoodleoverflow[$user->id] = []; + $postsbyforum[$user->id] = []; foreach ($moodleoverflows as $moodleoverflow) { $context = $contexts[$moodleoverflow->id]; @@ -982,24 +918,23 @@ public function test_delete_data_for_users(): void { $discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $discussion->id]); $discussions[$discussion->id] = $discussion; - $postsbymoodleoverflow[$user->id][$context->id] = []; + $postsbyforum[$user->id][$context->id] = []; // Add a number of replies. $posts[$post->id] = $post; - $thismoodleoverflowposts[$post->id] = $post; - $postsbymoodleoverflow[$user->id][$context->id][$post->id] = $post; + $postsbyforum[$user->id][$context->id][$post->id] = $post; $reply = $this->generator->reply_to_post($post, $user); $posts[$reply->id] = $reply; - $postsbymoodleoverflow[$user->id][$context->id][$reply->id] = $reply; + $postsbyforum[$user->id][$context->id][$reply->id] = $reply; $reply = $this->generator->reply_to_post($post, $user); $posts[$reply->id] = $reply; - $postsbymoodleoverflow[$user->id][$context->id][$reply->id] = $reply; + $postsbyforum[$user->id][$context->id][$reply->id] = $reply; $reply = $this->generator->reply_to_post($reply, $user); $posts[$reply->id] = $reply; - $postsbymoodleoverflow[$user->id][$context->id][$reply->id] = $reply; + $postsbyforum[$user->id][$context->id][$reply->id] = $reply; // Add a fake inline image to the original post. $fs->create_file_from_string([ @@ -1026,7 +961,7 @@ public function test_delete_data_for_users(): void { $user1 = reset($users); foreach ($posts as $post) { // Mark the post as being read by user1. - \mod_moodleoverflow\readtracking::moodleoverflow_add_read_record($user1->id, $post->id); + readtracking::moodleoverflow_add_read_record($user1->id, $post->id); } // Rate all posts (Every user every post). @@ -1109,7 +1044,7 @@ public function test_delete_data_for_users(): void { // Get all the post ids where files should be deleted. $deletedpostids = []; $otherpostids = []; - foreach ($postsbymoodleoverflow as $user => $contexts) { + foreach ($postsbyforum as $user => $contexts) { foreach ($contexts as $thiscontextid => $theseposts) { $thesepostids = array_map(function($post) { return $post->id; @@ -1139,7 +1074,6 @@ public function test_delete_data_for_users(): void { * Ensure that the discussion author is listed as a user in the context. */ public function test_get_users_in_context_post_author(): void { - global $DB; $component = 'mod_moodleoverflow'; $course = $this->getDataGenerator()->create_course(); @@ -1208,7 +1142,7 @@ public function test_get_users_in_context_post_ratings(): void { $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $context = \context_module::instance($cm->id); - list($author, $user, $other) = $this->create_users($course, 3); + list($author, $user) = $this->create_users($course, 3); list($fd1, $fp1) = $this->generator->post_to_forum($moodleoverflow, $author); $time = time(); @@ -1223,8 +1157,8 @@ public function test_get_users_in_context_post_ratings(): void { ]; // Inserts a rating into the table. $DB->insert_record('moodleoverflow_ratings', $rating); - $userlist = new \core_privacy\local\request\userlist($context, $component); - \mod_moodleoverflow\privacy\provider::get_users_in_context($userlist); + $userlist = new userlist($context, $component); + provider::get_users_in_context($userlist); // Two users - author and rater. $this->assertCount(2, $userlist); @@ -1241,7 +1175,6 @@ public function test_get_users_in_context_post_ratings(): void { * Ensure that all users with a moodleoverflow subscription preference included as a user in the context. */ public function test_get_users_in_context_with_subscription(): void { - global $DB; $component = 'mod_moodleoverflow'; $course = $this->getDataGenerator()->create_course(); @@ -1250,17 +1183,13 @@ public function test_get_users_in_context_with_subscription(): void { $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $context = \context_module::instance($cm->id); - $othermoodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); - $othercm = get_coursemodule_from_instance('moodleoverflow', $othermoodleoverflow->id); - $othercontext = \context_module::instance($othercm->id); - - list($user, $otheruser) = $this->create_users($course, 2); + list($user) = $this->create_users($course, 2); // Subscribe the user to the moodleoverflow. - \mod_moodleoverflow\subscriptions::subscribe_user($user->id, $moodleoverflow, $context); + subscriptions::subscribe_user($user->id, $moodleoverflow, $context); - $userlist = new \core_privacy\local\request\userlist($context, $component); - \mod_moodleoverflow\privacy\provider::get_users_in_context($userlist); + $userlist = new userlist($context, $component); + provider::get_users_in_context($userlist); // One user - the one with a digest preference. $this->assertCount(1, $userlist); @@ -1291,15 +1220,15 @@ public function test_get_users_in_context_with_discussion_subscription(): void { list($author, $user, $otheruser) = $this->create_users($course, 3); // Post in both of the moodleoverflows. - list($fd1, $fp1) = $this->generator->post_to_forum($moodleoverflow, $author); - list($ofd1, $ofp1) = $this->generator->post_to_forum($othermoodleoverflow, $author); + list($fd1) = $this->generator->post_to_forum($moodleoverflow, $author); + list($ofd1) = $this->generator->post_to_forum($othermoodleoverflow, $author); // Subscribe the user to the discussions. - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($user->id, $fd1, $context); - \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($otheruser->id, $ofd1, $context); + subscriptions::subscribe_user_to_discussion($user->id, $fd1, $context); + subscriptions::subscribe_user_to_discussion($otheruser->id, $ofd1, $context); - $userlist = new \core_privacy\local\request\userlist($context, $component); - \mod_moodleoverflow\privacy\provider::get_users_in_context($userlist); + $userlist = new userlist($context, $component); + provider::get_users_in_context($userlist); // Two users - the author, and the one who subscribed. $this->assertCount(2, $userlist); @@ -1336,11 +1265,11 @@ public function test_get_users_in_context_with_read_post_tracking(): void { list($ofd1, $ofp1) = $this->generator->post_to_forum($othermoodleoverflow, $author); // Add read information for those users. - \mod_moodleoverflow\readtracking::moodleoverflow_add_read_record($user->id, $fp1->id); - \mod_moodleoverflow\readtracking::moodleoverflow_add_read_record($otheruser->id, $ofp1->id); + readtracking::moodleoverflow_add_read_record($user->id, $fp1->id); + readtracking::moodleoverflow_add_read_record($otheruser->id, $ofp1->id); - $userlist = new \core_privacy\local\request\userlist($context, $component); - \mod_moodleoverflow\privacy\provider::get_users_in_context($userlist); + $userlist = new userlist($context, $component); + provider::get_users_in_context($userlist); // Two user - the author, and the one who has read the post. $this->assertCount(2, $userlist); @@ -1354,8 +1283,8 @@ public function test_get_users_in_context_with_read_post_tracking(): void { $this->assertEquals($expected, $actual); // Testing again for the other context. - $userlist = new \core_privacy\local\request\userlist($othercontext, $component); - \mod_moodleoverflow\privacy\provider::get_users_in_context($userlist); + $userlist = new userlist($othercontext, $component); + provider::get_users_in_context($userlist); // Two user - the author, and the one who has read the post. $this->assertCount(2, $userlist); @@ -1373,7 +1302,6 @@ public function test_get_users_in_context_with_read_post_tracking(): void { * Ensure that all users with tracking preferences are included as a user in the context. */ public function test_get_users_in_context_with_tracking_preferences(): void { - global $DB; $component = 'mod_moodleoverflow'; $course = $this->getDataGenerator()->create_course(); @@ -1389,11 +1317,11 @@ public function test_get_users_in_context_with_tracking_preferences(): void { list($author, $user, $otheruser) = $this->create_users($course, 3); // Stop tracking the read posts. - \mod_moodleoverflow\readtracking::moodleoverflow_stop_tracking($moodleoverflow->id, $user->id); - \mod_moodleoverflow\readtracking::moodleoverflow_stop_tracking($othermoodleoverflow->id, $otheruser->id); + readtracking::moodleoverflow_stop_tracking($moodleoverflow->id, $user->id); + readtracking::moodleoverflow_stop_tracking($othermoodleoverflow->id, $otheruser->id); - $userlist = new \core_privacy\local\request\userlist($context, $component); - \mod_moodleoverflow\privacy\provider::get_users_in_context($userlist); + $userlist = new userlist($context, $component); + provider::get_users_in_context($userlist); // One user - the one who is tracking that moodleoverflow. $this->assertCount(1, $userlist); @@ -1407,8 +1335,8 @@ public function test_get_users_in_context_with_tracking_preferences(): void { $this->assertEquals($expected, $actual); // Testing the other context. - $userlist = new \core_privacy\local\request\userlist($othercontext, $component); - \mod_moodleoverflow\privacy\provider::get_users_in_context($userlist); + $userlist = new userlist($othercontext, $component); + provider::get_users_in_context($userlist); // One user - the one who is tracking that moodleoverflow. $this->assertCount(1, $userlist); @@ -1442,7 +1370,7 @@ public function test_grades(): void { list($user, $user2) = $this->create_and_enrol_users($course, 2); list( , $post) = $this->generator->post_to_forum($forum, $user); - \mod_moodleoverflow\ratings::moodleoverflow_add_rating($forum, $post->id, RATING_UPVOTE, $cm, $user2->id); + ratings::moodleoverflow_add_rating($forum, $post->id, RATING_UPVOTE, $cm, $user2->id); moodleoverflow_update_all_grades_for_cm($forum->id); $grades = grade_get_grades($course->id, 'mod', 'moodleoverflow', $forum->id, [$user->id, $user2->id]); @@ -1451,7 +1379,7 @@ public function test_grades(): void { // Test export. $this->export_context_data_for_user($user->id, $context, 'mod_moodleoverflow'); - $writer = \core_privacy\local\request\writer::with_context($context); + $writer = writer::with_context($context); $metadata = $writer->get_all_metadata([]); self::assertArrayHasKey('grade', $metadata); self::assertEquals(2.5, $metadata['grade']->value); @@ -1462,16 +1390,14 @@ public function test_grades(): void { self::assertContains("$context->id", $contextlist->get_contextids()); provider::delete_data_for_user($contextlist); moodleoverflow_update_all_grades_for_cm($forum->id); - $grades = $DB->get_records('moodleoverflow_grades', ['moodleoverflowid' => $forum->id], null, - 'userid, grade'); + $grades = $DB->get_records('moodleoverflow_grades', ['moodleoverflowid' => $forum->id], null, 'userid, grade'); self::assertEquals(2.5, $grades[$user->id]->grade); self::assertArrayNotHasKey($user2->id, $grades); // Test delete context. provider::delete_data_for_all_users_in_context($context); moodleoverflow_update_all_grades_for_cm($forum->id); - $grades = $DB->get_records('moodleoverflow_grades', ['moodleoverflowid' => $forum->id], null, - 'userid, grade'); + $grades = $DB->get_records('moodleoverflow_grades', ['moodleoverflowid' => $forum->id], null, 'userid, grade'); self::assertEmpty($grades); } } diff --git a/tests/subscriptions_test.php b/tests/subscriptions_test.php index 4b02a0854c..26d653b7a9 100644 --- a/tests/subscriptions_test.php +++ b/tests/subscriptions_test.php @@ -1112,8 +1112,8 @@ public function test_moodleoverflow_subscribe_toggle_as_other_repeat_subscriptio $discussion->moodleoverflow = $moodleoverflow->id; // Declare the options for the subscription tables. - $discussoptions = ['userid' => $author->id, 'discussion' => $discussion->id]; - $subscriptionoptions = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id]; + $discussoptions = ['userid' => $user->id, 'discussion' => $discussion->id]; + $subscriptionoptions = ['userid' => $user->id, 'moodleoverflow' => $moodleoverflow->id]; // Confirm that the user is currently not subscribed to the moodleoverflow. $this->assertFalse(subscriptions::is_subscribed($user->id, $moodleoverflow, $modulecontext)); From 34ca1b853a3107a2236a8807310f30211cb075d0 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 20 Jun 2024 10:12:58 +0200 Subject: [PATCH 06/17] phpmd for privacy provider test --- tests/privacy_provider_test.php | 229 +++++++++----------------------- 1 file changed, 60 insertions(+), 169 deletions(-) diff --git a/tests/privacy_provider_test.php b/tests/privacy_provider_test.php index 63cd0b3ce0..1211803e44 100644 --- a/tests/privacy_provider_test.php +++ b/tests/privacy_provider_test.php @@ -27,6 +27,7 @@ global $CFG; use core_privacy\local\request\approved_contextlist; +use core_privacy\local\request\approved_userlist; use core_privacy\local\request\userlist; use core_privacy\local\request\writer; use mod_moodleoverflow\privacy\provider; @@ -298,10 +299,7 @@ public function test_user_has_posted_reply(): void { */ public function test_user_has_rated_others(): void { $course = $this->getDataGenerator()->create_course(); - $forum = $this->getDataGenerator()->create_module('moodleoverflow', [ - 'course' => $course->id, - 'scale' => 100, - ]); + $forum = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id, 'scale' => 100]); list($user, $otheruser) = $this->create_users($course, 2); list($discussion, $post) = $this->generator->post_to_forum($forum, $otheruser); $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); @@ -341,10 +339,7 @@ public function test_user_has_rated_others(): void { */ public function test_user_has_been_rated(): void { $course = $this->getDataGenerator()->create_course(); - $forum = $this->getDataGenerator()->create_module('moodleoverflow', [ - 'course' => $course->id, - 'scale' => 100, - ]); + $forum = $this->getDataGenerator()->create_module('moodleoverflow', [ 'course' => $course->id, 'scale' => 100]); list($user, $otheruser) = $this->create_users($course, 3); list($discussion, $post) = $this->generator->post_to_forum($forum, $user); $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); @@ -516,7 +511,7 @@ public function test_post_attachment_inclusion(): void { 'image contents (not really)'); // Create a second discussion + post in the forum without tags. - list($otherdiscussion, $otherpost) = $this->generator->post_to_forum($forum, $author); + list(, $otherpost) = $this->generator->post_to_forum($forum, $author); // Add a number of replies. $this->generator->reply_to_post($otherpost, $author); $this->generator->reply_to_post($otherpost, $author); @@ -571,14 +566,9 @@ public function test_all_users_deleted_from_context(): void { $reply = $this->generator->reply_to_post($reply, $user); $posts[$reply->id] = $reply; // Add a fake inline image to the original post. - $fs->create_file_from_string([ - 'contextid' => $context->id, - 'component' => 'mod_moodleoverflow', - 'filearea' => 'attachment', - 'itemid' => $post->id, - 'filepath' => '/', - 'filename' => 'example.jpg', - ], 'image contents (not really)'); + $fs->create_file_from_string(['contextid' => $context->id, 'component' => 'mod_moodleoverflow', + 'filearea' => 'attachment', 'itemid' => $post->id, 'filepath' => '/', + 'filename' => 'example.jpg', ], 'image contents (not really)'); } } // Mark all posts as read by user. @@ -660,11 +650,10 @@ public function test_all_users_deleted_from_context(): void { } // Ratings should not have been deleted. foreach ($postsinforum as $post) { - if (!isset($ratedposts[$post->id])) { - continue; + if (isset($ratedposts[$post->id])) { + $ratings = $DB->get_records('moodleoverflow_ratings', ['postid' => $post->id]); + $this->assertNotEmpty($ratings); } - $ratings = $DB->get_records('moodleoverflow_ratings', ['postid' => $post->id]); - $this->assertNotEmpty($ratings); } } @@ -780,9 +769,7 @@ public function test_delete_data_for_user(): void { // All posts should remain. $this->assertCount(40, $DB->get_records('moodleoverflow_posts')); // There should be 4 posts belonging to user1 that were not deleted. - $this->assertCount(4, $DB->get_records('moodleoverflow_posts', [ - 'userid' => $user1->id, - ])); + $this->assertCount(4, $DB->get_records('moodleoverflow_posts', ['userid' => $user1->id])); // Four of those posts should have been marked as deleted. // That means that the user ID is null and the message is empty. $this->assertCount(4, $DB->get_records_select('moodleoverflow_posts', "userid = :userid" @@ -793,19 +780,13 @@ public function test_delete_data_for_user(): void { ])); // Only user1's posts should have been marked this way. - $this->assertCount(4, $DB->get_records('moodleoverflow_posts', [ - 'userid' => 0, - ])); + $this->assertCount(4, $DB->get_records('moodleoverflow_posts', ['userid' => 0])); $this->assertCount(4, $DB->get_records_select('moodleoverflow_posts', - $DB->sql_compare_text('message') . " = " . $DB->sql_compare_text(':message'), [ - 'message' => '', - ])); + $DB->sql_compare_text('message') . " = " . $DB->sql_compare_text(':message'), ['message' => ''])); + // Only the posts in the first discussion should have been marked this way. - $this->assertCount(4, $DB->get_records_select('moodleoverflow_posts', - "userid = :userid AND id {$postinsql}", - array_merge($postinparams, [ - 'userid' => 0, - ]) + $this->assertCount(4, $DB->get_records_select('moodleoverflow_posts', "userid = :userid AND id {$postinsql}", + array_merge($postinparams, ['userid' => 0]) )); // Ratings should have been anonymized. @@ -965,7 +946,6 @@ public function test_delete_data_for_users(): void { } // Rate all posts (Every user every post). - foreach ($users as $user) { foreach ($posts as $post) { $discussion = $discussions[$post->discussion]; @@ -973,15 +953,9 @@ public function test_delete_data_for_users(): void { if ($post->userid != $user->id) { $time = time(); - $rating = (object) [ - 'userid' => $user->id, - 'postid' => $post->id, - 'discussionid' => $discussion->id, - 'moodleoverflowid' => $moodleoverflow->id, - 'rating' => 1, - 'firstrated' => $time, - 'lastchanged' => $time, - ]; + $rating = (object) ['userid' => $user->id, 'postid' => $post->id, 'discussionid' => $discussion->id, + 'moodleoverflowid' => $moodleoverflow->id, 'rating' => 1, 'firstrated' => $time, + 'lastchanged' => $time, ]; // Inserts a rating into the table. $DB->insert_record('moodleoverflow_ratings', $rating); } @@ -991,7 +965,7 @@ public function test_delete_data_for_users(): void { // Delete for one of the moodleoverflows all post for the first user. $firstcontext = reset($contexts); - $approveduserlist = new \core_privacy\local\request\approved_userlist($firstcontext, 'mod_moodleoverflow', [$user1->id]); + $approveduserlist = new approved_userlist($firstcontext, 'mod_moodleoverflow', [$user1->id]); provider::delete_data_for_users($approveduserlist); // All posts should remain (5 user * 2 Moodleoverflows * 4 Post per Moodleoverflow). @@ -999,9 +973,7 @@ public function test_delete_data_for_users(): void { // User 1 posted in every Moodleoverflow 4 post (8). // Post from the first Moodleoverflow are made anonymous. - $this->assertCount(4, $DB->get_records('moodleoverflow_posts', [ - 'userid' => $user1->id, - ])); + $this->assertCount(4, $DB->get_records('moodleoverflow_posts', ['userid' => $user1->id])); // All of the post from moodleoverflow 1 should have been filed with empty values. // That means the userid equals 0, message equals empty string, and message format equals FORMAT_PLAIN. @@ -1017,8 +989,7 @@ public function test_delete_data_for_users(): void { // Ratings were made anonymous from the affected posts. // All ratings from user1 in Moodleoverflow1 should have been deleted so 16 entries should be anonymous. // (20 post in Moodleoverflow -4 post belonging to user 1). - $this->assertCount(16, $DB->get_records_select('moodleoverflow_ratings', "userid = :userid" - , ['userid' => 0 ])); + $this->assertCount(16, $DB->get_records_select('moodleoverflow_ratings', "userid = :userid" , ['userid' => 0 ])); // All ratings should still exist (2 Moodleoverflows * 5 users * 16 post from other people). $this->assertCount(160, $DB->get_records('moodleoverflow_ratings')); @@ -1028,9 +999,7 @@ public function test_delete_data_for_users(): void { // User 1 posted in every Moodleoverflow 1 discussion. // Discussion from the first Moodleoverflow are made anonymous. - $this->assertCount(1, $DB->get_records('moodleoverflow_discussions', [ - 'userid' => $user1->id, - ])); + $this->assertCount(1, $DB->get_records('moodleoverflow_discussions', ['userid' => $user1->id])); // All of the discussions from moodleoverflow 1 should have been filed with empty values. // That means the userid equals 0, and name equals empty string. @@ -1074,20 +1043,18 @@ public function test_delete_data_for_users(): void { * Ensure that the discussion author is listed as a user in the context. */ public function test_get_users_in_context_post_author(): void { - $component = 'mod_moodleoverflow'; - $course = $this->getDataGenerator()->create_course(); $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $context = \context_module::instance($cm->id); - list($author, $user) = $this->create_users($course, 2); + list($author) = $this->create_users($course, 2); - list($fd1, $fp1) = $this->generator->post_to_forum($moodleoverflow, $author); + $this->generator->post_to_forum($moodleoverflow, $author); - $userlist = new \core_privacy\local\request\userlist($context, $component); - \mod_moodleoverflow\privacy\provider::get_users_in_context($userlist); + $userlist = new userlist($context, 'moodleoverflow'); + provider::get_users_in_context($userlist); // There should only be one user in the list. $this->assertCount(1, $userlist); @@ -1099,33 +1066,26 @@ public function test_get_users_in_context_post_author(): void { */ public function test_get_users_in_context_post_authors(): void { global $DB; - $component = 'mod_moodleoverflow'; - $course = $this->getDataGenerator()->create_course(); $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $context = \context_module::instance($cm->id); - list($author, $user, $other) = $this->create_users($course, 3); + list($author, $user) = $this->create_users($course, 3); - list($fd1, $fp1) = $this->generator->post_to_forum($moodleoverflow, $author); - $fp1reply = $this->generator->post_to_discussion($moodleoverflow, $fd1, $user); - $fd1 = $DB->get_record('moodleoverflow_discussions', ['id' => $fd1->id]); + list($fd1) = $this->generator->post_to_forum($moodleoverflow, $author); + $this->generator->post_to_discussion($moodleoverflow, $fd1, $user); + $DB->get_record('moodleoverflow_discussions', ['id' => $fd1->id]); - $userlist = new \core_privacy\local\request\userlist($context, $component); - \mod_moodleoverflow\privacy\provider::get_users_in_context($userlist); + $userlist = new userlist($context, 'mod_moodleoverflow'); + provider::get_users_in_context($userlist); // Two users - author and replier. $this->assertCount(2, $userlist); - $expected = [$author->id, $user->id]; - sort($expected); - $actual = $userlist->get_userids(); - sort($actual); - - $this->assertEquals($expected, $actual); + $this->assertEquals(sort($expected), sort($actual)); } /** @@ -1134,89 +1094,61 @@ public function test_get_users_in_context_post_authors(): void { */ public function test_get_users_in_context_post_ratings(): void { global $DB; - $component = 'mod_moodleoverflow'; - $course = $this->getDataGenerator()->create_course(); $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $context = \context_module::instance($cm->id); - list($author, $user) = $this->create_users($course, 3); - list($fd1, $fp1) = $this->generator->post_to_forum($moodleoverflow, $author); $time = time(); - $rating = (object) [ - 'userid' => $user->id, - 'postid' => $fp1->id, - 'discussionid' => $fd1->id, - 'moodleoverflowid' => $moodleoverflow->id, - 'rating' => 1, - 'firstrated' => $time, - 'lastchanged' => $time, - ]; + $rating = (object) ['userid' => $user->id, 'postid' => $fp1->id, 'discussionid' => $fd1->id, + 'moodleoverflowid' => $moodleoverflow->id, 'rating' => 1, 'firstrated' => $time, + 'lastchanged' => $time, ]; + // Inserts a rating into the table. $DB->insert_record('moodleoverflow_ratings', $rating); - $userlist = new userlist($context, $component); + $userlist = new userlist($context, 'mod_moodleoverflow'); provider::get_users_in_context($userlist); // Two users - author and rater. $this->assertCount(2, $userlist); - $expected = [$author->id, $user->id]; - sort($expected); - $actual = $userlist->get_userids(); - sort($actual); - $this->assertEquals($expected, $actual); + $this->assertEquals(sort($expected), sort($actual)); } /** * Ensure that all users with a moodleoverflow subscription preference included as a user in the context. */ public function test_get_users_in_context_with_subscription(): void { - $component = 'mod_moodleoverflow'; - $course = $this->getDataGenerator()->create_course(); - $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $context = \context_module::instance($cm->id); - list($user) = $this->create_users($course, 2); // Subscribe the user to the moodleoverflow. subscriptions::subscribe_user($user->id, $moodleoverflow, $context); - - $userlist = new userlist($context, $component); + $userlist = new userlist($context, 'mod_moodleoverflow'); provider::get_users_in_context($userlist); // One user - the one with a digest preference. $this->assertCount(1, $userlist); - $expected = [$user->id]; - sort($expected); - $actual = $userlist->get_userids(); - sort($actual); - - $this->assertEquals($expected, $actual); + $this->assertEquals(sort($expected), sort($actual)); } /** * Ensure that all users with a per-discussion subscription preference included as a user in the context. */ public function test_get_users_in_context_with_discussion_subscription(): void { - $component = 'mod_moodleoverflow'; - $course = $this->getDataGenerator()->create_course(); - $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); $context = \context_module::instance($cm->id); - $othermoodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); - list($author, $user, $otheruser) = $this->create_users($course, 3); // Post in both of the moodleoverflows. @@ -1227,127 +1159,92 @@ public function test_get_users_in_context_with_discussion_subscription(): void { subscriptions::subscribe_user_to_discussion($user->id, $fd1, $context); subscriptions::subscribe_user_to_discussion($otheruser->id, $ofd1, $context); - $userlist = new userlist($context, $component); + $userlist = new userlist($context, 'mod_moodleoverflow'); provider::get_users_in_context($userlist); // Two users - the author, and the one who subscribed. $this->assertCount(2, $userlist); - $expected = [$author->id, $user->id]; - sort($expected); - $actual = $userlist->get_userids(); - sort($actual); - - $this->assertEquals($expected, $actual); + $this->assertEquals(sort($expected), sort($actual)); } /** * Ensure that all users with read tracking are included as a user in the context. */ public function test_get_users_in_context_with_read_post_tracking(): void { - $component = 'mod_moodleoverflow'; - $course = $this->getDataGenerator()->create_course(); - $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); - $context = \context_module::instance($cm->id); $othermoodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $othercm = get_coursemodule_from_instance('moodleoverflow', $othermoodleoverflow->id); - $othercontext = \context_module::instance($othercm->id); - list($author, $user, $otheruser) = $this->create_users($course, 3); // Post in both of the moodleoverflows. - list($fd1, $fp1) = $this->generator->post_to_forum($moodleoverflow, $author); - list($ofd1, $ofp1) = $this->generator->post_to_forum($othermoodleoverflow, $author); + list(, $fp1) = $this->generator->post_to_forum($moodleoverflow, $author); + list(, $ofp1) = $this->generator->post_to_forum($othermoodleoverflow, $author); // Add read information for those users. readtracking::moodleoverflow_add_read_record($user->id, $fp1->id); readtracking::moodleoverflow_add_read_record($otheruser->id, $ofp1->id); - $userlist = new userlist($context, $component); + $userlist = new userlist(\context_module::instance($cm->id), 'mod_moodleoverflow'); provider::get_users_in_context($userlist); // Two user - the author, and the one who has read the post. $this->assertCount(2, $userlist); - $expected = [$author->id, $user->id]; - sort($expected); - $actual = $userlist->get_userids(); - sort($actual); - - $this->assertEquals($expected, $actual); + $this->assertEquals(sort($expected), sort($actual)); // Testing again for the other context. - $userlist = new userlist($othercontext, $component); + $userlist = new userlist(\context_module::instance($othercm->id), 'mod_moodleoverflow'); provider::get_users_in_context($userlist); // Two user - the author, and the one who has read the post. $this->assertCount(2, $userlist); - $expected = [$author->id, $otheruser->id]; - sort($expected); - $actual = $userlist->get_userids(); - sort($actual); - - $this->assertEquals($expected, $actual); + $this->assertEquals(sort($expected), sort($actual)); } /** * Ensure that all users with tracking preferences are included as a user in the context. */ public function test_get_users_in_context_with_tracking_preferences(): void { - $component = 'mod_moodleoverflow'; - $course = $this->getDataGenerator()->create_course(); - $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id); - $context = \context_module::instance($cm->id); $othermoodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id]); $othercm = get_coursemodule_from_instance('moodleoverflow', $othermoodleoverflow->id); $othercontext = \context_module::instance($othercm->id); - - list($author, $user, $otheruser) = $this->create_users($course, 3); + list(, $user, $otheruser) = $this->create_users($course, 3); // Stop tracking the read posts. readtracking::moodleoverflow_stop_tracking($moodleoverflow->id, $user->id); readtracking::moodleoverflow_stop_tracking($othermoodleoverflow->id, $otheruser->id); - $userlist = new userlist($context, $component); + $userlist = new userlist(\context_module::instance($cm->id), 'mod_moodleoverflow'); provider::get_users_in_context($userlist); // One user - the one who is tracking that moodleoverflow. $this->assertCount(1, $userlist); $expected = [$user->id]; - sort($expected); - $actual = $userlist->get_userids(); - sort($actual); - - $this->assertEquals($expected, $actual); + $this->assertEquals(sort($expected), sort($actual)); // Testing the other context. - $userlist = new userlist($othercontext, $component); + $userlist = new userlist($othercontext, 'mod_moodleoverflow'); provider::get_users_in_context($userlist); // One user - the one who is tracking that moodleoverflow. $this->assertCount(1, $userlist); - $expected = [$otheruser->id]; - sort($expected); - $actual = $userlist->get_userids(); - sort($actual); - - $this->assertEquals($expected, $actual); + $this->assertEquals(sort($expected), sort($actual)); } /** @@ -1359,12 +1256,8 @@ public function test_grades(): void { global $DB; $course = self::getDataGenerator()->create_course(); - $forum = self::getDataGenerator()->create_module('moodleoverflow', [ - 'course' => $course->id, - 'scale' => 100, - 'grademaxgrade' => 50, - 'gradescalefactor' => 2, - ]); + $forum = self::getDataGenerator()->create_module('moodleoverflow', ['course' => $course->id, 'scale' => 100, + 'grademaxgrade' => 50, 'gradescalefactor' => 2, ]); $cm = get_coursemodule_from_instance('moodleoverflow', $forum->id); $context = \context_module::instance($cm->id); @@ -1372,15 +1265,14 @@ public function test_grades(): void { list( , $post) = $this->generator->post_to_forum($forum, $user); ratings::moodleoverflow_add_rating($forum, $post->id, RATING_UPVOTE, $cm, $user2->id); moodleoverflow_update_all_grades_for_cm($forum->id); - $grades = grade_get_grades($course->id, 'mod', 'moodleoverflow', $forum->id, - [$user->id, $user2->id]); + $grades = grade_get_grades($course->id, 'mod', 'moodleoverflow', $forum->id, [$user->id, $user2->id]); self::assertEquals("2.50", $grades->items[0]->grades[$user->id]->str_grade); self::assertEquals("0.50", $grades->items[0]->grades[$user2->id]->str_grade); // Test export. $this->export_context_data_for_user($user->id, $context, 'mod_moodleoverflow'); $writer = writer::with_context($context); - $metadata = $writer->get_all_metadata([]); + $metadata = $writer->get_all_metadata(); self::assertArrayHasKey('grade', $metadata); self::assertEquals(2.5, $metadata['grade']->value); @@ -1397,7 +1289,6 @@ public function test_grades(): void { // Test delete context. provider::delete_data_for_all_users_in_context($context); moodleoverflow_update_all_grades_for_cm($forum->id); - $grades = $DB->get_records('moodleoverflow_grades', ['moodleoverflowid' => $forum->id], null, 'userid, grade'); - self::assertEmpty($grades); + self::assertEmpty($DB->get_records('moodleoverflow_grades', ['moodleoverflowid' => $forum->id], null, 'userid, grade')); } } From 1e58530ead6186166f9e40623452227036be9f6d Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 20 Jun 2024 11:19:45 +0200 Subject: [PATCH 07/17] WIP: codeclean userstats table --- classes/tables/userstats_table.php | 258 +++++++++++++++-------------- 1 file changed, 136 insertions(+), 122 deletions(-) diff --git a/classes/tables/userstats_table.php b/classes/tables/userstats_table.php index 93a771b22e..daaa2d3a41 100644 --- a/classes/tables/userstats_table.php +++ b/classes/tables/userstats_table.php @@ -26,6 +26,7 @@ defined('MOODLE_INTERNAL') || die(); use mod_moodleoverflow\ratings; +global $CFG; require_once($CFG->dirroot . '/mod/moodleoverflow/lib.php'); require_once($CFG->libdir . '/tablelib.php'); @@ -69,13 +70,8 @@ public function __construct($uniqueid, $courseid, $moodleoverflow, $url) { $this->set_attribute('class', 'moodleoverflow-statistics-table'); $this->set_attribute('id', $uniqueid); - $this->define_columns(['username', - 'receivedupvotes', - 'receiveddownvotes', - 'forumactivity', - 'courseactivity', - 'forumreputation', - 'coursereputation', ]); + $this->define_columns(['username', 'receivedupvotes', 'receiveddownvotes', 'forumactivity', 'courseactivity', + 'forumreputation', 'coursereputation', ]); $this->define_baseurl($url); $this->define_headers([get_string('fullnameuser'), get_string('userstatsupvotes', 'moodleoverflow'), @@ -102,84 +98,6 @@ public function out() { $this->finish_output(); } - /** - * Method to sort the userstatsdata-table. - * - * @param array $sortorder The sort order array. - * - * @return void - */ - private function sort_table_data($sortorder) { - $key = $sortorder['sortby']; - // The index of each object in usertable is it's value of $key. - $length = count($this->userstatsdata); - if ($sortorder['sortorder'] == 4) { - // 4 means sort in ascending order. - $this->quick_usertable_sort(0, $length - 1, $key, 'asc'); - } else if ($sortorder['sortorder'] == 3) { - // 3 means sort in descending order. - $this->quick_usertable_sort(0, $length - 1, $key, 'desc'); - } - } - - /** - * Sorts userstatsdata with quicksort algorithm. - * - * @param int $low index for quicksort. - * @param int $high index for quicksort. - * @param int $key the column that is being sorted (upvotes, downvotes etc.). - * @param string $order sort in ascending or descending order. - * - * @return void - */ - private function quick_usertable_sort($low, $high, $key, $order) { - if ($low >= $high) { - return; - } - $left = $low; - $right = $high; - $pivot = $this->userstatsdata[intval(($low + $high) / 2)]; - $pivot = $pivot->$key; - do { - if ($order == 'asc') { - while ($this->userstatsdata[$left]->$key < $pivot) { - $left++; - } - while ($this->userstatsdata[$right]->$key > $pivot) { - $right--; - } - } else if ($order == 'desc') { - while ($this->userstatsdata[$left]->$key > $pivot) { - $left++; - } - while ($this->userstatsdata[$right]->$key < $pivot) { - $right--; - } - } - if ($left <= $right) { - $temp = $this->userstatsdata[$right]; - $this->userstatsdata[$right] = $this->userstatsdata[$left]; - $this->userstatsdata[$left] = $temp; - $right--; - $left++; - } - } while ($left <= $right); - if ($low < $right) { - if ($order == 'asc') { - $this->quick_usertable_sort($low, $right, $key, 'asc'); - } else if ($order == 'desc') { - $this->quick_usertable_sort($low, $right, $key, 'desc'); - } - } - if ($high > $left) { - if ($order == 'asc') { - $this->quick_usertable_sort($left, $high, $key, 'asc'); - } else if ($order == 'desc') { - $this->quick_usertable_sort($left, $high, $key, 'desc'); - } - } - } - /** * Method to collect all the data. * Method will collect all users from the given course and will determine the user statistics @@ -198,55 +116,25 @@ public function get_table_data() { $student = $this->createstudent($user); foreach ($ratingdata as $row) { - // Is the rating from or for the current student? - if ($row->postuserid !== $student->id && $row->rateuserid !== $student->id) { - continue; - } - // Did the student receive an up- or downvote? - // Only count if the discussion is not anonymous or if the user is not starter of the discussion. - if ($row->postuserid == $student->id && - (($row->anonymoussetting == 0) || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) { - if ($row->rating == RATING_UPVOTE) { - $student->receivedupvotes += 1; - } else if ($row->rating == RATING_DOWNVOTE) { - $student->receiveddownvotes += 1; - } - } + // Only count if the post is not anonymous (no anonymous setting or only questioner anonymous discussion). + $this->process_received_votes($student, $row); // Did a student submit a rating? // For solution marks: only count a solution if the discussion is not completely anonymous. // For helpful marks: only count helpful marks if the discussion is not any kind of anonymous. // Up and downvotes are always counted. - if ($row->rateuserid == $student->id && !array_key_exists($row->rateid, $student->ratedposts) && - (($row->rating == RATING_SOLVED && $row->anonymoussetting != 2) || - ($row->rating == RATING_HELPFUL && $row->anonymoussetting == 0) || - ($row->rating == RATING_UPVOTE) || - ($row->rating == RATING_DOWNVOTE))) { - - if ($row->moodleoverflowid == $this->moodleoverflowid) { - $student->forumactivity += 1; - } - $student->courseactivity += 1; - $student->ratedposts[$row->rateid] = $row->rateid; - } + $this->process_submitted_ratings($student, $row); // Did the student write a post? Only count a written post if: the post is not in an anonymous discussion; // or the post is in a partial anonymous discussion and the user is not the starter of the discussion. - if ($row->postuserid == $student->id && !array_key_exists($row->postid, $student->submittedposts) && - ($row->anonymoussetting == 0 || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) { - - if ($row->moodleoverflowid == $this->moodleoverflowid) { - $student->forumactivity += 1; - } - $student->courseactivity += 1; - $student->submittedposts[$row->postid] = $row->postid; - } + $this->process_written_posts($student, $row); + } // Get the user reputation from the course. $student->forumreputation = ratings::moodleoverflow_get_reputation_instance($this->moodleoverflowid, $student->id); $student->coursereputation = ratings::moodleoverflow_get_reputation_course($this->courseid, $student->id); - array_push($this->userstatsdata, $student); + $this->userstatsdata[] = $student; } } @@ -350,7 +238,7 @@ public function col_coursereputation($row) { } /** - * Dependeng on the value display success or warning badge. + * Depending on the value display success or warning badge. * @param int $number * @return string */ @@ -373,6 +261,8 @@ public function other_cols($colname, $attempt) { return null; } + // Helper functions. + /** * Return a student object. * @param \stdClass $user @@ -421,4 +311,128 @@ private function get_rating_data() { WHERE discuss.course = ' . $this->courseid . ';'; return $DB->get_records_sql($sqlquery); } + + /** + * Process the received votes for a student. + * @param $student + * @param $row + * @return void + */ + private function process_received_votes(&$student, $row) { + if ($row->postuserid == $student->id && + (($row->anonymoussetting == 0) || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) { + if ($row->rating == RATING_UPVOTE) { + $student->receivedupvotes += 1; + } else if ($row->rating == RATING_DOWNVOTE) { + $student->receiveddownvotes += 1; + } + } + } + + /** + * Process the submitted ratings from a student. + * @param $student + * @param $row + * @return void + */ + private function process_submitted_ratings(&$student, $row) { + $solvedcheck = ($row->rating == RATING_SOLVED && $row->anonymoussetting != 2); + $helpfulcheck = ($row->rating == RATING_HELPFUL && $row->anonymoussetting == 0); + $isvote = ($row->rating == RATING_UPVOTE || $row->rating == RATING_DOWNVOTE); + + if ($row->rateuserid == $student->id && !array_key_exists($row->rateid, $student->ratedpost)) { + if ($solvedcheck || $helpfulcheck || $isvote) { + if ($row->moodleoverflowid == $this->moodleoverflowid) { + $student->forumactivity++; + } + $student->courseactivity++; + $student->ratedposts[$row->rateid] = $row->rateid; + } + } + } + + /** + * Process the written posts from a student. + * @param $student + * @param $row + * @return void + */ + private function process_written_posts(&$student, $row) { + if ($row->postuserid == $student->id && !array_key_exists($row->postid, $student->submittedposts) && + ($row->anonymoussetting == 0 || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) { + + if ($row->moodleoverflowid == $this->moodleoverflowid) { + $student->forumactivity += 1; + } + $student->courseactivity += 1; + $student->submittedposts[$row->postid] = $row->postid; + } + } + // Sort function. + + /** + * Method to sort the userstatsdata-table. + * @param array $sortorder The sort order array. + * @return void + */ + private function sort_table_data($sortorder) { + $key = $sortorder['sortby']; + // The index of each object in usertable is it's value of $key. + $length = count($this->userstatsdata); + if ($sortorder['sortorder'] == 4) { + // 4 means sort in ascending order. + $this->quick_usertable_sort(0, $length - 1, $key, 'asc'); + } else if ($sortorder['sortorder'] == 3) { + // 3 means sort in descending order. + $this->quick_usertable_sort(0, $length - 1, $key, 'desc'); + } + } + + /** + * Sorts userstatsdata with quicksort algorithm. + * + * @param int $low index for quicksort. + * @param int $high index for quicksort. + * @param int $key the column that is being sorted (upvotes, downvotes etc.). + * @param string $order sort in ascending or descending order. + * @return void + */ + private function quick_usertable_sort($low, $high, $key, $order) { + if ($low >= $high) { + return; + } + $left = $low; + $right = $high; + $pivot = $this->userstatsdata[intval(($low + $high) / 2)]->key; + + $compare = function($a, $b) use ($order) { + if ($order == 'asc') { + return $a < $b; + } else { + return $a > $b; + } + }; + + do { + while ($compare($this->userstatsdata[$left]->$key, $pivot)) { + $left++; + } + while ($compare($pivot, $this->userstatsdata[$right]->$key)) { + $right--; + } + if ($left <= $right) { + $temp = $this->userstatsdata[$right]; + $this->userstatsdata[$right] = $this->userstatsdata[$left]; + $this->userstatsdata[$left] = $temp; + $right--; + $left++; + } + } while ($left <= $right); + if ($low < $right) { + $this->quick_usertable_sort($low, $right, $key, $order); + } + if ($high > $left) { + $this->quick_usertable_sort($left, $high, $key, $order); + } + } } From e7360babfac6e68130c3ecad3bbe8ffe6a0f2d46 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 21 Jun 2024 11:26:53 +0200 Subject: [PATCH 08/17] complexity reduced in userstatstable --- classes/tables/userstats_table.php | 147 ++++++++++++----------------- locallib.php | 51 ++++++++++ 2 files changed, 109 insertions(+), 89 deletions(-) diff --git a/classes/tables/userstats_table.php b/classes/tables/userstats_table.php index daaa2d3a41..6a89d27beb 100644 --- a/classes/tables/userstats_table.php +++ b/classes/tables/userstats_table.php @@ -28,6 +28,7 @@ use mod_moodleoverflow\ratings; global $CFG; require_once($CFG->dirroot . '/mod/moodleoverflow/lib.php'); +require_once($CFG->dirroot . '/mod/moodleoverflow/locallib.php'); require_once($CFG->libdir . '/tablelib.php'); /** @@ -101,14 +102,14 @@ public function out() { /** * Method to collect all the data. * Method will collect all users from the given course and will determine the user statistics - * - * @return 2d-array with user statistic + * Builds an 2d-array with user statistic */ public function get_table_data() { // Get all userdata from a course. $context = \context_course::instance($this->courseid); $users = get_enrolled_users($context , '', 0, 'u.id, u.firstname, u.lastname'); + // Step 1.0: Build the datatable with all relevant information. $ratingdata = $this->get_rating_data(); // Step 2.0: Now collect the data for every user in the course. @@ -117,18 +118,19 @@ public function get_table_data() { foreach ($ratingdata as $row) { // Did the student receive an up- or downvote? - // Only count if the post is not anonymous (no anonymous setting or only questioner anonymous discussion). - $this->process_received_votes($student, $row); + if ($row->postuserid == $student->id) { + $this->process_received_votes($student, $row); + } // Did a student submit a rating? - // For solution marks: only count a solution if the discussion is not completely anonymous. - // For helpful marks: only count helpful marks if the discussion is not any kind of anonymous. - // Up and downvotes are always counted. - $this->process_submitted_ratings($student, $row); + if ($row->rateuserid == $student->id ) { + $this->process_submitted_ratings($student, $row); + } - // Did the student write a post? Only count a written post if: the post is not in an anonymous discussion; - // or the post is in a partial anonymous discussion and the user is not the starter of the discussion. - $this->process_written_posts($student, $row); + // Did the student write a post? + if ($row->postuserid == $student->id ) { + $this->process_written_posts($student, $row); + } } // Get the user reputation from the course. @@ -156,16 +158,16 @@ public function set_helpactivity() { get_string('helpamountofactivity', 'moodleoverflow')); $this->helpactivity->class = 'helpactivityclass btn btn-link'; $this->helpactivity->iconattributes = ['role' => 'button', - 'data-container' => 'body', - 'data-toggle' => 'popover', - 'data-placement' => 'right', - 'data-action' => 'showhelpicon', - 'data-html' => 'true', - 'data-trigger' => 'focus', - 'tabindex' => '0', - 'data-content' => '

' . - get_string('helpamountofactivity', 'moodleoverflow') . - '

', ]; + 'data-container' => 'body', + 'data-toggle' => 'popover', + 'data-placement' => 'right', + 'data-action' => 'showhelpicon', + 'data-html' => 'true', + 'data-trigger' => 'focus', + 'tabindex' => '0', + 'data-content' => '

' . + get_string('helpamountofactivity', 'moodleoverflow') . + '

', ]; $this->helpactivity->object = \html_writer::span($this->helpactivity->icon, $this->helpactivity->class, @@ -251,6 +253,7 @@ private function badge_render($number) { $number . \html_writer::end_span()); } } + /** * error handling * @param object $colname @@ -274,14 +277,14 @@ private function createstudent($user) { $student->name = $user->firstname . ' ' . $user->lastname; $linktostudent = new \moodle_url('/user/view.php', ['id' => $student->id, 'course' => $this->courseid]); $student->link = \html_writer::link($linktostudent->out(), $student->name); - $student->submittedposts = []; // Posts written by the student. Key = postid, Value = postid. - $student->ratedposts = []; // Posts that the student rated. Key = rateid, Value = rateid. + $student->submittedposts = []; // Posts written by the student. Key = postid, Value = postid. + $student->ratedposts = []; // Posts that the student rated. Key = rateid, Value = rateid. $student->receivedupvotes = 0; $student->receiveddownvotes = 0; - $student->forumactivity = 0; // Number of written posts and submitted ratings in the current moodleoverflow. - $student->courseactivity = 0; // Number of written posts and submitted ratings in the course. - $student->forumreputation = 0; // Reputation in the current moodleoverflow. - $student->coursereputation = 0; // Reputation in the course. + $student->forumactivity = 0; // Number of written posts and submitted ratings in the current moodleoverflow. + $student->courseactivity = 0; // Number of written posts and submitted ratings in the course. + $student->forumreputation = 0; // Reputation in the current moodleoverflow. + $student->coursereputation = 0; // Reputation in the course. return $student; } @@ -292,7 +295,6 @@ private function createstudent($user) { */ private function get_rating_data() { global $DB; - // Step 1.0: Build the datatable with all relevant Informations. $sqlquery = 'SELECT (ROW_NUMBER() OVER (ORDER BY ratings.id)) AS row_num, discuss.id AS discussid, discuss.userid AS discussuserid, @@ -319,8 +321,8 @@ private function get_rating_data() { * @return void */ private function process_received_votes(&$student, $row) { - if ($row->postuserid == $student->id && - (($row->anonymoussetting == 0) || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) { + // Only count received votes if the post is not anonymous (no anonymous setting or only questioner anonymous discussion). + if ((($row->anonymoussetting == 0) || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) { if ($row->rating == RATING_UPVOTE) { $student->receivedupvotes += 1; } else if ($row->rating == RATING_DOWNVOTE) { @@ -336,15 +338,16 @@ private function process_received_votes(&$student, $row) { * @return void */ private function process_submitted_ratings(&$student, $row) { + // For solution marks: only count a solution if the discussion is not completely anonymous. + // For helpful marks: only count helpful marks if the discussion is not any kind of anonymous. + // Up and downvotes are always counted. $solvedcheck = ($row->rating == RATING_SOLVED && $row->anonymoussetting != 2); $helpfulcheck = ($row->rating == RATING_HELPFUL && $row->anonymoussetting == 0); $isvote = ($row->rating == RATING_UPVOTE || $row->rating == RATING_DOWNVOTE); - if ($row->rateuserid == $student->id && !array_key_exists($row->rateid, $student->ratedpost)) { + if (!array_key_exists($row->rateid, $student->ratedposts)) { if ($solvedcheck || $helpfulcheck || $isvote) { - if ($row->moodleoverflowid == $this->moodleoverflowid) { - $student->forumactivity++; - } + $this->increment_forumactivity($student, $row); $student->courseactivity++; $student->ratedposts[$row->rateid] = $row->rateid; } @@ -352,22 +355,36 @@ private function process_submitted_ratings(&$student, $row) { } /** - * Process the written posts from a student. + * Process the written posts from a student for the activity. * @param $student * @param $row * @return void */ private function process_written_posts(&$student, $row) { - if ($row->postuserid == $student->id && !array_key_exists($row->postid, $student->submittedposts) && + // Only count a written post if: the post is not in an anonymous discussion: + // or the post is in a partial anonymous discussion and the user is not the starter of the discussion. + if (!array_key_exists($row->postid, $student->submittedposts) && ($row->anonymoussetting == 0 || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) { - if ($row->moodleoverflowid == $this->moodleoverflowid) { - $student->forumactivity += 1; - } + $this->increment_forumactivity($student, $row); $student->courseactivity += 1; $student->submittedposts[$row->postid] = $row->postid; } } + + /** + * Increments the forum activity of a student. + * @param $row + * @param $moodleoverflowid + * @param $forumactivity + * @return void + */ + private function increment_forumactivity(&$student, $row) { + if ($row->moodleoverflowid == $this->moodleoverflowid) { + $student->forumactivity++; + } + } + // Sort function. /** @@ -381,58 +398,10 @@ private function sort_table_data($sortorder) { $length = count($this->userstatsdata); if ($sortorder['sortorder'] == 4) { // 4 means sort in ascending order. - $this->quick_usertable_sort(0, $length - 1, $key, 'asc'); + moodleoverflow_quick_array_sort(0, $length - 1, $this->userstatsdata, $key, 'asc'); } else if ($sortorder['sortorder'] == 3) { // 3 means sort in descending order. - $this->quick_usertable_sort(0, $length - 1, $key, 'desc'); - } - } - - /** - * Sorts userstatsdata with quicksort algorithm. - * - * @param int $low index for quicksort. - * @param int $high index for quicksort. - * @param int $key the column that is being sorted (upvotes, downvotes etc.). - * @param string $order sort in ascending or descending order. - * @return void - */ - private function quick_usertable_sort($low, $high, $key, $order) { - if ($low >= $high) { - return; - } - $left = $low; - $right = $high; - $pivot = $this->userstatsdata[intval(($low + $high) / 2)]->key; - - $compare = function($a, $b) use ($order) { - if ($order == 'asc') { - return $a < $b; - } else { - return $a > $b; - } - }; - - do { - while ($compare($this->userstatsdata[$left]->$key, $pivot)) { - $left++; - } - while ($compare($pivot, $this->userstatsdata[$right]->$key)) { - $right--; - } - if ($left <= $right) { - $temp = $this->userstatsdata[$right]; - $this->userstatsdata[$right] = $this->userstatsdata[$left]; - $this->userstatsdata[$left] = $temp; - $right--; - $left++; - } - } while ($left <= $right); - if ($low < $right) { - $this->quick_usertable_sort($low, $right, $key, $order); - } - if ($high > $left) { - $this->quick_usertable_sort($left, $high, $key, $order); + moodleoverflow_quick_array_sort(0, $length - 1, $this->userstatsdata, $key, 'desc'); } } } diff --git a/locallib.php b/locallib.php index 299399afe7..fa184ff569 100644 --- a/locallib.php +++ b/locallib.php @@ -2130,3 +2130,54 @@ function moodleoverflow_update_all_grades() { moodleoverflow_update_all_grades_for_cm($cmid->id); } } + + +/** + * Function to sort an array with a quicksort algorithm. This function is a recursive function that needs to + * be called from outside. + * + * @param int $low The lowest index of the array. The first call should set it to 0. + * @param int $high The highest index of the array. The first call should set it to the length of the array - 1. + * @param array $array The array to be sorted. It is passed by reference. + * @param string $key The key/attribute after what the algorithm sorts. The key should be an comparable integer. + * @param string $order The order of the sorting. It can be 'asc' or 'desc'. + * @return void + */ +function moodleoverflow_quick_array_sort($low, $high, &$array, $key, $order) { + if ($low >= $high) { + return; + } + $left = $low; + $right = $high; + $pivot = $array[intval(($low + $high) / 2)]->$key; + + $compare = function($a, $b) use ($order) { + if ($order == 'asc') { + return $a < $b; + } else { + return $a > $b; + } + }; + + do { + while ($compare($array[$left]->$key, $pivot)) { + $left++; + } + while ($compare($pivot, $array[$right]->$key)) { + $right--; + } + if ($left <= $right) { + $temp = $array[$right]; + $array[$right] = $array[$left]; + $array[$left] = $temp; + $right--; + $left++; + } + } while ($left <= $right); + if ($low < $right) { + moodleoverflow_quick_array_sort($low, $right, $array, $key, $order); + } + if ($high > $left) { + moodleoverflow_quick_array_sort($left, $high, $array, $key, $order); + } +} From ab368776097fcc59a1d6d60a7696d44b60225cc0 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 21 Jun 2024 11:51:27 +0200 Subject: [PATCH 09/17] WIP: reduce complexity of ratings class --- classes/ratings.php | 65 ++++-------------------------- classes/tables/userstats_table.php | 4 +- locallib.php | 9 +++-- 3 files changed, 14 insertions(+), 64 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index c398b885fd..61db4e7e0e 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -267,7 +267,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { $startsolved = $index; $starthelpful = $index; $startother = $index; - self::moodleoverflow_quicksort_posts($sortedposts, $startsolvedandhelpful, $index - 1, 'votesdifference'); + moodleoverflow_quick_array_sort($sortedposts, $startsolvedandhelpful, $index - 1, 'votesdifference', 'desc'); self::moodleoverflow_check_equal_votes($sortedposts, $startsolvedandhelpful, $index - 1); } @@ -285,7 +285,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { if ($index > $startsolved) { $starthelpful = $index; $startother = $index; - self::moodleoverflow_quicksort_posts($sortedposts, $startsolved, $index - 1, 'votesdifference'); + moodleoverflow_quick_array_sort($sortedposts, $startsolved, $index - 1, 'votesdifference', 'desc'); self::moodleoverflow_check_equal_votes($sortedposts, $startsolved, $index - 1); } @@ -299,7 +299,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Update the indices and sort the group by votes. if ($index > $starthelpful) { $startother = $index; - self::moodleoverflow_quicksort_posts($sortedposts, $starthelpful, $index - 1, 'votesdifference'); + moodleoverflow_quick_array_sort($sortedposts, $starthelpful, $index - 1, 'votesdifference', 'desc'); self::moodleoverflow_check_equal_votes($sortedposts, $starthelpful, $index - 1); } } else { @@ -315,7 +315,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { if ($index > $starthelpful) { $startsolved = $index; $startother = $index; - self::moodleoverflow_quicksort_posts($sortedposts, $starthelpful, $index - 1, 'votesdifference'); + moodleoverflow_quick_array_sort($sortedposts, $starthelpful, $index - 1, 'votesdifference', 'desc'); self::moodleoverflow_check_equal_votes($sortedposts, $starthelpful, $index - 1); } @@ -329,7 +329,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Update the indices and sort the group by votes. if ($index > $startsolved) { $startother = $index; - self::moodleoverflow_quicksort_posts($sortedposts, $startsolved, $index - 1, 'votesdifference'); + moodleoverflow_quick_array_sort($sortedposts, $startsolved, $index - 1, 'votesdifference', 'desc'); self::moodleoverflow_check_equal_votes($sortedposts, $startsolved, $index - 1); } } @@ -343,7 +343,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { } // Update the indices and sort the group by votes. if ($index > $startother) { - self::moodleoverflow_quicksort_posts($sortedposts, $startother, $index - 1, 'votesdifference'); + moodleoverflow_quick_array_sort($sortedposts, $startother, $index - 1, 'votesdifference', 'desc'); self::moodleoverflow_check_equal_votes($sortedposts, $startother, $index - 1); } @@ -815,57 +815,6 @@ public static function moodleoverflow_user_can_rate($post, $modulecontext, $user && $post->reviewed == 1; } - /** - * Sorts answerposts of a discussion with quicksort algorithm - * @param array $posts the posts that are being sorted - * @param int $low the index from where the sorting begins - * @param int $high the index until the array is being sorted - * @param string $sortby the attribute by which the posts are being sorted, can be 'votesdifference' or 'modified' - */ - private static function moodleoverflow_quicksort_posts(array &$posts, $low, $high, $sortby): void { - if ($low >= $high) { - return; - } - $left = $low; - $right = $high; - $pivot = 0; - if ($sortby == 'votesdifference') { - $pivot = $posts[intval(($low + $high) / 2)]->votesdifference; - } else if ($sortby == 'modified') { - $pivot = $posts[intval(($low + $high) / 2)]->modified; - } - do { - if ($sortby == 'votesdifference') { - while ($posts[$left]->votesdifference > $pivot) { - $left++; - } - while ($posts[$right]->votesdifference < $pivot) { - $right--; - } - } else if ($sortby == 'modified') { - while ($posts[$left]->modified < $pivot) { - $left++; - } - while ($posts[$right]->modified > $pivot) { - $right--; - } - } - if ($left <= $right) { - $temp = $posts[$right]; - $posts[$right] = $posts[$left]; - $posts[$left] = $temp; - $right--; - $left++; - } - } while ($left <= $right); - if ($low < $right) { - self::moodleoverflow_quicksort_posts($posts, $low, $right, $sortby); - } - if ($high > $left ) { - self::moodleoverflow_quicksort_posts($posts, $left, $high, $sortby); - } - } - /** * Helper function for moodleoverflow_sort_answer_by_rating. For posts that have the same mark and votesdifference, * the posts are sorted by time modified @@ -883,7 +832,7 @@ private static function moodleoverflow_check_equal_votes(&$posts, $low, $high) { ($posts[$tempendindex]->votesdifference == $posts[$tempendindex + 1]->votesdifference)) { $tempendindex++; } - self::moodleoverflow_quicksort_posts($posts, $tempstartindex, $tempendindex, 'modified'); + moodleoverflow_quick_array_sort($posts, $tempstartindex, $tempendindex, 'modified', 'asc'); $low = $tempendindex + 1; } else { $low++; diff --git a/classes/tables/userstats_table.php b/classes/tables/userstats_table.php index 6a89d27beb..d88fa7ce21 100644 --- a/classes/tables/userstats_table.php +++ b/classes/tables/userstats_table.php @@ -398,10 +398,10 @@ private function sort_table_data($sortorder) { $length = count($this->userstatsdata); if ($sortorder['sortorder'] == 4) { // 4 means sort in ascending order. - moodleoverflow_quick_array_sort(0, $length - 1, $this->userstatsdata, $key, 'asc'); + moodleoverflow_quick_array_sort($this->userstatsdata, 0, $length - 1, $key, 'asc'); } else if ($sortorder['sortorder'] == 3) { // 3 means sort in descending order. - moodleoverflow_quick_array_sort(0, $length - 1, $this->userstatsdata, $key, 'desc'); + moodleoverflow_quick_array_sort($this->userstatsdata, 0, $length - 1, $key, 'desc'); } } } diff --git a/locallib.php b/locallib.php index fa184ff569..7454cda803 100644 --- a/locallib.php +++ b/locallib.php @@ -2136,14 +2136,15 @@ function moodleoverflow_update_all_grades() { * Function to sort an array with a quicksort algorithm. This function is a recursive function that needs to * be called from outside. * + * @param array $array The array to be sorted. It is passed by reference. * @param int $low The lowest index of the array. The first call should set it to 0. * @param int $high The highest index of the array. The first call should set it to the length of the array - 1. - * @param array $array The array to be sorted. It is passed by reference. + * * @param string $key The key/attribute after what the algorithm sorts. The key should be an comparable integer. * @param string $order The order of the sorting. It can be 'asc' or 'desc'. * @return void */ -function moodleoverflow_quick_array_sort($low, $high, &$array, $key, $order) { +function moodleoverflow_quick_array_sort(&$array, $low, $high, $key, $order) { if ($low >= $high) { return; } @@ -2175,9 +2176,9 @@ function moodleoverflow_quick_array_sort($low, $high, &$array, $key, $order) { } } while ($left <= $right); if ($low < $right) { - moodleoverflow_quick_array_sort($low, $right, $array, $key, $order); + moodleoverflow_quick_array_sort($array, $low, $right, $key, $order); } if ($high > $left) { - moodleoverflow_quick_array_sort($left, $high, $array, $key, $order); + moodleoverflow_quick_array_sort($array, $left, $high, $key, $order); } } From 3e1298f0c992047cc1657ac4b90f4793e53a71b0 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 21 Jun 2024 18:07:26 +0200 Subject: [PATCH 10/17] improved ratings sort function --- classes/ratings.php | 131 ++++++++++++-------------------------------- 1 file changed, 34 insertions(+), 97 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index 61db4e7e0e..80df690fec 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -244,111 +244,43 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { if ($posts[array_key_first($posts)]->ratingpreference == 1) { $solutionspreferred = true; } + // Build array groups for different types of answers (solved and helpful, only solved/helpful, unmarked). + $solvedhelpfulposts = []; + $solvedposts = []; + $helpfulposts = []; + $unmarkedposts = []; - // Sort the answer posts by ratings. - // Build groups of different types of answers (Solved and helpful, only solved/helpful, other). + // Sort the answer posts by ratings.. // markedsolved == 1 means the post is marked as solved. // markedhelpful == 1 means the post is marked as helpful. - // If a group is complete, sort the group. - $index = 1; - $startsolvedandhelpful = 1; - $startsolved = 1; - $starthelpful = 1; - $startother = 1; - // Solved and helpful posts are first. + // Step 1: Iterate trough the answerposts and assign each post to a group. foreach ($answerposts as $post) { - if ($post->markedsolution > 0 && $post->markedhelpful > 0) { - $sortedposts[$index] = $post; - $index++; - } - } - // Update the indices and sort the group by votes. - if ($index > $startsolvedandhelpful) { - $startsolved = $index; - $starthelpful = $index; - $startother = $index; - moodleoverflow_quick_array_sort($sortedposts, $startsolvedandhelpful, $index - 1, 'votesdifference', 'desc'); - self::moodleoverflow_check_equal_votes($sortedposts, $startsolvedandhelpful, $index - 1); - } - - // Check if solutions are preferred. - if ($solutionspreferred) { - - // Build the group of only solved posts. - foreach ($answerposts as $post) { - if ($post->markedsolution > 0 && $post->markedhelpful == 0) { - $sortedposts[$index] = $post; - $index++; - } - } - // Update the indices and sort the group by votes. - if ($index > $startsolved) { - $starthelpful = $index; - $startother = $index; - moodleoverflow_quick_array_sort($sortedposts, $startsolved, $index - 1, 'votesdifference', 'desc'); - self::moodleoverflow_check_equal_votes($sortedposts, $startsolved, $index - 1); - } - - // Build the group of only helpful posts. - foreach ($answerposts as $post) { - if ($post->markedsolution == 0 && $post->markedhelpful > 0) { - $sortedposts[$index] = $post; - $index++; - } - } - // Update the indices and sort the group by votes. - if ($index > $starthelpful) { - $startother = $index; - moodleoverflow_quick_array_sort($sortedposts, $starthelpful, $index - 1, 'votesdifference', 'desc'); - self::moodleoverflow_check_equal_votes($sortedposts, $starthelpful, $index - 1); - } - } else { - - // Build the group of only helpful posts. - foreach ($answerposts as $post) { - if ($post->markedsolution == 0 && $post->markedhelpful > 0) { - $sortedposts[$index] = $post; - $index++; + if ($post->markedsolution > 0) { + if ($post->markedhelpful > 0) { + $solvedhelpfulposts[] = $post; + } else { + $solvedposts[] = $post; } - } - // Update the indices and sort the group by votes. - if ($index > $starthelpful) { - $startsolved = $index; - $startother = $index; - moodleoverflow_quick_array_sort($sortedposts, $starthelpful, $index - 1, 'votesdifference', 'desc'); - self::moodleoverflow_check_equal_votes($sortedposts, $starthelpful, $index - 1); - } - - // Build the group of only solved posts. - foreach ($answerposts as $post) { - if ($post->markedsolution > 0 && $post->markedhelpful == 0) { - $sortedposts[$index] = $post; - $index++; + } else { + if ($post->markedhelpful > 0) { + $helpfulposts[] = $post; + } else { + $unmarkedposts[] = $post; } } - // Update the indices and sort the group by votes. - if ($index > $startsolved) { - $startother = $index; - moodleoverflow_quick_array_sort($sortedposts, $startsolved, $index - 1, 'votesdifference', 'desc'); - self::moodleoverflow_check_equal_votes($sortedposts, $startsolved, $index - 1); - } } - // Now build the group of posts without ratings like helpful/solved. - foreach ($answerposts as $post) { - if ($post->markedsolution == 0 && $post->markedhelpful == 0) { - $sortedposts[$index] = $post; - $index++; - } - } - // Update the indices and sort the group by votes. - if ($index > $startother) { - moodleoverflow_quick_array_sort($sortedposts, $startother, $index - 1, 'votesdifference', 'desc'); - self::moodleoverflow_check_equal_votes($sortedposts, $startother, $index - 1); - } + // Step 2: Sort each group after their votes and eventually time modified. + self::moodleoverflow_sort_postgroup($solvedhelpfulposts, 0, count($solvedhelpfulposts) - 1); + self::moodleoverflow_sort_postgroup($solvedposts, 0, count($solvedposts) - 1); + self::moodleoverflow_sort_postgroup($helpfulposts, 0, count($helpfulposts) - 1); + self::moodleoverflow_sort_postgroup($unmarkedposts, 0, count($unmarkedposts) - 1); - // Rearrange the indices and return the sorted posts. + // Step 3: Put each group together in the right order depending on the rating preferences. + $temp = $solutionspreferred ? array_merge($solvedposts, $helpfulposts) : array_merge($helpfulposts, $solvedposts); + $sortedposts = array_merge($sortedposts, $solvedhelpfulposts, $temp, $unmarkedposts); + // Rearrange the indices and return the sorted posts. $neworder = []; foreach ($sortedposts as $post) { $neworder[$post->id] = $post; @@ -816,14 +748,19 @@ public static function moodleoverflow_user_can_rate($post, $modulecontext, $user } /** - * Helper function for moodleoverflow_sort_answer_by_rating. For posts that have the same mark and votesdifference, - * the posts are sorted by time modified + * Helper function for moodleoverflow_sort_answer_by_rating. Sorts a group of posts (solved and helpful, only solved/helpful + * and other) after their votesdifference and if needed after their modified time. + * * @param array $posts The array that will be sorted * @param int $low Startindex from where equal votes will be checked * @param int $high Endindex until where equal votes will be checked * @return void */ - private static function moodleoverflow_check_equal_votes(&$posts, $low, $high) { + private static function moodleoverflow_sort_postgroup(&$posts, $low, $high) { + // First sort the array after their votesdifference. + moodleoverflow_quick_array_sort($posts, 0, $high, 'votesdifference', 'desc'); + + // Check if posts have the same votesdifference and sort them after their modified time if needed. while ($low < $high) { if ($posts[$low]->votesdifference == $posts[$low + 1]->votesdifference) { $tempstartindex = $low; From 6c3be91d5734f0dd491f95fb97c3b837183ebdc5 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 24 Jun 2024 09:57:28 +0200 Subject: [PATCH 11/17] WIP: reduce cyclomatic complexity --- classes/ratings.php | 90 ++++++++++++++------------------------------- locallib.php | 37 ++++++++++++++++++- 2 files changed, 63 insertions(+), 64 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index 80df690fec..52d5756256 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -62,20 +62,16 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati throw new moodle_exception('invalidratingid', 'moodleoverflow'); } - // Get the related discussion. - if (!$post = $DB->get_record('moodleoverflow_posts', ['id' => $postid])) { - throw new moodle_exception('invalidparentpostid', 'moodleoverflow'); - } + // Get the related post. + $post = moodleoverflow_get_record_or_exception('moodleoverflow_posts', ['id' => $postid], 'invalidparentpostid'); // Check if the post belongs to a discussion. - if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $post->discussion])) { - throw new moodle_exception('notpartofdiscussion', 'moodleoverflow'); - } + $discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', ['id' => $post->discussion], + 'notpartofdiscussion'); // Get the related course. - if (!$course = $DB->get_record('course', ['id' => $moodleoverflow->course])) { - throw new moodle_exception('invalidcourseid'); - } + $course = moodleoverflow_get_record_or_exception('course', ['id' => $moodleoverflow->course], + 'invalidcourseid', '*', true); // Are multiple marks allowed? $markssetting = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id], 'allowmultiplemarks'); @@ -86,8 +82,7 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati $coursecontext = \context_course::instance($course->id); // Redirect the user if capabilities are missing. - $canrate = self::moodleoverflow_user_can_rate($post, $modulecontext, $userid); - if (!$canrate) { + if (!self::moodleoverflow_user_can_rate($post, $modulecontext, $userid)) { // Catch unenrolled users. if (!isguestuser() && !is_enrolled($coursecontext)) { @@ -113,12 +108,8 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati // Check if we are removing a mark. if (in_array($rating / 10, $possibleratings)) { - - if (!get_config('moodleoverflow', 'allowratingchange')) { - throw new moodle_exception('noratingchangeallowed', 'moodleoverflow'); - - return false; - } + moodleoverflow_get_config_or_exception('moodleoverflow', 'allowratingchange', + 'noratingchangeallowed', 'moodleoverflow'); // Delete the rating. return self::moodleoverflow_remove_rating($postid, $rating / 10, $userid, $modulecontext); @@ -170,11 +161,8 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati // Update an rating record. if ($oldrating['normal']) { - if (!get_config('moodleoverflow', 'allowratingchange')) { - throw new moodle_exception('noratingchangeallowed', 'moodleoverflow'); - - return false; - } + moodleoverflow_get_config_or_exception('moodleoverflow', 'allowratingchange', + 'noratingchangeallowed', 'moodleoverflow'); // Check if the rating can still be changed. if (!self::moodleoverflow_can_be_changed($postid, $oldrating['normal']->rating, $userid)) { @@ -424,15 +412,12 @@ public static function moodleoverflow_get_reputation_instance($moodleoverflowid, } // Check the moodleoverflow instance. - if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflowid])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); - } - + $moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $moodleoverflowid], + 'invalidmoodleoverflowid'); // Initiate a variable. $reputation = 0; if ($moodleoverflow->anonymous != anonymous::EVERYTHING_ANONYMOUS) { - // Get all posts of this user in this module. // Do not count votes for own posts. $sql = "SELECT r.id, r.postid as post, r.rating @@ -449,38 +434,22 @@ public static function moodleoverflow_get_reputation_instance($moodleoverflowid, $params = [$userid, $userid, $moodleoverflowid]; $records = $DB->get_records_sql($sql, $params); - // Check if there are results. - $records = (isset($records)) ? $records : []; - // Iterate through all ratings. foreach ($records as $record) { - - // The rating is a downvote. - if ($record->rating == RATING_DOWNVOTE) { - $reputation += get_config('moodleoverflow', 'votescaledownvote'); - continue; + switch ($record->rating) { + case RATING_DOWNVOTE: + $reputation += get_config('moodleoverflow', 'votescaledownvote'); + break; + case RATING_UPVOTE: + $reputation += get_config('moodleoverflow', 'votescaleupvote'); + break; + case RATING_HELPFUL: + $reputation += get_config('moodleoverflow', 'votescalehelpful'); + break; + case RATING_SOLVED: + $reputation += get_config('moodleoverflow', 'votescalesolved'); + break; } - - // The rating is an upvote. - if ($record->rating == RATING_UPVOTE) { - $reputation += get_config('moodleoverflow', 'votescaleupvote'); - continue; - } - - // The post has been marked as helpful by the question owner. - if ($record->rating == RATING_HELPFUL) { - $reputation += get_config('moodleoverflow', 'votescalehelpful'); - continue; - } - - // The post has been marked as solved by a teacher. - if ($record->rating == RATING_SOLVED) { - $reputation += get_config('moodleoverflow', 'votescalesolved'); - continue; - } - - // Another rating should not exist. - continue; } } @@ -524,9 +493,7 @@ public static function moodleoverflow_get_reputation_course($courseid, $userid = $reputation = 0; // Check if the course exists. - if (!$course = $DB->get_record('course', ['id' => $courseid])) { - throw new moodle_exception('invalidcourseid'); - } + $course = moodleoverflow_get_record_or_exception('course', ['id' => $courseid], 'invalidcourseid', '*', true); // Get all moodleoverflow instances in this course. $sql = "SELECT id @@ -536,9 +503,6 @@ public static function moodleoverflow_get_reputation_course($courseid, $userid = $params = [$course->id]; $instances = $DB->get_records_sql($sql, $params); - // Check if there are instances in this course. - $instances = (isset($instances)) ? $instances : []; - // Sum the reputation of each individual instance. foreach ($instances as $instance) { $reputation += self::moodleoverflow_get_reputation_instance($instance->id, $userid); diff --git a/locallib.php b/locallib.php index 7454cda803..529f268a21 100644 --- a/locallib.php +++ b/locallib.php @@ -2121,7 +2121,6 @@ function moodleoverflow_update_all_grades_for_cm($moodleoverflowid) { /** * Updates all grades. - * */ function moodleoverflow_update_all_grades() { global $DB; @@ -2182,3 +2181,39 @@ function moodleoverflow_quick_array_sort(&$array, $low, $high, $key, $order) { moodleoverflow_quick_array_sort($array, $left, $high, $key, $order); } } + +/** + * Function to get a record from the database and throw an exception, if the record is not available. + * @param string $table The table to get the record from + * @param array $options Conditions for the record + * @param string $exceptionstring Name of the moodleoverflow exception that should be thrown in case there is no record. + * @param string $fields Optional fields that are retrieved from the found record. + * @param bool $coreexception Optional param if exception from the core exceptions. + * @return mixed $record The found record + */ +function moodleoverflow_get_record_or_exception($table, $options, $exceptionstring, $fields = '*', $coreexception = false) { + global $DB; + if (!$record = $DB->get_record($table, $options, $fields)) { + if ($coreexception) { + throw new moodle_exception('invalidcourseid'); + } else { + throw new moodle_exception($exceptionstring, 'moodleoverflow'); + } + } + return $record; +} + +/** + * Function to retrieve a config and throw an exception, if the config is not found. + * @param string $plugin Plugin that has the configuration + * @param string $configname Name of configuration + * @param string $errorcode Error code/name of the exception + * @param string $exceptionmodule Module that has the exception. + * @return mixed $config + */ +function moodleoverflow_get_config_or_exception($plugin, $configname, $errorcode, $exceptionmodule) { + if (!$config = get_config($plugin, $configname)) { + throw new moodle_exception($errorcode, $exceptionmodule); + } + return $config; +} From 7420b346e50f75a0b9fcc0a0d0e8f75895e4c4bf Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 27 Jun 2024 12:03:25 +0200 Subject: [PATCH 12/17] reduce php mess in ratings class --- classes/ratings.php | 168 +++++++++++++++++--------------------------- discussion.php | 5 +- externallib.php | 2 +- locallib.php | 42 ++++++++++- 4 files changed, 108 insertions(+), 109 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index 52d5756256..b9f9f06ecf 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -42,25 +42,18 @@ class ratings { * @param int $postid * @param int $rating * @param object $cm - * @param null $userid + * @param int $userid * * @return bool|int */ - public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rating, $cm, $userid = null) { - global $DB, $USER, $SESSION; - - // Has a user been submitted? - if (!isset($userid)) { - $userid = $USER->id; - } + public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rating, $cm, $userid) { + global $DB; // Is the submitted rating valid? $possibleratings = [RATING_NEUTRAL, RATING_DOWNVOTE, RATING_UPVOTE, RATING_SOLVED, RATING_HELPFUL, RATING_REMOVE_DOWNVOTE, RATING_REMOVE_UPVOTE, RATING_REMOVE_SOLVED, RATING_REMOVE_HELPFUL, ]; - if (!in_array($rating, $possibleratings)) { - throw new moodle_exception('invalidratingid', 'moodleoverflow'); - } + moodleoverflow_throw_exception_with_check(!in_array($rating, $possibleratings), 'invalidratingid'); // Get the related post. $post = moodleoverflow_get_record_or_exception('moodleoverflow_posts', ['id' => $postid], 'invalidparentpostid'); @@ -85,26 +78,17 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati if (!self::moodleoverflow_user_can_rate($post, $modulecontext, $userid)) { // Catch unenrolled users. - if (!isguestuser() && !is_enrolled($coursecontext)) { - $SESSION->wantsurl = qualified_me(); - $SESSION->enrolcancel = get_local_referer(false); - redirect(new \moodle_url('/enrol/index.php', [ - 'id' => $course->id, - 'returnurl' => '/mod/moodleoverflow/view.php?m' . $moodleoverflow->id, - ]), get_string('youneedtoenrol')); - } + $returnurl = '/mod/moodleoverflow/view.php?m' . $moodleoverflow->id; + moodleoverflow_catch_unenrolled_user($coursecontext, $course->id, $returnurl); // Notify the user, that he can not post a new discussion. throw new moodle_exception('noratemoodleoverflow', 'moodleoverflow'); } // Make sure post author != current user, unless they have permission. - if (($post->userid == $userid) && ! - (($rating == RATING_SOLVED || $rating == RATING_REMOVE_SOLVED) && - has_capability('mod/moodleoverflow:marksolved', $modulecontext)) - ) { - throw new moodle_exception('rateownpost', 'moodleoverflow'); - } + $authorcheck = ($post->userid == $userid) && ! (($rating == RATING_SOLVED || $rating == RATING_REMOVE_SOLVED) && + has_capability('mod/moodleoverflow:marksolved', $modulecontext)); + moodleoverflow_throw_exception_with_check($authorcheck, 'rateownpost'); // Check if we are removing a mark. if (in_array($rating / 10, $possibleratings)) { @@ -121,15 +105,13 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati // Mark a post as solution or as helpful. if ($rating == RATING_SOLVED || $rating == RATING_HELPFUL) { - // Check if the current user is the startuser. - if ($rating == RATING_HELPFUL && $userid != $discussion->userid) { - throw new moodle_exception('notstartuser', 'moodleoverflow'); - } + // Make sure that a helpful mark is made by the user who started the discussion. + $isnotstartuser = $rating == RATING_HELPFUL && $userid != $discussion->userid; + moodleoverflow_throw_exception_with_check($isnotstartuser, 'nostartuser'); - // Check if the current user is a teacher. - if ($rating == RATING_SOLVED && !has_capability('mod/moodleoverflow:marksolved', $modulecontext)) { - throw new moodle_exception('notteacher', 'moodleoverflow'); - } + // Make sure that a solution mark is made by a teacher (or someone with the right capability). + $isnotteacher = $rating == RATING_SOLVED && !has_capability('mod/moodleoverflow:marksolved', $modulecontext); + moodleoverflow_throw_exception_with_check($isnotteacher, 'notteacher'); // Check if multiple marks are not enabled. if (!$multiplemarks) { @@ -145,22 +127,18 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati return self::moodleoverflow_update_rating_record($post->id, $rating, $userid, $otherrating->id, $modulecontext); } else { - $mid = $moodleoverflow->id; - - return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, + return self::moodleoverflow_add_rating_record($moodleoverflow->id, $discussion->id, $post->id, $rating, $userid, $modulecontext); } - } else { // If multiplemarks are allowed, only create a new rating. - $mid = $moodleoverflow->id; - return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, $rating, $userid, $modulecontext); + return self::moodleoverflow_add_rating_record($moodleoverflow->id, $discussion->id, $post->id, + $rating, $userid, $modulecontext); } } // Update an rating record. if ($oldrating['normal']) { - moodleoverflow_get_config_or_exception('moodleoverflow', 'allowratingchange', 'noratingchangeallowed', 'moodleoverflow'); @@ -174,10 +152,8 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati } // Create a new rating record. - $mid = $moodleoverflow->id; - $did = $post->discussion; - - return self::moodleoverflow_add_rating_record($mid, $did, $postid, $rating, $userid, $modulecontext); + return self::moodleoverflow_add_rating_record($moodleoverflow->id, $post->discussion, $postid, + $rating, $userid, $modulecontext); } /** @@ -185,24 +161,16 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati * Whether within a course or an instance is decided by the settings. * * @param int $moodleoverflowid - * @param null $userid + * @param int $userid * @param bool $forcesinglerating If true you only get the reputation for the given $moodleoverflowid, * even if coursewidereputation = true * * @return int */ - public static function moodleoverflow_get_reputation($moodleoverflowid, $userid = null, $forcesinglerating = false) { - global $DB, $USER; - - // Get the user id. - if (!isset($userid)) { - $userid = $USER->id; - } - + public static function moodleoverflow_get_reputation($moodleoverflowid, $userid, $forcesinglerating = false) { // Check the moodleoverflow instance. - if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflowid])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); - } + $moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $moodleoverflowid], + 'invalidmoodleoverflowid'); // Check whether the reputation can be summed over the whole course. if ($moodleoverflow->coursewidereputation && !$forcesinglerating) { @@ -417,39 +385,38 @@ public static function moodleoverflow_get_reputation_instance($moodleoverflowid, // Initiate a variable. $reputation = 0; - if ($moodleoverflow->anonymous != anonymous::EVERYTHING_ANONYMOUS) { - // Get all posts of this user in this module. - // Do not count votes for own posts. - $sql = "SELECT r.id, r.postid as post, r.rating - FROM {moodleoverflow_posts} p - JOIN {moodleoverflow_ratings} r ON p.id = r.postid - WHERE p.userid = ? AND NOT r.userid = ? AND r.moodleoverflowid = ? "; + // Get all posts of this user in this module. + // Do not count votes for own posts. + $sql = "SELECT r.id, r.postid as post, r.rating + FROM {moodleoverflow_posts} p + JOIN {moodleoverflow_ratings} r ON p.id = r.postid + JOIN {moodleoverflow} m ON r.moodleoverflowid = m.id + WHERE p.userid = ? AND NOT r.userid = ? AND r.moodleoverflowid = ? AND m.anonymous <> ?"; - if ($moodleoverflow->anonymous == anonymous::QUESTION_ANONYMOUS) { - $sql .= " AND p.parent <> 0 "; - } + if ($moodleoverflow->anonymous == anonymous::QUESTION_ANONYMOUS) { + $sql .= " AND p.parent <> 0 "; + } - $sql .= "ORDER BY r.postid ASC"; - - $params = [$userid, $userid, $moodleoverflowid]; - $records = $DB->get_records_sql($sql, $params); - - // Iterate through all ratings. - foreach ($records as $record) { - switch ($record->rating) { - case RATING_DOWNVOTE: - $reputation += get_config('moodleoverflow', 'votescaledownvote'); - break; - case RATING_UPVOTE: - $reputation += get_config('moodleoverflow', 'votescaleupvote'); - break; - case RATING_HELPFUL: - $reputation += get_config('moodleoverflow', 'votescalehelpful'); - break; - case RATING_SOLVED: - $reputation += get_config('moodleoverflow', 'votescalesolved'); - break; - } + $sql .= "ORDER BY r.postid ASC"; + + $params = [$userid, $userid, $moodleoverflowid, anonymous::EVERYTHING_ANONYMOUS]; + $records = $DB->get_records_sql($sql, $params); + + // Iterate through all ratings. + foreach ($records as $record) { + switch ($record->rating) { + case RATING_DOWNVOTE: + $reputation += get_config('moodleoverflow', 'votescaledownvote'); + break; + case RATING_UPVOTE: + $reputation += get_config('moodleoverflow', 'votescaleupvote'); + break; + case RATING_HELPFUL: + $reputation += get_config('moodleoverflow', 'votescalehelpful'); + break; + case RATING_SOLVED: + $reputation += get_config('moodleoverflow', 'votescalesolved'); + break; } } @@ -527,11 +494,11 @@ private static function moodleoverflow_check_old_rating($postid, $userid, $oldra // Initiate the array. $rating = []; - // Get the normal rating. $sql = "SELECT * - FROM {moodleoverflow_ratings} - WHERE userid = ? AND postid = ? AND (rating = 1 OR rating = 2)"; - $rating['normal'] = $DB->get_record_sql($sql, [ $userid, $postid ]); + FROM {moodleoverflow_ratings}"; + // Get the normal rating. + $condition = "WHERE userid = ? AND postid = ? AND (rating = 1 OR rating = 2)"; + $rating['normal'] = $DB->get_record_sql($sql . $condition, [ $userid, $postid ]); // Return the rating if it is requested. if ($oldrating == RATING_DOWNVOTE || $oldrating == RATING_UPVOTE) { @@ -539,10 +506,8 @@ private static function moodleoverflow_check_old_rating($postid, $userid, $oldra } // Get the solved rating. - $sql = "SELECT * - FROM {moodleoverflow_ratings} - WHERE postid = ? AND rating = 3"; - $rating['solved'] = $DB->get_record_sql($sql, [ $postid ]); + $condition = "WHERE postid = ? AND rating = 3"; + $rating['solved'] = $DB->get_record_sql($sql . $condition, [ $postid ]); // Return the rating if it is requested. if ($oldrating == RATING_SOLVED) { @@ -550,10 +515,8 @@ private static function moodleoverflow_check_old_rating($postid, $userid, $oldra } // Get the helpful rating. - $sql = "SELECT * - FROM {moodleoverflow_ratings} - WHERE postid = ? AND rating = 4"; - $rating['helpful'] = $DB->get_record_sql($sql, [ $postid ]); + $condition = "WHERE postid = ? AND rating = 4"; + $rating['helpful'] = $DB->get_record_sql($sql . $condition, [ $postid ]); // Return the rating if it is requested. if ($oldrating == RATING_HELPFUL) { @@ -585,7 +548,6 @@ private static function moodleoverflow_can_be_changed($postid, $rating, $userid) /** * Removes a rating record. - * * @param int $postid * @param int $rating * @param int $userid @@ -605,11 +567,7 @@ private static function moodleoverflow_remove_rating($postid, $rating, $userid, $oldrecord = self::moodleoverflow_check_old_rating($postid, $userid, $rating); // Trigger an event. - $params = [ - 'objectid' => $oldrecord->id, - 'context' => $modulecontext, - ]; - $event = \mod_moodleoverflow\event\rating_deleted::create($params); + $event = \mod_moodleoverflow\event\rating_deleted::create(['objectid' => $oldrecord->id, 'context' => $modulecontext]); $event->add_record_snapshot('moodleoverflow_ratings', $oldrecord); $event->trigger(); diff --git a/discussion.php b/discussion.php index 295220bb08..fa32df35f9 100644 --- a/discussion.php +++ b/discussion.php @@ -21,6 +21,9 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die(); + +global $CFG, $PAGE, $USER, $SESSION, $OUTPUT; // Include config and locallib. require_once('../../config.php'); @@ -83,7 +86,7 @@ if (in_array($ratingid, [RATING_SOLVED, RATING_REMOVE_SOLVED, RATING_HELPFUL, RATING_REMOVE_HELPFUL])) { // Rate the post. - if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, $ratedpost, $ratingid, $cm)) { + if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, $ratedpost, $ratingid, $cm, $USER->id)) { throw new moodle_exception('ratingfailed', 'moodleoverflow'); } diff --git a/externallib.php b/externallib.php index 6427bbfcbb..c0d802d7e8 100644 --- a/externallib.php +++ b/externallib.php @@ -114,7 +114,7 @@ public static function record_vote($postid, $ratingid) { // Rate the post. if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, - $params['postid'], $params['ratingid'], $cm)) { + $params['postid'], $params['ratingid'], $cm, $USER->id)) { throw new moodle_exception('ratingfailed', 'moodleoverflow'); } diff --git a/locallib.php b/locallib.php index 529f268a21..e5a45a309d 100644 --- a/locallib.php +++ b/locallib.php @@ -2188,14 +2188,14 @@ function moodleoverflow_quick_array_sort(&$array, $low, $high, $key, $order) { * @param array $options Conditions for the record * @param string $exceptionstring Name of the moodleoverflow exception that should be thrown in case there is no record. * @param string $fields Optional fields that are retrieved from the found record. - * @param bool $coreexception Optional param if exception from the core exceptions. + * @param bool $coreexception Optional param if exception is from the core exceptions. * @return mixed $record The found record */ function moodleoverflow_get_record_or_exception($table, $options, $exceptionstring, $fields = '*', $coreexception = false) { global $DB; if (!$record = $DB->get_record($table, $options, $fields)) { if ($coreexception) { - throw new moodle_exception('invalidcourseid'); + throw new moodle_exception($exceptionstring); } else { throw new moodle_exception($exceptionstring, 'moodleoverflow'); } @@ -2217,3 +2217,41 @@ function moodleoverflow_get_config_or_exception($plugin, $configname, $errorcode } return $config; } + +/** + * Function that throws an exception if a given check is true. + * @param bool $check The result of a boolean check. + * @param string $errorcode Error code/name of the exception + * @param string $coreexception Optional param if exception is from the core exceptions and not moodleoverflow. + * @return void + */ +function moodleoverflow_throw_exception_with_check($check, $errorcode, $coreexception = false) { + if ($check) { + if ($coreexception) { + throw new moodle_exception($errorcode); + } else { + throw new moodle_exception($errorcode, 'moodleoverflow'); + } + } +} + +/** + * Function that catches unenrolled users and redirects them to the enrolment page. + * @param context $coursecontext The context of the course. + * @param int $courseid Id of the course that the user needs to enrol. + * @param string $returnurl The url to return to after the user has been enrolled. + * @return void + */ +function moodleoverflow_catch_unenrolled_user($coursecontext, $courseid, $returnurl) { + global $SESSION; + if (!isguestuser() && !is_enrolled($coursecontext)) { + if (enrol_selfenrol_available($courseid)) { + $SESSION->wantsurl = qualified_me(); + $SESSION->enrolcancel = get_local_referer(false); + redirect(new \moodle_url('/enrol/index.php', [ + 'id' => $courseid, + 'returnurl' => $returnurl, + ]), get_string('youneedtoenrol')); + } + } +} From 17514af7947c53185171cd802b27afda4dd8a36c Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 1 Jul 2024 13:31:28 +0200 Subject: [PATCH 13/17] phpmd cleaning --- classes/manager/mail_manager.php | 132 +++++++++++++------------------ classes/ratings.php | 4 +- classes/readtracking.php | 22 ++---- classes/task/send_mails.php | 15 +--- discussion.php | 15 ++-- externallib.php | 14 ++-- index.php | 7 +- locallib.php | 3 +- markposts.php | 17 ++-- subscribe.php | 7 +- tracking.php | 16 +--- view.php | 1 - 12 files changed, 95 insertions(+), 158 deletions(-) diff --git a/classes/manager/mail_manager.php b/classes/manager/mail_manager.php index 04dbba65e3..e822a01719 100644 --- a/classes/manager/mail_manager.php +++ b/classes/manager/mail_manager.php @@ -65,7 +65,7 @@ class mail_manager { * @return bool */ public static function moodleoverflow_send_mails(): bool { - global $DB, $PAGE; + global $CFG, $DB, $PAGE; // Get the course object of the top level site. $site = get_site(); @@ -87,8 +87,7 @@ public static function moodleoverflow_send_mails(): bool { $courses = []; $coursemodules = []; - // Posts older than x days will not be mailed. - // This will avoid problems with the cron not ran for a long time. + // Posts older than x days will not be mailed. This will avoid problems with the cron not ran for a long time. $timenow = time(); $endtime = $timenow - get_config('moodleoverflow', 'maxeditingtime'); $starttime = $endtime - (get_config('moodleoverflow', 'maxmailingtime') * 60 * 60); @@ -101,7 +100,6 @@ public static function moodleoverflow_send_mails(): bool { mtrace('Errors occurred while trying to mark some posts as being mailed.'); return false; } - // Loop through all posts to be mailed. foreach ($posts as $postid => $post) { self::check_post($post, $mailcount, $users, $discussions, $errorcount, $posts, $postid, @@ -125,7 +123,7 @@ public static function moodleoverflow_send_mails(): bool { $userto->markposts = []; // Cache the capabilities of the user. - cron_setup_user($userto); + $CFG->branch >= 402 ? \core\cron::setup_user($userto) : cron_setup_user($userto); // Reset the caches. foreach ($coursemodules as $moodleoverflowid) { @@ -136,7 +134,6 @@ public static function moodleoverflow_send_mails(): bool { // Loop through all posts of this users. foreach ($posts as $post) { - self::send_post($userto, $post, $coursemodules, $errorcount, $discussions, $moodleoverflows, $courses, $mailcount, $users, $site, $textout, $htmlout); } @@ -147,18 +144,13 @@ public static function moodleoverflow_send_mails(): bool { } // Check for all posts whether errors occurred. - if ($posts) { - - // Loop through all posts. - foreach ($posts as $post) { - - // Tracing information. - mtrace($mailcount[$post->id] . " users were sent post $post->id"); + foreach ($posts as $post) { + // Tracing information. + mtrace($mailcount[$post->id] . " users were sent post $post->id"); - // Mark the posts with errors in the database. - if ($errorcount[$post->id]) { - $DB->set_field('moodleoverflow_posts', 'mailed', self::MOODLEOVERFLOW_MAILED_ERROR, ['id' => $post->id]); - } + // Mark the posts with errors in the database. + if ($errorcount[$post->id]) { + $DB->set_field('moodleoverflow_posts', 'mailed', self::MOODLEOVERFLOW_MAILED_ERROR, ['id' => $post->id]); } } @@ -231,7 +223,6 @@ public static function moodleoverflow_mark_old_posts_as_mailed($endtime) { * @param stdClass $user */ public static function moodleoverflow_minimise_user_record(stdClass $user) { - // Remove all information for the mail generation that are not needed. unset($user->institution); unset($user->department); @@ -267,61 +258,31 @@ public static function moodleoverflow_minimise_user_record(stdClass $user) { private static function check_post($post, array &$mailcount, array &$users, array &$discussions, array &$errorcount, array &$posts, int $postid, array &$moodleoverflows, array &$courses, array &$coursemodules) { - global $DB; // Check the cache if the discussion exists. $discussionid = $post->discussion; - if (!isset($discussions[$discussionid])) { - // Retrieve the discussion from the database. - $discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $post->discussion]); - - // If there is a record, update the cache. Else ignore the post. - if ($discussion) { - $discussions[$discussionid] = $discussion; - subscriptions::fill_subscription_cache($discussion->moodleoverflow); - subscriptions::fill_discussion_subscription_cache($discussion->moodleoverflow); - } else { - mtrace('Could not find discussion ' . $discussionid); - unset($posts[$postid]); - return; - } + if (!self::cache_record('moodleoverflow_discussions', $discussionid, $discussions, + 'Could not find discussion ', $posts, $postid, true)) { + return; } // Retrieve the connected moodleoverflow instance from the database. $moodleoverflowid = $discussions[$discussionid]->moodleoverflow; - if (!isset($moodleoverflows[$moodleoverflowid])) { - - // Retrieve the record from the database and update the cache. - $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflowid]); - if ($moodleoverflow) { - $moodleoverflows[$moodleoverflowid] = $moodleoverflow; - } else { - mtrace('Could not find moodleoverflow ' . $moodleoverflowid); - unset($posts[$postid]); - return; - } + if (!self::cache_record('moodleoverflow', $moodleoverflowid, $moodleoverflows, + 'Could not find moodleoverflow ', $posts, $postid, false)) { + return; } // Retrieve the connected courses from the database. $courseid = $moodleoverflows[$moodleoverflowid]->course; - if (!isset($courses[$courseid])) { - - // Retrieve the record from the database and update the cache. - $course = $DB->get_record('course', ['id' => $courseid]); - if ($course) { - $courses[$courseid] = $course; - } else { - mtrace('Could not find course ' . $courseid); - unset($posts[$postid]); - return; - } + if (!self::cache_record('course', $courseid, $courses, + 'Could not find course ', $posts, $postid, false)) { + return; } // Retrieve the connected course modules from the database. if (!isset($coursemodules[$moodleoverflowid])) { - // Retrieve the coursemodule and update the cache. - $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflowid, $courseid); - if ($cm) { + if ($cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflowid, $courseid)) { $coursemodules[$moodleoverflowid] = $cm; } else { mtrace('Could not find course module for moodleoverflow ' . $moodleoverflowid); @@ -332,14 +293,12 @@ private static function check_post($post, array &$mailcount, array &$users, arra // Cache subscribed users of each moodleoverflow. if (!isset($subscribedusers[$moodleoverflowid])) { - // Retrieve the context module. $modulecontext = context_module::instance($coursemodules[$moodleoverflowid]->id); // Retrieve all subscribed users. $mid = $moodleoverflows[$moodleoverflowid]; - $subusers = subscriptions::get_subscribed_users($mid, $modulecontext, 'u.*', true); - if ($subusers) { + if ($subusers = subscriptions::get_subscribed_users($mid, $modulecontext, 'u.*', true)) { // Loop through all subscribed users. foreach ($subusers as $postuser) { // Save the user into the cache. @@ -360,6 +319,39 @@ private static function check_post($post, array &$mailcount, array &$users, arra $errorcount[$postid] = 0; } + /** + * Helper function for check_post(). Caches the a record exists in the database and caches the record if needed. + * @param string $table + * @param int $id + * @param array $cache + * @param string $errorMessage + * @param array $posts + * @param int $postid + * @param bool $fillsubscache If the subscription cache is being filled (only when checking discussion cache) + * @return bool + * @throws \dml_exception + */ + private static function cache_record($table, $id, &$cache, $errormessage, &$posts, $postid, $fillsubscache) { + global $DB; + // Check if cache if an record exists already in the cache. + if (!isset($cache[$id])) { + // If there is a record in the database, update the cache. Else ignore the post. + if ($record = $DB->get_record($table, ['id' => $id])) { + $cache[$id] = $record; + if ($fillsubscache) { + subscriptions::fill_subscription_cache($record->moodleoverflow); + subscriptions::fill_discussion_subscription_cache($record->moodleoverflow); + } + } else { + mtrace($errormessage . $id); + unset($posts[$postid]); + return false; + } + } + return true; + } + + /** * Send the Mail with information of the post depending on theinformation available. * E.g. anonymous post do not include names, users who want resumes do not get single mails. @@ -427,9 +419,7 @@ private static function send_post($userto, $post, array &$coursemodules, array & // Check whether the user is subscribed to the discussion. $uid = $userto->id; - $did = $post->discussion; - $issubscribed = subscriptions::is_subscribed($uid, $moodleoverflow, $modulecontext, $did); - if (!$issubscribed) { + if (!subscriptions::is_subscribed($uid, $moodleoverflow, $modulecontext, $post->discussion)) { return; } @@ -462,7 +452,7 @@ private static function send_post($userto, $post, array &$coursemodules, array & } // Setup roles and languages. - cron_setup_user($userto, $course); + $CFG->branch >= 402 ? \core\cron::setup_user($userto, $course) : cron_setup_user($userto, $course); // Cache the users capability to view full names. if (!isset($userto->viewfullnames[$moodleoverflow->id])) { @@ -520,16 +510,7 @@ private static function send_post($userto, $post, array &$coursemodules, array & } // Format the data. - $data = new moodleoverflow_email( - $course, - $cm, - $moodleoverflow, - $discussion, - $post, - $userfrom, - $userto, - $canreply - ); + $data = new moodleoverflow_email($course, $cm, $moodleoverflow, $discussion, $post, $userfrom, $userto, $canreply); // Retrieve the unsubscribe-link. $userfrom->customheaders[] = sprintf('List-Unsubscribe: <%s>', $data->get_unsubscribediscussionlink()); @@ -555,7 +536,6 @@ private static function send_post($userto, $post, array &$coursemodules, array & // Check whether the post is a reply. if ($post->parent) { - // Add a reply header. $parentid = generate_email_messageid(hash('sha256', $post->parent . 'to' . $userto->id)); $userfrom->customheaders[] = "In-Reply-To: $parentid"; diff --git a/classes/ratings.php b/classes/ratings.php index b9f9f06ecf..acc9821a02 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -281,9 +281,7 @@ public static function moodleoverflow_get_rating($postid) { global $DB; // Retrieve the full post. - if (!$post = $DB->get_record('moodleoverflow_posts', ['id' => $postid])) { - throw new moodle_exception('postnotexist', 'moodleoverflow'); - } + $post = moodleoverflow_get_record_or_exception('moodleoverflow_posts', ['id' => $postid], 'postnotexist'); // Get the rating for this single post. return self::moodleoverflow_get_ratings_by_discussion($post->discussion, $postid); diff --git a/classes/readtracking.php b/classes/readtracking.php index 0905e78fe6..bc2b556e82 100644 --- a/classes/readtracking.php +++ b/classes/readtracking.php @@ -90,13 +90,8 @@ public static function moodleoverflow_is_tracked($moodleoverflow, $user = null) $user = $USER; } - // Guests cannot track a moodleoverflow. - if (isguestuser($USER) || empty($USER->id)) { - return false; - } - - // Check if the moodleoverflow can be generally tracked. - if (!self::moodleoverflow_can_track_moodleoverflows($moodleoverflow)) { + // Guests cannot track a moodleoverflow. The moodleoverflow should be generally trackable. + if (isguestuser($USER) || empty($USER->id) || !self::moodleoverflow_can_track_moodleoverflows($moodleoverflow)) { return false; } @@ -135,11 +130,9 @@ public static function moodleoverflow_mark_moodleoverflow_read($cm, $userid = nu // Iterate through all of this discussions. foreach ($discussions as $discussionid) { - // Mark the discussion as read. - if (!self::moodleoverflow_mark_discussion_read($discussionid, context_module::instance($cm->id), $userid)) { - throw new moodle_exception('markreadfailed', 'moodleoverflow'); - } + $markedcheck = self::moodleoverflow_mark_discussion_read($discussionid, context_module::instance($cm->id), $userid); + moodleoverflow_throw_exception_with_check($markedcheck !== true, 'markreadfailed'); } return true; @@ -172,11 +165,8 @@ public static function moodleoverflow_mark_discussion_read($discussionid, $modco } // Mark the post as read. - if (!self::moodleoverflow_mark_post_read($userid, $post)) { - throw new moodle_exception('markreadfailed', 'moodleoverflow'); - - return false; - } + $postreadcheck = self::moodleoverflow_mark_post_read($userid, $post); + moodleoverflow_throw_exception_with_check(!$postreadcheck, 'markreadfailed'); } // The discussion has been marked as read. diff --git a/classes/task/send_mails.php b/classes/task/send_mails.php index 310bbc5f88..7991f55023 100644 --- a/classes/task/send_mails.php +++ b/classes/task/send_mails.php @@ -89,13 +89,10 @@ public function send_review_notifications() { } $course = null; - $moodleoverflow = null; $usersto = null; $cm = null; - $discussion = null; - $success = []; foreach ($postinfos as $postinfo) { @@ -135,16 +132,8 @@ public function send_review_notifications() { cron_setup_user($userto, $course); } - $maildata = new moodleoverflow_email( - $course, - $cm, - $moodleoverflow, - $discussion, - $post, - $userfrom, - $userto, - false - ); + $maildata = new moodleoverflow_email($course, $cm, $moodleoverflow, $discussion, + $post, $userfrom, $userto, false); $textcontext = $maildata->export_for_template($renderertext, true); $htmlcontext = $maildata->export_for_template($rendererhtml, false); diff --git a/discussion.php b/discussion.php index fa32df35f9..483ed43301 100644 --- a/discussion.php +++ b/discussion.php @@ -23,7 +23,7 @@ */ defined('MOODLE_INTERNAL') || die(); -global $CFG, $PAGE, $USER, $SESSION, $OUTPUT; +global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; // Include config and locallib. require_once('../../config.php'); @@ -42,19 +42,14 @@ $PAGE->add_body_class('limitedwidth'); // Check if the discussion is valid. -if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $d])) { - throw new moodle_exception('invaliddiscussionid', 'moodleoverflow'); -} +$discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', ['id' => $d], 'invaliddiscussionid'); // Check if the related moodleoverflow instance is valid. -if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $discussion->moodleoverflow])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); -} +$moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $discussion->moodleoverflow], + 'invalidmoodleoverflowid'); // Check if the related moodleoverflow instance is valid. -if (!$course = $DB->get_record('course', ['id' => $discussion->course])) { - throw new moodle_exception('invalidcourseid'); -} +$course = moodleoverflow_get_record_or_exception('course', ['id' => $discussion->course], 'invalidcourseid', '*', true); // Save the allowmultiplemarks setting. $marksetting = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id], 'allowmultiplemarks'); diff --git a/externallib.php b/externallib.php index c0d802d7e8..8e148d368f 100644 --- a/externallib.php +++ b/externallib.php @@ -88,19 +88,15 @@ public static function record_vote($postid, $ratingid) { $post = $DB->get_record('moodleoverflow_posts', ['id' => $params['postid']], '*', MUST_EXIST); // Check if the discussion is valid. - if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $post->discussion])) { - throw new moodle_exception('invaliddiscussionid', 'moodleoverflow'); - } + $discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', ['id' => $post->discussion], + 'invaliddiscussionid'); // Check if the related moodleoverflow instance is valid. - if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $discussion->moodleoverflow])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); - } + $moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $discussion->moodleoverflow], + 'invalidmoodleoverflowid'); // Check if the related moodleoverflow instance is valid. - if (!$course = $DB->get_record('course', ['id' => $discussion->course])) { - throw new moodle_exception('invalidcourseid'); - } + $course = moodleoverflow_get_record_or_exception('course', ['id' => $discussion->course], 'invalidcourseid', '*', true); // Get the related coursemodule and its context. if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) { diff --git a/index.php b/index.php index 979e43a7f1..ad3a6da9a7 100644 --- a/index.php +++ b/index.php @@ -21,6 +21,9 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die(); + +global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; // Require needed files. use core\context\course; @@ -46,9 +49,7 @@ $PAGE->set_url($url); // Check if the id is related to a valid course. -if (!$course = $DB->get_record('course', ['id' => $id])) { - throw new moodle_exception('invalidcourseid'); -} +$course = moodleoverflow_get_record_or_exception('course', ['id' => $id], 'invalidcourseid', '*', true); // From now on, the user must be enrolled to a course. require_course_login($course); diff --git a/locallib.php b/locallib.php index e5a45a309d..5e28218312 100644 --- a/locallib.php +++ b/locallib.php @@ -2183,7 +2183,8 @@ function moodleoverflow_quick_array_sort(&$array, $low, $high, $key, $order) { } /** - * Function to get a record from the database and throw an exception, if the record is not available. + * Function to get a record from the database and throw an exception, if the record is not available. The error string is + * retrieved from moodleoverflow but can be retrieved from the core too. * @param string $table The table to get the record from * @param array $options Conditions for the record * @param string $exceptionstring Name of the moodleoverflow exception that should be thrown in case there is no record. diff --git a/markposts.php b/markposts.php index 9354f62912..77c9362253 100644 --- a/markposts.php +++ b/markposts.php @@ -21,6 +21,9 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die(); + +global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; // We do not need the locallib here. require_once('../../config.php'); @@ -46,14 +49,10 @@ $PAGE->set_url($url); // Retrieve the connected moodleoverflow instance. -if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflowid])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); -} +$moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $moodleoverflowid], 'invalidmoodleoverflowid'); // Retrieve the connected course. -if (!$course = $DB->get_record('course', ['id' => $moodleoverflow->course])) { - throw new moodle_exception('invalidcourseid'); -} +$course = moodleoverflow_get_record_or_exception('course', ['id' => $moodleoverflow->course], 'invalidcourseid', '*', true); // Get the coursemodule. if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) { @@ -100,10 +99,7 @@ // Check if the discussion exists. $options = ['id' => $discussionid, 'moodleoverflow' => $moodleoverflow->id]; - $discussion = $DB->get_record('moodleoverflow_discussions', $options); - if (!$discussion) { - throw new moodle_exception('invaliddiscussionid', 'moodleoverflow'); - } + $discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', $options, 'invaliddiscussionid'); // Mark all the discussions read. if (!\mod_moodleoverflow\readtracking::moodleoverflow_mark_discussion_read($discussionid, @@ -114,7 +110,6 @@ $status = \core\output\notification::NOTIFY_ERROR; } else { - // The discussion is successfully marked as read. $message = get_string('markmoodleoverflowreadsuccessful', 'moodleoverflow'); $status = \core\output\notification::NOTIFY_SUCCESS; diff --git a/subscribe.php b/subscribe.php index 0ea5367b30..05a0a02bbe 100644 --- a/subscribe.php +++ b/subscribe.php @@ -25,6 +25,9 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die(); + +global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; require_once(dirname(dirname(dirname(__FILE__))) . '/config.php'); require_once(dirname(__FILE__) . '/locallib.php'); @@ -50,9 +53,7 @@ } if (!is_null($discussionid)) { $url->param('d', $discussionid); - if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $discussionid, 'moodleoverflow' => $id])) { - throw new moodle_exception('invaliddiscussionid', 'moodleoverflow'); - } + $discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', ['id' => $discussionid, 'moodleoverflow' => $id], 'invaliddiscussionid'); } // Set the pages URL. diff --git a/tracking.php b/tracking.php index b152d5d439..2e174f154b 100644 --- a/tracking.php +++ b/tracking.php @@ -34,14 +34,10 @@ require_sesskey(); // Retrieve the moodleoverflow instance to track or untrack. -if (!$moodleoverflow = $DB->get_record("moodleoverflow", ["id" => $id])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); -} +$moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $id], 'invalidmoodleoverflowid'); // Retrieve the course of the instance. -if (!$course = $DB->get_record("course", ["id" => $moodleoverflow->course])) { - throw new moodle_exception('invalidcoursemodule'); -} +$course = moodleoverflow_get_record_or_exception('course', ['id' => $moodleoverflow->course], 'invalidcourseid', '*', true); // Retrieve the course module of that course. if (!$cm = get_coursemodule_from_instance("moodleoverflow", $moodleoverflow->id, $course->id)) { @@ -95,9 +91,7 @@ redirect($returnpageurl, get_string('nownottracking', 'moodleoverflow', $info), 1); } else { - // The insertion failed. - - // Print an error message. + // The insertion failed. Print an error message. throw new moodle_exception('cannottrack', 'moodleoverflow', get_local_referer(false)); } @@ -116,9 +110,7 @@ redirect($returnto, get_string('nowtracking', 'moodleoverflow', $info), 1); } else { - // The deletion failed. - - // Print an error message. + // The deletion failed. Print an error message. throw new moodle_exception('cannottrack', 'moodleoverflow', get_local_referer(false)); } } diff --git a/view.php b/view.php index 4178d7913d..52b55a157a 100644 --- a/view.php +++ b/view.php @@ -65,7 +65,6 @@ // Save the allowmultiplemarks setting. $marksetting = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id], 'allowmultiplemarks'); - // Require a login. require_login($course, true, $cm); From 0552964f0446c04c7b445e520a7db91cb5a99696 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Tue, 2 Jul 2024 11:52:25 +0200 Subject: [PATCH 14/17] solve failing behat tests --- classes/manager/mail_manager.php | 132 +++++++++++++------------------ classes/ratings.php | 120 +++++++++++++--------------- classes/readtracking.php | 16 ++-- classes/task/send_mails.php | 15 +--- discussion.php | 16 ++-- externallib.php | 16 ++-- index.php | 5 +- locallib.php | 45 ++++++++++- markposts.php | 17 ++-- subscribe.php | 6 +- tracking.php | 17 ++-- view.php | 1 - 12 files changed, 189 insertions(+), 217 deletions(-) diff --git a/classes/manager/mail_manager.php b/classes/manager/mail_manager.php index 04dbba65e3..e822a01719 100644 --- a/classes/manager/mail_manager.php +++ b/classes/manager/mail_manager.php @@ -65,7 +65,7 @@ class mail_manager { * @return bool */ public static function moodleoverflow_send_mails(): bool { - global $DB, $PAGE; + global $CFG, $DB, $PAGE; // Get the course object of the top level site. $site = get_site(); @@ -87,8 +87,7 @@ public static function moodleoverflow_send_mails(): bool { $courses = []; $coursemodules = []; - // Posts older than x days will not be mailed. - // This will avoid problems with the cron not ran for a long time. + // Posts older than x days will not be mailed. This will avoid problems with the cron not ran for a long time. $timenow = time(); $endtime = $timenow - get_config('moodleoverflow', 'maxeditingtime'); $starttime = $endtime - (get_config('moodleoverflow', 'maxmailingtime') * 60 * 60); @@ -101,7 +100,6 @@ public static function moodleoverflow_send_mails(): bool { mtrace('Errors occurred while trying to mark some posts as being mailed.'); return false; } - // Loop through all posts to be mailed. foreach ($posts as $postid => $post) { self::check_post($post, $mailcount, $users, $discussions, $errorcount, $posts, $postid, @@ -125,7 +123,7 @@ public static function moodleoverflow_send_mails(): bool { $userto->markposts = []; // Cache the capabilities of the user. - cron_setup_user($userto); + $CFG->branch >= 402 ? \core\cron::setup_user($userto) : cron_setup_user($userto); // Reset the caches. foreach ($coursemodules as $moodleoverflowid) { @@ -136,7 +134,6 @@ public static function moodleoverflow_send_mails(): bool { // Loop through all posts of this users. foreach ($posts as $post) { - self::send_post($userto, $post, $coursemodules, $errorcount, $discussions, $moodleoverflows, $courses, $mailcount, $users, $site, $textout, $htmlout); } @@ -147,18 +144,13 @@ public static function moodleoverflow_send_mails(): bool { } // Check for all posts whether errors occurred. - if ($posts) { - - // Loop through all posts. - foreach ($posts as $post) { - - // Tracing information. - mtrace($mailcount[$post->id] . " users were sent post $post->id"); + foreach ($posts as $post) { + // Tracing information. + mtrace($mailcount[$post->id] . " users were sent post $post->id"); - // Mark the posts with errors in the database. - if ($errorcount[$post->id]) { - $DB->set_field('moodleoverflow_posts', 'mailed', self::MOODLEOVERFLOW_MAILED_ERROR, ['id' => $post->id]); - } + // Mark the posts with errors in the database. + if ($errorcount[$post->id]) { + $DB->set_field('moodleoverflow_posts', 'mailed', self::MOODLEOVERFLOW_MAILED_ERROR, ['id' => $post->id]); } } @@ -231,7 +223,6 @@ public static function moodleoverflow_mark_old_posts_as_mailed($endtime) { * @param stdClass $user */ public static function moodleoverflow_minimise_user_record(stdClass $user) { - // Remove all information for the mail generation that are not needed. unset($user->institution); unset($user->department); @@ -267,61 +258,31 @@ public static function moodleoverflow_minimise_user_record(stdClass $user) { private static function check_post($post, array &$mailcount, array &$users, array &$discussions, array &$errorcount, array &$posts, int $postid, array &$moodleoverflows, array &$courses, array &$coursemodules) { - global $DB; // Check the cache if the discussion exists. $discussionid = $post->discussion; - if (!isset($discussions[$discussionid])) { - // Retrieve the discussion from the database. - $discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $post->discussion]); - - // If there is a record, update the cache. Else ignore the post. - if ($discussion) { - $discussions[$discussionid] = $discussion; - subscriptions::fill_subscription_cache($discussion->moodleoverflow); - subscriptions::fill_discussion_subscription_cache($discussion->moodleoverflow); - } else { - mtrace('Could not find discussion ' . $discussionid); - unset($posts[$postid]); - return; - } + if (!self::cache_record('moodleoverflow_discussions', $discussionid, $discussions, + 'Could not find discussion ', $posts, $postid, true)) { + return; } // Retrieve the connected moodleoverflow instance from the database. $moodleoverflowid = $discussions[$discussionid]->moodleoverflow; - if (!isset($moodleoverflows[$moodleoverflowid])) { - - // Retrieve the record from the database and update the cache. - $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflowid]); - if ($moodleoverflow) { - $moodleoverflows[$moodleoverflowid] = $moodleoverflow; - } else { - mtrace('Could not find moodleoverflow ' . $moodleoverflowid); - unset($posts[$postid]); - return; - } + if (!self::cache_record('moodleoverflow', $moodleoverflowid, $moodleoverflows, + 'Could not find moodleoverflow ', $posts, $postid, false)) { + return; } // Retrieve the connected courses from the database. $courseid = $moodleoverflows[$moodleoverflowid]->course; - if (!isset($courses[$courseid])) { - - // Retrieve the record from the database and update the cache. - $course = $DB->get_record('course', ['id' => $courseid]); - if ($course) { - $courses[$courseid] = $course; - } else { - mtrace('Could not find course ' . $courseid); - unset($posts[$postid]); - return; - } + if (!self::cache_record('course', $courseid, $courses, + 'Could not find course ', $posts, $postid, false)) { + return; } // Retrieve the connected course modules from the database. if (!isset($coursemodules[$moodleoverflowid])) { - // Retrieve the coursemodule and update the cache. - $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflowid, $courseid); - if ($cm) { + if ($cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflowid, $courseid)) { $coursemodules[$moodleoverflowid] = $cm; } else { mtrace('Could not find course module for moodleoverflow ' . $moodleoverflowid); @@ -332,14 +293,12 @@ private static function check_post($post, array &$mailcount, array &$users, arra // Cache subscribed users of each moodleoverflow. if (!isset($subscribedusers[$moodleoverflowid])) { - // Retrieve the context module. $modulecontext = context_module::instance($coursemodules[$moodleoverflowid]->id); // Retrieve all subscribed users. $mid = $moodleoverflows[$moodleoverflowid]; - $subusers = subscriptions::get_subscribed_users($mid, $modulecontext, 'u.*', true); - if ($subusers) { + if ($subusers = subscriptions::get_subscribed_users($mid, $modulecontext, 'u.*', true)) { // Loop through all subscribed users. foreach ($subusers as $postuser) { // Save the user into the cache. @@ -360,6 +319,39 @@ private static function check_post($post, array &$mailcount, array &$users, arra $errorcount[$postid] = 0; } + /** + * Helper function for check_post(). Caches the a record exists in the database and caches the record if needed. + * @param string $table + * @param int $id + * @param array $cache + * @param string $errorMessage + * @param array $posts + * @param int $postid + * @param bool $fillsubscache If the subscription cache is being filled (only when checking discussion cache) + * @return bool + * @throws \dml_exception + */ + private static function cache_record($table, $id, &$cache, $errormessage, &$posts, $postid, $fillsubscache) { + global $DB; + // Check if cache if an record exists already in the cache. + if (!isset($cache[$id])) { + // If there is a record in the database, update the cache. Else ignore the post. + if ($record = $DB->get_record($table, ['id' => $id])) { + $cache[$id] = $record; + if ($fillsubscache) { + subscriptions::fill_subscription_cache($record->moodleoverflow); + subscriptions::fill_discussion_subscription_cache($record->moodleoverflow); + } + } else { + mtrace($errormessage . $id); + unset($posts[$postid]); + return false; + } + } + return true; + } + + /** * Send the Mail with information of the post depending on theinformation available. * E.g. anonymous post do not include names, users who want resumes do not get single mails. @@ -427,9 +419,7 @@ private static function send_post($userto, $post, array &$coursemodules, array & // Check whether the user is subscribed to the discussion. $uid = $userto->id; - $did = $post->discussion; - $issubscribed = subscriptions::is_subscribed($uid, $moodleoverflow, $modulecontext, $did); - if (!$issubscribed) { + if (!subscriptions::is_subscribed($uid, $moodleoverflow, $modulecontext, $post->discussion)) { return; } @@ -462,7 +452,7 @@ private static function send_post($userto, $post, array &$coursemodules, array & } // Setup roles and languages. - cron_setup_user($userto, $course); + $CFG->branch >= 402 ? \core\cron::setup_user($userto, $course) : cron_setup_user($userto, $course); // Cache the users capability to view full names. if (!isset($userto->viewfullnames[$moodleoverflow->id])) { @@ -520,16 +510,7 @@ private static function send_post($userto, $post, array &$coursemodules, array & } // Format the data. - $data = new moodleoverflow_email( - $course, - $cm, - $moodleoverflow, - $discussion, - $post, - $userfrom, - $userto, - $canreply - ); + $data = new moodleoverflow_email($course, $cm, $moodleoverflow, $discussion, $post, $userfrom, $userto, $canreply); // Retrieve the unsubscribe-link. $userfrom->customheaders[] = sprintf('List-Unsubscribe: <%s>', $data->get_unsubscribediscussionlink()); @@ -555,7 +536,6 @@ private static function send_post($userto, $post, array &$coursemodules, array & // Check whether the post is a reply. if ($post->parent) { - // Add a reply header. $parentid = generate_email_messageid(hash('sha256', $post->parent . 'to' . $userto->id)); $userfrom->customheaders[] = "In-Reply-To: $parentid"; diff --git a/classes/ratings.php b/classes/ratings.php index 52d5756256..54ea4a1130 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -42,25 +42,18 @@ class ratings { * @param int $postid * @param int $rating * @param object $cm - * @param null $userid + * @param int $userid * * @return bool|int */ - public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rating, $cm, $userid = null) { - global $DB, $USER, $SESSION; - - // Has a user been submitted? - if (!isset($userid)) { - $userid = $USER->id; - } + public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rating, $cm, $userid) { + global $DB, $SESSION; // Is the submitted rating valid? $possibleratings = [RATING_NEUTRAL, RATING_DOWNVOTE, RATING_UPVOTE, RATING_SOLVED, RATING_HELPFUL, RATING_REMOVE_DOWNVOTE, RATING_REMOVE_UPVOTE, RATING_REMOVE_SOLVED, RATING_REMOVE_HELPFUL, ]; - if (!in_array($rating, $possibleratings)) { - throw new moodle_exception('invalidratingid', 'moodleoverflow'); - } + moodleoverflow_throw_exception_with_check(!in_array($rating, $possibleratings), 'invalidratingid'); // Get the related post. $post = moodleoverflow_get_record_or_exception('moodleoverflow_posts', ['id' => $postid], 'invalidparentpostid'); @@ -93,18 +86,17 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati 'returnurl' => '/mod/moodleoverflow/view.php?m' . $moodleoverflow->id, ]), get_string('youneedtoenrol')); } + //$returnurl = '/mod/moodleoverflow/view.php?m' . $moodleoverflow->id; + //moodleoverflow_catch_unenrolled_user($coursecontext, $course->id, $returnurl); // Notify the user, that he can not post a new discussion. throw new moodle_exception('noratemoodleoverflow', 'moodleoverflow'); } // Make sure post author != current user, unless they have permission. - if (($post->userid == $userid) && ! - (($rating == RATING_SOLVED || $rating == RATING_REMOVE_SOLVED) && - has_capability('mod/moodleoverflow:marksolved', $modulecontext)) - ) { - throw new moodle_exception('rateownpost', 'moodleoverflow'); - } + $authorcheck = ($post->userid == $userid) && !(($rating == RATING_SOLVED || $rating == RATING_REMOVE_SOLVED) && + has_capability('mod/moodleoverflow:marksolved', $modulecontext)); + moodleoverflow_throw_exception_with_check($authorcheck, 'rateownpost'); // Check if we are removing a mark. if (in_array($rating / 10, $possibleratings)) { @@ -125,11 +117,17 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati if ($rating == RATING_HELPFUL && $userid != $discussion->userid) { throw new moodle_exception('notstartuser', 'moodleoverflow'); } + // Make sure that a helpful mark is made by the user who started the discussion. + //$isnotstartuser = $rating == RATING_HELPFUL && $userid != $discussion->userid; + //moodleoverflow_throw_exception_with_check($isnotstartuser, 'nostartuser'); // Check if the current user is a teacher. if ($rating == RATING_SOLVED && !has_capability('mod/moodleoverflow:marksolved', $modulecontext)) { throw new moodle_exception('notteacher', 'moodleoverflow'); } + // Make sure that a solution mark is made by a teacher (or someone with the right capability). + //$isnotteacher = $rating == RATING_SOLVED && !has_capability('mod/moodleoverflow:marksolved', $modulecontext); + //moodleoverflow_throw_exception_with_check($isnotteacher, 'notteacher'); // Check if multiple marks are not enabled. if (!$multiplemarks) { @@ -145,22 +143,18 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati return self::moodleoverflow_update_rating_record($post->id, $rating, $userid, $otherrating->id, $modulecontext); } else { - $mid = $moodleoverflow->id; - - return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, + return self::moodleoverflow_add_rating_record($moodleoverflow->id, $discussion->id, $post->id, $rating, $userid, $modulecontext); } - } else { // If multiplemarks are allowed, only create a new rating. - $mid = $moodleoverflow->id; - return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, $rating, $userid, $modulecontext); + return self::moodleoverflow_add_rating_record($moodleoverflow->id, $discussion->id, $post->id, + $rating, $userid, $modulecontext); } } // Update an rating record. if ($oldrating['normal']) { - moodleoverflow_get_config_or_exception('moodleoverflow', 'allowratingchange', 'noratingchangeallowed', 'moodleoverflow'); @@ -174,10 +168,8 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati } // Create a new rating record. - $mid = $moodleoverflow->id; - $did = $post->discussion; - - return self::moodleoverflow_add_rating_record($mid, $did, $postid, $rating, $userid, $modulecontext); + return self::moodleoverflow_add_rating_record($moodleoverflow->id, $post->discussion, $postid, + $rating, $userid, $modulecontext); } /** @@ -185,24 +177,16 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati * Whether within a course or an instance is decided by the settings. * * @param int $moodleoverflowid - * @param null $userid + * @param int $userid * @param bool $forcesinglerating If true you only get the reputation for the given $moodleoverflowid, * even if coursewidereputation = true * * @return int */ - public static function moodleoverflow_get_reputation($moodleoverflowid, $userid = null, $forcesinglerating = false) { - global $DB, $USER; - - // Get the user id. - if (!isset($userid)) { - $userid = $USER->id; - } - + public static function moodleoverflow_get_reputation($moodleoverflowid, $userid, $forcesinglerating = false) { // Check the moodleoverflow instance. - if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflowid])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); - } + $moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $moodleoverflowid], + 'invalidmoodleoverflowid'); // Check whether the reputation can be summed over the whole course. if ($moodleoverflow->coursewidereputation && !$forcesinglerating) { @@ -313,9 +297,7 @@ public static function moodleoverflow_get_rating($postid) { global $DB; // Retrieve the full post. - if (!$post = $DB->get_record('moodleoverflow_posts', ['id' => $postid])) { - throw new moodle_exception('postnotexist', 'moodleoverflow'); - } + $post = moodleoverflow_get_record_or_exception('moodleoverflow_posts', ['id' => $postid], 'postnotexist'); // Get the rating for this single post. return self::moodleoverflow_get_ratings_by_discussion($post->discussion, $postid); @@ -412,12 +394,15 @@ public static function moodleoverflow_get_reputation_instance($moodleoverflowid, } // Check the moodleoverflow instance. - $moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $moodleoverflowid], - 'invalidmoodleoverflowid'); + if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflowid])) { + throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); + } + // Initiate a variable. $reputation = 0; if ($moodleoverflow->anonymous != anonymous::EVERYTHING_ANONYMOUS) { + // Get all posts of this user in this module. // Do not count votes for own posts. $sql = "SELECT r.id, r.postid as post, r.rating @@ -434,21 +419,33 @@ public static function moodleoverflow_get_reputation_instance($moodleoverflowid, $params = [$userid, $userid, $moodleoverflowid]; $records = $DB->get_records_sql($sql, $params); + // Check if there are results. + $records = (isset($records)) ? $records : []; + // Iterate through all ratings. foreach ($records as $record) { - switch ($record->rating) { - case RATING_DOWNVOTE: - $reputation += get_config('moodleoverflow', 'votescaledownvote'); - break; - case RATING_UPVOTE: - $reputation += get_config('moodleoverflow', 'votescaleupvote'); - break; - case RATING_HELPFUL: - $reputation += get_config('moodleoverflow', 'votescalehelpful'); - break; - case RATING_SOLVED: - $reputation += get_config('moodleoverflow', 'votescalesolved'); - break; + + // The rating is a downvote. + if ($record->rating == RATING_DOWNVOTE) { + $reputation += get_config('moodleoverflow', 'votescaledownvote'); + continue; + } + + // The rating is an upvote. + if ($record->rating == RATING_UPVOTE) { + $reputation += get_config('moodleoverflow', 'votescaleupvote'); + continue; + } + + // The post has been marked as helpful by the question owner. + if ($record->rating == RATING_HELPFUL) { + $reputation += get_config('moodleoverflow', 'votescalehelpful'); + continue; + } + + // The post has been marked as solved by a teacher. + if ($record->rating == RATING_SOLVED) { + $reputation += get_config('moodleoverflow', 'votescalesolved'); } } } @@ -585,7 +582,6 @@ private static function moodleoverflow_can_be_changed($postid, $rating, $userid) /** * Removes a rating record. - * * @param int $postid * @param int $rating * @param int $userid @@ -605,11 +601,7 @@ private static function moodleoverflow_remove_rating($postid, $rating, $userid, $oldrecord = self::moodleoverflow_check_old_rating($postid, $userid, $rating); // Trigger an event. - $params = [ - 'objectid' => $oldrecord->id, - 'context' => $modulecontext, - ]; - $event = \mod_moodleoverflow\event\rating_deleted::create($params); + $event = \mod_moodleoverflow\event\rating_deleted::create(['objectid' => $oldrecord->id, 'context' => $modulecontext]); $event->add_record_snapshot('moodleoverflow_ratings', $oldrecord); $event->trigger(); diff --git a/classes/readtracking.php b/classes/readtracking.php index 0905e78fe6..c23947175b 100644 --- a/classes/readtracking.php +++ b/classes/readtracking.php @@ -90,13 +90,8 @@ public static function moodleoverflow_is_tracked($moodleoverflow, $user = null) $user = $USER; } - // Guests cannot track a moodleoverflow. - if (isguestuser($USER) || empty($USER->id)) { - return false; - } - - // Check if the moodleoverflow can be generally tracked. - if (!self::moodleoverflow_can_track_moodleoverflows($moodleoverflow)) { + // Guests cannot track a moodleoverflow. The moodleoverflow should be generally trackable. + if (isguestuser($USER) || empty($USER->id) || !self::moodleoverflow_can_track_moodleoverflows($moodleoverflow)) { return false; } @@ -135,11 +130,12 @@ public static function moodleoverflow_mark_moodleoverflow_read($cm, $userid = nu // Iterate through all of this discussions. foreach ($discussions as $discussionid) { - // Mark the discussion as read. if (!self::moodleoverflow_mark_discussion_read($discussionid, context_module::instance($cm->id), $userid)) { throw new moodle_exception('markreadfailed', 'moodleoverflow'); } + // $markedcheck = self::moodleoverflow_mark_discussion_read($discussionid, context_module::instance($cm->id), $userid); + // moodleoverflow_throw_exception_with_check($markedcheck !== true, 'markreadfailed'); } return true; @@ -174,9 +170,9 @@ public static function moodleoverflow_mark_discussion_read($discussionid, $modco // Mark the post as read. if (!self::moodleoverflow_mark_post_read($userid, $post)) { throw new moodle_exception('markreadfailed', 'moodleoverflow'); - - return false; } + //$postreadcheck = self::moodleoverflow_mark_post_read($userid, $post); + //moodleoverflow_throw_exception_with_check(!$postreadcheck, 'markreadfailed'); } // The discussion has been marked as read. diff --git a/classes/task/send_mails.php b/classes/task/send_mails.php index 310bbc5f88..7991f55023 100644 --- a/classes/task/send_mails.php +++ b/classes/task/send_mails.php @@ -89,13 +89,10 @@ public function send_review_notifications() { } $course = null; - $moodleoverflow = null; $usersto = null; $cm = null; - $discussion = null; - $success = []; foreach ($postinfos as $postinfo) { @@ -135,16 +132,8 @@ public function send_review_notifications() { cron_setup_user($userto, $course); } - $maildata = new moodleoverflow_email( - $course, - $cm, - $moodleoverflow, - $discussion, - $post, - $userfrom, - $userto, - false - ); + $maildata = new moodleoverflow_email($course, $cm, $moodleoverflow, $discussion, + $post, $userfrom, $userto, false); $textcontext = $maildata->export_for_template($renderertext, true); $htmlcontext = $maildata->export_for_template($rendererhtml, false); diff --git a/discussion.php b/discussion.php index 295220bb08..bb0cfec030 100644 --- a/discussion.php +++ b/discussion.php @@ -24,6 +24,7 @@ // Include config and locallib. require_once('../../config.php'); +global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; require_once($CFG->dirroot . '/mod/moodleoverflow/locallib.php'); // Declare optional parameters. @@ -39,19 +40,14 @@ $PAGE->add_body_class('limitedwidth'); // Check if the discussion is valid. -if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $d])) { - throw new moodle_exception('invaliddiscussionid', 'moodleoverflow'); -} +$discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', ['id' => $d], 'invaliddiscussionid'); // Check if the related moodleoverflow instance is valid. -if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $discussion->moodleoverflow])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); -} +$moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $discussion->moodleoverflow], + 'invalidmoodleoverflowid'); // Check if the related moodleoverflow instance is valid. -if (!$course = $DB->get_record('course', ['id' => $discussion->course])) { - throw new moodle_exception('invalidcourseid'); -} +$course = moodleoverflow_get_record_or_exception('course', ['id' => $discussion->course], 'invalidcourseid', '*', true); // Save the allowmultiplemarks setting. $marksetting = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id], 'allowmultiplemarks'); @@ -83,7 +79,7 @@ if (in_array($ratingid, [RATING_SOLVED, RATING_REMOVE_SOLVED, RATING_HELPFUL, RATING_REMOVE_HELPFUL])) { // Rate the post. - if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, $ratedpost, $ratingid, $cm)) { + if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, $ratedpost, $ratingid, $cm, $USER->id)) { throw new moodle_exception('ratingfailed', 'moodleoverflow'); } diff --git a/externallib.php b/externallib.php index 6427bbfcbb..8e148d368f 100644 --- a/externallib.php +++ b/externallib.php @@ -88,19 +88,15 @@ public static function record_vote($postid, $ratingid) { $post = $DB->get_record('moodleoverflow_posts', ['id' => $params['postid']], '*', MUST_EXIST); // Check if the discussion is valid. - if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $post->discussion])) { - throw new moodle_exception('invaliddiscussionid', 'moodleoverflow'); - } + $discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', ['id' => $post->discussion], + 'invaliddiscussionid'); // Check if the related moodleoverflow instance is valid. - if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $discussion->moodleoverflow])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); - } + $moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $discussion->moodleoverflow], + 'invalidmoodleoverflowid'); // Check if the related moodleoverflow instance is valid. - if (!$course = $DB->get_record('course', ['id' => $discussion->course])) { - throw new moodle_exception('invalidcourseid'); - } + $course = moodleoverflow_get_record_or_exception('course', ['id' => $discussion->course], 'invalidcourseid', '*', true); // Get the related coursemodule and its context. if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) { @@ -114,7 +110,7 @@ public static function record_vote($postid, $ratingid) { // Rate the post. if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, - $params['postid'], $params['ratingid'], $cm)) { + $params['postid'], $params['ratingid'], $cm, $USER->id)) { throw new moodle_exception('ratingfailed', 'moodleoverflow'); } diff --git a/index.php b/index.php index 979e43a7f1..a798a7457e 100644 --- a/index.php +++ b/index.php @@ -26,6 +26,7 @@ use core\context\course; require_once(dirname(dirname(dirname(__FILE__))) . '/config.php'); +global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; require_once(dirname(__FILE__) . '/locallib.php'); require_once($CFG->dirroot . '/course/lib.php'); @@ -46,9 +47,7 @@ $PAGE->set_url($url); // Check if the id is related to a valid course. -if (!$course = $DB->get_record('course', ['id' => $id])) { - throw new moodle_exception('invalidcourseid'); -} +$course = moodleoverflow_get_record_or_exception('course', ['id' => $id], 'invalidcourseid', '*', true); // From now on, the user must be enrolled to a course. require_course_login($course); diff --git a/locallib.php b/locallib.php index 529f268a21..5e28218312 100644 --- a/locallib.php +++ b/locallib.php @@ -2183,19 +2183,20 @@ function moodleoverflow_quick_array_sort(&$array, $low, $high, $key, $order) { } /** - * Function to get a record from the database and throw an exception, if the record is not available. + * Function to get a record from the database and throw an exception, if the record is not available. The error string is + * retrieved from moodleoverflow but can be retrieved from the core too. * @param string $table The table to get the record from * @param array $options Conditions for the record * @param string $exceptionstring Name of the moodleoverflow exception that should be thrown in case there is no record. * @param string $fields Optional fields that are retrieved from the found record. - * @param bool $coreexception Optional param if exception from the core exceptions. + * @param bool $coreexception Optional param if exception is from the core exceptions. * @return mixed $record The found record */ function moodleoverflow_get_record_or_exception($table, $options, $exceptionstring, $fields = '*', $coreexception = false) { global $DB; if (!$record = $DB->get_record($table, $options, $fields)) { if ($coreexception) { - throw new moodle_exception('invalidcourseid'); + throw new moodle_exception($exceptionstring); } else { throw new moodle_exception($exceptionstring, 'moodleoverflow'); } @@ -2217,3 +2218,41 @@ function moodleoverflow_get_config_or_exception($plugin, $configname, $errorcode } return $config; } + +/** + * Function that throws an exception if a given check is true. + * @param bool $check The result of a boolean check. + * @param string $errorcode Error code/name of the exception + * @param string $coreexception Optional param if exception is from the core exceptions and not moodleoverflow. + * @return void + */ +function moodleoverflow_throw_exception_with_check($check, $errorcode, $coreexception = false) { + if ($check) { + if ($coreexception) { + throw new moodle_exception($errorcode); + } else { + throw new moodle_exception($errorcode, 'moodleoverflow'); + } + } +} + +/** + * Function that catches unenrolled users and redirects them to the enrolment page. + * @param context $coursecontext The context of the course. + * @param int $courseid Id of the course that the user needs to enrol. + * @param string $returnurl The url to return to after the user has been enrolled. + * @return void + */ +function moodleoverflow_catch_unenrolled_user($coursecontext, $courseid, $returnurl) { + global $SESSION; + if (!isguestuser() && !is_enrolled($coursecontext)) { + if (enrol_selfenrol_available($courseid)) { + $SESSION->wantsurl = qualified_me(); + $SESSION->enrolcancel = get_local_referer(false); + redirect(new \moodle_url('/enrol/index.php', [ + 'id' => $courseid, + 'returnurl' => $returnurl, + ]), get_string('youneedtoenrol')); + } + } +} diff --git a/markposts.php b/markposts.php index 9354f62912..77c9362253 100644 --- a/markposts.php +++ b/markposts.php @@ -21,6 +21,9 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die(); + +global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; // We do not need the locallib here. require_once('../../config.php'); @@ -46,14 +49,10 @@ $PAGE->set_url($url); // Retrieve the connected moodleoverflow instance. -if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflowid])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); -} +$moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $moodleoverflowid], 'invalidmoodleoverflowid'); // Retrieve the connected course. -if (!$course = $DB->get_record('course', ['id' => $moodleoverflow->course])) { - throw new moodle_exception('invalidcourseid'); -} +$course = moodleoverflow_get_record_or_exception('course', ['id' => $moodleoverflow->course], 'invalidcourseid', '*', true); // Get the coursemodule. if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) { @@ -100,10 +99,7 @@ // Check if the discussion exists. $options = ['id' => $discussionid, 'moodleoverflow' => $moodleoverflow->id]; - $discussion = $DB->get_record('moodleoverflow_discussions', $options); - if (!$discussion) { - throw new moodle_exception('invaliddiscussionid', 'moodleoverflow'); - } + $discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', $options, 'invaliddiscussionid'); // Mark all the discussions read. if (!\mod_moodleoverflow\readtracking::moodleoverflow_mark_discussion_read($discussionid, @@ -114,7 +110,6 @@ $status = \core\output\notification::NOTIFY_ERROR; } else { - // The discussion is successfully marked as read. $message = get_string('markmoodleoverflowreadsuccessful', 'moodleoverflow'); $status = \core\output\notification::NOTIFY_SUCCESS; diff --git a/subscribe.php b/subscribe.php index 0ea5367b30..3a70a89d24 100644 --- a/subscribe.php +++ b/subscribe.php @@ -25,9 +25,9 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - require_once(dirname(dirname(dirname(__FILE__))) . '/config.php'); require_once(dirname(__FILE__) . '/locallib.php'); +global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; // Define required and optional params. $id = required_param('id', PARAM_INT); // The moodleoverflow to set subscription on. @@ -50,9 +50,7 @@ } if (!is_null($discussionid)) { $url->param('d', $discussionid); - if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $discussionid, 'moodleoverflow' => $id])) { - throw new moodle_exception('invaliddiscussionid', 'moodleoverflow'); - } + $discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', ['id' => $discussionid, 'moodleoverflow' => $id], 'invaliddiscussionid'); } // Set the pages URL. diff --git a/tracking.php b/tracking.php index b152d5d439..4c5c5b2224 100644 --- a/tracking.php +++ b/tracking.php @@ -25,6 +25,7 @@ // Require needed files. require_once("../../config.php"); require_once("locallib.php"); +global $CFG, $DB, $USER; // Get submitted parameters. $id = required_param('id', PARAM_INT); // The moodleoverflow to track or untrack. @@ -34,14 +35,10 @@ require_sesskey(); // Retrieve the moodleoverflow instance to track or untrack. -if (!$moodleoverflow = $DB->get_record("moodleoverflow", ["id" => $id])) { - throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow'); -} +$moodleoverflow = moodleoverflow_get_record_or_exception('moodleoverflow', ['id' => $id], 'invalidmoodleoverflowid'); // Retrieve the course of the instance. -if (!$course = $DB->get_record("course", ["id" => $moodleoverflow->course])) { - throw new moodle_exception('invalidcoursemodule'); -} +$course = moodleoverflow_get_record_or_exception('course', ['id' => $moodleoverflow->course], 'invalidcourseid', '*', true); // Retrieve the course module of that course. if (!$cm = get_coursemodule_from_instance("moodleoverflow", $moodleoverflow->id, $course->id)) { @@ -95,9 +92,7 @@ redirect($returnpageurl, get_string('nownottracking', 'moodleoverflow', $info), 1); } else { - // The insertion failed. - - // Print an error message. + // The insertion failed. Print an error message. throw new moodle_exception('cannottrack', 'moodleoverflow', get_local_referer(false)); } @@ -116,9 +111,7 @@ redirect($returnto, get_string('nowtracking', 'moodleoverflow', $info), 1); } else { - // The deletion failed. - - // Print an error message. + // The deletion failed. Print an error message. throw new moodle_exception('cannottrack', 'moodleoverflow', get_local_referer(false)); } } diff --git a/view.php b/view.php index 4178d7913d..52b55a157a 100644 --- a/view.php +++ b/view.php @@ -65,7 +65,6 @@ // Save the allowmultiplemarks setting. $marksetting = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id], 'allowmultiplemarks'); - // Require a login. require_login($course, true, $cm); From 285e0df2293f2d665e3fdbd14b0d48cd718f6a53 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 12 Jul 2024 10:52:30 +0200 Subject: [PATCH 15/17] codecleaning --- discussion.php | 3 -- tests/behat/topicmove.feature | 68 +++++++++++++++++------------------ 2 files changed, 33 insertions(+), 38 deletions(-) diff --git a/discussion.php b/discussion.php index 28fbeeb481..bb0cfec030 100644 --- a/discussion.php +++ b/discussion.php @@ -21,9 +21,6 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - -global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; // Include config and locallib. require_once('../../config.php'); diff --git a/tests/behat/topicmove.feature b/tests/behat/topicmove.feature index 22ae518301..b0cb7dbffa 100644 --- a/tests/behat/topicmove.feature +++ b/tests/behat/topicmove.feature @@ -1,7 +1,6 @@ @mod @mod_moodleoverflow @javascript Feature: Teachers can move a discussion in one moodleoverflow forum to another moodleoverflow. - Background: Given the following "users" exist: | username | firstname | lastname | email | @@ -20,49 +19,48 @@ Feature: Teachers can move a discussion in one moodleoverflow forum to another m | moodleoverflow | everything anonymous | Test moodleoverflow description | C1 | 2 | 4 | And I log in as "admin" - Scenario: Move topic from public forum Given I am on "Course 1" course homepage - And I add a new discussion to "public moodleoverflow one" moodleoverflow with: + And I add a new discussion to "public moodleoverflow one" moodleoverflow with: | Subject | Public Message | | Message | This is the public message | - And I follow "public moodleoverflow one" - And I click on "Move this discussion to another moodleoverflow" "link" - Then I should see "public moodleoverflow two" - And I should see "question anonymous" - And I should see "everything anonymous" - And I should not see "Move discussion to public moodleoverflow one" - When I click on "Move discussion to public moodleoverflow two" "link" - And I am on "Course 1" course homepage - And I follow "public moodleoverflow two" - Then I should see "Public Message" + And I follow "public moodleoverflow one" + And I click on "Move this discussion to another moodleoverflow" "link" + Then I should see "public moodleoverflow two" + And I should see "question anonymous" + And I should see "everything anonymous" + And I should not see "Move discussion to public moodleoverflow one" + When I click on "Move discussion to public moodleoverflow two" "link" + And I am on "Course 1" course homepage + And I follow "public moodleoverflow two" + Then I should see "Public Message" Scenario: Move topic from question anonymous forum Given I am on "Course 1" course homepage - And I add a new discussion to "question anonymous" moodleoverflow with: - | Subject | Question Message | - | Message | This is the question anonymous message | - And I follow "question anonymous" - And I click on "Move this discussion to another moodleoverflow" "link" - And I should not see "Move discussion to public moodleoverflow one" - And I should not see "Move discussion to public moodleoverflow two" - And I should see "question anonymous" - And I should see "everything anonymous" - When I click on "Move discussion to everything anonymous" "link" - And I am on "Course 1" course homepage - And I follow "everything anonymous" - Then I should see "Question Message" + And I add a new discussion to "question anonymous" moodleoverflow with: + | Subject | Question Message | + | Message | This is the question anonymous message | + And I follow "question anonymous" + And I click on "Move this discussion to another moodleoverflow" "link" + And I should not see "Move discussion to public moodleoverflow one" + And I should not see "Move discussion to public moodleoverflow two" + And I should see "question anonymous" + And I should see "everything anonymous" + When I click on "Move discussion to everything anonymous" "link" + And I am on "Course 1" course homepage + And I follow "everything anonymous" + Then I should see "Question Message" Scenario: Move topic from question anonymous forum Given I am on "Course 1" course homepage - And I add a new discussion to "everything anonymous" moodleoverflow with: - | Subject | Everything Message | - | Message | This is the everything anonymous message | - And I follow "everything anonymous" - And I click on "Move this discussion to another moodleoverflow" "link" - And I should not see "Move discussion to public moodleoverflow one" - And I should not see "Move discussion to public moodleoverflow two" - And I should not see "Move discussion to question anonymous" - And I should not see "Move discussion to everything anonymous" + And I add a new discussion to "everything anonymous" moodleoverflow with: + | Subject | Everything Message | + | Message | This is the everything anonymous message | + And I follow "everything anonymous" + And I click on "Move this discussion to another moodleoverflow" "link" + And I should not see "Move discussion to public moodleoverflow one" + And I should not see "Move discussion to public moodleoverflow two" + And I should not see "Move discussion to question anonymous" + And I should not see "Move discussion to everything anonymous" From cabcaf3d81d4a886ce0271b22407f311e192cc16 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 9 Aug 2024 14:01:05 -0700 Subject: [PATCH 16/17] fix tests and new codecleaning --- classes/privacy/data_export_helper.php | 1 + classes/ratings.php | 12 ++++++------ subscribe.php | 5 ++++- tests/behat/installed.feature | 4 ++-- tests/privacy_provider_test.php | 1 + 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/classes/privacy/data_export_helper.php b/classes/privacy/data_export_helper.php index 858ae859f0..4e23c43fca 100644 --- a/classes/privacy/data_export_helper.php +++ b/classes/privacy/data_export_helper.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Privacy Subsystem implementation for mod_moodleoverflow. * diff --git a/classes/ratings.php b/classes/ratings.php index 0bc764e2e1..f664aa735d 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -264,7 +264,7 @@ public static function moodleoverflow_user_rated($postid, $userid = null) { // Get the rating. $sql = "SELECT firstrated, rating FROM {moodleoverflow_ratings} - WHERE userid = ? AND postid = ? AND (rating = 1 OR rating = 2)"; + WHERE userid = ? AND postid = ? AND (rating = 1 OR rating = 2)"; return ($DB->get_record_sql($sql, [ $userid, $postid ])); } @@ -421,7 +421,7 @@ public static function moodleoverflow_get_reputation_instance($moodleoverflowid, // Votes for own posts are not counting. $sql = "SELECT COUNT(id) as amount FROM {moodleoverflow_ratings} - WHERE userid = ? AND moodleoverflowid = ? AND (rating = 1 OR rating = 2)"; + WHERE userid = ? AND moodleoverflowid = ? AND (rating = 1 OR rating = 2)"; $params = [$userid, $moodleoverflowid]; $votes = $DB->get_record_sql($sql, $params); @@ -494,8 +494,8 @@ private static function moodleoverflow_check_old_rating($postid, $userid, $oldra $sql = "SELECT * FROM {moodleoverflow_ratings}"; // Get the normal rating. - $condition = "WHERE userid = ? AND postid = ? AND (rating = 1 OR rating = 2)"; - $rating['normal'] = $DB->get_record_sql($sql . $condition, [ $userid, $postid ]); + $condition = " WHERE userid = ? AND postid = ? AND (rating = 1 OR rating = 2)"; + $rating['normal'] = $DB->get_record_sql($sql . $condition, [$userid, $postid]); // Return the rating if it is requested. if ($oldrating == RATING_DOWNVOTE || $oldrating == RATING_UPVOTE) { @@ -503,7 +503,7 @@ private static function moodleoverflow_check_old_rating($postid, $userid, $oldra } // Get the solved rating. - $condition = "WHERE postid = ? AND rating = 3"; + $condition = " WHERE postid = ? AND rating = 3"; $rating['solved'] = $DB->get_record_sql($sql . $condition, [ $postid ]); // Return the rating if it is requested. @@ -512,7 +512,7 @@ private static function moodleoverflow_check_old_rating($postid, $userid, $oldra } // Get the helpful rating. - $condition = "WHERE postid = ? AND rating = 4"; + $condition = " WHERE postid = ? AND rating = 4"; $rating['helpful'] = $DB->get_record_sql($sql . $condition, [ $postid ]); // Return the rating if it is requested. diff --git a/subscribe.php b/subscribe.php index 3a70a89d24..0af8f73c2a 100644 --- a/subscribe.php +++ b/subscribe.php @@ -25,8 +25,10 @@ * @copyright 2017 Kennet Winter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once(dirname(dirname(dirname(__FILE__))) . '/config.php'); require_once(dirname(__FILE__) . '/locallib.php'); + global $CFG, $DB, $PAGE, $USER, $SESSION, $OUTPUT; // Define required and optional params. @@ -50,7 +52,8 @@ } if (!is_null($discussionid)) { $url->param('d', $discussionid); - $discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', ['id' => $discussionid, 'moodleoverflow' => $id], 'invaliddiscussionid'); + $discussion = moodleoverflow_get_record_or_exception('moodleoverflow_discussions', + ['id' => $discussionid, 'moodleoverflow' => $id], 'invaliddiscussionid'); } // Set the pages URL. diff --git a/tests/behat/installed.feature b/tests/behat/installed.feature index 9ef93e4436..52e9a0c4a1 100644 --- a/tests/behat/installed.feature +++ b/tests/behat/installed.feature @@ -1,4 +1,4 @@ -@mod @mod_moodleoverflow +@mod @mod_moodleoverflow @javascript Feature: Installation succeeds In order to use this plugin As a user @@ -8,5 +8,5 @@ Feature: Installation succeeds Given I log in as "admin" And I navigate to "Plugins > Plugins overview" in site administration Then the following should exist in the "plugins-control-panel" table: + |Plugin name| |moodleoverflow| - |mod_moodleoverflow| diff --git a/tests/privacy_provider_test.php b/tests/privacy_provider_test.php index 1211803e44..a9e7490712 100644 --- a/tests/privacy_provider_test.php +++ b/tests/privacy_provider_test.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Tests for the moodleoverflow implementation of the Privacy Provider API. * From b3b4d7dbe3c5cf2ae372b9a249cc1a7b99ce1a62 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 9 Sep 2024 11:01:04 +0200 Subject: [PATCH 17/17] update moodle ci --- .github/workflows/moodle-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 11b0d3ca71..37cf0557c1 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -50,7 +50,7 @@ jobs: - name: Initialise moodle-plugin-ci run: | - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci 4.5.4 echo $(cd ci/bin; pwd) >> $GITHUB_PATH echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH sudo locale-gen en_AU.UTF-8 @@ -173,7 +173,7 @@ jobs: - name: Initialise moodle-plugin-ci run: | - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci 4.5.4 echo $(cd ci/bin; pwd) >> $GITHUB_PATH echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH sudo locale-gen en_AU.UTF-8