lib.php 30.5 KB
Newer Older
1
<?php
Nigel McNie's avatar
Nigel McNie committed
2
/**
3
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
4 5
 * Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
 *                         http://wiki.mahara.org/Contributors
Nigel McNie's avatar
Nigel McNie committed
6
 *
7 8 9 10
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
Nigel McNie's avatar
Nigel McNie committed
11
 *
12 13 14 15
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
Nigel McNie's avatar
Nigel McNie committed
16
 *
17 18
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Nigel McNie's avatar
Nigel McNie committed
19 20 21
 *
 * @package    mahara
 * @subpackage interaction-forum
22
 * @author     Catalyst IT Ltd
Nigel McNie's avatar
Nigel McNie committed
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
24
 * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
Nigel McNie's avatar
Nigel McNie committed
25 26
 *
 */
27

28 29
require_once('activity.php');

30 31
class PluginInteractionForum extends PluginInteraction {

32 33
    public static function instance_config_form($group, $instance=null) {
        if (isset($instance)) {
34 35 36 37
            $instanceconfig = get_records_assoc('interaction_forum_instance_config', 'forum', $instance->get('id'), '', 'field,value');
            $autosubscribe = isset($instanceconfig['autosubscribe']) ? $instanceconfig['autosubscribe']->value : false;
            $weight = isset($instanceconfig['weight']) ? $instanceconfig['weight']->value : null;
            $createtopicusers = isset($instanceconfig['createtopicusers']) ? $instanceconfig['createtopicusers']->value : null;
38
            $closetopics = !empty($instanceconfig['closetopics']);
39 40
            $indentmode = isset($instanceconfig['indentmode']) ? $instanceconfig['indentmode']->value : null;
            $maxindent = isset($instanceconfig['maxindent']) ? $instanceconfig['maxindent']->value : null;
41

42 43 44 45 46 47
            $moderators = get_column_sql(
                'SELECT fm.user FROM {interaction_forum_moderator} fm
                JOIN {usr} u ON (fm.user = u.id AND u.deleted = 0)
                WHERE fm.forum = ?',
                array($instance->get('id'))
            );
48 49
        }

50 51 52 53 54 55 56 57 58 59 60 61
        if ($instance === null) {
            $exclude = '';
        }
        else {
            $exclude = 'AND i.id != ' . db_quote($instance->get('id'));
        }

        $existing = get_records_sql_array('
            SELECT i.id, i.title, c.value AS weight
            FROM {interaction_instance} i
            INNER JOIN {interaction_forum_instance_config} c ON (i.id = c.forum AND c.field = \'weight\')
            WHERE i.group = ?
Nigel McNie's avatar
Nigel McNie committed
62
            AND i.deleted != 1
63 64 65 66 67 68 69 70 71 72 73 74
            ' . $exclude . '
            ORDER BY c.value',
            array($group->id));
        if ($existing) {
            foreach ($existing as &$item) {
                $item = (array)$item;
            }
        }
        else {
            $existing = array();
        }

75
        return array(
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
            'indentmode' => array(
                'type'         => 'select',
                'title'        => get_string('indentmode', 'interaction.forum'),
                'options'      => array('full_indent'  => get_string('indentfullindent', 'interaction.forum'),
                                        'max_indent'   => get_string('indentmaxindent', 'interaction.forum'),
                                        'no_indent'    => get_string('indentflatindent', 'interaction.forum') ),
                'description'  => get_string('indentmodedescription', 'interaction.forum'),
                'defaultvalue' => isset($indentmode) ? $indentmode : 'full_indent',
                'rules' => array(
                    'required' => true,
                ),
            ),
            'maxindent' => array(
                'type'         => 'text',
                'title'        => get_string('maxindent', 'interaction.forum'),
                'size'         => 2,
                'defaultvalue' => isset($maxindent) ? $maxindent : 10,
                'class'        => (isset($indentmode) & $indentmode == 'max_indent') ? '' : 'hidden',
                'rules' => array(
                    'integer' => true,
                    'minvalue' => 1,
                    'maxvalue' => 100,
                ),
            ),
100 101 102
            'fieldset' => array(
                'type' => 'fieldset',
                'collapsible' => true,
103
                'collapsed' => true,
104 105
                'legend' => get_string('settings'),
                'elements' => array(
106 107 108 109 110 111 112 113 114 115 116 117
                    'autosubscribe' => array(
                        'type'         => 'select',
                        'title'        => get_string('autosubscribeusers', 'interaction.forum'),
                        'options'      => array(true  => get_string('yes'),
                                                false => get_string('no')),
                        'description'  => get_string('autosubscribeusersdescription', 'interaction.forum'),
                        'defaultvalue' => isset($autosubscribe) ? $autosubscribe : false,
                        'rules' => array(
                            'required' => true,
                        ),
                        'help'         => true,
                    ),
118
                    'weight' => array(
119
                        'type' => 'weight',
120
                        'title' => get_string('Order', 'interaction.forum'),
121 122
                        'description' => get_string('orderdescription', 'interaction.forum'),
                        'defaultvalue' => isset($weight) ? $weight : count($existing),
123 124
                        'rules' => array(
                            'required' => true,
125 126 127
                        ),
                        'existing' => $existing,
                        'ignore'   => (count($existing) == 0)
128 129 130
                    ),
                    'moderator' => array(
                        'type' => 'userlist',
131
                        'title' => get_string('Moderators', 'interaction.forum'),
132 133 134
                        'description' => get_string('moderatorsdescription', 'interaction.forum'),
                        'defaultvalue' => isset($moderators) ? $moderators : null,
                        'group' => $group->id,
135
                        'includeadmins' => false,
136 137 138
                        'filter' => false,
                        'lefttitle' => get_string('potentialmoderators', 'interaction.forum'),
                        'righttitle' => get_string('currentmoderators', 'interaction.forum')
139 140 141 142 143 144 145 146 147 148 149 150
                    ),
                    'createtopicusers' => array(
                        'type'         => 'select',
                        'title'        => get_string('whocancreatetopics', 'interaction.forum'),
                        'options'      => array('members'    => get_string('allgroupmembers', 'group'),
                                                'moderators' => get_string('moderatorsandgroupadminsonly', 'interaction.forum')),
                        'description'  => get_string('createtopicusersdescription', 'interaction.forum'),
                        'defaultvalue' => (isset($createtopicusers) && $createtopicusers == 'moderators') ? 'moderators' : 'members',
                        'rules' => array(
                            'required' => true,
                        ),
                    ),
151 152 153 154 155 156
                    'closetopics' => array(
                        'type'         => 'checkbox',
                        'title'        => get_string('closetopics', 'interaction.forum'),
                        'description'  => get_string('closetopicsdescription', 'interaction.forum'),
                        'defaultvalue' => !empty($closetopics),
                    ),
157 158 159 160 161
                )
            )
        );
    }

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
    public static function instance_config_js() {
        return <<<EOF
function update_maxindent() {
    var s = $('edit_interaction_indentmode');
    var m = $('edit_interaction_maxindent_container');
    var t = $('edit_interaction_maxindent');
    if (!m) {
        return;
    }
    if (s.options[s.selectedIndex].value == 'max_indent') {
        removeElementClass(m, 'hidden');
        removeElementClass(t, 'hidden');
    }
    else {
        addElementClass(m, 'hidden');
        addElementClass(t, 'hidden');
    }
}
addLoadEvent(function() {
    connect('edit_interaction_indentmode', 'onchange', update_maxindent);
});
EOF;
    }

186
    public static function instance_config_save($instance, $values){
187
        db_begin();
188 189 190 191 192 193 194 195 196 197 198 199 200

        // Autosubscribe
        delete_records_sql(
            "DELETE FROM {interaction_forum_instance_config}
            WHERE field = 'autosubscribe' AND forum = ?",
            array($instance->get('id'))
        );
        insert_record('interaction_forum_instance_config', (object)array(
            'forum' => $instance->get('id'),
            'field' => 'autosubscribe',
            'value' => (bool)$values['autosubscribe'],
        ));

201
        if ($values['justcreated'] && $values['autosubscribe']) {
202 203 204 205 206 207 208
            // Subscribe all existing users in the group to the forums
            if ($userids = get_column('group_member', 'member', 'group', $instance->get('group'))) {
                foreach ($userids as $userid) {
                    insert_record(
                        'interaction_forum_subscription_forum',
                        (object)array(
                            'forum' => $instance->get('id'),
209
                            'user'  => $userid,
210
                            'key'   => PluginInteractionForum::generate_unsubscribe_key(),
211 212 213 214 215 216 217
                        )
                    );
                }
            }
        }

        // Moderators
218 219 220 221
        delete_records(
            'interaction_forum_moderator',
            'forum', $instance->get('id')
        );
222 223 224 225 226 227 228 229 230 231
        if (isset($values['moderator']) && is_array($values['moderator'])) {
            foreach ($values['moderator'] as $user) {
                insert_record(
                    'interaction_forum_moderator',
                    (object)array(
                        'user' => $user,
                        'forum' => $instance->get('id')
                    )
                );
            }
232 233
        }

234
        // Re-order the forums according to their new ordering
235 236 237 238 239 240
        delete_records_sql(
            'DELETE FROM {interaction_forum_instance_config}
            WHERE field = \'weight\' AND forum IN (
                SELECT id FROM {interaction_instance} WHERE "group" = ?
            )',
            array($instance->get('group'))
241
        );
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270

        if (isset($values['weight'])) {
            foreach ($values['weight'] as $weight => $id) {
                if ($id === null) {
                    // This is where the current forum is to be placed
                    $id = $instance->get('id');
                }

                insert_record(
                    'interaction_forum_instance_config',
                    (object)array(
                        'forum' => $id,
                        'field' => 'weight',
                        'value' => $weight,
                    )
                );
            }
        }
        else {
            // Element was ignored - because this is the first forum in a group
            insert_record(
                'interaction_forum_instance_config',
                (object)array(
                    'forum' => $instance->get('id'),
                    'field' => 'weight',
                    'value' => 0,
                )
            );
        }
271 272 273 274 275 276 277 278 279 280 281 282 283

        // Create topic users
        delete_records_sql(
            "DELETE FROM {interaction_forum_instance_config}
            WHERE field = 'createtopicusers' AND forum = ?",
            array($instance->get('id'))
        );
        insert_record('interaction_forum_instance_config', (object)array(
            'forum' => $instance->get('id'),
            'field' => 'createtopicusers',
            'value' => $values['createtopicusers'] == 'moderators' ? 'moderators' : 'members',
        ));

284 285 286 287 288 289 290 291 292 293 294 295 296 297
        // Close topics
        delete_records_sql(
            "DELETE FROM {interaction_forum_instance_config}
            WHERE field = 'closetopics' AND forum = ?",
            array($instance->get('id'))
        );
        if (!empty($values['closetopics'])) {
            insert_record('interaction_forum_instance_config', (object)array(
                'forum' => $instance->get('id'),
                'field' => 'closetopics',
                'value' => 1,
            ));
        }

298 299 300 301 302 303
        //Indent mode
        delete_records_sql(
            "DELETE FROM {interaction_forum_instance_config}
            WHERE field = 'indentmode' AND forum = ?",
            array($instance->get('id'))
        );
304 305 306
        if (!isset($values['indentmode'])) {
            $values['indentmode'] = 'full_indent';
        }
307 308 309 310 311 312 313 314 315 316 317 318
        insert_record('interaction_forum_instance_config', (object)array(
            'forum' => $instance->get('id'),
            'field' => 'indentmode',
            'value' => $values['indentmode'],
        ));

        //Max indent
        delete_records_sql(
            "DELETE FROM {interaction_forum_instance_config}
            WHERE field = 'maxindent' AND forum = ?",
            array($instance->get('id'))
        );
319 320 321
        if (!isset($values['maxindent'])) {
            $values['maxindent'] = 10;
        }
322 323 324 325 326 327
        insert_record('interaction_forum_instance_config', (object)array(
            'forum' => $instance->get('id'),
            'field' => 'maxindent',
            'value' => $values['maxindent'],
        ));

328

Nigel McNie's avatar
Nigel McNie committed
329
        db_commit();
330
    }
331 332 333 334 335 336

