#!/usr/bin/perl #------------------------------------------------------------------------------ # mwForum - Web-based discussion forum # Copyright (c) 1999-2015 Markus Wichitill # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. #------------------------------------------------------------------------------ use strict; use warnings; no warnings qw(uninitialized redefine); # Imports use MwfMain; use List::Util qw(first); #------------------------------------------------------------------------------ # Init my ($m, $cfg, $lng, $user, $userId) = MwfMain->new($_[0]); # Check if user is admin $user->{admin} or $m->error('errNoAccess'); # Print header $m->printHeader(); # Get CGI parameters my $page = $m->paramInt('pg') || 1; my $search = $m->paramStr('search') || ""; my $field = $m->paramStrId('field') || $m->getVar('usrAdmFld', $userId) || 'realName'; my $sort = $m->paramStrId('sort') || $m->getVar('usrAdmSrt', $userId) || 'userName'; my $order = $m->paramStrId('order') || $m->getVar('usrAdmOrd', $userId) || 'desc'; my $hideEmpty = $m->paramDefined('search') ? $m->paramBool('hide') : $m->getVar('usrAdmHid', $userId) || 0; # Enforce valid parameters $sort = 'userName' if $sort !~ /^(?:userName|id|lastOnTime|field)\z/; $order = 'desc' if $order !~ /^(?:asc|desc)\z/; # What to search through when searching for "identity" my @identity = qw(userName realName oldNames email homepage icq lastIp comment); push @identity, grep($cfg->{$_}, qw(extra1 extra2 extra3)); # Shared formatting functions my $defTime = sub { $m->formatTime($_[0]{$field}, $m->{user}{timezone}) }; my $defUrl = sub { my $v = $_[0]{$field}; $v =~ /^https?:\/\/[^\s\\\[\]{}<>)|^`'"]+\z/ ? "$v" : $v; }; # Install case-i LIKE function for SQLite $m->{dbh}->func('LIKE', 2, sub { my $a = shift(); my $b = shift(); utf8::decode($a); utf8::decode($b); index(lc($a), lc($b)) > -1 }, 'create_function') if $m->{sqlite} && $cfg->{sqliteLike} && length($search); # Parse badges my %badges = (); if ($field eq '_badges') { for my $line (@{$cfg->{badges}}) { my ($id, $smallIcon, $bigIcon) = $line =~ /(\w+)\s+\w+\s+(\S+)\s+(\S+)/; $badges{$id} = $smallIcon ne '-' ? $smallIcon : $bigIcon; } } # Define views my $like = $m->{pgsql} ? 'ILIKE' : 'LIKE'; my $percent = $m->{sqlite} && $cfg->{sqliteLike} ? "" : "%"; my $defFields = join(", ", 'users.id', 'users.userName', $sort eq 'lastOnTime' ? 'users.lastOnTime' : ()); my $defFrom = "FROM users AS users WHERE users.id IN (:pageUserIds)"; my $defJoin = $hideEmpty ? 'INNER' : 'LEFT'; my $defGroup = $defFields; my $defSort = $sort ne 'field' ? "users.$sort" : 'users.userName'; my $searchEsc = $m->escHtml($search); my $searchLike = $m->dbEscLike($searchEsc); my $views = [ { name => " Identity", field => '_identity', notes => "no view-specific sorting; searching by username, real name, old usernames, email, " . "website, messenger, last IP, comments, and custom profile fields 1-3 when used; " . "no empty entry hiding", searchParam => $percent . $searchLike . $percent, searchUsers => sub { my $where = !length($search) ? "" : "WHERE ". join(" $like :search OR ", @identity) . " $like :search"; $m->fetchAllArray(" SELECT id FROM users AS users $where ORDER BY $defSort $order", $_[0]) }, fetchUsers => sub { $m->fetchAllHash(" SELECT $defFields, realName, email $defFrom ORDER BY $defSort $order", $_[0]) }, columns => [ { name => "Email", value => sub { "$_[0]{email}" } }, { name => "Real Name", value => sub { $_[0]{realName} } }, { name => "Old Names", value => sub { $_[0]{oldNames} } }, ], }, { name => "Bans", field => '_bans', notes => "view-specific sorting by ban time; searching by both reasons; only banned users are shown", searchParam => $percent . $searchLike . $percent, searchUsers => sub { my $where = length($search) ? "WHERE reason $like :search OR intReason $like :search" : ""; my $fldSort = $sort eq 'field' ? 'bans.banTime' : "users.$sort"; $m->fetchAllArray(" SELECT users.id FROM users AS users INNER JOIN userBans AS bans ON bans.userId = users.id $where ORDER BY $fldSort $order, users.userName", $_[0]) }, fetchUsers => sub { my $fldSort = $sort eq 'field' ? 'bans.banTime' : "users.$sort"; $m->fetchAllHash(" SELECT $defFields, bans.banTime, bans.duration, bans.reason, bans.intReason FROM users AS users INNER JOIN userBans AS bans ON bans.userId = users.id WHERE users.id IN (:pageUserIds) ORDER BY $fldSort $order, users.userName", $_[0]) }, columns => [ { name => "Ban Time", value => sub { my $v = $_[0]{banTime}; $v ? $m->formatTime($v, $m->{user}{timezone}) : "" } }, { name => "Dur.", value => sub { my $v = $_[0]{duration}; return "" if !defined($v); return "∞" if $v == 0; $v } }, { name => "Reason", value => sub { $_[0]{reason} } }, { name => "Internal", value => sub { $_[0]{intReason} } }, ], }, { name => "Badges", field => '_badges', notes => "no view-specific sorting; searching by identifier prefix", searchParam => $searchLike . $percent, searchUsers => sub { my $where = length($search) ? "WHERE userBadges.badge LIKE :search" : ""; $m->fetchAllArray(" SELECT users.id, GROUP_CONCAT(userBadges.badge) AS badges FROM users AS users $defJoin JOIN userBadges AS userBadges ON userBadges.userId = users.id $where GROUP BY $defGroup ORDER BY $defSort $order", $_[0]); }, fetchUsers => sub { $m->fetchAllHash(" SELECT users.id, users.userName, GROUP_CONCAT(userBadges.badge) AS badges FROM users AS users $defJoin JOIN userBadges AS userBadges ON userBadges.userId = users.id WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $defSort $order", $_[0]); }, columns => [ { name => "Badges", value => sub { join(" ", map("$_", sort(split(',', $_[0]{badges})))); } }, ], }, { name => "Notifications", field => '_notes', notes => "no view-specific sorting; no searching", searchUsers => sub { $m->fetchAllArray(" SELECT users.id FROM users AS users $defJoin JOIN notes AS notes ON notes.userId = users.id GROUP BY $defGroup ORDER BY $defSort $order"); }, fetchUsers => sub { $m->dbDo("SET group_concat_max_len = 32768") if $m->{mysql}; $m->fetchAllHash(" SELECT users.id, users.userName, GROUP_CONCAT('
' || notes.body || '
') AS notes FROM users AS users $defJoin JOIN notes AS notes ON notes.userId = users.id WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $defSort $order", $_[0]); }, columns => [ { name => "Notifications", value => sub { my $v = $_[0]{notes}; $v =~ s!,
!
\n
!g; $v } }, ], }, { name => "Style Snippets", field => '_snippets', notes => "no view-specific sorting; searching by identifier prefix", searchParam => $searchLike . $percent, searchUsers => sub { my $where = length($search) ? "WHERE vars.name LIKE :search" : ""; $m->fetchAllArray(" SELECT users.id FROM users AS users $defJoin JOIN userVariables AS vars ON vars.userId = users.id AND vars.name LIKE 'sty%' $where GROUP BY $defGroup ORDER BY $defSort $order", $_[0]); }, fetchUsers => sub { $m->fetchAllHash(" SELECT users.id, users.userName, GROUP_CONCAT(vars.name) AS snippets FROM users AS users $defJoin JOIN userVariables AS vars ON vars.userId = users.id AND vars.name LIKE 'sty%' WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $defSort $order", $_[0]); }, columns => [ { name => "Style Snippets", value => sub { $_[0]{snippets} } } ], }, { name => "Groups", field => '_groups', notes => "no view-specific sorting; searching by group title", searchParam => $searchLike, searchUsers => sub { my $where = length($search) ? "WHERE groups.title = :search" : ""; $m->fetchAllArray(" SELECT users.id FROM users AS users $defJoin JOIN groupMembers AS groupMembers ON groupMembers.userId = users.id $defJoin JOIN groups AS groups ON groups.id = groupMembers.groupId $where GROUP BY $defGroup ORDER BY $defSort $order", $_[0]); }, fetchUsers => sub { $m->dbDo("SET group_concat_max_len = 32768") if $m->{mysql}; $m->fetchAllHash(" SELECT users.id, users.userName, GROUP_CONCAT('#' || groups.title || '#') AS groups FROM users AS users $defJoin JOIN groupMembers AS groupMembers ON groupMembers.userId = users.id $defJoin JOIN groups AS groups ON groups.id = groupMembers.groupId WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $defSort $order", $_[0]); }, columns => [ { name => "Groups", value => sub { my $v = $_[0]{groups}; $v =~ s!#,#!, !g; $v =~ s!#!!g; $v } }, ], }, { name => "Ignored By", field => '_ignored', notes => "view-specific sorting by number of ignoring users; no searching", searchUsers => sub { my $fldSort = $sort eq 'field' ? 'ignoreNum' : "users.$sort"; $m->fetchAllArray(" SELECT users.id, COUNT(ignores.userId) AS ignoreNum FROM users AS users $defJoin JOIN userIgnores AS ignores ON ignores.ignoredId = users.id GROUP BY $defGroup ORDER BY $fldSort $order, users.userName"); }, fetchUsers => sub { my $fldSort = $sort eq 'field' ? 'ignoreNum' : "users.$sort"; $m->fetchAllHash(" SELECT users.id, users.userName, COUNT(ignores.userId) AS ignoreNum, GROUP_CONCAT(ignorers.userName) AS ignorerNames FROM users AS users $defJoin JOIN userIgnores AS ignores ON ignores.ignoredId = users.id $defJoin JOIN users AS ignorers ON ignorers.id = ignores.userId WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $fldSort $order, users.userName", $_[0]); }, columns => [ { name => "#", value => sub { $_[0]{ignoreNum} } }, { name => "Ignored By", value => sub { my $v = $_[0]{ignorerNames}; $v =~ s!,!, !g; $v } } ], }, { name => "Ignored Users", field => '_ignoring', notes => "view-specific sorting by number of ignored users; no searching", searchUsers => sub { my $fldSort = $sort eq 'field' ? 'ignoreNum' : "users.$sort"; $m->fetchAllArray(" SELECT users.id, COUNT(ignores.userId) AS ignoreNum FROM users AS users $defJoin JOIN userIgnores AS ignores ON ignores.userId = users.id GROUP BY $defGroup ORDER BY $fldSort $order, users.userName"); }, fetchUsers => sub { my $fldSort = $sort eq 'field' ? 'ignoreNum' : "users.$sort"; $m->fetchAllHash(" SELECT users.id, users.userName, COUNT(ignores.userId) AS ignoreNum, GROUP_CONCAT(ignoreds.userName) AS ignoredNames FROM users AS users $defJoin JOIN userIgnores AS ignores ON ignores.userId = users.id $defJoin JOIN users AS ignoreds ON ignoreds.id = ignores.ignoredId WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $fldSort $order, users.userName", $_[0]); }, columns => [ { name => "#", value => sub { $_[0]{ignoreNum} } }, { name => "Ignored Users", value => sub { my $v = $_[0]{ignoredNames}; $v =~ s!,!, !g; $v } } ], }, { name => "Watched By", field => '_watched', notes => "view-specific sorting by number of watching users; no searching", searchUsers => sub { my $fldSort = $sort eq 'field' ? 'watchNum' : "users.$sort"; $m->fetchAllArray(" SELECT users.id, COUNT(watches.userId) AS watchNum FROM users AS users $defJoin JOIN watchUsers AS watches ON watches.watchedId = users.id GROUP BY $defGroup ORDER BY $fldSort $order, users.userName"); }, fetchUsers => sub { my $fldSort = $sort eq 'field' ? 'watchNum' : "users.$sort"; $m->fetchAllHash(" SELECT users.id, users.userName, COUNT(watches.userId) AS watchNum, GROUP_CONCAT(watchers.userName) AS watcherNames FROM users AS users $defJoin JOIN watchUsers AS watches ON watches.watchedId = users.id $defJoin JOIN users AS watchers ON watchers.id = watches.userId WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $fldSort $order, users.userName", $_[0]); }, columns => [ { name => "#", value => sub { $_[0]{watchNum} } }, { name => "Watched By", value => sub { my $v = $_[0]{watcherNames}; $v =~ s!,!, !g; $v } } ], }, { name => "Watched Users", field => '_watching', notes => "view-specific sorting by number of watched users; no searching", searchUsers => sub { my $fldSort = $sort eq 'field' ? 'watchNum' : "users.$sort"; $m->fetchAllArray(" SELECT users.id, COUNT(watches.userId) AS watchNum FROM users AS users $defJoin JOIN watchUsers AS watches ON watches.userId = users.id GROUP BY $defGroup ORDER BY $fldSort $order, users.userName"); }, fetchUsers => sub { my $fldSort = $sort eq 'field' ? 'watchNum' : "users.$sort"; $m->fetchAllHash(" SELECT users.id, users.userName, COUNT(watches.userId) AS watchNum, GROUP_CONCAT(watched.userName) AS watchedNames FROM users AS users $defJoin JOIN watchUsers AS watches ON watches.userId = users.id $defJoin JOIN users AS watched ON watched.id = watches.watchedId WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $fldSort $order, users.userName", $_[0]); }, columns => [ { name => "#", value => sub { $_[0]{watchNum} } }, { name => "Watched Users", value => sub { my $v = $_[0]{watchedNames}; $v =~ s!,!, !g; $v } } ], }, { name => "Watched Words", field => '_words', notes => "view-specific sorting by number of watched words; no searching", searchUsers => sub { my $fldSort = $sort eq 'field' ? 'watchNum' : "users.$sort"; $m->fetchAllArray(" SELECT users.id, COUNT(watches.word) AS watchNum FROM users AS users $defJoin JOIN watchWords AS watches ON watches.userId = users.id GROUP BY $defGroup ORDER BY $fldSort $order, users.userName"); }, fetchUsers => sub { my $fldSort = $sort eq 'field' ? 'watchNum' : "users.$sort"; $m->fetchAllHash(" SELECT users.id, users.userName, COUNT(watches.word) AS watchNum, GROUP_CONCAT(watches.word) AS words FROM users AS users $defJoin JOIN watchWords AS watches ON watches.userId = users.id WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $fldSort $order, users.userName", $_[0]); }, columns => [ { name => "#", value => sub { $_[0]{watchNum} } }, { name => "Words", value => sub { my $v = $_[0]{words}; $v =~ s!,!, !g; $v } } ], }, { name => "Board Subscriptions", field => '_boardsubs', notes => "view-specific sorting by number of subscribed boards; no searching", searchUsers => sub { my $fldSort = $sort eq 'field' ? 'subsNum' : "users.$sort"; $m->fetchAllArray(" SELECT users.id, COUNT(subs.userId) AS subsNum FROM users AS users $defJoin JOIN boardSubscriptions AS subs ON subs.userId = users.id GROUP BY $defGroup ORDER BY $fldSort $order, users.userName"); }, fetchUsers => sub { $m->dbDo("SET group_concat_max_len = 32768") if $m->{mysql}; my $fldSort = $sort eq 'field' ? 'subsNum' : "users.$sort"; $m->fetchAllHash(" SELECT users.id, users.userName, COUNT(subs.userId) AS subsNum, GROUP_CONCAT(REPLACE(boards.title, ',', '')) AS title FROM users AS users $defJoin JOIN boardSubscriptions AS subs ON subs.userId = users.id $defJoin JOIN boards AS boards ON boards.id = subs.boardId WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $fldSort $order, users.userName", $_[0]); }, columns => [ { name => "#", value => sub { $_[0]{subsNum} } }, { name => "Board Subscriptions", value => sub { my $v = $_[0]{title}; $v =~ s!,!, !g; $v } } ], }, { name => "Topic Subscriptions", field => '_topicsubs', notes => "view-specific sorting by number of subscribed topics; no searching", searchUsers => sub { my $fldSort = $sort eq 'field' ? 'subsNum' : "users.$sort"; $m->fetchAllArray(" SELECT users.id, COUNT(subs.userId) AS subsNum FROM users AS users $defJoin JOIN topicSubscriptions AS subs ON subs.userId = users.id GROUP BY $defGroup ORDER BY $fldSort $order, users.userName"); }, fetchUsers => sub { $m->dbDo("SET group_concat_max_len = 32768") if $m->{mysql}; my $fldSort = $sort eq 'field' ? 'subsNum' : "users.$sort"; $m->fetchAllHash(" SELECT users.id, users.userName, COUNT(subs.userId) AS subsNum, GROUP_CONCAT(REPLACE(topics.subject, ',', '')) AS subject FROM users AS users $defJoin JOIN topicSubscriptions AS subs ON subs.userId = users.id $defJoin JOIN topics AS topics ON topics.id = subs.topicId WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $fldSort $order, users.userName", $_[0]); }, columns => [ { name => "#", value => sub { $_[0]{subsNum} } }, { name => "Topic Subscriptions", value => sub { my $v = $_[0]{subject}; $v =~ s!,!, !g; $v } } ], }, { name => "Birthdate", field => '_birthdate', notes => "no searching", searchUsers => sub { my $where = $hideEmpty ? "WHERE birthday <> ''" : ""; $m->fetchAllArray(" SELECT id FROM users AS users $where ORDER BY birthyear $order, birthday $order", $_[0]) }, fetchUsers => sub { $m->fetchAllHash(" SELECT $defFields, birthyear, birthday $defFrom ORDER BY birthyear $order, birthday $order", $_[0]) }, columns => [ { name => "Birthdate", value => sub { ($_[0]->{birthyear} ? $_[0]->{birthyear} : "0000") . "-$_[0]->{birthday}" } }, ], }, { name => "Active Time", field => '_active', notes => "no searching", searchUsers => sub { my $where = $hideEmpty ? "WHERE lastOnTime - regTime > 0" : ""; my $fldSort = $sort eq 'field' ? 'activeSeconds' : "users.$sort"; $m->fetchAllArray(" SELECT id, lastOnTime - regTime AS activeSeconds FROM users AS users $where ORDER BY $fldSort $order", $_[0]) }, fetchUsers => sub { my $fldSort = $sort eq 'field' ? 'activeSeconds' : "users.$sort"; $m->fetchAllHash(" SELECT $defFields, lastOnTime - regTime AS activeSeconds, ROUND((lastOnTime - regTime) / 86400) AS activeDays $defFrom ORDER BY $fldSort $order", $_[0]) }, columns => [ { name => "Active Time (days)", value => sub { $_[0]->{activeDays} } }, { name => "Active Time (seconds)", value => sub { $_[0]->{activeSeconds} } }, ], }, { name => "Posts Existing", field => '_postexist', notes => "no searching", searchUsers => sub { my $fldSort = $sort eq 'field' ? 'postsExist' : "users.$sort"; $m->fetchAllArray(" SELECT users.id, COUNT(posts.id) AS postsExist FROM users AS users $defJoin JOIN posts ON posts.userId = users.id GROUP BY $defGroup ORDER BY $fldSort $order", $_[0]) }, fetchUsers => sub { my $fldSort = $sort eq 'field' ? 'postsExist' : "users.$sort"; $m->fetchAllHash(" SELECT $defFields, COUNT(posts.id) AS postsExist FROM users AS users $defJoin JOIN posts AS posts ON posts.userId = users.id WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $fldSort $order", $_[0]) }, columns => [ { name => "Posts Existing", value => sub { $_[0]->{postsExist} } }, ], }, { name => "Post Upvotes", field => '_upvotes', notes => "no searching", searchUsers => sub { my $fldSort = $sort eq 'field' ? 'postLikes' : "users.$sort"; $m->fetchAllArray(" SELECT users.id, COUNT(postLikes.postId) AS postLikes FROM users AS users $defJoin JOIN posts ON posts.userId = users.id $defJoin JOIN postLikes ON postLikes.postId = posts.id GROUP BY $defGroup ORDER BY $fldSort $order", $_[0]) }, fetchUsers => sub { my $fldSort = $sort eq 'field' ? 'postLikes' : "users.$sort"; $m->fetchAllHash(" SELECT $defFields, COUNT(postLikes.postId) AS postLikes FROM users AS users $defJoin JOIN posts ON posts.userId = users.id $defJoin JOIN postLikes ON postLikes.postId = posts.id WHERE users.id IN (:pageUserIds) GROUP BY $defGroup ORDER BY $fldSort $order", $_[0]) }, columns => [ { name => "Post Upvotes", value => sub { $_[0]->{postLikes} } }, ], }, { name => "Avatar", field => 'avatar', columns => [ { name => "Avatar", value => sub { my $v = $_[0]{avatar}; return if !$v; index($v, "gravatar:") == 0 ? "" : ""; }, }, { name => "Type", value => sub { my $v = $_[0]{avatar}; return "Gravatar" if index($v, "gravatar:") == 0; return "Gallery" if index($v, "gallery/") == 0; return "Upload" if $v; }, }, ], }, { name => "Email", field => 'email', columns => [ { name => "Email", value => sub { "$_[0]{email}" } }, ], }, { name => "Registration Time", field => 'regTime', type => 'int', columns => [ { name => "Registration Time", value => $defTime } ], }, { name => "Last Online Time", field => 'lastOnTime', type => 'int', columns => [ { name => "Last Online Time", value => $defTime } ], }, { name => "Prev. Online Time", field => 'prevOnTime', type => 'int', columns => [ { name => "Prev. Online Time", value => $defTime } ], }, { name => "Website", field => 'homepage', columns => [ { name => "Website", value => $defUrl } ], }, { name => "OpenID", field => 'openId', columns => [ { name => "OpenID", value => $defUrl } ], }, { name => "Username", field => 'userName', columns => [] }, { name => "Administrator", field => 'admin', type => 'int' }, { name => "Birthyear", field => 'birthyear', type => 'int' }, { name => "Disable Email", field => 'dontEmail', type => 'int' }, { name => "Email Notifications", field => 'msgNotify', type => 'int' }, { name => "Reply Notifications", field => 'notify', type => 'int' }, { name => "Privacy", field => 'privacy', type => 'int' }, { name => "Temporary Login", field => 'tempLogin', type => 'int' }, { name => "Show Board Desc.", field => 'boardDescs', type => 'int' }, { name => "Show Decoration", field => 'showDeco', type => 'int' }, { name => "Show Avatars", field => 'showAvatars', type => 'int' }, { name => "Show Embed. Images", field => 'showImages', type => 'int' }, { name => "Show Signatures", field => 'showSigs', type => 'int' }, { name => "Collapse Branches", field => 'collapse', type => 'int' }, { name => "Font Size", field => 'fontSize', type => 'int' }, { name => "Threading Indent", field => 'indent', type => 'int' }, { name => "Posts Per Page", field => 'postsPP', type => 'int' }, { name => "Topics Per Page", field => 'topicsPP', type => 'int' }, { name => "Posts Posted", field => 'postNum', type => 'int' }, { name => "Bounce Counter", field => 'bounceNum', type => 'int' }, { name => "Policy Version", field => 'policyAccept', type => 'int' }, { name => "Renames Left", field => 'renamesLeft', type => 'int' }, { name => "Old Usernames", field => 'oldNames' }, { name => "Real Name", field => 'realName' }, { name => "Title", field => 'title' }, { name => "Occupation", field => 'occupation' }, { name => "Hobbies", field => 'hobbies' }, { name => "Location", field => 'location' }, { name => "Messenger", field => 'icq' }, { name => "Signature", field => 'signature' }, { name => "Miscellaneous", field => 'blurb' }, { name => "Custom 1", field => 'extra1' }, { name => "Custom 2", field => 'extra2' }, { name => "Custom 3", field => 'extra3' }, { name => "Birthday", field => 'birthday' }, { name => "Timezone", field => 'timezone' }, { name => "Language", field => 'language' }, { name => "Style", field => 'style' }, { name => "Font Face", field => 'fontFace' }, { name => "User Agent", field => 'userAgent' }, { name => "IP Address", field => 'lastIp' }, { name => "PGP Key ID", field => 'gpgKeyId' }, { name => "Comments", field => 'comment' }, ]; my $view = (first{ $_->{field} eq $field } @$views) || $views->[1]; $field = $view->{field}; # Save options $m->setVar('usrAdmFld', $field, $userId); $m->setVar('usrAdmSrt', $sort, $userId); $m->setVar('usrAdmOrd', $order, $userId); $m->setVar('usrAdmHid', $hideEmpty, $userId); # Searching my $searchParam = ""; my $searchStr = ""; if (length($search)) { if ($view->{searchUsers}) { $searchParam = $view->{searchParam}; } elsif ($view->{type} eq 'int') { $searchParam = int($search || 0); $searchStr = "AND $field = :search"; } else { $searchParam = $percent . $searchLike . $percent; $searchStr = "AND $field $like :search"; } } # Hiding empty fields my $hideEmptyStr = ""; if ($hideEmpty && !$view->{searchUsers}) { if ($view->{type} eq 'int') { $hideEmptyStr = "AND $field > 0" } else { $hideEmptyStr = "AND $field <> ''" } } # Ordering my $orderStr = ""; if ($sort eq 'id') { $orderStr = "users.id $order" } elsif ($sort eq 'userName') { $orderStr = "users.userName $order" } elsif ($sort eq 'lastOnTime') { $orderStr = "users.lastOnTime $order" } elsif ($sort eq 'field') { $orderStr = "users.$field $order, users.userName" } # Get ids of users my $users = $view->{searchUsers} ? $view->{searchUsers}({ search => $searchParam }) : $m->fetchAllArray(" SELECT id FROM users AS users WHERE 1 = 1 $searchStr $hideEmptyStr ORDER BY $orderStr", { search => $searchParam }); # Print page bar my $usersPP = $cfg->{usersPP} || 100; my $pageNum = int(@$users / $usersPP) + (@$users % $usersPP != 0); my @pageLinks = $pageNum < 2 ? () : $m->pageLinks('user_admin', [], $page, $pageNum); my @navLinks = ({ url => $m->url('forum_show'), txt => 'comUp', ico => 'up' }); my @adminLinks = ({ url => $m->url('user_set'), txt => "Set", ico => 'edit' }); $m->printPageBar(mainTitle => "User Administration", navLinks => \@navLinks, pageLinks => \@pageLinks, adminLinks => \@adminLinks); # Get users on page my @pageUsers = @$users[($page - 1) * $usersPP .. $m->min($page * $usersPP, scalar @$users) - 1]; my @pageUserIds = map($_->[0], @pageUsers); $users = $view->{fetchUsers} ? $view->{fetchUsers}({ pageUserIds => \@pageUserIds }) : $m->fetchAllHash(" SELECT $defFields, $field FROM users AS users WHERE id IN (:pageUserIds) ORDER BY $orderStr", { pageUserIds => \@pageUserIds }); # Determine checkbox, radiobutton and listbox states my $hideEmptyChk = $hideEmpty ? 'checked' : "", my %state = ( $sort => 'selected', $order => 'selected', "field$field" => 'selected' ); # Print user list form print "
\n", "
\n", "
List Users
\n", "
\n", "
\n", "\n", "\n", "\n", "\n", "\n", $m->submitButton("List", 'search'), "
\n", $view->{notes} ? "
View notes: $view->{notes}
" : "", "
\n", "
\n", "
\n\n"; # Print user list header my $defColumns = [ { name => $view->{name}, value => sub { $_[0]{$field} } } ]; my $columns = $view->{columns} ? $view->{columns} : $defColumns; print "\n", "\n", "\n", map("\n", @$columns), "\n"; # Print user list for my $listUser (@$users) { my $infUrl = $m->url('user_info', uid => $listUser->{id}); print "\n", "\n", map("\n", @$columns), "\n"; } print "
Username$_->{name}
$listUser->{userName}" . $_->{value}($listUser) . "
\n\n"; # Log action and finish $m->logAction(3, 'user', 'admin', $userId); $m->printFooter(); $m->finish();