/** * Fetch some member data! * * @param string|null $query_where * @param string|string[] $query_where_params * @param string $query_limit * @param string $query_order * @param string $output_method */ function ssi_queryMembers($query_where = null, $query_where_params = array(), $query_limit = '', $query_order = 'id_member DESC', $output_method = 'echo') { global $memberContext; if ($query_where === null) { return; } require_once SUBSDIR . '/Members.subs.php'; $members_data = retrieveMemberData(array($query_where => $query_where_params, 'limit' => !empty($query_limit) ? (int) $query_limit : 10, 'order_by' => $query_order, 'activated_status' => 1)); $members = array(); foreach ($members_data['member_info'] as $row) { $members[] = $row['id']; } if (empty($members)) { return array(); } // Load the members. loadMemberData($members); // Draw the table! if ($output_method == 'echo') { echo ' <table class="ssi_table">'; } $query_members = array(); foreach ($members as $member) { // Load their context data. if (!loadMemberContext($member)) { continue; } // Store this member's information. $query_members[$member] = $memberContext[$member]; // Only do something if we're echo'ing. if ($output_method == 'echo') { echo ' <tr> <td class="centertext"> ', $query_members[$member]['link'], ' <br />', $query_members[$member]['blurb'], ' <br />', $query_members[$member]['avatar']['image'], ' </td> </tr>'; } } // End the table if appropriate. if ($output_method == 'echo') { echo ' </table>'; } // Send back the data. return $query_members; }
/** * Send the announcement in chunks. * * splits the members to be sent a topic announcement into chunks. * composes notification messages in all languages needed. * does the actual sending of the topic announcements in chunks. * calculates a rough estimate of the percentage items sent. * Accessed by action=announce;sa=send * @uses announcement template announcement_send sub template */ public function action_send() { global $topic, $board, $board_info, $context, $modSettings, $language, $scripturl; checkSession(); $context['start'] = empty($_REQUEST['start']) ? 0 : (int) $_REQUEST['start']; $groups = array_merge($board_info['groups'], array(1)); $who = array(); // Load any supplied membergroups (from announcement_send template pause loop) if (isset($_POST['membergroups'])) { $_POST['who'] = explode(',', $_POST['membergroups']); } // Check that at least one membergroup was selected (set from announce sub template) if (empty($_POST['who'])) { fatal_lang_error('no_membergroup_selected'); } // Make sure all membergroups are integers and can access the board of the announcement. foreach ($_POST['who'] as $id => $mg) { $who[$id] = in_array((int) $mg, $groups) ? (int) $mg : 0; } // Get the topic details that we are going to send require_once SUBSDIR . '/Topic.subs.php'; $topic_info = getTopicInfo($topic, 'message'); // Prepare a plain text (markdown) body for email use, does the censoring as well require_once SUBSDIR . '/Emailpost.subs.php'; pbe_prepare_text($topic_info['body'], $topic_info['subject']); // We need this in order to be able send emails. require_once SUBSDIR . '/Mail.subs.php'; require_once SUBSDIR . '/Members.subs.php'; // Select the email addresses for this batch. $conditions = array('activated_status' => 1, 'member_greater' => $context['start'], 'group_list' => $who, 'order_by' => 'id_member', 'limit' => empty($modSettings['mail_queue']) ? 25 : 500); // Have we allowed members to opt out of announcements? if (!empty($modSettings['allow_disableAnnounce'])) { $conditions['notify_announcements'] = 1; } $data = retrieveMemberData($conditions); // All members have received a mail. Go to the next screen. if (empty($data) || $data['member_count'] === 0) { logAction('announce_topic', array('topic' => $topic), 'user'); if (!empty($_REQUEST['move']) && allowedTo('move_any')) { redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback')); } elseif (!empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.new;boardseen#new', isBrowser('ie')); } else { redirectexit('board=' . $board . '.0'); } } // Loop through all members that'll receive an announcement in this batch. $announcements = array(); foreach ($data['member_info'] as $row) { $cur_language = empty($row['language']) || empty($modSettings['userLanguage']) ? $language : $row['language']; // If the language wasn't defined yet, load it and compose a notification message. if (!isset($announcements[$cur_language])) { $replacements = array('TOPICSUBJECT' => $topic_info['subject'], 'MESSAGE' => $topic_info['body'], 'TOPICLINK' => $scripturl . '?topic=' . $topic . '.0'); $emaildata = loadEmailTemplate('new_announcement', $replacements, $cur_language); $announcements[$cur_language] = array('subject' => $emaildata['subject'], 'body' => $emaildata['body'], 'recipients' => array()); } $announcements[$cur_language]['recipients'][$row['id']] = $row['email']; $context['start'] = $row['id']; } // For each language send a different mail - low priority... foreach ($announcements as $lang => $mail) { sendmail($mail['recipients'], $mail['subject'], $mail['body'], null, null, false, 5); } // Provide an overall indication of progress, this is not strictly correct if ($data['member_count'] < $conditions['limit']) { $context['percentage_done'] = 100; } else { $context['percentage_done'] = round(100 * $context['start'] / $modSettings['latestMember'], 1); } // Prepare for the template $context['move'] = empty($_REQUEST['move']) ? 0 : 1; $context['go_back'] = empty($_REQUEST['goback']) ? 0 : 1; $context['membergroups'] = implode(',', $who); $context['topic_subject'] = $topic_info['subject']; $context['sub_template'] = 'announcement_send'; // Go back to the correct language for the user ;) if (!empty($modSettings['userLanguage'])) { loadLanguage('Post'); } }
/** * This function handles the approval, rejection, activation or deletion of members. * * What it does: * - Called by ?action=admin;area=viewmembers;sa=approve. * - Requires the moderate_forum permission. * - Redirects to ?action=admin;area=viewmembers;sa=browse * with the same parameters as the calling page. */ public function action_approve() { global $scripturl, $modSettings; // First, check our session. checkSession(); require_once SUBSDIR . '/Mail.subs.php'; require_once SUBSDIR . '/Members.subs.php'; // We also need to the login languages here - for emails. loadLanguage('Login'); // Start off clean $conditions = array(); // Sort out where we are going... $current_filter = $conditions['activated_status'] = (int) $_REQUEST['orig_filter']; // If we are applying a filter do just that - then redirect. if (isset($_REQUEST['filter']) && $_REQUEST['filter'] != $_REQUEST['orig_filter']) { redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $_REQUEST['filter'] . ';start=' . $_REQUEST['start']); } // Nothing to do? if (!isset($_POST['todoAction']) && !isset($_POST['time_passed'])) { redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); } // Are we dealing with members who have been waiting for > set amount of time? if (isset($_POST['time_passed'])) { $conditions['time_before'] = time() - 86400 * (int) $_POST['time_passed']; } else { $conditions['members'] = array(); foreach ($_POST['todoAction'] as $id) { $conditions['members'][] = (int) $id; } } $data = retrieveMemberData($conditions); if ($data['member_count'] == 0) { redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); } $member_info = $data['member_info']; $conditions['members'] = $data['members']; // Are we activating or approving the members? if ($_POST['todo'] == 'ok' || $_POST['todo'] == 'okemail') { // Approve / activate this member. approveMembers($conditions); // Check for email. if ($_POST['todo'] == 'okemail') { foreach ($member_info as $member) { $replacements = array('NAME' => $member['name'], 'USERNAME' => $member['username'], 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member['id'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder'); $emaildata = loadEmailTemplate('admin_approve_accept', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } } // Update the menu action cache so its forced to refresh cache_put_data('num_menu_errors', null, 900); } elseif ($_POST['todo'] == 'require_activation') { require_once SUBSDIR . '/Auth.subs.php'; // We have to do this for each member I'm afraid. foreach ($member_info as $member) { $conditions['selected_member'] = $member['id']; // Generate a random activation code. $conditions['validation_code'] = generateValidationCode(); // Set these members for activation - I know this includes two id_member checks but it's safer than bodging $condition ;). enforceReactivation($conditions); $replacements = array('USERNAME' => $member['name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $conditions['validation_code'], 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], 'ACTIVATIONCODE' => $conditions['validation_code']); $emaildata = loadEmailTemplate('admin_approve_activation', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } } elseif ($_POST['todo'] == 'reject' || $_POST['todo'] == 'rejectemail') { deleteMembers($conditions['members']); // Send email telling them they aren't welcome? if ($_POST['todo'] == 'rejectemail') { foreach ($member_info as $member) { $replacements = array('USERNAME' => $member['name']); $emaildata = loadEmailTemplate('admin_approve_reject', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } } elseif ($_POST['todo'] == 'delete' || $_POST['todo'] == 'deleteemail') { deleteMembers($conditions['members']); // Send email telling them they aren't welcome? if ($_POST['todo'] == 'deleteemail') { foreach ($member_info as $member) { $replacements = array('USERNAME' => $member['name']); $emaildata = loadEmailTemplate('admin_approve_delete', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } } elseif ($_POST['todo'] == 'remind') { foreach ($member_info as $member) { $replacements = array('USERNAME' => $member['name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $member['code'], 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], 'ACTIVATIONCODE' => $member['code']); $emaildata = loadEmailTemplate('admin_approve_remind', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } // Log what we did? if (!empty($modSettings['modlog_enabled']) && in_array($_POST['todo'], array('ok', 'okemail', 'require_activation', 'remind'))) { $log_action = $_POST['todo'] == 'remind' ? 'remind_member' : 'approve_member'; foreach ($member_info as $member) { logAction($log_action, array('member' => $member['id']), 'admin'); } } // Although updateStats *may* catch this, best to do it manually just in case (Doesn't always sort out unapprovedMembers). if (in_array($current_filter, array(3, 4))) { updateSettings(array('unapprovedMembers' => $modSettings['unapprovedMembers'] > $data['member_count'] ? $modSettings['unapprovedMembers'] - $data['member_count'] : 0)); } // Update the member's stats. (but, we know the member didn't change their name.) updateStats('member', false); // If they haven't been deleted, update the post group statistics on them... if (!in_array($_POST['todo'], array('delete', 'deleteemail', 'reject', 'rejectemail', 'remind'))) { updateStats('postgroups', $conditions['members']); } redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); }
/** * Activate members * * @package Members * @param mixed[] $conditions associative array holding the conditions for the WHERE clause of the query. * Possible keys: * - activated_status (boolen) must be present * - time_before (integer) * - members (array of integers) */ function approveMembers($conditions) { $db = database(); // This shall be present assert(isset($conditions['activated_status'])); $available_conditions = array('time_before' => ' AND date_registered < {int:time_before}', 'members' => ' AND id_member IN ({array_int:members})'); // @todo maybe an hook here? $query_cond = array(); $query = false; foreach ($conditions as $key => $dummy) { if (isset($available_conditions[$key])) { if ($key === 'time_before') { $query = true; } $query_cond[] = $available_conditions[$key]; } } if ($query) { $data = retrieveMemberData($conditions); $members_id = $data['members']; } else { $members_id = $conditions['members']; } $conditions['is_activated'] = $conditions['activated_status'] >= 10 ? 11 : 1; $conditions['blank_string'] = ''; // Approve/activate this member. $db->query('', ' UPDATE {db_prefix}members SET validation_code = {string:blank_string}, is_activated = {int:is_activated} WHERE is_activated = {int:activated_status}' . implode('', $query_cond), $conditions); // Let the integration know that they've been activated! foreach ($members_id as $member_id) { call_integration_hook('integrate_activate', array($member_id, $conditions['activated_status'], $conditions['is_activated'])); } return $conditions['is_activated']; }