/**
  * Convenience function for subclasses. Returns HTML code suitable to
  * use for a button in this area.
  * @param mod_forumng_discussion $discussion
  * @param string $name Text of button
  * @param string $script Name/path of .php script (relative to mod/forumng)
  * @param bool $post If true, makes the button send a POST request
  * @param array $options If included, passes these options as well as 'd'
  * @param string $extrahtml If specified, adds this HTML at end of (just
  *   inside) the form
  * @param bool $highlight If true, adds a highlight class to the form
  * @param bool $selector If true, adds a selector class to the form (indicating that the
  *   JavaScript post selector should be used)
  * @return string HTML code for button
  */
 protected static function get_button($discussion, $name, $script, $post = false, $options = array(), $extrahtml = '', $highlight = false, $selector = false)
 {
     $method = $post ? 'post' : 'get';
     $optionshtml = '';
     $options['d'] = $discussion->get_id();
     if ($discussion->get_forum()->is_shared()) {
         $options['clone'] = $discussion->get_forum()->get_course_module_id();
     }
     if ($post) {
         $options['sesskey'] = sesskey();
     }
     foreach ($options as $key => $value) {
         $optionshtml .= '<input type="hidden" name="' . $key . '" value="' . $value . '" />';
     }
     $class = '';
     if ($highlight) {
         $class = 'forumng-highlight';
     }
     if ($selector) {
         $class .= ' forumng-selectorbutton';
     }
     if ($class !== '') {
         $class = ' class="' . trim($class) . '"';
     }
     return "<form method='{$method}' action='{$script}' {$class}><div>" . "{$optionshtml}<input type='submit' value='{$name}' />" . "{$extrahtml}</div></form>";
 }
 /**
  * Adds a discussion to the list (internal use only).
  * @param mod_forumng_discussion $discussion
  */
 function add_discussion($discussion)
 {
     if ($discussion->is_sticky() && !$discussion->is_deleted()) {
         $this->stickydiscussions[$discussion->get_id()] = $discussion;
     } else {
         $this->normaldiscussions[$discussion->get_id()] = $discussion;
     }
 }
function forumngfeature_usage_show_mostreaders($params, $forum = null)
{
    global $DB, $PAGE;
    $cloneid = empty($params['clone']) ? 0 : $params['clone'];
    if ($forum == null) {
        if (empty($params['id'])) {
            throw new moodle_exception('Missing forum id param');
        }
        $forum = mod_forumng::get_from_cmid($params['id'], $cloneid);
    }
    $groupwhere = '';
    $groupparams = array();
    $groupid = 0;
    if (!empty($params['group']) && $params['group'] != mod_forumng::NO_GROUPS && $params['group'] != mod_forumng::ALL_GROUPS) {
        $groupwhere = 'AND (fd.groupid = :groupid OR fd.groupid IS NULL)';
        $groupid = $params['group'];
        $groupparams = array('groupid' => $groupid);
    }
    if (has_capability('mod/forumng:viewreadinfo', $forum->get_context())) {
        if (!$PAGE->has_set_url()) {
            // Set context when called via ajax.
            $PAGE->set_context($forum->get_context());
        }
        $renderer = $PAGE->get_renderer('forumngfeature_usage');
        // Only get enrolled users - speeds up query significantly on large forums.
        list($sql, $params) = get_enrolled_sql($forum->get_context(), '', $groupid, true);
        // View discussions read.
        $readers = $DB->get_recordset_sql("\n                SELECT COUNT(fr.userid) AS count, fr.discussionid\n                  FROM {forumng_discussions} fd\n            RIGHT JOIN (\n\t\t                SELECT discussionid, userid\n\t\t                  FROM (\n\t\t                        SELECT * FROM {forumng_read}\n\t\t                     UNION ALL\n\t\t                        SELECT frp.id, frp.userid, fp.discussionid, frp.time\n                                  FROM {forumng_posts} fp\n                            RIGHT JOIN {forumng_read_posts} frp ON fp.id = frp.postid\n                                 WHERE fp.deleted = 0 AND fp.oldversion = 0\n                        ) frp GROUP BY discussionid, userid\n                ) fr ON fr.discussionid = fd.id\n                 WHERE fd.forumngid = :courseid\n                   AND fd.deleted = 0\n                {$groupwhere}\n                   AND fr.userid IN({$sql})\n              GROUP BY fr.discussionid\n              ORDER BY count desc, fr.discussionid desc", array_merge(array('courseid' => $forum->get_id()), $groupparams, $params), 0, 5);
        $readerlist = array();
        foreach ($readers as $discuss) {
            $discussion = mod_forumng_discussion::get_from_id($discuss->discussionid, $cloneid);
            list($content, $user) = $renderer->render_usage_discussion_info($forum, $discussion);
            $readerlist[] = $renderer->render_usage_list_item($forum, $discuss->count, $user, $content);
        }
        return $renderer->render_usage_list($readerlist, 'mostreaders', false);
    }
}
Example #4
0
 public function apply($discussion, $all, $selected, $formdata)
 {
     global $CFG;
     $filecontext = $discussion->get_context();
     $forum = $discussion;
     if (!isset($formdata->mailnow)) {
         $formdata->mailnow = false;
     }
     foreach ($selected as $postid) {
         // Call the lock for selected discussions.
         $discussion = mod_forumng_discussion::get_from_id($postid, $formdata->clone);
         if (!$discussion->is_deleted() && !$discussion->is_locked()) {
             $newpostid = $discussion->lock($formdata->subject, $formdata->message['text'], $formdata->message['format'], $formdata->attachments, $formdata->mailnow, '', '', $formdata->asmoderator);
             // Save attachments.
             file_save_draft_area_files($formdata->attachments, $filecontext->id, 'mod_forumng', 'attachment', $newpostid, null);
             $newtext = file_save_draft_area_files($formdata->message['itemid'], $filecontext->id, 'mod_forumng', 'message', $newpostid, null, $formdata->message['text']);
             if ($newtext !== $formdata->message['text']) {
                 mod_forumng_post::update_message_for_files($newpostid, $newtext);
             }
         }
     }
     // Redirect to the Main page.
     redirect('../../view.php?' . $forum->get_link_params(mod_forumng::PARAM_PLAIN));
 }
 /**
  * Obtain all flagged discussions in the forum by the given or current user,
  * The results should be ordered by the last post modified date (fplast.modified DESC)
  * @param int $userid User whose flags will be retrieved; 0 = current
  * @return array Array of mod_forumng_discussion objects
  */
 public function get_flagged_discussions($userid = 0)
 {
     global $USER;
     if ($userid != -1) {
         if ($userid == 0) {
             $userid = $USER->id;
         }
         $records = mod_forumng_discussion::query_discussions('fd.forumngid = ? AND ff.flagged IS NOT NULL AND ff.discussionid = fd.id AND ff.userid = ?', array($this->get_id(), $userid), $userid, 'x.flagged DESC', '', '', $this, true);
     }
     $result = array();
     foreach ($records as $record) {
         // Get discussion details from record and create discussionfields.
         $discussion = new mod_forumng_discussion($this, $record, true, $userid);
         $result[$record->id] = $discussion;
     }
     return $result;
 }
 /**
  * Either delete or archive old discussions based on the forum setting
  */
 public static function archive_old_discussions()
 {
     global $CFG, $DB;
     $now = time();
     $housekeepingquery = "\nFROM\n    {forumng_discussions} fd\n    INNER JOIN {forumng_posts} fp ON fd.lastpostid = fp.id\n    INNER JOIN {forumng} f ON fd.forumngid = f.id\nWHERE\n    f.removeafter<>0 AND fd.sticky<>1 AND fp.modified<? - f.removeafter\n";
     $housekeepingparams = array($now);
     $count = $DB->count_records_sql("SELECT COUNT(1) {$housekeepingquery}", $housekeepingparams);
     if ($count) {
         if (!PHPUNIT_TEST) {
             mtrace("\nBeginning processing {$count} discussion archiving/deleting requests");
         }
         $housekeepingrs = $DB->get_recordset_sql("\nSELECT\n    fd.id AS discussionid, f.id AS forumngid, f.removeafter, f.removeto\n{$housekeepingquery}\nORDER BY f.removeto", $housekeepingparams);
         $targetforum = null;
         $targetcourseid = null;
         $cronlog = '';
         $discussionmovecount = 0;
         $discussiondeletecount = 0;
         $discussionautolocked = 0;
         foreach ($housekeepingrs as $rec) {
             $discussion = mod_forumng_discussion::get_from_id($rec->discussionid, mod_forumng::CLONE_DIRECT);
             if ($rec->removeto) {
                 if ($rec->removeto == -1) {
                     // Locked record or discussion deleted.
                     if ($discussion->is_locked() || $discussion->is_auto_locked() || $discussion->is_deleted()) {
                         continue;
                     } else {
                         $end = $discussion->get_time_end();
                         $canautolock = true;
                         // Check to see whether time now is beyond the end time.
                         if ($end > $now) {
                             $canautolock = false;
                         }
                         if ($canautolock) {
                             // Lock record.
                             $discussion->auto_lock();
                             $discussionautolocked++;
                         } else {
                             continue;
                         }
                     }
                 } else {
                     // Moving to a different forum.
                     $forum = $discussion->get_forum();
                     $course = $forum->get_course();
                     $modinfo = get_fast_modinfo($course);
                     if ($forum->can_archive_forum($modinfo, $cronlog)) {
                         // Do not get the target forum and course id again
                         // if the target forum is the same.
                         if (!$targetforum || $targetforum->get_id() != $rec->removeto) {
                             $targetforum = mod_forumng::get_from_id($rec->removeto, mod_forumng::CLONE_DIRECT);
                             $targetforum = $targetforum->get_real_forum();
                         }
                         // Target discussion groupid must be the same as the original groupid.
                         $targetgroupmode = $targetforum->get_group_mode();
                         $targetgroupid = $targetgroupmode ? $discussion->get_group_id() : null;
                         $discussion->move($targetforum, $targetgroupid);
                         $discussionmovecount++;
                     }
                 }
             } else {
                 // Delete all discussions and relevant data permanently.
                 $discussion->permanently_delete();
                 $discussiondeletecount++;
             }
         }
         $housekeepingrs->close();
         if (!PHPUNIT_TEST) {
             mtrace("\n {$discussionmovecount} discussions have been archived and " . "{$discussiondeletecount} discussions have been deleted permanently and " . "{$discussionautolocked} discussions have been automatically locked");
         }
     }
 }
 /**
  * Either delete or archive old discussions based on the forum setting
  */
 static function archive_old_discussions()
 {
     global $CFG, $DB;
     $now = time();
     $housekeepingquery = "\nFROM\n    {forumng_discussions} fd\n    INNER JOIN {forumng_posts} fp ON fd.lastpostid = fp.id\n    INNER JOIN {forumng} f ON fd.forumngid = f.id\nWHERE\n    f.removeafter<>0 AND fd.sticky<>1 AND fp.modified<? - f.removeafter\n";
     $housekeepingparams = array($now);
     $count = $DB->count_records_sql("SELECT COUNT(1) {$housekeepingquery}", $housekeepingparams);
     if ($count) {
         mtrace("\nBeginning processing {$count} discussion archiving/deleting requests");
         $housekeepingrs = $DB->get_recordset_sql("\nSELECT\n    fd.id AS discussionid, f.id AS forumngid, f.removeafter, f.removeto\n{$housekeepingquery}\nORDER BY f.removeto", $housekeepingparams);
         $targetforum = null;
         $targetcourseid = null;
         $cronlog = '';
         $discussionmovecount = 0;
         $discussiondeletecount = 0;
         foreach ($housekeepingrs as $rec) {
             $discussion = mod_forumng_discussion::get_from_id($rec->discussionid, mod_forumng::CLONE_DIRECT);
             if ($rec->removeto) {
                 //moving to a different forum
                 $forum = $discussion->get_forum();
                 $course = $forum->get_course();
                 $modinfo = get_fast_modinfo($course);
                 if ($forum->can_archive_forum($modinfo, $cronlog)) {
                     // Do not get the target forum and course id again
                     // if the target forum is the same
                     if (!$targetforum || $targetforum->get_id() != $rec->removeto) {
                         $targetforum = mod_forumng::get_from_id($rec->removeto, mod_forumng::CLONE_DIRECT);
                         $targetforum = $targetforum->get_real_forum();
                     }
                     //target discussion groupid must be the same as the original groupid
                     $targetgroupmode = $targetforum->get_group_mode();
                     $targetgroupid = $targetgroupmode ? $discussion->get_group_id() : null;
                     $discussion->move($targetforum, $targetgroupid);
                     $discussionmovecount++;
                 }
             } else {
                 //Delete all discussions and relevant data permanently
                 $discussion->permanently_delete();
                 $discussiondeletecount++;
             }
         }
         $housekeepingrs->close();
         mtrace("\n {$discussionmovecount} discussions have been archived and " . "{$discussiondeletecount} discussions have been deleted permanently.");
     }
 }
 public function load_data()
 {
     global $DB, $COURSE;
     // Load base data
     $this->load_base_data($this->forumngid);
     // Get all files used in the discussions.
     if ($this->discussionids == '') {
         // Fallback in case nothing sent - get every discussion in forum!
         $this->discussionids = array();
         $groupid = mod_forumng::get_activity_group($this->cm, true);
         if ($groupid == -1) {
             $groupid = null;
         }
         $discussions = $DB->get_records('forumng_discussions', array('forumngid' => $this->cm->instance, 'groupid' => $groupid), '', 'id, postid');
         foreach ($discussions as $discussionrec) {
             if (!$discussionrec->postid) {
                 continue;
             }
             $discussion = mod_forumng_discussion::get_from_id($discussionrec->id, $this->cloneid);
             if ($discussion->can_view()) {
                 $this->discussionids[] = $discussion->get_id();
             }
         }
     } else {
         $this->posts = $this->discussionids;
         // Set so decode works.
         $this->discussionids = $this->decode_string_to_array();
         $this->posts = '';
     }
     if (empty($this->discussionids)) {
         throw new moodle_exception('exportallnodisc', 'forumngfeature_export', $this->get_return_url());
     }
     foreach ($this->discussionids as $discussionid) {
         $this->discussionid = $discussionid;
         $this->add_files();
     }
 }
