view.php 14 KB
Newer Older
Clare Lenihan's avatar
Clare Lenihan committed
1 2 3 4 5
<?php
/**
 *
 * @package    mahara
 * @subpackage interaction-forum
6
 * @author     Catalyst IT Ltd
7 8
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
 * @copyright  For copyright information on Mahara, please see the README file distributed with this software.
Clare Lenihan's avatar
Clare Lenihan committed
9 10
 *
 */
11

Clare Lenihan's avatar
Clare Lenihan committed
12
define('INTERNAL', 1);
13
define('PUBLIC', 1);
14
define('MENUITEM', 'groups/forums');
15 16 17 18
define('SECTION_PLUGINTYPE', 'interaction');
define('SECTION_PLUGINNAME', 'forum');
define('SECTION_PAGE', 'view');

Clare Lenihan's avatar
Clare Lenihan committed
19 20
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
require_once('group.php');
Clare Lenihan's avatar
Clare Lenihan committed
21
safe_require('interaction', 'forum');
22 23
require_once(get_config('docroot') . 'interaction/lib.php');
require_once('pieforms/pieform.php');
Clare Lenihan's avatar
Clare Lenihan committed
24 25 26 27 28 29

$forumid = param_integer('id');
$offset = param_integer('offset', 0);
$userid = $USER->get('id');
$topicsperpage = 25;

Clare Lenihan's avatar
Clare Lenihan committed
30 31 32
// if offset isn't a multiple of $topicsperpage, make it the closest smaller multiple
$offset = (int)($offset / $topicsperpage) * $topicsperpage;

