use renderer_base;
/**
- * Forum class.
+ * Paged Content exporter.
*
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
/** @var int recordcount The total number of records available */
private $recordcount;
- /** @var closurcallable The callback to use to determine a page URL */
+ /** @var callable The callback to use to determine a page URL */
private $pageurlcallback;
/**
* Optional, defaults to PORTFOLIO_ADD_FULL_FORM
* @param string $addstr string to use for the button or icon alt text or link text.
* This is whole string, not key. optional, defaults to 'Add to portfolio';
- * @return void|string
+ * @return void|string|moodle_url
*/
public function to_html($format=null, $addstr=null) {
global $CFG, $COURSE, $OUTPUT, $USER;
* announce Whether the notification should be announced to screen readers.
Example context (json):
- { "message": "Your pants are on fire!", "closebutton": 1, "announce": 1, "extraclasses": "foo bar", "isSuccess": 1}
+ { "message": "Your pants are on fire!", "closebutton": 1, "announce": 1, "extraclasses": "foo bar", "issuccess": 1}
}}
{{#issuccess}}
{{> core/notification_success}}
* @return array Keys are the property names, values are their values.
*/
protected function get_other_values(renderer_base $output) {
- global $CFG;
-
$post = $this->post;
$authorgroups = $this->related['authorgroups'];
$forum = $this->related['forum'];
$discussion = $this->related['discussion'];
$author = $this->related['author'];
$user = $this->related['user'];
- $context = $this->related['context'];
$readreceiptcollection = $this->related['readreceiptcollection'];
$rating = $this->related['rating'];
$tags = $this->related['tags'];
$attachments = $this->related['attachments'];
$includehtml = $this->related['includehtml'];
- $forumrecord = $this->get_forum_record();
- $discussionrecord = $this->get_discussion_record();
- $postrecord = $this->get_post_record();
$isdeleted = $post->is_deleted();
$hasrating = $rating != null;
$hastags = !empty($tags);
*/
protected static function define_related() {
return [
- 'legacydatamapperfactory' => 'mod_forum\local\factories\legacy_data_mapper',
'capabilitymanager' => 'mod_forum\local\managers\capability',
'readreceiptcollection' => 'mod_forum\local\entities\post_read_receipt_collection?',
'urlfactory' => 'mod_forum\local\factories\url',
* @return string
*/
private function get_message(post_entity $post) : string {
+ global $CFG;
+
$context = $this->related['context'];
$message = file_rewrite_pluginfile_urls(
$post->get_message(),
if (!empty($CFG->enableplagiarism)) {
require_once($CFG->libdir . '/plagiarismlib.php');
+ $forum = $this->related['forum'];
$message .= plagiarism_get_links([
'userid' => $post->get_author_id(),
'content' => $message,
$post,
$urlfactory
) {
- $contextid = $attachment->get_contextid();
$exporter = new stored_file_exporter($attachment, ['context' => $context]);
$exportedattachment = $exporter->export($output);
$exporturl = $canexport ? $urlfactory->get_export_attachment_url_from_post_and_attachment($post, $attachment) : null;
*
* @param stdClass $exportedauthor The exported author object
* @param int $timecreated The post time created timestamp if it's to be displayed
+ * @return string
*/
private function get_author_subheading_html(stdClass $exportedauthor, int $timecreated) : string {
$fullname = $exportedauthor->fullname;
$date = "<time>{$formatteddate}</time>";
return get_string('bynameondate', 'mod_forum', ['name' => $name, 'date' => $date]);
}
-
- /**
- * Get the legacy forum record.
- *
- * @return stdClass
- */
- private function get_forum_record() : stdClass {
- $forumdbdatamapper = $this->related['legacydatamapperfactory']->get_forum_data_mapper();
- return $forumdbdatamapper->to_legacy_object($this->related['forum']);
- }
-
- /**
- * Get the legacy discussion record.
- *
- * @return stdClass
- */
- private function get_discussion_record() : stdClass {
- $discussiondbdatamapper = $this->related['legacydatamapperfactory']->get_discussion_data_mapper();
- return $discussiondbdatamapper->to_legacy_object($this->related['discussion']);
- }
-
- /**
- * Get the legacy post record.
- *
- * @return stdClass
- */
- private function get_post_record() : stdClass {
- $postdbdatamapper = $this->related['legacydatamapperfactory']->get_post_data_mapper();
- return $postdbdatamapper->to_legacy_object($this->post);
- }
}
defined('MOODLE_INTERNAL') || die();
+use mod_forum\local\entities\author as author_entity;
+use mod_forum\local\entities\post as post_entity;
use mod_forum\local\exporters\post as post_exporter;
use core\external\exporter;
use renderer_base;
*/
protected static function define_related() {
return [
- 'legacydatamapperfactory' => 'mod_forum\local\factories\legacy_data_mapper',
'capabilitymanager' => 'mod_forum\local\managers\capability',
'urlfactory' => 'mod_forum\local\factories\url',
'forum' => 'mod_forum\local\entities\forum',
bool $includehtml = false
) : posts_exporter {
return new posts_exporter($posts, $authorsbyid, $attachmentsbypostid, $groupsbyauthorid, $tagsbypostid, $ratingbypostid, [
- 'legacydatamapperfactory' => $this->legacydatamapperfactory,
'capabilitymanager' => $this->managerfactory->get_capability_manager($forum),
'urlfactory' => $this->urlfactory,
'forum' => $forum,
*/
public function get_replies_to_post(post_entity $post, string $orderby = 'created ASC') : array {
$alias = $this->get_table_alias();
- $params = [$post->get_discussion_id(), $post->get_time_created()];
+ $params = [$post->get_discussion_id(), $post->get_time_created(), $post->get_id()];
// Unfortunately the best we can do to filter down the query is ignore all posts
// that were created before the given post (since they can't be replies).
- $wheresql = "{$alias}.discussion = ? and {$alias}.created > ?";
+ $wheresql = "{$alias}.discussion = ? and {$alias}.created >= ? and {$alias}.id != ?";
$orderbysql = $alias . '.' . $orderby;
$sql = $this->generate_get_records_sql($wheresql, $orderbysql);
$records = $this->get_db()->get_records_sql($sql, $params);
* @deprecated since Moodle 3.7
*/
function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode, $canreply=NULL, $canrate=false) {
- debugging('forum_print_discussion() has been deprecated, please use \mod_forum\local\renderers\discussion instead.', DEBUG_DEVELOPER);
+ debugging('forum_print_discussion() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\discussion instead.', DEBUG_DEVELOPER);
global $USER, $CFG;
* @deprecated since Moodle 3.7
*/
function forum_post_nesting_cache() {
- debugging('forum_post_nesting_cache() has been deprecated, please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
+ debugging('forum_post_nesting_cache() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
static $nesting = array();
return $nesting;
}
* @deprecated since Moodle 3.7
*/
function forum_should_start_post_nesting($id) {
- debugging('forum_should_start_post_nesting() has been deprecated, please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
+ debugging('forum_should_start_post_nesting() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
$cache = forum_post_nesting_cache();
if (!array_key_exists($id, $cache)) {
$cache[$id] = 1;
* @deprecated since Moodle 3.7
*/
function forum_should_end_post_nesting($id) {
- debugging('forum_should_end_post_nesting() has been deprecated, please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
+ debugging('forum_should_end_post_nesting() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
$cache = forum_post_nesting_cache();
if (!array_key_exists($id, $cache)) {
return true;
* @deprecated since Moodle 3.7
*/
function forum_print_post_start($post, $return = false) {
- debugging('forum_print_post_start() has been deprecated, please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
+ debugging('forum_print_post_start() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
$output = '';
if (forum_should_start_post_nesting($post->id)) {
* @deprecated since Moodle 3.7
*/
function forum_print_post_end($post, $return = false) {
- debugging('forum_print_post_end() has been deprecated, please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
+ debugging('forum_print_post_end() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
$output = '';
if (forum_should_end_post_nesting($post->id)) {
*/
function forum_print_post($post, $discussion, $forum, &$cm, $course, $ownpost=false, $reply=false, $link=false,
$footer="", $highlight="", $postisread=null, $dummyifcantsee=true, $istracked=null, $return=false) {
- debugging('forum_print_post() has been deprecated, please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
+ debugging('forum_print_post() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
global $USER, $CFG, $OUTPUT;
require_once($CFG->libdir . '/filelib.php');
* @deprecated since Moodle 3.7
*/
function forum_print_posts_flat($course, &$cm, $forum, $discussion, $post, $mode, $reply, $forumtracked, $posts) {
- debugging('forum_print_posts_flat() has been deprecated, please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
+ debugging('forum_print_posts_flat() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
global $USER, $CFG;
$link = false;
* @deprecated since Moodle 3.7
*/
function forum_print_posts_threaded($course, &$cm, $forum, $discussion, $parent, $depth, $reply, $forumtracked, $posts) {
- debugging('forum_print_posts_threaded() has been deprecated, please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
+ debugging('forum_print_posts_threaded() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
global $USER, $CFG;
$link = false;
* @deprecated since Moodle 3.7
*/
function forum_print_posts_nested($course, &$cm, $forum, $discussion, $parent, $reply, $forumtracked, $posts) {
- debugging('forum_print_posts_nested() has been deprecated, please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
+ debugging('forum_print_posts_nested() has been deprecated, ' .
+ 'please use \mod_forum\local\renderers\posts instead.', DEBUG_DEVELOPER);
global $USER, $CFG;
$link = false;
* @return \stdClass
*/
public static function set_subscription_state($forumid, $discussionid, $targetstate) {
- global $DB, $PAGE, $USER;
+ global $PAGE, $USER;
$params = self::validate_parameters(self::set_subscription_state_parameters(), [
'forumid' => $forumid,
$vaultfactory = mod_forum\local\container::get_vault_factory();
$forumvault = $vaultfactory->get_forum_vault();
$forum = $forumvault->get_from_id($params['forumid']);
- $course = $forum->get_course_record();
$coursemodule = $forum->get_course_module_record();
$context = $forum->get_context();
self::validate_context($context);
- $managerfactory = mod_forum\local\container::get_manager_factory();
- $capabilitymanager = $managerfactory->get_capability_manager($forum);
$discussionvault = $vaultfactory->get_discussion_vault();
$discussion = $discussionvault->get_from_id($params['discussionid']);
$legacydatamapperfactory = mod_forum\local\container::get_legacy_data_mapper_factory();
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/forum_post_email_htmlemail
+ @template mod_forum/forum_discussion
- Template which defines a forum post for sending in a single-post HTML email.
+ Template for displaying a single forum discussion.
Classes required for JS:
* none
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/forum_post_email_htmlemail
+ @template mod_forum/forum_discussion_nested_post
- Template which defines a forum post for sending in a single-post HTML email.
+ Template to render a post in a nested format.
Classes required for JS:
* none
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/forum_post_email_htmlemail
+ @template mod_forum/forum_discussion_nested_posts
- Template which defines a forum post for sending in a single-post HTML email.
+ Template to render a list of posts in a nested format.
Classes required for JS:
* none
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/forum_post_email_htmlemail
+ @template mod_forum/forum_discussion_post
- Template which defines a forum post for sending in a single-post HTML email.
+ Template to render a single post from a discussion.
Classes required for JS:
* none
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/forum_post_email_htmlemail
+ @template mod_forum/forum_discussion_posts
- Template which defines a forum post for sending in a single-post HTML email.
+ Template to render a list of posts for a discussion.
Classes required for JS:
* none
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/forum_post_email_htmlemail
+ @template mod_forum/forum_discussion_threaded_post
- Template which defines a forum post for sending in a single-post HTML email.
+ Template to render a single post from a discussion in a threaded format.
Classes required for JS:
* none
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/forum_post_email_htmlemail
+ @template mod_forum/forum_discussion_threaded_posts
- Template which defines a forum post for sending in a single-post HTML email.
+ Template to render a list of posts in a threaded format.
Classes required for JS:
* none
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/forum_post_email_htmlemail
+ @template mod_forum/forum_posts_with_context_links
- Template which defines a forum post for sending in a single-post HTML email.
+ Template to render a list of posts with breadcrumb style subject and a link
+ in the footer to the full discussion.
Classes required for JS:
* none
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/qanda_discussion_list
+ @template mod_forum/news_discussion_list
- Template which defines a forum post for sending in a single-post HTML email.
+ Template to render a list of discussions for a news forum
Classes required for JS:
* none
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
- @template mod_forum/qanda_discussion_list
+ @template mod_forum/single_discussion_list
- Template which defines a forum post for sending in a single-post HTML email.
+ Template to render a discussion for a single discussion forum.
Classes required for JS:
* none
$b = ['id' => 2, 'parent' => 1];
$c = ['id' => 3, 'parent' => 1];
$d = ['id' => 4, 'parent' => 2];
+ $e = ['id' => 5, 'parent' => 0];
$expected = [
- [$a, [[$b, [[$d, []]]], [$c, []]]]
+ [$e, []],
+ [$a, [[$b, [[$d, []]]], [$c, []]]],
];
- $actual = $sorter->sort_into_children([$d, $b, $a, $c]);
+ $actual = $sorter->sort_into_children([$d, $b, $e, $a, $c]);
$this->assertEquals($expected, $actual);
}
$this->resetAfterTest();
$datagenerator = $this->getDataGenerator();
+ $forumgenerator = $datagenerator->get_plugin_generator('mod_forum');
$user = $datagenerator->create_user();
$course = $datagenerator->create_course();
$forum = $datagenerator->create_module('forum', ['course' => $course->id]);
[$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
- $post2 = $this->helper_reply_to_post($post1, $user);
+ // Create a post with the same created time as the parent post to ensure
+ // we've covered every possible scenario.
+ $post2 = $forumgenerator->create_post((object) [
+ 'discussion' => $post1->discussion,
+ 'parent' => $post1->id,
+ 'userid' => $user->id,
+ 'mailnow' => 1,
+ 'subject' => 'Some subject',
+ 'created' => $post1->created
+ ]);
$post3 = $this->helper_reply_to_post($post1, $user);
$post4 = $this->helper_reply_to_post($post2, $user);
[$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
This files describes API changes in /mod/forum/*,
information provided here is intended especially for developers.
+=== 3.7 ===
+ * Changed the forum discussion rendering to use templates rather than print functions.
+ * Added new forum entities, factories, exporters, renderers, and vaults in the local namespace to better encapsulate the forum data.
+ * Deprecated all of the forum_print_* functions in lib.php.
+
=== 3.6 ===
* forum_print_post should be surrounded with calls to forum_print_post_start and forum_print_post_end to create the proper HTML structure for the post.
$cmid = optional_param('id', 0, PARAM_INT);
$forumid = optional_param('f', 0, PARAM_INT);
-$pageno = optional_param('p', 0, PARAM_INT);
+$mode = optional_param('mode', 0, PARAM_INT);
+$showall = optional_param('showall', '', PARAM_INT);
+$pageno = optional_param('page', 0, PARAM_INT);
+$search = optional_param('search', '', PARAM_CLEAN);
+$pageno = optional_param('p', $pageno, PARAM_INT);
$pagesize = optional_param('s', 0, PARAM_INT);
$sortorder = optional_param('o', null, PARAM_INT);
-$mode = optional_param('mode', 0, PARAM_INT);
if (!$cmid && !$forumid) {
print_error('missingparameter');
throw new \moodle_exception('Unable to find forum with id ' . $forumid);
}
+if (!empty($showall)) {
+ // The user wants to see all discussions.
+ $pageno = 0;
+ $pagesize = 0;
+}
+
$urlfactory = mod_forum\local\container::get_url_factory();
$capabilitymanager = $managerfactory->get_capability_manager($forum);
$PAGE->set_title($forum->get_name());
$PAGE->add_body_class('forumtype-' . $forum->get_type());
$PAGE->set_heading($course->fullname);
-$PAGE->set_button(forum_search_form($course));
+$PAGE->set_button(forum_search_form($course, $search));
if (empty($cm->visible) && !has_capability('moodle/course:viewhiddenactivities', $forum->get_context())) {
redirect(