Example #9
0
 /**
  * Called when displaying a group of posts together on one page.
  * @param mod_forumng_discussion $discussion Forum object
  * @param string $html HTML that has already been created for the group
  *   of posts
  * @return string Modified (if necessary) HTML
  */
 public function render_post_group($discussion, $html)
 {
     // Add ForumNG rating form if there are any ForumNG rating selects.
     // Check any Form exists before adding actionform.
     $hasratings = strpos($html, '<div class="forumng-editrating">') !== false;
     $hasform = strpos($html, '<form') !== false;
     if ($hasratings && !$hasform) {
         $script = '<script type="text/javascript">' . 'document.getElementById("forumng-actionform").autocomplete=false;' . '</script>';
         $html = '<form method="post" id="forumng-actionform" ' . 'action="action.php"><div>' . $script . $html . $discussion->get_link_params(mod_forumng::PARAM_FORM);
         if ($hasratings) {
             $html .= '<input type="submit" id="forumng-saveallratings" value="' . get_string('saveallratings', 'forumng') . '" name="action.rate"/>';
         }
         $html .= '</div></form>';
     }
     return $html;
 }
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
require_once '../../config.php';
require_once 'mod_forumng.php';
// Require discussion parameter here. Other parameters may be required in forum
// type.
$discussionid = required_param('d', PARAM_INT);
$pageparams = array('d' => $discussionid);
$cloneid = optional_param('clone', 0, PARAM_INT);
if ($cloneid) {
    $pageparams['clone'] = $cloneid;
}
// Construct discussion variable (will check id is valid)
// Retrieve new copy of discussion from database, but store it in cache
// for further use.
$discussion = mod_forumng_discussion::get_from_id($discussionid, $cloneid, 0, false, true);
$forum = $discussion->get_forum();
$course = $forum->get_course();
$cm = $forum->get_course_module();
$context = $forum->get_context();
$draftid = optional_param('draft', 0, PARAM_INT);
if ($draftid) {
    $pageparams['draft'] = $draftid;
    $draft = mod_forumng_draft::get_from_id($draftid);
    if (!$draft->is_reply() || $draft->get_discussion_id() != $discussionid) {
        print_error('draft_mismatch', 'forumng', $forum->get_url(mod_forumng::PARAM_HTML));
    }
    $root = $discussion->get_root_post();
    $inreplyto = $root->find_child($draft->get_parent_post_id(), false);
    if (!$inreplyto || !$inreplyto->can_reply($whynot) || !$discussion->can_view()) {
        if (!$whynot) {
 /**
  * Extend tests that check forumns and discussions being marked as read.
  *
  */
 public function test_discussions_mark_read()
 {
     global $USER, $DB;
     $this->resetAfterTest(true);
     $this->setAdminUser();
     $adminid = $USER->id;
     $generator = $this->getDataGenerator()->get_plugin_generator('mod_forumng');
     $course = $this->get_new_course();
     $etuser1 = $this->get_new_user('editingteacher', $course->id);
     $suser1 = $this->get_new_user('student', $course->id);
     $suser2 = $this->get_new_user('student', $course->id);
     $group1 = $this->get_new_group($course->id);
     $group2 = $this->get_new_group($course->id);
     $this->get_new_group_member($group1->id, $etuser1->id);
     $this->get_new_group_member($group1->id, $suser1->id);
     // Create 2 forums (1 group forum, 1 no groups), each with 1 discussion.
     $forum1 = $this->get_new_forumng($course->id, array('groupmode' => VISIBLEGROUPS));
     $forum2 = $this->get_new_forumng($course->id);
     $did1 = $generator->create_discussion(array('course' => $course, 'forum' => $forum1->get_id(), 'userid' => $etuser1->id, 'groupid' => $group1->id));
     $did2 = $generator->create_discussion(array('course' => $course, 'forum' => $forum2->get_id(), 'userid' => $etuser1->id));
     // Set the time for offset use.
     $posttime = time();
     // Ensure user prefs allow discussions/posts to be marked as read 'automatically'.
     unset_user_preference('forumng_manualmark', $etuser1);
     unset_user_preference('forumng_manualmark', $suser1);
     // Root post auto marked as read for ET the creator, of forum1 at group level.
     $etforums = mod_forumng::get_course_forums($course, $etuser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forum contains discussion post read by etuser1.
     $this->assertFalse($etforums[$forum1->get_id()]->has_unread_discussions());
     $this->assertEquals(0, $etforums[$forum1->get_id()]->get_num_unread_discussions());
     // Suser1 has NOT read root posts.
     $s1forums = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forums contain discussion posts NOT read by Suser1.
     $this->assertTrue($s1forums[$forum1->get_id()]->has_unread_discussions());
     $this->assertTrue($s1forums[$forum2->get_id()]->has_unread_discussions());
     // Discussion contains posts NOT read by S1.
     $this->assertEquals(1, $s1forums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(1, $s1forums[$forum2->get_id()]->get_num_unread_discussions());
     // User Prefs allow the marking of both discussion root posts as read 'automatically'.
     $posttime = $posttime + 2;
     $did1read = mod_forumng_discussion::get_from_id($did1[0], 0);
     $did1read->mark_read($posttime, $suser1->id);
     $did2read = mod_forumng_discussion::get_from_id($did2[0], 0);
     $did2read->mark_read($posttime, $suser1->id);
     // Check the root posts now marked as read for S1.
     $s1forums = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forums contain NO discussions not read by Suser1.
     $this->assertFalse($s1forums[$forum1->get_id()]->has_unread_discussions());
     $this->assertFalse($s1forums[$forum2->get_id()]->has_unread_discussions());
     // No forumn discussions contain root posts not read by Suser1.
     $this->assertEquals(0, $s1forums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(0, $s1forums[$forum2->get_id()]->get_num_unread_discussions());
     // Set user pref so discussions/posts marked 'manually'.
     set_user_preference('forumng_manualmark', 1, $etuser1);
     set_user_preference('forumng_manualmark', 1, $suser1);
     // Add extra posts to both discussions with time modified offset.
     $posttime = $posttime + 2;
     $did1s1p1 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser1->id, 'modified' => $posttime));
     $did1etp1 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $etuser1->id, 'modified' => $posttime));
     $did1s2p1 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser2->id, 'modified' => $posttime));
     $did2s1p2 = $generator->create_post(array('discussionid' => $did2[0], 'parentpostid' => $did2[1], 'userid' => $suser1->id, 'modified' => $posttime));
     $did2etp2 = $generator->create_post(array('discussionid' => $did2[0], 'parentpostid' => $did2[1], 'userid' => $etuser1->id, 'modified' => $posttime));
     $did2s2p1 = $generator->create_post(array('discussionid' => $did2[0], 'parentpostid' => $did2[1], 'userid' => $suser2->id, 'modified' => $posttime));
     $did1s1post1 = mod_forumng_post::get_from_id($did1s1p1->id, 0);
     $did2s1post2 = mod_forumng_post::get_from_id($did2s1p2->id, 0);
     $did1etpost1 = mod_forumng_post::get_from_id($did1etp1->id, 0);
     $did2etpost2 = mod_forumng_post::get_from_id($did2etp2->id, 0);
     $did1s2post1 = mod_forumng_post::get_from_id($did1s2p1->id, 0);
     $did2s2post1 = mod_forumng_post::get_from_id($did2s2p1->id, 0);
     // Check read status of new posts.
     $etforums = mod_forumng::get_course_forums($course, $etuser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Discussions DO have posts not read by ET.
     $this->assertTrue($etforums[$forum1->get_id()]->has_unread_discussions());
     $this->assertTrue($etforums[$forum2->get_id()]->has_unread_discussions());
     // A number of discussions contain posts NOT read by ET.
     $this->assertEquals(1, $etforums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(1, $etforums[$forum2->get_id()]->get_num_unread_discussions());
     $s1forums = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Discussions DO have posts not read by Suser1.
     $this->assertTrue($s1forums[$forum1->get_id()]->has_unread_discussions());
     $this->assertTrue($s1forums[$forum2->get_id()]->has_unread_discussions());
     // A number of discussions contain posts NOT read by Suser1.
     $this->assertEquals(1, $s1forums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(1, $s1forums[$forum2->get_id()]->get_num_unread_discussions());
     // Mark posts read individually.
     $posttime = $posttime + 2;
     $did1s1post1->mark_read($posttime, $etuser1->id);
     // Poster suser1, reader teacher 1.
     $did2s1post2->mark_read($posttime, $etuser1->id);
     // Poster suser1, reader teacher 1.
     $did1etpost1->mark_read($posttime, $suser1->id);
     // Poster etuser1, reader suser1.
     $did2etpost2->mark_read($posttime, $suser1->id);
     // Poster etuser1, reader suser1.
     $did1s2post1->mark_read($posttime, $suser1->id);
     $did2s2post1->mark_read($posttime, $suser1->id);
     $did1s2post1->mark_read($posttime, $etuser1->id);
     $did2s2post1->mark_read($posttime, $etuser1->id);
     // Check read status of newly marked read posts.
     $etforums = mod_forumng::get_course_forums($course, $etuser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Discussions have NO posts not read by ET.
     $this->assertFalse($etforums[$forum1->get_id()]->has_unread_discussions());
     $this->assertFalse($etforums[$forum2->get_id()]->has_unread_discussions());
     // No discussions contain posts not read by ET.
     $this->assertEquals(0, $etforums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(0, $etforums[$forum2->get_id()]->get_num_unread_discussions());
     $s1forums = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Discussions have NO posts not read by Suser1.
     $this->assertFalse($s1forums[$forum1->get_id()]->has_unread_discussions());
     $this->assertFalse($s1forums[$forum2->get_id()]->has_unread_discussions());
     // No discussions contain posts not read by Suser1.
     $this->assertEquals(0, $s1forums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(0, $s1forums[$forum2->get_id()]->get_num_unread_discussions());
     // Get read counts for ET user, includes their own posts,
     // also checks both query_forums() and query_discussions().
     $discussion1etuser = mod_forumng_discussion::get_from_id($did1[0], 0, $etuser1->id);
     $etuserposts = $discussion1etuser->get_num_posts();
     $this->assertEquals(1, count($etuserposts));
     $unreadpostsetuser = $discussion1etuser->get_num_unread_posts();
     $this->assertEquals(0, $unreadpostsetuser);
     $readpostsetuser = $DB->get_records('forumng_read_posts', array('userid' => $etuser1->id));
     $this->assertCount(4, $readpostsetuser);
     $discussion2etuser = mod_forumng_discussion::get_from_id($did2[0], 0, $etuser1->id);
     $etuserposts = $discussion2etuser->get_num_posts();
     $this->assertEquals(1, count($etuserposts));
     $unreadpostsetuser = $discussion2etuser->get_num_unread_posts();
     $this->assertEquals(0, $unreadpostsetuser);
     $readpostsetuser = $DB->get_records('forumng_read_posts', array('userid' => $etuser1->id));
     $this->assertCount(4, $readpostsetuser);
     // Get read counts for the student user 1, includes count of their own posts.
     $discussion1suser1 = mod_forumng_discussion::get_from_id($did1[0], 0, $suser1->id);
     $suser1posts = $discussion1suser1->get_num_posts();
     $this->assertEquals(1, count($suser1posts));
     $unreadpostsuser1 = $discussion1suser1->get_num_unread_posts();
     $this->assertEquals(0, $unreadpostsuser1);
     $readpostsuser1 = $DB->get_records('forumng_read_posts', array('userid' => $suser1->id));
     $this->assertCount(4, $readpostsuser1);
     $discussion2suser1 = mod_forumng_discussion::get_from_id($did2[0], 0, $suser1->id);
     $suser1posts = $discussion2suser1->get_num_posts();
     $this->assertEquals(1, count($suser1posts));
     $unreadpostsuser1 = $discussion2suser1->get_num_unread_posts();
     $this->assertEquals(0, $unreadpostsuser1);
     $readpostsuser1 = $DB->get_records('forumng_read_posts', array('userid' => $suser1->id));
     $this->assertCount(4, $readpostsuser1);
     // Ensure user prefs allow discussions/posts to be marked as read 'automatically'.
     unset_user_preference('forumng_manualmark', $etuser1);
     unset_user_preference('forumng_manualmark', $suser1);
     // Mark read at forumn/discussion level 'automatically'.
     $posttime = $posttime + 2;
     // Mark forumn/discussion 1 read 'automatically'.
     $did1read = mod_forumng_discussion::get_from_id($did1[0], 0);
     $did1read->mark_read($posttime, $etuser1->id);
     $did1read->mark_read($posttime, $suser1->id);
     // Mark forumn/discussion 2 read 'automatically'.
     $did2read = mod_forumng_discussion::get_from_id($did2[0], 0);
     $did2read->mark_read($posttime, $suser1->id);
     $did2read->mark_read($posttime, $etuser1->id);
     // Re-check Forumn read status of forum/discussions/posts.
     $etforums = mod_forumng::get_course_forums($course, $etuser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forum discussions have NO posts not read by ET.
     $this->assertFalse($etforums[$forum1->get_id()]->has_unread_discussions('use'));
     $this->assertFalse($etforums[$forum2->get_id()]->has_unread_discussions());
     // No forum discussion contains posts not read by ET.
     $this->assertEquals(0, $etforums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(0, $etforums[$forum2->get_id()]->get_num_unread_discussions());
     $s1forums = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forum discussions have NO posts not read by S1.
     $this->assertFalse($s1forums[$forum1->get_id()]->has_unread_discussions());
     $this->assertFalse($s1forums[$forum2->get_id()]->has_unread_discussions());
     // No forum discussion contains posts not read by S1.
     $this->assertEquals(0, $s1forums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(0, $s1forums[$forum2->get_id()]->get_num_unread_discussions());
     // Add some more posts to discussion 2 only, to remain NOT MARKED manually.
     $posttime = $posttime + 2;
     $did2s1p3 = $generator->create_post(array('discussionid' => $did2[0], 'parentpostid' => $did2[1], 'userid' => $suser1->id, 'modified' => $posttime));
     $did2s1post3 = mod_forumng_post::get_from_id($did2s1p3->id, 0);
     $did2etp3 = $generator->create_post(array('discussionid' => $did2[0], 'parentpostid' => $did2[1], 'userid' => $suser2->id, 'modified' => $posttime));
     $did2etpost3 = mod_forumng_post::get_from_id($did2etp3->id, 0);
     // Setuser pref so discussions/posts can be marked 'manually'.
     set_user_preference('forumng_manualmark', 1, $etuser1);
     set_user_preference('forumng_manualmark', 1, $suser1);
     // Check read status of forum/discussions/posts.
     $etforums = mod_forumng::get_course_forums($course, $etuser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forumn discussion 1 has NO post not read by ET.
     $this->assertFalse($etforums[$forum1->get_id()]->has_unread_discussions());
     $this->assertEquals(0, $etforums[$forum1->get_id()]->get_num_unread_discussions());
     // Forumn discussion 2 has post NOT read by ET.
     $this->assertTrue($etforums[$forum2->get_id()]->has_unread_discussions());
     $this->assertEquals(1, $etforums[$forum2->get_id()]->get_num_unread_discussions());
     $s1forums = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forumn discussions 1 has NO post unread by S1.
     $this->assertFalse($s1forums[$forum1->get_id()]->has_unread_discussions());
     $this->assertEquals(0, $s1forums[$forum1->get_id()]->get_num_unread_discussions());
     // Forumn discussion 2 DOES contain posts not read by S1.
     $this->assertTrue($s1forums[$forum2->get_id()]->has_unread_discussions());
     $this->assertEquals(1, $s1forums[$forum2->get_id()]->get_num_unread_discussions());
     // Mark only the older posts read individually.
     $posttime = $posttime + 2;
     $did1s1post1->mark_read($posttime, $etuser1->id);
     // Poster suser1, reader teacher 1.
     $did2s1post2->mark_read($posttime, $etuser1->id);
     // Poster suser1, reader teacher 1.
     $did1etpost1->mark_read($posttime, $suser1->id);
     // Poster etuser1, reader suser1.
     $did2etpost2->mark_read($posttime, $suser1->id);
     // Poster etuser1, reader suser1.
     // Get read counts for ET user, includes their own posts,
     // also checks both query_forums() and query_discussions().
     $discussion1etuser = mod_forumng_discussion::get_from_id($did1[0], 0, $etuser1->id);
     $etuserposts = $discussion1etuser->get_num_posts();
     $this->assertEquals(4, $etuserposts);
     $unreadpostsetuser = $discussion1etuser->get_num_unread_posts();
     $this->assertEquals(0, $unreadpostsetuser);
     $readpostsetuser = $DB->get_records('forumng_read_posts', array('userid' => $etuser1->id));
     $this->assertCount(2, $readpostsetuser);
     $discussion2etuser = mod_forumng_discussion::get_from_id($did2[0], 0, $etuser1->id);
     $etuserposts = $discussion2etuser->get_num_posts();
     $this->assertEquals(6, $etuserposts);
     $unreadpostsetuser = $discussion2etuser->get_num_unread_posts();
     $this->assertEquals(2, $unreadpostsetuser);
     // Get read counts for the student user 1, includes count of their own posts.
     $discussion1suser1 = mod_forumng_discussion::get_from_id($did1[0], 0, $suser1->id);
     $suser1posts = $discussion1suser1->get_num_posts();
     $this->assertEquals(1, count($suser1posts));
     $unreadpostsuser1 = $discussion1suser1->get_num_unread_posts();
     $this->assertEquals(0, $unreadpostsuser1);
     $readpostsuser1 = $DB->get_records('forumng_read_posts', array('userid' => $suser1->id));
     $this->assertCount(2, $readpostsuser1);
     $discussion2suser1 = mod_forumng_discussion::get_from_id($did2[0], 0, $suser1->id);
     $suser1posts = $discussion2suser1->get_num_posts();
     $this->assertEquals(1, count($suser1posts));
     $unreadpostsuser1 = $discussion2suser1->get_num_unread_posts();
     $this->assertEquals(1, $unreadpostsuser1);
     $readpostsuser1 = $DB->get_records('forumng_read_posts', array('userid' => $suser1->id));
     $this->assertCount(2, $readpostsuser1);
     // Check read status of forum/discussions/posts.
     $etforums = mod_forumng::get_course_forums($course, $etuser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forumn discussion 1  has NO posts not read by ET.
     $this->assertFalse($etforums[$forum1->get_id()]->has_unread_discussions());
     $this->assertEquals(0, $etforums[$forum1->get_id()]->get_num_unread_discussions());
     // Forumn discussion 2 contains posts NOT read by ET.
     $this->assertTrue($etforums[$forum2->get_id()]->has_unread_discussions());
     $this->assertEquals(1, $etforums[$forum2->get_id()]->get_num_unread_discussions());
     $s1forums = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forumn discussion 1 has NO posts not read by S1.
     $this->assertFalse($etforums[$forum1->get_id()]->has_unread_discussions());
     $this->assertEquals(0, $etforums[$forum1->get_id()]->get_num_unread_discussions());
     // Forumn discussion 2 contains posts NOT read by S1.
     $this->assertTrue($etforums[$forum2->get_id()]->has_unread_discussions());
     $this->assertEquals(1, $etforums[$forum2->get_id()]->get_num_unread_discussions());
     // Mark forumns read 'automatically'.
     $forums = mod_forumng::get_course_forums($course, $etuser1->id);
     $posttime = $posttime + 2;
     $forums[$forum1->get_id()]->mark_read(0, $posttime, $etuser1->id);
     $forums[$forum2->get_id()]->mark_read(0, $posttime, $etuser1->id);
     $forums = mod_forumng::get_course_forums($course, $suser1->id);
     $posttime = $posttime + 2;
     $forums[$forum2->get_id()]->mark_read(0, $posttime, $suser1->id);
     $forums[$forum1->get_id()]->mark_read(0, $posttime, $suser1->id);
     // Check Discussion read status of forum/discussions.
     $etforums = mod_forumng::get_course_forums($course, $etuser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forum discussions have NO posts not read by ET.
     $this->assertFalse($etforums[$forum1->get_id()]->has_unread_discussions());
     $this->assertFalse($etforums[$forum2->get_id()]->has_unread_discussions());
     // Forum discussions contain NO posts unread by ET.
     $this->assertEquals(0, $etforums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(0, $etforums[$forum2->get_id()]->get_num_unread_discussions());
     $s1forums = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS);
     // Forum discussions have NO posts not read by S1.
     $this->assertFalse($s1forums[$forum1->get_id()]->has_unread_discussions());
     $this->assertFalse($s1forums[$forum2->get_id()]->has_unread_discussions());
     // No Forum 1 discussion contains posts not read by S1.
     $this->assertEquals(0, $s1forums[$forum1->get_id()]->get_num_unread_discussions());
     $this->assertEquals(0, $s1forums[$forum2->get_id()]->get_num_unread_discussions());
 }
 /**
  * Displays the discussion page.
  * @param mod_forumng_discussion $discussion Discussion
  */
 public function print_discussion_page($discussion)
 {
     global $PAGE;
     $out = mod_forumng_utils::get_renderer();
     $previousread = (int) $discussion->get_time_read();
     // 'Read date' option (used when viewing all posts so that they keep
     // their read/unread colouring)
     $timeread = optional_param('timeread', 0, PARAM_INT);
     if ($timeread) {
         $discussion->pretend_time_read($timeread);
         $previousread = $timeread;
     }
     // 'Expand all' option (always chosen for non-JS browsers)
     $expandall = optional_param('expand', 0, PARAM_INT) || $PAGE->devicetypeinuse == 'legacy';
     // 'Expand all' option (always chosen for non-JS browsers)
     $collapseall = optional_param('collapse', 0, PARAM_INT);
     if (!$collapseall && !$expandall && $PAGE->devicetypeinuse == 'mobile') {
         $collapseall = 1;
     }
     // Link back to first unread post if there is one
     print $discussion->display_unread_skip_link();
     // Magic expand tracker (for use in JS only, never set server-side).
     // This tracks expanded posts, and makes the Back button 'work' in
     // the sense that it will expand these posts again.
     print '<form method="post" action="."><div>' . '<input type="hidden" id="expanded_posts" name="expanded_posts" ' . 'value="" /></div></form>';
     // Get content for all posts in the discussion
     $options = array();
     if ($expandall) {
         $options[mod_forumng_post::OPTION_CHILDREN_EXPANDED] = true;
     }
     if ($collapseall) {
         $options[mod_forumng_post::OPTION_CHILDREN_COLLAPSED] = true;
     }
     $content = $out->render_discussion($discussion, $options);
     // Some post display options use the read time to construct links
     // (usually for non-JS version) so that unread state is maintained.
     $options[mod_forumng_post::OPTION_READ_TIME] = $previousread;
     // Display expand all option if there are any 'Expand' links in content
     $fakedate = '&amp;timeread=' . $previousread;
     print '<div id="forumng-expandall">';
     $showexpandall = preg_match('~<a [^>]*href="discuss\\.php\\?d=[0-9]+[^"]*&amp;expand=1#p[0-9]+">~', $content);
     // Note: On bad browsers we always expand all posts
     $showcollapseall = preg_match('~<div class="forumng-post forumng-full.*<div class="forumng-post forumng-full~s', $content) && $PAGE->devicetypeinuse != 'legacy';
     if ($showexpandall) {
         print '<a class="forumng-expandall-link" href="' . $discussion->get_url(mod_forumng::PARAM_HTML) . '&amp;expand=1' . $fakedate . '">' . get_string('expandall', 'forumng') . '</a>';
         if ($showcollapseall) {
             print '<span class="forumng-dot-separator"> &#x2022; </span>';
         }
     }
     if ($showcollapseall) {
         print '<a class="forumng-collapseall-link" href="' . $discussion->get_url(mod_forumng::PARAM_HTML) . '&amp;collapse=1' . $fakedate . '">' . get_string('collapseall', 'forumng') . '</a> ';
     }
     print '</div>';
     // Display content
     print $content;
     // Link back to forum
     print $discussion->display_link_back_to_forum();
     // Display discussion features (row of buttons)
     print $discussion->display_forumngfeature_discussions();
     // Display the subscription options to this disucssion if available
     print $discussion->display_subscribe_options();
     // Atom/RSS links
     print $discussion->display_feed_links();
     // Set read data [shouldn't this logic be somewhere else as it is not
     // part of display?]
     if (mod_forumng::mark_read_automatically()) {
         $discussion->mark_read();
     }
 }
 /**
  * Create a discussion using the generator, returns discussion object
  * @param mod_forumng $forum
  * @param array $options Must contain userid
  * @return mod_forumng_discussion
  */
 public function get_new_discussion(mod_forumng $forum, array $options)
 {
     $options['forum'] = $forum->get_id();
     $options['course'] = $forum->get_course_id();
     $generator = $this->getDataGenerator()->get_plugin_generator('mod_forumng');
     $dis = $generator->create_discussion($options);
     return mod_forumng_discussion::get_from_id($dis[0], mod_forumng::CLONE_DIRECT);
 }
 /**
  * Calls search_update on each child of the current post, and recurses.
  * Used when the subject's discussion is changed.
  */
 public function search_update_children()
 {
     if (!mod_forumng::search_installed()) {
         return;
     }
     // If the in-memory post object isn't already part of a full
     // discussion...
     if (!is_array($this->children)) {
         // ...then get one
         $discussion = mod_forumng_discussion::get_from_id($this->discussion->get_id(), $this->get_forum()->get_course_module_id());
         $post = $discussion->get_root_post()->find_child($this->get_id());
         // Do this update on the new discussion
         $post->search_update_children();
         return;
     }
     // Loop through all children
     foreach ($this->children as $child) {
         // Update its search fields
         $child->search_update();
         // Recurse
         $child->search_update_children();
     }
 }
Example #15
0
function get_forum_discussions_groups($selectedids, $forum, $cloneid)
{
    $groups = array();
    foreach ($selectedids as $d) {
        // We have the discussions and forum cmid, check to see whether it has groups.
        $discussion = mod_forumng_discussion::get_from_id($d, $cloneid);
        // Work out target group.
        $group = get_target_group($discussion, $forum, true);
        $groups[] = $group;
    }
    $groups = array_unique($groups);
    return $groups;
}
Example #16
0
function make_discussion($forum, $posts, $readusers, &$userids, $ratingpercent)
{
    set_time_limit(200);
    // Make discussion
    static $index = 0;
    $index++;
    list($discussionid, $postid) = $forum->create_discussion(null, 'Discussion ' . $index, get_post_text(), FORMAT_HTML, array(), false, 0, 0, false, false, $userids[mt_rand(0, count($userids) - 1)], false);
    $discussion = mod_forumng_discussion::get_from_id($discussionid, mod_forumng::CLONE_DIRECT);
    // Make posts
    $count = my_random($posts) - 1;
    $allposts = array($discussion->get_root_post());
    for ($i = 0; $i < $count; $i++) {
        make_post($discussion, $allposts, $userids, $ratingpercent);
    }
    // Mark the discussion read if requested
    if ($readusers > 0) {
        $now = time();
        for ($i = 0; $i < $readusers; $i++) {
            $discussion->mark_read($now, $userids[$i]);
        }
    }
    // Progress
    print '.';
}
 /**
  * Obtains list of posts to include in an Atom/RSS feed.
  * @param int $groupid Group ID (may be ALL_GROUPS)
  * @param int $userid User ID
  * @param mod_forumng_discussion $discussion Discussion object (intended only
  *   for calls via the mod_forumng_discussion method)
  * @return array Array of mod_forumng_post objects
  */
 public function get_feed_posts($groupid, $userid, $discussion = null)
 {
     // Don't let user view any posts in a discussion feed they can't see
     // (I don't think they should be given a key in this case, but just
     // to be sure).
     if ($discussion && !$this->get_type()->can_view_discussion($discussion, $userid)) {
         return array();
     }
     // Number of items to output
     $items = $this->get_effective_feed_items();
     // Get most recent N posts from db
     $whereparams = array();
     if ($discussion) {
         $where = 'fd.id = ?';
         $whereparams[] = $discussion->get_id();
     } else {
         $where = 'fd.forumngid = ?';
         $whereparams[] = $this->get_id();
         if ($this->get_group_mode() && $groupid != self::ALL_GROUPS) {
             $where .= ' AND fd.groupid = ?';
             $whereparams[] = $groupid;
         }
     }
     // Don't include deleted or old-version posts
     $where .= ' AND fp.oldversion = 0 AND fp.deleted = 0 AND fd.deleted = 0';
     // Or ones out of time
     $now = time();
     $where .= " AND (fd.timestart < ?)" . " AND (fd.timeend = 0 OR fd.timeend > ?)";
     $whereparams[] = $now;
     $whereparams[] = $now;
     $postrecs = mod_forumng_post::query_posts($where, $whereparams, 'GREATEST(fp.created, fd.timestart) DESC', false, false, false, $userid, true, false, 0, $items);
     if (count($postrecs) == 0) {
         // No posts!
         return array();
     }
     $result = array();
     if ($discussion) {
         foreach ($postrecs as $rec) {
             $post = new mod_forumng_post($discussion, $rec, null);
             $result[$rec->id] = $post;
         }
     } else {
         // Based on these posts, get all mentioned discussions
         $discussionids = array();
         $discussionposts = array();
         foreach ($postrecs as $rec) {
             $discussionids[] = $rec->discussionid;
             $discussionposts[$rec->discussionid][] = $rec->id;
         }
         list($discussionpart, $discussionpartparams) = mod_forumng_utils::get_in_array_sql('fd.id', $discussionids);
         $rs = mod_forumng_discussion::query_discussions($discussionpart, $discussionpartparams, -1, 'id');
         // Build the discussion and post objects
         $posts = array();
         foreach ($rs as $rec) {
             $discussion = new mod_forumng_discussion($this, $rec, true, -1);
             if ($discussion->can_view($userid)) {
                 foreach ($discussionposts[$discussion->get_id()] as $postid) {
                     $post = new mod_forumng_post($discussion, $postrecs[$postid], null);
                     $posts[$postid] = $post;
                 }
             }
         }
         $rs->close();
         // Put them back in order of the post records, and return
         foreach ($postrecs as $rec) {
             // Records might be excluded if user can't view discussion
             if (array_key_exists($rec->id, $posts)) {
                 $result[$rec->id] = $posts[$rec->id];
             }
         }
     }
     return $result;
 }
Example #18
0
/**
 * Returns an array of recipients for OU alerts
 * @param char $type
 * @param int $id
 * @returns array
 */
function forumng_oualerts_additional_recipients($type, $id)
{
    global $CFG;
    require_once $CFG->dirroot . '/mod/forumng/mod_forumng.php';
    require_once $CFG->dirroot . '/mod/forumng/mod_forumng_discussion.php';
    $recipents = array();
    if ($type == 'post') {
        $discussion = mod_forumng_discussion::get_from_post_id($id, mod_forumng::CLONE_DIRECT);
        $forum = $discussion->get_forum();
        $recipients = $forum->get_reportingemails();
    }
    return $recipients;
}
 /**
  * Tests discussion locking
  */
 public function test_lock()
 {
     global $USER, $DB;
     $this->resetAfterTest();
     $this->setAdminUser();
     $course1 = $this->get_new_course();
     $orig = $this->get_new_forumng($course1->id, array('removeto' => -1, 'removeafter' => 1));
     $dis = $this->get_new_discussion($orig, array('userid' => $USER->id));
     $dis2 = $this->get_new_discussion($orig, array('userid' => $USER->id));
     $dis3 = $this->get_new_discussion($orig, array('userid' => $USER->id));
     // Alter post modified times to in past.
     foreach ($DB->get_records('forumng_posts') as $post) {
         $new = new stdClass();
         $new->id = $post->id;
         $new->modified = 1420070400;
         $DB->update_record('forumng_posts', $new);
     }
     // Delete dis2 so not auto-locked.
     $dis2->delete(false);
     $this->assertFalse($dis->is_locked());
     $this->assertFalse($dis->is_auto_locked());
     $lockpostid = $dis->lock('sub', 'mess', FORMAT_HTML);
     $this->assertTrue($dis->is_locked());
     $this->assertFalse($dis->is_auto_locked());
     $dis = mod_forumng_discussion::get_from_id($dis->get_id(), mod_forumng::CLONE_DIRECT);
     $this->assertTrue($dis->is_locked());
     $this->assertFalse($dis->is_auto_locked());
     $dis->unlock();
     $this->assertFalse($dis->is_locked());
     $this->assertFalse($dis->is_auto_locked());
     $lockpost = mod_forumng_post::get_from_id($lockpostid, mod_forumng::CLONE_DIRECT);
     $this->assertNotEmpty($lockpost->get_deleted());
     // Check auto-locking ($dis3 should be auto-locked only).
     $dis->lock('', '', FORMAT_HTML);
     mod_forumng_cron::archive_old_discussions();
     $dis = mod_forumng_discussion::get_from_id($dis->get_id(), mod_forumng::CLONE_DIRECT);
     $dis2 = mod_forumng_discussion::get_from_id($dis2->get_id(), mod_forumng::CLONE_DIRECT);
     $dis3 = mod_forumng_discussion::get_from_id($dis3->get_id(), mod_forumng::CLONE_DIRECT);
     $this->assertTrue($dis->is_locked());
     $this->assertFalse($dis->is_auto_locked());
     $this->assertFalse($dis2->is_locked());
     $this->assertFalse($dis2->is_auto_locked());
     $this->assertTrue($dis3->is_locked());
     $this->assertTrue($dis3->is_auto_locked());
 }
Example #20
0
 * Script used to paste discussion into new forum.
 * @package forumngfeature
 * @subpackage copy
 * @copyright 2011 The Open University
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
// Scripts for paste the discussion or cancel the paste.
require_once '../../../../config.php';
require_once $CFG->dirroot . '/mod/forumng/mod_forumng.php';
$cmid = required_param('cmid', PARAM_INT);
$groupid = optional_param('group', mod_forumng::NO_GROUPS, PARAM_INT);
$cloneid = optional_param('clone', 0, PARAM_INT);
$targetforum = mod_forumng::get_from_cmid($cmid, $cloneid);
if (optional_param('cancel', '', PARAM_RAW)) {
    unset($SESSION->forumng_copyfrom);
    redirect($targetforum->get_url(mod_forumng::PARAM_PLAIN));
}
// If the paste action has already been done or cancelled in a different window/tab.
if (!isset($SESSION->forumng_copyfrom)) {
    redirect($targetforum->get_url(mod_forumng::PARAM_PLAIN));
}
$olddiscussionid = $SESSION->forumng_copyfrom;
$oldcloneid = $SESSION->forumng_copyfromclone;
$olddiscussion = mod_forumng_discussion::get_from_id($olddiscussionid, $oldcloneid);
// Check permission to copy the discussion
require_capability('mod/forumng:copydiscussion', $olddiscussion->get_forum()->get_context());
// Security check to see if can start a new discussion in the target forum.
$targetforum->require_start_discussion($groupid);
$olddiscussion->copy($targetforum, $groupid);
unset($SESSION->forumng_copyfrom);
redirect($targetforum->get_url(mod_forumng::PARAM_PLAIN));
 /**
  * Merges the contents of this discussion into another discussion.
  * @param mod_forumng_discussion $targetdiscussion Target discussion
  * @param int $userid User ID (0 = current)
  * @param bool $log True to log this action
  */
 public function merge_into($targetdiscussion, $userid = 0, $log = true)
 {
     global $DB;
     $transaction = $DB->start_delegated_transaction();
     // Delete search data for the source discussion
     $this->ismakingsearchchange = true;
     $root = $this->get_root_post();
     $root->search_update();
     $root->search_update_children();
     $this->ismakingsearchchange = false;
     // Update parent post id of root post
     $record = new stdClass();
     $record->id = $this->discussionfields->postid;
     $record->parentpostid = $targetdiscussion->discussionfields->postid;
     $DB->update_record('forumng_posts', $record);
     // Move all posts into new discussion
     $DB->execute("UPDATE {forumng_posts} SET discussionid = ? WHERE discussionid = ?", array($targetdiscussion->get_id(), $this->get_id()));
     // Delete this discussion
     $DB->delete_records('forumng_discussions', array('id' => $this->discussionfields->id));
     // Attachments are OK because they are still in the same context, postid
     // etc (note this would NOT be the case if we allowed merging between
     // forums).
     if ($this->get_forum()->get_id() != $targetdiscussion->get_forum()->get_id()) {
         throw new coding_exception('Cannot merge into different forum');
     }
     // Merging the discussion into another might cause completion changes
     // (if there was a requirement for discussions and this is no longer
     // a discussion in its own right).
     $this->update_completion(false);
     // Update the search data for the target discussion after the merge
     $newroot = $targetdiscussion->get_root_post();
     $newroot->search_update();
     $newroot->search_update_children();
     if ($log) {
         $this->log('merge discussion', 'd' . $this->get_id() . ' into d' . $targetdiscussion->get_id());
     }
     $transaction->allow_commit();
     $this->uncache();
     $targetdiscussion->uncache();
 }
 public function test_rating()
 {
     global $USER, $DB;
     $this->resetAfterTest();
     $generator = $this->getDataGenerator()->get_plugin_generator('mod_forumng');
     $course = $this->get_new_course();
     $course2 = $this->get_new_course();
     $suser = $this->get_new_user('student', $course->id);
     $this->setAdminUser();
     $forum = $this->get_new_forumng($course->id, array('name' => 'TEST', 'intro' => 'abc123', 'enableratings' => mod_forumng::FORUMNG_STANDARD_RATING, 'ratingscale' => 10));
     $forum2 = $this->get_new_forumng($course->id, array('name' => 'TEST2', 'intro' => 'abc123', 'enableratings' => mod_forumng::FORUMNG_NO_RATING));
     $forum3 = $this->get_new_forumng($course2->id, array('name' => 'TEST', 'intro' => 'abc123', 'enableratings' => mod_forumng::FORUMNG_STANDARD_RATING, 'ratingscale' => 10));
     $did1 = $generator->create_discussion(array('course' => $course, 'forum' => $forum->get_id(), 'userid' => $suser->id));
     $did2 = $generator->create_discussion(array('course' => $course, 'forum' => $forum->get_id(), 'userid' => $suser->id));
     $did3 = $generator->create_discussion(array('course' => $course, 'forum' => $forum->get_id(), 'userid' => $suser->id));
     $did4 = $generator->create_discussion(array('course' => $course, 'forum' => $forum->get_id(), 'userid' => $suser->id));
     // Add rating to all 3 discussions.
     $rm = new rating_manager();
     $params = new stdClass();
     $params->context = $forum->get_context();
     $params->component = 'mod_forumng';
     $params->ratingarea = 'post';
     $params->scaleid = $forum->get_rating_scale();
     $params->userid = $USER->id;
     $params->itemid = $did1[1];
     $rating = new rating($params);
     $rating->update_rating(5);
     $params->itemid = $did2[1];
     $rating = new rating($params);
     $rating->update_rating(5);
     $params->itemid = $did3[1];
     $rating = new rating($params);
     $rating->update_rating(5);
     // Check rating object gets added where expected.
     $post = mod_forumng_post::get_from_id($did1[1], mod_forumng::CLONE_DIRECT, false, false);
     $ratings = $post->get_ratings();
     $this->assertNotNull($ratings);
     $this->assertEquals($did1[1], $ratings->itemid);
     $post = mod_forumng_post::get_from_id($did1[1], mod_forumng::CLONE_DIRECT, true, false);
     $ratings = $post->get_ratings();
     $this->assertNotNull($ratings);
     $this->assertEquals($did1[1], $ratings->itemid);
     $post = mod_forumng_post::get_from_id($did1[1], mod_forumng::CLONE_DIRECT, true, true);
     $ratings = $post->get_ratings();
     $this->assertNotNull($ratings);
     $this->assertEquals($did1[1], $ratings->itemid);
     $ratedposts = $forum->get_all_posts_by_user($suser->id, null, 'fp.id', null, null, true);
     $this->assertCount(3, $ratedposts);
     $allposts = $forum->get_all_posts_by_user($suser->id, null);
     $this->assertCount(4, $allposts);
     $this->assertNotNull($allposts[$did1[1]]->get_ratings());
     // Update grades (does nothing).
     $forum->update_grades();
     // Enable rating grading, forumng_update_instance() should update grades.
     forumng_update_instance((object) array('instance' => $forum->get_id(), 'grading' => mod_forumng::GRADING_SUM));
     $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id);
     // Note sum is set to 10 not 15 as max grade is 10.
     $this->assertEquals(10, abs($grades->items[0]->grades[$suser->id]->grade));
     // Enable rating grading, forumng_update_instance() should update grades.
     forumng_update_instance((object) array('instance' => $forum->get_id(), 'grading' => mod_forumng::GRADING_COUNT));
     $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id);
     $this->assertEquals(3, abs($grades->items[0]->grades[$suser->id]->grade));
     // Check get_rated_posts_by_user.
     $extrapost = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser->id, 'created' => 1388589745));
     $extraposts = $forum->get_rated_posts_by_user($forum, $suser->id, -1, 'fp.id', null, null);
     $this->assertCount(0, $extraposts);
     $extraposts = $forum->get_rated_posts_by_user($forum, $USER->id, -1, 'fp.id', null, null);
     $this->assertCount(3, $extraposts);
     $params->itemid = $extrapost->id;
     $rating = new rating($params);
     $rating->update_rating(10);
     $extraposts = $forum->get_rated_posts_by_user($forum, $USER->id, -1, 'fp.id', null, null);
     $this->assertCount(4, $extraposts);
     // Now filter out the 'old' extrapost.
     $extraposts = $forum->get_rated_posts_by_user($forum, $USER->id, -1, 'fp.id', null, null, 1388600000);
     $this->assertCount(3, $extraposts);
     // Check discussion delete.
     $discuss = mod_forumng_discussion::get_from_id($did1[0], mod_forumng::CLONE_DIRECT);
     $discuss->permanently_delete();
     $rating = $DB->get_record('rating', array('itemid' => $did1[1]));
     $this->assertFalse($rating);
     $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id);
     $this->assertEquals(2, abs($grades->items[0]->grades[$suser->id]->grade));
     // Check discussion move.
     $discuss = mod_forumng_discussion::get_from_id($did2[0], mod_forumng::CLONE_DIRECT);
     $discuss->move($forum2, 0);
     $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id);
     $this->assertEquals(1, abs($grades->items[0]->grades[$suser->id]->grade));
     forumng_update_instance((object) array('instance' => $forum2->get_id(), 'grading' => mod_forumng::GRADING_COUNT, 'enableratings' => mod_forumng::FORUMNG_STANDARD_RATING, 'ratingscale' => 10));
     $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum2->get_id(), $suser->id);
     $this->assertEquals(1, abs($grades->items[0]->grades[$suser->id]->grade));
     $rating = $DB->get_record('rating', array('itemid' => $did2[1]));
     $this->assertNotEmpty($rating);
     $this->assertEquals($forum2->get_context(true)->id, $rating->contextid);
     // Check discussion copy.
     $discuss = mod_forumng_discussion::get_from_id($did3[0], mod_forumng::CLONE_DIRECT);
     $discuss->copy($forum3, 0);
     $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id);
     $this->assertEquals(1, abs($grades->items[0]->grades[$suser->id]->grade));
     // Check rating didn't copy as forum in another course.
     $ratingtotal = $DB->get_records('rating');
     $this->assertCount(2, $ratingtotal);
     // Check rating does copy to foum in same course.
     $discuss->copy($forum2, 0);
     $ratingtotal = $DB->get_records('rating');
     $this->assertCount(3, $ratingtotal);
     // Check forum deleting.
     course_delete_module($forum->get_course_module_id());
     $ratingtotal = $DB->get_records('rating');
     $this->assertCount(2, $ratingtotal);
     $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id);
     $this->assertEmpty($grades->items);
 }
 /**
  * This function handles all aspects of page processing and then calls
  * methods in $selector at the appropriate moments.
  * @param post_selector $selector Object that extends this base class
  */
 public static function go($selector)
 {
     global $PAGE, $FULLME, $SESSION;
     $id = required_param('id', PARAM_INT);
     $cloneid = optional_param('clone', 0, PARAM_INT);
     $fromselect = optional_param('fromselect', 0, PARAM_INT);
     $all = optional_param('all', '', PARAM_RAW);
     $select = optional_param('select', '', PARAM_RAW);
     $isform = optional_param('postselectform', 0, PARAM_INT);
     $PAGE->set_url($FULLME);
     // Get basic objects.
     $forum = mod_forumng::get_from_cmid($id, $cloneid);
     $forumngid = $forum->get_id();
     $params = array_merge($_REQUEST, $forum->get_link_params_array());
     if (optional_param('cancel', '', PARAM_RAW)) {
         // CALL TYPE 6.
         redirect('../../view.php?' . $forum->get_link_params(mod_forumng::PARAM_PLAIN));
     }
     $cm = $forum->get_course_module();
     $course = $forum->get_course();
     $groupid = mod_forumng::get_activity_group($cm, true);
     // Page name and permissions.
     $pagename = $selector->get_page_name();
     $buttonname = $selector->get_button_name();
     $forum->require_view($groupid);
     $selector->require_capability($forum->get_context(), $forum);
     if (!($fromselect || $isform || $all)) {
         // Either an initial request (non-JS) to display the 'dialog' box,
         // or a request to show the list of posts with checkboxes for selection.
         // Both types share same navigation.
         $out = $forum->init_page(new moodle_url('/mod/forumng/view.php', $forum->get_link_params_array()));
         print $out->header();
         if (!$select) {
             // Show initial dialog.
             print $out->box_start();
             print html_writer::tag('h2', $buttonname);
             print html_writer::start_tag('form', array('action' => $_SERVER['PHP_SELF'], 'method' => 'get', 'id' => 'discsel'));
             print html_writer::start_tag('div');
             foreach ($params as $param => $paramval) {
                 print html_writer::empty_tag('input', array('name' => $param, 'type' => 'hidden', 'value' => $paramval));
             }
             print html_writer::tag('p', get_string('selectordiscall', 'forumng'));
             print html_writer::start_tag('div', array('class' => 'forumng-buttons'));
             print html_writer::empty_tag('input', array('name' => 'all', 'type' => 'submit', 'value' => get_string('selectoralldisc', 'forumng')));
             print html_writer::empty_tag('input', array('name' => 'select', 'type' => 'submit', 'value' => get_string('selectorselecteddisc', 'forumng')));
             print html_writer::empty_tag('input', array('name' => 'cancel', 'type' => 'submit', 'value' => get_string('cancel')));
             print html_writer::end_tag('div');
             print html_writer::end_tag('div');
             print html_writer::end_tag('form');
             print $out->box_end();
         } else {
             // Show list of posts to select.
             print html_writer::start_tag('div', array('class' => 'forumng-selectintro'));
             print html_writer::tag('p', get_string('selectdiscintro', 'forumng'));
             print html_writer::end_tag('div');
             print html_writer::start_tag('form', array('action' => $_SERVER['PHP_SELF'], 'method' => 'post', 'id' => 'discsel'));
             print html_writer::start_tag('div');
             print $forum->get_link_params(mod_forumng::PARAM_FORM);
             print html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'fromselect', 'value' => '1'));
             foreach ($params as $param => $paramval) {
                 print html_writer::empty_tag('input', array('name' => $param, 'type' => 'hidden', 'value' => $paramval));
             }
             // Now show discussions, allow for override at type level if following is no good.
             if (method_exists($forum->get_type(), 'print_select_page')) {
                 print $forum->get_type()->print_select_page($forum, $groupid);
             } else {
                 // Use default processing, get view and hack in selectors.
                 ob_start();
                 $forum->get_type()->print_view_page($forum, $groupid);
                 $discussionhtml = ob_get_contents();
                 ob_end_clean();
                 // Try and hack into the discussion list - must be xhtml...
                 $doc = new DOMDocument('1.0', 'utf-8');
                 @$doc->loadHTML($discussionhtml);
                 $docnew = new DOMDocument('1.0', 'utf-8');
                 $xpath = new DOMXPath($doc);
                 $lists = $xpath->query("//table[contains(concat(' ',normalize-space(@class),' '),' forumng-discussionlist ')]");
                 // Remove all links.
                 foreach ($lists as $list) {
                     $links = $xpath->query("//a|//form", $list);
                     foreach ($links as $node) {
                         if ($node->nodeName == 'a') {
                             // Disable links.
                             $node->removeAttribute('href');
                         } else {
                             // Remove any forms.
                             $node->parentNode->removeChild($node);
                         }
                     }
                     // Add in discussion select.
                     $rows = $xpath->query("//table[@class='generaltable forumng-discussionlist']\n                                //tr[not(@class) or @class!='forumng-divider']", $list);
                     for ($a = 0, $len = $rows->length; $a < $len; $a++) {
                         // Add in select options for each row, checking types.
                         $row = $rows->item($a);
                         if ($a == 0) {
                             $newcell = $doc->createElement('th', get_string('selectorselectdisc', 'mod_forumng'));
                             $newcell->setAttribute('class', 'header');
                             $newcell->setAttribute('scope', 'col');
                             $row->appendChild($newcell);
                         } else {
                             $id = $row->getAttribute('id');
                             if (strpos($id, 'discrow') === false) {
                                 continue;
                             }
                             // Get discussion id from row id as added by renderer.
                             $id = str_replace('discrow_', '', $id);
                             // Check if we include checkbox or not.
                             $classar = explode(' ', $row->getAttribute('class'));
                             $includematches = array_intersect($selector->only_discussion_types(), $classar);
                             $excludematches = array_intersect($selector->exclude_discussion_types(), $classar);
                             if ((count($selector->only_discussion_types()) == 0 || count($includematches) > 0) && count($excludematches) == 0) {
                                 // OK to include, add checkbox and label.
                                 $select = $doc->createElement('input');
                                 $select->setAttribute('type', 'checkbox');
                                 $select->setAttribute('name', "selectd{$id}");
                                 $select->setAttribute('id', "selectd{$id}");
                                 $label = $doc->createElement('label', get_string('selectorselectdisc', 'mod_forumng'));
                                 $label->setAttribute('for', "selectd{$id}");
                                 $label->setAttribute('class', 'accesshide');
                                 $newcell = $doc->createElement('td');
                                 $newcell->setAttribute('class', 'dselect');
                                 $newcell->appendChild($select);
                                 $newcell->appendChild($label);
                                 $row->appendChild($newcell);
                             } else {
                                 $newcell = $doc->createElement('td', '&nbsp;');
                                 $row->appendChild($newcell);
                             }
                         }
                     }
                     // Keep only discussion list by moving to new xml doc.
                     $newnode = $docnew->importNode($list, true);
                     $docnew->appendChild($newnode);
                 }
                 print $docnew->saveHTML();
             }
             print html_writer::start_tag('div', array('class' => 'forumng-selectoutro'));
             print html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('confirmselection', 'forumng')));
             print html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'cancel', 'value' => get_string('cancel')));
             print html_writer::end_tag('div');
             print html_writer::end_tag('div');
             print html_writer::end_tag('form');
         }
         // Display footer.
         print $out->footer();
     } else {
         // Call types 3, 4, and 5 use the form (and may include list of postids).
         $postids = array();
         $selectedids = array();
         foreach ($_POST as $field => $value) {
             $matches = array();
             if (!is_array($value) && (string) $value !== '0' && preg_match('~^selectd([0-9]+)$~', $field, $matches)) {
                 $selectedids[] = $matches[1];
             }
         }
         if (!empty($selectedids)) {
             // Check access.
             foreach ($selectedids as $id) {
                 $discuss = mod_forumng_discussion::get_from_id($id, $cloneid);
                 if ($forum->get_type()->can_view_discussion($discuss)) {
                     $postids[] = $id;
                 }
             }
         } else {
             if (!$all) {
                 // No slections made.
                 redirect('../../view.php?' . $forum->get_link_params(mod_forumng::PARAM_PLAIN));
             }
             // Work out discussion list for this page (e.g. selected All).
             $sortorder = optional_param('sort', 'd', PARAM_ALPHA);
             if (isset($SESSION->forumng_discussionlist[$forumngid]->sort)) {
                 $sortorder = $SESSION->forumng_discussionlist[$forumngid]->sort;
             }
             $page = optional_param('page', 1, PARAM_INT);
             if (isset($SESSION->forumng_discussionlist[$forumngid]->page)) {
                 $page = $SESSION->forumng_discussionlist[$forumngid]->page;
             }
             $sortchar = substr($sortorder, 0, 1);
             if (strlen($sortorder) == 2) {
                 $sortreverse = substr($sortorder, 1, 1) == 'r' ? true : false;
             } else {
                 $sortreverse = false;
             }
             $sort = mod_forumng::get_sort_code($sortchar);
             $list = $forum->get_discussion_list($groupid, $forum->can_view_hidden(), $page, $sort, $sortreverse);
             $discussionsarr = array_merge($list->get_sticky_discussions(), $list->get_normal_discussions());
             // Double check ID is valid and user can view.
             for ($a = 0; $a < count($discussionsarr); $a++) {
                 if ($forum->get_type()->can_view_discussion($discussionsarr[$a])) {
                     $postids[] = $discussionsarr[$a]->get_id();
                 }
             }
         }
         $out = $forum->init_page(new moodle_url('/mod/forumng/view.php', $forum->get_link_params_array()), $pagename);
         // Get form to use.
         $mform = $selector->get_form($forum, $all, $postids);
         if (!$mform) {
             // Some options do not need a confirmation form; in that case,
             // just apply the action immediately.
             $selector->apply($forum, $all, $postids, null);
             exit;
         }
         // Check cancel.
         if ($mform->is_cancelled()) {
             redirect('../../view.php?' . $forum->get_link_params(mod_forumng::PARAM_PLAIN));
         }
         if ($fromform = $mform->get_data()) {
             // User submitted form to confirm process, which should now be
             // applied by selector.
             $selector->apply($forum, $all, $postids, $fromform);
             exit;
         } else {
             print $out->header();
             // User requested form either via JavaScript or the other way, and
             // either with all messages or the whole discussion.
             // Print form.
             print $mform->display();
             // Print optional content that goes after form.
             print $selector->get_content_after_form($forum, $all, $postids, $fromform);
             // Display footer.
             print $out->footer();
         }
     }
 }
