Example #1
0
/**
 * Update some basic statistics.
 *
 * 'member' statistic updates the latest member, the total member
 *  count, and the number of unapproved members.
 * 'member' also only counts approved members when approval is on, but
 *  is much more efficient with it off.
 *
 * 'message' changes the total number of messages, and the
 *  highest message id by id_msg - which can be parameters 1 and 2,
 *  respectively.
 *
 * 'topic' updates the total number of topics, or if parameter1 is true
 *  simply increments them.
 *
 * 'subject' updateds the log_search_subjects in the event of a topic being
 *  moved, removed or split.  parameter1 is the topicid, parameter2 is the new subject
 *
 * 'postgroups' case updates those members who match condition's
 *  post-based membergroups in the database (restricted by parameter1).
 *
 * @param string $type Stat type - can be 'member', 'message', 'topic', 'subject' or 'postgroups'
 * @param int|string|boolean|mixed[]|null $parameter1 pass through value
 * @param int|string|boolean|mixed[]|null $parameter2 pass through value
 */
function updateStats($type, $parameter1 = null, $parameter2 = null)
{
    switch ($type) {
        case 'member':
            require_once SUBSDIR . '/Members.subs.php';
            updateMemberStats($parameter1, $parameter2);
            break;
        case 'message':
            require_once SUBSDIR . '/Messages.subs.php';
            updateMessageStats($parameter1, $parameter2);
            break;
        case 'subject':
            require_once SUBSDIR . '/Messages.subs.php';
            updateSubjectStats($parameter1, $parameter2);
            break;
        case 'topic':
            require_once SUBSDIR . '/Topic.subs.php';
            updateTopicStats($parameter1);
            break;
        case 'postgroups':
            require_once SUBSDIR . '/Membergroups.subs.php';
            updatePostGroupStats($parameter1, $parameter2);
            break;
        default:
            trigger_error('updateStats(): Invalid statistic type \'' . $type . '\'', E_USER_NOTICE);
    }
}
Example #2
0
/**
 * General function to split off a topic.
 * creates a new topic and moves the messages with the IDs in
 * array messagesToBeSplit to the new topic.
 * the subject of the newly created topic is set to 'newSubject'.
 * marks the newly created message as read for the user splitting it.
 * updates the statistics to reflect a newly created topic.
 * logs the action in the moderation log.
 * a notification is sent to all users monitoring this topic.
 *
 * @param int $split1_ID_TOPIC
 * @param int[] $splitMessages
 * @param string $new_subject
 * @return int the topic ID of the new split topic.
 */