    public static function get_activity_types() {
        return array(
            (object)array(
                'name' => 'newpost',
                'admin' => 0,
337
                'delay' => 1
338 339
            )
        );
340
    }
341 342 343 344 345 346 347 348 349 350

    public static function get_cron() {
        return array(
            (object)array(
                'callfunction' => 'interaction_forum_new_post',
                'minute'       => '*/30',
            ),
        );
    }

351 352 353 354 355 356 357 358 359 360 361 362
    /**
     * Subscribes the forum plugin to events
     *
     * @return array
     */
    public static function get_event_subscriptions() {
        return array(
            (object)array(
                'plugin'       => 'forum',
                'event'        => 'userjoinsgroup',
                'callfunction' => 'user_joined_group',
            ),
363 364 365 366 367
            (object)array(
                'plugin'       => 'forum',
                'event'        => 'creategroup',
                'callfunction' => 'create_default_forum',
            ),
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
        );
    }

    /**
     * When a user joins a group, subscribe them automatically to all forums 
     * that should be subscribable
     *
     * @param array $eventdata
     */
    public static function user_joined_group($event, $gm) {
        if ($forumids = get_column_sql("
            SELECT ii.id
            FROM {group} g
            LEFT JOIN {interaction_instance} ii ON g.id = ii.group
            LEFT JOIN {interaction_forum_instance_config} ific ON ific.forum = ii.id
383
            WHERE \"group\" = ? AND ific.field = 'autosubscribe' and ific.value = '1'",
384 385 386 387 388 389 390
            array($gm['group']))) {
            db_begin();
            foreach ($forumids as $forumid) {
                insert_record(
                    'interaction_forum_subscription_forum',
                    (object)array(
                        'forum' => $forumid,
391
                        'user'  => $gm['member'],
392
                        'key'   => PluginInteractionForum::generate_unsubscribe_key(),
393 394 395 396 397 398 399
                    )
                );
            }
            db_commit();
        }
    }

400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
    /**
     * When a group is created, create one forum automatically.
     *
     * @param array $eventdata
     */
    public static function create_default_forum($event, $eventdata) {
        global $USER;
        $creator = 0;
        if (isset($eventdata['members'][$USER->get('id')])) {
            $creator = $USER->get('id');
        }
        else {
            foreach($eventdata['members'] as $userid => $role) {
                if ($role == 'admin') {
                    $creator = $userid;
                    break;
                }
            }
        }
        db_begin();
        $forum = new InteractionForumInstance(0, (object) array(
            'group'       => $eventdata['id'],
            'creator'     => $creator,
            'title'       => get_string('defaultforumtitle', 'interaction.forum'),
            'description' => get_string('defaultforumdescription', 'interaction.forum', $eventdata['name']),
        ));
        $forum->commit();
        self::instance_config_save($forum, array(
            'createtopicusers' => 'members',
            'autosubscribe'    => 1,
            'justcreated'      => 1,
        ));
        db_commit();
    }

435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
    /**
     * Optional method. Takes a list of forums and sorts them according to 
     * their weights for the sideblock
     *
     * @param array $forums An array of hashes of forum data
     * @return array        The array, sorted appropriately
     */
    public static function sideblock_sort($forums) {
        if (!$forums) {
            return $forums;
        }

        $weights = get_records_assoc('interaction_forum_instance_config', 'field', 'weight', 'forum', 'forum, value');
        foreach ($forums as &$forum) {
            // Note: forums expect every forum to have a 'weight' record in the 
            // forum instance config table, so we don't need to check that 
            // there is a weight for the forum here - there should be, 
            // otherwise someone has futz'd with the database or there's a bug 
            // elsewhere that allowed this to happen
            $forum->weight = $weights[$forum->id]->value;
        }
        usort($forums, create_function('$a, $b', 'return $a->weight > $b->weight;'));
        return $forums;
    }

460 461 462 463

