/**
  * Marks the selected topics as read.
  * Accessed by action=markasread;sa=unreadreplies
  */
 public function action_markreplies()
 {
     global $user_info, $modSettings;
     // Make sure all the topics are integers!
     $topics = array_map('intval', explode('-', $_REQUEST['topics']));
     require_once SUBSDIR . '/Topic.subs.php';
     $logged_topics = getLoggedTopics($user_info['id'], $topics);
     $markRead = array();
     foreach ($topics as $id_topic) {
         $markRead[] = array($user_info['id'], (int) $id_topic, $modSettings['maxMsgID'], (int) (!empty($logged_topics[$id_topic])));
     }
     markTopicsRead($markRead, true);
     if (isset($_SESSION['topicseen_cache'])) {
         $_SESSION['topicseen_cache'] = array();
     }
     return 'action=unreadreplies';
 }
Beispiel #2
0
/**
 * Set off/on unread reply subscription for a topic
 *
 * @param int $id_member
 * @param int $topic
 * @param bool $on = false
 */
function setTopicWatch($id_member, $topic, $on = false)
{
    global $user_info;
    $db = database();
    // find the current entry if it exists that is
    $was_set = getLoggedTopics($user_info['id'], array($topic));
    // Set topic unwatched on/off for this topic.
    $db->insert(empty($was_set[$topic]) ? 'ignore' : 'replace', '{db_prefix}log_topics', array('id_member' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'unwatched' => 'int'), array($id_member, $topic, !empty($was_set[$topic]['id_msg']) ? $was_set[$topic]['id_msg'] : 0, $on ? 1 : 0), array('id_member', 'id_topic'));
}
    /**
     * Allows for moderation from the message index.
     * @todo refactor this...
     */
    public function action_quickmod()
    {
        global $board, $user_info, $modSettings, $context;
        $db = database();
        // Check the session = get or post.
        checkSession('request');
        // Lets go straight to the restore area.
        if (isset($_REQUEST['qaction']) && $_REQUEST['qaction'] == 'restore' && !empty($_REQUEST['topics'])) {
            redirectexit('action=restoretopic;topics=' . implode(',', $_REQUEST['topics']) . ';' . $context['session_var'] . '=' . $context['session_id']);
        }
        if (isset($_SESSION['topicseen_cache'])) {
            $_SESSION['topicseen_cache'] = array();
        }
        // This is going to be needed to send off the notifications and for updateLastMessages().
        require_once SUBSDIR . '/Post.subs.php';
        require_once SUBSDIR . '/Notification.subs.php';
        // Process process process data.
        require_once SUBSDIR . '/Topic.subs.php';
        // Remember the last board they moved things to.
        if (isset($_REQUEST['move_to'])) {
            $_SESSION['move_to_topic'] = array('move_to' => $_REQUEST['move_to'], 'redirect_topic' => !empty($_REQUEST['redirect_topic']) ? (int) $_REQUEST['redirect_topic'] : 0, 'redirect_expires' => !empty($_REQUEST['redirect_expires']) ? (int) $_REQUEST['redirect_expires'] : 0);
        }
        // Only a few possible actions.
        $possibleActions = array();
        if (!empty($board)) {
            $boards_can = array('make_sticky' => allowedTo('make_sticky') ? array($board) : array(), 'move_any' => allowedTo('move_any') ? array($board) : array(), 'move_own' => allowedTo('move_own') ? array($board) : array(), 'remove_any' => allowedTo('remove_any') ? array($board) : array(), 'remove_own' => allowedTo('remove_own') ? array($board) : array(), 'lock_any' => allowedTo('lock_any') ? array($board) : array(), 'lock_own' => allowedTo('lock_own') ? array($board) : array(), 'merge_any' => allowedTo('merge_any') ? array($board) : array(), 'approve_posts' => allowedTo('approve_posts') ? array($board) : array());
            $redirect_url = 'board=' . $board . '.' . $_REQUEST['start'];
        } else {
            $boards_can = boardsAllowedTo(array('make_sticky', 'move_any', 'move_own', 'remove_any', 'remove_own', 'lock_any', 'lock_own', 'merge_any', 'approve_posts'), true, false);
            $redirect_url = isset($_POST['redirect_url']) ? $_POST['redirect_url'] : (isset($_SESSION['old_url']) ? $_SESSION['old_url'] : '');
        }
        if (!$user_info['is_guest']) {
            $possibleActions[] = 'markread';
        }
        if (!empty($boards_can['make_sticky']) && !empty($modSettings['enableStickyTopics'])) {
            $possibleActions[] = 'sticky';
        }
        if (!empty($boards_can['move_any']) || !empty($boards_can['move_own'])) {
            $possibleActions[] = 'move';
        }
        if (!empty($boards_can['remove_any']) || !empty($boards_can['remove_own'])) {
            $possibleActions[] = 'remove';
        }
        if (!empty($boards_can['lock_any']) || !empty($boards_can['lock_own'])) {
            $possibleActions[] = 'lock';
        }
        if (!empty($boards_can['merge_any'])) {
            $possibleActions[] = 'merge';
        }
        if (!empty($boards_can['approve_posts'])) {
            $possibleActions[] = 'approve';
        }
        // Two methods: $_REQUEST['actions'] (id_topic => action), and $_REQUEST['topics'] and $_REQUEST['qaction'].
        // (if action is 'move', $_REQUEST['move_to'] or $_REQUEST['move_tos'][$topic] is used.)
        if (!empty($_REQUEST['topics'])) {
            // If the action isn't valid, just quit now.
            if (empty($_REQUEST['qaction']) || !in_array($_REQUEST['qaction'], $possibleActions)) {
                redirectexit($redirect_url);
            }
            // Merge requires all topics as one parameter and can be done at once.
            if ($_REQUEST['qaction'] == 'merge') {
                // Merge requires at least two topics.
                if (empty($_REQUEST['topics']) || count($_REQUEST['topics']) < 2) {
                    redirectexit($redirect_url);
                }
                require_once CONTROLLERDIR . '/MergeTopics.controller.php';
                $controller = new MergeTopics_Controller();
                return $controller->action_mergeExecute($_REQUEST['topics']);
            }
            // Just convert to the other method, to make it easier.
            foreach ($_REQUEST['topics'] as $topic) {
                $_REQUEST['actions'][(int) $topic] = $_REQUEST['qaction'];
            }
        }
        // Weird... how'd you get here?
        if (empty($_REQUEST['actions'])) {
            redirectexit($redirect_url);
        }
        // Validate each action.
        $temp = array();
        foreach ($_REQUEST['actions'] as $topic => $action) {
            if (in_array($action, $possibleActions)) {
                $temp[(int) $topic] = $action;
            }
        }
        $_REQUEST['actions'] = $temp;
        if (!empty($_REQUEST['actions'])) {
            // Find all topics...
            $topics_info = topicsDetails(array_keys($_REQUEST['actions']));
            foreach ($topics_info as $row) {
                if (!empty($board)) {
                    if ($row['id_board'] != $board || $modSettings['postmod_active'] && !$row['approved'] && !allowedTo('approve_posts')) {
                        unset($_REQUEST['actions'][$row['id_topic']]);
                    }
                } else {
                    // Don't allow them to act on unapproved posts they can't see...
                    if ($modSettings['postmod_active'] && !$row['approved'] && !in_array(0, $boards_can['approve_posts']) && !in_array($row['id_board'], $boards_can['approve_posts'])) {
                        unset($_REQUEST['actions'][$row['id_topic']]);
                    } elseif ($_REQUEST['actions'][$row['id_topic']] == 'sticky' && !in_array(0, $boards_can['make_sticky']) && !in_array($row['id_board'], $boards_can['make_sticky'])) {
                        unset($_REQUEST['actions'][$row['id_topic']]);
                    } elseif ($_REQUEST['actions'][$row['id_topic']] == 'move' && !in_array(0, $boards_can['move_any']) && !in_array($row['id_board'], $boards_can['move_any']) && ($row['id_member_started'] != $user_info['id'] || !in_array(0, $boards_can['move_own']) && !in_array($row['id_board'], $boards_can['move_own']))) {
                        unset($_REQUEST['actions'][$row['id_topic']]);
                    } elseif ($_REQUEST['actions'][$row['id_topic']] == 'remove' && !in_array(0, $boards_can['remove_any']) && !in_array($row['id_board'], $boards_can['remove_any']) && ($row['id_member_started'] != $user_info['id'] || !in_array(0, $boards_can['remove_own']) && !in_array($row['id_board'], $boards_can['remove_own']))) {
                        unset($_REQUEST['actions'][$row['id_topic']]);
                    } elseif ($_REQUEST['actions'][$row['id_topic']] == 'lock' && !in_array(0, $boards_can['lock_any']) && !in_array($row['id_board'], $boards_can['lock_any']) && ($row['id_member_started'] != $user_info['id'] || $row['locked'] == 1 || !in_array(0, $boards_can['lock_own']) && !in_array($row['id_board'], $boards_can['lock_own']))) {
                        unset($_REQUEST['actions'][$row['id_topic']]);
                    } elseif ($_REQUEST['actions'][$row['id_topic']] == 'approve' && (!$row['unapproved_posts'] || !in_array(0, $boards_can['approve_posts']) && !in_array($row['id_board'], $boards_can['approve_posts']))) {
                        unset($_REQUEST['actions'][$row['id_topic']]);
                    }
                }
            }
        }
        $stickyCache = array();
        $moveCache = array(0 => array(), 1 => array());
        $removeCache = array();
        $lockCache = array();
        $markCache = array();
        $approveCache = array();
        // Separate the actions.
        foreach ($_REQUEST['actions'] as $topic => $action) {
            $topic = (int) $topic;
            if ($action == 'markread') {
                $markCache[] = $topic;
            } elseif ($action == 'sticky') {
                $stickyCache[] = $topic;
            } elseif ($action == 'move') {
                moveTopicConcurrence();
                // $moveCache[0] is the topic, $moveCache[1] is the board to move to.
                $moveCache[1][$topic] = (int) (isset($_REQUEST['move_tos'][$topic]) ? $_REQUEST['move_tos'][$topic] : $_REQUEST['move_to']);
                if (empty($moveCache[1][$topic])) {
                    continue;
                }
                $moveCache[0][] = $topic;
            } elseif ($action == 'remove') {
                $removeCache[] = $topic;
            } elseif ($action == 'lock') {
                $lockCache[] = $topic;
            } elseif ($action == 'approve') {
                $approveCache[] = $topic;
            }
        }
        if (empty($board)) {
            $affectedBoards = array();
        } else {
            $affectedBoards = array($board => array(0, 0));
        }
        // Do all the stickies...
        if (!empty($stickyCache)) {
            toggleTopicSticky($stickyCache);
            // Get the board IDs and Sticky status
            $request = $db->query('', '
				SELECT id_topic, id_board, is_sticky
				FROM {db_prefix}topics
				WHERE id_topic IN ({array_int:sticky_topic_ids})
				LIMIT ' . count($stickyCache), array('sticky_topic_ids' => $stickyCache));
            $stickyCacheBoards = array();
            $stickyCacheStatus = array();
            while ($row = $db->fetch_assoc($request)) {
                $stickyCacheBoards[$row['id_topic']] = $row['id_board'];
                $stickyCacheStatus[$row['id_topic']] = empty($row['is_sticky']);
            }
            $db->free_result($request);
        }
        // Move sucka! (this is, by the by, probably the most complicated part....)
        if (!empty($moveCache[0])) {
            // I know - I just KNOW you're trying to beat the system.  Too bad for you... we CHECK :P.
            $request = $db->query('', '
				SELECT t.id_topic, t.id_board, b.count_posts
				FROM {db_prefix}topics AS t
					LEFT JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board)
				WHERE t.id_topic IN ({array_int:move_topic_ids})' . (!empty($board) && !allowedTo('move_any') ? '
					AND t.id_member_started = {int:current_member}' : '') . '
				LIMIT ' . count($moveCache[0]), array('current_member' => $user_info['id'], 'move_topic_ids' => $moveCache[0]));
            $moveTos = array();
            $moveCache2 = array();
            $countPosts = array();
            while ($row = $db->fetch_assoc($request)) {
                $to = $moveCache[1][$row['id_topic']];
                if (empty($to)) {
                    continue;
                }
                // Does this topic's board count the posts or not?
                $countPosts[$row['id_topic']] = empty($row['count_posts']);
                if (!isset($moveTos[$to])) {
                    $moveTos[$to] = array();
                }
                $moveTos[$to][] = $row['id_topic'];
                // For reporting...
                $moveCache2[] = array($row['id_topic'], $row['id_board'], $to);
            }
            $db->free_result($request);
            $moveCache = $moveCache2;
            // Do the actual moves...
            foreach ($moveTos as $to => $topics) {
                moveTopics($topics, $to);
            }
            // Does the post counts need to be updated?
            if (!empty($moveTos)) {
                require_once SUBSDIR . '/Boards.subs.php';
                $topicRecounts = array();
                $boards_info = fetchBoardsInfo(array('boards' => array_keys($moveTos)), array('selects' => 'posts'));
                foreach ($boards_info as $row) {
                    $cp = empty($row['count_posts']);
                    // Go through all the topics that are being moved to this board.
                    foreach ($moveTos[$row['id_board']] as $topic) {
                        // If both boards have the same value for post counting then no adjustment needs to be made.
                        if ($countPosts[$topic] != $cp) {
                            // If the board being moved to does count the posts then the other one doesn't so add to their post count.
                            $topicRecounts[$topic] = $cp ? 1 : -1;
                        }
                    }
                }
                if (!empty($topicRecounts)) {
                    // Get all the members who have posted in the moved topics.
                    $posters = topicsPosters(array_keys($topicRecounts));
                    foreach ($posters as $id_member => $topics) {
                        $post_adj = 0;
                        foreach ($topics as $id_topic) {
                            $post_adj += $topicRecounts[$id_topic];
                        }
                        // And now update that member's post counts
                        if (!empty($post_adj)) {
                            updateMemberData($id_member, array('posts' => 'posts + ' . $post_adj));
                        }
                    }
                }
            }
        }
        // Now delete the topics...
        if (!empty($removeCache)) {
            // They can only delete their own topics. (we wouldn't be here if they couldn't do that..)
            $result = $db->query('', '
				SELECT id_topic, id_board
				FROM {db_prefix}topics
				WHERE id_topic IN ({array_int:removed_topic_ids})' . (!empty($board) && !allowedTo('remove_any') ? '
					AND id_member_started = {int:current_member}' : '') . '
				LIMIT ' . count($removeCache), array('current_member' => $user_info['id'], 'removed_topic_ids' => $removeCache));
            $removeCache = array();
            $removeCacheBoards = array();
            while ($row = $db->fetch_assoc($result)) {
                $removeCache[] = $row['id_topic'];
                $removeCacheBoards[$row['id_topic']] = $row['id_board'];
            }
            $db->free_result($result);
            // Maybe *none* were their own topics.
            if (!empty($removeCache)) {
                // Gotta send the notifications *first*!
                foreach ($removeCache as $topic) {
                    // Only log the topic ID if it's not in the recycle board.
                    logAction('remove', array(empty($modSettings['recycle_enable']) || $modSettings['recycle_board'] != $removeCacheBoards[$topic] ? 'topic' : 'old_topic_id' => $topic, 'board' => $removeCacheBoards[$topic]));
                    sendNotifications($topic, 'remove');
                }
                removeTopics($removeCache);
            }
        }
        // Approve the topics...
        if (!empty($approveCache)) {
            // We need unapproved topic ids and their authors!
            $request = $db->query('', '
				SELECT id_topic, id_member_started
				FROM {db_prefix}topics
				WHERE id_topic IN ({array_int:approve_topic_ids})
					AND approved = {int:not_approved}
				LIMIT ' . count($approveCache), array('approve_topic_ids' => $approveCache, 'not_approved' => 0));
            $approveCache = array();
            $approveCacheMembers = array();
            while ($row = $db->fetch_assoc($request)) {
                $approveCache[] = $row['id_topic'];
                $approveCacheMembers[$row['id_topic']] = $row['id_member_started'];
            }
            $db->free_result($request);
            // Any topics to approve?
            if (!empty($approveCache)) {
                // Handle the approval part...
                approveTopics($approveCache);
                // Time for some logging!
                foreach ($approveCache as $topic) {
                    logAction('approve_topic', array('topic' => $topic, 'member' => $approveCacheMembers[$topic]));
                }
            }
        }
        // And (almost) lastly, lock the topics...
        if (!empty($lockCache)) {
            $lockStatus = array();
            // Gotta make sure they CAN lock/unlock these topics...
            if (!empty($board) && !allowedTo('lock_any')) {
                // Make sure they started the topic AND it isn't already locked by someone with higher priv's.
                $result = $db->query('', '
					SELECT id_topic, locked, id_board
					FROM {db_prefix}topics
					WHERE id_topic IN ({array_int:locked_topic_ids})
						AND id_member_started = {int:current_member}
						AND locked IN (2, 0)
					LIMIT ' . count($lockCache), array('current_member' => $user_info['id'], 'locked_topic_ids' => $lockCache));
                $lockCache = array();
                $lockCacheBoards = array();
                while ($row = $db->fetch_assoc($result)) {
                    $lockCache[] = $row['id_topic'];
                    $lockCacheBoards[$row['id_topic']] = $row['id_board'];
                    $lockStatus[$row['id_topic']] = empty($row['locked']);
                }
                $db->free_result($result);
            } else {
                $result = $db->query('', '
					SELECT id_topic, locked, id_board
					FROM {db_prefix}topics
					WHERE id_topic IN ({array_int:locked_topic_ids})
					LIMIT ' . count($lockCache), array('locked_topic_ids' => $lockCache));
                $lockCacheBoards = array();
                while ($row = $db->fetch_assoc($result)) {
                    $lockStatus[$row['id_topic']] = empty($row['locked']);
                    $lockCacheBoards[$row['id_topic']] = $row['id_board'];
                }
                $db->free_result($result);
            }
            // It could just be that *none* were their own topics...
            if (!empty($lockCache)) {
                // Alternate the locked value.
                $db->query('', '
					UPDATE {db_prefix}topics
					SET locked = CASE WHEN locked = {int:is_locked} THEN ' . (allowedTo('lock_any') ? '1' : '2') . ' ELSE 0 END
					WHERE id_topic IN ({array_int:locked_topic_ids})', array('locked_topic_ids' => $lockCache, 'is_locked' => 0));
            }
        }
        if (!empty($markCache)) {
            $logged_topics = getLoggedTopics($user_info['id'], $markCache);
            $markArray = array();
            foreach ($markCache as $topic) {
                $markArray[] = array($user_info['id'], $topic, $modSettings['maxMsgID'], (int) (!empty($logged_topics[$topic])));
            }
            markTopicsRead($markArray, true);
        }
        foreach ($moveCache as $topic) {
            // Didn't actually move anything!
            if (!isset($topic[0])) {
                break;
            }
            logAction('move', array('topic' => $topic[0], 'board_from' => $topic[1], 'board_to' => $topic[2]));
            sendNotifications($topic[0], 'move');
        }
        foreach ($lockCache as $topic) {
            logAction($lockStatus[$topic] ? 'lock' : 'unlock', array('topic' => $topic, 'board' => $lockCacheBoards[$topic]));
            sendNotifications($topic, $lockStatus[$topic] ? 'lock' : 'unlock');
        }
        foreach ($stickyCache as $topic) {
            logAction($stickyCacheStatus[$topic] ? 'unsticky' : 'sticky', array('topic' => $topic, 'board' => $stickyCacheBoards[$topic]));
            sendNotifications($topic, 'sticky');
        }
        updateStats('topic');
        updateStats('message');
        updateSettings(array('calendar_updated' => time()));
        if (!empty($affectedBoards)) {
            updateLastMessages(array_keys($affectedBoards));
        }
        redirectexit($redirect_url);
    }