Example #24
0
// Set up page
$pagename = get_string('merge', 'forumngfeature_merge');
$url = new moodle_url('/mod/forumng/feature/merge/merge.php', $pageparams);
$out = $discussion->init_page($url, $pagename);
// Require that you can see this discussion (etc) and merge them
$discussion->require_view();
if (!$discussion->can_split($whynot)) {
    print_error($whynot, 'forumng');
}
if ($stage == 2) {
    if (!confirm_sesskey()) {
        print_error('invalidsesskey');
    }
    if (!isset($_POST['cancel'])) {
        // Get source discussion and check permissions
        $sourcediscussion = mod_forumng_discussion::get_from_id($SESSION->forumng_mergefrom->discussionid, $SESSION->forumng_mergefrom->cloneid);
        $sourcediscussion->require_view();
        if (!$sourcediscussion->can_split($whynot)) {
            print_error($whynot, 'forumng');
        }
        if ($sourcediscussion->get_forum()->get_id() != $discussion->get_forum()->get_id()) {
            print_error('error_wrongforum', 'forumngfeature_merge');
        }
        // Do actual merge
        $sourcediscussion->merge_into($discussion);
    }
    unset($SESSION->forumng_mergefrom);
    redirect('../../discuss.php?' . $discussion->get_link_params(mod_forumng::PARAM_PLAIN));
}
// Create form
require_once 'merge_form.php';
 public function test_tag_discussion()
 {
     global $DB, $USER, $SITE, $CFG;
     require_once $CFG->dirroot . '/tag/lib.php';
     $this->resetAfterTest(true);
     $this->setAdminUser();
     // Create the generator object and do standard checks.
     $generator = self::getDataGenerator()->get_plugin_generator('mod_forumng');
     // Create course.
     $record = new stdClass();
     $record->shortname = 'testcourse';
     $course = self::getDataGenerator()->create_course($record);
     // Create groups.
     $group1 = $this->get_new_group($course->id);
     $group2 = $this->get_new_group($course->id);
     // Create forum.
     $forumrecord = $generator->create_instance(array('course' => $course->id, 'tags' => true, 'groupmode' => VISIBLEGROUPS));
     $forum = mod_forumng::get_from_id($forumrecord->id, mod_forumng::CLONE_DIRECT, true);
     // Set use tag.
     $CFG->usetags = true;
     // Set forum to tag enabling.
     $this->assertTrue($CFG->usetags);
     $this->assertEquals(true, $forum->get_tags_enabled());
     // Start a discussion in forum (group1).
     $record = new stdClass();
     $record->course = $course->id;
     $record->forum = $forum->get_id();
     $record->groupid = $group1->id;
     $record->userid = $USER->id;
     $record->timestart = time();
     $ids1 = $generator->create_discussion($record);
     // Start a second discussion in forum (group1).
     $record = new stdClass();
     $record->course = $course->id;
     $record->forum = $forum->get_id();
     $record->groupid = $group1->id;
     $record->userid = $USER->id;
     $record->timestart = time();
     $ids2 = $generator->create_discussion($record);
     // Start a third discussion in forum (group2).
     $record = new stdClass();
     $record->course = $course->id;
     $record->forum = $forum->get_id();
     $record->groupid = $group2->id;
     $record->userid = $USER->id;
     $record->timestart = time();
     $ids3 = $generator->create_discussion($record);
     // Set up tags in each discussion.
     $discussionid = $ids1[0];
     $discussion = mod_forumng_discussion::get_from_id($discussionid, 0);
     $this->assertEmpty($discussion->get_tags());
     // Edit discussion settings.
     $discussion->edit_settings($discussion::NOCHANGE, $discussion::NOCHANGE, $discussion::NOCHANGE, $discussion::NOCHANGE, $discussion::NOCHANGE, array('tag1', 'tag2', 'tag3'));
     $tags1 = $discussion->get_tags();
     $this->assertCount(3, $tags1);
     $discussion1 = $discussion;
     $discussionid = $ids2[0];
     $discussion = mod_forumng_discussion::get_from_id($discussionid, 0);
     $this->assertEmpty($discussion->get_tags());
     // Edit discussion settings.
     $discussion->edit_settings(mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, array('tag1', 'tag2'));
     $tags2 = $discussion->get_tags();
     $this->assertCount(2, $tags2);
     $discussion2 = $discussion;
     $discussionid = $ids3[0];
     $discussion = mod_forumng_discussion::get_from_id($discussionid, 0);
     $this->assertEmpty($discussion->get_tags());
     // Edit discussion settings.
     $discussion->edit_settings(mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, array('tag1'));
     $tags3 = $discussion->get_tags();
     $this->assertCount(1, $tags3);
     $discussion3 = $discussion;
     // Create a discussion with no tags for later use.
     $record = new stdClass();
     $record->course = $course->id;
     $record->forum = $forum->get_id();
     $record->groupid = $group2->id;
     $record->userid = $USER->id;
     $record->timestart = time();
     $ids4 = $generator->create_discussion($record);
     // Get id of 'tag1'.
     $tagid = array_search('tag1', $tags3);
     // Get all tags and check on numbers for each tag.
     $tagsused = $forum->get_tags_used();
     $this->assertCount(3, $tagsused);
     $tagsused1 = $forum->get_tags_used($group1->id);
     $this->assertCount(3, $tagsused1);
     $tagsused2 = $forum->get_tags_used($group2->id);
     $this->assertCount(1, $tagsused2);
     $this->assertArrayHasKey($tagid, $tagsused2);
     $this->assertObjectHasAttribute('displayname', $tagsused2[$tagid]);
     $this->assertObjectHasAttribute('count', $tagsused2[$tagid]);
     $this->assertEquals('tag1', $tagsused2[$tagid]->displayname);
     $this->assertEquals(1, $tagsused2[$tagid]->count);
     // Get all discussions featuring 'tag1'.
     $list = $forum->get_discussion_list(mod_forumng::ALL_GROUPS, $forum->can_view_hidden(), 1, mod_forumng::SORT_DATE, false, 0, true, $tagid);
     $taggedlist = $list->get_normal_discussions();
     $this->assertCount(3, $taggedlist);
     // Get all discussions featuring 'tag1'.for group1.
     $list1 = $forum->get_discussion_list($group1->id, $forum->can_view_hidden(), 1, mod_forumng::SORT_DATE, false, 0, true, $tagid);
     $taggedlist1 = $list1->get_normal_discussions();
     $this->assertCount(2, $taggedlist1);
     // Get all discussions featuring 'tag1'.for group2.
     $list2 = $forum->get_discussion_list($group2->id, $forum->can_view_hidden(), 1, mod_forumng::SORT_DATE, false, 0, true, $tagid);
     $taggedlist2 = $list2->get_normal_discussions();
     $this->assertCount(1, $taggedlist2);
     // Get all discussions featuring 'tag3'.for group2 - which should be none.
     $tagid = array_search('tag3', $tags1);
     $list = $forum->get_discussion_list($group2->id, $forum->can_view_hidden(), 1, mod_forumng::SORT_DATE, false, 0, true, $tagid);
     $taggedlist = $list->get_normal_discussions();
     $this->assertCount(0, $taggedlist);
     // Set tags specifically for group 1.
     $forumng = new stdClass();
     $forumng->settags = array('g1 vamp', 'g1 zomb', 'g1 mumm', 'g1 damm');
     $forumng->id = $forum->get_id();
     $forumng->instance = $forum->get_id();
     $forumng->tags = 1;
     forumng_update_instance($forumng);
     $context = $forum->get_context();
     mod_forumng::set_group_tags($forum->get_id(), $group1->id, $forumng->settags);
     $tagsused1 = $forum::get_set_tags($forumng->id, $group1->id);
     $this->assertCount(4, $tagsused1);
     // Set tags for group 2 (should return main set tags also).
     $g2tags = array('g2 ghost', 'g2 ghoul', 'g2 googl', 'g2 welf', 'g2 gobb');
     mod_forumng::set_group_tags($forum->get_id(), $group2->id, $g2tags);
     $tagsused2 = $forum::get_set_tags($forumng->id, $group2->id);
     $this->assertCount(9, $tagsused2);
     $tagsused3 = $forum::get_set_tags($forumng->id);
     $this->assertCount(4, $tagsused3);
     // Test that group only tags can be returned.
     $tagsused1 = $forum::get_set_tags($forumng->id, $group1->id, true);
     $this->assertCount(4, $tagsused1);
     $tagsused2 = $forum::get_set_tags($forumng->id, $group2->id, true);
     $this->assertCount(5, $tagsused2);
     // Need to test permanently delete.
     $discussionid = $ids4[0];
     $discussion = mod_forumng_discussion::get_from_id($discussionid, 0);
     $this->assertEmpty($discussion->get_tags());
     // Edit discussion settings.
     $discussion->edit_settings(mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, array('t1', 't2', 't3'));
     $tags4 = $discussion->get_tags();
     $this->assertCount(3, $tags4);
     $discussion4 = $discussion;
     // Delete discussion.
     $discussion4->permanently_delete(false);
     $this->assertFalse($DB->get_record('forumng_discussions', array('id' => $discussion->get_id())));
     $this->assertEmpty($DB->get_records('tag_instance', array('itemid' => $discussion->get_id(), 'itemtype' => 'forumng discussions')));
     // Test group tag setting.
     $user2 = $this->get_new_user();
     $this->setUser($user2);
     mod_forumng::set_group_tags($forumng->id, $group1->id, array('t1', 'tnew'));
     $tagsused = $forum::get_set_tags($forumng->id, $group1->id, true);
     $this->assertCount(2, $tagsused);
     mod_forumng::set_group_tags($forumng->id, $group1->id, array('t1'));
     $tagsused = $forum::get_set_tags($forumng->id, $group1->id, true);
     $this->assertCount(1, $tagsused);
     // Create a new forum and add same group tags.
     $forumrecord2 = $generator->create_instance(array('course' => $course->id, 'tags' => true, 'groupmode' => VISIBLEGROUPS));
     $forum2 = mod_forumng::get_from_id($forumrecord2->id, mod_forumng::CLONE_DIRECT, true);
     mod_forumng::set_group_tags($forumrecord2->id, $group1->id, array('t1'));
     $tagsused = $forum::get_set_tags($forumrecord2->id, $group1->id, true);
     $this->assertCount(1, $tagsused);
     // Create a new forum and add same group tags (should use another user).
     $forumrecord2 = $generator->create_instance(array('course' => $course->id, 'tags' => true, 'groupmode' => VISIBLEGROUPS));
     $forum2 = mod_forumng::get_from_id($forumrecord2->id, mod_forumng::CLONE_DIRECT, true);
     mod_forumng::set_group_tags($forumrecord2->id, $group1->id, array('t1'));
     $tagsused = $forum::get_set_tags($forumrecord2->id, $group1->id, true);
     $this->assertCount(1, $tagsused);
     // Create a new forum and add same group tags (should fail as ou of users).
     $forumrecord2 = $generator->create_instance(array('course' => $course->id, 'tags' => true, 'groupmode' => VISIBLEGROUPS));
     $forum2 = mod_forumng::get_from_id($forumrecord2->id, mod_forumng::CLONE_DIRECT, true);
     $this->setExpectedException('moodle_exception');
     mod_forumng::set_group_tags($forumrecord2->id, $group1->id, array('t1'));
     // Do not add any tests after this point as exception called above.
 }
