PageRenderTime 51ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/sources/admin/Modlog.php

https://github.com/Arantor/Elkarte
PHP | 631 lines | 484 code | 60 blank | 87 comment | 93 complexity | 4ca84da3ab1d460605a2c5f58854d2a3 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0
  1. <?php
  2. /**
  3. * @name ElkArte Forum
  4. * @copyright ElkArte Forum contributors
  5. * @license BSD http://opensource.org/licenses/BSD-3-Clause
  6. *
  7. * This software is a derived product, based on:
  8. *
  9. * Simple Machines Forum (SMF)
  10. * copyright: 2011 Simple Machines (http://www.simplemachines.org)
  11. * license: BSD, See included LICENSE.TXT for terms and conditions.
  12. *
  13. * @version 1.0 Alpha
  14. *
  15. * The moderation log is this file's only job.
  16. * It views it, and that's about all it does.
  17. *
  18. */
  19. if (!defined('ELKARTE'))
  20. die('No access...');
  21. /**
  22. * Prepares the information from the moderation log for viewing.
  23. * Show the moderation log, or admin log...
  24. * Disallows the deletion of events within twenty-four hours of now.
  25. * Requires the admin_forum permission for admin log.
  26. * Accessed via ?action=moderate;area=modlog.
  27. *
  28. * @uses Modlog template, main sub-template.
  29. */
  30. function action_modlog()
  31. {
  32. global $txt, $modSettings, $context, $scripturl, $user_info, $smcFunc, $settings;
  33. // Are we looking at the moderation log or the administration log.
  34. $context['log_type'] = isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'adminlog' ? 3 : 1;
  35. if ($context['log_type'] == 3)
  36. isAllowedTo('admin_forum');
  37. // These change dependant on whether we are viewing the moderation or admin log.
  38. if ($context['log_type'] == 3 || $_REQUEST['action'] == 'admin')
  39. $context['url_start'] = '?action=admin;area=logs;sa=' . ($context['log_type'] == 3 ? 'adminlog' : 'modlog') . ';type=' . $context['log_type'];
  40. else
  41. $context['url_start'] = '?action=moderate;area=modlog;type=' . $context['log_type'];
  42. $context['can_delete'] = allowedTo('admin_forum');
  43. loadLanguage('Modlog');
  44. $context['page_title'] = $context['log_type'] == 3 ? $txt['modlog_admin_log'] : $txt['modlog_view'];
  45. // The number of entries to show per page of log file.
  46. $context['displaypage'] = 30;
  47. // Amount of hours that must pass before allowed to delete file.
  48. $context['hoursdisable'] = 24;
  49. // Handle deletion...
  50. if (isset($_POST['removeall']) && $context['can_delete'])
  51. {
  52. checkSession();
  53. validateToken('mod-ml');
  54. $smcFunc['db_query']('', '
  55. DELETE FROM {db_prefix}log_actions
  56. WHERE id_log = {int:moderate_log}
  57. AND log_time < {int:twenty_four_hours_wait}',
  58. array(
  59. 'twenty_four_hours_wait' => time() - $context['hoursdisable'] * 3600,
  60. 'moderate_log' => $context['log_type'],
  61. )
  62. );
  63. }
  64. elseif (!empty($_POST['remove']) && isset($_POST['delete']) && $context['can_delete'])
  65. {
  66. checkSession();
  67. validateToken('mod-ml');
  68. $smcFunc['db_query']('', '
  69. DELETE FROM {db_prefix}log_actions
  70. WHERE id_log = {int:moderate_log}
  71. AND id_action IN ({array_string:delete_actions})
  72. AND log_time < {int:twenty_four_hours_wait}',
  73. array(
  74. 'twenty_four_hours_wait' => time() - $context['hoursdisable'] * 3600,
  75. 'delete_actions' => array_unique($_POST['delete']),
  76. 'moderate_log' => $context['log_type'],
  77. )
  78. );
  79. }
  80. // Do the column stuff!
  81. $sort_types = array(
  82. 'action' =>'lm.action',
  83. 'time' => 'lm.log_time',
  84. 'member' => 'mem.real_name',
  85. 'group' => 'mg.group_name',
  86. 'ip' => 'lm.ip',
  87. );
  88. // Setup the direction stuff...
  89. $context['order'] = isset($_REQUEST['sort']) && isset($sort_types[$_REQUEST['sort']]) ? $_REQUEST['sort'] : 'time';
  90. // If we're coming from a search, get the variables.
  91. if (!empty($_REQUEST['params']) && empty($_REQUEST['is_search']))
  92. {
  93. $search_params = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));
  94. $search_params = @unserialize($search_params);
  95. }
  96. // This array houses all the valid search types.
  97. $searchTypes = array(
  98. 'action' => array('sql' => 'lm.action', 'label' => $txt['modlog_action']),
  99. 'member' => array('sql' => 'mem.real_name', 'label' => $txt['modlog_member']),
  100. 'group' => array('sql' => 'mg.group_name', 'label' => $txt['modlog_position']),
  101. 'ip' => array('sql' => 'lm.ip', 'label' => $txt['modlog_ip'])
  102. );
  103. if (!isset($search_params['string']) || (!empty($_REQUEST['search']) && $search_params['string'] != $_REQUEST['search']))
  104. $search_params_string = empty($_REQUEST['search']) ? '' : $_REQUEST['search'];
  105. else
  106. $search_params_string = $search_params['string'];
  107. if (isset($_REQUEST['search_type']) || empty($search_params['type']) || !isset($searchTypes[$search_params['type']]))
  108. $search_params_type = isset($_REQUEST['search_type']) && isset($searchTypes[$_REQUEST['search_type']]) ? $_REQUEST['search_type'] : (isset($searchTypes[$context['order']]) ? $context['order'] : 'member');
  109. else
  110. $search_params_type = $search_params['type'];
  111. $search_params_column = $searchTypes[$search_params_type]['sql'];
  112. $search_params = array(
  113. 'string' => $search_params_string,
  114. 'type' => $search_params_type,
  115. );
  116. // Setup the search context.
  117. $context['search_params'] = empty($search_params['string']) ? '' : base64_encode(serialize($search_params));
  118. $context['search'] = array(
  119. 'string' => $search_params['string'],
  120. 'type' => $search_params['type'],
  121. 'label' => $searchTypes[$search_params_type]['label'],
  122. );
  123. // If they are searching by action, then we must do some manual intervention to search in their language!
  124. if ($search_params['type'] == 'action' && !empty($search_params['string']))
  125. {
  126. // For the moment they can only search for ONE action!
  127. foreach ($txt as $key => $text)
  128. {
  129. if (substr($key, 0, 10) == 'modlog_ac_' && strpos($text, $search_params['string']) !== false)
  130. {
  131. $search_params['string'] = substr($key, 10);
  132. break;
  133. }
  134. }
  135. }
  136. require_once(SUBSDIR . '/List.subs.php');
  137. // This is all the information required for a watched user listing.
  138. $listOptions = array(
  139. 'id' => 'moderation_log_list',
  140. 'width' => '100%',
  141. 'items_per_page' => $context['displaypage'],
  142. 'no_items_label' => $txt['modlog_' . ($context['log_type'] == 3 ? 'admin_log_' : '') . 'no_entries_found'],
  143. 'base_href' => $scripturl . $context['url_start'] . (!empty($context['search_params']) ? ';params=' . $context['search_params'] : ''),
  144. 'default_sort_col' => 'time',
  145. 'get_items' => array(
  146. 'function' => 'list_getModLogEntries',
  147. 'params' => array(
  148. (!empty($search_params['string']) ? ' INSTR({raw:sql_type}, {string:search_string})' : ''),
  149. array('sql_type' => $search_params_column, 'search_string' => $search_params['string']),
  150. $context['log_type'],
  151. ),
  152. ),
  153. 'get_count' => array(
  154. 'function' => 'list_getModLogEntryCount',
  155. 'params' => array(
  156. (!empty($search_params['string']) ? ' INSTR({raw:sql_type}, {string:search_string})' : ''),
  157. array('sql_type' => $search_params_column, 'search_string' => $search_params['string']),
  158. $context['log_type'],
  159. ),
  160. ),
  161. // This assumes we are viewing by user.
  162. 'columns' => array(
  163. 'action' => array(
  164. 'header' => array(
  165. 'value' => $txt['modlog_action'],
  166. 'class' => 'lefttext first_th',
  167. ),
  168. 'data' => array(
  169. 'db' => 'action_text',
  170. 'class' => 'smalltext',
  171. ),
  172. 'sort' => array(
  173. 'default' => 'lm.action',
  174. 'reverse' => 'lm.action DESC',
  175. ),
  176. ),
  177. 'time' => array(
  178. 'header' => array(
  179. 'value' => $txt['modlog_date'],
  180. 'class' => 'lefttext',
  181. ),
  182. 'data' => array(
  183. 'db' => 'time',
  184. 'class' => 'smalltext',
  185. ),
  186. 'sort' => array(
  187. 'default' => 'lm.log_time DESC',
  188. 'reverse' => 'lm.log_time',
  189. ),
  190. ),
  191. 'moderator' => array(
  192. 'header' => array(
  193. 'value' => $txt['modlog_member'],
  194. 'class' => 'lefttext',
  195. ),
  196. 'data' => array(
  197. 'db' => 'moderator_link',
  198. 'class' => 'smalltext',
  199. ),
  200. 'sort' => array(
  201. 'default' => 'mem.real_name',
  202. 'reverse' => 'mem.real_name DESC',
  203. ),
  204. ),
  205. 'position' => array(
  206. 'header' => array(
  207. 'value' => $txt['modlog_position'],
  208. 'class' => 'lefttext',
  209. ),
  210. 'data' => array(
  211. 'db' => 'position',
  212. 'class' => 'smalltext',
  213. ),
  214. 'sort' => array(
  215. 'default' => 'mg.group_name',
  216. 'reverse' => 'mg.group_name DESC',
  217. ),
  218. ),
  219. 'ip' => array(
  220. 'header' => array(
  221. 'value' => $txt['modlog_ip'],
  222. 'class' => 'lefttext',
  223. ),
  224. 'data' => array(
  225. 'db' => 'ip',
  226. 'class' => 'smalltext',
  227. ),
  228. 'sort' => array(
  229. 'default' => 'lm.ip',
  230. 'reverse' => 'lm.ip DESC',
  231. ),
  232. ),
  233. 'delete' => array(
  234. 'header' => array(
  235. 'value' => '<input type="checkbox" name="all" class="input_check" onclick="invertAll(this, this.form);" />',
  236. 'class' => 'centercol',
  237. ),
  238. 'data' => array(
  239. 'function' => create_function('$entry', '
  240. return \'<input type="checkbox" class="input_check" name="delete[]" value="\' . $entry[\'id\'] . \'"\' . ($entry[\'editable\'] ? \'\' : \' disabled="disabled"\') . \' />\';
  241. '),
  242. 'class' => 'centercol',
  243. ),
  244. ),
  245. ),
  246. 'form' => array(
  247. 'href' => $scripturl . $context['url_start'],
  248. 'include_sort' => true,
  249. 'include_start' => true,
  250. 'hidden_fields' => array(
  251. $context['session_var'] => $context['session_id'],
  252. 'params' => $context['search_params']
  253. ),
  254. 'token' => 'mod-ml',
  255. ),
  256. 'additional_rows' => array(
  257. array(
  258. 'position' => 'below_table_data',
  259. 'value' => '
  260. ' . $txt['modlog_search'] . ' (' . $txt['modlog_by'] . ': ' . $context['search']['label'] . '):
  261. <input type="text" name="search" size="18" value="' . $smcFunc['htmlspecialchars']($context['search']['string']) . '" class="input_text" />
  262. <input type="submit" name="is_search" value="' . $txt['modlog_go'] . '" class="button_submit" style="float:none" />
  263. ' . ($context['can_delete'] ? '&nbsp;|
  264. <input type="submit" name="remove" value="' . $txt['modlog_remove'] . '" onclick="return confirm(\'' . $txt['modlog_remove_selected_confirm'] . '\');" class="button_submit" />
  265. <input type="submit" name="removeall" value="' . $txt['modlog_removeall'] . '" onclick="return confirm(\'' . $txt['modlog_remove_all_confirm'] . '\');" class="button_submit" />' : ''),
  266. 'class' => 'floatright',
  267. ),
  268. ),
  269. );
  270. createToken('mod-ml');
  271. // Create the watched user list.
  272. createList($listOptions);
  273. $context['sub_template'] = 'show_list';
  274. $context['default_list'] = 'moderation_log_list';
  275. $context[$context['moderation_menu_name']]['tab_data'] = array(
  276. 'title' => $txt['modlog_' . ($context['log_type'] == 3 ? 'admin' : 'moderation') . '_log'],
  277. 'help' => $context['log_type'] == 3 ? 'adminlog' : 'modlog',
  278. 'description' => $txt['modlog_' . ($context['log_type'] == 3 ? 'admin' : 'moderation') . '_log_desc']
  279. );
  280. }
  281. /**
  282. * Get the number of mod log entries.
  283. * Callback for createList() in action_modlog().
  284. *
  285. * @param $query_string
  286. * @param $query_params
  287. * @param $log_type
  288. */
  289. function list_getModLogEntryCount($query_string = '', $query_params = array(), $log_type = 1)
  290. {
  291. global $smcFunc, $user_info;
  292. $modlog_query = allowedTo('admin_forum') || $user_info['mod_cache']['bq'] == '1=1' ? '1=1' : ($user_info['mod_cache']['bq'] == '0=1' ? 'lm.id_board = 0 AND lm.id_topic = 0' : (strtr($user_info['mod_cache']['bq'], array('id_board' => 'b.id_board')) . ' AND ' . strtr($user_info['mod_cache']['bq'], array('id_board' => 't.id_board'))));
  293. $result = $smcFunc['db_query']('', '
  294. SELECT COUNT(*)
  295. FROM {db_prefix}log_actions AS lm
  296. LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lm.id_member)
  297. LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_group_id} THEN mem.id_post_group ELSE mem.id_group END)
  298. LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lm.id_board)
  299. LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lm.id_topic)
  300. WHERE id_log = {int:log_type}
  301. AND {raw:modlog_query}'
  302. . (!empty($query_string) ? '
  303. AND ' . $query_string : ''),
  304. array_merge($query_params, array(
  305. 'reg_group_id' => 0,
  306. 'log_type' => $log_type,
  307. 'modlog_query' => $modlog_query,
  308. ))
  309. );
  310. list ($entry_count) = $smcFunc['db_fetch_row']($result);
  311. $smcFunc['db_free_result']($result);
  312. return $entry_count;
  313. }
  314. /**
  315. * Gets the moderation log entries that match the specified parameters.
  316. * Callback for createList() in action_modlog().
  317. *
  318. * @param $start
  319. * @param $items_per_page
  320. * @param $sort
  321. * @param $query_string
  322. * @param $query_params
  323. * @param $log_type
  324. */
  325. function list_getModLogEntries($start, $items_per_page, $sort, $query_string = '', $query_params = array(), $log_type = 1)
  326. {
  327. global $context, $scripturl, $txt, $smcFunc, $user_info;
  328. $modlog_query = allowedTo('admin_forum') || $user_info['mod_cache']['bq'] == '1=1' ? '1=1' : ($user_info['mod_cache']['bq'] == '0=1' ? 'lm.id_board = 0 AND lm.id_topic = 0' : (strtr($user_info['mod_cache']['bq'], array('id_board' => 'b.id_board')) . ' AND ' . strtr($user_info['mod_cache']['bq'], array('id_board' => 't.id_board'))));
  329. // Do a little bit of self protection.
  330. if (!isset($context['hoursdisable']))
  331. $context['hoursdisable'] = 24;
  332. // Can they see the IP address?
  333. $seeIP = allowedTo('moderate_forum');
  334. // Here we have the query getting the log details.
  335. $result = $smcFunc['db_query']('', '
  336. SELECT
  337. lm.id_action, lm.id_member, lm.ip, lm.log_time, lm.action, lm.id_board, lm.id_topic, lm.id_msg, lm.extra,
  338. mem.real_name, mg.group_name
  339. FROM {db_prefix}log_actions AS lm
  340. LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lm.id_member)
  341. LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_group_id} THEN mem.id_post_group ELSE mem.id_group END)
  342. LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lm.id_board)
  343. LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lm.id_topic)
  344. WHERE id_log = {int:log_type}
  345. AND {raw:modlog_query}'
  346. . (!empty($query_string) ? '
  347. AND ' . $query_string : '') . '
  348. ORDER BY ' . $sort . '
  349. LIMIT ' . $start . ', ' . $items_per_page,
  350. array_merge($query_params, array(
  351. 'reg_group_id' => 0,
  352. 'log_type' => $log_type,
  353. 'modlog_query' => $modlog_query,
  354. ))
  355. );
  356. // Arrays for decoding objects into.
  357. $topics = array();
  358. $boards = array();
  359. $members = array();
  360. $messages = array();
  361. $entries = array();
  362. while ($row = $smcFunc['db_fetch_assoc']($result))
  363. {
  364. $row['extra'] = @unserialize($row['extra']);
  365. // Corrupt?
  366. $row['extra'] = is_array($row['extra']) ? $row['extra'] : array();
  367. // Add on some of the column stuff info
  368. if (!empty($row['id_board']))
  369. {
  370. if ($row['action'] == 'move')
  371. $row['extra']['board_to'] = $row['id_board'];
  372. else
  373. $row['extra']['board'] = $row['id_board'];
  374. }
  375. if (!empty($row['id_topic']))
  376. $row['extra']['topic'] = $row['id_topic'];
  377. if (!empty($row['id_msg']))
  378. $row['extra']['message'] = $row['id_msg'];
  379. // Is this associated with a topic?
  380. if (isset($row['extra']['topic']))
  381. $topics[(int) $row['extra']['topic']][] = $row['id_action'];
  382. if (isset($row['extra']['new_topic']))
  383. $topics[(int) $row['extra']['new_topic']][] = $row['id_action'];
  384. // How about a member?
  385. if (isset($row['extra']['member']))
  386. {
  387. // Guests don't have names!
  388. if (empty($row['extra']['member']))
  389. $row['extra']['member'] = $txt['modlog_parameter_guest'];
  390. else
  391. {
  392. // Try to find it...
  393. $members[(int) $row['extra']['member']][] = $row['id_action'];
  394. }
  395. }
  396. // Associated with a board?
  397. if (isset($row['extra']['board_to']))
  398. $boards[(int) $row['extra']['board_to']][] = $row['id_action'];
  399. if (isset($row['extra']['board_from']))
  400. $boards[(int) $row['extra']['board_from']][] = $row['id_action'];
  401. if (isset($row['extra']['board']))
  402. $boards[(int) $row['extra']['board']][] = $row['id_action'];
  403. // A message?
  404. if (isset($row['extra']['message']))
  405. $messages[(int) $row['extra']['message']][] = $row['id_action'];
  406. // IP Info?
  407. if (isset($row['extra']['ip_range']))
  408. if ($seeIP)
  409. $row['extra']['ip_range'] = '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['extra']['ip_range'] . '">' . $row['extra']['ip_range'] . '</a>';
  410. else
  411. $row['extra']['ip_range'] = $txt['logged'];
  412. // Email?
  413. if (isset($row['extra']['email']))
  414. $row['extra']['email'] = '<a href="mailto:' . $row['extra']['email'] . '">' . $row['extra']['email'] . '</a>';
  415. // Bans are complex.
  416. if ($row['action'] == 'ban')
  417. {
  418. $row['action_text'] = $txt['modlog_ac_ban'];
  419. foreach (array('member', 'email', 'ip_range', 'hostname') as $type)
  420. if (isset($row['extra'][$type]))
  421. $row['action_text'] .= $txt['modlog_ac_ban_trigger_' . $type];
  422. }
  423. // The array to go to the template. Note here that action is set to a "default" value of the action doesn't match anything in the descriptions. Allows easy adding of logging events with basic details.
  424. $entries[$row['id_action']] = array(
  425. 'id' => $row['id_action'],
  426. 'ip' => $seeIP ? $row['ip'] : $txt['logged'],
  427. 'position' => empty($row['real_name']) && empty($row['group_name']) ? $txt['guest'] : $row['group_name'],
  428. 'moderator_link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>' : (empty($row['real_name']) ? ($txt['guest'] . (!empty($row['extra']['member_acted']) ? ' (' . $row['extra']['member_acted'] . ')' : '')) : $row['real_name']),
  429. 'time' => timeformat($row['log_time']),
  430. 'timestamp' => forum_time(true, $row['log_time']),
  431. 'editable' => time() > $row['log_time'] + $context['hoursdisable'] * 3600,
  432. 'extra' => $row['extra'],
  433. 'action' => $row['action'],
  434. 'action_text' => isset($row['action_text']) ? $row['action_text'] : '',
  435. );
  436. }
  437. $smcFunc['db_free_result']($result);
  438. if (!empty($boards))
  439. {
  440. $request = $smcFunc['db_query']('', '
  441. SELECT id_board, name
  442. FROM {db_prefix}boards
  443. WHERE id_board IN ({array_int:board_list})
  444. LIMIT ' . count(array_keys($boards)),
  445. array(
  446. 'board_list' => array_keys($boards),
  447. )
  448. );
  449. while ($row = $smcFunc['db_fetch_assoc']($request))
  450. {
  451. foreach ($boards[$row['id_board']] as $action)
  452. {
  453. // Make the board number into a link - dealing with moving too.
  454. if (isset($entries[$action]['extra']['board_to']) && $entries[$action]['extra']['board_to'] == $row['id_board'])
  455. $entries[$action]['extra']['board_to'] = '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>';
  456. elseif (isset($entries[$action]['extra']['board_from']) && $entries[$action]['extra']['board_from'] == $row['id_board'])
  457. $entries[$action]['extra']['board_from'] = '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>';
  458. elseif (isset($entries[$action]['extra']['board']) && $entries[$action]['extra']['board'] == $row['id_board'])
  459. $entries[$action]['extra']['board'] = '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>';
  460. }
  461. }
  462. $smcFunc['db_free_result']($request);
  463. }
  464. if (!empty($topics))
  465. {
  466. $request = $smcFunc['db_query']('', '
  467. SELECT ms.subject, t.id_topic
  468. FROM {db_prefix}topics AS t
  469. INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)
  470. WHERE t.id_topic IN ({array_int:topic_list})
  471. LIMIT ' . count(array_keys($topics)),
  472. array(
  473. 'topic_list' => array_keys($topics),
  474. )
  475. );
  476. while ($row = $smcFunc['db_fetch_assoc']($request))
  477. {
  478. foreach ($topics[$row['id_topic']] as $action)
  479. {
  480. $this_action = &$entries[$action];
  481. // This isn't used in the current theme.
  482. $this_action['topic'] = array(
  483. 'id' => $row['id_topic'],
  484. 'subject' => $row['subject'],
  485. 'href' => $scripturl . '?topic=' . $row['id_topic'] . '.0',
  486. 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['subject'] . '</a>'
  487. );
  488. // Make the topic number into a link - dealing with splitting too.
  489. if (isset($this_action['extra']['topic']) && $this_action['extra']['topic'] == $row['id_topic'])
  490. $this_action['extra']['topic'] = '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.' . (isset($this_action['extra']['message']) ? 'msg' . $this_action['extra']['message'] . '#msg' . $this_action['extra']['message'] : '0') . '">' . $row['subject'] . '</a>';
  491. elseif (isset($this_action['extra']['new_topic']) && $this_action['extra']['new_topic'] == $row['id_topic'])
  492. $this_action['extra']['new_topic'] = '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.' . (isset($this_action['extra']['message']) ? 'msg' . $this_action['extra']['message'] . '#msg' . $this_action['extra']['message'] : '0') . '">' . $row['subject'] . '</a>';
  493. }
  494. }
  495. $smcFunc['db_free_result']($request);
  496. }
  497. if (!empty($messages))
  498. {
  499. $request = $smcFunc['db_query']('', '
  500. SELECT id_msg, subject
  501. FROM {db_prefix}messages
  502. WHERE id_msg IN ({array_int:message_list})
  503. LIMIT ' . count(array_keys($messages)),
  504. array(
  505. 'message_list' => array_keys($messages),
  506. )
  507. );
  508. while ($row = $smcFunc['db_fetch_assoc']($request))
  509. {
  510. foreach ($messages[$row['id_msg']] as $action)
  511. {
  512. $this_action = &$entries[$action];
  513. // This isn't used in the current theme.
  514. $this_action['message'] = array(
  515. 'id' => $row['id_msg'],
  516. 'subject' => $row['subject'],
  517. 'href' => $scripturl . '?msg=' . $row['id_msg'],
  518. 'link' => '<a href="' . $scripturl . '?msg=' . $row['id_msg'] . '">' . $row['subject'] . '</a>',
  519. );
  520. // Make the message number into a link.
  521. if (isset($this_action['extra']['message']) && $this_action['extra']['message'] == $row['id_msg'])
  522. $this_action['extra']['message'] = '<a href="' . $scripturl . '?msg=' . $row['id_msg'] . '">' . $row['subject'] . '</a>';
  523. }
  524. }
  525. $smcFunc['db_free_result']($request);
  526. }
  527. if (!empty($members))
  528. {
  529. $request = $smcFunc['db_query']('', '
  530. SELECT real_name, id_member
  531. FROM {db_prefix}members
  532. WHERE id_member IN ({array_int:member_list})
  533. LIMIT ' . count(array_keys($members)),
  534. array(
  535. 'member_list' => array_keys($members),
  536. )
  537. );
  538. while ($row = $smcFunc['db_fetch_assoc']($request))
  539. {
  540. foreach ($members[$row['id_member']] as $action)
  541. {
  542. // Not used currently.
  543. $entries[$action]['member'] = array(
  544. 'id' => $row['id_member'],
  545. 'name' => $row['real_name'],
  546. 'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
  547. 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>'
  548. );
  549. // Make the member number into a name.
  550. $entries[$action]['extra']['member'] = '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>';
  551. }
  552. }
  553. $smcFunc['db_free_result']($request);
  554. }
  555. // Do some formatting of the action string.
  556. foreach ($entries as $k => $entry)
  557. {
  558. // Make any message info links so its easier to go find that message.
  559. if (isset($entry['extra']['message']) && (empty($entry['message']) || empty($entry['message']['id'])))
  560. $entries[$k]['extra']['message'] = '<a href="' . $scripturl . '?msg=' . $entry['extra']['message'] . '">' . $entry['extra']['message'] . '</a>';
  561. // Mark up any deleted members, topics and boards.
  562. foreach (array('board', 'board_from', 'board_to', 'member', 'topic', 'new_topic') as $type)
  563. if (!empty($entry['extra'][$type]) && is_numeric($entry['extra'][$type]))
  564. $entries[$k]['extra'][$type] = sprintf($txt['modlog_id'], $entry['extra'][$type]);
  565. if (empty($entries[$k]['action_text']))
  566. $entries[$k]['action_text'] = isset($txt['modlog_ac_' . $entry['action']]) ? $txt['modlog_ac_' . $entry['action']] : $entry['action'];
  567. $entries[$k]['action_text'] = preg_replace('~\{([A-Za-z\d_]+)\}~ie', 'isset($entries[$k][\'extra\'][\'$1\']) ? $entries[$k][\'extra\'][\'$1\'] : \'\'', $entries[$k]['action_text']);
  568. }
  569. // Back we go!
  570. return $entries;
  571. }