function splitTopic($split1_ID_TOPIC, $splitMessages, $new_subject)
{
    global $txt;
    $db = database();
    // Nothing to split?
    if (empty($splitMessages)) {
        fatal_lang_error('no_posts_selected', false);
    }
    // Get some board info.
    $request = $db->query('', '
		SELECT id_board, approved
		FROM {db_prefix}topics
		WHERE id_topic = {int:id_topic}
		LIMIT 1', array('id_topic' => $split1_ID_TOPIC));
    list($id_board, $split1_approved) = $db->fetch_row($request);
    $db->free_result($request);
    // Find the new first and last not in the list. (old topic)
    $request = $db->query('', '
		SELECT
			MIN(m.id_msg) AS myid_first_msg, MAX(m.id_msg) AS myid_last_msg, COUNT(*) AS message_count, m.approved
		FROM {db_prefix}messages AS m
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:id_topic})
		WHERE m.id_msg NOT IN ({array_int:no_msg_list})
			AND m.id_topic = {int:id_topic}
		GROUP BY m.approved
		ORDER BY m.approved DESC
		LIMIT 2', array('id_topic' => $split1_ID_TOPIC, 'no_msg_list' => $splitMessages));
    // You can't select ALL the messages!
    if ($db->num_rows($request) == 0) {
        fatal_lang_error('selected_all_posts', false);
    }
    $split1_first_msg = null;
    $split1_last_msg = null;
    while ($row = $db->fetch_assoc($request)) {
        // Get the right first and last message dependant on approved state...
        if (empty($split1_first_msg) || $row['myid_first_msg'] < $split1_first_msg) {
            $split1_first_msg = $row['myid_first_msg'];
        }
        if (empty($split1_last_msg) || $row['approved']) {
            $split1_last_msg = $row['myid_last_msg'];
        }
        // Get the counts correct...
        if ($row['approved']) {
            $split1_replies = $row['message_count'] - 1;
            $split1_unapprovedposts = 0;
        } else {
            if (!isset($split1_replies)) {
                $split1_replies = 0;
            } elseif (!$split1_approved) {
                $split1_replies++;
            }
            $split1_unapprovedposts = $row['message_count'];
        }
    }
    $db->free_result($request);
    $split1_firstMem = getMsgMemberID($split1_first_msg);
    $split1_lastMem = getMsgMemberID($split1_last_msg);
    // Find the first and last in the list. (new topic)
    $request = $db->query('', '
		SELECT MIN(id_msg) AS myid_first_msg, MAX(id_msg) AS myid_last_msg, COUNT(*) AS message_count, approved
		FROM {db_prefix}messages
		WHERE id_msg IN ({array_int:msg_list})
			AND id_topic = {int:id_topic}
		GROUP BY id_topic, approved
		ORDER BY approved DESC
		LIMIT 2', array('msg_list' => $splitMessages, 'id_topic' => $split1_ID_TOPIC));
    while ($row = $db->fetch_assoc($request)) {
        // As before get the right first and last message dependant on approved state...
        if (empty($split2_first_msg) || $row['myid_first_msg'] < $split2_first_msg) {
            $split2_first_msg = $row['myid_first_msg'];
        }
        if (empty($split2_last_msg) || $row['approved']) {
            $split2_last_msg = $row['myid_last_msg'];
        }
        // Then do the counts again...
        if ($row['approved']) {
            $split2_approved = true;
            $split2_replies = $row['message_count'] - 1;
            $split2_unapprovedposts = 0;
        } else {
            // Should this one be approved??
            if ($split2_first_msg == $row['myid_first_msg']) {
                $split2_approved = false;
            }
            if (!isset($split2_replies)) {
                $split2_replies = 0;
            } elseif (!$split2_approved) {
                $split2_replies++;
            }
            $split2_unapprovedposts = $row['message_count'];
        }
    }
    $db->free_result($request);
    $split2_firstMem = getMsgMemberID($split2_first_msg);
    $split2_lastMem = getMsgMemberID($split2_last_msg);
    // No database changes yet, so let's double check to see if everything makes at least a little sense.
    if ($split1_first_msg <= 0 || $split1_last_msg <= 0 || $split2_first_msg <= 0 || $split2_last_msg <= 0 || $split1_replies < 0 || $split2_replies < 0 || $split1_unapprovedposts < 0 || $split2_unapprovedposts < 0 || !isset($split1_approved) || !isset($split2_approved)) {
        fatal_lang_error('cant_find_messages');
    }
    // You cannot split off the first message of a topic.
    if ($split1_first_msg > $split2_first_msg) {
        fatal_lang_error('split_first_post', false);
    }
    // We're off to insert the new topic!  Use 0 for now to avoid UNIQUE errors.
    $db->insert('', '{db_prefix}topics', array('id_board' => 'int', 'id_member_started' => 'int', 'id_member_updated' => 'int', 'id_first_msg' => 'int', 'id_last_msg' => 'int', 'num_replies' => 'int', 'unapproved_posts' => 'int', 'approved' => 'int', 'is_sticky' => 'int'), array((int) $id_board, $split2_firstMem, $split2_lastMem, 0, 0, $split2_replies, $split2_unapprovedposts, (int) $split2_approved, 0), array('id_topic'));
    $split2_ID_TOPIC = $db->insert_id('{db_prefix}topics', 'id_topic');
    if ($split2_ID_TOPIC <= 0) {
        fatal_lang_error('cant_insert_topic');
    }
    // Move the messages over to the other topic.
    $new_subject = strtr(Util::htmltrim(Util::htmlspecialchars($new_subject)), array("\r" => '', "\n" => '', "\t" => ''));
    // Check the subject length.
    if (Util::strlen($new_subject) > 100) {
        $new_subject = Util::substr($new_subject, 0, 100);
    }
    // Valid subject?
    if ($new_subject != '') {
        $db->query('', '
			UPDATE {db_prefix}messages
			SET
				id_topic = {int:id_topic},
				subject = CASE WHEN id_msg = {int:split_first_msg} THEN {string:new_subject} ELSE {string:new_subject_replies} END
			WHERE id_msg IN ({array_int:split_msgs})', array('split_msgs' => $splitMessages, 'id_topic' => $split2_ID_TOPIC, 'new_subject' => $new_subject, 'split_first_msg' => $split2_first_msg, 'new_subject_replies' => $txt['response_prefix'] . $new_subject));
        // Cache the new topics subject... we can do it now as all the subjects are the same!
        updateStats('subject', $split2_ID_TOPIC, $new_subject);
    }
    // Any associated reported posts better follow...
    require_once SUBSDIR . '/Topic.subs.php';
    updateSplitTopics(array('splitMessages' => $splitMessages, 'split2_ID_TOPIC' => $split2_ID_TOPIC, 'split1_replies' => $split1_replies, 'split1_first_msg' => $split1_first_msg, 'split1_last_msg' => $split1_last_msg, 'split1_firstMem' => $split1_firstMem, 'split1_lastMem' => $split1_lastMem, 'split1_unapprovedposts' => $split1_unapprovedposts, 'split1_ID_TOPIC' => $split1_ID_TOPIC, 'split2_first_msg' => $split2_first_msg, 'split2_last_msg' => $split2_last_msg, 'split2_ID_TOPIC' => $split2_ID_TOPIC, 'split2_approved' => $split2_approved), $id_board);
    require_once SUBSDIR . '/FollowUps.subs.php';
    // Let's see if we can create a stronger bridge between the two topics
    // @todo not sure what message from the oldest topic I should link to the new one, so I'll go with the first
    linkMessages($split1_first_msg, $split2_ID_TOPIC);
    // Copy log topic entries.
    // @todo This should really be chunked.
    $request = $db->query('', '
		SELECT id_member, id_msg, unwatched
		FROM {db_prefix}log_topics
		WHERE id_topic = {int:id_topic}', array('id_topic' => (int) $split1_ID_TOPIC));
    if ($db->num_rows($request) > 0) {
        $replaceEntries = array();
        while ($row = $db->fetch_assoc($request)) {
            $replaceEntries[] = array($row['id_member'], $split2_ID_TOPIC, $row['id_msg'], $row['unwatched']);
        }
        require_once SUBSDIR . '/Topic.subs.php';
        markTopicsRead($replaceEntries, false);
        unset($replaceEntries);
    }
    $db->free_result($request);
    // Housekeeping.
    updateTopicStats();
    updateLastMessages($id_board);
    logAction('split', array('topic' => $split1_ID_TOPIC, 'new_topic' => $split2_ID_TOPIC, 'board' => $id_board));
    // Notify people that this topic has been split?
    require_once SUBSDIR . '/Notification.subs.php';
    sendNotifications($split1_ID_TOPIC, 'split');
    // If there's a search index that needs updating, update it...
    require_once SUBSDIR . '/Search.subs.php';
    $searchAPI = findSearchAPI();
    if (is_callable(array($searchAPI, 'topicSplit'))) {
        $searchAPI->topicSplit($split2_ID_TOPIC, $splitMessages);
    }
    // Return the ID of the newly created topic.
    return $split2_ID_TOPIC;
}