diff options
22 files changed, 615 insertions, 367 deletions
diff --git a/phpBB/adm/style/acp_database.html b/phpBB/adm/style/acp_database.html index 39f06319f9..ed0f4dd453 100644 --- a/phpBB/adm/style/acp_database.html +++ b/phpBB/adm/style/acp_database.html @@ -20,7 +20,6 @@ <p class="submit-buttons"> <input class="button1" type="submit" id="submit" name="submit" value="{L_START_RESTORE}" /> <input class="button2" type="submit" id="delete" name="delete" value="{L_DELETE_BACKUP}" /> - <input class="button2" type="submit" id="download" name="download" value="{L_DOWNLOAD_BACKUP}" /> </p> {S_FORM_TOKEN} </fieldset> @@ -72,7 +71,6 @@ <dt><label for="where">{L_ACTION}{L_COLON}</label></dt> <dd> <label><input id="where" type="radio" class="radio" name="where" value="store" checked="checked" /> {L_STORE_LOCAL}</label> - <label><input type="radio" class="radio" name="where" value="download" /> {L_DOWNLOAD}</label> </dd> </dl> <dl> diff --git a/phpBB/config/default/container/services_content.yml b/phpBB/config/default/container/services_content.yml index 602fd25f4e..6717c20337 100644 --- a/phpBB/config/default/container/services_content.yml +++ b/phpBB/config/default/container/services_content.yml @@ -35,6 +35,7 @@ services: - '@config_text' - '@dbal.conn' - '@user' + - '@dispatcher' - '%core.root_path%' - '%core.php_ext%' diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index 02dad993f8..fb782ee452 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -28,29 +28,29 @@ acp_bbcodes_edit_fieldsets_after * Since: 3.1.0-a3 * Purpose: Add settings to BBCode add/edit form -acp_email_group_options_append +acp_email_find_username_append === * Location: adm/style/acp_email.html * Since: 3.1.7-RC1 -* Purpose: Add content at the end of the group options select box +* Purpose: Add content at the end of the find username link -acp_email_group_options_prepend +acp_email_find_username_prepend === * Location: adm/style/acp_email.html * Since: 3.1.7-RC1 -* Purpose: Add content at the start of the group options select box +* Purpose: Add content at the start of the find username link -acp_email_find_username_append +acp_email_group_options_append === * Location: adm/style/acp_email.html * Since: 3.1.7-RC1 -* Purpose: Add content at the end of the fimd username link +* Purpose: Add content at the end of the group options select box -acp_email_find_username_prepend +acp_email_group_options_prepend === * Location: adm/style/acp_email.html * Since: 3.1.7-RC1 -* Purpose: Add content at the start of the fimd username link +* Purpose: Add content at the start of the group options select box acp_email_options_after === @@ -160,17 +160,17 @@ acp_forums_rules_settings_prepend * Since: 3.1.2-RC1 * Purpose: Add settings to forums before rules settings section -acp_group_options_before +acp_group_options_after === * Location: adm/style/acp_groups.html * Since: 3.1.0-b4 -* Purpose: Add addtional options to group settings (before GROUP_FOUNDER_MANAGE) +* Purpose: Add additional options to group settings (after GROUP_RECEIVE_PM) -acp_group_options_after +acp_group_options_before === * Location: adm/style/acp_groups.html * Since: 3.1.0-b4 -* Purpose: Add addtional options to group settings (after GROUP_RECEIVE_PM) +* Purpose: Add additional options to group settings (before GROUP_FOUNDER_MANAGE) acp_groups_find_username_append === @@ -281,29 +281,29 @@ acp_overall_header_stylesheets_after * Purpose: Add assets after stylesheets within the `<head>` tags in the ACP. Note that INCLUDECSS will not work with this event. -acp_permission_forum_copy_src_forum_append +acp_permission_forum_copy_dest_forum_append === * Location: adm/style/permission_forum_copy.html * Since: 3.1.7-RC1 -* Purpose: Add content after the sourse forum select form +* Purpose: Add content after the destination forum select form -acp_permission_forum_copy_src_forum_prepend +acp_permission_forum_copy_dest_forum_prepend === * Location: adm/style/permission_forum_copy.html * Since: 3.1.7-RC1 -* Purpose: Add content before the sourse forum select form +* Purpose: Add content before the destination forum select form -acp_permission_forum_copy_dest_forum_append +acp_permission_forum_copy_src_forum_append === * Location: adm/style/permission_forum_copy.html * Since: 3.1.7-RC1 -* Purpose: Add content after the destiny forum select form +* Purpose: Add content after the source forum select form -acp_permission_forum_copy_dest_forum_prepend +acp_permission_forum_copy_src_forum_prepend === * Location: adm/style/permission_forum_copy.html * Since: 3.1.7-RC1 -* Purpose: Add content before the destiny forum select form +* Purpose: Add content before the source forum select form acp_permissions_add_group_options_append === @@ -498,41 +498,6 @@ acp_ranks_list_header_before * Purpose: Add content after the last header-column (but before the action column) in the ranks list in the ACP -acp_styles_list_before -=== -* Locations: - + adm/style/acp_styles.html -* Since: 3.1.7-RC1 -* Purpose: Add content before list of styles - -acp_users_mode_add -=== -* Locations: - + adm/style/acp_users.html -* Since: 3.2.2-RC1 -* Purpose: Add extra modes to the ACP user page - -acp_users_profile_before -=== -* Locations: - + adm/style/acp_users_profile.html -* Since: 3.1.4-RC1 -* Purpose: Add content before the profile details when editing a user in the ACP - -acp_users_profile_after -=== -* Locations: - + adm/style/acp_users_profile.html -* Since: 3.1.4-RC1 -* Purpose: Add content after the profile details but before the custom profile fields when editing a user in the ACP - -acp_users_profile_custom_after -=== -* Locations: - + adm/style/acp_users_profile.html -* Since: 3.1.4-RC1 -* Purpose: Add content after the the custom profile fields when editing a user in the ACP - acp_simple_footer_after === * Location: adm/style/simple_footer.html @@ -558,6 +523,20 @@ acp_simple_header_stylesheets_after * Purpose: Add assets after stylesheets within the `<head>` tags in the simple header of the ACP. Note that INCLUDECSS will not work with this event. +acp_styles_list_before +=== +* Locations: + + adm/style/acp_styles.html +* Since: 3.1.7-RC1 +* Purpose: Add content before list of styles + +acp_users_mode_add +=== +* Locations: + + adm/style/acp_users.html +* Since: 3.2.2-RC1 +* Purpose: Add extra modes to the ACP user page + acp_users_overview_options_append === * Location: adm/style/acp_users_overview.html @@ -570,12 +549,6 @@ acp_users_prefs_append * Since: 3.1.0-b3 * Purpose: Add user options fieldset to the bottom of ACP users prefs settings -acp_users_prefs_prepend -=== -* Location: adm/style/acp_users_prefs.html -* Since: 3.1.0-b3 -* Purpose: Add user options fieldset to the top of ACP users prefs settings - acp_users_prefs_personal_append === * Location: adm/style/acp_users_prefs.html @@ -600,6 +573,12 @@ acp_users_prefs_post_prepend * Since: 3.1.0-b3 * Purpose: Add user options fieldset to the top of ACP users post prefs settings +acp_users_prefs_prepend +=== +* Location: adm/style/acp_users_prefs.html +* Since: 3.1.0-b3 +* Purpose: Add user options fieldset to the top of ACP users prefs settings + acp_users_prefs_view_append === * Location: adm/style/acp_users_prefs.html @@ -612,6 +591,27 @@ acp_users_prefs_view_prepend * Since: 3.1.0-b3 * Purpose: Add user options fieldset to the top of ACP users view prefs settings +acp_users_profile_after +=== +* Locations: + + adm/style/acp_users_profile.html +* Since: 3.1.4-RC1 +* Purpose: Add content after the profile details but before the custom profile fields when editing a user in the ACP + +acp_users_profile_before +=== +* Locations: + + adm/style/acp_users_profile.html +* Since: 3.1.4-RC1 +* Purpose: Add content before the profile details when editing a user in the ACP + +acp_users_profile_custom_after +=== +* Locations: + + adm/style/acp_users_profile.html +* Since: 3.1.4-RC1 +* Purpose: Add content after the the custom profile fields when editing a user in the ACP + acp_users_select_group_after === * Location: adm/style/acp_users.html @@ -764,6 +764,13 @@ forumlist_body_last_poster_username_prepend * Since: 3.2.4-RC1 * Purpose: Prepend information to last poster username of member +forumlist_body_last_row_after +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.1.0-b2 +* Purpose: Add content after the very last row of the forum list. + forumlist_body_subforum_link_append === * Locations: @@ -792,13 +799,6 @@ forumlist_body_subforums_before * Since: 3.1.0-a4 * Purpose: Add content before the list of subforums (if any) for each forum on the forum list. -forumlist_body_last_row_after -=== -* Locations: - + styles/prosilver/template/forumlist_body.html -* Since: 3.1.0-b2 -* Purpose: Add content after the very last row of the forum list. - index_body_birthday_block_before === * Locations: @@ -932,19 +932,19 @@ mcp_forum_actions_before * Since: 3.1.11-RC1 * Purpose: Add some information before actions fieldset -mcp_forum_topic_title_before +mcp_forum_topic_title_after === * Locations: + styles/prosilver/template/mcp_forum.html * Since: 3.1.6-RC1 -* Purpose: Add some information before the topic title +* Purpose: Add some information after the topic title -mcp_forum_topic_title_after +mcp_forum_topic_title_before === * Locations: + styles/prosilver/template/mcp_forum.html * Since: 3.1.6-RC1 -* Purpose: Add some information after the topic title +* Purpose: Add some information before the topic title mcp_front_latest_logs_after === @@ -1693,19 +1693,61 @@ overall_header_stylesheets_after * Purpose: Add asset calls after stylesheets within the `</head>` tag. Note that INCLUDECSS will not work with this event. +posting_attach_body_attach_row_after +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content after attachment row in the file list + +posting_attach_body_attach_row_append +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content appending the attachment row in the file list + +posting_attach_body_attach_row_before +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content before attachment row in the file list + posting_attach_body_attach_row_controls_append === * Locations: + styles/prosilver/template/posting_attach_body.html * Since: 3.2.2-RC1 -* Purpose: Add content after attachment control elements +* Purpose: Add content after attachment control elements posting_attach_body_attach_row_controls_prepend === * Locations: + styles/prosilver/template/posting_attach_body.html * Since: 3.2.2-RC1 -* Purpose: Add content before attachment control elements +* Purpose: Add content before attachment control elements + +posting_attach_body_attach_row_prepend +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content prepending attachment row in the file list + +posting_attach_body_file_list_after +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content after attachments list + +posting_attach_body_file_list_before +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content before attachments list posting_editor_add_panel_tab === @@ -1903,33 +1945,33 @@ posting_topic_title_before * Since: 3.1.6-RC1 * Purpose: Allows to add some information on the left of the topic title in the posting form -quickreply_editor_panel_after +quickreply_editor_message_after === * Locations: + styles/prosilver/template/quickreply_editor.html -* Since: 3.1.0-b2 -* Purpose: Add content after the quick reply panel (but inside the form) +* Since: 3.1.0-a4 +* Purpose: Add content after the quick reply textbox -quickreply_editor_panel_before +quickreply_editor_message_before === * Locations: + styles/prosilver/template/quickreply_editor.html -* Since: 3.1.0-b2 -* Purpose: Add content before the quick reply panel (but inside the form) +* Since: 3.1.0-a4 +* Purpose: Add content before the quick reply textbox -quickreply_editor_message_after +quickreply_editor_panel_after === * Locations: + styles/prosilver/template/quickreply_editor.html -* Since: 3.1.0-a4 -* Purpose: Add content after the quick reply textbox +* Since: 3.1.0-b2 +* Purpose: Add content after the quick reply panel (but inside the form) -quickreply_editor_message_before +quickreply_editor_panel_before === * Locations: + styles/prosilver/template/quickreply_editor.html -* Since: 3.1.0-a4 -* Purpose: Add content before the quick reply textbox +* Since: 3.1.0-b2 +* Purpose: Add content before the quick reply panel (but inside the form) quickreply_editor_subject_before === @@ -2191,7 +2233,7 @@ simple_header_stylesheets_after * Purpose: Add asset calls after stylesheets within the `</head>` tag. Note that INCLUDECSS will not work with this event. -topiclist_row_prepend +topiclist_row_append === * Locations: + styles/prosilver/template/search_results.html @@ -2201,7 +2243,7 @@ topiclist_row_prepend * Changed: 3.1.6-RC1 Added event to mcp_forum.html * Purpose: Add content into topic rows (inside the elements containing topic titles) -topiclist_row_append +topiclist_row_prepend === * Locations: + styles/prosilver/template/search_results.html @@ -2234,6 +2276,20 @@ ucp_agreement_terms_before * Since: 3.1.0-b3 * Purpose: Add content before the terms of agreement text at user registration +ucp_friend_list_after +=== +* Locations: + + styles/prosilver/template/ucp_zebra_friends.html +* Since: 3.1.0-a4 +* Purpose: Add optional elements after list of friends in UCP + +ucp_friend_list_before +=== +* Locations: + + styles/prosilver/template/ucp_zebra_friends.html +* Since: 3.1.0-a4 +* Purpose: Add optional elements before list of friends in UCP + ucp_main_front_user_activity_after === * Locations: @@ -2416,6 +2472,13 @@ ucp_pm_viewmessage_rank_before * Purpose: Add data before the rank on the user profile when viewing a private message +ucp_prefs_personal_append +=== +* Locations: + + styles/prosilver/template/ucp_prefs_personal.html +* Since: 3.1.0-a1 +* Purpose: Add user options to the bottom of the Edit Global Settings block + ucp_prefs_personal_prepend === * Locations: @@ -2423,12 +2486,12 @@ ucp_prefs_personal_prepend * Since: 3.1.0-a1 * Purpose: Add user options to the top of the Edit Global Settings block -ucp_prefs_personal_append +ucp_prefs_post_append === * Locations: - + styles/prosilver/template/ucp_prefs_personal.html + + styles/prosilver/template/ucp_prefs_post.html * Since: 3.1.0-a1 -* Purpose: Add user options to the bottom of the Edit Global Settings block +* Purpose: Add user options to the bottom of the Edit Posting Defaults block ucp_prefs_post_prepend === @@ -2437,12 +2500,13 @@ ucp_prefs_post_prepend * Since: 3.1.0-a1 * Purpose: Add user options to the top of the Edit Posting Defaults block -ucp_prefs_post_append +ucp_prefs_view_radio_buttons_append === * Locations: - + styles/prosilver/template/ucp_prefs_post.html + + styles/prosilver/template/ucp_prefs_view.html * Since: 3.1.0-a1 -* Purpose: Add user options to the bottom of the Edit Posting Defaults block +* Purpose: Add options to the bottom of the radio buttons block of the Edit +Display Options screen ucp_prefs_view_radio_buttons_prepend === @@ -2452,12 +2516,12 @@ ucp_prefs_view_radio_buttons_prepend * Purpose: Add options to the top of the radio buttons block of the Edit Display Options screen -ucp_prefs_view_radio_buttons_append +ucp_prefs_view_select_menu_append === * Locations: + styles/prosilver/template/ucp_prefs_view.html * Since: 3.1.0-a1 -* Purpose: Add options to the bottom of the radio buttons block of the Edit +* Purpose: Add options to the bottom of the drop-down lists block of the Edit Display Options screen ucp_prefs_view_select_menu_prepend @@ -2468,13 +2532,12 @@ ucp_prefs_view_select_menu_prepend * Purpose: Add options to the top of the drop-down lists block of the Edit Display Options screen -ucp_prefs_view_select_menu_append +ucp_profile_profile_info_after === * Locations: - + styles/prosilver/template/ucp_prefs_view.html -* Since: 3.1.0-a1 -* Purpose: Add options to the bottom of the drop-down lists block of the Edit -Display Options screen + + styles/prosilver/template/ucp_profile_profile_info.html +* Since: 3.1.4-RC1 +* Purpose: Add options in profile page fieldset - after custom profile fields. ucp_profile_profile_info_before === @@ -2483,12 +2546,12 @@ ucp_profile_profile_info_before * Since: 3.1.4-RC1 * Purpose: Add options in profile page fieldset - before jabber field. -ucp_profile_profile_info_after +ucp_profile_register_details_after === * Locations: - + styles/prosilver/template/ucp_profile_profile_info.html + + styles/prosilver/template/ucp_profile_reg_details.html * Since: 3.1.4-RC1 -* Purpose: Add options in profile page fieldset - after custom profile fields. +* Purpose: Add options in profile page fieldset - after confirm password field. ucp_profile_register_details_before === @@ -2497,12 +2560,12 @@ ucp_profile_register_details_before * Since: 3.1.4-RC1 * Purpose: Add options in profile page fieldset - before first field. -ucp_profile_register_details_after +ucp_profile_signature_posting_editor_options_prepend === * Locations: - + styles/prosilver/template/ucp_profile_reg_details.html -* Since: 3.1.4-RC1 -* Purpose: Add options in profile page fieldset - after confirm password field. + + styles/prosilver/template/ucp_profile_signature.html +* Since: 3.2.6-RC1 +* Purpose: Add options signature posting editor - before first option. ucp_register_buttons_before === @@ -2511,33 +2574,33 @@ ucp_register_buttons_before * Since: 3.1.11-RC1 * Purpose: Add content before buttons in registration form. -ucp_register_credentials_before +ucp_register_credentials_after === * Locations: + styles/prosilver/template/ucp_register.html * Since: 3.1.0-b5 -* Purpose: Add options in registration page fieldset - before first field. +* Purpose: Add options in registration page fieldset - after password field. -ucp_register_profile_fields_after +ucp_register_credentials_before === * Locations: + styles/prosilver/template/ucp_register.html * Since: 3.1.0-b5 -* Purpose: Add options in registration page fieldset - after last field. +* Purpose: Add options in registration page fieldset - before first field. -ucp_register_credentials_after +ucp_register_options_before === * Locations: + styles/prosilver/template/ucp_register.html * Since: 3.1.0-b5 -* Purpose: Add options in registration page fieldset - after password field. +* Purpose: Add options in registration page fieldset - before language selector. -ucp_register_options_before +ucp_register_profile_fields_after === * Locations: + styles/prosilver/template/ucp_register.html * Since: 3.1.0-b5 -* Purpose: Add options in registration page fieldset - before language selector. +* Purpose: Add options in registration page fieldset - after last field. ucp_register_profile_fields_before === @@ -2546,20 +2609,6 @@ ucp_register_profile_fields_before * Since: 3.1.0-b5 * Purpose: Add options in registration page fieldset - before profile fields. -ucp_friend_list_before -=== -* Locations: - + styles/prosilver/template/ucp_zebra_friends.html -* Since: 3.1.0-a4 -* Purpose: Add optional elements before list of friends in UCP - -ucp_friend_list_after -=== -* Locations: - + styles/prosilver/template/ucp_zebra_friends.html -* Since: 3.1.0-a4 -* Purpose: Add optional elements after list of friends in UCP - viewforum_body_last_post_author_username_append === * Locations: @@ -2623,13 +2672,6 @@ viewforum_body_topicrow_row_before * Since: 3.1.10-RC1 * Purpose: Add content before list of topics. -viewforum_buttons_bottom_before -=== -* Locations: - + styles/prosilver/template/viewforum_body.html -* Since: 3.1.0-RC5 -* Purpose: Add buttons before New Topic button on the bottom of the topic's list - viewforum_buttons_bottom_after === * Locations: @@ -2637,12 +2679,12 @@ viewforum_buttons_bottom_after * Since: 3.1.0-RC5 * Purpose: Add buttons after New Topic button on the bottom of the topic's list -viewforum_buttons_top_before +viewforum_buttons_bottom_before === * Locations: + styles/prosilver/template/viewforum_body.html * Since: 3.1.0-RC5 -* Purpose: Add buttons before New Topic button on the top of the topic's list +* Purpose: Add buttons before New Topic button on the bottom of the topic's list viewforum_buttons_top_after === @@ -2651,47 +2693,12 @@ viewforum_buttons_top_after * Since: 3.1.0-RC5 * Purpose: Add buttons after New Topic button on the top of the topic's list -viewtopic_buttons_bottom_before -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.0-RC5 -* Purpose: Add buttons before Post Reply button on the bottom of the posts's list - -viewtopic_buttons_bottom_after -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.0-RC5 -* Purpose: Add buttons after Post Reply button on the bottom of the posts's list - -viewtopic_buttons_top_before -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.0-RC5 -* Purpose: Add buttons before Post Reply button on the top of the posts's list - -viewtopic_buttons_top_after +viewforum_buttons_top_before === * Locations: - + styles/prosilver/template/viewtopic_body.html + + styles/prosilver/template/viewforum_body.html * Since: 3.1.0-RC5 -* Purpose: Add buttons after Post Reply button on the top of the posts's list - -viewtopic_dropdown_bottom_custom -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.6-RC1 -* Purpose: Create a custom dropdown menu - -viewtopic_dropdown_top_custom -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.6-RC1 -* Purpose: Create a custom dropdown menu +* Purpose: Add buttons before New Topic button on the top of the topic's list viewforum_forum_name_append === @@ -2735,20 +2742,6 @@ viewonline_body_username_prepend * Since: 3.2.4-RC1 * Purpose: Prepend information to username of member -viewtopic_print_head_append -=== -* Locations: - + styles/prosilver/template/viewtopic_print.html -* Since: 3.1.0-a1 -* Purpose: Add asset calls directly before the `</head>` tag of the Print Topic screen - -viewtopic_body_pagination_top_after -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.4-RC1 -* Purpose: Add content after the pagination at top - viewtopic_body_avatar_after === * Locations: @@ -2787,6 +2780,13 @@ viewtopic_body_footer_before * Purpose: Add content to the bottom of the View topic screen below the posts and quick reply, directly before the jumpbox in Prosilver. +viewtopic_body_pagination_top_after +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.4-RC1 +* Purpose: Add content after the pagination at top + viewtopic_body_poll_after === * Locations: @@ -2889,28 +2889,28 @@ viewtopic_body_postrow_back2top_after * Locations: + styles/prosilver/template/viewtopic_body.html * Since: 3.1.8-RC1 -* Purpose: Add content to the post's bottom after the back to top link +* Purpose: Add content to the post's bottom after the back to top link viewtopic_body_postrow_back2top_append === * Locations: + styles/prosilver/template/viewtopic_body.html * Since: 3.1.8-RC1 -* Purpose: Add content to the post's bottom directly after the back to top link +* Purpose: Add content to the post's bottom directly after the back to top link viewtopic_body_postrow_back2top_before === * Locations: + styles/prosilver/template/viewtopic_body.html * Since: 3.1.8-RC1 -* Purpose: Add content to the post's bottom before the back to top link +* Purpose: Add content to the post's bottom before the back to top link viewtopic_body_postrow_back2top_prepend === * Locations: + styles/prosilver/template/viewtopic_body.html * Since: 3.1.8-RC1 -* Purpose: Add content to the post's bottom directly before the back to top link +* Purpose: Add content to the post's bottom directly before the back to top link viewtopic_body_postrow_content_after === @@ -3007,19 +3007,61 @@ viewtopic_body_topic_actions_before * Since: 3.1.0-a4 * Purpose: Add data before the topic actions buttons (after the posts sorting options) -viewtopic_topic_title_after +viewtopic_buttons_bottom_after === * Locations: + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.7-RC1 -* Purpose: Add content directly after the topic title link on the View topic screen (outside of the h2 HTML tag) +* Since: 3.1.0-RC5 +* Purpose: Add buttons after Post Reply button on the bottom of the posts's list -viewtopic_topic_title_before +viewtopic_buttons_bottom_before === * Locations: + styles/prosilver/template/viewtopic_body.html -* Since: 3.2.2-RC1 -* Purpose: Add content directly before the topic title link on the View topic screen (outside of the h2 HTML tag) +* Since: 3.1.0-RC5 +* Purpose: Add buttons before Post Reply button on the bottom of the posts's list + +viewtopic_buttons_top_after +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.0-RC5 +* Purpose: Add buttons after Post Reply button on the top of the posts's list + +viewtopic_buttons_top_before +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.0-RC5 +* Purpose: Add buttons before Post Reply button on the top of the posts's list + +viewtopic_dropdown_bottom_custom +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.6-RC1 +* Purpose: Create a custom dropdown menu + +viewtopic_dropdown_top_custom +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.6-RC1 +* Purpose: Create a custom dropdown menu + +viewtopic_print_head_append +=== +* Locations: + + styles/prosilver/template/viewtopic_print.html +* Since: 3.1.0-a1 +* Purpose: Add asset calls directly before the `</head>` tag of the Print Topic screen + +viewtopic_topic_title_after +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.7-RC1 +* Purpose: Add content directly after the topic title link on the View topic screen (outside of the h2 HTML tag) viewtopic_topic_title_append === @@ -3028,6 +3070,13 @@ viewtopic_topic_title_append * Since: 3.1.0-b3 * Purpose: Add content directly after the topic title link on the View topic screen +viewtopic_topic_title_before +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.2.2-RC1 +* Purpose: Add content directly before the topic title link on the View topic screen (outside of the h2 HTML tag) + viewtopic_topic_title_prepend === * Locations: diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 19c4f6e4f1..05f2b98524 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -23,6 +23,7 @@ class acp_database { var $db_tools; var $u_action; + public $page_title; function main($id, $mode) { @@ -69,18 +70,13 @@ class acp_database trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } - $store = $download = $structure = $schema_data = false; + $store = $structure = $schema_data = false; - if ($where == 'store_and_download' || $where == 'store') + if ($where == 'store') { $store = true; } - if ($where == 'store_and_download' || $where == 'download') - { - $download = true; - } - if ($type == 'full' || $type == 'structure') { $structure = true; @@ -98,8 +94,9 @@ class acp_database $filename = 'backup_' . $time . '_' . unique_id(); + /** @var phpbb\db\extractor\extractor_interface $extractor Database extractor */ $extractor = $phpbb_container->get('dbal.extractor'); - $extractor->init_extractor($format, $filename, $time, $download, $store); + $extractor->init_extractor($format, $filename, $time, false, $store); $extractor->write_start($table_prefix); @@ -145,11 +142,6 @@ class acp_database $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_BACKUP'); - if ($download == true) - { - exit; - } - trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action)); break; @@ -201,16 +193,10 @@ class acp_database case 'submit': $delete = $request->variable('delete', ''); $file = $request->variable('file', ''); - $download = $request->variable('download', ''); - if (!preg_match('#^backup_\d{10,}_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches)) - { - trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); - } + $backup_info = $this->get_backup_file($phpbb_root_path . 'store/', $file); - $file_name = $phpbb_root_path . 'store/' . $matches[0]; - - if (!file_exists($file_name) || !is_readable($file_name)) + if (empty($backup_info) || !is_readable($backup_info['file_name'])) { trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -219,7 +205,7 @@ class acp_database { if (confirm_box(true)) { - unlink($file_name); + unlink($backup_info['file_name']); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_DELETE'); trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action)); } @@ -228,50 +214,12 @@ class acp_database confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file))); } } - else if ($download || confirm_box(true)) + else if (confirm_box(true)) { - if ($download) - { - $name = $matches[0]; - - switch ($matches[1]) - { - case 'sql': - $mimetype = 'text/x-sql'; - break; - case 'sql.bz2': - $mimetype = 'application/x-bzip2'; - break; - case 'sql.gz': - $mimetype = 'application/x-gzip'; - break; - } - - header('Cache-Control: private, no-cache'); - header("Content-Type: $mimetype; name=\"$name\""); - header("Content-disposition: attachment; filename=$name"); - - @set_time_limit(0); - - $fp = @fopen($file_name, 'rb'); - - if ($fp !== false) - { - while (!feof($fp)) - { - echo fread($fp, 8192); - } - fclose($fp); - } - - flush(); - exit; - } - - switch ($matches[1]) + switch ($backup_info['extensions']) { case 'sql': - $fp = fopen($file_name, 'rb'); + $fp = fopen($backup_info['file_name'], 'rb'); $read = 'fread'; $seek = 'fseek'; $eof = 'feof'; @@ -280,7 +228,7 @@ class acp_database break; case 'sql.bz2': - $fp = bzopen($file_name, 'r'); + $fp = bzopen($backup_info['file_name'], 'r'); $read = 'bzread'; $seek = ''; $eof = 'feof'; @@ -289,13 +237,17 @@ class acp_database break; case 'sql.gz': - $fp = gzopen($file_name, 'rb'); + $fp = gzopen($backup_info['file_name'], 'rb'); $read = 'gzread'; $seek = 'gzseek'; $eof = 'gzeof'; $close = 'gzclose'; $fgetd = 'fgetd'; break; + + default: + trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + return; } switch ($db->get_sql_layer()) @@ -375,43 +327,13 @@ class acp_database trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action)); break; } - else if (!$download) + else { confirm_box(false, $user->lang['RESTORE_SELECTED_BACKUP'], build_hidden_fields(array('file' => $file))); } default: - $methods = array('sql'); - $available_methods = array('sql.gz' => 'zlib', 'sql.bz2' => 'bz2'); - - foreach ($available_methods as $type => $module) - { - if (!@extension_loaded($module)) - { - continue; - } - $methods[] = $type; - } - - $dir = $phpbb_root_path . 'store/'; - $dh = @opendir($dir); - - $backup_files = array(); - - if ($dh) - { - while (($file = readdir($dh)) !== false) - { - if (preg_match('#^backup_(\d{10,})_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches)) - { - if (in_array($matches[2], $methods)) - { - $backup_files[(int) $matches[1]] = $file; - } - } - } - closedir($dh); - } + $backup_files = $this->get_file_list($phpbb_root_path . 'store/'); if (!empty($backup_files)) { @@ -420,8 +342,8 @@ class acp_database foreach ($backup_files as $name => $file) { $template->assign_block_vars('files', array( - 'FILE' => $file, - 'NAME' => $user->format_date($name, 'd-m-Y H:i:s', true), + 'FILE' => sha1($file), + 'NAME' => $user->format_date($name, 'd-m-Y H:i', true), 'SUPPORTED' => true, )); } @@ -435,6 +357,92 @@ class acp_database break; } } + + /** + * Get backup file from file hash + * + * @param string $directory Relative path to directory + * @param string $file_hash Hash of selected file + * + * @return array Backup file data or empty array if unable to find file + */ + protected function get_backup_file($directory, $file_hash) + { + $backup_data = []; + + $file_list = $this->get_file_list($directory); + $supported_extensions = $this->get_supported_extensions(); + + foreach ($file_list as $file) + { + preg_match('#^backup_(\d{10,})_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches); + if (sha1($file) === $file_hash && in_array($matches[2], $supported_extensions)) + { + $backup_data = [ + 'file_name' => $directory . $file, + 'extension' => $matches[2], + ]; + break; + } + } + + return $backup_data; + } + + /** + * Get backup file list for directory + * + * @param string $directory Relative path to backup directory + * + * @return array List of backup files in specified directory + */ + protected function get_file_list($directory) + { + $supported_extensions = $this->get_supported_extensions(); + + $dh = @opendir($directory); + + $backup_files = []; + + if ($dh) + { + while (($file = readdir($dh)) !== false) + { + if (preg_match('#^backup_(\d{10,})_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches)) + { + if (in_array($matches[2], $supported_extensions)) + { + $backup_files[(int) $matches[1]] = $file; + } + } + } + closedir($dh); + } + + return $backup_files; + } + + /** + * Get supported extensions for backup + * + * @return array List of supported extensions + */ + protected function get_supported_extensions() + { + $extensions = ['sql']; + $available_methods = ['sql.gz' => 'zlib', 'sql.bz2' => 'bz2']; + + foreach ($available_methods as $type => $module) + { + if (!@extension_loaded($module)) + { + continue; + } + $extensions[] = $type; + } + + return $extensions; + } } // get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P) diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php index 0f403896a7..ad394e3782 100644 --- a/phpBB/includes/compatibility_globals.php +++ b/phpBB/includes/compatibility_globals.php @@ -29,7 +29,7 @@ function register_compatibility_globals() { global $phpbb_container; - global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log; + global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $language, $phpbb_log; global $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template; // set up caching @@ -48,6 +48,9 @@ function register_compatibility_globals() /* @var $user \phpbb\user */ $user = $phpbb_container->get('user'); + /* @var \phpbb\language\language $language */ + $language = $phpbb_container->get('language'); + /* @var $auth \phpbb\auth\auth */ $auth = $phpbb_container->get('auth'); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 99f65a0e92..24f251601f 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -680,8 +680,6 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ } } } - - return; } else if ($mode == 'topics') { @@ -808,8 +806,6 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ unset($tracking); } - - return; } else if ($mode == 'topic') { @@ -923,8 +919,6 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $user->set_cookie('track', tracking_serialize($tracking), $post_time + 31536000); $request->overwrite($config['cookie_name'] . '_track', tracking_serialize($tracking), \phpbb\request\request_interface::COOKIE); } - - return; } else if ($mode == 'post') { @@ -949,9 +943,28 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $db->sql_return_on_error(false); } - - return; } + + /** + * This event is used for performing actions directly after forums, + * topics or posts have been marked as read. + * + * @event core.markread_after + * @var string mode Variable containing marking mode value + * @var mixed forum_id Variable containing forum id, or false + * @var mixed topic_id Variable containing topic id, or false + * @var int post_time Variable containing post time + * @var int user_id Variable containing the user id + * @since 3.2.6-RC1 + */ + $vars = array( + 'mode', + 'forum_id', + 'topic_id', + 'post_time', + 'user_id', + ); + extract($phpbb_dispatcher->trigger_event('core.markread_after', compact($vars))); } /** @@ -2130,25 +2143,29 @@ function check_form_key($form_name, $timespan = false) /** * Build Confirm box * @param boolean $check True for checking if confirmed (without any additional parameters) and false for displaying the confirm box -* @param string $title Title/Message used for confirm box. +* @param string|array $title Title/Message used for confirm box. * message text is _CONFIRM appended to title. * If title cannot be found in user->lang a default one is displayed * If title_CONFIRM cannot be found in user->lang the text given is used. +* If title is an array, the first array value is used as explained per above, +* all other array values are sent as parameters to the language function. * @param string $hidden Hidden variables * @param string $html_body Template used for confirm box * @param string $u_action Custom form action +* +* @return bool True if confirmation was successful, false if not */ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '') { global $user, $template, $db, $request; - global $config, $phpbb_path_helper; + global $config, $language, $phpbb_path_helper; if (isset($_POST['cancel'])) { return false; } - $confirm = ($user->lang['YES'] === $request->variable('confirm', '', true, \phpbb\request\request_interface::POST)); + $confirm = ($language->lang('YES') === $request->variable('confirm', '', true, \phpbb\request\request_interface::POST)); if ($check && $confirm) { @@ -2182,13 +2199,27 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo // generate activation key $confirm_key = gen_rand_string(10); + // generate language strings + if (is_array($title)) + { + $key = array_shift($title); + $count = array_shift($title); + $confirm_title = $language->is_set($key) ? $language->lang($key, $count, $title) : $language->lang('CONFIRM'); + $confirm_text = $language->is_set($key . '_CONFIRM') ? $language->lang($key . '_CONFIRM', $count, $title) : $key; + } + else + { + $confirm_title = $language->is_set($title) ? $language->lang($title) : $language->lang('CONFIRM'); + $confirm_text = $language->is_set($title . '_CONFIRM') ? $language->lang($title . '_CONFIRM') : $title; + } + if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) { - adm_page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]); + adm_page_header($confirm_title); } else { - page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]); + page_header($confirm_title); } $template->set_filenames(array( @@ -2208,10 +2239,10 @@ 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, 1), - 'MESSAGE_TEXT' => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'], + 'MESSAGE_TITLE' => $confirm_title, + 'MESSAGE_TEXT' => $confirm_text, - 'YES_VALUE' => $user->lang['YES'], + 'YES_VALUE' => $language->lang('YES'), 'S_CONFIRM_ACTION' => $u_action, 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields, 'S_AJAX_REQUEST' => $request->is_ajax(), @@ -2227,10 +2258,10 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo $json_response = new \phpbb\json_response; $json_response->send(array( 'MESSAGE_BODY' => $template->assign_display('body'), - 'MESSAGE_TITLE' => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title], - 'MESSAGE_TEXT' => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'], + 'MESSAGE_TITLE' => $confirm_title, + 'MESSAGE_TEXT' => $confirm_text, - 'YES_VALUE' => $user->lang['YES'], + 'YES_VALUE' => $language->lang('YES'), 'S_CONFIRM_ACTION' => str_replace('&', '&', $u_action), //inefficient, rewrite whole function 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields )); @@ -2244,6 +2275,8 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo { page_footer(); } + + exit; // unreachable, page_footer() above will call exit() } /** diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 2cb50a5a34..fb9241d4aa 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -1718,16 +1718,20 @@ function phpbb_validate_timezone($timezone) return (in_array($timezone, phpbb_get_timezone_identifiers($timezone))) ? false : 'TIMEZONE_INVALID'; } -/** -* Check to see if the username has been taken, or if it is disallowed. -* Also checks if it includes the " character, which we don't allow in usernames. -* Used for registering, changing names, and posting anonymously with a username -* -* @param string $username The username to check -* @param string $allowed_username An allowed username, default being $user->data['username'] -* -* @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) -*/ +/*** + * Validate Username + * + * Check to see if the username has been taken, or if it is disallowed. + * Also checks if it includes the " character or the 4-bytes Unicode ones + * (aka emojis) which we don't allow in usernames. + * Used for registering, changing names, and posting anonymously with a username + * + * @param string $username The username to check + * @param string $allowed_username An allowed username, default being $user->data['username'] + * + * @return mixed Either false if validation succeeded or a string which will be + * used as the error message (with the variable name appended) + */ function validate_username($username, $allowed_username = false) { global $config, $db, $user, $cache; @@ -1740,6 +1744,14 @@ function validate_username($username, $allowed_username = false) return false; } + // The very first check is for + // out-of-bounds characters that are currently + // not supported by utf8_bin in MySQL + if (preg_match('/[\x{10000}-\x{10FFFF}]/u', $username)) + { + return 'INVALID_EMOJIS'; + } + // ... fast checks first. if (strpos($username, '"') !== false || strpos($username, '"') !== false || empty($clean_username)) { diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index d20878a279..c3e3ade160 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -426,6 +426,23 @@ function change_topic_type($action, $topic_ids) if (confirm_box(true)) { + + /** + * Perform additional actions before changing topic(s) type + * + * @event core.mcp_change_topic_type_before + * @var int new_topic_type The candidated topic type. + * @var int forum_id The forum ID for the topic ID(s). + * @var array topic_ids Array containing the topic ID(s) that will be changed + * @since 3.2.6-RC1 + */ + $vars = array( + 'new_topic_type', + 'forum_id', + 'topic_ids', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_change_topic_type_before', compact($vars))); + $db->sql_transaction('begin'); $sql = 'UPDATE ' . TOPICS_TABLE . " @@ -459,6 +476,22 @@ function change_topic_type($action, $topic_ids) } } + /** + * Perform additional actions after changing topic types + * + * @event core.mcp_change_topic_type_after + * @var int new_topic_type The newly changed topic type. + * @var int forum_id The forum ID where the newly changed topic type belongs to. + * @var array topic_ids Array containing the topic IDs that have been changed + * @since 3.2.6-RC1 + */ + $vars = array( + 'new_topic_type', + 'forum_id', + 'topic_ids', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_change_topic_type_after', compact($vars))); + meta_refresh(2, $redirect); $message = $user->lang[$success_msg]; @@ -941,10 +974,11 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' 'DELETE_TOPIC_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_TOPIC_PERMANENTLY', count($topic_ids)), )); - $l_confirm = (count($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS'; + $count = count($topic_ids); + $l_confirm = $count === 1 ? 'DELETE_TOPIC' : 'DELETE_TOPICS'; if ($only_softdeleted) { - $l_confirm .= '_PERMANENTLY'; + $l_confirm = array($l_confirm . '_PERMANENTLY', $count); $s_hidden_fields['delete_permanent'] = '1'; } else if ($only_shadow || !$auth->acl_get('m_softdelete', $forum_id)) @@ -1195,10 +1229,11 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', 'DELETE_POST_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_POST_PERMANENTLY', count($post_ids)), )); - $l_confirm = (count($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS'; + $count = count($post_ids); + $l_confirm = $count === 1 ? 'DELETE_POST' : 'DELETE_POSTS'; if ($only_softdeleted) { - $l_confirm .= '_PERMANENTLY'; + $l_confirm = array($l_confirm . '_PERMANENTLY', $count); $s_hidden_fields['delete_permanent'] = '1'; } else if (!$auth->acl_get('m_softdelete', $forum_id)) diff --git a/phpBB/language/en/acp/database.php b/phpBB/language/en/acp/database.php index ab85701eaa..302aaee570 100644 --- a/phpBB/language/en/acp/database.php +++ b/phpBB/language/en/acp/database.php @@ -38,14 +38,15 @@ if (empty($lang) || !is_array($lang)) // Database Backup/Restore $lang = array_merge($lang, array( - 'ACP_BACKUP_EXPLAIN' => 'Here you can backup all your phpBB related data. You may store the resulting archive in your <samp>store/</samp> folder or download it directly. Depending on your server configuration you may be able to compress the file in a number of formats.', + 'ACP_BACKUP_EXPLAIN' => 'Here you can backup all your phpBB related data. The resulting archive will be stored in your <samp>store/</samp> folder. Depending on your server configuration you may be able to compress the file in a number of formats.', 'ACP_RESTORE_EXPLAIN' => 'This will perform a full restore of all phpBB tables from a saved file. If your server supports it you may use a gzip or bzip2 compressed text file and it will automatically be decompressed. <strong>WARNING</strong> This will overwrite any existing data. The restore may take a long time to process please do not move from this page till it is complete. Backups are stored in the <samp>store/</samp> folder and are assumed to be generated by phpBB’s backup functionality. Restoring backups that were not created by the built in system may or may not work.', - 'BACKUP_DELETE' => 'The backup file has been deleted successfully.', - 'BACKUP_INVALID' => 'The selected file to backup is invalid.', - 'BACKUP_OPTIONS' => 'Backup options', - 'BACKUP_SUCCESS' => 'The backup file has been created successfully.', - 'BACKUP_TYPE' => 'Backup type', + 'BACKUP_DELETE' => 'The backup file has been deleted successfully.', + 'BACKUP_INVALID' => 'The selected file to backup is invalid.', + 'BACKUP_NOT_SUPPORTED' => 'The selected backup is not supported', + 'BACKUP_OPTIONS' => 'Backup options', + 'BACKUP_SUCCESS' => 'The backup file has been created successfully.', + 'BACKUP_TYPE' => 'Backup type', 'DATABASE' => 'Database utilities', 'DATA_ONLY' => 'Data only', diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index a037c5bfe8..835030762c 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -780,6 +780,10 @@ $lang = array_merge($lang, array( 'TOPIC_REVIEW' => 'Topic review', 'TOPIC_TITLE' => 'Topic title', 'TOPIC_UNAPPROVED' => 'This topic has not been approved.', + 'TOPIC_UNAPPROVED_FORUM' => array( + 1 => 'Topic awaiting approval', + 2 => 'Topics awaiting approval', + ), 'TOPIC_DELETED' => 'This topic has been deleted.', 'TOTAL_ATTACHMENTS' => 'Attachment(s)', 'TOTAL_LOGS' => array( diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php index d5c6778e3b..2622fb57b7 100644 --- a/phpBB/language/en/ucp.php +++ b/phpBB/language/en/ucp.php @@ -272,6 +272,7 @@ $lang = array_merge($lang, array( 'IMPORTANT_NEWS' => 'Important announcements', 'INVALID_USER_BIRTHDAY' => 'The entered birthday is not a valid date.', 'INVALID_CHARS_USERNAME' => 'The username contains forbidden characters.', + 'INVALID_EMOJIS_USERNAME' => 'The username contains forbidden characters (Emoji).', 'INVALID_CHARS_NEW_PASSWORD'=> 'The password does not contain the required characters.', 'ITEMS_REQUIRED' => 'The items marked with * are required profile fields and need to be filled out.', diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index 3a620de63a..b26d7c8f94 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -1385,11 +1385,6 @@ switch ($mode) } $sort_params[] = "mode=$mode"; - $pagination_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $params)); - $sort_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $sort_params)); - - unset($search_params, $sort_params); - $u_first_char_params = implode('&', $u_first_char_params); $u_first_char_params .= ($u_first_char_params) ? '&' : ''; @@ -1401,16 +1396,47 @@ switch ($mode) } $first_characters['other'] = $user->lang['OTHER']; + $first_char_block_vars = []; + foreach ($first_characters as $char => $desc) { - $template->assign_block_vars('first_char', array( + $first_char_block_vars[] = [ 'DESC' => $desc, 'VALUE' => $char, 'S_SELECTED' => ($first_char == $char) ? true : false, 'U_SORT' => append_sid("{$phpbb_root_path}memberlist.$phpEx", $u_first_char_params . 'first_char=' . $char) . '#memberlist', - )); + ]; } + /** + * Modify memberlist sort and pagination parameters + * + * @event core.memberlist_modify_sort_pagination_params + * @var array sort_params Array with URL parameters for sorting + * @var array params Array with URL parameters for pagination + * @var array first_characters Array that maps each letter in a-z, 'other' and the empty string to their display representation + * @var string u_first_char_params Concatenated URL parameters for first character search links + * @var array first_char_block_vars Template block variables for each first character + * @var int total_users Total number of users found in this search + * @since 3.2.6-RC1 + */ + $vars = [ + 'sort_params', + 'params', + 'first_characters', + 'u_first_char_params', + 'first_char_block_vars', + 'total_users', + ]; + extract($phpbb_dispatcher->trigger_event('core.memberlist_modify_sort_pagination_params', compact($vars))); + + $template->assign_block_vars_array('first_char', $first_char_block_vars); + + $pagination_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $params)); + $sort_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $sort_params)); + + unset($search_params, $sort_params); + // Some search user specific data if (($mode == '' || $mode == 'searchuser') && ($config['load_search'] || $auth->acl_get('a_'))) { diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php index f3dfd07ae8..93419d2915 100644 --- a/phpBB/phpbb/auth/provider/oauth/oauth.php +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -221,24 +221,33 @@ class oauth extends \phpbb\auth\provider\base 'provider' => $service_name_original, 'oauth_provider_id' => $unique_id ); + $sql = 'SELECT user_id FROM ' . $this->auth_provider_oauth_token_account_assoc . ' WHERE ' . $this->db->sql_build_array('SELECT', $data); $result = $this->db->sql_query($sql); $row = $this->db->sql_fetchrow($result); $this->db->sql_freeresult($result); + $redirect_data = array( + 'auth_provider' => 'oauth', + 'login_link_oauth_service' => $service_name_original, + ); + /** * Event is triggered before check if provider is already associated with an account * * @event core.oauth_login_after_check_if_provider_id_has_match - * @var array row User row - * @var array data Provider data - * @var \OAuth\Common\Service\ServiceInterface service OAuth service + * @var array row User row + * @var array data Provider data + * @var array redirect_data Data to be appended to the redirect url + * @var \OAuth\Common\Service\ServiceInterface service OAuth service * @since 3.2.3-RC1 + * @changed 3.2.6-RC1 Added redirect_data */ $vars = array( 'row', 'data', + 'redirect_data', 'service', ); extract($this->dispatcher->trigger_event('core.oauth_login_after_check_if_provider_id_has_match', compact($vars))); @@ -250,10 +259,7 @@ class oauth extends \phpbb\auth\provider\base 'status' => LOGIN_SUCCESS_LINK_PROFILE, 'error_msg' => 'LOGIN_OAUTH_ACCOUNT_NOT_LINKED', 'user_row' => array(), - 'redirect_data' => array( - 'auth_provider' => 'oauth', - 'login_link_oauth_service' => $service_name_original, - ), + 'redirect_data' => $redirect_data, ); } @@ -699,6 +705,7 @@ class oauth extends \phpbb\auth\provider\base 'oauth_service' => $actual_name, ), + 'SERVICE_ID' => $actual_name, 'SERVICE_NAME' => $this->user->lang['AUTH_PROVIDER_OAUTH_SERVICE_' . strtoupper($actual_name)], 'UNIQUE_ID' => (isset($oauth_user_ids[$actual_name])) ? $oauth_user_ids[$actual_name] : null, ); diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php index 085b20c234..c3942bd7ce 100644 --- a/phpBB/phpbb/event/md_exporter.php +++ b/phpBB/phpbb/event/md_exporter.php @@ -143,6 +143,8 @@ class md_exporter list($event_name, $details) = explode("\n===\n", $event, 2); $this->validate_event_name($event_name); + $sorted_events = [$this->current_event, $event_name]; + natsort($sorted_events); $this->current_event = $event_name; if (isset($this->events[$this->current_event])) @@ -150,6 +152,12 @@ class md_exporter throw new \LogicException("The event '{$this->current_event}' is defined multiple times"); } + // Use array_values() to get actual first element and check against natural order + if (array_values($sorted_events)[0] === $event_name) + { + throw new \LogicException("The event '{$sorted_events[1]}' should be defined before '{$sorted_events[0]}'"); + } + if (($this->filter == 'adm' && strpos($this->current_event, 'acp_') !== 0) || ($this->filter == 'styles' && strpos($this->current_event, 'acp_') === 0)) { diff --git a/phpBB/phpbb/message/admin_form.php b/phpBB/phpbb/message/admin_form.php index 96b8d3499e..ae1c1d8614 100644 --- a/phpBB/phpbb/message/admin_form.php +++ b/phpBB/phpbb/message/admin_form.php @@ -22,6 +22,9 @@ class admin_form extends form /** @var \phpbb\config\db_text */ protected $config_text; + /** @var \phpbb\event\dispatcher_interface */ + protected $dispatcher; + /** @var string */ protected $subject; /** @var string */ @@ -37,13 +40,15 @@ class admin_form extends form * @param \phpbb\config\db_text $config_text * @param \phpbb\db\driver\driver_interface $db * @param \phpbb\user $user + * @param \phpbb\event\dispatcher_interface $dispatcher * @param string $phpbb_root_path * @param string $phpEx */ - public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\config\db_text $config_text, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $phpEx) + public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\config\db_text $config_text, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\event\dispatcher_interface $dispatcher, $phpbb_root_path, $phpEx) { parent::__construct($auth, $config, $db, $user, $phpbb_root_path, $phpEx); $this->config_text = $config_text; + $this->dispatcher = $dispatcher; } /** @@ -91,6 +96,29 @@ class admin_form extends form $this->errors[] = $this->user->lang['EMPTY_MESSAGE_EMAIL']; } + $subject = $this->subject; + $body = $this->body; + $errors = $this->errors; + + /** + * You can use this event to modify subject and/or body and add new errors. + * + * @event core.message_admin_form_submit_before + * @var string subject Message subject + * @var string body Message body + * @var array errors Form errors + * @since 3.2.6-RC1 + */ + $vars = [ + 'subject', + 'body', + 'errors', + ]; + extract($this->dispatcher->trigger_event('core.message_admin_form_submit_before', compact($vars))); + $this->subject = $subject; + $this->body = $body; + $this->errors = $errors; + if ($this->user->data['is_registered']) { $this->message->set_sender_from_user($this->user); diff --git a/phpBB/posting.php b/phpBB/posting.php index 59be983987..75085a5635 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1649,6 +1649,20 @@ if ($generate_quote) 'user_id' => $post_data['poster_id'], ); + /** + * This event allows you to modify the quote attributes of the post being quoted + * + * @event core.posting_modify_quote_attributes + * @var array quote_attributes Array with quote attributes + * @var array post_data Array with post data + * @since 3.2.6-RC1 + */ + $vars = array( + 'quote_attributes', + 'post_data', + ); + extract($phpbb_dispatcher->trigger_event('core.posting_modify_quote_attributes', compact($vars))); + /** @var \phpbb\language\language $language */ $language = $phpbb_container->get('language'); phpbb_format_quote($language, $message_parser, $bbcode_utils, $bbcode_status, $quote_attributes); diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html index eed27b5131..8250a1fd07 100644 --- a/phpBB/styles/prosilver/template/forumlist_body.html +++ b/phpBB/styles/prosilver/template/forumlist_body.html @@ -103,7 +103,11 @@ <!-- ENDIF --> <br />{forumrow.LAST_POST_TIME} <!-- ELSE --> - {L_NO_POSTS}<br /> + {% if forumrow.U_UNAPPROVED_TOPICS %} + {{ lang('TOPIC_UNAPPROVED_FORUM', forumrow.TOPICS) }} + {% else %} + {{ lang('NO_POSTS') }} + {% endif %} <!-- ENDIF --> </span> </dd> diff --git a/phpBB/styles/prosilver/template/login_body_oauth.html b/phpBB/styles/prosilver/template/login_body_oauth.html index 156485d211..1364d01ccb 100644 --- a/phpBB/styles/prosilver/template/login_body_oauth.html +++ b/phpBB/styles/prosilver/template/login_body_oauth.html @@ -1,8 +1,6 @@ +<br> <div class="content"> - <!-- BEGIN oauth --> - <dl> - <dt> </dt> - <dd><a href="{oauth.REDIRECT_URL}" class="button2">{oauth.SERVICE_NAME}</a></dd> - </dl> - <!-- END oauth --> + {% for oauth in oauth %} + <a href="{{ oauth.REDIRECT_URL }}" class="button2">{{ oauth.SERVICE_NAME }}</a> + {% endfor %} </div> diff --git a/phpBB/styles/prosilver/template/posting_attach_body.html b/phpBB/styles/prosilver/template/posting_attach_body.html index 444713d6e0..b46e9c9175 100644 --- a/phpBB/styles/prosilver/template/posting_attach_body.html +++ b/phpBB/styles/prosilver/template/posting_attach_body.html @@ -21,6 +21,7 @@ <input type="button" class="button2" value="{L_PLUPLOAD_ADD_FILES}" id="add_files" /> </div> + {% EVENT posting_attach_body_file_list_before %} <div class="panel<!-- IF not .attach_row --> hidden<!-- ENDIF --> file-list-container" id="file-list-container"> <div class="inner"> <table class="table1 zebra-list fixed-width-table"> @@ -55,16 +56,18 @@ <span class="file-status"></span> </td> </tr> + {% EVENT posting_attach_body_attach_row_before %} <!-- BEGIN attach_row --> + {% EVENT posting_attach_body_attach_row_prepend %} <tr class="attach-row" data-attach-id="{attach_row.ATTACH_ID}"> <td class="attach-name"> <span class="file-name ellipsis-text"><a href="{attach_row.U_VIEW_ATTACHMENT}">{attach_row.FILENAME}</a></span> - <!-- EVENT posting_attach_body_attach_row_controls_prepend --> + {% EVENT posting_attach_body_attach_row_controls_prepend %} <span class="attach-controls"> <!-- IF S_INLINE_ATTACHMENT_OPTIONS --><input type="button" value="{L_PLACE_INLINE}" class="button2 file-inline-bbcode" /> <!-- ENDIF --> <input type="submit" name="delete_file[{attach_row.ASSOC_INDEX}]" value="{L_DELETE_FILE}" class="button2 file-delete" /> </span> - <!-- EVENT posting_attach_body_attach_row_controls_append --> + {% EVENT posting_attach_body_attach_row_controls_append %} <span class="clear"></span> </td> <td class="attach-comment"> @@ -78,10 +81,13 @@ <span class="file-status file-uploaded"></span> </td> </tr> + {% EVENT posting_attach_body_attach_row_append %} <!-- END attach_row --> + {% EVENT posting_attach_body_attach_row_after %} </tbody> </table> </div> </div> + {% EVENT posting_attach_body_file_list_after %} </div> </div> diff --git a/phpBB/styles/prosilver/template/ucp_auth_link_oauth.html b/phpBB/styles/prosilver/template/ucp_auth_link_oauth.html index 18316613b0..60061a3139 100644 --- a/phpBB/styles/prosilver/template/ucp_auth_link_oauth.html +++ b/phpBB/styles/prosilver/template/ucp_auth_link_oauth.html @@ -1,5 +1,5 @@ <!-- BEGIN oauth --> - <form id="ucp" method="post" action="{S_UCP_ACTION}"> + <form id="ucp_oauth_{oauth.SERVICE_ID}" method="post" action="{S_UCP_ACTION}"> <h3>{oauth.SERVICE_NAME}</h3> <fieldset class="fields2"> diff --git a/phpBB/styles/prosilver/template/ucp_profile_signature.html b/phpBB/styles/prosilver/template/ucp_profile_signature.html index 614f6f440d..ed28b7ab02 100644 --- a/phpBB/styles/prosilver/template/ucp_profile_signature.html +++ b/phpBB/styles/prosilver/template/ucp_profile_signature.html @@ -24,6 +24,7 @@ <!-- INCLUDE posting_editor.html --> <h3>{L_OPTIONS}</h3> <fieldset> + {% EVENT ucp_profile_signature_posting_editor_options_prepend %} <!-- IF S_BBCODE_ALLOWED --> <div><label for="disable_bbcode"><input type="checkbox" name="disable_bbcode" id="disable_bbcode"{S_BBCODE_CHECKED} /> {L_DISABLE_BBCODE}</label></div> <!-- ENDIF --> diff --git a/tests/functions/validate_username_test.php b/tests/functions/validate_username_test.php index d310f58036..cee5d38400 100644 --- a/tests/functions/validate_username_test.php +++ b/tests/functions/validate_username_test.php @@ -47,6 +47,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case 'foobar_letter_num' => array(), 'foobar_letter_num_sp' => array(), 'foobar_quot' => array('INVALID_CHARS'), + 'foobar_emoji' => array('INVALID_EMOJIS'), 'barfoo_disallow' => array('USERNAME_DISALLOWED'), 'admin_taken' => array('USERNAME_TAKEN'), 'group_taken' => array('USERNAME_TAKEN'), @@ -60,6 +61,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case 'foobar_letter_num' => array(), 'foobar_letter_num_sp' => array('INVALID_CHARS'), 'foobar_quot' => array('INVALID_CHARS'), + 'foobar_emoji' => array('INVALID_EMOJIS'), 'barfoo_disallow' => array('USERNAME_DISALLOWED'), 'admin_taken' => array('USERNAME_TAKEN'), 'group_taken' => array('INVALID_CHARS'), @@ -73,6 +75,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case 'foobar_letter_num' => array(), 'foobar_letter_num_sp' => array('INVALID_CHARS'), 'foobar_quot' => array('INVALID_CHARS'), + 'foobar_emoji' => array('INVALID_EMOJIS'), 'barfoo_disallow' => array('USERNAME_DISALLOWED'), 'admin_taken' => array('USERNAME_TAKEN'), 'group_taken' => array('USERNAME_TAKEN'), @@ -86,6 +89,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case 'foobar_letter_num' => array(), 'foobar_letter_num_sp' => array('INVALID_CHARS'), 'foobar_quot' => array('INVALID_CHARS'), + 'foobar_emoji' => array('INVALID_EMOJIS'), 'barfoo_disallow' => array('USERNAME_DISALLOWED'), 'admin_taken' => array('USERNAME_TAKEN'), 'group_taken' => array('INVALID_CHARS'), @@ -99,6 +103,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case 'foobar_letter_num' => array(), 'foobar_letter_num_sp' => array(), 'foobar_quot' => array('INVALID_CHARS'), + 'foobar_emoji' => array('INVALID_EMOJIS'), 'barfoo_disallow' => array('USERNAME_DISALLOWED'), 'admin_taken' => array('USERNAME_TAKEN'), 'group_taken' => array('USERNAME_TAKEN'), @@ -112,6 +117,7 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case 'foobar_letter_num' => array(), 'foobar_letter_num_sp' => array('INVALID_CHARS'), 'foobar_quot' => array('INVALID_CHARS'), + 'foobar_emoji' => array('INVALID_EMOJIS'), 'barfoo_disallow' => array('USERNAME_DISALLOWED'), 'admin_taken' => array('USERNAME_TAKEN'), 'group_taken' => array('USERNAME_TAKEN'), @@ -173,6 +179,11 @@ class phpbb_functions_validate_data_test extends phpbb_database_test_case '"foobar"', array('username'), ), + 'foobar_emoji' => array( + $expected['foobar_emoji'], + 'username😮', + array('username'), + ), 'barfoo_disallow' => array( $expected['barfoo_disallow'], 'barfoo', |