    /**
     * Process new forum posts.
     *
464
     * @param array $postnow An array of post ids to be sent immediately.  If null, send all posts older than postdelay.
465 466 467 468
     */
    public static function interaction_forum_new_post($postnow=null) {
        if (is_array($postnow) && !empty($postnow)) {
            $values = array();
469
            $postswhere = 'id IN (' . join(',', array_map('intval', $postnow)) . ')';
470
            $delay = false;
471 472 473
        }
        else {
            $currenttime = time();
474
            $minpostdelay = $currenttime - get_config_plugin('interaction', 'forum', 'postdelay') * 60;
475 476
            $values = array(db_format_timestamp($minpostdelay));
            $postswhere = 'ctime < ?';
477
            $delay = null;
478
        }
479
        $posts = get_column_sql('SELECT id FROM {interaction_forum_post} WHERE sent = 0 AND deleted = 0 AND ' . $postswhere, $values);
480
        if ($posts) {
481 482
            set_field_select('interaction_forum_post', 'sent', 1, 'deleted = 0 AND sent = 0 AND ' . $postswhere, $values);
            foreach ($posts as $postid) {
483
                activity_occurred('newpost', array('postid' => $postid), 'interaction', 'forum', $delay);
484 485 486
            }
        }
    }
487 488 489 490

