News:

SMF 2.1.4 has been released! Take it for a spin! Read more.

Main Menu

Last Post On MemberList.

Started by Nathaniel, October 28, 2008, 10:02:24 AM

Previous topic - Next topic

Nathaniel

Link to Mod

Last Post On MemberList 1.03 by Nathaniel
Overview

This mod adds a "Last Post" column to the MemberList, allowing you to view the date of the last post of each of your members. It also allows you to sort the MemberList by the last post of every member, meaning that you view your members in order of when they last made a post.

SMF Version Support
This mod is officially supported for SMF 2.0 and above only. Below is a list of available versions of this mod and the previous versions of SMF that they supported. Use them at your own risk. The mod author will not be supporting or upgrading this mod in any way for versions of SMF below 2.0.

Version 1.01: SMF 1.1.x and versions of SMF 2 before SMF 2 RC2.
Version 1.02: SMF 2 RC2 and RC3.
Version 1.03: SMF 2 RC4 and RC5.

Donate
If this mod has helped you, then feel free to support the developer by Donating. Any amount of money is welcome.

Themes/Templates
This mod only edits a single template file, the 'Memberlist.template.php' file which is not used in most custom themes. If your custom theme doesn't contain this file then it should work automatically. Otherwise refer to the information below to make this mod work in your custom theme.

Default Template Install Problems:
If you want to install this mod for a custom theme (that has its own 'Memberlist.template.php' file), then find the relevant edits in this section for your version of SMF.

If you are having problem with this mod installing for the default theme with SMF 1.1.x and you are only receiving errors for the 'Memberlist.template.php edit, then you can install the mod normally and then perform the steps set out in the 'TroubleShooting' section for the default theme. Its likely that you have installed another mod which edits the same parts of that template file.

Custom theme edit for SMF 2 RC4 and above
Code ("Find (Memberlist.template.php - curve themes)") Select
               <td class="windowbg lefttext">', $member['registered_date'], '</td>
Code ("Replace") Select
                <td class="windowbg lefttext">', $member['registered_date'], '</td>
               <td class="windowbg lefttext">', $member['last_post'], '</td>


Custom theme edit for SMF 2 RC2 and SMF 2 RC3
Code ("Find (Memberlist.template.php - curve themes)") Select
               <td class="windowbg" align="', $context['right_to_left'] ? 'right' : 'left', '">', $member['registered_date'], '</td>
Code ("Replace") Select
               <td class="windowbg" align="', $context['right_to_left'] ? 'right' : 'left', '">', $member['registered_date'], '</td>
               <td class="windowbg" align="', $context['right_to_left'] ? 'right' : 'left', '">', $member['last_post'], '</td>
Code ("Find (Memberlist.template.php - core themes)") Select
               <td align="center" class="windowbg">', $member['registered_date'], '</td>
Code ("Replace") Select
               <td align="center" class="windowbg">', $member['registered_date'], '</td>
               <td align="center" class="windowbg">', $member['last_post'], '</td>


Custom theme edit for SMF 1.1.x and SMF 2 (only versions below SMF 2 RC2)
Code ("Find (Memberlist.template.php)") Select
            <td class="windowbg" align="left">', $member['registered_date'], '</td>
Code ("Replace") Select
            <td class="windowbg" align="left">', $member['registered_date'], '</td>
            <td class="windowbg" align="left">', $member['last_post'], '</td>


Custom theme edit For SMF 1.1.x only
Code ("Find all occurrences (Memberlist.template.php)") Select
colspan="12"
Code ("Replace") Select
colspan="13"

Troubleshooting (SMF 1.1.x only)
If the final edit for SMF 1.1.x failed, the one that changes the 'colspan' value, then its possible that you have already installed another mod that adds columns to this list. If that is the case, then you can try to find all cases of this code, where x is greater than 12.
colspan="x"

Replace with this code:
colspan="x+1"

So if the code was like this:
colspan="13"

You would change it to this:
colspan="14"

Remember that you will have to perform that edit four times in the 'Memberlist.template.php' file.

If you need any help with edits for custom themes, then you can ask for it in the support topic for this mod, remember that you will have to post the 'Memberlist.template.php' file from your custom theme, otherwise I will not be able to perform the edits.

Version Changes
v1.3 - 5 November 2010
Updated for SMF 2 RC4.

