예제 #1
0
 /**
  * Callback used to prepare the mention message for mentions, likes, removed likes and buddies
  *
  * @param mixed[] $mentions : Mentions retrieved from the database by getUserMentions
  * @param string $type : the type of the mention
  */
 public function prepareMentionMessage(&$mentions, $type)
 {
     global $txt, $scripturl, $context, $modSettings, $user_info;
     $boards = array();
     $removed = false;
     foreach ($mentions as $key => $row) {
         // To ensure it is not done twice
         if ($row['mention_type'] != $type) {
             continue;
         }
         // These things are associated to messages and require permission checks
         if (in_array($row['mention_type'], array('men', 'like', 'rlike'))) {
             $boards[$key] = $row['id_board'];
         }
         $mentions[$key]['message'] = str_replace(array('{msg_link}', '{msg_url}', '{subject}'), array('<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . ';mentionread;mark=read;' . $context['session_var'] . '=' . $context['session_id'] . ';item=' . $row['id_mention'] . '#msg' . $row['id_msg'] . '">' . $row['subject'] . '</a>', $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . ';mentionread;' . $context['session_var'] . '=' . $context['session_id'] . 'item=' . $row['id_mention'] . '#msg' . $row['id_msg'], $row['subject']), $txt['mention_' . $row['mention_type']]);
     }
     // Do the permissions checks and replace inappropriate messages
     if (!empty($boards)) {
         require_once SUBSDIR . '/Boards.subs.php';
         $accessibleBoards = accessibleBoards($boards);
         foreach ($boards as $key => $board) {
             // You can't see the board where this mention is, so we drop it from the results
             if (!in_array($board, $accessibleBoards)) {
                 $removed = true;
                 unset($mentions[$key]);
             }
         }
     }
     // If some of these mentions are no longer visable, we need to do some maintenance
     if ($removed) {
         if (!empty($modSettings['user_access_mentions'])) {
             $modSettings['user_access_mentions'] = @unserialize($modSettings['user_access_mentions']);
         } else {
             $modSettings['user_access_mentions'] = array();
         }
         $modSettings['user_access_mentions'][$user_info['id']] = 0;
         updateSettings(array('user_access_mentions' => serialize($modSettings['user_access_mentions'])));
         scheduleTaskImmediate('user_access_mentions');
     }
     return $removed;
 }
예제 #2
0
    /**
     * Re-syncs if a user can access a mention,
     *
     * - for example if they loose or gain access to a board, this will correct
     * the viewing of the mention table.  Since this can be a large job it is run
     * as a scheduled immediate task
     */
    public function user_access_mentions()
    {
        global $modSettings;
        $db = database();
        $user_access_mentions = @unserialize($modSettings['user_access_mentions']);
        // This should be set only because of an immediate scheduled task, so higher priority
        if (!empty($user_access_mentions)) {
            foreach ($user_access_mentions as $member => $begin) {
                // Just to stay on the safe side...
                if (empty($member)) {
                    continue;
                }
                require_once SUBSDIR . '/Boards.subs.php';
                require_once SUBSDIR . '/Mentions.subs.php';
                require_once SUBSDIR . '/Members.subs.php';
                $user_see_board = memberQuerySeeBoard($member);
                $limit = 100;
                // We need to repeat this twice: once to find the boards the user can access,
                // once for those he cannot access
                foreach (array('can', 'cannot') as $can) {
                    // Let's always start from the begin
                    $start = $begin;
                    while (true) {
                        // Find all the mentions that this user can or cannot see
                        $request = $db->query('', '
							SELECT mnt.id_mention, m.id_board
							FROM {db_prefix}log_mentions as mnt
								LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = mnt.id_msg)
								LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
							WHERE mnt.id_member = {int:current_member}
								AND mnt.mention_type IN ({array_string:mention_types})
								AND {raw:user_see_board}
							LIMIT {int:start}, {int:limit}', array('current_member' => $member, 'mention_types' => array('men', 'like', 'rlike'), 'user_see_board' => ($can == 'can' ? '' : 'NOT ') . $user_see_board, 'start' => $start, 'limit' => $limit));
                        $mentions = array();
                        $remove = array();
                        while ($row = $db->fetch_assoc($request)) {
                            if (empty($row['id_board'])) {
                                $remove[] = $row['id_mention'];
                            } else {
                                $mentions[] = $row['id_mention'];
                            }
                        }
                        $db->free_result($request);
                        if (!empty($remove)) {
                            removeMentions($remove);
                        }
                        // If we found something toggle them and increment the start for the next round
                        if (!empty($mentions)) {
                            toggleMentionsAccessibility($mentions, $can == 'can');
                        } else {
                            break;
                        }
                        // Next batch
                        $start += $limit;
                    }
                }
                // Drop the member
                unset($user_access_mentions[$member]);
                // And save everything for the next run
                updateSettings(array('user_access_mentions' => serialize($user_access_mentions)));
                // Count helps keep things correct
                countUserMentions(false, '', $member);
                // Run this only once for each user, it may be quite heavy, let's split up the load
                break;
            }
            // If there are no more users, scheduleTaskImmediate can be stopped
            if (empty($user_access_mentions)) {
                removeScheduleTaskImmediate('user_access_mentions', false);
            }
            return true;
        } else {
            // Checks 10 users at a time, the scheduled task is set to run once per hour, so 240 users a day
            // @todo <= I know you like it Spuds! :P It may be necessary to set it to something higher.
            $limit = 10;
            $current_check = !empty($modSettings['mentions_member_check']) ? $modSettings['mentions_member_check'] : 0;
            require_once SUBSDIR . '/Members.subs.php';
            require_once SUBSDIR . '/Mentions.subs.php';
            // Grab users with mentions
            $request = $db->query('', '
				SELECT COUNT(DISTINCT(id_member))
				FROM {db_prefix}log_mentions
				WHERE id_member > {int:last_id_member}
					AND mention_type IN ({array_string:mention_types})', array('last_id_member' => $current_check, 'mention_types' => array('men', 'like', 'rlike')));
            list($remaining) = $db->fetch_row($request);
            $db->free_result($request);
            if ($remaining == 0) {
                $current_check = 0;
            }
            // Grab users with mentions
            $request = $db->query('', '
				SELECT DISTINCT(id_member) as id_member
				FROM {db_prefix}log_mentions
				WHERE id_member > {int:last_id_member}
					AND mention_type IN ({array_string:mention_types})
				LIMIT {int:limit}', array('last_id_member' => $current_check, 'mention_types' => array('men', 'like', 'rlike'), 'limit' => $limit));
            // Remember where we are
            updateSettings(array('mentions_member_check' => $current_check + $limit));
            while ($row = $db->fetch_assoc($request)) {
                // Rebuild 'query_see_board', a lot of code duplication... :(
                $user_see_board = memberQuerySeeBoard($row['id_member']);
                // Find out if this user cannot see something that was supposed to be able to see
                $request2 = $db->query('', '
					SELECT mnt.id_mention
					FROM {db_prefix}log_mentions as mnt
						LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = mnt.id_msg)
						LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
					WHERE mnt.id_member = {int:current_member}
						AND mnt.mention_type IN ({array_string:mention_types})
						AND {raw:user_see_board}
						AND status < 0
					LIMIT 1', array('current_member' => $row['id_member'], 'mention_types' => array('men', 'like', 'rlike'), 'user_see_board' => 'NOT ' . $user_see_board));
                // One row of results is enough: scheduleTaskImmediate!
                if ($db->num_rows($request2) == 1) {
                    if (!empty($modSettings['user_access_mentions'])) {
                        $modSettings['user_access_mentions'] = @unserialize($modSettings['user_access_mentions']);
                    } else {
                        $modSettings['user_access_mentions'] = array();
                    }
                    // But if the member is already on the list, let's skip it
                    if (!isset($modSettings['user_access_mentions'][$row['id_member']])) {
                        $modSettings['user_access_mentions'][$row['id_member']] = 0;
                        updateSettings(array('user_access_mentions' => serialize(array_unique($modSettings['user_access_mentions']))));
                        scheduleTaskImmediate('user_access_mentions');
                    }
                }
                $db->free_result($request2);
            }
            $db->free_result($request);
            return true;
        }
    }