    public static function can_be_disabled() {
        return false; //TODO until it either becomes an artefact plugin or stops being hardcoded everywhere
    }
491 492 493 494 495 496 497 498 499 500 501 502

    /**
     * Generates a random key to use for unsubscription requests.
     *
     * See the interaction_forum_subscription_* tables and related operations 
     * on them for more information.
     *
     * @return string A random key
     */
    public static function generate_unsubscribe_key() {
        return dechex(mt_rand());
    }
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531


    public static function has_config() {
        return true;
    }

    public static function get_config_options() {
        $postdelay = get_config_plugin('interaction', 'forum', 'postdelay');
        if (!is_numeric($postdelay)) {
            $postdelay = 30;
        }

        return array(
            'elements' => array(
                'postdelay' => array(
                    'title'        => get_string('postdelay', 'interaction.forum'),
                    'description'  => get_string('postdelaydescription', 'interaction.forum'),
                    'type'         => 'text',
                    'rules'        => array('integer' => true, 'minvalue' => 0, 'maxvalue' => 10000000),
                    'defaultvalue' => (int) $postdelay,
                ),
            ),
            'renderer' => 'table'
        );
    }

    public static function save_config_options($values) {
        set_config_plugin('interaction', 'forum', 'postdelay', $values['postdelay']);
    }
532 533 534 535 536 537 538 539
}