v1.02 - 27 May 2010
Changed package info to work with SMF 2 RC3.
Removed official support for SMF versions below SMF 2 RC2.

v1.01 - 19 November 2009
Added support for SMF 2 RC2 and curve.
Fixed a bug with the sorting. The sorting of members by last post didn't work properly.

v1.0 - 23 October 2008
Original Mod release.
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

xconnect



Nathaniel

@xconnect,
I am glad that you like it. :)

@PLAYBOY,
For the moment I don't have time to update my demo sites, to add any mods to them. I have uploaded a screenshot of what the mod looks like when its in use.
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

PLAYBOY


Ncen

#5
This is great! ^^

How could i change the "time" to look like: "Today, 08:10 PM", for examples? It's the yesterday/today part i'm having trouble with, the other i could just change with '%Y-%m-%d', no?

Also: Could i get this to work on Administrator memberlist,

And: Possibly being able to sort by it?
Like this: if (!isset($_REQUEST['sort']) || !isset($context['columns'][$_REQUEST['sort']]))
$_REQUEST['sort'] = 'last_post';


Thanks in advance,

Nathaniel

@Innocenzia,
1) Find the code below from your 'Memberlist.php' file (SMF1.1.x):
timeformat($row['posterTime'], '%Y-%m-%d')
Replace with this code:
timeformat($row['posterTime'])
2) Yes, but that would be a different mod (as it would require completly different code changes). Try asking about that in one of code related boards.
3) This field is sortable for the memberlist.

@Everyone,
I have tested this mod for SMF 1.1.7, it works so the mod page has been updated to say that it is compatible.
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

PrizeLive.com

Sorting by date does not work.
Get Paid Instantly via PayPal (or other options) at PrizeLive.com!

Nathaniel

Hmm, this mod shouldn't effect that at all.

Which version of SMF are you running?
Can you post a link to your site where its occuring? So I can see what is happening.
If you could atttach your './Sources/Memberlist.php' as an attachment to your next post, then that would be useful as well. :)
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

Morp

Could you make this compatible with 1.0.10?

Nathaniel

Quote from: Morp on July 20, 2009, 06:23:12 PM
Could you make this compatible with 1.0.10?

I have no intention of making this mod compatible with the SMF 1.0.x line, although I think you are referring to SMF 1.1.10. While I haven't tested this mod for SMF 1.1.10 it should work with it, as there weren't many changes (only security fixes I believe).
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

Morp

Quote from: Nathaniel on July 21, 2009, 02:24:38 AM
Quote from: Morp on July 20, 2009, 06:23:12 PM
Could you make this compatible with 1.0.10?

I have no intention of making this mod compatible with the SMF 1.0.x line, although I think you are referring to SMF 1.1.10. While I haven't tested this mod for SMF 1.1.10 it should work with it, as there weren't many changes (only security fixes I believe).

Yes sorry. I meant 1.1.10, was a bit tired yesterday.

Nathaniel

v1.01:
Added support for SMF 2 RC2 and curve.
Fixed a bug with the sorting. The sorting of members by last post didn't work properly.
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

kherezae

Hi,

This mod is so helpful, thanks for your time spent developing it!

I'm having trouble getting it to mesh right with the Subaccounts mod, though.  Could you help me with that?  When I click to sort by Last Post, it only shows my root admin account and any subaccounts registered, not the rest of the members.

I only encountered one error when installing the code, so I attempted to put it in manually; knowing me, this is where the error lies.  It was here:

LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:regular_id_group} THEN mem.id_post_group ELSE mem.id_group END)' : '') . ($_REQUEST['sort'] == 'last_post' ? '
LEFT JOIN {db_prefix}messages AS msg ON (msg.id_member = mem.id_member)' : '') . '
LEFT JOIN {db_prefix}subaccounts AS sub ON (sub.id_member = mem.id_member)
WHERE mem.is_activated = {int:is_activated}' . (empty($where) ? '' : '
AND ' . $where) . ($_REQUEST['sort'] == 'last_post' ? '
GROUP BY mem.id_member' : '') . '
AND sub.id_member IS NULL


In case you need the whole memberlist code:

