diff options
41 files changed, 637 insertions, 115 deletions
diff --git a/phpBB/adm/style/acp_ext_list.html b/phpBB/adm/style/acp_ext_list.html index 8feb12a423..ccc39ea76d 100644 --- a/phpBB/adm/style/acp_ext_list.html +++ b/phpBB/adm/style/acp_ext_list.html @@ -44,7 +44,7 @@ <tbody> <!-- IF .enabled --> <tr> - <td class="row3" colspan="4"><strong>{L_EXTENSIONS_ENABLED}</strong></td> + <td class="row3" colspan="4"><strong>{L_EXTENSIONS_ENABLED}</strong><!-- EVENT acp_ext_list_enabled_title_after --></td> </tr> <!-- BEGIN enabled --> <tr class="ext_enabled row-highlight"> @@ -69,7 +69,7 @@ <!-- IF .disabled --> <tr> - <td class="row3" colspan="4"><strong>{L_EXTENSIONS_DISABLED}</strong></td> + <td class="row3" colspan="4"><strong>{L_EXTENSIONS_DISABLED}</strong><!-- EVENT acp_ext_list_disabled_title_after --></td> </tr> <!-- BEGIN disabled --> <tr class="ext_disabled row-highlight"> diff --git a/phpBB/adm/style/ajax.js b/phpBB/adm/style/ajax.js index 4ad6b6afa5..7ddd2d3742 100644 --- a/phpBB/adm/style/ajax.js +++ b/phpBB/adm/style/ajax.js @@ -62,7 +62,125 @@ phpbb.addAjaxCallback('row_delete', function(res) { } }); +/** + * Handler for submitting permissions form in chunks + * This call will submit permissions forms in chunks of 5 fieldsets. + */ +function submitPermissions() { + var $form = $('form#set-permissions'), + fieldsetList = $form.find('fieldset[id^=perm]'), + formDataSets = [], + $submitAllButton = $form.find('input[type=submit][name^=action]')[0], + $submitButton = $form.find('input[type=submit][data-clicked=true]')[0]; + + // Set proper start values for handling refresh of page + var permissionSubmitSize = 0, + permissionRequestCount = 0, + forumIds = [], + permissionSubmitFailed = false; + + if ($submitAllButton !== $submitButton) { + fieldsetList = $form.find('fieldset#' + $submitButton.closest('fieldset.permissions').id); + } + + $.each(fieldsetList, function (key, value) { + if (key % 5 === 0) { + formDataSets[Math.floor(key / 5)] = $form.find('fieldset#' + value.id).serialize(); + } else { + formDataSets[Math.floor(key / 5)] += '&' + $form.find('fieldset#' + value.id).serialize(); + } + }); + + permissionSubmitSize = formDataSets.length; + + // Add each forum ID to forum ID list to preserve selected forums + $.each($form.find('input[type=hidden][name^=forum_id]'), function (key, value) { + if (value.name.match(/^forum_id\[([0-9]+)\]$/)) { + forumIds.push(value.value); + } + }); + + /** + * Handler for submitted permissions form chunk + * + * @param {object} res Object returned by AJAX call + */ + function handlePermissionReturn(res) { + permissionRequestCount++; + var $dark = $('#darkenwrapper'); + + if (res.S_USER_WARNING) { + phpbb.alert(res.MESSAGE_TITLE, res.MESSAGE_TEXT); + permissionSubmitFailed = true; + } else if (!permissionSubmitFailed && res.S_USER_NOTICE) { + // Display success message at the end of submitting the form + if (permissionRequestCount >= permissionSubmitSize) { + var $alert = phpbb.alert(res.MESSAGE_TITLE, res.MESSAGE_TEXT); + var $alertBoxLink = $alert.find('p.alert_text > a'); + + // Create form to submit instead of normal "Back to previous page" link + if ($alertBoxLink) { + // Remove forum_id[] from URL + $alertBoxLink.attr('href', $alertBoxLink.attr('href').replace(/(&forum_id\[\]=[0-9]+)/g, '')); + var previousPageForm = '<form action="' + $alertBoxLink.attr('href') + '" method="post">'; + $.each(forumIds, function (key, value) { + previousPageForm += '<input type="text" name="forum_id[]" value="' + value + '" />'; + }); + previousPageForm += '</form>'; + + $alertBoxLink.on('click', function (e) { + var $previousPageForm = $(previousPageForm); + $('body').append($previousPageForm); + e.preventDefault(); + $previousPageForm.submit(); + }); + } + + // Do not allow closing alert + $dark.off('click'); + $alert.find('.alert_close').hide(); + + if (typeof res.REFRESH_DATA !== 'undefined') { + setTimeout(function () { + // Create forum to submit using POST. This will prevent + // exceeding the maximum length of URLs + var form = '<form action="' + res.REFRESH_DATA.url.replace(/(&forum_id\[\]=[0-9]+)/g, '') + '" method="post">'; + $.each(forumIds, function (key, value) { + form += '<input type="text" name="forum_id[]" value="' + value + '" />'; + }); + form += '</form>'; + $form = $(form); + $('body').append($form); + + // Hide the alert even if we refresh the page, in case the user + // presses the back button. + $dark.fadeOut(phpbb.alertTime, function () { + if (typeof $alert !== 'undefined') { + $alert.hide(); + } + }); + + // Submit form + $form.submit(); + }, res.REFRESH_DATA.time * 1000); // Server specifies time in seconds + } + } + } + } + // Create AJAX request for each form data set + $.each(formDataSets, function (key, formData) { + $.ajax({ + url: $form.action, + type: 'POST', + data: formData + '&' + $submitAllButton.name + '=' + encodeURIComponent($submitAllButton.value) + + '&creation_time=' + $form.find('input[type=hidden][name=creation_time]')[0].value + + '&form_token=' + $form.find('input[type=hidden][name=form_token]')[0].value, + success: handlePermissionReturn, + error: handlePermissionReturn + }); + }); +} $('[data-ajax]').each(function() { var $this = $(this), @@ -83,6 +201,18 @@ $('[data-ajax]').each(function() { */ $(function() { phpbb.resizeTextArea($('textarea:not(.no-auto-resize)'), {minHeight: 75}); + + var $setPermissionsForm = $('form#set-permissions'); + if ($setPermissionsForm.length) { + $setPermissionsForm.on('submit', function (e) { + submitPermissions(); + e.preventDefault(); + }); + $setPermissionsForm.find('input[type=submit]').click(function() { + $('input[type=submit]', $(this).parents($('form#set-permissions'))).removeAttr('data-clicked'); + $(this).attr('data-clicked', true); + }); + } }); diff --git a/phpBB/config/auth.yml b/phpBB/config/auth.yml index 88a90ca2d6..ef06080d38 100644 --- a/phpBB/config/auth.yml +++ b/phpBB/config/auth.yml @@ -62,6 +62,7 @@ services: - @auth.provider.oauth.service_collection - %tables.users% - @service_container + - @dispatcher - %core.root_path% - %core.php_ext% tags: diff --git a/phpBB/docs/CREDITS.txt b/phpBB/docs/CREDITS.txt index 471e6b3c88..26ff8fcc80 100644 --- a/phpBB/docs/CREDITS.txt +++ b/phpBB/docs/CREDITS.txt @@ -27,7 +27,6 @@ phpBB Lead Developer: Marc (Marc Alexander) phpBB Developers: bantu (Andreas Fischer) CHItA (Máté Bartus) Elsensee (Oliver Schramm) - nickvergessen (Joas Schilling) Nicofuma (Tristan Darricau) prototech (Cesar Gallegos) @@ -60,6 +59,7 @@ phpBB Developers: A_Jelly_Doughnut (Josh Woody) [01/2010 - 11/2010] igorw (Igor Wiedler) [08/2010 - 02/2013] imkingdavid (David King) [11/2012 - 06/2014] kellanved (Henry Sudhof) [04/2007 - 03/2011] + nickvergessen (Joas Schilling)[04/2010 - 12/2015] Oleg (Oleg Pudeyev) [01/2011 - 05/2013] rxu (Ruslan Uzdenov) [04/2010 - 12/2012] TerraFrost (Jim Wigginton) [04/2009 - 01/2011] diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html index eb0fb60de2..56b71006c7 100644 --- a/phpBB/docs/coding-guidelines.html +++ b/phpBB/docs/coding-guidelines.html @@ -1123,9 +1123,6 @@ append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp; <ul> <li> - <p>Use <code>sizeof</code> instead of <code>count</code></p> - </li> - <li> <p>Use <code>strpos</code> instead of <code>strstr</code></p> </li> <li> diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index 0abda89706..0ebaf8f3e0 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -58,6 +58,18 @@ acp_email_options_after * Since: 3.1.2-RC1 * Purpose: Add settings to mass email form +acp_ext_list_disabled_title_after +=== +* Location: adm/style/acp_ext_list.html +* Since: 3.1.11-RC1 +* Purpose: Add text after disabled extensions section title. + +acp_ext_list_enabled_title_after +=== +* Location: adm/style/acp_ext_list.html +* Since: 3.1.11-RC1 +* Purpose: Add text after enabled extensions section title. + acp_forums_custom_settings === * Location: adm/style/acp_forums.html diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 816387967a..e4650455c4 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -42,7 +42,7 @@ class acp_attachments function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_container; + global $db, $user, $auth, $template, $cache, $phpbb_container, $phpbb_dispatcher; global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; $this->id = $id; @@ -162,6 +162,18 @@ class acp_attachments ) ); + /** + * Event to add and/or modify acp_attachement configurations + * + * @event core.acp_attachments_config_edit_add + * @var array display_vars Array of config values to display and process + * @var string mode Mode of the config page we are displaying + * @var boolean submit Do we display the form or process the submission + * @since 3.1.11-RC1 + */ + $vars = array('display_vars', 'mode', 'submit'); + extract($phpbb_dispatcher->trigger_event('core.acp_attachments_config_edit_add', compact($vars))); + $this->new_config = $config; $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => '')) : $this->new_config; $error = array(); diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index e004d2e81f..c8f6f426c6 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -1017,7 +1017,7 @@ class acp_board $user->timezone = $old_tz; return "<select name=\"dateoptions\" id=\"dateoptions\" onchange=\"if (this.value == 'custom') { document.getElementById('" . addslashes($key) . "').value = '" . addslashes($value) . "'; } else { document.getElementById('" . addslashes($key) . "').value = this.value; }\">$dateformat_options</select> - <input type=\"text\" name=\"config[$key]\" id=\"$key\" value=\"$value\" maxlength=\"30\" />"; + <input type=\"text\" name=\"config[$key]\" id=\"$key\" value=\"$value\" maxlength=\"64\" />"; } /** diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index f97711d69d..5a2ded91e2 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -34,7 +34,7 @@ class acp_extensions function main() { // Start the page - global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpEx, $phpbb_log, $cache; + global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpEx, $phpbb_log, $cache, $phpbb_dispatcher; $this->db = $db; $this->config = $config; @@ -43,6 +43,7 @@ class acp_extensions $this->cache = $cache; $this->request = $request; $this->log = $phpbb_log; + $this->phpbb_dispatcher = $phpbb_dispatcher; $user->add_lang(array('install', 'acp/extensions', 'migrator')); @@ -55,6 +56,21 @@ class acp_extensions $safe_time_limit = (ini_get('max_execution_time') / 2); $start_time = time(); + /** + * Event to run a specific action on extension + * + * @event core.acp_extensions_run_action + * @var string action Action to run + * @var string u_action Url we are at + * @var string ext_name Extension name from request + * @var int safe_time_limit Safe limit of execution time + * @var int start_time Start time + * @since 3.1.11-RC1 + */ + $u_action = $this->u_action; + $vars = array('action', 'u_action', 'ext_name', 'safe_time_limit', 'start_time'); + extract($this->phpbb_dispatcher->trigger_event('core.acp_extensions_run_action', compact($vars))); + // Cancel action if ($request->is_set_post('cancel')) { diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index 660afb4e93..62e75a2db7 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -755,6 +755,7 @@ class acp_permissions $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_id, $forum_id); + meta_refresh(5, $this->u_action); trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); } @@ -825,10 +826,12 @@ class acp_permissions if ($mode == 'setting_forum_local' || $mode == 'setting_mod_local') { + meta_refresh(5, $this->u_action . '&forum_id[]=' . implode('&forum_id[]=', $forum_ids)); trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action . '&forum_id[]=' . implode('&forum_id[]=', $forum_ids))); } else { + meta_refresh(5, $this->u_action); trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); } } @@ -899,10 +902,12 @@ class acp_permissions if ($mode == 'setting_forum_local' || $mode == 'setting_mod_local') { + meta_refresh(5, $this->u_action . '&forum_id[]=' . implode('&forum_id[]=', $forum_id)); trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action . '&forum_id[]=' . implode('&forum_id[]=', $forum_id))); } else { + meta_refresh(5, $this->u_action); trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); } } diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 2d4897c47d..9e6cc49522 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -597,13 +597,13 @@ class acp_profile if (!sizeof($error)) { - if (!check_form_key($form_key)) - { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); - } - if (($step == 3 && (sizeof($this->lang_defs['iso']) == 1 || $save)) || ($action == 'edit' && $save)) { + if (!check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $this->save_profile_field($cp, $field_type, $action); } } diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index f15a75e9a1..cc1e5df084 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -50,14 +50,12 @@ class acp_search function settings($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $request; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $submit = (isset($_POST['submit'])) ? true : false; - $form_key = 'acp_search'; - add_form_key($form_key); - if ($submit && !check_form_key($form_key)) + if ($submit && !check_link_hash($request->variable('hash', ''), 'acp_search')) { trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -233,7 +231,7 @@ class acp_search 'S_YES_SEARCH' => (bool) $config['load_search'], 'S_SETTINGS' => true, - 'U_ACTION' => $this->u_action) + 'U_ACTION' => $this->u_action . '&hash=' . generate_link_hash('acp_search')) ); } @@ -253,10 +251,7 @@ class acp_search } $submit = $request->is_set_post('submit', false); - $form_key = 'acp_search'; - add_form_key($form_key); - - if (!check_form_key($form_key) && in_array($action, array('delete', 'create'))) + if (!check_link_hash($request->variable('hash', ''), 'acp_search') && in_array($action, array('create', 'delete'))) { trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -310,7 +305,7 @@ class acp_search if (method_exists($this->search, 'delete_index')) { // pass a reference to myself so the $search object can make use of save_state() and attributes - if ($error = $this->search->delete_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete", false))) + if ($error = $this->search->delete_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete&hash=" . generate_link_hash('acp_search'), false))) { $this->state = array(''); $this->save_state(); @@ -355,7 +350,7 @@ class acp_search $mtime = explode(' ', microtime()); $totaltime = $mtime[0] + $mtime[1] - $starttime; $rows_per_second = $row_count / $totaltime; - meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter)); + meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search'))); trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter, $rows_per_second)); } } @@ -445,7 +440,7 @@ class acp_search $mtime = explode(' ', microtime()); $totaltime = $mtime[0] + $mtime[1] - $starttime; $rows_per_second = $row_count / $totaltime; - meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter)); + meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search'))); trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); } } @@ -524,7 +519,7 @@ class acp_search $template->assign_vars(array( 'S_INDEX' => true, - 'U_ACTION' => $this->u_action, + 'U_ACTION' => $this->u_action . '&hash=' . generate_link_hash('acp_search'), 'U_PROGRESS_BAR' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=progress_bar"), 'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=progress_bar")), )); @@ -533,7 +528,7 @@ class acp_search { $template->assign_vars(array( 'S_CONTINUE_INDEXING' => $this->state[1], - 'U_CONTINUE_INDEXING' => $this->u_action . '&action=' . $this->state[1], + 'U_CONTINUE_INDEXING' => $this->u_action . '&action=' . $this->state[1] . '&hash=' . generate_link_hash('acp_search'), 'L_CONTINUE' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING'] : $user->lang['CONTINUE_DELETING_INDEX'], 'L_CONTINUE_EXPLAIN' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING_EXPLAIN'] : $user->lang['CONTINUE_DELETING_INDEX_EXPLAIN']) ); diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 1e453e88ad..cd44800af8 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -373,11 +373,6 @@ class acp_users if ($user_row['user_type'] == USER_NORMAL) { user_active_flip('deactivate', $user_id, INACTIVE_REMIND); - - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_actkey = '" . $db->sql_escape($user_actkey) . "' - WHERE user_id = $user_id"; - $db->sql_query($sql); } else { @@ -386,8 +381,18 @@ class acp_users FROM ' . USERS_TABLE . ' WHERE user_id = ' . $user_id; $result = $db->sql_query($sql); - $user_actkey = (string) $db->sql_fetchfield('user_actkey'); + $user_activation_key = (string) $db->sql_fetchfield('user_actkey'); $db->sql_freeresult($result); + + $user_actkey = empty($user_activation_key) ? $user_actkey : $user_activation_key; + } + + if ($user_row['user_type'] == USER_NORMAL || empty($user_activation_key)) + { + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_actkey = '" . $db->sql_escape($user_actkey) . "' + WHERE user_id = $user_id"; + $db->sql_query($sql); } $messenger = new messenger(false); @@ -1924,7 +1929,7 @@ class acp_users 'S_FORM_ENCTYPE' => ' enctype="multipart/form-data"', - 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), + 'L_AVATAR_EXPLAIN' => $user->lang(($config['avatar_filesize'] == 0) ? 'AVATAR_EXPLAIN_NO_FILESIZE' : 'AVATAR_EXPLAIN', $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), 'S_AVATARS_ENABLED' => ($config['allow_avatar'] && $avatars_enabled), )); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index a152d9b620..ba448f3125 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2776,7 +2776,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo $u_action .= ((strpos($u_action, '?') === false) ? '?' : '&') . 'confirm_key=' . $confirm_key; $template->assign_vars(array( - 'MESSAGE_TITLE' => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title], + 'MESSAGE_TITLE' => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang($title, 1), 'MESSAGE_TEXT' => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'], 'YES_VALUE' => $user->lang['YES'], diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 8e60804d6e..8858d1a307 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -980,7 +980,7 @@ function bbcode_nl2br($text) */ function smiley_text($text, $force_option = false) { - global $config, $user, $phpbb_path_helper; + global $config, $user, $phpbb_path_helper, $phpbb_dispatcher; if ($force_option || !$config['allow_smilies'] || !$user->optionget('viewsmilies')) { @@ -989,6 +989,16 @@ function smiley_text($text, $force_option = false) else { $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_path_helper->get_web_root_path(); + + /** + * Event to override the root_path for smilies + * + * @event core.smiley_text_root_path + * @var string root_path root_path for smilies + * @since 3.1.11-RC1 + */ + $vars = array('root_path'); + extract($phpbb_dispatcher->trigger_event('core.smiley_text_root_path', compact($vars))); return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/(.*?) \/><!\-\- s\1 \-\->#', '<img class="smilies" src="' . $root_path . $config['smilies_path'] . '/\2 />', $text); } } diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php index c571de579e..86c60c31ff 100644 --- a/phpBB/includes/functions_download.php +++ b/phpBB/includes/functions_download.php @@ -677,6 +677,8 @@ function phpbb_download_handle_forum_auth($db, $auth, $topic_id) */ function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id) { + global $phpbb_dispatcher; + if (!$auth->acl_get('u_pm_download')) { send_status_line(403, 'Forbidden'); @@ -685,6 +687,18 @@ function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id) $allowed = phpbb_download_check_pm_auth($db, $user_id, $msg_id); + /** + * Event to modify PM attachments download auth + * + * @event core.modify_pm_attach_download_auth + * @var bool allowed Whether the user is allowed to download from that PM or not + * @var int msg_id The id of the PM to download from + * @var int user_id The user id for auth check + * @since 3.1.11-RC1 + */ + $vars = array('allowed', 'msg_id', 'user_id'); + extract($phpbb_dispatcher->trigger_event('core.modify_pm_attach_download_auth', compact($vars))); + if (!$allowed) { send_status_line(403, 'Forbidden'); diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 9b3ca14101..f141637fb9 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -438,7 +438,7 @@ class messenger */ function build_header($to, $cc, $bcc) { - global $config; + global $config, $phpbb_dispatcher; // We could use keys here, but we won't do this for 3.0.x to retain backwards compatibility $headers = array(); @@ -470,6 +470,16 @@ class messenger $headers[] = 'X-MimeOLE: phpBB3'; $headers[] = 'X-phpBB-Origin: phpbb://' . str_replace(array('http://', 'https://'), array('', ''), generate_board_url()); + /** + * Event to modify email header entries + * + * @event core.modify_email_headers + * @var array headers Array containing email header entries + * @since 3.1.11-RC1 + */ + $vars = array('headers'); + extract($phpbb_dispatcher->trigger_event('core.modify_email_headers', compact($vars))); + if (sizeof($this->extra_headers)) { $headers = array_merge($headers, $this->extra_headers); diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 57c68d4935..30f5ba91ef 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -119,6 +119,15 @@ function generate_smilies($mode, $forum_id) foreach ($smilies as $row) { + /** + * Modify smiley root path before populating smiley list + * + * @event core.generate_smilies_before + * @var string root_path root_path for smilies + * @since 3.1.11-RC1 + */ + $vars = array('root_path'); + extract($phpbb_dispatcher->trigger_event('core.generate_smilies_before', compact($vars))); $template->assign_block_vars('smiley', array( 'SMILEY_CODE' => $row['code'], 'A_SMILEY_CODE' => addslashes($row['code']), @@ -1074,7 +1083,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id } $sql_ary = array( - 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe', + 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe, uu.username as post_delete_username, uu.user_colour as post_delete_user_colour', 'FROM' => array( USERS_TABLE => 'u', @@ -1086,6 +1095,10 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id 'FROM' => array(ZEBRA_TABLE => 'z'), 'ON' => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id', ), + array( + 'FROM' => array(USERS_TABLE => 'uu'), + 'ON' => 'uu.user_id = p.post_delete_user', + ), ), 'WHERE' => $db->sql_in_set('p.post_id', $post_list) . ' @@ -1194,6 +1207,31 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id']; $u_show_post = append_sid($phpbb_root_path . 'viewtopic.' . $phpEx, "f=$forum_id&t=$topic_id&p={$row['post_id']}&view=show#p{$row['post_id']}"); + $l_deleted_message = ''; + if ($row['post_visibility'] == ITEM_DELETED) + { + $display_postername = get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']); + + // User having deleted the post also being the post author? + if (!$row['post_delete_user'] || $row['post_delete_user'] == $poster_id) + { + $display_username = $display_postername; + } + else + { + $display_username = get_username_string('full', $row['post_delete_user'], $row['post_delete_username'], $row['post_delete_user_colour']); + } + + if ($row['post_delete_reason']) + { + $l_deleted_message = $user->lang('POST_DELETED_BY_REASON', $display_postername, $display_username, $user->format_date($row['post_delete_time'], false, true), $row['post_delete_reason']); + } + else + { + $l_deleted_message = $user->lang('POST_DELETED_BY', $display_postername, $display_username, $user->format_date($row['post_delete_time'], false, true)); + } + } + $post_row = array( 'POST_AUTHOR_FULL' => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR_COLOUR' => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), @@ -1204,6 +1242,8 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id 'S_FRIEND' => ($row['friend']) ? true : false, 'S_IGNORE_POST' => ($row['foe']) ? true : false, 'L_IGNORE_POST' => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "<a href=\"{$u_show_post}\" onclick=\"phpbb.toggleDisplay('{$post_anchor}', 1); return false;\">", '</a>') : '', + 'S_POST_DELETED' => ($row['post_visibility'] == ITEM_DELETED) ? true : false, + 'L_DELETE_POST' => $l_deleted_message, 'POST_SUBJECT' => $post_subject, 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']), diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 1639eb1a4c..4aad1746d5 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -889,9 +889,16 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id) SET pm_unread = 0 WHERE msg_id = $msg_id AND user_id = $user_id - AND folder_id = $folder_id"; + AND folder_id = $folder_id + AND pm_unread = 1"; $db->sql_query($sql); + // If the message is already marked as read, we just skip the rest to avoid negative PM count + if (!$db->sql_affectedrows()) + { + return; + } + $sql = 'UPDATE ' . USERS_TABLE . " SET user_unread_privmsg = user_unread_privmsg - 1 WHERE user_id = $user_id"; diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index b82abe0c5e..0b39339c7f 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -2279,7 +2279,7 @@ function phpbb_avatar_explanation_string() { global $config, $user; - return $user->lang('AVATAR_EXPLAIN', + return $user->lang(($config['avatar_filesize'] == 0) ? 'AVATAR_EXPLAIN_NO_FILESIZE' : 'AVATAR_EXPLAIN', $user->lang('PIXELS', (int) $config['avatar_max_width']), $user->lang('PIXELS', (int) $config['avatar_max_height']), round($config['avatar_filesize'] / 1024)); diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index 7df712f65f..e4c0640ec7 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -396,7 +396,7 @@ function mcp_resync_topics($topic_ids) */ function merge_topics($forum_id, $topic_ids, $to_topic_id) { - global $db, $template, $user, $phpEx, $phpbb_root_path, $auth; + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $phpbb_dispatcher; if (!sizeof($topic_ids)) { @@ -411,9 +411,9 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) $sync_topics = array_merge($topic_ids, array($to_topic_id)); - $topic_data = phpbb_get_topic_data($sync_topics, 'm_merge'); + $all_topic_data = phpbb_get_topic_data($sync_topics, 'm_merge'); - if (!sizeof($topic_data) || empty($topic_data[$to_topic_id])) + if (!sizeof($all_topic_data) || empty($all_topic_data[$to_topic_id])) { $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); return; @@ -421,13 +421,13 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) $sync_forums = array(); $topic_views = 0; - foreach ($topic_data as $data) + foreach ($all_topic_data as $data) { $sync_forums[$data['forum_id']] = $data['forum_id']; - $topic_views += $data['topic_views']; + $topic_views = max($topic_views, $data['topic_views']); } - $topic_data = $topic_data[$to_topic_id]; + $to_topic_data = $all_topic_data[$to_topic_id]; $post_id_list = request_var('post_id_list', array(0)); $start = request_var('start', 0); @@ -475,10 +475,10 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) if (confirm_box(true)) { - $to_forum_id = $topic_data['forum_id']; + $to_forum_id = $to_topic_data['forum_id']; move_posts($post_id_list, $to_topic_id, false); - add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']); + add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $to_topic_data['topic_title']); // Update topic views count $sql = 'UPDATE ' . TOPICS_TABLE . ' @@ -511,6 +511,20 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) $redirect = request_var('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&t=$to_topic_id"); $redirect = reapply_sid($redirect); + /** + * Perform additional actions after merging topics. + * + * @event core.mcp_forum_merge_topics_after + * @var array all_topic_data The data from all topics involved in the merge + * @var int to_topic_id The ID of the topic into which the rest are merged + * @since 3.1.11-RC1 + */ + $vars = array( + 'all_topic_data', + 'to_topic_id', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_forum_merge_topics_after', compact($vars))); + meta_refresh(3, $redirect); trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); } diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php index 59525c6b16..93ee07b1cf 100644 --- a/phpBB/language/en/ucp.php +++ b/phpBB/language/en/ucp.php @@ -100,6 +100,7 @@ $lang = array_merge($lang, array( 'AVATAR_DRIVER_UPLOAD_TITLE' => 'Upload avatar', 'AVATAR_DRIVER_UPLOAD_EXPLAIN' => 'Upload your own custom avatar.', 'AVATAR_EXPLAIN' => 'Maximum dimensions; width: %1$s, height: %2$s, file size: %3$.2f KiB.', + 'AVATAR_EXPLAIN_NO_FILESIZE' => 'Maximum dimensions; width: %1$s, height: %2$s.', 'AVATAR_FEATURES_DISABLED' => 'The avatar functionality is currently disabled.', 'AVATAR_GALLERY' => 'Local gallery', 'AVATAR_GENERAL_UPLOAD_ERROR' => 'Could not upload avatar to %s.', diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php index 9f6345fbba..bd2a414033 100644 --- a/phpBB/phpbb/auth/provider/oauth/oauth.php +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -98,6 +98,13 @@ class oauth extends \phpbb\auth\provider\base protected $phpbb_container; /** + * phpBB event dispatcher + * + * @var \phpbb\event\dispatcher_interface + */ + protected $dispatcher; + + /** * phpBB root path * * @var string @@ -124,10 +131,11 @@ class oauth extends \phpbb\auth\provider\base * @param \phpbb\di\service_collection $service_providers Contains \phpbb\auth\provider\oauth\service_interface * @param string $users_table * @param \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container DI container + * @param \phpbb\event\dispatcher_interface $dispatcher phpBB event dispatcher * @param string $phpbb_root_path * @param string $php_ext */ - public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, \phpbb\event\dispatcher_interface $dispatcher, $phpbb_root_path, $php_ext) { $this->db = $db; $this->config = $config; @@ -139,6 +147,7 @@ class oauth extends \phpbb\auth\provider\base $this->service_providers = $service_providers; $this->users_table = $users_table; $this->phpbb_container = $phpbb_container; + $this->dispatcher = $dispatcher; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; } @@ -238,6 +247,18 @@ class oauth extends \phpbb\auth\provider\base // Update token storage to store the user_id $storage->set_user_id($row['user_id']); + /** + * Event is triggered after user is successfuly logged in via OAuth. + * + * @event core.auth_oauth_login_after + * @var array row User row + * @since 3.1.11-RC1 + */ + $vars = array( + 'row', + ); + extract($this->dispatcher->trigger_event('core.auth_oauth_login_after', compact($vars))); + // The user is now authenticated and can be logged in return array( 'status' => LOGIN_SUCCESS, @@ -542,6 +563,18 @@ class oauth extends \phpbb\auth\provider\base $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))); } /** diff --git a/phpBB/phpbb/db/migration/data/v31x/remove_duplicate_migrations.php b/phpBB/phpbb/db/migration/data/v31x/remove_duplicate_migrations.php new file mode 100644 index 0000000000..417d569a09 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/remove_duplicate_migrations.php @@ -0,0 +1,77 @@ +<?php + +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\db\migration\data\v31x; + +class remove_duplicate_migrations extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v31x\v3110'); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'deduplicate_entries'))), + ); + } + + public function deduplicate_entries() + { + $migration_state = array(); + $duplicate_migrations = array(); + + $sql = "SELECT * + FROM " . $this->table_prefix . 'migrations'; + $result = $this->db->sql_query($sql); + + if (!$this->db->get_sql_error_triggered()) + { + while ($migration = $this->db->sql_fetchrow($result)) + { + $migration_state[$migration['migration_name']] = $migration; + + $migration_state[$migration['migration_name']]['migration_depends_on'] = unserialize($migration['migration_depends_on']); + } + } + + $this->db->sql_freeresult($result); + + foreach ($migration_state as $name => $migration) + { + $prepended_name = ($name[0] == '\\' ? '' : '\\') . $name; + $prefixless_name = $name[0] == '\\' ? substr($name, 1) : $name; + + if ($prepended_name != $name && isset($migration_state[$prepended_name]) && $migration_state[$prepended_name]['migration_depends_on'] == $migration_state[$name]['migration_depends_on']) + { + $duplicate_migrations[] = $name; + unset($migration_state[$prepended_name]); + } + else if ($prefixless_name != $name && isset($migration_state[$prefixless_name]) && $migration_state[$prefixless_name]['migration_depends_on'] == $migration_state[$name]['migration_depends_on']) + { + $duplicate_migrations[] = $prefixless_name; + unset($migration_state[$prefixless_name]); + } + } + + if (count($duplicate_migrations)) + { + $sql = 'DELETE + FROM ' . $this->table_prefix . 'migrations + WHERE ' . $this->db->sql_in_set('migration_name', $duplicate_migrations); + $this->db->sql_query($sql); + } + } +} diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php index 4c4c0a8672..45a333ac94 100644 --- a/phpBB/phpbb/db/migrator.php +++ b/phpBB/phpbb/db/migrator.php @@ -201,6 +201,34 @@ class migrator } /** + * Get a valid migration name from the migration state array in case the + * supplied name is not in the migration state list. + * + * @param string $name Migration name + * @return string Migration name + */ + protected function get_valid_name($name) + { + // Try falling back to a valid migration name with or without leading backslash + if (!isset($this->migration_state[$name])) + { + $prepended_name = ($name[0] == '\\' ? '' : '\\') . $name; + $prefixless_name = $name[0] == '\\' ? substr($name, 1) : $name; + + if (isset($this->migration_state[$prepended_name])) + { + $name = $prepended_name; + } + else if (isset($this->migration_state[$prefixless_name])) + { + $name = $prefixless_name; + } + } + + return $name; + } + + /** * Effectively runs a single update step from the next migration to be applied. * * @return null @@ -209,6 +237,8 @@ class migrator { foreach ($this->migrations as $name) { + $name = $this->get_valid_name($name); + if (!isset($this->migration_state[$name]) || !$this->migration_state[$name]['migration_schema_done'] || !$this->migration_state[$name]['migration_data_done']) @@ -264,6 +294,9 @@ class migrator foreach ($state['migration_depends_on'] as $depend) { + $depend = $this->get_valid_name($depend); + + // Test all possible namings before throwing exception if ($this->unfulfillable($depend) !== false) { throw new \phpbb\db\migration\exception('MIGRATION_NOT_FULFILLABLE', $name, $depend); @@ -742,6 +775,8 @@ class migrator */ public function unfulfillable($name) { + $name = $this->get_valid_name($name); + if (isset($this->migration_state[$name]) || isset($this->fulfillable_migrations[$name])) { return false; @@ -757,6 +792,7 @@ class migrator foreach ($depends as $depend) { + $depend = $this->get_valid_name($depend); $unfulfillable = $this->unfulfillable($depend); if ($unfulfillable !== false) { diff --git a/phpBB/phpbb/event/kernel_exception_subscriber.php b/phpBB/phpbb/event/kernel_exception_subscriber.php index 9d15f9370e..1ee771cfe7 100644 --- a/phpBB/phpbb/event/kernel_exception_subscriber.php +++ b/phpBB/phpbb/event/kernel_exception_subscriber.php @@ -61,7 +61,7 @@ class kernel_exception_subscriber implements EventSubscriberInterface $exception = $event->getException(); $message = $exception->getMessage(); - $this->type_caster->set_var($message, $message, 'string', false, false); + $this->type_caster->set_var($message, $message, 'string', true, false); if ($exception instanceof \phpbb\exception\exception_interface) { diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php index 094ff78abe..8f199cd931 100644 --- a/phpBB/phpbb/log/log.php +++ b/phpBB/phpbb/log/log.php @@ -893,9 +893,29 @@ class log implements \phpbb\log\log_interface $forum_auth = array('f_read' => array(), 'm_' => array()); $topic_ids = array_unique($topic_ids); - $sql = 'SELECT topic_id, forum_id - FROM ' . TOPICS_TABLE . ' - WHERE ' . $this->db->sql_in_set('topic_id', array_map('intval', $topic_ids)); + $sql_ary = array( + 'SELECT' => 'topic_id, forum_id', + 'FROM' => array( + TOPICS_TABLE => 't', + ), + 'WHERE' => $this->db->sql_in_set('topic_id', array_map('intval', $topic_ids)), + ); + + /** + * Allow modifying SQL query before topic data is retrieved. + * + * @event core.phpbb_log_get_topic_auth_sql_before + * @var array topic_ids Array with unique topic IDs + * @var array sql_ary SQL array + * @since 3.1.11-RC1 + */ + $vars = array( + 'topic_ids', + 'sql_ary', + ); + extract($this->dispatcher->trigger_event('core.phpbb_log_get_topic_auth_sql_before', compact($vars))); + + $sql = $this->db->sql_build_query('SELECT', $sql_ary); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php index 785e5f243d..cc32984ac6 100644 --- a/phpBB/phpbb/notification/type/report_pm.php +++ b/phpBB/phpbb/notification/type/report_pm.php @@ -52,7 +52,7 @@ class report_pm extends \phpbb\notification\type\pm * * @var string Permission name */ - protected $permission = 'm_report'; + protected $permission = 'm_pm_report'; /** * Notification option data (for outputting to the user) diff --git a/phpBB/styles/prosilver/template/ajax.js b/phpBB/styles/prosilver/template/ajax.js index e3780f024a..311da92a95 100644 --- a/phpBB/styles/prosilver/template/ajax.js +++ b/phpBB/styles/prosilver/template/ajax.js @@ -132,9 +132,9 @@ phpbb.markNotifications = function($popup, unreadCount) { // Update the unread count. $('strong', '#notification_list_button').html(unreadCount); - // Remove the Mark all read link if there are no unread notifications. + // Remove the Mark all read link & notification count if there are no unread notifications. if (!unreadCount) { - $('#mark_all_notifications').remove(); + $('#mark_all_notifications, #notification_list_button > strong').remove(); } // Update page title diff --git a/phpBB/styles/prosilver/template/jumpbox.html b/phpBB/styles/prosilver/template/jumpbox.html index 3096d08318..fcd8ddbc1e 100644 --- a/phpBB/styles/prosilver/template/jumpbox.html +++ b/phpBB/styles/prosilver/template/jumpbox.html @@ -1,32 +1,34 @@ -<!-- IF S_VIEWTOPIC --> - <p class="jumpbox-return"><a href="{U_VIEW_FORUM}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO_FORUM}</a></p> -<!-- ELSEIF S_VIEWFORUM --> - <p class="jumpbox-return"><a href="{U_INDEX}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO_INDEX}</a></p> -<!-- ELSEIF SEARCH_TOPIC --> - <p class="jumpbox-return"><a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}" accesskey="r">{L_RETURN_TO_TOPIC}</a></p> -<!-- ELSEIF S_SEARCH_ACTION --> - <p class="jumpbox-return"><a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}" accesskey="r">{L_GO_TO_SEARCH_ADV}</a></p> -<!-- ENDIF --> +<div class="action-bar actions-jump"> + <!-- IF S_VIEWTOPIC --> + <p class="jumpbox-return"><a href="{U_VIEW_FORUM}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO_FORUM}</a></p> + <!-- ELSEIF S_VIEWFORUM --> + <p class="jumpbox-return"><a href="{U_INDEX}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO_INDEX}</a></p> + <!-- ELSEIF SEARCH_TOPIC --> + <p class="jumpbox-return"><a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}" accesskey="r">{L_RETURN_TO_TOPIC}</a></p> + <!-- ELSEIF S_SEARCH_ACTION --> + <p class="jumpbox-return"><a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}" accesskey="r">{L_GO_TO_SEARCH_ADV}</a></p> + <!-- ENDIF --> -<!-- IF S_DISPLAY_JUMPBOX --> + <!-- IF S_DISPLAY_JUMPBOX --> - <div class="dropdown-container dropdown-container-{S_CONTENT_FLOW_END}<!-- IF not S_IN_MCP --> dropdown-up<!-- ENDIF --> dropdown-{S_CONTENT_FLOW_BEGIN} dropdown-button-control" id="jumpbox"> - <span title="<!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->" class="dropdown-trigger button dropdown-select"> - <!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF --> - </span> - <div class="dropdown hidden"> - <div class="pointer"><div class="pointer-inner"></div></div> - <ul class="dropdown-contents"> - <!-- BEGIN jumpbox_forums --> - <!-- IF jumpbox_forums.FORUM_ID neq -1 --> - <li><!-- BEGIN level --> <!-- END level --><a href="{jumpbox_forums.LINK}">{jumpbox_forums.FORUM_NAME}</a></li> - <!-- ENDIF --> - <!-- END jumpbox_forums --> - </ul> + <div class="dropdown-container dropdown-container-{S_CONTENT_FLOW_END}<!-- IF not S_IN_MCP --> dropdown-up<!-- ENDIF --> dropdown-{S_CONTENT_FLOW_BEGIN} dropdown-button-control" id="jumpbox"> + <span title="<!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->" class="dropdown-trigger button dropdown-select"> + <!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF --> + </span> + <div class="dropdown hidden"> + <div class="pointer"><div class="pointer-inner"></div></div> + <ul class="dropdown-contents"> + <!-- BEGIN jumpbox_forums --> + <!-- IF jumpbox_forums.FORUM_ID neq -1 --> + <li><!-- BEGIN level --> <!-- END level --><a href="{jumpbox_forums.LINK}">{jumpbox_forums.FORUM_NAME}</a></li> + <!-- ENDIF --> + <!-- END jumpbox_forums --> + </ul> + </div> </div> - </div> -<!-- ELSE --> - <br /><br /> -<!-- ENDIF --> + <!-- ELSE --> + </br></br> + <!-- ENDIF --> +</div> diff --git a/phpBB/styles/prosilver/template/navbar_header.html b/phpBB/styles/prosilver/template/navbar_header.html index e948e2e0f6..e5f354a943 100644 --- a/phpBB/styles/prosilver/template/navbar_header.html +++ b/phpBB/styles/prosilver/template/navbar_header.html @@ -18,7 +18,7 @@ <!-- IF S_USER_LOGGED_IN --> <li class="small-icon icon-search-new"><a href="{U_SEARCH_NEW}" role="menuitem">{L_SEARCH_NEW}</a></li> <!-- ENDIF --> - <!-- IF S_LOAD_UNREADS --> + <!-- IF S_LOAD_UNREADS --> <li class="small-icon icon-search-unread"><a href="{U_SEARCH_UNREAD}" role="menuitem">{L_SEARCH_UNREAD}</a></li> <!-- ENDIF --> <li class="small-icon icon-search-unanswered"><a href="{U_SEARCH_UNANSWERED}" role="menuitem">{L_SEARCH_UNANSWERED}</a></li> @@ -55,14 +55,14 @@ <div class="pointer"><div class="pointer-inner"></div></div> <ul class="dropdown-contents" role="menu"> <!-- IF U_RESTORE_PERMISSIONS --><li class="small-icon icon-restore-permissions"><a href="{U_RESTORE_PERMISSIONS}">{L_RESTORE_PERMISSIONS}</a></li><!-- ENDIF --> - + <!-- EVENT navbar_header_profile_list_before --> - + <li class="small-icon icon-ucp"><a href="{U_PROFILE}" title="{L_PROFILE}" role="menuitem">{L_PROFILE}</a></li> <li class="small-icon icon-profile"><a href="{U_USER_PROFILE}" title="{L_READ_PROFILE}" role="menuitem">{L_READ_PROFILE}</a></li> - + <!-- EVENT navbar_header_profile_list_after --> - + <li class="separator"></li> <li class="small-icon icon-logout"><a href="{U_LOGIN_LOGOUT}" title="{L_LOGIN_LOGOUT}" accesskey="x" role="menuitem">{L_LOGIN_LOGOUT}</a></li> </ul> @@ -72,12 +72,12 @@ </li> <!-- IF S_DISPLAY_PM --> <li class="small-icon icon-pm rightside" data-skip-responsive="true"> - <a href="{U_PRIVATEMSGS}" role="menuitem"><span>{L_PRIVATE_MESSAGES} [</span><strong>{PRIVATE_MESSAGE_COUNT}</strong><span>]</span></a> + <a href="{U_PRIVATEMSGS}" role="menuitem"><span>{L_PRIVATE_MESSAGES} </span><!-- IF PRIVATE_MESSAGE_COUNT --><strong class="badge">{PRIVATE_MESSAGE_COUNT}</strong><!-- ENDIF --></a> </li> <!-- ENDIF --> <!-- IF S_NOTIFICATIONS_DISPLAY --> <li class="small-icon icon-notification dropdown-container dropdown-{S_CONTENT_FLOW_END} rightside" data-skip-responsive="true"> - <a href="{U_VIEW_ALL_NOTIFICATIONS}" id="notification_list_button" class="dropdown-trigger"><span>{L_NOTIFICATIONS} [</span><strong>{NOTIFICATIONS_COUNT}</strong><span>]</span></a> + <a href="{U_VIEW_ALL_NOTIFICATIONS}" id="notification_list_button" class="dropdown-trigger"><span>{L_NOTIFICATIONS} </span><!-- IF NOTIFICATIONS_COUNT --><strong class="badge">{NOTIFICATIONS_COUNT}</strong><!-- ENDIF --></a> <!-- INCLUDE notification_dropdown.html --> </li> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/posting_attach_body.html b/phpBB/styles/prosilver/template/posting_attach_body.html index 81b2c2bf41..d7922297a7 100644 --- a/phpBB/styles/prosilver/template/posting_attach_body.html +++ b/phpBB/styles/prosilver/template/posting_attach_body.html @@ -7,7 +7,7 @@ <dl> <dt><label for="fileupload">{L_FILENAME}{L_COLON}</label></dt> <dd> - <input type="file" name="fileupload" id="fileupload" maxlength="{FILESIZE}" value="" class="inputbox autowidth" /> + <input type="file" name="fileupload" id="fileupload" class="inputbox autowidth" /> <input type="submit" name="add_file" value="{L_ADD_FILE}" class="button2" onclick="upload = true;" /> </dd> </dl> diff --git a/phpBB/styles/prosilver/template/posting_topic_review.html b/phpBB/styles/prosilver/template/posting_topic_review.html index c51d8032dc..4d5ab16afe 100644 --- a/phpBB/styles/prosilver/template/posting_topic_review.html +++ b/phpBB/styles/prosilver/template/posting_topic_review.html @@ -16,6 +16,10 @@ <div class="post bg3 post-ignore"> <div class="inner"> {topic_review_row.L_IGNORE_POST} + <!-- ELSE IF topic_review_row.S_POST_DELETED --> + <div class="post bg3 post-ignore"> + <div class="inner"> + {topic_review_row.L_DELETE_POST} <!-- ELSE --> <div class="post <!-- IF topic_review_row.S_ROW_COUNT is odd -->bg1<!-- ELSE -->bg2<!-- ENDIF --><!-- IF topic_review_row.POST_ID == REPORTED_POST_ID --> reported<!-- ENDIF -->"> <div class="inner"> diff --git a/phpBB/styles/prosilver/template/ucp_main_subscribed.html b/phpBB/styles/prosilver/template/ucp_main_subscribed.html index ef03317578..2d65b800a0 100644 --- a/phpBB/styles/prosilver/template/ucp_main_subscribed.html +++ b/phpBB/styles/prosilver/template/ucp_main_subscribed.html @@ -30,7 +30,7 @@ {forumrow.FORUM_DESC} <!-- IF forumrow.LAST_POST_TIME --> <div class="responsive-show" style="display: none;"> - {L_LAST_POST} {L_POST_BY_AUTHOR} {forumrow.LAST_POST_AUTHOR_FULL} « <a href="{topicrow.U_LAST_POST}">{forumrow.LAST_POST_TIME}</a> + {L_LAST_POST} {L_POST_BY_AUTHOR} {forumrow.LAST_POST_AUTHOR_FULL} « <a href="{forumrow.U_LAST_POST}">{forumrow.LAST_POST_TIME}</a> </div> <!-- ENDIF --> </div> @@ -113,9 +113,9 @@ <div class="action-bar bottom"> <div class="pagination"> {TOTAL_TOPICS} - <!-- IF .pagination --> + <!-- IF .pagination --> <!-- INCLUDE pagination.html --> - <!-- ELSE --> + <!-- ELSE --> • {PAGE_NUMBER} <!-- ENDIF --> </div> diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index 29cf641df2..9095e61369 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -1161,3 +1161,8 @@ ul.linklist li.responsive-menu a.responsive-menu-link:hover:before, ul.linklist li.notification-reported strong, li.notification-disapproved strong { color: #D31141; } + +.badge { + background-color: #D31141; + color: #ffffff; +} diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index 5dd5ecdb28..cf6d14e6ab 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -137,7 +137,9 @@ p.right { } p.jumpbox-return { - margin-top: 1em; + margin-top: 10px; + margin-bottom: 0; + float: left; } b, strong { @@ -1251,6 +1253,22 @@ ul.linklist:after, margin-left: 58px; } +.badge { + border-radius: 10px; + opacity: 0.8; + text-align: center; + white-space: nowrap; + font-size: 10px; + line-height: 1; + float: right; + display: inline-block; + margin-left: 3px; + vertical-align: baseline; + position: relative; + top: 3px; + padding: 4px 6px; +} + /* Navbar specific list items ----------------------------------------*/ @@ -1281,10 +1299,6 @@ ul.linklist:after, display: none; } -.compact .icon-notification > a > strong, .compact .icon-pm > a > strong { - padding-left: 2px; -} - .dropdown-page-jump .dropdown { top: 20px; } diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 780e43e09b..5c98a9c931 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -495,6 +495,28 @@ if ($config['allow_topic_notify']) } } +/** +* Event to modify highlight. +* +* @event core.viewtopic_highlight_modify +* @var string highlight String to be highlighted +* @var string highlight_match Highlight string to be used in preg_replace +* @var array topic_data Topic data +* @var int start Pagination start +* @var int total_posts Number of posts +* @var string viewtopic_url Current viewtopic URL +* @since 3.1.11-RC1 +*/ +$vars = array( + 'highlight', + 'highlight_match', + 'topic_data', + 'start', + 'total_posts', + 'viewtopic_url', +); +extract($phpbb_dispatcher->trigger_event('core.viewtopic_highlight_modify', compact($vars))); + // Bookmarks if ($config['allow_bookmarks'] && $user->data['is_registered'] && request_var('bookmark', 0)) { diff --git a/tests/functional/notification_test.php b/tests/functional/notification_test.php index ec03f7a6a4..d4c61cc062 100644 --- a/tests/functional/notification_test.php +++ b/tests/functional/notification_test.php @@ -82,6 +82,6 @@ class phpbb_functional_notification_test extends phpbb_functional_test_case // Get form token $link = $crawler->selectLink($this->lang('NOTIFICATIONS_MARK_ALL_READ'))->link()->getUri(); $crawler = self::request('GET', substr($link, strpos($link, 'ucp.'))); - $this->assertEquals(0, $crawler->filter('#notification_list_button strong')->text()); + $this->assertCount(0, $crawler->filter('#notification_list_button strong')); } } diff --git a/tests/functional/search/base.php b/tests/functional/search/base.php index d41e3ec925..f1e9b517d4 100644 --- a/tests/functional/search/base.php +++ b/tests/functional/search/base.php @@ -76,18 +76,16 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case { $this->add_lang('acp/search'); $crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid); - $form_values = $crawler->selectButton('Delete index')->form()->getValues(); - $crawler = self::request( - 'POST', - 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid, + $form = $crawler->selectButton('Create index')->form(); + $form_values = $form->getValues(); + $form_values = array_merge($form_values, array( 'search_type' => $this->search_backend, 'action' => 'create', - 'submit' => true, - 'form_token' => $form_values['form_token'], - 'creation_time' => $form_values['creation_time'], ) ); + $form->setValues($form_values); + $crawler = self::submit($form); $this->assertContainsLang('SEARCH_INDEX_CREATED', $crawler->text()); } @@ -95,18 +93,16 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case { $this->add_lang('acp/search'); $crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid); - $form_values = $crawler->selectButton('Delete index')->form()->getValues(); - $crawler = self::request( - 'POST', - 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid, + $form = $crawler->selectButton('Delete index')->form(); + $form_values = $form->getValues(); + $form_values = array_merge($form_values, array( 'search_type' => $this->search_backend, 'action' => 'delete', - 'submit' => true, - 'form_token' => $form_values['form_token'], - 'creation_time' => $form_values['creation_time'], ) ); + $form->setValues($form_values); + $crawler = self::submit($form); $this->assertContainsLang('SEARCH_INDEX_REMOVED', $crawler->text()); } } diff --git a/tests/functional/user_password_reset_test.php b/tests/functional/user_password_reset_test.php index f9406f0eb5..3da78407cf 100644 --- a/tests/functional/user_password_reset_test.php +++ b/tests/functional/user_password_reset_test.php @@ -113,6 +113,49 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca $this->assertContains($this->lang('LOGIN_ERROR_PASSWORD', '', ''), $crawler->filter('html')->text()); } + /** + * @depends test_login + */ + public function test_acivateAfterDeactivate() + { + // User is active, actkey should not exist + $this->get_user_data(); + $this->assertEmpty($this->user_data['user_actkey']); + + $this->login(); + $this->admin_login(); + $this->add_lang('acp/users'); + + // Go to user account page + $crawler = self::request('GET', 'adm/index.php?i=acp_users&mode=overview&sid=' . $this->sid); + $this->assertContainsLang('FIND_USERNAME', $crawler->filter('html')->text()); + + $form = $crawler->selectButton('Submit')->form(); + $crawler = self::submit($form, array('username' => 'reset-password-test-user')); + + // Deactivate account and go back to overview of current user + $this->assertContainsLang('USER_TOOLS', $crawler->filter('html')->text()); + $form = $crawler->filter('input[name=update]')->selectButton('Submit')->form(); + $crawler = self::submit($form, array('action' => 'active')); + + $this->assertContainsLang('USER_ADMIN_DEACTIVED', $crawler->filter('html')->text()); + $link = $crawler->selectLink('Back to previous page')->link(); + $crawler = self::request('GET', preg_replace('#(.+)(adm/index.php.+)#', '$2', $link->getUri())); + + // Ensure again that actkey is empty after deactivation + $this->get_user_data(); + $this->assertEmpty($this->user_data['user_actkey']); + + // Force reactivation of account and check that act key is not empty anymore + $this->assertContainsLang('USER_TOOLS', $crawler->filter('html')->text()); + $form = $crawler->filter('input[name=update]')->selectButton('Submit')->form(); + $crawler = self::submit($form, array('action' => 'reactivate')); + $this->assertContainsLang('FORCE_REACTIVATION_SUCCESS', $crawler->filter('html')->text()); + + $this->get_user_data(); + $this->assertNotEmpty($this->user_data['user_actkey']); + } + protected function get_user_data() { $db = $this->get_db(); diff --git a/tests/functions/user_delete_test.php b/tests/functions/user_delete_test.php index db52dcded7..c224323273 100644 --- a/tests/functions/user_delete_test.php +++ b/tests/functions/user_delete_test.php @@ -71,6 +71,7 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case $oauth_provider_collection, 'phpbb_users', $phpbb_container, + $phpbb_dispatcher, $this->phpbb_root_path, $this->php_ext ); |