MDL-65032 mod_forum: Updates based on Jun's feedback
[moodle.git] / mod / forum / classes / local / entities / forum.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Forum class.
19  *
20  * @package    mod_forum
21  * @copyright  2019 Ryan Wyllie <ryan@moodle.com>
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 namespace mod_forum\local\entities;
27 defined('MOODLE_INTERNAL') || die();
29 global $CFG;
30 require_once($CFG->dirroot . '/mod/forum/lib.php');
31 require_once($CFG->dirroot . '/rating/lib.php');
33 use mod_forum\local\entities\discussion as discussion_entity;
34 use context;
35 use stdClass;
37 /**
38  * Forum class.
39  *
40  * @copyright  2019 Ryan Wyllie <ryan@moodle.com>
41  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42  */
43 class forum {
44     /** @var context $context The forum module context */
45     private $context;
46     /** @var stdClass $coursemodule The forum course module record */
47     private $coursemodule;
48     /** @var stdClass $course The forum course record */
49     private $course;
50     /** @var int $effectivegroupmode The effective group mode */
51     private $effectivegroupmode;
52     /** @var int $id ID */
53     private $id;
54     /** @var int $courseid Id of the course this forum is in */
55     private $courseid;
56     /** @var string $type The forum type, e.g. single, qanda, etc */
57     private $type;
58     /** @var string $name Name of the forum */
59     private $name;
60     /** @var string $intro Intro text */
61     private $intro;
62     /** @var int $introformat Format of the intro text */
63     private $introformat;
64     /** @var int $assessed The forum rating aggregate */
65     private $assessed;
66     /** @var int $assesstimestart Timestamp to begin assessment */
67     private $assesstimestart;
68     /** @var int $assesstimefinish Timestamp to end assessment */
69     private $assesstimefinish;
70     /** @var int $scale The rating scale */
71     private $scale;
72     /** @var int $maxbytes Maximum attachment size */
73     private $maxbytes;
74     /** @var int $maxattachments Maximum number of attachments */
75     private $maxattachments;
76     /** @var int $forcesubscribe Does the forum force users to subscribe? */
77     private $forcesubscribe;
78     /** @var int $trackingtype Tracking type */
79     private $trackingtype;
80     /** @var int $rsstype RSS type */
81     private $rsstype;
82     /** @var int $rssarticles RSS articles */
83     private $rssarticles;
84     /** @var int $timemodified Timestamp when the forum was last modified */
85     private $timemodified;
86     /** @var int $warnafter Warn after */
87     private $warnafter;
88     /** @var int $blockafter Block after */
89     private $blockafter;
90     /** @var int $blockperiod Block period */
91     private $blockperiod;
92     /** @var int $completiondiscussions Completion discussions */
93     private $completiondiscussions;
94     /** @var int $completionreplies Completion replies */
95     private $completionreplies;
96     /** @var int $completionposts Completion posts */
97     private $completionposts;
98     /** @var bool $displaywordcounts Should display word counts in posts */
99     private $displaywordcounts;
100     /** @var bool $lockdiscussionafter Timestamp after which discussions should be locked */
101     private $lockdiscussionafter;
102     /** @var int $duedate Timestamp that represents the due date for forum posts */
103     private $duedate;
104     /** @var int $cutoffdate Timestamp after which forum posts will no longer be accepted */
105     private $cutoffdate;
107     /**
108      * Constructor
109      *
110      * @param context $context The forum module context
111      * @param stdClass $coursemodule The forum course module record
112      * @param stdClass $course The forum course record
113      * @param int $effectivegroupmode The effective group mode
114      * @param int $id ID
115      * @param int $courseid Id of the course this forum is in
116      * @param string $type The forum type, e.g. single, qanda, etc
117      * @param string $name Name of the forum
118      * @param string $intro Intro text
119      * @param int $introformat Format of the intro text
120      * @param int $assessed The forum rating aggregate
121      * @param int $assesstimestart Timestamp to begin assessment
122      * @param int $assesstimefinish Timestamp to end assessment
123      * @param int $scale The rating scale
124      * @param int $maxbytes Maximum attachment size
125      * @param int $maxattachments Maximum number of attachments
126      * @param int $forcesubscribe Does the forum force users to subscribe?
127      * @param int $trackingtype Tracking type
128      * @param int $rsstype RSS type
129      * @param int $rssarticles RSS articles
130      * @param int $timemodified Timestamp when the forum was last modified
131      * @param int $warnafter Warn after
132      * @param int $blockafter Block after
133      * @param int $blockperiod Block period
134      * @param int $completiondiscussions Completion discussions
135      * @param int $completionreplies Completion replies
136      * @param int $completionposts Completion posts
137      * @param bool $displaywordcount Should display word counts in posts
138      * @param int $lockdiscussionafter Timestamp after which discussions should be locked
139      * @param int $duedate Timestamp that represents the due date for forum posts
140      * @param int $cutoffdate Timestamp after which forum posts will no longer be accepted
141      */
142     public function __construct(
143         context $context,
144         stdClass $coursemodule,
145         stdClass $course,
146         int $effectivegroupmode,
147         int $id,
148         int $courseid,
149         string $type,
150         string $name,
151         string $intro,
152         int $introformat,
153         int $assessed,
154         int $assesstimestart,
155         int $assesstimefinish,
156         int $scale,
157         int $maxbytes,
158         int $maxattachments,
159         int $forcesubscribe,
160         int $trackingtype,
161         int $rsstype,
162         int $rssarticles,
163         int $timemodified,
164         int $warnafter,
165         int $blockafter,
166         int $blockperiod,
167         int $completiondiscussions,
168         int $completionreplies,
169         int $completionposts,
170         bool $displaywordcount,
171         int $lockdiscussionafter,
172         int $duedate,
173         int $cutoffdate
174     ) {
175         $this->context = $context;
176         $this->coursemodule = $coursemodule;
177         $this->course = $course;
178         $this->effectivegroupmode = $effectivegroupmode;
179         $this->id = $id;
180         $this->courseid = $courseid;
181         $this->type = $type;
182         $this->name = $name;
183         $this->intro = $intro;
184         $this->introformat = $introformat;
185         $this->assessed = $assessed;
186         $this->assesstimestart = $assesstimestart;
187         $this->assesstimefinish = $assesstimefinish;
188         $this->scale = $scale;
189         $this->maxbytes = $maxbytes;
190         $this->maxattachments = $maxattachments;
191         $this->forcesubscribe = $forcesubscribe;
192         $this->trackingtype = $trackingtype;
193         $this->rsstype = $rsstype;
194         $this->rssarticles = $rssarticles;
195         $this->timemodified = $timemodified;
196         $this->warnafter = $warnafter;
197         $this->blockafter = $blockafter;
198         $this->blockperiod = $blockperiod;
199         $this->completiondiscussions = $completiondiscussions;
200         $this->completionreplies = $completionreplies;
201         $this->completionposts = $completionposts;
202         $this->displaywordcount = $displaywordcount;
203         $this->lockdiscussionafter = $lockdiscussionafter;
204         $this->duedate = $duedate;
205         $this->cutoffdate = $cutoffdate;
206     }
208     /**
209      * Get the forum module context.
210      *
211      * @return context
212      */
213     public function get_context() : context {
214         return $this->context;
215     }
217     /**
218      * Get the forum course module record
219      *
220      * @return stdClass
221      */
222     public function get_course_module_record() : stdClass {
223         return $this->coursemodule;
224     }
226     /**
227      * Get the effective group mode.
228      *
229      * @return int
230      */
231     public function get_effective_group_mode() : int {
232         return $this->effectivegroupmode;
233     }
235     /**
236      * Check if the forum is set to group mode.
237      *
238      * @return bool
239      */
240     public function is_in_group_mode() : bool {
241         return $this->get_effective_group_mode() !== NOGROUPS;
242     }
244     /**
245      * Get the course record.
246      *
247      * @return stdClass
248      */
249     public function get_course_record() : stdClass {
250         return $this->course;
251     }
253     /**
254      * Get the forum id.
255      *
256      * @return int
257      */
258     public function get_id() : int {
259         return $this->id;
260     }
262     /**
263      * Get the id of the course that the forum belongs to.
264      *
265      * @return int
266      */
267     public function get_course_id() : int {
268         return $this->courseid;
269     }
271     /**
272      * Get the forum type.
273      *
274      * @return string
275      */
276     public function get_type() : string {
277         return $this->type;
278     }
280     /**
281      * Get the forum name.
282      *
283      * @return string
284      */
285     public function get_name() : string {
286         return $this->name;
287     }
289     /**
290      * Get the forum intro text.
291      *
292      * @return string
293      */
294     public function get_intro() : string {
295         return $this->intro;
296     }
298     /**
299      * Get the forum intro text format.
300      *
301      * @return int
302      */
303     public function get_intro_format() : int {
304         return $this->introformat;
305     }
307     /**
308      * Get the rating aggregate.
309      *
310      * @return int
311      */
312     public function get_rating_aggregate() : int {
313         return $this->assessed;
314     }
316     /**
317      * Does the forum have a rating aggregate?
318      *
319      * @return bool
320      */
321     public function has_rating_aggregate() : bool {
322         return $this->get_rating_aggregate() != RATING_AGGREGATE_NONE;
323     }
325     /**
326      * Get the timestamp for when the assessment period begins.
327      *
328      * @return int
329      */
330     public function get_assess_time_start() : int {
331         return $this->assesstimestart;
332     }
334     /**
335      * Get the timestamp for when the assessment period ends.
336      *
337      * @return int
338      */
339     public function get_assess_time_finish() : int {
340         return $this->assesstimefinish;
341     }
343     /**
344      * Get the rating scale.
345      *
346      * @return int
347      */
348     public function get_scale() : int {
349         return $this->scale;
350     }
352     /**
353      * Get the maximum bytes.
354      *
355      * @return int
356      */
357     public function get_max_bytes() : int {
358         return $this->maxbytes;
359     }
361     /**
362      * Get the maximum number of attachments.
363      *
364      * @return int
365      */
366     public function get_max_attachments() : int {
367         return $this->maxattachments;
368     }
370     /**
371      * Get the subscription mode.
372      *
373      * @return int
374      */
375     public function get_subscription_mode() : int {
376         return $this->forcesubscribe;
377     }
379     /**
380      * Is the subscription mode set to optional.
381      *
382      * @return bool
383      */
384     public function is_subscription_optional() : bool {
385         return $this->get_subscription_mode() === FORUM_CHOOSESUBSCRIBE;
386     }
388     /**
389      * Is the subscription mode set to forced.
390      *
391      * @return bool
392      */
393     public function is_subscription_forced() : bool {
394         return $this->get_subscription_mode() === FORUM_FORCESUBSCRIBE;
395     }
397     /**
398      * Is the subscription mode set to automatic.
399      *
400      * @return bool
401      */
402     public function is_subscription_automatic() : bool {
403         return $this->get_subscription_mode() === FORUM_INITIALSUBSCRIBE;
404     }
406     /**
407      * Is the subscription mode set to disabled.
408      *
409      * @return bool
410      */
411     public function is_subscription_disabled() : bool {
412         return $this->get_subscription_mode() === FORUM_DISALLOWSUBSCRIBE;
413     }
415     /**
416      * Get the tracking type.
417      *
418      * @return int
419      */
420     public function get_tracking_type() : int {
421         return $this->trackingtype;
422     }
424     /**
425      * Get the RSS type.
426      *
427      * @return int
428      */
429     public function get_rss_type() : int {
430         return $this->rsstype;
431     }
433     /**
434      * Get the RSS articles.
435      *
436      * @return int
437      */
438     public function get_rss_articles() : int {
439         return $this->rssarticles;
440     }
442     /**
443      * Get the timestamp for when the forum was last modified.
444      *
445      * @return int
446      */
447     public function get_time_modified() : int {
448         return $this->timemodified;
449     }
451     /**
452      * Get warn after.
453      *
454      * @return int
455      */
456     public function get_warn_after() : int {
457         return $this->warnafter;
458     }
460     /**
461      * Get block after.
462      *
463      * @return int
464      */
465     public function get_block_after() : int {
466         return $this->blockafter;
467     }
469     /**
470      * Get the block period.
471      *
472      * @return int
473      */
474     public function get_block_period() : int {
475         return $this->blockperiod;
476     }
478     /**
479      * Does the forum have blocking enabled?
480      *
481      * @return bool
482      */
483     public function has_blocking_enabled() : bool {
484         return !empty($this->get_block_after()) && !empty($this->get_block_period());
485     }
487     /**
488      * Get the completion discussions.
489      *
490      * @return int
491      */
492     public function get_completion_discussions() : int {
493         return $this->completiondiscussions;
494     }
496     /**
497      * Get the completion replies.
498      *
499      * @return int
500      */
501     public function get_completion_replies() : int {
502         return $this->completionreplies;
503     }
505     /**
506      * Get the completion posts.
507      *
508      * @return int
509      */
510     public function get_completion_posts() : int {
511         return $this->completionposts;
512     }
514     /**
515      * Should the word counts be shown in the posts?
516      *
517      * @return bool
518      */
519     public function should_display_word_count() : bool {
520         return $this->displaywordcount;
521     }
523     /**
524      * Get the timestamp after which the discussion should be locked.
525      *
526      * @return int
527      */
528     public function get_lock_discussions_after() : int {
529         return $this->lockdiscussionafter;
530     }
532     /**
533      * Does the forum have a discussion locking timestamp?
534      *
535      * @return bool
536      */
537     public function has_lock_discussions_after() : bool {
538         return !empty($this->get_lock_discussions_after());
539     }
541     /**
542      * Check whether the discussion is locked based on forum's time based locking criteria
543      *
544      * @param discussion_entity $discussion
545      * @return bool
546      */
547     public function is_discussion_time_locked(discussion_entity $discussion) : bool {
548         if (!$this->has_lock_discussions_after()) {
549             return false;
550         }
552         if ($this->get_type() === 'single') {
553             // It does not make sense to lock a single discussion forum.
554             return false;
555         }
557         return (($discussion->get_time_modified() + $this->get_lock_discussions_after()) < time());
558     }
560     /**
561      * Get the cutoff date.
562      *
563      * @return int
564      */
565     public function get_cutoff_date() : int {
566         return $this->cutoffdate;
567     }
569     /**
570      * Does the forum have a cutoff date?
571      *
572      * @return bool
573      */
574     public function has_cutoff_date() : bool {
575         return !empty($this->get_cutoff_date());
576     }
578     /**
579      * Is the cutoff date for the forum reached?
580      *
581      * @return bool
582      */
583     public function is_cutoff_date_reached() : bool {
584         if ($this->has_cutoff_date() && ($this->get_cutoff_date() < time())) {
585             return true;
586         }
588         return false;
589     }
591     /**
592      * Get the due date.
593      *
594      * @return int
595      */
596     public function get_due_date() : int {
597         return $this->duedate;
598     }
600     /**
601      * Does the forum have a due date?
602      *
603      * @return bool
604      */
605     public function has_due_date() : bool {
606         return !empty($this->get_due_date());
607     }
609     /**
610      * Is the due date for the forum reached?
611      *
612      * @return bool
613      */
614     public function is_due_date_reached() : bool {
615         if ($this->has_due_date() && ($this->get_due_date() < time())) {
616             return true;
617         }
619         return false;
620     }
622     /**
623      * Is the discussion locked? - Takes into account both discussion settings AND forum's criteria
624      *
625      * @param discussion_entity $discussion The discussion to check
626      * @return bool
627      */
628     public function is_discussion_locked(discussion_entity $discussion) : bool {
629         if ($discussion->is_locked()) {
630             return true;
631         }
633         return $this->is_discussion_time_locked($discussion);
634     }