// Show a listing of the registered members.
function Memberlist()
{
global $scripturl, $txt, $modSettings, $context, $settings, $modSettings;

// Make sure they can view the memberlist.
isAllowedTo('view_mlist');

loadTemplate('Memberlist');

$context['listing_by'] = !empty($_GET['sa']) ? $_GET['sa'] : 'all';

// $subActions array format:
// 'subaction' => array('label', 'function', 'is_selected')
$subActions = array(
'all' => array($txt['view_all_members'], 'MLAll', $context['listing_by'] == 'all'),
'search' => array($txt['mlist_search'], 'MLSearch', $context['listing_by'] == 'search'),
);

// Set up the sort links.
$context['sort_links'] = array();
foreach ($subActions as $act => $text)
$context['sort_links'][] = array(
'label' => $text[0],
'action' => $act,
'selected' => $text[2],
);

$context['num_members'] = $modSettings['totalMembers'];

// Set up the columns...
$context['columns'] = array(
'is_online' => array(
'label' => $txt['status'],
'width' => '20'
),
'real_name' => array(
'label' => $txt['username']
),
'email_address' => array(
'label' => $txt['email'],
'width' => '25'
),
'website_url' => array(
'label' => $txt['website'],
'width' => '25',
'link_with' => 'website',
),
'icq' => array(
'label' => $txt['icq'],
'width' => '25'
),
'aim' => array(
'label' => $txt['aim'],
'width' => '25'
),
'yim' => array(
'label' => $txt['yim'],
'width' => '25'
),
'msn' => array(
'label' => $txt['msn'],
'width' => '25'
),
'id_group' => array(
'label' => $txt['position']
),
'registered' => array(
'label' => $txt['date_registered']
),
// Add the last post column, for the Last Post On MemberList Mod.
'last_post' => array(
'label' => ucwords($txt['last_post'])
),
'posts' => array(
'label' => $txt['posts'],
'width' => '115',
'colspan' => '2',
'default_sort_rev' => true,
)
);

$context['colspan'] = 0;
$context['disabled_fields'] = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array();
foreach ($context['columns'] as $key => $column)
{
if (isset($context['disabled_fields'][$key]) || (isset($column['link_with']) && isset($context['disabled_fields'][$column['link_with']])))
{
unset($context['columns'][$key]);
continue;
}

$context['colspan'] += isset($column['colspan']) ? $column['colspan'] : 1;
}

$context['linktree'][] = array(
'url' => $scripturl . '?action=mlist',
'name' => $txt['members_list']
);

$context['can_send_pm'] = allowedTo('pm_send');

// Jump to the sub action.
if (isset($subActions[$context['listing_by']]))
$subActions[$context['listing_by']][1]();
else
$subActions['all'][1]();
}

// List all members, page by page.
function MLAll()
{
global $txt, $scripturl, $user_info;
global $modSettings, $context, $smcFunc;

// The chunk size for the cached index.
$cache_step_size = 500;

// Only use caching if:
// 1. there are at least 2k members,
// 2. the default sorting method (real_name) is being used,
// 3. the page shown is high enough to make a DB filesort unprofitable.
$use_cache = $modSettings['totalMembers'] > 2000 && (!isset($_REQUEST['sort']) || $_REQUEST['sort'] === 'real_name') && isset($_REQUEST['start']) && $_REQUEST['start'] > $cache_step_size;

if ($use_cache)
{
// Maybe there's something cached already.
if (!empty($modSettings['memberlist_cache']))
$memberlist_cache = @unserialize($modSettings['memberlist_cache']);

// The chunk size for the cached index.
$cache_step_size = 500;

// Only update the cache if something changed or no cache existed yet.
if (empty($memberlist_cache) || empty($modSettings['memberlist_updated']) || $memberlist_cache['last_update'] < $modSettings['memberlist_updated'])
{
$request = $smcFunc['db_query']('', '
SELECT mem.real_name
FROM {db_prefix}members AS mem
LEFT JOIN {db_prefix}subaccounts AS sub ON (sub.id_member = mem.id_member)
WHERE mem.is_activated = {int:is_activated}
AND sub.id_member IS NULL
ORDER BY real_name',
array(
'is_activated' => 1,
)
);

$memberlist_cache = array(
'last_update' => time(),
'num_members' => $smcFunc['db_num_rows']($request),
'index' => array(),
);

for ($i = 0, $n = $smcFunc['db_num_rows']($request); $i < $n; $i += $cache_step_size)
{
$smcFunc['db_data_seek']($request, $i);
list($memberlist_cache['index'][$i]) = $smcFunc['db_fetch_row']($request);
}
$smcFunc['db_data_seek']($request, $memberlist_cache['num_members'] - 1);
list($memberlist_cache['index'][$i]) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);

// Now we've got the cache...store it.
updateSettings(array('memberlist_cache' => serialize($memberlist_cache)));
}

$context['num_members'] = $memberlist_cache['num_members'];
}