Example #26
0
    array_push($tags, '');
}
$customdata = array('options' => array(), 'cmid' => $cm->id, 'group' => $groupid, 'tags' => $tags, 'params' => $urlparams);
// Set up page.
$pagename = get_string('editdiscussiontags', 'forumngfeature_edittags');
$url = new moodle_url('/mod/forumng/feature/edittags/edittags.php', $pageparams);
$out = $discussion->init_page($url, $pagename);
$mform = new mod_forumng_edittags_form($url, $customdata);
if ($mform->is_cancelled()) {
    // Form is cancelled, redirect back to the discussion.
    redirect('../../discuss.php?' . $discussion->get_link_params(mod_forumng::PARAM_PLAIN));
} else {
    if ($fromform = $mform->get_data()) {
        if (!isset($fromform->tags)) {
            $fromform->tags = null;
        }
        $discussion = mod_forumng_discussion::get_from_id($d, $cloneid);
        $discussion->edit_settings(mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, mod_forumng_discussion::NOCHANGE, $fromform->tags);
        redirect('../../discuss.php?' . $discussion->get_link_params(mod_forumng::PARAM_PLAIN));
    } else {
        $navigation = array();
        print $out->header();
        // Require JavaScript (form.js).
        $forum->print_form_js();
        $mform->display();
        $PAGE->requires->yui_module('moodle-mod_forumng-tagselector', 'M.mod_forumng.tagselector.init', array('id_tags_othertags', $forum->get_tags_used($groupid, true)));
        $PAGE->requires->strings_for_js(array('numberofdiscussions'), 'forumng');
        // Display footer.
        print $out->footer();
    }
}
 /**
  * This function handles all aspects of page processing and then calls
  * methods in $selector at the appropriate moments.
  * @param post_selector $selector Object that extends this base class
  * @param string $rawurl Raw 'name' part of url e.g. '/mod/forumng/feature/frog/frog.php'
  */
 public static function go($selector)
 {
     global $PAGE, $FULLME;
     $d = required_param('d', PARAM_INT);
     $cloneid = optional_param('clone', 0, PARAM_INT);
     $PAGE->set_url($FULLME);
     $fromselect = optional_param('fromselect', 0, PARAM_INT);
     $all = optional_param('all', '', PARAM_RAW);
     $select = optional_param('select', '', PARAM_RAW);
     // Get basic objects
     $discussion = mod_forumng_discussion::get_from_id($d, $cloneid);
     if (optional_param('cancel', '', PARAM_RAW)) {
         // CALL TYPE 6
         redirect('../../discuss.php?' . $discussion->get_link_params(mod_forumng::PARAM_PLAIN));
     }
     $forum = $discussion->get_forum();
     $cm = $forum->get_course_module();
     $course = $forum->get_course();
     $isform = optional_param('postselectform', 0, PARAM_INT);
     // Page name and permissions
     $pagename = $selector->get_page_name();
     $buttonname = $selector->get_button_name();
     $discussion->require_view();
     $selector->require_capability($forum->get_context(), $discussion);
     if (!($fromselect || $isform || $all)) {
         // Either an initial request (non-JS) to display the 'dialog' box,
         // or a request to show the list of posts with checkboxes for
         // selection
         // Both types share same navigation
         $out = $discussion->init_page($discussion->get_moodle_url(), $pagename);
         print $out->header();
         if (!$select) {
             // Show initial dialog
             print $out->box_start();
             print html_writer::tag('h2', $buttonname);
             print html_writer::start_tag('form', array('action' => $_SERVER['PHP_SELF'], 'method' => 'get'));
             print html_writer::start_tag('div');
             print $discussion->get_link_params(mod_forumng::PARAM_FORM);
             print html_writer::tag('p', get_string('selectorall', 'forumng'));
             print html_writer::start_tag('div', array('class' => 'forumng-buttons'));
             print html_writer::empty_tag('input', array('name' => 'all', 'type' => 'submit', 'value' => get_string('discussion', 'forumng')));
             print html_writer::empty_tag('input', array('name' => 'select', 'type' => 'submit', 'value' => get_string('selectedposts', 'forumng')));
             print html_writer::end_tag('div');
             print html_writer::end_tag('div');
             print html_writer::end_tag('form');
             print $out->box_end();
         } else {
             // Show list of posts to select
             print html_writer::start_tag('div', array('class' => 'forumng-selectintro'));
             print html_writer::tag('p', get_string('selectintro', 'forumng'));
             print html_writer::end_tag('div');
             print html_writer::start_tag('form', array('action' => $_SERVER['PHP_SELF'], 'method' => 'post'));
             print html_writer::start_tag('div');
             print $discussion->get_link_params(mod_forumng::PARAM_FORM);
             print html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'fromselect', 'value' => '1'));
             print $out->render_discussion($discussion, array(mod_forumng_post::OPTION_NO_COMMANDS => true, mod_forumng_post::OPTION_CHILDREN_EXPANDED => true, mod_forumng_post::OPTION_SELECTABLE => true));
             print html_writer::start_tag('div', array('class' => 'forumng-selectoutro'));
             print html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('confirmselection', 'forumng')));
             print html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'cancel', 'value' => get_string('cancel')));
             print html_writer::end_tag('div');
             print html_writer::end_tag('div');
             print html_writer::end_tag('form');
         }
         // Display footer
         print $out->footer();
     } else {
         // Call types 3, 4, and 5 use the form (and may include list of postids)
         if ($all) {
             $postids = false;
         } else {
             $postids = array();
             foreach ($_POST as $field => $value) {
                 $matches = array();
                 if (!is_array($value) && (string) $value !== '0' && preg_match('~^selectp([0-9]+)$~', $field, $matches)) {
                     $postids[] = $matches[1];
                 }
             }
         }
         $out = $discussion->init_page($discussion->get_moodle_url(), $pagename);
         // Get form to use
         $mform = $selector->get_form($discussion, $all, $postids);
         if (!$mform) {
             // Some options do not need a confirmation form; in that case,
             // just apply the action immediately.
             $selector->apply($discussion, $all, $postids, null);
             exit;
         }
         // Check cancel
         if ($mform->is_cancelled()) {
             redirect('../../discuss.php?' . $discussion->get_link_params(mod_forumng::PARAM_PLAIN));
         }
         if ($fromform = $mform->get_data()) {
             // User submitted form to confirm process, which should now be
             // applied by selector.
             $selector->apply($discussion, $all, $postids, $fromform);
             exit;
         } else {
             print $out->header();
             // User requested form either via JavaScript or the other way, and
             // either with all messages or the whole discussion.
             // Print form
             print $mform->display();
             // Print optional content that goes after form
             print $selector->get_content_after_form($discussion, $all, $postids, $fromform);
             // Display footer
             print $out->footer();
         }
     }
 }
