/** * Constructor * * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher * @param \phpbb\user $user User Object */ public function __construct(\phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\user $user) { $this->dispatcher = $phpbb_dispatcher; $this->user = $user; $categories = $this->categories; $types = $this->types; $permissions = $this->permissions; /** * Allows to specify additional permission categories, types and permissions * * @event core.permissions * @var array types Array with permission types (a_, u_, m_, etc.) * @var array categories Array with permission categories (pm, post, settings, misc, etc.) * @var array permissions Array with permissions. Each Permission has the following layout: * '<type><permission>' => array( * 'lang' => 'Language Key with a Short description', // Optional, if not set, * // the permissions identifier '<type><permission>' is used with * // all uppercase. * 'cat' => 'Identifier of the category, the permission should be displayed in', * ), * Example: * 'u_viewprofile' => array( * 'lang' => 'ACL_U_VIEWPROFILE', * 'cat' => 'profile', * ), * @since 3.1.0-a1 */ $vars = array('types', 'categories', 'permissions'); extract($phpbb_dispatcher->trigger_event('core.permissions', compact($vars))); $this->categories = $categories; $this->types = $types; $this->permissions = $permissions; }
/** * Controller for /help/{mode} routes * * @param string $mode * @return \Symfony\Component\HttpFoundation\Response A Symfony Response object * @throws http_exception when the $mode is not known by any extension */ public function handle($mode) { switch ($mode) { case 'faq': case 'bbcode': $page_title = $mode === 'faq' ? $this->user->lang['FAQ_EXPLAIN'] : $this->user->lang['BBCODE_GUIDE']; $this->user->add_lang($mode, false, true); break; default: $page_title = $this->user->lang['FAQ_EXPLAIN']; $ext_name = $lang_file = ''; /** * You can use this event display a custom help page * * @event core.faq_mode_validation * @var string page_title Title of the page * @var string mode FAQ that is going to be displayed * @var string lang_file Language file containing the help data * @var string ext_name Vendor and extension name where the help * language file can be loaded from * @since 3.1.4-RC1 */ $vars = array('page_title', 'mode', 'lang_file', 'ext_name'); extract($this->dispatcher->trigger_event('core.faq_mode_validation', compact($vars))); if ($ext_name === '' || $lang_file === '') { throw new http_exception(404, 'Not Found'); } $this->user->add_lang($lang_file, false, true, $ext_name); break; } $this->template->assign_vars(array('L_FAQ_TITLE' => $page_title, 'S_IN_FAQ' => true)); $this->assign_to_template($this->user->help); make_jumpbox(append_sid("{$this->root_path}viewforum.{$this->php_ext}")); return $this->helper->render('faq_body.html', $page_title); }
/** * {@inheritdoc} */ public function parse($text) { $parser = $this; /** * Modify a text before it is parsed * * @event core.text_formatter_s9e_parse_before * @var \phpbb\textformatter\s9e\parser parser This parser service * @var string text The original text * @since 3.2.0-a1 */ $vars = array('parser', 'text'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_parse_before', compact($vars))); $xml = $this->parser->parse($text); /** * Modify a parsed text in its XML form * * @event core.text_formatter_s9e_parse_after * @var \phpbb\textformatter\s9e\parser parser This parser service * @var string xml The parsed text, in XML * @since 3.2.0-a1 */ $vars = array('parser', 'xml'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_parse_after', compact($vars))); return $xml; }
/** * {@inheritdoc} */ public function render($xml) { if (isset($this->quote_helper)) { $xml = $this->quote_helper->inject_metadata($xml); } $renderer = $this; /** * Modify a parsed text before it is rendered * * @event core.text_formatter_s9e_render_before * @var \phpbb\textformatter\s9e\renderer renderer This renderer service * @var string xml The parsed text, in its XML form * @since 3.2.0-a1 */ $vars = array('renderer', 'xml'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_before', compact($vars))); if (isset($this->censor) && $this->viewcensors) { // NOTE: censorHtml() is XML-safe $xml = $this->censor->censorHtml($xml, true); } $html = $this->renderer->render($xml); /** * Modify a rendered text * * @event core.text_formatter_s9e_render_after * @var string html The rendered text's HTML * @var \phpbb\textformatter\s9e\renderer renderer This renderer service * @since 3.2.0-a1 */ $vars = array('html', 'renderer'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_after', compact($vars))); return $html; }
/** * {@inheritdoc} */ public function get_item() { if (!isset($this->result)) { if (!$this->get_sql()) { return false; } $sql_ary = $this->sql; /** * Event to modify the feed item sql * * @event core.feed_base_modify_item_sql * @var array sql_ary The SQL array to get the feed item data * * @since 3.1.10-RC1 */ $vars = array('sql_ary'); extract($this->phpbb_dispatcher->trigger_event('core.feed_base_modify_item_sql', compact($vars))); $this->sql = $sql_ary; unset($sql_ary); // Query database $sql = $this->db->sql_build_query('SELECT', $this->sql); $this->result = $this->db->sql_query_limit($sql, $this->num_items); } return $this->db->sql_fetchrow($this->result); }
/** * Add a notification * * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types) * Note: If you send an array of types, any user who could receive multiple notifications from this single item will only receive * a single notification. If they MUST receive multiple notifications, call this function multiple times instead of sending an array * @param array $data Data specific for this type that will be inserted * @param array $options Optional options to control what notifications are loaded * ignore_users array of data to specify which users should not receive certain types of notifications * @return array Information about what users were notified and how they were notified */ public function add_notifications($notification_type_name, $data, array $options = array()) { $options = array_merge(array('ignore_users' => array()), $options); if (is_array($notification_type_name)) { $notified_users = array(); $temp_options = $options; foreach ($notification_type_name as $type) { $temp_options['ignore_users'] = $options['ignore_users'] + $notified_users; $notified_users += $this->add_notifications($type, $data, $temp_options); } return $notified_users; } // find out which users want to receive this type of notification $notify_users = $this->get_item_type_class($notification_type_name)->find_users_for_notification($data, $options); /** * Allow filtering the notify_users array for a notification that is about to be sent. * Here, $notify_users is already filtered by f_read and the ignored list included in the options variable * * @event core.notification_manager_add_notifications * @var string notification_type_name The forum id from where the topic belongs * @var array data Data specific for the notification_type_name used will be inserted * @var array notify_users The array of userid that are going to be notified for this notification. Set to array() to cancel. * @var array options The options that were used when this method was called (read only) * * @since 3.1.3-RC1 */ $vars = array('notification_type_name', 'data', 'notify_users', 'options'); extract($this->phpbb_dispatcher->trigger_event('core.notification_manager_add_notifications', compact($vars))); $this->add_notifications_for_users($notification_type_name, $data, $notify_users); return $notify_users; }
/** * Create topic/post visibility SQL for all forums on the board * * Note: Read permissions are not checked. Forums without read permissions * should be in $exclude_forum_ids * * @param $mode string Either "topic" or "post" * @param $exclude_forum_ids array Array of forum ids which are excluded * @param $table_alias string Table alias to prefix in SQL queries * @return string The appropriate combination SQL logic for topic/post_visibility */ public function get_global_visibility_sql($mode, $exclude_forum_ids = array(), $table_alias = '') { $where_sqls = array(); $approve_forums = array_diff(array_keys($this->auth->acl_getf('m_approve', true)), $exclude_forum_ids); $visibility_sql_overwrite = null; /** * Allow changing the result of calling get_global_visibility_sql * * @event core.phpbb_content_visibility_get_global_visibility_before * @var array where_sqls The action the user tried to execute * @var string mode Either "topic" or "post" depending on the query this is being used in * @var array exclude_forum_ids Array of forum ids the current user doesn't have access to * @var string table_alias Table alias to prefix in SQL queries * @var array approve_forums Array of forums where the user has m_approve permissions * @var string visibility_sql_overwrite Forces the function to return an implosion of where_sqls (joined by "OR") * @since 3.1.3-RC1 */ $vars = array('where_sqls', 'mode', 'exclude_forum_ids', 'table_alias', 'approve_forums', 'visibility_sql_overwrite'); extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_global_visibility_before', compact($vars))); if ($visibility_sql_overwrite) { return $visibility_sql_overwrite; } if (sizeof($exclude_forum_ids)) { $where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true) . ' AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')'; } else { $where_sqls[] = $table_alias . $mode . '_visibility = ' . ITEM_APPROVED; } if (sizeof($approve_forums)) { $where_sqls[] = $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums); return '(' . implode(' OR ', $where_sqls) . ')'; } // There is only one element, so we just return that one return $where_sqls[0]; }
/** * Generate a pagination link based on the url and the page information * * @param string $base_url is url prepended to all links generated within the function * If you use page numbers inside your controller route, base_url should contains a placeholder (%d) * for the page. Also be sure to specify the pagination path information into the start_name argument * @param string $on_page is the page for which we want to generate the link * @param string $start_name is the name of the parameter containing the first item of the given page (example: start=20) * If you use page numbers inside your controller route, start name should be the string * that should be removed for the first page (example: /page/%d) * @param int $per_page the number of items, posts, etc. to display per page, used to determine the number of pages to produce * @return string URL for the requested page */ protected function generate_page_link($base_url, $on_page, $start_name, $per_page) { // A listener can set this variable to the new pagination URL // to override the generate_page_link() function generated value $generate_page_link_override = false; /** * Execute code and/or override generate_page_link() * * To override the generate_page_link() function generated value * set $generate_page_link_override to the new URL value * * @event core.pagination_generate_page_link * @var string base_url is url prepended to all links generated within the function * If you use page numbers inside your controller route, base_url should contains a placeholder (%d) * for the page. Also be sure to specify the pagination path information into the start_name argument * @var string on_page is the page for which we want to generate the link * @var string start_name is the name of the parameter containing the first item of the given page (example: start=20) * If you use page numbers inside your controller route, start name should be the string * that should be removed for the first page (example: /page/%d) * @var int per_page the number of items, posts, etc. to display per page, used to determine the number of pages to produce * @var bool|string generate_page_link_override Shall we return custom pagination link (string URL) or not (false) * @since 3.1.0-RC5 */ $vars = array('base_url', 'on_page', 'start_name', 'per_page', 'generate_page_link_override'); extract($this->phpbb_dispatcher->trigger_event('core.pagination_generate_page_link', compact($vars))); if ($generate_page_link_override) { return $generate_page_link_override; } if (!is_string($base_url)) { if (is_array($base_url['routes'])) { $route = $on_page > 1 ? $base_url['routes'][1] : $base_url['routes'][0]; } else { $route = $base_url['routes']; } $params = isset($base_url['params']) ? $base_url['params'] : array(); $is_amp = isset($base_url['is_amp']) ? $base_url['is_amp'] : true; $session_id = isset($base_url['session_id']) ? $base_url['session_id'] : false; if ($on_page > 1 || !is_array($base_url['routes'])) { $params[$start_name] = (int) $on_page; } return $this->helper->route($route, $params, $is_amp, $session_id); } else { $url_delim = strpos($base_url, '?') === false ? '?' : (strpos($base_url, '?') === strlen($base_url) - 1 ? '' : '&'); return $on_page > 1 ? $base_url . $url_delim . $start_name . '=' . ($on_page - 1) * $per_page : $base_url; } }
/** * Really send the feed * * @param feed_interface $feed * * @return Response * * @throw exception\feed_exception */ protected function send_feed_do(feed_interface $feed) { $feed_updated_time = 0; $item_vars = array(); $board_url = $this->feed_helper->get_board_url(); // Open Feed $feed->open(); // Iterate through items while ($row = $feed->get_item()) { /** * Event to modify the feed row * * @event core.feed_modify_feed_row * @var int forum_id Forum ID * @var string mode Feeds mode (forums|topics|topics_new|topics_active|news) * @var array row Array with feed data * @var int topic_id Topic ID * * @since 3.1.10-RC1 */ $vars = array('forum_id', 'mode', 'row', 'topic_id'); extract($this->phpbb_dispatcher->trigger_event('core.feed_modify_feed_row', compact($vars))); // BBCode options to correctly disable urls, smilies, bbcode... if ($feed->get('options') === null) { // Allow all combinations $options = 7; if ($feed->get('enable_bbcode') !== null && $feed->get('enable_smilies') !== null && $feed->get('enable_magic_url') !== null) { $options = ($row[$feed->get('enable_bbcode')] ? OPTION_FLAG_BBCODE : 0) + ($row[$feed->get('enable_smilies')] ? OPTION_FLAG_SMILIES : 0) + ($row[$feed->get('enable_magic_url')] ? OPTION_FLAG_LINKS : 0); } } else { $options = $row[$feed->get('options')]; } $title = isset($row[$feed->get('title')]) && $row[$feed->get('title')] !== '' ? $row[$feed->get('title')] : (isset($row[$feed->get('title2')]) ? $row[$feed->get('title2')] : ''); $published = $feed->get('published') !== null ? (int) $row[$feed->get('published')] : 0; $updated = $feed->get('updated') !== null ? (int) $row[$feed->get('updated')] : 0; $display_attachments = $this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $row['forum_id']) && isset($row['post_attachment']) && $row['post_attachment'] ? true : false; $item_row = array('author' => $feed->get('creator') !== null ? $row[$feed->get('creator')] : '', 'published' => $published > 0 ? $this->feed_helper->format_date($published) : '', 'updated' => $updated > 0 ? $this->feed_helper->format_date($updated) : '', 'link' => '', 'title' => censor_text($title), 'category' => $this->config['feed_item_statistics'] && !empty($row['forum_id']) ? $board_url . '/viewforum.' . $this->php_ext . '?f=' . $row['forum_id'] : '', 'category_name' => $this->config['feed_item_statistics'] && isset($row['forum_name']) ? $row['forum_name'] : '', 'description' => censor_text($this->feed_helper->generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options, $row['forum_id'], $display_attachments ? $feed->get_attachments($row['post_id']) : array())), 'statistics' => ''); // Adjust items, fill link, etc. $feed->adjust_item($item_row, $row); $item_vars[] = $item_row; $feed_updated_time = max($feed_updated_time, $published, $updated); } // If we do not have any items at all, sending the current time is better than sending no time. if (!$feed_updated_time) { $feed_updated_time = time(); } $feed->close(); $content = $this->template->render('feed.xml.twig', array('FEED_IMAGE' => '', 'SELF_LINK' => $this->controller_helper->route($this->request->attributes->get('_route'), $this->request->attributes->get('_route_params'), true, '', UrlGeneratorInterface::ABSOLUTE_URL), 'FEED_LINK' => $board_url . '/index.' . $this->php_ext, 'FEED_TITLE' => $this->config['sitename'], 'FEED_SUBTITLE' => $this->config['site_desc'], 'FEED_UPDATED' => $this->feed_helper->format_date($feed_updated_time), 'FEED_LANG' => $this->user->lang['USER_LANG'], 'FEED_AUTHOR' => $this->config['sitename'], 'FEED_ROWS' => $item_vars)); $response = new Response($content); $response->headers->set('Content-Type', 'application/atom+xml'); $response->setCharset('UTF-8'); $response->setLastModified(new \DateTime('@' . $feed_updated_time)); if (!empty($this->user->data['is_bot'])) { // Let reverse proxies know we detected a bot. $response->headers->set('X-PHPBB-IS-BOT', 'yes'); } return $response; }
public function info($user_id) { if (!$this->auth->acl_gets('u_viewprofile')) { trigger_error('NOT_AUTHORISED'); } $sql_ary = array('SELECT' => 'u.username, u.user_colour, u.user_regdate, u.user_posts, u.user_lastvisit, u.user_rank, u.user_avatar, u.user_avatar_type, u.user_avatar_width, u.user_avatar_height', 'FROM' => array(USERS_TABLE => 'u'), 'WHERE' => 'u.user_id = ' . (int) $user_id); /** * Modify SQL query in tas2580 AJAX userinfo extension * * @event tas2580.userinfo_modify_sql * @var string sql_ary The SQL query * @var int user_id The ID of the user * @since 0.2.3 */ $vars = array('sql_ary', 'user_id'); extract($this->phpbb_dispatcher->trigger_event('tas2580.userinfo_modify_sql', compact($vars))); $result = $this->db->sql_query_limit($this->db->sql_build_query('SELECT', $sql_ary), 1); $this->data = $this->db->sql_fetchrow($result); $this->db->sql_freeresult($result); if (!function_exists('phpbb_get_user_rank')) { include $this->phpbb_root_path . 'includes/functions_display.' . $this->php_ext; } $user_rank_data = phpbb_get_user_rank($this->data, $this->data['user_posts']); // Get the avatar // Wen need to use the full URL here because we don't know the path where userinfo is called define('PHPBB_USE_BOARD_URL_PATH', true); $avatar = phpbb_get_user_avatar($this->data); $avatar = empty($avatar) ? '<img src="' . generate_board_url() . '/styles/' . $this->user->style['style_name'] . '/theme/images/no_avatar.gif" width="100" height="100" alt="' . $this->user->lang('USER_AVATAR') . '">' : $avatar; $memberdays = max(1, round((time() - $this->data['user_regdate']) / 86400)); $posts_per_day = $this->data['user_posts'] / $memberdays; $percentage = $this->config['num_posts'] ? min(100, $this->data['user_posts'] / $this->config['num_posts'] * 100) : 0; $result = array('userinfo_header' => sprintf($this->user->lang['VIEWING_PROFILE'], $this->data['username']), 'username' => get_username_string('no_profile', $user_id, $this->data['username'], $this->data['user_colour']), 'regdate' => $this->user->format_date($this->data['user_regdate']), 'posts' => $this->data['user_posts'], 'lastvisit' => $this->user->format_date($this->data['user_lastvisit']), 'avatar' => $avatar, 'rank' => empty($user_rank_data['title']) ? $this->user->lang('NA') : $user_rank_data['title'], 'postsperday' => $this->user->lang('POST_DAY', $posts_per_day), 'percentage' => $this->user->lang('POST_PCT', $percentage)); /** * Modify return data in tas2580 AJAX userinfo extension * * @event tas2580.userinfo_modify_result * @var array result The result array * @var int user_id The ID of the user * @since 0.2.3 */ $vars = array('result', 'user_id'); extract($this->phpbb_dispatcher->trigger_event('tas2580.userinfo_modify_result', compact($vars))); return new JsonResponse($result); }
/** * Inject topic preview text into the template * * @param array $row Row data * @param array $block Template vars array * @return array Template vars array * @access public */ public function display_topic_preview($row, $block) { if (!$this->is_enabled()) { return $block; } $block = array_merge($block, array('TOPIC_PREVIEW_FIRST_POST' => !empty($row['first_post_text']) ? censor_text($this->trim_tools->trim_text($row['first_post_text'], $this->config['topic_preview_limit'])) : '', 'TOPIC_PREVIEW_LAST_POST' => !empty($row['last_post_text']) && $row['topic_first_post_id'] != $row['topic_last_post_id'] ? censor_text($this->trim_tools->trim_text($row['last_post_text'], $this->config['topic_preview_limit'])) : '', 'TOPIC_PREVIEW_FIRST_AVATAR' => $this->get_user_avatar_helper($row, 'fp'), 'TOPIC_PREVIEW_LAST_AVATAR' => $this->get_user_avatar_helper($row, 'lp'))); $tp_avatars = $this->avatars_enabled(); /** * EVENT to modify the topic preview display output before it gets inserted in the template block * * @event vse.topicpreview.display_topic_preview * @var array row Row data * @var array block Template vars array * @var bool tp_avatars Display avatars setting * @since 2.1.0 */ $vars = array('row', 'block', 'tp_avatars'); extract($this->dispatcher->trigger_event('vse.topicpreview.display_topic_preview', compact($vars))); return $block; }
/** * Assign the user's profile fields data to the template * * @param array $profile_row Array with users profile field data * @param bool $use_contact_fields Should we display contact fields as such? * This requires special treatments (links should not be parsed in the values, and more) * @return array */ public function generate_profile_fields_template_data($profile_row, $use_contact_fields = true) { // $profile_row == $user_fields[$row['user_id']]; $tpl_fields = array(); $tpl_fields['row'] = $tpl_fields['blockrow'] = array(); /** * Event to modify data of the generated profile fields, before the template assignment loop * * @event core.generate_profile_fields_template_data_before * @var array profile_row Array with users profile field data * @var array tpl_fields Array with template data fields * @var bool use_contact_fields Should we display contact fields as such? * @since 3.1.0-b3 */ $vars = array('profile_row', 'tpl_fields', 'use_contact_fields'); extract($this->dispatcher->trigger_event('core.generate_profile_fields_template_data_before', compact($vars))); foreach ($profile_row as $ident => $ident_ary) { $profile_field = $this->type_collection[$ident_ary['data']['field_type']]; $value = $profile_field->get_profile_value($ident_ary['value'], $ident_ary['data']); $value_raw = $profile_field->get_profile_value_raw($ident_ary['value'], $ident_ary['data']); if ($value === null) { continue; } $field_desc = $contact_url = ''; if ($use_contact_fields && $ident_ary['data']['field_is_contact']) { $value = $profile_field->get_profile_contact_value($ident_ary['value'], $ident_ary['data']); $field_desc = $this->user->lang($ident_ary['data']['field_contact_desc']); if (strpos($field_desc, '%s') !== false) { $field_desc = sprintf($field_desc, $value); } $contact_url = ''; if (strpos($ident_ary['data']['field_contact_url'], '%s') !== false) { $contact_url = sprintf($ident_ary['data']['field_contact_url'], $value); } } $tpl_fields['row'] += array('PROFILE_' . strtoupper($ident) . '_IDENT' => $ident, 'PROFILE_' . strtoupper($ident) . '_VALUE' => $value, 'PROFILE_' . strtoupper($ident) . '_VALUE_RAW' => $value_raw, 'PROFILE_' . strtoupper($ident) . '_CONTACT' => $contact_url, 'PROFILE_' . strtoupper($ident) . '_DESC' => $field_desc, 'PROFILE_' . strtoupper($ident) . '_TYPE' => $ident_ary['data']['field_type'], 'PROFILE_' . strtoupper($ident) . '_NAME' => $this->user->lang($ident_ary['data']['lang_name']), 'PROFILE_' . strtoupper($ident) . '_EXPLAIN' => $this->user->lang($ident_ary['data']['lang_explain']), 'S_PROFILE_' . strtoupper($ident) . '_CONTACT' => $ident_ary['data']['field_is_contact'], 'S_PROFILE_' . strtoupper($ident) => true); $tpl_fields['blockrow'][] = array('PROFILE_FIELD_IDENT' => $ident, 'PROFILE_FIELD_VALUE' => $value, 'PROFILE_FIELD_VALUE_RAW' => $value_raw, 'PROFILE_FIELD_CONTACT' => $contact_url, 'PROFILE_FIELD_DESC' => $field_desc, 'PROFILE_FIELD_TYPE' => $ident_ary['data']['field_type'], 'PROFILE_FIELD_NAME' => $this->user->lang($ident_ary['data']['lang_name']), 'PROFILE_FIELD_EXPLAIN' => $this->user->lang($ident_ary['data']['lang_explain']), 'S_PROFILE_CONTACT' => $ident_ary['data']['field_is_contact'], 'S_PROFILE_' . strtoupper($ident) => true); } /** * Event to modify template data of the generated profile fields * * @event core.generate_profile_fields_template_data * @var array profile_row Array with users profile field data * @var array tpl_fields Array with template data fields * @var bool use_contact_fields Should we display contact fields as such? * @since 3.1.0-b3 */ $vars = array('profile_row', 'tpl_fields', 'use_contact_fields'); extract($this->dispatcher->trigger_event('core.generate_profile_fields_template_data', compact($vars))); return $tpl_fields; }
public function delete_thanks($post_id, $forum_id) { // $this->user->add_lang_ext('gfksx/ThanksForPosts', 'thanks_mod'); $to_id = $this->request->variable('to_id', 0); $forum_id = $forum_id ?: $this->request->variable('f', 0); $row = $this->get_post_info($post_id); // confirm $hidden = build_hidden_fields(array('to_id' => $to_id, 'rthanks' => $post_id)); /** * This event allows to interrupt before a thanks is deleted * * @event gfksx.thanksforposts.delete_thanks_before * @var int post_id The post id * @var int forum_id The forum id * @since 2.0.3 */ $vars = array('post_id', 'forum_id'); extract($this->phpbb_dispatcher->trigger_event('gfksx.thanksforposts.delete_thanks_before', compact($vars))); if (isset($this->config['remove_thanks']) ? !$this->config['remove_thanks'] : true) { trigger_error($this->user->lang['DISABLE_REMOVE_THANKS'] . '<br /><br />' . $this->user->lang('RETURN_POST', '<a href="' . append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", "f={$forum_id}&p={$post_id}#p{$post_id}") . '">', '</a>')); } if (confirm_box(true, 'REMOVE_THANKS', $hidden)) { if ($this->user->data['user_type'] != USER_IGNORE && !empty($to_id) && $this->auth->acl_get('f_thanks', $forum_id)) { $sql = "DELETE FROM " . $this->thanks_table . ' WHERE post_id =' . (int) $post_id . " AND user_id = " . (int) $this->user->data['user_id']; $this->db->sql_query($sql); $result = $this->db->sql_affectedrows($sql); if ($result != 0) { $lang_act = 'REMOVE'; $thanks_data = array('user_id' => (int) $this->user->data['user_id'], 'post_id' => $post_id, 'poster_id' => $to_id, 'topic_id' => (int) $row['topic_id'], 'forum_id' => $forum_id, 'thanks_time' => time(), 'username' => $this->user->data['username'], 'lang_act' => $lang_act, 'post_subject' => $row['post_subject']); $this->add_notification($thanks_data, 'gfksx.thanksforposts.notification.type.thanks_remove'); if (isset($this->config['thanks_info_page']) && $this->config['thanks_info_page']) { meta_refresh(1, append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", "f={$forum_id}&p={$post_id}#p{$post_id}")); trigger_error($this->user->lang['THANKS_INFO_' . $lang_act] . '<br /><br />' . $this->user->lang('RETURN_POST', '<a href="' . append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", "f={$forum_id}&p={$post_id}#p{$post_id}") . '">', '</a>')); } else { redirect(append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", "f={$forum_id}&p={$post_id}#p{$post_id}")); } } else { trigger_error($this->user->lang['INCORRECT_THANKS'] . '<br /><br />' . $this->user->lang('RETURN_POST', '<a href="' . append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", "f={$forum_id}&p={$post_id}#p{$post_id}") . '">', '</a>')); } } } else { confirm_box(false, 'REMOVE_THANKS', $hidden); redirect(append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", "f={$forum_id}&p={$post_id}#p{$post_id}")); } return; }
/** * Marks a topic as unsolved. * * @param array $topic_data Topic to be marked as unsolved. */ public function mark_unsolved($topic_data) { // Database column values to set. $column_data = array('topic_solved' => 0); if ($topic_data['forum_lock_solved'] && $this->auth->acl_get('m_lock', $topic_data['forum_id'])) { $column_data['topic_status'] = ITEM_UNLOCKED; } $this->update_topic($topic_data['topic_id'], $column_data); /** * This event allows you to perform additional actions after a topic has been marked as unsolved. * * @event tierra.topicsolved.mark_unsolved_after * @var array topic_data Array with general topic data * @var array column_data Array with topic data that the database has been updated with * @since 2.2.0 */ $vars = array('topic_data', 'column_data'); extract($this->dispatcher->trigger_event('tierra.topicsolved.mark_unsolved_after', compact($vars))); }
/** * Renders data for a page * * @param $page The page we are rendering for, one of index|custom|archive */ protected function render_page($page) { // Add lang file $this->user->add_lang('posting'); // If the static message is defined in the language file use it, else the entry in the database is used if (isset($this->user->lang['STATIC_MESSAGE'])) { $this->config['mchat_static_message'] = $this->user->lang('STATIC_MESSAGE'); } $this->template->assign_vars(array('MCHAT_FILE_NAME' => $this->helper->route('dmzx_mchat_controller'), 'MCHAT_REFRESH_JS' => 1000 * $this->config['mchat_refresh'], 'MCHAT_INPUT_TYPE' => $this->user->data['user_mchat_input_area'], 'MCHAT_RULES' => !empty($this->user->lang['MCHAT_RULES']) || !empty($this->config['mchat_rules']), 'MCHAT_ALLOW_USE' => $this->auth->acl_get('u_mchat_use'), 'MCHAT_ALLOW_SMILES' => $this->config['allow_smilies'] && $this->auth->acl_get('u_mchat_smilies'), 'MCHAT_ALLOW_BBCODES' => $this->config['allow_bbcode'] && $this->auth->acl_get('u_mchat_bbcode'), 'MCHAT_MESSAGE_TOP' => $this->config['mchat_message_top'], 'MCHAT_ARCHIVE_URL' => $this->helper->route('dmzx_mchat_page_controller', array('page' => 'archive')), 'MCHAT_INDEX_HEIGHT' => $this->config['mchat_index_height'], 'MCHAT_CUSTOM_HEIGHT' => $this->config['mchat_custom_height'], 'MCHAT_READ_ARCHIVE_BUTTON' => $this->auth->acl_get('u_mchat_archive'), 'MCHAT_FOUNDER' => $this->user->data['user_type'] == USER_FOUNDER, 'MCHAT_STATIC_MESS' => !empty($this->config['mchat_static_message']) ? htmlspecialchars_decode($this->config['mchat_static_message']) : '', 'L_MCHAT_COPYRIGHT' => base64_decode('PGEgaHJlZj0iaHR0cHM6Ly9lbnRyb3B5LmZpL2tlc2t1c3RlbHUvbWVtYmVybGlzdC5waHA/bW9kZT12aWV3cHJvZmlsZSZ1PTI5MiI+VGhlSDwvYT4gJmNvcHk7IDxhIGhyZWY9Imh0dHA6Ly9ybWNnaXJyODMub3JnIj5STWNHaXJyODM8L2E+ICZjb3B5OyA8YSBocmVmPSJodHRwOi8vd3d3LmRtengtd2ViLm5ldCIgdGl0bGU9Ind3dy5kbXp4LXdlYi5uZXQiPmRteng8L2E+'), 'MCHAT_MESSAGE_LNGTH' => $this->config['mchat_max_message_lngth'], 'MCHAT_MESS_LONG' => sprintf($this->user->lang('MCHAT_MESS_LONG'), $this->config['mchat_max_message_lngth']), 'MCHAT_USER_TIMEOUT_TIME' => gmdate('H:i:s', (int) $this->config['mchat_timeout']), 'MCHAT_WHOIS_REFRESH' => $this->config['mchat_whois'] ? 1000 * $this->config['mchat_whois_refresh'] : 0, 'MCHAT_WHOIS_REFRESH_EXPLAIN' => sprintf($this->user->lang('WHO_IS_REFRESH_EXPLAIN'), $this->config['mchat_whois_refresh']), 'MCHAT_PAUSE_ON_INPUT' => $this->config['mchat_pause_on_input'], 'MCHAT_REFRESH_YES' => sprintf($this->user->lang('MCHAT_REFRESH_YES'), $this->config['mchat_refresh']), 'MCHAT_LIVE_UPDATES' => $this->config['mchat_live_updates'], 'S_MCHAT_LOCATION' => $this->config['mchat_location'], 'S_MCHAT_SOUND_YES' => $this->user->data['user_mchat_sound'], 'U_MORE_SMILIES' => generate_board_url() . append_sid("/{$this->root_path}/posting.{$this->php_ext}", 'mode=smilies'), 'U_MCHAT_RULES' => $this->helper->route('dmzx_mchat_page_controller', array('page' => 'rules')), 'S_MCHAT_ON_INDEX' => $this->config['mchat_on_index'] && !empty($this->user->data['user_mchat_index']), 'S_MCHAT_MOBILE_BEFORE' => $this->user->data['user_mchat_mobile_before'], 'S_MCHAT_TITLEFLASHDURATION' => $this->user->data['user_mchat_titleflash_duration'], 'S_MCHAT_FOLLOW' => $this->user->data['user_mchat_follow'], 'S_MCHAT_ON_VIEWTOPIC' => $this->config['mchat_on_viewtopic'], 'S_MCHAT_ON_VIEWFORUM' => $this->config['mchat_on_viewforum'], 'S_MCHAT_SIMPLE_MSG' => $this->config['mchat_simple_msg'])); $sql_where = $this->user->data['user_mchat_topics'] ? '' : 'm.forum_id = 0'; $limit = $page == 'archive' ? $this->config['mchat_archive_limit'] : $this->config[$page == 'index' ? 'mchat_message_num' : 'mchat_message_limit']; $start = $page == 'archive' ? $this->request->variable('start', 0) : 0; $rows = $this->functions_mchat->mchat_get_messages($sql_where, $limit, $start); $this->assign_global_template_data(); $this->assign_messages($rows); // Render pagination if ($page == 'archive') { $archive_url = $this->helper->route('dmzx_mchat_page_controller', array('page' => 'archive')); $total_messages = $this->functions_mchat->mchat_total_message_count(); $this->pagination->generate_template_pagination($archive_url, 'pagination', 'start', $total_messages, $limit, $start); $this->template->assign_var('MCHAT_TOTAL_MESSAGES', sprintf($this->user->lang('MCHAT_TOTALMESSAGES'), $total_messages)); } // Render legend if ($page != 'index' && $this->config['mchat_whois']) { $legend = $this->functions_mchat->mchat_legend(); $this->template->assign_var('LEGEND', implode(', ', $legend)); } if ($this->auth->acl_get('u_mchat_use')) { add_form_key('mchat'); } $this->is_mchat_rendered = true; /** * Event render_helper_aft * * @event dmzx.mchat.core.render_helper_aft * @since 0.1.2 */ $this->dispatcher->dispatch('dmzx.mchat.core.render_helper_aft'); }
/** * {@inheritdoc} */ public function delete($row) { $error = array(); $destination = $this->config['avatar_path']; $prefix = $this->config['avatar_salt'] . '_'; $ext = substr(strrchr($row['avatar'], '.'), 1); $filename = $this->phpbb_root_path . $destination . '/' . $prefix . $row['id'] . '.' . $ext; /** * Before deleting an existing avatar * * @event core.avatar_driver_upload_delete_before * @var string destination Destination directory where the file is going to be deleted * @var string prefix Prefix for the avatar filename * @var array row Array with avatar row data * @var array error Array of errors, if filled in by this event file will not be deleted * @since 3.1.6-RC1 */ $vars = array('destination', 'prefix', 'row', 'error'); extract($this->dispatcher->trigger_event('core.avatar_driver_upload_delete_before', compact($vars))); if (!sizeof($error) && file_exists($filename)) { @unlink($filename); } return true; }
/** * Performs a search on an author's posts without caring about message contents. Depends on display specific params * * @param string $type contains either posts or topics depending on what should be searched for * @param boolean $firstpost_only if true, only topic starting posts will be considered * @param array $sort_by_sql contains SQL code for the ORDER BY part of a query * @param string $sort_key is the key of $sort_by_sql for the selected sorting * @param string $sort_dir is either a or d representing ASC and DESC * @param string $sort_days specifies the maximum amount of days a post may be old * @param array $ex_fid_ary specifies an array of forum ids which should not be searched * @param string $post_visibility specifies which types of posts the user can view in which forums * @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched * @param array $author_ary an array of author ids * @param string $author_name specifies the author match, when ANONYMOUS is also a search-match * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered * @param int $start indicates the first index of the page * @param int $per_page number of ids each page is supposed to contain * @return boolean|int total number of results */ public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) { // No author? No posts if (!sizeof($author_ary)) { return 0; } // generate a search_key from all the options to identify the results $search_key_array = array('', $type, $firstpost_only ? 'firstpost' : '', '', '', $sort_days, $sort_key, $topic_id, implode(',', $ex_fid_ary), $post_visibility, implode(',', $author_ary), $author_name); /** * Allow changing the search_key for cached results * * @event core.search_postgres_by_author_modify_search_key * @var array search_key_array Array with search parameters to generate the search_key * @var string type Searching type ('posts', 'topics') * @var boolean firstpost_only Flag indicating if only topic starting posts are considered * @var int sort_days Time, in days, of the oldest possible post to list * @var string sort_key The sort type used from the possible sort types * @var int topic_id Limit the search to this topic_id only * @var array ex_fid_ary Which forums not to search on * @var string post_visibility Post visibility data * @var array author_ary Array of user_id containing the users to filter the results to * @var string author_name The username to search on * @since 3.1.7-RC1 */ $vars = array('search_key_array', 'type', 'firstpost_only', 'sort_days', 'sort_key', 'topic_id', 'ex_fid_ary', 'post_visibility', 'author_ary', 'author_name'); extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_by_author_modify_search_key', compact($vars))); $search_key = md5(implode('#', $search_key_array)); if ($start < 0) { $start = 0; } // try reading the results from cache $result_count = 0; if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) { return $result_count; } $id_ary = array(); // Create some display specific sql strings if ($author_name) { // first one matches post of registered users, second one guests and deleted users $sql_author = '(' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')'; } else { $sql_author = $this->db->sql_in_set('p.poster_id', $author_ary); } $sql_fora = sizeof($ex_fid_ary) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; $sql_topic_id = $topic_id ? ' AND p.topic_id = ' . (int) $topic_id : ''; $sql_time = $sort_days ? ' AND p.post_time >= ' . (time() - $sort_days * 86400) : ''; $sql_firstpost = $firstpost_only ? ' AND p.post_id = t.topic_first_post_id' : ''; // Build sql strings for sorting $sql_sort = $sort_by_sql[$sort_key] . ($sort_dir == 'a' ? ' ASC' : ' DESC'); $sql_sort_table = $sql_sort_join = ''; switch ($sql_sort[0]) { case 'u': $sql_sort_table = USERS_TABLE . ' u, '; $sql_sort_join = $type == 'posts' ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster '; break; case 't': $sql_sort_table = $type == 'posts' && !$firstpost_only ? TOPICS_TABLE . ' t, ' : ''; $sql_sort_join = $type == 'posts' && !$firstpost_only ? ' AND t.topic_id = p.topic_id ' : ''; break; case 'f': $sql_sort_table = FORUMS_TABLE . ' f, '; $sql_sort_join = ' AND f.forum_id = p.forum_id '; break; } $m_approve_fid_sql = ' AND ' . $post_visibility; /** * Allow changing the query used to search for posts by author in fulltext_postgres * * @event core.search_postgres_author_count_query_before * @var int result_count The previous result count for the format of the query. * Set to 0 to force a re-count * @var string sql_sort_table CROSS JOIN'ed table to allow doing the sort chosen * @var string sql_sort_join Condition to define how to join the CROSS JOIN'ed table specifyed in sql_sort_table * @var array author_ary Array of user_id containing the users to filter the results to * @var string author_name An extra username to search on * @var string sql_author SQL WHERE condition for the post author ids * @var int topic_id Limit the search to this topic_id only * @var string sql_topic_id SQL of topic_id * @var string sort_by_sql The possible predefined sort types * @var string sort_key The sort type used from the possible sort types * @var string sort_dir "a" for ASC or "d" dor DESC for the sort order used * @var string sql_sort The result SQL when processing sort_by_sql + sort_key + sort_dir * @var string sort_days Time, in days, that the oldest post showing can have * @var string sql_time The SQL to search on the time specifyed by sort_days * @var bool firstpost_only Wether or not to search only on the first post of the topics * @var array ex_fid_ary Forum ids that must not be searched on * @var array sql_fora SQL query for ex_fid_ary * @var string m_approve_fid_sql WHERE clause condition on post_visibility restrictions * @var int start How many posts to skip in the search results (used for pagination) * @since 3.1.5-RC1 */ $vars = array('result_count', 'sql_sort_table', 'sql_sort_join', 'author_ary', 'author_name', 'sql_author', 'topic_id', 'sql_topic_id', 'sort_by_sql', 'sort_key', 'sort_dir', 'sql_sort', 'sort_days', 'sql_time', 'firstpost_only', 'ex_fid_ary', 'sql_fora', 'm_approve_fid_sql', 'start'); extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_author_count_query_before', compact($vars))); // Build the query for really selecting the post_ids if ($type == 'posts') { $sql = "SELECT p.post_id\n\t\t\t\tFROM " . $sql_sort_table . POSTS_TABLE . ' p' . ($firstpost_only ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "\n\t\t\t\tWHERE {$sql_author}\n\t\t\t\t\t{$sql_topic_id}\n\t\t\t\t\t{$sql_firstpost}\n\t\t\t\t\t{$m_approve_fid_sql}\n\t\t\t\t\t{$sql_fora}\n\t\t\t\t\t{$sql_sort_join}\n\t\t\t\t\t{$sql_time}\n\t\t\t\tORDER BY {$sql_sort}"; $field = 'post_id'; } else { $sql = "SELECT t.topic_id\n\t\t\t\tFROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p\n\t\t\t\tWHERE {$sql_author}\n\t\t\t\t\t{$sql_topic_id}\n\t\t\t\t\t{$sql_firstpost}\n\t\t\t\t\t{$m_approve_fid_sql}\n\t\t\t\t\t{$sql_fora}\n\t\t\t\t\tAND t.topic_id = p.topic_id\n\t\t\t\t\t{$sql_sort_join}\n\t\t\t\t\t{$sql_time}\n\t\t\t\tGROUP BY t.topic_id, {$sort_by_sql[$sort_key]}\n\t\t\t\tORDER BY {$sql_sort}"; $field = 'topic_id'; } $this->db->sql_transaction('begin'); // Only read one block of posts from the db and then cache it $result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start); while ($row = $this->db->sql_fetchrow($result)) { $id_ary[] = $row[$field]; } $this->db->sql_freeresult($result); // retrieve the total result count if needed if (!$result_count) { if ($type == 'posts') { $sql_count = "SELECT COUNT(*) as result_count\n\t\t\t\t\tFROM " . $sql_sort_table . POSTS_TABLE . ' p' . ($firstpost_only ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "\n\t\t\t\t\tWHERE {$sql_author}\n\t\t\t\t\t\t{$sql_topic_id}\n\t\t\t\t\t\t{$sql_firstpost}\n\t\t\t\t\t\t{$m_approve_fid_sql}\n\t\t\t\t\t\t{$sql_fora}\n\t\t\t\t\t\t{$sql_sort_join}\n\t\t\t\t\t\t{$sql_time}"; } else { $sql_count = "SELECT COUNT(*) as result_count\n\t\t\t\t\tFROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p\n\t\t\t\t\tWHERE {$sql_author}\n\t\t\t\t\t\t{$sql_topic_id}\n\t\t\t\t\t\t{$sql_firstpost}\n\t\t\t\t\t\t{$m_approve_fid_sql}\n\t\t\t\t\t\t{$sql_fora}\n\t\t\t\t\t\tAND t.topic_id = p.topic_id\n\t\t\t\t\t\t{$sql_sort_join}\n\t\t\t\t\t\t{$sql_time}\n\t\t\t\t\tGROUP BY t.topic_id, {$sort_by_sql[$sort_key]}"; } $this->db->sql_query($sql_count); $result_count = (int) $this->db->sql_fetchfield('result_count'); if (!$result_count) { return false; } } $this->db->sql_transaction('commit'); if ($start >= $result_count) { $start = floor(($result_count - 1) / $per_page) * $per_page; $result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start); while ($row = $this->db->sql_fetchrow($result)) { $id_ary[] = (int) $row[$field]; } $this->db->sql_freeresult($result); $id_ary = array_unique($id_ary); } if (sizeof($id_ary)) { $this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir); $id_ary = array_slice($id_ary, 0, $per_page); return $result_count; } return false; }
/** * Processes hookup set activedate requests * * @param \phpbb\event\data $event * @param bool $is_owner */ protected function process_set_activedate($event, $is_owner) { $set_active_set = $this->request->is_set('set_active', \phpbb\request\request_interface::POST) || $this->request->is_set('set_active', \phpbb\request\request_interface::GET); $set_active = $this->request->variable('set_active', 0); if (!$set_active_set) { return array(); } if (!$is_owner) { return array($this->user->lang('NOT_AUTH_HOOKUP')); } if ($set_active && !isset($this->hookup->hookup_dates[$set_active])) { trigger_error('NO_DATE'); } $active_date_formatted = $set_active != 0 ? $this->user->format_date($this->hookup->hookup_dates[$set_active]['date_time']) : '-'; $topic_id = $event['topic_id']; $forum_id = $event['forum_id']; $viewtopic_url = append_sid("{$this->phpbb_root_path}viewtopic.{$this->phpEx}?f={$forum_id}&t={$topic_id}"); if (confirm_box(true)) { $title_prefix = $this->request->variable('title_prefix', false); $send_email = $this->request->variable('send_email', false); $post_reply = $this->request->variable('post_reply', false); $topic_data = $event['topic_data']; $new_title = preg_replace('#^(\\[.+?\\] )?#', $set_active != 0 ? '[' . $this->user->format_date($this->hookup->hookup_dates[$set_active]['date_time'], $this->user->lang['HOOKUP_DATEFORMAT_TITLE']) . '] ' : '', $event['topic_data']['topic_title']); /** * Perform additional actions when active date is set * * @event gn36.hookup.set_activedate_confirmed * @var bool title_prefix User wants to have a title prefix added * @var bool send_email User wants E-Mails to be sent * @var bool post_reply User wants to post a reply to the topic * @var int set_active Date selected as active (0 means reset of active date) * @var string new_title The new topic title that will be present after the update * @var int topic_id ID of the topic of the hookup * @var int forum_id ID of the forum the topic is in * @var array topic_data Topic data as received from core.viewtopic_assign_template_vars_before * @since 1.0.0-dev */ $vars = array('title_prefix', 'send_email', 'post_reply', 'set_active', 'new_title', 'topic_id', 'forum_id', 'topic_data'); extract($this->phpbb_dispatcher->trigger_event('gn36.hookup.set_activedate_confirmed', compact($vars))); //insert active date (short format) into topic title. this will use language //and timezone of the "active maker" but the alternative would be //to query the HOOKUP_DATES table every time we need the topic title if ($set_active == 0 || $title_prefix) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET hookup_active_date = ' . (int) $set_active . ",\n\t\t\t\t\t\t\ttopic_title = '" . $this->db->sql_escape($new_title) . "'\n\t\t\t\t\t\t\t\t\tWHERE topic_id = {$topic_id}"; $this->db->sql_query($sql); $sql = "UPDATE " . POSTS_TABLE . "\n\t\t\t\t\t\tSET post_subject='" . $this->db->sql_escape($new_title) . "'\n\t\t\t\t\t\t\t\tWHERE post_id = {$event['topic_data']['topic_first_post_id']}"; $this->db->sql_query($sql); } else { //only set hookup_active_date $sql = 'UPDATE ' . TOPICS_TABLE . ' SET hookup_active_date = ' . (int) $set_active . "\n\t\t\t\t\t\t\t\tWHERE topic_id = {$topic_id}"; $this->db->sql_query($sql); } //notify all members about active date if ($set_active && $send_email && !empty($this->hookup->hookup_users)) { if ($this->messenger == null) { include_once $this->phpbb_root_path . 'includes/functions_messenger.' . $this->phpEx; $this->messenger = new \messenger(); } $messenger = $this->messenger; $title_without_date = preg_replace('#^(\\[.+?\\] )#', '', $event['topic_data']['topic_title']); $sql = 'SELECT u.user_id, u.username, u.user_lang, u.user_dateformat, u.user_email, u.user_jabber, u.user_notify_type FROM ' . USERS_TABLE . " u\n\t\t\t\t\tWHERE " . $this->db->sql_in_set('user_id', array_keys($this->hookup->hookup_users)); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $messenger->template('@gn36_hookup/hookup_active_date', $row['user_lang']); $messenger->to($row['user_email'], $row['username']); $messenger->im($row['user_jabber'], $row['username']); $messenger->assign_vars(array('USERNAME' => $row['username'], 'TOPIC_TITLE' => $title_without_date, 'U_TOPIC' => generate_board_url() . "/viewtopic.{$this->phpEx}?f={$forum_id}&t={$topic_id}", 'ACTIVE_DATE' => $this->user->format_date($this->hookup->hookup_dates[$set_active]['date_time'], $row['user_dateformat']), 'ACTIVE_DATE_SHORT' => $this->user->format_date($this->hookup->hookup_dates[$set_active]['date_time'], $this->user->lang['HOOKUP_DATEFORMAT']))); $messenger->send($row['user_notify_type']); } $this->db->sql_freeresult($result); $messenger->save_queue(); } //post reply to this topic. Again this can only be in the "active maker"s language if ($set_active && $post_reply) { $message = $this->user->lang['SET_ACTIVE_POST_TEMPLATE']; $message = str_replace('{ACTIVE_DATE}', $this->user->format_date($this->hookup->hookup_dates[$set_active]['date_time'], $this->user->lang['HOOKUP_DATEFORMAT_POST']), $message); //TODO: functions_post_oo! //$post = new post($topic_id); //$post->post_text = $message; //$post->submit(); } meta_refresh(3, $viewtopic_url); $message = ($set_active != 0 ? sprintf($this->user->lang['ACTIVE_DATE_SET'], $active_date_formatted) : $this->user->lang['ACTIVE_DATE_UNSET']) . '<br /><br />' . sprintf($this->user->lang['RETURN_TOPIC'], '<a href="' . $viewtopic_url . '">', '</a>'); trigger_error($message); } else { $s_hidden_fields = build_hidden_fields(array('t' => $topic_id, 'set_active' => $set_active)); if ($set_active != 0) { confirm_box(false, sprintf($this->user->lang['SET_ACTIVE_CONFIRM'], $active_date_formatted), $s_hidden_fields, '@gn36_hookup/hookup_active_date_confirm.html'); } else { confirm_box(false, 'UNSET_ACTIVE', $s_hidden_fields); } } return array(); }
public function posts_merging($event) { $mode = $event['mode']; $subject = $event['subject']; $username = $event['username']; $topic_type = $event['topic_type']; $poll = $event['poll']; $data = $event['data']; $update_message = $event['update_message']; $update_search_index = $event['update_search_index']; $current_time = time(); $do_not_merge_with_previous = $this->request->variable('posts_merging_option', false); if (!$do_not_merge_with_previous && !$this->helper->post_needs_approval($data) && in_array($mode, array('reply', 'quote')) && $this->merge_interval && !$this->helper->excluded_from_merge($data)) { $merge_post_data = $this->helper->get_last_post_data($data); // Do not merge if there's no last post data, the post is locked or allowed merge period has left if (!$merge_post_data || $merge_post_data['post_edit_locked'] || $current_time - (int) $merge_post_data['topic_last_post_time'] > $this->merge_interval || !$this->user->data['is_registered']) { return; } // Also, don't let user to violate attachments limit by posts merging // In this case, also don't merge posts and return // Exceptions are administrators and forum moderators $num_old_attachments = $this->helper->count_post_attachments((int) $merge_post_data['post_id']); $num_new_attachments = sizeof($data['attachment_data']); $total_attachments_count = $num_old_attachments + $num_new_attachments; if ($total_attachments_count > $this->config['max_attachments'] && !$this->auth->acl_get('a_') && !$this->auth->acl_get('m_', (int) $data['forum_id'])) { return; } $data['post_id'] = (int) $merge_post_data['post_id']; $merge_post_data['post_attachment'] = $total_attachments_count ? 1 : 0; // Decode old message and addon $merge_post_data['post_text'] = $this->helper->prepare_text_for_merge($merge_post_data); $data['message'] = $this->helper->prepare_text_for_merge($data); // Handle inline attachments BBCode in old message if ($num_new_attachments) { $merge_post_data['post_text'] = preg_replace('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#e', "'[attachment='.(\\1 + {$num_new_attachments}).']\\2[/attachment]'", $merge_post_data['post_text']); } // Prepare message separator $this->user->add_lang_ext('rxu/PostsMerging', 'posts_merging'); $interval = $this->helper->get_time_interval($current_time, $merge_post_data['post_time']); $time = array(); $time[] = $interval->h ? $this->user->lang('D_HOURS', $interval->h) : null; $time[] = $interval->i ? $this->user->lang('D_MINUTES', $interval->i) : null; $time[] = $interval->s ? $this->user->lang('D_SECONDS', $interval->s) : null; $separator = $this->user->lang('MERGE_SEPARATOR', implode(' ', $time)); // Merge subject if (!empty($subject) && $subject != $merge_post_data['post_subject'] && $merge_post_data['post_id'] != $merge_post_data['topic_first_post_id']) { $separator .= sprintf($this->user->lang['MERGE_SUBJECT'], $subject); } // Merge posts $merge_post_data['post_text'] = $merge_post_data['post_text'] . $separator . $data['message']; // Make sure the message is safe $this->type_cast_helper->recursive_set_var($merge_post_data['post_text'], '', true); //Prepare post for submit $options = ''; $warn_msg = generate_text_for_storage($merge_post_data['post_text'], $merge_post_data['bbcode_uid'], $merge_post_data['bbcode_bitfield'], $options, $merge_post_data['enable_bbcode'], $merge_post_data['enable_magic_url'], $merge_post_data['enable_smilies']); // If $warn_msg is not empty, the merged message does not conform some restrictions // In this case we simply don't merge and return back to the function submit_post() if (!empty($warn_msg)) { return; } // Update post time and submit post to database $merge_post_data['post_time'] = $data['post_time'] = $current_time; $this->helper->submit_post_to_database($merge_post_data); // Submit attachments $this->helper->submit_attachments($data); // Update read tracking $this->helper->update_read_tracking($data); // If a username was supplied or the poster is a guest, we will use the supplied username. // Doing it this way we can use "...post by guest-username..." in notifications when // "guest-username" is supplied or ommit the username if it is not. $username = $username !== '' || !$this->user->data['is_registered'] ? $username : $this->user->data['username']; // Send Notifications // Despite the post_id is the same and users who've been already notified // won't be notified again about the same post_id, we send notifications // for new users possibly subscribed to it $notification_data = array_merge($data, array('topic_title' => isset($data['topic_title']) ? $data['topic_title'] : $subject, 'post_username' => $username, 'poster_id' => (int) $data['poster_id'], 'post_text' => $data['message'], 'post_time' => $merge_post_data['post_time'], 'post_subject' => $subject)); $this->notification_manager->add_notifications(array('notification.type.quote', 'notification.type.bookmark', 'notification.type.post'), $notification_data); // Update search index $this->helper->update_search_index($merge_post_data); //Generate redirection URL and redirecting $params = $add_anchor = ''; $params .= '&t=' . $data['topic_id']; $params .= '&p=' . $data['post_id']; $add_anchor = '#p' . $data['post_id']; $url = "{$this->phpbb_root_path}viewtopic.{$this->php_ext}"; $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor; /** * Modify the data for post submitting * * @event rxu.postsmerging.posts_merging_end * @var string mode Variable containing posting mode value * @var string subject Variable containing post subject value * @var string username Variable containing post author name * @var int topic_type Variable containing topic type value * @var array poll Array with the poll data for the post * @var array data Array with the data for the post * @var bool update_message Flag indicating if the post will be updated * @var bool update_search_index Flag indicating if the search index will be updated * @var string url The "Return to topic" URL * @since 2.0.0 */ $vars = array('mode', 'subject', 'username', 'topic_type', 'poll', 'data', 'update_message', 'update_search_index', 'url'); extract($this->phpbb_dispatcher->trigger_event('rxu.postsmerging.posts_merging_end', compact($vars))); redirect($url); } }
/** * Generate the debug output string * * @param \phpbb\db\driver\driver_interface $db Database connection * @param \phpbb\config\config $config Config object * @param \phpbb\auth\auth $auth Auth object * @param \phpbb\user $user User object * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher * @return string */ function phpbb_generate_debug_output(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\auth\auth $auth, \phpbb\user $user, \phpbb\event\dispatcher_interface $phpbb_dispatcher) { $debug_info = array(); // Output page creation time if (defined('PHPBB_DISPLAY_LOAD_TIME')) { if (isset($GLOBALS['starttime'])) { $totaltime = microtime(true) - $GLOBALS['starttime']; $debug_info[] = sprintf('<abbr title="SQL time: %.3fs / PHP time: %.3fs">Time: %.3fs</abbr>', $db->get_sql_time(), $totaltime - $db->get_sql_time(), $totaltime); } $debug_info[] = sprintf('<abbr title="Cached: %d">Queries: %d</abbr>', $db->sql_num_queries(true), $db->sql_num_queries()); $memory_usage = memory_get_peak_usage(); if ($memory_usage) { $memory_usage = get_formatted_filesize($memory_usage); $debug_info[] = 'Peak Memory Usage: ' . $memory_usage; } } if (defined('DEBUG')) { $debug_info[] = 'GZIP: ' . ($config['gzip_compress'] && @extension_loaded('zlib') ? 'On' : 'Off'); if ($user->load) { $debug_info[] = 'Load: ' . $user->load; } if ($auth->acl_get('a_')) { $debug_info[] = '<a href="' . build_url() . '&explain=1">SQL Explain</a>'; } } /** * Modify debug output information * * @event core.phpbb_generate_debug_output * @var array debug_info Array of strings with debug information * * @since 3.1.0-RC3 */ $vars = array('debug_info'); extract($phpbb_dispatcher->trigger_event('core.phpbb_generate_debug_output', compact($vars))); return implode(' | ', $debug_info); }
/** * Set topic visibility * * Allows approving (which is akin to undeleting/restore) or soft deleting an entire topic. * Calls set_post_visibility as needed. * * Note: By default, when a soft deleted topic is restored. Only posts that * were approved at the time of soft deleting, are being restored. * Same applies to soft deleting. Only approved posts will be marked * as soft deleted. * If you want to update all posts, use the force option. * * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} * @param $topic_id mixed Topic ID to act on * @param $forum_id int Forum where $topic_id is found * @param $user_id int User performing the action * @param $time int Timestamp when the action is performed * @param $reason string Reason why the visibilty was changed. * @param $force_update_all bool Force to update all posts within the topic * @return array Changed topic data, empty array if an error occured. */ public function set_topic_visibility($visibility, $topic_id, $forum_id, $user_id, $time, $reason, $force_update_all = false) { if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE))) { return array(); } if (!$force_update_all) { $sql = 'SELECT topic_visibility, topic_delete_time FROM ' . $this->topics_table . ' WHERE topic_id = ' . (int) $topic_id; $result = $this->db->sql_query($sql); $original_topic_data = $this->db->sql_fetchrow($result); $this->db->sql_freeresult($result); if (!$original_topic_data) { // The topic does not exist... return array(); } } if (!function_exists('truncate_string')) { include $this->phpbb_root_path . 'includes/functions_content.' . $this->php_ext; } // Note, we do not set a reason for the posts, just for the topic $data = array('topic_visibility' => (int) $visibility, 'topic_delete_user' => (int) $user_id, 'topic_delete_time' => (int) $time ?: time(), 'topic_delete_reason' => truncate_string($reason, 255, 255, false)); /** * Perform actions right before the query to change topic visibility * * @event core.set_topic_visibility_before_sql * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} * @var int topic_id Topic of the post IDs to be modified. * @var int forum_id Forum ID that the topic_id resides in. * @var int user_id User ID doing this action. * @var int timestamp Timestamp of this action. * @var string reason Reason specified by the user for this change. * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state. * @var array data The data array for this action. * @since 3.1.10-RC1 */ $vars = array('visibility', 'topic_id', 'forum_id', 'user_id', 'timestamp', 'reason', 'force_update_all', 'data'); extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_before_sql', compact($vars))); $sql = 'UPDATE ' . $this->topics_table . ' SET ' . $this->db->sql_build_array('UPDATE', $data) . ' WHERE topic_id = ' . (int) $topic_id; $this->db->sql_query($sql); if (!$this->db->sql_affectedrows()) { return array(); } if (!$force_update_all && $original_topic_data['topic_delete_time'] && $original_topic_data['topic_visibility'] == ITEM_DELETED && $visibility == ITEM_APPROVED) { // If we're restoring a topic we only restore posts, that were soft deleted through the topic soft deletion. $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility'], $original_topic_data['topic_delete_time']); } else { if (!$force_update_all && $original_topic_data['topic_visibility'] == ITEM_APPROVED && $visibility == ITEM_DELETED) { // If we're soft deleting a topic we only mark approved posts as soft deleted. $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility']); } else { $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true); } } /** * Perform actions after all steps to changing topic visibility * * @event core.set_topic_visibility_after * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} * @var int topic_id Topic of the post IDs to be modified. * @var int forum_id Forum ID that the topic_id resides in. * @var int user_id User ID doing this action. * @var int timestamp Timestamp of this action. * @var string reason Reason specified by the user for this change. * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state. * @var array data The data array for this action. * @since 3.1.10-RC1 */ $vars = array('visibility', 'topic_id', 'forum_id', 'user_id', 'timestamp', 'reason', 'force_update_all', 'data'); extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_after', compact($vars))); return $data; }
/** * Processes the users's profile-field data and generates an avatar (when available). * It also tries to determine the faction of a gaming character, based on the data. * * @var array profile_row Array with users profile field data * @var array tpl_fields Array with template data fields * * @return array $tpl_fields Array with modified template data fields */ public function process_pf_show($profile_row, $tpl_fields) { $avatars_path = !empty($this->pbwow_config['avatars_path']) ? $this->root_path . $this->pbwow_config['avatars_path'] . '/' : false; if (empty($profile_row)) { return $tpl_fields; } if ($this->avatars_enabled_full && $avatars_path) { $avatar = ''; $faction = 0; $width = $height = 64; // A listener can set this variable to `true` when it overrides this function $function_override = false; /** * Event to modify the profile field processing script before the supported games are processed * * @event paybas.pbwow.modify_process_pf_before * @var array profile_row Array with users profile field data * @var array tpl_fields Array with template data fields * @var string avatars_path The path to the dir containing the game-avatars * @var string avatar Filename of the avatar img * @var int width The width of the avatar img (in pixels) * @var int height The height of the avatar img (in pixels) * @var int faction The faction of the character * @var bool function_override Return the results right after this, or continue? * @since 3.0.0 */ $vars = array('profile_row', 'tpl_fields', 'avatars_path', 'avatar', 'width', 'height', 'faction', 'function_override'); extract($this->dispatcher->trigger_event('paybas.pbwow.modify_process_pf_before', compact($vars))); if ($function_override) { return $tpl_fields; } $wow_r = isset($tpl_fields['row']['PROFILE_PB_WOW_RACE_VALUE_RAW']) ? $profile_row['pb_wow_race']['value'] - 1 : null; // Get the WoW race ID $wow_c = isset($tpl_fields['row']['PROFILE_PB_WOW_CLASS_VALUE_RAW']) ? $profile_row['pb_wow_class']['value'] - 1 : null; // Get the WoW class ID $wow_g = isset($tpl_fields['row']['PROFILE_PB_WOW_GENDER_VALUE_RAW']) ? $profile_row['pb_wow_gender']['value'] - 1 : null; // Get the WoW gender ID $wow_l = isset($tpl_fields['row']['PROFILE_PB_WOW_LEVEL_VALUE_RAW']) ? $profile_row['pb_wow_level']['value'] - 1 : null; // Get the WoW level $d3_c = isset($tpl_fields['row']['PROFILE_PB_DIABLO_CLASS_VALUE_RAW']) ? $profile_row['pb_diablo_class']['value'] - 1 : null; // Get the Diablo class ID $d3_f = isset($tpl_fields['row']['PROFILE_PB_DIABLO_FOLLOWER_VALUE_RAW']) ? $profile_row['pb_diablo_follower']['value'] - 1 : null; // Get the Diablo class ID $d3_g = isset($tpl_fields['row']['PROFILE_PB_DIABLO_GENDER_VALUE_RAW']) ? $profile_row['pb_diablo_gender']['value'] - 1 : null; // Get the Diablo gender ID $ws_r = isset($tpl_fields['row']['PROFILE_PB_WILDSTAR_RACE_VALUE_RAW']) ? $profile_row['pb_wildstar_race']['value'] - 1 : null; // Get the Wildstar race ID $ws_c = isset($tpl_fields['row']['PROFILE_PB_WILDSTAR_CLASS_VALUE_RAW']) ? $profile_row['pb_wildstar_class']['value'] - 1 : null; // Get the Wildstar class ID $ws_g = isset($tpl_fields['row']['PROFILE_PB_WILDSTAR_GENDER_VALUE_RAW']) ? $profile_row['pb_wildstar_gender']['value'] - 1 : null; // Get the Wildstar gender ID $ws_p = isset($tpl_fields['row']['PROFILE_PB_WILDSTAR_PATH_VALUE_RAW']) ? $profile_row['pb_wildstar_path']['value'] - 1 : null; // Get the Wildstar path ID //$bnet_h = (isset($tpl_fields['row']['PROFILE_PB_BNET_HOST_VALUE'])) ? $tpl_fields['row']['PROFILE_PB_BNET_HOST_VALUE'] : NULL; // Get the Battle.net host //$bnet_r = (isset($tpl_fields['row']['PROFILE_PB_BNET_REALM_VALUE'])) ? $tpl_fields['row']['PROFILE_PB_BNET_REALM_VALUE'] : NULL; // Get the Battle.net realm //$bnet_n = (isset($tpl_fields['row']['PROFILE_PB_BNET_NAME_VALUE'])) ? $tpl_fields['row']['PROFILE_PB_BNET_NAME_VALUE'] : NULL; // Get the Battle.net character name //$bnet_u = isset($tpl_fields['row']['PROFILE_PB_BNET_URL_VALUE']) ? $profile_row['pb_bnet_url']['value'] : null; // Get the Battle.net avatar $bnet_a = isset($tpl_fields['row']['PROFILE_PB_BNET_AVATAR_VALUE']) ? $profile_row['pb_bnet_avatar']['value'] : null; // Get the Battle.net avatar // I know it looks silly, but we need this to fix icon classes in templates if ($wow_r > 0) { $tpl_fields['row']['PROFILE_PB_WOW_RACE_VALUE_RAW'] = $wow_r; } if ($wow_c > 0) { $tpl_fields['row']['PROFILE_PB_WOW_CLASS_VALUE_RAW'] = $wow_c; } if ($wow_g > 0) { $tpl_fields['row']['PROFILE_PB_WOW_GENDER_VALUE_RAW'] = $wow_g; } if ($d3_c > 0) { $tpl_fields['row']['PROFILE_PB_DIABLO_CLASS_VALUE_RAW'] = $d3_c; } if ($d3_f > 0) { $tpl_fields['row']['PROFILE_PB_DIABLO_FOLLOWER_VALUE_RAW'] = $d3_f; } if ($d3_g > 0) { $tpl_fields['row']['PROFILE_PB_DIABLO_GENDER_VALUE_RAW'] = $d3_g; } if ($ws_r > 0) { $tpl_fields['row']['PROFILE_PB_WILDSTAR_RACE_VALUE_RAW'] = $ws_r; } if ($ws_c > 0) { $tpl_fields['row']['PROFILE_PB_WILDSTAR_CLASS_VALUE_RAW'] = $ws_c; } if ($ws_g > 0) { $tpl_fields['row']['PROFILE_PB_WILDSTAR_GENDER_VALUE_RAW'] = $ws_g; } if ($ws_p > 0) { $tpl_fields['row']['PROFILE_PB_WILDSTAR_PATH_VALUE_RAW'] = $ws_p; } $valid = false; // determines whether a specific profile field combination is valid (for the game) $avail = false; // determines whether an avatar image is available for the profile field combination /* Battle.net API */ //if ($bneth !== NULL && $bnet_r !== NULL && $bnet_n !== NULL && $user_id !== 0 && $bnet_a !== NULL) { if ($bnet_a !== null) { if (isset($wow_r)) { $faction = in_array($wow_r, array(1, 3, 4, 7, 11, 12)) ? 1 : 2; } $width = 84; $height = 84; $avatars_path = ''; $avatar = $bnet_a; } else { if ($wow_r !== null) { /* Remapping options */ // $R = $wow_r; // $wow_r = ($R == 1) ? 4 : $wow_r; // first item in CPF (with "none" = 0), map to race 4 (Night Elf) // $wow_r = ($R == 2) ? 9 : $wow_r; // second item in CPF, map to race 9 (Goblin) // $wow_r = ($R == 3) ? 12 : $wow_r; // third item in CPF, map to race 12 (Worgen) // $wow_r = ($R == 4) ? 2 : $wow_r; // fourth item in CPF, map to race 2 (Orc) // etc. etc. // $C = $wow_c; // $wow_c = ($C == 1) ? 1 : $wow_c; // first item in CPF (with "none" = 0), map to class 1 (Warrior) // $wow_c = ($C == 2) ? 4 : $wow_c; // second item in CPF, map to class 4 (Rogue) // $wow_c = ($C == 3) ? 6 : $wow_c; // third item in CPF, map to class 6 (Death Knight) // etc. etc. /* For reference wow_r = 1 > Human wow_r = 2 > Orc wow_r = 3 > Dwarf wow_r = 4 > Night Elf wow_r = 5 > Undead wow_r = 6 > Tauren wow_r = 7 > Gnome wow_r = 8 > Troll wow_r = 9 > Goblin wow_r = 10 > Blood Elf wow_r = 11 > Draenei wow_r = 12 > Worgen wow_r = 13 > Pandaren wow_c = 1 > Warrior wow_c = 2 > Paladin wow_c = 3 > Hunter wow_c = 4 > Rogue wow_c = 5 > Priest wow_c = 6 > Death Knight wow_c = 7 > Shaman wow_c = 8 > Mage wow_c = 9 > Warlock wow_c = 10 > Monk wow_c = 11 > Druid */ $faction = 3; // Set faction to neutral, until we can determine correct faction switch ($wow_r) { case 1: // Human $valid = in_array($wow_c, array(1, 2, 3, 4, 5, 6, 8, 9, 10)) ? true : false; $avail = in_array($wow_c, array(1, 2, 4, 5, 6, 8, 9)) ? true : false; $faction = 1; break; case 2: // Orc $valid = in_array($wow_c, array(1, 3, 4, 6, 7, 8, 9, 10)) ? true : false; $avail = in_array($wow_c, array(1, 3, 4, 6, 7, 9)) ? true : false; $faction = 2; break; case 3: // Dwarf $valid = in_array($wow_c, array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) ? true : false; $avail = in_array($wow_c, array(1, 2, 3, 4, 5, 6)) ? true : false; $faction = 1; break; case 4: // Night Elf $valid = in_array($wow_c, array(1, 3, 4, 5, 6, 8, 10, 11)) ? true : false; $avail = in_array($wow_c, array(1, 3, 4, 5, 6, 11)) ? true : false; $faction = 1; break; case 5: // Undead $valid = in_array($wow_c, array(1, 3, 4, 5, 6, 8, 9, 10)) ? true : false; $avail = in_array($wow_c, array(1, 4, 5, 6, 8, 9)) ? true : false; $faction = 2; break; case 6: // Tauren $valid = in_array($wow_c, array(1, 2, 3, 5, 6, 7, 10, 11)) ? true : false; $avail = in_array($wow_c, array(1, 3, 6, 7, 11)) ? true : false; $faction = 2; break; case 7: // Gnome $valid = in_array($wow_c, array(1, 4, 5, 6, 8, 9, 10)) ? true : false; $avail = in_array($wow_c, array(1, 4, 6, 8, 9)) ? true : false; $faction = 1; break; case 8: // Troll $valid = in_array($wow_c, array(1, 3, 4, 5, 6, 7, 8, 9, 10, 11)) ? true : false; $avail = in_array($wow_c, array(1, 3, 4, 5, 6, 7, 8)) ? true : false; $faction = 2; break; case 9: // Goblin $valid = in_array($wow_c, array(1, 3, 4, 5, 6, 7, 8, 9)) ? true : false; //$avail = (in_array($c, array())) ? true : false; $faction = 2; break; case 10: // Blood Elf $valid = in_array($wow_c, array(1, 2, 3, 4, 5, 6, 8, 9, 10)) ? true : false; $avail = in_array($wow_c, array(2, 3, 4, 5, 6, 8, 9)) ? true : false; $faction = 2; break; case 11: // Draenei $valid = in_array($wow_c, array(1, 2, 3, 5, 6, 7, 8, 10)) ? true : false; $avail = in_array($wow_c, array(1, 2, 3, 5, 6, 7, 8)) ? true : false; $faction = 1; break; case 12: // Worgen $valid = in_array($wow_c, array(1, 3, 4, 5, 6, 8, 9, 11)) ? true : false; //$avail = (in_array($c, array())) ? true : false; $faction = 1; break; case 13: // Pandaren $valid = in_array($wow_c, array(1, 3, 4, 5, 7, 8, 10)) ? true : false; //$avail = (in_array($c, array())) ? true : false; $faction = 3; break; } $wow_g = max(0, $wow_g - 1); // 0 = none, 1 = male, 2 = female, but we need a 0/1 map if ($valid && $avail) { if ($wow_l >= 80) { $path = 'wow/80'; } else { if ($wow_l >= 70) { $path = 'wow/70'; } else { if ($wow_l >= 60) { $path = 'wow/60'; } else { $path = 'wow/default'; } } } $avatar = $path . '/' . $wow_g . '-' . $wow_r . '-' . $wow_c . '.gif'; $width = 64; $height = 64; } else { $avatar = 'wow/new/' . $wow_r . '-' . $wow_g . '.jpg'; $width = 84; $height = 84; } } else { if ($d3_c !== null) { switch ($d3_c) { case 1: // Barbarian $avatar = 'barbarian'; break; case 2: // Demon Hunter $avatar = 'demonhunter'; break; case 3: // Monk $avatar = 'monk'; break; case 4: // Witch Doctor $avatar = 'witchdoctor'; break; case 5: // Wizard $avatar = 'wizard'; break; case 6: // Crusader $avatar = 'crusader'; break; } $d3_g = isset($d3_g) && $d3_g > 1 ? 'female' : 'male'; $avatar = 'diablo/' . $avatar . '_' . $d3_g . '.png'; $width = 64; $height = 64; $faction = 3; } else { if ($ws_r !== null) { /* For reference ws_r = 1 > Human ws_r = 2 > Cassian ws_r = 3 > Granok ws_r = 4 > Draken ws_r = 5 > Aurin ws_r = 6 > Chua ws_r = 7 > Mordesh ws_r = 8 > Mechari ws_c = 1 > Warrior ws_c = 2 > Esper ws_c = 3 > Spellslinger ws_c = 4 > Stalker ws_c = 5 > Medic ws_c = 6 > Engineer */ $faction = 3; // Set faction to neutral, until we can determine correct faction switch ($ws_r) { case 1: // Human $valid = $avail = in_array($ws_c, array(1, 2, 3, 4, 5, 6)) ? true : false; $faction = 1; break; case 2: // Cassian $valid = $avail = in_array($ws_c, array(1, 2, 3, 4, 5, 6)) ? true : false; $faction = 2; break; case 3: // Granok $valid = $avail = in_array($ws_c, array(1, 5, 6)) ? true : false; $faction = 1; break; case 4: // Draken $valid = $avail = in_array($ws_c, array(1, 3, 4)) ? true : false; $faction = 2; break; case 5: // Aurin $valid = $avail = in_array($ws_c, array(2, 3, 4)) ? true : false; $faction = 1; break; case 6: // Chua $valid = $avail = in_array($ws_c, array(2, 3, 5, 6)) ? true : false; $faction = 2; break; case 7: // Mordesh $valid = $avail = in_array($ws_c, array(1, 3, 4, 5, 6)) ? true : false; $faction = 1; break; case 8: // Mechari $valid = $avail = in_array($ws_c, array(1, 4, 5, 6)) ? true : false; $faction = 2; break; } $ws_g = max(0, $ws_g - 1); // 0 = none, 1 = male, 2 = female, but we need a 0/1 map if ($valid) { //$avatar = 'wildstar/' . $ws_r . '-' . $wsg . '-' . $ws_c . '.jpg'; // Valid $avatar = 'wildstar/' . $ws_r . '.jpg'; // Valid } else { $avatar = 'wildstar/' . $ws_r . '.jpg'; // Invalid, show generic race avatar } $width = 64; $height = 64; } } } } /** * Event to modify the profile field processing script after the supported games are processed * * @event paybas.pbwow.modify_process_pf_after * @var array profile_row Array with users profile field data * @var array tpl_fields Array with template data fields * @var string avatars_path The path to the dir containing the game-avatars * @var string avatar Filename of the avatar img * @var bool valid Whether an PF-value combination is valid (only used in certain cases) * @var bool avail Whether an avatar is available (only used in certain cases) * @var int width The width of the avatar img (in pixels) * @var int height The height of the avatar img (in pixels) * @var int faction The faction of the character * @since 3.0.0 */ $vars = array('profile_row', 'tpl_fields', 'avatars_path', 'avatar', 'valid', 'avail', 'width', 'height', 'faction'); extract($this->dispatcher->trigger_event('paybas.pbwow.modify_process_pf_after', compact($vars))); // Add to template fields if ($faction || $avatar) { $tpl_fields['row'] += array('PROFILE_PBFACTION' => $faction ? $faction : false, 'PROFILE_PBAVATAR' => '<img src="' . $avatars_path . $avatar . '" width="' . $width . '" height="' . $height . '" alt="" />'); } } return $tpl_fields; }
/** * {@inheritDoc} */ public function get_logs($mode, $count_logs = true, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $log_time = 0, $sort_by = 'l.log_time DESC', $keywords = '') { $this->entry_count = 0; $this->last_page_offset = $offset; $topic_id_list = $reportee_id_list = array(); $profile_url = $this->get_is_admin() && $this->phpbb_admin_path ? append_sid("{$this->phpbb_admin_path}index.{$this->php_ext}", 'i=users&mode=overview') : append_sid("{$this->phpbb_root_path}memberlist.{$this->php_ext}", 'mode=viewprofile'); switch ($mode) { case 'admin': $log_type = LOG_ADMIN; $sql_additional = ''; break; case 'mod': $log_type = LOG_MOD; $sql_additional = ''; if ($topic_id) { $sql_additional = 'AND l.topic_id = ' . (int) $topic_id; } else { if (is_array($forum_id)) { $sql_additional = 'AND ' . $this->db->sql_in_set('l.forum_id', array_map('intval', $forum_id)); } else { if ($forum_id) { $sql_additional = 'AND l.forum_id = ' . (int) $forum_id; } } } break; case 'user': $log_type = LOG_USERS; $sql_additional = 'AND l.reportee_id = ' . (int) $user_id; break; case 'users': $log_type = LOG_USERS; $sql_additional = ''; break; case 'critical': $log_type = LOG_CRITICAL; $sql_additional = ''; break; default: $log_type = false; $sql_additional = ''; } /** * Overwrite log type and limitations before we count and get the logs * * NOTE: if log_type is false, no entries will be returned. * * @event core.get_logs_modify_type * @var string mode Mode of the entries we display * @var bool count_logs Do we count all matching entries? * @var int limit Limit the number of entries * @var int offset Offset when fetching the entries * @var mixed forum_id Limit entries to the forum_id, * can also be an array of forum_ids * @var int topic_id Limit entries to the topic_id * @var int user_id Limit entries to the user_id * @var int log_time Limit maximum age of log entries * @var string sort_by SQL order option * @var string keywords Will only return entries that have the * keywords in log_operation or log_data * @var string profile_url URL to the users profile * @var int log_type Limit logs to a certain type. If log_type * is false, no entries will be returned. * @var string sql_additional Additional conditions for the entries, * e.g.: 'AND l.forum_id = 1' * @since 3.1.0-a1 */ $vars = array('mode', 'count_logs', 'limit', 'offset', 'forum_id', 'topic_id', 'user_id', 'log_time', 'sort_by', 'keywords', 'profile_url', 'log_type', 'sql_additional'); extract($this->dispatcher->trigger_event('core.get_logs_modify_type', compact($vars))); if ($log_type === false) { $this->last_page_offset = 0; return array(); } $sql_keywords = ''; if (!empty($keywords)) { // Get the SQL condition for our keywords $sql_keywords = $this->generate_sql_keyword($keywords); } $get_logs_sql_ary = array('SELECT' => 'l.*, u.username, u.username_clean, u.user_colour', 'FROM' => array($this->log_table => 'l', USERS_TABLE => 'u'), 'WHERE' => 'l.log_type = ' . (int) $log_type . "\n\t\t\t\t\tAND l.user_id = u.user_id\n\t\t\t\t\t{$sql_keywords}\n\t\t\t\t\t{$sql_additional}", 'ORDER_BY' => $sort_by); if ($log_time) { $get_logs_sql_ary['WHERE'] = 'l.log_time >= ' . (int) $log_time . ' AND ' . $get_logs_sql_ary['WHERE']; } /** * Modify the query to obtain the logs data * * @event core.get_logs_main_query_before * @var array get_logs_sql_ary The array in the format of the query builder with the query * to get the log count and the log list * @var string mode Mode of the entries we display * @var bool count_logs Do we count all matching entries? * @var int limit Limit the number of entries * @var int offset Offset when fetching the entries * @var mixed forum_id Limit entries to the forum_id, * can also be an array of forum_ids * @var int topic_id Limit entries to the topic_id * @var int user_id Limit entries to the user_id * @var int log_time Limit maximum age of log entries * @var string sort_by SQL order option * @var string keywords Will only return entries that have the * keywords in log_operation or log_data * @var string profile_url URL to the users profile * @var int log_type Limit logs to a certain type. If log_type * is false, no entries will be returned. * @var string sql_additional Additional conditions for the entries, * e.g.: 'AND l.forum_id = 1' * @since 3.1.5-RC1 */ $vars = array('get_logs_sql_ary', 'mode', 'count_logs', 'limit', 'offset', 'forum_id', 'topic_id', 'user_id', 'log_time', 'sort_by', 'keywords', 'profile_url', 'log_type', 'sql_additional'); extract($this->dispatcher->trigger_event('core.get_logs_main_query_before', compact($vars))); if ($count_logs) { $count_logs_sql_ary = $get_logs_sql_ary; $count_logs_sql_ary['SELECT'] = 'COUNT(l.log_id) AS total_entries'; unset($count_logs_sql_ary['ORDER_BY']); $sql = $this->db->sql_build_query('SELECT', $count_logs_sql_ary); $result = $this->db->sql_query($sql); $this->entry_count = (int) $this->db->sql_fetchfield('total_entries'); $this->db->sql_freeresult($result); if ($this->entry_count == 0) { // Save the queries, because there are no logs to display $this->last_page_offset = 0; return array(); } // Return the user to the last page that is valid while ($this->last_page_offset >= $this->entry_count) { $this->last_page_offset = max(0, $this->last_page_offset - $limit); } } $sql = $this->db->sql_build_query('SELECT', $get_logs_sql_ary); $result = $this->db->sql_query_limit($sql, $limit, $this->last_page_offset); $i = 0; $log = array(); while ($row = $this->db->sql_fetchrow($result)) { $row['forum_id'] = (int) $row['forum_id']; if ($row['topic_id']) { $topic_id_list[] = (int) $row['topic_id']; } if ($row['reportee_id']) { $reportee_id_list[] = (int) $row['reportee_id']; } $log_entry_data = array('id' => (int) $row['log_id'], 'reportee_id' => (int) $row['reportee_id'], 'reportee_username' => '', 'reportee_username_full' => '', 'user_id' => (int) $row['user_id'], 'username' => $row['username'], 'username_full' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $profile_url), 'ip' => $row['log_ip'], 'time' => (int) $row['log_time'], 'forum_id' => (int) $row['forum_id'], 'topic_id' => (int) $row['topic_id'], 'viewforum' => $row['forum_id'] && $this->auth->acl_get('f_read', $row['forum_id']) ? append_sid("{$this->phpbb_root_path}viewforum.{$this->php_ext}", 'f=' . $row['forum_id']) : false, 'action' => isset($this->user->lang[$row['log_operation']]) ? $row['log_operation'] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}'); /** * Modify the entry's data before it is returned * * @event core.get_logs_modify_entry_data * @var array row Entry data from the database * @var array log_entry_data Entry's data which is returned * @since 3.1.0-a1 */ $vars = array('row', 'log_entry_data'); extract($this->dispatcher->trigger_event('core.get_logs_modify_entry_data', compact($vars))); $log[$i] = $log_entry_data; if (!empty($row['log_data'])) { $log_data_ary = unserialize($row['log_data']); $log_data_ary = $log_data_ary !== false ? $log_data_ary : array(); if (isset($this->user->lang[$row['log_operation']])) { // Check if there are more occurrences of % than // arguments, if there are we fill out the arguments // array. It doesn't matter if we add more arguments than // placeholders. $num_args = 0; if (!is_array($this->user->lang[$row['log_operation']])) { $num_args = substr_count($this->user->lang[$row['log_operation']], '%'); } else { foreach ($this->user->lang[$row['log_operation']] as $case => $plural_string) { $num_args = max($num_args, substr_count($plural_string, '%')); } } if ($num_args - sizeof($log_data_ary) > 0) { $log_data_ary = array_merge($log_data_ary, array_fill(0, $num_args - sizeof($log_data_ary), '')); } $lang_arguments = array_merge(array($log[$i]['action']), $log_data_ary); $log[$i]['action'] = call_user_func_array(array($this->user, 'lang'), $lang_arguments); // If within the admin panel we do not censor text out if ($this->get_is_admin()) { $log[$i]['action'] = bbcode_nl2br($log[$i]['action']); } else { $log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action'])); } } else { if (!empty($log_data_ary)) { $log[$i]['action'] .= '<br />' . implode('', $log_data_ary); } } /* Apply make_clickable... has to be seen if it is for good. :/ // Seems to be not for the moment, reconsider later... $log[$i]['action'] = make_clickable($log[$i]['action']); */ } else { $log[$i]['action'] = $this->user->lang($log[$i]['action']); } $i++; } $this->db->sql_freeresult($result); /** * Get some additional data after we got all log entries * * @event core.get_logs_get_additional_data * @var array log Array with all our log entries * @var array topic_id_list Array of topic ids, for which we * get the permission data * @var array reportee_id_list Array of additional user IDs we * get the username strings for * @since 3.1.0-a1 */ $vars = array('log', 'topic_id_list', 'reportee_id_list'); extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', compact($vars))); if (sizeof($topic_id_list)) { $topic_auth = $this->get_topic_auth($topic_id_list); foreach ($log as $key => $row) { $log[$key]['viewtopic'] = isset($topic_auth['f_read'][$row['topic_id']]) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&t=' . $row['topic_id']) : false; $log[$key]['viewlogs'] = isset($topic_auth['m_'][$row['topic_id']]) ? append_sid("{$this->phpbb_root_path}mcp.{$this->php_ext}", 'i=logs&mode=topic_logs&t=' . $row['topic_id'], true, $this->user->session_id) : false; } } if (sizeof($reportee_id_list)) { $reportee_data_list = $this->get_reportee_data($reportee_id_list); foreach ($log as $key => $row) { if (!isset($reportee_data_list[$row['reportee_id']])) { continue; } $log[$key]['reportee_username'] = $reportee_data_list[$row['reportee_id']]['username']; $log[$key]['reportee_username_full'] = get_username_string('full', $row['reportee_id'], $reportee_data_list[$row['reportee_id']]['username'], $reportee_data_list[$row['reportee_id']]['user_colour'], false, $profile_url); } } /** * Allow modifying or execute extra final filter on log entries * * @event core.get_logs_after * @var array log Array with all our log entries * @var array topic_id_list Array of topic ids, for which we * get the permission data * @var array reportee_id_list Array of additional user IDs we * get the username strings for * @var string mode Mode of the entries we display * @var bool count_logs Do we count all matching entries? * @var int limit Limit the number of entries * @var int offset Offset when fetching the entries * @var mixed forum_id Limit entries to the forum_id, * can also be an array of forum_ids * @var int topic_id Limit entries to the topic_id * @var int user_id Limit entries to the user_id * @var int log_time Limit maximum age of log entries * @var string sort_by SQL order option * @var string keywords Will only return entries that have the * keywords in log_operation or log_data * @var string profile_url URL to the users profile * @var int log_type The type of logs it was filtered * @since 3.1.3-RC1 */ $vars = array('log', 'topic_id_list', 'reportee_id_list', 'mode', 'count_logs', 'limit', 'offset', 'forum_id', 'topic_id', 'user_id', 'log_time', 'sort_by', 'keywords', 'profile_url', 'log_type'); extract($this->dispatcher->trigger_event('core.get_logs_after', compact($vars))); return $log; }
/** * Get similar topics by matching topic titles * * NOTE: Currently requires MySQL due to the use of FULLTEXT indexes * and MATCH and AGAINST and UNIX_TIMESTAMP. MySQL FULLTEXT has built-in * English ignore words. We use phpBB's ignore words for non-English * languages. We also remove any admin-defined special ignore words. * * @param array $topic_data Array with topic data * @return null * @access public */ public function display_similar_topics($topic_data) { $topic_title = $this->clean_topic_title($topic_data['topic_title']); // If the cleaned up topic_title is empty, no need to continue if (empty($topic_title)) { return; } // Similar Topics query $sql_array = array('SELECT' => "f.forum_id, f.forum_name, t.*,\n\t\t\t\tMATCH (t.topic_title) AGAINST ('" . $this->db->sql_escape($topic_title) . "') AS score", 'FROM' => array(TOPICS_TABLE => 't'), 'LEFT_JOIN' => array(array('FROM' => array(FORUMS_TABLE => 'f'), 'ON' => 'f.forum_id = t.forum_id')), 'WHERE' => "MATCH (t.topic_title) AGAINST ('" . $this->db->sql_escape($topic_title) . "') >= 0.5\n\t\t\t\tAND t.topic_status <> " . ITEM_MOVED . ' AND t.topic_visibility = ' . ITEM_APPROVED . ' AND t.topic_time > (UNIX_TIMESTAMP() - ' . $this->config['similar_topics_time'] . ') AND t.topic_id <> ' . (int) $topic_data['topic_id']); // Add topic tracking data to the query (only if query caching is off) if ($this->user->data['is_registered'] && $this->config['load_db_lastread'] && !$this->config['similar_topics_cache']) { $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_TRACK_TABLE => 'tt'), 'ON' => 'tt.topic_id = t.topic_id AND tt.user_id = ' . $this->user->data['user_id']); $sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TRACK_TABLE => 'ft'), 'ON' => 'ft.forum_id = f.forum_id AND ft.user_id = ' . $this->user->data['user_id']); $sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time as f_mark_time'; } else { if ($this->config['load_anon_lastread'] || $this->user->data['is_registered']) { // Cookie based tracking copied from search.php $tracking_topics = $this->request->variable($this->config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE); $tracking_topics = $tracking_topics ? tracking_unserialize($tracking_topics) : array(); } } // We need to exclude passworded forums so we do not leak the topic title $passworded_forums = $this->user->get_passworded_forums(); // See if the admin set this forum to only search a specific group of other forums, and include them if (!empty($topic_data['similar_topic_forums'])) { // Remove any passworded forums from this group of forums we will be searching $included_forums = array_diff(explode(',', $topic_data['similar_topic_forums']), $passworded_forums); // if there's nothing left to display (user has no access to the forums we want to search) if (empty($included_forums)) { return; } $sql_array['WHERE'] .= ' AND ' . $this->db->sql_in_set('f.forum_id', $included_forums); } else { if (!empty($this->config['similar_topics_ignore'])) { // Add passworded forums to the exlude array $excluded_forums = array_unique(array_merge(explode(',', $this->config['similar_topics_ignore']), $passworded_forums)); $sql_array['WHERE'] .= ' AND ' . $this->db->sql_in_set('f.forum_id', $excluded_forums, true); } else { if (!empty($passworded_forums)) { $sql_array['WHERE'] .= ' AND ' . $this->db->sql_in_set('f.forum_id', $passworded_forums, true); } } } /** * Event to modify the sql_array for similar topics * * @event vse.similartopics.get_topic_data * @var array sql_array SQL array to get similar topics data * @since 1.3.0 */ $vars = array('sql_array'); extract($this->dispatcher->trigger_event('vse.similartopics.get_topic_data', compact($vars))); $sql = $this->db->sql_build_query('SELECT', $sql_array); $result = $this->db->sql_query_limit($sql, $this->config['similar_topics_limit'], 0, $this->config['similar_topics_cache']); // Grab icons $icons = $this->cache->obtain_icons(); $rowset = array(); while ($row = $this->db->sql_fetchrow($result)) { $similar_forum_id = (int) $row['forum_id']; $similar_topic_id = (int) $row['topic_id']; $rowset[$similar_topic_id] = $row; if ($this->auth->acl_get('f_read', $similar_forum_id)) { // Get topic tracking info if ($this->user->data['is_registered'] && $this->config['load_db_lastread'] && !$this->config['similar_topics_cache']) { $topic_tracking_info = get_topic_tracking($similar_forum_id, $similar_topic_id, $rowset, array($similar_forum_id => $row['f_mark_time'])); } else { if ($this->config['load_anon_lastread'] || $this->user->data['is_registered']) { $topic_tracking_info = get_complete_topic_tracking($similar_forum_id, $similar_topic_id); if (!$this->user->data['is_registered']) { $this->user->data['user_lastmark'] = isset($tracking_topics['l']) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $this->config['board_startdate']) : 0; } } } // Replies $replies = $this->content_visibility->get_count('topic_posts', $row, $similar_forum_id) - 1; // Get folder img, topic status/type related information $folder_img = $folder_alt = $topic_type = ''; $unread_topic = isset($topic_tracking_info[$similar_topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$similar_topic_id] ? true : false; topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); $topic_unapproved = $row['topic_visibility'] == ITEM_UNAPPROVED && $this->auth->acl_get('m_approve', $similar_forum_id) ? true : false; $posts_unapproved = $row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $this->auth->acl_get('m_approve', $similar_forum_id) ? true : false; //$topic_deleted = $row['topic_visibility'] == ITEM_DELETED; $u_mcp_queue = $topic_unapproved || $posts_unapproved ? append_sid("{$this->root_path}mcp.{$this->php_ext}", 'i=queue&mode=' . ($topic_unapproved ? 'approve_details' : 'unapproved_posts') . "&t={$similar_topic_id}", true, $this->user->session_id) : ''; //$u_mcp_queue = (!$u_mcp_queue && $topic_deleted) ? append_sid("{$this->root_path}mcp.{$this->php_ext}", "i=queue&mode=deleted_topics&t=$similar_topic_id", true, $this->user->session_id) : $u_mcp_queue; $base_url = append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id); $topic_row = array('TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 'FIRST_POST_TIME' => $this->user->format_date($row['topic_time']), 'LAST_POST_TIME' => $this->user->format_date($row['topic_last_post_time']), 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 'TOPIC_REPLIES' => $replies, 'TOPIC_VIEWS' => $row['topic_views'], 'TOPIC_TITLE' => $row['topic_title'], 'FORUM_TITLE' => $row['forum_name'], 'TOPIC_IMG_STYLE' => $folder_img, 'TOPIC_FOLDER_IMG' => $this->user->img($folder_img, $folder_alt), 'TOPIC_FOLDER_IMG_ALT' => $this->user->lang($folder_alt), 'TOPIC_ICON_IMG' => !empty($icons[$row['icon_id']]) ? $icons[$row['icon_id']]['img'] : '', 'TOPIC_ICON_IMG_WIDTH' => !empty($icons[$row['icon_id']]) ? $icons[$row['icon_id']]['width'] : '', 'TOPIC_ICON_IMG_HEIGHT' => !empty($icons[$row['icon_id']]) ? $icons[$row['icon_id']]['height'] : '', 'ATTACH_ICON_IMG' => $this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $similar_forum_id) && $row['topic_attachment'] ? $this->user->img('icon_topic_attach', $this->user->lang('TOTAL_ATTACHMENTS')) : '', 'UNAPPROVED_IMG' => $topic_unapproved || $posts_unapproved ? $this->user->img('icon_topic_unapproved', $topic_unapproved ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', 'S_UNREAD_TOPIC' => $unread_topic, 'S_TOPIC_REPORTED' => !empty($row['topic_reported']) && $this->auth->acl_get('m_report', $similar_forum_id) ? true : false, 'S_TOPIC_UNAPPROVED' => $topic_unapproved, 'S_POSTS_UNAPPROVED' => $posts_unapproved, 'S_HAS_POLL' => $row['poll_start'] ? true : false, 'U_NEWEST_POST' => append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id . '&view=unread') . '#unread', 'U_LAST_POST' => append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], 'U_VIEW_TOPIC' => append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id), 'U_VIEW_FORUM' => append_sid("{$this->root_path}viewforum.{$this->php_ext}", 'f=' . $similar_forum_id), 'U_MCP_REPORT' => append_sid("{$this->root_path}mcp.{$this->php_ext}", 'i=reports&mode=reports&f=' . $similar_forum_id . '&t=' . $similar_topic_id, true, $this->user->session_id), 'U_MCP_QUEUE' => $u_mcp_queue); /** * Event to modify the similar topics template block * * @event vse.similartopics.modify_topicrow * @var array row Array with similar topic data * @var array topic_row Template block array * @since 1.3.0 */ $vars = array('row', 'topic_row'); extract($this->dispatcher->trigger_event('vse.similartopics.modify_topicrow', compact($vars))); $this->template->assign_block_vars('similar', $topic_row); $this->pagination->generate_template_pagination($base_url, 'similar.pagination', 'start', $replies + 1, $this->config['posts_per_page'], 1, true, true); } } $this->db->sql_freeresult($result); $this->user->add_lang_ext('vse/similartopics', 'similar_topics'); $this->template->assign_vars(array('L_SIMILAR_TOPICS' => $this->user->lang('SIMILAR_TOPICS'), 'NEWEST_POST_IMG' => $this->user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), 'LAST_POST_IMG' => $this->user->img('icon_topic_latest', 'VIEW_LATEST_POST'), 'REPORTED_IMG' => $this->user->img('icon_topic_reported', 'TOPIC_REPORTED'), 'POLL_IMG' => $this->user->img('icon_topic_poll', 'TOPIC_POLL'))); }
/** * Processes hookup set activedate requests * * @param \phpbb\event\data $event * @param bool $is_owner */ protected function process_set_activedate($event, $is_owner) { $set_active_set = $this->request->is_set('set_active', \phpbb\request\request_interface::POST) || $this->request->is_set('set_active', \phpbb\request\request_interface::GET); $set_active = $this->request->variable('set_active', 0); if (!$set_active_set) { return array(); } if (!$is_owner) { return array($this->user->lang('NOT_AUTH_HOOKUP')); } if ($set_active && !isset($this->hookup->hookup_dates[$set_active])) { trigger_error('NO_DATE'); } $active_date_formatted = '-'; if ($set_active != 0) { $active_date_formatted = $this->user->format_date($this->hookup->hookup_dates[$set_active]['date_time']); if ($this->hookup->hookup_dates[$set_active]['text'] != null) { $active_date_formatted = $this->hookup->hookup_dates[$set_active]['text']; } } $topic_id = $event['topic_id']; $forum_id = $event['forum_id']; $viewtopic_url = append_sid("{$this->phpbb_root_path}viewtopic.{$this->phpEx}?f={$forum_id}&t={$topic_id}"); if (confirm_box(true)) { $title_prefix = $this->request->variable('title_prefix', false); $send_email = $this->request->variable('send_email', false); $post_reply = $this->request->variable('post_reply', false); $topic_data = $event['topic_data']; $new_string = ''; if ($set_active != 0) { if ($this->hookup->hookup_dates[$set_active]['text'] != null) { $new_string = '[' . $this->hookup->hookup_dates[$set_active]['text'] . '] '; } else { $new_string = '[' . $this->user->format_date($this->hookup->hookup_dates[$set_active]['date_time'], $this->user->lang['HOOKUP_DATEFORMAT_TITLE']) . '] '; } } $new_title = preg_replace('#^(\\[.+?\\] )?#', $new_string, $event['topic_data']['topic_title']); /** * Perform additional actions when active date is set * * @event gn36.hookup.set_activedate_confirmed * @var bool title_prefix User wants to have a title prefix added * @var bool send_email User wants E-Mails to be sent * @var bool post_reply User wants to post a reply to the topic * @var int set_active Date selected as active (0 means reset of active date) * @var string new_title The new topic title that will be present after the update * @var int topic_id ID of the topic of the hookup * @var int forum_id ID of the forum the topic is in * @var array topic_data Topic data as received from core.viewtopic_assign_template_vars_before * @since 1.0.0-a1 */ $vars = array('title_prefix', 'send_email', 'post_reply', 'set_active', 'new_title', 'topic_id', 'forum_id', 'topic_data'); extract($this->phpbb_dispatcher->trigger_event('gn36.hookup.set_activedate_confirmed', compact($vars))); //insert active date (short format) into topic title. this will use language //and timezone of the "active maker" but the alternative would be //to query the HOOKUP_DATES table every time we need the topic title if ($set_active == 0 || $title_prefix) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET hookup_active_date = ' . (int) $set_active . ",\n\t\t\t\t\t\t\ttopic_title = '" . $this->db->sql_escape($new_title) . "'\n\t\t\t\t\t\t\t\t\tWHERE topic_id = {$topic_id}"; $this->db->sql_query($sql); $sql = "UPDATE " . POSTS_TABLE . "\n\t\t\t\t\t\tSET post_subject='" . $this->db->sql_escape($new_title) . "'\n\t\t\t\t\t\t\t\tWHERE post_id = {$event['topic_data']['topic_first_post_id']}"; $this->db->sql_query($sql); } else { //only set hookup_active_date $sql = 'UPDATE ' . TOPICS_TABLE . ' SET hookup_active_date = ' . (int) $set_active . "\n\t\t\t\t\t\t\t\tWHERE topic_id = {$topic_id}"; $this->db->sql_query($sql); } $this->hookup->update_available_sums(); //notify all members about active date if (!empty($this->hookup->hookup_users)) { if ($set_active) { $notify_data = array('user_id' => $this->user->data['user_id'], 'date_id' => $set_active, 'date' => $this->hookup->hookup_dates[$set_active]['date_time'], 'text' => $this->hookup->hookup_dates[$set_active]['text'], 'topic_title' => $event['topic_data']['topic_title'], 'topic_id' => $event['topic_id'], 'forum_id' => $event['forum_id'], 'yes' => $this->hookup->hookup_available_sums[$set_active][\gn36\hookup\functions\hookup::HOOKUP_YES], 'no' => $this->hookup->hookup_available_sums[$set_active][\gn36\hookup\functions\hookup::HOOKUP_NO], 'maybe' => $this->hookup->hookup_available_sums[$set_active][\gn36\hookup\functions\hookup::HOOKUP_MAYBE]); $this->notification_manager->add_notifications('gn36.hookup.notification.type.active_date_set', $notify_data); $this->notification_manager->update_notifications('gn36.hookup.notification.type.active_date_set', $notify_data); $this->notification_manager->delete_notifications('gn36.hookup.notification.type.active_date_reset', $event['topic_id']); } else { $notify_data = array('user_id' => $this->user->data['user_id'], 'topic_title' => isset($new_title) ? $new_title : $event['topic_data']['topic_title'], 'topic_id' => $event['topic_id'], 'forum_id' => $event['forum_id']); $this->notification_manager->delete_notifications('gn36.hookup.notification.type.active_date_set', $event['topic_id']); $this->notification_manager->add_notifications('gn36.hookup.notification.type.active_date_reset', $notify_data); $this->notification_manager->update_notifications('gn36.hookup.notification.type.active_date_reset', $notify_data); } } //post reply to this topic. Again this can only be in the "active maker"s language if ($set_active && $post_reply) { $message = $this->user->lang['SET_ACTIVE_POST_TEMPLATE']; $active_date = $this->user->format_date($this->hookup->hookup_dates[$set_active]['date_time'], $this->user->lang['HOOKUP_DATEFORMAT_POST']); if ($this->hookup->hookup_dates[$set_active]['text'] != null) { $active_date = $this->hookup->hookup_dates[$set_active]['text']; } $message = str_replace('{ACTIVE_DATE}', $active_date, $message); //TODO: functions_post_oo! //$post = new post($topic_id); //$post->post_text = $message; //$post->submit(); } meta_refresh(3, $viewtopic_url); $message = ($set_active != 0 ? sprintf($this->user->lang['ACTIVE_DATE_SET'], $active_date_formatted) : $this->user->lang['ACTIVE_DATE_UNSET']) . '<br /><br />' . sprintf($this->user->lang['RETURN_TOPIC'], '<a href="' . $viewtopic_url . '">', '</a>'); trigger_error($message); } else { $s_hidden_fields = build_hidden_fields(array('t' => $topic_id, 'set_active' => $set_active)); if ($set_active != 0) { confirm_box(false, sprintf($this->user->lang['SET_ACTIVE_CONFIRM'], $active_date_formatted), $s_hidden_fields, '@gn36_hookup/hookup_active_date_confirm.html'); } else { confirm_box(false, 'UNSET_ACTIVE', $s_hidden_fields); } } return array(); }
public function main($id, $mode) { global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config, $phpbb_dispatcher, $phpbb_container; $this->db = $db; $this->user = $user; $this->template = $template; $this->request = $request; $this->cache = $cache; $this->auth = $auth; $this->text_formatter_cache = $phpbb_container->get('text_formatter.cache'); $this->config = $config; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $phpEx; $this->dispatcher = $phpbb_dispatcher; $this->default_style = $config['default_style']; $this->styles_path = $this->phpbb_root_path . $this->styles_path_absolute . '/'; $this->u_base_action = append_sid("{$phpbb_admin_path}index.{$this->php_ext}", "i={$id}"); $this->s_hidden_fields = array('mode' => $mode); $this->user->add_lang('acp/styles'); $this->tpl_name = 'acp_styles'; $this->page_title = 'ACP_CAT_STYLES'; $this->mode = $mode; $action = $this->request->variable('action', ''); $post_actions = array('install', 'activate', 'deactivate', 'uninstall'); foreach ($post_actions as $key) { if ($this->request->is_set_post($key)) { $action = $key; } } // The uninstall action uses confirm_box() to verify the validity of the request, // so there is no need to check for a valid token here. if (in_array($action, $post_actions) && $action != 'uninstall') { $is_valid_request = check_link_hash($request->variable('hash', ''), $action) || check_form_key('styles_management'); if (!$is_valid_request) { trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } } if ($action != '') { $this->s_hidden_fields['action'] = $action; } $this->template->assign_vars(array('U_ACTION' => $this->u_base_action, 'S_HIDDEN_FIELDS' => build_hidden_fields($this->s_hidden_fields))); /** * Run code before ACP styles action execution * * @event core.acp_styles_action_before * @var int id Module ID * @var string mode Active module * @var string action Module that should be run * @since 3.1.7-RC1 */ $vars = array('id', 'mode', 'action'); extract($this->dispatcher->trigger_event('core.acp_styles_action_before', compact($vars))); // Execute actions switch ($action) { case 'install': $this->action_install(); return; case 'uninstall': $this->action_uninstall(); return; case 'activate': $this->action_activate(); return; case 'deactivate': $this->action_deactivate(); return; case 'details': $this->action_details(); return; default: $this->frontend(); } }
/** * Performs the query that inserts an account link * * @param array $data This array is passed to db->sql_build_array */ protected function link_account_perform_link(array $data) { $sql = 'INSERT INTO ' . $this->auth_provider_oauth_token_account_assoc . ' ' . $this->db->sql_build_array('INSERT', $data); $this->db->sql_query($sql); /** * Event is triggered after user links account. * * @event core.auth_oauth_link_after * @var array data User row * @since 3.1.11-RC1 */ $vars = array('data'); extract($this->dispatcher->trigger_event('core.auth_oauth_link_after', compact($vars))); }
/** * Moves topics to a new forum after they have been locked * * @param array $topic_data * @param string $action */ public function move_topics($topic_data, $action) { $first_topic_data = reset($topic_data); $is_enabled = (int) $first_topic_data[$action]; $to_forum_id = (int) $first_topic_data['move_topics_when_locked_to']; /** * This event allows you to perform additional actions before locked topics are moved. * * @event kasimi.movetopicswhenlocked.move_topics_before * @var array topic_data Array with general topic data * @var string action Who triggered the forums to be moved, one of move_topics_when_locked|move_topics_when_locked_solved * @var int is_enabled Whether or not the forum's ACP settings specify the topics to be moved * @var int to_forum_id The destination forum * @since 1.0.2 */ $vars = array('topic_data', 'action', 'is_enabled', 'to_forum_id'); extract($this->dispatcher->trigger_event('kasimi.movetopicswhenlocked.move_topics_before', compact($vars))); // Forum settings are set to not move the topics if (!$is_enabled || !$to_forum_id) { return; } $forum_id = (int) $first_topic_data['forum_id']; // The topics are already in the destination forum if ($forum_id == $to_forum_id) { return; } if (!function_exists('phpbb_get_forum_data')) { include $this->root_path . 'includes/functions_mcp.' . $this->php_ext; } $to_forum_data = phpbb_get_forum_data($to_forum_id, 'f_post'); // The destination forum does not exist if (empty($to_forum_data)) { return; } // The following code is taken from the mcp_move_topic() function in /includes/mpc/mcp_main.php $topics_moved = $topics_moved_unapproved = $topics_moved_softdeleted = 0; $posts_moved = $posts_moved_unapproved = $posts_moved_softdeleted = 0; foreach ($topic_data as $topic_id => $topic_info) { if ($topic_info['topic_visibility'] == ITEM_APPROVED) { $topics_moved++; } else { if ($topic_info['topic_visibility'] == ITEM_UNAPPROVED || $topic_info['topic_visibility'] == ITEM_REAPPROVE) { $topics_moved_unapproved++; } else { if ($topic_info['topic_visibility'] == ITEM_DELETED) { $topics_moved_softdeleted++; } } } $posts_moved += $topic_info['topic_posts_approved']; $posts_moved_unapproved += $topic_info['topic_posts_unapproved']; $posts_moved_softdeleted += $topic_info['topic_posts_softdeleted']; } $this->db->sql_transaction('begin'); if (!function_exists('move_topics')) { include $this->root_path . 'includes/functions_admin.' . $this->php_ext; } // Move topics, but do not resync yet move_topics(array_keys($topic_data), $to_forum_id, false); foreach ($topic_data as $topic_id => $row) { // We add the $to_forum_id twice, because 'forum_id' is updated // when the topic is moved again later. $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, 'LOG_MOVED_LOCKED_TOPIC', false, array('forum_id' => (int) $to_forum_id, 'topic_id' => (int) $topic_id, $row['topic_title'], $row['forum_name'], $to_forum_data[$to_forum_id]['forum_name'])); } $sync_sql = array(); if ($posts_moved) { $sync_sql[$to_forum_id][] = 'forum_posts_approved = forum_posts_approved + ' . (int) $posts_moved; $sync_sql[$forum_id][] = 'forum_posts_approved = forum_posts_approved - ' . (int) $posts_moved; } if ($posts_moved_unapproved) { $sync_sql[$to_forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved + ' . (int) $posts_moved_unapproved; $sync_sql[$forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved - ' . (int) $posts_moved_unapproved; } if ($posts_moved_softdeleted) { $sync_sql[$to_forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted + ' . (int) $posts_moved_softdeleted; $sync_sql[$forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted - ' . (int) $posts_moved_softdeleted; } if ($topics_moved) { $sync_sql[$to_forum_id][] = 'forum_topics_approved = forum_topics_approved + ' . (int) $topics_moved; if ($topics_moved > 0) { $sync_sql[$forum_id][] = 'forum_topics_approved = forum_topics_approved - ' . (int) $topics_moved; } } if ($topics_moved_unapproved) { $sync_sql[$to_forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved + ' . (int) $topics_moved_unapproved; $sync_sql[$forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved - ' . (int) $topics_moved_unapproved; } if ($topics_moved_softdeleted) { $sync_sql[$to_forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted + ' . (int) $topics_moved_softdeleted; $sync_sql[$forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted - ' . (int) $topics_moved_softdeleted; } foreach ($sync_sql as $forum_id_key => $array) { $sql = 'UPDATE ' . FORUMS_TABLE . ' SET ' . implode(', ', $array) . ' WHERE forum_id = ' . (int) $forum_id_key; $this->db->sql_query($sql); } $this->db->sql_transaction('commit'); sync('forum', 'forum_id', array($forum_id, $to_forum_id)); /** * This event allows you to perform additional actions after locked topics have been moved. * * @event kasimi.movetopicswhenlocked.move_topics_after * @var array topic_data Array with general topic data * @var string action Who triggered the forums to be moved, one of move_topics_when_locked|move_topics_when_locked_solved * @var int to_forum_id The destination forum * @var int topics_moved Number of moved topics * @var int topics_moved_unapproved Number of moved unapproved topics * @var int topics_moved_softdeleted Number of moved soft-deleted topics * @var int posts_moved Number of moved posts * @var int posts_moved_unapproved Number of moved unapproved posts * @var int posts_moved_softdeleted Number of moved soft-deleted posts * @since 1.0.2 */ $vars = array('topic_data', 'action', 'to_forum_id', 'topics_moved', 'topics_moved_unapproved', 'topics_moved_softdeleted', 'posts_moved', 'posts_moved_unapproved', 'posts_moved_softdeleted'); extract($this->dispatcher->trigger_event('kasimi.movetopicswhenlocked.move_topics_after', compact($vars))); unset($topic_data); }
public function display_recent_topics($tpl_loopname = 'recent_topics', $spec_forum_id = 0, $include_subforums = true) { $this->user->add_lang_ext('paybas/recenttopics', 'recenttopics'); /** * Set some internal needed variables */ $topics_per_page = $this->config['rt_number']; $num_pages = $this->config['rt_page_number']; $min_topic_level = $this->config['rt_min_topic_level']; $excluded_topics = $this->config['rt_anti_topics']; $display_parent_forums = $this->config['rt_parents']; $unread_only = $this->config['rt_unreadonly']; $sort_topics = $this->config['rt_sort_start_time'] ? 'topic_time' : 'topic_last_post_time'; $persistent_display = $this->config['rt_persistent_display']; if ($persistent_display) { $this->template->assign_vars(array(strtoupper($tpl_loopname) . '_DISPLAY' => true)); } $start = $this->request->variable($tpl_loopname . '_start', 0); $excluded_topic_ids = explode(', ', $excluded_topics); $total_limit = $topics_per_page * $num_pages; if (!function_exists('display_forums')) { include $this->root_path . 'includes/functions_display.' . $this->phpEx; } /** * Get the forums we take our topics from */ // Get the allowed forums $forum_ary = array(); $forum_read_ary = $this->auth->acl_getf('f_read'); foreach ($forum_read_ary as $forum_id => $allowed) { if ($allowed['f_read']) { $forum_ary[] = (int) $forum_id; } } $forum_ids = array_unique($forum_ary); if (!sizeof($forum_ids)) { // No forums with f_read return; } $spec_forum_ary = array(); if ($spec_forum_id) { // Only take a special-forum if (!$include_subforums) { if (!in_array($spec_forum_id, $forum_ids)) { return; } $forum_ids = array(); $sql = 'SELECT 1 as display_forum FROM ' . FORUMS_TABLE . ' WHERE forum_id = ' . intval($spec_forum_id) . ' AND forum_recent_topics = 1'; $result = $this->db->sql_query_limit($sql, 1); $display_forum = (bool) $this->db->sql_fetchfield('display_forum'); $this->db->sql_freeresult($result); if ($display_forum) { $forum_ids = array($spec_forum_id); } } else { // ... and it's subforums $sql = 'SELECT f2.forum_id FROM ' . FORUMS_TABLE . ' f1 LEFT JOIN ' . FORUMS_TABLE . " f2\n\t\t\t\t\t\tON (f2.left_id BETWEEN f1.left_id AND f1.right_id\n\t\t\t\t\t\t\tAND f2.forum_recent_topics = 1)\n\t\t\t\t\tWHERE f1.forum_id = {$spec_forum_id}\n\t\t\t\t\t\tAND f1.forum_recent_topics = 1\n\t\t\t\t\tORDER BY f2.left_id DESC"; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $spec_forum_ary[] = $row['forum_id']; } $this->db->sql_freeresult($result); $forum_ids = array_intersect($forum_ids, $spec_forum_ary); if (!sizeof($forum_ids)) { return; } } } else { $sql = 'SELECT forum_id FROM ' . FORUMS_TABLE . ' WHERE ' . $this->db->sql_in_set('forum_id', $forum_ids) . ' AND forum_recent_topics = 1'; $result = $this->db->sql_query($sql); $forum_ids = array(); while ($row = $this->db->sql_fetchrow($result)) { $forum_ids[] = $row['forum_id']; } $this->db->sql_freeresult($result); } // No forums with f_read or recent topics enabled if (!sizeof($forum_ids)) { return; } // Remove duplicated ids $forum_ids = array_unique($forum_ids); $forums = $topic_list = array(); $topics_count = 0; $obtain_icons = false; // Either use the phpBB core function to get unread topics, or the custom function for default behavior if ($unread_only && $this->user->data['user_id'] != ANONYMOUS) { // Get unread topics $sql_extra = ' AND ' . $this->db->sql_in_set('t.topic_id', $excluded_topic_ids, true); $sql_extra .= ' AND ' . $this->content_visibility->get_forums_visibility_sql('topic', $forum_ids, $table_alias = 't.'); $unread_topics = get_unread_topics(false, $sql_extra, '', $total_limit); foreach ($unread_topics as $topic_id => $mark_time) { $topics_count++; if ($topics_count > $start && $topics_count <= $start + $topics_per_page) { $topic_list[] = $topic_id; } } } else { // Get the allowed topics $sql_array = array('SELECT' => 't.forum_id, t.topic_id, t.topic_type, t.icon_id, tt.mark_time, ft.mark_time as f_mark_time', 'FROM' => array(TOPICS_TABLE => 't'), 'LEFT_JOIN' => array(array('FROM' => array(TOPICS_TRACK_TABLE => 'tt'), 'ON' => 'tt.topic_id = t.topic_id AND tt.user_id = ' . $this->user->data['user_id']), array('FROM' => array(FORUMS_TRACK_TABLE => 'ft'), 'ON' => 'ft.forum_id = t.forum_id AND ft.user_id = ' . $this->user->data['user_id'])), 'WHERE' => $this->db->sql_in_set('t.topic_id', $excluded_topic_ids, true) . ' AND t.topic_status <> ' . ITEM_MOVED . ' AND ' . $this->content_visibility->get_forums_visibility_sql('topic', $forum_ids, $table_alias = 't.'), 'ORDER_BY' => 't.' . $sort_topics . ' DESC'); // Check if we want all topics, or only stickies/announcements/globals if ($min_topic_level > 0) { $sql_array['WHERE'] .= ' AND t.topic_type >= ' . $min_topic_level; } /** * Event to modify the SQL query before the allowed topics list data is retrieved * * @event paybas.recenttopics.sql_pull_topics_list * @var array sql_array The SQL array * @since 2.0.4 */ $vars = array('sql_array'); extract($this->dispatcher->trigger_event('paybas.recenttopics.sql_pull_topics_list', compact($vars))); $sql = $this->db->sql_build_query('SELECT', $sql_array); $result = $this->db->sql_query_limit($sql, $total_limit); while ($row = $this->db->sql_fetchrow($result)) { $topics_count++; if ($topics_count > $start && $topics_count <= $start + $topics_per_page) { $topic_list[] = $row['topic_id']; $rowset[$row['topic_id']] = $row; if (!isset($forums[$row['forum_id']]) && $this->user->data['is_registered'] && $this->config['load_db_lastread']) { $forums[$row['forum_id']]['mark_time'] = $row['f_mark_time']; } $forums[$row['forum_id']]['topic_list'][] = $row['topic_id']; $forums[$row['forum_id']]['rowset'][$row['topic_id']] =& $rowset[$row['topic_id']]; if ($row['icon_id'] && $this->auth->acl_get('f_icons', $row['forum_id'])) { $obtain_icons = true; } } } $this->db->sql_freeresult($result); } // No topics to display if (!sizeof($topic_list)) { return; } // Grab icons if ($obtain_icons) { $icons = $this->cache->obtain_icons(); } else { $icons = array(); } // Borrowed from search.php foreach ($forums as $forum_id => $forum) { if ($this->user->data['is_registered'] && $this->config['load_db_lastread']) { $topic_tracking_info[$forum_id] = get_topic_tracking($forum_id, $forum['topic_list'], $forum['rowset'], array($forum_id => $forum['mark_time']), $forum_id ? false : $forum['topic_list']); } else { if ($this->config['load_anon_lastread'] || $this->user->data['is_registered']) { $tracking_topics = $this->request->variable($this->config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE); $tracking_topics = $tracking_topics ? tracking_unserialize($tracking_topics) : array(); $topic_tracking_info[$forum_id] = get_complete_topic_tracking($forum_id, $forum['topic_list'], $forum_id ? false : $forum['topic_list']); if (!$this->user->data['is_registered']) { $this->user->data['user_lastmark'] = isset($tracking_topics['l']) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $this->config['board_startdate']) : 0; } } } } // Now only pull the data of the requested topics $sql_array = array('SELECT' => 't.*, tp.topic_posted, f.forum_name', 'FROM' => array(TOPICS_TABLE => 't'), 'LEFT_JOIN' => array(array('FROM' => array(TOPICS_POSTED_TABLE => 'tp'), 'ON' => 't.topic_id = tp.topic_id AND tp.user_id = ' . $this->user->data['user_id']), array('FROM' => array(FORUMS_TABLE => 'f'), 'ON' => 'f.forum_id = t.forum_id')), 'WHERE' => $this->db->sql_in_set('t.topic_id', $topic_list), 'ORDER_BY' => 't.' . $sort_topics . ' DESC'); if ($display_parent_forums) { $sql_array['SELECT'] .= ', f.parent_id, f.forum_parents, f.left_id, f.right_id'; } /** * Event to modify the SQL query before the topics data is retrieved * * @event paybas.recenttopics.sql_pull_topics_data * @var array sql_array The SQL array * @since 2.0.0 */ $vars = array('sql_array'); extract($this->dispatcher->trigger_event('paybas.recenttopics.sql_pull_topics_data', compact($vars))); $sql = $this->db->sql_build_query('SELECT', $sql_array); $result = $this->db->sql_query_limit($sql, $topics_per_page); $rowset = $topic_icons = array(); while ($row = $this->db->sql_fetchrow($result)) { $rowset[] = $row; } $this->db->sql_freeresult($result); // No topics returned by the DB if (!sizeof($rowset)) { return; } /** * Event to modify the topics list data before we start the display loop * * @event paybas.recenttopics.modify_topics_list * @var array topic_list Array of all the topic IDs * @var array rowset The full topics list array * @since 2.0.1 */ $vars = array('topic_list', 'rowset'); extract($this->dispatcher->trigger_event('paybas.recenttopics.modify_topics_list', compact($vars))); foreach ($rowset as $row) { $topic_id = $row['topic_id']; $forum_id = $row['forum_id']; $s_type_switch_test = $row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL ? 1 : 0; //$replies = ($this->auth->acl_get('m_approve', $forum_id)) ? $row['topic_replies_real'] : $row['topic_replies']; $replies = $this->content_visibility->get_count('topic_posts', $row, $forum_id) - 1; if ($unread_only) { topic_status($row, $replies, true, $folder_img, $folder_alt, $topic_type); $unread_topic = true; } else { topic_status($row, $replies, isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']] ? true : false, $folder_img, $folder_alt, $topic_type); $unread_topic = isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']] ? true : false; } $view_topic_url = append_sid("{$this->root_path}viewtopic.{$this->phpEx}", 'f=' . $forum_id . '&t=' . $topic_id); $view_forum_url = append_sid("{$this->root_path}viewforum.{$this->phpEx}", 'f=' . $forum_id); $topic_unapproved = $row['topic_visibility'] == ITEM_UNAPPROVED && $this->auth->acl_get('m_approve', $forum_id); $posts_unapproved = $row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $this->auth->acl_get('m_approve', $forum_id); $u_mcp_queue = $topic_unapproved || $posts_unapproved ? append_sid("{$this->root_path}mcp.{$this->phpEx}", 'i=queue&mode=' . ($topic_unapproved ? 'approve_details' : 'unapproved_posts') . "&t={$topic_id}", true, $this->user->session_id) : ''; $s_type_switch = $row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL ? 1 : 0; if (!empty($icons[$row['icon_id']])) { $topic_icons[] = $topic_id; } // Get folder img, topic status/type related information $folder_img = $folder_alt = $topic_type = ''; topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); $tpl_ary = array('FORUM_ID' => $forum_id, 'TOPIC_ID' => $topic_id, 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 'FIRST_POST_TIME' => $this->user->format_date($row['topic_time']), 'LAST_POST_SUBJECT' => censor_text($row['topic_last_post_subject']), 'LAST_POST_TIME' => $this->user->format_date($row['topic_last_post_time']), 'LAST_VIEW_TIME' => $this->user->format_date($row['topic_last_view_time']), 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 'REPLIES' => $replies, 'VIEWS' => $row['topic_views'], 'TOPIC_TITLE' => censor_text($row['topic_title']), 'FORUM_NAME' => $row['forum_name'], 'TOPIC_TYPE' => $topic_type, 'TOPIC_IMG_STYLE' => $folder_img, 'TOPIC_FOLDER_IMG' => $this->user->img($folder_img, $folder_alt), 'TOPIC_FOLDER_IMG_ALT' => $this->user->lang[$folder_alt], 'TOPIC_ICON_IMG' => !empty($icons[$row['icon_id']]) ? $icons[$row['icon_id']]['img'] : '', 'TOPIC_ICON_IMG_WIDTH' => !empty($icons[$row['icon_id']]) ? $icons[$row['icon_id']]['width'] : '', 'TOPIC_ICON_IMG_HEIGHT' => !empty($icons[$row['icon_id']]) ? $icons[$row['icon_id']]['height'] : '', 'ATTACH_ICON_IMG' => $this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $forum_id) && $row['topic_attachment'] ? $this->user->img('icon_topic_attach', $this->user->lang['TOTAL_ATTACHMENTS']) : '', 'UNAPPROVED_IMG' => $topic_unapproved || $posts_unapproved ? $this->user->img('icon_topic_unapproved', $topic_unapproved ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', 'REPORTED_IMG' => $row['topic_reported'] && $this->auth->acl_get('m_report', $forum_id) ? $this->user->img('icon_topic_reported', 'TOPIC_REPORTED') : '', 'S_HAS_POLL' => $row['poll_start'] ? true : false, 'S_TOPIC_TYPE' => $row['topic_type'], 'S_USER_POSTED' => isset($row['topic_posted']) && $row['topic_posted'] ? true : false, 'S_UNREAD_TOPIC' => $unread_topic, 'S_TOPIC_REPORTED' => $row['topic_reported'] && $this->auth->acl_get('m_report', $forum_id) ? true : false, 'S_TOPIC_UNAPPROVED' => $topic_unapproved, 'S_POSTS_UNAPPROVED' => $posts_unapproved, 'S_POST_ANNOUNCE' => $row['topic_type'] == POST_ANNOUNCE ? true : false, 'S_POST_GLOBAL' => $row['topic_type'] == POST_GLOBAL ? true : false, 'S_POST_STICKY' => $row['topic_type'] == POST_STICKY ? true : false, 'S_TOPIC_LOCKED' => $row['topic_status'] == ITEM_LOCKED ? true : false, 'S_TOPIC_MOVED' => $row['topic_status'] == ITEM_MOVED ? true : false, 'S_TOPIC_TYPE_SWITCH' => $s_type_switch == $s_type_switch_test ? -1 : $s_type_switch_test, 'U_NEWEST_POST' => $view_topic_url . '&view=unread#unread', 'U_LAST_POST' => $view_topic_url . '&p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id'], 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 'U_VIEW_TOPIC' => $view_topic_url, 'U_VIEW_FORUM' => $view_forum_url, 'U_MCP_REPORT' => append_sid("{$this->root_path}mcp.{$this->phpEx}", 'i=reports&mode=reports&f=' . $forum_id . '&t=' . $topic_id, true, $this->user->session_id), 'U_MCP_QUEUE' => $u_mcp_queue); /** * Modify the topic data before it is assigned to the template * * @event paybas.recenttopics.modify_tpl_ary * @var array row Array with topic data * @var array tpl_ary Template block array with topic data * @since 2.0.0 */ $vars = array('row', 'tpl_ary'); extract($this->dispatcher->trigger_event('paybas.recenttopics.modify_tpl_ary', compact($vars))); $this->template->assign_block_vars($tpl_loopname, $tpl_ary); $this->pagination->generate_template_pagination($view_topic_url, $tpl_loopname . '.pagination', 'start', $replies + 1, $this->config['posts_per_page'], 1, true, true); if ($display_parent_forums) { $forum_parents = get_forum_parents($row); foreach ($forum_parents as $parent_id => $data) { $this->template->assign_block_vars($tpl_loopname . '.parent_forums', array('FORUM_ID' => $parent_id, 'FORUM_NAME' => $data[0], 'U_VIEW_FORUM' => append_sid("{$this->root_path}viewforum.{$this->phpEx}", 'f=' . $parent_id))); } } } // Get URL-parameters for pagination $url_params = explode('&', $this->user->page['query_string']); $append_params = false; foreach ($url_params as $param) { if (!$param) { continue; } if (strpos($param, '=') === false) { // Fix MSSTI Advanced BBCode MOD $append_params[$param] = '1'; continue; } list($name, $value) = explode('=', $param); if ($name != $tpl_loopname . '_start') { $append_params[$name] = $value; } } $pagination_url = append_sid($this->root_path . $this->user->page['page_name'], $append_params); $this->pagination->generate_template_pagination($pagination_url, 'rt_pagination', $tpl_loopname . '_start', $topics_count, $topics_per_page, $start); $this->template->assign_vars(array('RT_SORT_START_TIME' => $sort_topics === 'topic_time' ? true : false, 'S_TOPIC_ICONS' => sizeof($topic_icons) ? true : false, 'NEWEST_POST_IMG' => $this->user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), 'LAST_POST_IMG' => $this->user->img('icon_topic_latest', 'VIEW_LATEST_POST'), 'POLL_IMG' => $this->user->img('icon_topic_poll', 'TOPIC_POLL'), strtoupper($tpl_loopname) . '_DISPLAY' => true)); }
/** * Generate and return a new configured instance of s9e\TextFormatter\Configurator * * @return Configurator */ public function get_configurator() { // Create a new Configurator $configurator = new Configurator(); /** * Modify the s9e\TextFormatter configurator before the default settings are set * * @event core.text_formatter_s9e_configure_before * @var \s9e\TextFormatter\Configurator configurator Configurator instance * @since 3.2.0-a1 */ $vars = array('configurator'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_configure_before', compact($vars))); // Reset the list of allowed schemes foreach ($configurator->urlConfig->getAllowedSchemes() as $scheme) { $configurator->urlConfig->disallowScheme($scheme); } foreach (explode(',', $this->config['allowed_schemes_links']) as $scheme) { $configurator->urlConfig->allowScheme(trim($scheme)); } // Convert newlines to br elements by default $configurator->rootRules->enableAutoLineBreaks(); // Don't automatically ignore text in places where text is not allowed $configurator->rulesGenerator->remove('IgnoreTextIfDisallowed'); // Don't remove comments and instead convert them to xsl:comment elements $configurator->templateNormalizer->remove('RemoveComments'); $configurator->templateNormalizer->add('TransposeComments'); // Set the rendering engine and configure it to save to the cache dir $configurator->rendering->engine = 'PHP'; $configurator->rendering->engine->cacheDir = $this->cache_dir; $configurator->rendering->engine->defaultClassPrefix = 's9e_renderer_'; $configurator->rendering->engine->enableQuickRenderer = true; // Create custom filters for BBCode tokens that are supported in phpBB but not in // s9e\TextFormatter $filter = new RegexpFilter('#^' . get_preg_expression('relative_url') . '$#Du'); $configurator->attributeFilters->add('#local_url', $filter); $configurator->attributeFilters->add('#relative_url', $filter); // INTTEXT regexp from acp_bbcodes $filter = new RegexpFilter('!^([\\p{L}\\p{N}\\-+,_. ]+)$!Du'); $configurator->attributeFilters->add('#inttext', $filter); // Create custom filters for Flash restrictions, which use the same values as the image // restrictions but have their own error message $configurator->attributeFilters->add('#flashheight', __NAMESPACE__ . '\\parser::filter_flash_height')->addParameterByName('max_img_height')->addParameterByName('logger'); $configurator->attributeFilters->add('#flashwidth', __NAMESPACE__ . '\\parser::filter_flash_width')->addParameterByName('max_img_width')->addParameterByName('logger'); // Create a custom filter for phpBB's per-mode font size limits $configurator->attributeFilters->add('#fontsize', __NAMESPACE__ . '\\parser::filter_font_size')->addParameterByName('max_font_size')->addParameterByName('logger')->markAsSafeInCSS(); // Create a custom filter for image URLs $configurator->attributeFilters->add('#imageurl', __NAMESPACE__ . '\\parser::filter_img_url')->addParameterByName('urlConfig')->addParameterByName('logger')->addParameterByName('max_img_height')->addParameterByName('max_img_width')->markAsSafeAsURL(); // Add default BBCodes foreach ($this->get_default_bbcodes($configurator) as $bbcode) { $configurator->BBCodes->addCustom($bbcode['usage'], $bbcode['template']); } // Modify the template to disable images/flash depending on user's settings foreach (array('FLASH', 'IMG') as $name) { $tag = $configurator->tags[$name]; $tag->template = '<xsl:choose><xsl:when test="$S_VIEW' . $name . '">' . $tag->template . '</xsl:when><xsl:otherwise><xsl:apply-templates/></xsl:otherwise></xsl:choose>'; } // Load custom BBCodes foreach ($this->data_access->get_bbcodes() as $row) { // Insert the board's URL before {LOCAL_URL} tokens $tpl = preg_replace_callback('#\\{LOCAL_URL\\d*\\}#', function ($m) { return generate_board_url() . '/' . $m[0]; }, $row['bbcode_tpl']); try { $configurator->BBCodes->addCustom($row['bbcode_match'], new UnsafeTemplate($tpl)); } catch (\Exception $e) { /** * @todo log an error? */ } } // Load smilies foreach ($this->data_access->get_smilies() as $row) { $configurator->Emoticons->add($row['code'], '<img class="smilies" src="{$T_SMILIES_PATH}/' . htmlspecialchars($row['smiley_url']) . '" alt="{.}" title="' . htmlspecialchars($row['emotion']) . '"/>'); } if (isset($configurator->Emoticons)) { // Force emoticons to be rendered as text if $S_VIEWSMILIES is not set $configurator->Emoticons->notIfCondition = 'not($S_VIEWSMILIES)'; // Only parse emoticons at the beginning of the text or if they're preceded by any // one of: a new line, a space, a dot, or a right square bracket $configurator->Emoticons->notAfter = '[^\\n .\\]]'; } // Load the censored words $censor = $this->data_access->get_censored_words(); if (!empty($censor)) { // Use a namespaced tag to avoid collisions $configurator->plugins->load('Censor', array('tagName' => 'censor:tag')); foreach ($censor as $row) { // NOTE: words are stored as HTML, we need to decode them to plain text $configurator->Censor->add(htmlspecialchars_decode($row['word']), htmlspecialchars_decode($row['replacement'])); } } // Load the magic links plugins. We do that after BBCodes so that they use the same tags $configurator->plugins->load('Autoemail'); $configurator->plugins->load('Autolink', array('matchWww' => true)); // Register some vars with a default value. Those should be set at runtime by whatever calls // the parser $configurator->registeredVars['max_font_size'] = 0; $configurator->registeredVars['max_img_height'] = 0; $configurator->registeredVars['max_img_width'] = 0; // Load the Emoji plugin and modify its tag's template to obey viewsmilies $configurator->Emoji->setImageSize(18); $tag = $configurator->Emoji->getTag(); $tag->template = '<xsl:choose><xsl:when test="$S_VIEWSMILIES">' . str_replace('class="emoji"', 'class="smilies"', $tag->template) . '</xsl:when><xsl:otherwise><xsl:value-of select="."/></xsl:otherwise></xsl:choose>'; /** * Modify the s9e\TextFormatter configurator after the default settings are set * * @event core.text_formatter_s9e_configure_after * @var \s9e\TextFormatter\Configurator configurator Configurator instance * @since 3.2.0-a1 */ $vars = array('configurator'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_configure_after', compact($vars))); return $configurator; }