// Without cache we need an extra query to get the amount of members.
else
{
$request = $smcFunc['db_query']('', '
SELECT COUNT(*)
FROM {db_prefix}members AS mem
LEFT JOIN {db_prefix}subaccounts AS sub ON (sub.id_member = mem.id_member)
WHERE mem.is_activated = {int:is_activated}
AND sub.id_member IS NULL',
array(
'is_activated' => 1,
)
);
list ($context['num_members']) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);
}

// Set defaults for sort (real_name) and start. (0)
if (!isset($_REQUEST['sort']) || !isset($context['columns'][$_REQUEST['sort']]))
$_REQUEST['sort'] = 'real_name';

if (!is_numeric($_REQUEST['start']))
{
if (preg_match('~^[^\'\\\\/]~' . ($context['utf8'] ? 'u' : ''), $smcFunc['strtolower']($_REQUEST['start']), $match) === 0)
fatal_error('Hacker?', false);

$_REQUEST['start'] = $match[0];

$request = $smcFunc['db_query']('substring', '
SELECT COUNT(*)
FROM {db_prefix}members AS mem
LEFT JOIN {db_prefix}subaccounts AS sub ON (sub.id_member = mem.id_member)
WHERE LOWER(SUBSTRING(mem.real_name, 1, 1)) < {string:first_letter}
AND mem.is_activated = {int:is_activated}
AND sub.id_member IS NULL',
array(
'is_activated' => 1,
'first_letter' => $_REQUEST['start'],
)
);
list ($_REQUEST['start']) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);
}

$context['letter_links'] = '';
for ($i = 97; $i < 123; $i++)
$context['letter_links'] .= '<a href="' . $scripturl . '?action=mlist;sa=all;start=' . chr($i) . '#letter' . chr($i) . '">' . strtoupper(chr($i)) . '</a> ';

// Sort out the column information.
foreach ($context['columns'] as $col => $column_details)
{
$context['columns'][$col]['href'] = $scripturl . '?action=mlist;sort=' . $col . ';start=0';

if ((!isset($_REQUEST['desc']) && $col == $_REQUEST['sort']) || ($col != $_REQUEST['sort'] && !empty($column_details['default_sort_rev'])))
$context['columns'][$col]['href'] .= ';desc';

$context['columns'][$col]['link'] = '<a href="' . $context['columns'][$col]['href'] . '" rel="nofollow">' . $context['columns'][$col]['label'] . '</a>';
$context['columns'][$col]['selected'] = $_REQUEST['sort'] == $col;
}

$context['sort_by'] = $_REQUEST['sort'];
$context['sort_direction'] = !isset($_REQUEST['desc']) ? 'up' : 'down';

// Construct the page index.
$context['page_index'] = constructPageIndex($scripturl . '?action=mlist;sort=' . $_REQUEST['sort'] . (isset($_REQUEST['desc']) ? ';desc' : ''), $_REQUEST['start'], $context['num_members'], $modSettings['defaultMaxMembers']);

// Send the data to the template.
$context['start'] = $_REQUEST['start'] + 1;
$context['end'] = min($_REQUEST['start'] + $modSettings['defaultMaxMembers'], $context['num_members']);

$context['can_moderate_forum'] = allowedTo('moderate_forum');
$context['page_title'] = sprintf($txt['viewing_members'], $context['start'], $context['end']);
$context['linktree'][] = array(
'url' => $scripturl . '?action=mlist;sort=' . $_REQUEST['sort'] . ';start=' . $_REQUEST['start'],
'name' => &$context['page_title'],
'extra_after' => ' (' . sprintf($txt['of_total_members'], $context['num_members']) . ')'
);