class InteractionForumInstance extends InteractionInstance {

    public static function get_plugin() {
        return 'forum';
    }

540 541
    public function interaction_remove_user($userid) {
        delete_records('interaction_forum_moderator', 'forum', $this->id, 'user', $userid);
542 543 544 545 546
        delete_records('interaction_forum_subscription_forum', 'forum', $this->id, 'user', $userid);
        delete_records_select('interaction_forum_subscription_topic',
            'user = ? AND topic IN (SELECT id FROM {interaction_forum_topic} WHERE forum = ?)',
            array($userid, $this->id)
        );
547 548
    }

549 550
}

551 552 553 554 555 556
class ActivityTypeInteractionForumNewPost extends ActivityTypePlugin {

    protected $postid;

    public function __construct($data) {
        parent::__construct($data);
557
        $this->overridemessagecontents = true;
558 559 560 561 562

        $post = get_record_sql('
            SELECT
                p.subject, p.body, p.poster, p.parent, ' . db_format_tsfield('p.ctime', 'ctime') . ',
                t.id AS topicid, fp.subject AS topicsubject, f.title AS forumtitle, g.name AS groupname, f.id AS forumid
563
            FROM {interaction_forum_post} p
564 565 566 567 568
            INNER JOIN {interaction_forum_topic} t ON (t.id = p.topic AND t.deleted = 0)
            INNER JOIN {interaction_forum_post} fp ON (fp.parent IS NULL AND fp.topic = t.id)
            INNER JOIN {interaction_instance} f ON (t.forum = f.id AND f.deleted = 0)
            INNER JOIN {group} g ON (f.group = g.id AND g.deleted = 0)
            WHERE p.id = ? AND p.deleted = 0',
569 570
            array($this->postid)
        );
571 572 573 574 575 576 577 578

        // The post may have been deleted during the activity delay
        if (!$post) {
            $this->users = array();
            return;
        }

        $subscribers = get_records_sql_assoc('
579
            SELECT "user" AS subscriber, \'topic\' AS type, "key" FROM {interaction_forum_subscription_topic} WHERE topic = ?
580
            UNION
581
            SELECT "user" AS subscriber, \'forum\' AS type, "key" FROM {interaction_forum_subscription_forum} WHERE forum = ?
582 583 584 585 586
            ORDER BY type',
            array($post->topicid, $post->forumid)
        );

        $this->users = $subscribers ? activity_get_users($this->get_id(), array_keys($subscribers)) : array();
587
        $this->fromuser = $post->poster;
588

589 590 591
        // When emailing forum posts, create Message-Id headers for threaded display by email clients
        $urlinfo = parse_url(get_config('wwwroot'));
        $hostname = $urlinfo['host'];
592
        $cleanforumname = str_replace('"', "'", strip_tags($post->forumtitle));
593
        $this->customheaders = array(
594 595
            'List-Id: "' . $cleanforumname . '" <forum' . $post->forumid . '@' . $hostname . '>',
            'List-Help: ' . get_config('wwwroot') . 'interaction/forum/view.php?id=' . $post->forumid,
596 597
            'Message-ID: <forumpost' . $this->postid . '@' . $hostname . '>',
        );
598 599 600 601
        if ($post->parent) {
            $this->customheaders[] = 'In-Reply-To: <forumpost' . $post->parent . '@' . $hostname . '>';
            $this->customheaders[] = 'References: <forumpost' . $post->parent . '@' . $hostname . '>';
        }
602 603

        $posttime = strftime(get_string('strftimedaydatetime'), $post->ctime);
604
        $htmlbody = $post->body;
605
        $this->message = strip_tags(str_shorten_html($htmlbody, 200, true)); // For internal notifications.
606

607
        $textbody = trim(html2text($post->body));
608
        $postlink = get_config('wwwroot') . 'interaction/forum/topic.php?id=' . $post->topicid . '#post' . $this->postid;
609

610
        $this->url = $postlink;
611
        $this->add_urltext(array(
612
            'key'     => 'Topic',
613 614
            'section' => 'interaction.forum'
        ));
615

616
        foreach ($this->users as &$user) {
617
            $lang = (empty($user->lang) || $user->lang == 'default') ? get_config('lang') : $user->lang;
618
            if ($post->parent) {
619
                $user->subject = get_string_from_language($lang, 'replyforumpostnotificationsubject', 'interaction.forum', $post->groupname, $post->forumtitle, $post->topicsubject);
620 621
            }
            else {
622
                $user->subject = get_string_from_language($lang, 'newforumpostnotificationsubject', 'interaction.forum', $post->groupname, $post->forumtitle, $post->subject);
623
            }
624

625
            $type = $subscribers[$user->id]->type;
626
            $unsubscribeid = $post->{$type . 'id'};
627
            $unsubscribelink = get_config('wwwroot') . 'interaction/forum/unsubscribe.php?' . $type . '=' . $unsubscribeid . '&key=' . $subscribers[$user->id]->key;
628

629
            $user->emailmessage = get_string_from_language($lang, 'forumposttemplate', 'interaction.forum',
630 631
                $post->subject ? $post->subject : get_string_from_language($lang, 're', 'interaction.forum', $post->topicsubject),
                display_name($post->poster, $user),
632 633
                $posttime,
                $textbody,
634
                $postlink,
635
                $type,
636
                $unsubscribelink
637
            );
638 639 640 641 642
            $user->htmlmessage = get_string_from_language($lang, 'forumposthtmltemplate', 'interaction.forum',
                $post->subject ? $post->subject : get_string_from_language($lang, 're', 'interaction.forum', $post->topicsubject),
                display_name($post->poster, $user),
                $posttime,
                $htmlbody,
643 644 645
                $postlink,
                $unsubscribelink,
                $type
646
            );
647 648 649
        }
    }

650 651 652 653
    public function get_subject($user) {
        return $user->subject;
    }

654 655 656 657 658 659 660
    public function get_plugintype(){
        return 'interaction';
    }

