Chris@76: array('function', 'permission')
Chris@76: $subActions = array(
Chris@76: 'editnews' => array('EditNews', 'edit_news'),
Chris@76: 'mailingmembers' => array('SelectMailingMembers', 'send_mail'),
Chris@76: 'mailingcompose' => array('ComposeMailing', 'send_mail'),
Chris@76: 'mailingsend' => array('SendMailing', 'send_mail'),
Chris@76: 'settings' => array('ModifyNewsSettings', 'admin_forum'),
Chris@76: );
Chris@76:
Chris@76: // Default to sub action 'main' or 'settings' depending on permissions.
Chris@76: $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : (allowedTo('edit_news') ? 'editnews' : (allowedTo('send_mail') ? 'mailingmembers' : 'settings'));
Chris@76:
Chris@76: // Have you got the proper permissions?
Chris@76: isAllowedTo($subActions[$_REQUEST['sa']][1]);
Chris@76:
Chris@76: // Create the tabs for the template.
Chris@76: $context[$context['admin_menu_name']]['tab_data'] = array(
Chris@76: 'title' => $txt['news_title'],
Chris@76: 'help' => 'edit_news',
Chris@76: 'description' => $txt['admin_news_desc'],
Chris@76: 'tabs' => array(
Chris@76: 'editnews' => array(
Chris@76: ),
Chris@76: 'mailingmembers' => array(
Chris@76: 'description' => $txt['news_mailing_desc'],
Chris@76: ),
Chris@76: 'settings' => array(
Chris@76: 'description' => $txt['news_settings_desc'],
Chris@76: ),
Chris@76: ),
Chris@76: );
Chris@76:
Chris@76: // Force the right area...
Chris@76: if (substr($_REQUEST['sa'], 0, 7) == 'mailing')
Chris@76: $context[$context['admin_menu_name']]['current_subsection'] = 'mailingmembers';
Chris@76:
Chris@76: $subActions[$_REQUEST['sa']][0]();
Chris@76: }
Chris@76:
Chris@76: // Let the administrator(s) edit the news.
Chris@76: function EditNews()
Chris@76: {
Chris@76: global $txt, $modSettings, $context, $sourcedir, $user_info;
Chris@76: global $smcFunc;
Chris@76:
Chris@76: require_once($sourcedir . '/Subs-Post.php');
Chris@76:
Chris@76: // The 'remove selected' button was pressed.
Chris@76: if (!empty($_POST['delete_selection']) && !empty($_POST['remove']))
Chris@76: {
Chris@76: checkSession();
Chris@76:
Chris@76: // Store the news temporarily in this array.
Chris@76: $temp_news = explode("\n", $modSettings['news']);
Chris@76:
Chris@76: // Remove the items that were selected.
Chris@76: foreach ($temp_news as $i => $news)
Chris@76: if (in_array($i, $_POST['remove']))
Chris@76: unset($temp_news[$i]);
Chris@76:
Chris@76: // Update the database.
Chris@76: updateSettings(array('news' => implode("\n", $temp_news)));
Chris@76:
Chris@76: logAction('news');
Chris@76: }
Chris@76: // The 'Save' button was pressed.
Chris@76: elseif (!empty($_POST['save_items']))
Chris@76: {
Chris@76: checkSession();
Chris@76:
Chris@76: foreach ($_POST['news'] as $i => $news)
Chris@76: {
Chris@76: if (trim($news) == '')
Chris@76: unset($_POST['news'][$i]);
Chris@76: else
Chris@76: {
Chris@76: $_POST['news'][$i] = $smcFunc['htmlspecialchars']($_POST['news'][$i], ENT_QUOTES);
Chris@76: preparsecode($_POST['news'][$i]);
Chris@76: }
Chris@76: }
Chris@76:
Chris@76: // Send the new news to the database.
Chris@76: updateSettings(array('news' => implode("\n", $_POST['news'])));
Chris@76:
Chris@76: // Log this into the moderation log.
Chris@76: logAction('news');
Chris@76: }
Chris@76:
Chris@76: // Ready the current news.
Chris@76: foreach (explode("\n", $modSettings['news']) as $id => $line)
Chris@76: $context['admin_current_news'][$id] = array(
Chris@76: 'id' => $id,
Chris@76: 'unparsed' => un_preparsecode($line),
Chris@76: 'parsed' => preg_replace('~<([/]?)form[^>]*?[>]*>~i', '<$1form>', parse_bbc($line)),
Chris@76: );
Chris@76:
Chris@76: $context['sub_template'] = 'edit_news';
Chris@76: $context['page_title'] = $txt['admin_edit_news'];
Chris@76: }
Chris@76:
Chris@76: function SelectMailingMembers()
Chris@76: {
Chris@76: global $txt, $context, $modSettings, $smcFunc;
Chris@76:
Chris@76: $context['page_title'] = $txt['admin_newsletters'];
Chris@76:
Chris@76: $context['sub_template'] = 'email_members';
Chris@76:
Chris@76: $context['groups'] = array();
Chris@76: $postGroups = array();
Chris@76: $normalGroups = array();
Chris@76:
Chris@76: // If we have post groups disabled then we need to give a "ungrouped members" option.
Chris@76: if (empty($modSettings['permission_enable_postgroups']))
Chris@76: {
Chris@76: $context['groups'][0] = array(
Chris@76: 'id' => 0,
Chris@76: 'name' => $txt['membergroups_members'],
Chris@76: 'member_count' => 0,
Chris@76: );
Chris@76: $normalGroups[0] = 0;
Chris@76: }
Chris@76:
Chris@76: // Get all the extra groups as well as Administrator and Global Moderator.
Chris@76: $request = $smcFunc['db_query']('', '
Chris@76: SELECT mg.id_group, mg.group_name, mg.min_posts
Chris@76: FROM {db_prefix}membergroups AS mg' . (empty($modSettings['permission_enable_postgroups']) ? '
Chris@76: WHERE mg.min_posts = {int:min_posts}' : '') . '
Chris@76: GROUP BY mg.id_group, mg.min_posts, mg.group_name
Chris@76: ORDER BY mg.min_posts, CASE WHEN mg.id_group < {int:newbie_group} THEN mg.id_group ELSE 4 END, mg.group_name',
Chris@76: array(
Chris@76: 'min_posts' => -1,
Chris@76: 'newbie_group' => 4,
Chris@76: )
Chris@76: );
Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76: {
Chris@76: $context['groups'][$row['id_group']] = array(
Chris@76: 'id' => $row['id_group'],
Chris@76: 'name' => $row['group_name'],
Chris@76: 'member_count' => 0,
Chris@76: );
Chris@76:
Chris@76: if ($row['min_posts'] == -1)
Chris@76: $normalGroups[$row['id_group']] = $row['id_group'];
Chris@76: else
Chris@76: $postGroups[$row['id_group']] = $row['id_group'];
Chris@76: }
Chris@76: $smcFunc['db_free_result']($request);
Chris@76:
Chris@76: // If we have post groups, let's count the number of members...
Chris@76: if (!empty($postGroups))
Chris@76: {
Chris@76: $query = $smcFunc['db_query']('', '
Chris@76: SELECT mem.id_post_group AS id_group, COUNT(*) AS member_count
Chris@76: FROM {db_prefix}members AS mem
Chris@76: WHERE mem.id_post_group IN ({array_int:post_group_list})
Chris@76: GROUP BY mem.id_post_group',
Chris@76: array(
Chris@76: 'post_group_list' => $postGroups,
Chris@76: )
Chris@76: );
Chris@76: while ($row = $smcFunc['db_fetch_assoc']($query))
Chris@76: $context['groups'][$row['id_group']]['member_count'] += $row['member_count'];
Chris@76: $smcFunc['db_free_result']($query);
Chris@76: }
Chris@76:
Chris@76: if (!empty($normalGroups))
Chris@76: {
Chris@76: // Find people who are members of this group...
Chris@76: $query = $smcFunc['db_query']('', '
Chris@76: SELECT id_group, COUNT(*) AS member_count
Chris@76: FROM {db_prefix}members
Chris@76: WHERE id_group IN ({array_int:normal_group_list})
Chris@76: GROUP BY id_group',
Chris@76: array(
Chris@76: 'normal_group_list' => $normalGroups,
Chris@76: )
Chris@76: );
Chris@76: while ($row = $smcFunc['db_fetch_assoc']($query))
Chris@76: $context['groups'][$row['id_group']]['member_count'] += $row['member_count'];
Chris@76: $smcFunc['db_free_result']($query);
Chris@76:
Chris@76: // Also do those who have it as an additional membergroup - this ones more yucky...
Chris@76: $query = $smcFunc['db_query']('', '
Chris@76: SELECT mg.id_group, COUNT(*) AS member_count
Chris@76: FROM {db_prefix}membergroups AS mg
Chris@76: INNER JOIN {db_prefix}members AS mem ON (mem.additional_groups != {string:blank_string}
Chris@76: AND mem.id_group != mg.id_group
Chris@76: AND FIND_IN_SET(mg.id_group, mem.additional_groups) != 0)
Chris@76: WHERE mg.id_group IN ({array_int:normal_group_list})
Chris@76: GROUP BY mg.id_group',
Chris@76: array(
Chris@76: 'normal_group_list' => $normalGroups,
Chris@76: 'blank_string' => '',
Chris@76: )
Chris@76: );
Chris@76: while ($row = $smcFunc['db_fetch_assoc']($query))
Chris@76: $context['groups'][$row['id_group']]['member_count'] += $row['member_count'];
Chris@76: $smcFunc['db_free_result']($query);
Chris@76: }
Chris@76:
Chris@76: // Any moderators?
Chris@76: $request = $smcFunc['db_query']('', '
Chris@76: SELECT COUNT(DISTINCT id_member) AS num_distinct_mods
Chris@76: FROM {db_prefix}moderators
Chris@76: LIMIT 1',
Chris@76: array(
Chris@76: )
Chris@76: );
Chris@76: list ($context['groups'][3]['member_count']) = $smcFunc['db_fetch_row']($request);
Chris@76: $smcFunc['db_free_result']($request);
Chris@76:
Chris@76: $context['can_send_pm'] = allowedTo('pm_send');
Chris@76: }
Chris@76:
Chris@76: // Email your members...
Chris@76: function ComposeMailing()
Chris@76: {
Chris@76: global $txt, $sourcedir, $context, $smcFunc;
Chris@76:
Chris@76: // Start by finding any members!
Chris@76: $toClean = array();
Chris@76: if (!empty($_POST['members']))
Chris@76: $toClean[] = 'members';
Chris@76: if (!empty($_POST['exclude_members']))
Chris@76: $toClean[] = 'exclude_members';
Chris@76: if (!empty($toClean))
Chris@76: {
Chris@76: require_once($sourcedir . '/Subs-Auth.php');
Chris@76: foreach ($toClean as $type)
Chris@76: {
Chris@76: // Remove the quotes.
Chris@76: $_POST[$type] = strtr($_POST[$type], array('\\"' => '"'));
Chris@76:
Chris@76: preg_match_all('~"([^"]+)"~', $_POST[$type], $matches);
Chris@76: $_POST[$type] = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $_POST[$type]))));
Chris@76:
Chris@76: foreach ($_POST[$type] as $index => $member)
Chris@76: if (strlen(trim($member)) > 0)
Chris@76: $_POST[$type][$index] = $smcFunc['htmlspecialchars']($smcFunc['strtolower'](trim($member)));
Chris@76: else
Chris@76: unset($_POST[$type][$index]);
Chris@76:
Chris@76: // Find the members
Chris@76: $_POST[$type] = implode(',', array_keys(findMembers($_POST[$type])));
Chris@76: }
Chris@76: }
Chris@76:
Chris@76: if (isset($_POST['member_list']) && is_array($_POST['member_list']))
Chris@76: {
Chris@76: $members = array();
Chris@76: foreach ($_POST['member_list'] as $member_id)
Chris@76: $members[] = (int) $member_id;
Chris@76: $_POST['members'] = implode(',', $members);
Chris@76: }
Chris@76:
Chris@76: if (isset($_POST['exclude_member_list']) && is_array($_POST['exclude_member_list']))
Chris@76: {
Chris@76: $members = array();
Chris@76: foreach ($_POST['exclude_member_list'] as $member_id)
Chris@76: $members[] = (int) $member_id;
Chris@76: $_POST['exclude_members'] = implode(',', $members);
Chris@76: }
Chris@76:
Chris@76: // Clean the other vars.
Chris@76: SendMailing(true);
Chris@76:
Chris@76: // We need a couple strings from the email template file
Chris@76: loadLanguage('EmailTemplates');
Chris@76:
Chris@76: // Get a list of all full banned users. Use their Username and email to find them. Only get the ones that can't login to turn off notification.
Chris@76: $request = $smcFunc['db_query']('', '
Chris@76: SELECT DISTINCT mem.id_member
Chris@76: FROM {db_prefix}ban_groups AS bg
Chris@76: INNER JOIN {db_prefix}ban_items AS bi ON (bg.id_ban_group = bi.id_ban_group)
Chris@76: INNER JOIN {db_prefix}members AS mem ON (bi.id_member = mem.id_member)
Chris@76: WHERE (bg.cannot_access = {int:cannot_access} OR bg.cannot_login = {int:cannot_login})
Chris@76: AND (bg.expire_time IS NULL OR bg.expire_time > {int:current_time})',
Chris@76: array(
Chris@76: 'cannot_access' => 1,
Chris@76: 'cannot_login' => 1,
Chris@76: 'current_time' => time(),
Chris@76: )
Chris@76: );
Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76: $context['recipients']['exclude_members'][] = $row['id_member'];
Chris@76: $smcFunc['db_free_result']($request);
Chris@76:
Chris@76: $request = $smcFunc['db_query']('', '
Chris@76: SELECT DISTINCT bi.email_address
Chris@76: FROM {db_prefix}ban_items AS bi
Chris@76: INNER JOIN {db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group)
Chris@76: WHERE (bg.cannot_access = {int:cannot_access} OR bg.cannot_login = {int:cannot_login})
Chris@76: AND (COALESCE(bg.expire_time, 1=1) OR bg.expire_time > {int:current_time})
Chris@76: AND bi.email_address != {string:blank_string}',
Chris@76: array(
Chris@76: 'cannot_access' => 1,
Chris@76: 'cannot_login' => 1,
Chris@76: 'current_time' => time(),
Chris@76: 'blank_string' => '',
Chris@76: )
Chris@76: );
Chris@76: $condition_array = array();
Chris@76: $condition_array_params = array();
Chris@76: $count = 0;
Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76: {
Chris@76: $condition_array[] = '{string:email_' . $count . '}';
Chris@76: $condition_array_params['email_' . $count++] = $row['email_address'];
Chris@76: }
Chris@76:
Chris@76: if (!empty($condition_array))
Chris@76: {
Chris@76: $request = $smcFunc['db_query']('', '
Chris@76: SELECT id_member
Chris@76: FROM {db_prefix}members
Chris@76: WHERE email_address IN(' . implode(', ', $condition_array) .')',
Chris@76: $condition_array_params
Chris@76: );
Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76: $context['recipients']['exclude_members'][] = $row['id_member'];
Chris@76: }
Chris@76:
Chris@76: // Did they select moderators - if so add them as specific members...
Chris@76: if ((!empty($context['recipients']['groups']) && in_array(3, $context['recipients']['groups'])) || (!empty($context['recipients']['exclude_groups']) && in_array(3, $context['recipients']['exclude_groups'])))
Chris@76: {
Chris@76: $request = $smcFunc['db_query']('', '
Chris@76: SELECT DISTINCT mem.id_member AS identifier
Chris@76: FROM {db_prefix}members AS mem
Chris@76: INNER JOIN {db_prefix}moderators AS mods ON (mods.id_member = mem.id_member)
Chris@76: WHERE mem.is_activated = {int:is_activated}',
Chris@76: array(
Chris@76: 'is_activated' => 1,
Chris@76: )
Chris@76: );
Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76: {
Chris@76: if (in_array(3, $context['recipients']))
Chris@76: $context['recipients']['exclude_members'][] = $row['identifier'];
Chris@76: else
Chris@76: $context['recipients']['members'][] = $row['identifier'];
Chris@76: }
Chris@76: $smcFunc['db_free_result']($request);
Chris@76: }
Chris@76:
Chris@76: // For progress bar!
Chris@76: $context['total_emails'] = count($context['recipients']['emails']);
Chris@76: $request = $smcFunc['db_query']('', '
Chris@76: SELECT MAX(id_member)
Chris@76: FROM {db_prefix}members',
Chris@76: array(
Chris@76: )
Chris@76: );
Chris@76: list ($context['max_id_member']) = $smcFunc['db_fetch_row']($request);
Chris@76: $smcFunc['db_free_result']($request);
Chris@76:
Chris@76: // Clean up the arrays.
Chris@76: $context['recipients']['members'] = array_unique($context['recipients']['members']);
Chris@76: $context['recipients']['exclude_members'] = array_unique($context['recipients']['exclude_members']);
Chris@76:
Chris@76: // Setup the template!
Chris@76: $context['page_title'] = $txt['admin_newsletters'];
Chris@76: $context['sub_template'] = 'email_members_compose';
Chris@76:
Chris@76: $context['default_subject'] = htmlspecialchars($context['forum_name'] . ': ' . $txt['subject']);
Chris@76: $context['default_message'] = htmlspecialchars($txt['message'] . "\n\n" . $txt['regards_team'] . "\n\n" . '{$board_url}');
Chris@76: }
Chris@76:
Chris@76: // Send out the mailing!
Chris@76: function SendMailing($clean_only = false)
Chris@76: {
Chris@76: global $txt, $sourcedir, $context, $smcFunc;
Chris@76: global $scripturl, $modSettings, $user_info;
Chris@76:
Chris@76: // How many to send at once? Quantity depends on whether we are queueing or not.
Chris@76: $num_at_once = empty($modSettings['mail_queue']) ? 60 : 1000;
Chris@76:
Chris@76: // If by PM's I suggest we half the above number.
Chris@76: if (!empty($_POST['send_pm']))
Chris@76: $num_at_once /= 2;
Chris@76:
Chris@76: checkSession();
Chris@76:
Chris@76: // Where are we actually to?
Chris@76: $context['start'] = isset($_REQUEST['start']) ? $_REQUEST['start'] : 0;
Chris@76: $context['email_force'] = !empty($_POST['email_force']) ? 1 : 0;
Chris@76: $context['send_pm'] = !empty($_POST['send_pm']) ? 1 : 0;
Chris@76: $context['total_emails'] = !empty($_POST['total_emails']) ? (int) $_POST['total_emails'] : 0;
Chris@76: $context['max_id_member'] = !empty($_POST['max_id_member']) ? (int) $_POST['max_id_member'] : 0;
Chris@76: $context['send_html'] = !empty($_POST['send_html']) ? '1' : '0';
Chris@76: $context['parse_html'] = !empty($_POST['parse_html']) ? '1' : '0';
Chris@76:
Chris@76: // Create our main context.
Chris@76: $context['recipients'] = array(
Chris@76: 'groups' => array(),
Chris@76: 'exclude_groups' => array(),
Chris@76: 'members' => array(),
Chris@76: 'exclude_members' => array(),
Chris@76: 'emails' => array(),
Chris@76: );
Chris@76:
Chris@76: // Have we any excluded members?
Chris@76: if (!empty($_POST['exclude_members']))
Chris@76: {
Chris@76: $members = explode(',', $_POST['exclude_members']);
Chris@76: foreach ($members as $member)
Chris@76: if ($member >= $context['start'])
Chris@76: $context['recipients']['exclude_members'][] = (int) $member;
Chris@76: }
Chris@76:
Chris@76: // What about members we *must* do?
Chris@76: if (!empty($_POST['members']))
Chris@76: {
Chris@76: $members = explode(',', $_POST['members']);
Chris@76: foreach ($members as $member)
Chris@76: if ($member >= $context['start'])
Chris@76: $context['recipients']['members'][] = (int) $member;
Chris@76: }
Chris@76: // Cleaning groups is simple - although deal with both checkbox and commas.
Chris@76: if (!empty($_POST['groups']))
Chris@76: {
Chris@76: if (is_array($_POST['groups']))
Chris@76: {
Chris@76: foreach ($_POST['groups'] as $group => $dummy)
Chris@76: $context['recipients']['groups'][] = (int) $group;
Chris@76: }
Chris@76: else
Chris@76: {
Chris@76: $groups = explode(',', $_POST['groups']);
Chris@76: foreach ($groups as $group)
Chris@76: $context['recipients']['groups'][] = (int) $group;
Chris@76: }
Chris@76: }
Chris@76: // Same for excluded groups
Chris@76: if (!empty($_POST['exclude_groups']))
Chris@76: {
Chris@76: if (is_array($_POST['exclude_groups']))
Chris@76: {
Chris@76: foreach ($_POST['exclude_groups'] as $group => $dummy)
Chris@76: $context['recipients']['exclude_groups'][] = (int) $group;
Chris@76: }
Chris@76: else
Chris@76: {
Chris@76: $groups = explode(',', $_POST['exclude_groups']);
Chris@76: foreach ($groups as $group)
Chris@76: $context['recipients']['exclude_groups'][] = (int) $group;
Chris@76: }
Chris@76: }
Chris@76: // Finally - emails!
Chris@76: if (!empty($_POST['emails']))
Chris@76: {
Chris@76: $addressed = array_unique(explode(';', strtr($_POST['emails'], array("\n" => ';', "\r" => ';', ',' => ';'))));
Chris@76: foreach ($addressed as $curmem)
Chris@76: {
Chris@76: $curmem = trim($curmem);
Chris@76: if ($curmem != '')
Chris@76: $context['recipients']['emails'][$curmem] = $curmem;
Chris@76: }
Chris@76: }
Chris@76:
Chris@76: // If we're only cleaning drop out here.
Chris@76: if ($clean_only)
Chris@76: return;
Chris@76:
Chris@76: require_once($sourcedir . '/Subs-Post.php');
Chris@76:
Chris@76: // Save the message and its subject in $context
Chris@76: $context['subject'] = htmlspecialchars($_POST['subject']);
Chris@76: $context['message'] = htmlspecialchars($_POST['message']);
Chris@76:
Chris@76: // Prepare the message for sending it as HTML
Chris@76: if (!$context['send_pm'] && !empty($_POST['send_html']))
Chris@76: {
Chris@76: // Prepare the message for HTML.
Chris@76: if (!empty($_POST['parse_html']))
Chris@76: $_POST['message'] = str_replace(array("\n", ' '), array('
' . "\n", ' '), $_POST['message']);
Chris@76:
Chris@76: // This is here to prevent spam filters from tagging this as spam.
Chris@76: if (preg_match('~\