// List out the different sorting methods...
$sort_methods = array(
'is_online' => array(
'down' => '(IFNULL(lo.log_time, 1=1)' . (!allowedTo('moderate_forum') ? ' OR NOT mem.show_online' : '') . ') ASC, real_name ASC',
'up' => '(IFNULL(lo.log_time, 1=1)' . (!allowedTo('moderate_forum') ? ' OR NOT mem.show_online' : '') . ') DESC, real_name DESC'
),
'real_name' => array(
'down' => 'mem.real_name DESC',
'up' => 'mem.real_name ASC'
),
'email_address' => array(
'down' => allowedTo('moderate_forum') ? 'mem.email_address DESC' : 'mem.hide_email DESC, mem.email_address DESC',
'up' => allowedTo('moderate_forum') ? 'mem.email_address ASC' : 'mem.hide_email ASC, mem.email_address ASC'
),
'website_url' => array(
'down' => 'LENGTH(mem.website_url) > 0 ASC, IFNULL(mem.website_url, 1=1) DESC, mem.website_url DESC',
'up' => 'LENGTH(mem.website_url) > 0 DESC, IFNULL(mem.website_url, 1=1) ASC, mem.website_url ASC'
),
'icq' => array(
'down' => 'LENGTH(mem.icq) > 0 ASC, mem.icq = 0 DESC, mem.icq DESC',
'up' => 'LENGTH(mem.icq) > 0 DESC, mem.icq = 0 ASC, mem.icq ASC'
),
'aim' => array(
'down' => 'LENGTH(mem.aim) > 0 ASC, IFNULL(mem.aim, 1=1) DESC, mem.aim DESC',
'up' => 'LENGTH(mem.aim) > 0 DESC, IFNULL(mem.aim, 1=1) ASC, mem.aim ASC'
),
'yim' => array(
'down' => 'LENGTH(mem.yim) > 0 ASC, IFNULL(mem.yim, 1=1) DESC, mem.yim DESC',
'up' => 'LENGTH(mem.yim) > 0 DESC, IFNULL(mem.yim, 1=1) ASC, mem.yim ASC'
),
'msn' => array(
'down' => 'LENGTH(mem.msn) > 0 ASC, IFNULL(mem.msn, 1=1) DESC, mem.msn DESC',
'up' => 'LENGTH(mem.msn) > 0 DESC, IFNULL(mem.msn, 1=1) ASC, mem.msn ASC'
),
'registered' => array(
'down' => 'mem.date_registered DESC',
'up' => 'mem.date_registered ASC'
),
// Add the last post column, for the Last Post On MemberList Mod.
'last_post' => array(
'down' => 'ISNULL(msg.ID_MSG) DESC, MAX(msg.ID_MSG) ASC',
'up' => 'ISNULL(msg.ID_MSG) ASC, MAX(msg.ID_MSG) DESC'
),
'id_group' => array(
'down' => 'IFNULL(mg.group_name, 1=1) DESC, mg.group_name DESC',
'up' => 'IFNULL(mg.group_name, 1=1) ASC, mg.group_name ASC'
),
'posts' => array(
'down' => 'mem.posts DESC',
'up' => 'mem.posts ASC'
)
);

$limit = $_REQUEST['start'];
$query_parameters = array(
'regular_id_group' => 0,
'is_activated' => 1,
'sort' => $sort_methods[$_REQUEST['sort']][$context['sort_direction']],
);

// Using cache allows to narrow down the list to be retrieved.
if ($use_cache && $_REQUEST['sort'] === 'real_name' && !isset($_REQUEST['desc']))
{
$first_offset = $_REQUEST['start'] - ($_REQUEST['start'] % $cache_step_size);
$second_offset = ceil(($_REQUEST['start'] + $modSettings['defaultMaxMembers']) / $cache_step_size) * $cache_step_size;

$where = 'mem.real_name BETWEEN {string:real_name_low} AND {string:real_name_high}';
$query_parameters['real_name_low'] = $memberlist_cache['index'][$first_offset];
$query_parameters['real_name_high'] = $memberlist_cache['index'][$second_offset];
$limit -= $first_offset;
}

// Reverse sorting is a bit more complicated...
elseif ($use_cache && $_REQUEST['sort'] === 'real_name')
{
$first_offset = floor(($memberlist_cache['num_members'] - $modSettings['defaultMaxMembers'] - $_REQUEST['start']) / $cache_step_size) * $cache_step_size;
if ($first_offset < 0)
$first_offset = 0;
$second_offset = ceil(($memberlist_cache['num_members'] - $_REQUEST['start']) / $cache_step_size) * $cache_step_size;

$where = 'mem.real_name BETWEEN {string:real_name_low} AND {string:real_name_high}';
$query_parameters['real_name_low'] = $memberlist_cache['index'][$first_offset];
$query_parameters['real_name_high'] = $memberlist_cache['index'][$second_offset];
$limit = $second_offset - ($memberlist_cache['num_members'] - $_REQUEST['start']) - ($second_offset > $memberlist_cache['num_members'] ? $cache_step_size - ($memberlist_cache['num_members'] % $cache_step_size) : 0);
}