    public function get_pluginname(){
        return 'forum';
    }
661 662

    public function get_required_parameters() {
663
        return array('postid');
664
    }
665 666
}

667 668 669 670 671
// constants for forum membership types
define('INTERACTION_FORUM_ADMIN', 1);
define('INTERACTION_FORUM_MOD', 2);
define('INTERACTION_FORUM_MEMBER', 4);

672
/**
673
 * Can a user access a given forum?
Clare Lenihan's avatar
Clare Lenihan committed
674
 *
675 676 677
 * @param int $forumid id of forum
 * @param int $userid optional id of user, defaults to logged in user
 *
678
 * @returns constant access level or false
679
 */
680
function user_can_access_forum($forumid, $userid=null) {
681 682 683 684 685
    if (empty($userid)) {
        global $USER;
        $userid = $USER->get('id');
    }
    else if (!is_int($userid)) {
686
        throw new InvalidArgumentException("non integer user id given to user_can_access_forum: $userid");
687 688
    }
    if (!is_int($forumid)) {
689 690 691 692 693 694
        throw new InvalidArgumentException("non integer forum id given to user_can_access_forum: $forumid");
    }

    $membership = 0;

    $groupid = get_field('interaction_instance', '"group"', 'id', $forumid);
695
    $groupmembership = group_user_access((int)$groupid, (int)$userid);
696 697 698 699 700

    if (!$groupmembership) {
        return $membership;
    }
    $membership = $membership | INTERACTION_FORUM_MEMBER;
701
    if ($groupmembership == 'admin') {
702 703
        $membership = $membership | INTERACTION_FORUM_ADMIN | INTERACTION_FORUM_MOD;
    }
704
    if (record_exists('interaction_forum_moderator', 'forum', $forumid, 'user', $userid)) {
705
        $membership = $membership | INTERACTION_FORUM_MOD;
706
    }
707
    return $membership;
708 709
}