Example #28
0
    // View posts that have been flagged.
    $flagged = $DB->get_recordset_sql("\n            SELECT COUNT(ff.id) AS count, fp.id\n              FROM {forumng_flags} ff\n        INNER JOIN {forumng_posts} fp ON fp.id = ff.postid\n        INNER JOIN {forumng_discussions} fd ON fd.id = fp.discussionid\n             WHERE fd.forumngid = ?\n               AND fd.deleted = 0\n               AND fp.deleted = 0\n               AND fp.oldversion = 0\n            {$groupwhere}\n          GROUP BY fp.id\n          ORDER BY count desc, fp.id desc", array_merge(array($forum->get_id()), $groupparams), 0, 5);
    $flaggedlist = array();
    foreach ($flagged as $apost) {
        $post = mod_forumng_post::get_from_id($apost->id, $cloneid, true, true);
        list($content, $user) = $renderer->render_usage_post_info($forum, $post->get_discussion(), $post);
        $flaggedlist[] = $renderer->render_usage_list_item($forum, $apost->count, $user, $content);
    }
    $usageoutput .= html_writer::start_div('forumng_usage_flagged');
    $usageoutput .= $renderer->render_usage_list($flaggedlist, 'mostflagged');
    $usageoutput .= html_writer::end_div();
    // View discussions that have been flagged.
    $flagged = $DB->get_recordset_sql("\n            SELECT COUNT(ff.id) AS count, fd.id\n            FROM {forumng_flags} ff\n            INNER JOIN {forumng_discussions} fd ON fd.id = ff.discussionid\n            WHERE fd.forumngid = ?\n            AND fd.deleted = 0\n            {$groupwhere}\n            GROUP BY fd.id\n            ORDER BY count desc, fd.id desc", array_merge(array($forum->get_id()), $groupparams), 0, 5);
    $flaggedlist = array();
    foreach ($flagged as $adiscuss) {
        $discuss = mod_forumng_discussion::get_from_id($adiscuss->id, $cloneid, 0, true);
        list($content, $user) = $renderer->render_usage_discussion_info($forum, $discuss);
        $flaggedlist[] = $renderer->render_usage_list_item($forum, $adiscuss->count, $user, $content);
    }
    $usageoutput .= html_writer::start_div('forumng_usage_flagged');
    $usageoutput .= $renderer->render_usage_list($flaggedlist, 'mostflaggeddiscussions');
    $usageoutput .= html_writer::end_div();
}
// Show ratings.
if (has_capability('mod/forumng:viewanyrating', $forum->get_context())) {
    $gradingstr = '';
    $ratingtype = $forum->get_enableratings();
    if ($ratingtype && $forum->get_rating_scale() != 0) {
        // Get grading type from forum.
        $gradingtype = $forum->get_grading();
        $counttype = '';
 public function prepare_package()
 {
     global $CFG;
     /*
      * decoding the array from letters to numbers, see export.php
      */
     if ($this->posts !== '') {
         $selected = $this->decode_string_to_array();
     } else {
         $selected = false;
     }
     // Set up the start of the XHTML file.
     $allhtml = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' . '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . html_writer::start_tag('html', array('xmlns' => 'http://www.w3.org/1999/xhtml'));
     $allhtml .= html_writer::tag('head', html_writer::empty_tag('meta', array('http-equiv' => 'Content-Type', 'content' => 'text/html; charset=utf-8')) . html_writer::tag('title', get_string('export', 'forumngfeature_export')));
     $allhtml .= html_writer::start_tag('body') . "\n";
     $poststext = '';
     $postshtml = '';
     // we need a discussion object
     $discussion = mod_forumng_discussion::get_from_id($this->discussionid, $this->cloneid);
     $discussion->build_selected_posts_email($selected, $poststext, $postshtml, array(mod_forumng_post::OPTION_EXPORT => true));
     $allhtml .= $postshtml;
     // Finish the file.
     $allhtml .= html_writer::end_tag('body') . html_writer::end_tag('html');
     // Remove embedded img and attachment paths.
     $plugin = $this->get('exporter')->get('instance')->get('plugin');
     $portfolioformat = $this->get('exporter')->get('format');
     foreach ($this->files as $file) {
         $filename = $file->get_filename();
         $urlencfilename = rawurlencode($filename);
         $portfoliofiledir = $portfolioformat->get_file_directory();
         if ($plugin == 'download') {
             // non-encoded embedded image filenames
             $pattern = '/src=.*?' . preg_quote($filename) . '\\"/';
             $replace = 'src="' . $portfoliofiledir . $filename . '"';
             $allhtml = preg_replace($pattern, $replace, $allhtml);
             // urlencoded embedded image filenames
             $pattern = '/src=.*?' . preg_quote($urlencfilename) . '\\"/';
             $replace = 'src="' . $portfoliofiledir . $urlencfilename . '"';
             $allhtml = preg_replace($pattern, $replace, $allhtml);
             // non-encoded attached filenames
             $pattern = '/href=.*?' . preg_quote($filename) . '\\"/';
             $replace = 'href="' . $portfoliofiledir . $filename . '"';
             $allhtml = preg_replace($pattern, $replace, $allhtml);
             // urlencoded attached filenames
             $pattern = '/href=.*?' . preg_quote($urlencfilename) . '\\"/';
             $replace = 'href="' . $portfoliofiledir . $urlencfilename . '"';
             $allhtml = preg_replace($pattern, $replace, $allhtml);
         }
         if ($plugin == 'rtf') {
             $pattern = '/src=.*?' . $filename . '\\"/';
             $replace = 'src="' . $portfoliofiledir . $filename . '"';
             $allhtml = preg_replace($pattern, $replace, $allhtml);
             $pattern = '/src=\\"http:\\/\\/.*?' . preg_quote($filename) . '.*?\\"/';
             $replace = 'src="' . $portfoliofiledir . $filename . '"';
             $allhtml = preg_replace($pattern, $replace, $allhtml);
             $pattern = '/src=\\"http:\\/\\/.*?' . preg_quote($urlencfilename) . '.*?\\"/';
             $replace = 'src="' . $portfoliofiledir . $filename . '"';
             $allhtml = preg_replace($pattern, $replace, $allhtml);
         }
     }
     $content = $allhtml;
     $name = $this->make_filename_safe('forum_discussion') . '.html';
     $manifest = $this->exporter->get('format') instanceof PORTFOLIO_FORMAT_RICH;
     $this->copy_files($this->multifiles);
     $this->get('exporter')->write_new_file($content, $name, $manifest);
 }