// Select the members from the database.
$request = $smcFunc['db_query']('', '
SELECT mem.id_member
FROM {db_prefix}members AS mem' . ($_REQUEST['sort'] === 'is_online' ? '
LEFT JOIN {db_prefix}log_online AS lo ON (lo.id_member = mem.id_member)' : '') . ($_REQUEST['sort'] === 'id_group' ? '
LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:regular_id_group} THEN mem.id_post_group ELSE mem.id_group END)' : '') . ($_REQUEST['sort'] == 'last_post' ? '
LEFT JOIN {db_prefix}messages AS msg ON (msg.id_member = mem.id_member)' : '') . '
LEFT JOIN {db_prefix}subaccounts AS sub ON (sub.id_member = mem.id_member)
WHERE mem.is_activated = {int:is_activated}' . (empty($where) ? '' : '
AND ' . $where) . ($_REQUEST['sort'] == 'last_post' ? '
GROUP BY mem.id_member' : '') . '
AND sub.id_member IS NULL
ORDER BY {raw:sort}
LIMIT ' . $limit . ', ' . $modSettings['defaultMaxMembers'],
$query_parameters
);
printMemberListRows($request);
$smcFunc['db_free_result']($request);

// Add anchors at the start of each letter.
if ($_REQUEST['sort'] == 'real_name')
{
$last_letter = '';
foreach ($context['members'] as $i => $dummy)
{
$this_letter = $smcFunc['strtolower']($smcFunc['substr']($context['members'][$i]['name'], 0, 1));

if ($this_letter != $last_letter && preg_match('~[a-z]~', $this_letter) === 1)
{
$context['members'][$i]['sort_letter'] = htmlspecialchars($this_letter);
$last_letter = $this_letter;
}
}
}
}

