Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401]

   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/>.
  16  
  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   */
  24  
  25  namespace mod_forum\local\entities;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  global $CFG;
  30  require_once($CFG->dirroot . '/mod/forum/lib.php');
  31  require_once($CFG->dirroot . '/rating/lib.php');
  32  
  33  use mod_forum\local\entities\discussion as discussion_entity;
  34  use context;
  35  use stdClass;
  36  
  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 $gradeforum The grade for the forum when grading holistically */
  73      private $gradeforum;
  74      /** @var bool $gradeforumnotify Whether to notify students when the forum is graded holistically */
  75      private $gradeforumnotify;
  76      /** @var int $maxbytes Maximum attachment size */
  77      private $maxbytes;
  78      /** @var int $maxattachments Maximum number of attachments */
  79      private $maxattachments;
  80      /** @var int $forcesubscribe Does the forum force users to subscribe? */
  81      private $forcesubscribe;
  82      /** @var int $trackingtype Tracking type */
  83      private $trackingtype;
  84      /** @var int $rsstype RSS type */
  85      private $rsstype;
  86      /** @var int $rssarticles RSS articles */
  87      private $rssarticles;
  88      /** @var int $timemodified Timestamp when the forum was last modified */
  89      private $timemodified;
  90      /** @var int $warnafter Warn after */
  91      private $warnafter;
  92      /** @var int $blockafter Block after */
  93      private $blockafter;
  94      /** @var int $blockperiod Block period */
  95      private $blockperiod;
  96      /** @var int $completiondiscussions Completion discussions */
  97      private $completiondiscussions;
  98      /** @var int $completionreplies Completion replies */
  99      private $completionreplies;
 100      /** @var int $completionposts Completion posts */
 101      private $completionposts;
 102      /** @var bool $displaywordcount Should display word counts in posts */
 103      private $displaywordcount;
 104      /** @var bool $lockdiscussionafter Timestamp after which discussions should be locked */
 105      private $lockdiscussionafter;
 106      /** @var int $duedate Timestamp that represents the due date for forum posts */
 107      private $duedate;
 108      /** @var int $cutoffdate Timestamp after which forum posts will no longer be accepted */
 109      private $cutoffdate;
 110  
 111      /**
 112       * Constructor
 113       *
 114       * @param context $context The forum module context
 115       * @param stdClass $coursemodule The forum course module record
 116       * @param stdClass $course The forum course record
 117       * @param int $effectivegroupmode The effective group mode
 118       * @param int $id ID
 119       * @param int $courseid Id of the course this forum is in
 120       * @param string $type The forum type, e.g. single, qanda, etc
 121       * @param string $name Name of the forum
 122       * @param string $intro Intro text
 123       * @param int $introformat Format of the intro text
 124       * @param int $assessed The forum rating aggregate
 125       * @param int $assesstimestart Timestamp to begin assessment
 126       * @param int $assesstimefinish Timestamp to end assessment
 127       * @param int $scale The rating scale
 128       * @param int $gradeforum The holistic grade
 129       * @param bool $gradeforumnotify Default for whether to notify students when grade holistically
 130       * @param int $maxbytes Maximum attachment size
 131       * @param int $maxattachments Maximum number of attachments
 132       * @param int $forcesubscribe Does the forum force users to subscribe?
 133       * @param int $trackingtype Tracking type
 134       * @param int $rsstype RSS type
 135       * @param int $rssarticles RSS articles
 136       * @param int $timemodified Timestamp when the forum was last modified
 137       * @param int $warnafter Warn after
 138       * @param int $blockafter Block after
 139       * @param int $blockperiod Block period
 140       * @param int $completiondiscussions Completion discussions
 141       * @param int $completionreplies Completion replies
 142       * @param int $completionposts Completion posts
 143       * @param bool $displaywordcount Should display word counts in posts
 144       * @param int $lockdiscussionafter Timestamp after which discussions should be locked
 145       * @param int $duedate Timestamp that represents the due date for forum posts
 146       * @param int $cutoffdate Timestamp after which forum posts will no longer be accepted
 147       */
 148      public function __construct(
 149          context $context,
 150          stdClass $coursemodule,
 151          stdClass $course,
 152          int $effectivegroupmode,
 153          int $id,
 154          int $courseid,
 155          string $type,
 156          string $name,
 157          string $intro,
 158          int $introformat,
 159          int $assessed,
 160          int $assesstimestart,
 161          int $assesstimefinish,
 162          int $scale,
 163          int $gradeforum,
 164          bool $gradeforumnotify,
 165          int $maxbytes,
 166          int $maxattachments,
 167          int $forcesubscribe,
 168          int $trackingtype,
 169          int $rsstype,
 170          int $rssarticles,
 171          int $timemodified,
 172          int $warnafter,
 173          int $blockafter,
 174          int $blockperiod,
 175          int $completiondiscussions,
 176          int $completionreplies,
 177          int $completionposts,
 178          bool $displaywordcount,
 179          int $lockdiscussionafter,
 180          int $duedate,
 181          int $cutoffdate
 182      ) {
 183          $this->context = $context;
 184          $this->coursemodule = $coursemodule;
 185          $this->course = $course;
 186          $this->effectivegroupmode = $effectivegroupmode;
 187          $this->id = $id;
 188          $this->courseid = $courseid;
 189          $this->type = $type;
 190          $this->name = $name;
 191          $this->intro = $intro;
 192          $this->introformat = $introformat;
 193          $this->assessed = $assessed;
 194          $this->assesstimestart = $assesstimestart;
 195          $this->assesstimefinish = $assesstimefinish;
 196          $this->scale = $scale;
 197          $this->gradeforum = $gradeforum;
 198          $this->gradeforumnotify = $gradeforumnotify;
 199          $this->maxbytes = $maxbytes;
 200          $this->maxattachments = $maxattachments;
 201          $this->forcesubscribe = $forcesubscribe;
 202          $this->trackingtype = $trackingtype;
 203          $this->rsstype = $rsstype;
 204          $this->rssarticles = $rssarticles;
 205          $this->timemodified = $timemodified;
 206          $this->warnafter = $warnafter;
 207          $this->blockafter = $blockafter;
 208          $this->blockperiod = $blockperiod;
 209          $this->completiondiscussions = $completiondiscussions;
 210          $this->completionreplies = $completionreplies;
 211          $this->completionposts = $completionposts;
 212          $this->displaywordcount = $displaywordcount;
 213          $this->lockdiscussionafter = $lockdiscussionafter;
 214          $this->duedate = $duedate;
 215          $this->cutoffdate = $cutoffdate;
 216      }
 217  
 218      /**
 219       * Get the forum module context.
 220       *
 221       * @return context
 222       */
 223      public function get_context() : context {
 224          return $this->context;
 225      }
 226  
 227      /**
 228       * Get the forum course module record
 229       *
 230       * @return stdClass
 231       */
 232      public function get_course_module_record() : stdClass {
 233          return $this->coursemodule;
 234      }
 235  
 236      /**
 237       * Get the effective group mode.
 238       *
 239       * @return int
 240       */
 241      public function get_effective_group_mode() : int {
 242          return $this->effectivegroupmode;
 243      }
 244  
 245      /**
 246       * Check if the forum is set to group mode.
 247       *
 248       * @return bool
 249       */
 250      public function is_in_group_mode() : bool {
 251          return $this->get_effective_group_mode() !== NOGROUPS;
 252      }
 253  
 254      /**
 255       * Get the course record.
 256       *
 257       * @return stdClass
 258       */
 259      public function get_course_record() : stdClass {
 260          return $this->course;
 261      }
 262  
 263      /**
 264       * Get the forum id.
 265       *
 266       * @return int
 267       */
 268      public function get_id() : int {
 269          return $this->id;
 270      }
 271  
 272      /**
 273       * Get the id of the course that the forum belongs to.
 274       *
 275       * @return int
 276       */
 277      public function get_course_id() : int {
 278          return $this->courseid;
 279      }
 280  
 281      /**
 282       * Get the forum type.
 283       *
 284       * @return string
 285       */
 286      public function get_type() : string {
 287          return $this->type;
 288      }
 289  
 290      /**
 291       * Get the forum name.
 292       *
 293       * @return string
 294       */
 295      public function get_name() : string {
 296          return $this->name;
 297      }
 298  
 299      /**
 300       * Get the forum intro text.
 301       *
 302       * @return string
 303       */
 304      public function get_intro() : string {
 305          return $this->intro;
 306      }
 307  
 308      /**
 309       * Get the forum intro text format.
 310       *
 311       * @return int
 312       */
 313      public function get_intro_format() : int {
 314          return $this->introformat;
 315      }
 316  
 317      /**
 318       * Get the rating aggregate.
 319       *
 320       * @return int
 321       */
 322      public function get_rating_aggregate() : int {
 323          return $this->assessed;
 324      }
 325  
 326      /**
 327       * Does the forum have a rating aggregate?
 328       *
 329       * @return bool
 330       */
 331      public function has_rating_aggregate() : bool {
 332          return $this->get_rating_aggregate() != RATING_AGGREGATE_NONE;
 333      }
 334  
 335      /**
 336       * Get the timestamp for when the assessment period begins.
 337       *
 338       * @return int
 339       */
 340      public function get_assess_time_start() : int {
 341          return $this->assesstimestart;
 342      }
 343  
 344      /**
 345       * Get the timestamp for when the assessment period ends.
 346       *
 347       * @return int
 348       */
 349      public function get_assess_time_finish() : int {
 350          return $this->assesstimefinish;
 351      }
 352  
 353      /**
 354       * Get the rating scale.
 355       *
 356       * @return int
 357       */
 358      public function get_scale() : int {
 359          return $this->scale;
 360      }
 361  
 362      /**
 363       * Get the grade for the forum when grading holistically.
 364       *
 365       * @return int
 366       */
 367      public function get_grade_for_forum() : int {
 368          return $this->gradeforum;
 369      }
 370  
 371      /**
 372       * Whether grading is enabled for this item.
 373       *
 374       * @return bool
 375       */
 376      public function is_grading_enabled(): bool {
 377          return $this->get_grade_for_forum() !== 0;
 378      }
 379  
 380      /**
 381       * Get the default for whether the students should be notified when grading holistically.
 382       *
 383       * @return bool
 384       */
 385      public function should_notify_students_default_when_grade_for_forum(): bool {
 386          return $this->gradeforumnotify;
 387      }
 388  
 389      /**
 390       * Get the maximum bytes.
 391       *
 392       * @return int
 393       */
 394      public function get_max_bytes() : int {
 395          return $this->maxbytes;
 396      }
 397  
 398      /**
 399       * Get the maximum number of attachments.
 400       *
 401       * @return int
 402       */
 403      public function get_max_attachments() : int {
 404          return $this->maxattachments;
 405      }
 406  
 407      /**
 408       * Get the subscription mode.
 409       *
 410       * @return int
 411       */
 412      public function get_subscription_mode() : int {
 413          return $this->forcesubscribe;
 414      }
 415  
 416      /**
 417       * Is the subscription mode set to optional.
 418       *
 419       * @return bool
 420       */
 421      public function is_subscription_optional() : bool {
 422          return $this->get_subscription_mode() === FORUM_CHOOSESUBSCRIBE;
 423      }
 424  
 425      /**
 426       * Is the subscription mode set to forced.
 427       *
 428       * @return bool
 429       */
 430      public function is_subscription_forced() : bool {
 431          return $this->get_subscription_mode() === FORUM_FORCESUBSCRIBE;
 432      }
 433  
 434      /**
 435       * Is the subscription mode set to automatic.
 436       *
 437       * @return bool
 438       */
 439      public function is_subscription_automatic() : bool {
 440          return $this->get_subscription_mode() === FORUM_INITIALSUBSCRIBE;
 441      }
 442  
 443      /**
 444       * Is the subscription mode set to disabled.
 445       *
 446       * @return bool
 447       */
 448      public function is_subscription_disabled() : bool {
 449          return $this->get_subscription_mode() === FORUM_DISALLOWSUBSCRIBE;
 450      }
 451  
 452      /**
 453       * Get the tracking type.
 454       *
 455       * @return int
 456       */
 457      public function get_tracking_type() : int {
 458          return $this->trackingtype;
 459      }
 460  
 461      /**
 462       * Get the RSS type.
 463       *
 464       * @return int
 465       */
 466      public function get_rss_type() : int {
 467          return $this->rsstype;
 468      }
 469  
 470      /**
 471       * Get the RSS articles.
 472       *
 473       * @return int
 474       */
 475      public function get_rss_articles() : int {
 476          return $this->rssarticles;
 477      }
 478  
 479      /**
 480       * Get the timestamp for when the forum was last modified.
 481       *
 482       * @return int
 483       */
 484      public function get_time_modified() : int {
 485          return $this->timemodified;
 486      }
 487  
 488      /**
 489       * Get warn after.
 490       *
 491       * @return int
 492       */
 493      public function get_warn_after() : int {
 494          return $this->warnafter;
 495      }
 496  
 497      /**
 498       * Get block after.
 499       *
 500       * @return int
 501       */
 502      public function get_block_after() : int {
 503          return $this->blockafter;
 504      }
 505  
 506      /**
 507       * Get the block period.
 508       *
 509       * @return int
 510       */
 511      public function get_block_period() : int {
 512          return $this->blockperiod;
 513      }
 514  
 515      /**
 516       * Does the forum have blocking enabled?
 517       *
 518       * @return bool
 519       */
 520      public function has_blocking_enabled() : bool {
 521          return !empty($this->get_block_after()) && !empty($this->get_block_period());
 522      }
 523  
 524      /**
 525       * Get the completion discussions.
 526       *
 527       * @return int
 528       */
 529      public function get_completion_discussions() : int {
 530          return $this->completiondiscussions;
 531      }
 532  
 533      /**
 534       * Get the completion replies.
 535       *
 536       * @return int
 537       */
 538      public function get_completion_replies() : int {
 539          return $this->completionreplies;
 540      }
 541  
 542      /**
 543       * Get the completion posts.
 544       *
 545       * @return int
 546       */
 547      public function get_completion_posts() : int {
 548          return $this->completionposts;
 549      }
 550  
 551      /**
 552       * Should the word counts be shown in the posts?
 553       *
 554       * @return bool
 555       */
 556      public function should_display_word_count() : bool {
 557          return $this->displaywordcount;
 558      }
 559  
 560      /**
 561       * Get the timestamp after which the discussion should be locked.
 562       *
 563       * @return int
 564       */
 565      public function get_lock_discussions_after() : int {
 566          return $this->lockdiscussionafter;
 567      }
 568  
 569      /**
 570       * Does the forum have a discussion locking timestamp?
 571       *
 572       * @return bool
 573       */
 574      public function has_lock_discussions_after() : bool {
 575          return !empty($this->get_lock_discussions_after());
 576      }
 577  
 578      /**
 579       * Check whether the discussion is locked based on forum's time based locking criteria
 580       *
 581       * @param discussion_entity $discussion
 582       * @return bool
 583       */
 584      public function is_discussion_time_locked(discussion_entity $discussion) : bool {
 585          if (!$this->has_lock_discussions_after()) {
 586              return false;
 587          }
 588  
 589          if ($this->get_type() === 'single') {
 590              // It does not make sense to lock a single discussion forum.
 591              return false;
 592          }
 593  
 594          return (($discussion->get_time_modified() + $this->get_lock_discussions_after()) < time());
 595      }
 596  
 597      /**
 598       * Get the cutoff date.
 599       *
 600       * @return int
 601       */
 602      public function get_cutoff_date() : int {
 603          return $this->cutoffdate;
 604      }
 605  
 606      /**
 607       * Does the forum have a cutoff date?
 608       *
 609       * @return bool
 610       */
 611      public function has_cutoff_date() : bool {
 612          return !empty($this->get_cutoff_date());
 613      }
 614  
 615      /**
 616       * Is the cutoff date for the forum reached?
 617       *
 618       * @return bool
 619       */
 620      public function is_cutoff_date_reached() : bool {
 621          if ($this->has_cutoff_date() && ($this->get_cutoff_date() < time())) {
 622              return true;
 623          }
 624  
 625          return false;
 626      }
 627  
 628      /**
 629       * Get the due date.
 630       *
 631       * @return int
 632       */
 633      public function get_due_date() : int {
 634          return $this->duedate;
 635      }
 636  
 637      /**
 638       * Does the forum have a due date?
 639       *
 640       * @return bool
 641       */
 642      public function has_due_date() : bool {
 643          return !empty($this->get_due_date());
 644      }
 645  
 646      /**
 647       * Is the due date for the forum reached?
 648       *
 649       * @return bool
 650       */
 651      public function is_due_date_reached() : bool {
 652          if ($this->has_due_date() && ($this->get_due_date() < time())) {
 653              return true;
 654          }
 655  
 656          return false;
 657      }
 658  
 659      /**
 660       * Is the discussion locked? - Takes into account both discussion settings AND forum's criteria
 661       *
 662       * @param discussion_entity $discussion The discussion to check
 663       * @return bool
 664       */
 665      public function is_discussion_locked(discussion_entity $discussion) : bool {
 666          if ($discussion->is_locked()) {
 667              return true;
 668          }
 669  
 670          return $this->is_discussion_time_locked($discussion);
 671      }
 672  }