710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
/**
 * Is a user allowed to edit a post
 *
 * @param boolean $moderator
 * @param int $poster the the id of the user who created the post
 * @param int $posttime the time the post was made
 * @param int $userid optional id of user, defaults to logged in user
 *
 * @returns boolean
 */
function user_can_edit_post($poster, $posttime, $userid=null) {
	if (empty($userid)) {
        global $USER;
        $userid = $USER->get('id');
    }
725
    return $poster == $userid && $posttime > (time() - get_config_plugin('interaction', 'forum', 'postdelay') * 60);
726 727
}

728 729 730 731 732 733 734 735
/**
 * Generates a relative date containing yesterday/today when appropriate
 *
 * @param string $relative the format (for strftime) for a relative date (with %v where yesterday/today should be)
 * @param string $absolute the format (for strftime) for an absolute date
 * @param int $time1 the time to display
 * @param int $time2 optional the time $time1 is relative to, defaults to current time
 */
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
function relative_date($relative, $absolute, $time1, $time2=null) {
    if ($time2==null) {
        $time2 = time();
    }

    $date = getdate($time1);

    $yesterday = getdate(strtotime('-1 day', $time2));
    $tomorrow = getdate(strtotime('+1 day', $time2));
    $today = getdate($time2);

    if ($date['year'] == $yesterday['year'] && $date['yday'] == $yesterday['yday']) {
        return str_replace('%v', get_string('yesterday', 'interaction.forum'), strftime($relative, $time1));
    }
    else if ($date['year'] == $today['year'] && $date['yday'] == $today['yday']) {
        return str_replace('%v', get_string('today', 'interaction.forum'), strftime($relative, $time1));
    }
    return strftime($absolute, $time1);

}

757 758 759 760 761 762
function subscribe_forum_validate(Pieform $form, $values) {
    if (!is_logged_in()) {
        throw new AccessDeniedException();
    }
}

763 764
function subscribe_forum_submit(Pieform $form, $values) {
    global $USER, $SESSION;
765 766
    if ($values['type'] == 'subscribe') {
        db_begin();
767 768 769 770
        insert_record(
            'interaction_forum_subscription_forum',
            (object)array(
                'forum' => $values['forum'],
771
                'user'  => $USER->get('id'),
772
                'key'   => PluginInteractionForum::generate_unsubscribe_key(),
773 774 775 776 777 778 779 780 781 782 783 784
            )
        );
        delete_records_sql(
            'DELETE FROM {interaction_forum_subscription_topic}
            WHERE topic IN (
                SELECT id
                FROM {interaction_forum_topic}
                WHERE forum = ?
                AND "user" = ?
            )',
            array($values['forum'], $USER->get('id'))
        );
785
        db_commit();
786 787 788 789 790 791 792 793 794 795
        $SESSION->add_ok_msg(get_string('forumsuccessfulsubscribe', 'interaction.forum'));
    }
    else {
        delete_records(
            'interaction_forum_subscription_forum',
            'forum', $values['forum'],
            'user', $USER->get('id')
        );
        $SESSION->add_ok_msg(get_string('forumsuccessfulunsubscribe', 'interaction.forum'));
    }
796 797 798 799 800 801
    if ($values['redirect'] == 'index') {
        redirect('/interaction/forum/index.php?group=' . $values['group']);
    }
    else {
        redirect('/interaction/forum/view.php?id=' . $values['forum'] . '&offset=' . $values['offset']);
    }
802 803
}

804
?>