// Search for members...
function MLSearch()
{
global $txt, $scripturl, $context, $user_info, $modSettings, $smcFunc;

$context['page_title'] = $txt['mlist_search'];
$context['can_moderate_forum'] = allowedTo('moderate_forum');

// Can they search custom fields?
$request = $smcFunc['db_query']('', '
SELECT col_name, field_name, field_desc
FROM {db_prefix}custom_fields
WHERE active = {int:active}
' . (allowedTo('admin_forum') ? '' : ' AND private < {int:private_level}') . '
AND can_search = {int:can_search}
AND (field_type = {string:field_type_text} OR field_type = {string:field_type_textarea})',
array(
'active' => 1,
'can_search' => 1,
'private_level' => 2,
'field_type_text' => 'text',
'field_type_textarea' => 'textarea',
)
);
$context['custom_search_fields'] = array();
while ($row = $smcFunc['db_fetch_assoc']($request))
$context['custom_search_fields'][$row['col_name']] = array(
'colname' => $row['col_name'],
'name' => $row['field_name'],
'desc' => $row['field_desc'],
);
$smcFunc['db_free_result']($request);

// They're searching..
if (isset($_REQUEST['search']) && isset($_REQUEST['fields']))
{
$_POST['search'] = trim(isset($_GET['search']) ? $_GET['search'] : $_POST['search']);
$_POST['fields'] = isset($_GET['fields']) ? explode(',', $_GET['fields']) : $_POST['fields'];

$context['old_search'] = $_REQUEST['search'];
$context['old_search_value'] = urlencode($_REQUEST['search']);

// No fields?  Use default...
if (empty($_POST['fields']))
$_POST['fields'] = array('name');

$query_parameters = array(
'regular_id_group' => 0,
'is_activated' => 1,
'blank_string' => '',
'search' => '%' . strtr($smcFunc['htmlspecialchars']($_POST['search'], ENT_QUOTES), array('_' => '\\_', '%' => '\\%', '*' => '%')) . '%',
);

// Search for a name?
if (in_array('name', $_POST['fields']))
$fields = array('member_name', 'real_name');
else
$fields = array();
// Search for messengers...
if (in_array('messenger', $_POST['fields']) && (!$user_info['is_guest'] || empty($modSettings['guest_hideContacts'])))
$fields += array(3 => 'msn', 'aim', 'icq', 'yim');
// Search for websites.
if (in_array('website', $_POST['fields']))
$fields += array(7 => 'website_title', 'website_url');
// Search for groups.
if (in_array('group', $_POST['fields']))
$fields += array(9 => 'IFNULL(group_name, {string:blank_string})');
// Search for an email address?
if (in_array('email', $_POST['fields']))
{
$fields += array(2 => allowedTo('moderate_forum') ? 'email_address' : '(hide_email = 0 AND email_address');
$condition = allowedTo('moderate_forum') ? '' : ')';
}
else
$condition = '';

$customJoin = array();
$customCount = 10;
// Any custom fields to search for - these being tricky?
foreach ($_POST['fields'] as $field)
{
$curField = substr($field, 5);
if (substr($field, 0, 5) == 'cust_' && isset($context['custom_search_fields'][$curField]))
{
$customJoin[] = 'LEFT JOIN {db_prefix}themes AS t' . $curField . ' ON (t' . $curField . '.variable = {string:t' . $curField . '} AND t' . $curField . '.id_theme = 1 AND t' . $curField . '.id_member = mem.id_member)';
$query_parameters['t' . $curField] = $curField;
$fields += array($customCount++ => 'IFNULL(t' . $curField . '.value, {string:blank_string})');
}
}

$query = $_POST['search'] == '' ? '= {string:blank_string}' : 'LIKE {string:search}';

$customJoin[] = 'LEFT JOIN {db_prefix}subaccounts AS sub ON (sub.id_member = mem.id_member)';

$request = $smcFunc['db_query']('', '
SELECT COUNT(*)
FROM {db_prefix}members AS mem
LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:regular_id_group} THEN mem.id_post_group ELSE mem.id_group END)' .
(empty($customJoin) ? '' : implode('
', $customJoin)) . '
WHERE (' . implode( ' ' . $query . ' OR ', $fields) . ' ' . $query . $condition . ')
AND mem.is_activated = {int:is_activated}
AND sub.id_member IS NULL',
$query_parameters
);
list ($numResults) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);

$context['page_index'] = constructPageIndex($scripturl . '?action=mlist;sa=search;search=' . $_POST['search'] . ';fields=' . implode(',', $_POST['fields']), $_REQUEST['start'], $numResults, $modSettings['defaultMaxMembers']);

// Find the members from the database.
// !!!SLOW This query is slow.
$request = $smcFunc['db_query']('', '
SELECT mem.id_member
FROM {db_prefix}members AS mem
LEFT JOIN {db_prefix}log_online AS lo ON (lo.id_member = mem.id_member)
LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:regular_id_group} THEN mem.id_post_group ELSE mem.id_group END)' .
(empty($customJoin) ? '' : implode('
', $customJoin)) . '
WHERE (' . implode( ' ' . $query . ' OR ', $fields) . ' ' . $query . $condition . ')
AND mem.is_activated = {int:is_activated}
AND sub.id_member IS NULL
LIMIT ' . $_REQUEST['start'] . ', ' . $modSettings['defaultMaxMembers'],
$query_parameters
);
printMemberListRows($request);
$smcFunc['db_free_result']($request);
}
else
{
// These are all the possible fields.
$context['search_fields'] = array(
'name' => $txt['mlist_search_name'],
'email' => $txt['mlist_search_email'],
'messenger' => $txt['mlist_search_messenger'],
'website' => $txt['mlist_search_website'],
'group' => $txt['mlist_search_group'],
);

foreach ($context['custom_search_fields'] as $field)
$context['search_fields']['cust_' . $field['colname']] = sprintf($txt['mlist_search_by'], $field['name']);

// What do we search for by default?
$context['search_defaults'] = array('name', 'email');

$context['sub_template'] = 'search';
$context['old_search'] = isset($_GET['search']) ? $_GET['search'] : (isset($_POST['search']) ? htmlspecialchars($_POST['search']) : '');
}

$context['linktree'][] = array(
'url' => $scripturl . '?action=mlist;sa=search',
'name' => &$context['page_title']
);
}