33
$forum = get_record_sql(
34
    'SELECT f.title, f.description, f.id, COUNT(t.id) AS topiccount, s.forum AS subscribed, g.id AS groupid, g.name AS groupname, ic.value AS newtopicusers
Clare Lenihan's avatar
Clare Lenihan committed
35
    FROM {interaction_instance} f
36
    INNER JOIN {group} g ON (g.id = f."group" AND g.deleted = ?)
37
    LEFT JOIN {interaction_forum_topic} t ON (t.forum = f.id AND t.deleted != 1)
Clare Lenihan's avatar
Clare Lenihan committed
38
    LEFT JOIN {interaction_forum_subscription_forum} s ON (s.forum = f.id AND s."user" = ?)
39
    LEFT JOIN {interaction_forum_instance_config} ic ON (f.id = ic.forum AND ic.field = \'createtopicusers\')
40
    WHERE f.id = ?
41
    AND f.deleted != 1
42
    GROUP BY 1, 2, 3, 5, 6, 7, 8',
43
    array(0, $userid, $forumid)
Clare Lenihan's avatar
Clare Lenihan committed
44 45
);

46
if (!$forum) {
47
    throw new InteractionInstanceNotFoundException(get_string('cantfindforum', 'interaction.forum', $forumid));
Clare Lenihan's avatar
Clare Lenihan committed
48 49
}

50 51
define('GROUP', $forum->groupid);

52 53 54
$membership = user_can_access_forum((int)$forumid);
$admin = (bool)($membership & INTERACTION_FORUM_ADMIN);
$moderator = (bool)($membership & INTERACTION_FORUM_MOD);
55 56
$group = get_record('group', 'id', $forum->groupid);
$publicgroup = $group->public;
Evan Goldenberg's avatar
Evan Goldenberg committed
57
if (!$membership && !$publicgroup) {
58
    throw new GroupAccessDeniedException(get_string('cantviewforums', 'interaction.forum'));
Clare Lenihan's avatar
Clare Lenihan committed
59 60
}

61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
// Get other forums to which the current user can move topics
$otherforums = array();
if ($admin) {
    $otherforums = get_records_sql_array(
        'SELECT id, title
        FROM {interaction_instance} f
        WHERE f.id <> ?
            AND f.group = ?
            AND f.deleted = 0
            AND f.plugin = ?
        ORDER BY f.title',
        array($forumid, $forum->groupid, 'forum')
    );
}
else if ($moderator) {
    $otherforums = get_records_sql_array(
        'SELECT id, title
        FROM {interaction_instance} f
            INNER JOIN {interaction_forum_moderator} fm ON (fm.forum = f.id)
        WHERE f.id <> ?
            AND f.group = ?
            AND f.deleted = 0
            AND f.plugin = ?
            AND fm.user = ?
        ORDER BY f.title',
        array($forumid, $forum->groupid, 'forum', $userid)
    );
}
89
$ineditwindow = group_within_edit_window($group);
90

91 92 93 94
if (!$ineditwindow) {
    $moderator = false;
}

95
define('TITLE', $forum->groupname . ' - ' . $forum->title);
Clare Lenihan's avatar
Clare Lenihan committed
96

Evan Goldenberg's avatar
Evan Goldenberg committed
97 98
$feedlink = get_config('wwwroot') . 'interaction/forum/atom.php?type=f&id=' . $forum->id;

99 100 101 102 103 104
$moderators = get_column_sql(
    'SELECT gm.user FROM {interaction_forum_moderator} gm
    INNER JOIN {usr} u ON (u.id = gm.user AND u.deleted = 0)
    WHERE gm.forum = ?',
    array($forumid)
);
105

106
// updates the selected topics as subscribed/closed/sticky
107
if ($membership && isset($_POST['checked'])) {
108
    $checked = array_map('intval', array_keys($_POST['checked']));
Clare Lenihan's avatar
Clare Lenihan committed
109
    // get type based on which button was pressed
110 111
    if (isset($_POST['updatetopics'])) {
        $type = $_POST['type'];
Clare Lenihan's avatar
Clare Lenihan committed
112
    }
113 114
    // check that user is only messing with topics from this forum
    $alltopics = get_column('interaction_forum_topic', 'id', 'forum', $forumid, 'deleted', 0);
115
    if ($checked == array_intersect($checked, $alltopics)) { // $checked is a subset of the topics in this forum
116
        form_validate(param_variable('sesskey', null));
Clare Lenihan's avatar
Clare Lenihan committed
117
        if ($moderator && $type == 'sticky') {
118
            set_field_select('interaction_forum_topic', 'sticky', 1, 'id IN (' . implode(',', $checked) . ')', array());
119 120
            $SESSION->add_ok_msg(get_string('topicstickysuccess', 'interaction.forum'));
        }
Clare Lenihan's avatar
Clare Lenihan committed
121
        else if ($moderator && $type == 'unsticky') {
122
            set_field_select('interaction_forum_topic', 'sticky', 0, 'id IN (' . implode(',', $checked) . ')', array());
Clare Lenihan's avatar
Clare Lenihan committed
123 124 125
            $SESSION->add_ok_msg(get_string('topicunstickysuccess', 'interaction.forum'));
        }
        else if ($moderator && $type == 'closed') {
126
            set_field_select('interaction_forum_topic', 'closed', 1, 'id IN (' . implode(',', $checked) . ')', array());
127 128
            $SESSION->add_ok_msg(get_string('topicclosedsuccess', 'interaction.forum'));
        }
Clare Lenihan's avatar
Clare Lenihan committed
129
        else if ($moderator && $type == 'open') {
130
            set_field_select('interaction_forum_topic', 'closed', 0, 'id IN (' . implode(',', $checked) . ')', array());
131
            $SESSION->add_ok_msg(get_string('topicopenedsuccess', 'interaction.forum'));
Clare Lenihan's avatar
Clare Lenihan committed
132
        }
133 134 135 136 137 138 139 140 141 142
        else if ($moderator && $type == 'moveto') {
            $newforumid = param_integer('newforum');
            // Check if the new forum is in the current group
            $newforum = interaction_instance_from_id($newforumid);
            if ($newforum && $newforum->get('group') == $forum->groupid) {
                set_field_select('interaction_forum_topic', 'forum', $newforumid, 'id IN (' . implode(',', $checked) . ')', array());
                PluginInteractionForum::interaction_forum_new_post($checked);
                $SESSION->add_ok_msg(get_string('topicmovedsuccess', 'interaction.forum', count($checked)));
            }
        }
Clare Lenihan's avatar
Clare Lenihan committed
143 144
        else if ($type == 'subscribe' && !$forum->subscribed) {
            db_begin();
145
            foreach ($checked as $key => $value) {
146 147 148 149 150 151
                if (!record_exists('interaction_forum_subscription_topic', 'user', $USER->get('id'), 'topic', $value)) {
                    insert_record('interaction_forum_subscription_topic',
                        (object) array(
                            'user'  => $USER->get('id'),
                            'topic' => $value,
                            'key'   => PluginInteractionForum::generate_unsubscribe_key(),
152
                    ));
153
                }
154
            }
Clare Lenihan's avatar
Clare Lenihan committed
155
            db_commit();
156 157
            $SESSION->add_ok_msg(get_string('topicsubscribesuccess', 'interaction.forum'));
        }
Clare Lenihan's avatar
Clare Lenihan committed
158 159
        else if ($type == 'unsubscribe' && !$forum->subscribed) {
            delete_records_sql('DELETE FROM {interaction_forum_subscription_topic}
160
                WHERE topic IN (' . implode(',', $checked) . ') AND "user" = ?',
Clare Lenihan's avatar
Clare Lenihan committed
161 162 163 164
                array($USER->get('id')
            ));
            $SESSION->add_ok_msg(get_string('topicunsubscribesuccess', 'interaction.forum'));
        }
Clare Lenihan's avatar
Clare Lenihan committed
165
    }
166
    else { // $checked contains bad values
167
        $SESSION->add_error_msg(get_string('topicupdatefailed', 'interaction.forum'));
Clare Lenihan's avatar
Clare Lenihan committed
168
    }
Clare Lenihan's avatar
Clare Lenihan committed
169
    redirect('/interaction/forum/view.php?id=' . $forumid . '&offset=' . $offset);
170 171
}

172 173 174 175 176 177 178
if ($membership) {
    $forum->subscribe = pieform(array(
        'name' => 'subscribe_forum',
        'renderer' => 'div',
        'plugintype' => 'interaction',
        'pluginname' => 'forum',
        'autofocus' => false,
179
        'class' => 'form-as-button pull-left',
180 181
        'elements' => array(
            'submit' => array(
182 183 184
                'type' => 'button',
                'usebuttontag' => true,
                'class' => 'btn btn-default',
Pat Kira's avatar
Pat Kira committed
185
                'value' => $forum->subscribed ? '<span class="fa fa-lg fa-times prs text-danger"></span> ' . get_string('unsubscribefromforum', 'interaction.forum') : '<span class="fa fa-lg fa-star prs text-primary"></span> ' .  get_string('subscribetoforum', 'interaction.forum'),
186
                'help' => false
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
            ),
            'forum' => array(
                'type' => 'hidden',
                'value' => $forumid
            ),
            'redirect' => array(
                'type' => 'hidden',
                'value' => 'view'
            ),
            'offset' => array(
                'type' => 'hidden',
                'value' => $offset
            ),
            'type' => array(
                'type' => 'hidden',
                'value' => $forum->subscribed ? 'unsubscribe' : 'subscribe'
            )
204
        )
205 206
    ));
}
207

208 209 210
// gets the info about topics
// the last post is found by taking the max id of the posts in a topic with the max post time
// taking the max id is needed because multiple posts can have the same post time
211
$sql = 'SELECT t.id, p1.subject, p1.body, p1.poster, p1.deleted, m.user AS moderator, COUNT(p2.id) AS postcount, t.closed, s.topic AS subscribed, p4.id AS lastpost, ' . db_format_tsfield('p4.ctime', 'lastposttime') . ', p4.poster AS lastposter, m2.user AS lastpostermoderator
212
    FROM {interaction_forum_topic} t
Clare Lenihan's avatar
Clare Lenihan committed
213
    INNER JOIN {interaction_forum_post} p1 ON (p1.topic = t.id AND p1.parent IS NULL)
214 215 216 217 218
    LEFT JOIN (
        SELECT m.forum, m.user
        FROM {interaction_forum_moderator} m
        INNER JOIN {usr} u ON (m.user = u.id AND u.deleted = 0)
    ) m ON (m.forum = t.forum AND p1.poster = m.user)
219
    INNER JOIN {interaction_forum_post} p2 ON (p2.topic = t.id AND p2.deleted != 1)
Clare Lenihan's avatar
Clare Lenihan committed
220
    LEFT JOIN {interaction_forum_subscription_topic} s ON (s.topic = t.id AND s."user" = ?)
221
    INNER JOIN (
222
        SELECT MAX(p2.id) AS post, t.id AS topic
Clare Lenihan's avatar
Clare Lenihan committed
223
        FROM {interaction_forum_topic} t
224 225 226
        INNER JOIN (
            SELECT MAX(p.ctime) AS ctime, t.id AS topic
            FROM {interaction_forum_topic} t
227
            INNER JOIN {interaction_forum_post} p ON (p.topic = t.id AND p.deleted = 0)
228 229
            GROUP BY 2
        ) p1 ON t.id = p1.topic
230
        INNER JOIN {interaction_forum_post} p2 ON (p1.topic = p2.topic AND p1.ctime = p2.ctime AND p2.deleted = 0)
Clare Lenihan's avatar
Clare Lenihan committed
231 232
        GROUP BY 2
    ) p3 ON p3.topic = t.id
233
    LEFT JOIN {interaction_forum_post} p4 ON (p4.id = p3.post)
234
    LEFT JOIN {interaction_forum_topic} t2 ON (p4.topic = t2.id)
235 236 237 238 239
    LEFT JOIN (
        SELECT m.forum, m.user
        FROM {interaction_forum_moderator} m
        INNER JOIN {usr} u ON (m.user = u.id AND u.deleted = 0)
    ) m2 ON (p4.poster = m2.user AND t2.forum = m2.forum)
Clare Lenihan's avatar
Clare Lenihan committed
240
    WHERE t.forum = ?
Clare Lenihan's avatar
Clare Lenihan committed
241
    AND t.sticky = ?
Clare Lenihan's avatar
Clare Lenihan committed
242
    AND t.deleted != 1
Clare Lenihan's avatar
Clare Lenihan committed
243
    GROUP BY 1, 2, 3, 4, 5, 6, 8, 9, 10, p4.ctime, p4.poster, p4.id, m2.user
244
    ORDER BY p4.ctime DESC, p4.id DESC';
Clare Lenihan's avatar
Clare Lenihan committed
245

Clare Lenihan's avatar
Clare Lenihan committed
246 247 248 249
$stickytopics = get_records_sql_array($sql, array($userid, $forumid, 1));

$regulartopics = get_records_sql_array($sql, array($userid, $forumid, 0), $offset, $topicsperpage);

Clare Lenihan's avatar
Clare Lenihan committed
250 251
setup_topics($stickytopics);
setup_topics($regulartopics);
Clare Lenihan's avatar
Clare Lenihan committed
252 253

$pagination = build_pagination(array(
Clare Lenihan's avatar
Clare Lenihan committed
254
    'url' => get_config('wwwroot') . 'interaction/forum/view.php?id=' . $forumid,
255
    'count' => $forum->topiccount,
Clare Lenihan's avatar
Clare Lenihan committed
256 257
    'limit' => $topicsperpage,
    'offset' => $offset,
Eugene Venter's avatar
Eugene Venter committed
258 259
    'jumplinks' => 6,
    'numbersincludeprevnext' => 2,
Clare Lenihan's avatar
Clare Lenihan committed
260 261
    'resultcounttextsingular' => get_string('topiclower', 'interaction.forum'),
    'resultcounttextplural' => get_string('topicslower', 'interaction.forum')
Clare Lenihan's avatar
Clare Lenihan committed
262 263
));

264 265 266 267 268 269 270 271 272 273 274 275 276 277
$inlinejavascript = <<<EOF
addLoadEvent(function() {
    forEach(getElementsByTagAndClassName('input', 'topic-checkbox'), function(checkbox) {
        var tr = getFirstParentByTagAndClassName(checkbox, 'tr', null);
        var origColour = tr.style.backgroundColor;
        connect(checkbox, 'onclick', function(e) {
            if (tr.style.backgroundColor == origColour) {
                tr.style.backgroundColor = '#ffc';
            }
            else {
                tr.style.backgroundColor = origColour;
            }
        });
    });
278 279 280 281 282 283 284 285 286 287
    if (action = document.getElementById('action')) {
        connect(action, 'onchange', function(e) {
            if (this.options[this.selectedIndex].value == 'moveto') {
                \$j('#otherforums').removeClass('hidden');
            }
            else {
                \$j('#otherforums').addClass('hidden');
            }
        });
    }
288 289 290
});
EOF;

Evan Goldenberg's avatar
Evan Goldenberg committed
291 292
$headers = array();
if ($publicgroup) {
293
    $headers[] = '<link rel="alternate" type="application/atom+xml" href="' . $feedlink . '">';
Evan Goldenberg's avatar
Evan Goldenberg committed
294 295 296
}

$smarty = smarty(array(), $headers, array(), array());
297
$smarty->assign('heading', $forum->groupname);
298
$smarty->assign('subsectionheading', get_string('nameplural', 'interaction.forum'));
299
$smarty->assign('subheading', $forum->title);
300
$smarty->assign('headingclass', 'page-header');
Clare Lenihan's avatar
Clare Lenihan committed
301
$smarty->assign('forum', $forum);
302
$smarty->assign('otherforums', $otherforums);
Evan Goldenberg's avatar
Evan Goldenberg committed
303
$smarty->assign('publicgroup', $publicgroup);
304
$smarty->assign('ineditwindow', $ineditwindow);
Evan Goldenberg's avatar
Evan Goldenberg committed
305
$smarty->assign('feedlink', $feedlink);
306
$smarty->assign('membership', $membership);
Clare Lenihan's avatar
Clare Lenihan committed
307 308
$smarty->assign('moderator', $moderator);
$smarty->assign('admin', $admin);
309
$smarty->assign('groupadmins', group_get_admin_ids($forum->groupid));
Clare Lenihan's avatar
Clare Lenihan committed
310 311
$smarty->assign('stickytopics', $stickytopics);
$smarty->assign('regulartopics', $regulartopics);
312
$smarty->assign('moderators', $moderators);
313 314
$smarty->assign('closedicon', 'fa fa-lock-alt');
$smarty->assign('subscribedicon', 'fa fa-star');
Clare Lenihan's avatar
Clare Lenihan committed
315
$smarty->assign('pagination', $pagination['html']);
316
$smarty->assign('INLINEJAVASCRIPT', $inlinejavascript);
Clare Lenihan's avatar
Clare Lenihan committed
317
$smarty->display('interaction:forum:view.tpl');
Clare Lenihan's avatar
Clare Lenihan committed
318 319 320 321 322 323

/**
 * format body
 * format lastposttime
 */
function setup_topics(&$topics) {
324
    global $moderator;
Clare Lenihan's avatar
Clare Lenihan committed
325
    if ($topics) {
326
        foreach ($topics as $topic) {
327
            $topic->lastposttime = relative_date(get_string('strftimerecentrelative', 'interaction.forum'), get_string('strftimerecent'), $topic->lastposttime);
Evan Goldenberg's avatar
Evan Goldenberg committed
328
            $topic->feedlink = get_config('wwwroot') . 'interaction/forum/atom.php?type=t&id=' . $topic->id;
329 330 331
            $topic->containsobjectionable = false;
            if ($moderator) {
                $topic->containsobjectionable = (bool) count_records_sql(
332 333 334
                    "SELECT count(fp.id) FROM {interaction_forum_post} fp
                     JOIN {objectionable} o ON (o.objecttype = 'forum' AND o.objectid = fp.id)
                     WHERE fp.deleted = 0 AND o.resolvedby IS NULL AND o.resolvedtime IS NULL AND fp.topic = ?", array($topic->id));
335
            }
Clare Lenihan's avatar
Clare Lenihan committed
336 337 338
        }
    }
}