function printMemberListRows($request)
{
global $scripturl, $txt, $user_info, $modSettings;
global $context, $settings, $memberContext, $smcFunc;

// Get the most posts.
$result = $smcFunc['db_query']('', '
SELECT MAX(posts)
FROM {db_prefix}members',
array(
)
);
list ($MOST_POSTS) = $smcFunc['db_fetch_row']($result);
$smcFunc['db_free_result']($result);

// Avoid division by zero...
if ($MOST_POSTS == 0)
$MOST_POSTS = 1;

$members = array();
while ($row = $smcFunc['db_fetch_assoc']($request))
$members[] = $row['id_member'];

// Load all the members for display.
loadMemberData($members);

// Load the last posts of the members.
$last_posts = loadMemberLastPosts($members);

$context['members'] = array();
$context['subaccount_list'] = array();
$context['subaccounts_online'] = array();
foreach ($members as $member)
{
if (!loadMemberContext($member))
continue;

$context['members'][$member] = $memberContext[$member];
$context['members'][$member]['last_post'] = $last_posts[$member];
$context['members'][$member]['post_percent'] = round(($context['members'][$member]['real_posts'] * 100) / $MOST_POSTS);
$context['members'][$member]['registered_date'] = strftime('%Y-%m-%d', $context['members'][$member]['registered_timestamp']);

if (!empty($context['members'][$member]['subaccounts']) && !empty($modSettings['subaccountsShowInMemberlist']))
{
if (!$context['members'][$member]['online']['is_online'])
$context['subaccount_list'] = array_merge($context['subaccount_list'], array_keys($context['members'][$member]['subaccounts']));
else
foreach ($context['members'][$member]['subaccounts'] as $account)
$context['subaccounts_online'][$account['id']] = $settings['images_url'] . '/useroff.gif';
}
}

if (!empty($context['subaccount_list']))
{
$request = $smcFunc['db_query']('', '
SELECT IFNULL(lo.log_time, 0) AS is_online, mem.id_member
FROM {db_prefix}members as mem
LEFT JOIN {db_prefix}log_online as lo ON (lo.id_member = mem.id_member)
WHERE mem.id_member IN ({array_int:members})',
array(
'members' => $context['subaccount_list'],
)
);
while ($row = $smcFunc['db_fetch_assoc']($request))
$context['subaccounts_online'][$row['id_member']] = $settings['images_url'] . '/' . (!empty($row['is_online']) ? 'useron' : 'useroff') . '.gif';
$smcFunc['db_free_result']($request);
}
}

// This function loads the last posts by each member passed in the $members array.
function loadMemberLastPosts($members)
{
global $smcFunc, $scripturl;

// Whoa? Please don't give us bad info. :P
if(empty($members) || !is_array($members))
return array();

// Query to make a list of the 'last post' for each member.
$result = $smcFunc['db_query']('', '
SELECT MAX(id_msg) AS id_msg
FROM {db_prefix}messages
WHERE id_member IN ({array_int:members})
GROUP BY id_member',
array(
'members' => $members,
)
);

// Make a list of the 'lastest posts' for each member
$last_posts = array();
while($row = $smcFunc['db_fetch_assoc']($result))
$last_posts[] = $row['id_msg'];

// Free the db resource.
$smcFunc['db_free_result']($result);

$return = array();
// Don't bother with the query and data formating, if we don't have any posts for these members. ;)
if(!empty($last_posts))
{
// Query to get all of the necessary data for each 'last post'.
$result = $smcFunc['db_query']('', '
SELECT id_member, id_msg, poster_time, id_topic
FROM {db_prefix}messages
WHERE ID_MSG IN ({array_int:last_posts})',
array(
'last_posts' => $last_posts,
)
);

// Setup the formating for each 'last post' field.
while($row = $smcFunc['db_fetch_assoc']($result))
$return[$row['id_member']] = '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'] . '">' . timeformat($row['poster_time'], '%Y-%m-%d') . '</a>';

// Free the db resource.
$smcFunc['db_free_result']($result);
}

// Check that every member has a last post, or put in some special text if they don't. ;)
foreach($members as $member)
{
if(!isset($return[$member]))
$return[$member] = '-';
}

return $return;
}
?>



I really appreciate any help you can offer!  Thanks!

kherezae


Nathaniel

v1.02 - 27 May 2010
Changed package info to work with SMF 2 RC3.
Removed official support for SMF versions below SMF 2 RC2.
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

Nathaniel

v1.3 - 5 November 2010
Updated for SMF 2 RC4.
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

Nathaniel

Confirmed Support for SMF 2.0 final.
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

Advertisement: