From 48fc908e6b0d1b18f679278297213738c0647bc1 Mon Sep 17 00:00:00 2001 From: hjpotter92 Date: Fri, 28 Feb 2014 03:58:32 +0530 Subject: [PATCH 0001/1676] [ticket/11875] Upgrade default data type from MEDIUMINT to INT Use 4-byte data type INT(10) for user_id, post_id and topic_id across all tables instead of previously used 3-byte MEDIUMINT(8) PHPBB3-11875 --- phpBB/includes/db/schema_data.php | 84 +++++++++++++++---------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/phpBB/includes/db/schema_data.php b/phpBB/includes/db/schema_data.php index 0447895433..72e8035821 100644 --- a/phpBB/includes/db/schema_data.php +++ b/phpBB/includes/db/schema_data.php @@ -53,7 +53,7 @@ $schema_data['phpbb_attachments'] = array( 'COLUMNS' => array( 'attach_id' => array('UINT', NULL, 'auto_increment'), 'post_msg_id' => array('UINT', 0), - 'topic_id' => array('UINT', 0), + 'topic_id' => array('UINT:10', 0), 'in_message' => array('BOOL', 0), 'poster_id' => array('UINT', 0), 'is_orphan' => array('BOOL', 1), @@ -135,7 +135,7 @@ $schema_data['phpbb_acl_roles_data'] = array( $schema_data['phpbb_acl_users'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'forum_id' => array('UINT', 0), 'auth_option_id' => array('UINT', 0), 'auth_role_id' => array('UINT', 0), @@ -190,8 +190,8 @@ $schema_data['phpbb_bbcodes'] = array( $schema_data['phpbb_bookmarks'] = array( 'COLUMNS' => array( - 'topic_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'topic_id' => array('UINT:10', 0), + 'user_id' => array('UINT:10', 0), ), 'PRIMARY_KEY' => array('topic_id', 'user_id'), ); @@ -201,7 +201,7 @@ $schema_data['phpbb_bots'] = array( 'bot_id' => array('UINT', NULL, 'auto_increment'), 'bot_active' => array('BOOL', 1), 'bot_name' => array('STEXT_UNI', ''), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'bot_agent' => array('VCHAR', ''), 'bot_ip' => array('VCHAR', ''), ), @@ -257,8 +257,8 @@ $schema_data['phpbb_disallow'] = array( $schema_data['phpbb_drafts'] = array( 'COLUMNS' => array( 'draft_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('UINT', 0), - 'topic_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), + 'topic_id' => array('UINT:10', 0), 'forum_id' => array('UINT', 0), 'save_time' => array('TIMESTAMP', 0), 'draft_subject' => array('STEXT_UNI', ''), @@ -363,7 +363,7 @@ $schema_data['phpbb_forums'] = array( $schema_data['phpbb_forums_access'] = array( 'COLUMNS' => array( 'forum_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'session_id' => array('CHAR:32', ''), ), 'PRIMARY_KEY' => array('forum_id', 'user_id', 'session_id'), @@ -371,7 +371,7 @@ $schema_data['phpbb_forums_access'] = array( $schema_data['phpbb_forums_track'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'forum_id' => array('UINT', 0), 'mark_time' => array('TIMESTAMP', 0), ), @@ -381,7 +381,7 @@ $schema_data['phpbb_forums_track'] = array( $schema_data['phpbb_forums_watch'] = array( 'COLUMNS' => array( 'forum_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'notify_status' => array('BOOL', 0), ), 'KEYS' => array( @@ -455,9 +455,9 @@ $schema_data['phpbb_log'] = array( 'COLUMNS' => array( 'log_id' => array('UINT', NULL, 'auto_increment'), 'log_type' => array('TINT:4', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'forum_id' => array('UINT', 0), - 'topic_id' => array('UINT', 0), + 'topic_id' => array('UINT:10', 0), 'reportee_id' => array('UINT', 0), 'log_ip' => array('VCHAR:40', ''), 'log_time' => array('TIMESTAMP', 0), @@ -481,7 +481,7 @@ $schema_data['phpbb_login_attempts'] = array( 'attempt_browser' => array('VCHAR:150', ''), 'attempt_forwarded_for' => array('VCHAR:255', ''), 'attempt_time' => array('TIMESTAMP', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'username' => array('VCHAR_UNI:255', 0), 'username_clean' => array('VCHAR_CI', 0), ), @@ -496,7 +496,7 @@ $schema_data['phpbb_login_attempts'] = array( $schema_data['phpbb_moderator_cache'] = array( 'COLUMNS' => array( 'forum_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'username' => array('VCHAR_UNI:255', ''), 'group_id' => array('UINT', 0), 'group_name' => array('VCHAR_UNI', ''), @@ -561,7 +561,7 @@ $schema_data['phpbb_notifications'] = array( 'notification_type_id' => array('USINT', 0), 'item_id' => array('UINT', 0), 'item_parent_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'notification_read' => array('BOOL', 0), 'notification_time' => array('TIMESTAMP', 1), 'notification_data' => array('TEXT_UNI', ''), @@ -575,7 +575,7 @@ $schema_data['phpbb_notifications'] = array( $schema_data['phpbb_oauth_accounts'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'provider' => array('VCHAR', ''), 'oauth_provider_id' => array('TEXT_UNI', ''), ), @@ -587,7 +587,7 @@ $schema_data['phpbb_oauth_accounts'] = array( $schema_data['phpbb_oauth_tokens'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT', 0), // phpbb_users.user_id + 'user_id' => array('UINT:10', 0), // phpbb_users.user_id 'session_id' => array('CHAR:32', ''), // phpbb_sessions.session_id used only when user_id not set 'provider' => array('VCHAR', ''), // Name of the OAuth provider 'oauth_token' => array('MTEXT', ''), // Serialized token @@ -601,7 +601,7 @@ $schema_data['phpbb_oauth_tokens'] = array( $schema_data['phpbb_poll_options'] = array( 'COLUMNS' => array( 'poll_option_id' => array('TINT:4', 0), - 'topic_id' => array('UINT', 0), + 'topic_id' => array('UINT:10', 0), 'poll_option_text' => array('TEXT_UNI', ''), 'poll_option_total' => array('UINT', 0), ), @@ -613,7 +613,7 @@ $schema_data['phpbb_poll_options'] = array( $schema_data['phpbb_poll_votes'] = array( 'COLUMNS' => array( - 'topic_id' => array('UINT', 0), + 'topic_id' => array('UINT:10', 0), 'poll_option_id' => array('TINT:4', 0), 'vote_user_id' => array('UINT', 0), 'vote_user_ip' => array('VCHAR:40', ''), @@ -627,8 +627,8 @@ $schema_data['phpbb_poll_votes'] = array( $schema_data['phpbb_posts'] = array( 'COLUMNS' => array( - 'post_id' => array('UINT', NULL, 'auto_increment'), - 'topic_id' => array('UINT', 0), + 'post_id' => array('UINT:10', NULL, 'auto_increment'), + 'topic_id' => array('UINT:10', 0), 'forum_id' => array('UINT', 0), 'poster_id' => array('UINT', 0), 'icon_id' => array('UINT', 0), @@ -706,7 +706,7 @@ $schema_data['phpbb_privmsgs'] = array( $schema_data['phpbb_privmsgs_folder'] = array( 'COLUMNS' => array( 'folder_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'folder_name' => array('VCHAR_UNI', ''), 'pm_count' => array('UINT', 0), ), @@ -719,7 +719,7 @@ $schema_data['phpbb_privmsgs_folder'] = array( $schema_data['phpbb_privmsgs_rules'] = array( 'COLUMNS' => array( 'rule_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'rule_check' => array('UINT', 0), 'rule_connection' => array('UINT', 0), 'rule_string' => array('VCHAR_UNI', ''), @@ -737,7 +737,7 @@ $schema_data['phpbb_privmsgs_rules'] = array( $schema_data['phpbb_privmsgs_to'] = array( 'COLUMNS' => array( 'msg_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'author_id' => array('UINT', 0), 'pm_deleted' => array('BOOL', 0), 'pm_new' => array('BOOL', 1), @@ -787,7 +787,7 @@ $schema_data['phpbb_profile_fields'] = array( $schema_data['phpbb_profile_fields_data'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'pf_phpbb_location' => array('VCHAR', ''), 'pf_phpbb_interests' => array('TEXT_UNI', ''), 'pf_phpbb_occupation' => array('TEXT_UNI', ''), @@ -832,9 +832,9 @@ $schema_data['phpbb_reports'] = array( 'COLUMNS' => array( 'report_id' => array('UINT', NULL, 'auto_increment'), 'reason_id' => array('USINT', 0), - 'post_id' => array('UINT', 0), + 'post_id' => array('UINT:10', 0), 'pm_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'user_notify' => array('BOOL', 0), 'report_closed' => array('BOOL', 0), 'report_time' => array('TIMESTAMP', 0), @@ -889,7 +889,7 @@ $schema_data['phpbb_search_wordlist'] = array( $schema_data['phpbb_search_wordmatch'] = array( 'COLUMNS' => array( - 'post_id' => array('UINT', 0), + 'post_id' => array('UINT:10', 0), 'word_id' => array('UINT', 0), 'title_match' => array('BOOL', 0), ), @@ -927,7 +927,7 @@ $schema_data['phpbb_sessions'] = array( $schema_data['phpbb_sessions_keys'] = array( 'COLUMNS' => array( 'key_id' => array('CHAR:32', ''), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'last_ip' => array('VCHAR:40', ''), 'last_login' => array('TIMESTAMP', 0), ), @@ -995,7 +995,7 @@ $schema_data['phpbb_teampage'] = array( $schema_data['phpbb_topics'] = array( 'COLUMNS' => array( - 'topic_id' => array('UINT', NULL, 'auto_increment'), + 'topic_id' => array('UINT:10', NULL, 'auto_increment'), 'forum_id' => array('UINT', 0), 'icon_id' => array('UINT', 0), 'topic_attachment' => array('BOOL', 0), @@ -1047,8 +1047,8 @@ $schema_data['phpbb_topics'] = array( $schema_data['phpbb_topics_track'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT', 0), - 'topic_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), + 'topic_id' => array('UINT:10', 0), 'forum_id' => array('UINT', 0), 'mark_time' => array('TIMESTAMP', 0), ), @@ -1061,8 +1061,8 @@ $schema_data['phpbb_topics_track'] = array( $schema_data['phpbb_topics_posted'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT', 0), - 'topic_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), + 'topic_id' => array('UINT:10', 0), 'topic_posted' => array('BOOL', 0), ), 'PRIMARY_KEY' => array('user_id', 'topic_id'), @@ -1070,8 +1070,8 @@ $schema_data['phpbb_topics_posted'] = array( $schema_data['phpbb_topics_watch'] = array( 'COLUMNS' => array( - 'topic_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'topic_id' => array('UINT:10', 0), + 'user_id' => array('UINT:10', 0), 'notify_status' => array('BOOL', 0), ), 'KEYS' => array( @@ -1085,7 +1085,7 @@ $schema_data['phpbb_user_notifications'] = array( 'COLUMNS' => array( 'item_type' => array('VCHAR:255', ''), 'item_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'method' => array('VCHAR:255', ''), 'notify' => array('BOOL', 1), ), @@ -1094,7 +1094,7 @@ $schema_data['phpbb_user_notifications'] = array( $schema_data['phpbb_user_group'] = array( 'COLUMNS' => array( 'group_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'group_leader' => array('BOOL', 0), 'user_pending' => array('BOOL', 1), ), @@ -1107,7 +1107,7 @@ $schema_data['phpbb_user_group'] = array( $schema_data['phpbb_users'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT', NULL, 'auto_increment'), + 'user_id' => array('UINT:10', NULL, 'auto_increment'), 'user_type' => array('TINT:2', 0), 'group_id' => array('UINT', 3), 'user_permissions' => array('MTEXT', ''), @@ -1192,8 +1192,8 @@ $schema_data['phpbb_users'] = array( $schema_data['phpbb_warnings'] = array( 'COLUMNS' => array( 'warning_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('UINT', 0), - 'post_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), + 'post_id' => array('UINT:10', 0), 'log_id' => array('UINT', 0), 'warning_time' => array('TIMESTAMP', 0), ), @@ -1211,7 +1211,7 @@ $schema_data['phpbb_words'] = array( $schema_data['phpbb_zebra'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT', 0), + 'user_id' => array('UINT:10', 0), 'zebra_id' => array('UINT', 0), 'friend' => array('BOOL', 0), 'foe' => array('BOOL', 0), From f6e45ed24420e719a969ffd301cf019ba0aa912a Mon Sep 17 00:00:00 2001 From: hjpotter92 Date: Sun, 2 Mar 2014 21:58:10 +0530 Subject: [PATCH 0002/1676] [ticket/11875] Create new map for UNSIGNED 4-byte integer ULINT => Unsigned Large INTeger --- phpBB/includes/db/schema_data.php | 85 ++++++++++++++++--------------- phpBB/phpbb/db/tools.php | 12 ++++- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/phpBB/includes/db/schema_data.php b/phpBB/includes/db/schema_data.php index 72e8035821..dc85ff327b 100644 --- a/phpBB/includes/db/schema_data.php +++ b/phpBB/includes/db/schema_data.php @@ -29,6 +29,7 @@ $schema_data = array(); * Column Types: * INT:x => SIGNED int(x) * BINT => BIGINT +* ULINT => UNSIGNED int(10) * UINT => mediumint(8) UNSIGNED * UINT:x => int(x) UNSIGNED * TINT:x => tinyint(x) @@ -53,7 +54,7 @@ $schema_data['phpbb_attachments'] = array( 'COLUMNS' => array( 'attach_id' => array('UINT', NULL, 'auto_increment'), 'post_msg_id' => array('UINT', 0), - 'topic_id' => array('UINT:10', 0), + 'topic_id' => array('ULINT', 0), 'in_message' => array('BOOL', 0), 'poster_id' => array('UINT', 0), 'is_orphan' => array('BOOL', 1), @@ -135,7 +136,7 @@ $schema_data['phpbb_acl_roles_data'] = array( $schema_data['phpbb_acl_users'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'forum_id' => array('UINT', 0), 'auth_option_id' => array('UINT', 0), 'auth_role_id' => array('UINT', 0), @@ -190,8 +191,8 @@ $schema_data['phpbb_bbcodes'] = array( $schema_data['phpbb_bookmarks'] = array( 'COLUMNS' => array( - 'topic_id' => array('UINT:10', 0), - 'user_id' => array('UINT:10', 0), + 'topic_id' => array('ULINT', 0), + 'user_id' => array('ULINT', 0), ), 'PRIMARY_KEY' => array('topic_id', 'user_id'), ); @@ -201,7 +202,7 @@ $schema_data['phpbb_bots'] = array( 'bot_id' => array('UINT', NULL, 'auto_increment'), 'bot_active' => array('BOOL', 1), 'bot_name' => array('STEXT_UNI', ''), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'bot_agent' => array('VCHAR', ''), 'bot_ip' => array('VCHAR', ''), ), @@ -257,8 +258,8 @@ $schema_data['phpbb_disallow'] = array( $schema_data['phpbb_drafts'] = array( 'COLUMNS' => array( 'draft_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('UINT:10', 0), - 'topic_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), + 'topic_id' => array('ULINT', 0), 'forum_id' => array('UINT', 0), 'save_time' => array('TIMESTAMP', 0), 'draft_subject' => array('STEXT_UNI', ''), @@ -363,7 +364,7 @@ $schema_data['phpbb_forums'] = array( $schema_data['phpbb_forums_access'] = array( 'COLUMNS' => array( 'forum_id' => array('UINT', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'session_id' => array('CHAR:32', ''), ), 'PRIMARY_KEY' => array('forum_id', 'user_id', 'session_id'), @@ -371,7 +372,7 @@ $schema_data['phpbb_forums_access'] = array( $schema_data['phpbb_forums_track'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'forum_id' => array('UINT', 0), 'mark_time' => array('TIMESTAMP', 0), ), @@ -381,7 +382,7 @@ $schema_data['phpbb_forums_track'] = array( $schema_data['phpbb_forums_watch'] = array( 'COLUMNS' => array( 'forum_id' => array('UINT', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'notify_status' => array('BOOL', 0), ), 'KEYS' => array( @@ -455,9 +456,9 @@ $schema_data['phpbb_log'] = array( 'COLUMNS' => array( 'log_id' => array('UINT', NULL, 'auto_increment'), 'log_type' => array('TINT:4', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'forum_id' => array('UINT', 0), - 'topic_id' => array('UINT:10', 0), + 'topic_id' => array('ULINT', 0), 'reportee_id' => array('UINT', 0), 'log_ip' => array('VCHAR:40', ''), 'log_time' => array('TIMESTAMP', 0), @@ -481,7 +482,7 @@ $schema_data['phpbb_login_attempts'] = array( 'attempt_browser' => array('VCHAR:150', ''), 'attempt_forwarded_for' => array('VCHAR:255', ''), 'attempt_time' => array('TIMESTAMP', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'username' => array('VCHAR_UNI:255', 0), 'username_clean' => array('VCHAR_CI', 0), ), @@ -496,7 +497,7 @@ $schema_data['phpbb_login_attempts'] = array( $schema_data['phpbb_moderator_cache'] = array( 'COLUMNS' => array( 'forum_id' => array('UINT', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'username' => array('VCHAR_UNI:255', ''), 'group_id' => array('UINT', 0), 'group_name' => array('VCHAR_UNI', ''), @@ -561,7 +562,7 @@ $schema_data['phpbb_notifications'] = array( 'notification_type_id' => array('USINT', 0), 'item_id' => array('UINT', 0), 'item_parent_id' => array('UINT', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'notification_read' => array('BOOL', 0), 'notification_time' => array('TIMESTAMP', 1), 'notification_data' => array('TEXT_UNI', ''), @@ -575,7 +576,7 @@ $schema_data['phpbb_notifications'] = array( $schema_data['phpbb_oauth_accounts'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'provider' => array('VCHAR', ''), 'oauth_provider_id' => array('TEXT_UNI', ''), ), @@ -587,7 +588,7 @@ $schema_data['phpbb_oauth_accounts'] = array( $schema_data['phpbb_oauth_tokens'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT:10', 0), // phpbb_users.user_id + 'user_id' => array('ULINT', 0), // phpbb_users.user_id 'session_id' => array('CHAR:32', ''), // phpbb_sessions.session_id used only when user_id not set 'provider' => array('VCHAR', ''), // Name of the OAuth provider 'oauth_token' => array('MTEXT', ''), // Serialized token @@ -601,7 +602,7 @@ $schema_data['phpbb_oauth_tokens'] = array( $schema_data['phpbb_poll_options'] = array( 'COLUMNS' => array( 'poll_option_id' => array('TINT:4', 0), - 'topic_id' => array('UINT:10', 0), + 'topic_id' => array('ULINT', 0), 'poll_option_text' => array('TEXT_UNI', ''), 'poll_option_total' => array('UINT', 0), ), @@ -613,7 +614,7 @@ $schema_data['phpbb_poll_options'] = array( $schema_data['phpbb_poll_votes'] = array( 'COLUMNS' => array( - 'topic_id' => array('UINT:10', 0), + 'topic_id' => array('ULINT', 0), 'poll_option_id' => array('TINT:4', 0), 'vote_user_id' => array('UINT', 0), 'vote_user_ip' => array('VCHAR:40', ''), @@ -627,8 +628,8 @@ $schema_data['phpbb_poll_votes'] = array( $schema_data['phpbb_posts'] = array( 'COLUMNS' => array( - 'post_id' => array('UINT:10', NULL, 'auto_increment'), - 'topic_id' => array('UINT:10', 0), + 'post_id' => array('ULINT', NULL, 'auto_increment'), + 'topic_id' => array('ULINT', 0), 'forum_id' => array('UINT', 0), 'poster_id' => array('UINT', 0), 'icon_id' => array('UINT', 0), @@ -706,7 +707,7 @@ $schema_data['phpbb_privmsgs'] = array( $schema_data['phpbb_privmsgs_folder'] = array( 'COLUMNS' => array( 'folder_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'folder_name' => array('VCHAR_UNI', ''), 'pm_count' => array('UINT', 0), ), @@ -719,7 +720,7 @@ $schema_data['phpbb_privmsgs_folder'] = array( $schema_data['phpbb_privmsgs_rules'] = array( 'COLUMNS' => array( 'rule_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'rule_check' => array('UINT', 0), 'rule_connection' => array('UINT', 0), 'rule_string' => array('VCHAR_UNI', ''), @@ -737,7 +738,7 @@ $schema_data['phpbb_privmsgs_rules'] = array( $schema_data['phpbb_privmsgs_to'] = array( 'COLUMNS' => array( 'msg_id' => array('UINT', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'author_id' => array('UINT', 0), 'pm_deleted' => array('BOOL', 0), 'pm_new' => array('BOOL', 1), @@ -787,7 +788,7 @@ $schema_data['phpbb_profile_fields'] = array( $schema_data['phpbb_profile_fields_data'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'pf_phpbb_location' => array('VCHAR', ''), 'pf_phpbb_interests' => array('TEXT_UNI', ''), 'pf_phpbb_occupation' => array('TEXT_UNI', ''), @@ -832,9 +833,9 @@ $schema_data['phpbb_reports'] = array( 'COLUMNS' => array( 'report_id' => array('UINT', NULL, 'auto_increment'), 'reason_id' => array('USINT', 0), - 'post_id' => array('UINT:10', 0), + 'post_id' => array('ULINT', 0), 'pm_id' => array('UINT', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'user_notify' => array('BOOL', 0), 'report_closed' => array('BOOL', 0), 'report_time' => array('TIMESTAMP', 0), @@ -889,7 +890,7 @@ $schema_data['phpbb_search_wordlist'] = array( $schema_data['phpbb_search_wordmatch'] = array( 'COLUMNS' => array( - 'post_id' => array('UINT:10', 0), + 'post_id' => array('ULINT', 0), 'word_id' => array('UINT', 0), 'title_match' => array('BOOL', 0), ), @@ -927,7 +928,7 @@ $schema_data['phpbb_sessions'] = array( $schema_data['phpbb_sessions_keys'] = array( 'COLUMNS' => array( 'key_id' => array('CHAR:32', ''), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'last_ip' => array('VCHAR:40', ''), 'last_login' => array('TIMESTAMP', 0), ), @@ -995,7 +996,7 @@ $schema_data['phpbb_teampage'] = array( $schema_data['phpbb_topics'] = array( 'COLUMNS' => array( - 'topic_id' => array('UINT:10', NULL, 'auto_increment'), + 'topic_id' => array('ULINT', NULL, 'auto_increment'), 'forum_id' => array('UINT', 0), 'icon_id' => array('UINT', 0), 'topic_attachment' => array('BOOL', 0), @@ -1047,8 +1048,8 @@ $schema_data['phpbb_topics'] = array( $schema_data['phpbb_topics_track'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT:10', 0), - 'topic_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), + 'topic_id' => array('ULINT', 0), 'forum_id' => array('UINT', 0), 'mark_time' => array('TIMESTAMP', 0), ), @@ -1061,8 +1062,8 @@ $schema_data['phpbb_topics_track'] = array( $schema_data['phpbb_topics_posted'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT:10', 0), - 'topic_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), + 'topic_id' => array('ULINT', 0), 'topic_posted' => array('BOOL', 0), ), 'PRIMARY_KEY' => array('user_id', 'topic_id'), @@ -1070,8 +1071,8 @@ $schema_data['phpbb_topics_posted'] = array( $schema_data['phpbb_topics_watch'] = array( 'COLUMNS' => array( - 'topic_id' => array('UINT:10', 0), - 'user_id' => array('UINT:10', 0), + 'topic_id' => array('ULINT', 0), + 'user_id' => array('ULINT', 0), 'notify_status' => array('BOOL', 0), ), 'KEYS' => array( @@ -1085,7 +1086,7 @@ $schema_data['phpbb_user_notifications'] = array( 'COLUMNS' => array( 'item_type' => array('VCHAR:255', ''), 'item_id' => array('UINT', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'method' => array('VCHAR:255', ''), 'notify' => array('BOOL', 1), ), @@ -1094,7 +1095,7 @@ $schema_data['phpbb_user_notifications'] = array( $schema_data['phpbb_user_group'] = array( 'COLUMNS' => array( 'group_id' => array('UINT', 0), - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'group_leader' => array('BOOL', 0), 'user_pending' => array('BOOL', 1), ), @@ -1107,7 +1108,7 @@ $schema_data['phpbb_user_group'] = array( $schema_data['phpbb_users'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT:10', NULL, 'auto_increment'), + 'user_id' => array('ULINT', NULL, 'auto_increment'), 'user_type' => array('TINT:2', 0), 'group_id' => array('UINT', 3), 'user_permissions' => array('MTEXT', ''), @@ -1192,8 +1193,8 @@ $schema_data['phpbb_users'] = array( $schema_data['phpbb_warnings'] = array( 'COLUMNS' => array( 'warning_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('UINT:10', 0), - 'post_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), + 'post_id' => array('ULINT', 0), 'log_id' => array('UINT', 0), 'warning_time' => array('TIMESTAMP', 0), ), @@ -1211,7 +1212,7 @@ $schema_data['phpbb_words'] = array( $schema_data['phpbb_zebra'] = array( 'COLUMNS' => array( - 'user_id' => array('UINT:10', 0), + 'user_id' => array('ULINT', 0), 'zebra_id' => array('UINT', 0), 'friend' => array('BOOL', 0), 'foe' => array('BOOL', 0), diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php index 3a7207e743..7f143873b1 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/db/tools.php @@ -44,6 +44,7 @@ class tools 'mysql_41' => array( 'INT:' => 'int(%d)', 'BINT' => 'bigint(20)', + 'ULINT' => 'INT(10) UNSIGNED', 'UINT' => 'mediumint(8) UNSIGNED', 'UINT:' => 'int(%d) UNSIGNED', 'TINT:' => 'tinyint(%d)', @@ -74,6 +75,7 @@ class tools 'mysql_40' => array( 'INT:' => 'int(%d)', 'BINT' => 'bigint(20)', + 'ULINT' => 'INT(10) UNSIGNED', 'UINT' => 'mediumint(8) UNSIGNED', 'UINT:' => 'int(%d) UNSIGNED', 'TINT:' => 'tinyint(%d)', @@ -104,6 +106,7 @@ class tools 'firebird' => array( 'INT:' => 'INTEGER', 'BINT' => 'DOUBLE PRECISION', + 'ULINT' => 'INTEGER', 'UINT' => 'INTEGER', 'UINT:' => 'INTEGER', 'TINT:' => 'INTEGER', @@ -134,6 +137,7 @@ class tools 'mssql' => array( 'INT:' => '[int]', 'BINT' => '[float]', + 'ULINT' => '[int]', 'UINT' => '[int]', 'UINT:' => '[int]', 'TINT:' => '[int]', @@ -164,6 +168,7 @@ class tools 'mssqlnative' => array( 'INT:' => '[int]', 'BINT' => '[float]', + 'ULINT' => '[int]', 'UINT' => '[int]', 'UINT:' => '[int]', 'TINT:' => '[int]', @@ -194,6 +199,7 @@ class tools 'oracle' => array( 'INT:' => 'number(%d)', 'BINT' => 'number(20)', + 'ULINT' => 'number(10)', 'UINT' => 'number(8)', 'UINT:' => 'number(%d)', 'TINT:' => 'number(%d)', @@ -224,7 +230,8 @@ class tools 'sqlite' => array( 'INT:' => 'int(%d)', 'BINT' => 'bigint(20)', - 'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED', + 'ULINT' => 'INTEGER UNSIGNED', // 'int(10) UNSIGNED + 'UINT' => 'INTEGER UNSIGNED', // 'mediumint(8) UNSIGNED', 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED', 'TINT:' => 'tinyint(%d)', 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED', @@ -254,6 +261,7 @@ class tools 'postgres' => array( 'INT:' => 'INT4', 'BINT' => 'INT8', + 'ULINT' => 'INT4', // unsigned 'UINT' => 'INT4', // unsigned 'UINT:' => 'INT4', // unsigned 'USINT' => 'INT2', // unsigned @@ -287,7 +295,7 @@ class tools * A list of types being unsigned for better reference in some db's * @var array */ - var $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP'); + var $unsigned_types = array('ULINT', 'UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP'); /** * A list of supported DBMS. We change this class to support more DBMS, the DBMS itself only need to follow some rules. From 7696f39ac3ecb803468f230129a76dac59f2972b Mon Sep 17 00:00:00 2001 From: hjpotter92 Date: Sun, 2 Mar 2014 23:23:44 +0530 Subject: [PATCH 0003/1676] [ticket/11875] Recreate schemas for install PHPBB3-11875 --- phpBB/install/schemas/mysql_40_schema.sql | 84 +++++++++++------------ phpBB/install/schemas/mysql_41_schema.sql | 84 +++++++++++------------ phpBB/install/schemas/oracle_schema.sql | 84 +++++++++++------------ phpBB/install/schemas/postgres_schema.sql | 78 ++++++++++----------- phpBB/phpbb/db/tools.php | 8 +-- 5 files changed, 169 insertions(+), 169 deletions(-) diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index 16c26fac4a..93a90e3a7c 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -7,7 +7,7 @@ CREATE TABLE phpbb_attachments ( attach_id mediumint(8) UNSIGNED NOT NULL auto_increment, post_msg_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, in_message tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, poster_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, is_orphan tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, @@ -79,7 +79,7 @@ CREATE TABLE phpbb_acl_roles_data ( # Table: 'phpbb_acl_users' CREATE TABLE phpbb_acl_users ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, auth_option_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, auth_role_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, @@ -128,8 +128,8 @@ CREATE TABLE phpbb_bbcodes ( # Table: 'phpbb_bookmarks' CREATE TABLE phpbb_bookmarks ( - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (topic_id, user_id) ); @@ -139,7 +139,7 @@ CREATE TABLE phpbb_bots ( bot_id mediumint(8) UNSIGNED NOT NULL auto_increment, bot_active tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, bot_name blob NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, bot_agent varbinary(255) DEFAULT '' NOT NULL, bot_ip varbinary(255) DEFAULT '' NOT NULL, PRIMARY KEY (bot_id), @@ -189,8 +189,8 @@ CREATE TABLE phpbb_disallow ( # Table: 'phpbb_drafts' CREATE TABLE phpbb_drafts ( draft_id mediumint(8) UNSIGNED NOT NULL auto_increment, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, save_time int(11) UNSIGNED DEFAULT '0' NOT NULL, draft_subject blob NOT NULL, @@ -289,7 +289,7 @@ CREATE TABLE phpbb_forums ( # Table: 'phpbb_forums_access' CREATE TABLE phpbb_forums_access ( forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, session_id binary(32) DEFAULT '' NOT NULL, PRIMARY KEY (forum_id, user_id, session_id) ); @@ -297,7 +297,7 @@ CREATE TABLE phpbb_forums_access ( # Table: 'phpbb_forums_track' CREATE TABLE phpbb_forums_track ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (user_id, forum_id) @@ -307,7 +307,7 @@ CREATE TABLE phpbb_forums_track ( # Table: 'phpbb_forums_watch' CREATE TABLE phpbb_forums_watch ( forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, notify_status tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, KEY forum_id (forum_id), KEY user_id (user_id), @@ -373,9 +373,9 @@ CREATE TABLE phpbb_lang ( CREATE TABLE phpbb_log ( log_id mediumint(8) UNSIGNED NOT NULL auto_increment, log_type tinyint(4) DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, reportee_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, log_ip varbinary(40) DEFAULT '' NOT NULL, log_time int(11) UNSIGNED DEFAULT '0' NOT NULL, @@ -397,7 +397,7 @@ CREATE TABLE phpbb_login_attempts ( attempt_browser varbinary(150) DEFAULT '' NOT NULL, attempt_forwarded_for varbinary(255) DEFAULT '' NOT NULL, attempt_time int(11) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, username blob NOT NULL, username_clean blob NOT NULL, KEY att_ip (attempt_ip, attempt_time), @@ -410,7 +410,7 @@ CREATE TABLE phpbb_login_attempts ( # Table: 'phpbb_moderator_cache' CREATE TABLE phpbb_moderator_cache ( forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, username blob NOT NULL, group_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, group_name blob NOT NULL, @@ -469,7 +469,7 @@ CREATE TABLE phpbb_notifications ( notification_type_id smallint(4) UNSIGNED DEFAULT '0' NOT NULL, item_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, item_parent_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, notification_read tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, notification_time int(11) UNSIGNED DEFAULT '1' NOT NULL, notification_data blob NOT NULL, @@ -481,7 +481,7 @@ CREATE TABLE phpbb_notifications ( # Table: 'phpbb_oauth_accounts' CREATE TABLE phpbb_oauth_accounts ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, provider varbinary(255) DEFAULT '' NOT NULL, oauth_provider_id blob NOT NULL, PRIMARY KEY (user_id, provider) @@ -490,7 +490,7 @@ CREATE TABLE phpbb_oauth_accounts ( # Table: 'phpbb_oauth_tokens' CREATE TABLE phpbb_oauth_tokens ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, session_id binary(32) DEFAULT '' NOT NULL, provider varbinary(255) DEFAULT '' NOT NULL, oauth_token mediumblob NOT NULL, @@ -502,7 +502,7 @@ CREATE TABLE phpbb_oauth_tokens ( # Table: 'phpbb_poll_options' CREATE TABLE phpbb_poll_options ( poll_option_id tinyint(4) DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, poll_option_text blob NOT NULL, poll_option_total mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, KEY poll_opt_id (poll_option_id), @@ -512,7 +512,7 @@ CREATE TABLE phpbb_poll_options ( # Table: 'phpbb_poll_votes' CREATE TABLE phpbb_poll_votes ( - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, poll_option_id tinyint(4) DEFAULT '0' NOT NULL, vote_user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, vote_user_ip varbinary(40) DEFAULT '' NOT NULL, @@ -524,8 +524,8 @@ CREATE TABLE phpbb_poll_votes ( # Table: 'phpbb_posts' CREATE TABLE phpbb_posts ( - post_id mediumint(8) UNSIGNED NOT NULL auto_increment, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + post_id INT(10) UNSIGNED NOT NULL auto_increment, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, poster_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, icon_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, @@ -599,7 +599,7 @@ CREATE TABLE phpbb_privmsgs ( # Table: 'phpbb_privmsgs_folder' CREATE TABLE phpbb_privmsgs_folder ( folder_id mediumint(8) UNSIGNED NOT NULL auto_increment, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, folder_name blob NOT NULL, pm_count mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (folder_id), @@ -610,7 +610,7 @@ CREATE TABLE phpbb_privmsgs_folder ( # Table: 'phpbb_privmsgs_rules' CREATE TABLE phpbb_privmsgs_rules ( rule_id mediumint(8) UNSIGNED NOT NULL auto_increment, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, rule_check mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, rule_connection mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, rule_string blob NOT NULL, @@ -626,7 +626,7 @@ CREATE TABLE phpbb_privmsgs_rules ( # Table: 'phpbb_privmsgs_to' CREATE TABLE phpbb_privmsgs_to ( msg_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, author_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, pm_deleted tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, pm_new tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, @@ -672,7 +672,7 @@ CREATE TABLE phpbb_profile_fields ( # Table: 'phpbb_profile_fields_data' CREATE TABLE phpbb_profile_fields_data ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, pf_phpbb_location varbinary(255) DEFAULT '' NOT NULL, pf_phpbb_interests blob NOT NULL, pf_phpbb_occupation blob NOT NULL, @@ -717,9 +717,9 @@ CREATE TABLE phpbb_ranks ( CREATE TABLE phpbb_reports ( report_id mediumint(8) UNSIGNED NOT NULL auto_increment, reason_id smallint(4) UNSIGNED DEFAULT '0' NOT NULL, - post_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + post_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, pm_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, user_notify tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, report_closed tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, report_time int(11) UNSIGNED DEFAULT '0' NOT NULL, @@ -770,7 +770,7 @@ CREATE TABLE phpbb_search_wordlist ( # Table: 'phpbb_search_wordmatch' CREATE TABLE phpbb_search_wordmatch ( - post_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + post_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, word_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, title_match tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, UNIQUE unq_mtch (word_id, post_id, title_match), @@ -804,7 +804,7 @@ CREATE TABLE phpbb_sessions ( # Table: 'phpbb_sessions_keys' CREATE TABLE phpbb_sessions_keys ( key_id binary(32) DEFAULT '' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, last_ip varbinary(40) DEFAULT '' NOT NULL, last_login int(11) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (key_id, user_id), @@ -865,7 +865,7 @@ CREATE TABLE phpbb_teampage ( # Table: 'phpbb_topics' CREATE TABLE phpbb_topics ( - topic_id mediumint(8) UNSIGNED NOT NULL auto_increment, + topic_id INT(10) UNSIGNED NOT NULL auto_increment, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, icon_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, topic_attachment tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, @@ -915,8 +915,8 @@ CREATE TABLE phpbb_topics ( # Table: 'phpbb_topics_track' CREATE TABLE phpbb_topics_track ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (user_id, topic_id), @@ -927,8 +927,8 @@ CREATE TABLE phpbb_topics_track ( # Table: 'phpbb_topics_posted' CREATE TABLE phpbb_topics_posted ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, topic_posted tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (user_id, topic_id) ); @@ -936,8 +936,8 @@ CREATE TABLE phpbb_topics_posted ( # Table: 'phpbb_topics_watch' CREATE TABLE phpbb_topics_watch ( - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, notify_status tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, KEY topic_id (topic_id), KEY user_id (user_id), @@ -949,7 +949,7 @@ CREATE TABLE phpbb_topics_watch ( CREATE TABLE phpbb_user_notifications ( item_type varbinary(255) DEFAULT '' NOT NULL, item_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, method varbinary(255) DEFAULT '' NOT NULL, notify tinyint(1) UNSIGNED DEFAULT '1' NOT NULL ); @@ -958,7 +958,7 @@ CREATE TABLE phpbb_user_notifications ( # Table: 'phpbb_user_group' CREATE TABLE phpbb_user_group ( group_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, group_leader tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, user_pending tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, KEY group_id (group_id), @@ -969,7 +969,7 @@ CREATE TABLE phpbb_user_group ( # Table: 'phpbb_users' CREATE TABLE phpbb_users ( - user_id mediumint(8) UNSIGNED NOT NULL auto_increment, + user_id INT(10) UNSIGNED NOT NULL auto_increment, user_type tinyint(2) DEFAULT '0' NOT NULL, group_id mediumint(8) UNSIGNED DEFAULT '3' NOT NULL, user_permissions mediumblob NOT NULL, @@ -1052,8 +1052,8 @@ CREATE TABLE phpbb_users ( # Table: 'phpbb_warnings' CREATE TABLE phpbb_warnings ( warning_id mediumint(8) UNSIGNED NOT NULL auto_increment, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - post_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + post_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, log_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, warning_time int(11) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (warning_id) @@ -1071,7 +1071,7 @@ CREATE TABLE phpbb_words ( # Table: 'phpbb_zebra' CREATE TABLE phpbb_zebra ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, zebra_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, friend tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, foe tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index b345e1f474..38db154905 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -7,7 +7,7 @@ CREATE TABLE phpbb_attachments ( attach_id mediumint(8) UNSIGNED NOT NULL auto_increment, post_msg_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, in_message tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, poster_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, is_orphan tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, @@ -79,7 +79,7 @@ CREATE TABLE phpbb_acl_roles_data ( # Table: 'phpbb_acl_users' CREATE TABLE phpbb_acl_users ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, auth_option_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, auth_role_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, @@ -128,8 +128,8 @@ CREATE TABLE phpbb_bbcodes ( # Table: 'phpbb_bookmarks' CREATE TABLE phpbb_bookmarks ( - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (topic_id, user_id) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; @@ -139,7 +139,7 @@ CREATE TABLE phpbb_bots ( bot_id mediumint(8) UNSIGNED NOT NULL auto_increment, bot_active tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, bot_name varchar(255) DEFAULT '' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, bot_agent varchar(255) DEFAULT '' NOT NULL, bot_ip varchar(255) DEFAULT '' NOT NULL, PRIMARY KEY (bot_id), @@ -189,8 +189,8 @@ CREATE TABLE phpbb_disallow ( # Table: 'phpbb_drafts' CREATE TABLE phpbb_drafts ( draft_id mediumint(8) UNSIGNED NOT NULL auto_increment, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, save_time int(11) UNSIGNED DEFAULT '0' NOT NULL, draft_subject varchar(255) DEFAULT '' NOT NULL, @@ -289,7 +289,7 @@ CREATE TABLE phpbb_forums ( # Table: 'phpbb_forums_access' CREATE TABLE phpbb_forums_access ( forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, session_id char(32) DEFAULT '' NOT NULL, PRIMARY KEY (forum_id, user_id, session_id) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; @@ -297,7 +297,7 @@ CREATE TABLE phpbb_forums_access ( # Table: 'phpbb_forums_track' CREATE TABLE phpbb_forums_track ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (user_id, forum_id) @@ -307,7 +307,7 @@ CREATE TABLE phpbb_forums_track ( # Table: 'phpbb_forums_watch' CREATE TABLE phpbb_forums_watch ( forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, notify_status tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, KEY forum_id (forum_id), KEY user_id (user_id), @@ -373,9 +373,9 @@ CREATE TABLE phpbb_lang ( CREATE TABLE phpbb_log ( log_id mediumint(8) UNSIGNED NOT NULL auto_increment, log_type tinyint(4) DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, reportee_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, log_ip varchar(40) DEFAULT '' NOT NULL, log_time int(11) UNSIGNED DEFAULT '0' NOT NULL, @@ -397,7 +397,7 @@ CREATE TABLE phpbb_login_attempts ( attempt_browser varchar(150) DEFAULT '' NOT NULL, attempt_forwarded_for varchar(255) DEFAULT '' NOT NULL, attempt_time int(11) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, username varchar(255) DEFAULT '0' NOT NULL, username_clean varchar(255) DEFAULT '0' NOT NULL, KEY att_ip (attempt_ip, attempt_time), @@ -410,7 +410,7 @@ CREATE TABLE phpbb_login_attempts ( # Table: 'phpbb_moderator_cache' CREATE TABLE phpbb_moderator_cache ( forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, username varchar(255) DEFAULT '' NOT NULL, group_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, group_name varchar(255) DEFAULT '' NOT NULL, @@ -469,7 +469,7 @@ CREATE TABLE phpbb_notifications ( notification_type_id smallint(4) UNSIGNED DEFAULT '0' NOT NULL, item_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, item_parent_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, notification_read tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, notification_time int(11) UNSIGNED DEFAULT '1' NOT NULL, notification_data text NOT NULL, @@ -481,7 +481,7 @@ CREATE TABLE phpbb_notifications ( # Table: 'phpbb_oauth_accounts' CREATE TABLE phpbb_oauth_accounts ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, provider varchar(255) DEFAULT '' NOT NULL, oauth_provider_id text NOT NULL, PRIMARY KEY (user_id, provider) @@ -490,7 +490,7 @@ CREATE TABLE phpbb_oauth_accounts ( # Table: 'phpbb_oauth_tokens' CREATE TABLE phpbb_oauth_tokens ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, session_id char(32) DEFAULT '' NOT NULL, provider varchar(255) DEFAULT '' NOT NULL, oauth_token mediumtext NOT NULL, @@ -502,7 +502,7 @@ CREATE TABLE phpbb_oauth_tokens ( # Table: 'phpbb_poll_options' CREATE TABLE phpbb_poll_options ( poll_option_id tinyint(4) DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, poll_option_text text NOT NULL, poll_option_total mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, KEY poll_opt_id (poll_option_id), @@ -512,7 +512,7 @@ CREATE TABLE phpbb_poll_options ( # Table: 'phpbb_poll_votes' CREATE TABLE phpbb_poll_votes ( - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, poll_option_id tinyint(4) DEFAULT '0' NOT NULL, vote_user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, vote_user_ip varchar(40) DEFAULT '' NOT NULL, @@ -524,8 +524,8 @@ CREATE TABLE phpbb_poll_votes ( # Table: 'phpbb_posts' CREATE TABLE phpbb_posts ( - post_id mediumint(8) UNSIGNED NOT NULL auto_increment, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + post_id INT(10) UNSIGNED NOT NULL auto_increment, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, poster_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, icon_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, @@ -599,7 +599,7 @@ CREATE TABLE phpbb_privmsgs ( # Table: 'phpbb_privmsgs_folder' CREATE TABLE phpbb_privmsgs_folder ( folder_id mediumint(8) UNSIGNED NOT NULL auto_increment, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, folder_name varchar(255) DEFAULT '' NOT NULL, pm_count mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (folder_id), @@ -610,7 +610,7 @@ CREATE TABLE phpbb_privmsgs_folder ( # Table: 'phpbb_privmsgs_rules' CREATE TABLE phpbb_privmsgs_rules ( rule_id mediumint(8) UNSIGNED NOT NULL auto_increment, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, rule_check mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, rule_connection mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, rule_string varchar(255) DEFAULT '' NOT NULL, @@ -626,7 +626,7 @@ CREATE TABLE phpbb_privmsgs_rules ( # Table: 'phpbb_privmsgs_to' CREATE TABLE phpbb_privmsgs_to ( msg_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, author_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, pm_deleted tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, pm_new tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, @@ -672,7 +672,7 @@ CREATE TABLE phpbb_profile_fields ( # Table: 'phpbb_profile_fields_data' CREATE TABLE phpbb_profile_fields_data ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, pf_phpbb_location varchar(255) DEFAULT '' NOT NULL, pf_phpbb_interests text NOT NULL, pf_phpbb_occupation text NOT NULL, @@ -717,9 +717,9 @@ CREATE TABLE phpbb_ranks ( CREATE TABLE phpbb_reports ( report_id mediumint(8) UNSIGNED NOT NULL auto_increment, reason_id smallint(4) UNSIGNED DEFAULT '0' NOT NULL, - post_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + post_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, pm_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, user_notify tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, report_closed tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, report_time int(11) UNSIGNED DEFAULT '0' NOT NULL, @@ -770,7 +770,7 @@ CREATE TABLE phpbb_search_wordlist ( # Table: 'phpbb_search_wordmatch' CREATE TABLE phpbb_search_wordmatch ( - post_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + post_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, word_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, title_match tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, UNIQUE unq_mtch (word_id, post_id, title_match), @@ -804,7 +804,7 @@ CREATE TABLE phpbb_sessions ( # Table: 'phpbb_sessions_keys' CREATE TABLE phpbb_sessions_keys ( key_id char(32) DEFAULT '' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, last_ip varchar(40) DEFAULT '' NOT NULL, last_login int(11) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (key_id, user_id), @@ -865,7 +865,7 @@ CREATE TABLE phpbb_teampage ( # Table: 'phpbb_topics' CREATE TABLE phpbb_topics ( - topic_id mediumint(8) UNSIGNED NOT NULL auto_increment, + topic_id INT(10) UNSIGNED NOT NULL auto_increment, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, icon_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, topic_attachment tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, @@ -915,8 +915,8 @@ CREATE TABLE phpbb_topics ( # Table: 'phpbb_topics_track' CREATE TABLE phpbb_topics_track ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (user_id, topic_id), @@ -927,8 +927,8 @@ CREATE TABLE phpbb_topics_track ( # Table: 'phpbb_topics_posted' CREATE TABLE phpbb_topics_posted ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, topic_posted tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (user_id, topic_id) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; @@ -936,8 +936,8 @@ CREATE TABLE phpbb_topics_posted ( # Table: 'phpbb_topics_watch' CREATE TABLE phpbb_topics_watch ( - topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + topic_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, notify_status tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, KEY topic_id (topic_id), KEY user_id (user_id), @@ -949,7 +949,7 @@ CREATE TABLE phpbb_topics_watch ( CREATE TABLE phpbb_user_notifications ( item_type varchar(255) DEFAULT '' NOT NULL, item_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, method varchar(255) DEFAULT '' NOT NULL, notify tinyint(1) UNSIGNED DEFAULT '1' NOT NULL ) CHARACTER SET `utf8` COLLATE `utf8_bin`; @@ -958,7 +958,7 @@ CREATE TABLE phpbb_user_notifications ( # Table: 'phpbb_user_group' CREATE TABLE phpbb_user_group ( group_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, group_leader tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, user_pending tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, KEY group_id (group_id), @@ -969,7 +969,7 @@ CREATE TABLE phpbb_user_group ( # Table: 'phpbb_users' CREATE TABLE phpbb_users ( - user_id mediumint(8) UNSIGNED NOT NULL auto_increment, + user_id INT(10) UNSIGNED NOT NULL auto_increment, user_type tinyint(2) DEFAULT '0' NOT NULL, group_id mediumint(8) UNSIGNED DEFAULT '3' NOT NULL, user_permissions mediumtext NOT NULL, @@ -1052,8 +1052,8 @@ CREATE TABLE phpbb_users ( # Table: 'phpbb_warnings' CREATE TABLE phpbb_warnings ( warning_id mediumint(8) UNSIGNED NOT NULL auto_increment, - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - post_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, + post_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, log_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, warning_time int(11) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (warning_id) @@ -1071,7 +1071,7 @@ CREATE TABLE phpbb_words ( # Table: 'phpbb_zebra' CREATE TABLE phpbb_zebra ( - user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + user_id INT(10) UNSIGNED DEFAULT '0' NOT NULL, zebra_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, friend tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, foe tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index b819ba2c59..fe3cd8312e 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -49,7 +49,7 @@ CONNECT phpbb/phpbb_password; CREATE TABLE phpbb_attachments ( attach_id number(8) NOT NULL, post_msg_id number(8) DEFAULT '0' NOT NULL, - topic_id number(8) DEFAULT '0' NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, in_message number(1) DEFAULT '0' NOT NULL, poster_id number(8) DEFAULT '0' NOT NULL, is_orphan number(1) DEFAULT '1' NOT NULL, @@ -195,7 +195,7 @@ CREATE INDEX phpbb_acl_roles_data_ath_op_id ON phpbb_acl_roles_data (auth_option Table: 'phpbb_acl_users' */ CREATE TABLE phpbb_acl_users ( - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, forum_id number(8) DEFAULT '0' NOT NULL, auth_option_id number(8) DEFAULT '0' NOT NULL, auth_role_id number(8) DEFAULT '0' NOT NULL, @@ -277,8 +277,8 @@ CREATE INDEX phpbb_bbcodes_display_on_post ON phpbb_bbcodes (display_on_posting) Table: 'phpbb_bookmarks' */ CREATE TABLE phpbb_bookmarks ( - topic_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, CONSTRAINT pk_phpbb_bookmarks PRIMARY KEY (topic_id, user_id) ) / @@ -291,7 +291,7 @@ CREATE TABLE phpbb_bots ( bot_id number(8) NOT NULL, bot_active number(1) DEFAULT '1' NOT NULL, bot_name varchar2(765) DEFAULT '' , - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, bot_agent varchar2(255) DEFAULT '' , bot_ip varchar2(255) DEFAULT '' , CONSTRAINT pk_phpbb_bots PRIMARY KEY (bot_id) @@ -391,8 +391,8 @@ END; */ CREATE TABLE phpbb_drafts ( draft_id number(8) NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, - topic_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, forum_id number(8) DEFAULT '0' NOT NULL, save_time number(11) DEFAULT '0' NOT NULL, draft_subject varchar2(765) DEFAULT '' , @@ -573,7 +573,7 @@ END; */ CREATE TABLE phpbb_forums_access ( forum_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, session_id char(32) DEFAULT '' , CONSTRAINT pk_phpbb_forums_access PRIMARY KEY (forum_id, user_id, session_id) ) @@ -584,7 +584,7 @@ CREATE TABLE phpbb_forums_access ( Table: 'phpbb_forums_track' */ CREATE TABLE phpbb_forums_track ( - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, forum_id number(8) DEFAULT '0' NOT NULL, mark_time number(11) DEFAULT '0' NOT NULL, CONSTRAINT pk_phpbb_forums_track PRIMARY KEY (user_id, forum_id) @@ -597,7 +597,7 @@ CREATE TABLE phpbb_forums_track ( */ CREATE TABLE phpbb_forums_watch ( forum_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, notify_status number(1) DEFAULT '0' NOT NULL ) / @@ -729,9 +729,9 @@ END; CREATE TABLE phpbb_log ( log_id number(8) NOT NULL, log_type number(4) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, forum_id number(8) DEFAULT '0' NOT NULL, - topic_id number(8) DEFAULT '0' NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, reportee_id number(8) DEFAULT '0' NOT NULL, log_ip varchar2(40) DEFAULT '' , log_time number(11) DEFAULT '0' NOT NULL, @@ -778,7 +778,7 @@ CREATE TABLE phpbb_login_attempts ( attempt_browser varchar2(150) DEFAULT '' , attempt_forwarded_for varchar2(255) DEFAULT '' , attempt_time number(11) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, username varchar2(765) DEFAULT '0' NOT NULL, username_clean varchar2(255) DEFAULT '0' NOT NULL ) @@ -798,7 +798,7 @@ CREATE INDEX phpbb_login_attempts_user_id ON phpbb_login_attempts (user_id) */ CREATE TABLE phpbb_moderator_cache ( forum_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, username varchar2(765) DEFAULT '' , group_id number(8) DEFAULT '0' NOT NULL, group_name varchar2(765) DEFAULT '' , @@ -906,7 +906,7 @@ CREATE TABLE phpbb_notifications ( notification_type_id number(4) DEFAULT '0' NOT NULL, item_id number(8) DEFAULT '0' NOT NULL, item_parent_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, notification_read number(1) DEFAULT '0' NOT NULL, notification_time number(11) DEFAULT '1' NOT NULL, notification_data clob DEFAULT '' , @@ -939,7 +939,7 @@ END; Table: 'phpbb_oauth_accounts' */ CREATE TABLE phpbb_oauth_accounts ( - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, provider varchar2(255) DEFAULT '' , oauth_provider_id clob DEFAULT '' , CONSTRAINT pk_phpbb_oauth_accounts PRIMARY KEY (user_id, provider) @@ -951,7 +951,7 @@ CREATE TABLE phpbb_oauth_accounts ( Table: 'phpbb_oauth_tokens' */ CREATE TABLE phpbb_oauth_tokens ( - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, session_id char(32) DEFAULT '' , provider varchar2(255) DEFAULT '' , oauth_token clob DEFAULT '' @@ -968,7 +968,7 @@ CREATE INDEX phpbb_oauth_tokens_provider ON phpbb_oauth_tokens (provider) */ CREATE TABLE phpbb_poll_options ( poll_option_id number(4) DEFAULT '0' NOT NULL, - topic_id number(8) DEFAULT '0' NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, poll_option_text clob DEFAULT '' , poll_option_total number(8) DEFAULT '0' NOT NULL ) @@ -983,7 +983,7 @@ CREATE INDEX phpbb_poll_options_topic_id ON phpbb_poll_options (topic_id) Table: 'phpbb_poll_votes' */ CREATE TABLE phpbb_poll_votes ( - topic_id number(8) DEFAULT '0' NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, poll_option_id number(4) DEFAULT '0' NOT NULL, vote_user_id number(8) DEFAULT '0' NOT NULL, vote_user_ip varchar2(40) DEFAULT '' @@ -1001,8 +1001,8 @@ CREATE INDEX phpbb_poll_votes_vote_user_ip ON phpbb_poll_votes (vote_user_ip) Table: 'phpbb_posts' */ CREATE TABLE phpbb_posts ( - post_id number(8) NOT NULL, - topic_id number(8) DEFAULT '0' NOT NULL, + post_id number(10) NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, forum_id number(8) DEFAULT '0' NOT NULL, poster_id number(8) DEFAULT '0' NOT NULL, icon_id number(8) DEFAULT '0' NOT NULL, @@ -1125,7 +1125,7 @@ END; */ CREATE TABLE phpbb_privmsgs_folder ( folder_id number(8) NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, folder_name varchar2(765) DEFAULT '' , pm_count number(8) DEFAULT '0' NOT NULL, CONSTRAINT pk_phpbb_privmsgs_folder PRIMARY KEY (folder_id) @@ -1156,7 +1156,7 @@ END; */ CREATE TABLE phpbb_privmsgs_rules ( rule_id number(8) NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, rule_check number(8) DEFAULT '0' NOT NULL, rule_connection number(8) DEFAULT '0' NOT NULL, rule_string varchar2(765) DEFAULT '' , @@ -1192,7 +1192,7 @@ END; */ CREATE TABLE phpbb_privmsgs_to ( msg_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, author_id number(8) DEFAULT '0' NOT NULL, pm_deleted number(1) DEFAULT '0' NOT NULL, pm_new number(1) DEFAULT '1' NOT NULL, @@ -1265,7 +1265,7 @@ END; Table: 'phpbb_profile_fields_data' */ CREATE TABLE phpbb_profile_fields_data ( - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, pf_phpbb_location varchar2(255) DEFAULT '' , pf_phpbb_interests clob DEFAULT '' , pf_phpbb_occupation clob DEFAULT '' , @@ -1338,9 +1338,9 @@ END; CREATE TABLE phpbb_reports ( report_id number(8) NOT NULL, reason_id number(4) DEFAULT '0' NOT NULL, - post_id number(8) DEFAULT '0' NOT NULL, + post_id number(10) DEFAULT '0' NOT NULL, pm_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, user_notify number(1) DEFAULT '0' NOT NULL, report_closed number(1) DEFAULT '0' NOT NULL, report_time number(11) DEFAULT '0' NOT NULL, @@ -1454,7 +1454,7 @@ END; Table: 'phpbb_search_wordmatch' */ CREATE TABLE phpbb_search_wordmatch ( - post_id number(8) DEFAULT '0' NOT NULL, + post_id number(10) DEFAULT '0' NOT NULL, word_id number(8) DEFAULT '0' NOT NULL, title_match number(1) DEFAULT '0' NOT NULL, CONSTRAINT u_phpbb_unq_mtch UNIQUE (word_id, post_id, title_match) @@ -1499,7 +1499,7 @@ CREATE INDEX phpbb_sessions_session_fid ON phpbb_sessions (session_forum_id) */ CREATE TABLE phpbb_sessions_keys ( key_id char(32) DEFAULT '' , - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, last_ip varchar2(40) DEFAULT '' , last_login number(11) DEFAULT '0' NOT NULL, CONSTRAINT pk_phpbb_sessions_keys PRIMARY KEY (key_id, user_id) @@ -1641,7 +1641,7 @@ END; Table: 'phpbb_topics' */ CREATE TABLE phpbb_topics ( - topic_id number(8) NOT NULL, + topic_id number(10) NOT NULL, forum_id number(8) DEFAULT '0' NOT NULL, icon_id number(8) DEFAULT '0' NOT NULL, topic_attachment number(1) DEFAULT '0' NOT NULL, @@ -1716,8 +1716,8 @@ END; Table: 'phpbb_topics_track' */ CREATE TABLE phpbb_topics_track ( - user_id number(8) DEFAULT '0' NOT NULL, - topic_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, forum_id number(8) DEFAULT '0' NOT NULL, mark_time number(11) DEFAULT '0' NOT NULL, CONSTRAINT pk_phpbb_topics_track PRIMARY KEY (user_id, topic_id) @@ -1733,8 +1733,8 @@ CREATE INDEX phpbb_topics_track_forum_id ON phpbb_topics_track (forum_id) Table: 'phpbb_topics_posted' */ CREATE TABLE phpbb_topics_posted ( - user_id number(8) DEFAULT '0' NOT NULL, - topic_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, topic_posted number(1) DEFAULT '0' NOT NULL, CONSTRAINT pk_phpbb_topics_posted PRIMARY KEY (user_id, topic_id) ) @@ -1745,8 +1745,8 @@ CREATE TABLE phpbb_topics_posted ( Table: 'phpbb_topics_watch' */ CREATE TABLE phpbb_topics_watch ( - topic_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + topic_id number(10) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, notify_status number(1) DEFAULT '0' NOT NULL ) / @@ -1764,7 +1764,7 @@ CREATE INDEX phpbb_topics_watch_notify_stat ON phpbb_topics_watch (notify_status CREATE TABLE phpbb_user_notifications ( item_type varchar2(255) DEFAULT '' , item_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, method varchar2(255) DEFAULT '' , notify number(1) DEFAULT '1' NOT NULL ) @@ -1776,7 +1776,7 @@ CREATE TABLE phpbb_user_notifications ( */ CREATE TABLE phpbb_user_group ( group_id number(8) DEFAULT '0' NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, group_leader number(1) DEFAULT '0' NOT NULL, user_pending number(1) DEFAULT '1' NOT NULL ) @@ -1793,7 +1793,7 @@ CREATE INDEX phpbb_user_group_group_leader ON phpbb_user_group (group_leader) Table: 'phpbb_users' */ CREATE TABLE phpbb_users ( - user_id number(8) NOT NULL, + user_id number(10) NOT NULL, user_type number(2) DEFAULT '0' NOT NULL, group_id number(8) DEFAULT '3' NOT NULL, user_permissions clob DEFAULT '' , @@ -1898,8 +1898,8 @@ END; */ CREATE TABLE phpbb_warnings ( warning_id number(8) NOT NULL, - user_id number(8) DEFAULT '0' NOT NULL, - post_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, + post_id number(10) DEFAULT '0' NOT NULL, log_id number(8) DEFAULT '0' NOT NULL, warning_time number(11) DEFAULT '0' NOT NULL, CONSTRAINT pk_phpbb_warnings PRIMARY KEY (warning_id) @@ -1955,7 +1955,7 @@ END; Table: 'phpbb_zebra' */ CREATE TABLE phpbb_zebra ( - user_id number(8) DEFAULT '0' NOT NULL, + user_id number(10) DEFAULT '0' NOT NULL, zebra_id number(8) DEFAULT '0' NOT NULL, friend number(1) DEFAULT '0' NOT NULL, foe number(1) DEFAULT '0' NOT NULL, diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index be8af3c873..031a473a84 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -91,7 +91,7 @@ CREATE SEQUENCE phpbb_attachments_seq; CREATE TABLE phpbb_attachments ( attach_id INT4 DEFAULT nextval('phpbb_attachments_seq'), post_msg_id INT4 DEFAULT '0' NOT NULL CHECK (post_msg_id >= 0), - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), + topic_id INT4 DEFAULT '0' NOT NULL, in_message INT2 DEFAULT '0' NOT NULL CHECK (in_message >= 0), poster_id INT4 DEFAULT '0' NOT NULL CHECK (poster_id >= 0), is_orphan INT2 DEFAULT '1' NOT NULL CHECK (is_orphan >= 0), @@ -177,7 +177,7 @@ CREATE INDEX phpbb_acl_roles_data_ath_op_id ON phpbb_acl_roles_data (auth_option Table: 'phpbb_acl_users' */ CREATE TABLE phpbb_acl_users ( - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, forum_id INT4 DEFAULT '0' NOT NULL CHECK (forum_id >= 0), auth_option_id INT4 DEFAULT '0' NOT NULL CHECK (auth_option_id >= 0), auth_role_id INT4 DEFAULT '0' NOT NULL CHECK (auth_role_id >= 0), @@ -234,8 +234,8 @@ CREATE INDEX phpbb_bbcodes_display_on_post ON phpbb_bbcodes (display_on_posting) Table: 'phpbb_bookmarks' */ CREATE TABLE phpbb_bookmarks ( - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + topic_id INT4 DEFAULT '0' NOT NULL, + user_id INT4 DEFAULT '0' NOT NULL, PRIMARY KEY (topic_id, user_id) ); @@ -249,7 +249,7 @@ CREATE TABLE phpbb_bots ( bot_id INT4 DEFAULT nextval('phpbb_bots_seq'), bot_active INT2 DEFAULT '1' NOT NULL CHECK (bot_active >= 0), bot_name varchar(255) DEFAULT '' NOT NULL, - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, bot_agent varchar(255) DEFAULT '' NOT NULL, bot_ip varchar(255) DEFAULT '' NOT NULL, PRIMARY KEY (bot_id) @@ -313,8 +313,8 @@ CREATE SEQUENCE phpbb_drafts_seq; CREATE TABLE phpbb_drafts ( draft_id INT4 DEFAULT nextval('phpbb_drafts_seq'), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, + topic_id INT4 DEFAULT '0' NOT NULL, forum_id INT4 DEFAULT '0' NOT NULL CHECK (forum_id >= 0), save_time INT4 DEFAULT '0' NOT NULL CHECK (save_time >= 0), draft_subject varchar(255) DEFAULT '' NOT NULL, @@ -429,7 +429,7 @@ CREATE INDEX phpbb_forums_forum_lastpost_id ON phpbb_forums (forum_last_post_id) */ CREATE TABLE phpbb_forums_access ( forum_id INT4 DEFAULT '0' NOT NULL CHECK (forum_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, session_id char(32) DEFAULT '' NOT NULL, PRIMARY KEY (forum_id, user_id, session_id) ); @@ -439,7 +439,7 @@ CREATE TABLE phpbb_forums_access ( Table: 'phpbb_forums_track' */ CREATE TABLE phpbb_forums_track ( - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, forum_id INT4 DEFAULT '0' NOT NULL CHECK (forum_id >= 0), mark_time INT4 DEFAULT '0' NOT NULL CHECK (mark_time >= 0), PRIMARY KEY (user_id, forum_id) @@ -451,7 +451,7 @@ CREATE TABLE phpbb_forums_track ( */ CREATE TABLE phpbb_forums_watch ( forum_id INT4 DEFAULT '0' NOT NULL CHECK (forum_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, notify_status INT2 DEFAULT '0' NOT NULL CHECK (notify_status >= 0) ); @@ -533,9 +533,9 @@ CREATE SEQUENCE phpbb_log_seq; CREATE TABLE phpbb_log ( log_id INT4 DEFAULT nextval('phpbb_log_seq'), log_type INT2 DEFAULT '0' NOT NULL, - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, forum_id INT4 DEFAULT '0' NOT NULL CHECK (forum_id >= 0), - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), + topic_id INT4 DEFAULT '0' NOT NULL, reportee_id INT4 DEFAULT '0' NOT NULL CHECK (reportee_id >= 0), log_ip varchar(40) DEFAULT '' NOT NULL, log_time INT4 DEFAULT '0' NOT NULL CHECK (log_time >= 0), @@ -559,7 +559,7 @@ CREATE TABLE phpbb_login_attempts ( attempt_browser varchar(150) DEFAULT '' NOT NULL, attempt_forwarded_for varchar(255) DEFAULT '' NOT NULL, attempt_time INT4 DEFAULT '0' NOT NULL CHECK (attempt_time >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, username varchar(255) DEFAULT '0' NOT NULL, username_clean varchar_ci DEFAULT '0' NOT NULL ); @@ -574,7 +574,7 @@ CREATE INDEX phpbb_login_attempts_user_id ON phpbb_login_attempts (user_id); */ CREATE TABLE phpbb_moderator_cache ( forum_id INT4 DEFAULT '0' NOT NULL CHECK (forum_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, username varchar(255) DEFAULT '' NOT NULL, group_id INT4 DEFAULT '0' NOT NULL CHECK (group_id >= 0), group_name varchar(255) DEFAULT '' NOT NULL, @@ -647,7 +647,7 @@ CREATE TABLE phpbb_notifications ( notification_type_id INT2 DEFAULT '0' NOT NULL CHECK (notification_type_id >= 0), item_id INT4 DEFAULT '0' NOT NULL CHECK (item_id >= 0), item_parent_id INT4 DEFAULT '0' NOT NULL CHECK (item_parent_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, notification_read INT2 DEFAULT '0' NOT NULL CHECK (notification_read >= 0), notification_time INT4 DEFAULT '1' NOT NULL CHECK (notification_time >= 0), notification_data varchar(4000) DEFAULT '' NOT NULL, @@ -661,7 +661,7 @@ CREATE INDEX phpbb_notifications_user ON phpbb_notifications (user_id, notificat Table: 'phpbb_oauth_accounts' */ CREATE TABLE phpbb_oauth_accounts ( - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, provider varchar(255) DEFAULT '' NOT NULL, oauth_provider_id varchar(4000) DEFAULT '' NOT NULL, PRIMARY KEY (user_id, provider) @@ -672,7 +672,7 @@ CREATE TABLE phpbb_oauth_accounts ( Table: 'phpbb_oauth_tokens' */ CREATE TABLE phpbb_oauth_tokens ( - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, session_id char(32) DEFAULT '' NOT NULL, provider varchar(255) DEFAULT '' NOT NULL, oauth_token TEXT DEFAULT '' NOT NULL @@ -686,7 +686,7 @@ CREATE INDEX phpbb_oauth_tokens_provider ON phpbb_oauth_tokens (provider); */ CREATE TABLE phpbb_poll_options ( poll_option_id INT2 DEFAULT '0' NOT NULL, - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), + topic_id INT4 DEFAULT '0' NOT NULL, poll_option_text varchar(4000) DEFAULT '' NOT NULL, poll_option_total INT4 DEFAULT '0' NOT NULL CHECK (poll_option_total >= 0) ); @@ -698,7 +698,7 @@ CREATE INDEX phpbb_poll_options_topic_id ON phpbb_poll_options (topic_id); Table: 'phpbb_poll_votes' */ CREATE TABLE phpbb_poll_votes ( - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), + topic_id INT4 DEFAULT '0' NOT NULL, poll_option_id INT2 DEFAULT '0' NOT NULL, vote_user_id INT4 DEFAULT '0' NOT NULL CHECK (vote_user_id >= 0), vote_user_ip varchar(40) DEFAULT '' NOT NULL @@ -715,7 +715,7 @@ CREATE SEQUENCE phpbb_posts_seq; CREATE TABLE phpbb_posts ( post_id INT4 DEFAULT nextval('phpbb_posts_seq'), - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), + topic_id INT4 DEFAULT '0' NOT NULL, forum_id INT4 DEFAULT '0' NOT NULL CHECK (forum_id >= 0), poster_id INT4 DEFAULT '0' NOT NULL CHECK (poster_id >= 0), icon_id INT4 DEFAULT '0' NOT NULL CHECK (icon_id >= 0), @@ -797,7 +797,7 @@ CREATE SEQUENCE phpbb_privmsgs_folder_seq; CREATE TABLE phpbb_privmsgs_folder ( folder_id INT4 DEFAULT nextval('phpbb_privmsgs_folder_seq'), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, folder_name varchar(255) DEFAULT '' NOT NULL, pm_count INT4 DEFAULT '0' NOT NULL CHECK (pm_count >= 0), PRIMARY KEY (folder_id) @@ -812,7 +812,7 @@ CREATE SEQUENCE phpbb_privmsgs_rules_seq; CREATE TABLE phpbb_privmsgs_rules ( rule_id INT4 DEFAULT nextval('phpbb_privmsgs_rules_seq'), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, rule_check INT4 DEFAULT '0' NOT NULL CHECK (rule_check >= 0), rule_connection INT4 DEFAULT '0' NOT NULL CHECK (rule_connection >= 0), rule_string varchar(255) DEFAULT '' NOT NULL, @@ -830,7 +830,7 @@ CREATE INDEX phpbb_privmsgs_rules_user_id ON phpbb_privmsgs_rules (user_id); */ CREATE TABLE phpbb_privmsgs_to ( msg_id INT4 DEFAULT '0' NOT NULL CHECK (msg_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, author_id INT4 DEFAULT '0' NOT NULL CHECK (author_id >= 0), pm_deleted INT2 DEFAULT '0' NOT NULL CHECK (pm_deleted >= 0), pm_new INT2 DEFAULT '1' NOT NULL CHECK (pm_new >= 0), @@ -882,7 +882,7 @@ CREATE INDEX phpbb_profile_fields_fld_ordr ON phpbb_profile_fields (field_order) Table: 'phpbb_profile_fields_data' */ CREATE TABLE phpbb_profile_fields_data ( - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, pf_phpbb_location varchar(255) DEFAULT '' NOT NULL, pf_phpbb_interests varchar(4000) DEFAULT '' NOT NULL, pf_phpbb_occupation varchar(4000) DEFAULT '' NOT NULL, @@ -939,9 +939,9 @@ CREATE SEQUENCE phpbb_reports_seq; CREATE TABLE phpbb_reports ( report_id INT4 DEFAULT nextval('phpbb_reports_seq'), reason_id INT2 DEFAULT '0' NOT NULL CHECK (reason_id >= 0), - post_id INT4 DEFAULT '0' NOT NULL CHECK (post_id >= 0), + post_id INT4 DEFAULT '0' NOT NULL, pm_id INT4 DEFAULT '0' NOT NULL CHECK (pm_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, user_notify INT2 DEFAULT '0' NOT NULL CHECK (user_notify >= 0), report_closed INT2 DEFAULT '0' NOT NULL CHECK (report_closed >= 0), report_time INT4 DEFAULT '0' NOT NULL CHECK (report_time >= 0), @@ -1004,7 +1004,7 @@ CREATE INDEX phpbb_search_wordlist_wrd_cnt ON phpbb_search_wordlist (word_count) Table: 'phpbb_search_wordmatch' */ CREATE TABLE phpbb_search_wordmatch ( - post_id INT4 DEFAULT '0' NOT NULL CHECK (post_id >= 0), + post_id INT4 DEFAULT '0' NOT NULL, word_id INT4 DEFAULT '0' NOT NULL CHECK (word_id >= 0), title_match INT2 DEFAULT '0' NOT NULL CHECK (title_match >= 0) ); @@ -1042,7 +1042,7 @@ CREATE INDEX phpbb_sessions_session_fid ON phpbb_sessions (session_forum_id); */ CREATE TABLE phpbb_sessions_keys ( key_id char(32) DEFAULT '' NOT NULL, - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, last_ip varchar(40) DEFAULT '' NOT NULL, last_login INT4 DEFAULT '0' NOT NULL CHECK (last_login >= 0), PRIMARY KEY (key_id, user_id) @@ -1175,8 +1175,8 @@ CREATE INDEX phpbb_topics_fid_time_moved ON phpbb_topics (forum_id, topic_last_p Table: 'phpbb_topics_track' */ CREATE TABLE phpbb_topics_track ( - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, + topic_id INT4 DEFAULT '0' NOT NULL, forum_id INT4 DEFAULT '0' NOT NULL CHECK (forum_id >= 0), mark_time INT4 DEFAULT '0' NOT NULL CHECK (mark_time >= 0), PRIMARY KEY (user_id, topic_id) @@ -1189,8 +1189,8 @@ CREATE INDEX phpbb_topics_track_forum_id ON phpbb_topics_track (forum_id); Table: 'phpbb_topics_posted' */ CREATE TABLE phpbb_topics_posted ( - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, + topic_id INT4 DEFAULT '0' NOT NULL, topic_posted INT2 DEFAULT '0' NOT NULL CHECK (topic_posted >= 0), PRIMARY KEY (user_id, topic_id) ); @@ -1200,8 +1200,8 @@ CREATE TABLE phpbb_topics_posted ( Table: 'phpbb_topics_watch' */ CREATE TABLE phpbb_topics_watch ( - topic_id INT4 DEFAULT '0' NOT NULL CHECK (topic_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + topic_id INT4 DEFAULT '0' NOT NULL, + user_id INT4 DEFAULT '0' NOT NULL, notify_status INT2 DEFAULT '0' NOT NULL CHECK (notify_status >= 0) ); @@ -1215,7 +1215,7 @@ CREATE INDEX phpbb_topics_watch_notify_stat ON phpbb_topics_watch (notify_status CREATE TABLE phpbb_user_notifications ( item_type varchar(255) DEFAULT '' NOT NULL, item_id INT4 DEFAULT '0' NOT NULL CHECK (item_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, method varchar(255) DEFAULT '' NOT NULL, notify INT2 DEFAULT '1' NOT NULL CHECK (notify >= 0) ); @@ -1226,7 +1226,7 @@ CREATE TABLE phpbb_user_notifications ( */ CREATE TABLE phpbb_user_group ( group_id INT4 DEFAULT '0' NOT NULL CHECK (group_id >= 0), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, group_leader INT2 DEFAULT '0' NOT NULL CHECK (group_leader >= 0), user_pending INT2 DEFAULT '1' NOT NULL CHECK (user_pending >= 0) ); @@ -1328,8 +1328,8 @@ CREATE SEQUENCE phpbb_warnings_seq; CREATE TABLE phpbb_warnings ( warning_id INT4 DEFAULT nextval('phpbb_warnings_seq'), - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), - post_id INT4 DEFAULT '0' NOT NULL CHECK (post_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, + post_id INT4 DEFAULT '0' NOT NULL, log_id INT4 DEFAULT '0' NOT NULL CHECK (log_id >= 0), warning_time INT4 DEFAULT '0' NOT NULL CHECK (warning_time >= 0), PRIMARY KEY (warning_id) @@ -1353,7 +1353,7 @@ CREATE TABLE phpbb_words ( Table: 'phpbb_zebra' */ CREATE TABLE phpbb_zebra ( - user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0), + user_id INT4 DEFAULT '0' NOT NULL, zebra_id INT4 DEFAULT '0' NOT NULL CHECK (zebra_id >= 0), friend INT2 DEFAULT '0' NOT NULL CHECK (friend >= 0), foe INT2 DEFAULT '0' NOT NULL CHECK (foe >= 0), diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php index 7f143873b1..18e30d309a 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/db/tools.php @@ -230,12 +230,12 @@ class tools 'sqlite' => array( 'INT:' => 'int(%d)', 'BINT' => 'bigint(20)', - 'ULINT' => 'INTEGER UNSIGNED', // 'int(10) UNSIGNED + 'ULINT' => 'INTEGER UNSIGNED', // 'int(10) UNSIGNED', 'UINT' => 'INTEGER UNSIGNED', // 'mediumint(8) UNSIGNED', 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED', 'TINT:' => 'tinyint(%d)', - 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED', - 'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED', + 'USINT' => 'INTEGER UNSIGNED', // 'mediumint(4) UNSIGNED', + 'BOOL' => 'INTEGER UNSIGNED', // 'tinyint(1) UNSIGNED', 'VCHAR' => 'varchar(255)', 'VCHAR:' => 'varchar(%d)', 'CHAR:' => 'char(%d)', @@ -247,7 +247,7 @@ class tools 'STEXT_UNI' => 'text(65535)', 'TEXT_UNI' => 'text(65535)', 'MTEXT_UNI' => 'mediumtext(16777215)', - 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED', + 'TIMESTAMP' => 'INTEGER UNSIGNED', // 'int(11) UNSIGNED', 'DECIMAL' => 'decimal(5,2)', 'DECIMAL:' => 'decimal(%d,2)', 'PDECIMAL' => 'decimal(6,3)', From 6aeb22bfd70ce16fb04d7d4f99cbef6c8d94395a Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sun, 18 May 2014 17:43:26 -0700 Subject: [PATCH 0004/1676] [ticket/12564] Remove version definition from ACP/MCP/UCP module info files PHPBB3-12564 --- phpBB/includes/acp/info/acp_attachments.php | 1 - phpBB/includes/acp/info/acp_ban.php | 1 - phpBB/includes/acp/info/acp_bbcodes.php | 1 - phpBB/includes/acp/info/acp_board.php | 1 - phpBB/includes/acp/info/acp_bots.php | 1 - phpBB/includes/acp/info/acp_captcha.php | 1 - phpBB/includes/acp/info/acp_database.php | 1 - phpBB/includes/acp/info/acp_disallow.php | 1 - phpBB/includes/acp/info/acp_email.php | 1 - phpBB/includes/acp/info/acp_extensions.php | 1 - phpBB/includes/acp/info/acp_forums.php | 1 - phpBB/includes/acp/info/acp_groups.php | 1 - phpBB/includes/acp/info/acp_icons.php | 1 - phpBB/includes/acp/info/acp_inactive.php | 1 - phpBB/includes/acp/info/acp_jabber.php | 1 - phpBB/includes/acp/info/acp_language.php | 1 - phpBB/includes/acp/info/acp_logs.php | 1 - phpBB/includes/acp/info/acp_main.php | 1 - phpBB/includes/acp/info/acp_modules.php | 1 - phpBB/includes/acp/info/acp_permission_roles.php | 1 - phpBB/includes/acp/info/acp_permissions.php | 1 - phpBB/includes/acp/info/acp_php_info.php | 1 - phpBB/includes/acp/info/acp_profile.php | 1 - phpBB/includes/acp/info/acp_prune.php | 1 - phpBB/includes/acp/info/acp_ranks.php | 1 - phpBB/includes/acp/info/acp_reasons.php | 1 - phpBB/includes/acp/info/acp_search.php | 1 - phpBB/includes/acp/info/acp_send_statistics.php | 1 - phpBB/includes/acp/info/acp_styles.php | 1 - phpBB/includes/acp/info/acp_update.php | 1 - phpBB/includes/acp/info/acp_users.php | 1 - phpBB/includes/acp/info/acp_words.php | 1 - phpBB/includes/mcp/info/mcp_ban.php | 1 - phpBB/includes/mcp/info/mcp_logs.php | 1 - phpBB/includes/mcp/info/mcp_main.php | 1 - phpBB/includes/mcp/info/mcp_notes.php | 1 - phpBB/includes/mcp/info/mcp_pm_reports.php | 1 - phpBB/includes/mcp/info/mcp_queue.php | 1 - phpBB/includes/mcp/info/mcp_reports.php | 1 - phpBB/includes/mcp/info/mcp_warn.php | 1 - phpBB/includes/ucp/info/ucp_attachments.php | 1 - phpBB/includes/ucp/info/ucp_auth_link.php | 1 - phpBB/includes/ucp/info/ucp_groups.php | 1 - phpBB/includes/ucp/info/ucp_main.php | 1 - phpBB/includes/ucp/info/ucp_notifications.php | 1 - phpBB/includes/ucp/info/ucp_pm.php | 1 - phpBB/includes/ucp/info/ucp_prefs.php | 1 - phpBB/includes/ucp/info/ucp_profile.php | 1 - phpBB/includes/ucp/info/ucp_zebra.php | 1 - 49 files changed, 49 deletions(-) diff --git a/phpBB/includes/acp/info/acp_attachments.php b/phpBB/includes/acp/info/acp_attachments.php index 8fad241451..96ba8abb17 100644 --- a/phpBB/includes/acp/info/acp_attachments.php +++ b/phpBB/includes/acp/info/acp_attachments.php @@ -17,7 +17,6 @@ class acp_attachments_info return array( 'filename' => 'acp_attachments', 'title' => 'ACP_ATTACHMENTS', - 'version' => '1.0.0', 'modes' => array( 'attach' => array('title' => 'ACP_ATTACHMENT_SETTINGS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_ATTACHMENTS')), 'extensions' => array('title' => 'ACP_MANAGE_EXTENSIONS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')), diff --git a/phpBB/includes/acp/info/acp_ban.php b/phpBB/includes/acp/info/acp_ban.php index 37f0f021a7..3f05cfd2fe 100644 --- a/phpBB/includes/acp/info/acp_ban.php +++ b/phpBB/includes/acp/info/acp_ban.php @@ -17,7 +17,6 @@ class acp_ban_info return array( 'filename' => 'acp_ban', 'title' => 'ACP_BAN', - 'version' => '1.0.0', 'modes' => array( 'email' => array('title' => 'ACP_BAN_EMAILS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), 'ip' => array('title' => 'ACP_BAN_IPS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), diff --git a/phpBB/includes/acp/info/acp_bbcodes.php b/phpBB/includes/acp/info/acp_bbcodes.php index 5c88ca8a0f..599de72f92 100644 --- a/phpBB/includes/acp/info/acp_bbcodes.php +++ b/phpBB/includes/acp/info/acp_bbcodes.php @@ -17,7 +17,6 @@ class acp_bbcodes_info return array( 'filename' => 'acp_bbcodes', 'title' => 'ACP_BBCODES', - 'version' => '1.0.0', 'modes' => array( 'bbcodes' => array('title' => 'ACP_BBCODES', 'auth' => 'acl_a_bbcode', 'cat' => array('ACP_MESSAGES')), ), diff --git a/phpBB/includes/acp/info/acp_board.php b/phpBB/includes/acp/info/acp_board.php index 50d5a4f4e1..c0a75bb99f 100644 --- a/phpBB/includes/acp/info/acp_board.php +++ b/phpBB/includes/acp/info/acp_board.php @@ -17,7 +17,6 @@ class acp_board_info return array( 'filename' => 'acp_board', 'title' => 'ACP_BOARD_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'settings' => array('title' => 'ACP_BOARD_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), 'features' => array('title' => 'ACP_BOARD_FEATURES', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), diff --git a/phpBB/includes/acp/info/acp_bots.php b/phpBB/includes/acp/info/acp_bots.php index c30ab588ab..6d5bcde9f8 100644 --- a/phpBB/includes/acp/info/acp_bots.php +++ b/phpBB/includes/acp/info/acp_bots.php @@ -17,7 +17,6 @@ class acp_bots_info return array( 'filename' => 'acp_bots', 'title' => 'ACP_BOTS', - 'version' => '1.0.0', 'modes' => array( 'bots' => array('title' => 'ACP_BOTS', 'auth' => 'acl_a_bots', 'cat' => array('ACP_GENERAL_TASKS')), ), diff --git a/phpBB/includes/acp/info/acp_captcha.php b/phpBB/includes/acp/info/acp_captcha.php index 3f31b4c102..a3fc173ff2 100644 --- a/phpBB/includes/acp/info/acp_captcha.php +++ b/phpBB/includes/acp/info/acp_captcha.php @@ -17,7 +17,6 @@ class acp_captcha_info return array( 'filename' => 'acp_captcha', 'title' => 'ACP_CAPTCHA', - 'version' => '1.0.0', 'modes' => array( 'visual' => array('title' => 'ACP_VC_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), 'img' => array('title' => 'ACP_VC_CAPTCHA_DISPLAY', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION'), 'display' => false) diff --git a/phpBB/includes/acp/info/acp_database.php b/phpBB/includes/acp/info/acp_database.php index c8ad65e255..3bd1d2529b 100644 --- a/phpBB/includes/acp/info/acp_database.php +++ b/phpBB/includes/acp/info/acp_database.php @@ -17,7 +17,6 @@ class acp_database_info return array( 'filename' => 'acp_database', 'title' => 'ACP_DATABASE', - 'version' => '1.0.0', 'modes' => array( 'backup' => array('title' => 'ACP_BACKUP', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')), 'restore' => array('title' => 'ACP_RESTORE', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')), diff --git a/phpBB/includes/acp/info/acp_disallow.php b/phpBB/includes/acp/info/acp_disallow.php index f9dd4c32c0..74c707faa7 100644 --- a/phpBB/includes/acp/info/acp_disallow.php +++ b/phpBB/includes/acp/info/acp_disallow.php @@ -17,7 +17,6 @@ class acp_disallow_info return array( 'filename' => 'acp_disallow', 'title' => 'ACP_DISALLOW', - 'version' => '1.0.0', 'modes' => array( 'usernames' => array('title' => 'ACP_DISALLOW_USERNAMES', 'auth' => 'acl_a_names', 'cat' => array('ACP_USER_SECURITY')), ), diff --git a/phpBB/includes/acp/info/acp_email.php b/phpBB/includes/acp/info/acp_email.php index 620904c956..64450bb3f4 100644 --- a/phpBB/includes/acp/info/acp_email.php +++ b/phpBB/includes/acp/info/acp_email.php @@ -17,7 +17,6 @@ class acp_email_info return array( 'filename' => 'acp_email', 'title' => 'ACP_MASS_EMAIL', - 'version' => '1.0.0', 'modes' => array( 'email' => array('title' => 'ACP_MASS_EMAIL', 'auth' => 'acl_a_email && cfg_email_enable', 'cat' => array('ACP_GENERAL_TASKS')), ), diff --git a/phpBB/includes/acp/info/acp_extensions.php b/phpBB/includes/acp/info/acp_extensions.php index 174b365af0..6fcbe3f9bb 100644 --- a/phpBB/includes/acp/info/acp_extensions.php +++ b/phpBB/includes/acp/info/acp_extensions.php @@ -17,7 +17,6 @@ class acp_extensions_info return array( 'filename' => 'acp_extensions', 'title' => 'ACP_EXTENSION_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_EXTENSION_MANAGEMENT')), ), diff --git a/phpBB/includes/acp/info/acp_forums.php b/phpBB/includes/acp/info/acp_forums.php index e5281a4e58..7a4dd25908 100644 --- a/phpBB/includes/acp/info/acp_forums.php +++ b/phpBB/includes/acp/info/acp_forums.php @@ -17,7 +17,6 @@ class acp_forums_info return array( 'filename' => 'acp_forums', 'title' => 'ACP_FORUM_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'manage' => array('title' => 'ACP_MANAGE_FORUMS', 'auth' => 'acl_a_forum', 'cat' => array('ACP_MANAGE_FORUMS')), ), diff --git a/phpBB/includes/acp/info/acp_groups.php b/phpBB/includes/acp/info/acp_groups.php index af3f4893fd..0c962d7591 100644 --- a/phpBB/includes/acp/info/acp_groups.php +++ b/phpBB/includes/acp/info/acp_groups.php @@ -17,7 +17,6 @@ class acp_groups_info return array( 'filename' => 'acp_groups', 'title' => 'ACP_GROUPS_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'manage' => array('title' => 'ACP_GROUPS_MANAGE', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')), 'position' => array('title' => 'ACP_GROUPS_POSITION', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')), diff --git a/phpBB/includes/acp/info/acp_icons.php b/phpBB/includes/acp/info/acp_icons.php index e0cf05660c..aefab52c9e 100644 --- a/phpBB/includes/acp/info/acp_icons.php +++ b/phpBB/includes/acp/info/acp_icons.php @@ -17,7 +17,6 @@ class acp_icons_info return array( 'filename' => 'acp_icons', 'title' => 'ACP_ICONS_SMILIES', - 'version' => '1.0.0', 'modes' => array( 'icons' => array('title' => 'ACP_ICONS', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')), 'smilies' => array('title' => 'ACP_SMILIES', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')), diff --git a/phpBB/includes/acp/info/acp_inactive.php b/phpBB/includes/acp/info/acp_inactive.php index 02b1fcdaa2..6b54d8f71c 100644 --- a/phpBB/includes/acp/info/acp_inactive.php +++ b/phpBB/includes/acp/info/acp_inactive.php @@ -17,7 +17,6 @@ class acp_inactive_info return array( 'filename' => 'acp_inactive', 'title' => 'ACP_INACTIVE_USERS', - 'version' => '1.0.0', 'modes' => array( 'list' => array('title' => 'ACP_INACTIVE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')), ), diff --git a/phpBB/includes/acp/info/acp_jabber.php b/phpBB/includes/acp/info/acp_jabber.php index 3ad05e1a6a..b66ceb317e 100644 --- a/phpBB/includes/acp/info/acp_jabber.php +++ b/phpBB/includes/acp/info/acp_jabber.php @@ -17,7 +17,6 @@ class acp_jabber_info return array( 'filename' => 'acp_jabber', 'title' => 'ACP_JABBER_SETTINGS', - 'version' => '1.0.0', 'modes' => array( 'settings' => array('title' => 'ACP_JABBER_SETTINGS', 'auth' => 'acl_a_jabber', 'cat' => array('ACP_CLIENT_COMMUNICATION')), ), diff --git a/phpBB/includes/acp/info/acp_language.php b/phpBB/includes/acp/info/acp_language.php index 7f33a22fa6..e4d7ac051e 100644 --- a/phpBB/includes/acp/info/acp_language.php +++ b/phpBB/includes/acp/info/acp_language.php @@ -17,7 +17,6 @@ class acp_language_info return array( 'filename' => 'acp_language', 'title' => 'ACP_LANGUAGE', - 'version' => '1.0.0', 'modes' => array( 'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_LANGUAGE')), ), diff --git a/phpBB/includes/acp/info/acp_logs.php b/phpBB/includes/acp/info/acp_logs.php index 033f9baf50..3900bb3846 100644 --- a/phpBB/includes/acp/info/acp_logs.php +++ b/phpBB/includes/acp/info/acp_logs.php @@ -17,7 +17,6 @@ class acp_logs_info return array( 'filename' => 'acp_logs', 'title' => 'ACP_LOGGING', - 'version' => '1.0.0', 'modes' => array( 'admin' => array('title' => 'ACP_ADMIN_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), 'mod' => array('title' => 'ACP_MOD_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), diff --git a/phpBB/includes/acp/info/acp_main.php b/phpBB/includes/acp/info/acp_main.php index 4c1cb6dc0f..eb5feffb7d 100644 --- a/phpBB/includes/acp/info/acp_main.php +++ b/phpBB/includes/acp/info/acp_main.php @@ -17,7 +17,6 @@ class acp_main_info return array( 'filename' => 'acp_main', 'title' => 'ACP_INDEX', - 'version' => '1.0.0', 'modes' => array( 'main' => array('title' => 'ACP_INDEX', 'auth' => '', 'cat' => array('ACP_CAT_GENERAL')), ), diff --git a/phpBB/includes/acp/info/acp_modules.php b/phpBB/includes/acp/info/acp_modules.php index c9d2cffa72..f7933c0b1b 100644 --- a/phpBB/includes/acp/info/acp_modules.php +++ b/phpBB/includes/acp/info/acp_modules.php @@ -17,7 +17,6 @@ class acp_modules_info return array( 'filename' => 'acp_modules', 'title' => 'ACP_MODULE_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'acp' => array('title' => 'ACP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), 'ucp' => array('title' => 'UCP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), diff --git a/phpBB/includes/acp/info/acp_permission_roles.php b/phpBB/includes/acp/info/acp_permission_roles.php index ee2a3ee560..d8aea70048 100644 --- a/phpBB/includes/acp/info/acp_permission_roles.php +++ b/phpBB/includes/acp/info/acp_permission_roles.php @@ -17,7 +17,6 @@ class acp_permission_roles_info return array( 'filename' => 'acp_permission_roles', 'title' => 'ACP_PERMISSION_ROLES', - 'version' => '1.0.0', 'modes' => array( 'admin_roles' => array('title' => 'ACP_ADMIN_ROLES', 'auth' => 'acl_a_roles && acl_a_aauth', 'cat' => array('ACP_PERMISSION_ROLES')), 'user_roles' => array('title' => 'ACP_USER_ROLES', 'auth' => 'acl_a_roles && acl_a_uauth', 'cat' => array('ACP_PERMISSION_ROLES')), diff --git a/phpBB/includes/acp/info/acp_permissions.php b/phpBB/includes/acp/info/acp_permissions.php index 7b51b67a96..b3d3d04422 100644 --- a/phpBB/includes/acp/info/acp_permissions.php +++ b/phpBB/includes/acp/info/acp_permissions.php @@ -17,7 +17,6 @@ class acp_permissions_info return array( 'filename' => 'acp_permissions', 'title' => 'ACP_PERMISSIONS', - 'version' => '1.0.0', 'modes' => array( 'intro' => array('title' => 'ACP_PERMISSIONS', 'auth' => 'acl_a_authusers || acl_a_authgroups || acl_a_viewauth', 'cat' => array('ACP_CAT_PERMISSIONS')), 'trace' => array('title' => 'ACP_PERMISSION_TRACE', 'auth' => 'acl_a_viewauth', 'display' => false, 'cat' => array('ACP_PERMISSION_MASKS')), diff --git a/phpBB/includes/acp/info/acp_php_info.php b/phpBB/includes/acp/info/acp_php_info.php index a456e4b8b7..79408f2a92 100644 --- a/phpBB/includes/acp/info/acp_php_info.php +++ b/phpBB/includes/acp/info/acp_php_info.php @@ -17,7 +17,6 @@ class acp_php_info_info return array( 'filename' => 'acp_php_info', 'title' => 'ACP_PHP_INFO', - 'version' => '1.0.0', 'modes' => array( 'info' => array('title' => 'ACP_PHP_INFO', 'auth' => 'acl_a_phpinfo', 'cat' => array('ACP_GENERAL_TASKS')), ), diff --git a/phpBB/includes/acp/info/acp_profile.php b/phpBB/includes/acp/info/acp_profile.php index 6fa673b094..9575caba9d 100644 --- a/phpBB/includes/acp/info/acp_profile.php +++ b/phpBB/includes/acp/info/acp_profile.php @@ -17,7 +17,6 @@ class acp_profile_info return array( 'filename' => 'acp_profile', 'title' => 'ACP_CUSTOM_PROFILE_FIELDS', - 'version' => '1.0.0', 'modes' => array( 'profile' => array('title' => 'ACP_CUSTOM_PROFILE_FIELDS', 'auth' => 'acl_a_profile', 'cat' => array('ACP_CAT_USERS')), ), diff --git a/phpBB/includes/acp/info/acp_prune.php b/phpBB/includes/acp/info/acp_prune.php index 0f70d9d638..f44e78adfc 100644 --- a/phpBB/includes/acp/info/acp_prune.php +++ b/phpBB/includes/acp/info/acp_prune.php @@ -17,7 +17,6 @@ class acp_prune_info return array( 'filename' => 'acp_prune', 'title' => 'ACP_PRUNING', - 'version' => '1.0.0', 'modes' => array( 'forums' => array('title' => 'ACP_PRUNE_FORUMS', 'auth' => 'acl_a_prune', 'cat' => array('ACP_MANAGE_FORUMS')), 'users' => array('title' => 'ACP_PRUNE_USERS', 'auth' => 'acl_a_userdel', 'cat' => array('ACP_CAT_USERS')), diff --git a/phpBB/includes/acp/info/acp_ranks.php b/phpBB/includes/acp/info/acp_ranks.php index 651a86471d..c5c9b2cf10 100644 --- a/phpBB/includes/acp/info/acp_ranks.php +++ b/phpBB/includes/acp/info/acp_ranks.php @@ -17,7 +17,6 @@ class acp_ranks_info return array( 'filename' => 'acp_ranks', 'title' => 'ACP_RANKS', - 'version' => '1.0.0', 'modes' => array( 'ranks' => array('title' => 'ACP_MANAGE_RANKS', 'auth' => 'acl_a_ranks', 'cat' => array('ACP_CAT_USERS')), ), diff --git a/phpBB/includes/acp/info/acp_reasons.php b/phpBB/includes/acp/info/acp_reasons.php index 9f8f2ced77..12529248f5 100644 --- a/phpBB/includes/acp/info/acp_reasons.php +++ b/phpBB/includes/acp/info/acp_reasons.php @@ -17,7 +17,6 @@ class acp_reasons_info return array( 'filename' => 'acp_reasons', 'title' => 'ACP_REASONS', - 'version' => '1.0.0', 'modes' => array( 'main' => array('title' => 'ACP_MANAGE_REASONS', 'auth' => 'acl_a_reasons', 'cat' => array('ACP_GENERAL_TASKS')), ), diff --git a/phpBB/includes/acp/info/acp_search.php b/phpBB/includes/acp/info/acp_search.php index 494d8afd67..aed1e32883 100644 --- a/phpBB/includes/acp/info/acp_search.php +++ b/phpBB/includes/acp/info/acp_search.php @@ -17,7 +17,6 @@ class acp_search_info return array( 'filename' => 'acp_search', 'title' => 'ACP_SEARCH', - 'version' => '1.0.0', 'modes' => array( 'settings' => array('title' => 'ACP_SEARCH_SETTINGS', 'auth' => 'acl_a_search', 'cat' => array('ACP_SERVER_CONFIGURATION')), 'index' => array('title' => 'ACP_SEARCH_INDEX', 'auth' => 'acl_a_search', 'cat' => array('ACP_CAT_DATABASE')), diff --git a/phpBB/includes/acp/info/acp_send_statistics.php b/phpBB/includes/acp/info/acp_send_statistics.php index 07e7f3ba5c..69bee6e03e 100644 --- a/phpBB/includes/acp/info/acp_send_statistics.php +++ b/phpBB/includes/acp/info/acp_send_statistics.php @@ -17,7 +17,6 @@ class acp_send_statistics_info return array( 'filename' => 'acp_send_statistics', 'title' => 'ACP_SEND_STATISTICS', - 'version' => '1.0.0', 'modes' => array( 'send_statistics' => array('title' => 'ACP_SEND_STATISTICS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), ), diff --git a/phpBB/includes/acp/info/acp_styles.php b/phpBB/includes/acp/info/acp_styles.php index 3137c4781b..f5d146e490 100644 --- a/phpBB/includes/acp/info/acp_styles.php +++ b/phpBB/includes/acp/info/acp_styles.php @@ -17,7 +17,6 @@ class acp_styles_info return array( 'filename' => 'acp_styles', 'title' => 'ACP_CAT_STYLES', - 'version' => '2.0.0', 'modes' => array( 'style' => array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), 'install' => array('title' => 'ACP_STYLES_INSTALL', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), diff --git a/phpBB/includes/acp/info/acp_update.php b/phpBB/includes/acp/info/acp_update.php index 3d491216a8..3739da30fb 100644 --- a/phpBB/includes/acp/info/acp_update.php +++ b/phpBB/includes/acp/info/acp_update.php @@ -17,7 +17,6 @@ class acp_update_info return array( 'filename' => 'acp_update', 'title' => 'ACP_UPDATE', - 'version' => '1.0.0', 'modes' => array( 'version_check' => array('title' => 'ACP_VERSION_CHECK', 'auth' => 'acl_a_board', 'cat' => array('ACP_AUTOMATION')), ), diff --git a/phpBB/includes/acp/info/acp_users.php b/phpBB/includes/acp/info/acp_users.php index 1848622a1c..4ffad1abbf 100644 --- a/phpBB/includes/acp/info/acp_users.php +++ b/phpBB/includes/acp/info/acp_users.php @@ -17,7 +17,6 @@ class acp_users_info return array( 'filename' => 'acp_users', 'title' => 'ACP_USER_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'overview' => array('title' => 'ACP_MANAGE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')), 'feedback' => array('title' => 'ACP_USER_FEEDBACK', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), diff --git a/phpBB/includes/acp/info/acp_words.php b/phpBB/includes/acp/info/acp_words.php index 48cb3fbdd1..d6d5d89a21 100644 --- a/phpBB/includes/acp/info/acp_words.php +++ b/phpBB/includes/acp/info/acp_words.php @@ -17,7 +17,6 @@ class acp_words_info return array( 'filename' => 'acp_words', 'title' => 'ACP_WORDS', - 'version' => '1.0.0', 'modes' => array( 'words' => array('title' => 'ACP_WORDS', 'auth' => 'acl_a_words', 'cat' => array('ACP_MESSAGES')), ), diff --git a/phpBB/includes/mcp/info/mcp_ban.php b/phpBB/includes/mcp/info/mcp_ban.php index a3a1e0ef9a..c736977b6a 100644 --- a/phpBB/includes/mcp/info/mcp_ban.php +++ b/phpBB/includes/mcp/info/mcp_ban.php @@ -17,7 +17,6 @@ class mcp_ban_info return array( 'filename' => 'mcp_ban', 'title' => 'MCP_BAN', - 'version' => '1.0.0', 'modes' => array( 'user' => array('title' => 'MCP_BAN_USERNAMES', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), 'ip' => array('title' => 'MCP_BAN_IPS', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), diff --git a/phpBB/includes/mcp/info/mcp_logs.php b/phpBB/includes/mcp/info/mcp_logs.php index fc30a600c0..12ef43bf75 100644 --- a/phpBB/includes/mcp/info/mcp_logs.php +++ b/phpBB/includes/mcp/info/mcp_logs.php @@ -17,7 +17,6 @@ class mcp_logs_info return array( 'filename' => 'mcp_logs', 'title' => 'MCP_LOGS', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'MCP_LOGS_FRONT', 'auth' => 'acl_m_ || aclf_m_', 'cat' => array('MCP_LOGS')), 'forum_logs' => array('title' => 'MCP_LOGS_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_LOGS')), diff --git a/phpBB/includes/mcp/info/mcp_main.php b/phpBB/includes/mcp/info/mcp_main.php index 705715cbeb..949f4e9aae 100644 --- a/phpBB/includes/mcp/info/mcp_main.php +++ b/phpBB/includes/mcp/info/mcp_main.php @@ -17,7 +17,6 @@ class mcp_main_info return array( 'filename' => 'mcp_main', 'title' => 'MCP_MAIN', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'MCP_MAIN_FRONT', 'auth' => '', 'cat' => array('MCP_MAIN')), 'forum_view' => array('title' => 'MCP_MAIN_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_MAIN')), diff --git a/phpBB/includes/mcp/info/mcp_notes.php b/phpBB/includes/mcp/info/mcp_notes.php index a77b461bbd..4a80df3521 100644 --- a/phpBB/includes/mcp/info/mcp_notes.php +++ b/phpBB/includes/mcp/info/mcp_notes.php @@ -17,7 +17,6 @@ class mcp_notes_info return array( 'filename' => 'mcp_notes', 'title' => 'MCP_NOTES', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'MCP_NOTES_FRONT', 'auth' => '', 'cat' => array('MCP_NOTES')), 'user_notes' => array('title' => 'MCP_NOTES_USER', 'auth' => '', 'cat' => array('MCP_NOTES')), diff --git a/phpBB/includes/mcp/info/mcp_pm_reports.php b/phpBB/includes/mcp/info/mcp_pm_reports.php index d530a917cb..2febf4cf7f 100644 --- a/phpBB/includes/mcp/info/mcp_pm_reports.php +++ b/phpBB/includes/mcp/info/mcp_pm_reports.php @@ -17,7 +17,6 @@ class mcp_pm_reports_info return array( 'filename' => 'mcp_pm_reports', 'title' => 'MCP_PM_REPORTS', - 'version' => '1.0.0', 'modes' => array( 'pm_reports' => array('title' => 'MCP_PM_REPORTS_OPEN', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), 'pm_reports_closed' => array('title' => 'MCP_PM_REPORTS_CLOSED', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), diff --git a/phpBB/includes/mcp/info/mcp_queue.php b/phpBB/includes/mcp/info/mcp_queue.php index 68cac5abd2..443d281aae 100644 --- a/phpBB/includes/mcp/info/mcp_queue.php +++ b/phpBB/includes/mcp/info/mcp_queue.php @@ -17,7 +17,6 @@ class mcp_queue_info return array( 'filename' => 'mcp_queue', 'title' => 'MCP_QUEUE', - 'version' => '1.0.0', 'modes' => array( 'unapproved_topics' => array('title' => 'MCP_QUEUE_UNAPPROVED_TOPICS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), 'unapproved_posts' => array('title' => 'MCP_QUEUE_UNAPPROVED_POSTS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), diff --git a/phpBB/includes/mcp/info/mcp_reports.php b/phpBB/includes/mcp/info/mcp_reports.php index cb6962a1d5..e181125975 100644 --- a/phpBB/includes/mcp/info/mcp_reports.php +++ b/phpBB/includes/mcp/info/mcp_reports.php @@ -17,7 +17,6 @@ class mcp_reports_info return array( 'filename' => 'mcp_reports', 'title' => 'MCP_REPORTS', - 'version' => '1.0.0', 'modes' => array( 'reports' => array('title' => 'MCP_REPORTS_OPEN', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), 'reports_closed' => array('title' => 'MCP_REPORTS_CLOSED', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), diff --git a/phpBB/includes/mcp/info/mcp_warn.php b/phpBB/includes/mcp/info/mcp_warn.php index d5ac1eedbf..0d7f64c7a3 100644 --- a/phpBB/includes/mcp/info/mcp_warn.php +++ b/phpBB/includes/mcp/info/mcp_warn.php @@ -17,7 +17,6 @@ class mcp_warn_info return array( 'filename' => 'mcp_warn', 'title' => 'MCP_WARN', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'MCP_WARN_FRONT', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), 'list' => array('title' => 'MCP_WARN_LIST', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), diff --git a/phpBB/includes/ucp/info/ucp_attachments.php b/phpBB/includes/ucp/info/ucp_attachments.php index adc7b92920..8bfe1452c7 100644 --- a/phpBB/includes/ucp/info/ucp_attachments.php +++ b/phpBB/includes/ucp/info/ucp_attachments.php @@ -17,7 +17,6 @@ class ucp_attachments_info return array( 'filename' => 'ucp_attachments', 'title' => 'UCP_ATTACHMENTS', - 'version' => '1.0.0', 'modes' => array( 'attachments' => array('title' => 'UCP_MAIN_ATTACHMENTS', 'auth' => 'acl_u_attach', 'cat' => array('UCP_MAIN')), ), diff --git a/phpBB/includes/ucp/info/ucp_auth_link.php b/phpBB/includes/ucp/info/ucp_auth_link.php index 3a34232d28..8b141a99ea 100644 --- a/phpBB/includes/ucp/info/ucp_auth_link.php +++ b/phpBB/includes/ucp/info/ucp_auth_link.php @@ -17,7 +17,6 @@ class ucp_auth_link_info return array( 'filename' => 'ucp_auth_link', 'title' => 'UCP_AUTH_LINK', - 'version' => '1.0.0', 'modes' => array( 'auth_link' => array('title' => 'UCP_AUTH_LINK_MANAGE', 'auth' => 'authmethod_oauth', 'cat' => array('UCP_PROFILE')), ), diff --git a/phpBB/includes/ucp/info/ucp_groups.php b/phpBB/includes/ucp/info/ucp_groups.php index b7ffcd0971..1e83401c45 100644 --- a/phpBB/includes/ucp/info/ucp_groups.php +++ b/phpBB/includes/ucp/info/ucp_groups.php @@ -17,7 +17,6 @@ class ucp_groups_info return array( 'filename' => 'ucp_groups', 'title' => 'UCP_USERGROUPS', - 'version' => '1.0.0', 'modes' => array( 'membership' => array('title' => 'UCP_USERGROUPS_MEMBER', 'auth' => '', 'cat' => array('UCP_USERGROUPS')), 'manage' => array('title' => 'UCP_USERGROUPS_MANAGE', 'auth' => '', 'cat' => array('UCP_USERGROUPS')), diff --git a/phpBB/includes/ucp/info/ucp_main.php b/phpBB/includes/ucp/info/ucp_main.php index e40a0cc1c5..ab504db39c 100644 --- a/phpBB/includes/ucp/info/ucp_main.php +++ b/phpBB/includes/ucp/info/ucp_main.php @@ -17,7 +17,6 @@ class ucp_main_info return array( 'filename' => 'ucp_main', 'title' => 'UCP_MAIN', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'UCP_MAIN_FRONT', 'auth' => '', 'cat' => array('UCP_MAIN')), 'subscribed' => array('title' => 'UCP_MAIN_SUBSCRIBED', 'auth' => '', 'cat' => array('UCP_MAIN')), diff --git a/phpBB/includes/ucp/info/ucp_notifications.php b/phpBB/includes/ucp/info/ucp_notifications.php index 98d8b9db61..69e3328c77 100644 --- a/phpBB/includes/ucp/info/ucp_notifications.php +++ b/phpBB/includes/ucp/info/ucp_notifications.php @@ -17,7 +17,6 @@ class ucp_notifications_info return array( 'filename' => 'ucp_notifications', 'title' => 'UCP_NOTIFICATION_OPTIONS', - 'version' => '1.0.0', 'modes' => array( 'notification_options' => array('title' => 'UCP_NOTIFICATION_OPTIONS', 'auth' => '', 'cat' => array('UCP_PREFS')), 'notification_list' => array('title' => 'UCP_NOTIFICATION_LIST', 'auth' => '', 'cat' => array('UCP_MAIN')), diff --git a/phpBB/includes/ucp/info/ucp_pm.php b/phpBB/includes/ucp/info/ucp_pm.php index a80de21999..c80ff429aa 100644 --- a/phpBB/includes/ucp/info/ucp_pm.php +++ b/phpBB/includes/ucp/info/ucp_pm.php @@ -16,7 +16,6 @@ class ucp_pm_info return array( 'filename' => 'ucp_pm', 'title' => 'UCP_PM', - 'version' => '1.0.0', 'modes' => array( 'view' => array('title' => 'UCP_PM_VIEW', 'auth' => 'cfg_allow_privmsg', 'display' => false, 'cat' => array('UCP_PM')), 'compose' => array('title' => 'UCP_PM_COMPOSE', 'auth' => 'cfg_allow_privmsg', 'cat' => array('UCP_PM')), diff --git a/phpBB/includes/ucp/info/ucp_prefs.php b/phpBB/includes/ucp/info/ucp_prefs.php index 91fbd7a14c..42b5d45f95 100644 --- a/phpBB/includes/ucp/info/ucp_prefs.php +++ b/phpBB/includes/ucp/info/ucp_prefs.php @@ -17,7 +17,6 @@ class ucp_prefs_info return array( 'filename' => 'ucp_prefs', 'title' => 'UCP_PREFS', - 'version' => '1.0.0', 'modes' => array( 'personal' => array('title' => 'UCP_PREFS_PERSONAL', 'auth' => '', 'cat' => array('UCP_PREFS')), 'post' => array('title' => 'UCP_PREFS_POST', 'auth' => '', 'cat' => array('UCP_PREFS')), diff --git a/phpBB/includes/ucp/info/ucp_profile.php b/phpBB/includes/ucp/info/ucp_profile.php index e974cea713..38b5f74752 100644 --- a/phpBB/includes/ucp/info/ucp_profile.php +++ b/phpBB/includes/ucp/info/ucp_profile.php @@ -17,7 +17,6 @@ class ucp_profile_info return array( 'filename' => 'ucp_profile', 'title' => 'UCP_PROFILE', - 'version' => '1.0.0', 'modes' => array( 'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => 'acl_u_chgprofileinfo', 'cat' => array('UCP_PROFILE')), 'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => 'acl_u_sig', 'cat' => array('UCP_PROFILE')), diff --git a/phpBB/includes/ucp/info/ucp_zebra.php b/phpBB/includes/ucp/info/ucp_zebra.php index db57102aae..202769f77a 100644 --- a/phpBB/includes/ucp/info/ucp_zebra.php +++ b/phpBB/includes/ucp/info/ucp_zebra.php @@ -17,7 +17,6 @@ class ucp_zebra_info return array( 'filename' => 'ucp_zebra', 'title' => 'UCP_ZEBRA', - 'version' => '1.0.0', 'modes' => array( 'friends' => array('title' => 'UCP_ZEBRA_FRIENDS', 'auth' => '', 'cat' => array('UCP_ZEBRA')), 'foes' => array('title' => 'UCP_ZEBRA_FOES', 'auth' => '', 'cat' => array('UCP_ZEBRA')), From a18c293739d00be2ca9bce8b6e0cb367325dee60 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Tue, 20 May 2014 11:37:42 -0700 Subject: [PATCH 0005/1676] [ticket/12564] Remove version definitions from modules in tests PHPBB3-12564 --- tests/extension/ext/vendor2/bar/acp/a_info.php | 1 - tests/extension/ext/vendor2/foo/acp/a_info.php | 1 - tests/extension/ext/vendor2/foo/acp/fail_info.php | 1 - tests/extension/ext/vendor2/foo/mcp/a_info.php | 1 - tests/extension/includes/acp/info/acp_foobar.php | 1 - tests/extension/modules_test.php | 10 ---------- .../functional/fixtures/ext/foo/bar/acp/main_info.php | 1 - .../functional/fixtures/ext/foo/bar/ucp/main_info.php | 1 - 8 files changed, 17 deletions(-) diff --git a/tests/extension/ext/vendor2/bar/acp/a_info.php b/tests/extension/ext/vendor2/bar/acp/a_info.php index 8132df587f..8268006f9f 100644 --- a/tests/extension/ext/vendor2/bar/acp/a_info.php +++ b/tests/extension/ext/vendor2/bar/acp/a_info.php @@ -9,7 +9,6 @@ class a_info return array( 'filename' => 'vendor2\\bar\\acp\\a_module', 'title' => 'Bar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('ACP_MODS')), ), diff --git a/tests/extension/ext/vendor2/foo/acp/a_info.php b/tests/extension/ext/vendor2/foo/acp/a_info.php index e1eaa340b7..48ab4cf8e7 100644 --- a/tests/extension/ext/vendor2/foo/acp/a_info.php +++ b/tests/extension/ext/vendor2/foo/acp/a_info.php @@ -9,7 +9,6 @@ class a_info return array( 'filename' => 'vendor2\\foo\\acp\\a_module', 'title' => 'Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => 'ext_vendor2/foo', 'cat' => array('ACP_MODS')), ), diff --git a/tests/extension/ext/vendor2/foo/acp/fail_info.php b/tests/extension/ext/vendor2/foo/acp/fail_info.php index d9b4353957..78479fee70 100644 --- a/tests/extension/ext/vendor2/foo/acp/fail_info.php +++ b/tests/extension/ext/vendor2/foo/acp/fail_info.php @@ -13,7 +13,6 @@ class foo_info return array( 'filename' => 'vendor2\foo\acp\fail_module', 'title' => 'Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('ACP_MODS')), ), diff --git a/tests/extension/ext/vendor2/foo/mcp/a_info.php b/tests/extension/ext/vendor2/foo/mcp/a_info.php index b5599fde65..2532e44b12 100644 --- a/tests/extension/ext/vendor2/foo/mcp/a_info.php +++ b/tests/extension/ext/vendor2/foo/mcp/a_info.php @@ -9,7 +9,6 @@ class a_info return array( 'filename' => 'vendor2\\foo\\mcp\\a_module', 'title' => 'Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('MCP_MAIN')), ), diff --git a/tests/extension/includes/acp/info/acp_foobar.php b/tests/extension/includes/acp/info/acp_foobar.php index b89cfb9574..bb648e6ee1 100644 --- a/tests/extension/includes/acp/info/acp_foobar.php +++ b/tests/extension/includes/acp/info/acp_foobar.php @@ -17,7 +17,6 @@ class acp_foobar_info return array( 'filename' => 'acp_foobar', 'title' => 'ACP Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'test' => array('title' => 'Test', 'auth' => '', 'cat' => array('ACP_GENERAL')), ), diff --git a/tests/extension/modules_test.php b/tests/extension/modules_test.php index e396b7b73e..0559a7e8a0 100644 --- a/tests/extension/modules_test.php +++ b/tests/extension/modules_test.php @@ -58,7 +58,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'vendor2\\foo\\acp\\a_module' => array( 'filename' => 'vendor2\\foo\\acp\\a_module', 'title' => 'Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => 'ext_vendor2/foo', 'cat' => array('ACP_MODS')), ), @@ -66,7 +65,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'acp_foobar' => array( 'filename' => 'acp_foobar', 'title' => 'ACP Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'test' => array('title' => 'Test', 'auth' => '', 'cat' => array('ACP_GENERAL')), ), @@ -80,7 +78,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'vendor2\\foo\\mcp\\a_module' => array( 'filename' => 'vendor2\\foo\\mcp\\a_module', 'title' => 'Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('MCP_MAIN')), ), @@ -94,7 +91,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'vendor2\\foo\\mcp\\a_module' => array( 'filename' => 'vendor2\\foo\\mcp\\a_module', 'title' => 'Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('MCP_MAIN')), ), @@ -108,7 +104,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'vendor2\\foo\\mcp\\a_module' => array( 'filename' => 'vendor2\\foo\\mcp\\a_module', 'title' => 'Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('MCP_MAIN')), ), @@ -132,7 +127,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'vendor2\\foo\\acp\\a_module' => array ( 'filename' => 'vendor2\\foo\\acp\\a_module', 'title' => 'Foobar', - 'version' => '3.1.0-dev', 'modes' => array ( 'config' => array ('title' => 'Config', 'auth' => 'ext_vendor2/foo', 'cat' => array ('ACP_MODS')), ), @@ -156,7 +150,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'vendor2\\foo\\acp\\a_module' => array( 'filename' => 'vendor2\\foo\\acp\\a_module', 'title' => 'Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => 'ext_vendor2/foo', 'cat' => array('ACP_MODS')), ), @@ -164,7 +157,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'acp_foobar' => array( 'filename' => 'acp_foobar', 'title' => 'ACP Foobar', - 'version' => '3.1.0-dev', 'modes' => array( 'test' => array('title' => 'Test', 'auth' => '', 'cat' => array('ACP_GENERAL')), ), @@ -172,7 +164,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'vendor2\\bar\\acp\\a_module' => array( 'filename' => 'vendor2\\bar\\acp\\a_module', 'title' => 'Bar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('ACP_MODS')), ), @@ -185,7 +176,6 @@ class phpbb_extension_modules_test extends phpbb_test_case 'vendor2\\bar\\acp\\a_module' => array( 'filename' => 'vendor2\\bar\\acp\\a_module', 'title' => 'Bar', - 'version' => '3.1.0-dev', 'modes' => array( 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('ACP_MODS')), ), diff --git a/tests/functional/fixtures/ext/foo/bar/acp/main_info.php b/tests/functional/fixtures/ext/foo/bar/acp/main_info.php index 2ad6d08503..c6d801881f 100644 --- a/tests/functional/fixtures/ext/foo/bar/acp/main_info.php +++ b/tests/functional/fixtures/ext/foo/bar/acp/main_info.php @@ -25,7 +25,6 @@ class main_info return array( 'filename' => 'foo\bar\acp\main_module', 'title' => 'ACP_FOOBAR_TITLE', - 'version' => '1.0.0', 'modes' => array( 'mode' => array('title' => 'ACP_FOOBAR_MODE', 'auth' => '', 'cat' => array('ACP_FOOBAR_TITLE')), ), diff --git a/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php b/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php index 2ba37f3050..fdf9cc3241 100644 --- a/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php +++ b/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php @@ -17,7 +17,6 @@ class main_info return array( 'filename' => '\foo\bar\ucp\main_module', 'title' => 'ACP_FOOBAR_TITLE', - 'version' => '1.0.0', 'modes' => array( 'mode' => array('title' => 'ACP_FOOBAR_MODE', 'auth' => '', 'cat' => array('ACP_FOOBAR_TITLE')), ), From 084875f3434b19264d841a8521fced1718efc946 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sat, 7 Jun 2014 03:28:44 +0200 Subject: [PATCH 0006/1676] [ticket/12516] Always preview signature in UCP/ACP module PHPBB3-12516 --- phpBB/includes/acp/acp_users.php | 75 ++++++++++---------- phpBB/includes/ucp/ucp_profile.php | 108 ++++++++++++++--------------- 2 files changed, 86 insertions(+), 97 deletions(-) diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index b653ddd13b..8d506fe6e0 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -1901,50 +1901,54 @@ class acp_users case 'sig': - include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx); - $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $this->optionget($user_row, 'sig_bbcode') : false; - $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $this->optionget($user_row, 'sig_smilies') : false; - $enable_urls = ($config['allow_sig_links']) ? (bool) $this->optionget($user_row, 'sig_links') : false; - $signature = utf8_normalize_nfc(request_var('signature', (string) $user_row['user_sig'], true)); + $enable_bbcode = ($config['allow_sig_bbcode']) ? $this->optionget($user_row, 'sig_bbcode') : false; + $enable_smilies = ($config['allow_sig_smilies']) ? $this->optionget($user_row, 'sig_smilies') : false; + $enable_urls = ($config['allow_sig_links']) ? $this->optionget($user_row, 'sig_links') : false; - $preview = (isset($_POST['preview'])) ? true : false; + $decoded_message = generate_text_for_edit($user_row['user_sig'], $user_row['user_sig_bbcode_uid'], $user_row['user_sig_bbcode_bitfield']); + $signature = $request->variable('signature', $decoded_message['text'], true); + $signature_preview = ''; - if ($submit || $preview) + if ($submit || $request->is_set_post('preview')) { - include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx); - - $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false; - $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false; - $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false; - - $message_parser = new parse_message($signature); - - // Allowing Quote BBCode - $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig'); - - if (sizeof($message_parser->warn_msg)) - { - $error[] = implode('
', $message_parser->warn_msg); - } + $enable_bbcode = ($config['allow_sig_bbcode']) ? !$request->variable('disable_bbcode', false) : false; + $enable_smilies = ($config['allow_sig_smilies']) ? !$request->variable('disable_smilies', false) : false; + $enable_urls = ($config['allow_sig_links']) ? !$request->variable('disable_magic_url', false) : false; if (!check_form_key($form_name)) { - $error = 'FORM_INVALID'; + $error[] = 'FORM_INVALID'; } + } - if (!sizeof($error) && $submit) + $bbcode_uid = $bbcode_bitfield = $bbcode_flags = ''; + $warn_msg = generate_text_for_storage($signature, $bbcode_uid, $bbcode_bitfield, $bbcode_flags, $enable_bbcode, $enable_urls, $enable_smilies); + + if (sizeof($warn_msg)) + { + $error += $warn_msg; + } + + if (!$submit) + { + // Parse it for displaying + $signature_preview = generate_text_for_display($signature, $bbcode_uid, $bbcode_bitfield, $bbcode_flags); + } + else + { + if (!sizeof($error)) { $this->optionset($user_row, 'sig_bbcode', $enable_bbcode); $this->optionset($user_row, 'sig_smilies', $enable_smilies); $this->optionset($user_row, 'sig_links', $enable_urls); $sql_ary = array( - 'user_sig' => (string) $message_parser->message, + 'user_sig' => $signature, 'user_options' => $user_row['user_options'], - 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid, - 'user_sig_bbcode_bitfield' => (string) $message_parser->bbcode_bitfield + 'user_sig_bbcode_uid' => $bbcode_uid, + 'user_sig_bbcode_bitfield' => $bbcode_bitfield, ); $sql = 'UPDATE ' . USERS_TABLE . ' @@ -1954,26 +1958,17 @@ class acp_users trigger_error($user->lang['USER_SIG_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } - - // Replace "error" strings with their real, localised form - $error = array_map(array($user, 'lang'), $error); } - $signature_preview = ''; + // Replace "error" strings with their real, localised form + $error = array_map(array($user, 'lang'), $error); - if ($preview) - { - // Now parse it for displaying - $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); - unset($message_parser); - } - - decode_message($signature, $user_row['user_sig_bbcode_uid']); + $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield); $template->assign_vars(array( 'S_SIGNATURE' => true, - 'SIGNATURE' => $signature, + 'SIGNATURE' => $decoded_message['text'], 'SIGNATURE_PREVIEW' => $signature_preview, 'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '', diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index c7ed12f4ee..48c98c9bcd 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -36,7 +36,6 @@ class ucp_profile $user->add_lang('posting'); - $preview = $request->variable('preview', false, false, \phpbb\request\request_interface::POST); $submit = $request->variable('submit', false, false, \phpbb\request\request_interface::POST); $delete = $request->variable('delete', false, false, \phpbb\request\request_interface::POST); $error = $data = array(); @@ -414,79 +413,72 @@ class ucp_profile include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $user->optionget('sig_bbcode') : false; - $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $user->optionget('sig_smilies') : false; - $enable_urls = ($config['allow_sig_links']) ? (bool) $user->optionget('sig_links') : false; + $enable_bbcode = ($config['allow_sig_bbcode']) ? $user->optionget('sig_bbcode') : false; + $enable_smilies = ($config['allow_sig_smilies']) ? $user->optionget('sig_smilies') : false; + $enable_urls = ($config['allow_sig_links']) ? $user->optionget('sig_links') : false; - $signature = utf8_normalize_nfc(request_var('signature', (string) $user->data['user_sig'], true)); + $decoded_message = generate_text_for_edit($user->data['user_sig'], $user->data['user_sig_bbcode_uid'], $user->data['user_sig_bbcode_bitfield']); + $signature = $request->variable('signature', $decoded_message['text'], true); + $signature_preview = ''; - add_form_key('ucp_sig'); - - if ($submit || $preview) + if ($submit || $request->is_set_post('preview')) { - include($phpbb_root_path . 'includes/message_parser.' . $phpEx); + $enable_bbcode = ($config['allow_sig_bbcode']) ? !$request->variable('disable_bbcode', false) : false; + $enable_smilies = ($config['allow_sig_smilies']) ? !$request->variable('disable_smilies', false) : false; + $enable_urls = ($config['allow_sig_links']) ? !$request->variable('disable_magic_url', false) : false; - $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false; - $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false; - $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false; + if (!check_form_key('ucp_sig')) + { + $error[] = 'FORM_INVALID'; + } + } + $bbcode_uid = $bbcode_bitfield = $bbcode_flags = ''; + $warn_msg = generate_text_for_storage($signature, $bbcode_uid, $bbcode_bitfield, $bbcode_flags, $enable_bbcode, $enable_urls, $enable_smilies); + + if (sizeof($warn_msg)) + { + $error += $warn_msg; + } + + if (!$submit) + { + // Parse it for displaying + $signature_preview = generate_text_for_display($signature, $bbcode_uid, $bbcode_bitfield, $bbcode_flags); + } + else + { if (!sizeof($error)) { - $message_parser = new parse_message($signature); + $user->optionset('sig_bbcode', $enable_bbcode); + $user->optionset('sig_smilies', $enable_smilies); + $user->optionset('sig_links', $enable_urls); - // Allowing Quote BBCode - $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig'); + $sql_ary = array( + 'user_sig' => $signature, + 'user_options' => $user->data['user_options'], + 'user_sig_bbcode_uid' => $bbcode_uid, + 'user_sig_bbcode_bitfield' => $bbcode_bitfield + ); - if (sizeof($message_parser->warn_msg)) - { - $error[] = implode('
', $message_parser->warn_msg); - } + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); - if (!check_form_key('ucp_sig')) - { - $error[] = 'FORM_INVALID'; - } - - if (!sizeof($error) && $submit) - { - $user->optionset('sig_bbcode', $enable_bbcode); - $user->optionset('sig_smilies', $enable_smilies); - $user->optionset('sig_links', $enable_urls); - - $sql_ary = array( - 'user_sig' => (string) $message_parser->message, - 'user_options' => $user->data['user_options'], - 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid, - 'user_sig_bbcode_bitfield' => $message_parser->bbcode_bitfield - ); - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE user_id = ' . $user->data['user_id']; - $db->sql_query($sql); - - $message = $user->lang['PROFILE_UPDATED'] . '

' . sprintf($user->lang['RETURN_UCP'], '', ''); - trigger_error($message); - } + $message = $user->lang['PROFILE_UPDATED'] . '

' . sprintf($user->lang['RETURN_UCP'], '', ''); + trigger_error($message); } - - // Replace "error" strings with their real, localised form - $error = array_map(array($user, 'lang'), $error); } - $signature_preview = ''; - if ($preview) - { - // Now parse it for displaying - $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); - unset($message_parser); - } + // Replace "error" strings with their real, localised form + $error = array_map(array($user, 'lang'), $error); - decode_message($signature, $user->data['user_sig_bbcode_uid']); + $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield); $template->assign_vars(array( 'ERROR' => (sizeof($error)) ? implode('
', $error) : '', - 'SIGNATURE' => $signature, + 'SIGNATURE' => $decoded_message['text'], 'SIGNATURE_PREVIEW' => $signature_preview, 'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '', @@ -509,6 +501,8 @@ class ucp_profile 'S_LINKS_ALLOWED' => ($config['allow_sig_links']) ? true : false) ); + add_form_key('ucp_sig'); + // Build custom bbcodes array display_custom_bbcodes(); From 2276c1c0f246a39dee8d0e979c89e8de0ee7a5de Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 22 Jun 2014 18:08:38 +0200 Subject: [PATCH 0007/1676] [ticket/12387] Cleanup *_free_result call and remove @ on that call PHPBB3-12387 --- phpBB/phpbb/db/driver/driver.php | 8 ++-- phpBB/phpbb/db/driver/mssql.php | 44 ++++++++++++-------- phpBB/phpbb/db/driver/mssql_odbc.php | 30 +++++++++----- phpBB/phpbb/db/driver/mssqlnative.php | 32 +++++++++------ phpBB/phpbb/db/driver/mysql.php | 56 ++++++++++++++++--------- phpBB/phpbb/db/driver/mysqli.php | 44 ++++++++++++-------- phpBB/phpbb/db/driver/oracle.php | 59 +++++++++++++++++---------- phpBB/phpbb/db/driver/postgres.php | 45 ++++++++++++-------- phpBB/phpbb/db/driver/sqlite.php | 36 +++++++++------- phpBB/phpbb/db/driver/sqlite3.php | 14 +++++-- 10 files changed, 231 insertions(+), 137 deletions(-) diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 3d4aa95606..3c23f8fa36 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -175,7 +175,7 @@ abstract class driver implements driver_interface $query_id = $this->query_result; } - if ($query_id !== false) + if ($query_id) { $result = array(); while ($row = $this->sql_fetchrow($query_id)) @@ -206,7 +206,7 @@ abstract class driver implements driver_interface return $cache->sql_rowseek($rownum, $query_id); } - if ($query_id === false) + if (!$query_id) { return false; } @@ -214,7 +214,7 @@ abstract class driver implements driver_interface $this->sql_freeresult($query_id); $query_id = $this->sql_query($this->last_query_text); - if ($query_id === false) + if (!$query_id) { return false; } @@ -243,7 +243,7 @@ abstract class driver implements driver_interface $query_id = $this->query_result; } - if ($query_id !== false) + if ($query_id) { if ($rownum !== false) { diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 2e56638617..14a9fd938c 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -71,8 +71,8 @@ class mssql extends \phpbb\db\driver\driver $row = false; if ($result_id) { - $row = @mssql_fetch_assoc($result_id); - @mssql_free_result($result_id); + $row = mssql_fetch_assoc($result_id); + mssql_free_result($result_id); } $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0; @@ -153,6 +153,11 @@ class mssql extends \phpbb\db\driver\driver $this->sql_report('stop', $query); } + if (!$this->query_result) + { + return false; + } + if ($cache && $cache_ttl) { $this->open_queries[(int) $this->query_result] = $this->query_result; @@ -233,12 +238,12 @@ class mssql extends \phpbb\db\driver\driver return $cache->sql_fetchrow($query_id); } - if ($query_id === false) + if (!$query_id) { return false; } - $row = @mssql_fetch_assoc($query_id); + $row = mssql_fetch_assoc($query_id); // I hope i am able to remove this later... hopefully only a PHP or MSSQL bug if ($row) @@ -269,7 +274,7 @@ class mssql extends \phpbb\db\driver\driver return $cache->sql_rowseek($rownum, $query_id); } - return ($query_id !== false) ? @mssql_data_seek($query_id, $rownum) : false; + return ($query_id) ? @mssql_data_seek($query_id, $rownum) : false; } /** @@ -280,12 +285,12 @@ class mssql extends \phpbb\db\driver\driver $result_id = @mssql_query('SELECT SCOPE_IDENTITY()', $this->db_connect_id); if ($result_id) { - if ($row = @mssql_fetch_assoc($result_id)) + if ($row = mssql_fetch_assoc($result_id)) { - @mssql_free_result($result_id); + mssql_free_result($result_id); return $row['computed']; } - @mssql_free_result($result_id); + mssql_free_result($result_id); } return false; @@ -311,7 +316,7 @@ class mssql extends \phpbb\db\driver\driver if (isset($this->open_queries[(int) $query_id])) { unset($this->open_queries[(int) $query_id]); - return @mssql_free_result($query_id); + return mssql_free_result($query_id); } return false; @@ -359,9 +364,9 @@ class mssql extends \phpbb\db\driver\driver $result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id); if ($result_id) { - $row = @mssql_fetch_assoc($result_id); + $row = mssql_fetch_assoc($result_id); $error['code'] = $row['code']; - @mssql_free_result($result_id); + mssql_free_result($result_id); } // Get full error message if possible @@ -372,12 +377,12 @@ class mssql extends \phpbb\db\driver\driver if ($result_id) { - $row = @mssql_fetch_assoc($result_id); + $row = mssql_fetch_assoc($result_id); if (!empty($row['message'])) { $error['message'] .= '
' . $row['message']; } - @mssql_free_result($result_id); + mssql_free_result($result_id); } } else @@ -423,13 +428,13 @@ class mssql extends \phpbb\db\driver\driver if ($result = @mssql_query($query, $this->db_connect_id)) { @mssql_next_result($result); - while ($row = @mssql_fetch_row($result)) + while ($row = mssql_fetch_row($result)) { $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); } } @mssql_query('SET SHOWPLAN_TEXT OFF;', $this->db_connect_id); - @mssql_free_result($result); + mssql_free_result($result); if ($html_table) { @@ -442,11 +447,14 @@ class mssql extends \phpbb\db\driver\driver $endtime = $endtime[0] + $endtime[1]; $result = @mssql_query($query, $this->db_connect_id); - while ($void = @mssql_fetch_assoc($result)) + if ($result) { - // Take the time spent on parsing rows into account + while ($void = mssql_fetch_assoc($result)) + { + // Take the time spent on parsing rows into account + } + mssql_free_result($result); } - @mssql_free_result($result); $splittime = explode(' ', microtime()); $splittime = $splittime[0] + $splittime[1]; diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index de90d878e7..847cdeb188 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -98,8 +98,8 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base $row = false; if ($result_id) { - $row = @odbc_fetch_array($result_id); - @odbc_free_result($result_id); + $row = odbc_fetch_array($result_id); + odbc_free_result($result_id); } $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0; @@ -173,6 +173,11 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base $this->sql_report('stop', $query); } + if (!$this->query_result) + { + return false; + } + if ($cache && $cache_ttl) { $this->open_queries[(int) $this->query_result] = $this->query_result; @@ -253,7 +258,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base return $cache->sql_fetchrow($query_id); } - return ($query_id !== false) ? @odbc_fetch_array($query_id) : false; + return ($query_id) ? odbc_fetch_array($query_id) : false; } /** @@ -265,13 +270,13 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base if ($result_id) { - if (@odbc_fetch_array($result_id)) + if (odbc_fetch_array($result_id)) { - $id = @odbc_result($result_id, 1); - @odbc_free_result($result_id); + $id = odbc_result($result_id, 1); + odbc_free_result($result_id); return $id; } - @odbc_free_result($result_id); + odbc_free_result($result_id); } return false; @@ -297,7 +302,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base if (isset($this->open_queries[(int) $query_id])) { unset($this->open_queries[(int) $query_id]); - return @odbc_free_result($query_id); + return odbc_free_result($query_id); } return false; @@ -352,11 +357,14 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base $endtime = $endtime[0] + $endtime[1]; $result = @odbc_exec($this->db_connect_id, $query); - while ($void = @odbc_fetch_array($result)) + if ($result) { - // Take the time spent on parsing rows into account + while ($void = odbc_fetch_array($result)) + { + // Take the time spent on parsing rows into account + } + odbc_free_result($result); } - @odbc_free_result($result); $splittime = explode(' ', microtime()); $splittime = $splittime[0] + $splittime[1]; diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index a7f93c8feb..fbf37cbff2 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -146,6 +146,11 @@ class mssqlnative extends \phpbb\db\driver\mssql_base $this->sql_report('stop', $query); } + if (!$this->query_result) + { + return false; + } + if ($cache && $cache_ttl) { $this->open_queries[(int) $this->query_result] = $this->query_result; @@ -234,12 +239,12 @@ class mssqlnative extends \phpbb\db\driver\mssql_base return $cache->sql_fetchrow($query_id); } - if ($query_id === false) + if (!$query_id) { return false; } - $row = @sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC); + $row = sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC); if ($row) { @@ -264,11 +269,11 @@ class mssqlnative extends \phpbb\db\driver\mssql_base { $result_id = @sqlsrv_query($this->db_connect_id, 'SELECT @@IDENTITY'); - if ($result_id !== false) + if ($result_id) { - $row = @sqlsrv_fetch_array($result_id); + $row = sqlsrv_fetch_array($result_id); $id = $row[0]; - @sqlsrv_free_stmt($result_id); + sqlsrv_free_stmt($result_id); return $id; } else @@ -297,7 +302,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base if (isset($this->open_queries[(int) $query_id])) { unset($this->open_queries[(int) $query_id]); - return @sqlsrv_free_stmt($query_id); + return sqlsrv_free_stmt($query_id); } return false; @@ -370,14 +375,14 @@ class mssqlnative extends \phpbb\db\driver\mssql_base @sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT ON;'); if ($result = @sqlsrv_query($this->db_connect_id, $query)) { - @sqlsrv_next_result($result); - while ($row = @sqlsrv_fetch_array($result)) + sqlsrv_next_result($result); + while ($row = sqlsrv_fetch_array($result)) { $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); } + sqlsrv_free_stmt($result); } @sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT OFF;'); - @sqlsrv_free_stmt($result); if ($html_table) { @@ -390,11 +395,14 @@ class mssqlnative extends \phpbb\db\driver\mssql_base $endtime = $endtime[0] + $endtime[1]; $result = @sqlsrv_query($this->db_connect_id, $query); - while ($void = @sqlsrv_fetch_array($result)) + if ($result) { - // Take the time spent on parsing rows into account + while ($void = sqlsrv_fetch_array($result)) + { + // Take the time spent on parsing rows into account + } + sqlsrv_free_stmt($result); } - @sqlsrv_free_stmt($result); $splittime = explode(' ', microtime()); $splittime = $splittime[0] + $splittime[1]; diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index 569bd4f10a..50bb8204a8 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -70,9 +70,16 @@ class mysql extends \phpbb\db\driver\mysql_base if (version_compare($this->sql_server_info(true), '5.0.2', '>=')) { $result = @mysql_query('SELECT @@session.sql_mode AS sql_mode', $this->db_connect_id); - $row = @mysql_fetch_assoc($result); - @mysql_free_result($result); - $modes = array_map('trim', explode(',', $row['sql_mode'])); + if ($result) + { + $row = mysql_fetch_assoc($result); + mysql_free_result($result); + $modes = array_map('trim', explode(',', $row['sql_mode'])); + } + else + { + $modes = array(); + } // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES if (!in_array('TRADITIONAL', $modes)) @@ -114,14 +121,17 @@ class mysql extends \phpbb\db\driver\mysql_base if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mysql_version')) === false) { $result = @mysql_query('SELECT VERSION() AS version', $this->db_connect_id); - $row = @mysql_fetch_assoc($result); - @mysql_free_result($result); - - $this->sql_server_version = $row['version']; - - if (!empty($cache) && $use_cache) + if ($result) { - $cache->put('mysql_version', $this->sql_server_version); + $row = mysql_fetch_assoc($result); + mysql_free_result($result); + + $this->sql_server_version = $row['version']; + + if (!empty($cache) && $use_cache) + { + $cache->put('mysql_version', $this->sql_server_version); + } } } @@ -182,6 +192,11 @@ class mysql extends \phpbb\db\driver\mysql_base $this->sql_report('stop', $query); } + if (!$this->query_result) + { + return false; + } + if ($cache && $cache_ttl) { $this->open_queries[(int) $this->query_result] = $this->query_result; @@ -249,7 +264,7 @@ class mysql extends \phpbb\db\driver\mysql_base return $cache->sql_fetchrow($query_id); } - return ($query_id !== false) ? @mysql_fetch_assoc($query_id) : false; + return ($query_id) ? mysql_fetch_assoc($query_id) : false; } /** @@ -300,7 +315,7 @@ class mysql extends \phpbb\db\driver\mysql_base if (isset($this->open_queries[(int) $query_id])) { unset($this->open_queries[(int) $query_id]); - return @mysql_free_result($query_id); + return mysql_free_result($query_id); } return false; @@ -403,12 +418,12 @@ class mysql extends \phpbb\db\driver\mysql_base if ($result = @mysql_query("EXPLAIN $explain_query", $this->db_connect_id)) { - while ($row = @mysql_fetch_assoc($result)) + while ($row = mysql_fetch_assoc($result)) { $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); } + mysql_free_result($result); } - @mysql_free_result($result); if ($html_table) { @@ -423,7 +438,7 @@ class mysql extends \phpbb\db\driver\mysql_base if ($result = @mysql_query('SHOW PROFILE ALL;', $this->db_connect_id)) { $this->html_hold .= '
'; - while ($row = @mysql_fetch_assoc($result)) + while ($row = mysql_fetch_assoc($result)) { // make HTML safe if (!empty($row['Source_function'])) @@ -441,8 +456,8 @@ class mysql extends \phpbb\db\driver\mysql_base } $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); } + mysql_free_result($result); } - @mysql_free_result($result); if ($html_table) { @@ -460,11 +475,14 @@ class mysql extends \phpbb\db\driver\mysql_base $endtime = $endtime[0] + $endtime[1]; $result = @mysql_query($query, $this->db_connect_id); - while ($void = @mysql_fetch_assoc($result)) + if ($result) { - // Take the time spent on parsing rows into account + while ($void = mysql_fetch_assoc($result)) + { + // Take the time spent on parsing rows into account + } + mysql_free_result($result); } - @mysql_free_result($result); $splittime = explode(' ', microtime()); $splittime = $splittime[0] + $splittime[1]; diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 520bb65b67..410d84c1df 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -71,9 +71,10 @@ class mysqli extends \phpbb\db\driver\mysql_base if (version_compare($this->sql_server_info(true), '5.0.2', '>=')) { $result = @mysqli_query($this->db_connect_id, 'SELECT @@session.sql_mode AS sql_mode'); - if ($result !== null) + if ($result) { - $row = @mysqli_fetch_assoc($result); + $row = mysqli_fetch_assoc($result); + mysqli_free_result($result); $modes = array_map('trim', explode(',', $row['sql_mode'])); } @@ -81,7 +82,6 @@ class mysqli extends \phpbb\db\driver\mysql_base { $modes = array(); } - @mysqli_free_result($result); // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES if (!in_array('TRADITIONAL', $modes)) @@ -116,9 +116,10 @@ class mysqli extends \phpbb\db\driver\mysql_base if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mysqli_version')) === false) { $result = @mysqli_query($this->db_connect_id, 'SELECT VERSION() AS version'); - if ($result !== null) + if ($result) { - $row = @mysqli_fetch_assoc($result); + $row = mysqli_fetch_assoc($result); + mysqli_free_result($result); $this->sql_server_version = $row['version']; @@ -127,7 +128,6 @@ class mysqli extends \phpbb\db\driver\mysql_base $cache->put('mysqli_version', $this->sql_server_version); } } - @mysqli_free_result($result); } return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version; @@ -191,6 +191,11 @@ class mysqli extends \phpbb\db\driver\mysql_base $this->sql_report('stop', $query); } + if (!$this->query_result) + { + return false; + } + if ($cache && $cache_ttl) { $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); @@ -234,9 +239,9 @@ class mysqli extends \phpbb\db\driver\mysql_base return $cache->sql_fetchrow($query_id); } - if ($query_id !== false && $query_id !== null) + if ($query_id) { - $result = @mysqli_fetch_assoc($query_id); + $result = mysqli_fetch_assoc($query_id); return $result !== null ? $result : false; } @@ -260,7 +265,7 @@ class mysqli extends \phpbb\db\driver\mysql_base return $cache->sql_rowseek($rownum, $query_id); } - return ($query_id !== false) ? @mysqli_data_seek($query_id, $rownum) : false; + return ($query_id) ? @mysqli_data_seek($query_id, $rownum) : false; } /** @@ -288,7 +293,12 @@ class mysqli extends \phpbb\db\driver\mysql_base return $cache->sql_freeresult($query_id); } - return @mysqli_free_result($query_id); + if (!$this->query_result) + { + return false; + } + + return mysqli_free_result($query_id); } /** @@ -387,12 +397,12 @@ class mysqli extends \phpbb\db\driver\mysql_base if ($result = @mysqli_query($this->db_connect_id, "EXPLAIN $explain_query")) { - while ($row = @mysqli_fetch_assoc($result)) + while ($row = mysqli_fetch_assoc($result)) { $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); } + mysqli_free_result($result); } - @mysqli_free_result($result); if ($html_table) { @@ -407,7 +417,7 @@ class mysqli extends \phpbb\db\driver\mysql_base if ($result = @mysqli_query($this->db_connect_id, 'SHOW PROFILE ALL;')) { $this->html_hold .= '
'; - while ($row = @mysqli_fetch_assoc($result)) + while ($row = mysqli_fetch_assoc($result)) { // make HTML safe if (!empty($row['Source_function'])) @@ -425,8 +435,8 @@ class mysqli extends \phpbb\db\driver\mysql_base } $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); } + mysqli_free_result($result); } - @mysqli_free_result($result); if ($html_table) { @@ -444,14 +454,14 @@ class mysqli extends \phpbb\db\driver\mysql_base $endtime = $endtime[0] + $endtime[1]; $result = @mysqli_query($this->db_connect_id, $query); - if ($result !== null) + if ($result) { - while ($void = @mysqli_fetch_assoc($result)) + while ($void = mysqli_fetch_assoc($result)) { // Take the time spent on parsing rows into account } + mysqli_free_result($result); } - @mysqli_free_result($result); $splittime = explode(' ', microtime()); $splittime = $splittime[0] + $splittime[1]; diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index bfc5373e35..0dfd8484ee 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -431,6 +431,11 @@ class oracle extends \phpbb\db\driver\driver $this->sql_report('stop', $query); } + if (!$this->query_result) + { + return false; + } + if ($cache && $cache_ttl) { $this->open_queries[(int) $this->query_result] = $this->query_result; @@ -491,10 +496,10 @@ class oracle extends \phpbb\db\driver\driver return $cache->sql_fetchrow($query_id); } - if ($query_id !== false) + if ($query_id) { $row = array(); - $result = @ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS); + $result = ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS); if (!$result || !$row) { @@ -542,7 +547,7 @@ class oracle extends \phpbb\db\driver\driver return $cache->sql_rowseek($rownum, $query_id); } - if ($query_id === false) + if (!$query_id) { return false; } @@ -575,18 +580,24 @@ class oracle extends \phpbb\db\driver\driver { $query = 'SELECT ' . $tablename[1] . '_seq.currval FROM DUAL'; $stmt = @ociparse($this->db_connect_id, $query); - @ociexecute($stmt, OCI_DEFAULT); - - $temp_result = @ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS); - @ocifreestatement($stmt); - - if ($temp_result) + if ($stmt) { - return $temp_array['CURRVAL']; - } - else - { - return false; + $success = @ociexecute($stmt, OCI_DEFAULT); + + if ($success) + { + $temp_result = ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS); + ocifreestatement($stmt); + + if ($temp_result) + { + return $temp_array['CURRVAL']; + } + else + { + return false; + } + } } } } @@ -614,7 +625,7 @@ class oracle extends \phpbb\db\driver\driver if (isset($this->open_queries[(int) $query_id])) { unset($this->open_queries[(int) $query_id]); - return @ocifreestatement($query_id); + return ocifreestatement($query_id); } return false; @@ -770,14 +781,20 @@ class oracle extends \phpbb\db\driver\driver $endtime = $endtime[0] + $endtime[1]; $result = @ociparse($this->db_connect_id, $query); - $success = @ociexecute($result, OCI_DEFAULT); - $row = array(); - - while (@ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS)) + if ($result) { - // Take the time spent on parsing rows into account + $success = @ociexecute($result, OCI_DEFAULT); + if ($success) + { + $row = array(); + + while (ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS)) + { + // Take the time spent on parsing rows into account + } + @ocifreestatement($result); + } } - @ocifreestatement($result); $splittime = explode(' ', microtime()); $splittime = $splittime[0] + $splittime[1]; diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index a4aa9497ed..3fade46bdd 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -127,14 +127,17 @@ class postgres extends \phpbb\db\driver\driver if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('pgsql_version')) === false) { $query_id = @pg_query($this->db_connect_id, 'SELECT VERSION() AS version'); - $row = @pg_fetch_assoc($query_id, null); - @pg_free_result($query_id); - - $this->sql_server_version = (!empty($row['version'])) ? trim(substr($row['version'], 10)) : 0; - - if (!empty($cache) && $use_cache) + if ($query_id) { - $cache->put('pgsql_version', $this->sql_server_version); + $row = pg_fetch_assoc($query_id, null); + pg_free_result($query_id); + + $this->sql_server_version = (!empty($row['version'])) ? trim(substr($row['version'], 10)) : 0; + + if (!empty($cache) && $use_cache) + { + $cache->put('pgsql_version', $this->sql_server_version); + } } } @@ -196,6 +199,11 @@ class postgres extends \phpbb\db\driver\driver $this->sql_report('stop', $query); } + if (!$this->query_result) + { + return false; + } + if ($cache && $cache_ttl) { $this->open_queries[(int) $this->query_result] = $this->query_result; @@ -271,7 +279,7 @@ class postgres extends \phpbb\db\driver\driver return $cache->sql_fetchrow($query_id); } - return ($query_id !== false) ? @pg_fetch_assoc($query_id, null) : false; + return ($query_id) ? pg_fetch_assoc($query_id, null) : false; } /** @@ -291,7 +299,7 @@ class postgres extends \phpbb\db\driver\driver return $cache->sql_rowseek($rownum, $query_id); } - return ($query_id !== false) ? @pg_result_seek($query_id, $rownum) : false; + return ($query_id) ? @pg_result_seek($query_id, $rownum) : false; } /** @@ -313,8 +321,8 @@ class postgres extends \phpbb\db\driver\driver return false; } - $temp_result = @pg_fetch_assoc($temp_q_id, null); - @pg_free_result($query_id); + $temp_result = pg_fetch_assoc($temp_q_id, null); + pg_free_result($query_id); return ($temp_result) ? $temp_result['last_value'] : false; } @@ -343,7 +351,7 @@ class postgres extends \phpbb\db\driver\driver if (isset($this->open_queries[(int) $query_id])) { unset($this->open_queries[(int) $query_id]); - return @pg_free_result($query_id); + return pg_free_result($query_id); } return false; @@ -440,12 +448,12 @@ class postgres extends \phpbb\db\driver\driver if ($result = @pg_query($this->db_connect_id, "EXPLAIN $explain_query")) { - while ($row = @pg_fetch_assoc($result, null)) + while ($row = pg_fetch_assoc($result, null)) { $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); } + pg_free_result($result); } - @pg_free_result($result); if ($html_table) { @@ -460,11 +468,14 @@ class postgres extends \phpbb\db\driver\driver $endtime = $endtime[0] + $endtime[1]; $result = @pg_query($this->db_connect_id, $query); - while ($void = @pg_fetch_assoc($result, null)) + if ($result) { - // Take the time spent on parsing rows into account + while ($void = pg_fetch_assoc($result, null)) + { + // Take the time spent on parsing rows into account + } + pg_free_result($result); } - @pg_free_result($result); $splittime = explode(' ', microtime()); $splittime = $splittime[0] + $splittime[1]; diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index f4c5e240fc..9130b2b292 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -70,13 +70,16 @@ class sqlite extends \phpbb\db\driver\driver if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('sqlite_version')) === false) { $result = @sqlite_query('SELECT sqlite_version() AS version', $this->db_connect_id); - $row = @sqlite_fetch_array($result, SQLITE_ASSOC); - - $this->sql_server_version = (!empty($row['version'])) ? $row['version'] : 0; - - if (!empty($cache) && $use_cache) + if ($result) { - $cache->put('sqlite_version', $this->sql_server_version); + $row = sqlite_fetch_array($result, SQLITE_ASSOC); + + $this->sql_server_version = (!empty($row['version'])) ? $row['version'] : 0; + + if (!empty($cache) && $use_cache) + { + $cache->put('sqlite_version', $this->sql_server_version); + } } } @@ -137,15 +140,15 @@ class sqlite extends \phpbb\db\driver\driver $this->sql_report('stop', $query); } + if (!$this->query_result) + { + return false; + } + if ($cache && $cache_ttl) { - $this->open_queries[(int) $this->query_result] = $this->query_result; $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } - else if (strpos($query, 'SELECT') === 0 && $this->query_result) - { - $this->open_queries[(int) $this->query_result] = $this->query_result; - } } else if (defined('DEBUG')) { @@ -203,7 +206,7 @@ class sqlite extends \phpbb\db\driver\driver return $cache->sql_fetchrow($query_id); } - return ($query_id !== false) ? @sqlite_fetch_array($query_id, SQLITE_ASSOC) : false; + return ($query_id) ? sqlite_fetch_array($query_id, SQLITE_ASSOC) : false; } /** @@ -223,7 +226,7 @@ class sqlite extends \phpbb\db\driver\driver return $cache->sql_rowseek($rownum, $query_id); } - return ($query_id !== false) ? @sqlite_seek($query_id, $rownum) : false; + return ($query_id) ? @sqlite_seek($query_id, $rownum) : false; } /** @@ -337,9 +340,12 @@ class sqlite extends \phpbb\db\driver\driver $endtime = $endtime[0] + $endtime[1]; $result = @sqlite_query($query, $this->db_connect_id); - while ($void = @sqlite_fetch_array($result, SQLITE_ASSOC)) + if ($result) { - // Take the time spent on parsing rows into account + while ($void = sqlite_fetch_array($result, SQLITE_ASSOC)) + { + // Take the time spent on parsing rows into account + } } $splittime = explode(' ', microtime()); diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 2c6bf99497..4ca3d8f91d 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -50,7 +50,7 @@ class sqlite3 extends \phpbb\db\driver\driver $this->dbo = new \SQLite3($this->server, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE); $this->db_connect_id = true; } - catch (Exception $e) + catch (\Exception $e) { return array('message' => $e->getMessage()); } @@ -138,6 +138,11 @@ class sqlite3 extends \phpbb\db\driver\driver $this->sql_report('stop', $query); } + if (!$this->query_result) + { + return false; + } + if ($cache && $cache_ttl) { $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); @@ -362,9 +367,12 @@ class sqlite3 extends \phpbb\db\driver\driver $endtime = $endtime[0] + $endtime[1]; $result = $this->dbo->query($query); - while ($void = $result->fetchArray(SQLITE3_ASSOC)) + if ($result) { - // Take the time spent on parsing rows into account + while ($void = $result->fetchArray(SQLITE3_ASSOC)) + { + // Take the time spent on parsing rows into account + } } $splittime = explode(' ', microtime()); From adba7d471583537fb20c18dca08c571909171aeb Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 22 Jun 2014 19:34:02 +0200 Subject: [PATCH 0008/1676] [ticket/12387] mssql_query return true if a select query returns 0 row PHPBB3-12387 --- phpBB/phpbb/db/driver/mssql.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 14a9fd938c..0809703b48 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -163,7 +163,7 @@ class mssql extends \phpbb\db\driver\driver $this->open_queries[(int) $this->query_result] = $this->query_result; $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } - else if (strpos($query, 'SELECT') === 0 && $this->query_result) + else if (strpos($query, 'SELECT') === 0 && $this->query_result !== true) { $this->open_queries[(int) $this->query_result] = $this->query_result; } @@ -238,7 +238,7 @@ class mssql extends \phpbb\db\driver\driver return $cache->sql_fetchrow($query_id); } - if (!$query_id) + if (!$query_id || $query_id === true) { return false; } @@ -269,6 +269,11 @@ class mssql extends \phpbb\db\driver\driver $query_id = $this->query_result; } + if ($query_id === true) + { + return false; + } + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_rowseek($rownum, $query_id); @@ -308,6 +313,11 @@ class mssql extends \phpbb\db\driver\driver $query_id = $this->query_result; } + if ($query_id === true) + { + return false; + } + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); From 50f4bea6101f64c513b3918ade58a712b00f3df7 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 22 Jun 2014 19:35:07 +0200 Subject: [PATCH 0009/1676] [ticket/12387] Remove unnecessary checks PHPBB3-12387 --- phpBB/phpbb/db/driver/mssql_odbc.php | 2 +- phpBB/phpbb/db/driver/mssqlnative.php | 2 +- phpBB/phpbb/db/driver/mysql.php | 2 +- phpBB/phpbb/db/driver/oracle.php | 2 +- phpBB/phpbb/db/driver/postgres.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index 847cdeb188..0a15148e1d 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -183,7 +183,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base $this->open_queries[(int) $this->query_result] = $this->query_result; $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } - else if (strpos($query, 'SELECT') === 0 && $this->query_result) + else if (strpos($query, 'SELECT') === 0) { $this->open_queries[(int) $this->query_result] = $this->query_result; } diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index fbf37cbff2..3bc9ecda75 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -156,7 +156,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base $this->open_queries[(int) $this->query_result] = $this->query_result; $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } - else if (strpos($query, 'SELECT') === 0 && $this->query_result) + else if (strpos($query, 'SELECT') === 0) { $this->open_queries[(int) $this->query_result] = $this->query_result; } diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index 50bb8204a8..ed8f16fa5f 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -202,7 +202,7 @@ class mysql extends \phpbb\db\driver\mysql_base $this->open_queries[(int) $this->query_result] = $this->query_result; $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } - else if (strpos($query, 'SELECT') === 0 && $this->query_result) + else if (strpos($query, 'SELECT') === 0) { $this->open_queries[(int) $this->query_result] = $this->query_result; } diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index 0dfd8484ee..cacee3ef41 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -441,7 +441,7 @@ class oracle extends \phpbb\db\driver\driver $this->open_queries[(int) $this->query_result] = $this->query_result; $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } - else if (strpos($query, 'SELECT') === 0 && $this->query_result) + else if (strpos($query, 'SELECT') === 0) { $this->open_queries[(int) $this->query_result] = $this->query_result; } diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 3fade46bdd..78825de73c 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -209,7 +209,7 @@ class postgres extends \phpbb\db\driver\driver $this->open_queries[(int) $this->query_result] = $this->query_result; $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } - else if (strpos($query, 'SELECT') === 0 && $this->query_result) + else if (strpos($query, 'SELECT') === 0) { $this->open_queries[(int) $this->query_result] = $this->query_result; } From d039f56af00fb98b2b03f54f00ce4bb1436e9932 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 22 Jun 2014 22:49:33 +0200 Subject: [PATCH 0010/1676] [ticket/12387] Use the hash as query_id for caching PHPBB3-12387 --- phpBB/phpbb/cache/driver/file.php | 8 ++++---- phpBB/phpbb/cache/driver/memory.php | 11 +++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php index b32af32d25..fbd3b571f7 100644 --- a/phpBB/phpbb/cache/driver/file.php +++ b/phpBB/phpbb/cache/driver/file.php @@ -396,13 +396,13 @@ class file extends \phpbb\cache\driver\base { // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); + $query_id = md5($query); - if (($rowset = $this->_read('sql_' . md5($query))) === false) + if (($rowset = $this->_read('sql_' . $query_id)) === false) { return false; } - $query_id = sizeof($this->sql_rowset); $this->sql_rowset[$query_id] = $rowset; $this->sql_row_pointer[$query_id] = 0; @@ -417,7 +417,7 @@ class file extends \phpbb\cache\driver\base // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - $query_id = sizeof($this->sql_rowset); + $query_id = md5($query); $this->sql_rowset[$query_id] = array(); $this->sql_row_pointer[$query_id] = 0; @@ -427,7 +427,7 @@ class file extends \phpbb\cache\driver\base } $db->sql_freeresult($query_result); - if ($this->_write('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl + time(), $query)) + if ($this->_write('sql_' . $query_id, $this->sql_rowset[$query_id], $ttl + time(), $query)) { return $query_id; } diff --git a/phpBB/phpbb/cache/driver/memory.php b/phpBB/phpbb/cache/driver/memory.php index 5dee375192..cb2b6a10a7 100644 --- a/phpBB/phpbb/cache/driver/memory.php +++ b/phpBB/phpbb/cache/driver/memory.php @@ -266,9 +266,9 @@ abstract class memory extends \phpbb\cache\driver\base { // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - $query_id = sizeof($this->sql_rowset); + $query_id = md5($query); - if (($result = $this->_read('sql_' . md5($query))) === false) + if (($result = $this->_read('sql_' . $query_id)) === false) { return false; } @@ -286,7 +286,7 @@ abstract class memory extends \phpbb\cache\driver\base { // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - $hash = md5($query); + $query_id = md5($query); // determine which tables this query belongs to // Some queries use backticks, namely the get_database_size() query @@ -315,14 +315,13 @@ abstract class memory extends \phpbb\cache\driver\base $temp = array(); } - $temp[$hash] = true; + $temp[$query_id] = true; // This must never expire $this->_write('sql_' . $table_name, $temp, 0); } // store them in the right place - $query_id = sizeof($this->sql_rowset); $this->sql_rowset[$query_id] = array(); $this->sql_row_pointer[$query_id] = 0; @@ -332,7 +331,7 @@ abstract class memory extends \phpbb\cache\driver\base } $db->sql_freeresult($query_result); - $this->_write('sql_' . $hash, $this->sql_rowset[$query_id], $ttl); + $this->_write('sql_' . $query_id, $this->sql_rowset[$query_id], $ttl); return $query_id; } From bc3659a1861597b8edd5b9b3789260b93ac3f121 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 22 Jun 2014 23:13:10 +0200 Subject: [PATCH 0011/1676] [ticket/12387] Fix \phpbb\db\driver\mysqli::sql_freeresult PHPBB3-12387 --- phpBB/phpbb/db/driver/mysqli.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 410d84c1df..4c6963673e 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -293,11 +293,16 @@ class mysqli extends \phpbb\db\driver\mysql_base return $cache->sql_freeresult($query_id); } - if (!$this->query_result) + if (!$query_id) { return false; } + if ($query_id === true) + { + return true; + } + return mysqli_free_result($query_id); } From cc32ee8a2848b902f7dc9d809499855a78cb41f4 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 23 Jun 2014 00:31:56 +0200 Subject: [PATCH 0012/1676] [ticket/12387] Fix a call to sql_freeresult in full_text_native PHPBB3-12387 --- phpBB/phpbb/search/fulltext_native.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index f7b1751a51..8d97916ec5 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -848,7 +848,7 @@ class fulltext_native extends \phpbb\search\base $sql_calc = $this->db->sql_build_query('SELECT', $sql_array_copy); unset($sql_array_copy); - $this->db->sql_query($sql_calc); + $result = $this->db->sql_query($sql_calc); $this->db->sql_freeresult($result); $sql_count = 'SELECT FOUND_ROWS() as total_results'; From 192b8e2568f499aa2ead98a24d8dd5541b1f315a Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 2 Aug 2014 19:09:42 +0200 Subject: [PATCH 0013/1676] [ticket/11649] Expose Twig through the container PHPBB3-11649 --- phpBB/config/services.yml | 4 ++ phpBB/config/twig.yml | 36 +++++++++++++++++ phpBB/phpbb/template/twig/environment.php | 30 +++++++++++++- phpBB/phpbb/template/twig/twig.php | 39 +++++------------- tests/controller/helper_route_test.php | 23 ++++++++++- tests/extension/metadata_manager_test.php | 40 +++++++++++++------ tests/template/template_events_test.php | 23 ++++++++++- tests/template/template_test_case.php | 22 +++++++++- .../template/template_test_case_with_tree.php | 22 +++++++++- 9 files changed, 192 insertions(+), 47 deletions(-) create mode 100644 phpBB/config/twig.yml diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index a9f9f5ed19..8caf1af683 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -10,6 +10,7 @@ imports: - { resource: mimetype_guessers.yml } - { resource: passwords.yml } - { resource: profilefields.yml } + - { resource: twig.yml } services: acl.permissions: @@ -339,6 +340,9 @@ services: - @config - @user - @template_context + - @template.twig.environment + - %core.template.cache_path% + - @template.twig.extensions.collection - @ext.manager template_context: diff --git a/phpBB/config/twig.yml b/phpBB/config/twig.yml new file mode 100644 index 0000000000..eb3e6c0924 --- /dev/null +++ b/phpBB/config/twig.yml @@ -0,0 +1,36 @@ +parameters: + core.template.cache_path: %core.root_path%cache/twig/ + +services: + template.twig.environment: + class: phpbb\template\twig\environment + arguments: + - @config + - @path_helper + - @service_container + - %core.template.cache_path% + - @ext.manager + - @template.twig.loader + + template.twig.lexer: + class: phpbb\template\twig\lexer + arguments: + - @template.twig.environment + + template.twig.loader: + class: phpbb\template\twig\loader + + template.twig.extensions.collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: twig.extension } + + template.twig.extensions.phpbb: + class: phpbb\template\twig\extension + arguments: + - @template_context + - @user + tags: + - { name: twig.extension } diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php index 476ffd935e..df586af9e5 100644 --- a/phpBB/phpbb/template/twig/environment.php +++ b/phpBB/phpbb/template/twig/environment.php @@ -13,6 +13,9 @@ namespace phpbb\template\twig; +use Twig_Lexer; +use Twig_LexerInterface; + class environment extends \Twig_Environment { /** @var \phpbb\config\config */ @@ -21,6 +24,9 @@ class environment extends \Twig_Environment /** @var \phpbb\path_helper */ protected $phpbb_path_helper; + /** @var \Symfony\Component\DependencyInjection\ContainerInterface */ + protected $container; + /** @var \phpbb\extension\manager */ protected $extension_manager; @@ -38,23 +44,45 @@ class environment extends \Twig_Environment * * @param \phpbb\config\config $phpbb_config The phpBB configuration * @param \phpbb\path_helper $path_helper phpBB path helper + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container * @param \phpbb\extension\manager $extension_manager phpBB extension manager * @param \Twig_LoaderInterface $loader Twig loader interface * @param array $options Array of options to pass to Twig */ - public function __construct($phpbb_config, \phpbb\path_helper $path_helper, \phpbb\extension\manager $extension_manager = null, \Twig_LoaderInterface $loader = null, $options = array()) + public function __construct($phpbb_config, \phpbb\path_helper $path_helper, \Symfony\Component\DependencyInjection\ContainerInterface $container, $cache_path, \phpbb\extension\manager $extension_manager = null, \Twig_LoaderInterface $loader = null, $options = array()) { $this->phpbb_config = $phpbb_config; $this->phpbb_path_helper = $path_helper; $this->extension_manager = $extension_manager; + $this->container = $container; $this->phpbb_root_path = $this->phpbb_path_helper->get_phpbb_root_path(); $this->web_root_path = $this->phpbb_path_helper->get_web_root_path(); + $options = array_merge(array( + 'cache' => (defined('IN_INSTALL')) ? false : $cache_path, + 'debug' => defined('DEBUG'), + 'auto_reload' => (bool) $this->phpbb_config['load_tplcompile'], + 'autoescape' => false, + ), $options); + return parent::__construct($loader, $options); } + /** + * {@inheritdoc} + */ + public function getLexer() + { + if (null === $this->lexer) { + $this->lexer = $this->container->get('template.twig.lexer'); + } + + return $this->lexer; + } + + /** * Get the list of enabled phpBB extensions * diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php index 5e2057f818..dd6117819a 100644 --- a/phpBB/phpbb/template/twig/twig.php +++ b/phpBB/phpbb/template/twig/twig.php @@ -78,9 +78,12 @@ class twig extends \phpbb\template\base * @param \phpbb\config\config $config * @param \phpbb\user $user * @param \phpbb\template\context $context template context + * @param \phpbb\template\twig\environment $twig_environment + * @param string $cache_path + * @param array|\ArrayAccess $extensions * @param \phpbb\extension\manager $extension_manager extension manager, if null then template events will not be invoked */ - public function __construct(\phpbb\path_helper $path_helper, $config, $user, \phpbb\template\context $context, \phpbb\extension\manager $extension_manager = null) + public function __construct(\phpbb\path_helper $path_helper, $config, $user, \phpbb\template\context $context, \phpbb\template\twig\environment $twig_environment, $cache_path, $extensions = array(), \phpbb\extension\manager $extension_manager = null) { $this->path_helper = $path_helper; $this->phpbb_root_path = $path_helper->get_phpbb_root_path(); @@ -89,35 +92,13 @@ class twig extends \phpbb\template\base $this->user = $user; $this->context = $context; $this->extension_manager = $extension_manager; + $this->cachepath = $cache_path; + $this->twig = $twig_environment; - $this->cachepath = $this->phpbb_root_path . 'cache/twig/'; - - // Initiate the loader, __main__ namespace paths will be setup later in set_style_names() - $loader = new \phpbb\template\twig\loader(''); - - $this->twig = new \phpbb\template\twig\environment( - $this->config, - $this->path_helper, - $this->extension_manager, - $loader, - array( - 'cache' => (defined('IN_INSTALL')) ? false : $this->cachepath, - 'debug' => defined('DEBUG'), - 'auto_reload' => (bool) $this->config['load_tplcompile'], - 'autoescape' => false, - ) - ); - - $this->twig->addExtension( - new \phpbb\template\twig\extension( - $this->context, - $this->user - ) - ); - - $lexer = new \phpbb\template\twig\lexer($this->twig); - - $this->twig->setLexer($lexer); + foreach ($extensions as $extension) + { + $this->twig->addExtension($extension); + } // Add admin namespace if ($this->path_helper->get_adm_relative_path() !== null && is_dir($this->phpbb_root_path . $this->path_helper->get_adm_relative_path() . 'style/')) diff --git a/tests/controller/helper_route_test.php b/tests/controller/helper_route_test.php index 206c3a4f0b..8113bd0018 100644 --- a/tests/controller/helper_route_test.php +++ b/tests/controller/helper_route_test.php @@ -31,7 +31,28 @@ class phpbb_controller_helper_route_test extends phpbb_test_case $phpEx ); $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $this->user, new \phpbb\template\context()); + + $container = new phpbb_mock_container_builder(); + $cache_path = $phpbb_root_path . 'cache/twig'; + $context = new \phpbb\template\context(); + $loader = new \phpbb\template\twig\loader(''); + $twig = new \phpbb\template\twig\environment( + $this->config, + $phpbb_path_helper, + $container, + $cache_path, + null, + $loader, + array( + 'cache' => false, + 'debug' => false, + 'auto_reload' => true, + 'autoescape' => false, + ) + ); + $this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $this->user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); + $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); + $this->extension_manager = new phpbb_mock_extension_manager( dirname(__FILE__) . '/', array( diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index 535e4fe0d5..fdb9deda53 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -47,20 +47,35 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $this->user = new \phpbb\user(); $this->table_prefix = 'phpbb_'; - $this->template = new \phpbb\template\twig\twig( - new \phpbb\path_helper( - new \phpbb\symfony_request( - new phpbb_mock_request() - ), - new \phpbb\filesystem(), - $this->getMock('\phpbb\request\request'), - $this->phpbb_root_path, - $this->phpEx + $container = new phpbb_mock_container_builder(); + $cache_path = $this->phpbb_root_path . 'cache/twig'; + $context = new \phpbb\template\context(); + $loader = new \phpbb\template\twig\loader(''); + $phpbb_path_helper =new \phpbb\path_helper( + new \phpbb\symfony_request( + new phpbb_mock_request() ), - $this->config, - $this->user, - new \phpbb\template\context() + new \phpbb\filesystem(), + $this->getMock('\phpbb\request\request'), + $this->phpbb_root_path, + $this->phpEx ); + $twig = new \phpbb\template\twig\environment( + $this->config, + $phpbb_path_helper, + $container, + $cache_path, + null, + $loader, + array( + 'cache' => false, + 'debug' => false, + 'auto_reload' => true, + 'autoescape' => false, + ) + ); + $this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $this->user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); + $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $this->migrator = new \phpbb\db\migrator( $this->config, @@ -73,7 +88,6 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case array(), new \phpbb\db\migration\helper() ); - $container = new phpbb_mock_container_builder(); $container->set('migrator', $this->migrator); $this->extension_manager = new \phpbb\extension\manager( diff --git a/tests/template/template_events_test.php b/tests/template/template_events_test.php index c415c969fe..e8ffea8d11 100644 --- a/tests/template/template_events_test.php +++ b/tests/template/template_events_test.php @@ -147,7 +147,28 @@ Zeta test event in all', $phpbb_root_path, $phpEx ); - $this->template = new \phpbb\template\twig\twig($path_helper, $config, $user, new \phpbb\template\context, $this->extension_manager); + + $container = new phpbb_mock_container_builder(); + $cache_path = $phpbb_root_path . 'cache/twig'; + $context = new \phpbb\template\context(); + $loader = new \phpbb\template\twig\loader(''); + $twig = new \phpbb\template\twig\environment( + $config, + $path_helper, + $container, + $cache_path, + $this->extension_manager, + $loader, + array( + 'cache' => false, + 'debug' => false, + 'auto_reload' => true, + 'autoescape' => false, + ) + ); + $this->template = new \phpbb\template\twig\twig($path_helper, $config, $user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager); + $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); + $this->template->set_custom_style(((!empty($style_names)) ? $style_names : 'silver'), array($this->template_path)); } } diff --git a/tests/template/template_test_case.php b/tests/template/template_test_case.php index 83446b5352..1f46d6ff71 100644 --- a/tests/template/template_test_case.php +++ b/tests/template/template_test_case.php @@ -78,7 +78,27 @@ class phpbb_template_template_test_case extends phpbb_test_case ); $this->template_path = $this->test_path . '/templates'; - $this->template = new \phpbb\template\twig\twig($path_helper, $config, $this->user, new \phpbb\template\context()); + + $container = new phpbb_mock_container_builder(); + $cache_path = $phpbb_root_path . 'cache/twig'; + $context = new \phpbb\template\context(); + $loader = new \phpbb\template\twig\loader(''); + $twig = new \phpbb\template\twig\environment( + $config, + $path_helper, + $container, + $cache_path, + null, + $loader, + array( + 'cache' => false, + 'debug' => false, + 'auto_reload' => true, + 'autoescape' => false, + ) + ); + $this->template = new phpbb\template\twig\twig($path_helper, $config, $user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); + $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $this->template->set_custom_style('tests', $this->template_path); } diff --git a/tests/template/template_test_case_with_tree.php b/tests/template/template_test_case_with_tree.php index 68ecc4b706..c634e2051a 100644 --- a/tests/template/template_test_case_with_tree.php +++ b/tests/template/template_test_case_with_tree.php @@ -34,7 +34,27 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat $this->template_path = $this->test_path . '/templates'; $this->parent_template_path = $this->test_path . '/parent_templates'; - $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $user, new phpbb\template\context()); + + $container = new phpbb_mock_container_builder(); + $cache_path = $phpbb_root_path . 'cache/twig'; + $context = new \phpbb\template\context(); + $loader = new \phpbb\template\twig\loader(''); + $twig = new \phpbb\template\twig\environment( + $config, + $this->phpbb_path_helper, + $container, + $cache_path, + null, + $loader, + array( + 'cache' => false, + 'debug' => false, + 'auto_reload' => true, + 'autoescape' => false, + ) + ); + $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); + $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $this->template->set_custom_style('tests', array($this->template_path, $this->parent_template_path)); } } From 827510a4185ae8ef6fbf0d0f2fbeb92bf63ccace Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 9 Aug 2014 16:14:58 +0200 Subject: [PATCH 0014/1676] [ticket/11649] Fix coding style PHPBB3-11649 --- phpBB/phpbb/template/twig/environment.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php index df586af9e5..f6d9b73178 100644 --- a/phpBB/phpbb/template/twig/environment.php +++ b/phpBB/phpbb/template/twig/environment.php @@ -44,7 +44,8 @@ class environment extends \Twig_Environment * * @param \phpbb\config\config $phpbb_config The phpBB configuration * @param \phpbb\path_helper $path_helper phpBB path helper - * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container The dependency injection container + * @param string $cache_path The path to the cache directory * @param \phpbb\extension\manager $extension_manager phpBB extension manager * @param \Twig_LoaderInterface $loader Twig loader interface * @param array $options Array of options to pass to Twig @@ -61,11 +62,11 @@ class environment extends \Twig_Environment $this->web_root_path = $this->phpbb_path_helper->get_web_root_path(); $options = array_merge(array( - 'cache' => (defined('IN_INSTALL')) ? false : $cache_path, - 'debug' => defined('DEBUG'), - 'auto_reload' => (bool) $this->phpbb_config['load_tplcompile'], - 'autoescape' => false, - ), $options); + 'cache' => (defined('IN_INSTALL')) ? false : $cache_path, + 'debug' => defined('DEBUG'), + 'auto_reload' => (bool) $this->phpbb_config['load_tplcompile'], + 'autoescape' => false, + ), $options); return parent::__construct($loader, $options); } @@ -75,7 +76,8 @@ class environment extends \Twig_Environment */ public function getLexer() { - if (null === $this->lexer) { + if (null === $this->lexer) + { $this->lexer = $this->container->get('template.twig.lexer'); } From e7e6d45789d4084b98a9c6227a42976e4a1d8f7f Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 10 Aug 2014 02:26:16 +0200 Subject: [PATCH 0015/1676] [ticket/12957] Update the constructions of the template engine PHPBB3-12957 --- phpBB/includes/bbcode.php | 21 ++++++++++++++++++-- phpBB/includes/functions_messenger.php | 20 +++++++++++++++++-- phpBB/install/index.php | 24 ++++++++++++++++++++++- phpBB/phpbb/template/twig/environment.php | 1 + phpBB/phpbb/template/twig/lexer.php | 5 +++++ 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index 3460db4882..d5e01a7e1e 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -129,13 +129,30 @@ class bbcode */ function bbcode_cache_init() { - global $phpbb_root_path, $phpEx, $config, $user, $phpbb_extension_manager, $phpbb_path_helper; + global $phpbb_root_path, $phpEx, $config, $user, $phpbb_extension_manager, $phpbb_path_helper, $phpbb_container; if (empty($this->template_filename)) { $this->template_bitfield = new bitfield($user->style['bbcode_bitfield']); - $template = new phpbb\template\twig\twig($phpbb_path_helper, $config, $user, new phpbb\template\context(), $phpbb_extension_manager); + $template = new \phpbb\template\twig\twig( + $phpbb_container->get('path_helper'), + $phpbb_container->get('config'), + $phpbb_container->get('user'), + new \phpbb\template\context(), + new \phpbb\template\twig\environment( + $phpbb_container->get('config'), + $phpbb_container->get('path_helper'), + $phpbb_container, + $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('ext.manager'), + new \phpbb\template\twig\loader() + ), + $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('template.twig.extensions.collection'), + $phpbb_extension_manager + ); + $template->set_style(); $template->set_filenames(array('bbcode.html' => 'bbcode.html')); $this->template_filename = $template->get_source_file_for_handle('bbcode.html'); diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 3657a89aa0..4b4ee10259 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -637,14 +637,30 @@ class messenger */ protected function setup_template() { - global $config, $phpbb_path_helper, $user, $phpbb_extension_manager; + global $config, $phpbb_path_helper, $user, $phpbb_extension_manager, $phpbb_container; if ($this->template instanceof \phpbb\template\template) { return; } - $this->template = new \phpbb\template\twig\twig($phpbb_path_helper, $config, $user, new \phpbb\template\context(), $phpbb_extension_manager); + $this->template = new \phpbb\template\twig\twig( + $phpbb_container->get('path_helper'), + $phpbb_container->get('config'), + $phpbb_container->get('user'), + new \phpbb\template\context(), + new \phpbb\template\twig\environment( + $phpbb_container->get('config'), + $phpbb_container->get('path_helper'), + $phpbb_container, + $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('ext.manager'), + new \phpbb\template\twig\loader() + ), + $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('template.twig.extensions.collection'), + $phpbb_extension_manager + ); } /** diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 395aff6c7d..3d5e546ffb 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -137,6 +137,7 @@ $phpbb_container_builder->set_custom_parameters(array( $phpbb_container = $phpbb_container_builder->get_container(); $phpbb_container->register('dbal.conn.driver')->setSynthetic(true); +$phpbb_container->register('template.twig.environment')->setSynthetic(true); $phpbb_container->compile(); $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); @@ -268,7 +269,28 @@ $config = new \phpbb\config\config(array( $symfony_request = $phpbb_container->get('symfony_request'); $phpbb_filesystem = $phpbb_container->get('filesystem'); $phpbb_path_helper = $phpbb_container->get('path_helper'); -$template = new \phpbb\template\twig\twig($phpbb_path_helper, $config, $user, new \phpbb\template\context()); +$cache_path = $phpbb_root_path . 'cache/'; + +$twig_environment = new \phpbb\template\twig\environment( + $config, + $phpbb_path_helper, + $phpbb_container, + $cache_path, + null, + $phpbb_container->get('template.twig.loader') +); + +$phpbb_container->set('template.twig.environment', $twig_environment); +$template = new \phpbb\template\twig\twig( + $phpbb_path_helper, + $config, + $user, + new \phpbb\template\context(), + $twig_environment, + $cache_path, + array($phpbb_container->get('template.twig.extensions.phpbb')) +); + $paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style'); $paths = array_filter($paths, 'is_dir'); $template->set_custom_style(array( diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php index f6d9b73178..b3f57b016f 100644 --- a/phpBB/phpbb/template/twig/environment.php +++ b/phpBB/phpbb/template/twig/environment.php @@ -79,6 +79,7 @@ class environment extends \Twig_Environment if (null === $this->lexer) { $this->lexer = $this->container->get('template.twig.lexer'); + $this->lexer->set_environment($this); } return $this->lexer; diff --git a/phpBB/phpbb/template/twig/lexer.php b/phpBB/phpbb/template/twig/lexer.php index c5dc7273ba..a7848738bb 100644 --- a/phpBB/phpbb/template/twig/lexer.php +++ b/phpBB/phpbb/template/twig/lexer.php @@ -15,6 +15,11 @@ namespace phpbb\template\twig; class lexer extends \Twig_Lexer { + public function set_environment(\Twig_Environment $env) + { + $this->env = $env; + } + public function tokenize($code, $filename = null) { // Our phpBB tags From 143c1ba8d10bc27500812acd433ffca56110f02c Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 10 Aug 2014 04:01:47 +0200 Subject: [PATCH 0016/1676] [ticket/12957] Removed unused use PHPBB3-12957 --- phpBB/phpbb/template/twig/environment.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php index b3f57b016f..0ba7a265e4 100644 --- a/phpBB/phpbb/template/twig/environment.php +++ b/phpBB/phpbb/template/twig/environment.php @@ -13,9 +13,6 @@ namespace phpbb\template\twig; -use Twig_Lexer; -use Twig_LexerInterface; - class environment extends \Twig_Environment { /** @var \phpbb\config\config */ From 8c4057404996c03fb08013bbd68a70ea6511ff02 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 10 Aug 2014 12:05:28 +0200 Subject: [PATCH 0017/1676] [ticket/12958] Remove subsilver2 for phpBB 3.2 PHPBB3-12958 --- phpBB/styles/subsilver2/style.cfg | 32 - .../subsilver2/template/attachment.html | 121 -- phpBB/styles/subsilver2/template/bbcode.html | 69 - .../subsilver2/template/breadcrumbs.html | 14 - .../subsilver2/template/captcha_default.html | 17 - .../subsilver2/template/captcha_qa.html | 8 - .../template/captcha_recaptcha.html | 36 - .../subsilver2/template/confirm_body.html | 28 - .../template/confirm_delete_body.html | 53 - .../styles/subsilver2/template/faq_body.html | 63 - .../subsilver2/template/forumlist_body.html | 94 -- phpBB/styles/subsilver2/template/index.htm | 16 - .../subsilver2/template/index_body.html | 140 -- phpBB/styles/subsilver2/template/jumpbox.html | 19 - .../subsilver2/template/login_body.html | 111 -- .../subsilver2/template/login_body_oauth.html | 7 - .../subsilver2/template/login_forum.html | 56 - .../subsilver2/template/mcp_approve.html | 49 - phpBB/styles/subsilver2/template/mcp_ban.html | 120 -- .../subsilver2/template/mcp_footer.html | 27 - .../styles/subsilver2/template/mcp_forum.html | 93 -- .../styles/subsilver2/template/mcp_front.html | 137 -- .../subsilver2/template/mcp_header.html | 60 - .../styles/subsilver2/template/mcp_logs.html | 46 - .../subsilver2/template/mcp_message.html | 14 - .../styles/subsilver2/template/mcp_move.html | 46 - .../subsilver2/template/mcp_notes_front.html | 22 - .../subsilver2/template/mcp_notes_user.html | 125 -- .../styles/subsilver2/template/mcp_post.html | 211 --- .../styles/subsilver2/template/mcp_queue.html | 76 - .../subsilver2/template/mcp_reports.html | 67 - .../styles/subsilver2/template/mcp_topic.html | 154 -- .../subsilver2/template/mcp_warn_front.html | 74 - .../subsilver2/template/mcp_warn_list.html | 43 - .../subsilver2/template/mcp_warn_post.html | 62 - .../subsilver2/template/mcp_warn_user.html | 75 - .../styles/subsilver2/template/mcp_whois.html | 15 - .../subsilver2/template/memberlist_body.html | 119 -- .../subsilver2/template/memberlist_email.html | 99 -- .../subsilver2/template/memberlist_group.html | 17 - .../subsilver2/template/memberlist_im.html | 44 - .../template/memberlist_search.html | 126 -- .../subsilver2/template/memberlist_team.html | 50 - .../subsilver2/template/memberlist_view.html | 199 --- .../subsilver2/template/message_body.html | 16 - .../subsilver2/template/overall_footer.html | 27 - .../subsilver2/template/overall_header.html | 262 ---- .../subsilver2/template/pagination.html | 11 - .../template/posting_attach_body.html | 83 -- .../subsilver2/template/posting_body.html | 426 ------ .../subsilver2/template/posting_buttons.html | 94 -- .../template/posting_poll_body.html | 36 - .../subsilver2/template/posting_preview.html | 70 - .../template/posting_progress_bar.html | 44 - .../subsilver2/template/posting_review.html | 99 -- .../subsilver2/template/posting_smilies.html | 38 - .../template/posting_topic_review.html | 110 -- .../template/profilefields/bool.html | 7 - .../template/profilefields/date.html | 5 - .../template/profilefields/dropdown.html | 5 - .../template/profilefields/int.html | 3 - .../template/profilefields/string.html | 3 - .../template/profilefields/text.html | 3 - .../template/profilefields/url.html | 3 - .../template/quickreply_editor.html | 29 - .../subsilver2/template/report_body.html | 49 - .../subsilver2/template/search_body.html | 95 -- .../subsilver2/template/search_results.html | 160 --- .../styles/subsilver2/template/searchbox.html | 1 - .../subsilver2/template/simple_footer.html | 15 - .../subsilver2/template/simple_header.html | 24 - phpBB/styles/subsilver2/template/timezone.js | 21 - .../subsilver2/template/timezone_option.html | 20 - .../subsilver2/template/ucp_agreement.html | 87 -- .../subsilver2/template/ucp_attachments.html | 58 - .../subsilver2/template/ucp_auth_link.html | 19 - .../template/ucp_auth_link_oauth.html | 34 - .../template/ucp_avatar_options_gravatar.html | 13 - .../template/ucp_avatar_options_local.html | 38 - .../template/ucp_avatar_options_remote.html | 10 - .../template/ucp_avatar_options_upload.html | 12 - .../subsilver2/template/ucp_footer.html | 13 - .../template/ucp_groups_manage.html | 230 --- .../template/ucp_groups_membership.html | 93 -- .../subsilver2/template/ucp_header.html | 163 --- .../subsilver2/template/ucp_login_link.html | 74 - .../template/ucp_main_bookmarks.html | 86 -- .../subsilver2/template/ucp_main_drafts.html | 96 -- .../subsilver2/template/ucp_main_front.html | 72 - .../template/ucp_main_subscribed.html | 95 -- .../template/ucp_notifications.html | 141 -- .../subsilver2/template/ucp_pm_history.html | 73 - .../template/ucp_pm_message_footer.html | 47 - .../template/ucp_pm_message_header.html | 34 - .../subsilver2/template/ucp_pm_options.html | 192 --- .../template/ucp_pm_viewfolder.html | 131 -- .../template/ucp_pm_viewmessage.html | 136 -- .../template/ucp_pm_viewmessage_print.html | 121 -- .../template/ucp_prefs_personal.html | 71 - .../subsilver2/template/ucp_prefs_post.html | 35 - .../subsilver2/template/ucp_prefs_view.html | 77 - .../template/ucp_profile_autologin_keys.html | 50 - .../template/ucp_profile_avatar.html | 51 - .../template/ucp_profile_profile_info.html | 42 - .../template/ucp_profile_reg_details.html | 47 - .../template/ucp_profile_signature.html | 132 -- .../subsilver2/template/ucp_register.html | 101 -- .../subsilver2/template/ucp_remind.html | 28 - .../subsilver2/template/ucp_resend.html | 29 - .../subsilver2/template/ucp_zebra_foes.html | 28 - .../template/ucp_zebra_friends.html | 30 - .../subsilver2/template/viewforum_body.html | 359 ----- .../subsilver2/template/viewonline_body.html | 57 - .../subsilver2/template/viewonline_whois.html | 12 - .../subsilver2/template/viewtopic_body.html | 440 ------ .../subsilver2/template/viewtopic_print.html | 135 -- .../subsilver2/theme/en/button_pm_new.gif | Bin 1135 -> 0 bytes .../subsilver2/theme/en/button_pm_reply.gif | Bin 1667 -> 0 bytes .../theme/en/button_topic_locked.gif | Bin 1101 -> 0 bytes .../subsilver2/theme/en/button_topic_new.gif | Bin 1164 -> 0 bytes .../theme/en/button_topic_reply.gif | Bin 1234 -> 0 bytes .../subsilver2/theme/en/icon_contact_aim.gif | Bin 580 -> 0 bytes .../theme/en/icon_contact_email.gif | Bin 659 -> 0 bytes .../subsilver2/theme/en/icon_contact_icq.gif | Bin 574 -> 0 bytes .../theme/en/icon_contact_jabber.gif | Bin 674 -> 0 bytes .../subsilver2/theme/en/icon_contact_msnm.gif | Bin 1503 -> 0 bytes .../subsilver2/theme/en/icon_contact_pm.gif | Bin 706 -> 0 bytes .../subsilver2/theme/en/icon_contact_www.gif | Bin 604 -> 0 bytes .../theme/en/icon_contact_yahoo.gif | Bin 663 -> 0 bytes .../subsilver2/theme/en/icon_post_delete.gif | Bin 314 -> 0 bytes .../subsilver2/theme/en/icon_post_edit.gif | Bin 662 -> 0 bytes .../subsilver2/theme/en/icon_post_info.gif | Bin 305 -> 0 bytes .../subsilver2/theme/en/icon_post_quote.gif | Bin 666 -> 0 bytes .../subsilver2/theme/en/icon_post_report.gif | Bin 308 -> 0 bytes .../subsilver2/theme/en/icon_user_offline.gif | Bin 547 -> 0 bytes .../subsilver2/theme/en/icon_user_online.gif | Bin 520 -> 0 bytes .../subsilver2/theme/en/icon_user_profile.gif | Bin 667 -> 0 bytes .../subsilver2/theme/en/icon_user_search.gif | Bin 608 -> 0 bytes .../subsilver2/theme/en/icon_user_warn.gif | Bin 673 -> 0 bytes .../styles/subsilver2/theme/en/stylesheet.css | 116 -- .../subsilver2/theme/images/announce_read.gif | Bin 307 -> 0 bytes .../theme/images/announce_read_locked.gif | Bin 304 -> 0 bytes .../images/announce_read_locked_mine.gif | Bin 324 -> 0 bytes .../theme/images/announce_read_mine.gif | Bin 328 -> 0 bytes .../theme/images/announce_unread.gif | Bin 289 -> 0 bytes .../theme/images/announce_unread_locked.gif | Bin 292 -> 0 bytes .../images/announce_unread_locked_mine.gif | Bin 308 -> 0 bytes .../theme/images/announce_unread_mine.gif | Bin 305 -> 0 bytes .../subsilver2/theme/images/background.gif | Bin 666 -> 0 bytes .../subsilver2/theme/images/cellpic.gif | Bin 722 -> 0 bytes .../subsilver2/theme/images/cellpic1.gif | Bin 246 -> 0 bytes .../subsilver2/theme/images/cellpic2.jpg | Bin 480 -> 0 bytes .../subsilver2/theme/images/cellpic2_rtl.jpg | Bin 601 -> 0 bytes .../subsilver2/theme/images/cellpic3.gif | Bin 257 -> 0 bytes .../subsilver2/theme/images/created_by.jpg | Bin 15319 -> 0 bytes .../subsilver2/theme/images/forum_link.gif | Bin 714 -> 0 bytes .../subsilver2/theme/images/forum_read.gif | Bin 677 -> 0 bytes .../theme/images/forum_read_locked.gif | Bin 673 -> 0 bytes .../theme/images/forum_read_subforum.gif | Bin 705 -> 0 bytes .../subsilver2/theme/images/forum_unread.gif | Bin 663 -> 0 bytes .../theme/images/forum_unread_locked.gif | Bin 660 -> 0 bytes .../theme/images/forum_unread_subforum.gif | Bin 688 -> 0 bytes .../subsilver2/theme/images/icon_mini_faq.gif | Bin 219 -> 0 bytes .../theme/images/icon_mini_groups.gif | Bin 222 -> 0 bytes .../theme/images/icon_mini_login.gif | Bin 233 -> 0 bytes .../theme/images/icon_mini_members.gif | Bin 223 -> 0 bytes .../theme/images/icon_mini_message.gif | Bin 232 -> 0 bytes .../theme/images/icon_mini_notification.gif | Bin 543 -> 0 bytes .../theme/images/icon_mini_profile.gif | Bin 238 -> 0 bytes .../theme/images/icon_mini_register.gif | Bin 224 -> 0 bytes .../theme/images/icon_mini_search.gif | Bin 238 -> 0 bytes .../theme/images/icon_post_target.gif | Bin 122 -> 0 bytes .../theme/images/icon_post_target_unread.gif | Bin 122 -> 0 bytes .../theme/images/icon_topic_attach.gif | Bin 217 -> 0 bytes .../theme/images/icon_topic_deleted.png | Bin 1205 -> 0 bytes .../theme/images/icon_topic_latest.gif | Bin 135 -> 0 bytes .../theme/images/icon_topic_newest.gif | Bin 133 -> 0 bytes .../theme/images/icon_topic_reported.gif | Bin 462 -> 0 bytes .../theme/images/icon_topic_unapproved.gif | Bin 334 -> 0 bytes .../styles/subsilver2/theme/images/index.htm | 16 - .../subsilver2/theme/images/no_avatar.gif | Bin 930 -> 0 bytes .../subsilver2/theme/images/poll_center.gif | Bin 92 -> 0 bytes .../subsilver2/theme/images/poll_left.gif | Bin 113 -> 0 bytes .../subsilver2/theme/images/poll_right.gif | Bin 113 -> 0 bytes .../subsilver2/theme/images/site_logo.gif | Bin 7151 -> 0 bytes .../styles/subsilver2/theme/images/spacer.gif | Bin 43 -> 0 bytes .../subsilver2/theme/images/sticky_read.gif | Bin 344 -> 0 bytes .../theme/images/sticky_read_locked.gif | Bin 338 -> 0 bytes .../theme/images/sticky_read_locked_mine.gif | Bin 336 -> 0 bytes .../theme/images/sticky_read_mine.gif | Bin 352 -> 0 bytes .../subsilver2/theme/images/sticky_unread.gif | Bin 325 -> 0 bytes .../theme/images/sticky_unread_locked.gif | Bin 324 -> 0 bytes .../images/sticky_unread_locked_mine.gif | Bin 336 -> 0 bytes .../theme/images/sticky_unread_mine.gif | Bin 339 -> 0 bytes .../subsilver2/theme/images/topic_moved.gif | Bin 660 -> 0 bytes .../subsilver2/theme/images/topic_read.gif | Bin 344 -> 0 bytes .../theme/images/topic_read_hot.gif | Bin 1902 -> 0 bytes .../theme/images/topic_read_hot_mine.gif | Bin 1903 -> 0 bytes .../theme/images/topic_read_locked.gif | Bin 333 -> 0 bytes .../theme/images/topic_read_locked_mine.gif | Bin 337 -> 0 bytes .../theme/images/topic_read_mine.gif | Bin 350 -> 0 bytes .../subsilver2/theme/images/topic_unread.gif | Bin 336 -> 0 bytes .../theme/images/topic_unread_hot.gif | Bin 1888 -> 0 bytes .../theme/images/topic_unread_hot_mine.gif | Bin 1895 -> 0 bytes .../theme/images/topic_unread_locked.gif | Bin 459 -> 0 bytes .../theme/images/topic_unread_locked_mine.gif | Bin 334 -> 0 bytes .../theme/images/topic_unread_mine.gif | Bin 350 -> 0 bytes .../subsilver2/theme/images/upload_bar.gif | Bin 12892 -> 0 bytes .../subsilver2/theme/images/whosonline.gif | Bin 929 -> 0 bytes phpBB/styles/subsilver2/theme/stylesheet.css | 1242 ----------------- 210 files changed, 9979 deletions(-) delete mode 100644 phpBB/styles/subsilver2/style.cfg delete mode 100644 phpBB/styles/subsilver2/template/attachment.html delete mode 100644 phpBB/styles/subsilver2/template/bbcode.html delete mode 100644 phpBB/styles/subsilver2/template/breadcrumbs.html delete mode 100644 phpBB/styles/subsilver2/template/captcha_default.html delete mode 100644 phpBB/styles/subsilver2/template/captcha_qa.html delete mode 100644 phpBB/styles/subsilver2/template/captcha_recaptcha.html delete mode 100644 phpBB/styles/subsilver2/template/confirm_body.html delete mode 100644 phpBB/styles/subsilver2/template/confirm_delete_body.html delete mode 100644 phpBB/styles/subsilver2/template/faq_body.html delete mode 100644 phpBB/styles/subsilver2/template/forumlist_body.html delete mode 100644 phpBB/styles/subsilver2/template/index.htm delete mode 100644 phpBB/styles/subsilver2/template/index_body.html delete mode 100644 phpBB/styles/subsilver2/template/jumpbox.html delete mode 100644 phpBB/styles/subsilver2/template/login_body.html delete mode 100644 phpBB/styles/subsilver2/template/login_body_oauth.html delete mode 100644 phpBB/styles/subsilver2/template/login_forum.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_approve.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_ban.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_footer.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_forum.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_front.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_header.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_logs.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_message.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_move.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_notes_front.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_notes_user.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_post.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_queue.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_reports.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_topic.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_warn_front.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_warn_list.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_warn_post.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_warn_user.html delete mode 100644 phpBB/styles/subsilver2/template/mcp_whois.html delete mode 100644 phpBB/styles/subsilver2/template/memberlist_body.html delete mode 100644 phpBB/styles/subsilver2/template/memberlist_email.html delete mode 100644 phpBB/styles/subsilver2/template/memberlist_group.html delete mode 100644 phpBB/styles/subsilver2/template/memberlist_im.html delete mode 100644 phpBB/styles/subsilver2/template/memberlist_search.html delete mode 100644 phpBB/styles/subsilver2/template/memberlist_team.html delete mode 100644 phpBB/styles/subsilver2/template/memberlist_view.html delete mode 100644 phpBB/styles/subsilver2/template/message_body.html delete mode 100644 phpBB/styles/subsilver2/template/overall_footer.html delete mode 100644 phpBB/styles/subsilver2/template/overall_header.html delete mode 100644 phpBB/styles/subsilver2/template/pagination.html delete mode 100644 phpBB/styles/subsilver2/template/posting_attach_body.html delete mode 100644 phpBB/styles/subsilver2/template/posting_body.html delete mode 100644 phpBB/styles/subsilver2/template/posting_buttons.html delete mode 100644 phpBB/styles/subsilver2/template/posting_poll_body.html delete mode 100644 phpBB/styles/subsilver2/template/posting_preview.html delete mode 100644 phpBB/styles/subsilver2/template/posting_progress_bar.html delete mode 100644 phpBB/styles/subsilver2/template/posting_review.html delete mode 100644 phpBB/styles/subsilver2/template/posting_smilies.html delete mode 100644 phpBB/styles/subsilver2/template/posting_topic_review.html delete mode 100644 phpBB/styles/subsilver2/template/profilefields/bool.html delete mode 100644 phpBB/styles/subsilver2/template/profilefields/date.html delete mode 100644 phpBB/styles/subsilver2/template/profilefields/dropdown.html delete mode 100644 phpBB/styles/subsilver2/template/profilefields/int.html delete mode 100644 phpBB/styles/subsilver2/template/profilefields/string.html delete mode 100644 phpBB/styles/subsilver2/template/profilefields/text.html delete mode 100644 phpBB/styles/subsilver2/template/profilefields/url.html delete mode 100644 phpBB/styles/subsilver2/template/quickreply_editor.html delete mode 100644 phpBB/styles/subsilver2/template/report_body.html delete mode 100644 phpBB/styles/subsilver2/template/search_body.html delete mode 100644 phpBB/styles/subsilver2/template/search_results.html delete mode 100644 phpBB/styles/subsilver2/template/searchbox.html delete mode 100644 phpBB/styles/subsilver2/template/simple_footer.html delete mode 100644 phpBB/styles/subsilver2/template/simple_header.html delete mode 100644 phpBB/styles/subsilver2/template/timezone.js delete mode 100644 phpBB/styles/subsilver2/template/timezone_option.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_agreement.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_attachments.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_auth_link.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_auth_link_oauth.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_avatar_options_gravatar.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_avatar_options_local.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_avatar_options_remote.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_avatar_options_upload.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_footer.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_groups_manage.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_groups_membership.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_header.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_login_link.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_main_bookmarks.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_main_drafts.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_main_front.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_main_subscribed.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_notifications.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_pm_history.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_pm_message_footer.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_pm_message_header.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_pm_options.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_pm_viewfolder.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_pm_viewmessage.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_prefs_personal.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_prefs_post.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_prefs_view.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_profile_autologin_keys.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_profile_avatar.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_profile_profile_info.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_profile_reg_details.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_profile_signature.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_register.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_remind.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_resend.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_zebra_foes.html delete mode 100644 phpBB/styles/subsilver2/template/ucp_zebra_friends.html delete mode 100644 phpBB/styles/subsilver2/template/viewforum_body.html delete mode 100644 phpBB/styles/subsilver2/template/viewonline_body.html delete mode 100644 phpBB/styles/subsilver2/template/viewonline_whois.html delete mode 100644 phpBB/styles/subsilver2/template/viewtopic_body.html delete mode 100644 phpBB/styles/subsilver2/template/viewtopic_print.html delete mode 100644 phpBB/styles/subsilver2/theme/en/button_pm_new.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/button_pm_reply.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/button_topic_locked.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/button_topic_new.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/button_topic_reply.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_contact_aim.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_contact_email.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_contact_icq.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_contact_jabber.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_contact_msnm.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_contact_pm.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_contact_www.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_contact_yahoo.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_post_delete.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_post_edit.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_post_info.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_post_quote.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_post_report.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_user_offline.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_user_online.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_user_profile.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_user_search.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/icon_user_warn.gif delete mode 100644 phpBB/styles/subsilver2/theme/en/stylesheet.css delete mode 100644 phpBB/styles/subsilver2/theme/images/announce_read.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/announce_read_locked.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/announce_read_locked_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/announce_read_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/announce_unread.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/announce_unread_locked.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/announce_unread_locked_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/announce_unread_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/background.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/cellpic.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/cellpic1.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/cellpic2.jpg delete mode 100644 phpBB/styles/subsilver2/theme/images/cellpic2_rtl.jpg delete mode 100644 phpBB/styles/subsilver2/theme/images/cellpic3.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/created_by.jpg delete mode 100644 phpBB/styles/subsilver2/theme/images/forum_link.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/forum_read.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/forum_read_locked.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/forum_read_subforum.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/forum_unread.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/forum_unread_locked.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/forum_unread_subforum.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_mini_faq.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_mini_groups.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_mini_login.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_mini_members.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_mini_message.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_mini_notification.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_mini_profile.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_mini_register.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_mini_search.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_post_target.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_post_target_unread.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_topic_attach.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_topic_deleted.png delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_topic_latest.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_topic_newest.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_topic_reported.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/icon_topic_unapproved.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/index.htm delete mode 100644 phpBB/styles/subsilver2/theme/images/no_avatar.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/poll_center.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/poll_left.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/poll_right.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/site_logo.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/spacer.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/sticky_read.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/sticky_read_locked.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/sticky_read_locked_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/sticky_read_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/sticky_unread.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/sticky_unread_locked.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/sticky_unread_locked_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/sticky_unread_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_moved.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_read.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_read_hot.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_read_hot_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_read_locked.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_read_locked_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_read_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_unread.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_unread_hot.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_unread_hot_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_unread_locked.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_unread_locked_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/topic_unread_mine.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/upload_bar.gif delete mode 100644 phpBB/styles/subsilver2/theme/images/whosonline.gif delete mode 100644 phpBB/styles/subsilver2/theme/stylesheet.css diff --git a/phpBB/styles/subsilver2/style.cfg b/phpBB/styles/subsilver2/style.cfg deleted file mode 100644 index 633acf66e0..0000000000 --- a/phpBB/styles/subsilver2/style.cfg +++ /dev/null @@ -1,32 +0,0 @@ -# -# phpBB Style Configuration File -# -# This file is part of the phpBB Forum Software package. -# -# @copyright (c) phpBB Limited -# @license GNU General Public License, version 2 (GPL-2.0) -# -# For full copyright and license information, please see -# the docs/CREDITS.txt file. -# -# At the left is the name, please do not change this -# At the right the value is entered -# -# Values get trimmed, if you want to add a space in front or at the end of -# the value, then enclose the value with single or double quotes. -# Single and double quotes do not need to be escaped. -# -# - -# General Information about this style -name = subsilver2 -copyright = © 2005 phpBB Limited -style_version = 3.1.0-RC2 -phpbb_version = 3.1.0-RC2 - -# Defining a different template bitfield -# template_bitfield = lNg= - -# Parent style -# Set value to empty or to this style's name if this style does not have a parent style -parent = subsilver2 diff --git a/phpBB/styles/subsilver2/template/attachment.html b/phpBB/styles/subsilver2/template/attachment.html deleted file mode 100644 index baad7c6cfc..0000000000 --- a/phpBB/styles/subsilver2/template/attachment.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - [{_file.DENIED_MESSAGE}]
- - - - {L_FILE_COMMENT}{L_COLON} {_file.COMMENT}
- - - - {_file.DOWNLOAD_NAME}
- {_file.DOWNLOAD_NAME} [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ] - - - - {_file.DOWNLOAD_NAME}
- {_file.DOWNLOAD_NAME} [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ] - - - - - {_file.UPLOAD_ICON} - {_file.DOWNLOAD_NAME} [{_file.FILESIZE} {_file.SIZE_LANG}] -
- {_file.L_DOWNLOAD_COUNT} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - -
- [ {L_PLAY_QUICKTIME_FILE} ] - {_file.DOWNLOAD_NAME} [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ] - - -
- - - diff --git a/phpBB/styles/subsilver2/template/bbcode.html b/phpBB/styles/subsilver2/template/bbcode.html deleted file mode 100644 index 9ee5acec34..0000000000 --- a/phpBB/styles/subsilver2/template/bbcode.html +++ /dev/null @@ -1,69 +0,0 @@ -
    -
      -
    - -
      -
    - -
  • -
  • - - -
    {USERNAME} {L_WROTE}{L_COLON}
    - - - -
    {L_QUOTE}{L_COLON}
    - - - -
    - - - -
    {L_CODE}{L_COLON}
    -
    -
    -
    -
    - - - -
    {L_ATTACHMENT}{L_COLON}
    - - - -
    - - - - - - - - - - - - -{TEXT} - -{TEXT} - -{L_IMAGE} - -{DESCRIPTION} - -{DESCRIPTION} - - - - - - - - - - - - diff --git a/phpBB/styles/subsilver2/template/breadcrumbs.html b/phpBB/styles/subsilver2/template/breadcrumbs.html deleted file mode 100644 index 25387da832..0000000000 --- a/phpBB/styles/subsilver2/template/breadcrumbs.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - -
    - - - - -

    {S_TIMEZONE}

    - -
    diff --git a/phpBB/styles/subsilver2/template/captcha_default.html b/phpBB/styles/subsilver2/template/captcha_default.html deleted file mode 100644 index 1be25403ce..0000000000 --- a/phpBB/styles/subsilver2/template/captcha_default.html +++ /dev/null @@ -1,17 +0,0 @@ - - {L_CONFIRM_CODE} - - - - {L_CONFIRM_EXPLAIN} - - - - {L_CONFIRM_CODE} - - - - {L_CONFIRM_CODE}{L_COLON}
    {L_CONFIRM_CODE_EXPLAIN} - tabindex="{$CAPTCHA_TAB_INDEX}" /> - - diff --git a/phpBB/styles/subsilver2/template/captcha_qa.html b/phpBB/styles/subsilver2/template/captcha_qa.html deleted file mode 100644 index 90a6492400..0000000000 --- a/phpBB/styles/subsilver2/template/captcha_qa.html +++ /dev/null @@ -1,8 +0,0 @@ - - {L_CONFIRM_QUESTION} - - - {QA_CONFIRM_QUESTION}{L_COLON}
    {L_CONFIRM_QUESTION_EXPLAIN} - tabindex="{$CAPTCHA_TAB_INDEX}" /> - - diff --git a/phpBB/styles/subsilver2/template/captcha_recaptcha.html b/phpBB/styles/subsilver2/template/captcha_recaptcha.html deleted file mode 100644 index 0d116b361f..0000000000 --- a/phpBB/styles/subsilver2/template/captcha_recaptcha.html +++ /dev/null @@ -1,36 +0,0 @@ - - - {L_CONFIRM_CODE} - - - {L_CONFIRM_CODE}{L_COLON}
    {L_RECAPTCHA_EXPLAIN} - - - - - - - - - - -{L_RECAPTCHA_NOT_AVAILABLE} - diff --git a/phpBB/styles/subsilver2/template/confirm_body.html b/phpBB/styles/subsilver2/template/confirm_body.html deleted file mode 100644 index 1712017c38..0000000000 --- a/phpBB/styles/subsilver2/template/confirm_body.html +++ /dev/null @@ -1,28 +0,0 @@ - - -
    - -
    - - - - - - - - -
    {MESSAGE_TITLE}

    {MESSAGE_TEXT}


    {S_HIDDEN_FIELDS}  
    - -
    - -
    - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/confirm_delete_body.html b/phpBB/styles/subsilver2/template/confirm_delete_body.html deleted file mode 100644 index 18df397fc3..0000000000 --- a/phpBB/styles/subsilver2/template/confirm_delete_body.html +++ /dev/null @@ -1,53 +0,0 @@ - - -
    - -
    - - - - - - - - -
    {MESSAGE_TITLE}
    -
    -

    {MESSAGE_TEXT}

    -
    - - - - - - - - - - - - -
    {L_DELETE_PERMANENTLY}{L_COLON} - - {L_DELETE_TOPIC_PERMANENTLY}{L_DELETE_POST_PERMANENTLY} -
    {L_DELETE_REASON}{L_COLON}
    {L_DELETE_REASON_EXPLAIN}
    -
    - - {S_HIDDEN_FIELDS} -    - -
    - -
    - -
    - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/faq_body.html b/phpBB/styles/subsilver2/template/faq_body.html deleted file mode 100644 index b3c41e932a..0000000000 --- a/phpBB/styles/subsilver2/template/faq_body.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - -
    - - - - - - - - - - - -
    {L_FAQ_TITLE}
    - - {faq_block.BLOCK_TITLE}
    - - {faq_block.faq_row.FAQ_QUESTION}
    - -
    - -
     
    - -
    - - - - - - - - - - - - - - - -

    {faq_block.BLOCK_TITLE}

    - - - -
    » {faq_block.faq_row.FAQ_QUESTION}
    -
    {faq_block.faq_row.FAQ_ANSWER}
    -

    {L_BACK_TO_TOP}

    -
    - -
    - - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/forumlist_body.html b/phpBB/styles/subsilver2/template/forumlist_body.html deleted file mode 100644 index 0d522a6959..0000000000 --- a/phpBB/styles/subsilver2/template/forumlist_body.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_MARK_FORUMS_READ} 
     {L_FORUM}  {L_TOPICS}  {L_POSTS}  {L_LAST_POST} 

    {forumrow.FORUM_NAME}

     
    {forumrow.FORUM_FOLDER_IMG} - -
    {forumrow.FORUM_IMAGE}
    - - {forumrow.FORUM_NAME} -

    {forumrow.FORUM_DESC}

    -
    {L_REDIRECTS}{L_COLON} {forumrow.CLICKS} 

    {L_FORUM}

     
    {forumrow.FORUM_FOLDER_IMG} - -
    {forumrow.FORUM_IMAGE}
    - - {forumrow.FORUM_NAME} -

    {forumrow.FORUM_DESC}

    - -

    {forumrow.L_MODERATOR_STR}{L_COLON} {forumrow.MODERATORS}

    - - - -

    {forumrow.L_SUBFORUM_STR}{L_COLON} - - {forumrow.subforum.SUBFORUM_NAME}{L_COMMA_SEPARATOR} - -

    - - -

    {forumrow.TOPICS}

    {forumrow.POSTS}

    - - - -

    {forumrow.LAST_POST_SUBJECT_TRUNCATED}

    - -

    - - {UNAPPROVED_IMG}  - - {UNAPPROVED_POST_IMG}  - - {forumrow.LAST_POST_TIME} -

    -

    {forumrow.LAST_POSTER_FULL} - {LAST_POST_IMG} -

    - -

    {L_NO_POSTS}

    - -

    {L_NO_FORUMS}

    diff --git a/phpBB/styles/subsilver2/template/index.htm b/phpBB/styles/subsilver2/template/index.htm deleted file mode 100644 index 4763c05f0e..0000000000 --- a/phpBB/styles/subsilver2/template/index.htm +++ /dev/null @@ -1,16 +0,0 @@ - - -subSilver created by subBlue Design - - - - - - - - - -
    Created by subBlue Design
    - - - \ No newline at end of file diff --git a/phpBB/styles/subsilver2/template/index_body.html b/phpBB/styles/subsilver2/template/index_body.html deleted file mode 100644 index 1a2786015f..0000000000 --- a/phpBB/styles/subsilver2/template/index_body.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - -

    - - - - - - - - - {L_DELETE_COOKIES} - | - - {L_THE_TEAM} - - | - {L_CONTACT_US} - - - - -
    - -
    - - - - - - -
    - - - - - - - - - - - - - - - - - - -

    {L_WHO_IS_ONLINE}

    {L_WHO_IS_ONLINE}

    {L_WHO_IS_ONLINE}{L_WHO_IS_ONLINE} - - - {TOTAL_USERS_ONLINE} ({L_ONLINE_EXPLAIN})
    {RECORD_USERS}

    {LOGGED_IN_USER_LIST} - -
    -
    {L_LEGEND} :: {LEGEND}
    - - - -
    - - - - - - - - - -

    {L_BIRTHDAYS}

    {L_BIRTHDAYS} -

    - - {L_CONGRATULATIONS}{L_COLON} {birthdays.USERNAME} ({birthdays.AGE}), {L_NO_BIRTHDAYS} - -

    -
    - - -
    - - - - - - - - - -

    {L_STATISTICS}

    {L_STATISTICS} -

    - - {TOTAL_POSTS} | {TOTAL_TOPICS} | {TOTAL_USERS} | {NEWEST_USER} - -

    -
    - - - - -
    - -
    - - - - - - - - -

    {L_LOGIN_LOGOUT}

    {L_USERNAME}{L_COLON}   {L_PASSWORD}{L_COLON}   {L_FORGOT_PASS}  {L_LOG_ME_IN}  
    - {S_LOGIN_REDIRECT} - {S_FORM_TOKEN} -
    - - -
    - - - - - - - - - - - - -
    {FORUM_UNREAD_IMG}{L_UNREAD_POSTS}  {FORUM_IMG}{L_NO_UNREAD_POSTS}  {FORUM_LOCKED_IMG}{L_FORUM_LOCKED}
    - - diff --git a/phpBB/styles/subsilver2/template/jumpbox.html b/phpBB/styles/subsilver2/template/jumpbox.html deleted file mode 100644 index e0603c6a6e..0000000000 --- a/phpBB/styles/subsilver2/template/jumpbox.html +++ /dev/null @@ -1,19 +0,0 @@ - - -
    - - - - - -
    {HIDDEN_FIELDS_FOR_JUMPBOX}{L_SELECT_TOPICS_FROM}{L_MODERATE_FORUM}{L_JUMP_TO}{L_COLON}  
    - -
    - diff --git a/phpBB/styles/subsilver2/template/login_body.html b/phpBB/styles/subsilver2/template/login_body.html deleted file mode 100644 index ed63e748cf..0000000000 --- a/phpBB/styles/subsilver2/template/login_body.html +++ /dev/null @@ -1,111 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - -
    {L_LOGIN}{LOGIN_EXPLAIN}
    {LOGIN_EXPLAIN}
    -

    {L_LOGIN_INFO}

    - -

    - {L_TERMS_USE} | {L_PRIVACY} -

    -
    class="row2"class="row1"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {LOGIN_ERROR}
    style="width: 50%; text-align: {S_CONTENT_FLOW_END};">{L_USERNAME}{L_COLON} - -
    {L_REGISTER} - -
    style="width: 50%; text-align: {S_CONTENT_FLOW_END};">{L_PASSWORD}{L_COLON} - -
    {L_FORGOT_PASS} -
    {L_RESEND_ACTIVATION} -
      {L_LOG_ME_IN}
      {L_HIDE_ME}
    -
    - - - - - -{S_LOGIN_REDIRECT} - - - -
    colspan="2" align="center">{S_HIDDEN_FIELDS}
    -{S_FORM_TOKEN} -
    - -
    - - - -
    - -
    - - - - diff --git a/phpBB/styles/subsilver2/template/login_body_oauth.html b/phpBB/styles/subsilver2/template/login_body_oauth.html deleted file mode 100644 index 6f374fa4f2..0000000000 --- a/phpBB/styles/subsilver2/template/login_body_oauth.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - {oauth.SERVICE_NAME} - - - diff --git a/phpBB/styles/subsilver2/template/login_forum.html b/phpBB/styles/subsilver2/template/login_forum.html deleted file mode 100644 index 9a141fc295..0000000000 --- a/phpBB/styles/subsilver2/template/login_forum.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - -

    - - -
    - -
    - - - - - - - - - - - - - - -
    {L_LOGIN}
    {L_LOGIN_FORUM}
    - - - - - - - - - - - -
    {LOGIN_ERROR}
    {L_PASSWORD}{L_COLON}
    -
    {S_HIDDEN_FIELDS}
    - {S_FORM_TOKEN} - {S_LOGIN_REDIRECT} -
    - -
    - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/mcp_approve.html b/phpBB/styles/subsilver2/template/mcp_approve.html deleted file mode 100644 index 8c2ef0806b..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_approve.html +++ /dev/null @@ -1,49 +0,0 @@ - - -
    - -
    - - - - - - - - -
    {MESSAGE_TITLE}
    - - {ADDITIONAL_MSG}
    - - - {L_NOTIFY_POSTER_APPROVAL}{L_NOTIFY_POSTER_DISAPPROVAL}
    - - -
    - - - - - - - - - -
    {L_DISAPPROVE_REASON}{L_COLON}
    {L_MORE_INFO}{L_COLON}
    {L_CAN_LEAVE_BLANK}
    -
    - -
    {S_HIDDEN_FIELDS}{MESSAGE_TEXT}

    -    -
    - {S_FORM_TOKEN} -
    - -
    - -
    - - - -
    - - diff --git a/phpBB/styles/subsilver2/template/mcp_ban.html b/phpBB/styles/subsilver2/template/mcp_ban.html deleted file mode 100644 index cc24d21d73..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_ban.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {L_EXPLAIN}
    {L_BAN_CELL}{L_COLON} - -
    [ {L_FIND_USERNAME} ] -
    {L_BAN_LENGTH}{L_COLON}
    {L_YEAR_MONTH_DAY}
    {L_BAN_EXCLUDE}{L_COLON}
    {L_BAN_EXCLUDE_EXPLAIN}
    {L_YES}   {L_NO}
    {L_BAN_REASON}{L_COLON}
    {L_BAN_GIVE_REASON}{L_COLON}
       
    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_UNBAN_TITLE}
    {L_UNBAN_EXPLAIN}
    {L_BAN_CELL}{L_COLON}
    {L_BAN_LENGTH}{L_COLON}
    {L_BAN_REASON}{L_COLON}
    {L_BAN_GIVE_REASON}{L_COLON}
       
    {L_NO_BAN_CELL}
    -{S_FORM_TOKEN} -
    - - diff --git a/phpBB/styles/subsilver2/template/mcp_footer.html b/phpBB/styles/subsilver2/template/mcp_footer.html deleted file mode 100644 index 280920b148..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_footer.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - -
     [ {TOTAL_TOPICS}{TOTAL_POSTS}{TOTAL}
    -
    - - -
    - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/mcp_forum.html b/phpBB/styles/subsilver2/template/mcp_forum.html deleted file mode 100644 index b168bf3ac8..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_forum.html +++ /dev/null @@ -1,93 +0,0 @@ - - -
    - -{L_VIEW_FORUM_LOGS} - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_DISPLAY_TOPICS}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
      {L_TOPICS}  {L_REPLIES}  {L_LAST_POST}  {L_MARK} 
    {topicrow.TOPIC_FOLDER_IMG} - - [ {L_SELECT_MERGE} - -

    {NEWEST_POST_IMG} {topicrow.ATTACH_ICON_IMG} {topicrow.TOPIC_TITLE} - - {topicrow.UNAPPROVED_IMG}  - - - {topicrow.DELETED_IMG}  - - - {REPORTED_IMG}  - - - [ {L_DELETE_SHADOW_TOPIC} ]  - -

    -

    {topicrow.REPLIES}

    {topicrow.LAST_POST_TIME}

    - checked="checked" />  -

    {L_NO_TOPICS}

    - - -
    -{S_FORM_TOKEN} -
    - - - - - - -
    {L_MARK_ALL} :: {L_UNMARK_ALL}
    - - - diff --git a/phpBB/styles/subsilver2/template/mcp_front.html b/phpBB/styles/subsilver2/template/mcp_front.html deleted file mode 100644 index 7c17e13c52..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_front.html +++ /dev/null @@ -1,137 +0,0 @@ - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_LATEST_UNAPPROVED}
     {L_FORUM}  {L_TOPIC}  {L_SUBJECT}  {L_AUTHOR}  {L_POST_TIME}  {L_SELECT} 
    {unapproved.FORUM_NAME}{unapproved.FORUM_NAME}
    [ {L_MODERATE} ]
    {unapproved.TOPIC_TITLE}
    [ {L_MODERATE} ]
    {unapproved.ATTACH_ICON_IMG} {unapproved.SUBJECT}
    [ {L_VIEW_DETAILS} ]
    {unapproved.AUTHOR_FULL}{unapproved.POST_TIME}
    {L_UNAPPROVED_TOTAL}
    {S_HIDDEN_FIELDS}  
    - {S_FORM_TOKEN} -
    - - - - - -
    {L_MARK_ALL} :: {L_UNMARK_ALL}
    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_LATEST_REPORTED}
     {L_FORUM}  {L_TOPIC}  {L_SUBJECT}  {L_REPORTER}  {L_REPORT_TIME} 
    {report.FORUM_NAME}{report.FORUM_NAME}
    [ {L_MODERATE} ]
    {report.TOPIC_TITLE}
    [ {L_MODERATE} ]
    {report.ATTACH_ICON_IMG} {report.SUBJECT}
    [ {L_VIEW_DETAILS} ]
    {report.REPORTER_FULL}{report.REPORT_TIME}
    {L_REPORTS_TOTAL}
    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_LATEST_REPORTED_PMS}
     {L_PM_SUBJECT}  {L_PM_FROM}  {L_TO} & {L_BCC}  {L_SENT_AT}  {L_REPORTER}  {L_REPORT_TIME} 
    {pm_report.ATTACH_ICON_IMG} {pm_report.PM_SUBJECT}
    [ {L_VIEW_DETAILS} ]
    {pm_report.PM_AUTHOR_FULL}{pm_report.RECIPIENTS}{pm_report.PM_TIME}{pm_report.REPORTER_FULL}{pm_report.REPORT_TIME}
    {L_PM_REPORTS_TOTAL}
    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_LATEST_LOGS}
    {L_USERNAME}{L_IP}{L_ACTION}{L_TIME}
    {log.USERNAME}{log.IP}{log.ACTION}{L_VIEW_TOPIC} | {L_VIEW_TOPIC_LOGS}{log.TIME}
    {L_NO_ENTRIES}
    - -
    - - - diff --git a/phpBB/styles/subsilver2/template/mcp_header.html b/phpBB/styles/subsilver2/template/mcp_header.html deleted file mode 100644 index 7144750ed4..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_header.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/phpBB/styles/subsilver2/template/posting_body.html b/phpBB/styles/subsilver2/template/posting_body.html deleted file mode 100644 index 321e4227ee..0000000000 --- a/phpBB/styles/subsilver2/template/posting_body.html +++ /dev/null @@ -1,426 +0,0 @@ - - - - - - - -
    - -

    {L_FORUM_RULES}


    - {L_FORUM_RULES_LINK} - -

    {L_FORUM_RULES}


    - {FORUM_RULES} - -
    - -
    - - - - - -

    - - - - - - - -
    - - - - - - - - - - - -
    {L_OPTIONS}
    {l_block1.L_TITLE} - - - - {l_block1.L_TITLE} - -
    - -
    - - - - - - - - - -
    {L_MESSAGE}

    {MESSAGE}

    {return_links.MESSAGE_LINK}

    - -
    - diff --git a/phpBB/styles/subsilver2/template/mcp_logs.html b/phpBB/styles/subsilver2/template/mcp_logs.html deleted file mode 100644 index 64f2a6a64d..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_logs.html +++ /dev/null @@ -1,46 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_USERNAME}{L_IP}{L_TIME}{L_ACTION}{L_MARK}
    {log.USERNAME}{log.IP}{log.DATE}{log.ACTION}
    {log.DATA}
    {L_SEARCH_KEYWORDS}{L_COLON}  
    {L_DISPLAY_LOG}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
     
    {L_NO_ENTRIES}
    -{S_FORM_TOKEN} -
    - -

    - - diff --git a/phpBB/styles/subsilver2/template/mcp_message.html b/phpBB/styles/subsilver2/template/mcp_message.html deleted file mode 100644 index 5699dd54af..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_message.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - -
    {MESSAGE_TITLE}

    {MESSAGE_TEXT}

    - -
    - - diff --git a/phpBB/styles/subsilver2/template/mcp_move.html b/phpBB/styles/subsilver2/template/mcp_move.html deleted file mode 100644 index b8958187e6..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_move.html +++ /dev/null @@ -1,46 +0,0 @@ - - -
    - -
    - - - - - - - - -
    {MESSAGE_TITLE}
    - - {ADDITIONAL_MSG}
    - - -
    {L_SELECT_DESTINATION_FORUM}  
    -
    - - {L_LEAVE_SHADOW}
    - - - {L_LOCK_TOPIC}
    - -
    {S_HIDDEN_FIELDS}{MESSAGE_TEXT}

    -    - - {L_NO_DESTINATION_FORUM}

    - {S_HIDDEN_FIELDS} - - -
    - {S_FORM_TOKEN} -
    - -
    - -
    - - - -
    - - diff --git a/phpBB/styles/subsilver2/template/mcp_notes_front.html b/phpBB/styles/subsilver2/template/mcp_notes_front.html deleted file mode 100644 index e2e14e0150..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_notes_front.html +++ /dev/null @@ -1,22 +0,0 @@ - - -
    - - - - - - - - - - - - -
    {L_SELECT_USER}
    {L_FIND_USERNAME}{L_COLON}
    [ {L_FIND_USERNAME} ]
    -{S_FORM_TOKEN} -
    - -

    - - diff --git a/phpBB/styles/subsilver2/template/mcp_notes_user.html b/phpBB/styles/subsilver2/template/mcp_notes_user.html deleted file mode 100644 index 4bd8de6862..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_notes_user.html +++ /dev/null @@ -1,125 +0,0 @@ - - -
    - - - - - - - - - -
    {USERNAME}
    - - - - - - - - - - - - - - - - - -
    {USERNAME_FULL}
    {RANK_TITLE}
    {RANK_IMG}
    {AVATAR_IMG}
    -
    - - - - - - - - - - - - - -
    {L_JOINED}{L_COLON} {JOINED}
    {L_TOTAL_POSTS}{L_COLON} {POSTS}
    {L_WARNINGS}{L_COLON} {WARNINGS}
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_FEEDBACK}
    {L_SEARCH_KEYWORDS}{L_COLON}  
    {L_DISPLAY_LOG}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY}{L_COLON} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
    {L_REPORT_BY}{L_IP}{L_TIME}{L_ACTION}{L_MARK}
    {usernotes.REPORT_BY}{usernotes.IP}{usernotes.REPORT_AT} - {usernotes.ACTION} -
    » [ {usernotes.DATA} ] -
     
    {L_NO_FEEDBACK}
    - -
    - - - - - - - - - - - - - - -
    {L_ADD_FEEDBACK}
    {L_ADD_FEEDBACK_EXPLAIN}
      
    - - - - - - -
    {PAGE_NUMBER} [ {TOTAL_REPORTS} ]
    -{S_FORM_TOKEN} -
    - -

    - - diff --git a/phpBB/styles/subsilver2/template/mcp_post.html b/phpBB/styles/subsilver2/template/mcp_post.html deleted file mode 100644 index f5052ee2d0..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_post.html +++ /dev/null @@ -1,211 +0,0 @@ - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_PM_REPORT_DETAILS}{L_REPORT_DETAILS}
    {L_REPORT_REASON}{L_COLON} {REPORT_REASON_TITLE} » {REPORT_REASON_DESCRIPTION}
    {L_REPORTER}{L_COLON} style="font-weight: bold; color: {REPORTER_COLOUR};">{REPORTER_NAME}   [ {L_READ_PROFILE} | {L_VIEW_NOTES} | {L_WARN_USER} ]
    {L_REPORTED}{L_COLON} {REPORT_DATE}
    {L_MORE_INFO}
    {REPORT_TEXT}
    {L_REPORT_CLOSED}  
    - - - {S_FORM_TOKEN} -
    - -
    - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_PM}{L_POST_DETAILS}
    {RETURN_QUEUE} | {RETURN_TOPIC_SIMPLE} | {RETURN_POST}{RETURN_REPORTS} | {L_VIEW_POST} | {L_VIEW_TOPIC} | {L_VIEW_FORUM}{RETURN_TOPIC}
    {L_PM_SUBJECT}{L_POST_SUBJECT}{L_COLON} - {POST_SUBJECT} - {UNAPPROVED_IMG} {L_POST_UNAPPROVED} - {DELETED_IMG} {L_POST_DELETED} - {REPORTED_IMG} {L_POST_REPORTED} -
    {L_PM_FROM}{L_POSTER}{L_COLON} style="font-weight: bold; color: {POST_AUTHOR_COLOUR}">{POST_AUTHOR}   [ {L_READ_PROFILE} | {L_VIEW_NOTES} | {L_WARN_USER} ]
    {L_THIS_PM_IP}{L_THIS_POST_IP}{L_COLON} - - {POST_IPADDR}{POST_IP} ({POST_IP}{L_LOOKUP_IP}) - - {POST_IPADDR} ({POST_IP}){POST_IP} ({L_LOOKUP_IP}) - -
    {L_SENT_AT}{L_POSTED}{L_COLON} {POST_DATE}
    {L_TO}{L_COLON} - - {to_recipient.NAME}{to_recipient.NAME_FULL}  - -
    {L_BCC}{L_COLON} - - {bcc_recipient.NAME}{bcc_recipient.NAME_FULL}  - -
    {L_PREVIEW}
    - - -
    {POST_PREVIEW}
    - - -

    - - - - - - - - - - -
    {L_ATTACHMENTS}{L_COLON}
    {attachment.DISPLAY_ATTACHMENT}
    - - -
     
    -{S_FORM_TOKEN} -
    - - -
    - - - -
    - - - - -
    - - - - - - - - - - - - - - - - - -
    {L_MOD_OPTIONS}
    {L_CHANGE_POSTER}

    [ {L_FIND_USERNAME} ]
    {S_FORM_TOKEN}
    {L_MOD_OPTIONS}
    {S_FORM_TOKEN}
    - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_IP_INFO}
    {L_OTHER_USERS}
    {userrow.USERNAME}{userrow.USERNAME} [ {userrow.NUM_POSTS} {userrow.L_POST_S} ]{SEARCH_IMG}
    {L_NO_MATCHES_FOUND}
    {L_IPS_POSTED_FROM}[ {L_LOOKUP_ALL} ]
    {iprow.HOSTNAME} ({iprow.IP}){iprow.IP} [ {iprow.NUM_POSTS} {iprow.L_POST_S} ][ {L_LOOKUP_IP} ]
    {L_NO_MATCHES_FOUND}
    - - - - - diff --git a/phpBB/styles/subsilver2/template/mcp_queue.html b/phpBB/styles/subsilver2/template/mcp_queue.html deleted file mode 100644 index 7ca659b5da..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_queue.html +++ /dev/null @@ -1,76 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_DISPLAY_OPTIONS}
    {L_DISPLAY_ITEMS}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} {L_FORUM}     {L_ONLY_TOPIC}  
     {L_TOPIC}{L_POST}  {L_AUTHOR}  {L_POST_TIME}  {L_SELECT} 

    {postrow.ATTACH_ICON_IMG} {postrow.POST_SUBJECT}

    - {L_FORUM}{L_COLON} {postrow.FORUM_NAME}{postrow.FORUM_NAME}
    {postrow.POST_AUTHOR_FULL}
    - [ {L_VIEW_DETAILS} ]
    {postrow.POST_TIME} - - - - - -
    - - - {L_NO_TOPICS_DELETED}{L_NO_POSTS_DELETED} - - {L_NO_TOPICS_QUEUE}{L_NO_POSTS_QUEUE} - - -
    - -    - - -    - - -
    -{S_FORM_TOKEN} -
    - - - - - -
    - - - {L_MARK_ALL} :: {L_UNMARK_ALL} - - {L_MARK_ALL} :: {L_UNMARK_ALL} - - -
    - - diff --git a/phpBB/styles/subsilver2/template/mcp_reports.html b/phpBB/styles/subsilver2/template/mcp_reports.html deleted file mode 100644 index 158f9c2603..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_reports.html +++ /dev/null @@ -1,67 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_DISPLAY_OPTIONS}
    {L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} {L_FORUM}     {L_ONLY_TOPIC}  
     {L_PM}  {L_TO} & {L_BCC}  {L_POST}  {L_AUTHOR}  {L_REPORTER}  {L_REPORT_TIME}  {L_SELECT} 

    {postrow.ATTACH_ICON_IMG} {postrow.PM_SUBJECT}

    - {L_PM_FROM}{L_COLON} {postrow.PM_AUTHOR_FULL}
    {postrow.RECIPIENTS}
    - {L_SENT_AT}{L_COLON} {postrow.PM_TIME}

    {postrow.ATTACH_ICON_IMG} {postrow.POST_SUBJECT}

    - {L_FORUM}{L_COLON} {postrow.FORUM_NAME}{postrow.FORUM_NAME}
    {postrow.POST_AUTHOR_FULL}
    - {postrow.POST_TIME}
    {postrow.REPORTER_FULL}{postrow.REPORT_TIME}
    - [ {L_VIEW_DETAILS} ]
    {L_NO_POSTS}
    - - - -   - -
    -{S_FORM_TOKEN} -
    - - - - - -
    {L_MARK_ALL} :: {L_UNMARK_ALL}
    - - diff --git a/phpBB/styles/subsilver2/template/mcp_topic.html b/phpBB/styles/subsilver2/template/mcp_topic.html deleted file mode 100644 index cba473147e..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_topic.html +++ /dev/null @@ -1,154 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_SPLIT_TOPIC}
    {L_SPLIT_TOPIC_EXPLAIN}
    {L_SPLIT_SUBJECT}
    {L_SPLIT_FORUM}
    {L_TOPIC_ICON} - - - - -
    checked="checked" />{L_NO_TOPIC_ICON} checked="checked" />
    -
    {L_MERGE_POSTS}
    {L_MERGE_TOPIC_EXPLAIN}
    {L_MERGE_TOPIC_ID} {L_SELECT_TOPIC}
    {TO_TOPIC_INFO}
    {L_DISPLAY_OPTIONS}
    {L_POSTS_PER_PAGE}
    {L_POSTS_PER_PAGE_EXPLAIN}
    {L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
    {L_TOPIC_REVIEW}{L_COLON} {TOPIC_TITLE}
    {RETURN_TOPIC}
    - - - - - -
     {L_POST_SUBJECT}{L_COLON} {postrow.POST_SUBJECT}
    -
    {INFO_IMG}
    - - - - - - - -
    -
    {postrow.MESSAGE}
    - -

    - - - - - - - - - - -
    {L_ATTACHMENTS}{L_COLON}
    {postrow.attachment.DISPLAY_ATTACHMENT}
    - - -
    - - - - - - -
    - {UNAPPROVED_IMG} {L_POST_UNAPPROVED}
    - {DELETED_IMG} {L_POST_DELETED}
    - {REPORTED_IMG} {L_POST_REPORTED} -
    {postrow.MINI_POST_IMG}{L_POSTED}{L_COLON} {postrow.POST_DATE}
    -
    -
    checked="checked" />
     
    -{S_HIDDEN_FIELDS} -{S_FORM_TOKEN} -
    - - - - - -
    {L_MARK_ALL} :: {L_UNMARK_ALL}
    - - diff --git a/phpBB/styles/subsilver2/template/mcp_warn_front.html b/phpBB/styles/subsilver2/template/mcp_warn_front.html deleted file mode 100644 index f6daec9cc5..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_warn_front.html +++ /dev/null @@ -1,74 +0,0 @@ - - -
    - - - - - - - - - - - - -
    {L_SELECT_USER}
    {L_FIND_USERNAME}{L_COLON}
    [ {L_FIND_USERNAME} ]
    -{S_FORM_TOKEN} -
    - -

    - - - - - - - - - - - - - - - - - - - - - - - -
    {L_MOST_WARNINGS}
     {L_USERNAME}  {L_WARNINGS}  {L_LATEST_WARNING_TIME}  
    {highest.USERNAME_FULL}{highest.WARNINGS}{highest.WARNING_TIME}{L_VIEW_NOTES}
    {L_NO_WARNINGS}
    - -

    - - - - - - - - - - - - - - - - - - - - - - - -
    {L_LATEST_WARNINGS}
     {L_USERNAME}  {L_TIME}  {L_TOTAL_WARNINGS}  
    {latest.USERNAME_FULL}{latest.WARNING_TIME}{latest.WARNINGS}{L_VIEW_NOTES}
    {L_NO_WARNINGS}
    - -

    - - diff --git a/phpBB/styles/subsilver2/template/mcp_warn_list.html b/phpBB/styles/subsilver2/template/mcp_warn_list.html deleted file mode 100644 index 6e263b6403..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_warn_list.html +++ /dev/null @@ -1,43 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_WARNED_USERS}
     {L_USERNAME}  {L_WARNINGS}  {L_LATEST_WARNING_TIME}  
    {user.USERNAME_FULL}{user.WARNINGS}{user.WARNING_TIME}{L_VIEW_NOTES}
    {L_NO_WARNINGS}
    {L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
    - - - - - - -
    {PAGE_NUMBER} [ {TOTAL_USERS} ]
    -{S_FORM_TOKEN} -
    - -

    - - diff --git a/phpBB/styles/subsilver2/template/mcp_warn_post.html b/phpBB/styles/subsilver2/template/mcp_warn_post.html deleted file mode 100644 index 223457d158..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_warn_post.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - -
    {L_POST}
    - - - - - - - - - - - - - - - - - -
    {USERNAME}
    {RANK_TITLE}
    {RANK_IMG}
    {AVATAR_IMG}
    -
    - {POST} -
    - -

    - -
    - - - - - - - - - - - - - - - - - - - -
    {L_ADD_WARNING}
    {L_ADD_WARNING_EXPLAIN}
    {L_NOTIFY_USER_WARN}
      
    -{S_FORM_TOKEN} -
    - -

    - - diff --git a/phpBB/styles/subsilver2/template/mcp_warn_user.html b/phpBB/styles/subsilver2/template/mcp_warn_user.html deleted file mode 100644 index 6b78c71557..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_warn_user.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - -
    {USERNAME}
    - - - - - - - - - - - - - - - - - -
    {USERNAME_FULL}
    {RANK_TITLE}
    {RANK_IMG}
    {AVATAR_IMG}
    -
    - - - - - - - - - - - - - -
    {L_JOINED}{L_COLON} {JOINED}
    {L_TOTAL_POSTS}{L_COLON} {POSTS}
    {L_WARNINGS}{L_COLON} {WARNINGS}
    -
    - -

    - -
    - - - - - - - - - - - - - - - - - - - -
    {L_ADD_WARNING}
    {L_ADD_WARNING_EXPLAIN}
    {L_NOTIFY_USER_WARN}
      
    -{S_FORM_TOKEN} -
    - -

    - - diff --git a/phpBB/styles/subsilver2/template/mcp_whois.html b/phpBB/styles/subsilver2/template/mcp_whois.html deleted file mode 100644 index 3e3b983059..0000000000 --- a/phpBB/styles/subsilver2/template/mcp_whois.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - -
    {L_WHOIS}
    {RETURN_POST}
    {WHOIS}
    - - diff --git a/phpBB/styles/subsilver2/template/memberlist_body.html b/phpBB/styles/subsilver2/template/memberlist_body.html deleted file mode 100644 index ecfb4b69c5..0000000000 --- a/phpBB/styles/subsilver2/template/memberlist_body.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - -
    - - - - - - - - - -
    {L_USERNAME_BEGINS_WITH}{L_COLON} -  {L_FIND_USERNAME}{L_HIDE_MEMBER_SEARCH}
    - {S_FORM_TOKEN} -
    - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    #{L_USERNAME}{L_JOINED}{L_POSTS}{L_RANK}{L_SEND_MESSAGE}{L_EMAIL}{L_MARK}
    {L_GROUP_LEADER}
    {L_GROUP_MEMBERS}
     {memberrow.ROW_NUMBER} {memberrow.USERNAME_FULL}{L_SELECT} ] {memberrow.JOINED} {memberrow.POSTS}{memberrow.RANK_IMG}{memberrow.RANK_TITLE} {PM_IMG}  {EMAIL_IMG}  {memberrow.PROFILE_FIELD1_VALUE}
    - {L_NO_GROUP_MEMBERS}{L_NO_MEMBERS} -
    {L_SELECT_SORT_METHOD}{L_COLON}   {L_ORDER}  
    -{S_FORM_TOKEN} - -
    - - - - - - -
    {PAGE_NUMBER} [ {TOTAL_USERS} ]{L_MARK_ALL} :: {L_UNMARK_ALL}
    - - - - - - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/memberlist_email.html b/phpBB/styles/subsilver2/template/memberlist_email.html deleted file mode 100644 index 13ff4baace..0000000000 --- a/phpBB/styles/subsilver2/template/memberlist_email.html +++ /dev/null @@ -1,99 +0,0 @@ - - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_CONTACT_ADMIN}{L_SEND_EMAIL_USER}{L_EMAIL_TOPIC}
    {ERROR_MESSAGE}
    {CONTACT_INFO}
    {L_RECIPIENT}{USERNAME}
    {L_SUBJECT}
    {L_RECIPIENT}{L_ADMINISTRATOR}
    {L_SENDER_EMAIL_ADDRESS}
    {L_SENDER_NAME}
    {L_EMAIL_ADDRESS}
    {L_REAL_NAME}
    {L_DEST_LANG}
    {L_DEST_LANG_EXPLAIN}
    {L_MESSAGE_BODY}
    {L_EMAIL_BODY_EXPLAIN}
    {L_OPTIONS} - - - - - -
    {L_CC_EMAIL}
    -
    - - {S_FORM_TOKEN} - -
    - -
    - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/memberlist_group.html b/phpBB/styles/subsilver2/template/memberlist_group.html deleted file mode 100644 index 4140c8cdbf..0000000000 --- a/phpBB/styles/subsilver2/template/memberlist_group.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - -
    {L_GROUP_INFORMATION}
    {L_GROUP_NAME}{L_COLON} style="color:#{GROUP_COLOR}">{GROUP_NAME}{AVATAR_IMG}
    {RANK_IMG}{GROUP_RANK}

    {PM_IMG}
    {L_GROUP_DESC}{L_COLON}{GROUP_DESC}

    {GROUP_TYPE}

    diff --git a/phpBB/styles/subsilver2/template/memberlist_im.html b/phpBB/styles/subsilver2/template/memberlist_im.html deleted file mode 100644 index a19229605a..0000000000 --- a/phpBB/styles/subsilver2/template/memberlist_im.html +++ /dev/null @@ -1,44 +0,0 @@ - - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_SEND_IM}
    {L_SEND_IM_EXPLAIN}
    {L_IM_RECIPIENT}{L_COLON} {USERNAME} [ {IM_CONTACT} ] {PRESENCE_IMG}
    {L_IM_MESSAGE}{L_COLON}
    {L_IM_SENT_JABBER}
    {L_IM_NO_JABBER}
    -{S_FORM_TOKEN} -
    - -{L_CLOSE_WINDOW} - - diff --git a/phpBB/styles/subsilver2/template/memberlist_search.html b/phpBB/styles/subsilver2/template/memberlist_search.html deleted file mode 100644 index 12dd10be2e..0000000000 --- a/phpBB/styles/subsilver2/template/memberlist_search.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_FIND_USERNAME}
    {L_FIND_USERNAME_EXPLAIN}
    {L_USERNAME}{L_COLON}{L_EMAIL}{L_COLON} 
    {L_JOINED}{L_COLON} {L_POSTS}{L_COLON}
    {L_LAST_ACTIVE}{L_COLON} {L_POST_IP}{L_COLON} 
    {L_GROUP}{L_COLON}{L_JABBER}{L_COLON} 
    {L_SORT_BY}{L_COLON}   
      
    -{S_FORM_TOKEN} -
    - -
    diff --git a/phpBB/styles/subsilver2/template/memberlist_team.html b/phpBB/styles/subsilver2/template/memberlist_team.html deleted file mode 100644 index a4f38aafc4..0000000000 --- a/phpBB/styles/subsilver2/template/memberlist_team.html +++ /dev/null @@ -1,50 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_USERNAME}{L_FORUMS}{L_PRIMARY_GROUP}{L_RANK}{L_SEND_MESSAGE}
    {group.GROUP_NAME}{group.GROUP_NAME}
    {group.user.USERNAME_FULL}{group.user.FORUMS}-  - - style="font-weight: bold; color:#{group.user.GROUP_COLOR}" href="{group.user.U_GROUP}">{group.user.GROUP_NAME} - - {group.user.GROUP_NAME} - -  {group.user.RANK_IMG}{group.user.RANK_TITLE} {PM_IMG} 
    {L_NO_MEMBERS}
    - -
    - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/memberlist_view.html b/phpBB/styles/subsilver2/template/memberlist_view.html deleted file mode 100644 index 00c627f62e..0000000000 --- a/phpBB/styles/subsilver2/template/memberlist_view.html +++ /dev/null @@ -1,199 +0,0 @@ - - -
    - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_VIEWING_PROFILE}

    {L_USER_PRESENCE}

    {L_USER_FORUM}

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_USER_IS_INACTIVE}
    {L_INACTIVE_REASON}{L_COLON} {USER_INACTIVE_REASON}

    {USERNAME} [ {L_USER_BAN} ] [ {L_USER_ADMIN} ]
    {RANK_TITLE}
    {RANK_IMG}
    {AVATAR_IMG}
    {ONLINE_IMG}
    [ {L_USE_PERMISSIONS} ]
    [ - - {L_REMOVE_FRIEND} - - {L_REMOVE_FOE} - - {L_ADD_FRIEND} | {L_ADD_FOE} - - ]
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_JOINED}{L_COLON} {JOINED}
    {L_LAST_ACTIVE}{L_COLON} {LAST_ACTIVE}
    {L_WARNINGS}{L_COLON} {WARNINGS}
    [ {L_VIEW_NOTES} | {L_WARN_USER} ]
    {L_TOTAL_POSTS}{L_COLON} {POSTS}
    [{POSTS_PCT} / {POSTS_DAY}] -
    [{L_POSTS_IN_QUEUE}]
    [{L_POSTS_IN_QUEUE}] -
    {L_SEARCH_USER_POSTS}
    {L_ACTIVE_IN_FORUM}{L_COLON} {ACTIVE_FORUM}
    [ {ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT} ]-
    {L_ACTIVE_IN_TOPIC}{L_COLON} {ACTIVE_TOPIC}
    [ {ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT} ]-
    -

    {L_CONTACT}

    {L_ABOUT_USER}

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_EMAIL_ADDRESS}{L_COLON} {EMAIL_IMG}
    {L_PM}{L_COLON} {PM_IMG}
    {L_JABBER}{L_COLON} {JABBER_IMG}{USER_JABBER_IMG}
    {custom_fields.PROFILE_FIELD_NAME}{L_COLON} {custom_fields.PROFILE_FIELD_DESC}{custom_fields.PROFILE_FIELD_VALUE}
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_USERGROUPS}{L_COLON}
    {L_AGE}{L_COLON} {AGE}
    {PROFILE_FIELD1_NAME}{L_COLON} {PROFILE_FIELD1_VALUE}
    {custom_fields.PROFILE_FIELD_NAME}{L_COLON} {custom_fields.PROFILE_FIELD_VALUE}
    -

    {L_SIGNATURE}

    {SIGNATURE}
    - -
    - - - -
    - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/message_body.html b/phpBB/styles/subsilver2/template/message_body.html deleted file mode 100644 index b9b502a57f..0000000000 --- a/phpBB/styles/subsilver2/template/message_body.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - -
    {MESSAGE_TITLE}

    {MESSAGE_TEXT}


    - -
    - - - - diff --git a/phpBB/styles/subsilver2/template/overall_footer.html b/phpBB/styles/subsilver2/template/overall_footer.html deleted file mode 100644 index 42ee17f2ed..0000000000 --- a/phpBB/styles/subsilver2/template/overall_footer.html +++ /dev/null @@ -1,27 +0,0 @@ - - - {RUN_CRON_TASK} - - - - -
    - [ {L_ACP} ]

    - - - {CREDIT_LINE} -
    {TRANSLATION_INFO} - -
    [ {DEBUG_OUTPUT} ]
    -
    - - - - - - - -{$SCRIPTS} - - - diff --git a/phpBB/styles/subsilver2/template/overall_header.html b/phpBB/styles/subsilver2/template/overall_header.html deleted file mode 100644 index ebb7b3be4d..0000000000 --- a/phpBB/styles/subsilver2/template/overall_header.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - -{META} -<!-- IF UNREAD_NOTIFICATIONS_COUNT -->({UNREAD_NOTIFICATIONS_COUNT}) <!-- ENDIF --><!-- IF not S_VIEWTOPIC and not S_VIEWFORUM -->{SITENAME} - <!-- ENDIF --><!-- IF S_IN_MCP -->{L_MCP} - <!-- ELSEIF S_IN_UCP -->{L_UCP} - <!-- ENDIF -->{PAGE_TITLE}<!-- IF S_VIEWTOPIC or S_VIEWFORUM --> - {SITENAME}<!-- ENDIF --> - - - - - - - - - - - - - - - - - - - - - - -{$STYLESHEETS} - - - - - - - - - - -
    - -
    - - - - - -
    {SITE_LOGO_IMG}

    {SITENAME}

    {SITE_DESCRIPTION}
    -
    - - - -
    - - - - - -
    {LAST_VISIT_DATE}{CURRENT_TIME}
    -
    - -
    - - - -
    - - - - - -
    - - - - - - - -
    - diff --git a/phpBB/styles/subsilver2/template/pagination.html b/phpBB/styles/subsilver2/template/pagination.html deleted file mode 100644 index b1c1d0e6c9..0000000000 --- a/phpBB/styles/subsilver2/template/pagination.html +++ /dev/null @@ -1,11 +0,0 @@ - - {L_GOTO_PAGE} - - {L_PREVIOUS} - {pagination.PAGE_NUMBER} - {L_ELLIPSIS} - {L_NEXT} - {pagination.PAGE_NUMBER} - - - diff --git a/phpBB/styles/subsilver2/template/posting_attach_body.html b/phpBB/styles/subsilver2/template/posting_attach_body.html deleted file mode 100644 index 8c70e4c831..0000000000 --- a/phpBB/styles/subsilver2/template/posting_attach_body.html +++ /dev/null @@ -1,83 +0,0 @@ -
    - - - - - - - {L_ADD_ATTACHMENT} -
    {L_ADD_ATTACHMENT_EXPLAIN}
    {L_FILENAME}
    {L_FILE_COMMENT} - - - - - -
      - - - - -
    -
    -
    {L_POSTED_ATTACHMENTS}
    {L_FILENAME}{attach_row.FILENAME}
    {L_FILE_COMMENT}{attach_row.S_HIDDEN} - - - - - -
      - - - - -
    -
    -
    - - - - - - -
    {L_INFORMATION}
    {L_DRAFT_LOADED_PM}{L_DRAFT_LOADED}
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_LOAD_DRAFT}
    {L_LOAD_DRAFT_EXPLAIN}
    {L_SAVE_DATE}{L_DRAFT_TITLE}{L_OPTIONS}
    {draftrow.DATE}{draftrow.DRAFT_SUBJECT} -
    {L_TOPIC}{L_COLON} {draftrow.TITLE} -
    {L_FORUM}{L_COLON} {draftrow.TITLE} -
    {L_PRIVATE_MESSAGE} -
    {L_NO_TOPIC_FORUM} -
    {L_LOAD_DRAFT}
    - -
    - - - - - - - - - - - - - - - - - - -
    {L_MOVE}
    {L_UNGLOBALISE_EXPLAIN}

    {L_SELECT_DESTINATION_FORUM}  


      
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_POST_A}
    {ERROR}
    {L_ICON}{L_COLON} - - - - -
    {L_NO_TOPIC_ICON}{L_NO_PM_ICON}
    -
    {L_USERNAME}{L_COLON}
    {L_TO}{L_COLON} - {S_HIDDEN_ADDRESS_FIELD} - - - {to_recipient.NAME}{to_recipient.NAME_FULL}   - - - {L_NO_TO_RECIPIENT} - -
    {L_BCC}{L_COLON} - - - {bcc_recipient.NAME}{bcc_recipient.NAME_FULL}   - - - {L_NO_BCC_RECIPIENT} - -
    {L_SUBJECT}{L_COLON}
    {L_MESSAGE_BODY}{L_COLON}
    {L_MESSAGE_BODY_EXPLAIN} 

    - - - - - - - - - - - - - - - -
    {L_SMILIES}
    - - {smiley.SMILEY_CODE} - -
    {L_MORE_SMILIES}
    - -
    - - - - - - - - - - - - -
    -
    -
    {L_ATTACHMENTS}{L_COLON}  -
    {L_OPTIONS}{L_COLON}
    - - - - - - - - - - - - - - - - - - -
    {BBCODE_STATUS}
    {IMG_STATUS}
    {FLASH_STATUS}
    {URL_STATUS}
    {SMILIES_STATUS}
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_DISABLE_BBCODE}
    {L_DISABLE_SMILIES}
    {L_DISABLE_MAGIC_URL}
    {L_ATTACH_SIG}
    {L_NOTIFY_REPLY}
    {L_LOCK_TOPIC}
    {L_LOCK_POST} [{L_LOCK_POST_EXPLAIN}]
    {L_CHANGE_TOPIC_TO}{L_POST_TOPIC_AS}{L_COLON} {topic_type.L_TOPIC_TYPE}  
    -
    {L_DELETE_POST}{L_COLON} - - - - - - - - - - - -
    {L_DELETE_POST_WARN}
    {L_DELETE_POST_PERMANENTLY}
    -
    {L_STICK_TOPIC_FOR}{L_COLON}
    {L_STICKY_ANNOUNCE_TIME_LIMIT}
     {L_DAYS} {L_STICK_TOPIC_FOR_EXPLAIN}
    {L_EDIT_REASON}{L_COLON}
    - -   -   -   -   -
    {L_POLL_DELETE}{L_COLON}
    {S_HIDDEN_FIELDS} - -   - -   -   - -   -
    - - {S_FORM_TOKEN} - - -
    - - - - - - - - - - - - -
    - - - - - - - - -

    {L_WHO_IS_ONLINE}

    {LOGGED_IN_USER_LIST}
    - - -
    - - - - - -
    - - - diff --git a/phpBB/styles/subsilver2/template/posting_buttons.html b/phpBB/styles/subsilver2/template/posting_buttons.html deleted file mode 100644 index d1c0f79a16..0000000000 --- a/phpBB/styles/subsilver2/template/posting_buttons.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - {L_FONT_SIZE}{L_COLON} -
    - - - - - - - -
    - - onmouseover="helpline('cb_{custom_tags.BBCODE_ID}')" onmouseout="helpline('tip')" /> - -
    - - - - - - colspan="2"> - - {L_FONT_COLOR} - - - diff --git a/phpBB/styles/subsilver2/template/posting_poll_body.html b/phpBB/styles/subsilver2/template/posting_poll_body.html deleted file mode 100644 index 67996eaf33..0000000000 --- a/phpBB/styles/subsilver2/template/posting_poll_body.html +++ /dev/null @@ -1,36 +0,0 @@ - - - {L_ADD_POLL} - - - {L_ADD_POLL_EXPLAIN} - - - {L_POLL_QUESTION}{L_COLON} - - - - {L_POLL_OPTIONS}{L_COLON}
    {L_POLL_OPTIONS_EXPLAIN} - - - - {L_POLL_MAX_OPTIONS}{L_COLON}
    {L_POLL_MAX_OPTIONS_EXPLAIN} - - - - {L_POLL_FOR}{L_COLON} -  {L_DAYS} {L_POLL_FOR_EXPLAIN} - - - - {L_POLL_VOTE_CHANGE}{L_COLON}
    {L_POLL_VOTE_CHANGE_EXPLAIN} - - - - - - - {L_POLL_DELETE}{L_COLON} - checked="checked" /> - - diff --git a/phpBB/styles/subsilver2/template/posting_preview.html b/phpBB/styles/subsilver2/template/posting_preview.html deleted file mode 100644 index b0dbef6a5a..0000000000 --- a/phpBB/styles/subsilver2/template/posting_preview.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - -
    {L_PREVIEW}
    {MINI_POST_IMG}{L_POSTED}{L_COLON} {POST_DATE}     {L_POST_SUBJECT}{L_COLON} {PREVIEW_SUBJECT}

    - - - - - - - - - - -
    {POLL_QUESTION}
    {L_POLL_LENGTH}
    - - - - - - - -
    - - - - - - {poll_option.POLL_OPTION_CAPTION}
    -
    {L_MAX_VOTES}
    -
    - - - - -
    {PREVIEW_MESSAGE}
    - -

    - - - - - - - - - - -
    {L_ATTACHMENTS}{L_COLON}
    {attachment.DISPLAY_ATTACHMENT}
    - -
    _________________
    {PREVIEW_SIGNATURE}
    -
    - -
    diff --git a/phpBB/styles/subsilver2/template/posting_progress_bar.html b/phpBB/styles/subsilver2/template/posting_progress_bar.html deleted file mode 100644 index f9decc506b..0000000000 --- a/phpBB/styles/subsilver2/template/posting_progress_bar.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - -
    - - - - -

    {L_UPLOAD_IN_PROGRESS}

    {PROGRESS_BAR}


    {L_CLOSE_WINDOW}

    -
    - - - diff --git a/phpBB/styles/subsilver2/template/posting_review.html b/phpBB/styles/subsilver2/template/posting_review.html deleted file mode 100644 index c118499564..0000000000 --- a/phpBB/styles/subsilver2/template/posting_review.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - -
    {L_POST_REVIEW}
    {L_POST_REVIEW_EXPLAIN}
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_AUTHOR}{L_MESSAGE}
    {post_review_row.L_IGNORE_POST} - - - - -
    -
    - - - - - - - -
     {L_POST_SUBJECT}{L_COLON} {post_review_row.POST_SUBJECT} 
    -
    - - - - - - - -
    - - - - -
    {post_review_row.MESSAGE}
    - - -

    - - - - - - - - - - -
    {L_ATTACHMENTS}{L_COLON}
    {post_review_row.attachment.DISPLAY_ATTACHMENT}
    - - -
    -
    - - - - - - -
     {post_review_row.MINI_POST_IMG}{post_review_row.MINI_POST_IMG}{L_POSTED}{L_COLON} {post_review_row.POST_DATE}
    -
    -
    -
    - -
    diff --git a/phpBB/styles/subsilver2/template/posting_smilies.html b/phpBB/styles/subsilver2/template/posting_smilies.html deleted file mode 100644 index 7087414fa8..0000000000 --- a/phpBB/styles/subsilver2/template/posting_smilies.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - -
    - - - - - - - -
    {L_SMILIES}
    {smiley.SMILEY_CODE}
    - - {L_GOTO_PAGE} - - {pagination.PAGE_NUMBER} - {pagination.PAGE_NUMBER} - {L_ELLIPSIS} - {pagination.PAGE_NUMBER} - {pagination.PAGE_NUMBER} - - -
    - - {L_CLOSE_WINDOW}
    -
    - diff --git a/phpBB/styles/subsilver2/template/posting_topic_review.html b/phpBB/styles/subsilver2/template/posting_topic_review.html deleted file mode 100644 index 20976861fc..0000000000 --- a/phpBB/styles/subsilver2/template/posting_topic_review.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - -
    {L_TOPIC_REVIEW} - {TOPIC_TITLE}
    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_AUTHOR}{L_MESSAGE}
    {topic_review_row.L_IGNORE_POST} - - - - -
    -
    - - - - - - - -
     {L_POST_SUBJECT}{L_COLON} {topic_review_row.POST_SUBJECT} {QUOTE_IMG}
    -
    - - - - - - - -
    - - - - -
    - - - - {REPORTED_IMG} - -
    - -
    {topic_review_row.MESSAGE}
    - - -

    - - - - - - - - - - -
    {L_ATTACHMENTS}{L_COLON}
    {topic_review_row.attachment.DISPLAY_ATTACHMENT}
    - - - - - -
    -
    - - - - - - -
    [ {L_POST_DETAILS} ]{topic_review_row.MINI_POST_IMG}{topic_review_row.MINI_POST_IMG}{L_POSTED}{L_COLON} {topic_review_row.POST_DATE}
    -
    -
    -
    - -
    diff --git a/phpBB/styles/subsilver2/template/profilefields/bool.html b/phpBB/styles/subsilver2/template/profilefields/bool.html deleted file mode 100644 index f57bd4e4da..0000000000 --- a/phpBB/styles/subsilver2/template/profilefields/bool.html +++ /dev/null @@ -1,7 +0,0 @@ - - - {bool.options.VALUE}    - - checked="checked" /> - - diff --git a/phpBB/styles/subsilver2/template/profilefields/date.html b/phpBB/styles/subsilver2/template/profilefields/date.html deleted file mode 100644 index e2da2463a5..0000000000 --- a/phpBB/styles/subsilver2/template/profilefields/date.html +++ /dev/null @@ -1,5 +0,0 @@ - -{L_DAY}{L_COLON} -{L_MONTH}{L_COLON} -{L_YEAR}{L_COLON} - diff --git a/phpBB/styles/subsilver2/template/profilefields/dropdown.html b/phpBB/styles/subsilver2/template/profilefields/dropdown.html deleted file mode 100644 index 16242da895..0000000000 --- a/phpBB/styles/subsilver2/template/profilefields/dropdown.html +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/phpBB/styles/subsilver2/template/profilefields/int.html b/phpBB/styles/subsilver2/template/profilefields/int.html deleted file mode 100644 index 067921e320..0000000000 --- a/phpBB/styles/subsilver2/template/profilefields/int.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/phpBB/styles/subsilver2/template/profilefields/string.html b/phpBB/styles/subsilver2/template/profilefields/string.html deleted file mode 100644 index 5a98562e2a..0000000000 --- a/phpBB/styles/subsilver2/template/profilefields/string.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/phpBB/styles/subsilver2/template/profilefields/text.html b/phpBB/styles/subsilver2/template/profilefields/text.html deleted file mode 100644 index df2474ad3e..0000000000 --- a/phpBB/styles/subsilver2/template/profilefields/text.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/phpBB/styles/subsilver2/template/profilefields/url.html b/phpBB/styles/subsilver2/template/profilefields/url.html deleted file mode 100644 index 42805aa98d..0000000000 --- a/phpBB/styles/subsilver2/template/profilefields/url.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/phpBB/styles/subsilver2/template/quickreply_editor.html b/phpBB/styles/subsilver2/template/quickreply_editor.html deleted file mode 100644 index 5afc723f48..0000000000 --- a/phpBB/styles/subsilver2/template/quickreply_editor.html +++ /dev/null @@ -1,29 +0,0 @@ -
    - - - - - - - - - - - - - - - - - - -
    {L_QUICKREPLY}
    {L_SUBJECT}{L_COLON}
    {L_MESSAGE}{L_COLON}
    -   - - - {S_FORM_TOKEN} - {QR_HIDDEN_FIELDS} -
    - -
    -
    diff --git a/phpBB/styles/subsilver2/template/report_body.html b/phpBB/styles/subsilver2/template/report_body.html deleted file mode 100644 index 906a957ef4..0000000000 --- a/phpBB/styles/subsilver2/template/report_body.html +++ /dev/null @@ -1,49 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_REPORT_POST}{L_REPORT_MESSAGE}
    {ERROR}
    {L_REPORT_POST_EXPLAIN}{L_REPORT_MESSAGE_EXPLAIN}
    {L_REASON}{L_COLON}
    {L_REPORT_NOTIFY}{L_COLON}
    {L_REPORT_NOTIFY_EXPLAIN}
    checked="checked" />  {L_YES}   checked="checked" />  {L_NO}
    {L_MORE_INFO}{L_COLON}
    {L_CAN_LEAVE_BLANK}
     
    -{S_FORM_TOKEN} -
    - -
    - - - -
    - - diff --git a/phpBB/styles/subsilver2/template/search_body.html b/phpBB/styles/subsilver2/template/search_body.html deleted file mode 100644 index c0199fbae8..0000000000 --- a/phpBB/styles/subsilver2/template/search_body.html +++ /dev/null @@ -1,95 +0,0 @@ - - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_SEARCH_QUERY}
    {L_SEARCH_KEYWORDS}{L_COLON}
    {L_SEARCH_KEYWORDS_EXPLAIN}

    {L_SEARCH_ALL_TERMS}
    {L_SEARCH_ANY_TERMS}
    {L_SEARCH_AUTHOR}{L_COLON}
    {L_SEARCH_AUTHOR_EXPLAIN}
    {L_SEARCH_FORUMS}{L_COLON}
    {L_SEARCH_FORUMS_EXPLAIN}
    {L_SEARCH_OPTIONS}
    {L_SEARCH_SUBFORUMS}{L_COLON} {L_YES}   {L_NO}{L_SEARCH_WITHIN}{L_COLON} {L_SEARCH_TITLE_MSG}
    {L_SEARCH_MSG_ONLY}
    {L_SEARCH_TITLE_ONLY}
    {L_SEARCH_FIRST_POST}
    {L_RESULT_SORT}{L_COLON} {S_SELECT_SORT_KEY}
    {L_SORT_ASCENDING}
    {L_SORT_DESCENDING}
    {L_DISPLAY_RESULTS}{L_COLON} {L_POSTS}   {L_TOPICS}
    {L_RESULT_DAYS}{L_COLON} {S_SELECT_SORT_DAYS}{L_RETURN_FIRST}{L_COLON} {L_POST_CHARACTERS}
    {S_HIDDEN_FIELDS}  
    - -
    - -
    - - - - - - - - - - - - - -
    {L_RECENT_SEARCHES}
    {recentsearch.KEYWORDS}{recentsearch.TIME}
    - -
    - - -
    - - - -
    - -
    - - - - diff --git a/phpBB/styles/subsilver2/template/search_results.html b/phpBB/styles/subsilver2/template/search_results.html deleted file mode 100644 index 23d0b3a146..0000000000 --- a/phpBB/styles/subsilver2/template/search_results.html +++ /dev/null @@ -1,160 +0,0 @@ - - -
    - - - - - - - - - -
    {SEARCH_TITLE}{SEARCH_MATCHES}
    {L_SEARCHED_TOPIC}{L_COLON} {SEARCH_TOPIC}
    {L_SEARCHED_FOR}{L_COLON} {SEARCH_WORDS} {L_IGNORED_TERMS}{L_COLON} {IGNORED_WORDS}
    {L_SEARCH_IN_RESULTS}{L_COLON}
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      {L_TOPICS}  {L_AUTHOR}  {L_REPLIES}  {L_VIEWS}  {L_LAST_POST} 
    {searchresults.TOPIC_FOLDER_IMG} - - - - - - {NEWEST_POST_IMG} - {searchresults.ATTACH_ICON_IMG} {searchresults.TOPIC_TITLE} - - {searchresults.UNAPPROVED_IMG}  - - - {DELETED_IMG}  - - - {REPORTED_IMG}  - - -

    [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON} - - - {searchresults.pagination.PAGE_NUMBER} - {L_ELLIPSIS} - - {searchresults.pagination.PAGE_NUMBER} - - - ]

    - -

    {L_IN} {searchresults.FORUM_TITLE}

    - -

    {searchresults.TOPIC_AUTHOR_FULL}

    {searchresults.TOPIC_REPLIES}

    {searchresults.TOPIC_VIEWS}

    -

    {searchresults.LAST_POST_TIME}

    -

    {searchresults.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG} -

    -
    {L_NO_SEARCH_RESULTS}
    {L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY}{L_COLON} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_AUTHOR}{L_MESSAGE}
    {searchresults.L_IGNORE_POST}

     {L_FORUM}{L_COLON} {searchresults.FORUM_TITLE}   {L_TOPIC}{L_COLON} {searchresults.TOPIC_TITLE}

    - - - - -
    -
    - -  {L_POST_SUBJECT}{L_COLON} {searchresults.POST_SUBJECT} - - [ {L_JUMP_TO_POST} ] - -
    -
    {L_POSTED}{L_COLON} {searchresults.POST_DATE} 
    -
    -

    {L_REPLIES}{L_COLON} {searchresults.TOPIC_REPLIES}
    {L_VIEWS}{L_COLON} {searchresults.TOPIC_VIEWS}


    - - - - -
    {searchresults.MESSAGE}
    -
    {L_NO_SEARCH_RESULTS}
    {L_SORT_BY}{L_COLON} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
    - - -
    - -
    {PAGE_NUMBER} [ {SEARCH_MATCHES} ]
    - - -

    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/searchbox.html b/phpBB/styles/subsilver2/template/searchbox.html deleted file mode 100644 index 49de299ea2..0000000000 --- a/phpBB/styles/subsilver2/template/searchbox.html +++ /dev/null @@ -1 +0,0 @@ -
    {L_SEARCH_FOR}{L_COLON} {S_SEARCH_LOCAL_HIDDEN_FIELDS}
    diff --git a/phpBB/styles/subsilver2/template/simple_footer.html b/phpBB/styles/subsilver2/template/simple_footer.html deleted file mode 100644 index d69c56fb8c..0000000000 --- a/phpBB/styles/subsilver2/template/simple_footer.html +++ /dev/null @@ -1,15 +0,0 @@ - -
    - -
    - {CREDIT_LINE} -
    - - - - - - -{$SCRIPTS} - - diff --git a/phpBB/styles/subsilver2/template/simple_header.html b/phpBB/styles/subsilver2/template/simple_header.html deleted file mode 100644 index 0c3dff4a05..0000000000 --- a/phpBB/styles/subsilver2/template/simple_header.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - -{META} -{SITENAME} • <!-- IF S_IN_MCP -->{L_MCP} • <!-- ELSEIF S_IN_UCP -->{L_UCP} • <!-- ENDIF -->{PAGE_TITLE} - - - - - - -{$STYLESHEETS} - - - - - - - - -
    diff --git a/phpBB/styles/subsilver2/template/timezone.js b/phpBB/styles/subsilver2/template/timezone.js deleted file mode 100644 index c5829c0bb1..0000000000 --- a/phpBB/styles/subsilver2/template/timezone.js +++ /dev/null @@ -1,21 +0,0 @@ -(function($) { // Avoid conflicts with other libraries - -"use strict"; - -$('#tz_date').change(function() { - phpbb.timezoneSwitchDate(false); -}); - -$('#tz_select_date_suggest').click(function(){ - phpbb.timezonePreselectSelect(true); -}); - -$(document).ready( - phpbb.timezoneEnableDateSelection -); - -$(document).ready( - phpbb.timezonePreselectSelect($('#tz_select_date_suggest').attr('timezone-preselect') == 'true') -); - -})(jQuery); // Avoid conflicts with other libraries diff --git a/phpBB/styles/subsilver2/template/timezone_option.html b/phpBB/styles/subsilver2/template/timezone_option.html deleted file mode 100644 index 0f27719f86..0000000000 --- a/phpBB/styles/subsilver2/template/timezone_option.html +++ /dev/null @@ -1,20 +0,0 @@ - - {L_BOARD_TIMEZONE}{L_COLON} - - - - - - - - - diff --git a/phpBB/styles/subsilver2/template/ucp_agreement.html b/phpBB/styles/subsilver2/template/ucp_agreement.html deleted file mode 100644 index fca7eb2368..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_agreement.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - -
    - - - - -
    {L_LANGUAGE}{L_COLON}
    - {S_HIDDEN_FIELDS} -
    - - -
    - - - - - - - - -
    {SITENAME} - {L_REGISTRATION}
    - - - - - - - - -

    {L_COPPA_BIRTHDAY}

    {L_COPPA_NO} :: {L_COPPA_YES}

    - -
    {L_TERMS_OF_USE}

    - -
    -

    - -
    -
    -
    - {S_HIDDEN_FIELDS} - {S_FORM_TOKEN} -
    - - - - - - - - - - -
    {SITENAME} - {AGREEMENT_TITLE}
    - - - - -
    -
    {AGREEMENT_TEXT}

    -
    - {L_BACK} -
    -
    -
    - - - - diff --git a/phpBB/styles/subsilver2/template/ucp_attachments.html b/phpBB/styles/subsilver2/template/ucp_attachments.html deleted file mode 100644 index 0f6101aac7..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_attachments.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    #{L_FILENAME}{L_POST_TIME}{L_FILESIZE}{L_DOWNLOADS}{L_DELETE}
    - - - - - - -
     [ {TOTAL_ATTACHMENTS} ] 
    -
     {attachrow.ROW_NUMBER} {attachrow.FILENAME}
    {L_PM}{L_COLON} {L_TOPIC}{L_COLON} {attachrow.TOPIC_TITLE}
     {attachrow.POST_TIME} {attachrow.SIZE}{attachrow.DOWNLOAD_COUNT}
    {L_SORT_BY}{L_COLON}  
     
    - - - - - - - - - - - - -
    {L_TITLE}
    {L_UCP_NO_ATTACHMENTS}
    - - - - diff --git a/phpBB/styles/subsilver2/template/ucp_auth_link.html b/phpBB/styles/subsilver2/template/ucp_auth_link.html deleted file mode 100644 index 75e3133fcf..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_auth_link.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - -
    {L_UCP_AUTH_LINK_TITLE}
    {ERROR}
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_auth_link_oauth.html b/phpBB/styles/subsilver2/template/ucp_auth_link_oauth.html deleted file mode 100644 index 80564d207b..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_auth_link_oauth.html +++ /dev/null @@ -1,34 +0,0 @@ - - - {oauth.SERVICE_NAME} - - - - -
    - - - - - - - - - - - - - - - - - - -
    {L_UCP_AUTH_LINK_ID}{L_COLON}{oauth.UNIQUE_ID}
     
    {L_UCP_AUTH_LINK_ASK}
    - {oauth.HIDDEN_FIELDS} - {S_HIDDEN_FIELDS} - {S_FORM_TOKEN} -
    - - - diff --git a/phpBB/styles/subsilver2/template/ucp_avatar_options_gravatar.html b/phpBB/styles/subsilver2/template/ucp_avatar_options_gravatar.html deleted file mode 100644 index b8840e0aab..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_avatar_options_gravatar.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - -
    {L_GRAVATAR_AVATAR_EMAIL}{L_COLON}
    {L_GRAVATAR_AVATAR_EMAIL_EXPLAIN}
    {L_GRAVATAR_AVATAR_SIZE}{L_COLON}
    {L_GRAVATAR_AVATAR_SIZE_EXPLAIN}
    - {L_PIXEL} ×  - {L_PIXEL} -
    diff --git a/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html b/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html deleted file mode 100644 index 7beddfc109..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - -
    {L_AVATAR_CATEGORY}{L_COLON}   -
    - - - - - - - - - - - - - - - - - -
    {avatar_local_col.avatar_local_col.AVATAR_NAME}
    {L_NO_AVATAR_CATEGORY}
    -
    {L_NO_AVATARS}
    diff --git a/phpBB/styles/subsilver2/template/ucp_avatar_options_remote.html b/phpBB/styles/subsilver2/template/ucp_avatar_options_remote.html deleted file mode 100644 index 50ebb9b93d..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_avatar_options_remote.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - -
    {L_LINK_REMOTE_AVATAR}{L_COLON}
    {L_LINK_REMOTE_AVATAR_EXPLAIN}
    {L_LINK_REMOTE_SIZE}{L_COLON}
    {L_LINK_REMOTE_SIZE_EXPLAIN}
    {L_PIXEL} × {L_PIXEL}
    diff --git a/phpBB/styles/subsilver2/template/ucp_avatar_options_upload.html b/phpBB/styles/subsilver2/template/ucp_avatar_options_upload.html deleted file mode 100644 index 6b813baeaa..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_avatar_options_upload.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - -
    {L_UPLOAD_AVATAR_FILE}{L_COLON}
    {L_UPLOAD_AVATAR_URL}{L_COLON}
    {L_UPLOAD_AVATAR_URL_EXPLAIN}
    diff --git a/phpBB/styles/subsilver2/template/ucp_footer.html b/phpBB/styles/subsilver2/template/ucp_footer.html deleted file mode 100644 index 57adb2da97..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_footer.html +++ /dev/null @@ -1,13 +0,0 @@ - - {S_FORM_TOKEN} - - -{S_FORM_TOKEN} - -
    - - - -
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_groups_manage.html b/phpBB/styles/subsilver2/template/ucp_groups_manage.html deleted file mode 100644 index 55c1c20528..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_groups_manage.html +++ /dev/null @@ -1,230 +0,0 @@ - - - - - -
    -

    {L_WARNING}

    -

    {ERROR_MSG}

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_USERGROUPS}
    {L_GROUPS_EXPLAIN}
    {L_GROUP_DETAILS}
    for="group_name">{L_GROUP_NAME}{L_COLON} style="color: #{GROUP_COLOUR};">{GROUP_NAME}
    -
    checked="checked" /> {L_PARSE_BBCODE}   checked="checked" /> {L_PARSE_SMILIES}   checked="checked" /> {L_PARSE_URLS} -

    {L_GROUP_TYPE_EXPLAIN}
    - {L_GROUP_OPEN}   - {L_GROUP_REQUEST}   - {L_GROUP_CLOSED}   - {L_GROUP_HIDDEN} -
    {L_GROUP_SETTINGS_SAVE}

    {L_GROUP_COLOR_EXPLAIN}
    -    - [ {L_COLOUR_SWATCH} ] - -
    {L_GROUP_AVATAR}

    {L_AVATAR_EXPLAIN}
    {AVATAR_IMAGE}

     {L_DELETE_AVATAR}
    {L_AVATAR_FEATURES_DISABLED}
    {L_AVATAR_SELECT}
    {L_AVATAR_TYPE}{L_COLON} -
    {avatar_drivers.L_EXPLAIN}
    {avatar_drivers.OUTPUT}
    {S_HIDDEN_FIELDS}  -
    - - - - - -

    {L_GROUP_MEMBERS}

    - -

    {L_GROUP_MEMBERS_EXPLAIN}

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_USERNAME}{L_GROUP_DEFAULT}{L_JOINED}{L_POSTS}{L_MARK}
    {L_GROUP_LEAD}
    {leader.USERNAME_FULL}{L_YES}{L_NO}{leader.JOINED}{leader.USER_POSTS}
    {L_GROUP_PENDING}
    {L_GROUP_APPROVED}
    {member.USERNAME_FULL}{L_YES}{L_NO}{member.JOINED}{member.USER_POSTS}
    {L_GROUPS_NO_MEMBERS}
    - - - -
    -
    - -

    {L_ADD_USERS}

    - -

    {L_ADD_USERS_UCP_EXPLAIN}

    - - - - - - - - - - - - - - - - -
    {L_ADD_USERS}

    {L_USER_GROUP_DEFAULT_EXPLAIN}
    {L_YES}   {L_NO}

    {L_USERNAMES_EXPLAIN}

    [ {L_FIND_USERNAME} ]
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_USERGROUPS}
    {L_GROUPS_EXPLAIN}
    {L_GROUP_DETAILS}{L_OPTIONS}
    {L_GROUP_LEADER}
    style="color: #{leader.GROUP_COLOUR};">{leader.GROUP_NAME}

    {leader.GROUP_DESC}

    {L_EDIT}{L_GROUP_LIST}
    {L_NO_LEADERS}
     
    - - - - diff --git a/phpBB/styles/subsilver2/template/ucp_groups_membership.html b/phpBB/styles/subsilver2/template/ucp_groups_membership.html deleted file mode 100644 index 846d48007e..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_groups_membership.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_USERGROUPS}
    {L_GROUPS_EXPLAIN}
    {L_GROUP_DETAILS}{L_SELECT}
    {L_GROUP_LEADER}
    checked="checked" value="{leader.GROUP_ID}" /> - style="color: #{leader.GROUP_COLOUR};">{leader.GROUP_NAME} -
    {leader.GROUP_DESC} -
    {leader.GROUP_STATUS} -
    {L_GROUP_MEMBER}
    checked="checked" value="{member.GROUP_ID}" /> - style="color: #{member.GROUP_COLOUR};">{member.GROUP_NAME} -
    {member.GROUP_DESC} -
    {member.GROUP_STATUS} -
    {L_GROUP_PENDING}
      - style="color: #{pending.GROUP_COLOUR};">{pending.GROUP_NAME} -
    {pending.GROUP_DESC} -
    {pending.GROUP_STATUS} -
    {L_GROUP_NONMEMBER}
      - style="color: #{nonmember.GROUP_COLOUR};">{nonmember.GROUP_NAME} -
    {nonmember.GROUP_DESC} -
    {nonmember.GROUP_STATUS} -
    {L_SELECT}{L_COLON}   
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_header.html b/phpBB/styles/subsilver2/template/ucp_header.html deleted file mode 100644 index e3aaef6943..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_header.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - -
    - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_PM_TO}
    {L_USERNAME}{L_COLON}
    [ {L_FIND_USERNAME} ]
     
    {L_USERNAMES}{L_COLON}

    - [ {L_FIND_USERNAME} ] -
    {L_USERGROUPS}{L_COLON}
      
      
    -
    - - - - - - - - - - - - - -
    {L_OPTIONS}
    {l_block1.L_TITLE} - - - - - - - -
    - - - - - - - -
    {l_block1.L_TITLE} - -
    - -
    - - - - - - - - - - - - - - - - -
    {L_MESSAGE_COLOURS}
    {pm_colour_info.LANG}{pm_colour_info.IMG}{pm_colour_info.LANG}
    - -
    - - - - - - - - - - -
    {L_FRIENDS}
    - - {L_FRIENDS_ONLINE} - - - -
    - - {L_FRIENDS_OFFLINE} - - - -
    - - -
    diff --git a/phpBB/styles/subsilver2/template/ucp_login_link.html b/phpBB/styles/subsilver2/template/ucp_login_link.html deleted file mode 100644 index 5d8e3ee27b..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_login_link.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - -
    {SITENAME} - {L_LOGIN_LINK}
    {L_LOGIN_LINK_EXPLAIN}
    {LOGIN_LINK_ERROR}
    - - - - - - - - - -
    {L_REGISTER}
    {S_HIDDEN_FIELDS}
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - {S_LOGIN_REDIRECT} - - - - -
    {L_LOGIN}
    {LOGIN_ERROR}
     {S_HIDDEN_FIELDS}
    -
    -
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_main_bookmarks.html b/phpBB/styles/subsilver2/template/ucp_main_bookmarks.html deleted file mode 100644 index e91417503f..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_main_bookmarks.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_UCP}
    {L_BOOKMARKS_EXPLAIN}
    {L_BOOKMARKS}
    {L_BOOKMARKS_DISABLED}
    - - - - - - -
     [ {TOTAL_TOPICS} ] 
    -
    {topicrow.TOPIC_FOLDER_IMG}{L_DELETED_TOPIC} -

    {NEWEST_POST_IMG} {topicrow.ATTACH_ICON_IMG} {topicrow.TOPIC_TITLE}

    - {L_GLOBAL_ANNOUNCEMENT}{L_FORUM}{L_COLON} {topicrow.FORUM_NAME} - -

    [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON} - - - {topicrow.pagination.PAGE_NUMBER} - {L_ELLIPSIS} - - {topicrow.pagination.PAGE_NUMBER} - - - ]

    - -
    -

    {topicrow.LAST_POST_TIME}

    -

    {topicrow.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG} -

    -
    {L_NO_BOOKMARKS}
     
    - - - - - - diff --git a/phpBB/styles/subsilver2/template/ucp_main_drafts.html b/phpBB/styles/subsilver2/template/ucp_main_drafts.html deleted file mode 100644 index d63d678250..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_main_drafts.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_UCP}
    {L_DRAFTS_EXPLAIN}
    {ERROR}
    {L_SAVE_DATE}{L_DRAFT_TITLE}{L_OPTIONS}{L_DELETE}
    {draftrow.DATE} -

    {draftrow.DRAFT_SUBJECT}

    - {L_TOPIC}{L_COLON} {draftrow.TITLE} - {L_FORUM}{L_COLON} {draftrow.TITLE} - {L_PRIVATE_MESSAGE} - {L_NO_TOPIC_FORUM} -
    {L_LOAD_DRAFT}
    {L_VIEW_EDIT}
    {L_NO_SAVED_DRAFTS}
     
    {L_SUBJECT}{L_COLON}
    {L_MESSAGE}{L_COLON}
    {L_EDIT_DRAFT_EXPLAIN}
    - - - - - - - - - -
    - - - - -
    -
    -
    -

    {L_BACK_TO_DRAFTS}

    {S_HIDDEN_FIELDS}  
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_main_front.html b/phpBB/styles/subsilver2/template/ucp_main_front.html deleted file mode 100644 index 5dea2b4f03..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_main_front.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_UCP}

    {L_UCP_WELCOME}

    {L_IMPORTANT_NEWS}
    {topicrow.TOPIC_FOLDER_IMG} -

    {NEWEST_POST_IMG} {topicrow.ATTACH_ICON_IMG} {topicrow.TOPIC_TITLE}

    {topicrow.GOTO_PAGE}

    -
    -

    {topicrow.LAST_POST_TIME}

    -

    {topicrow.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG} -

    -
    {L_NO_IMPORTANT_NEWS}
    {L_YOUR_DETAILS}
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_JOINED}{L_COLON} {JOINED}
    {L_TOTAL_POSTS}{L_COLON} {POSTS}
    [{POSTS_PCT} / {POSTS_DAY}]
    {L_SEARCH_YOUR_POSTS}
    {POSTS}
    {L_ACTIVE_IN_FORUM}{L_COLON} {ACTIVE_FORUM}
    [ {ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT} ]-
    {L_ACTIVE_IN_TOPIC}{L_COLON} {ACTIVE_TOPIC}
    [ {ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT} ]-
    {L_YOUR_WARNINGS}{L_COLON} {WARNING_IMG} [ {WARNINGS} ]
    -
     
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_main_subscribed.html b/phpBB/styles/subsilver2/template/ucp_main_subscribed.html deleted file mode 100644 index c6ae1b6cab..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_main_subscribed.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_UCP}
    {L_WATCHED_EXPLAIN}
    {L_WATCHED_FORUMS}
    {forumrow.FORUM_FOLDER_IMG}

    {forumrow.FORUM_NAME}

    {forumrow.LAST_POST_TIME}
    {forumrow.LAST_POST_AUTHOR_FULL} {LAST_POST_IMG}{L_NO_POSTS}
    {L_NO_WATCHED_FORUMS}
    {L_WATCHED_TOPICS}
    - - - - - - -
     [ {TOTAL_TOPICS} ] 
    -
    {topicrow.TOPIC_FOLDER_IMG} -

    - {NEWEST_POST_IMG} {topicrow.ATTACH_ICON_IMG}{topicrow.TOPIC_TITLE} -

    - {L_GLOBAL_ANNOUNCEMENT}{L_FORUM}{L_COLON} {topicrow.FORUM_NAME} - -

    [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON} - - - {topicrow.pagination.PAGE_NUMBER} - {L_ELLIPSIS} - - {topicrow.pagination.PAGE_NUMBER} - - - ]

    - -
    -

    {topicrow.LAST_POST_TIME}

    -

    {topicrow.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG} -

    -
    {L_NO_WATCHED_TOPICS}
     
    - - - - - diff --git a/phpBB/styles/subsilver2/template/ucp_notifications.html b/phpBB/styles/subsilver2/template/ucp_notifications.html deleted file mode 100644 index b0d2925b68..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_notifications.html +++ /dev/null @@ -1,141 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {TITLE}
    {TITLE_EXPLAIN}
    {L_NOTIFICATION_TYPE}{L_NOTIFICATIONS}{notification_methods.NAME}
    {notification_types.GROUP_NAME}
    - {notification_types.NAME} -
       {notification_types.EXPLAIN} -
    checked="checked" /> checked="checked" />
    - - {S_HIDDEN_FIELDS} -    - - {S_FORM_TOKEN} -
    - - - - - -
    - - - - - -
    - - - - - - -
     {L_NOTIFICATIONS} [ {TOTAL_COUNT}
    - -
    -
    - -
    - - - - - - - - - - - - - - - - - - -
    - - - - -
    -
    {L_NOTIFICATIONS}{L_MARK_READ}
    - {notification_list.AVATAR} - - - - {notification_list.FORMATTED_TITLE} {notification_list.REFERENCE} -
    - {notification_list.FORUM}
    - {notification_list.REASON}
    - {notification_list.TIME} -
    -
    - disabled="disabled" /> -
    - - {S_HIDDEN_FIELDS} - - {S_FORM_TOKEN} -
    -
    - - - - - - -
    - - - - -
    - -
    -
    - - - - - - - -
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_pm_history.html b/phpBB/styles/subsilver2/template/ucp_pm_history.html deleted file mode 100644 index c07edb0f68..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_pm_history.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - -
    {L_MESSAGE_HISTORY}
    - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_AUTHOR}{L_MESSAGE}
    - - - - -
    -
    class="current"> -
    {L_PM_SUBJECT}{L_COLON} {history_row.SUBJECT}
    {L_FOLDER}{L_COLON} {history_row.FOLDER}
    -
    - - - - - - - -
    - - - - -
    {history_row.MESSAGE}{L_MESSAGE_REMOVED_FROM_OUTBOX}
    -
    - - - - - - -
     {history_row.MINI_POST_IMG}{L_SENT_AT}{L_COLON} {history_row.SENT_DATE}
    -
    -
    {L_VIEW_PM}
    -
    - -
    diff --git a/phpBB/styles/subsilver2/template/ucp_pm_message_footer.html b/phpBB/styles/subsilver2/template/ucp_pm_message_footer.html deleted file mode 100644 index 20c5c7fe9f..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_pm_message_footer.html +++ /dev/null @@ -1,47 +0,0 @@ - - - {S_FORM_TOKEN} - - - - - - - -
    - - - - - -
    - - - {L_PRINT_PM} | - {L_FORWARD_PM} - | {L_REPLY_TO_ALL} - - - - - -
    - - - -   - {S_FORM_TOKEN} -
    - - -
    - {L_DISPLAY_MESSAGES}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} - {S_FORM_TOKEN} -
    - -
    -
    - - - - diff --git a/phpBB/styles/subsilver2/template/ucp_pm_message_header.html b/phpBB/styles/subsilver2/template/ucp_pm_message_header.html deleted file mode 100644 index 370fa673dd..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_pm_message_header.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - -
    - - - - - -
    - - - - - - - - - - -
     [ {FOLDER_CUR_MESSAGES}/{FOLDER_MAX_MESSAGES} {L_MESSAGES} ({FOLDER_PERCENT}%) ]  [ {FOLDER_CUR_MESSAGES} {L_MESSAGES} ] 
    - - - - - - {L_VIEW_PREVIOUS_HISTORY} | {L_VIEW_NEXT_HISTORY} | - {L_VIEW_PREVIOUS_PM} | {L_VIEW_NEXT_PM}  - - -
    -
    diff --git a/phpBB/styles/subsilver2/template/ucp_pm_options.html b/phpBB/styles/subsilver2/template/ucp_pm_options.html deleted file mode 100644 index beb867c75a..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_pm_options.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - - -
    - {ERROR_MESSAGE} - {NOTIFICATION_MESSAGE} -
    -
    - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_ADD_NEW_RULE}
    {L_IF}{L_COLON}{CHECK_CURRENT} 
     {RULE_CURRENT} 
      - - - - -  [ {L_FIND_USERNAME} ] - - {L_NO_GROUPS} - - - {COND_CURRENT} - - -  
     {ACTION_CURRENT} 
    - -
    - - - - - - - - - - - - - - - - - - - -
    {L_DEFINED_RULES}
    #{rule.COUNT}{L_IF} {rule.CHECK}{rule.RULE}{rule.STRING}{rule.ACTION} -> {rule.FOLDER}
    {L_NO_RULES_DEFINED}
    - -
    - - - - - - - - - - - - - - - - - -
    {L_RENAME_FOLDER}
    {L_RENAME_FOLDER}{L_COLON}
    {L_NEW_FOLDER_NAME}{L_COLON}
    - -
    - - - - - - - - - - - - - - - - - - - - -
    {L_ADD_FOLDER}
    {L_MAX_FOLDER_REACHED}
    {L_ADD_FOLDER}{L_COLON}
    - - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    {L_REMOVE_FOLDER}
    {L_REMOVE_FOLDER}{L_COLON} {L_AND}
      {L_MOVE_DELETED_MESSAGES_TO}  
      {L_DELETE_MESSAGES_IN_FOLDER}
     
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_FOLDER_OPTIONS}
    {L_IF_FOLDER_FULL}{L_COLON}  {L_DELETE_OLDEST_MESSAGES}
      {L_MOVE_TO_FOLDER}{L_COLON}
      {L_HOLD_NEW_MESSAGES}
    {L_DEFAULT_ACTION}{L_COLON}
    {L_DEFAULT_ACTION_EXPLAIN}
    {DEFAULT_ACTION}
    -{S_FORM_TOKEN} -
    - diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewfolder.html b/phpBB/styles/subsilver2/template/ucp_pm_viewfolder.html deleted file mode 100644 index edcf553b84..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_pm_viewfolder.html +++ /dev/null @@ -1,131 +0,0 @@ - - -
    - - - - - -
    - - - - - - - -
    - - - - - - - - - - - - - - - - - -
    {L_OPTIONS}
    {L_DELIMITER}{L_COLON}
    {L_ENCLOSURE}{L_COLON}
      
    - {S_FORM_TOKEN} - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - {RULE_REMOVED_MESSAGES} -
    - - - {NOT_MOVED_MESSAGES}
    {RELEASE_MESSAGE_INFO} - -
     {L_SUBJECT}  {L_RECIPIENTS}{L_AUTHOR}  {L_SENT_AT}  {L_MARK} 
    {messagerow.FOLDER_IMG}{messagerow.PM_ICON_IMG} - -   - - {messagerow.PM_IMG}  - - - - {messagerow.ATTACH_ICON_IMG} - - {L_MESSAGE_REMOVED_FROM_OUTBOX}
    - {L_DELETE_MESSAGE} - - {messagerow.SUBJECT} - - - {REPORTED_IMG}  - - -
    {L_PM_FROM_REMOVED_AUTHOR} - -

    {messagerow.RECIPIENTS}{messagerow.MESSAGE_AUTHOR_FULL}

    {messagerow.SENT_TIME}

    - - {L_USER_NEW_PERMISSION_DISALLOWED}{L_NO_AUTH_SEND_MESSAGE} - - {L_NO_MESSAGES} - -
    - - - - - - - -
    - -
     
    -
      
    - -
    - -
    - - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage.html b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage.html deleted file mode 100644 index 9536b1f8c5..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage.html +++ /dev/null @@ -1,136 +0,0 @@ - - -
    - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_PM_SUBJECT}{L_COLON}{SUBJECT}
    {L_PM_FROM}{L_COLON}{MESSAGE_AUTHOR_FULL}
    {L_SENT_AT}{L_COLON}{SENT_DATE}
    {L_TO}{L_COLON} - - {to_recipient.NAME}{to_recipient.NAME_FULL}  - -
    {L_BCC}{L_COLON} - - {bcc_recipient.NAME}{bcc_recipient.NAME_FULL}  - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - -
    {L_MESSAGE}
    - - - - -
    -
    {MESSAGE}
    - - -

    - - - - - - - - - - -
    {L_ATTACHMENTS}{L_COLON}
    {attachment.DISPLAY_ATTACHMENT}
    - - - -

    {L_DOWNLOAD_NOTICE}
    - - -
    _________________
    {SIGNATURE}
    - - - {EDITED_MESSAGE} - - -

    - - - - - -
    {REPORT_IMG} {DELETE_IMG}
    - -
    -
    - - -
    - -
    - - -
    - -
    - - - - diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html deleted file mode 100644 index f70f39f9d8..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - -{SITENAME} :: {PAGE_TITLE} - - - - - - - - - - - - - - - - - -
    {SITENAME}
    {L_PRIVATE_MESSAGING}

    {SUBJECT}
    {PAGE_NUMBER}
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    {L_PM_FROM}{L_COLON} {MESSAGE_AUTHOR} [ {SENT_DATE} ]
    {L_TO}{L_COLON} - - class="sep">{to_recipient.NAME}  - -
    {L_BCC}{L_COLON} - - class="sep">{bcc_recipient.NAME}  - -

    {MESSAGE}
    - -
    - - - - - - - - - -
    {PAGE_NUMBER}{S_TIMEZONE}
    Powered by phpBB® Forum Software © phpBB Limited
    https://www.phpbb.com/
    - - - diff --git a/phpBB/styles/subsilver2/template/ucp_prefs_personal.html b/phpBB/styles/subsilver2/template/ucp_prefs_personal.html deleted file mode 100644 index 1c76e3226d..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_prefs_personal.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {ERROR}
    {L_SHOW_EMAIL}{L_COLON} checked="checked" />{L_YES}   checked="checked" />{L_NO}
    {L_ADMIN_EMAIL}{L_COLON} checked="checked" />{L_YES}   checked="checked" />{L_NO}
    {L_ALLOW_PM}{L_COLON}
    {L_ALLOW_PM_EXPLAIN}
    checked="checked" />{L_YES}   checked="checked" />{L_NO}
    {L_HIDE_ONLINE}{L_COLON}
    {L_HIDE_ONLINE_EXPLAIN}
    checked="checked" />{L_YES}   checked="checked" />{L_NO}
    {L_NOTIFY_METHOD}{L_COLON}
    {L_NOTIFY_METHOD_EXPLAIN}
    checked="checked" />{L_NOTIFY_METHOD_EMAIL}   checked="checked" />{L_NOTIFY_METHOD_IM}   checked="checked" />{L_NOTIFY_METHOD_BOTH}
    {L_BOARD_LANGUAGE}{L_COLON}
    {L_BOARD_STYLE}{L_COLON}
    {L_BOARD_DATE_FORMAT}{L_COLON}
    {L_BOARD_DATE_FORMAT_EXPLAIN}
    - -
    style="display:none;">
    -
    {S_HIDDEN_FIELDS}  
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_prefs_post.html b/phpBB/styles/subsilver2/template/ucp_prefs_post.html deleted file mode 100644 index 0a558b863c..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_prefs_post.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {ERROR}
    {L_DEFAULT_BBCODE}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {L_DEFAULT_SMILIES}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {L_DEFAULT_ADD_SIG}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {L_DEFAULT_NOTIFY}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {S_HIDDEN_FIELDS}  
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_prefs_view.html b/phpBB/styles/subsilver2/template/ucp_prefs_view.html deleted file mode 100644 index c10c458627..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_prefs_view.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {ERROR}
    {L_VIEW_IMAGES}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {L_VIEW_FLASH}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {L_VIEW_SMILIES}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {L_VIEW_SIGS}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {L_VIEW_AVATARS}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {L_DISABLE_CENSORS}{L_COLON} checked="checked" />{L_YES}    checked="checked" />{L_NO}
    {L_VIEW_TOPICS_DAYS}{L_COLON}{S_TOPIC_SORT_DAYS}
    {L_VIEW_TOPICS_KEY}{L_COLON}{S_TOPIC_SORT_KEY}
    {L_VIEW_TOPICS_DIR}{L_COLON}{S_TOPIC_SORT_DIR}
    {L_VIEW_POSTS_DAYS}{L_COLON}{S_POST_SORT_DAYS}
    {L_VIEW_POSTS_KEY}{L_COLON}{S_POST_SORT_KEY}
    {L_VIEW_POSTS_DIR}{L_COLON}{S_POST_SORT_DIR}
    {S_HIDDEN_FIELDS}  
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_profile_autologin_keys.html b/phpBB/styles/subsilver2/template/ucp_profile_autologin_keys.html deleted file mode 100644 index 3f63319b59..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_profile_autologin_keys.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {ERROR}
    {L_PROFILE_AUTOLOGIN_KEYS}
    {L_LOGIN_KEY}{L_IP}{L_LOGIN_TIME}{L_MARK}
    {sessions.IP}{sessions.LOGIN_TIME}
    {L_PROFILE_NO_AUTOLOGIN_KEYS}
    - {S_HIDDEN_FIELDS} - {S_FORM_TOKEN} -
    - - - - - - diff --git a/phpBB/styles/subsilver2/template/ucp_profile_avatar.html b/phpBB/styles/subsilver2/template/ucp_profile_avatar.html deleted file mode 100644 index fc52c149c6..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_profile_avatar.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {ERROR}
    {L_CURRENT_IMAGE}{L_COLON}
    {L_AVATAR_EXPLAIN}

    - {AVATAR}

     {L_DELETE_AVATAR} - -
    {L_AVATAR_FEATURES_DISABLED}
    {L_AVATAR_SELECT}
    {L_AVATAR_TYPE}{L_COLON} -
    {avatar_drivers.L_EXPLAIN}
    {avatar_drivers.OUTPUT}
    {S_HIDDEN_FIELDS}  
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html b/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html deleted file mode 100644 index 2d0140a15d..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {ERROR}
    {L_PROFILE_INFO_NOTICE}
    {L_UCP_JABBER}{L_COLON}
    {L_BIRTHDAY}{L_COLON}
    {L_BIRTHDAY_EXPLAIN}
    {L_DAY}{L_COLON} {L_MONTH}{L_COLON} {L_YEAR}{L_COLON}
    - {profile_fields.LANG_NAME}{L_COLON} - * -
    {profile_fields.LANG_EXPLAIN} -
    {profile_fields.FIELD}
    {profile_fields.ERROR}
    {S_HIDDEN_FIELDS}  
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html b/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html deleted file mode 100644 index d8fe84bf79..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {L_FORCE_PASSWORD_EXPLAIN}
    {ERROR}
    {L_USERNAME}{L_COLON}
    {L_USERNAME_EXPLAIN}
    {USERNAME}
    {L_EMAIL_ADDRESS}{L_COLON} {EMAIL}
    {L_NEW_PASSWORD}{L_COLON}
    {L_CHANGE_PASSWORD_EXPLAIN}
    {L_CONFIRM_PASSWORD}{L_COLON}
    {L_CONFIRM_PASSWORD_EXPLAIN}
    {L_CONFIRM_CHANGES}
    {L_CURRENT_PASSWORD}{L_COLON}
    {L_CURRENT_CHANGE_PASSWORD_EXPLAIN}{L_CURRENT_PASSWORD_EXPLAIN}
    {S_HIDDEN_FIELDS}  
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_profile_signature.html b/phpBB/styles/subsilver2/template/ucp_profile_signature.html deleted file mode 100644 index 5a2690edda..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_profile_signature.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {L_SIGNATURE_EXPLAIN}
    {ERROR}
    - {L_SIGNATURE_EXPLAIN} - - - - - - - - - - - - -
    {L_SMILIES}
    - - {smiley.SMILEY_CODE} - -
    {L_MORE_SMILIES}
    -
    - - - - - - - - - - - - - - -
    - - - - -
    -
    -
    -
    {L_OPTIONS}
    - - - - - - - - - - - - - - - - -
    {BBCODE_STATUS}
    {IMG_STATUS}
    {FLASH_STATUS}
    {URL_STATUS}
    {SMILIES_STATUS}
    -
    - - - - - - - - - - - - - - - - - - - -
    {L_DISABLE_BBCODE}
    {L_DISABLE_SMILIES}
    {L_DISABLE_MAGIC_URL}
    -
    {L_SIGNATURE_PREVIEW}
    {SIGNATURE_PREVIEW}
    {S_HIDDEN_FIELDS}    
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_register.html b/phpBB/styles/subsilver2/template/ucp_register.html deleted file mode 100644 index 162fa2a020..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_register.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_REGISTRATION}
    {ERROR}
    {L_REG_COND}
    {L_USERNAME}{L_COLON}
    {L_USERNAME_EXPLAIN}
    {L_EMAIL_ADDRESS}{L_COLON}
    {L_PASSWORD}{L_COLON}
    {L_PASSWORD_EXPLAIN}
    {L_CONFIRM_PASSWORD}{L_COLON}
    {L_LANGUAGE}{L_COLON}
    {L_ITEMS_REQUIRED}
    - {profile_fields.LANG_NAME}{L_COLON} - * -
    {profile_fields.LANG_EXPLAIN} -
    {profile_fields.FIELD}
    {profile_fields.ERROR}
    {L_COPPA_COMPLIANCE}
    {L_COPPA_EXPLAIN}
    {S_HIDDEN_FIELDS}  
    -{S_FORM_TOKEN} -
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_remind.html b/phpBB/styles/subsilver2/template/ucp_remind.html deleted file mode 100644 index f7fde4b3be..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_remind.html +++ /dev/null @@ -1,28 +0,0 @@ - - -
    - -
    - - - - - - - - - - - - - - - - -
    {L_SEND_PASSWORD}
    {L_USERNAME}{L_COLON}
    {L_EMAIL_ADDRESS}{L_COLON}
    {L_EMAIL_REMIND}
    {S_HIDDEN_FIELDS}  
    -{S_FORM_TOKEN} -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_resend.html b/phpBB/styles/subsilver2/template/ucp_resend.html deleted file mode 100644 index 62e7e96d6b..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_resend.html +++ /dev/null @@ -1,29 +0,0 @@ - - -
    - -
    - - - - - - - - - - - - - - - - -
    {L_UCP_RESEND}
    {L_USERNAME}{L_COLON}
    {L_EMAIL_ADDRESS}{L_COLON}
    {L_EMAIL_REMIND}
    {S_HIDDEN_FIELDS}  
    -{S_FORM_TOKEN} - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_zebra_foes.html b/phpBB/styles/subsilver2/template/ucp_zebra_foes.html deleted file mode 100644 index 6149a80e69..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_zebra_foes.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {L_FOES_EXPLAIN}
    {ERROR}
    {L_YOUR_FOES}{L_COLON}
    {L_YOUR_FOES_EXPLAIN}
    {L_NO_FOES}
    {L_ADD_FOES}{L_COLON}
    {L_ADD_FOES_EXPLAIN} [ {L_FIND_USERNAME} ]

    {S_HIDDEN_FIELDS}  
    - - diff --git a/phpBB/styles/subsilver2/template/ucp_zebra_friends.html b/phpBB/styles/subsilver2/template/ucp_zebra_friends.html deleted file mode 100644 index 3e18af9969..0000000000 --- a/phpBB/styles/subsilver2/template/ucp_zebra_friends.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_TITLE}
    {L_FRIENDS_EXPLAIN}
    {ERROR}
    {L_YOUR_FRIENDS}{L_COLON}
    {L_YOUR_FRIENDS_EXPLAIN}
    {L_NO_FRIENDS}
    {L_ADD_FRIENDS}{L_COLON}
    {L_ADD_FRIENDS_EXPLAIN} [ {L_FIND_USERNAME} ]

    {S_HIDDEN_FIELDS}  
    - - diff --git a/phpBB/styles/subsilver2/template/viewforum_body.html b/phpBB/styles/subsilver2/template/viewforum_body.html deleted file mode 100644 index e34d1807e6..0000000000 --- a/phpBB/styles/subsilver2/template/viewforum_body.html +++ /dev/null @@ -1,359 +0,0 @@ - - - -
    - -

    {L_FORUM_RULES}


    - {L_FORUM_RULES_LINK} - -

    {L_FORUM_RULES}


    - {FORUM_RULES} - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_ACTIVE_TOPICS}
     {L_TOPICS}  {L_TOPICS}  {L_AUTHOR}  {L_REPLIES}  {L_VIEWS}  {L_LAST_POST} 
    {topicrow.TOPIC_FOLDER_IMG} - - {NEWEST_POST_IMG} - {topicrow.ATTACH_ICON_IMG} {topicrow.TOPIC_TYPE} {topicrow.TOPIC_TITLE} - - {topicrow.UNAPPROVED_IMG}  - - - {DELETED_IMG}  - - - {REPORTED_IMG}  - - -

    [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON} - - - {topicrow.pagination.PAGE_NUMBER} - {L_ELLIPSIS} - - {topicrow.pagination.PAGE_NUMBER} - - - ]

    - - -

    {topicrow.TOPIC_AUTHOR_FULL}

    {topicrow.REPLIES}

    {topicrow.VIEWS}

    -

    {topicrow.LAST_POST_TIME}

    -

    {topicrow.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG} -

    -
    {L_NO_TOPICS}{L_NO_TOPICS_TIME_FRAME}{L_NO_TOPICS}{L_NO_TOPICS_TIME_FRAME}
     
    - -
    - - - - -
    - - - - - -

    - - -
    - - - - - - -
    {L_NO_READ_ACCESS}
    - - - -

    - -
    - - - - - - - - -

    {L_LOGIN_LOGOUT}

    {L_USERNAME}{L_COLON}   {L_PASSWORD}{L_COLON}   {L_LOG_ME_IN}  
    - {S_LOGIN_REDIRECT} -
    - - - -
    - - - - - - - - - - - - - - -
    {POST_IMG} [ {TOTAL_TOPICS} ] 
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - -
    -
     {L_TOPICS}  {L_TOPICS}  {L_AUTHOR}  {L_REPLIES}  {L_VIEWS}  {L_LAST_POST} 
    {L_ANNOUNCEMENTS}
    {L_TOPICS}
    {topicrow.TOPIC_FOLDER_IMG} - - {NEWEST_POST_IMG} - {topicrow.ATTACH_ICON_IMG} {topicrow.TOPIC_TYPE} - {topicrow.TOPIC_TITLE} - - {topicrow.UNAPPROVED_IMG}  - - - {DELETED_IMG}  - - - {REPORTED_IMG}  - - -

    [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON} - - - {topicrow.pagination.PAGE_NUMBER} - {L_ELLIPSIS} - - {topicrow.pagination.PAGE_NUMBER} - - - ]

    - -

    {L_IN} {topicrow.FORUM_NAME}

    - -

    {topicrow.TOPIC_AUTHOR_FULL}

    {topicrow.REPLIES}

    {topicrow.VIEWS}

    -

    {topicrow.LAST_POST_TIME}

    -

    {topicrow.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG} -

    -
    {L_NO_TOPICS}{L_NO_TOPICS_TIME_FRAME}{L_NO_TOPICS}{L_NO_TOPICS_TIME_FRAME}
    - - - -
    {L_DISPLAY_TOPICS}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
    -
    - - - - - - - - - - - - - - -
    {POST_IMG} [ {TOTAL_TOPICS} ] 
    - - -
    -
    - - - - -
    - - - - - - - - -

    {L_WHO_IS_ONLINE}

    {LOGGED_IN_USER_LIST}

    - - - -
    - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {FOLDER_UNREAD_IMG}{L_UNREAD_POSTS}  {FOLDER_IMG}{L_NO_UNREAD_POSTS}  {FOLDER_ANNOUNCE_IMG}{L_ICON_ANNOUNCEMENT}
    {FOLDER_HOT_UNREAD_IMG}{L_UNREAD_POSTS_HOT}  {FOLDER_HOT_IMG}{L_NO_UNREAD_POSTS_HOT}  {FOLDER_STICKY_IMG}{L_ICON_STICKY}
    {FOLDER_LOCKED_UNREAD_IMG}{L_UNREAD_POSTS_LOCKED}  {FOLDER_LOCKED_IMG}{L_NO_UNREAD_POSTS_LOCKED}  {FOLDER_MOVED_IMG}{L_TOPIC_MOVED}
    -
    {rules.RULE}
    - - -
    - - - - - - -
    - - diff --git a/phpBB/styles/subsilver2/template/viewonline_body.html b/phpBB/styles/subsilver2/template/viewonline_body.html deleted file mode 100644 index 70b8b52efa..0000000000 --- a/phpBB/styles/subsilver2/template/viewonline_body.html +++ /dev/null @@ -1,57 +0,0 @@ - - -

    {TOTAL_REGISTERED_USERS_ONLINE}

    -

    {TOTAL_GUEST_USERS_ONLINE} [ {L_SWITCH_GUEST_DISPLAY} ]

    -
    - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - -
    {L_USERNAME}{L_LAST_UPDATED}{L_FORUM_LOCATION}

    {user_row.USERNAME_FULL}

    {L_IP}{L_COLON} {user_row.USER_IP} » {L_WHOIS}

    - {user_row.USER_BROWSER}

     {user_row.LASTUPDATE}

    {user_row.FORUM_LOCATION}

    {L_LEGEND} :: {LEGEND}
    - - - - - - - -
    - - -
    {L_ONLINE_EXPLAIN}
    - -
    - - - -
    - -
    - - diff --git a/phpBB/styles/subsilver2/template/viewonline_whois.html b/phpBB/styles/subsilver2/template/viewonline_whois.html deleted file mode 100644 index ca5b326df8..0000000000 --- a/phpBB/styles/subsilver2/template/viewonline_whois.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - -
    {L_WHOIS}
    {WHOIS}

    {L_CLOSE_WINDOW}
    - - diff --git a/phpBB/styles/subsilver2/template/viewtopic_body.html b/phpBB/styles/subsilver2/template/viewtopic_body.html deleted file mode 100644 index 0f34b50950..0000000000 --- a/phpBB/styles/subsilver2/template/viewtopic_body.html +++ /dev/null @@ -1,440 +0,0 @@ - - - -
    - -

    {L_FORUM_RULES}


    - {L_FORUM_RULES_LINK} - -

    {L_FORUM_RULES}


    - {FORUM_RULES} - -
    - -
    - - - - -

    - -
    - - - - - - - - - - -
    - - {POST_IMG}  - {REPLY_IMG} - -  [ {TOTAL_POSTS} ] 
    - - - - - - - - - - -
    - - - - - -
    -

    - -
    - - - - - - - - - - - - - - - - - - - - - - -
    {POLL_QUESTION}
    {L_POLL_LENGTH}
    - - - - - - class="most-votes"> - - checked="checked" /> - - checked="checked" /> - - - - - - - - - - - - - - - -
    {poll_option.POLL_OPTION_CAPTION}{POLL_LEFT_CAP_IMG}{poll_option.POLL_OPTION_PERCENT}{POLL_RIGHT_CAP_IMG} {poll_option.POLL_OPTION_PERCENT} [ {poll_option.POLL_OPTION_RESULT} ]x
    -
    {L_MAX_VOTES}

    {L_TOTAL_VOTES}{L_COLON} {TOTAL_VOTES}
    {L_VIEW_RESULTS}
    - {S_HIDDEN_FIELDS} - {S_FORM_TOKEN} -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {L_AUTHOR}{L_MESSAGE}
    - - - - - {postrow.L_POST_DELETED_MESSAGE} - - {postrow.L_IGNORE_POST} - -
    {postrow.L_POST_DISPLAY} - -
    - - data-url="{postrow.U_MINI_POST}"> - - - - - - - - - - - -
     {L_POST_SUBJECT}{L_COLON} {postrow.POST_SUBJECT}
    {postrow.MINI_POST_IMG}{postrow.MINI_POST_IMG}{L_POSTED}{L_COLON} {postrow.POST_DATE} 
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {postrow.ONLINE_IMG}
    {postrow.RANK_TITLE}
    {postrow.RANK_IMG}
    {postrow.POSTER_AVATAR}
    - - -
    {L_JOINED}{L_COLON} {postrow.POSTER_JOINED} -
    {L_POSTS}{L_COLON} {postrow.POSTER_POSTS} -
    {L_WARNINGS}{L_COLON} {postrow.POSTER_WARNINGS} - - - -
    {postrow.PROFILE_FIELD1_NAME}{L_COLON} {postrow.PROFILE_FIELD1_VALUE} - - - - - -
    {postrow.custom_fields.PROFILE_FIELD_NAME}{L_COLON} {postrow.custom_fields.PROFILE_FIELD_VALUE} - - - -
    - -
    - - - - -
    - - - - - -
    - {UNAPPROVED_IMG} {L_POST_UNAPPROVED}
    - {DELETED_IMG} {L_POST_DELETED}
    - {REPORTED_IMG} {L_POST_REPORTED} -
    - -
    - - -
    {postrow.MESSAGE}
    - - -

    - - - - - - - - - - -
    {L_ATTACHMENTS}{L_COLON}
    {postrow.attachment.DISPLAY_ATTACHMENT}
    - - - -

    {L_DOWNLOAD_NOTICE}
    - - -

    _________________
    {postrow.SIGNATURE}
    - - - - - -

    - - - - - - - -
    {postrow.DELETED_MESSAGE}
    {postrow.DELETE_REASON}
    - -

    - {postrow.DELETED_MESSAGE} - - - -

    - - - - - - - -
    {postrow.EDITED_MESSAGE}
    {postrow.EDIT_REASON}
    - -

    - {postrow.EDITED_MESSAGE} - - - - -

    {postrow.BUMPED_MESSAGE}
    - - - -

    - - - - - -
    - - {REPORT_IMG} - {INFO_IMG} - {WARN_IMG} - {DELETE_IMG} - -
    -
    -
    {L_BACK_TO_TOP} - -
    - - - {EDIT_IMG} - {QUOTE_IMG} - - -  
    -
    - - - - - - - - -
    {L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
    - - - - - - - - - - - - - -
    - - {POST_IMG}  - {REPLY_IMG} - -  [ {TOTAL_POSTS} ] 
    - -
    - - - -
    - - - - - - - - -
    - - - - - - - - -

    {L_WHO_IS_ONLINE}

    {LOGGED_IN_USER_LIST}

    - - -
    - - - - - - -
    - -
    - {L_QUICK_MOD}{L_COLON} - - -
    - -
    {rules.RULE}
    - -
    - - - - - - -
    - - diff --git a/phpBB/styles/subsilver2/template/viewtopic_print.html b/phpBB/styles/subsilver2/template/viewtopic_print.html deleted file mode 100644 index a99d807cf2..0000000000 --- a/phpBB/styles/subsilver2/template/viewtopic_print.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - -{SITENAME} :: {PAGE_TITLE} - - - - - - - - - - - - - - - - - -
    {SITENAME}
    {U_FORUM}

    {TOPIC_TITLE}
    {U_TOPIC}
    {PAGE_NUMBER}
    - - - -
    - - - - - - - - - - - - - -
    {L_AUTHOR}{L_COLON} {postrow.POST_AUTHOR} [ {postrow.POST_DATE} ]
    {L_POST_SUBJECT}{L_COLON} {postrow.POST_SUBJECT}

    {postrow.MESSAGE} - - -

    - - - - - - - - - - -
    {L_ATTACHMENTS}{L_COLON}
    {postrow.attachment.DISPLAY_ATTACHMENT}
    - - -
    - - -
    - - - - - - - - - -
    {PAGE_NUMBER}{S_TIMEZONE}
    Powered by phpBB® Forum Software © phpBB Limited
    https://www.phpbb.com/
    - - - diff --git a/phpBB/styles/subsilver2/theme/en/button_pm_new.gif b/phpBB/styles/subsilver2/theme/en/button_pm_new.gif deleted file mode 100644 index 07df748d3a01253cc85055633f885a60e1e6c376..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1135 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 NR_$c`@f`&O06QuCa})po diff --git a/phpBB/styles/subsilver2/theme/en/button_topic_locked.gif b/phpBB/styles/subsilver2/theme/en/button_topic_locked.gif deleted file mode 100644 index 124a2d4a7d0d1a0eda170ebbfbeb7bbedeb49f5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1101 zcmbu4{WF_)0KmUbh&)fEgc?Cly`&N5uBwijTkjF-t-6_+ty^~sPQ}XzRcm{u4}!!? zTQ6-?3GvoAMyS_SHSxA~g8H5t+xcJ*r>{~^>5hc=g)oaK7IkdXFS5gfhCx9 z1PY~cYinEQGJp4R)^5#L>gmUuvX;KVp`4s-7e*kzrC0H*F*&;U62DWeSlWLhpIzD9 zQ?2dpAH-JoDc`=LrBnz9CnVELhnjyBJAchBubL%Sg%-8#sMT7n_5;t{HNAFyef{sf zy`3HP!ous7m6d~o4=*Mr!H@YGjpjcG{6B2o>p}oH0;i9ek552Pi{53^V=zZiUGnqz z&#L626e7-nI@lcS5+3w)K};DFv$9PSmm^&2U#WW1zG$7>-tTj`(&$X1T(q#nnO)E2 z^76Pe+avU&-d2`$vcu11_sbttR0^u9g#rg_k_C%SOrgR=`+RX*JDUdGVUTbsw!gv1 zQ<#wOXlOX85IRCKHYO1Vlc0n>}q&evkocEn!M;W1^r|wI25CoC%Y5gUOa0O$K+&X zbIwuN?y2#i9gxqlvEGFhtSjSmKJ5GptGLn5_pmnDRstK_=QPlhn4)pHIP#Blu3HDU zq|-Z^Qgl_gUirjqjr95Zhsx!4sM@!fnyQPxRw;mmilia~L2Lcgr&j zl%Zuto=g0SZB< z1$-}nw&Nr7{cRBxv1ijIc4Pohc#4z)kc4WO2|`lW>-i=WR9cD`o1M6?%qC|-RMCu} zG)f?kf}@HhEBtFqy*9aF)oiTXCYa5D4mC9(Pj&%Wt0{0Hde!cu77QddZOG=i?d$RttXCF|L?}SQ0^$cD@X0+U%N7Rcv;@cDpX=>4w{yK7H8W8N1nKU$&7@ zvfZV>-M2Gkx&35!DK7DMS=R_k@MfX`I)|q5Dk*H=tQsKYd$xcmRt7|fEtpdcQ=-$} y^$;W8`gSWfUd#nt8O_IB;`pdcj3>rSZ|I>95h5 zB~wP7Ze{-M2a9FHIJddAb${%g(Y)cFQvPXj8RJ3?;mqaXw{x=-dbhLX>9yLJtLl_$ zOkQn8R-N^De~9S{Xp=vAo+`<&>yTZFv>hwmDiUA8iW+4jCu&k}lGFL#`e zXc}MII8Xil=zb64Ntc~gqNI$x{DQ(?F-*rpL|3M5;uU%6)w1$y*Kbr@_w}^^$dWAGgW)tSY)5o(V2;?~=AQ(KQmg|Y4sau90 zj_4pOK9APtKZzr~jL6feB(=xu(Z#!V#*!rx2-UmBJ_RoAli`c4SRk5>`z$kpz!f z{ztkM2fbonIcuIPxgSmkDLAN1B5f0!&R$F_nAE%%Z`-O_$CN9ryDVe2=@Z0&-{mTN zp#RT~`W=XU&u>A%i7xZNMi~2Puve78=jq^jnp_u2oD>XGWIhy?*)RD0VwzG9dwLi7$6I9Q{5>JI1-!+AaBg9^71%=ti;1g14c#Pu1KJV}U;MR(1O)2-smo$GQyb~kAtO;Zm4-{ch)REd4@1xfEKDQ_H zW;{)mFr%n5bMOFyr;H5b8FfYg$N*(5dqLH`0NQT`7A diff --git a/phpBB/styles/subsilver2/theme/en/button_topic_reply.gif b/phpBB/styles/subsilver2/theme/en/button_topic_reply.gif deleted file mode 100644 index e8fe5115a0d116020046f073a1d69b99c54140ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1234 zcmbu)i&s*20KoCz|R?Kxewp_bXtF%?tbjPNiVOzyvT4;Haa-9p) z1SC^S&9x)=O7l@#(^_d0ByDY$J;chXxHKI;!{dX*+}Zwxeg1&&Io}#H-%2lDa?$APC*!|YyB^N9 zb={dA@9iHM*BPJ1>zld$x$X5Sdv(*62EqI-_BA_POVwK!L|nS%`q5ZKa*lyn2F4)L=`{?ByriYy$U^}@ zBcX5Fk+6VA(*1!75@3cCQS-H4x^I+!{b(E}ad#zJm^ql~PkK?Dd5yjUA8@C36>vf%UxmeO;94QxXJ5%cPbJQtJ*4BhAuB@vfEOQX9$xX zH|5aKKa>v=kj8^#w#WLYrr@;D7f8_X3aD`LWS@c+k+IEfI59#As`93HZE{(L8Wls| z;{{+SGI0rq+%C2QN~$&-e8rB~S9Fj*cqA8&l^+u0?{}BKNOBRU^o5xVla=xz?GLKm zRpr70;23$(E+%_UT~4^S$vyz}IHGi!^Y#i1c0q@|0bOtfC;Q4R{RC&hfg&;|dn$aF zTcKYkI9@1oW-_mSaeLD`@Zt05Lvhr_9)+x?~AmZ%TItN;uz zgpOK=D}uAc`Mec%2YM+dY@!N5`Dgk}D#zsiUCj&=1%&0MFz&T@4PfuC7YRhLYs|A{BiH7vVHhvtXf+ut;#Bx zezKF_Th~eF_#ngv#A`!i#8$yfSJaW(8FS3ZwSj4*V3~o=jJJK%h@D3_bV*N-&-Tc^ z?%4R^ki=jhNl_g1q|S}c_2cAq^OjT}v?VTCS8PO5&JWDL&i?dmdw_(o6YlWvSzK%L^!0&kGyq+U*}NtH|NpzUs%m_PE_a-$j2|vsa{BxH z)4WZ@)7ty|{q61TA^8LW0018VEC2ui07w87000I5;3tk_5CA5ru59bR@Om;3gvNNT z!vP}|6h~l3EarNgM4|yOI-LsvVnUs0eg#K$%k6r<;P3jIT{X!<*=^X z@A$lauSc6d0v#I%gaH-|9B>j10fdf^kdcy;l#>x10wM?=oPz)i83{lI4Ga+*sHv)} zs0$0K9S<8Fuc;jYthuTY0SF=!of{Dr5*!7Kiw?57xe*8m%Nq!S&$1o{2nx)(2M+)f zzmE?V4M`bs3>S@+kO~+W0)qz#2GSD>gi-?Rki6f&5dwOHfJKx88xI01T*xpWJOv08 z(sTBX7a0K!Gb(&=0^ElQ0Rs>qm>@_4C2<15JXp!HrAurEuqjwMG21i+0&=?Cxf1{Z zj}umYN)m)YoRSVum{`h`=>rT1-a$1%uU7|n7;p+`%9X26pe6t~$Z*a^hc|I-Tj zYJd*+dKr+5Z9;&YYx92n74||L8vpzA SC|}N8Ihj9CqDx;90suSYG3iGD diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_email.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_email.gif deleted file mode 100644 index f126a1960d91f1664b8898e14baafcb1fb6c4a8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 659 zcmV;E0&M+9Nk%w1VMqWJ0K^{v;o#u?{r$+u$F7lA=+&sEosl{uzvuzSG_|exlFM&meJ{ z`TF|w^!4fL>h10AA^8LW0018VEC2ui07w87000I5;3tk`X`X1RuB_;3n&-82ZKH1i zK?xw=z+lRADFgyLo^K{>wjz^_WICuG0|`RmBAt4_;IMd1_HHJTQDlKRav+*O19A;e z2n0xhQ}6r#fPsG)3uzw{ZG1#W5Ce7;6ju!f9UPXIn34IS8)I zHHg(Imjyx!0B(p-LBat9xi}oi;K4$M4E{3z02H{1SHWK$cx}0GVE_RJI2jCRz`#HS z1TljK?X@Apg9Q#cJeYt0g9HT~CS>4M!4}e}4?rdr8WaHl4F)B2KtL8j0tE#OD1(4= zj)4SaS-9Nk%w1VMqWJ0K^{v%gf6GUyW6fuNdgw_F@d^tHpQfyp`<39} z;H$*Y|NpVh+1&sCDqmR^d#l6m%J(*WpagLR!27^WF;mv!=Wbeb>+?;iX9w4~0Q8!0md!;IMe?g)~NuK!Y%~BrDcKL@Q<6 z@A$la&&Q`NB4&373U3t$8c75jeT|Nfb{hZ?A^~S#uBf`v5p%B3br4Xml_vF0KFVU zijczu!v$;$5~l$crpS!a1!yCo}Z!g{QdqL<5KnOKtO;5ey0xpTS!aZwGACQ z9B4oX4u?c9Iv9w^v7^Th!#X(om}+ChVJ1JjdNiN_fVBV-3rL~xf`SnbT9O#p$+M?V z10hjvL}x)+0Rsy}O8CiiXUms63&`Xk)8>mgNu+As%2jH)Gy)o+lTg6Iu?1Wt05H(C zEj5>wxGIoo0SgBycip;0CAEQs02#tcT_7Ms1__7t$^`)T8Z`xwA?tuFb7JJnm@{kM ztN;OL%nbl6$Pj2jXvU}koKDTUwd>cgW3yg>fYOIFre*8i&3iWjH6w~bAw#^l@#9<| M0Aj+tIf)PeJI}QDU;qFB diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_jabber.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_jabber.gif deleted file mode 100644 index be2e53f9c24249b2ca07635ed3b4d2ea1debce6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 674 zcmV;T0$u$_Nk%w1VMqWJ0K^{v_*ppn{QS(z%b%E-Xq~vT%GT)U==ykD;Nal%^Yhi# z*qXY^&)nk`YL)w@lK#iJ{gQY7xu@NXhV|0R+@+$y)ZN+S>HuAg|K;4nzP&(&r+KHo zEO?#l?d_0OTkY-bA^8LW0018VEC2ui07w87000I5;3tj-B2bb<35YSia4gSsO_ykd zVUt6(wxDoWLr@^QWWt9aI-fQ}<}i6!ACbrdka0o3PzIslabz712;=|&crNg`d`_?1 z@AC$MF=8|r9S3GuKNjSIG>k_iS4A{VR_0H1}R5($nL8;}*kj2qCrkR1pY!HNkA#>cJ- z%9FbV1R8q*&$peQ+R>E0uBur z&V$(Q!n_6?;x$~Lr=mG+2}ADdcOikv1PCPmph2@n0)mq;6BHR zngEgsI>?nGh(a0(3Jl2IyLV;>vvRw3m|36$QNunBH|W680%HvfHfZ2Wxq|@(Z-ZGj zP(s0g0TMnB$jiBO>6r$4YJhm5LIJH>7Z@0Wv4Ly`94t1Rt--YK&KdeOD1o530MViq z6kpD~XK@7!3LsdZKtTcM$`QDR&Rje7;;y@QSCAnCuuInks28vRd4~1y)o4K=;A~>|E$d1ti{r_&Dy%n*UaDP-0ASQzr!wqt7Vt3ZJV)vu*aR(@twri#pwCG*5bL- z-_79Z(%8f9db++1uJ(ope{EaG z*NRS$MQ6KQR+>wB$Zdqid4R!oi^qa;qia!#M{~1hY@K6jvs!AdTBzlkxXrVB$!Lbu zag*4BiOG4R=+Li0`@0#xJ=;Ysn+Ssh}>yPi{f&2OEy|jGQ z%Z%&bp}Vw+%9E%#`EgS>f*!v_vQTf>HPWb{pFPS;+^W* zq5bT${O-a1_1n|Ed;8_5=;PG>-iiA9`uOER@9*#I?Ck67>*(m{ z=H}+)f#>U3P z#KgnH!~g&PA^8LW00930EC2ui07w87000R80RIUbNU)&6g9sBUT*$DY!-o(fN}Ncs zA{G`EGd>i+v7;eKj{Nla66i{WA01PwT*VN;+jKlqW(YR-~}-AgR}{UkQjMP=Ja6fdcv{C2*?~CQGCk zXow)8!HKbW-v~e>R*ir;Vv8IhARrFjI2`qiJyIC2XoHFo z7;uQa)@`gF0dEMP5#R%gSk#0Kk3}p%i`dnTA44usPF*|7md9G#2CSDZTBr`W;KRoY zgj~nIbt^!`NayobMfRC*fZWym%#fpVb(1j3BI7nl4h{dtpf_+>_o;c%_^PW8Qd{_WC+02p& zE2F%k2p+^hlMEtlTp)}ATy|*y5JdREr4mR8fCHBT$l;|NX>I|85=t15rk7rlQw}=o zz(dbHz*YCmH@jS-N-D48$e(0{7s&)29LEw7SkDnrtFUBQo6K#ta{1I}bhf;Ij`uX#f`meD%bdz{3xB@B$Y%n81Mt5NE9M#vFI- zaX#c8+)qDFQ1;IbQ{-VVKl~`*^2;#CEc47X*KG61{^-EQ4h6mB^UpvBy^=;m7d=ow F06Y4NTHOEu diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_pm.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_pm.gif deleted file mode 100644 index 26ac558c2ff022b93db873cbf46043403f191512..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 706 zcmV;z0zLglNk%w1VMqWJ0K^{v=;-Ll$;tfu{7g(k##|n4o3iDF9*>%ywanLOuG9Ug zKk@PL+1c6p(PRK!j9(!WG-Y@fWsA<-;zWq4!LOQ@w8FrSQ1|%w^t};%#p~eU;B0bn zMwYx7bfP(WneFZEA^8LW0018VEC2ui07w87000I5;3tkBpq&6Y0w%*~tSZlRZOcHg z?MzCt6hotdvA}M~WD;-~Yz~`2z$XF(hZiD+s_c3JjEA!+){qz$45mRz8yMbrQc{RS z9{2~rFmU+&5f%y<3WW+5e~F5VjE#&P1rj3?5fTdrdW8*z6c+-Y0YXEY4HgTZsHv)} ztgWgN4w4^{0!$AI2Dkt|kuTs0-404;31o7ZzxUVxSaQKBFL52w|l4dCIDS=a$3$kk63bX)B4j#H*K;Qtuf&?A{a$T!| zfkp>e0YuD@pn`x3PA8l|`BZ=g4|F*k0I+uJ1g{Igc3nW$Y=y9exoQaTHY)?ZbSq@o z?7&3?ryLMWu$lnuOTwtbg_}UJ=YhqI0iac#x;7Zf(RrrXp8$pgcdp`Y=H3O0EGbL4>W;5zdrmE z`15Nx{6fF~{{G?TLI4zuGYbL(2B6?Sf(kOgU;qfb_uhjPF6co40XX=eh7DFoAqC%w o01E;hmT2OMD5e-dPqKVKM+c6?DC3MYGE!ZOa^$F^5+MKpJ1HkBhyVZp diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_www.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_www.gif deleted file mode 100644 index 14a33b36a544eacdfdb8eb63e3acb3490f95d71c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 604 zcmV-i0;By$Nk%w1VMqWJ0K^{v{Qdpc*VvoSgww(f2m8V`|a)RA^8LW0018VEC2ui07w87000I5;3tk`X`X1RuI$NKS<=pQZDNKY zVaFlaz+ehT$QcL(jBr_t3^o*s!41ejE#7gXy#?+%m`hmVSafCsNGuQ`gNJY$lyOL)xbkAl0Rlu8 zyR!1;1aCbLevsh-=F1Yr9)^&)b>;*P-coi=yS8oDvjar9%^PTVb+Ioz?*5Z`3#n9g6u`o>C+uPl>z1+;t?CtI5<>l(}_2267 z_xSkq^!3lr&+YB)A^8LW0018VEC2ui07w87000I5;3tk`X`X1Rt|`$}a13V{Yu~t; z8GO$lkOpB$9M*D3ZyWjA5d@vbJ z024t1vw)Bf2nh)n1qNh44ip#yjE#y&+nZSal z2MRoPu%}A_hMh=}z67vAgHCiE%%PJoplZ&fNE2l6a8susK^QVL@JY%-0}NVyJ_vyJ ztJ|*~Brt#rKtWUmRn1X-%Xd!$uCexD7!0pK0e^oCK(LUZ0t5s42uq%fVE}^-gzI9c zI}m48!ITM43~&=e5ds&OJfXlk3Iq=q$RH4Mx;6o-L^d!`pj&|k1_*9TuzmV3=~ylr zD1Q+E0Rsl5N<9zIC*OkQ*t09IfPI2;?+w6fA75cXfOaAVC|Ka3eft3Lgubsx)ErU+uPgI)YSU= z`pC)2E_Io+!pg$J!uVVFcD3tn+=6>tX#$$MFG+MOp?nn`3&(W zIP3Q0&fy3lV+FwOw#P|64 z`}_Os?d>BaChhI*A^8LW0018VEC2ui09pVP000I5;3tk`X`X1Ru5612MJ2g(ZQo_5 zRE3u$o&s)2BnA=|%i&;PCgJa&$Ec>@~^0|O41n32fpq*6!zv7^V2A1??HK%r2B3jhuOSTXpG9LSe2J0^2TN@52O5-eII-~$MP z4F-Y=9ZGa)27n_0x|v{LgD(TVHjpbywdzm=G}#4xrqd#jeOj!FJsP3Ggkcl_G-w+2 z=~S_BgQg4c&_IWMKne_yXAx(*1PVL^=s>uz;lqU^2srDj13*!Y8;_iTxUyx!4e65V z(2zlZ0R;jBt}q~#tW?=55LnH+wd>UxAOl=IK>&u4r3I93aQn6I->b1oct`*NRtBB} zeCFZ90|Vm{6g)9by}EVl&x=!ke!aW*@7pB|Khz+(^7G=;4>*6`Jp1?X10*-^KED0? w@Wl@p^}$Vf`>u$G-+%-bXyAPV06@VL2oxZc#)A+>DB&4vOkv@LE`$I8J3##+UH||9 diff --git a/phpBB/styles/subsilver2/theme/en/icon_post_info.gif b/phpBB/styles/subsilver2/theme/en/icon_post_info.gif deleted file mode 100644 index 166de2724f9ee3e8a62c08bf3d566c326d56cbe4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmV-10nYwMNk%w1VH5xq0K^{v@$vEC;NbuN|51;x6KRyp+vC&I({iJ{`uh6l=;({H z$J*N3$jQmU!^G_E?R}}g^z`+n#@5*6>$|(VXq~vT$I$%z{p0EFDR!N?(%%4GjL*-{ z_xSkx`}{$LsO|0TA^8LW0018VEC2ui02BZe000H9;3tk`X`X1Rt}Iy`geK3lMm%Fd z6qexsKmli<5K(xY4r0k{A}$ya!9uNO2A*RTlF*1WRcgfMiDfJZN5K2hB$)?~q%&3^ zIEe*YbLaT~5d;Jh99#x_g%FC03K||4iU0wJUy%Tp03I3_m}(n)01l#~3J;?Wc?^4~ z39YS~t_hP3Yy`3axVgFu1`QKz2Neq&#Kp!8z70_yIu#oX(9zP+L^%{OH8nRaDIowm DO^A*` diff --git a/phpBB/styles/subsilver2/theme/en/icon_post_quote.gif b/phpBB/styles/subsilver2/theme/en/icon_post_quote.gif deleted file mode 100644 index 4cf103280c67a0141c11a7ca426c12cc2a568a9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 666 zcmV;L0%iS2Nk%w1VOjtb0K^{v{QUgL$jF_Ym`zPfbDgv5>+9g);PdnI24$7m+1Zx1 z#Vz+Yl;Nl*Y9&4QQ-I-ey5VbiE6AlNLUGpRJb;IMd1E}PHj#)iNcF%S%Z;6kZS zCV)EtFo^H}fPsR8goTEO01|K_1QGxT7Xfv7cy~tv0*IQMoSGUE1R@)M0|5?o6cZY$ ztC$*{uzv~)v4#g32qF!C7Xl8a6BG`rb-lH*4-vyd! z8_EdE0OJ4)4+!BJ5eN+y016o23&$E63D6%6Ng9v?2Ci8fkl;YSg9s09cu=4n0SyQq zLX5y+A%q187HD|zumb`G93pH;NRs5Oe7gMq9XP-tzz$4vE;tzAVWrKRI9Ec*xN;3d z0xKgblCbi@g9987w8QWKLj$5YqvkZ=L0^NL95NVKaG|S!3Jxv|kSf)qf}TJl1|_g_ z!AcAkkOCFCpl*Z?Wb-u*JKnI9 zqo!I~1OlxFqD!A{Ac1x2*t1KwKtQ|q@8GE?@DKnaqXpwVs9(>%z5Dm>F@~_2CWr`~U_h;D7`cXyAbeCK#X>aBYYn1r=#TDB*+@nz2TMP-Lhf3n2giJGqh? ArT_o{ diff --git a/phpBB/styles/subsilver2/theme/en/icon_post_report.gif b/phpBB/styles/subsilver2/theme/en/icon_post_report.gif deleted file mode 100644 index 9a3f65b1e30105d6c8d1aab8f61d76871267ff21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 308 zcmV-40n7eJNk%w1VH5xq0K^{vYM!{s$;t8Y@&Et-;NalVa&i}Imd@Pc(9zNQ`uf`1 z+UV%$>9@DD!^_pLuf@g1?CtIJ^!4S-%euO{&O$=kfr0^EjK2T?_xSky{QWh3q5J#% zg|5Q(>FVR_@9pjFA^8LW0018VEC2ui02BZe000HC;3tk`X`X1Rt}J-~h9%FmWpLwR z9ogXjz(E9n`v7>GO(KCQP#DW)#G?@zHkoXeak)^mnaIK-vVgbUZ#Dr@kUy4WG|}l6 zl+1;@%*6QpT@`;~2yYe`5s8X{iUI_MWr+fllN1*Wln{@G0uY{`6%-PmdI5$I3#qCS z4yp@}4{rvq1hutxwF(Fi6K?9q0d{$fe+p-NhZlwz7K(fqX9|01lzasX5s@DO zU2$ZFf&&P%*qD13k(7bw*VCg0t5?(4!GR{ z8yf-x8RH(e1I_9f3C4B~81eG+^znuf3m5|cvj`4`3Hr@C&@bPB0q71K2$ZiLJyh;i zVOT)1qQ#384OQH?4Z#9z6rqXqxL{v30Q&%-U|iWD0)b--IwY7$v!=}i(kdi~FfIYE z1owO*5K1(`zGp*$4!FrQLW7rfc1D;=wW?L8g#Dskpd`jj)gGIBWo}s(lLK zn9~Mu0ED(8G*Ea-pt9x5m@{kM l%(=7X#~kW>P%_!G>C>oBb6ApON0HaCW5Ygzqjv2O06T(j1j_&b diff --git a/phpBB/styles/subsilver2/theme/en/icon_user_online.gif b/phpBB/styles/subsilver2/theme/en/icon_user_online.gif deleted file mode 100644 index b950612c575bf992ca9d9a30b75ba5b6760ef49f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 zcmV+j0{8t#Nk%w1VMqWJ0K^{v-QC^i=jW)prU71!w#l^l`T57k$I|7{PoqP^)xdkU zbBCyd&fMbj^z}uNJOBUxKYTW{$<%46U|^0}nZJ~z%%A%E{O$Da`~3ay@bLKf`Ea4S z$KA!#)YGc6x9#oiA^8LW0018VEC2ui07w87000I5;3tk`X`X1Ru59bRa4gSsZQm}l z4Setaz@TtQ9BvpR#(?o?I-k&}bV{vKmB`Q0QYdJ?;IMd1E}PHfLS!QvVBVIvd`_?1 zEeFIQf4KYq77YOdZE%2xb$J{Y2N#Hs1sMQ@9|K)zV;m9)2o)L!3JRPGj0hZ{d!eHj z8k(G*m>Pl|lmiX7xVgHx0SFTWq6r)b5CjVj1j8K4!^Ou0y%N9(1iRK50kmxm8QtFB z;N2At2i+19!vft16vM&@@9G)s71YZJ65;xi2DRM*00Rmf7+_pL1rica1ISKc0*4Br z^`cM@f`f|_2x<%fpkJGfAPXYsz%b#$UJD|HsyvBcK|PWIC`b&+v4h7-90BOu$+IT_ zh0+u_5I}&M&Xz?9Bu#oWB|ZWaTKb%7(?cx)9kOcO%2lfX2w)dwXOjVRz+-xVAFu#zkmY^9!$8fVZwOXd{Dyou;a&&A6w0`ct?@Tm@{KO Kf}?Zi5CA(JM(dIQ diff --git a/phpBB/styles/subsilver2/theme/en/icon_user_profile.gif b/phpBB/styles/subsilver2/theme/en/icon_user_profile.gif deleted file mode 100644 index d9cf7f4c4aeb2c706bdf74620ae593799808c432..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 667 zcmV;M0%ZM1Nk%w1VMqWJ0K^{v;NalO%F6uw{I|^4YMi$5pe_EcM24iaVz1cp^YaF0 zm)Y9dFkEW@U5m}!$)H8CA|M-Kyu9&xySJ>m{_r?gpYJqWAdt zHh-i4|KV4HlkM&8A^8LW0018VEC2ui07w87000I5;3tk504xiTWn=5Ua4gSsX%){? zR4VQNKp&ujp>!yiNQD(_I)8u&#!`7;ri-U`D{>GtjflZe7#l2%hI-9zyWjBmTSIV+ z914dZV=?6Z1pylZgoTEOh>41eiFkG&b%Y6GW@8b8jG2lK5*M0^8v_I)3WW(3Wt9;F zgP*Q=91;ox0<*3H2^k6^4Th5iz`zz6x1R~JtOE(Pw4WO#4ZMZV6%p1E3=9AXt%(p2 z3JMT}5F82w2?Pps4h|d*6L_??1K=7GpcxC%9}OG-2>@_lP=N{o1RMfz`^OL<1O^xI z9N55N!hj19Gz@S@Ae6rivp}-afFOgc3k@6pp5W&%LBI(T5F8*xK!OAh8C>ez2?1S# zazA~Zb19)gf&oSo%u+gFfPx7eAT&6zbLUE4E;AfJfItEVPY_~q*j8012cHlo{G^(I zg9oBUk-A(u%c+E>2ON~m1t0)RmjEU};EKS5gRlr1ELg#~amE3%4rDmHLe^ak6EYxO zF-zBg3>r9aQXrvm;{|?stysW8!(aptzfEAU*fisc4H)3eKtOVa3kTA8SiInK28+i( z5AXnwfbA81Q-4rU0`=@{*bf{Ckivv_?`OY@H*sOS`SapY1gNkJ(g4%};>RCQLB9R_ z@!iIUkH5eF|MyiO!6+Zd!ykYMCaB;Tf<o7+R;b1~k8q*khA)Hw06WW* B84mye diff --git a/phpBB/styles/subsilver2/theme/en/icon_user_search.gif b/phpBB/styles/subsilver2/theme/en/icon_user_search.gif deleted file mode 100644 index 46475fbf4ccbc72d0018b6f88595346ede169e48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 608 zcmV-m0-yayNk%w1VMqWJ0K^{vo#6cZ{QS$y%apUwWsQ6#zl9E4mPcjblkEFaibuph9RYuh^`1%k5@21;hxEzy!_#WKe2|O3?7Qd`_>^ zF$wXfV1{D`Q3e%)6%rA4h>4155f}v`337jI6=#Kqir(A znyqM@h!GqN4x(}$HKzd;2m~4dn6C-L8WFt-V21_62?Y@a8N&<92^JjC7Q}NA9uu`6 z4iVzw7YYgz1p@;G1;yj<2?G%X6af|%2zVM~#Ra4O4G;`SpaB#CfCn;AcsK5oH&Nmi zEGYK?f(8Z{GEP_!L83>A860E?a{$@B1QZtCXyBw|Wde!!J|>Y^AmvAo3?72>ND)E< z4hw+Z9ExGphCB&;X&6v6sX7NMZ4$5`QG+9!HHQXeAmE#Wpgjk07)!RSSu$b#F(9y^ z=mr7<5g-T|^#BJA@i2g?X_v2A4j#CAJ#aul#R47@D_+bv@c;@A5;W*W02u`j2p}h= zprHW)#Yr6C^X&L@W3F8x1#SRg0E5@CW6PdRySDAyvL^^=5NeNx3BU#D)-9m8@#Dyo uA0Mu~IC199kvC}Y=mS6E(X(sc&OJGAJ=T|b8Be~v`6bQ38(F_T1OPisW%|4T diff --git a/phpBB/styles/subsilver2/theme/en/icon_user_warn.gif b/phpBB/styles/subsilver2/theme/en/icon_user_warn.gif deleted file mode 100644 index 44cbcc953aeda524830703d373ae855a2a461637..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 673 zcmZ?wbhEHb6k!lyc$Ut<7}s<1t zo40QtJb3W^$B$dLZe`8e@%#6m)^&%D9zFW;JRht z|N8OseZk=c1mCWpn$+>fB%>F z@89U|KETX;Qd9FvLBUxUmq$~kJX^fvAUF5#Z{IKZ`W{nIIOXMaNJ!{XQqqTa?`{gsyCtnA0zcki!WJt87zeuc`#K}Syb`EwHm4p-D7BB@dvBaE6U}|RJW@4NYwxQH5m~{=~p)Ou+#Wk%# Qv5KKl)hh!RIWSlQ0G*v2*Z=?k diff --git a/phpBB/styles/subsilver2/theme/en/stylesheet.css b/phpBB/styles/subsilver2/theme/en/stylesheet.css deleted file mode 100644 index 57f9fce26d..0000000000 --- a/phpBB/styles/subsilver2/theme/en/stylesheet.css +++ /dev/null @@ -1,116 +0,0 @@ -/* EN Language Pack */ -.imageset.phpbb_aol-icon, .imageset.icon_contact_aim { - background-image: url("./icon_contact_aim.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.icon_contact_email { - background-image: url("./icon_contact_email.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.phpbb_icq-icon, .imageset.icon_contact_icq { - background-image: url("./icon_contact_icq.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.icon_contact_jabber { - background-image: url("./icon_contact_jabber.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.phpbb_wlm-icon, .imageset.icon_contact_msnm { - background-image: url("./icon_contact_msnm.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.icon_contact_pm { - background-image: url("./icon_contact_pm.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.phpbb_yahoo-icon, .imageset.icon_contact_yahoo { - background-image: url("./icon_contact_yahoo.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.phpbb_website-icon, .imageset.icon_contact_www { - background-image: url("./icon_contact_www.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.icon_post_delete { - background-image: url("./icon_post_delete.gif"); - padding-left: 20px; - padding-top: 20px; -} -.imageset.icon_post_edit { - background-image: url("./icon_post_edit.gif"); - padding-left: 90px; - padding-top: 20px; -} -.imageset.icon_post_info { - background-image: url("./icon_post_info.gif"); - padding-left: 20px; - padding-top: 20px; -} -.imageset.icon_post_quote { - background-image: url("./icon_post_quote.gif"); - padding-left: 90px; - padding-top: 20px; -} -.imageset.icon_post_report { - background-image: url("./icon_post_report.gif"); - padding-left: 20px; - padding-top: 20px; -} -.imageset.icon_user_online { - background-image: url("./icon_user_online.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.icon_user_offline { - background-image: url("./icon_user_offline.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.icon_user_profile { - background-image: url("./icon_user_profile.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.icon_user_search { - background-image: url("./icon_user_search.gif"); - padding-left: 72px; - padding-top: 20px; -} -.imageset.icon_user_warn { - background-image: url("./icon_user_warn.gif"); - padding-left: 20px; - padding-top: 20px; -} -.imageset.button_pm_new { - background-image: url("./button_pm_new.gif"); - padding-left: 97px; - padding-top: 27px; -} -.imageset.button_pm_reply { - background-image: url("./button_pm_reply.gif"); - padding-left: 90px; - padding-top: 20px; -} -.imageset.button_topic_locked { - background-image: url("./button_topic_locked.gif"); - padding-left: 97px; - padding-top: 27px; -} -.imageset.button_topic_new { - background-image: url("./button_topic_new.gif"); - padding-left: 97px; - padding-top: 27px; -} -.imageset.button_topic_reply { - background-image: url("./button_topic_reply.gif"); - padding-left: 97px; - padding-top: 27px; -} diff --git a/phpBB/styles/subsilver2/theme/images/announce_read.gif b/phpBB/styles/subsilver2/theme/images/announce_read.gif deleted file mode 100644 index 0589feb14f4363781bc2b20ded20759ba142aaea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307 zcmV-30nGkKNk%w1VG{rn0K^{vtI62v>gwL!-c?mqL75L(9zKz9v+ICqT%fF!PMO{dY=JajP>{Ucc{Q?jh^iD_SxCl zSBayTq^d%OssI1~A^8LW0018VEC2ui022Tb000HB;3tkEP#k2MQbhqY9-yX^dnFg3 z$g{W{iC|DS=`9L30z!yc%m9@jArg@YJ*ZTLA{;~vfiOi;932Y5fWd%(gu@NY=%R2W z!VD_o9e^k8WRtRodTPj8yg4@ z4s@xVUJ(NbsT&Xme;*heZ4kA#5Wxrr9CAJt5)vJ2%*h!Q4P_-B6%Q8I*AEpgJ>4lG F06W--dwu`_ diff --git a/phpBB/styles/subsilver2/theme/images/announce_read_locked.gif b/phpBB/styles/subsilver2/theme/images/announce_read_locked.gif deleted file mode 100644 index a738616e06af40f7713a543719b4e0be45cd2fa4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 304 zcmV-00nh$NNk%w1VG{rn0K^{vU|?YJ@$u^F>f__%9v&Xv-rh(^NUO=%+1c5!v9k5| z_zGf=fPjF-#l?)a%h1u$S(LH?UW_t&pTX4K;q3Bip}cpfz>1opX`HrIRaHWUsUUEf zn53%K$iBFqpHg79Qf962CCK_bz3gu@uiNU`Vy z!VD_oEqE*xA`TdLZ+ZiV0Et;!0*8l&1BnKSA9Rh5Qv?hJi3J4>i4+?Ho~3%600;=6 z26U>WUIZDSiM0kF79MR6s;UnUwYEMI7Z)6B$ib2$2O1I^5z*1g0Jl9O)dt$yApkop C(SvgU diff --git a/phpBB/styles/subsilver2/theme/images/announce_read_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/announce_read_locked_mine.gif deleted file mode 100644 index f7ffe7f8dd412179b92e43a11622539f065ac11f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 324 zcmV-K0lWT3Nk%w1VG{rn0K^{vU|?VY0Ri&z^5f&<>+9E7Pnu(7g8NJ!Y( z*{Q|TfPjF-#l<#!p8;Ns&(P5dVvlB;w1BI@jGLoVkF6&yFlJ_EZ=bkNPfyd{v?fm4#rqi0E1{UqCW!E*_dzMj0Ro294%K(rPFfS4)9nB{(K6$i+e#5;7J9!ODqv zT9b-kPC`KDa~K#b26lS{3+9>@-rlgWvg709sm0S%kFAur$;HLRW}38SW@Z5a z0SaP|^78V4fPgG4EYHx}N1{U+0xS*zz#3Uh zTATu7P7*xka}p9P8FqUB4HXp)8I2ha3mGR{42~I!4Fj430R?Cu8W8}S1DK=(0uUdC z8K;;5u&@V_7Z4e-u&=Nl9tRK+g}ku|iWUdF9uESM9})!z4-d$^(GLd#8-ph}6y1F! a-5VMRQ7i-+8W0%k>kt}2JMr=@ApkoMS$75i diff --git a/phpBB/styles/subsilver2/theme/images/announce_unread.gif b/phpBB/styles/subsilver2/theme/images/announce_unread.gif deleted file mode 100644 index 56b2702b172763bbe794c036602884c41f83ac3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 289 zcmV++0p9*cNk%w1VG{rn0K^{v|Hh06V2t$m`u?g_x}Jjm>(~FCI<3dj{nDpYac}|x z0*$uJ)w7IQldsjotJaS~YoWZ~>+!6HQ0~{hOo*e3e`tSULwAyt|F>`c-@kvUyGk@4 zE_j^5*yCcEv;Y79A^8LW0018VEC2ui022Tb000G^;3tma(JW+|c1?45)S;%4Tiiz= z&myGVz+8j}Y1}3bpawEKa59;RLQ#QcD5w<2VcjSQR!3ksT2K&Zg4%&bUo;~@fQ`0H zEp2o_AX;1ifB*=0fq)lT91Mj3goO+oA95Izly{Vrdl3NxoSk=_og5KzpaWhC8xN&> n9~ub;u(7hS6-+$|5)Tivx)KQxWF-_F90A70#4bF`DIowmKFxZB diff --git a/phpBB/styles/subsilver2/theme/images/announce_unread_locked.gif b/phpBB/styles/subsilver2/theme/images/announce_unread_locked.gif deleted file mode 100644 index 37033da653dc82b9a0fd10d6b77c1e666662991d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 292 zcmV+<0o(pZNk%w1VG{rn0K^{vU|?YV(x(Cf0{*I1|D8Jj#*F^!*9c&YNJvQj-@pI2 zZ>`7De_=z_!>f(9%v+SOE_j^Z>+!mtg7ot<7A^8LW0018VEC2ui022Tb000G{;3tma@;GFgcF$v4i<(BRVJ}B4 zi&SO*xX6z3uxT2<3PrYnBoZ2d!1GL4P$@{GiV;Yvje~IHumsMMbmM&9R7R7-`pl3r z*yqDU=;v qg{`C?6&VDxw6v~{JQ*Gr7qtYpuO$``5C_J_zz91eqzKN=ApkqL1BE#N diff --git a/phpBB/styles/subsilver2/theme/images/announce_unread_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/announce_unread_locked_mine.gif deleted file mode 100644 index d91f2520ca79a8f5471b397394973151b1482b61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 308 zcmV-40n7eJNk%w1VG{rn0K^{vU|?VZ0s{Tgr~ax{3}TG`ojU)so1Of~&r_po-SGm13B(N;Dtc;p6bx!q$&McaoNpfo9Igz$Y;^ z(A?v0pt+Q|$^ZZVA^8LW0018VEC2ui022Tb000HC;O8V!^_?E$oh(~zL7XJaluS(0 zo=@!OhhT!BYr%X0OmI2mw0cO(!6I2gCM^vzqp-xd3Izj_eQdxAN+1$eXb2`2gdwO$ z?vi>P(_uLXd36mj4SID14kr*828{*+gpL4{WFHI?j*XE9lL(U{1Ph|0gbS0SlNg)dN*jj05|D8Jh(x zo=5EGhM+>AYr%X3NpLy5w0g*jq0(4#A}t1TqN&8V8qI@~J#@et4x14hIoVEHo4X)YTLeIXl|hEg=9q DyuE?z diff --git a/phpBB/styles/subsilver2/theme/images/background.gif b/phpBB/styles/subsilver2/theme/images/background.gif deleted file mode 100644 index 5c731e4fc210f5084fd24f722993bd652fe217da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 666 zcmdUs+e=dc0EdrsvHL}WrVn|^)XKmfs!a*>AumA~U8tZJBdB~ddgx7CdMpNJmLy%+ zG8qg@rYtPM%kJ&mwsXIqopW||f>6yEj8^Nv=zI7*e?PvCu6CoTXA95^B!D7?LP63} zqM8(<30{fgtP;Q&KT7)$$_tYohzN$+Fe78Mgi<0x3NXP#IL9e*R*o@}PKz2Ps3adH zI7QY|l9m+Jgc3`85y}ITZirY3;V>yc1Ruh=ZxJ>aW&#);W+aRjNkJv}D9$MnR+eLF zNl%GdQcx3oG|nk8R@VI(?L#RqLV94r4dDnS(2~{x+VlB*Hk-|4GLj_y_5b(dzntpa z<`MvC0~(9=#U?=Mum0*s=Es9W;P8{DCX1zNj>GY#y+s zrhU5A`Tksm;p8PY=+rGEmG#31Zdh-3l{Z{=)Gp6XL58NDzE`IE{TE(0^{t9uYc-I7+TiBM(%RMB+Z|c+{4b-#Lm~w*WTCOF)5% z*53dB|Nj2|+jRt;?ddQ)7#&E z|Ni~{A^8LV00000EC2ui0Qvw0000L6K!tEf6iz4<&_GEUI0pr2VLFwJBv?r+mD1@d z6%?wcxk1bjoXuu1*enK%ywf4rPp6Ciz!&&8e;XS-JRCAG5j8OwF)S-AB_%3536%?% z4w()BoF1MCprH(-0So~Ts2L9#tQid=4L>3xCOg34-CPx&h@xKZtBqy9C+F>aLv}Fq+0p|!ET)yZK^K;ypq3A5I$?Ps3 zo~QMqN*zQ9hWi>Y6k&L@qAS5l2@>j8D0_D8+N79rky~)}_8UhXy)Z)##x>}mNI?Jq EJ1XXQ%m4rY diff --git a/phpBB/styles/subsilver2/theme/images/cellpic1.gif b/phpBB/styles/subsilver2/theme/images/cellpic1.gif deleted file mode 100644 index 715b8d4aa8b8752fc3e2ff6deb214cd424ad413f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 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 diff --git a/phpBB/styles/subsilver2/theme/images/forum_read.gif b/phpBB/styles/subsilver2/theme/images/forum_read.gif deleted file mode 100644 index 9b2bc47c67aa83051fcf1a312a739046b9976b8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 677 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 WaRfMgXqSRS2@@w85Wor)1OPk92sRP` diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_faq.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_faq.gif deleted file mode 100644 index fc50e7ca30185ecd403af8273c69be68e228f50c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmV<103`oMNk%w1VGIBb0K^{vxysXgpRiPfoY~&t%h%oe{QW|9kYkRchpxk_!pD>Gk#X{QUfkw#x!YZ0+ss z=H})&fu;Zd|NsC0A^8LW0018VEC2ui01N;P000G8;Fon|NoFGDt?Wu=Qqi`B)UAo4 zX#%s7E`vj$Ibblr<1xUSOh_0fV5cEmE~M*adVo~E*)Jgg*qAq@Gt;oKxH}R{d$1UA V?h#1_@wof%2q+W{CM75#06SVcbLs#9 diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_groups.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_groups.gif deleted file mode 100644 index a4d1c7bb70f67e7d0e06683bcf245f9bd7a7ffb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 222 zcmV<403rWJNk%w1VGIBb0K^{v=;-M3^77{9=I7_fz(%_4W1T<>l<`?2fn0@bK{W_xJq#{5^xG z077Fpfu;Zd|NsC0A^8LW0018VEC2ui01N;P000GB;8%2HNfzHlcx=lO*XFpcvvstq zkSynMK#oR3QfP!h<n5G#blH#z3Kvq*Mwb5WrwaTMi~^v5+tjjwN{jbT$&pqYW4g Y1d+{!F}VvWfE5fE9|SihCm$gIJMyS`#Q*>R diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_login.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_login.gif deleted file mode 100644 index c7590a423f0765bbe9dae5b88b2a1df51933abcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 233 zcmVW8kw{QUferM1S> z+WY+d;_B^roUQNk^(9?;(cRx>FMe$Vtuv9(d_Q;J%gv5wZe?H%L++p z=H})&fu;Zd|NsC0A^8LW0018VEC2ui01N;P000GM;HPzDNopeDt?Wu@*s>Z~W~>X= zt<4hzo5YIb$pjoL#>9dk3KT8Nq(DM!E}lfj1E~y11p&absT3#Q&cGtDY&L+6;zGJy jGUYdb!|7lsfEN=L6nqjG8V3=4jC=HGZs^78WR?Cd{gwv}>FWOe{^jN6JcFl>x6Jzb`uF$u^z`)Y?d|aJ@Bl(% zIDw@A00960|NsC0A^8LW0018VEC2ui01N;P000GC;8$>DNfuufcx=lC6}7nTLUC;8 zZ9FfLE{TLdFc?U~j-kg(kStJ3;&ORlFeGXR!_;U<7zV?u$(S3Yawo%7063IL1L6h< Z1Oo)6azNk*6M+*46(0c(CM75#06S(?bT9w_ diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_message.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_message.gif deleted file mode 100644 index b8aea1eafb5cffabb6b2ceb80b5d8bae1795429f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 zcmVFJEN%jV|h z{{H?rfu;Zd{{R30A^8LW0015UEC2ui01N;P000GLpr>_YNor!jt?XK8QnOlD`_6Kw@B`E5YDFAPFvm3&vofOv)XC1!1V5 i1CvZg0?GI@2@?|u3lbU!3mb}y8wV%_5hf)lApkoXTx?_j diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_notification.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_notification.gif deleted file mode 100644 index f165d3cb2780274a5ee82d987871bd118dfedd46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 543 zcmZ?wbhEHb}0Y1g?QKYslA^XK`?SMBQ#fByXW-Me@94^&*+l5=Zo^o@<7 zhgUTmTN3m0*U#zoF&{4U-a0hl>VfG$AIw>|X3eEd8DB2<+qbSbvm(B~B;eBS{@^Ku?w&2JE$&SW9^F0N4DK$juDsR?M*5RnT|B#$ z*!8RgdRn>#<#-%)7SHjJbTsGUQ0;DEvXtW2RCm^5VrpTukP)>}G&N>qY+>aVG7#ak x6<1?zVKd~Du$PtA)nM~gF&pVwWE>28UXw0#NYq` diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_profile.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_profile.gif deleted file mode 100644 index 1ec7c649e9d5770776a1e3fd6518536506054aa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 238 zcmVTWVIb4)pKkDQE{pg(ku*3r(Xsi$va zSWJ_+#k#+xfOq8b_@SJf6BHJJzv0rZY}DT3X0zIcgoB!7NcZ>m`~3X!^74bLzv$`e zkGISJ|Nl9GrT_o`A^8LW0018VEC2ui01N;P000GR;KzAnNpd3BO;wd-UB`{s7AQtg zVI4+x2}pooQNTLC3PHk@ATT~p=V1X@Er`p7gh3E3mWDP%(pCm&!zM%aWHy=tgF(?u oHl&P3AecBJb$A|l6asY=3k7%_8XN};2L}ZP6OAG!CMY2QJFk{zX8-^I diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_register.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_register.gif deleted file mode 100644 index b49ac31ec996b7dad9e9b067c8a0ad5b61e3bbff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224 zcmV<603ZKHNk%w1VGIBb0K^{vho-fXy3Y0W^)hCGAzF9){Qb7Z&4;eTnzFv*=jr0) z<<{ThkgB*+ew69%@aXODa+asz<>d@YYK*qa z>gwt^fu;Zd|NsC0A^8LW0018VEC2ui01N;P000GD;J0;TNp51`t?U|XRMD;%P*C0M zNd(}LGl>Rau>gw}Az;EJB^{4JVlel;DkLVN}i)4(UwLaNciBhl1fC a446D7qo8aK5qlYfg9j)9I3_0_ApkoRS#u}= diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_search.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_search.gif deleted file mode 100644 index 2bd1a648c05986bbb8be73ec1346224a269611d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 238 zcmV!-xiSeCWt_W$zo@_(zs$K2-j`uv>S z{e8RIujKz@rN;R9_=Bakx7Ov~^#63Aw(|D*((nK4@A2j3<@)^n4NGc8h^pu5>BZ{( zkGISJ|Nl9GrT_o`A^8LW0018VEC2ui01N;P000GR;KzAnNpd3Bt?bH;*K~M+HzeIf zb|X`41jwbc%TP9o-=U)ObTWy^aU-cXNSDm&r;un2B!@9aX>clFk6}PyYyg!Kyi>XDp35% z!pH#Bssj=RnZdxKZlLP0a*t3;?#DaMPZ?bznI13TWA9@0P~4uJc&DkFvHijG#a$jk Hj11NQ?`AEC diff --git a/phpBB/styles/subsilver2/theme/images/icon_post_target_unread.gif b/phpBB/styles/subsilver2/theme/images/icon_post_target_unread.gif deleted file mode 100644 index 8ec44a17871a827ead40201b929e46622d58586b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122 zcmZ?wbhEHbAo-gk5 J5MpGo1^|-ADbxS} diff --git a/phpBB/styles/subsilver2/theme/images/icon_topic_attach.gif b/phpBB/styles/subsilver2/theme/images/icon_topic_attach.gif deleted file mode 100644 index 1c9c89bc703289f2f25cc4f9a80e60b27f9baa19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 217 zcmV;~04D!ONk%w1VGaNi0J8u9Sy^smWO#3HgLQR>fPjyPh?bL+otc`XtgN)Xy~4i0 z#Kp$R&d$)**4XCe<^TWyA^8LW000gEEC2ui01f~W000Dr&^1KFAVxLEB?$$RAVzR7 zodF;l*91Z9072K$Hf}S3k=Hgv?`Lxe5sU!`*JvF8i_bE!5F|J%hSUK=1W*oDV=Dk0 zzF0t`03?{vj%Q;a;1u2pYz)SEA}$990t7R4Mk@^ofe9M{N)8JF1~M*^9R~vj2@4Af T2n7TSHVXy=rhs4$5dZ)?1=&WS diff --git a/phpBB/styles/subsilver2/theme/images/icon_topic_deleted.png b/phpBB/styles/subsilver2/theme/images/icon_topic_deleted.png deleted file mode 100644 index 494b4fb563a6708b734ffba6e5674860f0c1925e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1205 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFhHZsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6s4IL(9V zO~LIJ6P$YWfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tao{eq%$xuYI?djhE&{| zb7{Z!(LjmgAFK5*stQfc^K@IyQ*_$?gRIN-j2*j}H%g>@P`+z4Bj-t4pwX=}lXOy& zgf9E4*{cV|zc2o6^VMRe&DT}G=Ty)8Jm*bnd*rR5XENMDB zWc?LsVVz$an$4a**H|PS9hD>AtNSeG;Wq86Ln7~{lrKEqWfZ0A(*AG5jKi~cl`V?B z8}%`>_3x`a9gMZNH;QTO?hEBfG$}dv^0@7~Ex&?F8WPR7&p6JZ_Ex$(?~>G~z=!O8 zF>zZDh4b!F4s4GPZ!5LY_`mIt^PERK%@WR>duLfJj?H-_#9n4$ZuQJXN2vGuou~DQ zckVwvCBJ?ZEBD14c5<~3Ti?Ar%6UH5`McPs>@~;u6^^VqV%Rvj;)8nwBg4bxHh#xh R+HQaf5>Hn@mvv4FO#no9rK$h` diff --git a/phpBB/styles/subsilver2/theme/images/icon_topic_latest.gif b/phpBB/styles/subsilver2/theme/images/icon_topic_latest.gif deleted file mode 100644 index b45e57aedbb344d0a0486b3e56234b0c7fa2b416..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135 zcmV;20C@jLNk%w1VG;ld0J9GO00030|Ns5{{psoH@bK`rx3~BA_xbtx^YioV?d{Ui z(zUg<*x1V!YA^8LW000jFEC2ui01^NR000Cu@X1MmwY1j2aef}i9hY>S prl6{Td6vLo%uEZuHh>VkVpl&vVnB5KCPzS{z+4(&#>VXI?CR?3(qLd|p1JPs?u417 z;p*=!&hsvd!CEm$l)eqXAxwou{l}i=n>1z{o8vIDw_!mXtB#8XqA)6E19w9efs- zmpK6|1Uvwk76z6U7o|BYAT=2pm!%gkCm0^HvpGFJsur}f7_kSxzXb>|AP5)02Mhws z3l zModu9M^FI;6C_+faB{h467J>~1=#n!_#i!CyHpVi>i z!P39)@9*a3=l}ozA^8LW0018VEC2ui022Tb000Hc;3taGqXDS45MwJozylEy;lPh8 zMo2|;zYeg1h`1sN0%0?;WHN%urBfUYG|G+h$rW5G8ixom_)WMI0k?2iBt8;Aa69Q- z(1(D0kmwu^ej9>n85SFPVG9v{e}5cX78o8L0SF6<2a}px0vnnNWCIA9njC8es0IpQ z1OTb10R^%FsR0dg9}x?*s0F76wh2Zb5C94Rw7yRT$O;Sq6(b884amwF%ni>AE-(xY g3gHS34HN*}I#(JA6zvEAWI8Pl5gHl@GCCmuJA8+T(EtDd diff --git a/phpBB/styles/subsilver2/theme/images/index.htm b/phpBB/styles/subsilver2/theme/images/index.htm deleted file mode 100644 index 29531416fe..0000000000 --- a/phpBB/styles/subsilver2/theme/images/index.htm +++ /dev/null @@ -1,16 +0,0 @@ - - -subSilver created by subBlue Design - - - - - - - - - -
    Created by subBlue Design
    - - - \ No newline at end of file diff --git a/phpBB/styles/subsilver2/theme/images/no_avatar.gif b/phpBB/styles/subsilver2/theme/images/no_avatar.gif deleted file mode 100644 index ad73330e713ec9a21f97366b326a8c66afe5e9bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 930 zcmV;T16}+_Nk%w1VPpVg0M!5h!_3s-=IPqth19I^!oe!#m?2-;pXx4 z_2lU6!_Cz8_xS1U@6p)a$I#d1>FxCP_uJv+;pOS&>FnoQ6%sUqgoT9?6&QSdUl0ifhLMtk1_=<1 zTL1zIlbw)hY95S;PU3YWDB_uL7! z03h|FX24w^3i*en7j3nYtKz;q!c zu?v_ExZHIB)3%wg2-w6KOD7}$nLJU|WYjX~DVU5<8uhf2(a5EpOfvEaby7%18LLX- zxJIH@Ll#Fh{7MMoD1>AOEsQAeYr%bK|IxEoHD5A#TIT^&x3nELaZAmCo1rbJx4}ZD z@w|q3#xk7G8VeET@|ffyw{9lv1?}<>R}N=+K2mC+s?kU^(X9sRB5ERz+7hdz?==z@ zEdscJQ4EHQ04-S9E`q>A0S)&w6!3uTb%+2XG>!-m!t;XyKuI1b@Bnd!0xN>9D3BqV z2?`>rilAVk775u^4UoVD0!4|mgG!(PvF5=C{Dyqc9U2>?0AM63Y;eX2DjX<@3MY`! z0S69x!a)aNbU;Ccr%-^u;TIHgcnSw!oFF1B5puCXgD0M%f`VE+U|@@=q%hzWApA!o zEFbW91qwUrg2ELf+!rJ)CCo>K3Gf~1i2?0Rv7wW?P%uRX=}{Sr2<1glfR?)y5XA%G zff>sRH#YI5nYxJSL$AcLo<$N*>&8ITG~mqx^(Dk?D`f$6J~Y#Iar EJ3isPuK)l5 diff --git a/phpBB/styles/subsilver2/theme/images/poll_center.gif b/phpBB/styles/subsilver2/theme/images/poll_center.gif deleted file mode 100644 index 99473151ec87bc348047acc19f0a5a5b4ef20e44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92 zcmZ?wbhEHbWMtrB*v!E2|Nno6*q(p?{(b-c{qyI~zkmOJ|Ni~!*ROZ(+{u6qDE?#t Z3+sSLkQodtoCXb=rxczo5MX4m1^^6W9;yHU diff --git a/phpBB/styles/subsilver2/theme/images/poll_left.gif b/phpBB/styles/subsilver2/theme/images/poll_left.gif deleted file mode 100644 index 269088b81d28737b750a79d929ff77437e48172c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113 zcmZ?wbhEHbWMSZ8*v!w6HEr$x|Nq6Zr@edk?)UHC-@bigitBy!_S5IjpDR}$Y}<6= z&F63T@84g&dB@{tFMui)f3h$#Fz_?zFaQC_3u9-zA2t0`pacfj) RGUo9-WFdCJBZP&)8USI+HDCY$ diff --git a/phpBB/styles/subsilver2/theme/images/poll_right.gif b/phpBB/styles/subsilver2/theme/images/poll_right.gif deleted file mode 100644 index f9584e23a1ad55fdccbff4dc1c83de3ab63c5f88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113 zcmZ?wbhEHbWMSZ8*v!u$mObtB=g;@<-TVLle^TGlmJP?4;(8yw{ZzT?@bBNhuim+T z{P^*uYd2oGa%K0Sqd+x^KUo+V82A}<7=Qp|1_O(nz=F?yhUq;`TbO1gsB}uO^cF5_ Re86zXNr9))GlYe~8UWh-Gv@#R diff --git a/phpBB/styles/subsilver2/theme/images/site_logo.gif b/phpBB/styles/subsilver2/theme/images/site_logo.gif deleted file mode 100644 index abce3cd51d33335210257301228219d18e6dcf56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7151 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 diff --git a/phpBB/styles/subsilver2/theme/images/spacer.gif b/phpBB/styles/subsilver2/theme/images/spacer.gif deleted file mode 100644 index 5bfd67a2d6f72ac3a55cbfcea5866e841d22f5d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43 mcmZ?wbhEHbWMp7uXkdT>#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 diff --git a/phpBB/styles/subsilver2/theme/images/sticky_read.gif b/phpBB/styles/subsilver2/theme/images/sticky_read.gif deleted file mode 100644 index 09861a996c79b9a87904909fb4e5ad851e97d84b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 344 zcmV-e0jK^)Nk%w1VG{rn0K^{v+}zx-%-TnZs%4X_$H&K6Sy|%aRJ?eq8T?d>EaB$|3Ljs7%T%X&c(I_|^4S)cG{RAckuGb-HC@zpo>vU15 z9R=>A^WOCmToeuzTU-)*OD72n4*(8Q50M508e}5~9SxBVk&Ofg79MjO3LO=i4+I7V z00#pJHzNvm5361UtOE)QClCXY1`lfhtO7G5W2^ue1OyQn$^ZihBX!K68X6V^7y!!= q9U~bY90MF42nYfb76+fYCmR6+5IiUX9RnI3yk%JP7fgr<0RTH%oPzBD diff --git a/phpBB/styles/subsilver2/theme/images/sticky_read_locked.gif b/phpBB/styles/subsilver2/theme/images/sticky_read_locked.gif deleted file mode 100644 index 24bca303d6f6222ae51b672cc0a2970481c4de6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 338 zcmV-Y0j>T=Nk%w1VG{rn0K^{vU|?YA=;-b3?QNmE;^X5;NJu0kB=Pd{M~SN3+}yCt z+6G{bSy@^7{Qbwr#}#RlinPjksllJX(&z8=?eq7~(9zD{=QDbqB5{~yldIX~>{5iD zyu7@Rqpg^jnE(I(A^8LW0018VEC2ui022Tb000Hg;3s~~G>Qs>K-4Kh%QLjvfGEna zH0ShKhe!+qIUEQTjOApx7>yH7;E?FZT%TJ&AYd2_f&@Z>{U|U5uGer73?h<9>l7KN z4GeDJ^4|3xTpk7@V zp9P;I19kzbUJL}E0~#N%5*d;N0c)%P2r~c$SrV%W6%Gy^6}O+$$aT#e9UB`R4i(eX k9}^1~85au>5C|9@->o7I3Kgxdk0psK2+S=MBB_&8mNM@V0TU%R~xytbH z@W#f*xw^XE<>)rvs4la#eh<|pkzV;MKNk92pG#D6^sS~h(bXDnIux5MbtA;1jm6$MB+kG z5Qxm-8%BH^4hKCyDG(N48wDE!UjbAV6lfn75CH@Q3;_e11Pf+p5)PU%n*#&@sFWxH z2Th|4rl$Y~s3`|~qkXamPPGYpu>)ZRvJ*D5A7-%&%oq!@sHg@X5eEwl3>+F791IlE i(bEtQ4jvf~bQ2XE;L@wV34|Xj?Z}e%vj+P5ApkpUp@ZfC diff --git a/phpBB/styles/subsilver2/theme/images/sticky_read_mine.gif b/phpBB/styles/subsilver2/theme/images/sticky_read_mine.gif deleted file mode 100644 index 381634c36432700e28d09d505a39f23d413dbb03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 352 zcmV-m0iXUyNk%w1VG{rn0K^{vxw^VrTU*-N+LyV?>gwyp#>V60<4K6Au*uc|0Ra z23?7NtHIvo=zUj$SR5NIC?3M* z%KxZRX`sCP+`R4c_hgKi+2-wZnWTDxbH=one5kzZ%&GeP{r>Rc#F=Ey;OXb^_5AJJ zPIG(N+ty)%i2wipA^8LW0018VEC2ui022Tb000HT;3s~THi`m*D9$M=1HiNpg9rjO zSf>Vb8yx_kxEMEx%qfG|I5z=7z$uWqKDU6D6VpBf*H5*f1q=pc3PqtXohXq;!!zK> z8;D3`*8|840|j??NiF~t2NeSo2aS#%U?U0ujsuR4698@&6aW(mpr4=#1pqfA3=g9T z5_O;j3=k&@9t5_wTm!crGb0EXx3?Gz!4e9R5(~;05)uZ=&=?3K8g&L-YzP3u$_5N4 X76J?cJSYep2CcGTSK<_IA0YrcrtyMh diff --git a/phpBB/styles/subsilver2/theme/images/sticky_unread_locked.gif b/phpBB/styles/subsilver2/theme/images/sticky_unread_locked.gif deleted file mode 100644 index 608f4822e3c320addf9d5ebd2060ef3e3fea9dca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 324 zcmV-K0lWT3Nk%w1VG{rn0K^{vU|?VeR(<^3ydi9l{?n%YwQaD-(nv^1{>P9(g{O?Q z%KPWh{O#OnpuBvjy#J_D=kWDTb9?&y{bGfUdV+JrnPhaCq{g(D{_x__-{kG{_o0en zkern3%&FPt?f?J(A^8LW0018VEC2ui022Tb000HS;3s|(G>S%&DB3A1!O*l`lNg2* zNGCL84BcR$z!({c%qf##I2jAW!fBAXKDUK764Oo$*H2ZT9RvboheM$-og5Z{U=oPP z1qq8~*Bi(=0UURCNiG8&1RVhv1dWbgCkg|O0geO!m;-JS4g(hmpr4?a2bd!b6QH0J zbqJUZ9v`L(69u-mTmc1`6Egq@SQWRo6%V_Z$iNB|56u-66dTRR$sZ7P8(eG&0~OSy WA`%7-20SPU-@jolzX$H_Apkp{wT8(6 diff --git a/phpBB/styles/subsilver2/theme/images/sticky_unread_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/sticky_unread_locked_mine.gif deleted file mode 100644 index fe5e11531221b56a7751be81c5da782a02060de4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 336 zcmV-W0k8f?Nk%w1VG{rn0K^{vU|?VZ0s{Tjto+807GsG1sZ#sp&qzo}3`uA4?daU% z#-hV10pYkeIH($*-xJ z*~+@ek4@FDga7~kA^8LW0018VEC2ui022Tb000He;FoBdqI@XYK#O#u3KGnSb6yTq zRT7b)jG6F3AS@b*WMXka$%Fw;!k{r&D+EU>2(>N{1Z$>|`c$A4D*=J9J|2z7tHP)| z1Og0VVZbjkL_aAC1b7<=8F-2UOl2Pg0|Fcf8;b%1V`UNx1D%ka0|24~F9{9{9-yh6 zq6eZW4j2=&6BGyx6QT}HuMHRlz`zV(1)>->00$os7Qw;I#iG*64-^sC9TXH6*V5A; igbWr81QHSu1RdV3Cv>gI(ehC+~Vb9j-7pcX2;jxHh7nRtHH>RP41*u zjFgCAeSz7^y6^ArA^8LW0018VEC2ui022Tb000Hh;72qAMSUomL|AsBl(NhUb6!m3 zI2k~og_&>y0ALb?Bmr|l$%G3J!O$>R9RNlu2(@Aq0Ba?Y`Z%B#D?p*JP9}-T%TcH^ z0)dVKW58o7L_aAM0C)om9C(TWOl2Pc0s$Th1B(FyV`Ui_0-cbZpaTFe1PmAups1i6 z01*u-3>^=%4;Bgqvm6XfDG411z`zAyz#APlDG><4!3Z1778xlM782GP78VHB+!`2z l00jsI02vt(02W}k?K!#O)V0aG&++EYz5nF-y?ggs*B&@>>85r2 zy0rPbcV50fbN{8DZKu~BzjEc~oq`odZajNCbLT0|+GSY__k>N`cK6}a$1mS}|Ni~` z`}g}U-Q9TP{DR#lGw1Etf93wg>$iJ09NK#JX4TqbH*eowvhVca3)g}tZ_Zh;Yu({< zbG9Bmd*yoZs-w4Gyq|yQ%ADP&G^^L%d;A>ek0A;af3h$#FgP;kfZPv?69)E=4USFC zVn%Z9MqC{Ycv;Vv9R!PEN|kq zu@%_0X8p!Z(lZ=IWOfOx)liYzr_RdcC}zyRb`Q`JwTpMp{On|9v*syRbsAIcNp5u#lQbVlN9%qoG}dL&2fx`fS&< zZV2o+e6&+RΜ7>fu>T)h1C#HiR}E^k5S7A1W@gjV z)8pggnWn8NbeXcUvitk{5@(Xb*yFvvzIm#`Y@xi*;O9jn>htwU z{x84h|F}2T*w?emfC0=`f@{|&uKxb_iLu*FO-(OeytsGo-sZ0F=jZ2pdwchu6h9gK z@zJA4XU?AeMS3tbHPzYKS-iJzWMt&--MgVP*J82Q&0DvU$>ihYv!S7(>FMdl-m|T( ztz~6p+qZ9D{?U>Br?0x*?sz;tGcz+gI~(phJ~uZv`S?j>;tym;ck{7J-+uQ)#s^=p z-Tn8cAK3ZhiD%E(whuN0`_wyoio8dUoET2dJw15(r{zVh?p;v#r`UK98q1T2f1cdP5SRXIG>rE6>$B1>7GRrdMNPA=*AX16acBUxWbYC$uS~xLp2qK9PCnKrf`FYy{bWSYP(H( z7T&% z7tgQm-*Ye9UWh2{?!Ox%K_g+X*#`|CxUwgPVi1~bfd+A4Xh{tSK2-Ynl!H(Ux*n#TT0kY-j6LMdnlNYWv>eoC$% zB?FY*yif=5kPb^vO>!?y&1YiaW*fp!*Qffe@p@d(_h3RpH67l!GTTyG^=WDYYh zJtG%PNCK{=@;xr;@Gc%TtZL1(vdqgM>X+}2$?va`i7+yeb1))^1%#%@-fW2}C{WX_ zOYSOEXwA^3bJV$bZC3UkQ-q0T>X#EWbYp3iQjM1E89&TMG5P9kC`oPwo(mZ>*UyQl zw#X$WIRA}+a%Jjp&dbp)nG%2iN}!TW*Mrrh*%1+fNG=FBgeAm}Xk0;H;hiBuQ%?Cf zwyKjbn&>-R)S*yX>#{dB3dgU1MWE;s%U9H#pd&>NBN*TdZC(lZqleJERmFE~Qpkzo nh17VQM{B6ueD6t{U&L^-oNKUyD!#x_$oQZ`*s3zfvK#*aqCm*{ diff --git a/phpBB/styles/subsilver2/theme/images/topic_read_hot_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_read_hot_mine.gif deleted file mode 100644 index 853452a74bec80d2bf976a65b79b89d7cb559b23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1903 zcmeH`{ZA8j9LK-+(Dqu6+9K9EN_#D^T(DaT237~tyHcra&Xf!{T$bgEj%c!E7efqL z5byc`)i9WG=oU6}2u_#Hq-ru{QFd4A#K^KbH8M?HDH5k6(gq_nHnIbLSsIIK%duGO`i&duboxR1@!;U#)YR10-ZL#N zEfp0NTefUjx$|KA$%`J3CmxSaPfyRx%!K=n&CbqFJa`xxyA6HVwd2Up*WZ4h`_Tbk zSO4VHJtu!G_4vt}Jp+xwK21}1F?;CX@l)y9NBd9yJpFJ+h+bdYcI2z!tDhbehOYhD zeRk~p$S?Er^WepMLEwK7u+Haf-q7$)4ei}f{;C6kWGU+tRFMzX1N(yP!Z!ifJlLxf zL@E|i>%3&JY~o^1=dxGWFGrz}U#TirZj2<6m<1s>S9_!Wx}1_tMlYzp>sI1Qf&ol0 zRIu9OXNQCu6t(KdKQ1d0dvvxcCc$zP|Bclhj`UA>p!`CL(3KG|1ecWJhI^3#;$GYaKz| z!F6BE9ilF{&=uyF+p=j1`3wWDpatl7sk{5OCCNg(V&7a@v(b6r*<|fX#|OoZpWYxA znJE^Sp#TONfXmF9z+No>92KK@qmIb%M3hEN&g#E_UlJk1Dy@;2@PxEh)QnxV254=G zvN==FKz^0#y=RSaeuP#NAPDLcVh@s2%7r;7_^U-SA&786 zJ3B5?L0Vm)%SO0<%HfQ?YWT$7U^6JFAvtAAJide=YW3}S zf@6X-ZqjB+;I9euHl>?L4Y)%P?#@PZK2XP_6lf%D#YmvY*)SR*n$!X7>-m{epak@; z$BIp1hEiz}vztmK1XP2YH@Oq+HXhC^Z7C#u%u*1|()@@#e~wIKVF$afpP_j;*I?pV zI-F|+T}EqCwE;IdIfgiTGz=G(+Q%J?hbpJ>F0!*r0?(V;p*-IUX1he^EiQ} z^Y{8SeWBjo-v9sqA^8LW0018VEC2ui022Tb000Hb;3tYy(PU^>aAPY%4m2tB14FJT z4Va?+2n_-=khmlVjv}b>2@!=5Hhy)b`2#r_*TnPqY0Rt7I7n)@R2_6Ps z91aNym!<-!01Fu`5(OTwWdgpwsS5`<9}^A+yRV~=sRj%V7$YVI03O!Y0L~5tE-(xW f)Y%IQ7TY-=0UHem7VQHLVdo<@8yy=mIUxW$un>jZ diff --git a/phpBB/styles/subsilver2/theme/images/topic_read_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_read_locked_mine.gif deleted file mode 100644 index 3f24928b480c6934719af67078bbc33504d9dd79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 337 zcmV-X0j~Z>Nk%w1VG{rn0K^{v_4V{cMMbg6)$8l(*Vor(o3^mAvBt;80s;b*w#Z;$ zVB_QCOp2+Rr>-b-m=b1@$=Ts@qPq@Kb>iphG<>0inWX6G=G)`vfUCg)UX1ec@ZR3t z;_2*XhnMc|?(gsKA^8LW0018VEC2ui022Tb000Hf;5Qh?c41DYQrPsp?-C%i6hS}^ zMNb5O3Ystn&=@rwMgcYxA_&Bs(W87dg#&~76Ybd9-amn9v=l58w(3(0l~o*svSNb5Dy0gy`#>l2MrkzFeu9#*x3Zp4;Vim jJPilq+Xn^}-QO<>6b>B~@Es0@>OTSz6!{Th-yr}yGzEp| diff --git a/phpBB/styles/subsilver2/theme/images/topic_read_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_read_mine.gif deleted file mode 100644 index 560927aa06e330dafd28c472dfe8ab7d30d8d847..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmV-k0ipg!Nk%w1VG{rn0K^{v0s;cGwY9>-#IecM+S=M;Vq#{SwvUgG>+9?D^YfOu z%HZJPps1`&im51bnELwq5@wM)Iy%tM(8<~1a-zEqQg!9#=QMnwgqft<+kRHA^8LW0018VEC2ui022Tb000Hs;D-bZk!jARUYhs4?-BuYMNQ9> zOcX@Hp8{>DOK=iMPs0G44FQrs;Si7=>8WbFYfQ^Z878V2z3Umk-0&JQR1q7WE zpaTt~d611#3$+4f84$H#VN(GI2ekwN8wei;8mbEf0t{ec1k4>j9}^G)(FDuc(ajJO wFem~N+|d%=8bBXC3Msfx4jmZ#9S)QAKn75_K#;;2bs+!%J8$2J-T(jq diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread.gif b/phpBB/styles/subsilver2/theme/images/topic_unread.gif deleted file mode 100644 index 4e56157dce0020df7062b904591dcdaa38dda08d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 336 zcmV-W0k8f?Nk%w1VG{rn0K^{v^Yiq&lWbyMS*pp{wY9bE?Cjj!+)Ie3#m2{qv&iJJ zf0B}tT#>BfVuIXE|tb613!q~YrB z0bYzafu%Klq5uE?A^8LW0018VEC2ui022Tb000He;3tY!0&%F90Anjo(NqDn1W&F= z9UJY_n*+r~VfYAw1pz@T2uA~tuOJ9y1eiqu(11uphe4BoxtJ9gN1>2ld@PYBHDERi z2x~`tU|b{XW@!xt4jvK-6aZ^gfM^a44Gsqhh-(NK3V;Cu29S~i0|x~SRRNi1n~(+w zUH}o03j$aI8CDAh1`Y%qEEEZl4XXsPS-1!cI3E=e2)NG94yz9w8zUwN(a*UE4-pA2 iFb@dW4&wwG-Z>vp5DXgc2N7ZFBN7xH9vw0{Apkog5Pe|) diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread_hot.gif b/phpBB/styles/subsilver2/theme/images/topic_unread_hot.gif deleted file mode 100644 index ceef4919d58bd233720aec226d7fa6c244dc2e89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1888 zcmeH`{cjU>9LK-+)Vn^=9_`kZ*_G?)2I7L{VR#_WYd5wEGK$Vn6}2@yEJ|W)fD{Ac zZo78foa`VIM_fn?+7k=|sK7YXb z;r01^DqpFf7q~S*4aO~CXlUq*!(TtYY46>;chwtqpZ)2^;d4K(cy;-O3l};+tFbp7 zy>{)|*002m4xAYuAK$ZQ&+Xf{zl+~ozkdDj@bJ~ER|6*oJ5QcWCX@Gj8v6VD?~Fcp z^YfDH?9M4J za_ML2-R7Eor`^rr>mxUZBegVluylJk`QV|G|8hm(z}}wN&TlULnf|-GZy+RI86ErM z^w6)p7h@9>6X4lABk(^67$@XaORHZmvpSZ}nPo|uWVGeu`sVhp}`9Kr_0f@`yh!wj+7MnLN z_5uiv%>AUg#*;Y8qaUtjLs1R^&%Na7O69}-O&XoLg^svH6rH~%;z&NY7tC#(Z4%-> zYal$2h_)q}x|Ny&-)?6Fuzu}=+AcDtllT={yFGQ9wFUEZJIbkeJ^b7CGte)}%Y|o| z`h~6IhnNC}P@ywvUPqxY03=@!Ve8mnvt`R5nS}j+<-^VUr`D_*P)tz-7b=KH#IP(e z6u>|R6d7XgWr-2)D8uC#7Nth1ekNDNu&G#r#p;UGF0ze*{Zn(4+jOY}z&Q;*0KC6j z8|r5(0qcVME4XQMDRS%Fiu0sF+0i;92E!`*t|inc676lVXtzDxb6wWcmk^mcttlO0 zU2!ZISEtR;Fk~aAqXPhnp99iql6_{kHPl!?T{*9n^2TLkj*WHhTICwVN-B?$K_kaY zRi^fI%xJ~c^5SSn=!K*`^d{r!HKA&X3EqNuMkq9T1oQA(sZvh~ATe6mfNN?!J}SX3)fluy zyP2~EaMK)Ou}=_Hhab~_WQYL_;6R!&q``}Xo@OXaT0|Z*3g6X48kCrEb_D9<$nQ#LdawQ diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread_hot_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_unread_hot_mine.gif deleted file mode 100644 index 1c748f708a9649ed38354eb0bf56a22e0998435a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1895 zcmeH`{ZA8j9LK-+Q105o^=MhGOKq>LLbst73<;Z#9u%-sKy*u1onftUjQGPWMwgOo zde>fCrcCO>5I3?EP;uEq%1ky*9JyXA)`w&;_TXHiw8~TxTp63xrH);73BT;O{p$A* zct5;8@9(-7>nfges(=#ATfoG`#F3#dp5AkGW@bkD#{1`fzBzRMr-u3s7cX8Mey`Pb z;L~f@uC;$6>>B)Lety2Er{~U{JKs*;YH4XnCX-jMUiE(&A3k*|l}i0N5{SiO)3f)s zd~j-NYU*IyD+9+*{BXiuUS2*jGUER{GTPVX_xtzm-TS(I!#v-?9X*zqzB@NJH~keG zzWfW++}Zl^8E0qzjj3D7@V*N6c=4s{U!ik0Q+yo z9ZtqCgSVRcHnF2!0mUk&7ayqg;zXI+K{HTHuQWC8300r-$)9l_YZ?Os@psiFHn#(c zT!2dSBPf)hJwy?`wnA#9Sv{!vFa?s_goXmS8ftsAOR|E{y3MqJ4>dLvaDV}M$f}j~ zc}^I)qQXd;S~IxLm$TDgv!&jW;4*Cm2)7}DgAiHG*xO+5jeJa9-^=i$gj)9N-DSf< zsUKAqt%^Ikb0CdMXTx_6L^mqsY7ibPJg-<%XpDyFU`-s8n>cr3b{z^=nqtj5E%*(r z*i6@)jJCUES0FA$hlKNbEy5XT5rv0TH<9G*g9Nb@ZVvUnW@TXYjOESlQfrQP@VW$j z2u_j(hXNSLK&}X`8SKXka3@c*I^EjzEES7j6rH*4;ypZ~R659B8usbs#M_#50${8X z8wG8@R|UMK1YjI+td4zZHAS|suDd|$h-00aaTr$E4p&mM2p{R9EII#a*^;$%Cj^=m z@u!_oqzcEB88eh*X_b!dBQ*%h=n-S5#w~EZgV;u`%T$%*pP)<}7~Vd}AC_-DWH*pj zSSn&O8^Tr(VN};MRR*s_siZS@S8!S((IN591& zr0{Pl4bTomZ6xfj$>;%8Nzom*A&w3f8eBnha)*@AQb8c@F@UM|x!hEOsa5IJc%PZA z_G88}`~`PVPz*uPqM-yx00yL@;q#z@KTW3u;3+V6)8p zs?m~mcasoBiQ?ju+rqoqOGnI0&_^qJn14~u0`_M>lYqdiMaO_PUg(lwm7m!tCxem2 mjZHTxCz_KhT^|I7d}{zx7`66R!Ar}Q>Vk15wcN*mHU9txbjv&d diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread_locked.gif b/phpBB/styles/subsilver2/theme/images/topic_unread_locked.gif deleted file mode 100644 index 720e21028931a2bada129f617207b0e8e5183d96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 459 zcmV;+0W|(cNk%w1VG{rn0M$PLq{Y_V-Q7rvtI~xs)YR1RmNj;$z;C0y_xJbD;OEQB z%jD$bEOwjm@$rYU$=cf5>hbpB;o(`8v&F^5?Ck6pX_Lp>=6gtG_rLnWL z;p*<^=jZeD^O9jJu*};5UW{m-xtyk}wsbGQzrPJ-kztIXu% zVvf1f-z0FBIeebP*yHi@^op&&?C$TAr?L9{{d$w2McR zBoPq-6AUpdCMXfZ%d`Oj1REhXKO!>$&W0c7=K&8TCk8?Z6+92y^xF>)6C*7gLqgwvDX)UqI)$;Q4W}CLSxw!%Y0@~Z#!^Oto;o+9K z%JG&pVPRpQsH{wisVH-p5@wOqhBL|8;c}w8(b3T`Ffiuk<}`evgqft<vI=j!h6?(gsKA^8LW0018VEC2ui022Tb000Hc;0F}Vk!jDSURw9PZ&DfbHc3M+ zP0$2?44N=U%yk?D*i2}k6p0?>E64;47T99vA^0Ge9M2*Wh%7v4k0zPfFc=MS!~>86 z?gvOm;TWW`cK{0kbN~kz0vZ#Af>@3L02US$4hn0Gj*bxtl9UPp4v~_XSOE#A2wWWy zr>CTY76}vu8y+778V9Fj0lmEk2M8QK9}*A+9>5xytkN z^W?IBkB^Vw;NYOBtW1ijD07$+W|7I+;c}w8_rQoZHZ_iOSLNsEG<>0inWWp}=Ygxh z1zLn&iJ$K7?(gsKA^8LW0018VEC2ui022Tb000Hs;D-!OqiqnUV%zn-Z&L|0H%Uq^ zP0<8@0GcpI%v~M_*i0x03;>LQ!K3gXUqNOAK(GKR4C)0^_!yWBM}@*(R01B)CaK{7 z01gC~%?1n*2muin2_01)Pkd|@27mz=1sf9{fP0E>7Z(8!33CV+0~HI31ON@02Al;C zl>`K%Y^4pe24or$vkZ3?02W;gvrZfy9|s!&7YzXh4!U5<1|2>h5)lRg!OF@3%MKh8 wFen4uMscx5FHu&9T1T9KMG91KyX4Cbs+!%JCoCa5&!@I diff --git a/phpBB/styles/subsilver2/theme/images/upload_bar.gif b/phpBB/styles/subsilver2/theme/images/upload_bar.gif deleted file mode 100644 index 75cf61c59e0c3b736b47150d64e69193fb685639..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12892 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 RIq~=D^XrU>oip&I{{w%u5=sC7 diff --git a/phpBB/styles/subsilver2/theme/images/whosonline.gif b/phpBB/styles/subsilver2/theme/images/whosonline.gif deleted file mode 100644 index b45092743218db5a4a6b80bf45a9f215c26ca7f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 929 zcmV;S177?`Nk%w1VJ-j}0Oo%H)z#I>(boU)2le&!%FD|ub(-DX-2x0}`3YGA0s^S1 zsvB15NnwrU<>g>hC~Tp;+1c3@X_M~m?*IR@MTe>3;o+K^nPz2V#KgtCyu4$YwxzAH zTaT)RvB*=Au>V(4|Nn06?Ck03={h<(qr}z!vjEE6jDgh5yF@aE_j9WK7nF z0K|$nt+ly*9UiX3&#=wg|I1pRrmz3tNdLx;slCVF>+$2`1umqsgf3$+1FL8ktE{bF9uG>iq&*aytY}kHW){A!5*iQ0l(1?8tO-$CPY4Om zLl`1!6dlx(EJxVcA8ukiHP06ctR_HU=Y=F5xxNWHTX-Z$K!g>I6a|M!z+xmHAr>vx zvD1M-$dUvpXb>dAQ9^(S4h5ZvFr$~R7@;Ebg0yUHBdBgK%+u~27Vx%(STHg z1gRqaP*|Wku)&A~QUnBPQ=>wK6;!b1yF(%F*#;M&)ToibPX#|ICQJw-fQA7B1acg8 zIMT5nKQg+gsInl&WdkYn?2%I#jEx0hdPA5#Vh)HmG#Kp2kfY&j+I#>&Ad|+)ivtdj09e0bL>2}XFy#4i;`<*G zWeBX0!Ndmo9qR=cAOT1eV2*u%xPSu&D*!M;92N*DAO=X_Fb#r&JWv1~`bjuo1`1d> z42FW3!bS!d5D?%B7-WD191#dcq97({5J3(;D4?SPKIBkFC^JUVM .header > .header_settings { - float: right; - font-weight: normal; - text-transform: none; -} - -#notification_list .footer { - text-align: center; - font-size: 1.2em; - border: 1px solid #A9B8C2; - border-top: 0; -} - -.notification_list img { - max-width: 50px; - max-height: 50px; -} - -#notification_list .footer > a { - display: block; -} - -#notification_list .notification-time { - font-size: 0.9em; - float: right; -} - -.notification_list .notifications_time { - font-size: 0.8em; -} From 59780bbd091c9e162eaf5f399f9bb2440605c4f7 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 10 Aug 2014 12:17:03 +0200 Subject: [PATCH 0018/1676] [ticket/12958] Remove more references of subsilver2 PHPBB3-12958 --- .gitignore | 1 - build/build.xml | 3 - build/package.php | 8 -- phpBB/develop/imageset_to_css.php | 2 +- phpBB/docs/INSTALL.html | 2 +- phpBB/docs/events.md | 119 +----------------- phpBB/install/install_update.php | 2 +- phpBB/phpbb/event/md_exporter.php | 11 +- tests/event/md_exporter_test.php | 1 - .../phpbb_functional_test_case.php | 4 +- 10 files changed, 9 insertions(+), 144 deletions(-) diff --git a/.gitignore b/.gitignore index de503c10ad..4afe253848 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ /phpBB/store/* /phpBB/styles/* !/phpBB/styles/prosilver -!/phpBB/styles/subsilver2 /phpBB/vendor /tests/phpbb_unit_tests.sqlite* /tests/test_config*.php diff --git a/build/build.xml b/build/build.xml index ca71aae924..9b088982e8 100644 --- a/build/build.xml +++ b/build/build.xml @@ -175,9 +175,6 @@ - run_command('rm -v ./release_files/subsilver2_' . $package->get('new_version_number') . ".{$extension}"); // Build Package $package->run_command("$compress_command ./release_files/" . $package->get('release_filename') . '.' . $extension . ' ' . $package->get('package_name')); - - // Build subSilver2 Package - $package->run_command("$compress_command ./release_files/subsilver2_" . $package->get('new_version_number') . '.' . $extension . ' subsilver2'); } // Microsoft Web PI packaging diff --git a/phpBB/develop/imageset_to_css.php b/phpBB/develop/imageset_to_css.php index d49fe9c741..bbe7c31c83 100644 --- a/phpBB/develop/imageset_to_css.php +++ b/phpBB/develop/imageset_to_css.php @@ -7,7 +7,7 @@ */ $phpbb_root_path = '../'; -$style = 'subsilver2'; +$style = 'prosilver'; $imageset_path = $phpbb_root_path . 'styles/' . $style . '/imageset'; $theme_path = $phpbb_root_path . 'styles/' . $style . '/theme'; diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html index e3e12a3176..7e31e0815e 100644 --- a/phpBB/docs/INSTALL.html +++ b/phpBB/docs/INSTALL.html @@ -314,7 +314,7 @@

    If you have non-English language packs installed, you may want to see if a new version has been made available. A number of missing strings may have been added which, though not essential, may be beneficial to users. Please note that at this time not all language packs have been updated so you should be prepared to periodically check for updates.

    -

    These update methods will only update the standard styles, prosilver and subsilver2, any other styles you have installed for your board will usually also need to be updated.

    +

    These update methods will only update the standard style prosilver, any other styles you have installed for your board will usually also need to be updated.

    diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index 4f39e71c3c..584bde6fa6 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -212,7 +212,6 @@ forumlist_body_category_header_after === * Locations: + styles/prosilver/template/forumlist_body.html - + styles/subsilver2/template/forumlist_body.html * Since: 3.1.0-a4 * Purpose: Add content after the header of the category on the forum list. @@ -220,7 +219,6 @@ forumlist_body_category_header_before === * Locations: + styles/prosilver/template/forumlist_body.html - + styles/subsilver2/template/forumlist_body.html * Since: 3.1.0-a4 * Purpose: Add content before the header of the category on the forum list. @@ -228,7 +226,6 @@ forumlist_body_last_post_title_prepend === * Locations: + styles/prosilver/template/forumlist_body.html - + styles/subsilver2/template/forumlist_body.html * Since: 3.1.0-a1 * Purpose: Add content before the post title of the latest post in a forum on the forum list. @@ -236,7 +233,6 @@ forumlist_body_subforums_after === * Locations: + styles/prosilver/template/forumlist_body.html - + styles/subsilver2/template/forumlist_body.html * Since: 3.1.0-a4 * Purpose: Add content after the list of subforums (if any) for each forum on the forum list. @@ -244,7 +240,6 @@ forumlist_body_subforums_before === * Locations: + styles/prosilver/template/forumlist_body.html - + styles/subsilver2/template/forumlist_body.html * Since: 3.1.0-a4 * Purpose: Add content before the list of subforums (if any) for each forum on the forum list. @@ -252,7 +247,6 @@ forumlist_body_last_row_after === * Locations: + styles/prosilver/template/forumlist_body.html - + styles/subsilver2/template/forumlist_body.html * Since: 3.1.0-b2 * Purpose: Add content after the very last row of the forum list. @@ -260,7 +254,6 @@ index_body_block_birthday_append === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-b3 * Purpose: Append content to the birthday list on the Board index @@ -268,7 +261,6 @@ index_body_block_birthday_prepend === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-b3 * Purpose: Prepend content to the birthday list on the Board index @@ -276,7 +268,6 @@ index_body_block_online_append === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-b3 * Purpose: Append content to the online list on the Board index @@ -284,7 +275,6 @@ index_body_block_online_prepend === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-b3 * Purpose: Prepend content to the online list on the Board index @@ -292,7 +282,6 @@ index_body_block_stats_append === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-b3 * Purpose: Append content to the statistics list on the Board index @@ -300,7 +289,6 @@ index_body_block_stats_prepend === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-b3 * Purpose: Prepend content to the statistics list on the Board index @@ -308,7 +296,6 @@ index_body_markforums_after === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-RC2 * Purpose: Add content after the mark-read link above the forum list on Board index @@ -316,7 +303,6 @@ index_body_markforums_before === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-RC2 * Purpose: Add content before the mark-read link above the forum list on Board index @@ -324,7 +310,6 @@ index_body_stat_blocks_after === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-b3 * Purpose: Add new statistic blocks below the Who Is Online and Board Statistics blocks @@ -332,7 +317,6 @@ index_body_stat_blocks_before === * Locations: + styles/prosilver/template/index_body.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-a1 * Purpose: Add new statistic blocks above the Who Is Online and Board Statistics blocks @@ -340,7 +324,6 @@ mcp_ban_fields_after === * Locations: + styles/prosilver/template/mcp_ban.html - + styles/subsilver2/template/mcp_ban.html * Since: 3.1.0-RC3 * Purpose: Add additional fields to the ban form in MCP @@ -348,7 +331,6 @@ mcp_ban_fields_before === * Locations: + styles/prosilver/template/mcp_ban.html - + styles/subsilver2/template/mcp_ban.html * Since: 3.1.0-RC3 * Purpose: Add additional fields to the ban form in MCP @@ -356,7 +338,6 @@ mcp_ban_unban_after === * Locations: + styles/prosilver/template/mcp_ban.html - + styles/subsilver2/template/mcp_ban.html * Since: 3.1.0-RC3 * Purpose: Add additional fields to the unban form in MCP @@ -364,7 +345,6 @@ mcp_ban_unban_before === * Locations: + styles/prosilver/template/mcp_ban.html - + styles/subsilver2/template/mcp_ban.html * Since: 3.1.0-RC3 * Purpose: Add additional fields to the unban form in MCP @@ -372,7 +352,6 @@ memberlist_body_username_append === * Locations: + styles/prosilver/template/memberlist_body.html - + styles/subsilver2/template/memberlist_body.html * Since: 3.1.0-a1 * Purpose: Add information after every username in the memberlist. Works in all display modes (leader, group and normal memberlist). @@ -381,7 +360,6 @@ memberlist_body_username_prepend === * Locations: + styles/prosilver/template/memberlist_body.html - + styles/subsilver2/template/memberlist_body.html * Since: 3.1.0-a1 * Purpose: Add information before every username in the memberlist. Works in all display modes (leader, group and normal memberlist). @@ -390,7 +368,6 @@ memberlist_view_contact_after === * Locations: + styles/prosilver/template/memberlist_view.html - + styles/subsilver2/template/memberlist_view.html * Since: 3.1.0-b2 * Purpose: Add content after the user contact part of any user profile @@ -398,7 +375,6 @@ memberlist_view_contact_before === * Locations: + styles/prosilver/template/memberlist_view.html - + styles/subsilver2/template/memberlist_view.html * Since: 3.1.0-b2 * Purpose: Add content before the user contact part of any user profile @@ -406,7 +382,6 @@ memberlist_view_content_append === * Locations: + styles/prosilver/template/memberlist_view.html - + styles/subsilver2/template/memberlist_view.html * Since: 3.1.0-b2 * Purpose: Add custom content to the user profile view after the main content @@ -414,7 +389,6 @@ memberlist_view_content_prepend === * Locations: + styles/prosilver/template/memberlist_view.html - + styles/subsilver2/template/memberlist_view.html * Since: 3.1.0-b3 * Purpose: Add custom content to the user profile view before the main content @@ -422,7 +396,6 @@ memberlist_view_user_statistics_after === * Locations: + styles/prosilver/template/memberlist_view.html - + styles/subsilver2/template/memberlist_view.html * Since: 3.1.0-a1 * Purpose: Add entries after the user statistics part of any user profile @@ -430,7 +403,6 @@ memberlist_view_user_statistics_before === * Locations: + styles/prosilver/template/memberlist_view.html - + styles/subsilver2/template/memberlist_view.html * Since: 3.1.0-a1 * Purpose: Add entries before the user statistics part of any user profile @@ -487,7 +459,6 @@ overall_footer_after === * Locations: + styles/prosilver/template/overall_footer.html - + styles/subsilver2/template/overall_footer.html * Since: 3.1.0-a1 * Purpose: Add content at the end of the file, directly prior to the `` tag @@ -495,7 +466,6 @@ overall_footer_breadcrumb_append === * Locations: + styles/prosilver/template/navbar_footer.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-a1 * Purpose: Add links to the list of breadcrumbs in the footer @@ -503,7 +473,6 @@ overall_footer_breadcrumb_prepend === * Locations: + styles/prosilver/template/navbar_footer.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-RC3 * Purpose: Add links to the list of breadcrumbs in the footer (after site-home, but before board-index) @@ -511,7 +480,6 @@ overall_footer_content_after === * Locations: + styles/prosilver/template/overall_footer.html - + styles/subsilver2/template/overall_footer.html * Since: 3.1.0-a3 * Purpose: Add content on all pages after the main content, before the footer @@ -519,7 +487,6 @@ overall_footer_copyright_append === * Locations: + styles/prosilver/template/overall_footer.html - + styles/subsilver2/template/overall_footer.html * Since: 3.1.0-a1 * Purpose: Add content after the copyright line (no new line by default), before the ACP link @@ -527,7 +494,6 @@ overall_footer_copyright_prepend === * Locations: + styles/prosilver/template/overall_footer.html - + styles/subsilver2/template/overall_footer.html * Since: 3.1.0-a1 * Purpose: Add content before the copyright line @@ -535,7 +501,6 @@ overall_footer_page_body_after === * Locations: + styles/prosilver/template/overall_footer.html - + styles/subsilver2/template/overall_footer.html * Since: 3.1.0-b3 * Purpose: Add content after the page-body, but before the footer @@ -543,7 +508,6 @@ overall_footer_teamlink_after === * Locations: + styles/prosilver/template/navbar_footer.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-b3 * Purpose: Add contents after the team-link in the footer @@ -551,7 +515,6 @@ overall_footer_teamlink_before === * Locations: + styles/prosilver/template/navbar_footer.html - + styles/subsilver2/template/index_body.html * Since: 3.1.0-b3 * Purpose: Add contents before the team-link in the footer @@ -559,7 +522,6 @@ overall_footer_timezone_after === * Locations: + styles/prosilver/template/navbar_footer.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-b3 * Purpose: Add content to the navbar in the page footer, after "Timezone" @@ -567,7 +529,6 @@ overall_footer_timezone_before === * Locations: + styles/prosilver/template/navbar_footer.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-b3 * Purpose: Add content to the navbar in the page footer, before "Timezone" @@ -575,7 +536,6 @@ overall_header_body_before === * Locations: + styles/prosilver/template/overall_header.html - + styles/subsilver2/template/overall_header.html * Since: 3.1.0-b2 * Purpose: Add content to the header body @@ -583,7 +543,6 @@ overall_header_breadcrumb_append === * Locations: + styles/prosilver/template/navbar_header.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-a1 * Purpose: Add links to the list of breadcrumbs in the header @@ -591,7 +550,6 @@ overall_header_breadcrumb_prepend === * Locations: + styles/prosilver/template/navbar_header.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-RC3 * Purpose: Add links to the list of breadcrumbs in the header (after site-home, but before board-index) @@ -599,7 +557,6 @@ overall_header_breadcrumbs_after === * Locations: + styles/prosilver/template/navbar_header.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-RC3 * Purpose: Add content after the breadcrumbs (outside of the breadcrumbs container) @@ -607,7 +564,6 @@ overall_header_breadcrumbs_before === * Locations: + styles/prosilver/template/navbar_header.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-RC3 * Purpose: Add content before the breadcrumbs (outside of the breadcrumbs container) @@ -615,7 +571,6 @@ overall_header_content_before === * Locations: + styles/prosilver/template/overall_header.html - + styles/subsilver2/template/overall_header.html * Since: 3.1.0-a3 * Purpose: Add content on all pages before the main content, after the header @@ -623,7 +578,6 @@ overall_header_head_append === * Locations: + styles/prosilver/template/overall_header.html - + styles/subsilver2/template/overall_header.html * Since: 3.1.0-a1 * Purpose: Add asset calls directly before the `` tag @@ -631,7 +585,6 @@ overall_header_navigation_append === * Locations: + styles/prosilver/template/navbar_header.html - + styles/subsilver2/template/overall_header.html * Since: 3.1.0-a1 * Purpose: Add links after the navigation links in the header @@ -639,7 +592,6 @@ overall_header_navigation_prepend === * Locations: + styles/prosilver/template/navbar_header.html - + styles/subsilver2/template/overall_header.html * Since: 3.1.0-a1 * Purpose: Add links before the navigation links in the header @@ -647,7 +599,6 @@ overall_header_navlink_append === * Locations: + styles/prosilver/template/navbar_header.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-b3 * Purpose: Add content after each individual navlink (breadcrumb) @@ -655,7 +606,6 @@ overall_header_navlink_prepend === * Locations: + styles/prosilver/template/navbar_header.html - + styles/subsilver2/template/breadcrumbs.html * Since: 3.1.0-b3 * Purpose: Add content before each individual navlink (breadcrumb) @@ -663,7 +613,6 @@ overall_header_page_body_before === * Locations: + styles/prosilver/template/overall_header.html - + styles/subsilver2/template/overall_header.html * Since: 3.1.0-b3 * Purpose: Add content after the page-header, but before the page-body @@ -671,7 +620,6 @@ overall_header_stylesheets_after === * Locations: + styles/prosilver/template/overall_header.html - + styles/subsilver2/template/overall_header.html * Since: 3.1.0-RC3 * Purpose: Add asset calls after stylesheets within the `` tag. Note that INCLUDECSS will not work with this event. @@ -680,7 +628,6 @@ posting_editor_buttons_after === * Locations: + styles/prosilver/template/posting_buttons.html - + styles/subsilver2/template/posting_buttons.html * Since: 3.1.0-a3 * Purpose: Add content after the BBCode posting buttons @@ -688,7 +635,6 @@ posting_editor_buttons_before === * Locations: + styles/prosilver/template/posting_buttons.html - + styles/subsilver2/template/posting_buttons.html * Since: 3.1.0-a3 * Purpose: Add content before the BBCode posting buttons @@ -696,7 +642,6 @@ posting_editor_message_after === * Locations: + styles/prosilver/template/posting_editor.html - + styles/subsilver2/template/posting_body.html * Since: 3.1.0-a2 * Purpose: Add field (e.g. textbox) to the posting screen after the message @@ -704,7 +649,6 @@ posting_editor_message_before === * Locations: + styles/prosilver/template/posting_editor.html - + styles/subsilver2/template/posting_body.html * Since: 3.1.0-a2 * Purpose: Add field (e.g. textbox) to the posting screen before the message @@ -712,7 +656,6 @@ posting_editor_options_prepend === * Locations: + styles/prosilver/template/posting_editor.html - + styles/subsilver2/template/posting_body.html * Since: 3.1.0-a1 * Purpose: Add posting options on the posting screen @@ -720,7 +663,6 @@ posting_editor_subject_after === * Locations: + styles/prosilver/template/posting_editor.html - + styles/subsilver2/template/posting_body.html * Since: 3.1.0-a2 * Purpose: Add field (e.g. textbox) to the posting screen after the subject @@ -728,7 +670,6 @@ posting_editor_subject_before === * Locations: + styles/prosilver/template/posting_editor.html - + styles/subsilver2/template/posting_body.html * Since: 3.1.0-a2 * Purpose: Add field (e.g. textbox) to the posting screen before the subject @@ -736,7 +677,6 @@ quickreply_editor_panel_after === * Locations: + styles/prosilver/template/quickreply_editor.html - + styles/subsilver2/template/quickreply_editor.html * Since: 3.1.0-b2 * Purpose: Add content after the quick reply panel (but inside the form) @@ -744,7 +684,6 @@ quickreply_editor_panel_before === * Locations: + styles/prosilver/template/quickreply_editor.html - + styles/subsilver2/template/quickreply_editor.html * Since: 3.1.0-b2 * Purpose: Add content before the quick reply panel (but inside the form) @@ -752,7 +691,6 @@ quickreply_editor_message_after === * Locations: + styles/prosilver/template/quickreply_editor.html - + styles/subsilver2/template/quickreply_editor.html * Since: 3.1.0-a4 * Purpose: Add content after the quick reply textbox @@ -760,7 +698,6 @@ quickreply_editor_message_before === * Locations: + styles/prosilver/template/quickreply_editor.html - + styles/subsilver2/template/quickreply_editor.html * Since: 3.1.0-a4 * Purpose: Add content before the quick reply textbox @@ -768,7 +705,6 @@ search_results_post_after === * Locations: + styles/prosilver/template/search_results.html - + styles/subsilver2/template/search_results.html * Since: 3.1.0-b3 * Purpose: Add data after search result posts @@ -776,7 +712,6 @@ search_results_post_before === * Locations: + styles/prosilver/template/search_results.html - + styles/subsilver2/template/search_results.html * Since: 3.1.0-b3 * Purpose: Add data before search result posts @@ -798,7 +733,6 @@ search_results_topic_after === * Locations: + styles/prosilver/template/search_results.html - + styles/subsilver2/template/search_results.html * Since: 3.1.0-b4 * Purpose: Add data after search result topics @@ -806,7 +740,6 @@ search_results_topic_before === * Locations: + styles/prosilver/template/search_results.html - + styles/subsilver2/template/search_results.html * Since: 3.1.0-b4 * Purpose: Add data before search result topics @@ -814,7 +747,6 @@ simple_footer_after === * Locations: + styles/prosilver/template/simple_footer.html - + styles/subsilver2/template/simple_footer.html * Since: 3.1.0-a1 * Purpose: Add content directly prior to the `` tag of the simple footer @@ -822,7 +754,6 @@ simple_header_body_before === * Locations: + styles/prosilver/template/simple_header.html - + styles/subsilver2/template/simple_header.html * Since: 3.1.0-b2 * Purpose: Add content to the header body @@ -830,7 +761,6 @@ simple_header_head_append === * Locations: + styles/prosilver/template/simple_header.html - + styles/subsilver2/template/simple_header.html * Since: 3.1.0-b4 * Purpose: Add asset calls directly before the `` tag @@ -838,7 +768,6 @@ simple_header_stylesheets_after === * Locations: + styles/prosilver/template/simple_header.html - + styles/subsilver2/template/simple_header.html * Since: 3.1.0-RC3 * Purpose: Add asset calls after stylesheets within the `` tag. Note that INCLUDECSS will not work with this event. @@ -848,8 +777,6 @@ topiclist_row_prepend * Locations: + styles/prosilver/template/search_results.html + styles/prosilver/template/viewforum_body.html - + styles/subsilver2/template/search_results.html - + styles/subsilver2/template/viewforum_body.html * Since: 3.1.0-a1 * Purpose: Add content into topic rows (inside the elements containing topic titles) @@ -858,8 +785,6 @@ topiclist_row_append * Locations: + styles/prosilver/template/search_results.html + styles/prosilver/template/viewforum_body.html - + styles/subsilver2/template/search_results.html - + styles/subsilver2/template/viewforum_body.html * Since: 3.1.0-a1 * Purpose: Add content into topic rows (inside the elements containing topic titles) @@ -867,7 +792,6 @@ ucp_agreement_terms_after === * Locations: + styles/prosilver/template/ucp_agreement.html - + styles/subsilver2/template/ucp_agreement.html * Since: 3.1.0-b3 * Purpose: Add content after the terms of agreement text at user registration @@ -875,7 +799,6 @@ ucp_agreement_terms_before === * Locations: + styles/prosilver/template/ucp_agreement.html - + styles/subsilver2/template/ucp_agreement.html * Since: 3.1.0-b3 * Purpose: Add content before the terms of agreement text at user registration @@ -929,7 +852,6 @@ ucp_pm_viewmessage_post_buttons_after === * Locations: + styles/prosilver/template/ucp_pm_viewmessage.html - + styles/subsilver2/template/ucp_pm_viewmessage.html * Since: 3.1.0-RC3 * Purpose: Add post button to private messages (next to edit, quote etc), at the end of the list. @@ -938,7 +860,6 @@ ucp_pm_viewmessage_post_buttons_before === * Locations: + styles/prosilver/template/ucp_pm_viewmessage.html - + styles/subsilver2/template/ucp_pm_viewmessage.html * Since: 3.1.0-RC3 * Purpose: Add post button to private messages (next to edit, quote etc), at the start of the list. @@ -947,7 +868,6 @@ ucp_pm_viewmessage_print_head_append === * Locations: + styles/prosilver/template/ucp_pm_viewmessage_print.html - + styles/subsilver2/template/ucp_pm_viewmessage_print.html * Since: 3.1.0-a1 * Purpose: Add asset calls directly before the `` tag of the Print PM screen @@ -955,7 +875,6 @@ ucp_prefs_personal_prepend === * Locations: + styles/prosilver/template/ucp_prefs_personal.html - + styles/subsilver2/template/ucp_prefs_personal.html * Since: 3.1.0-a1 * Purpose: Add user options to the top of the Edit Global Settings block @@ -963,7 +882,6 @@ ucp_prefs_personal_append === * Locations: + styles/prosilver/template/ucp_prefs_personal.html - + styles/subsilver2/template/ucp_prefs_personal.html * Since: 3.1.0-a1 * Purpose: Add user options to the bottom of the Edit Global Settings block @@ -971,7 +889,6 @@ ucp_prefs_post_prepend === * Locations: + styles/prosilver/template/ucp_prefs_post.html - + styles/subsilver2/template/ucp_prefs_post.html * Since: 3.1.0-a1 * Purpose: Add user options to the top of the Edit Posting Defaults block @@ -979,7 +896,6 @@ ucp_prefs_post_append === * Locations: + styles/prosilver/template/ucp_prefs_post.html - + styles/subsilver2/template/ucp_prefs_post.html * Since: 3.1.0-a1 * Purpose: Add user options to the bottom of the Edit Posting Defaults block @@ -987,7 +903,6 @@ ucp_prefs_view_radio_buttons_prepend === * Locations: + styles/prosilver/template/ucp_prefs_view.html - + styles/subsilver2/template/ucp_prefs_view.html * Since: 3.1.0-a1 * Purpose: Add options to the top of the radio buttons block of the Edit Display Options screen @@ -996,7 +911,6 @@ ucp_prefs_view_radio_buttons_append === * Locations: + styles/prosilver/template/ucp_prefs_view.html - + styles/subsilver2/template/ucp_prefs_view.html * Since: 3.1.0-a1 * Purpose: Add options to the bottom of the radio buttons block of the Edit Display Options screen @@ -1005,7 +919,6 @@ ucp_prefs_view_select_menu_prepend === * Locations: + styles/prosilver/template/ucp_prefs_view.html - + styles/subsilver2/template/ucp_prefs_view.html * Since: 3.1.0-a1 * Purpose: Add options to the top of the drop-down lists block of the Edit Display Options screen @@ -1014,7 +927,6 @@ ucp_prefs_view_select_menu_append === * Locations: + styles/prosilver/template/ucp_prefs_view.html - + styles/subsilver2/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 @@ -1023,7 +935,6 @@ ucp_register_credentials_before === * Locations: + styles/prosilver/template/ucp_register.html - + styles/subsilver2/template/ucp_register.html * Since: 3.1.0-b5 * Purpose: Add options in registration page fieldset - before first field. @@ -1031,7 +942,6 @@ ucp_register_profile_fields_after === * Locations: + styles/prosilver/template/ucp_register.html - + styles/subsilver2/template/ucp_register.html * Since: 3.1.0-b5 * Purpose: Add options in registration page fieldset - after last field. @@ -1039,7 +949,6 @@ ucp_register_credentials_after === * Locations: + styles/prosilver/template/ucp_register.html - + styles/subsilver2/template/ucp_register.html * Since: 3.1.0-b5 * Purpose: Add options in registration page fieldset - after password field. @@ -1047,7 +956,6 @@ ucp_register_options_before === * Locations: + styles/prosilver/template/ucp_register.html - + styles/subsilver2/template/ucp_register.html * Since: 3.1.0-b5 * Purpose: Add options in registration page fieldset - before language selector. @@ -1055,7 +963,6 @@ ucp_register_profile_fields_before === * Locations: + styles/prosilver/template/ucp_register.html - + styles/subsilver2/template/ucp_register.html * Since: 3.1.0-b5 * Purpose: Add options in registration page fieldset - before profile fields. @@ -1063,7 +970,6 @@ ucp_friend_list_before === * Locations: + styles/prosilver/template/ucp_zebra_friends.html - + styles/subsilver2/template/ucp_zebra_friends.html * Since: 3.1.0-a4 * Purpose: Add optional elements before list of friends in UCP @@ -1071,7 +977,6 @@ ucp_friend_list_after === * Locations: + styles/prosilver/template/ucp_zebra_friends.html - + styles/subsilver2/template/ucp_zebra_friends.html * Since: 3.1.0-a4 * Purpose: Add optional elements after list of friends in UCP @@ -1079,7 +984,6 @@ viewforum_forum_name_append === * Locations: + styles/prosilver/template/viewforum_body.html - + styles/subsilver2/template/viewforum_body.html * Since: 3.1.0-b3 * Purpose: Add content directly after the forum name link on the View forum screen @@ -1087,7 +991,6 @@ viewforum_forum_name_prepend === * Locations: + styles/prosilver/template/viewforum_body.html - + styles/subsilver2/template/viewforum_body.html * Since: 3.1.0-b3 * Purpose: Add content directly before the forum name link on the View forum screen @@ -1095,7 +998,6 @@ viewtopic_print_head_append === * Locations: + styles/prosilver/template/viewtopic_print.html - + styles/subsilver2/template/viewtopic_print.html * Since: 3.1.0-a1 * Purpose: Add asset calls directly before the `` tag of the Print Topic screen @@ -1103,7 +1005,6 @@ viewtopic_body_avatar_after === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-RC3 * Purpose: Add content right after the avatar when viewing topics @@ -1111,7 +1012,6 @@ viewtopic_body_avatar_before === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-RC3 * Purpose: Add content right before the avatar when viewing topics @@ -1135,17 +1035,14 @@ viewtopic_body_footer_before === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-a1 * Purpose: Add content to the bottom of the View topic screen below the posts -and quick reply, directly before the jumpbox in Prosilver, breadcrumbs in -Subsilver2. +and quick reply, directly before the jumpbox in Prosilver. viewtopic_body_poll_option_after === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-b3 * Purpose: Add content after the poll option the list. @@ -1154,7 +1051,6 @@ viewtopic_body_poll_option_before === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-b3 * Purpose: Add content before the poll option the list. @@ -1163,7 +1059,6 @@ viewtopic_body_poll_question_append === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-b3 * Purpose: Add content directly after the poll question on the View topic screen @@ -1171,7 +1066,6 @@ viewtopic_body_poll_question_prepend === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-b3 * Purpose: Add content directly before the poll question on the View topic screen @@ -1179,7 +1073,6 @@ viewtopic_body_post_buttons_after === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-a1 * Purpose: Add post button to posts (next to edit, quote etc), at the end of the list. @@ -1188,7 +1081,6 @@ viewtopic_body_post_buttons_before === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-a1 * Purpose: Add post button to posts (next to edit, quote etc), at the start of the list. @@ -1197,7 +1089,6 @@ viewtopic_body_postrow_custom_fields_after === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-a1 * Purpose: Add data after the custom fields on the user profile when viewing a post @@ -1206,7 +1097,6 @@ viewtopic_body_postrow_custom_fields_before === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-a1 * Purpose: Add data before the custom fields on the user profile when viewing a post @@ -1215,7 +1105,6 @@ viewtopic_body_postrow_post_after === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-a4 * Purpose: Add data after posts @@ -1223,7 +1112,6 @@ viewtopic_body_postrow_post_before === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-a4 * Purpose: Add data before posts @@ -1231,7 +1119,6 @@ viewtopic_body_postrow_post_notices_after === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-b2 * Purpose: Add posts specific custom notices at the notices bottom. @@ -1239,7 +1126,6 @@ viewtopic_body_postrow_post_notices_before === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-b2 * Purpose: Add posts specific custom notices at the notices top. @@ -1247,7 +1133,6 @@ viewtopic_body_topic_actions_before === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-a4 * Purpose: Add data before the topic actions buttons (after the posts sorting options) @@ -1255,7 +1140,6 @@ viewtopic_topic_title_append === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-b3 * Purpose: Add content directly after the topic title link on the View topic screen @@ -1263,7 +1147,6 @@ viewtopic_topic_title_prepend === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-a1 * Purpose: Add content directly before the topic title link on the View topic screen diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index 82ca0fc18d..bd8d3751e1 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -1689,7 +1689,7 @@ class install_update extends module // Get custom installed styles... $sql = 'SELECT style_name, style_path FROM ' . STYLES_TABLE . " - WHERE LOWER(style_name) NOT IN ('subsilver2', 'prosilver')"; + WHERE LOWER(style_name) NOT IN ('prosilver')"; $result = $db->sql_query($sql); $templates = array(); diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php index f7021875f3..84b10e79c1 100644 --- a/phpBB/phpbb/event/md_exporter.php +++ b/phpBB/phpbb/event/md_exporter.php @@ -89,7 +89,7 @@ class md_exporter { $this->crawl_eventsmd($md_file, 'styles'); - $styles = array('prosilver', 'subsilver2'); + $styles = array('prosilver'); foreach ($styles as $style) { $file_list = $this->get_recursive_file_list( @@ -179,7 +179,7 @@ class md_exporter { $wiki_page = '= Template Events =' . "\n"; $wiki_page .= '{| class="zebra sortable" cellspacing="0" cellpadding="5"' . "\n"; - $wiki_page .= '! Identifier !! Prosilver Placement (If applicable) !! Subsilver Placement (If applicable) !! Added in Release !! Explanation' . "\n"; + $wiki_page .= '! Identifier !! Prosilver Placement (If applicable) !! Added in Release !! Explanation' . "\n"; } foreach ($this->events as $event_name => $event) @@ -193,7 +193,7 @@ class md_exporter } else { - $wiki_page .= implode(', ', $event['files']['prosilver']) . ' || ' . implode(', ', $event['files']['subsilver2']); + $wiki_page .= implode(', ', $event['files']['prosilver']); } $wiki_page .= " || {$event['since']} || " . str_replace("\n", ' ', $event['description']) . "\n"; @@ -246,7 +246,6 @@ class md_exporter { $files_list = array( 'prosilver' => array(), - 'subsilver2' => array(), 'adm' => array(), ); @@ -266,10 +265,6 @@ class md_exporter { $files_list['prosilver'][] = substr($file, strlen('styles/prosilver/template/')); } - else if (($this->filter !== 'adm') && strpos($file, 'styles/subsilver2/template/') === 0) - { - $files_list['subsilver2'][] = substr($file, strlen('styles/subsilver2/template/')); - } else if (($this->filter === 'adm') && strpos($file, 'adm/style/') === 0) { $files_list['adm'][] = substr($file, strlen('adm/style/')); diff --git a/tests/event/md_exporter_test.php b/tests/event/md_exporter_test.php index 0f9d855caa..28649e4f21 100644 --- a/tests/event/md_exporter_test.php +++ b/tests/event/md_exporter_test.php @@ -41,7 +41,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case $styles = array( 'adm/style/' => 'adm', 'styles/prosilver/template/' => 'styles', - 'styles/subsilver2/template/' => 'styles', ); foreach ($styles as $path => $filter) { diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 80e6293ff9..6a33fd7711 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -474,7 +474,7 @@ class phpbb_functional_test_case extends phpbb_test_case )); $db->sql_query($sql); - if ($style_path != 'prosilver' && $style_path != 'subsilver2') + if ($style_path != 'prosilver') { @mkdir($phpbb_root_path . 'styles/' . $style_path, 0777); @mkdir($phpbb_root_path . 'styles/' . $style_path . '/template', 0777); @@ -513,7 +513,7 @@ class phpbb_functional_test_case extends phpbb_test_case $db->sql_query('DELETE FROM ' . STYLES_TEMPLATE_TABLE . ' WHERE template_id = ' . $style_id); $db->sql_query('DELETE FROM ' . STYLES_THEME_TABLE . ' WHERE theme_id = ' . $style_id); - if ($style_path != 'prosilver' && $style_path != 'subsilver2') + if ($style_path != 'prosilver') { @rmdir($phpbb_root_path . 'styles/' . $style_path . '/template'); @rmdir($phpbb_root_path . 'styles/' . $style_path); From 7faf66c492c038dcbd3dd09d8064ff0b15bb0ee6 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 12 Aug 2014 10:56:20 +0200 Subject: [PATCH 0019/1676] [ticket/12974] Update nightly build version to 3.2.0-a1-dev PHPBB3-12974 --- build/build.xml | 2 +- phpBB/includes/constants.php | 2 +- phpBB/install/schemas/schema_data.sql | 2 +- phpBB/styles/prosilver/style.cfg | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/build.xml b/build/build.xml index 991d344331..8e968a908f 100644 --- a/build/build.xml +++ b/build/build.xml @@ -2,7 +2,7 @@ - + diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 0eac2e9417..126cf44842 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -28,7 +28,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -define('PHPBB_VERSION', '3.1.0-RC4-dev'); +define('PHPBB_VERSION', '3.2.0-a1-dev'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 37e1c8de50..c32e2f825a 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -273,7 +273,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0 INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.1.0-RC4-dev'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-a1-dev'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg index aea59021d6..481b80d912 100644 --- a/phpBB/styles/prosilver/style.cfg +++ b/phpBB/styles/prosilver/style.cfg @@ -21,8 +21,8 @@ # General Information about this style name = prosilver copyright = © phpBB Limited, 2007 -style_version = 3.1.0-RC3 -phpbb_version = 3.1.0-RC3 +style_version = 3.2.0-a1-dev +phpbb_version = 3.2.0-a1-dev # Defining a different template bitfield # template_bitfield = lNg= From 61dc381be618f22fa28c8b81786f88843effade3 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 1 Sep 2014 00:33:54 +0200 Subject: [PATCH 0020/1676] [ticket/13024] Fix event file (remove subsilver references) PHPBB3-13024 --- phpBB/docs/events.md | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index b6a9b2b4f5..2129c43757 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -1119,7 +1119,6 @@ viewtopic_body_postrow_post_content_footer === * Locations: + styles/prosilver/template/viewtopic_body.html - + styles/subsilver2/template/viewtopic_body.html * Since: 3.1.0-RC4 * Purpose: Add data at the end of the posts. From 55a3c96fb008a96e43572329ed5127ce7d6f5f6f Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 2 Sep 2014 22:12:11 +0200 Subject: [PATCH 0021/1676] [ticket/12661] Fix unit tests PHPBB3-12661 --- tests/template/template_allfolder_test.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/template/template_allfolder_test.php b/tests/template/template_allfolder_test.php index b4ad84e9c3..e87688a57c 100644 --- a/tests/template/template_allfolder_test.php +++ b/tests/template/template_allfolder_test.php @@ -51,9 +51,29 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case ) ); + $container = new phpbb_mock_container_builder(); + $cache_path = $phpbb_root_path . 'cache/twig'; + $context = new \phpbb\template\context(); + $loader = new \phpbb\template\twig\loader(''); + $twig = new \phpbb\template\twig\environment( + $config, + $path_helper, + $container, + $cache_path, + $this->extension_manager, + $loader, + array( + 'cache' => false, + 'debug' => false, + 'auto_reload' => true, + 'autoescape' => false, + ) + ); + $this->template = new \phpbb\template\twig\twig($path_helper, $config, $this->user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager); + $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); + $this->template_path = $this->test_path . '/templates'; $this->ext_template_path = 'tests/extension/ext/vendor4/bar/styles/all/template'; - $this->template = new \phpbb\template\twig\twig($path_helper, $config, $this->user, new \phpbb\template\context(), $this->extension_manager); $this->template->set_custom_style('all', array($this->template_path, $this->ext_template_path)); } } From 03a1c7ed2ee5e8df79e0e13a6d2599ba80acbb46 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 4 Oct 2014 21:16:12 +0200 Subject: [PATCH 0022/1676] [ticket/13130] Updates dependencies to Symfony 2.5 PHPBB3-13130 --- phpBB/composer.json | 30 +++--- phpBB/composer.lock | 230 +++++++++++++++++++++++--------------------- 2 files changed, 136 insertions(+), 124 deletions(-) diff --git a/phpBB/composer.json b/phpBB/composer.json index 69f0de8479..d197e906d9 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -27,13 +27,13 @@ "require": { "php": ">=5.3.3", "lusitanian/oauth": "0.2.*", - "symfony/config": "2.3.*", - "symfony/console": "2.3.*", - "symfony/dependency-injection": "2.3.*", - "symfony/event-dispatcher": "2.3.*", - "symfony/http-kernel": "2.3.*", - "symfony/routing": "2.3.*", - "symfony/yaml": "2.3.*", + "symfony/config": "2.5.*", + "symfony/console": "2.5.*", + "symfony/dependency-injection": "2.5.*", + "symfony/event-dispatcher": "2.5.*", + "symfony/http-kernel": "2.5.*", + "symfony/routing": "2.5.*", + "symfony/yaml": "2.5.*", "twig/twig": "1.13.*" }, "require-dev": { @@ -43,13 +43,13 @@ "phing/phing": "2.4.*", "sami/sami": "1.*", "squizlabs/php_codesniffer": "1.*", - "symfony/browser-kit": "2.3.*", - "symfony/css-selector": "2.3.*", - "symfony/debug": "2.3.*", - "symfony/dom-crawler": "2.3.*", - "symfony/filesystem": "2.3.*", - "symfony/finder": "2.3.*", - "symfony/http-foundation": "2.3.*", - "symfony/process": "2.3.*" + "symfony/browser-kit": "2.5.*", + "symfony/css-selector": "2.5.*", + "symfony/debug": "2.5.*", + "symfony/dom-crawler": "2.5.*", + "symfony/filesystem": "2.5.*", + "symfony/finder": "2.5.*", + "symfony/http-foundation": "2.5.*", + "symfony/process": "2.5.*" } } diff --git a/phpBB/composer.lock b/phpBB/composer.lock index b686bfef5c..1d0a4a1259 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "d93446768ea0665b7c55c01890153a67", + "hash": "1344b97ad0b4c8eb75a384a545065333", "packages": [ { "name": "lusitanian/oauth", @@ -108,17 +108,17 @@ }, { "name": "symfony/config", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/Config", "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "b34d2b32a92938476f0689486e7a11ea1aeb079e" + "reference": "0316364bfebc8b080077c731a99f189341476bd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/b34d2b32a92938476f0689486e7a11ea1aeb079e", - "reference": "b34d2b32a92938476f0689486e7a11ea1aeb079e", + "url": "https://api.github.com/repos/symfony/Config/zipball/0316364bfebc8b080077c731a99f189341476bd7", + "reference": "0316364bfebc8b080077c731a99f189341476bd7", "shasum": "" }, "require": { @@ -128,7 +128,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -152,36 +152,38 @@ ], "description": "Symfony Config Component", "homepage": "http://symfony.com", - "time": "2014-08-02 07:53:48" + "time": "2014-09-23 05:25:11" }, { "name": "symfony/console", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "a2723f99716c2fa6411e2eb5842edbe680e4b462" + "reference": "ca053eaa031c93afb68a71e4eb1f4168dfd4a661" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/a2723f99716c2fa6411e2eb5842edbe680e4b462", - "reference": "a2723f99716c2fa6411e2eb5842edbe680e4b462", + "url": "https://api.github.com/repos/symfony/Console/zipball/ca053eaa031c93afb68a71e4eb1f4168dfd4a661", + "reference": "ca053eaa031c93afb68a71e4eb1f4168dfd4a661", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { + "psr/log": "~1.0", "symfony/event-dispatcher": "~2.1" }, "suggest": { + "psr/log": "For using the console logger", "symfony/event-dispatcher": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -205,21 +207,21 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2014-08-07 15:55:24" + "time": "2014-09-25 09:53:56" }, { "name": "symfony/debug", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/Debug", "source": { "type": "git", "url": "https://github.com/symfony/Debug.git", - "reference": "91e3a1480c67601d2406cd938735abe0243e1c95" + "reference": "4a3dd4ef3fc0cee2fd9faaae12bd7af43afcf648" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Debug/zipball/91e3a1480c67601d2406cd938735abe0243e1c95", - "reference": "91e3a1480c67601d2406cd938735abe0243e1c95", + "url": "https://api.github.com/repos/symfony/Debug/zipball/4a3dd4ef3fc0cee2fd9faaae12bd7af43afcf648", + "reference": "4a3dd4ef3fc0cee2fd9faaae12bd7af43afcf648", "shasum": "" }, "require": { @@ -230,14 +232,13 @@ "symfony/http-kernel": "~2.1" }, "suggest": { - "symfony/class-loader": "", "symfony/http-foundation": "", "symfony/http-kernel": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -261,21 +262,21 @@ ], "description": "Symfony Debug Component", "homepage": "http://symfony.com", - "time": "2014-07-07 10:13:42" + "time": "2014-09-28 15:22:14" }, { "name": "symfony/dependency-injection", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/DependencyInjection", "source": { "type": "git", "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "5ee5795515be251c56057d79154e561ee1efecd2" + "reference": "1f01a64c9047909e40700a14ee34e8c446300618" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/5ee5795515be251c56057d79154e561ee1efecd2", - "reference": "5ee5795515be251c56057d79154e561ee1efecd2", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/1f01a64c9047909e40700a14ee34e8c446300618", + "reference": "1f01a64c9047909e40700a14ee34e8c446300618", "shasum": "" }, "require": { @@ -283,6 +284,7 @@ }, "require-dev": { "symfony/config": "~2.2", + "symfony/expression-language": "~2.4", "symfony/yaml": "~2.0" }, "suggest": { @@ -293,7 +295,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -317,28 +319,31 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "http://symfony.com", - "time": "2014-08-27 08:32:18" + "time": "2014-09-27 08:35:39" }, { "name": "symfony/event-dispatcher", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "2c64e46d7e22bcafcab4413ff62bc389abf87ea5" + "reference": "f6281337bf5f985f585d1db6a83adb05ce531f46" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/2c64e46d7e22bcafcab4413ff62bc389abf87ea5", - "reference": "2c64e46d7e22bcafcab4413ff62bc389abf87ea5", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/f6281337bf5f985f585d1db6a83adb05ce531f46", + "reference": "f6281337bf5f985f585d1db6a83adb05ce531f46", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "symfony/dependency-injection": "~2.0" + "psr/log": "~1.0", + "symfony/config": "~2.0", + "symfony/dependency-injection": "~2.0,<2.6.0", + "symfony/stopwatch": "~2.2" }, "suggest": { "symfony/dependency-injection": "", @@ -347,7 +352,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -371,21 +376,21 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "http://symfony.com", - "time": "2014-07-25 15:00:14" + "time": "2014-09-28 15:56:11" }, { "name": "symfony/filesystem", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "007359d2822d5eba4f04f6507bc9b46877c622b4" + "reference": "4e62fab0060a826561c78b665925b37c870c45f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/007359d2822d5eba4f04f6507bc9b46877c622b4", - "reference": "007359d2822d5eba4f04f6507bc9b46877c622b4", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/4e62fab0060a826561c78b665925b37c870c45f5", + "reference": "4e62fab0060a826561c78b665925b37c870c45f5", "shasum": "" }, "require": { @@ -394,7 +399,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -418,30 +423,33 @@ ], "description": "Symfony Filesystem Component", "homepage": "http://symfony.com", - "time": "2014-08-31 03:30:23" + "time": "2014-09-22 09:14:18" }, { "name": "symfony/http-foundation", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/HttpFoundation", "source": { "type": "git", "url": "https://github.com/symfony/HttpFoundation.git", - "reference": "d0125fed988da9e189864c2e6de967b3ee7f1d98" + "reference": "650e115af152d7a5e857d01c2cdb9a22809de9b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/d0125fed988da9e189864c2e6de967b3ee7f1d98", - "reference": "d0125fed988da9e189864c2e6de967b3ee7f1d98", + "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/650e115af152d7a5e857d01c2cdb9a22809de9b4", + "reference": "650e115af152d7a5e857d01c2cdb9a22809de9b4", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "symfony/expression-language": "~2.4" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -468,29 +476,29 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "http://symfony.com", - "time": "2014-09-03 07:39:11" + "time": "2014-09-25 09:52:29" }, { "name": "symfony/http-kernel", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/HttpKernel", "source": { "type": "git", "url": "https://github.com/symfony/HttpKernel.git", - "reference": "a24817f69012b23ce7c554af6b4c7b53235c7c55" + "reference": "6a3595611229def14d5e644f060cf372235532ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/a24817f69012b23ce7c554af6b4c7b53235c7c55", - "reference": "a24817f69012b23ce7c554af6b4c7b53235c7c55", + "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/6a3595611229def14d5e644f060cf372235532ec", + "reference": "6a3595611229def14d5e644f060cf372235532ec", "shasum": "" }, "require": { "php": ">=5.3.3", "psr/log": "~1.0", - "symfony/debug": "~2.3", - "symfony/event-dispatcher": "~2.1", - "symfony/http-foundation": "~2.2" + "symfony/debug": "~2.5", + "symfony/event-dispatcher": "~2.5", + "symfony/http-foundation": "~2.5" }, "require-dev": { "symfony/browser-kit": "~2.2", @@ -498,6 +506,7 @@ "symfony/config": "~2.0", "symfony/console": "~2.2", "symfony/dependency-injection": "~2.0", + "symfony/expression-language": "~2.4", "symfony/finder": "~2.0", "symfony/process": "~2.0", "symfony/routing": "~2.2", @@ -515,7 +524,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -539,41 +548,44 @@ ], "description": "Symfony HttpKernel Component", "homepage": "http://symfony.com", - "time": "2014-09-03 09:45:27" + "time": "2014-09-28 17:33:53" }, { "name": "symfony/routing", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/Routing", "source": { "type": "git", "url": "https://github.com/symfony/Routing.git", - "reference": "aa2beef5d5f1d84250b5ca73a4056c0504e5969e" + "reference": "9bc38fe72e0eff61611e7cd4df3accbce20b1d36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Routing/zipball/aa2beef5d5f1d84250b5ca73a4056c0504e5969e", - "reference": "aa2beef5d5f1d84250b5ca73a4056c0504e5969e", + "url": "https://api.github.com/repos/symfony/Routing/zipball/9bc38fe72e0eff61611e7cd4df3accbce20b1d36", + "reference": "9bc38fe72e0eff61611e7cd4df3accbce20b1d36", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "doctrine/common": "~2.2", + "doctrine/annotations": "~1.0", "psr/log": "~1.0", "symfony/config": "~2.2", + "symfony/expression-language": "~2.4", + "symfony/http-foundation": "~2.3", "symfony/yaml": "~2.0" }, "suggest": { - "doctrine/common": "", - "symfony/config": "", - "symfony/yaml": "" + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/yaml": "For using the YAML loader" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -597,21 +609,27 @@ ], "description": "Symfony Routing Component", "homepage": "http://symfony.com", - "time": "2014-08-15 09:05:55" + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2014-09-22 15:28:36" }, { "name": "symfony/yaml", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "71ceeca3d8164f0c5313127b24ad056071ccf2c6" + "reference": "b1dbc53593b98c2d694ebf383660ac9134d30b96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/71ceeca3d8164f0c5313127b24ad056071ccf2c6", - "reference": "71ceeca3d8164f0c5313127b24ad056071ccf2c6", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/b1dbc53593b98c2d694ebf383660ac9134d30b96", + "reference": "b1dbc53593b98c2d694ebf383660ac9134d30b96", "shasum": "" }, "require": { @@ -620,7 +638,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -644,7 +662,7 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2014-08-28 01:42:35" + "time": "2014-09-22 09:14:18" }, { "name": "twig/twig", @@ -1987,17 +2005,17 @@ }, { "name": "symfony/browser-kit", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/BrowserKit", "source": { "type": "git", "url": "https://github.com/symfony/BrowserKit.git", - "reference": "262d698efaa788ce24ff9c987378789bf3f81ce9" + "reference": "0cb9e603b1850c9495bfb96b3c4caf7ea17700d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/262d698efaa788ce24ff9c987378789bf3f81ce9", - "reference": "262d698efaa788ce24ff9c987378789bf3f81ce9", + "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/0cb9e603b1850c9495bfb96b3c4caf7ea17700d4", + "reference": "0cb9e603b1850c9495bfb96b3c4caf7ea17700d4", "shasum": "" }, "require": { @@ -2014,7 +2032,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -2038,21 +2056,21 @@ ], "description": "Symfony BrowserKit Component", "homepage": "http://symfony.com", - "time": "2014-08-05 07:20:55" + "time": "2014-09-22 09:14:18" }, { "name": "symfony/css-selector", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/CssSelector", "source": { "type": "git", "url": "https://github.com/symfony/CssSelector.git", - "reference": "8953d325d3341c246abadb79be172de95ef80664" + "reference": "caf5ecc3face1f22884fb74b8edab65ac5ba9976" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/CssSelector/zipball/8953d325d3341c246abadb79be172de95ef80664", - "reference": "8953d325d3341c246abadb79be172de95ef80664", + "url": "https://api.github.com/repos/symfony/CssSelector/zipball/caf5ecc3face1f22884fb74b8edab65ac5ba9976", + "reference": "caf5ecc3face1f22884fb74b8edab65ac5ba9976", "shasum": "" }, "require": { @@ -2061,7 +2079,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -2089,21 +2107,21 @@ ], "description": "Symfony CssSelector Component", "homepage": "http://symfony.com", - "time": "2014-08-27 08:24:06" + "time": "2014-09-22 09:14:18" }, { "name": "symfony/dom-crawler", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/DomCrawler", "source": { "type": "git", "url": "https://github.com/symfony/DomCrawler.git", - "reference": "bad8d98561f071639fa67b20680bffcc256ce252" + "reference": "a2804ec76442a9d0a3bb25f99a7830ba24743e07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/bad8d98561f071639fa67b20680bffcc256ce252", - "reference": "bad8d98561f071639fa67b20680bffcc256ce252", + "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/a2804ec76442a9d0a3bb25f99a7830ba24743e07", + "reference": "a2804ec76442a9d0a3bb25f99a7830ba24743e07", "shasum": "" }, "require": { @@ -2118,7 +2136,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -2142,21 +2160,21 @@ ], "description": "Symfony DomCrawler Component", "homepage": "http://symfony.com", - "time": "2014-08-21 00:21:59" + "time": "2014-09-22 09:14:18" }, { "name": "symfony/finder", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "f7a5a5a3b1fc0ec9a1a5b4429223a8726e0f4b55" + "reference": "d5033742b9a6206ef6d06e813870bca18e9205df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/f7a5a5a3b1fc0ec9a1a5b4429223a8726e0f4b55", - "reference": "f7a5a5a3b1fc0ec9a1a5b4429223a8726e0f4b55", + "url": "https://api.github.com/repos/symfony/Finder/zipball/d5033742b9a6206ef6d06e813870bca18e9205df", + "reference": "d5033742b9a6206ef6d06e813870bca18e9205df", "shasum": "" }, "require": { @@ -2165,7 +2183,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -2189,21 +2207,21 @@ ], "description": "Symfony Finder Component", "homepage": "http://symfony.com", - "time": "2014-08-31 04:03:32" + "time": "2014-09-27 08:35:39" }, { "name": "symfony/process", - "version": "v2.3.19", + "version": "v2.5.5", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "b8fc0e4b6750e4c458a38d038e6b4d538d4fe2bb" + "reference": "8a1ec96c4e519cee0fb971ea48a1eb7369dda54b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/b8fc0e4b6750e4c458a38d038e6b4d538d4fe2bb", - "reference": "b8fc0e4b6750e4c458a38d038e6b4d538d4fe2bb", + "url": "https://api.github.com/repos/symfony/Process/zipball/8a1ec96c4e519cee0fb971ea48a1eb7369dda54b", + "reference": "8a1ec96c4e519cee0fb971ea48a1eb7369dda54b", "shasum": "" }, "require": { @@ -2212,7 +2230,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -2236,20 +2254,14 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2014-08-28 09:02:24" + "time": "2014-09-23 05:25:11" } ], - "aliases": [ - - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": [ - - ], + "stability-flags": [], "platform": { "php": ">=5.3.3" }, - "platform-dev": [ - - ] + "platform-dev": [] } From a712d8a3b39025fde4652bbba0b9f466392c2d17 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 4 Oct 2014 23:25:40 +0200 Subject: [PATCH 0023/1676] [ticket/13130] Fix tests PHPBB3-13130 --- tests/test_framework/phpbb_functional_test_case.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 8927c4dbf9..c47ae2cab6 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -934,8 +934,7 @@ class phpbb_functional_test_case extends phpbb_test_case */ public function assert_checkbox_is_unchecked($crawler, $name, $message = '') { - $this->assertSame( - '', + $this->assertNull( $this->assert_find_one_checkbox($crawler, $name)->attr('checked'), $message ?: "Failed asserting that checkbox $name is unchecked." ); From 5a7caf65084369422fdbe4aaaae46e5de69cc594 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 20 Nov 2013 13:47:31 +0100 Subject: [PATCH 0024/1676] [feature/patchwork-utf8] Normalize with intl, use patchwork/utf8 as fallback --- phpBB/composer.json | 1 + phpBB/composer.lock | 56 + phpBB/develop/generate_utf_tables.php | 290 +--- phpBB/develop/unicode_testing.php | 35 - phpBB/develop/utf_normalizer_test.php | 394 ----- .../includes/utf/data/utf_canonical_comp.php | 2 - .../utf/data/utf_canonical_decomp.php | 2 - .../utf/data/utf_compatibility_decomp.php | 2 - phpBB/includes/utf/data/utf_nfc_qc.php | 2 - phpBB/includes/utf/data/utf_nfkc_qc.php | 2 - .../utf/data/utf_normalizer_common.php | 4 - phpBB/includes/utf/utf_normalizer.php | 1509 ----------------- phpBB/includes/utf/utf_tools.php | 121 +- phpBB/install/data/confusables.php | 8 +- phpBB/install/data/new_normalizer.php | 197 --- phpBB/install/database_update.php | 1 - phpBB/install/index.php | 1 - phpBB/phpbb/search/fulltext_native.php | 34 +- tests/RUNNING_TESTS.md | 5 +- tests/utf/normalizer_test.php | 327 ---- 20 files changed, 110 insertions(+), 2883 deletions(-) delete mode 100644 phpBB/develop/utf_normalizer_test.php delete mode 100644 phpBB/includes/utf/data/utf_canonical_comp.php delete mode 100644 phpBB/includes/utf/data/utf_canonical_decomp.php delete mode 100644 phpBB/includes/utf/data/utf_compatibility_decomp.php delete mode 100644 phpBB/includes/utf/data/utf_nfc_qc.php delete mode 100644 phpBB/includes/utf/data/utf_nfkc_qc.php delete mode 100644 phpBB/includes/utf/data/utf_normalizer_common.php delete mode 100644 phpBB/includes/utf/utf_normalizer.php delete mode 100644 phpBB/install/data/new_normalizer.php delete mode 100644 tests/utf/normalizer_test.php diff --git a/phpBB/composer.json b/phpBB/composer.json index d197e906d9..c6fcb281b9 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -27,6 +27,7 @@ "require": { "php": ">=5.3.3", "lusitanian/oauth": "0.2.*", + "patchwork/utf8": "1.1.*", "symfony/config": "2.5.*", "symfony/console": "2.5.*", "symfony/dependency-injection": "2.5.*", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 1d0a4a1259..ea177f537a 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -68,6 +68,62 @@ ], "time": "2013-08-29 21:40:04" }, + { + "name": "patchwork/utf8", + "version": "v1.1.26", + "source": { + "type": "git", + "url": "https://github.com/tchwork/utf8.git", + "reference": "6b8e46603b49ee87ad6bceb314da94cc04ffcdce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tchwork/utf8/zipball/6b8e46603b49ee87ad6bceb314da94cc04ffcdce", + "reference": "6b8e46603b49ee87ad6bceb314da94cc04ffcdce", + "shasum": "" + }, + "require": { + "lib-pcre": ">=7.3", + "php": ">=5.3.0" + }, + "suggest": { + "ext-iconv": "Use iconv for best performance", + "ext-intl": "Use Intl for best performance", + "ext-mbstring": "Use Mbstring for best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-0": { + "Patchwork": "class/", + "Normalizer": "class/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "(Apache-2.0 or GPL-2.0)" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + } + ], + "description": "Portable and performant UTF-8, Unicode and Grapheme Clusters for PHP", + "homepage": "https://github.com/tchwork/utf8", + "keywords": [ + "grapheme", + "i18n", + "unicode", + "utf-8", + "utf8" + ], + "time": "2014-11-08 10:13:25" + }, { "name": "psr/log", "version": "1.0.0", diff --git a/phpBB/develop/generate_utf_tables.php b/phpBB/develop/generate_utf_tables.php index 16a449679b..888c07676d 100644 --- a/phpBB/develop/generate_utf_tables.php +++ b/phpBB/develop/generate_utf_tables.php @@ -32,262 +32,11 @@ $phpbb_root_path = '../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); echo "Checking for required files\n"; -download('http://www.unicode.org/Public/UNIDATA/CompositionExclusions.txt'); -download('http://www.unicode.org/Public/UNIDATA/DerivedNormalizationProps.txt'); download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt'); echo "\n"; -require_once($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); -$file_contents = array(); - /** -* Generate some Hangul/Jamo stuff -*/ -echo "\nGenerating Hangul and Jamo tables\n"; -for ($i = 0; $i < UNICODE_HANGUL_LCOUNT; ++$i) -{ - $utf_char = cp_to_utf(UNICODE_HANGUL_LBASE + $i); - $file_contents['utf_normalizer_common']['utf_jamo_index'][$utf_char] = $i * UNICODE_HANGUL_VCOUNT * UNICODE_HANGUL_TCOUNT + UNICODE_HANGUL_SBASE; - $file_contents['utf_normalizer_common']['utf_jamo_type'][$utf_char] = UNICODE_JAMO_L; -} - -for ($i = 0; $i < UNICODE_HANGUL_VCOUNT; ++$i) -{ - $utf_char = cp_to_utf(UNICODE_HANGUL_VBASE + $i); - $file_contents['utf_normalizer_common']['utf_jamo_index'][$utf_char] = $i * UNICODE_HANGUL_TCOUNT; - $file_contents['utf_normalizer_common']['utf_jamo_type'][$utf_char] = UNICODE_JAMO_V; -} - -for ($i = 0; $i < UNICODE_HANGUL_TCOUNT; ++$i) -{ - $utf_char = cp_to_utf(UNICODE_HANGUL_TBASE + $i); - $file_contents['utf_normalizer_common']['utf_jamo_index'][$utf_char] = $i; - $file_contents['utf_normalizer_common']['utf_jamo_type'][$utf_char] = UNICODE_JAMO_T; -} - -/** -* Load the CompositionExclusions table -*/ -echo "Loading CompositionExclusion\n"; -$fp = fopen('CompositionExclusions.txt', 'rt'); - -$exclude = array(); -while (!feof($fp)) -{ - $line = fgets($fp, 1024); - - if (!strpos(' 0123456789ABCDEFabcdef', $line[0])) - { - continue; - } - - $cp = strtok($line, ' '); - - if ($pos = strpos($cp, '..')) - { - $start = hexdec(substr($cp, 0, $pos)); - $end = hexdec(substr($cp, $pos + 2)); - - for ($i = $start; $i < $end; ++$i) - { - $exclude[$i] = 1; - } - } - else - { - $exclude[hexdec($cp)] = 1; - } -} -fclose($fp); - -/** -* Load QuickCheck tables -*/ -echo "Generating QuickCheck tables\n"; -$fp = fopen('DerivedNormalizationProps.txt', 'rt'); - -while (!feof($fp)) -{ - $line = fgets($fp, 1024); - - if (!strpos(' 0123456789ABCDEFabcdef', $line[0])) - { - continue; - } - - $p = array_map('trim', explode(';', strtok($line, '#'))); - - /** - * Capture only NFC_QC, NFKC_QC - */ - if (!preg_match('#^NFK?C_QC$#', $p[1])) - { - continue; - } - - if ($pos = strpos($p[0], '..')) - { - $start = hexdec(substr($p[0], 0, $pos)); - $end = hexdec(substr($p[0], $pos + 2)); - } - else - { - $start = $end = hexdec($p[0]); - } - - if ($start >= UTF8_HANGUL_FIRST && $end <= UTF8_HANGUL_LAST) - { - /** - * We do not store Hangul syllables in the array - */ - continue; - } - - if ($p[2] == 'M') - { - $val = UNICODE_QC_MAYBE; - } - else - { - $val = UNICODE_QC_NO; - } - - if ($p[1] == 'NFKC_QC') - { - $file = 'utf_nfkc_qc'; - } - else - { - $file = 'utf_nfc_qc'; - } - - for ($i = $start; $i <= $end; ++$i) - { - /** - * The vars have the same name as the file: $utf_nfc_qc is in utf_nfc_qc.php - */ - $file_contents[$file][$file][cp_to_utf($i)] = $val; - } -} -fclose($fp); - -/** -* Do mappings -*/ -echo "Loading Unicode decomposition mappings\n"; -$fp = fopen($phpbb_root_path . 'develop/UnicodeData.txt', 'rt'); - -$map = array(); -while (!feof($fp)) -{ - $p = explode(';', fgets($fp, 1024)); - $cp = hexdec($p[0]); - - if (!empty($p[3])) - { - /** - * Store combining class > 0 - */ - $file_contents['utf_normalizer_common']['utf_combining_class'][cp_to_utf($cp)] = (int) $p[3]; - } - - if (!isset($p[5]) || !preg_match_all('#[0-9A-F]+#', strip_tags($p[5]), $m)) - { - continue; - } - - if (strpos($p[5], '>')) - { - $map['NFKD'][$cp] = implode(' ', array_map('hexdec', $m[0])); - } - else - { - $map['NFD'][$cp] = $map['NFKD'][$cp] = implode(' ', array_map('hexdec', $m[0])); - } -} -fclose($fp); - -/** -* Build the canonical composition table -*/ -echo "Generating the Canonical Composition table\n"; -foreach ($map['NFD'] as $cp => $decomp_seq) -{ - if (!strpos($decomp_seq, ' ') || isset($exclude[$cp])) - { - /** - * Singletons are excluded from canonical composition - */ - continue; - } - - $utf_seq = implode('', array_map('cp_to_utf', explode(' ', $decomp_seq))); - - if (!isset($file_contents['utf_canonical_comp']['utf_canonical_comp'][$utf_seq])) - { - $file_contents['utf_canonical_comp']['utf_canonical_comp'][$utf_seq] = cp_to_utf($cp); - } -} - -/** -* Decompose the NF[K]D mappings recursively and prepare the file contents -*/ -echo "Generating the Canonical and Compatibility Decomposition tables\n\n"; -foreach ($map as $type => $decomp_map) -{ - foreach ($decomp_map as $cp => $decomp_seq) - { - $decomp_map[$cp] = decompose($decomp_map, $decomp_seq); - } - unset($decomp_seq); - - if ($type == 'NFKD') - { - $file = 'utf_compatibility_decomp'; - $var = 'utf_compatibility_decomp'; - } - else - { - $file = 'utf_canonical_decomp'; - $var = 'utf_canonical_decomp'; - } - - /** - * Generate the corresponding file - */ - foreach ($decomp_map as $cp => $decomp_seq) - { - $file_contents[$file][$var][cp_to_utf($cp)] = implode('', array_map('cp_to_utf', explode(' ', $decomp_seq))); - } -} - -/** -* Generate and/or alter the files -*/ -foreach ($file_contents as $file => $contents) -{ - /** - * Generate a new file - */ - echo "Writing to $file.$phpEx\n"; - - if (!$fp = fopen($phpbb_root_path . 'includes/utf/data/' . $file . '.' . $phpEx, 'wb')) - { - trigger_error('Cannot open ' . $file . ' for write'); - } - - fwrite($fp, ' $val) - { - fwrite($fp, "\n\$GLOBALS[" . my_var_export($var) . ']=' . my_var_export($val) . ";"); - } - fclose($fp); -} - -echo "\n*** UTF-8 normalization tables done\n\n"; - -/** -* Now we'll generate the files needed by the search indexer +* Generate the files needed by the search indexer */ echo "Generating search indexer tables\n"; @@ -424,32 +173,6 @@ die("\nAll done!\n"); // Internal functions // //////////////////////////////////////////////////////////////////////////////// -/** -* Decompose a sequence recusively -* -* @param array $decomp_map Decomposition mapping, passed by reference -* @param string $decomp_seq Decomposition sequence as decimal codepoints separated with a space -* @return string Decomposition sequence, fully decomposed -*/ -function decompose(&$decomp_map, $decomp_seq) -{ - $ret = array(); - foreach (explode(' ', $decomp_seq) as $cp) - { - if (isset($decomp_map[$cp])) - { - $ret[] = decompose($decomp_map, $decomp_map[$cp]); - } - else - { - $ret[] = $cp; - } - } - - return implode(' ', $ret); -} - - /** * Return a parsable string representation of a variable * @@ -537,17 +260,6 @@ function hex_to_utf($hex) return cp_to_utf(hexdec($hex)); } -/** -* Return a UTF string formed from a sequence of codepoints in hexadecimal -* -* @param string $seq Sequence of codepoints, separated with a space -* @return string UTF-8 string -*/ -function hexseq_to_utf($seq) -{ - return implode('', array_map('hex_to_utf', explode(' ', $seq))); -} - /** * Convert a codepoint to a UTF-8 char * diff --git a/phpBB/develop/unicode_testing.php b/phpBB/develop/unicode_testing.php index ec3c71d078..ca6d1b5f48 100644 --- a/phpBB/develop/unicode_testing.php +++ b/phpBB/develop/unicode_testing.php @@ -81,38 +81,3 @@ function utf8_to_unicode_callback($m) { return '\u' . str_pad(base_convert(utf8_ord($m[0]), 10, 16), 4, '0', STR_PAD_LEFT) . ''; } - -/** -* A wrapper function for the normalizer which takes care of including the class if required and modifies the passed strings -* to be in NFKC -* -* @param mixed $strings a string or an array of strings to normalize -* @return mixed the normalized content, preserving array keys if array given. -*/ -function utf8_normalize_nfkc($strings) -{ - if (empty($strings)) - { - return $strings; - } - - if (!class_exists('utf_normalizer')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); - } - - if (!is_array($strings)) - { - utf_normalizer::nfkc($strings); - } - else if (is_array($strings)) - { - foreach ($strings as $key => $string) - { - utf_normalizer::nfkc($strings[$key]); - } - } - - return $strings; -} diff --git a/phpBB/develop/utf_normalizer_test.php b/phpBB/develop/utf_normalizer_test.php deleted file mode 100644 index 27ff786db7..0000000000 --- a/phpBB/develop/utf_normalizer_test.php +++ /dev/null @@ -1,394 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -if (php_sapi_name() != 'cli') -{ - die("This program must be run from the command line.\n"); -} - -// -// Security message: -// -// This script is potentially dangerous. -// Remove or comment the next line (die(".... ) to enable this script. -// Do NOT FORGET to either remove this script or disable it after you have used it. -// -die("Please read the first lines of this script for instructions on how to enable it"); - -set_time_limit(0); -error_reporting(E_ALL); - -define('IN_PHPBB', true); -$phpbb_root_path = '../'; -$phpEx = substr(strrchr(__FILE__, '.'), 1); - - -/** -* Let's download some files we need -*/ -download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt'); -download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt'); - -/** -* Those are the tests we run -*/ -$test_suite = array( - /** - * NFC - * c2 == NFC(c1) == NFC(c2) == NFC(c3) - * c4 == NFC(c4) == NFC(c5) - */ - 'NFC' => array( - 'c2' => array('c1', 'c2', 'c3'), - 'c4' => array('c4', 'c5') - ), - - /** - * NFD - * c3 == NFD(c1) == NFD(c2) == NFD(c3) - * c5 == NFD(c4) == NFD(c5) - */ - 'NFD' => array( - 'c3' => array('c1', 'c2', 'c3'), - 'c5' => array('c4', 'c5') - ), - - /** - * NFKC - * c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5) - */ - 'NFKC' => array( - 'c4' => array('c1', 'c2', 'c3', 'c4', 'c5') - ), - - /** - * NFKD - * c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5) - */ - 'NFKD' => array( - 'c5' => array('c1', 'c2', 'c3', 'c4', 'c5') - ) -); - -require_once($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); - -$i = $n = 0; -$failed = false; -$tested_chars = array(); - -$fp = fopen($phpbb_root_path . 'develop/NormalizationTest.txt', 'rb'); -while (!feof($fp)) -{ - $line = fgets($fp); - ++$n; - - if ($line[0] == '@') - { - if ($i) - { - echo "done\n"; - } - - $i = 0; - echo "\n", substr($line, 1), "\n\n"; - continue; - } - - if (!strpos(' 0123456789ABCDEF', $line[0])) - { - continue; - } - - if (++$i % 100 == 0) - { - echo $i, ' '; - } - - list($c1, $c2, $c3, $c4, $c5) = explode(';', $line); - - if (!strpos($c1, ' ')) - { - /** - * We are currently testing a single character, we add it to the list of - * characters we have processed so that we can exclude it when testing - * for invariants - */ - $tested_chars[$c1] = 1; - } - - foreach ($test_suite as $form => $serie) - { - foreach ($serie as $expected => $tests) - { - $hex_expected = ${$expected}; - $utf_expected = hexseq_to_utf($hex_expected); - - foreach ($tests as $test) - { - $utf_result = $utf_expected; - call_user_func(array('utf_normalizer', $form), $utf_result); - - if (strcmp($utf_expected, $utf_result)) - { - $failed = true; - $hex_result = utf_to_hexseq($utf_result); - - echo "\nFAILED $expected == $form($test) ($hex_expected != $hex_result)"; - } - } - } - - if ($failed) - { - die("\n\nFailed at line $n\n"); - } - } -} -fclose($fp); - -/** -* Test for invariants -*/ -echo "\n\nTesting for invariants...\n\n"; - -$fp = fopen($phpbb_root_path . 'develop/UnicodeData.txt', 'rt'); - -$n = 0; -while (!feof($fp)) -{ - if (++$n % 100 == 0) - { - echo $n, ' '; - } - - $line = fgets($fp, 1024); - - if (!$pos = strpos($line, ';')) - { - continue; - } - - $hex_tested = $hex_expected = substr($line, 0, $pos); - - if (isset($tested_chars[$hex_tested])) - { - continue; - } - - $utf_expected = hex_to_utf($hex_expected); - - if ($utf_expected >= UTF8_SURROGATE_FIRST - && $utf_expected <= UTF8_SURROGATE_LAST) - { - /** - * Surrogates are illegal on their own, we expect the normalizer - * to return a replacement char - */ - $utf_expected = UTF8_REPLACEMENT; - $hex_expected = utf_to_hexseq($utf_expected); - } - - foreach (array('nfc', 'nfkc', 'nfd', 'nfkd') as $form) - { - $utf_result = $utf_expected; - utf_normalizer::$form($utf_result); - $hex_result = utf_to_hexseq($utf_result); -// echo "$form($utf_expected) == $utf_result\n"; - - if (strcmp($utf_expected, $utf_result)) - { - $failed = 1; - - echo "\nFAILED $hex_expected == $form($hex_tested) ($hex_expected != $hex_result)"; - } - } - - if ($failed) - { - die("\n\nFailed at line $n\n"); - } -} -fclose($fp); - -die("\n\nALL TESTS PASSED SUCCESSFULLY\n"); - -/** -* Download a file to the develop/ dir -* -* @param string $url URL of the file to download -* @return null -*/ -function download($url) -{ - global $phpbb_root_path; - - if (file_exists($phpbb_root_path . 'develop/' . basename($url))) - { - return; - } - - echo 'Downloading from ', $url, ' '; - - if (!$fpr = fopen($url, 'rb')) - { - die("Can't download from $url\nPlease download it yourself and put it in the develop/ dir, kthxbai"); - } - - if (!$fpw = fopen($phpbb_root_path . 'develop/' . basename($url), 'wb')) - { - die("Can't open develop/" . basename($url) . " for output... please check your permissions or something"); - } - - $i = 0; - $chunk = 32768; - $done = ''; - - while (!feof($fpr)) - { - $i += fwrite($fpw, fread($fpr, $chunk)); - echo str_repeat("\x08", strlen($done)); - - $done = ($i >> 10) . ' KiB'; - echo $done; - } - fclose($fpr); - fclose($fpw); - - echo "\n"; -} - -/** -* Convert a UTF string to a sequence of codepoints in hexadecimal -* -* @param string $utf UTF string -* @return integer Unicode codepoints in hex -*/ -function utf_to_hexseq($str) -{ - $pos = 0; - $len = strlen($str); - $ret = array(); - - while ($pos < $len) - { - $c = $str[$pos]; - switch ($c & "\xF0") - { - case "\xC0": - case "\xD0": - $utf_char = substr($str, $pos, 2); - $pos += 2; - break; - - case "\xE0": - $utf_char = substr($str, $pos, 3); - $pos += 3; - break; - - case "\xF0": - $utf_char = substr($str, $pos, 4); - $pos += 4; - break; - - default: - $utf_char = $c; - ++$pos; - } - - $hex = dechex(utf_to_cp($utf_char)); - - if (!isset($hex[3])) - { - $hex = substr('000' . $hex, -4); - } - - $ret[] = $hex; - } - - return strtr(implode(' ', $ret), 'abcdef', 'ABCDEF'); -} - -/** -* Convert a UTF-8 char to its codepoint -* -* @param string $utf_char UTF-8 char -* @return integer Unicode codepoint -*/ -function utf_to_cp($utf_char) -{ - switch (strlen($utf_char)) - { - case 1: - return ord($utf_char); - - case 2: - return ((ord($utf_char[0]) & 0x1F) << 6) | (ord($utf_char[1]) & 0x3F); - - case 3: - return ((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F); - - case 4: - return ((ord($utf_char[0]) & 0x07) << 18) | ((ord($utf_char[1]) & 0x3F) << 12) | ((ord($utf_char[2]) & 0x3F) << 6) | (ord($utf_char[3]) & 0x3F); - - default: - die('UTF-8 chars can only be 1-4 bytes long'); - } -} - -/** -* Return a UTF string formed from a sequence of codepoints in hexadecimal -* -* @param string $seq Sequence of codepoints, separated with a space -* @return string UTF-8 string -*/ -function hexseq_to_utf($seq) -{ - return implode('', array_map('hex_to_utf', explode(' ', $seq))); -} - -/** -* Convert a codepoint in hexadecimal to a UTF-8 char -* -* @param string $hex Codepoint, in hexadecimal -* @return string UTF-8 char -*/ -function hex_to_utf($hex) -{ - return cp_to_utf(hexdec($hex)); -} - -/** -* Convert a codepoint to a UTF-8 char -* -* @param integer $cp Unicode codepoint -* @return string UTF-8 string -*/ -function cp_to_utf($cp) -{ - if ($cp > 0xFFFF) - { - return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); - } - else if ($cp > 0x7FF) - { - return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); - } - else if ($cp > 0x7F) - { - return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F)); - } - else - { - return chr($cp); - } -} diff --git a/phpBB/includes/utf/data/utf_canonical_comp.php b/phpBB/includes/utf/data/utf_canonical_comp.php deleted file mode 100644 index 2de3149ee8..0000000000 --- a/phpBB/includes/utf/data/utf_canonical_comp.php +++ /dev/null @@ -1,2 +0,0 @@ -'À','AÌ'=>'Ã','AÌ‚'=>'Â','Ã'=>'Ã','Ä'=>'Ä','AÌŠ'=>'Ã…','Ç'=>'Ç','EÌ€'=>'È','EÌ'=>'É','EÌ‚'=>'Ê','Ë'=>'Ë','IÌ€'=>'ÃŒ','IÌ'=>'Ã','IÌ‚'=>'ÃŽ','Ï'=>'Ã','Ñ'=>'Ñ','OÌ€'=>'Ã’','OÌ'=>'Ó','OÌ‚'=>'Ô','Õ'=>'Õ','Ö'=>'Ö','UÌ€'=>'Ù','UÌ'=>'Ú','UÌ‚'=>'Û','Ü'=>'Ü','YÌ'=>'Ã','aÌ€'=>'à','aÌ'=>'á','aÌ‚'=>'â','ã'=>'ã','ä'=>'ä','aÌŠ'=>'Ã¥','ç'=>'ç','eÌ€'=>'è','eÌ'=>'é','eÌ‚'=>'ê','ë'=>'ë','iÌ€'=>'ì','iÌ'=>'í','iÌ‚'=>'î','ï'=>'ï','ñ'=>'ñ','oÌ€'=>'ò','oÌ'=>'ó','oÌ‚'=>'ô','õ'=>'õ','ö'=>'ö','uÌ€'=>'ù','uÌ'=>'ú','uÌ‚'=>'û','ü'=>'ü','yÌ'=>'ý','ÿ'=>'ÿ','AÌ„'=>'Ä€','aÌ„'=>'Ä','Ă'=>'Ä‚','ă'=>'ă','Ą'=>'Ä„','ą'=>'Ä…','CÌ'=>'Ć','cÌ'=>'ć','CÌ‚'=>'Ĉ','cÌ‚'=>'ĉ','Ċ'=>'ÄŠ','ċ'=>'Ä‹','CÌŒ'=>'ÄŒ','cÌŒ'=>'Ä','DÌŒ'=>'ÄŽ','dÌŒ'=>'Ä','EÌ„'=>'Ä’','eÌ„'=>'Ä“','Ĕ'=>'Ä”','ĕ'=>'Ä•','Ė'=>'Ä–','ė'=>'Ä—','Ę'=>'Ę','ę'=>'Ä™','EÌŒ'=>'Äš','eÌŒ'=>'Ä›','GÌ‚'=>'Äœ','gÌ‚'=>'Ä','Ğ'=>'Äž','ğ'=>'ÄŸ','Ġ'=>'Ä ','ġ'=>'Ä¡','Ģ'=>'Ä¢','ģ'=>'Ä£','HÌ‚'=>'Ĥ','hÌ‚'=>'Ä¥','Ĩ'=>'Ĩ','ĩ'=>'Ä©','IÌ„'=>'Ī','iÌ„'=>'Ä«','Ĭ'=>'Ĭ','ĭ'=>'Ä­','Į'=>'Ä®','į'=>'į','İ'=>'İ','JÌ‚'=>'Ä´','jÌ‚'=>'ĵ','Ķ'=>'Ķ','ķ'=>'Ä·','LÌ'=>'Ĺ','lÌ'=>'ĺ','Ļ'=>'Ä»','ļ'=>'ļ','LÌŒ'=>'Ľ','lÌŒ'=>'ľ','NÌ'=>'Ń','nÌ'=>'Å„','Ņ'=>'Å…','ņ'=>'ņ','NÌŒ'=>'Ň','nÌŒ'=>'ň','OÌ„'=>'ÅŒ','oÌ„'=>'Å','Ŏ'=>'ÅŽ','ŏ'=>'Å','OÌ‹'=>'Å','oÌ‹'=>'Å‘','RÌ'=>'Å”','rÌ'=>'Å•','Ŗ'=>'Å–','ŗ'=>'Å—','RÌŒ'=>'Ř','rÌŒ'=>'Å™','SÌ'=>'Åš','sÌ'=>'Å›','SÌ‚'=>'Åœ','sÌ‚'=>'Å','Ş'=>'Åž','ş'=>'ÅŸ','SÌŒ'=>'Å ','sÌŒ'=>'Å¡','Ţ'=>'Å¢','ţ'=>'Å£','TÌŒ'=>'Ť','tÌŒ'=>'Å¥','Ũ'=>'Ũ','ũ'=>'Å©','UÌ„'=>'Ū','uÌ„'=>'Å«','Ŭ'=>'Ŭ','ŭ'=>'Å­','UÌŠ'=>'Å®','uÌŠ'=>'ů','UÌ‹'=>'Ű','uÌ‹'=>'ű','Ų'=>'Ų','ų'=>'ų','WÌ‚'=>'Å´','wÌ‚'=>'ŵ','YÌ‚'=>'Ŷ','yÌ‚'=>'Å·','Ÿ'=>'Ÿ','ZÌ'=>'Ź','zÌ'=>'ź','Ż'=>'Å»','ż'=>'ż','ZÌŒ'=>'Ž','zÌŒ'=>'ž','OÌ›'=>'Æ ','oÌ›'=>'Æ¡','UÌ›'=>'Ư','uÌ›'=>'ư','AÌŒ'=>'Ç','aÌŒ'=>'ÇŽ','IÌŒ'=>'Ç','iÌŒ'=>'Ç','OÌŒ'=>'Ç‘','oÌŒ'=>'Ç’','UÌŒ'=>'Ç“','uÌŒ'=>'Ç”','Ǖ'=>'Ç•','ǖ'=>'Ç–','ÜÌ'=>'Ç—','üÌ'=>'ǘ','Ǚ'=>'Ç™','ǚ'=>'Çš','Ǜ'=>'Ç›','ǜ'=>'Çœ','Ǟ'=>'Çž','ǟ'=>'ÇŸ','Ǡ'=>'Ç ','ǡ'=>'Ç¡','Ǣ'=>'Ç¢','ǣ'=>'Ç£','GÌŒ'=>'Ǧ','gÌŒ'=>'ǧ','KÌŒ'=>'Ǩ','kÌŒ'=>'Ç©','Ǫ'=>'Ǫ','ǫ'=>'Ç«','Ǭ'=>'Ǭ','ǭ'=>'Ç­','Æ·ÌŒ'=>'Ç®','Ê’ÌŒ'=>'ǯ','jÌŒ'=>'ǰ','GÌ'=>'Ç´','gÌ'=>'ǵ','NÌ€'=>'Ǹ','nÌ€'=>'ǹ','Ã…Ì'=>'Ǻ','Ã¥Ì'=>'Ç»','ÆÌ'=>'Ǽ','æÌ'=>'ǽ','ØÌ'=>'Ǿ','øÌ'=>'Ç¿','AÌ'=>'È€','aÌ'=>'È','AÌ‘'=>'È‚','aÌ‘'=>'ȃ','EÌ'=>'È„','eÌ'=>'È…','EÌ‘'=>'Ȇ','eÌ‘'=>'ȇ','IÌ'=>'Ȉ','iÌ'=>'ȉ','IÌ‘'=>'ÈŠ','iÌ‘'=>'È‹','OÌ'=>'ÈŒ','oÌ'=>'È','OÌ‘'=>'ÈŽ','oÌ‘'=>'È','RÌ'=>'È','rÌ'=>'È‘','RÌ‘'=>'È’','rÌ‘'=>'È“','UÌ'=>'È”','uÌ'=>'È•','UÌ‘'=>'È–','uÌ‘'=>'È—','Ș'=>'Ș','ș'=>'È™','Ț'=>'Èš','ț'=>'È›','HÌŒ'=>'Èž','hÌŒ'=>'ÈŸ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','ȩ'=>'È©','Ȫ'=>'Ȫ','ȫ'=>'È«','Ȭ'=>'Ȭ','ȭ'=>'È­','Ȯ'=>'È®','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','YÌ„'=>'Ȳ','yÌ„'=>'ȳ','̈Ì'=>'Í„','¨Ì'=>'Î…','ΑÌ'=>'Ά','ΕÌ'=>'Έ','ΗÌ'=>'Ή','ΙÌ'=>'Ί','ΟÌ'=>'ÎŒ','Î¥Ì'=>'ÎŽ','ΩÌ'=>'Î','ÏŠÌ'=>'Î','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','αÌ'=>'ά','εÌ'=>'έ','ηÌ'=>'ή','ιÌ'=>'ί','Ï‹Ì'=>'ΰ','ϊ'=>'ÏŠ','ϋ'=>'Ï‹','οÌ'=>'ÏŒ','Ï…Ì'=>'Ï','ωÌ'=>'ÏŽ','Ï’Ì'=>'Ï“','ϔ'=>'Ï”','Ѐ'=>'Ѐ','Ё'=>'Ð','ГÌ'=>'Ѓ','Ї'=>'Ї','КÌ'=>'ÐŒ','Ѝ'=>'Ð','Ў'=>'ÐŽ','Й'=>'Й','й'=>'й','ѐ'=>'Ñ','ё'=>'Ñ‘','гÌ'=>'Ñ“','ї'=>'Ñ—','кÌ'=>'Ñœ','ѝ'=>'Ñ','ў'=>'Ñž','Ñ´Ì'=>'Ѷ','ѵÌ'=>'Ñ·','Ӂ'=>'Ó','ӂ'=>'Ó‚','Ð̆'=>'Ó','ӑ'=>'Ó‘','Ð̈'=>'Ó’','ӓ'=>'Ó“','Ӗ'=>'Ó–','ӗ'=>'Ó—','Ӛ'=>'Óš','ӛ'=>'Ó›','Ӝ'=>'Óœ','ӝ'=>'Ó','Ӟ'=>'Óž','ӟ'=>'ÓŸ','Ӣ'=>'Ó¢','ӣ'=>'Ó£','Ӥ'=>'Ó¤','ӥ'=>'Ó¥','Ӧ'=>'Ó¦','ӧ'=>'Ó§','Ӫ'=>'Óª','ӫ'=>'Ó«','Ӭ'=>'Ó¬','Ñ̈'=>'Ó­','Ӯ'=>'Ó®','ӯ'=>'Ó¯','Ӱ'=>'Ó°','ӱ'=>'Ó±','Ӳ'=>'Ó²','ӳ'=>'Ó³','Ӵ'=>'Ó´','ӵ'=>'Óµ','Ӹ'=>'Ó¸','ӹ'=>'Ó¹','آ'=>'Ø¢','أ'=>'Ø£','ÙˆÙ”'=>'ؤ','إ'=>'Ø¥','ÙŠÙ”'=>'ئ','Û•Ù”'=>'Û€','ÛÙ”'=>'Û‚','Û’Ù”'=>'Û“','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','ো'=>'à§‹','ৌ'=>'à§Œ','ୈ'=>'à­ˆ','ୋ'=>'à­‹','ୌ'=>'à­Œ','ஔ'=>'à®”','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','ೀ'=>'à³€','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','ේ'=>'à·š','à·™à·'=>'à·œ','ෝ'=>'à·','ෞ'=>'à·ž','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ཱྀ'=>'à¾','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','á¬á¬µ'=>'ᬎ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','ᭀ'=>'á­€','ᭁ'=>'á­','ᭃ'=>'á­ƒ','AÌ¥'=>'Ḁ','aÌ¥'=>'á¸','Ḃ'=>'Ḃ','ḃ'=>'ḃ','BÌ£'=>'Ḅ','bÌ£'=>'ḅ','Ḇ'=>'Ḇ','ḇ'=>'ḇ','ÇÌ'=>'Ḉ','çÌ'=>'ḉ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','DÌ£'=>'Ḍ','dÌ£'=>'á¸','Ḏ'=>'Ḏ','ḏ'=>'á¸','Ḑ'=>'á¸','ḑ'=>'ḑ','DÌ­'=>'Ḓ','dÌ­'=>'ḓ','Ä’Ì€'=>'Ḕ','ḕ'=>'ḕ','Ä’Ì'=>'Ḗ','Ä“Ì'=>'ḗ','EÌ­'=>'Ḙ','eÌ­'=>'ḙ','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','ḝ'=>'á¸','Ḟ'=>'Ḟ','ḟ'=>'ḟ','GÌ„'=>'Ḡ','gÌ„'=>'ḡ','Ḣ'=>'Ḣ','ḣ'=>'ḣ','HÌ£'=>'Ḥ','hÌ£'=>'ḥ','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','HÌ®'=>'Ḫ','hÌ®'=>'ḫ','Ḭ'=>'Ḭ','ḭ'=>'ḭ','ÃÌ'=>'Ḯ','ïÌ'=>'ḯ','KÌ'=>'Ḱ','kÌ'=>'ḱ','KÌ£'=>'Ḳ','kÌ£'=>'ḳ','Ḵ'=>'Ḵ','ḵ'=>'ḵ','LÌ£'=>'Ḷ','lÌ£'=>'ḷ','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','LÌ­'=>'Ḽ','lÌ­'=>'ḽ','MÌ'=>'Ḿ','mÌ'=>'ḿ','Ṁ'=>'á¹€','ṁ'=>'á¹','MÌ£'=>'Ṃ','mÌ£'=>'ṃ','Ṅ'=>'Ṅ','ṅ'=>'á¹…','NÌ£'=>'Ṇ','nÌ£'=>'ṇ','Ṉ'=>'Ṉ','ṉ'=>'ṉ','NÌ­'=>'Ṋ','nÌ­'=>'ṋ','ÕÌ'=>'Ṍ','õÌ'=>'á¹','Ṏ'=>'Ṏ','ṏ'=>'á¹','Ṑ'=>'á¹','ÅÌ€'=>'ṑ','ÅŒÌ'=>'á¹’','ÅÌ'=>'ṓ','PÌ'=>'á¹”','pÌ'=>'ṕ','Ṗ'=>'á¹–','ṗ'=>'á¹—','Ṙ'=>'Ṙ','ṙ'=>'á¹™','RÌ£'=>'Ṛ','rÌ£'=>'á¹›','Ṝ'=>'Ṝ','ṝ'=>'á¹','Ṟ'=>'Ṟ','ṟ'=>'ṟ','Ṡ'=>'á¹ ','ṡ'=>'ṡ','SÌ£'=>'á¹¢','sÌ£'=>'á¹£','Ṥ'=>'Ṥ','ṥ'=>'á¹¥','Ṧ'=>'Ṧ','ṧ'=>'á¹§','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','TÌ£'=>'Ṭ','tÌ£'=>'á¹­','Ṯ'=>'á¹®','ṯ'=>'ṯ','TÌ­'=>'á¹°','tÌ­'=>'á¹±','Ṳ'=>'á¹²','ṳ'=>'á¹³','Ṵ'=>'á¹´','ṵ'=>'á¹µ','UÌ­'=>'á¹¶','uÌ­'=>'á¹·','ŨÌ'=>'Ṹ','Å©Ì'=>'á¹¹','Ṻ'=>'Ṻ','ṻ'=>'á¹»','Ṽ'=>'á¹¼','ṽ'=>'á¹½','VÌ£'=>'á¹¾','vÌ£'=>'ṿ','WÌ€'=>'Ẁ','wÌ€'=>'áº','WÌ'=>'Ẃ','wÌ'=>'ẃ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','WÌ£'=>'Ẉ','wÌ£'=>'ẉ','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','ẍ'=>'áº','Ẏ'=>'Ẏ','ẏ'=>'áº','ZÌ‚'=>'áº','zÌ‚'=>'ẑ','ZÌ£'=>'Ẓ','zÌ£'=>'ẓ','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','wÌŠ'=>'ẘ','yÌŠ'=>'ẙ','ẛ'=>'ẛ','AÌ£'=>'Ạ','aÌ£'=>'ạ','Ả'=>'Ả','ả'=>'ả','ÂÌ'=>'Ấ','âÌ'=>'ấ','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'ậ','Ä‚Ì'=>'Ắ','ăÌ'=>'ắ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','EÌ£'=>'Ẹ','eÌ£'=>'ẹ','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','ÊÌ'=>'Ế','êÌ'=>'ế','Ề'=>'Ề','ề'=>'á»','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','ễ'=>'á»…','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','IÌ£'=>'Ị','iÌ£'=>'ị','OÌ£'=>'Ọ','oÌ£'=>'á»','Ỏ'=>'Ỏ','ỏ'=>'á»','ÔÌ'=>'á»','ôÌ'=>'ố','Ồ'=>'á»’','ồ'=>'ồ','Ổ'=>'á»”','ổ'=>'ổ','Ỗ'=>'á»–','ỗ'=>'á»—','Ộ'=>'Ộ','á»Ì‚'=>'á»™','Æ Ì'=>'Ớ','Æ¡Ì'=>'á»›','Ờ'=>'Ờ','ờ'=>'á»','Ở'=>'Ở','ở'=>'ở','Ỡ'=>'á» ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','UÌ£'=>'Ụ','uÌ£'=>'ụ','Ủ'=>'Ủ','ủ'=>'á»§','ƯÌ'=>'Ứ','ưÌ'=>'ứ','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','ử'=>'á»­','Ữ'=>'á»®','ữ'=>'ữ','Ự'=>'á»°','ự'=>'á»±','YÌ€'=>'Ỳ','yÌ€'=>'ỳ','YÌ£'=>'á»´','yÌ£'=>'ỵ','Ỷ'=>'á»¶','ỷ'=>'á»·','Ỹ'=>'Ỹ','ỹ'=>'ỹ','ἀ'=>'á¼€','ἁ'=>'á¼','ἂ'=>'ἂ','á¼Ì€'=>'ἃ','á¼€Ì'=>'ἄ','á¼Ì'=>'á¼…','ἆ'=>'ἆ','á¼Í‚'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','ἈÌ'=>'Ἄ','ἉÌ'=>'á¼','Ἆ'=>'Ἆ','Ἇ'=>'á¼','ἐ'=>'á¼','ἑ'=>'ἑ','á¼Ì€'=>'á¼’','ἓ'=>'ἓ','á¼Ì'=>'á¼”','ἑÌ'=>'ἕ','Ἐ'=>'Ἐ','Ἑ'=>'á¼™','Ἒ'=>'Ἒ','Ἓ'=>'á¼›','ἘÌ'=>'Ἔ','á¼™Ì'=>'á¼','ἠ'=>'á¼ ','ἡ'=>'ἡ','ἢ'=>'á¼¢','ἣ'=>'á¼£','á¼ Ì'=>'ἤ','ἡÌ'=>'á¼¥','á¼ Í‚'=>'ἦ','ἧ'=>'á¼§','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','ἨÌ'=>'Ἤ','ἩÌ'=>'á¼­','Ἦ'=>'á¼®','Ἧ'=>'Ἧ','ἰ'=>'á¼°','ἱ'=>'á¼±','á¼°Ì€'=>'á¼²','ἳ'=>'á¼³','á¼°Ì'=>'á¼´','á¼±Ì'=>'á¼µ','á¼°Í‚'=>'á¼¶','ἷ'=>'á¼·','Ἰ'=>'Ἰ','Ἱ'=>'á¼¹','Ἲ'=>'Ἲ','Ἳ'=>'á¼»','ἸÌ'=>'á¼¼','á¼¹Ì'=>'á¼½','Ἶ'=>'á¼¾','Ἷ'=>'Ἷ','ὀ'=>'á½€','ὁ'=>'á½','ὂ'=>'ὂ','á½Ì€'=>'ὃ','á½€Ì'=>'ὄ','á½Ì'=>'á½…','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','ὈÌ'=>'Ὄ','ὉÌ'=>'á½','Ï…Ì“'=>'á½','Ï…Ì”'=>'ὑ','á½Ì€'=>'á½’','ὓ'=>'ὓ','á½Ì'=>'á½”','ὑÌ'=>'ὕ','á½Í‚'=>'á½–','ὗ'=>'á½—','Ὑ'=>'á½™','Ὓ'=>'á½›','á½™Ì'=>'á½','Ὗ'=>'Ὗ','ὠ'=>'á½ ','ὡ'=>'ὡ','ὢ'=>'á½¢','ὣ'=>'á½£','á½ Ì'=>'ὤ','ὡÌ'=>'á½¥','á½ Í‚'=>'ὦ','ὧ'=>'á½§','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','ὨÌ'=>'Ὤ','ὩÌ'=>'á½­','Ὦ'=>'á½®','Ὧ'=>'Ὧ','ὰ'=>'á½°','ὲ'=>'á½²','ὴ'=>'á½´','ὶ'=>'á½¶','ὸ'=>'ὸ','Ï…Ì€'=>'ὺ','ὼ'=>'á½¼','ᾀ'=>'á¾€','á¼Í…'=>'á¾','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ᾄ','á¼…Í…'=>'á¾…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ᾌ','á¼Í…'=>'á¾','ᾎ'=>'ᾎ','á¼Í…'=>'á¾','á¼ Í…'=>'á¾','ᾑ'=>'ᾑ','ᾒ'=>'á¾’','ᾓ'=>'ᾓ','ᾔ'=>'á¾”','ᾕ'=>'ᾕ','ᾖ'=>'á¾–','á¼§Í…'=>'á¾—','ᾘ'=>'ᾘ','ᾙ'=>'á¾™','ᾚ'=>'ᾚ','ᾛ'=>'á¾›','ᾜ'=>'ᾜ','á¼­Í…'=>'á¾','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á½ Í…'=>'á¾ ','ᾡ'=>'ᾡ','ᾢ'=>'á¾¢','ᾣ'=>'á¾£','ᾤ'=>'ᾤ','ᾥ'=>'á¾¥','ᾦ'=>'ᾦ','á½§Í…'=>'á¾§','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ᾬ','á½­Í…'=>'á¾­','ᾮ'=>'á¾®','ᾯ'=>'ᾯ','ᾰ'=>'á¾°','ᾱ'=>'á¾±','á½°Í…'=>'á¾²','ᾳ'=>'á¾³','ᾴ'=>'á¾´','ᾶ'=>'á¾¶','á¾¶Í…'=>'á¾·','Ᾰ'=>'Ᾰ','Ᾱ'=>'á¾¹','Ὰ'=>'Ὰ','ᾼ'=>'á¾¼','῁'=>'á¿','á½´Í…'=>'á¿‚','ῃ'=>'ῃ','ῄ'=>'á¿„','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Ὴ'=>'Ὴ','ῌ'=>'ῌ','῍'=>'á¿','᾿Ì'=>'῎','῏'=>'á¿','ῐ'=>'á¿','ῑ'=>'á¿‘','ÏŠÌ€'=>'á¿’','ῖ'=>'á¿–','ÏŠÍ‚'=>'á¿—','Ῐ'=>'Ῐ','Ῑ'=>'á¿™','Ὶ'=>'Ὶ','῝'=>'á¿','῾Ì'=>'῞','῟'=>'῟','ῠ'=>'á¿ ','Ï…Ì„'=>'á¿¡','ῢ'=>'á¿¢','ÏÌ“'=>'ῤ','ÏÌ”'=>'á¿¥','Ï…Í‚'=>'ῦ','ῧ'=>'á¿§','Ῠ'=>'Ῠ','Ῡ'=>'á¿©','Ὺ'=>'Ὺ','Ῥ'=>'Ῥ','῭'=>'á¿­','ῲ'=>'ῲ','ῳ'=>'ῳ','ÏŽÍ…'=>'á¿´','ῶ'=>'á¿¶','á¿¶Í…'=>'á¿·','Ὸ'=>'Ὸ','Ὼ'=>'Ὼ','ῼ'=>'ῼ','â†Ì¸'=>'↚','↛'=>'↛','↮'=>'↮','â‡Ì¸'=>'â‡','⇎'=>'⇎','⇏'=>'â‡','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','≁'=>'â‰','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','â‰Ì¸'=>'≭','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','⊁'=>'âŠ','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','⋠'=>'â‹ ','⋡'=>'â‹¡','⋢'=>'â‹¢','⋣'=>'â‹£','⋪'=>'⋪','⋫'=>'â‹«','⋬'=>'⋬','⋭'=>'â‹­','ã‹ã‚™'=>'ãŒ','ãã‚™'=>'ãŽ','ãã‚™'=>'ã','ã‘ã‚™'=>'ã’','ã“ã‚™'=>'ã”','ã•ã‚™'=>'ã–','ã—ã‚™'=>'ã˜','ã™ã‚™'=>'ãš','ã›ã‚™'=>'ãœ','ãã‚™'=>'ãž','ãŸã‚™'=>'ã ','ã¡ã‚™'=>'ã¢','ã¤ã‚™'=>'ã¥','ã¦ã‚™'=>'ã§','ã¨ã‚™'=>'ã©','ã¯ã‚™'=>'ã°','ã¯ã‚š'=>'ã±','ã²ã‚™'=>'ã³','ã²ã‚š'=>'ã´','ãµã‚™'=>'ã¶','ãµã‚š'=>'ã·','ã¸ã‚™'=>'ã¹','ã¸ã‚š'=>'ãº','ã»ã‚™'=>'ã¼','ã»ã‚š'=>'ã½','ã†ã‚™'=>'ã‚”','ã‚ã‚™'=>'ゞ','ã‚«ã‚™'=>'ガ','ã‚­ã‚™'=>'ã‚®','グ'=>'ã‚°','ゲ'=>'ゲ','ゴ'=>'ã‚´','ザ'=>'ã‚¶','ã‚·ã‚™'=>'ジ','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ã‚¿ã‚™'=>'ダ','ãƒã‚™'=>'ヂ','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒã‚™'=>'ãƒ','ãƒã‚š'=>'パ','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ポ'=>'ãƒ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ'); diff --git a/phpBB/includes/utf/data/utf_canonical_decomp.php b/phpBB/includes/utf/data/utf_canonical_decomp.php deleted file mode 100644 index 9fb90803e2..0000000000 --- a/phpBB/includes/utf/data/utf_canonical_decomp.php +++ /dev/null @@ -1,2 +0,0 @@ -'AÌ€','Ã'=>'AÌ','Â'=>'AÌ‚','Ã'=>'Ã','Ä'=>'Ä','Ã…'=>'AÌŠ','Ç'=>'Ç','È'=>'EÌ€','É'=>'EÌ','Ê'=>'EÌ‚','Ë'=>'Ë','ÃŒ'=>'IÌ€','Ã'=>'IÌ','ÃŽ'=>'IÌ‚','Ã'=>'Ï','Ñ'=>'Ñ','Ã’'=>'OÌ€','Ó'=>'OÌ','Ô'=>'OÌ‚','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'UÌ€','Ú'=>'UÌ','Û'=>'UÌ‚','Ü'=>'Ü','Ã'=>'YÌ','à'=>'aÌ€','á'=>'aÌ','â'=>'aÌ‚','ã'=>'ã','ä'=>'ä','Ã¥'=>'aÌŠ','ç'=>'ç','è'=>'eÌ€','é'=>'eÌ','ê'=>'eÌ‚','ë'=>'ë','ì'=>'iÌ€','í'=>'iÌ','î'=>'iÌ‚','ï'=>'ï','ñ'=>'ñ','ò'=>'oÌ€','ó'=>'oÌ','ô'=>'oÌ‚','õ'=>'õ','ö'=>'ö','ù'=>'uÌ€','ú'=>'uÌ','û'=>'uÌ‚','ü'=>'ü','ý'=>'yÌ','ÿ'=>'ÿ','Ä€'=>'AÌ„','Ä'=>'aÌ„','Ä‚'=>'Ă','ă'=>'ă','Ä„'=>'Ą','Ä…'=>'ą','Ć'=>'CÌ','ć'=>'cÌ','Ĉ'=>'CÌ‚','ĉ'=>'cÌ‚','ÄŠ'=>'Ċ','Ä‹'=>'ċ','ÄŒ'=>'CÌŒ','Ä'=>'cÌŒ','ÄŽ'=>'DÌŒ','Ä'=>'dÌŒ','Ä’'=>'EÌ„','Ä“'=>'eÌ„','Ä”'=>'Ĕ','Ä•'=>'ĕ','Ä–'=>'Ė','Ä—'=>'ė','Ę'=>'Ę','Ä™'=>'ę','Äš'=>'EÌŒ','Ä›'=>'eÌŒ','Äœ'=>'GÌ‚','Ä'=>'gÌ‚','Äž'=>'Ğ','ÄŸ'=>'ğ','Ä '=>'Ġ','Ä¡'=>'ġ','Ä¢'=>'Ģ','Ä£'=>'ģ','Ĥ'=>'HÌ‚','Ä¥'=>'hÌ‚','Ĩ'=>'Ĩ','Ä©'=>'ĩ','Ī'=>'IÌ„','Ä«'=>'iÌ„','Ĭ'=>'Ĭ','Ä­'=>'ĭ','Ä®'=>'Į','į'=>'į','İ'=>'İ','Ä´'=>'JÌ‚','ĵ'=>'jÌ‚','Ķ'=>'Ķ','Ä·'=>'ķ','Ĺ'=>'LÌ','ĺ'=>'lÌ','Ä»'=>'Ļ','ļ'=>'ļ','Ľ'=>'LÌŒ','ľ'=>'lÌŒ','Ń'=>'NÌ','Å„'=>'nÌ','Å…'=>'Ņ','ņ'=>'ņ','Ň'=>'NÌŒ','ň'=>'nÌŒ','ÅŒ'=>'OÌ„','Å'=>'oÌ„','ÅŽ'=>'Ŏ','Å'=>'ŏ','Å'=>'OÌ‹','Å‘'=>'oÌ‹','Å”'=>'RÌ','Å•'=>'rÌ','Å–'=>'Ŗ','Å—'=>'ŗ','Ř'=>'RÌŒ','Å™'=>'rÌŒ','Åš'=>'SÌ','Å›'=>'sÌ','Åœ'=>'SÌ‚','Å'=>'sÌ‚','Åž'=>'Ş','ÅŸ'=>'ş','Å '=>'SÌŒ','Å¡'=>'sÌŒ','Å¢'=>'Ţ','Å£'=>'ţ','Ť'=>'TÌŒ','Å¥'=>'tÌŒ','Ũ'=>'Ũ','Å©'=>'ũ','Ū'=>'UÌ„','Å«'=>'uÌ„','Ŭ'=>'Ŭ','Å­'=>'ŭ','Å®'=>'UÌŠ','ů'=>'uÌŠ','Ű'=>'UÌ‹','ű'=>'uÌ‹','Ų'=>'Ų','ų'=>'ų','Å´'=>'WÌ‚','ŵ'=>'wÌ‚','Ŷ'=>'YÌ‚','Å·'=>'yÌ‚','Ÿ'=>'Ÿ','Ź'=>'ZÌ','ź'=>'zÌ','Å»'=>'Ż','ż'=>'ż','Ž'=>'ZÌŒ','ž'=>'zÌŒ','Æ '=>'OÌ›','Æ¡'=>'oÌ›','Ư'=>'UÌ›','ư'=>'uÌ›','Ç'=>'AÌŒ','ÇŽ'=>'aÌŒ','Ç'=>'IÌŒ','Ç'=>'iÌŒ','Ç‘'=>'OÌŒ','Ç’'=>'oÌŒ','Ç“'=>'UÌŒ','Ç”'=>'uÌŒ','Ç•'=>'Ǖ','Ç–'=>'ǖ','Ç—'=>'ÜÌ','ǘ'=>'üÌ','Ç™'=>'Ǚ','Çš'=>'ǚ','Ç›'=>'Ǜ','Çœ'=>'ǜ','Çž'=>'Ǟ','ÇŸ'=>'ǟ','Ç '=>'Ǡ','Ç¡'=>'ǡ','Ç¢'=>'Ǣ','Ç£'=>'ǣ','Ǧ'=>'GÌŒ','ǧ'=>'gÌŒ','Ǩ'=>'KÌŒ','Ç©'=>'kÌŒ','Ǫ'=>'Ǫ','Ç«'=>'ǫ','Ǭ'=>'Ǭ','Ç­'=>'ǭ','Ç®'=>'Æ·ÌŒ','ǯ'=>'Ê’ÌŒ','ǰ'=>'jÌŒ','Ç´'=>'GÌ','ǵ'=>'gÌ','Ǹ'=>'NÌ€','ǹ'=>'nÌ€','Ǻ'=>'AÌŠÌ','Ç»'=>'aÌŠÌ','Ǽ'=>'ÆÌ','ǽ'=>'æÌ','Ǿ'=>'ØÌ','Ç¿'=>'øÌ','È€'=>'AÌ','È'=>'aÌ','È‚'=>'AÌ‘','ȃ'=>'aÌ‘','È„'=>'EÌ','È…'=>'eÌ','Ȇ'=>'EÌ‘','ȇ'=>'eÌ‘','Ȉ'=>'IÌ','ȉ'=>'iÌ','ÈŠ'=>'IÌ‘','È‹'=>'iÌ‘','ÈŒ'=>'OÌ','È'=>'oÌ','ÈŽ'=>'OÌ‘','È'=>'oÌ‘','È'=>'RÌ','È‘'=>'rÌ','È’'=>'RÌ‘','È“'=>'rÌ‘','È”'=>'UÌ','È•'=>'uÌ','È–'=>'UÌ‘','È—'=>'uÌ‘','Ș'=>'Ș','È™'=>'ș','Èš'=>'Ț','È›'=>'ț','Èž'=>'HÌŒ','ÈŸ'=>'hÌŒ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','È©'=>'ȩ','Ȫ'=>'Ȫ','È«'=>'ȫ','Ȭ'=>'Ȭ','È­'=>'ȭ','È®'=>'Ȯ','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'YÌ„','ȳ'=>'yÌ„','Í€'=>'Ì€','Í'=>'Ì','̓'=>'Ì“','Í„'=>'̈Ì','Í´'=>'ʹ',';'=>';','Î…'=>'¨Ì','Ά'=>'ΑÌ','·'=>'·','Έ'=>'ΕÌ','Ή'=>'ΗÌ','Ί'=>'ΙÌ','ÎŒ'=>'ΟÌ','ÎŽ'=>'Î¥Ì','Î'=>'ΩÌ','Î'=>'ϊÌ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'αÌ','έ'=>'εÌ','ή'=>'ηÌ','ί'=>'ιÌ','ΰ'=>'ϋÌ','ÏŠ'=>'ϊ','Ï‹'=>'ϋ','ÏŒ'=>'οÌ','Ï'=>'Ï…Ì','ÏŽ'=>'ωÌ','Ï“'=>'Ï’Ì','Ï”'=>'ϔ','Ѐ'=>'Ѐ','Ð'=>'Ё','Ѓ'=>'ГÌ','Ї'=>'Ї','ÐŒ'=>'КÌ','Ð'=>'Ѝ','ÐŽ'=>'Ў','Й'=>'Й','й'=>'й','Ñ'=>'ѐ','Ñ‘'=>'ё','Ñ“'=>'гÌ','Ñ—'=>'ї','Ñœ'=>'кÌ','Ñ'=>'ѝ','Ñž'=>'ў','Ѷ'=>'Ñ´Ì','Ñ·'=>'ѵÌ','Ó'=>'Ӂ','Ó‚'=>'ӂ','Ó'=>'Ð̆','Ó‘'=>'ӑ','Ó’'=>'Ð̈','Ó“'=>'ӓ','Ó–'=>'Ӗ','Ó—'=>'ӗ','Óš'=>'Ӛ','Ó›'=>'ӛ','Óœ'=>'Ӝ','Ó'=>'ӝ','Óž'=>'Ӟ','ÓŸ'=>'ӟ','Ó¢'=>'Ӣ','Ó£'=>'ӣ','Ó¤'=>'Ӥ','Ó¥'=>'ӥ','Ó¦'=>'Ӧ','Ó§'=>'ӧ','Óª'=>'Ӫ','Ó«'=>'ӫ','Ó¬'=>'Ӭ','Ó­'=>'Ñ̈','Ó®'=>'Ӯ','Ó¯'=>'ӯ','Ó°'=>'Ӱ','Ó±'=>'ӱ','Ó²'=>'Ӳ','Ó³'=>'ӳ','Ó´'=>'Ӵ','Óµ'=>'ӵ','Ó¸'=>'Ӹ','Ó¹'=>'ӹ','Ø¢'=>'آ','Ø£'=>'أ','ؤ'=>'ÙˆÙ”','Ø¥'=>'إ','ئ'=>'ÙŠÙ”','Û€'=>'Û•Ù”','Û‚'=>'ÛÙ”','Û“'=>'Û’Ù”','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','à¥'=>'ढ़','फ़'=>'फ़','य़'=>'य़','à§‹'=>'ো','à§Œ'=>'ৌ','à§œ'=>'ড়','à§'=>'ঢ়','à§Ÿ'=>'য়','ਲ਼'=>'ਲ਼','ਸ਼'=>'ਸ਼','à©™'=>'ਖ਼','ਗ਼'=>'ਗ਼','à©›'=>'ਜ਼','ਫ਼'=>'ਫ਼','à­ˆ'=>'ୈ','à­‹'=>'ୋ','à­Œ'=>'ୌ','à­œ'=>'ଡ଼','à­'=>'ଢ଼','à®”'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','à³€'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','à·š'=>'ේ','à·œ'=>'à·™à·','à·'=>'à·™à·à·Š','à·ž'=>'ෞ','གྷ'=>'གྷ','à½'=>'ཌྷ','དྷ'=>'དྷ','བྷ'=>'བྷ','ཛྷ'=>'ཛྷ','ཀྵ'=>'ཀྵ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ླྀ'=>'ླྀ','à¾'=>'ཱྀ','ྒྷ'=>'ྒྷ','à¾'=>'ྜྷ','ྡྷ'=>'ྡྷ','ྦྷ'=>'ྦྷ','ྫྷ'=>'ྫྷ','ྐྵ'=>'à¾à¾µ','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'á¬á¬µ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','á­€'=>'ᭀ','á­'=>'ᭁ','á­ƒ'=>'ᭃ','Ḁ'=>'AÌ¥','á¸'=>'aÌ¥','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'BÌ£','ḅ'=>'bÌ£','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'ÇÌ','ḉ'=>'çÌ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'DÌ£','á¸'=>'dÌ£','Ḏ'=>'Ḏ','á¸'=>'ḏ','á¸'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'DÌ­','ḓ'=>'dÌ­','Ḕ'=>'Ḕ','ḕ'=>'ḕ','Ḗ'=>'EÌ„Ì','ḗ'=>'eÌ„Ì','Ḙ'=>'EÌ­','ḙ'=>'eÌ­','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','á¸'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'GÌ„','ḡ'=>'gÌ„','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'HÌ£','ḥ'=>'hÌ£','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'HÌ®','ḫ'=>'hÌ®','Ḭ'=>'Ḭ','ḭ'=>'ḭ','Ḯ'=>'ÏÌ','ḯ'=>'ïÌ','Ḱ'=>'KÌ','ḱ'=>'kÌ','Ḳ'=>'KÌ£','ḳ'=>'kÌ£','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'LÌ£','ḷ'=>'lÌ£','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'LÌ­','ḽ'=>'lÌ­','Ḿ'=>'MÌ','ḿ'=>'mÌ','á¹€'=>'Ṁ','á¹'=>'ṁ','Ṃ'=>'MÌ£','ṃ'=>'mÌ£','Ṅ'=>'Ṅ','á¹…'=>'ṅ','Ṇ'=>'NÌ£','ṇ'=>'nÌ£','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'NÌ­','ṋ'=>'nÌ­','Ṍ'=>'ÕÌ','á¹'=>'õÌ','Ṏ'=>'Ṏ','á¹'=>'ṏ','á¹'=>'Ṑ','ṑ'=>'ṑ','á¹’'=>'OÌ„Ì','ṓ'=>'oÌ„Ì','á¹”'=>'PÌ','ṕ'=>'pÌ','á¹–'=>'Ṗ','á¹—'=>'ṗ','Ṙ'=>'Ṙ','á¹™'=>'ṙ','Ṛ'=>'RÌ£','á¹›'=>'rÌ£','Ṝ'=>'Ṝ','á¹'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','á¹ '=>'Ṡ','ṡ'=>'ṡ','á¹¢'=>'SÌ£','á¹£'=>'sÌ£','Ṥ'=>'SÌ̇','á¹¥'=>'sÌ̇','Ṧ'=>'Ṧ','á¹§'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'TÌ£','á¹­'=>'tÌ£','á¹®'=>'Ṯ','ṯ'=>'ṯ','á¹°'=>'TÌ­','á¹±'=>'tÌ­','á¹²'=>'Ṳ','á¹³'=>'ṳ','á¹´'=>'Ṵ','á¹µ'=>'ṵ','á¹¶'=>'UÌ­','á¹·'=>'uÌ­','Ṹ'=>'ŨÌ','á¹¹'=>'ũÌ','Ṻ'=>'Ṻ','á¹»'=>'ṻ','á¹¼'=>'Ṽ','á¹½'=>'ṽ','á¹¾'=>'VÌ£','ṿ'=>'vÌ£','Ẁ'=>'WÌ€','áº'=>'wÌ€','Ẃ'=>'WÌ','ẃ'=>'wÌ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'WÌ£','ẉ'=>'wÌ£','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','áº'=>'ẍ','Ẏ'=>'Ẏ','áº'=>'ẏ','áº'=>'ZÌ‚','ẑ'=>'zÌ‚','Ẓ'=>'ZÌ£','ẓ'=>'zÌ£','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'wÌŠ','ẙ'=>'yÌŠ','ẛ'=>'ẛ','Ạ'=>'AÌ£','ạ'=>'aÌ£','Ả'=>'Ả','ả'=>'ả','Ấ'=>'AÌ‚Ì','ấ'=>'aÌ‚Ì','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'ậ','Ắ'=>'ĂÌ','ắ'=>'ăÌ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'EÌ£','ẹ'=>'eÌ£','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'EÌ‚Ì','ế'=>'eÌ‚Ì','Ề'=>'Ề','á»'=>'ề','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','á»…'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'IÌ£','ị'=>'iÌ£','Ọ'=>'OÌ£','á»'=>'oÌ£','Ỏ'=>'Ỏ','á»'=>'ỏ','á»'=>'OÌ‚Ì','ố'=>'oÌ‚Ì','á»’'=>'Ồ','ồ'=>'ồ','á»”'=>'Ổ','ổ'=>'ổ','á»–'=>'Ỗ','á»—'=>'ỗ','Ộ'=>'Ộ','á»™'=>'ộ','Ớ'=>'OÌ›Ì','á»›'=>'oÌ›Ì','Ờ'=>'Ờ','á»'=>'ờ','Ở'=>'Ở','ở'=>'ở','á» '=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'UÌ£','ụ'=>'uÌ£','Ủ'=>'Ủ','á»§'=>'ủ','Ứ'=>'UÌ›Ì','ứ'=>'uÌ›Ì','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','á»­'=>'ử','á»®'=>'Ữ','ữ'=>'ữ','á»°'=>'Ự','á»±'=>'ự','Ỳ'=>'YÌ€','ỳ'=>'yÌ€','á»´'=>'YÌ£','ỵ'=>'yÌ£','á»¶'=>'Ỷ','á»·'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','á¼€'=>'ἀ','á¼'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἀÌ','á¼…'=>'ἁÌ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'ἈÌ','á¼'=>'ἉÌ','Ἆ'=>'Ἆ','á¼'=>'Ἇ','á¼'=>'ἐ','ἑ'=>'ἑ','á¼’'=>'ἒ','ἓ'=>'ἓ','á¼”'=>'ἐÌ','ἕ'=>'ἑÌ','Ἐ'=>'Ἐ','á¼™'=>'Ἑ','Ἒ'=>'Ἒ','á¼›'=>'Ἓ','Ἔ'=>'ἘÌ','á¼'=>'ἙÌ','á¼ '=>'ἠ','ἡ'=>'ἡ','á¼¢'=>'ἢ','á¼£'=>'ἣ','ἤ'=>'ἠÌ','á¼¥'=>'ἡÌ','ἦ'=>'ἦ','á¼§'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'ἨÌ','á¼­'=>'ἩÌ','á¼®'=>'Ἦ','Ἧ'=>'Ἧ','á¼°'=>'ἰ','á¼±'=>'ἱ','á¼²'=>'ἲ','á¼³'=>'ἳ','á¼´'=>'ἰÌ','á¼µ'=>'ἱÌ','á¼¶'=>'ἶ','á¼·'=>'ἷ','Ἰ'=>'Ἰ','á¼¹'=>'Ἱ','Ἲ'=>'Ἲ','á¼»'=>'Ἳ','á¼¼'=>'ἸÌ','á¼½'=>'ἹÌ','á¼¾'=>'Ἶ','Ἷ'=>'Ἷ','á½€'=>'ὀ','á½'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὀÌ','á½…'=>'ὁÌ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'ὈÌ','á½'=>'ὉÌ','á½'=>'Ï…Ì“','ὑ'=>'Ï…Ì”','á½’'=>'ὒ','ὓ'=>'ὓ','á½”'=>'Ï…Ì“Ì','ὕ'=>'Ï…Ì”Ì','á½–'=>'ὖ','á½—'=>'ὗ','á½™'=>'Ὑ','á½›'=>'Ὓ','á½'=>'ὙÌ','Ὗ'=>'Ὗ','á½ '=>'ὠ','ὡ'=>'ὡ','á½¢'=>'ὢ','á½£'=>'ὣ','ὤ'=>'ὠÌ','á½¥'=>'ὡÌ','ὦ'=>'ὦ','á½§'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'ὨÌ','á½­'=>'ὩÌ','á½®'=>'Ὦ','Ὧ'=>'Ὧ','á½°'=>'ὰ','á½±'=>'αÌ','á½²'=>'ὲ','á½³'=>'εÌ','á½´'=>'ὴ','á½µ'=>'ηÌ','á½¶'=>'ὶ','á½·'=>'ιÌ','ὸ'=>'ὸ','á½¹'=>'οÌ','ὺ'=>'Ï…Ì€','á½»'=>'Ï…Ì','á½¼'=>'ὼ','á½½'=>'ωÌ','á¾€'=>'ᾀ','á¾'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ἀÌÍ…','á¾…'=>'ἁÌÍ…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ἈÌÍ…','á¾'=>'ἉÌÍ…','ᾎ'=>'ᾎ','á¾'=>'ᾏ','á¾'=>'ᾐ','ᾑ'=>'ᾑ','á¾’'=>'ᾒ','ᾓ'=>'ᾓ','á¾”'=>'ἠÌÍ…','ᾕ'=>'ἡÌÍ…','á¾–'=>'ᾖ','á¾—'=>'ᾗ','ᾘ'=>'ᾘ','á¾™'=>'ᾙ','ᾚ'=>'ᾚ','á¾›'=>'ᾛ','ᾜ'=>'ἨÌÍ…','á¾'=>'ἩÌÍ…','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á¾ '=>'ᾠ','ᾡ'=>'ᾡ','á¾¢'=>'ᾢ','á¾£'=>'ᾣ','ᾤ'=>'ὠÌÍ…','á¾¥'=>'ὡÌÍ…','ᾦ'=>'ᾦ','á¾§'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ὨÌÍ…','á¾­'=>'ὩÌÍ…','á¾®'=>'ᾮ','ᾯ'=>'ᾯ','á¾°'=>'ᾰ','á¾±'=>'ᾱ','á¾²'=>'ᾲ','á¾³'=>'ᾳ','á¾´'=>'αÌÍ…','á¾¶'=>'ᾶ','á¾·'=>'ᾷ','Ᾰ'=>'Ᾰ','á¾¹'=>'Ᾱ','Ὰ'=>'Ὰ','á¾»'=>'ΑÌ','á¾¼'=>'ᾼ','á¾¾'=>'ι','á¿'=>'῁','á¿‚'=>'ῂ','ῃ'=>'ῃ','á¿„'=>'ηÌÍ…','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'ΕÌ','Ὴ'=>'Ὴ','á¿‹'=>'ΗÌ','ῌ'=>'ῌ','á¿'=>'῍','῎'=>'᾿Ì','á¿'=>'῏','á¿'=>'ῐ','á¿‘'=>'ῑ','á¿’'=>'ῒ','á¿“'=>'ϊÌ','á¿–'=>'ῖ','á¿—'=>'ῗ','Ῐ'=>'Ῐ','á¿™'=>'Ῑ','Ὶ'=>'Ὶ','á¿›'=>'ΙÌ','á¿'=>'῝','῞'=>'῾Ì','῟'=>'῟','á¿ '=>'ῠ','á¿¡'=>'Ï…Ì„','á¿¢'=>'ῢ','á¿£'=>'ϋÌ','ῤ'=>'ÏÌ“','á¿¥'=>'ÏÌ”','ῦ'=>'Ï…Í‚','á¿§'=>'ῧ','Ῠ'=>'Ῠ','á¿©'=>'Ῡ','Ὺ'=>'Ὺ','á¿«'=>'Î¥Ì','Ῥ'=>'Ῥ','á¿­'=>'῭','á¿®'=>'¨Ì','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','á¿´'=>'ωÌÍ…','á¿¶'=>'ῶ','á¿·'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'ΟÌ','Ὼ'=>'Ὼ','á¿»'=>'ΩÌ','ῼ'=>'ῼ','´'=>'´',' '=>' ','â€'=>' ','Ω'=>'Ω','K'=>'K','â„«'=>'AÌŠ','↚'=>'â†Ì¸','↛'=>'↛','↮'=>'↮','â‡'=>'â‡Ì¸','⇎'=>'⇎','â‡'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','â‰'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','≭'=>'â‰Ì¸','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','âŠ'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','â‹ '=>'⋠','â‹¡'=>'⋡','â‹¢'=>'⋢','â‹£'=>'⋣','⋪'=>'⋪','â‹«'=>'⋫','⋬'=>'⋬','â‹­'=>'⋭','〈'=>'〈','〉'=>'〉','⫝̸'=>'â«Ì¸','ãŒ'=>'ã‹ã‚™','ãŽ'=>'ãã‚™','ã'=>'ãã‚™','ã’'=>'ã‘ã‚™','ã”'=>'ã“ã‚™','ã–'=>'ã•ã‚™','ã˜'=>'ã—ã‚™','ãš'=>'ã™ã‚™','ãœ'=>'ã›ã‚™','ãž'=>'ãã‚™','ã '=>'ãŸã‚™','ã¢'=>'ã¡ã‚™','ã¥'=>'ã¤ã‚™','ã§'=>'ã¦ã‚™','ã©'=>'ã¨ã‚™','ã°'=>'ã¯ã‚™','ã±'=>'ã¯ã‚š','ã³'=>'ã²ã‚™','ã´'=>'ã²ã‚š','ã¶'=>'ãµã‚™','ã·'=>'ãµã‚š','ã¹'=>'ã¸ã‚™','ãº'=>'ã¸ã‚š','ã¼'=>'ã»ã‚™','ã½'=>'ã»ã‚š','ã‚”'=>'ã†ã‚™','ゞ'=>'ã‚ã‚™','ガ'=>'ã‚«ã‚™','ã‚®'=>'ã‚­ã‚™','ã‚°'=>'グ','ゲ'=>'ゲ','ã‚´'=>'ゴ','ã‚¶'=>'ザ','ジ'=>'ã‚·ã‚™','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ã‚¿ã‚™','ヂ'=>'ãƒã‚™','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒ'=>'ãƒã‚™','パ'=>'ãƒã‚š','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ãƒ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ','豈'=>'豈','ï¤'=>'æ›´','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'å¥','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'å–‡','奈'=>'奈','ï¤'=>'懶','癩'=>'癩','ï¤'=>'ç¾…','ï¤'=>'蘿','螺'=>'螺','裸'=>'裸','邏'=>'é‚','樂'=>'樂','洛'=>'æ´›','烙'=>'烙','珞'=>'çž','落'=>'è½','酪'=>'é…ª','駱'=>'é§±','亂'=>'亂','卵'=>'åµ','ï¤'=>'欄','爛'=>'爛','蘭'=>'蘭','鸞'=>'鸞','嵐'=>'åµ','濫'=>'æ¿«','藍'=>'è—','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'è Ÿ','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','來'=>'來','冷'=>'冷','勞'=>'勞','擄'=>'æ“„','櫓'=>'æ«“','爐'=>'çˆ','盧'=>'ç›§','老'=>'è€','蘆'=>'蘆','虜'=>'虜','路'=>'è·¯','露'=>'露','魯'=>'é­¯','鷺'=>'é·º','碌'=>'碌','祿'=>'祿','綠'=>'ç¶ ','菉'=>'è‰','錄'=>'錄','鹿'=>'鹿','ï¥'=>'è«–','壟'=>'壟','弄'=>'弄','籠'=>'ç± ','聾'=>'è¾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'é›·','壘'=>'壘','屢'=>'å±¢','樓'=>'樓','ï¥'=>'æ·š','漏'=>'æ¼','ï¥'=>'ç´¯','ï¥'=>'縷','陋'=>'陋','勒'=>'å‹’','肋'=>'è‚‹','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'ç¶¾','菱'=>'è±','陵'=>'陵','讀'=>'讀','拏'=>'æ‹','樂'=>'樂','ï¥'=>'諾','丹'=>'丹','寧'=>'寧','怒'=>'怒','率'=>'率','異'=>'ç•°','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'ä¸','泌'=>'泌','數'=>'數','索'=>'ç´¢','參'=>'åƒ','塞'=>'塞','省'=>'çœ','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'è¾°','沈'=>'沈','拾'=>'拾','若'=>'è‹¥','掠'=>'掠','略'=>'ç•¥','亮'=>'亮','兩'=>'å…©','凉'=>'凉','梁'=>'æ¢','糧'=>'ç³§','良'=>'良','諒'=>'è«’','量'=>'é‡','勵'=>'勵','呂'=>'å‘‚','ï¦'=>'女','廬'=>'廬','旅'=>'æ—…','濾'=>'濾','礪'=>'礪','閭'=>'é–­','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'æ­·','ï¦'=>'è½¢','年'=>'å¹´','ï¦'=>'æ†','ï¦'=>'戀','撚'=>'æ’š','漣'=>'æ¼£','煉'=>'ç…‰','璉'=>'ç’‰','秊'=>'ç§Š','練'=>'ç·´','聯'=>'è¯','輦'=>'輦','蓮'=>'è“®','連'=>'連','鍊'=>'éŠ','列'=>'列','ï¦'=>'劣','咽'=>'å’½','烈'=>'烈','裂'=>'裂','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'æ»','殮'=>'æ®®','簾'=>'ç°¾','獵'=>'çµ','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','玲'=>'玲','瑩'=>'ç‘©','羚'=>'羚','聆'=>'è†','鈴'=>'鈴','零'=>'é›¶','靈'=>'éˆ','領'=>'é ˜','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'å°¿','料'=>'æ–™','樂'=>'樂','ï§€'=>'燎','ï§'=>'療','ï§‚'=>'蓼','遼'=>'é¼','ï§„'=>'é¾','ï§…'=>'暈','阮'=>'阮','劉'=>'劉','杻'=>'æ»','柳'=>'柳','ï§Š'=>'æµ','ï§‹'=>'溜','ï§Œ'=>'ç‰','ï§'=>'ç•™','ï§Ž'=>'ç¡«','ï§'=>'ç´','ï§'=>'類','ï§‘'=>'å…­','ï§’'=>'戮','ï§“'=>'陸','ï§”'=>'倫','ï§•'=>'å´™','ï§–'=>'æ·ª','ï§—'=>'輪','律'=>'律','ï§™'=>'æ…„','ï§š'=>'æ —','ï§›'=>'率','ï§œ'=>'隆','ï§'=>'利','ï§ž'=>'å','ï§Ÿ'=>'å±¥','ï§ '=>'易','ï§¡'=>'æŽ','ï§¢'=>'梨','ï§£'=>'æ³¥','理'=>'ç†','ï§¥'=>'ç—¢','罹'=>'ç½¹','ï§§'=>'è£','裡'=>'裡','ï§©'=>'里','離'=>'離','ï§«'=>'匿','溺'=>'溺','ï§­'=>'å','ï§®'=>'ç‡','璘'=>'ç’˜','ï§°'=>'è—º','ï§±'=>'隣','ï§²'=>'é±—','ï§³'=>'麟','ï§´'=>'æž—','ï§µ'=>'æ·‹','ï§¶'=>'臨','ï§·'=>'ç«‹','笠'=>'笠','ï§¹'=>'ç²’','狀'=>'ç‹€','ï§»'=>'ç‚™','ï§¼'=>'è­˜','ï§½'=>'什','ï§¾'=>'茶','ï§¿'=>'刺','切'=>'切','ï¨'=>'度','拓'=>'æ‹“','糖'=>'ç³–','宅'=>'å®…','洞'=>'æ´ž','暴'=>'æš´','輻'=>'è¼»','行'=>'行','降'=>'é™','見'=>'見','廓'=>'廓','兀'=>'å…€','ï¨'=>'å—€','ï¨'=>'塚','晴'=>'æ™´','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'ç¦','靖'=>'é–','ï¨'=>'ç²¾','羽'=>'ç¾½','蘒'=>'蘒','諸'=>'諸','逸'=>'逸','都'=>'都','飯'=>'飯','飼'=>'飼','館'=>'館','鶴'=>'é¶´','侮'=>'ä¾®','僧'=>'僧','免'=>'å…','勉'=>'勉','勤'=>'勤','卑'=>'å‘','喝'=>'å–','嘆'=>'嘆','器'=>'器','塀'=>'å¡€','墨'=>'墨','層'=>'層','屮'=>'å±®','悔'=>'æ‚”','慨'=>'æ…¨','憎'=>'憎','ï©€'=>'懲','ï©'=>'æ•','ï©‚'=>'æ—¢','暑'=>'æš‘','ï©„'=>'梅','ï©…'=>'æµ·','渚'=>'渚','漢'=>'æ¼¢','煮'=>'ç…®','爫'=>'爫','琢'=>'ç¢','ï©‹'=>'碑','社'=>'社','ï©'=>'祉','祈'=>'祈','ï©'=>'ç¥','ï©'=>'祖','ï©‘'=>'ç¥','ï©’'=>'ç¦','ï©“'=>'禎','ï©”'=>'ç©€','ï©•'=>'çª','ï©–'=>'節','ï©—'=>'ç·´','縉'=>'縉','ï©™'=>'ç¹','署'=>'ç½²','ï©›'=>'者','臭'=>'臭','ï©'=>'艹','艹'=>'艹','著'=>'è‘—','ï© '=>'è¤','ï©¡'=>'視','ï©¢'=>'è¬','ï©£'=>'謹','賓'=>'賓','ï©¥'=>'è´ˆ','辶'=>'è¾¶','ï©§'=>'逸','難'=>'難','ï©©'=>'響','頻'=>'é »','ï©°'=>'並','况'=>'况','全'=>'å…¨','侀'=>'ä¾€','ï©´'=>'å……','冀'=>'冀','ï©¶'=>'勇','ï©·'=>'勺','喝'=>'å–','啕'=>'å••','喙'=>'å–™','ï©»'=>'å—¢','塚'=>'塚','墳'=>'墳','奄'=>'奄','ï©¿'=>'奔','婢'=>'å©¢','ïª'=>'嬨','廒'=>'å»’','廙'=>'å»™','彩'=>'彩','徭'=>'å¾­','惘'=>'惘','慎'=>'æ…Ž','愈'=>'愈','憎'=>'憎','慠'=>'æ… ','懲'=>'懲','戴'=>'戴','ïª'=>'æ„','搜'=>'æœ','ïª'=>'æ‘’','ïª'=>'æ•–','晴'=>'æ™´','朗'=>'朗','望'=>'望','杖'=>'æ–','歹'=>'æ­¹','殺'=>'殺','流'=>'æµ','滛'=>'æ»›','滋'=>'滋','漢'=>'æ¼¢','瀞'=>'瀞','煮'=>'ç…®','ïª'=>'çž§','爵'=>'爵','犯'=>'犯','猪'=>'猪','瑱'=>'瑱','甆'=>'甆','画'=>'ç”»','瘝'=>'ç˜','瘟'=>'瘟','益'=>'益','盛'=>'ç››','直'=>'ç›´','睊'=>'çŠ','着'=>'ç€','磌'=>'磌','窱'=>'窱','節'=>'節','类'=>'ç±»','絛'=>'çµ›','練'=>'ç·´','缾'=>'ç¼¾','者'=>'者','荒'=>'è’','華'=>'è¯','蝹'=>'è¹','襁'=>'è¥','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'è«‹','謁'=>'è¬','諾'=>'諾','諭'=>'è«­','謹'=>'謹','ï«€'=>'變','ï«'=>'è´ˆ','ï«‚'=>'輸','遲'=>'é²','ï«„'=>'醙','ï«…'=>'鉶','陼'=>'陼','難'=>'難','靖'=>'é–','韛'=>'韛','響'=>'響','ï«‹'=>'é ‹','頻'=>'é »','ï«'=>'鬒','龜'=>'龜','ï«'=>'𢡊','ï«'=>'𢡄','ï«‘'=>'ð£•','ï«’'=>'ã®','ï«“'=>'䀘','ï«”'=>'䀹','ï«•'=>'𥉉','ï«–'=>'ð¥³','ï«—'=>'𧻓','齃'=>'齃','ï«™'=>'龎','ï¬'=>'×™Ö´','ײַ'=>'ײַ','שׁ'=>'ש×','שׂ'=>'שׂ','שּׁ'=>'שּ×','שּׂ'=>'שּׂ','אַ'=>'×Ö·','אָ'=>'×Ö¸','אּ'=>'×Ö¼','בּ'=>'בּ','גּ'=>'×’Ö¼','דּ'=>'דּ','הּ'=>'×”Ö¼','וּ'=>'וּ','זּ'=>'×–Ö¼','טּ'=>'טּ','יּ'=>'×™Ö¼','ךּ'=>'ךּ','כּ'=>'×›Ö¼','לּ'=>'לּ','מּ'=>'מּ','ï­€'=>'× Ö¼','ï­'=>'סּ','ï­ƒ'=>'×£Ö¼','ï­„'=>'פּ','ï­†'=>'צּ','ï­‡'=>'×§Ö¼','ï­ˆ'=>'רּ','ï­‰'=>'שּ','ï­Š'=>'תּ','ï­‹'=>'וֹ','ï­Œ'=>'בֿ','ï­'=>'×›Ö¿','ï­Ž'=>'פֿ','ð…ž'=>'ð…—ð…¥','ð…Ÿ'=>'ð…˜ð…¥','ð… '=>'ð…˜ð…¥ð…®','ð…¡'=>'ð…˜ð…¥ð…¯','ð…¢'=>'ð…˜ð…¥ð…°','ð…£'=>'ð…˜ð…¥ð…±','ð…¤'=>'ð…˜ð…¥ð…²','ð†»'=>'ð†¹ð…¥','ð†¼'=>'ð†ºð…¥','ð†½'=>'ð†¹ð…¥ð…®','ð†¾'=>'ð†ºð…¥ð…®','ð†¿'=>'ð†¹ð…¥ð…¯','ð‡€'=>'ð†ºð…¥ð…¯','丽'=>'丽','ð¯ '=>'丸','乁'=>'ä¹','𠄢'=>'ð „¢','你'=>'ä½ ','侮'=>'ä¾®','侻'=>'ä¾»','倂'=>'倂','偺'=>'åº','備'=>'å‚™','僧'=>'僧','像'=>'åƒ','㒞'=>'ã’ž','ð¯ '=>'𠘺','免'=>'å…','ð¯ '=>'å…”','ð¯ '=>'å…¤','具'=>'å…·','𠔜'=>'𠔜','㒹'=>'ã’¹','內'=>'å…§','再'=>'å†','𠕋'=>'ð •‹','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','ð¯ '=>'凵','刃'=>'刃','㓟'=>'㓟','刻'=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'å‰','卑'=>'å‘','博'=>'åš','即'=>'å³','卽'=>'å½','卿'=>'å¿','卿'=>'å¿','卿'=>'å¿','𠨬'=>'𠨬','灰'=>'ç°','及'=>'åŠ','叟'=>'åŸ','𠭣'=>'ð ­£','叫'=>'å«','叱'=>'å±','吆'=>'å†','咞'=>'å’ž','吸'=>'å¸','呈'=>'呈','周'=>'周','咢'=>'å’¢','ð¯¡'=>'å“¶','唐'=>'å”','啓'=>'å•“','啣'=>'å•£','善'=>'å–„','善'=>'å–„','喙'=>'å–™','喫'=>'å–«','喳'=>'å–³','嗂'=>'å—‚','圖'=>'圖','嘆'=>'嘆','ð¯¡'=>'圗','噑'=>'噑','ð¯¡'=>'å™´','ð¯¡'=>'切','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'å ','型'=>'åž‹','堲'=>'å ²','報'=>'å ±','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','ð¯¡'=>'多','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'ã›®','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','寃'=>'寃','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'å°†','当'=>'当','尢'=>'å°¢','㞁'=>'ãž','屠'=>'å± ','屮'=>'å±®','峀'=>'å³€','岍'=>'å²','𡷤'=>'ð¡·¤','嵃'=>'嵃','𡷦'=>'ð¡·¦','嵮'=>'åµ®','嵫'=>'嵫','嵼'=>'åµ¼','ð¯¢'=>'å·¡','巢'=>'å·¢','㠯'=>'ã ¯','巽'=>'å·½','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'ã¡¢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','ð¯¢'=>'庶','廊'=>'廊','ð¯¢'=>'𪎒','ð¯¢'=>'廾','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'èˆ','弢'=>'å¼¢','弢'=>'å¼¢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'å½¢','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','ð¯¢'=>'å¿','志'=>'å¿—','忹'=>'忹','悁'=>'æ‚','㤺'=>'㤺','㤜'=>'㤜','悔'=>'æ‚”','𢛔'=>'𢛔','惇'=>'惇','慈'=>'æ…ˆ','慌'=>'æ…Œ','慎'=>'æ…Ž','慌'=>'æ…Œ','慺'=>'æ…º','憎'=>'憎','憲'=>'憲','憤'=>'憤','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'æˆ','戛'=>'戛','扝'=>'æ‰','抱'=>'抱','拔'=>'æ‹”','捐'=>'æ','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'æ¨','掃'=>'掃','揤'=>'æ¤','𢯱'=>'𢯱','搢'=>'æ¢','揅'=>'æ…','ð¯£'=>'掩','㨮'=>'㨮','摩'=>'æ‘©','摾'=>'摾','撝'=>'æ’','摷'=>'æ‘·','㩬'=>'㩬','敏'=>'æ•','敬'=>'敬','𣀊'=>'𣀊','旣'=>'æ—£','書'=>'書','ð¯£'=>'晉','㬙'=>'㬙','ð¯£'=>'æš‘','ð¯£'=>'㬈','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'æšœ','肭'=>'è‚­','䏙'=>'ä™','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'æž','杓'=>'æ“','ð¯£'=>'ð£ƒ','㭉'=>'ã­‰','柺'=>'柺','枅'=>'æž…','桒'=>'æ¡’','梅'=>'梅','𣑭'=>'𣑭','梎'=>'梎','栟'=>'æ Ÿ','椔'=>'椔','㮝'=>'ã®','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','櫛'=>'æ«›','㰘'=>'ã°˜','次'=>'次','𣢧'=>'𣢧','歔'=>'æ­”','㱎'=>'㱎','歲'=>'æ­²','殟'=>'殟','殺'=>'殺','殻'=>'æ®»','𣪍'=>'ð£ª','𡴋'=>'ð¡´‹','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'æ³','汧'=>'æ±§','洖'=>'æ´–','派'=>'æ´¾','ð¯¤'=>'æµ·','流'=>'æµ','浩'=>'浩','浸'=>'浸','涅'=>'æ¶…','𣴞'=>'𣴞','洴'=>'æ´´','港'=>'港','湮'=>'æ¹®','㴳'=>'ã´³','滋'=>'滋','滇'=>'滇','ð¯¤'=>'𣻑','淹'=>'æ·¹','ð¯¤'=>'æ½®','ð¯¤'=>'𣽞','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'ã¶–','灊'=>'çŠ','災'=>'ç½','灷'=>'ç·','炭'=>'ç‚­','𠔥'=>'𠔥','煅'=>'ç……','ð¯¤'=>'𤉣','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'ç‰','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'çº','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','㺸'=>'㺸','瑇'=>'瑇','瑜'=>'瑜','瑱'=>'瑱','璅'=>'ç’…','瓊'=>'瓊','㼛'=>'ã¼›','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'ç•°','𢆟'=>'𢆟','瘐'=>'ç˜','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'ð¥„','㿼'=>'㿼','䀈'=>'䀈','直'=>'ç›´','ð¯¥'=>'𥃳','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'çŠ','䀹'=>'䀹','瞋'=>'çž‹','䁆'=>'ä†','䂖'=>'ä‚–','ð¯¥'=>'ð¥','硎'=>'硎','ð¯¥'=>'碌','ð¯¥'=>'磌','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'ç¦','秫'=>'ç§«','䄯'=>'䄯','穀'=>'ç©€','穊'=>'穊','穏'=>'ç©','𥥼'=>'𥥼','ð¯¥'=>'𥪧','𥪧'=>'𥪧','竮'=>'ç«®','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'ç³’','䊠'=>'䊠','糨'=>'糨','糣'=>'ç³£','紀'=>'ç´€','𥾆'=>'𥾆','絣'=>'çµ£','䌁'=>'äŒ','緇'=>'ç·‡','縂'=>'縂','繅'=>'ç¹…','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'ä™','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'è ','𦖨'=>'𦖨','聰'=>'è°','𣍟'=>'ð£Ÿ','ð¯¦'=>'ä•','育'=>'育','脃'=>'脃','䐋'=>'ä‹','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'èˆ','舄'=>'舄','ð¯¦'=>'辞','䑫'=>'ä‘«','ð¯¦'=>'芑','ð¯¦'=>'芋','芝'=>'èŠ','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'è‹¥','茝'=>'èŒ','荣'=>'è£','莭'=>'莭','茣'=>'茣','ð¯¦'=>'莽','菧'=>'è§','著'=>'è‘—','荓'=>'è“','菊'=>'èŠ','菌'=>'èŒ','菜'=>'èœ','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'è”–','𧏊'=>'ð§Š','蕤'=>'蕤','𦼬'=>'𦼬','䕝'=>'ä•','䕡'=>'ä•¡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'ä•«','虐'=>'è™','虜'=>'虜','虧'=>'è™§','虩'=>'虩','蚩'=>'èš©','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'è¹','蜨'=>'蜨','蝫'=>'è«','螆'=>'螆','䗗'=>'ä——','蟡'=>'蟡','ð¯§'=>'è ','䗹'=>'ä—¹','衠'=>'è¡ ','衣'=>'è¡£','𧙧'=>'ð§™§','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'ã’»','𧢮'=>'ð§¢®','𧥦'=>'𧥦','ð¯§'=>'äš¾','䛇'=>'䛇','ð¯§'=>'誠','ð¯§'=>'è«­','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'è³','贛'=>'è´›','起'=>'èµ·','𧼯'=>'𧼯','𠠄'=>'ð  „','跋'=>'è·‹','趼'=>'è¶¼','跰'=>'è·°','ð¯§'=>'𠣞','軔'=>'è»”','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'𨗭','邔'=>'é‚”','郱'=>'郱','鄑'=>'é„‘','𨜮'=>'𨜮','鄛'=>'é„›','鈸'=>'鈸','鋗'=>'é‹—','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'é¹','鐕'=>'é•','𨯺'=>'𨯺','開'=>'é–‹','䦕'=>'䦕','閷'=>'é–·','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'å¶²','霣'=>'霣','𩅅'=>'ð©……','𩈚'=>'𩈚','䩮'=>'ä©®','䩶'=>'ä©¶','韠'=>'韠','𩐊'=>'ð©Š','䪲'=>'䪲','𩒖'=>'ð©’–','頋'=>'é ‹','頋'=>'é ‹','頩'=>'é ©','ð¯¨'=>'ð©–¶','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'é§‚','駾'=>'é§¾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'é±€','鳽'=>'é³½','ð¯¨'=>'䳎','䳭'=>'ä³­','ð¯¨'=>'éµ§','ð¯¨'=>'𪃎','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'äµ–','黹'=>'黹','黾'=>'黾','鼅'=>'é¼…','鼏'=>'é¼','鼖'=>'é¼–','鼻'=>'é¼»','ð¯¨'=>'𪘀'); diff --git a/phpBB/includes/utf/data/utf_compatibility_decomp.php b/phpBB/includes/utf/data/utf_compatibility_decomp.php deleted file mode 100644 index c62948e81a..0000000000 --- a/phpBB/includes/utf/data/utf_compatibility_decomp.php +++ /dev/null @@ -1,2 +0,0 @@ -' ','¨'=>' ̈','ª'=>'a','¯'=>' Ì„','²'=>'2','³'=>'3','´'=>' Ì','µ'=>'μ','¸'=>' ̧','¹'=>'1','º'=>'o','¼'=>'1â„4','½'=>'1â„2','¾'=>'3â„4','À'=>'AÌ€','Ã'=>'AÌ','Â'=>'AÌ‚','Ã'=>'Ã','Ä'=>'Ä','Ã…'=>'AÌŠ','Ç'=>'Ç','È'=>'EÌ€','É'=>'EÌ','Ê'=>'EÌ‚','Ë'=>'Ë','ÃŒ'=>'IÌ€','Ã'=>'IÌ','ÃŽ'=>'IÌ‚','Ã'=>'Ï','Ñ'=>'Ñ','Ã’'=>'OÌ€','Ó'=>'OÌ','Ô'=>'OÌ‚','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'UÌ€','Ú'=>'UÌ','Û'=>'UÌ‚','Ü'=>'Ü','Ã'=>'YÌ','à'=>'aÌ€','á'=>'aÌ','â'=>'aÌ‚','ã'=>'ã','ä'=>'ä','Ã¥'=>'aÌŠ','ç'=>'ç','è'=>'eÌ€','é'=>'eÌ','ê'=>'eÌ‚','ë'=>'ë','ì'=>'iÌ€','í'=>'iÌ','î'=>'iÌ‚','ï'=>'ï','ñ'=>'ñ','ò'=>'oÌ€','ó'=>'oÌ','ô'=>'oÌ‚','õ'=>'õ','ö'=>'ö','ù'=>'uÌ€','ú'=>'uÌ','û'=>'uÌ‚','ü'=>'ü','ý'=>'yÌ','ÿ'=>'ÿ','Ä€'=>'AÌ„','Ä'=>'aÌ„','Ä‚'=>'Ă','ă'=>'ă','Ä„'=>'Ą','Ä…'=>'ą','Ć'=>'CÌ','ć'=>'cÌ','Ĉ'=>'CÌ‚','ĉ'=>'cÌ‚','ÄŠ'=>'Ċ','Ä‹'=>'ċ','ÄŒ'=>'CÌŒ','Ä'=>'cÌŒ','ÄŽ'=>'DÌŒ','Ä'=>'dÌŒ','Ä’'=>'EÌ„','Ä“'=>'eÌ„','Ä”'=>'Ĕ','Ä•'=>'ĕ','Ä–'=>'Ė','Ä—'=>'ė','Ę'=>'Ę','Ä™'=>'ę','Äš'=>'EÌŒ','Ä›'=>'eÌŒ','Äœ'=>'GÌ‚','Ä'=>'gÌ‚','Äž'=>'Ğ','ÄŸ'=>'ğ','Ä '=>'Ġ','Ä¡'=>'ġ','Ä¢'=>'Ģ','Ä£'=>'ģ','Ĥ'=>'HÌ‚','Ä¥'=>'hÌ‚','Ĩ'=>'Ĩ','Ä©'=>'ĩ','Ī'=>'IÌ„','Ä«'=>'iÌ„','Ĭ'=>'Ĭ','Ä­'=>'ĭ','Ä®'=>'Į','į'=>'į','İ'=>'İ','IJ'=>'IJ','ij'=>'ij','Ä´'=>'JÌ‚','ĵ'=>'jÌ‚','Ķ'=>'Ķ','Ä·'=>'ķ','Ĺ'=>'LÌ','ĺ'=>'lÌ','Ä»'=>'Ļ','ļ'=>'ļ','Ľ'=>'LÌŒ','ľ'=>'lÌŒ','Ä¿'=>'L·','Å€'=>'l·','Ń'=>'NÌ','Å„'=>'nÌ','Å…'=>'Ņ','ņ'=>'ņ','Ň'=>'NÌŒ','ň'=>'nÌŒ','ʼn'=>'ʼn','ÅŒ'=>'OÌ„','Å'=>'oÌ„','ÅŽ'=>'Ŏ','Å'=>'ŏ','Å'=>'OÌ‹','Å‘'=>'oÌ‹','Å”'=>'RÌ','Å•'=>'rÌ','Å–'=>'Ŗ','Å—'=>'ŗ','Ř'=>'RÌŒ','Å™'=>'rÌŒ','Åš'=>'SÌ','Å›'=>'sÌ','Åœ'=>'SÌ‚','Å'=>'sÌ‚','Åž'=>'Ş','ÅŸ'=>'ş','Å '=>'SÌŒ','Å¡'=>'sÌŒ','Å¢'=>'Ţ','Å£'=>'ţ','Ť'=>'TÌŒ','Å¥'=>'tÌŒ','Ũ'=>'Ũ','Å©'=>'ũ','Ū'=>'UÌ„','Å«'=>'uÌ„','Ŭ'=>'Ŭ','Å­'=>'ŭ','Å®'=>'UÌŠ','ů'=>'uÌŠ','Ű'=>'UÌ‹','ű'=>'uÌ‹','Ų'=>'Ų','ų'=>'ų','Å´'=>'WÌ‚','ŵ'=>'wÌ‚','Ŷ'=>'YÌ‚','Å·'=>'yÌ‚','Ÿ'=>'Ÿ','Ź'=>'ZÌ','ź'=>'zÌ','Å»'=>'Ż','ż'=>'ż','Ž'=>'ZÌŒ','ž'=>'zÌŒ','Å¿'=>'s','Æ '=>'OÌ›','Æ¡'=>'oÌ›','Ư'=>'UÌ›','ư'=>'uÌ›','Ç„'=>'DZÌŒ','Ç…'=>'DzÌŒ','dž'=>'dzÌŒ','LJ'=>'LJ','Lj'=>'Lj','lj'=>'lj','ÇŠ'=>'NJ','Ç‹'=>'Nj','ÇŒ'=>'nj','Ç'=>'AÌŒ','ÇŽ'=>'aÌŒ','Ç'=>'IÌŒ','Ç'=>'iÌŒ','Ç‘'=>'OÌŒ','Ç’'=>'oÌŒ','Ç“'=>'UÌŒ','Ç”'=>'uÌŒ','Ç•'=>'Ǖ','Ç–'=>'ǖ','Ç—'=>'ÜÌ','ǘ'=>'üÌ','Ç™'=>'Ǚ','Çš'=>'ǚ','Ç›'=>'Ǜ','Çœ'=>'ǜ','Çž'=>'Ǟ','ÇŸ'=>'ǟ','Ç '=>'Ǡ','Ç¡'=>'ǡ','Ç¢'=>'Ǣ','Ç£'=>'ǣ','Ǧ'=>'GÌŒ','ǧ'=>'gÌŒ','Ǩ'=>'KÌŒ','Ç©'=>'kÌŒ','Ǫ'=>'Ǫ','Ç«'=>'ǫ','Ǭ'=>'Ǭ','Ç­'=>'ǭ','Ç®'=>'Æ·ÌŒ','ǯ'=>'Ê’ÌŒ','ǰ'=>'jÌŒ','DZ'=>'DZ','Dz'=>'Dz','dz'=>'dz','Ç´'=>'GÌ','ǵ'=>'gÌ','Ǹ'=>'NÌ€','ǹ'=>'nÌ€','Ǻ'=>'AÌŠÌ','Ç»'=>'aÌŠÌ','Ǽ'=>'ÆÌ','ǽ'=>'æÌ','Ǿ'=>'ØÌ','Ç¿'=>'øÌ','È€'=>'AÌ','È'=>'aÌ','È‚'=>'AÌ‘','ȃ'=>'aÌ‘','È„'=>'EÌ','È…'=>'eÌ','Ȇ'=>'EÌ‘','ȇ'=>'eÌ‘','Ȉ'=>'IÌ','ȉ'=>'iÌ','ÈŠ'=>'IÌ‘','È‹'=>'iÌ‘','ÈŒ'=>'OÌ','È'=>'oÌ','ÈŽ'=>'OÌ‘','È'=>'oÌ‘','È'=>'RÌ','È‘'=>'rÌ','È’'=>'RÌ‘','È“'=>'rÌ‘','È”'=>'UÌ','È•'=>'uÌ','È–'=>'UÌ‘','È—'=>'uÌ‘','Ș'=>'Ș','È™'=>'ș','Èš'=>'Ț','È›'=>'ț','Èž'=>'HÌŒ','ÈŸ'=>'hÌŒ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','È©'=>'ȩ','Ȫ'=>'Ȫ','È«'=>'ȫ','Ȭ'=>'Ȭ','È­'=>'ȭ','È®'=>'Ȯ','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'YÌ„','ȳ'=>'yÌ„','ʰ'=>'h','ʱ'=>'ɦ','ʲ'=>'j','ʳ'=>'r','Ê´'=>'ɹ','ʵ'=>'É»','ʶ'=>'Ê','Ê·'=>'w','ʸ'=>'y','˘'=>' ̆','Ë™'=>' ̇','Ëš'=>' ÌŠ','Ë›'=>' ̨','Ëœ'=>' ̃','Ë'=>' Ì‹','Ë '=>'É£','Ë¡'=>'l','Ë¢'=>'s','Ë£'=>'x','ˤ'=>'Ê•','Í€'=>'Ì€','Í'=>'Ì','̓'=>'Ì“','Í„'=>'̈Ì','Í´'=>'ʹ','ͺ'=>' Í…',';'=>';','΄'=>' Ì','Î…'=>' ̈Ì','Ά'=>'ΑÌ','·'=>'·','Έ'=>'ΕÌ','Ή'=>'ΗÌ','Ί'=>'ΙÌ','ÎŒ'=>'ΟÌ','ÎŽ'=>'Î¥Ì','Î'=>'ΩÌ','Î'=>'ϊÌ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'αÌ','έ'=>'εÌ','ή'=>'ηÌ','ί'=>'ιÌ','ΰ'=>'ϋÌ','ÏŠ'=>'ϊ','Ï‹'=>'ϋ','ÏŒ'=>'οÌ','Ï'=>'Ï…Ì','ÏŽ'=>'ωÌ','Ï'=>'β','Ï‘'=>'θ','Ï’'=>'Î¥','Ï“'=>'Î¥Ì','Ï”'=>'Ϋ','Ï•'=>'φ','Ï–'=>'Ï€','ϰ'=>'κ','ϱ'=>'Ï','ϲ'=>'Ï‚','Ï´'=>'Θ','ϵ'=>'ε','Ϲ'=>'Σ','Ѐ'=>'Ѐ','Ð'=>'Ё','Ѓ'=>'ГÌ','Ї'=>'Ї','ÐŒ'=>'КÌ','Ð'=>'Ѝ','ÐŽ'=>'Ў','Й'=>'Й','й'=>'й','Ñ'=>'ѐ','Ñ‘'=>'ё','Ñ“'=>'гÌ','Ñ—'=>'ї','Ñœ'=>'кÌ','Ñ'=>'ѝ','Ñž'=>'ў','Ѷ'=>'Ñ´Ì','Ñ·'=>'ѵÌ','Ó'=>'Ӂ','Ó‚'=>'ӂ','Ó'=>'Ð̆','Ó‘'=>'ӑ','Ó’'=>'Ð̈','Ó“'=>'ӓ','Ó–'=>'Ӗ','Ó—'=>'ӗ','Óš'=>'Ӛ','Ó›'=>'ӛ','Óœ'=>'Ӝ','Ó'=>'ӝ','Óž'=>'Ӟ','ÓŸ'=>'ӟ','Ó¢'=>'Ӣ','Ó£'=>'ӣ','Ó¤'=>'Ӥ','Ó¥'=>'ӥ','Ó¦'=>'Ӧ','Ó§'=>'ӧ','Óª'=>'Ӫ','Ó«'=>'ӫ','Ó¬'=>'Ӭ','Ó­'=>'Ñ̈','Ó®'=>'Ӯ','Ó¯'=>'ӯ','Ó°'=>'Ӱ','Ó±'=>'ӱ','Ó²'=>'Ӳ','Ó³'=>'ӳ','Ó´'=>'Ӵ','Óµ'=>'ӵ','Ó¸'=>'Ӹ','Ó¹'=>'ӹ','Ö‡'=>'Õ¥Ö‚','Ø¢'=>'آ','Ø£'=>'أ','ؤ'=>'ÙˆÙ”','Ø¥'=>'إ','ئ'=>'ÙŠÙ”','Ùµ'=>'اٴ','Ù¶'=>'وٴ','Ù·'=>'Û‡Ù´','Ù¸'=>'يٴ','Û€'=>'Û•Ù”','Û‚'=>'ÛÙ”','Û“'=>'Û’Ù”','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','à¥'=>'ढ़','फ़'=>'फ़','य़'=>'य़','à§‹'=>'ো','à§Œ'=>'ৌ','à§œ'=>'ড়','à§'=>'ঢ়','à§Ÿ'=>'য়','ਲ਼'=>'ਲ਼','ਸ਼'=>'ਸ਼','à©™'=>'ਖ਼','ਗ਼'=>'ਗ਼','à©›'=>'ਜ਼','ਫ਼'=>'ਫ਼','à­ˆ'=>'ୈ','à­‹'=>'ୋ','à­Œ'=>'ୌ','à­œ'=>'ଡ଼','à­'=>'ଢ଼','à®”'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','à³€'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','à·š'=>'ේ','à·œ'=>'à·™à·','à·'=>'à·™à·à·Š','à·ž'=>'ෞ','ำ'=>'à¹à¸²','ຳ'=>'à»àº²','ໜ'=>'ຫນ','à»'=>'ຫມ','༌'=>'་','གྷ'=>'གྷ','à½'=>'ཌྷ','དྷ'=>'དྷ','བྷ'=>'བྷ','ཛྷ'=>'ཛྷ','ཀྵ'=>'ཀྵ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ཷ'=>'ྲཱྀ','ླྀ'=>'ླྀ','ཹ'=>'ླཱྀ','à¾'=>'ཱྀ','ྒྷ'=>'ྒྷ','à¾'=>'ྜྷ','ྡྷ'=>'ྡྷ','ྦྷ'=>'ྦྷ','ྫྷ'=>'ྫྷ','ྐྵ'=>'à¾à¾µ','ဦ'=>'ဦ','ჼ'=>'ნ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'á¬á¬µ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','á­€'=>'ᭀ','á­'=>'ᭁ','á­ƒ'=>'ᭃ','á´¬'=>'A','á´­'=>'Æ','á´®'=>'B','á´°'=>'D','á´±'=>'E','á´²'=>'ÆŽ','á´³'=>'G','á´´'=>'H','á´µ'=>'I','á´¶'=>'J','á´·'=>'K','á´¸'=>'L','á´¹'=>'M','á´º'=>'N','á´¼'=>'O','á´½'=>'È¢','á´¾'=>'P','á´¿'=>'R','áµ€'=>'T','áµ'=>'U','ᵂ'=>'W','ᵃ'=>'a','ᵄ'=>'É','áµ…'=>'É‘','ᵆ'=>'á´‚','ᵇ'=>'b','ᵈ'=>'d','ᵉ'=>'e','ᵊ'=>'É™','ᵋ'=>'É›','ᵌ'=>'Éœ','áµ'=>'g','áµ'=>'k','áµ'=>'m','ᵑ'=>'Å‹','áµ’'=>'o','ᵓ'=>'É”','áµ”'=>'á´–','ᵕ'=>'á´—','áµ–'=>'p','áµ—'=>'t','ᵘ'=>'u','áµ™'=>'á´','ᵚ'=>'ɯ','áµ›'=>'v','ᵜ'=>'á´¥','áµ'=>'β','ᵞ'=>'γ','ᵟ'=>'δ','áµ '=>'φ','ᵡ'=>'χ','áµ¢'=>'i','áµ£'=>'r','ᵤ'=>'u','áµ¥'=>'v','ᵦ'=>'β','áµ§'=>'γ','ᵨ'=>'Ï','ᵩ'=>'φ','ᵪ'=>'χ','ᵸ'=>'н','á¶›'=>'É’','á¶œ'=>'c','á¶'=>'É•','á¶ž'=>'ð','á¶Ÿ'=>'Éœ','á¶ '=>'f','á¶¡'=>'ÉŸ','á¶¢'=>'É¡','á¶£'=>'É¥','ᶤ'=>'ɨ','á¶¥'=>'É©','ᶦ'=>'ɪ','á¶§'=>'áµ»','ᶨ'=>'Ê','á¶©'=>'É­','ᶪ'=>'á¶…','á¶«'=>'ÊŸ','ᶬ'=>'ɱ','á¶­'=>'ɰ','á¶®'=>'ɲ','ᶯ'=>'ɳ','á¶°'=>'É´','á¶±'=>'ɵ','á¶²'=>'ɸ','á¶³'=>'Ê‚','á¶´'=>'ʃ','á¶µ'=>'Æ«','á¶¶'=>'ʉ','á¶·'=>'ÊŠ','ᶸ'=>'á´œ','á¶¹'=>'Ê‹','ᶺ'=>'ÊŒ','á¶»'=>'z','á¶¼'=>'Ê','á¶½'=>'Ê‘','á¶¾'=>'Ê’','á¶¿'=>'θ','Ḁ'=>'AÌ¥','á¸'=>'aÌ¥','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'BÌ£','ḅ'=>'bÌ£','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'ÇÌ','ḉ'=>'çÌ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'DÌ£','á¸'=>'dÌ£','Ḏ'=>'Ḏ','á¸'=>'ḏ','á¸'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'DÌ­','ḓ'=>'dÌ­','Ḕ'=>'Ḕ','ḕ'=>'ḕ','Ḗ'=>'EÌ„Ì','ḗ'=>'eÌ„Ì','Ḙ'=>'EÌ­','ḙ'=>'eÌ­','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','á¸'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'GÌ„','ḡ'=>'gÌ„','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'HÌ£','ḥ'=>'hÌ£','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'HÌ®','ḫ'=>'hÌ®','Ḭ'=>'Ḭ','ḭ'=>'ḭ','Ḯ'=>'ÏÌ','ḯ'=>'ïÌ','Ḱ'=>'KÌ','ḱ'=>'kÌ','Ḳ'=>'KÌ£','ḳ'=>'kÌ£','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'LÌ£','ḷ'=>'lÌ£','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'LÌ­','ḽ'=>'lÌ­','Ḿ'=>'MÌ','ḿ'=>'mÌ','á¹€'=>'Ṁ','á¹'=>'ṁ','Ṃ'=>'MÌ£','ṃ'=>'mÌ£','Ṅ'=>'Ṅ','á¹…'=>'ṅ','Ṇ'=>'NÌ£','ṇ'=>'nÌ£','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'NÌ­','ṋ'=>'nÌ­','Ṍ'=>'ÕÌ','á¹'=>'õÌ','Ṏ'=>'Ṏ','á¹'=>'ṏ','á¹'=>'Ṑ','ṑ'=>'ṑ','á¹’'=>'OÌ„Ì','ṓ'=>'oÌ„Ì','á¹”'=>'PÌ','ṕ'=>'pÌ','á¹–'=>'Ṗ','á¹—'=>'ṗ','Ṙ'=>'Ṙ','á¹™'=>'ṙ','Ṛ'=>'RÌ£','á¹›'=>'rÌ£','Ṝ'=>'Ṝ','á¹'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','á¹ '=>'Ṡ','ṡ'=>'ṡ','á¹¢'=>'SÌ£','á¹£'=>'sÌ£','Ṥ'=>'SÌ̇','á¹¥'=>'sÌ̇','Ṧ'=>'Ṧ','á¹§'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'TÌ£','á¹­'=>'tÌ£','á¹®'=>'Ṯ','ṯ'=>'ṯ','á¹°'=>'TÌ­','á¹±'=>'tÌ­','á¹²'=>'Ṳ','á¹³'=>'ṳ','á¹´'=>'Ṵ','á¹µ'=>'ṵ','á¹¶'=>'UÌ­','á¹·'=>'uÌ­','Ṹ'=>'ŨÌ','á¹¹'=>'ũÌ','Ṻ'=>'Ṻ','á¹»'=>'ṻ','á¹¼'=>'Ṽ','á¹½'=>'ṽ','á¹¾'=>'VÌ£','ṿ'=>'vÌ£','Ẁ'=>'WÌ€','áº'=>'wÌ€','Ẃ'=>'WÌ','ẃ'=>'wÌ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'WÌ£','ẉ'=>'wÌ£','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','áº'=>'ẍ','Ẏ'=>'Ẏ','áº'=>'ẏ','áº'=>'ZÌ‚','ẑ'=>'zÌ‚','Ẓ'=>'ZÌ£','ẓ'=>'zÌ£','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'wÌŠ','ẙ'=>'yÌŠ','ẚ'=>'aʾ','ẛ'=>'ṡ','Ạ'=>'AÌ£','ạ'=>'aÌ£','Ả'=>'Ả','ả'=>'ả','Ấ'=>'AÌ‚Ì','ấ'=>'aÌ‚Ì','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'ậ','Ắ'=>'ĂÌ','ắ'=>'ăÌ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'EÌ£','ẹ'=>'eÌ£','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'EÌ‚Ì','ế'=>'eÌ‚Ì','Ề'=>'Ề','á»'=>'ề','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','á»…'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'IÌ£','ị'=>'iÌ£','Ọ'=>'OÌ£','á»'=>'oÌ£','Ỏ'=>'Ỏ','á»'=>'ỏ','á»'=>'OÌ‚Ì','ố'=>'oÌ‚Ì','á»’'=>'Ồ','ồ'=>'ồ','á»”'=>'Ổ','ổ'=>'ổ','á»–'=>'Ỗ','á»—'=>'ỗ','Ộ'=>'Ộ','á»™'=>'ộ','Ớ'=>'OÌ›Ì','á»›'=>'oÌ›Ì','Ờ'=>'Ờ','á»'=>'ờ','Ở'=>'Ở','ở'=>'ở','á» '=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'UÌ£','ụ'=>'uÌ£','Ủ'=>'Ủ','á»§'=>'ủ','Ứ'=>'UÌ›Ì','ứ'=>'uÌ›Ì','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','á»­'=>'ử','á»®'=>'Ữ','ữ'=>'ữ','á»°'=>'Ự','á»±'=>'ự','Ỳ'=>'YÌ€','ỳ'=>'yÌ€','á»´'=>'YÌ£','ỵ'=>'yÌ£','á»¶'=>'Ỷ','á»·'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','á¼€'=>'ἀ','á¼'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἀÌ','á¼…'=>'ἁÌ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'ἈÌ','á¼'=>'ἉÌ','Ἆ'=>'Ἆ','á¼'=>'Ἇ','á¼'=>'ἐ','ἑ'=>'ἑ','á¼’'=>'ἒ','ἓ'=>'ἓ','á¼”'=>'ἐÌ','ἕ'=>'ἑÌ','Ἐ'=>'Ἐ','á¼™'=>'Ἑ','Ἒ'=>'Ἒ','á¼›'=>'Ἓ','Ἔ'=>'ἘÌ','á¼'=>'ἙÌ','á¼ '=>'ἠ','ἡ'=>'ἡ','á¼¢'=>'ἢ','á¼£'=>'ἣ','ἤ'=>'ἠÌ','á¼¥'=>'ἡÌ','ἦ'=>'ἦ','á¼§'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'ἨÌ','á¼­'=>'ἩÌ','á¼®'=>'Ἦ','Ἧ'=>'Ἧ','á¼°'=>'ἰ','á¼±'=>'ἱ','á¼²'=>'ἲ','á¼³'=>'ἳ','á¼´'=>'ἰÌ','á¼µ'=>'ἱÌ','á¼¶'=>'ἶ','á¼·'=>'ἷ','Ἰ'=>'Ἰ','á¼¹'=>'Ἱ','Ἲ'=>'Ἲ','á¼»'=>'Ἳ','á¼¼'=>'ἸÌ','á¼½'=>'ἹÌ','á¼¾'=>'Ἶ','Ἷ'=>'Ἷ','á½€'=>'ὀ','á½'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὀÌ','á½…'=>'ὁÌ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'ὈÌ','á½'=>'ὉÌ','á½'=>'Ï…Ì“','ὑ'=>'Ï…Ì”','á½’'=>'ὒ','ὓ'=>'ὓ','á½”'=>'Ï…Ì“Ì','ὕ'=>'Ï…Ì”Ì','á½–'=>'ὖ','á½—'=>'ὗ','á½™'=>'Ὑ','á½›'=>'Ὓ','á½'=>'ὙÌ','Ὗ'=>'Ὗ','á½ '=>'ὠ','ὡ'=>'ὡ','á½¢'=>'ὢ','á½£'=>'ὣ','ὤ'=>'ὠÌ','á½¥'=>'ὡÌ','ὦ'=>'ὦ','á½§'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'ὨÌ','á½­'=>'ὩÌ','á½®'=>'Ὦ','Ὧ'=>'Ὧ','á½°'=>'ὰ','á½±'=>'αÌ','á½²'=>'ὲ','á½³'=>'εÌ','á½´'=>'ὴ','á½µ'=>'ηÌ','á½¶'=>'ὶ','á½·'=>'ιÌ','ὸ'=>'ὸ','á½¹'=>'οÌ','ὺ'=>'Ï…Ì€','á½»'=>'Ï…Ì','á½¼'=>'ὼ','á½½'=>'ωÌ','á¾€'=>'ᾀ','á¾'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ἀÌÍ…','á¾…'=>'ἁÌÍ…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ἈÌÍ…','á¾'=>'ἉÌÍ…','ᾎ'=>'ᾎ','á¾'=>'ᾏ','á¾'=>'ᾐ','ᾑ'=>'ᾑ','á¾’'=>'ᾒ','ᾓ'=>'ᾓ','á¾”'=>'ἠÌÍ…','ᾕ'=>'ἡÌÍ…','á¾–'=>'ᾖ','á¾—'=>'ᾗ','ᾘ'=>'ᾘ','á¾™'=>'ᾙ','ᾚ'=>'ᾚ','á¾›'=>'ᾛ','ᾜ'=>'ἨÌÍ…','á¾'=>'ἩÌÍ…','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á¾ '=>'ᾠ','ᾡ'=>'ᾡ','á¾¢'=>'ᾢ','á¾£'=>'ᾣ','ᾤ'=>'ὠÌÍ…','á¾¥'=>'ὡÌÍ…','ᾦ'=>'ᾦ','á¾§'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ὨÌÍ…','á¾­'=>'ὩÌÍ…','á¾®'=>'ᾮ','ᾯ'=>'ᾯ','á¾°'=>'ᾰ','á¾±'=>'ᾱ','á¾²'=>'ᾲ','á¾³'=>'ᾳ','á¾´'=>'αÌÍ…','á¾¶'=>'ᾶ','á¾·'=>'ᾷ','Ᾰ'=>'Ᾰ','á¾¹'=>'Ᾱ','Ὰ'=>'Ὰ','á¾»'=>'ΑÌ','á¾¼'=>'ᾼ','á¾½'=>' Ì“','á¾¾'=>'ι','᾿'=>' Ì“','á¿€'=>' Í‚','á¿'=>' ̈͂','á¿‚'=>'ῂ','ῃ'=>'ῃ','á¿„'=>'ηÌÍ…','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'ΕÌ','Ὴ'=>'Ὴ','á¿‹'=>'ΗÌ','ῌ'=>'ῌ','á¿'=>' ̓̀','῎'=>' Ì“Ì','á¿'=>' ̓͂','á¿'=>'ῐ','á¿‘'=>'ῑ','á¿’'=>'ῒ','á¿“'=>'ϊÌ','á¿–'=>'ῖ','á¿—'=>'ῗ','Ῐ'=>'Ῐ','á¿™'=>'Ῑ','Ὶ'=>'Ὶ','á¿›'=>'ΙÌ','á¿'=>' ̔̀','῞'=>' Ì”Ì','῟'=>' ̔͂','á¿ '=>'ῠ','á¿¡'=>'Ï…Ì„','á¿¢'=>'ῢ','á¿£'=>'ϋÌ','ῤ'=>'ÏÌ“','á¿¥'=>'ÏÌ”','ῦ'=>'Ï…Í‚','á¿§'=>'ῧ','Ῠ'=>'Ῠ','á¿©'=>'Ῡ','Ὺ'=>'Ὺ','á¿«'=>'Î¥Ì','Ῥ'=>'Ῥ','á¿­'=>' ̈̀','á¿®'=>' ̈Ì','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','á¿´'=>'ωÌÍ…','á¿¶'=>'ῶ','á¿·'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'ΟÌ','Ὼ'=>'Ὼ','á¿»'=>'ΩÌ','ῼ'=>'ῼ','´'=>' Ì','῾'=>' Ì”',' '=>' ','â€'=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ','‑'=>'â€','‗'=>' ̳','․'=>'.','‥'=>'..','…'=>'...',' '=>' ','″'=>'′′','‴'=>'′′′','‶'=>'‵‵','‷'=>'‵‵‵','‼'=>'!!','‾'=>' Ì…','â‡'=>'??','âˆ'=>'?!','â‰'=>'!?','â—'=>'′′′′','âŸ'=>' ','â°'=>'0','â±'=>'i','â´'=>'4','âµ'=>'5','â¶'=>'6','â·'=>'7','â¸'=>'8','â¹'=>'9','âº'=>'+','â»'=>'−','â¼'=>'=','â½'=>'(','â¾'=>')','â¿'=>'n','â‚€'=>'0','â‚'=>'1','â‚‚'=>'2','₃'=>'3','â‚„'=>'4','â‚…'=>'5','₆'=>'6','₇'=>'7','₈'=>'8','₉'=>'9','₊'=>'+','â‚‹'=>'−','₌'=>'=','â‚'=>'(','₎'=>')','â‚'=>'a','â‚‘'=>'e','â‚’'=>'o','â‚“'=>'x','â‚”'=>'É™','₨'=>'Rs','â„€'=>'a/c','â„'=>'a/s','â„‚'=>'C','℃'=>'°C','â„…'=>'c/o','℆'=>'c/u','ℇ'=>'Æ','℉'=>'°F','ℊ'=>'g','â„‹'=>'H','ℌ'=>'H','â„'=>'H','ℎ'=>'h','â„'=>'ħ','â„'=>'I','â„‘'=>'I','â„’'=>'L','â„“'=>'l','â„•'=>'N','â„–'=>'No','â„™'=>'P','ℚ'=>'Q','â„›'=>'R','ℜ'=>'R','â„'=>'R','â„ '=>'SM','â„¡'=>'TEL','â„¢'=>'TM','ℤ'=>'Z','Ω'=>'Ω','ℨ'=>'Z','K'=>'K','â„«'=>'AÌŠ','ℬ'=>'B','â„­'=>'C','ℯ'=>'e','â„°'=>'E','ℱ'=>'F','ℳ'=>'M','â„´'=>'o','ℵ'=>'×','â„¶'=>'ב','â„·'=>'×’','ℸ'=>'ד','ℹ'=>'i','â„»'=>'FAX','ℼ'=>'Ï€','ℽ'=>'γ','ℾ'=>'Γ','â„¿'=>'Π','â…€'=>'∑','â……'=>'D','â…†'=>'d','â…‡'=>'e','â…ˆ'=>'i','â…‰'=>'j','â…“'=>'1â„3','â…”'=>'2â„3','â…•'=>'1â„5','â…–'=>'2â„5','â…—'=>'3â„5','â…˜'=>'4â„5','â…™'=>'1â„6','â…š'=>'5â„6','â…›'=>'1â„8','â…œ'=>'3â„8','â…'=>'5â„8','â…ž'=>'7â„8','â…Ÿ'=>'1â„','â… '=>'I','â…¡'=>'II','â…¢'=>'III','â…£'=>'IV','â…¤'=>'V','â…¥'=>'VI','â…¦'=>'VII','â…§'=>'VIII','â…¨'=>'IX','â…©'=>'X','â…ª'=>'XI','â…«'=>'XII','â…¬'=>'L','â…­'=>'C','â…®'=>'D','â…¯'=>'M','â…°'=>'i','â…±'=>'ii','â…²'=>'iii','â…³'=>'iv','â…´'=>'v','â…µ'=>'vi','â…¶'=>'vii','â…·'=>'viii','â…¸'=>'ix','â…¹'=>'x','â…º'=>'xi','â…»'=>'xii','â…¼'=>'l','â…½'=>'c','â…¾'=>'d','â…¿'=>'m','↚'=>'â†Ì¸','↛'=>'↛','↮'=>'↮','â‡'=>'â‡Ì¸','⇎'=>'⇎','â‡'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','∬'=>'∫∫','∭'=>'∫∫∫','∯'=>'∮∮','∰'=>'∮∮∮','â‰'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','≭'=>'â‰Ì¸','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','âŠ'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','â‹ '=>'⋠','â‹¡'=>'⋡','â‹¢'=>'⋢','â‹£'=>'⋣','⋪'=>'⋪','â‹«'=>'⋫','⋬'=>'⋬','â‹­'=>'⋭','〈'=>'〈','〉'=>'〉','â‘ '=>'1','â‘¡'=>'2','â‘¢'=>'3','â‘£'=>'4','⑤'=>'5','â‘¥'=>'6','⑦'=>'7','â‘§'=>'8','⑨'=>'9','â‘©'=>'10','⑪'=>'11','â‘«'=>'12','⑬'=>'13','â‘­'=>'14','â‘®'=>'15','⑯'=>'16','â‘°'=>'17','⑱'=>'18','⑲'=>'19','⑳'=>'20','â‘´'=>'(1)','⑵'=>'(2)','â‘¶'=>'(3)','â‘·'=>'(4)','⑸'=>'(5)','⑹'=>'(6)','⑺'=>'(7)','â‘»'=>'(8)','⑼'=>'(9)','⑽'=>'(10)','⑾'=>'(11)','â‘¿'=>'(12)','â’€'=>'(13)','â’'=>'(14)','â’‚'=>'(15)','â’ƒ'=>'(16)','â’„'=>'(17)','â’…'=>'(18)','â’†'=>'(19)','â’‡'=>'(20)','â’ˆ'=>'1.','â’‰'=>'2.','â’Š'=>'3.','â’‹'=>'4.','â’Œ'=>'5.','â’'=>'6.','â’Ž'=>'7.','â’'=>'8.','â’'=>'9.','â’‘'=>'10.','â’’'=>'11.','â’“'=>'12.','â’”'=>'13.','â’•'=>'14.','â’–'=>'15.','â’—'=>'16.','â’˜'=>'17.','â’™'=>'18.','â’š'=>'19.','â’›'=>'20.','â’œ'=>'(a)','â’'=>'(b)','â’ž'=>'(c)','â’Ÿ'=>'(d)','â’ '=>'(e)','â’¡'=>'(f)','â’¢'=>'(g)','â’£'=>'(h)','â’¤'=>'(i)','â’¥'=>'(j)','â’¦'=>'(k)','â’§'=>'(l)','â’¨'=>'(m)','â’©'=>'(n)','â’ª'=>'(o)','â’«'=>'(p)','â’¬'=>'(q)','â’­'=>'(r)','â’®'=>'(s)','â’¯'=>'(t)','â’°'=>'(u)','â’±'=>'(v)','â’²'=>'(w)','â’³'=>'(x)','â’´'=>'(y)','â’µ'=>'(z)','â’¶'=>'A','â’·'=>'B','â’¸'=>'C','â’¹'=>'D','â’º'=>'E','â’»'=>'F','â’¼'=>'G','â’½'=>'H','â’¾'=>'I','â’¿'=>'J','â“€'=>'K','â“'=>'L','â“‚'=>'M','Ⓝ'=>'N','â“„'=>'O','â“…'=>'P','Ⓠ'=>'Q','Ⓡ'=>'R','Ⓢ'=>'S','Ⓣ'=>'T','Ⓤ'=>'U','â“‹'=>'V','Ⓦ'=>'W','â“'=>'X','Ⓨ'=>'Y','â“'=>'Z','â“'=>'a','â“‘'=>'b','â“’'=>'c','â““'=>'d','â“”'=>'e','â“•'=>'f','â“–'=>'g','â“—'=>'h','ⓘ'=>'i','â“™'=>'j','ⓚ'=>'k','â“›'=>'l','ⓜ'=>'m','â“'=>'n','ⓞ'=>'o','ⓟ'=>'p','â“ '=>'q','â“¡'=>'r','â“¢'=>'s','â“£'=>'t','ⓤ'=>'u','â“¥'=>'v','ⓦ'=>'w','â“§'=>'x','ⓨ'=>'y','â“©'=>'z','⓪'=>'0','⨌'=>'∫∫∫∫','â©´'=>'::=','⩵'=>'==','â©¶'=>'===','⫝̸'=>'â«Ì¸','ⵯ'=>'ⵡ','⺟'=>'æ¯','⻳'=>'龟','â¼€'=>'一','â¼'=>'丨','⼂'=>'丶','⼃'=>'丿','⼄'=>'ä¹™','â¼…'=>'亅','⼆'=>'二','⼇'=>'亠','⼈'=>'人','⼉'=>'å„¿','⼊'=>'å…¥','⼋'=>'å…«','⼌'=>'冂','â¼'=>'冖','⼎'=>'冫','â¼'=>'几','â¼'=>'凵','⼑'=>'刀','â¼’'=>'力','⼓'=>'勹','â¼”'=>'匕','⼕'=>'匚','â¼–'=>'匸','â¼—'=>'å','⼘'=>'åœ','â¼™'=>'å©','⼚'=>'厂','â¼›'=>'厶','⼜'=>'åˆ','â¼'=>'å£','⼞'=>'å›—','⼟'=>'土','â¼ '=>'士','⼡'=>'夂','â¼¢'=>'夊','â¼£'=>'夕','⼤'=>'大','â¼¥'=>'女','⼦'=>'å­','â¼§'=>'宀','⼨'=>'寸','⼩'=>'å°','⼪'=>'å°¢','⼫'=>'å°¸','⼬'=>'å±®','â¼­'=>'å±±','â¼®'=>'å·›','⼯'=>'å·¥','â¼°'=>'å·±','â¼±'=>'å·¾','â¼²'=>'å¹²','â¼³'=>'幺','â¼´'=>'广','â¼µ'=>'å»´','â¼¶'=>'廾','â¼·'=>'弋','⼸'=>'弓','â¼¹'=>'å½','⼺'=>'彡','â¼»'=>'å½³','â¼¼'=>'心','â¼½'=>'戈','â¼¾'=>'戶','⼿'=>'手','â½€'=>'支','â½'=>'æ”´','⽂'=>'æ–‡','⽃'=>'æ–—','⽄'=>'æ–¤','â½…'=>'æ–¹','⽆'=>'æ— ','⽇'=>'æ—¥','⽈'=>'æ›°','⽉'=>'月','⽊'=>'木','⽋'=>'欠','⽌'=>'æ­¢','â½'=>'æ­¹','⽎'=>'殳','â½'=>'毋','â½'=>'比','⽑'=>'毛','â½’'=>'æ°','⽓'=>'æ°”','â½”'=>'æ°´','⽕'=>'ç«','â½–'=>'爪','â½—'=>'父','⽘'=>'爻','â½™'=>'爿','⽚'=>'片','â½›'=>'牙','⽜'=>'牛','â½'=>'犬','⽞'=>'玄','⽟'=>'玉','â½ '=>'瓜','⽡'=>'瓦','â½¢'=>'甘','â½£'=>'生','⽤'=>'用','â½¥'=>'ç”°','⽦'=>'ç–‹','â½§'=>'ç–’','⽨'=>'ç™¶','⽩'=>'白','⽪'=>'çš®','⽫'=>'çš¿','⽬'=>'ç›®','â½­'=>'矛','â½®'=>'矢','⽯'=>'石','â½°'=>'示','â½±'=>'禸','â½²'=>'禾','â½³'=>'ç©´','â½´'=>'ç«‹','â½µ'=>'竹','â½¶'=>'ç±³','â½·'=>'糸','⽸'=>'ç¼¶','â½¹'=>'网','⽺'=>'羊','â½»'=>'ç¾½','â½¼'=>'è€','â½½'=>'而','â½¾'=>'耒','⽿'=>'耳','â¾€'=>'è¿','â¾'=>'肉','⾂'=>'臣','⾃'=>'自','⾄'=>'至','â¾…'=>'臼','⾆'=>'舌','⾇'=>'舛','⾈'=>'舟','⾉'=>'艮','⾊'=>'色','⾋'=>'艸','⾌'=>'è™','â¾'=>'虫','⾎'=>'è¡€','â¾'=>'行','â¾'=>'è¡£','⾑'=>'襾','â¾’'=>'見','⾓'=>'è§’','â¾”'=>'言','⾕'=>'è°·','â¾–'=>'豆','â¾—'=>'豕','⾘'=>'豸','â¾™'=>'è²','⾚'=>'赤','â¾›'=>'èµ°','⾜'=>'è¶³','â¾'=>'身','⾞'=>'車','⾟'=>'è¾›','â¾ '=>'è¾°','⾡'=>'è¾µ','â¾¢'=>'é‚‘','â¾£'=>'é…‰','⾤'=>'釆','â¾¥'=>'里','⾦'=>'金','â¾§'=>'é•·','⾨'=>'é–€','⾩'=>'阜','⾪'=>'éš¶','⾫'=>'éš¹','⾬'=>'雨','â¾­'=>'é‘','â¾®'=>'éž','⾯'=>'é¢','â¾°'=>'é©','â¾±'=>'韋','â¾²'=>'韭','â¾³'=>'音','â¾´'=>'é ','â¾µ'=>'風','â¾¶'=>'飛','â¾·'=>'食','⾸'=>'首','â¾¹'=>'香','⾺'=>'馬','â¾»'=>'骨','â¾¼'=>'高','â¾½'=>'髟','â¾¾'=>'鬥','⾿'=>'鬯','â¿€'=>'鬲','â¿'=>'鬼','â¿‚'=>'é­š','⿃'=>'é³¥','â¿„'=>'é¹µ','â¿…'=>'鹿','⿆'=>'麥','⿇'=>'麻','⿈'=>'黃','⿉'=>'é»','⿊'=>'黑','â¿‹'=>'黹','⿌'=>'黽','â¿'=>'鼎','⿎'=>'鼓','â¿'=>'é¼ ','â¿'=>'é¼»','â¿‘'=>'齊','â¿’'=>'é½’','â¿“'=>'é¾','â¿”'=>'龜','â¿•'=>'é¾ ',' '=>' ','〶'=>'〒','〸'=>'å','〹'=>'å„','〺'=>'å…','ãŒ'=>'ã‹ã‚™','ãŽ'=>'ãã‚™','ã'=>'ãã‚™','ã’'=>'ã‘ã‚™','ã”'=>'ã“ã‚™','ã–'=>'ã•ã‚™','ã˜'=>'ã—ã‚™','ãš'=>'ã™ã‚™','ãœ'=>'ã›ã‚™','ãž'=>'ãã‚™','ã '=>'ãŸã‚™','ã¢'=>'ã¡ã‚™','ã¥'=>'ã¤ã‚™','ã§'=>'ã¦ã‚™','ã©'=>'ã¨ã‚™','ã°'=>'ã¯ã‚™','ã±'=>'ã¯ã‚š','ã³'=>'ã²ã‚™','ã´'=>'ã²ã‚š','ã¶'=>'ãµã‚™','ã·'=>'ãµã‚š','ã¹'=>'ã¸ã‚™','ãº'=>'ã¸ã‚š','ã¼'=>'ã»ã‚™','ã½'=>'ã»ã‚š','ã‚”'=>'ã†ã‚™','ã‚›'=>' ã‚™','゜'=>' ゚','ゞ'=>'ã‚ã‚™','ゟ'=>'より','ガ'=>'ã‚«ã‚™','ã‚®'=>'ã‚­ã‚™','ã‚°'=>'グ','ゲ'=>'ゲ','ã‚´'=>'ゴ','ã‚¶'=>'ザ','ジ'=>'ã‚·ã‚™','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ã‚¿ã‚™','ヂ'=>'ãƒã‚™','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒ'=>'ãƒã‚™','パ'=>'ãƒã‚š','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ãƒ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ','ヿ'=>'コト','ㄱ'=>'á„€','ㄲ'=>'á„','ㄳ'=>'ᆪ','ã„´'=>'á„‚','ㄵ'=>'ᆬ','ã„¶'=>'ᆭ','ã„·'=>'ᄃ','ㄸ'=>'á„„','ㄹ'=>'á„…','ㄺ'=>'ᆰ','ã„»'=>'ᆱ','ㄼ'=>'ᆲ','ㄽ'=>'ᆳ','ㄾ'=>'ᆴ','ã„¿'=>'ᆵ','ã…€'=>'ᄚ','ã…'=>'ᄆ','ã…‚'=>'ᄇ','ã…ƒ'=>'ᄈ','ã…„'=>'á„¡','ã……'=>'ᄉ','ã…†'=>'ᄊ','ã…‡'=>'á„‹','ã…ˆ'=>'ᄌ','ã…‰'=>'á„','ã…Š'=>'ᄎ','ã…‹'=>'á„','ã…Œ'=>'á„','ã…'=>'á„‘','ã…Ž'=>'á„’','ã…'=>'á…¡','ã…'=>'á…¢','ã…‘'=>'á…£','ã…’'=>'á…¤','ã…“'=>'á…¥','ã…”'=>'á…¦','ã…•'=>'á…§','ã…–'=>'á…¨','ã…—'=>'á…©','ã…˜'=>'á…ª','ã…™'=>'á…«','ã…š'=>'á…¬','ã…›'=>'á…­','ã…œ'=>'á…®','ã…'=>'á…¯','ã…ž'=>'á…°','ã…Ÿ'=>'á…±','ã… '=>'á…²','ã…¡'=>'á…³','ã…¢'=>'á…´','ã…£'=>'á…µ','ã…¤'=>'á… ','ã…¥'=>'á„”','ã…¦'=>'á„•','ã…§'=>'ᇇ','ã…¨'=>'ᇈ','ã…©'=>'ᇌ','ã…ª'=>'ᇎ','ã…«'=>'ᇓ','ã…¬'=>'ᇗ','ã…­'=>'ᇙ','ã…®'=>'ᄜ','ã…¯'=>'á‡','ã…°'=>'ᇟ','ã…±'=>'á„','ã…²'=>'ᄞ','ã…³'=>'á„ ','ã…´'=>'á„¢','ã…µ'=>'á„£','ã…¶'=>'á„§','ã…·'=>'á„©','ã…¸'=>'á„«','ã…¹'=>'ᄬ','ã…º'=>'á„­','ã…»'=>'á„®','ã…¼'=>'ᄯ','ã…½'=>'ᄲ','ã…¾'=>'á„¶','ã…¿'=>'á…€','ㆀ'=>'á…‡','ã†'=>'á…Œ','ㆂ'=>'ᇱ','ㆃ'=>'ᇲ','ㆄ'=>'á…—','ㆅ'=>'á…˜','ㆆ'=>'á…™','ㆇ'=>'ᆄ','ㆈ'=>'ᆅ','ㆉ'=>'ᆈ','ㆊ'=>'ᆑ','ㆋ'=>'ᆒ','ㆌ'=>'ᆔ','ã†'=>'ᆞ','ㆎ'=>'ᆡ','㆒'=>'一','㆓'=>'二','㆔'=>'三','㆕'=>'å››','㆖'=>'上','㆗'=>'中','㆘'=>'下','㆙'=>'甲','㆚'=>'ä¹™','㆛'=>'丙','㆜'=>'ä¸','ã†'=>'天','㆞'=>'地','㆟'=>'人','㈀'=>'(á„€)','ãˆ'=>'(á„‚)','㈂'=>'(ᄃ)','㈃'=>'(á„…)','㈄'=>'(ᄆ)','㈅'=>'(ᄇ)','㈆'=>'(ᄉ)','㈇'=>'(á„‹)','㈈'=>'(ᄌ)','㈉'=>'(ᄎ)','㈊'=>'(á„)','㈋'=>'(á„)','㈌'=>'(á„‘)','ãˆ'=>'(á„’)','㈎'=>'(가)','ãˆ'=>'(á„‚á…¡)','ãˆ'=>'(다)','㈑'=>'(á„…á…¡)','㈒'=>'(마)','㈓'=>'(바)','㈔'=>'(사)','㈕'=>'(á„‹á…¡)','㈖'=>'(자)','㈗'=>'(차)','㈘'=>'(á„á…¡)','㈙'=>'(á„á…¡)','㈚'=>'(á„‘á…¡)','㈛'=>'(á„’á…¡)','㈜'=>'(주)','ãˆ'=>'(오전)','㈞'=>'(á„‹á…©á„’á…®)','㈠'=>'(一)','㈡'=>'(二)','㈢'=>'(三)','㈣'=>'(å››)','㈤'=>'(五)','㈥'=>'(å…­)','㈦'=>'(七)','㈧'=>'(å…«)','㈨'=>'(ä¹)','㈩'=>'(å)','㈪'=>'(月)','㈫'=>'(ç«)','㈬'=>'(æ°´)','㈭'=>'(木)','㈮'=>'(金)','㈯'=>'(土)','㈰'=>'(æ—¥)','㈱'=>'(æ ª)','㈲'=>'(有)','㈳'=>'(社)','㈴'=>'(å)','㈵'=>'(特)','㈶'=>'(財)','㈷'=>'(ç¥)','㈸'=>'(労)','㈹'=>'(代)','㈺'=>'(呼)','㈻'=>'(å­¦)','㈼'=>'(監)','㈽'=>'(ä¼)','㈾'=>'(資)','㈿'=>'(å”)','㉀'=>'(祭)','ã‰'=>'(休)','㉂'=>'(自)','㉃'=>'(至)','ã‰'=>'PTE','㉑'=>'21','㉒'=>'22','㉓'=>'23','㉔'=>'24','㉕'=>'25','㉖'=>'26','㉗'=>'27','㉘'=>'28','㉙'=>'29','㉚'=>'30','㉛'=>'31','㉜'=>'32','ã‰'=>'33','㉞'=>'34','㉟'=>'35','㉠'=>'á„€','㉡'=>'á„‚','㉢'=>'ᄃ','㉣'=>'á„…','㉤'=>'ᄆ','㉥'=>'ᄇ','㉦'=>'ᄉ','㉧'=>'á„‹','㉨'=>'ᄌ','㉩'=>'ᄎ','㉪'=>'á„','㉫'=>'á„','㉬'=>'á„‘','㉭'=>'á„’','㉮'=>'가','㉯'=>'á„‚á…¡','㉰'=>'다','㉱'=>'á„…á…¡','㉲'=>'마','㉳'=>'바','㉴'=>'사','㉵'=>'á„‹á…¡','㉶'=>'자','㉷'=>'차','㉸'=>'á„á…¡','㉹'=>'á„á…¡','㉺'=>'á„‘á…¡','㉻'=>'á„’á…¡','㉼'=>'참고','㉽'=>'주의','㉾'=>'á„‹á…®','㊀'=>'一','ãŠ'=>'二','㊂'=>'三','㊃'=>'å››','㊄'=>'五','㊅'=>'å…­','㊆'=>'七','㊇'=>'å…«','㊈'=>'ä¹','㊉'=>'å','㊊'=>'月','㊋'=>'ç«','㊌'=>'æ°´','ãŠ'=>'木','㊎'=>'金','ãŠ'=>'土','ãŠ'=>'æ—¥','㊑'=>'æ ª','㊒'=>'有','㊓'=>'社','㊔'=>'å','㊕'=>'特','㊖'=>'財','㊗'=>'ç¥','㊘'=>'労','㊙'=>'秘','㊚'=>'ç”·','㊛'=>'女','㊜'=>'é©','ãŠ'=>'優','㊞'=>'å°','㊟'=>'注','㊠'=>'é …','㊡'=>'休','㊢'=>'写','㊣'=>'æ­£','㊤'=>'上','㊥'=>'中','㊦'=>'下','㊧'=>'å·¦','㊨'=>'å³','㊩'=>'医','㊪'=>'å®—','㊫'=>'å­¦','㊬'=>'監','㊭'=>'ä¼','㊮'=>'資','㊯'=>'å”','㊰'=>'夜','㊱'=>'36','㊲'=>'37','㊳'=>'38','㊴'=>'39','㊵'=>'40','㊶'=>'41','㊷'=>'42','㊸'=>'43','㊹'=>'44','㊺'=>'45','㊻'=>'46','㊼'=>'47','㊽'=>'48','㊾'=>'49','㊿'=>'50','ã‹€'=>'1月','ã‹'=>'2月','ã‹‚'=>'3月','㋃'=>'4月','ã‹„'=>'5月','ã‹…'=>'6月','㋆'=>'7月','㋇'=>'8月','㋈'=>'9月','㋉'=>'10月','㋊'=>'11月','ã‹‹'=>'12月','㋌'=>'Hg','ã‹'=>'erg','㋎'=>'eV','ã‹'=>'LTD','ã‹'=>'ã‚¢','ã‹‘'=>'イ','ã‹’'=>'ウ','ã‹“'=>'エ','ã‹”'=>'オ','ã‹•'=>'ã‚«','ã‹–'=>'ã‚­','ã‹—'=>'ク','㋘'=>'ケ','ã‹™'=>'コ','㋚'=>'サ','ã‹›'=>'ã‚·','㋜'=>'ス','ã‹'=>'ã‚»','㋞'=>'ソ','㋟'=>'ã‚¿','ã‹ '=>'ãƒ','ã‹¡'=>'ツ','ã‹¢'=>'テ','ã‹£'=>'ト','㋤'=>'ナ','ã‹¥'=>'ニ','㋦'=>'ヌ','ã‹§'=>'ãƒ','㋨'=>'ノ','ã‹©'=>'ãƒ','㋪'=>'ヒ','ã‹«'=>'フ','㋬'=>'ヘ','ã‹­'=>'ホ','ã‹®'=>'マ','㋯'=>'ミ','ã‹°'=>'ム','㋱'=>'メ','㋲'=>'モ','㋳'=>'ヤ','ã‹´'=>'ユ','㋵'=>'ヨ','ã‹¶'=>'ラ','ã‹·'=>'リ','㋸'=>'ル','㋹'=>'レ','㋺'=>'ロ','ã‹»'=>'ワ','㋼'=>'ヰ','㋽'=>'ヱ','㋾'=>'ヲ','㌀'=>'ã‚¢ãƒã‚šãƒ¼ãƒˆ','ãŒ'=>'アルファ','㌂'=>'アンペア','㌃'=>'アール','㌄'=>'イニング','㌅'=>'インãƒ','㌆'=>'ウォン','㌇'=>'エスクード','㌈'=>'エーカー','㌉'=>'オンス','㌊'=>'オーム','㌋'=>'カイリ','㌌'=>'カラット','ãŒ'=>'カロリー','㌎'=>'ガロン','ãŒ'=>'ガンマ','ãŒ'=>'ギガ','㌑'=>'ギニー','㌒'=>'キュリー','㌓'=>'ギルダー','㌔'=>'キロ','㌕'=>'キログラム','㌖'=>'キロメートル','㌗'=>'キロワット','㌘'=>'グラム','㌙'=>'グラムトン','㌚'=>'クルゼイロ','㌛'=>'クローãƒ','㌜'=>'ケース','ãŒ'=>'コルナ','㌞'=>'コーポ','㌟'=>'サイクル','㌠'=>'サンãƒãƒ¼ãƒ ','㌡'=>'シリング','㌢'=>'センãƒ','㌣'=>'セント','㌤'=>'ダース','㌥'=>'デシ','㌦'=>'ドル','㌧'=>'トン','㌨'=>'ナノ','㌩'=>'ノット','㌪'=>'ãƒã‚¤ãƒ„','㌫'=>'ãƒã‚šãƒ¼ã‚»ãƒ³ãƒˆ','㌬'=>'ãƒã‚šãƒ¼ãƒ„','㌭'=>'ãƒã‚™ãƒ¼ãƒ¬ãƒ«','㌮'=>'ピアストル','㌯'=>'ピクル','㌰'=>'ピコ','㌱'=>'ビル','㌲'=>'ファラッド','㌳'=>'フィート','㌴'=>'ブッシェル','㌵'=>'フラン','㌶'=>'ヘクタール','㌷'=>'ペソ','㌸'=>'ペニヒ','㌹'=>'ヘルツ','㌺'=>'ペンス','㌻'=>'ページ','㌼'=>'ベータ','㌽'=>'ポイント','㌾'=>'ボルト','㌿'=>'ホン','ã€'=>'ポンド','ã'=>'ホール','ã‚'=>'ホーン','ãƒ'=>'マイクロ','ã„'=>'マイル','ã…'=>'マッãƒ','ã†'=>'マルク','ã‡'=>'マンション','ãˆ'=>'ミクロン','ã‰'=>'ミリ','ãŠ'=>'ミリãƒã‚™ãƒ¼ãƒ«','ã‹'=>'メガ','ãŒ'=>'メガトン','ã'=>'メートル','ãŽ'=>'ヤード','ã'=>'ヤール','ã'=>'ユアン','ã‘'=>'リットル','ã’'=>'リラ','ã“'=>'ルピー','ã”'=>'ルーブル','ã•'=>'レム','ã–'=>'レントゲン','ã—'=>'ワット','ã˜'=>'0点','ã™'=>'1点','ãš'=>'2点','ã›'=>'3点','ãœ'=>'4点','ã'=>'5点','ãž'=>'6点','ãŸ'=>'7点','ã '=>'8点','ã¡'=>'9点','ã¢'=>'10点','ã£'=>'11点','ã¤'=>'12点','ã¥'=>'13点','ã¦'=>'14点','ã§'=>'15点','ã¨'=>'16点','ã©'=>'17点','ãª'=>'18点','ã«'=>'19点','ã¬'=>'20点','ã­'=>'21点','ã®'=>'22点','ã¯'=>'23点','ã°'=>'24点','ã±'=>'hPa','ã²'=>'da','ã³'=>'AU','ã´'=>'bar','ãµ'=>'oV','ã¶'=>'pc','ã·'=>'dm','ã¸'=>'dm2','ã¹'=>'dm3','ãº'=>'IU','ã»'=>'å¹³æˆ','ã¼'=>'昭和','ã½'=>'大正','ã¾'=>'明治','ã¿'=>'æ ªå¼ä¼šç¤¾','㎀'=>'pA','ãŽ'=>'nA','㎂'=>'μA','㎃'=>'mA','㎄'=>'kA','㎅'=>'KB','㎆'=>'MB','㎇'=>'GB','㎈'=>'cal','㎉'=>'kcal','㎊'=>'pF','㎋'=>'nF','㎌'=>'μF','ãŽ'=>'μg','㎎'=>'mg','ãŽ'=>'kg','ãŽ'=>'Hz','㎑'=>'kHz','㎒'=>'MHz','㎓'=>'GHz','㎔'=>'THz','㎕'=>'μl','㎖'=>'ml','㎗'=>'dl','㎘'=>'kl','㎙'=>'fm','㎚'=>'nm','㎛'=>'μm','㎜'=>'mm','ãŽ'=>'cm','㎞'=>'km','㎟'=>'mm2','㎠'=>'cm2','㎡'=>'m2','㎢'=>'km2','㎣'=>'mm3','㎤'=>'cm3','㎥'=>'m3','㎦'=>'km3','㎧'=>'m∕s','㎨'=>'m∕s2','㎩'=>'Pa','㎪'=>'kPa','㎫'=>'MPa','㎬'=>'GPa','㎭'=>'rad','㎮'=>'rad∕s','㎯'=>'rad∕s2','㎰'=>'ps','㎱'=>'ns','㎲'=>'μs','㎳'=>'ms','㎴'=>'pV','㎵'=>'nV','㎶'=>'μV','㎷'=>'mV','㎸'=>'kV','㎹'=>'MV','㎺'=>'pW','㎻'=>'nW','㎼'=>'μW','㎽'=>'mW','㎾'=>'kW','㎿'=>'MW','ã€'=>'kΩ','ã'=>'MΩ','ã‚'=>'a.m.','ãƒ'=>'Bq','ã„'=>'cc','ã…'=>'cd','ã†'=>'C∕kg','ã‡'=>'Co.','ãˆ'=>'dB','ã‰'=>'Gy','ãŠ'=>'ha','ã‹'=>'HP','ãŒ'=>'in','ã'=>'KK','ãŽ'=>'KM','ã'=>'kt','ã'=>'lm','ã‘'=>'ln','ã’'=>'log','ã“'=>'lx','ã”'=>'mb','ã•'=>'mil','ã–'=>'mol','ã—'=>'PH','ã˜'=>'p.m.','ã™'=>'PPM','ãš'=>'PR','ã›'=>'sr','ãœ'=>'Sv','ã'=>'Wb','ãž'=>'V∕m','ãŸ'=>'A∕m','ã '=>'1æ—¥','ã¡'=>'2æ—¥','ã¢'=>'3æ—¥','ã£'=>'4æ—¥','ã¤'=>'5æ—¥','ã¥'=>'6æ—¥','ã¦'=>'7æ—¥','ã§'=>'8æ—¥','ã¨'=>'9æ—¥','ã©'=>'10æ—¥','ãª'=>'11æ—¥','ã«'=>'12æ—¥','ã¬'=>'13æ—¥','ã­'=>'14æ—¥','ã®'=>'15æ—¥','ã¯'=>'16æ—¥','ã°'=>'17æ—¥','ã±'=>'18æ—¥','ã²'=>'19æ—¥','ã³'=>'20æ—¥','ã´'=>'21æ—¥','ãµ'=>'22æ—¥','ã¶'=>'23æ—¥','ã·'=>'24æ—¥','ã¸'=>'25æ—¥','ã¹'=>'26æ—¥','ãº'=>'27æ—¥','ã»'=>'28æ—¥','ã¼'=>'29æ—¥','ã½'=>'30æ—¥','ã¾'=>'31æ—¥','ã¿'=>'gal','豈'=>'豈','ï¤'=>'æ›´','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'å¥','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'å–‡','奈'=>'奈','ï¤'=>'懶','癩'=>'癩','ï¤'=>'ç¾…','ï¤'=>'蘿','螺'=>'螺','裸'=>'裸','邏'=>'é‚','樂'=>'樂','洛'=>'æ´›','烙'=>'烙','珞'=>'çž','落'=>'è½','酪'=>'é…ª','駱'=>'é§±','亂'=>'亂','卵'=>'åµ','ï¤'=>'欄','爛'=>'爛','蘭'=>'蘭','鸞'=>'鸞','嵐'=>'åµ','濫'=>'æ¿«','藍'=>'è—','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'è Ÿ','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','來'=>'來','冷'=>'冷','勞'=>'勞','擄'=>'æ“„','櫓'=>'æ«“','爐'=>'çˆ','盧'=>'ç›§','老'=>'è€','蘆'=>'蘆','虜'=>'虜','路'=>'è·¯','露'=>'露','魯'=>'é­¯','鷺'=>'é·º','碌'=>'碌','祿'=>'祿','綠'=>'ç¶ ','菉'=>'è‰','錄'=>'錄','鹿'=>'鹿','ï¥'=>'è«–','壟'=>'壟','弄'=>'弄','籠'=>'ç± ','聾'=>'è¾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'é›·','壘'=>'壘','屢'=>'å±¢','樓'=>'樓','ï¥'=>'æ·š','漏'=>'æ¼','ï¥'=>'ç´¯','ï¥'=>'縷','陋'=>'陋','勒'=>'å‹’','肋'=>'è‚‹','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'ç¶¾','菱'=>'è±','陵'=>'陵','讀'=>'讀','拏'=>'æ‹','樂'=>'樂','ï¥'=>'諾','丹'=>'丹','寧'=>'寧','怒'=>'怒','率'=>'率','異'=>'ç•°','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'ä¸','泌'=>'泌','數'=>'數','索'=>'ç´¢','參'=>'åƒ','塞'=>'塞','省'=>'çœ','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'è¾°','沈'=>'沈','拾'=>'拾','若'=>'è‹¥','掠'=>'掠','略'=>'ç•¥','亮'=>'亮','兩'=>'å…©','凉'=>'凉','梁'=>'æ¢','糧'=>'ç³§','良'=>'良','諒'=>'è«’','量'=>'é‡','勵'=>'勵','呂'=>'å‘‚','ï¦'=>'女','廬'=>'廬','旅'=>'æ—…','濾'=>'濾','礪'=>'礪','閭'=>'é–­','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'æ­·','ï¦'=>'è½¢','年'=>'å¹´','ï¦'=>'æ†','ï¦'=>'戀','撚'=>'æ’š','漣'=>'æ¼£','煉'=>'ç…‰','璉'=>'ç’‰','秊'=>'ç§Š','練'=>'ç·´','聯'=>'è¯','輦'=>'輦','蓮'=>'è“®','連'=>'連','鍊'=>'éŠ','列'=>'列','ï¦'=>'劣','咽'=>'å’½','烈'=>'烈','裂'=>'裂','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'æ»','殮'=>'æ®®','簾'=>'ç°¾','獵'=>'çµ','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','玲'=>'玲','瑩'=>'ç‘©','羚'=>'羚','聆'=>'è†','鈴'=>'鈴','零'=>'é›¶','靈'=>'éˆ','領'=>'é ˜','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'å°¿','料'=>'æ–™','樂'=>'樂','ï§€'=>'燎','ï§'=>'療','ï§‚'=>'蓼','遼'=>'é¼','ï§„'=>'é¾','ï§…'=>'暈','阮'=>'阮','劉'=>'劉','杻'=>'æ»','柳'=>'柳','ï§Š'=>'æµ','ï§‹'=>'溜','ï§Œ'=>'ç‰','ï§'=>'ç•™','ï§Ž'=>'ç¡«','ï§'=>'ç´','ï§'=>'類','ï§‘'=>'å…­','ï§’'=>'戮','ï§“'=>'陸','ï§”'=>'倫','ï§•'=>'å´™','ï§–'=>'æ·ª','ï§—'=>'輪','律'=>'律','ï§™'=>'æ…„','ï§š'=>'æ —','ï§›'=>'率','ï§œ'=>'隆','ï§'=>'利','ï§ž'=>'å','ï§Ÿ'=>'å±¥','ï§ '=>'易','ï§¡'=>'æŽ','ï§¢'=>'梨','ï§£'=>'æ³¥','理'=>'ç†','ï§¥'=>'ç—¢','罹'=>'ç½¹','ï§§'=>'è£','裡'=>'裡','ï§©'=>'里','離'=>'離','ï§«'=>'匿','溺'=>'溺','ï§­'=>'å','ï§®'=>'ç‡','璘'=>'ç’˜','ï§°'=>'è—º','ï§±'=>'隣','ï§²'=>'é±—','ï§³'=>'麟','ï§´'=>'æž—','ï§µ'=>'æ·‹','ï§¶'=>'臨','ï§·'=>'ç«‹','笠'=>'笠','ï§¹'=>'ç²’','狀'=>'ç‹€','ï§»'=>'ç‚™','ï§¼'=>'è­˜','ï§½'=>'什','ï§¾'=>'茶','ï§¿'=>'刺','切'=>'切','ï¨'=>'度','拓'=>'æ‹“','糖'=>'ç³–','宅'=>'å®…','洞'=>'æ´ž','暴'=>'æš´','輻'=>'è¼»','行'=>'行','降'=>'é™','見'=>'見','廓'=>'廓','兀'=>'å…€','ï¨'=>'å—€','ï¨'=>'塚','晴'=>'æ™´','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'ç¦','靖'=>'é–','ï¨'=>'ç²¾','羽'=>'ç¾½','蘒'=>'蘒','諸'=>'諸','逸'=>'逸','都'=>'都','飯'=>'飯','飼'=>'飼','館'=>'館','鶴'=>'é¶´','侮'=>'ä¾®','僧'=>'僧','免'=>'å…','勉'=>'勉','勤'=>'勤','卑'=>'å‘','喝'=>'å–','嘆'=>'嘆','器'=>'器','塀'=>'å¡€','墨'=>'墨','層'=>'層','屮'=>'å±®','悔'=>'æ‚”','慨'=>'æ…¨','憎'=>'憎','ï©€'=>'懲','ï©'=>'æ•','ï©‚'=>'æ—¢','暑'=>'æš‘','ï©„'=>'梅','ï©…'=>'æµ·','渚'=>'渚','漢'=>'æ¼¢','煮'=>'ç…®','爫'=>'爫','琢'=>'ç¢','ï©‹'=>'碑','社'=>'社','ï©'=>'祉','祈'=>'祈','ï©'=>'ç¥','ï©'=>'祖','ï©‘'=>'ç¥','ï©’'=>'ç¦','ï©“'=>'禎','ï©”'=>'ç©€','ï©•'=>'çª','ï©–'=>'節','ï©—'=>'ç·´','縉'=>'縉','ï©™'=>'ç¹','署'=>'ç½²','ï©›'=>'者','臭'=>'臭','ï©'=>'艹','艹'=>'艹','著'=>'è‘—','ï© '=>'è¤','ï©¡'=>'視','ï©¢'=>'è¬','ï©£'=>'謹','賓'=>'賓','ï©¥'=>'è´ˆ','辶'=>'è¾¶','ï©§'=>'逸','難'=>'難','ï©©'=>'響','頻'=>'é »','ï©°'=>'並','况'=>'况','全'=>'å…¨','侀'=>'ä¾€','ï©´'=>'å……','冀'=>'冀','ï©¶'=>'勇','ï©·'=>'勺','喝'=>'å–','啕'=>'å••','喙'=>'å–™','ï©»'=>'å—¢','塚'=>'塚','墳'=>'墳','奄'=>'奄','ï©¿'=>'奔','婢'=>'å©¢','ïª'=>'嬨','廒'=>'å»’','廙'=>'å»™','彩'=>'彩','徭'=>'å¾­','惘'=>'惘','慎'=>'æ…Ž','愈'=>'愈','憎'=>'憎','慠'=>'æ… ','懲'=>'懲','戴'=>'戴','ïª'=>'æ„','搜'=>'æœ','ïª'=>'æ‘’','ïª'=>'æ•–','晴'=>'æ™´','朗'=>'朗','望'=>'望','杖'=>'æ–','歹'=>'æ­¹','殺'=>'殺','流'=>'æµ','滛'=>'æ»›','滋'=>'滋','漢'=>'æ¼¢','瀞'=>'瀞','煮'=>'ç…®','ïª'=>'çž§','爵'=>'爵','犯'=>'犯','猪'=>'猪','瑱'=>'瑱','甆'=>'甆','画'=>'ç”»','瘝'=>'ç˜','瘟'=>'瘟','益'=>'益','盛'=>'ç››','直'=>'ç›´','睊'=>'çŠ','着'=>'ç€','磌'=>'磌','窱'=>'窱','節'=>'節','类'=>'ç±»','絛'=>'çµ›','練'=>'ç·´','缾'=>'ç¼¾','者'=>'者','荒'=>'è’','華'=>'è¯','蝹'=>'è¹','襁'=>'è¥','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'è«‹','謁'=>'è¬','諾'=>'諾','諭'=>'è«­','謹'=>'謹','ï«€'=>'變','ï«'=>'è´ˆ','ï«‚'=>'輸','遲'=>'é²','ï«„'=>'醙','ï«…'=>'鉶','陼'=>'陼','難'=>'難','靖'=>'é–','韛'=>'韛','響'=>'響','ï«‹'=>'é ‹','頻'=>'é »','ï«'=>'鬒','龜'=>'龜','ï«'=>'𢡊','ï«'=>'𢡄','ï«‘'=>'ð£•','ï«’'=>'ã®','ï«“'=>'䀘','ï«”'=>'䀹','ï«•'=>'𥉉','ï«–'=>'ð¥³','ï«—'=>'𧻓','齃'=>'齃','ï«™'=>'龎','ff'=>'ff','ï¬'=>'fi','fl'=>'fl','ffi'=>'ffi','ffl'=>'ffl','ſt'=>'st','st'=>'st','ﬓ'=>'Õ´Õ¶','ﬔ'=>'Õ´Õ¥','ﬕ'=>'Õ´Õ«','ﬖ'=>'Õ¾Õ¶','ﬗ'=>'Õ´Õ­','ï¬'=>'×™Ö´','ײַ'=>'ײַ','ﬠ'=>'×¢','ﬡ'=>'×','ﬢ'=>'ד','ﬣ'=>'×”','ﬤ'=>'×›','ﬥ'=>'ל','ﬦ'=>'×','ﬧ'=>'ר','ﬨ'=>'ת','﬩'=>'+','שׁ'=>'ש×','שׂ'=>'שׂ','שּׁ'=>'שּ×','שּׂ'=>'שּׂ','אַ'=>'×Ö·','אָ'=>'×Ö¸','אּ'=>'×Ö¼','בּ'=>'בּ','גּ'=>'×’Ö¼','דּ'=>'דּ','הּ'=>'×”Ö¼','וּ'=>'וּ','זּ'=>'×–Ö¼','טּ'=>'טּ','יּ'=>'×™Ö¼','ךּ'=>'ךּ','כּ'=>'×›Ö¼','לּ'=>'לּ','מּ'=>'מּ','ï­€'=>'× Ö¼','ï­'=>'סּ','ï­ƒ'=>'×£Ö¼','ï­„'=>'פּ','ï­†'=>'צּ','ï­‡'=>'×§Ö¼','ï­ˆ'=>'רּ','ï­‰'=>'שּ','ï­Š'=>'תּ','ï­‹'=>'וֹ','ï­Œ'=>'בֿ','ï­'=>'×›Ö¿','ï­Ž'=>'פֿ','ï­'=>'×ל','ï­'=>'Ù±','ï­‘'=>'Ù±','ï­’'=>'Ù»','ï­“'=>'Ù»','ï­”'=>'Ù»','ï­•'=>'Ù»','ï­–'=>'Ù¾','ï­—'=>'Ù¾','ï­˜'=>'Ù¾','ï­™'=>'Ù¾','ï­š'=>'Ú€','ï­›'=>'Ú€','ï­œ'=>'Ú€','ï­'=>'Ú€','ï­ž'=>'Ùº','ï­Ÿ'=>'Ùº','ï­ '=>'Ùº','ï­¡'=>'Ùº','ï­¢'=>'Ù¿','ï­£'=>'Ù¿','ï­¤'=>'Ù¿','ï­¥'=>'Ù¿','ï­¦'=>'Ù¹','ï­§'=>'Ù¹','ï­¨'=>'Ù¹','ï­©'=>'Ù¹','ï­ª'=>'Ú¤','ï­«'=>'Ú¤','ï­¬'=>'Ú¤','ï­­'=>'Ú¤','ï­®'=>'Ú¦','ï­¯'=>'Ú¦','ï­°'=>'Ú¦','ï­±'=>'Ú¦','ï­²'=>'Ú„','ï­³'=>'Ú„','ï­´'=>'Ú„','ï­µ'=>'Ú„','ï­¶'=>'Úƒ','ï­·'=>'Úƒ','ï­¸'=>'Úƒ','ï­¹'=>'Úƒ','ï­º'=>'Ú†','ï­»'=>'Ú†','ï­¼'=>'Ú†','ï­½'=>'Ú†','ï­¾'=>'Ú‡','ï­¿'=>'Ú‡','ﮀ'=>'Ú‡','ï®'=>'Ú‡','ﮂ'=>'Ú','ﮃ'=>'Ú','ﮄ'=>'ÚŒ','ï®…'=>'ÚŒ','ﮆ'=>'ÚŽ','ﮇ'=>'ÚŽ','ﮈ'=>'Úˆ','ﮉ'=>'Úˆ','ﮊ'=>'Ú˜','ﮋ'=>'Ú˜','ﮌ'=>'Ú‘','ï®'=>'Ú‘','ﮎ'=>'Ú©','ï®'=>'Ú©','ï®'=>'Ú©','ﮑ'=>'Ú©','ï®’'=>'Ú¯','ﮓ'=>'Ú¯','ï®”'=>'Ú¯','ﮕ'=>'Ú¯','ï®–'=>'Ú³','ï®—'=>'Ú³','ﮘ'=>'Ú³','ï®™'=>'Ú³','ﮚ'=>'Ú±','ï®›'=>'Ú±','ﮜ'=>'Ú±','ï®'=>'Ú±','ﮞ'=>'Úº','ﮟ'=>'Úº','ï® '=>'Ú»','ﮡ'=>'Ú»','ﮢ'=>'Ú»','ﮣ'=>'Ú»','ﮤ'=>'Û•Ù”','ﮥ'=>'Û•Ù”','ﮦ'=>'Û','ï®§'=>'Û','ﮨ'=>'Û','ﮩ'=>'Û','ﮪ'=>'Ú¾','ﮫ'=>'Ú¾','ﮬ'=>'Ú¾','ï®­'=>'Ú¾','ï®®'=>'Û’','ﮯ'=>'Û’','ï®°'=>'Û’Ù”','ï®±'=>'Û’Ù”','ﯓ'=>'Ú­','ﯔ'=>'Ú­','ﯕ'=>'Ú­','ﯖ'=>'Ú­','ﯗ'=>'Û‡','ﯘ'=>'Û‡','ﯙ'=>'Û†','ﯚ'=>'Û†','ﯛ'=>'Ûˆ','ﯜ'=>'Ûˆ','ï¯'=>'Û‡Ù´','ﯞ'=>'Û‹','ﯟ'=>'Û‹','ﯠ'=>'Û…','ﯡ'=>'Û…','ﯢ'=>'Û‰','ﯣ'=>'Û‰','ﯤ'=>'Û','ﯥ'=>'Û','ﯦ'=>'Û','ﯧ'=>'Û','ﯨ'=>'Ù‰','ﯩ'=>'Ù‰','ﯪ'=>'ئا','ﯫ'=>'ئا','ﯬ'=>'ÙŠÙ”Û•','ﯭ'=>'ÙŠÙ”Û•','ﯮ'=>'ÙŠÙ”Ùˆ','ﯯ'=>'ÙŠÙ”Ùˆ','ﯰ'=>'ÙŠÙ”Û‡','ﯱ'=>'ÙŠÙ”Û‡','ﯲ'=>'ÙŠÙ”Û†','ﯳ'=>'ÙŠÙ”Û†','ﯴ'=>'ÙŠÙ”Ûˆ','ﯵ'=>'ÙŠÙ”Ûˆ','ﯶ'=>'ÙŠÙ”Û','ﯷ'=>'ÙŠÙ”Û','ﯸ'=>'ÙŠÙ”Û','ﯹ'=>'ÙŠÙ”Ù‰','ﯺ'=>'ÙŠÙ”Ù‰','ﯻ'=>'ÙŠÙ”Ù‰','ﯼ'=>'ÛŒ','ﯽ'=>'ÛŒ','ﯾ'=>'ÛŒ','ﯿ'=>'ÛŒ','ï°€'=>'ئج','ï°'=>'ئح','ï°‚'=>'ÙŠÙ”Ù…','ï°ƒ'=>'ÙŠÙ”Ù‰','ï°„'=>'ÙŠÙ”ÙŠ','ï°…'=>'بج','ï°†'=>'بح','ï°‡'=>'بخ','ï°ˆ'=>'بم','ï°‰'=>'بى','ï°Š'=>'بي','ï°‹'=>'تج','ï°Œ'=>'تح','ï°'=>'تخ','ï°Ž'=>'تم','ï°'=>'تى','ï°'=>'تي','ï°‘'=>'ثج','ï°’'=>'ثم','ï°“'=>'ثى','ï°”'=>'ثي','ï°•'=>'جح','ï°–'=>'جم','ï°—'=>'حج','ï°˜'=>'حم','ï°™'=>'خج','ï°š'=>'خح','ï°›'=>'خم','ï°œ'=>'سج','ï°'=>'سح','ï°ž'=>'سخ','ï°Ÿ'=>'سم','ï° '=>'صح','ï°¡'=>'صم','ï°¢'=>'ضج','ï°£'=>'ضح','ï°¤'=>'ضخ','ï°¥'=>'ضم','ï°¦'=>'طح','ï°§'=>'طم','ï°¨'=>'ظم','ï°©'=>'عج','ï°ª'=>'عم','ï°«'=>'غج','ï°¬'=>'غم','ï°­'=>'ÙØ¬','ï°®'=>'ÙØ­','ï°¯'=>'ÙØ®','ï°°'=>'ÙÙ…','ï°±'=>'ÙÙ‰','ï°²'=>'ÙÙŠ','ï°³'=>'قح','ï°´'=>'قم','ï°µ'=>'قى','ï°¶'=>'قي','ï°·'=>'كا','ï°¸'=>'كج','ï°¹'=>'كح','ï°º'=>'كخ','ï°»'=>'كل','ï°¼'=>'كم','ï°½'=>'كى','ï°¾'=>'كي','ï°¿'=>'لج','ï±€'=>'لح','ï±'=>'لخ','ﱂ'=>'لم','ﱃ'=>'لى','ﱄ'=>'لي','ï±…'=>'مج','ﱆ'=>'مح','ﱇ'=>'مخ','ﱈ'=>'مم','ﱉ'=>'مى','ﱊ'=>'مي','ﱋ'=>'نج','ﱌ'=>'نح','ï±'=>'نخ','ﱎ'=>'نم','ï±'=>'نى','ï±'=>'ني','ﱑ'=>'هج','ï±’'=>'هم','ﱓ'=>'هى','ï±”'=>'هي','ﱕ'=>'يج','ï±–'=>'يح','ï±—'=>'يخ','ﱘ'=>'يم','ï±™'=>'يى','ﱚ'=>'يي','ï±›'=>'ذٰ','ﱜ'=>'رٰ','ï±'=>'ىٰ','ﱞ'=>' ٌّ','ﱟ'=>' ÙÙ‘','ï± '=>' ÙŽÙ‘','ﱡ'=>' ÙÙ‘','ï±¢'=>' ÙÙ‘','ï±£'=>' ّٰ','ﱤ'=>'ئر','ï±¥'=>'ئز','ﱦ'=>'ÙŠÙ”Ù…','ï±§'=>'ÙŠÙ”Ù†','ﱨ'=>'ÙŠÙ”Ù‰','ﱩ'=>'ÙŠÙ”ÙŠ','ﱪ'=>'بر','ﱫ'=>'بز','ﱬ'=>'بم','ï±­'=>'بن','ï±®'=>'بى','ﱯ'=>'بي','ï±°'=>'تر','ï±±'=>'تز','ï±²'=>'تم','ï±³'=>'تن','ï±´'=>'تى','ï±µ'=>'تي','ï±¶'=>'ثر','ï±·'=>'ثز','ﱸ'=>'ثم','ï±¹'=>'ثن','ﱺ'=>'ثى','ï±»'=>'ثي','ï±¼'=>'ÙÙ‰','ï±½'=>'ÙÙŠ','ï±¾'=>'قى','ﱿ'=>'قي','ï²€'=>'كا','ï²'=>'كل','ﲂ'=>'كم','ﲃ'=>'كى','ﲄ'=>'كي','ï²…'=>'لم','ﲆ'=>'لى','ﲇ'=>'لي','ﲈ'=>'ما','ﲉ'=>'مم','ﲊ'=>'نر','ﲋ'=>'نز','ﲌ'=>'نم','ï²'=>'نن','ﲎ'=>'نى','ï²'=>'ني','ï²'=>'ىٰ','ﲑ'=>'ير','ï²’'=>'يز','ﲓ'=>'يم','ï²”'=>'ين','ﲕ'=>'يى','ï²–'=>'يي','ï²—'=>'ئج','ﲘ'=>'ئح','ï²™'=>'ئخ','ﲚ'=>'ÙŠÙ”Ù…','ï²›'=>'ÙŠÙ”Ù‡','ﲜ'=>'بج','ï²'=>'بح','ﲞ'=>'بخ','ﲟ'=>'بم','ï² '=>'به','ﲡ'=>'تج','ï²¢'=>'تح','ï²£'=>'تخ','ﲤ'=>'تم','ï²¥'=>'ته','ﲦ'=>'ثم','ï²§'=>'جح','ﲨ'=>'جم','ﲩ'=>'حج','ﲪ'=>'حم','ﲫ'=>'خج','ﲬ'=>'خم','ï²­'=>'سج','ï²®'=>'سح','ﲯ'=>'سخ','ï²°'=>'سم','ï²±'=>'صح','ï²²'=>'صخ','ï²³'=>'صم','ï²´'=>'ضج','ï²µ'=>'ضح','ï²¶'=>'ضخ','ï²·'=>'ضم','ﲸ'=>'طح','ï²¹'=>'ظم','ﲺ'=>'عج','ï²»'=>'عم','ï²¼'=>'غج','ï²½'=>'غم','ï²¾'=>'ÙØ¬','ﲿ'=>'ÙØ­','ï³€'=>'ÙØ®','ï³'=>'ÙÙ…','ﳂ'=>'قح','ﳃ'=>'قم','ﳄ'=>'كج','ï³…'=>'كح','ﳆ'=>'كخ','ﳇ'=>'كل','ﳈ'=>'كم','ﳉ'=>'لج','ﳊ'=>'لح','ﳋ'=>'لخ','ﳌ'=>'لم','ï³'=>'له','ﳎ'=>'مج','ï³'=>'مح','ï³'=>'مخ','ﳑ'=>'مم','ï³’'=>'نج','ﳓ'=>'نح','ï³”'=>'نخ','ﳕ'=>'نم','ï³–'=>'نه','ï³—'=>'هج','ﳘ'=>'هم','ï³™'=>'هٰ','ﳚ'=>'يج','ï³›'=>'يح','ﳜ'=>'يخ','ï³'=>'يم','ﳞ'=>'يه','ﳟ'=>'ÙŠÙ”Ù…','ï³ '=>'ÙŠÙ”Ù‡','ﳡ'=>'بم','ï³¢'=>'به','ï³£'=>'تم','ﳤ'=>'ته','ï³¥'=>'ثم','ﳦ'=>'ثه','ï³§'=>'سم','ﳨ'=>'سه','ﳩ'=>'شم','ﳪ'=>'شه','ﳫ'=>'كل','ﳬ'=>'كم','ï³­'=>'لم','ï³®'=>'نم','ﳯ'=>'نه','ï³°'=>'يم','ï³±'=>'يه','ï³²'=>'Ù€ÙŽÙ‘','ï³³'=>'Ù€ÙÙ‘','ï³´'=>'Ù€ÙÙ‘','ï³µ'=>'طى','ï³¶'=>'طي','ï³·'=>'عى','ﳸ'=>'عي','ï³¹'=>'غى','ﳺ'=>'غي','ï³»'=>'سى','ï³¼'=>'سي','ï³½'=>'شى','ï³¾'=>'شي','ﳿ'=>'حى','ï´€'=>'حي','ï´'=>'جى','ï´‚'=>'جي','ï´ƒ'=>'خى','ï´„'=>'خي','ï´…'=>'صى','ï´†'=>'صي','ï´‡'=>'ضى','ï´ˆ'=>'ضي','ï´‰'=>'شج','ï´Š'=>'شح','ï´‹'=>'شخ','ï´Œ'=>'شم','ï´'=>'شر','ï´Ž'=>'سر','ï´'=>'صر','ï´'=>'ضر','ï´‘'=>'طى','ï´’'=>'طي','ï´“'=>'عى','ï´”'=>'عي','ï´•'=>'غى','ï´–'=>'غي','ï´—'=>'سى','ï´˜'=>'سي','ï´™'=>'شى','ï´š'=>'شي','ï´›'=>'حى','ï´œ'=>'حي','ï´'=>'جى','ï´ž'=>'جي','ï´Ÿ'=>'خى','ï´ '=>'خي','ï´¡'=>'صى','ï´¢'=>'صي','ï´£'=>'ضى','ï´¤'=>'ضي','ï´¥'=>'شج','ï´¦'=>'شح','ï´§'=>'شخ','ï´¨'=>'شم','ï´©'=>'شر','ï´ª'=>'سر','ï´«'=>'صر','ï´¬'=>'ضر','ï´­'=>'شج','ï´®'=>'شح','ï´¯'=>'شخ','ï´°'=>'شم','ï´±'=>'سه','ï´²'=>'شه','ï´³'=>'طم','ï´´'=>'سج','ï´µ'=>'سح','ï´¶'=>'سخ','ï´·'=>'شج','ï´¸'=>'شح','ï´¹'=>'شخ','ï´º'=>'طم','ï´»'=>'ظم','ï´¼'=>'اً','ï´½'=>'اً','ïµ'=>'تجم','ﵑ'=>'تحج','ïµ’'=>'تحج','ﵓ'=>'تحم','ïµ”'=>'تخم','ﵕ'=>'تمج','ïµ–'=>'تمح','ïµ—'=>'تمخ','ﵘ'=>'جمح','ïµ™'=>'جمح','ﵚ'=>'حمي','ïµ›'=>'حمى','ﵜ'=>'سحج','ïµ'=>'سجح','ﵞ'=>'سجى','ﵟ'=>'سمح','ïµ '=>'سمح','ﵡ'=>'سمج','ïµ¢'=>'سمم','ïµ£'=>'سمم','ﵤ'=>'صحح','ïµ¥'=>'صحح','ﵦ'=>'صمم','ïµ§'=>'شحم','ﵨ'=>'شحم','ﵩ'=>'شجي','ﵪ'=>'شمخ','ﵫ'=>'شمخ','ﵬ'=>'شمم','ïµ­'=>'شمم','ïµ®'=>'ضحى','ﵯ'=>'ضخم','ïµ°'=>'ضخم','ïµ±'=>'طمح','ïµ²'=>'طمح','ïµ³'=>'طمم','ïµ´'=>'طمي','ïµµ'=>'عجم','ïµ¶'=>'عمم','ïµ·'=>'عمم','ﵸ'=>'عمى','ïµ¹'=>'غمم','ﵺ'=>'غمي','ïµ»'=>'غمى','ïµ¼'=>'ÙØ®Ù…','ïµ½'=>'ÙØ®Ù…','ïµ¾'=>'قمح','ﵿ'=>'قمم','ï¶€'=>'لحم','ï¶'=>'لحي','ï¶‚'=>'لحى','ﶃ'=>'لجج','ï¶„'=>'لجج','ï¶…'=>'لخم','ﶆ'=>'لخم','ﶇ'=>'لمح','ﶈ'=>'لمح','ﶉ'=>'محج','ï¶Š'=>'محم','ï¶‹'=>'محي','ï¶Œ'=>'مجح','ï¶'=>'مجم','ï¶Ž'=>'مخج','ï¶'=>'مخم','ï¶’'=>'مجخ','ï¶“'=>'همج','ï¶”'=>'همم','ï¶•'=>'نحم','ï¶–'=>'نحى','ï¶—'=>'نجم','ﶘ'=>'نجم','ï¶™'=>'نجى','ï¶š'=>'نمي','ï¶›'=>'نمى','ï¶œ'=>'يمم','ï¶'=>'يمم','ï¶ž'=>'بخي','ï¶Ÿ'=>'تجي','ï¶ '=>'تجى','ï¶¡'=>'تخي','ï¶¢'=>'تخى','ï¶£'=>'تمي','ﶤ'=>'تمى','ï¶¥'=>'جمي','ﶦ'=>'جحى','ï¶§'=>'جمى','ﶨ'=>'سخى','ï¶©'=>'صحي','ﶪ'=>'شحي','ï¶«'=>'ضحي','ﶬ'=>'لجي','ï¶­'=>'لمي','ï¶®'=>'يحي','ﶯ'=>'يجي','ï¶°'=>'يمي','ï¶±'=>'ممي','ï¶²'=>'قمي','ï¶³'=>'نحي','ï¶´'=>'قمح','ï¶µ'=>'لحم','ï¶¶'=>'عمي','ï¶·'=>'كمي','ﶸ'=>'نجح','ï¶¹'=>'مخي','ﶺ'=>'لجم','ï¶»'=>'كمم','ï¶¼'=>'لجم','ï¶½'=>'نجح','ï¶¾'=>'جحي','ï¶¿'=>'حجي','ï·€'=>'مجي','ï·'=>'Ùمي','ï·‚'=>'بحي','ï·ƒ'=>'كمم','ï·„'=>'عجم','ï·…'=>'صمم','ï·†'=>'سخي','ï·‡'=>'نجي','ï·°'=>'صلے','ï·±'=>'قلے','ï·²'=>'الله','ï·³'=>'اكبر','ï·´'=>'محمد','ï·µ'=>'صلعم','ï·¶'=>'رسول','ï··'=>'عليه','ï·¸'=>'وسلم','ï·¹'=>'صلى','ï·º'=>'صلى الله عليه وسلم','ï·»'=>'جل جلاله','ï·¼'=>'ریال','ï¸'=>',','︑'=>'ã€','︒'=>'。','︓'=>':','︔'=>';','︕'=>'!','︖'=>'?','︗'=>'〖','︘'=>'〗','︙'=>'...','︰'=>'..','︱'=>'—','︲'=>'–','︳'=>'_','︴'=>'_','︵'=>'(','︶'=>')','︷'=>'{','︸'=>'}','︹'=>'〔','︺'=>'〕','︻'=>'ã€','︼'=>'】','︽'=>'《','︾'=>'》','︿'=>'〈','ï¹€'=>'〉','ï¹'=>'「','﹂'=>'ã€','﹃'=>'『','﹄'=>'ã€','﹇'=>'[','﹈'=>']','﹉'=>' Ì…','﹊'=>' Ì…','﹋'=>' Ì…','﹌'=>' Ì…','ï¹'=>'_','﹎'=>'_','ï¹'=>'_','ï¹'=>',','﹑'=>'ã€','ï¹’'=>'.','ï¹”'=>';','﹕'=>':','ï¹–'=>'?','ï¹—'=>'!','﹘'=>'—','ï¹™'=>'(','﹚'=>')','ï¹›'=>'{','﹜'=>'}','ï¹'=>'〔','﹞'=>'〕','﹟'=>'#','ï¹ '=>'&','﹡'=>'*','ï¹¢'=>'+','ï¹£'=>'-','﹤'=>'<','ï¹¥'=>'>','﹦'=>'=','﹨'=>'\\','﹩'=>'$','﹪'=>'%','﹫'=>'@','ï¹°'=>' Ù‹','ï¹±'=>'ـً','ï¹²'=>' ÙŒ','ï¹´'=>' Ù','ï¹¶'=>' ÙŽ','ï¹·'=>'Ù€ÙŽ','ﹸ'=>' Ù','ï¹¹'=>'Ù€Ù','ﹺ'=>' Ù','ï¹»'=>'Ù€Ù','ï¹¼'=>' Ù‘','ï¹½'=>'ـّ','ï¹¾'=>' Ù’','ﹿ'=>'ـْ','ﺀ'=>'Ø¡','ïº'=>'آ','ﺂ'=>'آ','ﺃ'=>'أ','ﺄ'=>'أ','ﺅ'=>'ÙˆÙ”','ﺆ'=>'ÙˆÙ”','ﺇ'=>'إ','ﺈ'=>'إ','ﺉ'=>'ÙŠÙ”','ﺊ'=>'ÙŠÙ”','ﺋ'=>'ÙŠÙ”','ﺌ'=>'ÙŠÙ”','ïº'=>'ا','ﺎ'=>'ا','ïº'=>'ب','ïº'=>'ب','ﺑ'=>'ب','ﺒ'=>'ب','ﺓ'=>'Ø©','ﺔ'=>'Ø©','ﺕ'=>'ت','ﺖ'=>'ت','ﺗ'=>'ت','ﺘ'=>'ت','ﺙ'=>'Ø«','ﺚ'=>'Ø«','ﺛ'=>'Ø«','ﺜ'=>'Ø«','ïº'=>'ج','ﺞ'=>'ج','ﺟ'=>'ج','ﺠ'=>'ج','ﺡ'=>'Ø­','ﺢ'=>'Ø­','ﺣ'=>'Ø­','ﺤ'=>'Ø­','ﺥ'=>'Ø®','ﺦ'=>'Ø®','ﺧ'=>'Ø®','ﺨ'=>'Ø®','ﺩ'=>'د','ﺪ'=>'د','ﺫ'=>'ذ','ﺬ'=>'ذ','ﺭ'=>'ر','ﺮ'=>'ر','ﺯ'=>'ز','ﺰ'=>'ز','ﺱ'=>'س','ﺲ'=>'س','ﺳ'=>'س','ﺴ'=>'س','ﺵ'=>'Ø´','ﺶ'=>'Ø´','ﺷ'=>'Ø´','ﺸ'=>'Ø´','ﺹ'=>'ص','ﺺ'=>'ص','ﺻ'=>'ص','ﺼ'=>'ص','ﺽ'=>'ض','ﺾ'=>'ض','ﺿ'=>'ض','ﻀ'=>'ض','ï»'=>'Ø·','ﻂ'=>'Ø·','ﻃ'=>'Ø·','ﻄ'=>'Ø·','ï»…'=>'ظ','ﻆ'=>'ظ','ﻇ'=>'ظ','ﻈ'=>'ظ','ﻉ'=>'ع','ﻊ'=>'ع','ﻋ'=>'ع','ﻌ'=>'ع','ï»'=>'غ','ﻎ'=>'غ','ï»'=>'غ','ï»'=>'غ','ﻑ'=>'Ù','ï»’'=>'Ù','ﻓ'=>'Ù','ï»”'=>'Ù','ﻕ'=>'Ù‚','ï»–'=>'Ù‚','ï»—'=>'Ù‚','ﻘ'=>'Ù‚','ï»™'=>'Ùƒ','ﻚ'=>'Ùƒ','ï»›'=>'Ùƒ','ﻜ'=>'Ùƒ','ï»'=>'Ù„','ﻞ'=>'Ù„','ﻟ'=>'Ù„','ï» '=>'Ù„','ﻡ'=>'Ù…','ﻢ'=>'Ù…','ﻣ'=>'Ù…','ﻤ'=>'Ù…','ﻥ'=>'Ù†','ﻦ'=>'Ù†','ï»§'=>'Ù†','ﻨ'=>'Ù†','ﻩ'=>'Ù‡','ﻪ'=>'Ù‡','ﻫ'=>'Ù‡','ﻬ'=>'Ù‡','ï»­'=>'Ùˆ','ï»®'=>'Ùˆ','ﻯ'=>'Ù‰','ï»°'=>'Ù‰','ï»±'=>'ÙŠ','ﻲ'=>'ÙŠ','ﻳ'=>'ÙŠ','ï»´'=>'ÙŠ','ﻵ'=>'لآ','ï»¶'=>'لآ','ï»·'=>'لأ','ﻸ'=>'لأ','ﻹ'=>'لإ','ﻺ'=>'لإ','ï»»'=>'لا','ﻼ'=>'لا','ï¼'=>'!','"'=>'"','#'=>'#','$'=>'$','ï¼…'=>'%','&'=>'&','''=>'\'','('=>'(',')'=>')','*'=>'*','+'=>'+',','=>',','ï¼'=>'-','.'=>'.','ï¼'=>'/','ï¼'=>'0','1'=>'1','ï¼’'=>'2','3'=>'3','ï¼”'=>'4','5'=>'5','ï¼–'=>'6','ï¼—'=>'7','8'=>'8','ï¼™'=>'9',':'=>':','ï¼›'=>';','<'=>'<','ï¼'=>'=','>'=>'>','?'=>'?','ï¼ '=>'@','A'=>'A','ï¼¢'=>'B','ï¼£'=>'C','D'=>'D','ï¼¥'=>'E','F'=>'F','ï¼§'=>'G','H'=>'H','I'=>'I','J'=>'J','K'=>'K','L'=>'L','ï¼­'=>'M','ï¼®'=>'N','O'=>'O','ï¼°'=>'P','ï¼±'=>'Q','ï¼²'=>'R','ï¼³'=>'S','ï¼´'=>'T','ï¼µ'=>'U','ï¼¶'=>'V','ï¼·'=>'W','X'=>'X','ï¼¹'=>'Y','Z'=>'Z','ï¼»'=>'[','ï¼¼'=>'\\','ï¼½'=>']','ï¼¾'=>'^','_'=>'_','ï½€'=>'`','ï½'=>'a','b'=>'b','c'=>'c','d'=>'d','ï½…'=>'e','f'=>'f','g'=>'g','h'=>'h','i'=>'i','j'=>'j','k'=>'k','l'=>'l','ï½'=>'m','n'=>'n','ï½'=>'o','ï½'=>'p','q'=>'q','ï½’'=>'r','s'=>'s','ï½”'=>'t','u'=>'u','ï½–'=>'v','ï½—'=>'w','x'=>'x','ï½™'=>'y','z'=>'z','ï½›'=>'{','|'=>'|','ï½'=>'}','~'=>'~','⦅'=>'⦅','ï½ '=>'⦆','。'=>'。','ï½¢'=>'「','ï½£'=>'ã€','、'=>'ã€','ï½¥'=>'・','ヲ'=>'ヲ','ï½§'=>'ã‚¡','ィ'=>'ã‚£','ゥ'=>'ã‚¥','ェ'=>'ã‚§','ォ'=>'ã‚©','ャ'=>'ャ','ï½­'=>'ュ','ï½®'=>'ョ','ッ'=>'ッ','ï½°'=>'ー','ï½±'=>'ã‚¢','ï½²'=>'イ','ï½³'=>'ウ','ï½´'=>'エ','ï½µ'=>'オ','ï½¶'=>'ã‚«','ï½·'=>'ã‚­','ク'=>'ク','ï½¹'=>'ケ','コ'=>'コ','ï½»'=>'サ','ï½¼'=>'ã‚·','ï½½'=>'ス','ï½¾'=>'ã‚»','ソ'=>'ソ','ï¾€'=>'ã‚¿','ï¾'=>'ãƒ','ツ'=>'ツ','テ'=>'テ','ト'=>'ト','ï¾…'=>'ナ','ニ'=>'ニ','ヌ'=>'ヌ','ネ'=>'ãƒ','ノ'=>'ノ','ハ'=>'ãƒ','ヒ'=>'ヒ','フ'=>'フ','ï¾'=>'ヘ','ホ'=>'ホ','ï¾'=>'マ','ï¾'=>'ミ','ム'=>'ム','ï¾’'=>'メ','モ'=>'モ','ï¾”'=>'ヤ','ユ'=>'ユ','ï¾–'=>'ヨ','ï¾—'=>'ラ','リ'=>'リ','ï¾™'=>'ル','レ'=>'レ','ï¾›'=>'ロ','ワ'=>'ワ','ï¾'=>'ン','゙'=>'ã‚™','゚'=>'゚','ï¾ '=>'á… ','ᄀ'=>'á„€','ï¾¢'=>'á„','ï¾£'=>'ᆪ','ᄂ'=>'á„‚','ï¾¥'=>'ᆬ','ᆭ'=>'ᆭ','ï¾§'=>'ᄃ','ᄄ'=>'á„„','ᄅ'=>'á„…','ᆰ'=>'ᆰ','ᆱ'=>'ᆱ','ᆲ'=>'ᆲ','ï¾­'=>'ᆳ','ï¾®'=>'ᆴ','ᆵ'=>'ᆵ','ï¾°'=>'ᄚ','ï¾±'=>'ᄆ','ï¾²'=>'ᄇ','ï¾³'=>'ᄈ','ï¾´'=>'á„¡','ï¾µ'=>'ᄉ','ï¾¶'=>'ᄊ','ï¾·'=>'á„‹','ᄌ'=>'ᄌ','ï¾¹'=>'á„','ᄎ'=>'ᄎ','ï¾»'=>'á„','ï¾¼'=>'á„','ï¾½'=>'á„‘','ï¾¾'=>'á„’','ï¿‚'=>'á…¡','ᅢ'=>'á…¢','ï¿„'=>'á…£','ï¿…'=>'á…¤','ᅥ'=>'á…¥','ᅦ'=>'á…¦','ᅧ'=>'á…§','ï¿‹'=>'á…¨','ᅩ'=>'á…©','ï¿'=>'á…ª','ᅫ'=>'á…«','ï¿'=>'á…¬','ï¿’'=>'á…­','ï¿“'=>'á…®','ï¿”'=>'á…¯','ï¿•'=>'á…°','ï¿–'=>'á…±','ï¿—'=>'á…²','ᅳ'=>'á…³','ï¿›'=>'á…´','ᅵ'=>'á…µ','ï¿ '=>'¢','ï¿¡'=>'£','ï¿¢'=>'¬','ï¿£'=>' Ì„','¦'=>'¦','ï¿¥'=>'Â¥','₩'=>'â‚©','│'=>'│','ï¿©'=>'â†','↑'=>'↑','ï¿«'=>'→','↓'=>'↓','ï¿­'=>'â– ','ï¿®'=>'â—‹','ð…ž'=>'ð…—ð…¥','ð…Ÿ'=>'ð…˜ð…¥','ð… '=>'ð…˜ð…¥ð…®','ð…¡'=>'ð…˜ð…¥ð…¯','ð…¢'=>'ð…˜ð…¥ð…°','ð…£'=>'ð…˜ð…¥ð…±','ð…¤'=>'ð…˜ð…¥ð…²','ð†»'=>'ð†¹ð…¥','ð†¼'=>'ð†ºð…¥','ð†½'=>'ð†¹ð…¥ð…®','ð†¾'=>'ð†ºð…¥ð…®','ð†¿'=>'ð†¹ð…¥ð…¯','ð‡€'=>'ð†ºð…¥ð…¯','ð€'=>'A','ð'=>'B','ð‚'=>'C','ðƒ'=>'D','ð„'=>'E','ð…'=>'F','ð†'=>'G','ð‡'=>'H','ðˆ'=>'I','ð‰'=>'J','ðŠ'=>'K','ð‹'=>'L','ðŒ'=>'M','ð'=>'N','ðŽ'=>'O','ð'=>'P','ð'=>'Q','ð‘'=>'R','ð’'=>'S','ð“'=>'T','ð”'=>'U','ð•'=>'V','ð–'=>'W','ð—'=>'X','ð˜'=>'Y','ð™'=>'Z','ðš'=>'a','ð›'=>'b','ðœ'=>'c','ð'=>'d','ðž'=>'e','ðŸ'=>'f','ð '=>'g','ð¡'=>'h','ð¢'=>'i','ð£'=>'j','ð¤'=>'k','ð¥'=>'l','ð¦'=>'m','ð§'=>'n','ð¨'=>'o','ð©'=>'p','ðª'=>'q','ð«'=>'r','ð¬'=>'s','ð­'=>'t','ð®'=>'u','ð¯'=>'v','ð°'=>'w','ð±'=>'x','ð²'=>'y','ð³'=>'z','ð´'=>'A','ðµ'=>'B','ð¶'=>'C','ð·'=>'D','ð¸'=>'E','ð¹'=>'F','ðº'=>'G','ð»'=>'H','ð¼'=>'I','ð½'=>'J','ð¾'=>'K','ð¿'=>'L','ð‘€'=>'M','ð‘'=>'N','ð‘‚'=>'O','ð‘ƒ'=>'P','ð‘„'=>'Q','ð‘…'=>'R','ð‘†'=>'S','ð‘‡'=>'T','ð‘ˆ'=>'U','ð‘‰'=>'V','ð‘Š'=>'W','ð‘‹'=>'X','ð‘Œ'=>'Y','ð‘'=>'Z','ð‘Ž'=>'a','ð‘'=>'b','ð‘'=>'c','ð‘‘'=>'d','ð‘’'=>'e','ð‘“'=>'f','ð‘”'=>'g','ð‘–'=>'i','ð‘—'=>'j','ð‘˜'=>'k','ð‘™'=>'l','ð‘š'=>'m','ð‘›'=>'n','ð‘œ'=>'o','ð‘'=>'p','ð‘ž'=>'q','ð‘Ÿ'=>'r','ð‘ '=>'s','ð‘¡'=>'t','ð‘¢'=>'u','ð‘£'=>'v','ð‘¤'=>'w','ð‘¥'=>'x','ð‘¦'=>'y','ð‘§'=>'z','ð‘¨'=>'A','ð‘©'=>'B','ð‘ª'=>'C','ð‘«'=>'D','ð‘¬'=>'E','ð‘­'=>'F','ð‘®'=>'G','ð‘¯'=>'H','ð‘°'=>'I','ð‘±'=>'J','ð‘²'=>'K','ð‘³'=>'L','ð‘´'=>'M','ð‘µ'=>'N','ð‘¶'=>'O','ð‘·'=>'P','ð‘¸'=>'Q','ð‘¹'=>'R','ð‘º'=>'S','ð‘»'=>'T','ð‘¼'=>'U','ð‘½'=>'V','ð‘¾'=>'W','ð‘¿'=>'X','ð’€'=>'Y','ð’'=>'Z','ð’‚'=>'a','ð’ƒ'=>'b','ð’„'=>'c','ð’…'=>'d','ð’†'=>'e','ð’‡'=>'f','ð’ˆ'=>'g','ð’‰'=>'h','ð’Š'=>'i','ð’‹'=>'j','ð’Œ'=>'k','ð’'=>'l','ð’Ž'=>'m','ð’'=>'n','ð’'=>'o','ð’‘'=>'p','ð’’'=>'q','ð’“'=>'r','ð’”'=>'s','ð’•'=>'t','ð’–'=>'u','ð’—'=>'v','ð’˜'=>'w','ð’™'=>'x','ð’š'=>'y','ð’›'=>'z','ð’œ'=>'A','ð’ž'=>'C','ð’Ÿ'=>'D','ð’¢'=>'G','ð’¥'=>'J','ð’¦'=>'K','ð’©'=>'N','ð’ª'=>'O','ð’«'=>'P','ð’¬'=>'Q','ð’®'=>'S','ð’¯'=>'T','ð’°'=>'U','ð’±'=>'V','ð’²'=>'W','ð’³'=>'X','ð’´'=>'Y','ð’µ'=>'Z','ð’¶'=>'a','ð’·'=>'b','ð’¸'=>'c','ð’¹'=>'d','ð’»'=>'f','ð’½'=>'h','ð’¾'=>'i','ð’¿'=>'j','ð“€'=>'k','ð“'=>'l','ð“‚'=>'m','ð“ƒ'=>'n','ð“…'=>'p','ð“†'=>'q','ð“‡'=>'r','ð“ˆ'=>'s','ð“‰'=>'t','ð“Š'=>'u','ð“‹'=>'v','ð“Œ'=>'w','ð“'=>'x','ð“Ž'=>'y','ð“'=>'z','ð“'=>'A','ð“‘'=>'B','ð“’'=>'C','ð““'=>'D','ð“”'=>'E','ð“•'=>'F','ð“–'=>'G','ð“—'=>'H','ð“˜'=>'I','ð“™'=>'J','ð“š'=>'K','ð“›'=>'L','ð“œ'=>'M','ð“'=>'N','ð“ž'=>'O','ð“Ÿ'=>'P','ð“ '=>'Q','ð“¡'=>'R','ð“¢'=>'S','ð“£'=>'T','ð“¤'=>'U','ð“¥'=>'V','ð“¦'=>'W','ð“§'=>'X','ð“¨'=>'Y','ð“©'=>'Z','ð“ª'=>'a','ð“«'=>'b','ð“¬'=>'c','ð“­'=>'d','ð“®'=>'e','ð“¯'=>'f','ð“°'=>'g','ð“±'=>'h','ð“²'=>'i','ð“³'=>'j','ð“´'=>'k','ð“µ'=>'l','ð“¶'=>'m','ð“·'=>'n','ð“¸'=>'o','ð“¹'=>'p','ð“º'=>'q','ð“»'=>'r','ð“¼'=>'s','ð“½'=>'t','ð“¾'=>'u','ð“¿'=>'v','ð”€'=>'w','ð”'=>'x','ð”‚'=>'y','ð”ƒ'=>'z','ð”„'=>'A','ð”…'=>'B','ð”‡'=>'D','ð”ˆ'=>'E','ð”‰'=>'F','ð”Š'=>'G','ð”'=>'J','ð”Ž'=>'K','ð”'=>'L','ð”'=>'M','ð”‘'=>'N','ð”’'=>'O','ð”“'=>'P','ð””'=>'Q','ð”–'=>'S','ð”—'=>'T','ð”˜'=>'U','ð”™'=>'V','ð”š'=>'W','ð”›'=>'X','ð”œ'=>'Y','ð”ž'=>'a','ð”Ÿ'=>'b','ð” '=>'c','ð”¡'=>'d','ð”¢'=>'e','ð”£'=>'f','ð”¤'=>'g','ð”¥'=>'h','ð”¦'=>'i','ð”§'=>'j','ð”¨'=>'k','ð”©'=>'l','ð”ª'=>'m','ð”«'=>'n','ð”¬'=>'o','ð”­'=>'p','ð”®'=>'q','ð”¯'=>'r','ð”°'=>'s','ð”±'=>'t','ð”²'=>'u','ð”³'=>'v','ð”´'=>'w','ð”µ'=>'x','ð”¶'=>'y','ð”·'=>'z','ð”¸'=>'A','ð”¹'=>'B','ð”»'=>'D','ð”¼'=>'E','ð”½'=>'F','ð”¾'=>'G','ð•€'=>'I','ð•'=>'J','ð•‚'=>'K','ð•ƒ'=>'L','ð•„'=>'M','ð•†'=>'O','ð•Š'=>'S','ð•‹'=>'T','ð•Œ'=>'U','ð•'=>'V','ð•Ž'=>'W','ð•'=>'X','ð•'=>'Y','ð•’'=>'a','ð•“'=>'b','ð•”'=>'c','ð••'=>'d','ð•–'=>'e','ð•—'=>'f','ð•˜'=>'g','ð•™'=>'h','ð•š'=>'i','ð•›'=>'j','ð•œ'=>'k','ð•'=>'l','ð•ž'=>'m','ð•Ÿ'=>'n','ð• '=>'o','ð•¡'=>'p','ð•¢'=>'q','ð•£'=>'r','ð•¤'=>'s','ð•¥'=>'t','ð•¦'=>'u','ð•§'=>'v','ð•¨'=>'w','ð•©'=>'x','ð•ª'=>'y','ð•«'=>'z','ð•¬'=>'A','ð•­'=>'B','ð•®'=>'C','ð•¯'=>'D','ð•°'=>'E','ð•±'=>'F','ð•²'=>'G','ð•³'=>'H','ð•´'=>'I','ð•µ'=>'J','ð•¶'=>'K','ð•·'=>'L','ð•¸'=>'M','ð•¹'=>'N','ð•º'=>'O','ð•»'=>'P','ð•¼'=>'Q','ð•½'=>'R','ð•¾'=>'S','ð•¿'=>'T','ð–€'=>'U','ð–'=>'V','ð–‚'=>'W','ð–ƒ'=>'X','ð–„'=>'Y','ð–…'=>'Z','ð–†'=>'a','ð–‡'=>'b','ð–ˆ'=>'c','ð–‰'=>'d','ð–Š'=>'e','ð–‹'=>'f','ð–Œ'=>'g','ð–'=>'h','ð–Ž'=>'i','ð–'=>'j','ð–'=>'k','ð–‘'=>'l','ð–’'=>'m','ð–“'=>'n','ð–”'=>'o','ð–•'=>'p','ð––'=>'q','ð–—'=>'r','ð–˜'=>'s','ð–™'=>'t','ð–š'=>'u','ð–›'=>'v','ð–œ'=>'w','ð–'=>'x','ð–ž'=>'y','ð–Ÿ'=>'z','ð– '=>'A','ð–¡'=>'B','ð–¢'=>'C','ð–£'=>'D','ð–¤'=>'E','ð–¥'=>'F','ð–¦'=>'G','ð–§'=>'H','ð–¨'=>'I','ð–©'=>'J','ð–ª'=>'K','ð–«'=>'L','ð–¬'=>'M','ð–­'=>'N','ð–®'=>'O','ð–¯'=>'P','ð–°'=>'Q','ð–±'=>'R','ð–²'=>'S','ð–³'=>'T','ð–´'=>'U','ð–µ'=>'V','ð–¶'=>'W','ð–·'=>'X','ð–¸'=>'Y','ð–¹'=>'Z','ð–º'=>'a','ð–»'=>'b','ð–¼'=>'c','ð–½'=>'d','ð–¾'=>'e','ð–¿'=>'f','ð—€'=>'g','ð—'=>'h','ð—‚'=>'i','ð—ƒ'=>'j','ð—„'=>'k','ð—…'=>'l','ð—†'=>'m','ð—‡'=>'n','ð—ˆ'=>'o','ð—‰'=>'p','ð—Š'=>'q','ð—‹'=>'r','ð—Œ'=>'s','ð—'=>'t','ð—Ž'=>'u','ð—'=>'v','ð—'=>'w','ð—‘'=>'x','ð—’'=>'y','ð—“'=>'z','ð—”'=>'A','ð—•'=>'B','ð—–'=>'C','ð——'=>'D','ð—˜'=>'E','ð—™'=>'F','ð—š'=>'G','ð—›'=>'H','ð—œ'=>'I','ð—'=>'J','ð—ž'=>'K','ð—Ÿ'=>'L','ð— '=>'M','ð—¡'=>'N','ð—¢'=>'O','ð—£'=>'P','ð—¤'=>'Q','ð—¥'=>'R','ð—¦'=>'S','ð—§'=>'T','ð—¨'=>'U','ð—©'=>'V','ð—ª'=>'W','ð—«'=>'X','ð—¬'=>'Y','ð—­'=>'Z','ð—®'=>'a','ð—¯'=>'b','ð—°'=>'c','ð—±'=>'d','ð—²'=>'e','ð—³'=>'f','ð—´'=>'g','ð—µ'=>'h','ð—¶'=>'i','ð—·'=>'j','ð—¸'=>'k','ð—¹'=>'l','ð—º'=>'m','ð—»'=>'n','ð—¼'=>'o','ð—½'=>'p','ð—¾'=>'q','ð—¿'=>'r','ð˜€'=>'s','ð˜'=>'t','ð˜‚'=>'u','ð˜ƒ'=>'v','ð˜„'=>'w','ð˜…'=>'x','ð˜†'=>'y','ð˜‡'=>'z','ð˜ˆ'=>'A','ð˜‰'=>'B','ð˜Š'=>'C','ð˜‹'=>'D','ð˜Œ'=>'E','ð˜'=>'F','ð˜Ž'=>'G','ð˜'=>'H','ð˜'=>'I','ð˜‘'=>'J','ð˜’'=>'K','ð˜“'=>'L','ð˜”'=>'M','ð˜•'=>'N','ð˜–'=>'O','ð˜—'=>'P','ð˜˜'=>'Q','ð˜™'=>'R','ð˜š'=>'S','ð˜›'=>'T','ð˜œ'=>'U','ð˜'=>'V','ð˜ž'=>'W','ð˜Ÿ'=>'X','ð˜ '=>'Y','ð˜¡'=>'Z','ð˜¢'=>'a','ð˜£'=>'b','ð˜¤'=>'c','ð˜¥'=>'d','ð˜¦'=>'e','ð˜§'=>'f','ð˜¨'=>'g','ð˜©'=>'h','ð˜ª'=>'i','ð˜«'=>'j','ð˜¬'=>'k','ð˜­'=>'l','ð˜®'=>'m','ð˜¯'=>'n','ð˜°'=>'o','ð˜±'=>'p','ð˜²'=>'q','ð˜³'=>'r','ð˜´'=>'s','ð˜µ'=>'t','ð˜¶'=>'u','ð˜·'=>'v','ð˜¸'=>'w','ð˜¹'=>'x','ð˜º'=>'y','ð˜»'=>'z','ð˜¼'=>'A','ð˜½'=>'B','ð˜¾'=>'C','ð˜¿'=>'D','ð™€'=>'E','ð™'=>'F','ð™‚'=>'G','ð™ƒ'=>'H','ð™„'=>'I','ð™…'=>'J','ð™†'=>'K','ð™‡'=>'L','ð™ˆ'=>'M','ð™‰'=>'N','ð™Š'=>'O','ð™‹'=>'P','ð™Œ'=>'Q','ð™'=>'R','ð™Ž'=>'S','ð™'=>'T','ð™'=>'U','ð™‘'=>'V','ð™’'=>'W','ð™“'=>'X','ð™”'=>'Y','ð™•'=>'Z','ð™–'=>'a','ð™—'=>'b','ð™˜'=>'c','ð™™'=>'d','ð™š'=>'e','ð™›'=>'f','ð™œ'=>'g','ð™'=>'h','ð™ž'=>'i','ð™Ÿ'=>'j','ð™ '=>'k','ð™¡'=>'l','ð™¢'=>'m','ð™£'=>'n','ð™¤'=>'o','ð™¥'=>'p','ð™¦'=>'q','ð™§'=>'r','ð™¨'=>'s','ð™©'=>'t','ð™ª'=>'u','ð™«'=>'v','ð™¬'=>'w','ð™­'=>'x','ð™®'=>'y','ð™¯'=>'z','ð™°'=>'A','ð™±'=>'B','ð™²'=>'C','ð™³'=>'D','ð™´'=>'E','ð™µ'=>'F','ð™¶'=>'G','ð™·'=>'H','ð™¸'=>'I','ð™¹'=>'J','ð™º'=>'K','ð™»'=>'L','ð™¼'=>'M','ð™½'=>'N','ð™¾'=>'O','ð™¿'=>'P','ðš€'=>'Q','ðš'=>'R','ðš‚'=>'S','ðšƒ'=>'T','ðš„'=>'U','ðš…'=>'V','ðš†'=>'W','ðš‡'=>'X','ðšˆ'=>'Y','ðš‰'=>'Z','ðšŠ'=>'a','ðš‹'=>'b','ðšŒ'=>'c','ðš'=>'d','ðšŽ'=>'e','ðš'=>'f','ðš'=>'g','ðš‘'=>'h','ðš’'=>'i','ðš“'=>'j','ðš”'=>'k','ðš•'=>'l','ðš–'=>'m','ðš—'=>'n','ðš˜'=>'o','ðš™'=>'p','ðšš'=>'q','ðš›'=>'r','ðšœ'=>'s','ðš'=>'t','ðšž'=>'u','ðšŸ'=>'v','ðš '=>'w','ðš¡'=>'x','ðš¢'=>'y','ðš£'=>'z','ðš¤'=>'ı','ðš¥'=>'È·','ðš¨'=>'Α','ðš©'=>'Î’','ðšª'=>'Γ','ðš«'=>'Δ','ðš¬'=>'Ε','ðš­'=>'Ζ','ðš®'=>'Η','ðš¯'=>'Θ','ðš°'=>'Ι','ðš±'=>'Κ','ðš²'=>'Λ','ðš³'=>'Μ','ðš´'=>'Î','ðšµ'=>'Ξ','ðš¶'=>'Ο','ðš·'=>'Π','ðš¸'=>'Ρ','ðš¹'=>'Θ','ðšº'=>'Σ','ðš»'=>'Τ','ðš¼'=>'Î¥','ðš½'=>'Φ','ðš¾'=>'Χ','ðš¿'=>'Ψ','ð›€'=>'Ω','ð›'=>'∇','ð›‚'=>'α','ð›ƒ'=>'β','ð›„'=>'γ','ð›…'=>'δ','ð›†'=>'ε','ð›‡'=>'ζ','ð›ˆ'=>'η','ð›‰'=>'θ','ð›Š'=>'ι','ð›‹'=>'κ','ð›Œ'=>'λ','ð›'=>'μ','ð›Ž'=>'ν','ð›'=>'ξ','ð›'=>'ο','ð›‘'=>'Ï€','ð›’'=>'Ï','ð›“'=>'Ï‚','ð›”'=>'σ','ð›•'=>'Ï„','ð›–'=>'Ï…','ð›—'=>'φ','ð›˜'=>'χ','ð›™'=>'ψ','ð›š'=>'ω','ð››'=>'∂','ð›œ'=>'ε','ð›'=>'θ','ð›ž'=>'κ','ð›Ÿ'=>'φ','ð› '=>'Ï','ð›¡'=>'Ï€','ð›¢'=>'Α','ð›£'=>'Î’','ð›¤'=>'Γ','ð›¥'=>'Δ','ð›¦'=>'Ε','ð›§'=>'Ζ','ð›¨'=>'Η','ð›©'=>'Θ','ð›ª'=>'Ι','ð›«'=>'Κ','ð›¬'=>'Λ','ð›­'=>'Μ','ð›®'=>'Î','ð›¯'=>'Ξ','ð›°'=>'Ο','ð›±'=>'Π','ð›²'=>'Ρ','ð›³'=>'Θ','ð›´'=>'Σ','ð›µ'=>'Τ','ð›¶'=>'Î¥','ð›·'=>'Φ','ð›¸'=>'Χ','ð›¹'=>'Ψ','ð›º'=>'Ω','ð›»'=>'∇','ð›¼'=>'α','ð›½'=>'β','ð›¾'=>'γ','ð›¿'=>'δ','ðœ€'=>'ε','ðœ'=>'ζ','ðœ‚'=>'η','ðœƒ'=>'θ','ðœ„'=>'ι','ðœ…'=>'κ','ðœ†'=>'λ','ðœ‡'=>'μ','ðœˆ'=>'ν','ðœ‰'=>'ξ','ðœŠ'=>'ο','ðœ‹'=>'Ï€','ðœŒ'=>'Ï','ðœ'=>'Ï‚','ðœŽ'=>'σ','ðœ'=>'Ï„','ðœ'=>'Ï…','ðœ‘'=>'φ','ðœ’'=>'χ','ðœ“'=>'ψ','ðœ”'=>'ω','ðœ•'=>'∂','ðœ–'=>'ε','ðœ—'=>'θ','ðœ˜'=>'κ','ðœ™'=>'φ','ðœš'=>'Ï','ðœ›'=>'Ï€','ðœœ'=>'Α','ðœ'=>'Î’','ðœž'=>'Γ','ðœŸ'=>'Δ','ðœ '=>'Ε','ðœ¡'=>'Ζ','ðœ¢'=>'Η','ðœ£'=>'Θ','ðœ¤'=>'Ι','ðœ¥'=>'Κ','ðœ¦'=>'Λ','ðœ§'=>'Μ','ðœ¨'=>'Î','ðœ©'=>'Ξ','ðœª'=>'Ο','ðœ«'=>'Π','ðœ¬'=>'Ρ','ðœ­'=>'Θ','ðœ®'=>'Σ','ðœ¯'=>'Τ','ðœ°'=>'Î¥','ðœ±'=>'Φ','ðœ²'=>'Χ','ðœ³'=>'Ψ','ðœ´'=>'Ω','ðœµ'=>'∇','ðœ¶'=>'α','ðœ·'=>'β','ðœ¸'=>'γ','ðœ¹'=>'δ','ðœº'=>'ε','ðœ»'=>'ζ','ðœ¼'=>'η','ðœ½'=>'θ','ðœ¾'=>'ι','ðœ¿'=>'κ','ð€'=>'λ','ð'=>'μ','ð‚'=>'ν','ðƒ'=>'ξ','ð„'=>'ο','ð…'=>'Ï€','ð†'=>'Ï','ð‡'=>'Ï‚','ðˆ'=>'σ','ð‰'=>'Ï„','ðŠ'=>'Ï…','ð‹'=>'φ','ðŒ'=>'χ','ð'=>'ψ','ðŽ'=>'ω','ð'=>'∂','ð'=>'ε','ð‘'=>'θ','ð’'=>'κ','ð“'=>'φ','ð”'=>'Ï','ð•'=>'Ï€','ð–'=>'Α','ð—'=>'Î’','ð˜'=>'Γ','ð™'=>'Δ','ðš'=>'Ε','ð›'=>'Ζ','ðœ'=>'Η','ð'=>'Θ','ðž'=>'Ι','ðŸ'=>'Κ','ð '=>'Λ','ð¡'=>'Μ','ð¢'=>'Î','ð£'=>'Ξ','ð¤'=>'Ο','ð¥'=>'Π','ð¦'=>'Ρ','ð§'=>'Θ','ð¨'=>'Σ','ð©'=>'Τ','ðª'=>'Î¥','ð«'=>'Φ','ð¬'=>'Χ','ð­'=>'Ψ','ð®'=>'Ω','ð¯'=>'∇','ð°'=>'α','ð±'=>'β','ð²'=>'γ','ð³'=>'δ','ð´'=>'ε','ðµ'=>'ζ','ð¶'=>'η','ð·'=>'θ','ð¸'=>'ι','ð¹'=>'κ','ðº'=>'λ','ð»'=>'μ','ð¼'=>'ν','ð½'=>'ξ','ð¾'=>'ο','ð¿'=>'Ï€','ðž€'=>'Ï','ðž'=>'Ï‚','ðž‚'=>'σ','ðžƒ'=>'Ï„','ðž„'=>'Ï…','ðž…'=>'φ','ðž†'=>'χ','ðž‡'=>'ψ','ðžˆ'=>'ω','ðž‰'=>'∂','ðžŠ'=>'ε','ðž‹'=>'θ','ðžŒ'=>'κ','ðž'=>'φ','ðžŽ'=>'Ï','ðž'=>'Ï€','ðž'=>'Α','ðž‘'=>'Î’','ðž’'=>'Γ','ðž“'=>'Δ','ðž”'=>'Ε','ðž•'=>'Ζ','ðž–'=>'Η','ðž—'=>'Θ','ðž˜'=>'Ι','ðž™'=>'Κ','ðžš'=>'Λ','ðž›'=>'Μ','ðžœ'=>'Î','ðž'=>'Ξ','ðžž'=>'Ο','ðžŸ'=>'Π','ðž '=>'Ρ','ðž¡'=>'Θ','ðž¢'=>'Σ','ðž£'=>'Τ','ðž¤'=>'Î¥','ðž¥'=>'Φ','ðž¦'=>'Χ','ðž§'=>'Ψ','ðž¨'=>'Ω','ðž©'=>'∇','ðžª'=>'α','ðž«'=>'β','ðž¬'=>'γ','ðž­'=>'δ','ðž®'=>'ε','ðž¯'=>'ζ','ðž°'=>'η','ðž±'=>'θ','ðž²'=>'ι','ðž³'=>'κ','ðž´'=>'λ','ðžµ'=>'μ','ðž¶'=>'ν','ðž·'=>'ξ','ðž¸'=>'ο','ðž¹'=>'Ï€','ðžº'=>'Ï','ðž»'=>'Ï‚','ðž¼'=>'σ','ðž½'=>'Ï„','ðž¾'=>'Ï…','ðž¿'=>'φ','ðŸ€'=>'χ','ðŸ'=>'ψ','ðŸ‚'=>'ω','ðŸƒ'=>'∂','ðŸ„'=>'ε','ðŸ…'=>'θ','ðŸ†'=>'κ','ðŸ‡'=>'φ','ðŸˆ'=>'Ï','ðŸ‰'=>'Ï€','ðŸŠ'=>'Ïœ','ðŸ‹'=>'Ï','ðŸŽ'=>'0','ðŸ'=>'1','ðŸ'=>'2','ðŸ‘'=>'3','ðŸ’'=>'4','ðŸ“'=>'5','ðŸ”'=>'6','ðŸ•'=>'7','ðŸ–'=>'8','ðŸ—'=>'9','ðŸ˜'=>'0','ðŸ™'=>'1','ðŸš'=>'2','ðŸ›'=>'3','ðŸœ'=>'4','ðŸ'=>'5','ðŸž'=>'6','ðŸŸ'=>'7','ðŸ '=>'8','ðŸ¡'=>'9','ðŸ¢'=>'0','ðŸ£'=>'1','ðŸ¤'=>'2','ðŸ¥'=>'3','ðŸ¦'=>'4','ðŸ§'=>'5','ðŸ¨'=>'6','ðŸ©'=>'7','ðŸª'=>'8','ðŸ«'=>'9','ðŸ¬'=>'0','ðŸ­'=>'1','ðŸ®'=>'2','ðŸ¯'=>'3','ðŸ°'=>'4','ðŸ±'=>'5','ðŸ²'=>'6','ðŸ³'=>'7','ðŸ´'=>'8','ðŸµ'=>'9','ðŸ¶'=>'0','ðŸ·'=>'1','ðŸ¸'=>'2','ðŸ¹'=>'3','ðŸº'=>'4','ðŸ»'=>'5','ðŸ¼'=>'6','ðŸ½'=>'7','ðŸ¾'=>'8','ðŸ¿'=>'9','丽'=>'丽','ð¯ '=>'丸','乁'=>'ä¹','𠄢'=>'ð „¢','你'=>'ä½ ','侮'=>'ä¾®','侻'=>'ä¾»','倂'=>'倂','偺'=>'åº','備'=>'å‚™','僧'=>'僧','像'=>'åƒ','㒞'=>'ã’ž','ð¯ '=>'𠘺','免'=>'å…','ð¯ '=>'å…”','ð¯ '=>'å…¤','具'=>'å…·','𠔜'=>'𠔜','㒹'=>'ã’¹','內'=>'å…§','再'=>'å†','𠕋'=>'ð •‹','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','ð¯ '=>'凵','刃'=>'刃','㓟'=>'㓟','刻'=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'å‰','卑'=>'å‘','博'=>'åš','即'=>'å³','卽'=>'å½','卿'=>'å¿','卿'=>'å¿','卿'=>'å¿','𠨬'=>'𠨬','灰'=>'ç°','及'=>'åŠ','叟'=>'åŸ','𠭣'=>'ð ­£','叫'=>'å«','叱'=>'å±','吆'=>'å†','咞'=>'å’ž','吸'=>'å¸','呈'=>'呈','周'=>'周','咢'=>'å’¢','ð¯¡'=>'å“¶','唐'=>'å”','啓'=>'å•“','啣'=>'å•£','善'=>'å–„','善'=>'å–„','喙'=>'å–™','喫'=>'å–«','喳'=>'å–³','嗂'=>'å—‚','圖'=>'圖','嘆'=>'嘆','ð¯¡'=>'圗','噑'=>'噑','ð¯¡'=>'å™´','ð¯¡'=>'切','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'å ','型'=>'åž‹','堲'=>'å ²','報'=>'å ±','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','ð¯¡'=>'多','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'ã›®','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','寃'=>'寃','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'å°†','当'=>'当','尢'=>'å°¢','㞁'=>'ãž','屠'=>'å± ','屮'=>'å±®','峀'=>'å³€','岍'=>'å²','𡷤'=>'ð¡·¤','嵃'=>'嵃','𡷦'=>'ð¡·¦','嵮'=>'åµ®','嵫'=>'嵫','嵼'=>'åµ¼','ð¯¢'=>'å·¡','巢'=>'å·¢','㠯'=>'ã ¯','巽'=>'å·½','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'ã¡¢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','ð¯¢'=>'庶','廊'=>'廊','ð¯¢'=>'𪎒','ð¯¢'=>'廾','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'èˆ','弢'=>'å¼¢','弢'=>'å¼¢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'å½¢','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','ð¯¢'=>'å¿','志'=>'å¿—','忹'=>'忹','悁'=>'æ‚','㤺'=>'㤺','㤜'=>'㤜','悔'=>'æ‚”','𢛔'=>'𢛔','惇'=>'惇','慈'=>'æ…ˆ','慌'=>'æ…Œ','慎'=>'æ…Ž','慌'=>'æ…Œ','慺'=>'æ…º','憎'=>'憎','憲'=>'憲','憤'=>'憤','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'æˆ','戛'=>'戛','扝'=>'æ‰','抱'=>'抱','拔'=>'æ‹”','捐'=>'æ','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'æ¨','掃'=>'掃','揤'=>'æ¤','𢯱'=>'𢯱','搢'=>'æ¢','揅'=>'æ…','ð¯£'=>'掩','㨮'=>'㨮','摩'=>'æ‘©','摾'=>'摾','撝'=>'æ’','摷'=>'æ‘·','㩬'=>'㩬','敏'=>'æ•','敬'=>'敬','𣀊'=>'𣀊','旣'=>'æ—£','書'=>'書','ð¯£'=>'晉','㬙'=>'㬙','ð¯£'=>'æš‘','ð¯£'=>'㬈','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'æšœ','肭'=>'è‚­','䏙'=>'ä™','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'æž','杓'=>'æ“','ð¯£'=>'ð£ƒ','㭉'=>'ã­‰','柺'=>'柺','枅'=>'æž…','桒'=>'æ¡’','梅'=>'梅','𣑭'=>'𣑭','梎'=>'梎','栟'=>'æ Ÿ','椔'=>'椔','㮝'=>'ã®','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','櫛'=>'æ«›','㰘'=>'ã°˜','次'=>'次','𣢧'=>'𣢧','歔'=>'æ­”','㱎'=>'㱎','歲'=>'æ­²','殟'=>'殟','殺'=>'殺','殻'=>'æ®»','𣪍'=>'ð£ª','𡴋'=>'ð¡´‹','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'æ³','汧'=>'æ±§','洖'=>'æ´–','派'=>'æ´¾','ð¯¤'=>'æµ·','流'=>'æµ','浩'=>'浩','浸'=>'浸','涅'=>'æ¶…','𣴞'=>'𣴞','洴'=>'æ´´','港'=>'港','湮'=>'æ¹®','㴳'=>'ã´³','滋'=>'滋','滇'=>'滇','ð¯¤'=>'𣻑','淹'=>'æ·¹','ð¯¤'=>'æ½®','ð¯¤'=>'𣽞','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'ã¶–','灊'=>'çŠ','災'=>'ç½','灷'=>'ç·','炭'=>'ç‚­','𠔥'=>'𠔥','煅'=>'ç……','ð¯¤'=>'𤉣','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'ç‰','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'çº','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','㺸'=>'㺸','瑇'=>'瑇','瑜'=>'瑜','瑱'=>'瑱','璅'=>'ç’…','瓊'=>'瓊','㼛'=>'ã¼›','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'ç•°','𢆟'=>'𢆟','瘐'=>'ç˜','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'ð¥„','㿼'=>'㿼','䀈'=>'䀈','直'=>'ç›´','ð¯¥'=>'𥃳','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'çŠ','䀹'=>'䀹','瞋'=>'çž‹','䁆'=>'ä†','䂖'=>'ä‚–','ð¯¥'=>'ð¥','硎'=>'硎','ð¯¥'=>'碌','ð¯¥'=>'磌','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'ç¦','秫'=>'ç§«','䄯'=>'䄯','穀'=>'ç©€','穊'=>'穊','穏'=>'ç©','𥥼'=>'𥥼','ð¯¥'=>'𥪧','𥪧'=>'𥪧','竮'=>'ç«®','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'ç³’','䊠'=>'䊠','糨'=>'糨','糣'=>'ç³£','紀'=>'ç´€','𥾆'=>'𥾆','絣'=>'çµ£','䌁'=>'äŒ','緇'=>'ç·‡','縂'=>'縂','繅'=>'ç¹…','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'ä™','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'è ','𦖨'=>'𦖨','聰'=>'è°','𣍟'=>'ð£Ÿ','ð¯¦'=>'ä•','育'=>'育','脃'=>'脃','䐋'=>'ä‹','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'èˆ','舄'=>'舄','ð¯¦'=>'辞','䑫'=>'ä‘«','ð¯¦'=>'芑','ð¯¦'=>'芋','芝'=>'èŠ','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'è‹¥','茝'=>'èŒ','荣'=>'è£','莭'=>'莭','茣'=>'茣','ð¯¦'=>'莽','菧'=>'è§','著'=>'è‘—','荓'=>'è“','菊'=>'èŠ','菌'=>'èŒ','菜'=>'èœ','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'è”–','𧏊'=>'ð§Š','蕤'=>'蕤','𦼬'=>'𦼬','䕝'=>'ä•','䕡'=>'ä•¡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'ä•«','虐'=>'è™','虜'=>'虜','虧'=>'è™§','虩'=>'虩','蚩'=>'èš©','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'è¹','蜨'=>'蜨','蝫'=>'è«','螆'=>'螆','䗗'=>'ä——','蟡'=>'蟡','ð¯§'=>'è ','䗹'=>'ä—¹','衠'=>'è¡ ','衣'=>'è¡£','𧙧'=>'ð§™§','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'ã’»','𧢮'=>'ð§¢®','𧥦'=>'𧥦','ð¯§'=>'äš¾','䛇'=>'䛇','ð¯§'=>'誠','ð¯§'=>'è«­','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'è³','贛'=>'è´›','起'=>'èµ·','𧼯'=>'𧼯','𠠄'=>'ð  „','跋'=>'è·‹','趼'=>'è¶¼','跰'=>'è·°','ð¯§'=>'𠣞','軔'=>'è»”','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'𨗭','邔'=>'é‚”','郱'=>'郱','鄑'=>'é„‘','𨜮'=>'𨜮','鄛'=>'é„›','鈸'=>'鈸','鋗'=>'é‹—','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'é¹','鐕'=>'é•','𨯺'=>'𨯺','開'=>'é–‹','䦕'=>'䦕','閷'=>'é–·','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'å¶²','霣'=>'霣','𩅅'=>'ð©……','𩈚'=>'𩈚','䩮'=>'ä©®','䩶'=>'ä©¶','韠'=>'韠','𩐊'=>'ð©Š','䪲'=>'䪲','𩒖'=>'ð©’–','頋'=>'é ‹','頋'=>'é ‹','頩'=>'é ©','ð¯¨'=>'ð©–¶','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'é§‚','駾'=>'é§¾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'é±€','鳽'=>'é³½','ð¯¨'=>'䳎','䳭'=>'ä³­','ð¯¨'=>'éµ§','ð¯¨'=>'𪃎','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'äµ–','黹'=>'黹','黾'=>'黾','鼅'=>'é¼…','鼏'=>'é¼','鼖'=>'é¼–','鼻'=>'é¼»','ð¯¨'=>'𪘀'); diff --git a/phpBB/includes/utf/data/utf_nfc_qc.php b/phpBB/includes/utf/data/utf_nfc_qc.php deleted file mode 100644 index ff56357ea6..0000000000 --- a/phpBB/includes/utf/data/utf_nfc_qc.php +++ /dev/null @@ -1,2 +0,0 @@ -1,'Í'=>1,'̓'=>1,'Í„'=>1,'Í´'=>1,';'=>1,'·'=>1,'क़'=>1,'ख़'=>1,'ग़'=>1,'ज़'=>1,'ड़'=>1,'à¥'=>1,'फ़'=>1,'य़'=>1,'à§œ'=>1,'à§'=>1,'à§Ÿ'=>1,'ਲ਼'=>1,'ਸ਼'=>1,'à©™'=>1,'ਗ਼'=>1,'à©›'=>1,'ਫ਼'=>1,'à­œ'=>1,'à­'=>1,'གྷ'=>1,'à½'=>1,'དྷ'=>1,'བྷ'=>1,'ཛྷ'=>1,'ཀྵ'=>1,'ཱི'=>1,'ཱུ'=>1,'ྲྀ'=>1,'ླྀ'=>1,'à¾'=>1,'ྒྷ'=>1,'à¾'=>1,'ྡྷ'=>1,'ྦྷ'=>1,'ྫྷ'=>1,'ྐྵ'=>1,'á½±'=>1,'á½³'=>1,'á½µ'=>1,'á½·'=>1,'á½¹'=>1,'á½»'=>1,'á½½'=>1,'á¾»'=>1,'á¾¾'=>1,'Έ'=>1,'á¿‹'=>1,'á¿“'=>1,'á¿›'=>1,'á¿£'=>1,'á¿«'=>1,'á¿®'=>1,'`'=>1,'Ό'=>1,'á¿»'=>1,'´'=>1,' '=>1,'â€'=>1,'Ω'=>1,'K'=>1,'â„«'=>1,'〈'=>1,'〉'=>1,'⫝̸'=>1,'豈'=>1,'ï¤'=>1,'車'=>1,'賈'=>1,'滑'=>1,'串'=>1,'句'=>1,'龜'=>1,'龜'=>1,'契'=>1,'金'=>1,'喇'=>1,'奈'=>1,'ï¤'=>1,'癩'=>1,'ï¤'=>1,'ï¤'=>1,'螺'=>1,'裸'=>1,'邏'=>1,'樂'=>1,'洛'=>1,'烙'=>1,'珞'=>1,'落'=>1,'酪'=>1,'駱'=>1,'亂'=>1,'卵'=>1,'ï¤'=>1,'爛'=>1,'蘭'=>1,'鸞'=>1,'嵐'=>1,'濫'=>1,'藍'=>1,'襤'=>1,'拉'=>1,'臘'=>1,'蠟'=>1,'廊'=>1,'朗'=>1,'浪'=>1,'狼'=>1,'郎'=>1,'來'=>1,'冷'=>1,'勞'=>1,'擄'=>1,'櫓'=>1,'爐'=>1,'盧'=>1,'老'=>1,'蘆'=>1,'虜'=>1,'路'=>1,'露'=>1,'魯'=>1,'鷺'=>1,'碌'=>1,'祿'=>1,'綠'=>1,'菉'=>1,'錄'=>1,'鹿'=>1,'ï¥'=>1,'壟'=>1,'弄'=>1,'籠'=>1,'聾'=>1,'牢'=>1,'磊'=>1,'賂'=>1,'雷'=>1,'壘'=>1,'屢'=>1,'樓'=>1,'ï¥'=>1,'漏'=>1,'ï¥'=>1,'ï¥'=>1,'陋'=>1,'勒'=>1,'肋'=>1,'凜'=>1,'凌'=>1,'稜'=>1,'綾'=>1,'菱'=>1,'陵'=>1,'讀'=>1,'拏'=>1,'樂'=>1,'ï¥'=>1,'丹'=>1,'寧'=>1,'怒'=>1,'率'=>1,'異'=>1,'北'=>1,'磻'=>1,'便'=>1,'復'=>1,'不'=>1,'泌'=>1,'數'=>1,'索'=>1,'參'=>1,'塞'=>1,'省'=>1,'葉'=>1,'說'=>1,'殺'=>1,'辰'=>1,'沈'=>1,'拾'=>1,'若'=>1,'掠'=>1,'略'=>1,'亮'=>1,'兩'=>1,'凉'=>1,'梁'=>1,'糧'=>1,'良'=>1,'諒'=>1,'量'=>1,'勵'=>1,'呂'=>1,'ï¦'=>1,'廬'=>1,'旅'=>1,'濾'=>1,'礪'=>1,'閭'=>1,'驪'=>1,'麗'=>1,'黎'=>1,'力'=>1,'曆'=>1,'歷'=>1,'ï¦'=>1,'年'=>1,'ï¦'=>1,'ï¦'=>1,'撚'=>1,'漣'=>1,'煉'=>1,'璉'=>1,'秊'=>1,'練'=>1,'聯'=>1,'輦'=>1,'蓮'=>1,'連'=>1,'鍊'=>1,'列'=>1,'ï¦'=>1,'咽'=>1,'烈'=>1,'裂'=>1,'說'=>1,'廉'=>1,'念'=>1,'捻'=>1,'殮'=>1,'簾'=>1,'獵'=>1,'令'=>1,'囹'=>1,'寧'=>1,'嶺'=>1,'怜'=>1,'玲'=>1,'瑩'=>1,'羚'=>1,'聆'=>1,'鈴'=>1,'零'=>1,'靈'=>1,'領'=>1,'例'=>1,'禮'=>1,'醴'=>1,'隸'=>1,'惡'=>1,'了'=>1,'僚'=>1,'寮'=>1,'尿'=>1,'料'=>1,'樂'=>1,'ï§€'=>1,'ï§'=>1,'ï§‚'=>1,'遼'=>1,'ï§„'=>1,'ï§…'=>1,'阮'=>1,'劉'=>1,'杻'=>1,'柳'=>1,'ï§Š'=>1,'ï§‹'=>1,'ï§Œ'=>1,'ï§'=>1,'ï§Ž'=>1,'ï§'=>1,'ï§'=>1,'ï§‘'=>1,'ï§’'=>1,'ï§“'=>1,'ï§”'=>1,'ï§•'=>1,'ï§–'=>1,'ï§—'=>1,'律'=>1,'ï§™'=>1,'ï§š'=>1,'ï§›'=>1,'ï§œ'=>1,'ï§'=>1,'ï§ž'=>1,'ï§Ÿ'=>1,'ï§ '=>1,'ï§¡'=>1,'ï§¢'=>1,'ï§£'=>1,'理'=>1,'ï§¥'=>1,'罹'=>1,'ï§§'=>1,'裡'=>1,'ï§©'=>1,'離'=>1,'ï§«'=>1,'溺'=>1,'ï§­'=>1,'ï§®'=>1,'璘'=>1,'ï§°'=>1,'ï§±'=>1,'ï§²'=>1,'ï§³'=>1,'ï§´'=>1,'ï§µ'=>1,'ï§¶'=>1,'ï§·'=>1,'笠'=>1,'ï§¹'=>1,'狀'=>1,'ï§»'=>1,'ï§¼'=>1,'ï§½'=>1,'ï§¾'=>1,'ï§¿'=>1,'切'=>1,'ï¨'=>1,'拓'=>1,'糖'=>1,'宅'=>1,'洞'=>1,'暴'=>1,'輻'=>1,'行'=>1,'降'=>1,'見'=>1,'廓'=>1,'兀'=>1,'ï¨'=>1,'ï¨'=>1,'晴'=>1,'凞'=>1,'猪'=>1,'益'=>1,'礼'=>1,'神'=>1,'祥'=>1,'福'=>1,'靖'=>1,'ï¨'=>1,'羽'=>1,'蘒'=>1,'諸'=>1,'逸'=>1,'都'=>1,'飯'=>1,'飼'=>1,'館'=>1,'鶴'=>1,'侮'=>1,'僧'=>1,'免'=>1,'勉'=>1,'勤'=>1,'卑'=>1,'喝'=>1,'嘆'=>1,'器'=>1,'塀'=>1,'墨'=>1,'層'=>1,'屮'=>1,'悔'=>1,'慨'=>1,'憎'=>1,'ï©€'=>1,'ï©'=>1,'ï©‚'=>1,'暑'=>1,'ï©„'=>1,'ï©…'=>1,'渚'=>1,'漢'=>1,'煮'=>1,'爫'=>1,'琢'=>1,'ï©‹'=>1,'社'=>1,'ï©'=>1,'祈'=>1,'ï©'=>1,'ï©'=>1,'ï©‘'=>1,'ï©’'=>1,'ï©“'=>1,'ï©”'=>1,'ï©•'=>1,'ï©–'=>1,'ï©—'=>1,'縉'=>1,'ï©™'=>1,'署'=>1,'ï©›'=>1,'臭'=>1,'ï©'=>1,'艹'=>1,'著'=>1,'ï© '=>1,'ï©¡'=>1,'ï©¢'=>1,'ï©£'=>1,'賓'=>1,'ï©¥'=>1,'辶'=>1,'ï©§'=>1,'難'=>1,'ï©©'=>1,'頻'=>1,'ï©°'=>1,'况'=>1,'全'=>1,'侀'=>1,'ï©´'=>1,'冀'=>1,'ï©¶'=>1,'ï©·'=>1,'喝'=>1,'啕'=>1,'喙'=>1,'ï©»'=>1,'塚'=>1,'墳'=>1,'奄'=>1,'ï©¿'=>1,'婢'=>1,'ïª'=>1,'廒'=>1,'廙'=>1,'彩'=>1,'徭'=>1,'惘'=>1,'慎'=>1,'愈'=>1,'憎'=>1,'慠'=>1,'懲'=>1,'戴'=>1,'ïª'=>1,'搜'=>1,'ïª'=>1,'ïª'=>1,'晴'=>1,'朗'=>1,'望'=>1,'杖'=>1,'歹'=>1,'殺'=>1,'流'=>1,'滛'=>1,'滋'=>1,'漢'=>1,'瀞'=>1,'煮'=>1,'ïª'=>1,'爵'=>1,'犯'=>1,'猪'=>1,'瑱'=>1,'甆'=>1,'画'=>1,'瘝'=>1,'瘟'=>1,'益'=>1,'盛'=>1,'直'=>1,'睊'=>1,'着'=>1,'磌'=>1,'窱'=>1,'節'=>1,'类'=>1,'絛'=>1,'練'=>1,'缾'=>1,'者'=>1,'荒'=>1,'華'=>1,'蝹'=>1,'襁'=>1,'覆'=>1,'視'=>1,'調'=>1,'諸'=>1,'請'=>1,'謁'=>1,'諾'=>1,'諭'=>1,'謹'=>1,'ï«€'=>1,'ï«'=>1,'ï«‚'=>1,'遲'=>1,'ï«„'=>1,'ï«…'=>1,'陼'=>1,'難'=>1,'靖'=>1,'韛'=>1,'響'=>1,'ï«‹'=>1,'頻'=>1,'ï«'=>1,'龜'=>1,'ï«'=>1,'ï«'=>1,'ï«‘'=>1,'ï«’'=>1,'ï«“'=>1,'ï«”'=>1,'ï«•'=>1,'ï«–'=>1,'ï«—'=>1,'齃'=>1,'ï«™'=>1,'ï¬'=>1,'ײַ'=>1,'שׁ'=>1,'שׂ'=>1,'שּׁ'=>1,'שּׂ'=>1,'אַ'=>1,'אָ'=>1,'אּ'=>1,'בּ'=>1,'גּ'=>1,'דּ'=>1,'הּ'=>1,'וּ'=>1,'זּ'=>1,'טּ'=>1,'יּ'=>1,'ךּ'=>1,'כּ'=>1,'לּ'=>1,'מּ'=>1,'ï­€'=>1,'ï­'=>1,'ï­ƒ'=>1,'ï­„'=>1,'ï­†'=>1,'ï­‡'=>1,'ï­ˆ'=>1,'ï­‰'=>1,'ï­Š'=>1,'ï­‹'=>1,'ï­Œ'=>1,'ï­'=>1,'ï­Ž'=>1,'ð…ž'=>1,'ð…Ÿ'=>1,'ð… '=>1,'ð…¡'=>1,'ð…¢'=>1,'ð…£'=>1,'ð…¤'=>1,'ð†»'=>1,'ð†¼'=>1,'ð†½'=>1,'ð†¾'=>1,'ð†¿'=>1,'ð‡€'=>1,'丽'=>1,'ð¯ '=>1,'乁'=>1,'𠄢'=>1,'你'=>1,'侮'=>1,'侻'=>1,'倂'=>1,'偺'=>1,'備'=>1,'僧'=>1,'像'=>1,'㒞'=>1,'ð¯ '=>1,'免'=>1,'ð¯ '=>1,'ð¯ '=>1,'具'=>1,'𠔜'=>1,'㒹'=>1,'內'=>1,'再'=>1,'𠕋'=>1,'冗'=>1,'冤'=>1,'仌'=>1,'冬'=>1,'况'=>1,'𩇟'=>1,'ð¯ '=>1,'刃'=>1,'㓟'=>1,'刻'=>1,'剆'=>1,'割'=>1,'剷'=>1,'㔕'=>1,'勇'=>1,'勉'=>1,'勤'=>1,'勺'=>1,'包'=>1,'匆'=>1,'北'=>1,'卉'=>1,'卑'=>1,'博'=>1,'即'=>1,'卽'=>1,'卿'=>1,'卿'=>1,'卿'=>1,'𠨬'=>1,'灰'=>1,'及'=>1,'叟'=>1,'𠭣'=>1,'叫'=>1,'叱'=>1,'吆'=>1,'咞'=>1,'吸'=>1,'呈'=>1,'周'=>1,'咢'=>1,'ð¯¡'=>1,'唐'=>1,'啓'=>1,'啣'=>1,'善'=>1,'善'=>1,'喙'=>1,'喫'=>1,'喳'=>1,'嗂'=>1,'圖'=>1,'嘆'=>1,'ð¯¡'=>1,'噑'=>1,'ð¯¡'=>1,'ð¯¡'=>1,'壮'=>1,'城'=>1,'埴'=>1,'堍'=>1,'型'=>1,'堲'=>1,'報'=>1,'墬'=>1,'𡓤'=>1,'売'=>1,'壷'=>1,'夆'=>1,'ð¯¡'=>1,'夢'=>1,'奢'=>1,'𡚨'=>1,'𡛪'=>1,'姬'=>1,'娛'=>1,'娧'=>1,'姘'=>1,'婦'=>1,'㛮'=>1,'㛼'=>1,'嬈'=>1,'嬾'=>1,'嬾'=>1,'𡧈'=>1,'寃'=>1,'寘'=>1,'寧'=>1,'寳'=>1,'𡬘'=>1,'寿'=>1,'将'=>1,'当'=>1,'尢'=>1,'㞁'=>1,'屠'=>1,'屮'=>1,'峀'=>1,'岍'=>1,'𡷤'=>1,'嵃'=>1,'𡷦'=>1,'嵮'=>1,'嵫'=>1,'嵼'=>1,'ð¯¢'=>1,'巢'=>1,'㠯'=>1,'巽'=>1,'帨'=>1,'帽'=>1,'幩'=>1,'㡢'=>1,'𢆃'=>1,'㡼'=>1,'庰'=>1,'庳'=>1,'ð¯¢'=>1,'廊'=>1,'ð¯¢'=>1,'ð¯¢'=>1,'𢌱'=>1,'𢌱'=>1,'舁'=>1,'弢'=>1,'弢'=>1,'㣇'=>1,'𣊸'=>1,'𦇚'=>1,'形'=>1,'彫'=>1,'㣣'=>1,'徚'=>1,'ð¯¢'=>1,'志'=>1,'忹'=>1,'悁'=>1,'㤺'=>1,'㤜'=>1,'悔'=>1,'𢛔'=>1,'惇'=>1,'慈'=>1,'慌'=>1,'慎'=>1,'慌'=>1,'慺'=>1,'憎'=>1,'憲'=>1,'憤'=>1,'憯'=>1,'懞'=>1,'懲'=>1,'懶'=>1,'成'=>1,'戛'=>1,'扝'=>1,'抱'=>1,'拔'=>1,'捐'=>1,'𢬌'=>1,'挽'=>1,'拼'=>1,'捨'=>1,'掃'=>1,'揤'=>1,'𢯱'=>1,'搢'=>1,'揅'=>1,'ð¯£'=>1,'㨮'=>1,'摩'=>1,'摾'=>1,'撝'=>1,'摷'=>1,'㩬'=>1,'敏'=>1,'敬'=>1,'𣀊'=>1,'旣'=>1,'書'=>1,'ð¯£'=>1,'㬙'=>1,'ð¯£'=>1,'ð¯£'=>1,'㫤'=>1,'冒'=>1,'冕'=>1,'最'=>1,'暜'=>1,'肭'=>1,'䏙'=>1,'朗'=>1,'望'=>1,'朡'=>1,'杞'=>1,'杓'=>1,'ð¯£'=>1,'㭉'=>1,'柺'=>1,'枅'=>1,'桒'=>1,'梅'=>1,'𣑭'=>1,'梎'=>1,'栟'=>1,'椔'=>1,'㮝'=>1,'楂'=>1,'榣'=>1,'槪'=>1,'檨'=>1,'𣚣'=>1,'櫛'=>1,'㰘'=>1,'次'=>1,'𣢧'=>1,'歔'=>1,'㱎'=>1,'歲'=>1,'殟'=>1,'殺'=>1,'殻'=>1,'𣪍'=>1,'𡴋'=>1,'𣫺'=>1,'汎'=>1,'𣲼'=>1,'沿'=>1,'泍'=>1,'汧'=>1,'洖'=>1,'派'=>1,'ð¯¤'=>1,'流'=>1,'浩'=>1,'浸'=>1,'涅'=>1,'𣴞'=>1,'洴'=>1,'港'=>1,'湮'=>1,'㴳'=>1,'滋'=>1,'滇'=>1,'ð¯¤'=>1,'淹'=>1,'ð¯¤'=>1,'ð¯¤'=>1,'𣾎'=>1,'濆'=>1,'瀹'=>1,'瀞'=>1,'瀛'=>1,'㶖'=>1,'灊'=>1,'災'=>1,'灷'=>1,'炭'=>1,'𠔥'=>1,'煅'=>1,'ð¯¤'=>1,'熜'=>1,'𤎫'=>1,'爨'=>1,'爵'=>1,'牐'=>1,'𤘈'=>1,'犀'=>1,'犕'=>1,'𤜵'=>1,'𤠔'=>1,'獺'=>1,'王'=>1,'㺬'=>1,'玥'=>1,'㺸'=>1,'㺸'=>1,'瑇'=>1,'瑜'=>1,'瑱'=>1,'璅'=>1,'瓊'=>1,'㼛'=>1,'甤'=>1,'𤰶'=>1,'甾'=>1,'𤲒'=>1,'異'=>1,'𢆟'=>1,'瘐'=>1,'𤾡'=>1,'𤾸'=>1,'𥁄'=>1,'㿼'=>1,'䀈'=>1,'直'=>1,'ð¯¥'=>1,'𥃲'=>1,'𥄙'=>1,'𥄳'=>1,'眞'=>1,'真'=>1,'真'=>1,'睊'=>1,'䀹'=>1,'瞋'=>1,'䁆'=>1,'䂖'=>1,'ð¯¥'=>1,'硎'=>1,'ð¯¥'=>1,'ð¯¥'=>1,'䃣'=>1,'𥘦'=>1,'祖'=>1,'𥚚'=>1,'𥛅'=>1,'福'=>1,'秫'=>1,'䄯'=>1,'穀'=>1,'穊'=>1,'穏'=>1,'𥥼'=>1,'ð¯¥'=>1,'𥪧'=>1,'竮'=>1,'䈂'=>1,'𥮫'=>1,'篆'=>1,'築'=>1,'䈧'=>1,'𥲀'=>1,'糒'=>1,'䊠'=>1,'糨'=>1,'糣'=>1,'紀'=>1,'𥾆'=>1,'絣'=>1,'䌁'=>1,'緇'=>1,'縂'=>1,'繅'=>1,'䌴'=>1,'𦈨'=>1,'𦉇'=>1,'䍙'=>1,'𦋙'=>1,'罺'=>1,'𦌾'=>1,'羕'=>1,'翺'=>1,'者'=>1,'𦓚'=>1,'𦔣'=>1,'聠'=>1,'𦖨'=>1,'聰'=>1,'𣍟'=>1,'ð¯¦'=>1,'育'=>1,'脃'=>1,'䐋'=>1,'脾'=>1,'媵'=>1,'𦞧'=>1,'𦞵'=>1,'𣎓'=>1,'𣎜'=>1,'舁'=>1,'舄'=>1,'ð¯¦'=>1,'䑫'=>1,'ð¯¦'=>1,'ð¯¦'=>1,'芝'=>1,'劳'=>1,'花'=>1,'芳'=>1,'芽'=>1,'苦'=>1,'𦬼'=>1,'若'=>1,'茝'=>1,'荣'=>1,'莭'=>1,'茣'=>1,'ð¯¦'=>1,'菧'=>1,'著'=>1,'荓'=>1,'菊'=>1,'菌'=>1,'菜'=>1,'𦰶'=>1,'𦵫'=>1,'𦳕'=>1,'䔫'=>1,'蓱'=>1,'蓳'=>1,'蔖'=>1,'𧏊'=>1,'蕤'=>1,'𦼬'=>1,'䕝'=>1,'䕡'=>1,'𦾱'=>1,'𧃒'=>1,'䕫'=>1,'虐'=>1,'虜'=>1,'虧'=>1,'虩'=>1,'蚩'=>1,'蚈'=>1,'蜎'=>1,'蛢'=>1,'蝹'=>1,'蜨'=>1,'蝫'=>1,'螆'=>1,'䗗'=>1,'蟡'=>1,'ð¯§'=>1,'䗹'=>1,'衠'=>1,'衣'=>1,'𧙧'=>1,'裗'=>1,'裞'=>1,'䘵'=>1,'裺'=>1,'㒻'=>1,'𧢮'=>1,'𧥦'=>1,'ð¯§'=>1,'䛇'=>1,'ð¯§'=>1,'ð¯§'=>1,'變'=>1,'豕'=>1,'𧲨'=>1,'貫'=>1,'賁'=>1,'贛'=>1,'起'=>1,'𧼯'=>1,'𠠄'=>1,'跋'=>1,'趼'=>1,'跰'=>1,'ð¯§'=>1,'軔'=>1,'輸'=>1,'𨗒'=>1,'𨗭'=>1,'邔'=>1,'郱'=>1,'鄑'=>1,'𨜮'=>1,'鄛'=>1,'鈸'=>1,'鋗'=>1,'鋘'=>1,'鉼'=>1,'鏹'=>1,'鐕'=>1,'𨯺'=>1,'開'=>1,'䦕'=>1,'閷'=>1,'𨵷'=>1,'䧦'=>1,'雃'=>1,'嶲'=>1,'霣'=>1,'𩅅'=>1,'𩈚'=>1,'䩮'=>1,'䩶'=>1,'韠'=>1,'𩐊'=>1,'䪲'=>1,'𩒖'=>1,'頋'=>1,'頋'=>1,'頩'=>1,'ð¯¨'=>1,'飢'=>1,'䬳'=>1,'餩'=>1,'馧'=>1,'駂'=>1,'駾'=>1,'䯎'=>1,'𩬰'=>1,'鬒'=>1,'鱀'=>1,'鳽'=>1,'ð¯¨'=>1,'䳭'=>1,'ð¯¨'=>1,'ð¯¨'=>1,'䳸'=>1,'𪄅'=>1,'𪈎'=>1,'𪊑'=>1,'麻'=>1,'䵖'=>1,'黹'=>1,'黾'=>1,'鼅'=>1,'鼏'=>1,'鼖'=>1,'鼻'=>1,'ð¯¨'=>1,'Ì€'=>0,'Ì'=>0,'Ì‚'=>0,'̃'=>0,'Ì„'=>0,'̆'=>0,'̇'=>0,'̈'=>0,'̉'=>0,'ÌŠ'=>0,'Ì‹'=>0,'ÌŒ'=>0,'Ì'=>0,'Ì‘'=>0,'Ì“'=>0,'Ì”'=>0,'Ì›'=>0,'Ì£'=>0,'̤'=>0,'Ì¥'=>0,'̦'=>0,'̧'=>0,'̨'=>0,'Ì­'=>0,'Ì®'=>0,'̰'=>0,'̱'=>0,'̸'=>0,'Í‚'=>0,'Í…'=>0,'Ù“'=>0,'Ù”'=>0,'Ù•'=>0,'़'=>0,'া'=>0,'à§—'=>0,'ା'=>0,'à­–'=>0,'à­—'=>0,'ா'=>0,'ௗ'=>0,'à±–'=>0,'ೂ'=>0,'ೕ'=>0,'à³–'=>0,'à´¾'=>0,'ൗ'=>0,'à·Š'=>0,'à·'=>0,'à·Ÿ'=>0,'ီ'=>0,'á…¡'=>0,'á…¢'=>0,'á…£'=>0,'á…¤'=>0,'á…¥'=>0,'á…¦'=>0,'á…§'=>0,'á…¨'=>0,'á…©'=>0,'á…ª'=>0,'á…«'=>0,'á…¬'=>0,'á…­'=>0,'á…®'=>0,'á…¯'=>0,'á…°'=>0,'á…±'=>0,'á…²'=>0,'á…³'=>0,'á…´'=>0,'á…µ'=>0,'ᆨ'=>0,'ᆩ'=>0,'ᆪ'=>0,'ᆫ'=>0,'ᆬ'=>0,'ᆭ'=>0,'ᆮ'=>0,'ᆯ'=>0,'ᆰ'=>0,'ᆱ'=>0,'ᆲ'=>0,'ᆳ'=>0,'ᆴ'=>0,'ᆵ'=>0,'ᆶ'=>0,'ᆷ'=>0,'ᆸ'=>0,'ᆹ'=>0,'ᆺ'=>0,'ᆻ'=>0,'ᆼ'=>0,'ᆽ'=>0,'ᆾ'=>0,'ᆿ'=>0,'ᇀ'=>0,'á‡'=>0,'ᇂ'=>0,'ᬵ'=>0,'ã‚™'=>0,'゚'=>0); diff --git a/phpBB/includes/utf/data/utf_nfkc_qc.php b/phpBB/includes/utf/data/utf_nfkc_qc.php deleted file mode 100644 index 181a07b351..0000000000 --- a/phpBB/includes/utf/data/utf_nfkc_qc.php +++ /dev/null @@ -1,2 +0,0 @@ -1,'¨'=>1,'ª'=>1,'¯'=>1,'²'=>1,'³'=>1,'´'=>1,'µ'=>1,'¸'=>1,'¹'=>1,'º'=>1,'¼'=>1,'½'=>1,'¾'=>1,'IJ'=>1,'ij'=>1,'Ä¿'=>1,'Å€'=>1,'ʼn'=>1,'Å¿'=>1,'Ç„'=>1,'Ç…'=>1,'dž'=>1,'LJ'=>1,'Lj'=>1,'lj'=>1,'ÇŠ'=>1,'Ç‹'=>1,'ÇŒ'=>1,'DZ'=>1,'Dz'=>1,'dz'=>1,'ʰ'=>1,'ʱ'=>1,'ʲ'=>1,'ʳ'=>1,'Ê´'=>1,'ʵ'=>1,'ʶ'=>1,'Ê·'=>1,'ʸ'=>1,'˘'=>1,'Ë™'=>1,'Ëš'=>1,'Ë›'=>1,'Ëœ'=>1,'Ë'=>1,'Ë '=>1,'Ë¡'=>1,'Ë¢'=>1,'Ë£'=>1,'ˤ'=>1,'Í€'=>1,'Í'=>1,'̓'=>1,'Í„'=>1,'Í´'=>1,'ͺ'=>1,';'=>1,'΄'=>1,'Î…'=>1,'·'=>1,'Ï'=>1,'Ï‘'=>1,'Ï’'=>1,'Ï“'=>1,'Ï”'=>1,'Ï•'=>1,'Ï–'=>1,'ϰ'=>1,'ϱ'=>1,'ϲ'=>1,'Ï´'=>1,'ϵ'=>1,'Ϲ'=>1,'Ö‡'=>1,'Ùµ'=>1,'Ù¶'=>1,'Ù·'=>1,'Ù¸'=>1,'क़'=>1,'ख़'=>1,'ग़'=>1,'ज़'=>1,'ड़'=>1,'à¥'=>1,'फ़'=>1,'य़'=>1,'à§œ'=>1,'à§'=>1,'à§Ÿ'=>1,'ਲ਼'=>1,'ਸ਼'=>1,'à©™'=>1,'ਗ਼'=>1,'à©›'=>1,'ਫ਼'=>1,'à­œ'=>1,'à­'=>1,'ำ'=>1,'ຳ'=>1,'ໜ'=>1,'à»'=>1,'༌'=>1,'གྷ'=>1,'à½'=>1,'དྷ'=>1,'བྷ'=>1,'ཛྷ'=>1,'ཀྵ'=>1,'ཱི'=>1,'ཱུ'=>1,'ྲྀ'=>1,'ཷ'=>1,'ླྀ'=>1,'ཹ'=>1,'à¾'=>1,'ྒྷ'=>1,'à¾'=>1,'ྡྷ'=>1,'ྦྷ'=>1,'ྫྷ'=>1,'ྐྵ'=>1,'ჼ'=>1,'á´¬'=>1,'á´­'=>1,'á´®'=>1,'á´°'=>1,'á´±'=>1,'á´²'=>1,'á´³'=>1,'á´´'=>1,'á´µ'=>1,'á´¶'=>1,'á´·'=>1,'á´¸'=>1,'á´¹'=>1,'á´º'=>1,'á´¼'=>1,'á´½'=>1,'á´¾'=>1,'á´¿'=>1,'áµ€'=>1,'áµ'=>1,'ᵂ'=>1,'ᵃ'=>1,'ᵄ'=>1,'áµ…'=>1,'ᵆ'=>1,'ᵇ'=>1,'ᵈ'=>1,'ᵉ'=>1,'ᵊ'=>1,'ᵋ'=>1,'ᵌ'=>1,'áµ'=>1,'áµ'=>1,'áµ'=>1,'ᵑ'=>1,'áµ’'=>1,'ᵓ'=>1,'áµ”'=>1,'ᵕ'=>1,'áµ–'=>1,'áµ—'=>1,'ᵘ'=>1,'áµ™'=>1,'ᵚ'=>1,'áµ›'=>1,'ᵜ'=>1,'áµ'=>1,'ᵞ'=>1,'ᵟ'=>1,'áµ '=>1,'ᵡ'=>1,'áµ¢'=>1,'áµ£'=>1,'ᵤ'=>1,'áµ¥'=>1,'ᵦ'=>1,'áµ§'=>1,'ᵨ'=>1,'ᵩ'=>1,'ᵪ'=>1,'ᵸ'=>1,'á¶›'=>1,'á¶œ'=>1,'á¶'=>1,'á¶ž'=>1,'á¶Ÿ'=>1,'á¶ '=>1,'á¶¡'=>1,'á¶¢'=>1,'á¶£'=>1,'ᶤ'=>1,'á¶¥'=>1,'ᶦ'=>1,'á¶§'=>1,'ᶨ'=>1,'á¶©'=>1,'ᶪ'=>1,'á¶«'=>1,'ᶬ'=>1,'á¶­'=>1,'á¶®'=>1,'ᶯ'=>1,'á¶°'=>1,'á¶±'=>1,'á¶²'=>1,'á¶³'=>1,'á¶´'=>1,'á¶µ'=>1,'á¶¶'=>1,'á¶·'=>1,'ᶸ'=>1,'á¶¹'=>1,'ᶺ'=>1,'á¶»'=>1,'á¶¼'=>1,'á¶½'=>1,'á¶¾'=>1,'á¶¿'=>1,'ẚ'=>1,'ẛ'=>1,'á½±'=>1,'á½³'=>1,'á½µ'=>1,'á½·'=>1,'á½¹'=>1,'á½»'=>1,'á½½'=>1,'á¾»'=>1,'á¾½'=>1,'á¾¾'=>1,'᾿'=>1,'á¿€'=>1,'á¿'=>1,'Έ'=>1,'á¿‹'=>1,'á¿'=>1,'῎'=>1,'á¿'=>1,'á¿“'=>1,'á¿›'=>1,'á¿'=>1,'῞'=>1,'῟'=>1,'á¿£'=>1,'á¿«'=>1,'á¿­'=>1,'á¿®'=>1,'`'=>1,'Ό'=>1,'á¿»'=>1,'´'=>1,'῾'=>1,' '=>1,'â€'=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,'‑'=>1,'‗'=>1,'․'=>1,'‥'=>1,'…'=>1,' '=>1,'″'=>1,'‴'=>1,'‶'=>1,'‷'=>1,'‼'=>1,'‾'=>1,'â‡'=>1,'âˆ'=>1,'â‰'=>1,'â—'=>1,'âŸ'=>1,'â°'=>1,'â±'=>1,'â´'=>1,'âµ'=>1,'â¶'=>1,'â·'=>1,'â¸'=>1,'â¹'=>1,'âº'=>1,'â»'=>1,'â¼'=>1,'â½'=>1,'â¾'=>1,'â¿'=>1,'â‚€'=>1,'â‚'=>1,'â‚‚'=>1,'₃'=>1,'â‚„'=>1,'â‚…'=>1,'₆'=>1,'₇'=>1,'₈'=>1,'₉'=>1,'₊'=>1,'â‚‹'=>1,'₌'=>1,'â‚'=>1,'₎'=>1,'â‚'=>1,'â‚‘'=>1,'â‚’'=>1,'â‚“'=>1,'â‚”'=>1,'₨'=>1,'â„€'=>1,'â„'=>1,'â„‚'=>1,'℃'=>1,'â„…'=>1,'℆'=>1,'ℇ'=>1,'℉'=>1,'ℊ'=>1,'â„‹'=>1,'ℌ'=>1,'â„'=>1,'ℎ'=>1,'â„'=>1,'â„'=>1,'â„‘'=>1,'â„’'=>1,'â„“'=>1,'â„•'=>1,'â„–'=>1,'â„™'=>1,'ℚ'=>1,'â„›'=>1,'ℜ'=>1,'â„'=>1,'â„ '=>1,'â„¡'=>1,'â„¢'=>1,'ℤ'=>1,'Ω'=>1,'ℨ'=>1,'K'=>1,'â„«'=>1,'ℬ'=>1,'â„­'=>1,'ℯ'=>1,'â„°'=>1,'ℱ'=>1,'ℳ'=>1,'â„´'=>1,'ℵ'=>1,'â„¶'=>1,'â„·'=>1,'ℸ'=>1,'ℹ'=>1,'â„»'=>1,'ℼ'=>1,'ℽ'=>1,'ℾ'=>1,'â„¿'=>1,'â…€'=>1,'â……'=>1,'â…†'=>1,'â…‡'=>1,'â…ˆ'=>1,'â…‰'=>1,'â…“'=>1,'â…”'=>1,'â…•'=>1,'â…–'=>1,'â…—'=>1,'â…˜'=>1,'â…™'=>1,'â…š'=>1,'â…›'=>1,'â…œ'=>1,'â…'=>1,'â…ž'=>1,'â…Ÿ'=>1,'â… '=>1,'â…¡'=>1,'â…¢'=>1,'â…£'=>1,'â…¤'=>1,'â…¥'=>1,'â…¦'=>1,'â…§'=>1,'â…¨'=>1,'â…©'=>1,'â…ª'=>1,'â…«'=>1,'â…¬'=>1,'â…­'=>1,'â…®'=>1,'â…¯'=>1,'â…°'=>1,'â…±'=>1,'â…²'=>1,'â…³'=>1,'â…´'=>1,'â…µ'=>1,'â…¶'=>1,'â…·'=>1,'â…¸'=>1,'â…¹'=>1,'â…º'=>1,'â…»'=>1,'â…¼'=>1,'â…½'=>1,'â…¾'=>1,'â…¿'=>1,'∬'=>1,'∭'=>1,'∯'=>1,'∰'=>1,'〈'=>1,'〉'=>1,'â‘ '=>1,'â‘¡'=>1,'â‘¢'=>1,'â‘£'=>1,'⑤'=>1,'â‘¥'=>1,'⑦'=>1,'â‘§'=>1,'⑨'=>1,'â‘©'=>1,'⑪'=>1,'â‘«'=>1,'⑬'=>1,'â‘­'=>1,'â‘®'=>1,'⑯'=>1,'â‘°'=>1,'⑱'=>1,'⑲'=>1,'⑳'=>1,'â‘´'=>1,'⑵'=>1,'â‘¶'=>1,'â‘·'=>1,'⑸'=>1,'⑹'=>1,'⑺'=>1,'â‘»'=>1,'⑼'=>1,'⑽'=>1,'⑾'=>1,'â‘¿'=>1,'â’€'=>1,'â’'=>1,'â’‚'=>1,'â’ƒ'=>1,'â’„'=>1,'â’…'=>1,'â’†'=>1,'â’‡'=>1,'â’ˆ'=>1,'â’‰'=>1,'â’Š'=>1,'â’‹'=>1,'â’Œ'=>1,'â’'=>1,'â’Ž'=>1,'â’'=>1,'â’'=>1,'â’‘'=>1,'â’’'=>1,'â’“'=>1,'â’”'=>1,'â’•'=>1,'â’–'=>1,'â’—'=>1,'â’˜'=>1,'â’™'=>1,'â’š'=>1,'â’›'=>1,'â’œ'=>1,'â’'=>1,'â’ž'=>1,'â’Ÿ'=>1,'â’ '=>1,'â’¡'=>1,'â’¢'=>1,'â’£'=>1,'â’¤'=>1,'â’¥'=>1,'â’¦'=>1,'â’§'=>1,'â’¨'=>1,'â’©'=>1,'â’ª'=>1,'â’«'=>1,'â’¬'=>1,'â’­'=>1,'â’®'=>1,'â’¯'=>1,'â’°'=>1,'â’±'=>1,'â’²'=>1,'â’³'=>1,'â’´'=>1,'â’µ'=>1,'â’¶'=>1,'â’·'=>1,'â’¸'=>1,'â’¹'=>1,'â’º'=>1,'â’»'=>1,'â’¼'=>1,'â’½'=>1,'â’¾'=>1,'â’¿'=>1,'â“€'=>1,'â“'=>1,'â“‚'=>1,'Ⓝ'=>1,'â“„'=>1,'â“…'=>1,'Ⓠ'=>1,'Ⓡ'=>1,'Ⓢ'=>1,'Ⓣ'=>1,'Ⓤ'=>1,'â“‹'=>1,'Ⓦ'=>1,'â“'=>1,'Ⓨ'=>1,'â“'=>1,'â“'=>1,'â“‘'=>1,'â“’'=>1,'â““'=>1,'â“”'=>1,'â“•'=>1,'â“–'=>1,'â“—'=>1,'ⓘ'=>1,'â“™'=>1,'ⓚ'=>1,'â“›'=>1,'ⓜ'=>1,'â“'=>1,'ⓞ'=>1,'ⓟ'=>1,'â“ '=>1,'â“¡'=>1,'â“¢'=>1,'â“£'=>1,'ⓤ'=>1,'â“¥'=>1,'ⓦ'=>1,'â“§'=>1,'ⓨ'=>1,'â“©'=>1,'⓪'=>1,'⨌'=>1,'â©´'=>1,'⩵'=>1,'â©¶'=>1,'⫝̸'=>1,'ⵯ'=>1,'⺟'=>1,'⻳'=>1,'â¼€'=>1,'â¼'=>1,'⼂'=>1,'⼃'=>1,'⼄'=>1,'â¼…'=>1,'⼆'=>1,'⼇'=>1,'⼈'=>1,'⼉'=>1,'⼊'=>1,'⼋'=>1,'⼌'=>1,'â¼'=>1,'⼎'=>1,'â¼'=>1,'â¼'=>1,'⼑'=>1,'â¼’'=>1,'⼓'=>1,'â¼”'=>1,'⼕'=>1,'â¼–'=>1,'â¼—'=>1,'⼘'=>1,'â¼™'=>1,'⼚'=>1,'â¼›'=>1,'⼜'=>1,'â¼'=>1,'⼞'=>1,'⼟'=>1,'â¼ '=>1,'⼡'=>1,'â¼¢'=>1,'â¼£'=>1,'⼤'=>1,'â¼¥'=>1,'⼦'=>1,'â¼§'=>1,'⼨'=>1,'⼩'=>1,'⼪'=>1,'⼫'=>1,'⼬'=>1,'â¼­'=>1,'â¼®'=>1,'⼯'=>1,'â¼°'=>1,'â¼±'=>1,'â¼²'=>1,'â¼³'=>1,'â¼´'=>1,'â¼µ'=>1,'â¼¶'=>1,'â¼·'=>1,'⼸'=>1,'â¼¹'=>1,'⼺'=>1,'â¼»'=>1,'â¼¼'=>1,'â¼½'=>1,'â¼¾'=>1,'⼿'=>1,'â½€'=>1,'â½'=>1,'⽂'=>1,'⽃'=>1,'⽄'=>1,'â½…'=>1,'⽆'=>1,'⽇'=>1,'⽈'=>1,'⽉'=>1,'⽊'=>1,'⽋'=>1,'⽌'=>1,'â½'=>1,'⽎'=>1,'â½'=>1,'â½'=>1,'⽑'=>1,'â½’'=>1,'⽓'=>1,'â½”'=>1,'⽕'=>1,'â½–'=>1,'â½—'=>1,'⽘'=>1,'â½™'=>1,'⽚'=>1,'â½›'=>1,'⽜'=>1,'â½'=>1,'⽞'=>1,'⽟'=>1,'â½ '=>1,'⽡'=>1,'â½¢'=>1,'â½£'=>1,'⽤'=>1,'â½¥'=>1,'⽦'=>1,'â½§'=>1,'⽨'=>1,'⽩'=>1,'⽪'=>1,'⽫'=>1,'⽬'=>1,'â½­'=>1,'â½®'=>1,'⽯'=>1,'â½°'=>1,'â½±'=>1,'â½²'=>1,'â½³'=>1,'â½´'=>1,'â½µ'=>1,'â½¶'=>1,'â½·'=>1,'⽸'=>1,'â½¹'=>1,'⽺'=>1,'â½»'=>1,'â½¼'=>1,'â½½'=>1,'â½¾'=>1,'⽿'=>1,'â¾€'=>1,'â¾'=>1,'⾂'=>1,'⾃'=>1,'⾄'=>1,'â¾…'=>1,'⾆'=>1,'⾇'=>1,'⾈'=>1,'⾉'=>1,'⾊'=>1,'⾋'=>1,'⾌'=>1,'â¾'=>1,'⾎'=>1,'â¾'=>1,'â¾'=>1,'⾑'=>1,'â¾’'=>1,'⾓'=>1,'â¾”'=>1,'⾕'=>1,'â¾–'=>1,'â¾—'=>1,'⾘'=>1,'â¾™'=>1,'⾚'=>1,'â¾›'=>1,'⾜'=>1,'â¾'=>1,'⾞'=>1,'⾟'=>1,'â¾ '=>1,'⾡'=>1,'â¾¢'=>1,'â¾£'=>1,'⾤'=>1,'â¾¥'=>1,'⾦'=>1,'â¾§'=>1,'⾨'=>1,'⾩'=>1,'⾪'=>1,'⾫'=>1,'⾬'=>1,'â¾­'=>1,'â¾®'=>1,'⾯'=>1,'â¾°'=>1,'â¾±'=>1,'â¾²'=>1,'â¾³'=>1,'â¾´'=>1,'â¾µ'=>1,'â¾¶'=>1,'â¾·'=>1,'⾸'=>1,'â¾¹'=>1,'⾺'=>1,'â¾»'=>1,'â¾¼'=>1,'â¾½'=>1,'â¾¾'=>1,'⾿'=>1,'â¿€'=>1,'â¿'=>1,'â¿‚'=>1,'⿃'=>1,'â¿„'=>1,'â¿…'=>1,'⿆'=>1,'⿇'=>1,'⿈'=>1,'⿉'=>1,'⿊'=>1,'â¿‹'=>1,'⿌'=>1,'â¿'=>1,'⿎'=>1,'â¿'=>1,'â¿'=>1,'â¿‘'=>1,'â¿’'=>1,'â¿“'=>1,'â¿”'=>1,'â¿•'=>1,' '=>1,'〶'=>1,'〸'=>1,'〹'=>1,'〺'=>1,'ã‚›'=>1,'゜'=>1,'ゟ'=>1,'ヿ'=>1,'ㄱ'=>1,'ㄲ'=>1,'ㄳ'=>1,'ã„´'=>1,'ㄵ'=>1,'ã„¶'=>1,'ã„·'=>1,'ㄸ'=>1,'ㄹ'=>1,'ㄺ'=>1,'ã„»'=>1,'ㄼ'=>1,'ㄽ'=>1,'ㄾ'=>1,'ã„¿'=>1,'ã…€'=>1,'ã…'=>1,'ã…‚'=>1,'ã…ƒ'=>1,'ã…„'=>1,'ã……'=>1,'ã…†'=>1,'ã…‡'=>1,'ã…ˆ'=>1,'ã…‰'=>1,'ã…Š'=>1,'ã…‹'=>1,'ã…Œ'=>1,'ã…'=>1,'ã…Ž'=>1,'ã…'=>1,'ã…'=>1,'ã…‘'=>1,'ã…’'=>1,'ã…“'=>1,'ã…”'=>1,'ã…•'=>1,'ã…–'=>1,'ã…—'=>1,'ã…˜'=>1,'ã…™'=>1,'ã…š'=>1,'ã…›'=>1,'ã…œ'=>1,'ã…'=>1,'ã…ž'=>1,'ã…Ÿ'=>1,'ã… '=>1,'ã…¡'=>1,'ã…¢'=>1,'ã…£'=>1,'ã…¤'=>1,'ã…¥'=>1,'ã…¦'=>1,'ã…§'=>1,'ã…¨'=>1,'ã…©'=>1,'ã…ª'=>1,'ã…«'=>1,'ã…¬'=>1,'ã…­'=>1,'ã…®'=>1,'ã…¯'=>1,'ã…°'=>1,'ã…±'=>1,'ã…²'=>1,'ã…³'=>1,'ã…´'=>1,'ã…µ'=>1,'ã…¶'=>1,'ã…·'=>1,'ã…¸'=>1,'ã…¹'=>1,'ã…º'=>1,'ã…»'=>1,'ã…¼'=>1,'ã…½'=>1,'ã…¾'=>1,'ã…¿'=>1,'ㆀ'=>1,'ã†'=>1,'ㆂ'=>1,'ㆃ'=>1,'ㆄ'=>1,'ㆅ'=>1,'ㆆ'=>1,'ㆇ'=>1,'ㆈ'=>1,'ㆉ'=>1,'ㆊ'=>1,'ㆋ'=>1,'ㆌ'=>1,'ã†'=>1,'ㆎ'=>1,'㆒'=>1,'㆓'=>1,'㆔'=>1,'㆕'=>1,'㆖'=>1,'㆗'=>1,'㆘'=>1,'㆙'=>1,'㆚'=>1,'㆛'=>1,'㆜'=>1,'ã†'=>1,'㆞'=>1,'㆟'=>1,'㈀'=>1,'ãˆ'=>1,'㈂'=>1,'㈃'=>1,'㈄'=>1,'㈅'=>1,'㈆'=>1,'㈇'=>1,'㈈'=>1,'㈉'=>1,'㈊'=>1,'㈋'=>1,'㈌'=>1,'ãˆ'=>1,'㈎'=>1,'ãˆ'=>1,'ãˆ'=>1,'㈑'=>1,'㈒'=>1,'㈓'=>1,'㈔'=>1,'㈕'=>1,'㈖'=>1,'㈗'=>1,'㈘'=>1,'㈙'=>1,'㈚'=>1,'㈛'=>1,'㈜'=>1,'ãˆ'=>1,'㈞'=>1,'㈠'=>1,'㈡'=>1,'㈢'=>1,'㈣'=>1,'㈤'=>1,'㈥'=>1,'㈦'=>1,'㈧'=>1,'㈨'=>1,'㈩'=>1,'㈪'=>1,'㈫'=>1,'㈬'=>1,'㈭'=>1,'㈮'=>1,'㈯'=>1,'㈰'=>1,'㈱'=>1,'㈲'=>1,'㈳'=>1,'㈴'=>1,'㈵'=>1,'㈶'=>1,'㈷'=>1,'㈸'=>1,'㈹'=>1,'㈺'=>1,'㈻'=>1,'㈼'=>1,'㈽'=>1,'㈾'=>1,'㈿'=>1,'㉀'=>1,'ã‰'=>1,'㉂'=>1,'㉃'=>1,'ã‰'=>1,'㉑'=>1,'㉒'=>1,'㉓'=>1,'㉔'=>1,'㉕'=>1,'㉖'=>1,'㉗'=>1,'㉘'=>1,'㉙'=>1,'㉚'=>1,'㉛'=>1,'㉜'=>1,'ã‰'=>1,'㉞'=>1,'㉟'=>1,'㉠'=>1,'㉡'=>1,'㉢'=>1,'㉣'=>1,'㉤'=>1,'㉥'=>1,'㉦'=>1,'㉧'=>1,'㉨'=>1,'㉩'=>1,'㉪'=>1,'㉫'=>1,'㉬'=>1,'㉭'=>1,'㉮'=>1,'㉯'=>1,'㉰'=>1,'㉱'=>1,'㉲'=>1,'㉳'=>1,'㉴'=>1,'㉵'=>1,'㉶'=>1,'㉷'=>1,'㉸'=>1,'㉹'=>1,'㉺'=>1,'㉻'=>1,'㉼'=>1,'㉽'=>1,'㉾'=>1,'㊀'=>1,'ãŠ'=>1,'㊂'=>1,'㊃'=>1,'㊄'=>1,'㊅'=>1,'㊆'=>1,'㊇'=>1,'㊈'=>1,'㊉'=>1,'㊊'=>1,'㊋'=>1,'㊌'=>1,'ãŠ'=>1,'㊎'=>1,'ãŠ'=>1,'ãŠ'=>1,'㊑'=>1,'㊒'=>1,'㊓'=>1,'㊔'=>1,'㊕'=>1,'㊖'=>1,'㊗'=>1,'㊘'=>1,'㊙'=>1,'㊚'=>1,'㊛'=>1,'㊜'=>1,'ãŠ'=>1,'㊞'=>1,'㊟'=>1,'㊠'=>1,'㊡'=>1,'㊢'=>1,'㊣'=>1,'㊤'=>1,'㊥'=>1,'㊦'=>1,'㊧'=>1,'㊨'=>1,'㊩'=>1,'㊪'=>1,'㊫'=>1,'㊬'=>1,'㊭'=>1,'㊮'=>1,'㊯'=>1,'㊰'=>1,'㊱'=>1,'㊲'=>1,'㊳'=>1,'㊴'=>1,'㊵'=>1,'㊶'=>1,'㊷'=>1,'㊸'=>1,'㊹'=>1,'㊺'=>1,'㊻'=>1,'㊼'=>1,'㊽'=>1,'㊾'=>1,'㊿'=>1,'ã‹€'=>1,'ã‹'=>1,'ã‹‚'=>1,'㋃'=>1,'ã‹„'=>1,'ã‹…'=>1,'㋆'=>1,'㋇'=>1,'㋈'=>1,'㋉'=>1,'㋊'=>1,'ã‹‹'=>1,'㋌'=>1,'ã‹'=>1,'㋎'=>1,'ã‹'=>1,'ã‹'=>1,'ã‹‘'=>1,'ã‹’'=>1,'ã‹“'=>1,'ã‹”'=>1,'ã‹•'=>1,'ã‹–'=>1,'ã‹—'=>1,'㋘'=>1,'ã‹™'=>1,'㋚'=>1,'ã‹›'=>1,'㋜'=>1,'ã‹'=>1,'㋞'=>1,'㋟'=>1,'ã‹ '=>1,'ã‹¡'=>1,'ã‹¢'=>1,'ã‹£'=>1,'㋤'=>1,'ã‹¥'=>1,'㋦'=>1,'ã‹§'=>1,'㋨'=>1,'ã‹©'=>1,'㋪'=>1,'ã‹«'=>1,'㋬'=>1,'ã‹­'=>1,'ã‹®'=>1,'㋯'=>1,'ã‹°'=>1,'㋱'=>1,'㋲'=>1,'㋳'=>1,'ã‹´'=>1,'㋵'=>1,'ã‹¶'=>1,'ã‹·'=>1,'㋸'=>1,'㋹'=>1,'㋺'=>1,'ã‹»'=>1,'㋼'=>1,'㋽'=>1,'㋾'=>1,'㌀'=>1,'ãŒ'=>1,'㌂'=>1,'㌃'=>1,'㌄'=>1,'㌅'=>1,'㌆'=>1,'㌇'=>1,'㌈'=>1,'㌉'=>1,'㌊'=>1,'㌋'=>1,'㌌'=>1,'ãŒ'=>1,'㌎'=>1,'ãŒ'=>1,'ãŒ'=>1,'㌑'=>1,'㌒'=>1,'㌓'=>1,'㌔'=>1,'㌕'=>1,'㌖'=>1,'㌗'=>1,'㌘'=>1,'㌙'=>1,'㌚'=>1,'㌛'=>1,'㌜'=>1,'ãŒ'=>1,'㌞'=>1,'㌟'=>1,'㌠'=>1,'㌡'=>1,'㌢'=>1,'㌣'=>1,'㌤'=>1,'㌥'=>1,'㌦'=>1,'㌧'=>1,'㌨'=>1,'㌩'=>1,'㌪'=>1,'㌫'=>1,'㌬'=>1,'㌭'=>1,'㌮'=>1,'㌯'=>1,'㌰'=>1,'㌱'=>1,'㌲'=>1,'㌳'=>1,'㌴'=>1,'㌵'=>1,'㌶'=>1,'㌷'=>1,'㌸'=>1,'㌹'=>1,'㌺'=>1,'㌻'=>1,'㌼'=>1,'㌽'=>1,'㌾'=>1,'㌿'=>1,'ã€'=>1,'ã'=>1,'ã‚'=>1,'ãƒ'=>1,'ã„'=>1,'ã…'=>1,'ã†'=>1,'ã‡'=>1,'ãˆ'=>1,'ã‰'=>1,'ãŠ'=>1,'ã‹'=>1,'ãŒ'=>1,'ã'=>1,'ãŽ'=>1,'ã'=>1,'ã'=>1,'ã‘'=>1,'ã’'=>1,'ã“'=>1,'ã”'=>1,'ã•'=>1,'ã–'=>1,'ã—'=>1,'ã˜'=>1,'ã™'=>1,'ãš'=>1,'ã›'=>1,'ãœ'=>1,'ã'=>1,'ãž'=>1,'ãŸ'=>1,'ã '=>1,'ã¡'=>1,'ã¢'=>1,'ã£'=>1,'ã¤'=>1,'ã¥'=>1,'ã¦'=>1,'ã§'=>1,'ã¨'=>1,'ã©'=>1,'ãª'=>1,'ã«'=>1,'ã¬'=>1,'ã­'=>1,'ã®'=>1,'ã¯'=>1,'ã°'=>1,'ã±'=>1,'ã²'=>1,'ã³'=>1,'ã´'=>1,'ãµ'=>1,'ã¶'=>1,'ã·'=>1,'ã¸'=>1,'ã¹'=>1,'ãº'=>1,'ã»'=>1,'ã¼'=>1,'ã½'=>1,'ã¾'=>1,'ã¿'=>1,'㎀'=>1,'ãŽ'=>1,'㎂'=>1,'㎃'=>1,'㎄'=>1,'㎅'=>1,'㎆'=>1,'㎇'=>1,'㎈'=>1,'㎉'=>1,'㎊'=>1,'㎋'=>1,'㎌'=>1,'ãŽ'=>1,'㎎'=>1,'ãŽ'=>1,'ãŽ'=>1,'㎑'=>1,'㎒'=>1,'㎓'=>1,'㎔'=>1,'㎕'=>1,'㎖'=>1,'㎗'=>1,'㎘'=>1,'㎙'=>1,'㎚'=>1,'㎛'=>1,'㎜'=>1,'ãŽ'=>1,'㎞'=>1,'㎟'=>1,'㎠'=>1,'㎡'=>1,'㎢'=>1,'㎣'=>1,'㎤'=>1,'㎥'=>1,'㎦'=>1,'㎧'=>1,'㎨'=>1,'㎩'=>1,'㎪'=>1,'㎫'=>1,'㎬'=>1,'㎭'=>1,'㎮'=>1,'㎯'=>1,'㎰'=>1,'㎱'=>1,'㎲'=>1,'㎳'=>1,'㎴'=>1,'㎵'=>1,'㎶'=>1,'㎷'=>1,'㎸'=>1,'㎹'=>1,'㎺'=>1,'㎻'=>1,'㎼'=>1,'㎽'=>1,'㎾'=>1,'㎿'=>1,'ã€'=>1,'ã'=>1,'ã‚'=>1,'ãƒ'=>1,'ã„'=>1,'ã…'=>1,'ã†'=>1,'ã‡'=>1,'ãˆ'=>1,'ã‰'=>1,'ãŠ'=>1,'ã‹'=>1,'ãŒ'=>1,'ã'=>1,'ãŽ'=>1,'ã'=>1,'ã'=>1,'ã‘'=>1,'ã’'=>1,'ã“'=>1,'ã”'=>1,'ã•'=>1,'ã–'=>1,'ã—'=>1,'ã˜'=>1,'ã™'=>1,'ãš'=>1,'ã›'=>1,'ãœ'=>1,'ã'=>1,'ãž'=>1,'ãŸ'=>1,'ã '=>1,'ã¡'=>1,'ã¢'=>1,'ã£'=>1,'ã¤'=>1,'ã¥'=>1,'ã¦'=>1,'ã§'=>1,'ã¨'=>1,'ã©'=>1,'ãª'=>1,'ã«'=>1,'ã¬'=>1,'ã­'=>1,'ã®'=>1,'ã¯'=>1,'ã°'=>1,'ã±'=>1,'ã²'=>1,'ã³'=>1,'ã´'=>1,'ãµ'=>1,'ã¶'=>1,'ã·'=>1,'ã¸'=>1,'ã¹'=>1,'ãº'=>1,'ã»'=>1,'ã¼'=>1,'ã½'=>1,'ã¾'=>1,'ã¿'=>1,'豈'=>1,'ï¤'=>1,'車'=>1,'賈'=>1,'滑'=>1,'串'=>1,'句'=>1,'龜'=>1,'龜'=>1,'契'=>1,'金'=>1,'喇'=>1,'奈'=>1,'ï¤'=>1,'癩'=>1,'ï¤'=>1,'ï¤'=>1,'螺'=>1,'裸'=>1,'邏'=>1,'樂'=>1,'洛'=>1,'烙'=>1,'珞'=>1,'落'=>1,'酪'=>1,'駱'=>1,'亂'=>1,'卵'=>1,'ï¤'=>1,'爛'=>1,'蘭'=>1,'鸞'=>1,'嵐'=>1,'濫'=>1,'藍'=>1,'襤'=>1,'拉'=>1,'臘'=>1,'蠟'=>1,'廊'=>1,'朗'=>1,'浪'=>1,'狼'=>1,'郎'=>1,'來'=>1,'冷'=>1,'勞'=>1,'擄'=>1,'櫓'=>1,'爐'=>1,'盧'=>1,'老'=>1,'蘆'=>1,'虜'=>1,'路'=>1,'露'=>1,'魯'=>1,'鷺'=>1,'碌'=>1,'祿'=>1,'綠'=>1,'菉'=>1,'錄'=>1,'鹿'=>1,'ï¥'=>1,'壟'=>1,'弄'=>1,'籠'=>1,'聾'=>1,'牢'=>1,'磊'=>1,'賂'=>1,'雷'=>1,'壘'=>1,'屢'=>1,'樓'=>1,'ï¥'=>1,'漏'=>1,'ï¥'=>1,'ï¥'=>1,'陋'=>1,'勒'=>1,'肋'=>1,'凜'=>1,'凌'=>1,'稜'=>1,'綾'=>1,'菱'=>1,'陵'=>1,'讀'=>1,'拏'=>1,'樂'=>1,'ï¥'=>1,'丹'=>1,'寧'=>1,'怒'=>1,'率'=>1,'異'=>1,'北'=>1,'磻'=>1,'便'=>1,'復'=>1,'不'=>1,'泌'=>1,'數'=>1,'索'=>1,'參'=>1,'塞'=>1,'省'=>1,'葉'=>1,'說'=>1,'殺'=>1,'辰'=>1,'沈'=>1,'拾'=>1,'若'=>1,'掠'=>1,'略'=>1,'亮'=>1,'兩'=>1,'凉'=>1,'梁'=>1,'糧'=>1,'良'=>1,'諒'=>1,'量'=>1,'勵'=>1,'呂'=>1,'ï¦'=>1,'廬'=>1,'旅'=>1,'濾'=>1,'礪'=>1,'閭'=>1,'驪'=>1,'麗'=>1,'黎'=>1,'力'=>1,'曆'=>1,'歷'=>1,'ï¦'=>1,'年'=>1,'ï¦'=>1,'ï¦'=>1,'撚'=>1,'漣'=>1,'煉'=>1,'璉'=>1,'秊'=>1,'練'=>1,'聯'=>1,'輦'=>1,'蓮'=>1,'連'=>1,'鍊'=>1,'列'=>1,'ï¦'=>1,'咽'=>1,'烈'=>1,'裂'=>1,'說'=>1,'廉'=>1,'念'=>1,'捻'=>1,'殮'=>1,'簾'=>1,'獵'=>1,'令'=>1,'囹'=>1,'寧'=>1,'嶺'=>1,'怜'=>1,'玲'=>1,'瑩'=>1,'羚'=>1,'聆'=>1,'鈴'=>1,'零'=>1,'靈'=>1,'領'=>1,'例'=>1,'禮'=>1,'醴'=>1,'隸'=>1,'惡'=>1,'了'=>1,'僚'=>1,'寮'=>1,'尿'=>1,'料'=>1,'樂'=>1,'ï§€'=>1,'ï§'=>1,'ï§‚'=>1,'遼'=>1,'ï§„'=>1,'ï§…'=>1,'阮'=>1,'劉'=>1,'杻'=>1,'柳'=>1,'ï§Š'=>1,'ï§‹'=>1,'ï§Œ'=>1,'ï§'=>1,'ï§Ž'=>1,'ï§'=>1,'ï§'=>1,'ï§‘'=>1,'ï§’'=>1,'ï§“'=>1,'ï§”'=>1,'ï§•'=>1,'ï§–'=>1,'ï§—'=>1,'律'=>1,'ï§™'=>1,'ï§š'=>1,'ï§›'=>1,'ï§œ'=>1,'ï§'=>1,'ï§ž'=>1,'ï§Ÿ'=>1,'ï§ '=>1,'ï§¡'=>1,'ï§¢'=>1,'ï§£'=>1,'理'=>1,'ï§¥'=>1,'罹'=>1,'ï§§'=>1,'裡'=>1,'ï§©'=>1,'離'=>1,'ï§«'=>1,'溺'=>1,'ï§­'=>1,'ï§®'=>1,'璘'=>1,'ï§°'=>1,'ï§±'=>1,'ï§²'=>1,'ï§³'=>1,'ï§´'=>1,'ï§µ'=>1,'ï§¶'=>1,'ï§·'=>1,'笠'=>1,'ï§¹'=>1,'狀'=>1,'ï§»'=>1,'ï§¼'=>1,'ï§½'=>1,'ï§¾'=>1,'ï§¿'=>1,'切'=>1,'ï¨'=>1,'拓'=>1,'糖'=>1,'宅'=>1,'洞'=>1,'暴'=>1,'輻'=>1,'行'=>1,'降'=>1,'見'=>1,'廓'=>1,'兀'=>1,'ï¨'=>1,'ï¨'=>1,'晴'=>1,'凞'=>1,'猪'=>1,'益'=>1,'礼'=>1,'神'=>1,'祥'=>1,'福'=>1,'靖'=>1,'ï¨'=>1,'羽'=>1,'蘒'=>1,'諸'=>1,'逸'=>1,'都'=>1,'飯'=>1,'飼'=>1,'館'=>1,'鶴'=>1,'侮'=>1,'僧'=>1,'免'=>1,'勉'=>1,'勤'=>1,'卑'=>1,'喝'=>1,'嘆'=>1,'器'=>1,'塀'=>1,'墨'=>1,'層'=>1,'屮'=>1,'悔'=>1,'慨'=>1,'憎'=>1,'ï©€'=>1,'ï©'=>1,'ï©‚'=>1,'暑'=>1,'ï©„'=>1,'ï©…'=>1,'渚'=>1,'漢'=>1,'煮'=>1,'爫'=>1,'琢'=>1,'ï©‹'=>1,'社'=>1,'ï©'=>1,'祈'=>1,'ï©'=>1,'ï©'=>1,'ï©‘'=>1,'ï©’'=>1,'ï©“'=>1,'ï©”'=>1,'ï©•'=>1,'ï©–'=>1,'ï©—'=>1,'縉'=>1,'ï©™'=>1,'署'=>1,'ï©›'=>1,'臭'=>1,'ï©'=>1,'艹'=>1,'著'=>1,'ï© '=>1,'ï©¡'=>1,'ï©¢'=>1,'ï©£'=>1,'賓'=>1,'ï©¥'=>1,'辶'=>1,'ï©§'=>1,'難'=>1,'ï©©'=>1,'頻'=>1,'ï©°'=>1,'况'=>1,'全'=>1,'侀'=>1,'ï©´'=>1,'冀'=>1,'ï©¶'=>1,'ï©·'=>1,'喝'=>1,'啕'=>1,'喙'=>1,'ï©»'=>1,'塚'=>1,'墳'=>1,'奄'=>1,'ï©¿'=>1,'婢'=>1,'ïª'=>1,'廒'=>1,'廙'=>1,'彩'=>1,'徭'=>1,'惘'=>1,'慎'=>1,'愈'=>1,'憎'=>1,'慠'=>1,'懲'=>1,'戴'=>1,'ïª'=>1,'搜'=>1,'ïª'=>1,'ïª'=>1,'晴'=>1,'朗'=>1,'望'=>1,'杖'=>1,'歹'=>1,'殺'=>1,'流'=>1,'滛'=>1,'滋'=>1,'漢'=>1,'瀞'=>1,'煮'=>1,'ïª'=>1,'爵'=>1,'犯'=>1,'猪'=>1,'瑱'=>1,'甆'=>1,'画'=>1,'瘝'=>1,'瘟'=>1,'益'=>1,'盛'=>1,'直'=>1,'睊'=>1,'着'=>1,'磌'=>1,'窱'=>1,'節'=>1,'类'=>1,'絛'=>1,'練'=>1,'缾'=>1,'者'=>1,'荒'=>1,'華'=>1,'蝹'=>1,'襁'=>1,'覆'=>1,'視'=>1,'調'=>1,'諸'=>1,'請'=>1,'謁'=>1,'諾'=>1,'諭'=>1,'謹'=>1,'ï«€'=>1,'ï«'=>1,'ï«‚'=>1,'遲'=>1,'ï«„'=>1,'ï«…'=>1,'陼'=>1,'難'=>1,'靖'=>1,'韛'=>1,'響'=>1,'ï«‹'=>1,'頻'=>1,'ï«'=>1,'龜'=>1,'ï«'=>1,'ï«'=>1,'ï«‘'=>1,'ï«’'=>1,'ï«“'=>1,'ï«”'=>1,'ï«•'=>1,'ï«–'=>1,'ï«—'=>1,'齃'=>1,'ï«™'=>1,'ff'=>1,'ï¬'=>1,'fl'=>1,'ffi'=>1,'ffl'=>1,'ſt'=>1,'st'=>1,'ﬓ'=>1,'ﬔ'=>1,'ﬕ'=>1,'ﬖ'=>1,'ﬗ'=>1,'ï¬'=>1,'ײַ'=>1,'ﬠ'=>1,'ﬡ'=>1,'ﬢ'=>1,'ﬣ'=>1,'ﬤ'=>1,'ﬥ'=>1,'ﬦ'=>1,'ﬧ'=>1,'ﬨ'=>1,'﬩'=>1,'שׁ'=>1,'שׂ'=>1,'שּׁ'=>1,'שּׂ'=>1,'אַ'=>1,'אָ'=>1,'אּ'=>1,'בּ'=>1,'גּ'=>1,'דּ'=>1,'הּ'=>1,'וּ'=>1,'זּ'=>1,'טּ'=>1,'יּ'=>1,'ךּ'=>1,'כּ'=>1,'לּ'=>1,'מּ'=>1,'ï­€'=>1,'ï­'=>1,'ï­ƒ'=>1,'ï­„'=>1,'ï­†'=>1,'ï­‡'=>1,'ï­ˆ'=>1,'ï­‰'=>1,'ï­Š'=>1,'ï­‹'=>1,'ï­Œ'=>1,'ï­'=>1,'ï­Ž'=>1,'ï­'=>1,'ï­'=>1,'ï­‘'=>1,'ï­’'=>1,'ï­“'=>1,'ï­”'=>1,'ï­•'=>1,'ï­–'=>1,'ï­—'=>1,'ï­˜'=>1,'ï­™'=>1,'ï­š'=>1,'ï­›'=>1,'ï­œ'=>1,'ï­'=>1,'ï­ž'=>1,'ï­Ÿ'=>1,'ï­ '=>1,'ï­¡'=>1,'ï­¢'=>1,'ï­£'=>1,'ï­¤'=>1,'ï­¥'=>1,'ï­¦'=>1,'ï­§'=>1,'ï­¨'=>1,'ï­©'=>1,'ï­ª'=>1,'ï­«'=>1,'ï­¬'=>1,'ï­­'=>1,'ï­®'=>1,'ï­¯'=>1,'ï­°'=>1,'ï­±'=>1,'ï­²'=>1,'ï­³'=>1,'ï­´'=>1,'ï­µ'=>1,'ï­¶'=>1,'ï­·'=>1,'ï­¸'=>1,'ï­¹'=>1,'ï­º'=>1,'ï­»'=>1,'ï­¼'=>1,'ï­½'=>1,'ï­¾'=>1,'ï­¿'=>1,'ﮀ'=>1,'ï®'=>1,'ﮂ'=>1,'ﮃ'=>1,'ﮄ'=>1,'ï®…'=>1,'ﮆ'=>1,'ﮇ'=>1,'ﮈ'=>1,'ﮉ'=>1,'ﮊ'=>1,'ﮋ'=>1,'ﮌ'=>1,'ï®'=>1,'ﮎ'=>1,'ï®'=>1,'ï®'=>1,'ﮑ'=>1,'ï®’'=>1,'ﮓ'=>1,'ï®”'=>1,'ﮕ'=>1,'ï®–'=>1,'ï®—'=>1,'ﮘ'=>1,'ï®™'=>1,'ﮚ'=>1,'ï®›'=>1,'ﮜ'=>1,'ï®'=>1,'ﮞ'=>1,'ﮟ'=>1,'ï® '=>1,'ﮡ'=>1,'ﮢ'=>1,'ﮣ'=>1,'ﮤ'=>1,'ﮥ'=>1,'ﮦ'=>1,'ï®§'=>1,'ﮨ'=>1,'ﮩ'=>1,'ﮪ'=>1,'ﮫ'=>1,'ﮬ'=>1,'ï®­'=>1,'ï®®'=>1,'ﮯ'=>1,'ï®°'=>1,'ï®±'=>1,'ﯓ'=>1,'ﯔ'=>1,'ﯕ'=>1,'ﯖ'=>1,'ﯗ'=>1,'ﯘ'=>1,'ﯙ'=>1,'ﯚ'=>1,'ﯛ'=>1,'ﯜ'=>1,'ï¯'=>1,'ﯞ'=>1,'ﯟ'=>1,'ﯠ'=>1,'ﯡ'=>1,'ﯢ'=>1,'ﯣ'=>1,'ﯤ'=>1,'ﯥ'=>1,'ﯦ'=>1,'ﯧ'=>1,'ﯨ'=>1,'ﯩ'=>1,'ﯪ'=>1,'ﯫ'=>1,'ﯬ'=>1,'ﯭ'=>1,'ﯮ'=>1,'ﯯ'=>1,'ﯰ'=>1,'ﯱ'=>1,'ﯲ'=>1,'ﯳ'=>1,'ﯴ'=>1,'ﯵ'=>1,'ﯶ'=>1,'ﯷ'=>1,'ﯸ'=>1,'ﯹ'=>1,'ﯺ'=>1,'ﯻ'=>1,'ﯼ'=>1,'ﯽ'=>1,'ﯾ'=>1,'ﯿ'=>1,'ï°€'=>1,'ï°'=>1,'ï°‚'=>1,'ï°ƒ'=>1,'ï°„'=>1,'ï°…'=>1,'ï°†'=>1,'ï°‡'=>1,'ï°ˆ'=>1,'ï°‰'=>1,'ï°Š'=>1,'ï°‹'=>1,'ï°Œ'=>1,'ï°'=>1,'ï°Ž'=>1,'ï°'=>1,'ï°'=>1,'ï°‘'=>1,'ï°’'=>1,'ï°“'=>1,'ï°”'=>1,'ï°•'=>1,'ï°–'=>1,'ï°—'=>1,'ï°˜'=>1,'ï°™'=>1,'ï°š'=>1,'ï°›'=>1,'ï°œ'=>1,'ï°'=>1,'ï°ž'=>1,'ï°Ÿ'=>1,'ï° '=>1,'ï°¡'=>1,'ï°¢'=>1,'ï°£'=>1,'ï°¤'=>1,'ï°¥'=>1,'ï°¦'=>1,'ï°§'=>1,'ï°¨'=>1,'ï°©'=>1,'ï°ª'=>1,'ï°«'=>1,'ï°¬'=>1,'ï°­'=>1,'ï°®'=>1,'ï°¯'=>1,'ï°°'=>1,'ï°±'=>1,'ï°²'=>1,'ï°³'=>1,'ï°´'=>1,'ï°µ'=>1,'ï°¶'=>1,'ï°·'=>1,'ï°¸'=>1,'ï°¹'=>1,'ï°º'=>1,'ï°»'=>1,'ï°¼'=>1,'ï°½'=>1,'ï°¾'=>1,'ï°¿'=>1,'ï±€'=>1,'ï±'=>1,'ﱂ'=>1,'ﱃ'=>1,'ﱄ'=>1,'ï±…'=>1,'ﱆ'=>1,'ﱇ'=>1,'ﱈ'=>1,'ﱉ'=>1,'ﱊ'=>1,'ﱋ'=>1,'ﱌ'=>1,'ï±'=>1,'ﱎ'=>1,'ï±'=>1,'ï±'=>1,'ﱑ'=>1,'ï±’'=>1,'ﱓ'=>1,'ï±”'=>1,'ﱕ'=>1,'ï±–'=>1,'ï±—'=>1,'ﱘ'=>1,'ï±™'=>1,'ﱚ'=>1,'ï±›'=>1,'ﱜ'=>1,'ï±'=>1,'ﱞ'=>1,'ﱟ'=>1,'ï± '=>1,'ﱡ'=>1,'ï±¢'=>1,'ï±£'=>1,'ﱤ'=>1,'ï±¥'=>1,'ﱦ'=>1,'ï±§'=>1,'ﱨ'=>1,'ﱩ'=>1,'ﱪ'=>1,'ﱫ'=>1,'ﱬ'=>1,'ï±­'=>1,'ï±®'=>1,'ﱯ'=>1,'ï±°'=>1,'ï±±'=>1,'ï±²'=>1,'ï±³'=>1,'ï±´'=>1,'ï±µ'=>1,'ï±¶'=>1,'ï±·'=>1,'ﱸ'=>1,'ï±¹'=>1,'ﱺ'=>1,'ï±»'=>1,'ï±¼'=>1,'ï±½'=>1,'ï±¾'=>1,'ﱿ'=>1,'ï²€'=>1,'ï²'=>1,'ﲂ'=>1,'ﲃ'=>1,'ﲄ'=>1,'ï²…'=>1,'ﲆ'=>1,'ﲇ'=>1,'ﲈ'=>1,'ﲉ'=>1,'ﲊ'=>1,'ﲋ'=>1,'ﲌ'=>1,'ï²'=>1,'ﲎ'=>1,'ï²'=>1,'ï²'=>1,'ﲑ'=>1,'ï²’'=>1,'ﲓ'=>1,'ï²”'=>1,'ﲕ'=>1,'ï²–'=>1,'ï²—'=>1,'ﲘ'=>1,'ï²™'=>1,'ﲚ'=>1,'ï²›'=>1,'ﲜ'=>1,'ï²'=>1,'ﲞ'=>1,'ﲟ'=>1,'ï² '=>1,'ﲡ'=>1,'ï²¢'=>1,'ï²£'=>1,'ﲤ'=>1,'ï²¥'=>1,'ﲦ'=>1,'ï²§'=>1,'ﲨ'=>1,'ﲩ'=>1,'ﲪ'=>1,'ﲫ'=>1,'ﲬ'=>1,'ï²­'=>1,'ï²®'=>1,'ﲯ'=>1,'ï²°'=>1,'ï²±'=>1,'ï²²'=>1,'ï²³'=>1,'ï²´'=>1,'ï²µ'=>1,'ï²¶'=>1,'ï²·'=>1,'ﲸ'=>1,'ï²¹'=>1,'ﲺ'=>1,'ï²»'=>1,'ï²¼'=>1,'ï²½'=>1,'ï²¾'=>1,'ﲿ'=>1,'ï³€'=>1,'ï³'=>1,'ﳂ'=>1,'ﳃ'=>1,'ﳄ'=>1,'ï³…'=>1,'ﳆ'=>1,'ﳇ'=>1,'ﳈ'=>1,'ﳉ'=>1,'ﳊ'=>1,'ﳋ'=>1,'ﳌ'=>1,'ï³'=>1,'ﳎ'=>1,'ï³'=>1,'ï³'=>1,'ﳑ'=>1,'ï³’'=>1,'ﳓ'=>1,'ï³”'=>1,'ﳕ'=>1,'ï³–'=>1,'ï³—'=>1,'ﳘ'=>1,'ï³™'=>1,'ﳚ'=>1,'ï³›'=>1,'ﳜ'=>1,'ï³'=>1,'ﳞ'=>1,'ﳟ'=>1,'ï³ '=>1,'ﳡ'=>1,'ï³¢'=>1,'ï³£'=>1,'ﳤ'=>1,'ï³¥'=>1,'ﳦ'=>1,'ï³§'=>1,'ﳨ'=>1,'ﳩ'=>1,'ﳪ'=>1,'ﳫ'=>1,'ﳬ'=>1,'ï³­'=>1,'ï³®'=>1,'ﳯ'=>1,'ï³°'=>1,'ï³±'=>1,'ï³²'=>1,'ï³³'=>1,'ï³´'=>1,'ï³µ'=>1,'ï³¶'=>1,'ï³·'=>1,'ﳸ'=>1,'ï³¹'=>1,'ﳺ'=>1,'ï³»'=>1,'ï³¼'=>1,'ï³½'=>1,'ï³¾'=>1,'ﳿ'=>1,'ï´€'=>1,'ï´'=>1,'ï´‚'=>1,'ï´ƒ'=>1,'ï´„'=>1,'ï´…'=>1,'ï´†'=>1,'ï´‡'=>1,'ï´ˆ'=>1,'ï´‰'=>1,'ï´Š'=>1,'ï´‹'=>1,'ï´Œ'=>1,'ï´'=>1,'ï´Ž'=>1,'ï´'=>1,'ï´'=>1,'ï´‘'=>1,'ï´’'=>1,'ï´“'=>1,'ï´”'=>1,'ï´•'=>1,'ï´–'=>1,'ï´—'=>1,'ï´˜'=>1,'ï´™'=>1,'ï´š'=>1,'ï´›'=>1,'ï´œ'=>1,'ï´'=>1,'ï´ž'=>1,'ï´Ÿ'=>1,'ï´ '=>1,'ï´¡'=>1,'ï´¢'=>1,'ï´£'=>1,'ï´¤'=>1,'ï´¥'=>1,'ï´¦'=>1,'ï´§'=>1,'ï´¨'=>1,'ï´©'=>1,'ï´ª'=>1,'ï´«'=>1,'ï´¬'=>1,'ï´­'=>1,'ï´®'=>1,'ï´¯'=>1,'ï´°'=>1,'ï´±'=>1,'ï´²'=>1,'ï´³'=>1,'ï´´'=>1,'ï´µ'=>1,'ï´¶'=>1,'ï´·'=>1,'ï´¸'=>1,'ï´¹'=>1,'ï´º'=>1,'ï´»'=>1,'ï´¼'=>1,'ï´½'=>1,'ïµ'=>1,'ﵑ'=>1,'ïµ’'=>1,'ﵓ'=>1,'ïµ”'=>1,'ﵕ'=>1,'ïµ–'=>1,'ïµ—'=>1,'ﵘ'=>1,'ïµ™'=>1,'ﵚ'=>1,'ïµ›'=>1,'ﵜ'=>1,'ïµ'=>1,'ﵞ'=>1,'ﵟ'=>1,'ïµ '=>1,'ﵡ'=>1,'ïµ¢'=>1,'ïµ£'=>1,'ﵤ'=>1,'ïµ¥'=>1,'ﵦ'=>1,'ïµ§'=>1,'ﵨ'=>1,'ﵩ'=>1,'ﵪ'=>1,'ﵫ'=>1,'ﵬ'=>1,'ïµ­'=>1,'ïµ®'=>1,'ﵯ'=>1,'ïµ°'=>1,'ïµ±'=>1,'ïµ²'=>1,'ïµ³'=>1,'ïµ´'=>1,'ïµµ'=>1,'ïµ¶'=>1,'ïµ·'=>1,'ﵸ'=>1,'ïµ¹'=>1,'ﵺ'=>1,'ïµ»'=>1,'ïµ¼'=>1,'ïµ½'=>1,'ïµ¾'=>1,'ﵿ'=>1,'ï¶€'=>1,'ï¶'=>1,'ï¶‚'=>1,'ﶃ'=>1,'ï¶„'=>1,'ï¶…'=>1,'ﶆ'=>1,'ﶇ'=>1,'ﶈ'=>1,'ﶉ'=>1,'ï¶Š'=>1,'ï¶‹'=>1,'ï¶Œ'=>1,'ï¶'=>1,'ï¶Ž'=>1,'ï¶'=>1,'ï¶’'=>1,'ï¶“'=>1,'ï¶”'=>1,'ï¶•'=>1,'ï¶–'=>1,'ï¶—'=>1,'ﶘ'=>1,'ï¶™'=>1,'ï¶š'=>1,'ï¶›'=>1,'ï¶œ'=>1,'ï¶'=>1,'ï¶ž'=>1,'ï¶Ÿ'=>1,'ï¶ '=>1,'ï¶¡'=>1,'ï¶¢'=>1,'ï¶£'=>1,'ﶤ'=>1,'ï¶¥'=>1,'ﶦ'=>1,'ï¶§'=>1,'ﶨ'=>1,'ï¶©'=>1,'ﶪ'=>1,'ï¶«'=>1,'ﶬ'=>1,'ï¶­'=>1,'ï¶®'=>1,'ﶯ'=>1,'ï¶°'=>1,'ï¶±'=>1,'ï¶²'=>1,'ï¶³'=>1,'ï¶´'=>1,'ï¶µ'=>1,'ï¶¶'=>1,'ï¶·'=>1,'ﶸ'=>1,'ï¶¹'=>1,'ﶺ'=>1,'ï¶»'=>1,'ï¶¼'=>1,'ï¶½'=>1,'ï¶¾'=>1,'ï¶¿'=>1,'ï·€'=>1,'ï·'=>1,'ï·‚'=>1,'ï·ƒ'=>1,'ï·„'=>1,'ï·…'=>1,'ï·†'=>1,'ï·‡'=>1,'ï·°'=>1,'ï·±'=>1,'ï·²'=>1,'ï·³'=>1,'ï·´'=>1,'ï·µ'=>1,'ï·¶'=>1,'ï··'=>1,'ï·¸'=>1,'ï·¹'=>1,'ï·º'=>1,'ï·»'=>1,'ï·¼'=>1,'ï¸'=>1,'︑'=>1,'︒'=>1,'︓'=>1,'︔'=>1,'︕'=>1,'︖'=>1,'︗'=>1,'︘'=>1,'︙'=>1,'︰'=>1,'︱'=>1,'︲'=>1,'︳'=>1,'︴'=>1,'︵'=>1,'︶'=>1,'︷'=>1,'︸'=>1,'︹'=>1,'︺'=>1,'︻'=>1,'︼'=>1,'︽'=>1,'︾'=>1,'︿'=>1,'ï¹€'=>1,'ï¹'=>1,'﹂'=>1,'﹃'=>1,'﹄'=>1,'﹇'=>1,'﹈'=>1,'﹉'=>1,'﹊'=>1,'﹋'=>1,'﹌'=>1,'ï¹'=>1,'﹎'=>1,'ï¹'=>1,'ï¹'=>1,'﹑'=>1,'ï¹’'=>1,'ï¹”'=>1,'﹕'=>1,'ï¹–'=>1,'ï¹—'=>1,'﹘'=>1,'ï¹™'=>1,'﹚'=>1,'ï¹›'=>1,'﹜'=>1,'ï¹'=>1,'﹞'=>1,'﹟'=>1,'ï¹ '=>1,'﹡'=>1,'ï¹¢'=>1,'ï¹£'=>1,'﹤'=>1,'ï¹¥'=>1,'﹦'=>1,'﹨'=>1,'﹩'=>1,'﹪'=>1,'﹫'=>1,'ï¹°'=>1,'ï¹±'=>1,'ï¹²'=>1,'ï¹´'=>1,'ï¹¶'=>1,'ï¹·'=>1,'ﹸ'=>1,'ï¹¹'=>1,'ﹺ'=>1,'ï¹»'=>1,'ï¹¼'=>1,'ï¹½'=>1,'ï¹¾'=>1,'ﹿ'=>1,'ﺀ'=>1,'ïº'=>1,'ﺂ'=>1,'ﺃ'=>1,'ﺄ'=>1,'ﺅ'=>1,'ﺆ'=>1,'ﺇ'=>1,'ﺈ'=>1,'ﺉ'=>1,'ﺊ'=>1,'ﺋ'=>1,'ﺌ'=>1,'ïº'=>1,'ﺎ'=>1,'ïº'=>1,'ïº'=>1,'ﺑ'=>1,'ﺒ'=>1,'ﺓ'=>1,'ﺔ'=>1,'ﺕ'=>1,'ﺖ'=>1,'ﺗ'=>1,'ﺘ'=>1,'ﺙ'=>1,'ﺚ'=>1,'ﺛ'=>1,'ﺜ'=>1,'ïº'=>1,'ﺞ'=>1,'ﺟ'=>1,'ﺠ'=>1,'ﺡ'=>1,'ﺢ'=>1,'ﺣ'=>1,'ﺤ'=>1,'ﺥ'=>1,'ﺦ'=>1,'ﺧ'=>1,'ﺨ'=>1,'ﺩ'=>1,'ﺪ'=>1,'ﺫ'=>1,'ﺬ'=>1,'ﺭ'=>1,'ﺮ'=>1,'ﺯ'=>1,'ﺰ'=>1,'ﺱ'=>1,'ﺲ'=>1,'ﺳ'=>1,'ﺴ'=>1,'ﺵ'=>1,'ﺶ'=>1,'ﺷ'=>1,'ﺸ'=>1,'ﺹ'=>1,'ﺺ'=>1,'ﺻ'=>1,'ﺼ'=>1,'ﺽ'=>1,'ﺾ'=>1,'ﺿ'=>1,'ﻀ'=>1,'ï»'=>1,'ﻂ'=>1,'ﻃ'=>1,'ﻄ'=>1,'ï»…'=>1,'ﻆ'=>1,'ﻇ'=>1,'ﻈ'=>1,'ﻉ'=>1,'ﻊ'=>1,'ﻋ'=>1,'ﻌ'=>1,'ï»'=>1,'ﻎ'=>1,'ï»'=>1,'ï»'=>1,'ﻑ'=>1,'ï»’'=>1,'ﻓ'=>1,'ï»”'=>1,'ﻕ'=>1,'ï»–'=>1,'ï»—'=>1,'ﻘ'=>1,'ï»™'=>1,'ﻚ'=>1,'ï»›'=>1,'ﻜ'=>1,'ï»'=>1,'ﻞ'=>1,'ﻟ'=>1,'ï» '=>1,'ﻡ'=>1,'ﻢ'=>1,'ﻣ'=>1,'ﻤ'=>1,'ﻥ'=>1,'ﻦ'=>1,'ï»§'=>1,'ﻨ'=>1,'ﻩ'=>1,'ﻪ'=>1,'ﻫ'=>1,'ﻬ'=>1,'ï»­'=>1,'ï»®'=>1,'ﻯ'=>1,'ï»°'=>1,'ï»±'=>1,'ﻲ'=>1,'ﻳ'=>1,'ï»´'=>1,'ﻵ'=>1,'ï»¶'=>1,'ï»·'=>1,'ﻸ'=>1,'ﻹ'=>1,'ﻺ'=>1,'ï»»'=>1,'ﻼ'=>1,'ï¼'=>1,'"'=>1,'#'=>1,'$'=>1,'ï¼…'=>1,'&'=>1,'''=>1,'('=>1,')'=>1,'*'=>1,'+'=>1,','=>1,'ï¼'=>1,'.'=>1,'ï¼'=>1,'ï¼'=>1,'1'=>1,'ï¼’'=>1,'3'=>1,'ï¼”'=>1,'5'=>1,'ï¼–'=>1,'ï¼—'=>1,'8'=>1,'ï¼™'=>1,':'=>1,'ï¼›'=>1,'<'=>1,'ï¼'=>1,'>'=>1,'?'=>1,'ï¼ '=>1,'A'=>1,'ï¼¢'=>1,'ï¼£'=>1,'D'=>1,'ï¼¥'=>1,'F'=>1,'ï¼§'=>1,'H'=>1,'I'=>1,'J'=>1,'K'=>1,'L'=>1,'ï¼­'=>1,'ï¼®'=>1,'O'=>1,'ï¼°'=>1,'ï¼±'=>1,'ï¼²'=>1,'ï¼³'=>1,'ï¼´'=>1,'ï¼µ'=>1,'ï¼¶'=>1,'ï¼·'=>1,'X'=>1,'ï¼¹'=>1,'Z'=>1,'ï¼»'=>1,'ï¼¼'=>1,'ï¼½'=>1,'ï¼¾'=>1,'_'=>1,'ï½€'=>1,'ï½'=>1,'b'=>1,'c'=>1,'d'=>1,'ï½…'=>1,'f'=>1,'g'=>1,'h'=>1,'i'=>1,'j'=>1,'k'=>1,'l'=>1,'ï½'=>1,'n'=>1,'ï½'=>1,'ï½'=>1,'q'=>1,'ï½’'=>1,'s'=>1,'ï½”'=>1,'u'=>1,'ï½–'=>1,'ï½—'=>1,'x'=>1,'ï½™'=>1,'z'=>1,'ï½›'=>1,'|'=>1,'ï½'=>1,'~'=>1,'⦅'=>1,'ï½ '=>1,'。'=>1,'ï½¢'=>1,'ï½£'=>1,'、'=>1,'ï½¥'=>1,'ヲ'=>1,'ï½§'=>1,'ィ'=>1,'ゥ'=>1,'ェ'=>1,'ォ'=>1,'ャ'=>1,'ï½­'=>1,'ï½®'=>1,'ッ'=>1,'ï½°'=>1,'ï½±'=>1,'ï½²'=>1,'ï½³'=>1,'ï½´'=>1,'ï½µ'=>1,'ï½¶'=>1,'ï½·'=>1,'ク'=>1,'ï½¹'=>1,'コ'=>1,'ï½»'=>1,'ï½¼'=>1,'ï½½'=>1,'ï½¾'=>1,'ソ'=>1,'ï¾€'=>1,'ï¾'=>1,'ツ'=>1,'テ'=>1,'ト'=>1,'ï¾…'=>1,'ニ'=>1,'ヌ'=>1,'ネ'=>1,'ノ'=>1,'ハ'=>1,'ヒ'=>1,'フ'=>1,'ï¾'=>1,'ホ'=>1,'ï¾'=>1,'ï¾'=>1,'ム'=>1,'ï¾’'=>1,'モ'=>1,'ï¾”'=>1,'ユ'=>1,'ï¾–'=>1,'ï¾—'=>1,'リ'=>1,'ï¾™'=>1,'レ'=>1,'ï¾›'=>1,'ワ'=>1,'ï¾'=>1,'゙'=>1,'゚'=>1,'ï¾ '=>1,'ᄀ'=>1,'ï¾¢'=>1,'ï¾£'=>1,'ᄂ'=>1,'ï¾¥'=>1,'ᆭ'=>1,'ï¾§'=>1,'ᄄ'=>1,'ᄅ'=>1,'ᆰ'=>1,'ᆱ'=>1,'ᆲ'=>1,'ï¾­'=>1,'ï¾®'=>1,'ᆵ'=>1,'ï¾°'=>1,'ï¾±'=>1,'ï¾²'=>1,'ï¾³'=>1,'ï¾´'=>1,'ï¾µ'=>1,'ï¾¶'=>1,'ï¾·'=>1,'ᄌ'=>1,'ï¾¹'=>1,'ᄎ'=>1,'ï¾»'=>1,'ï¾¼'=>1,'ï¾½'=>1,'ï¾¾'=>1,'ï¿‚'=>1,'ᅢ'=>1,'ï¿„'=>1,'ï¿…'=>1,'ᅥ'=>1,'ᅦ'=>1,'ᅧ'=>1,'ï¿‹'=>1,'ᅩ'=>1,'ï¿'=>1,'ᅫ'=>1,'ï¿'=>1,'ï¿’'=>1,'ï¿“'=>1,'ï¿”'=>1,'ï¿•'=>1,'ï¿–'=>1,'ï¿—'=>1,'ᅳ'=>1,'ï¿›'=>1,'ᅵ'=>1,'ï¿ '=>1,'ï¿¡'=>1,'ï¿¢'=>1,'ï¿£'=>1,'¦'=>1,'ï¿¥'=>1,'₩'=>1,'│'=>1,'ï¿©'=>1,'↑'=>1,'ï¿«'=>1,'↓'=>1,'ï¿­'=>1,'ï¿®'=>1,'ð…ž'=>1,'ð…Ÿ'=>1,'ð… '=>1,'ð…¡'=>1,'ð…¢'=>1,'ð…£'=>1,'ð…¤'=>1,'ð†»'=>1,'ð†¼'=>1,'ð†½'=>1,'ð†¾'=>1,'ð†¿'=>1,'ð‡€'=>1,'ð€'=>1,'ð'=>1,'ð‚'=>1,'ðƒ'=>1,'ð„'=>1,'ð…'=>1,'ð†'=>1,'ð‡'=>1,'ðˆ'=>1,'ð‰'=>1,'ðŠ'=>1,'ð‹'=>1,'ðŒ'=>1,'ð'=>1,'ðŽ'=>1,'ð'=>1,'ð'=>1,'ð‘'=>1,'ð’'=>1,'ð“'=>1,'ð”'=>1,'ð•'=>1,'ð–'=>1,'ð—'=>1,'ð˜'=>1,'ð™'=>1,'ðš'=>1,'ð›'=>1,'ðœ'=>1,'ð'=>1,'ðž'=>1,'ðŸ'=>1,'ð '=>1,'ð¡'=>1,'ð¢'=>1,'ð£'=>1,'ð¤'=>1,'ð¥'=>1,'ð¦'=>1,'ð§'=>1,'ð¨'=>1,'ð©'=>1,'ðª'=>1,'ð«'=>1,'ð¬'=>1,'ð­'=>1,'ð®'=>1,'ð¯'=>1,'ð°'=>1,'ð±'=>1,'ð²'=>1,'ð³'=>1,'ð´'=>1,'ðµ'=>1,'ð¶'=>1,'ð·'=>1,'ð¸'=>1,'ð¹'=>1,'ðº'=>1,'ð»'=>1,'ð¼'=>1,'ð½'=>1,'ð¾'=>1,'ð¿'=>1,'ð‘€'=>1,'ð‘'=>1,'ð‘‚'=>1,'ð‘ƒ'=>1,'ð‘„'=>1,'ð‘…'=>1,'ð‘†'=>1,'ð‘‡'=>1,'ð‘ˆ'=>1,'ð‘‰'=>1,'ð‘Š'=>1,'ð‘‹'=>1,'ð‘Œ'=>1,'ð‘'=>1,'ð‘Ž'=>1,'ð‘'=>1,'ð‘'=>1,'ð‘‘'=>1,'ð‘’'=>1,'ð‘“'=>1,'ð‘”'=>1,'ð‘–'=>1,'ð‘—'=>1,'ð‘˜'=>1,'ð‘™'=>1,'ð‘š'=>1,'ð‘›'=>1,'ð‘œ'=>1,'ð‘'=>1,'ð‘ž'=>1,'ð‘Ÿ'=>1,'ð‘ '=>1,'ð‘¡'=>1,'ð‘¢'=>1,'ð‘£'=>1,'ð‘¤'=>1,'ð‘¥'=>1,'ð‘¦'=>1,'ð‘§'=>1,'ð‘¨'=>1,'ð‘©'=>1,'ð‘ª'=>1,'ð‘«'=>1,'ð‘¬'=>1,'ð‘­'=>1,'ð‘®'=>1,'ð‘¯'=>1,'ð‘°'=>1,'ð‘±'=>1,'ð‘²'=>1,'ð‘³'=>1,'ð‘´'=>1,'ð‘µ'=>1,'ð‘¶'=>1,'ð‘·'=>1,'ð‘¸'=>1,'ð‘¹'=>1,'ð‘º'=>1,'ð‘»'=>1,'ð‘¼'=>1,'ð‘½'=>1,'ð‘¾'=>1,'ð‘¿'=>1,'ð’€'=>1,'ð’'=>1,'ð’‚'=>1,'ð’ƒ'=>1,'ð’„'=>1,'ð’…'=>1,'ð’†'=>1,'ð’‡'=>1,'ð’ˆ'=>1,'ð’‰'=>1,'ð’Š'=>1,'ð’‹'=>1,'ð’Œ'=>1,'ð’'=>1,'ð’Ž'=>1,'ð’'=>1,'ð’'=>1,'ð’‘'=>1,'ð’’'=>1,'ð’“'=>1,'ð’”'=>1,'ð’•'=>1,'ð’–'=>1,'ð’—'=>1,'ð’˜'=>1,'ð’™'=>1,'ð’š'=>1,'ð’›'=>1,'ð’œ'=>1,'ð’ž'=>1,'ð’Ÿ'=>1,'ð’¢'=>1,'ð’¥'=>1,'ð’¦'=>1,'ð’©'=>1,'ð’ª'=>1,'ð’«'=>1,'ð’¬'=>1,'ð’®'=>1,'ð’¯'=>1,'ð’°'=>1,'ð’±'=>1,'ð’²'=>1,'ð’³'=>1,'ð’´'=>1,'ð’µ'=>1,'ð’¶'=>1,'ð’·'=>1,'ð’¸'=>1,'ð’¹'=>1,'ð’»'=>1,'ð’½'=>1,'ð’¾'=>1,'ð’¿'=>1,'ð“€'=>1,'ð“'=>1,'ð“‚'=>1,'ð“ƒ'=>1,'ð“…'=>1,'ð“†'=>1,'ð“‡'=>1,'ð“ˆ'=>1,'ð“‰'=>1,'ð“Š'=>1,'ð“‹'=>1,'ð“Œ'=>1,'ð“'=>1,'ð“Ž'=>1,'ð“'=>1,'ð“'=>1,'ð“‘'=>1,'ð“’'=>1,'ð““'=>1,'ð“”'=>1,'ð“•'=>1,'ð“–'=>1,'ð“—'=>1,'ð“˜'=>1,'ð“™'=>1,'ð“š'=>1,'ð“›'=>1,'ð“œ'=>1,'ð“'=>1,'ð“ž'=>1,'ð“Ÿ'=>1,'ð“ '=>1,'ð“¡'=>1,'ð“¢'=>1,'ð“£'=>1,'ð“¤'=>1,'ð“¥'=>1,'ð“¦'=>1,'ð“§'=>1,'ð“¨'=>1,'ð“©'=>1,'ð“ª'=>1,'ð“«'=>1,'ð“¬'=>1,'ð“­'=>1,'ð“®'=>1,'ð“¯'=>1,'ð“°'=>1,'ð“±'=>1,'ð“²'=>1,'ð“³'=>1,'ð“´'=>1,'ð“µ'=>1,'ð“¶'=>1,'ð“·'=>1,'ð“¸'=>1,'ð“¹'=>1,'ð“º'=>1,'ð“»'=>1,'ð“¼'=>1,'ð“½'=>1,'ð“¾'=>1,'ð“¿'=>1,'ð”€'=>1,'ð”'=>1,'ð”‚'=>1,'ð”ƒ'=>1,'ð”„'=>1,'ð”…'=>1,'ð”‡'=>1,'ð”ˆ'=>1,'ð”‰'=>1,'ð”Š'=>1,'ð”'=>1,'ð”Ž'=>1,'ð”'=>1,'ð”'=>1,'ð”‘'=>1,'ð”’'=>1,'ð”“'=>1,'ð””'=>1,'ð”–'=>1,'ð”—'=>1,'ð”˜'=>1,'ð”™'=>1,'ð”š'=>1,'ð”›'=>1,'ð”œ'=>1,'ð”ž'=>1,'ð”Ÿ'=>1,'ð” '=>1,'ð”¡'=>1,'ð”¢'=>1,'ð”£'=>1,'ð”¤'=>1,'ð”¥'=>1,'ð”¦'=>1,'ð”§'=>1,'ð”¨'=>1,'ð”©'=>1,'ð”ª'=>1,'ð”«'=>1,'ð”¬'=>1,'ð”­'=>1,'ð”®'=>1,'ð”¯'=>1,'ð”°'=>1,'ð”±'=>1,'ð”²'=>1,'ð”³'=>1,'ð”´'=>1,'ð”µ'=>1,'ð”¶'=>1,'ð”·'=>1,'ð”¸'=>1,'ð”¹'=>1,'ð”»'=>1,'ð”¼'=>1,'ð”½'=>1,'ð”¾'=>1,'ð•€'=>1,'ð•'=>1,'ð•‚'=>1,'ð•ƒ'=>1,'ð•„'=>1,'ð•†'=>1,'ð•Š'=>1,'ð•‹'=>1,'ð•Œ'=>1,'ð•'=>1,'ð•Ž'=>1,'ð•'=>1,'ð•'=>1,'ð•’'=>1,'ð•“'=>1,'ð•”'=>1,'ð••'=>1,'ð•–'=>1,'ð•—'=>1,'ð•˜'=>1,'ð•™'=>1,'ð•š'=>1,'ð•›'=>1,'ð•œ'=>1,'ð•'=>1,'ð•ž'=>1,'ð•Ÿ'=>1,'ð• '=>1,'ð•¡'=>1,'ð•¢'=>1,'ð•£'=>1,'ð•¤'=>1,'ð•¥'=>1,'ð•¦'=>1,'ð•§'=>1,'ð•¨'=>1,'ð•©'=>1,'ð•ª'=>1,'ð•«'=>1,'ð•¬'=>1,'ð•­'=>1,'ð•®'=>1,'ð•¯'=>1,'ð•°'=>1,'ð•±'=>1,'ð•²'=>1,'ð•³'=>1,'ð•´'=>1,'ð•µ'=>1,'ð•¶'=>1,'ð•·'=>1,'ð•¸'=>1,'ð•¹'=>1,'ð•º'=>1,'ð•»'=>1,'ð•¼'=>1,'ð•½'=>1,'ð•¾'=>1,'ð•¿'=>1,'ð–€'=>1,'ð–'=>1,'ð–‚'=>1,'ð–ƒ'=>1,'ð–„'=>1,'ð–…'=>1,'ð–†'=>1,'ð–‡'=>1,'ð–ˆ'=>1,'ð–‰'=>1,'ð–Š'=>1,'ð–‹'=>1,'ð–Œ'=>1,'ð–'=>1,'ð–Ž'=>1,'ð–'=>1,'ð–'=>1,'ð–‘'=>1,'ð–’'=>1,'ð–“'=>1,'ð–”'=>1,'ð–•'=>1,'ð––'=>1,'ð–—'=>1,'ð–˜'=>1,'ð–™'=>1,'ð–š'=>1,'ð–›'=>1,'ð–œ'=>1,'ð–'=>1,'ð–ž'=>1,'ð–Ÿ'=>1,'ð– '=>1,'ð–¡'=>1,'ð–¢'=>1,'ð–£'=>1,'ð–¤'=>1,'ð–¥'=>1,'ð–¦'=>1,'ð–§'=>1,'ð–¨'=>1,'ð–©'=>1,'ð–ª'=>1,'ð–«'=>1,'ð–¬'=>1,'ð–­'=>1,'ð–®'=>1,'ð–¯'=>1,'ð–°'=>1,'ð–±'=>1,'ð–²'=>1,'ð–³'=>1,'ð–´'=>1,'ð–µ'=>1,'ð–¶'=>1,'ð–·'=>1,'ð–¸'=>1,'ð–¹'=>1,'ð–º'=>1,'ð–»'=>1,'ð–¼'=>1,'ð–½'=>1,'ð–¾'=>1,'ð–¿'=>1,'ð—€'=>1,'ð—'=>1,'ð—‚'=>1,'ð—ƒ'=>1,'ð—„'=>1,'ð—…'=>1,'ð—†'=>1,'ð—‡'=>1,'ð—ˆ'=>1,'ð—‰'=>1,'ð—Š'=>1,'ð—‹'=>1,'ð—Œ'=>1,'ð—'=>1,'ð—Ž'=>1,'ð—'=>1,'ð—'=>1,'ð—‘'=>1,'ð—’'=>1,'ð—“'=>1,'ð—”'=>1,'ð—•'=>1,'ð—–'=>1,'ð——'=>1,'ð—˜'=>1,'ð—™'=>1,'ð—š'=>1,'ð—›'=>1,'ð—œ'=>1,'ð—'=>1,'ð—ž'=>1,'ð—Ÿ'=>1,'ð— '=>1,'ð—¡'=>1,'ð—¢'=>1,'ð—£'=>1,'ð—¤'=>1,'ð—¥'=>1,'ð—¦'=>1,'ð—§'=>1,'ð—¨'=>1,'ð—©'=>1,'ð—ª'=>1,'ð—«'=>1,'ð—¬'=>1,'ð—­'=>1,'ð—®'=>1,'ð—¯'=>1,'ð—°'=>1,'ð—±'=>1,'ð—²'=>1,'ð—³'=>1,'ð—´'=>1,'ð—µ'=>1,'ð—¶'=>1,'ð—·'=>1,'ð—¸'=>1,'ð—¹'=>1,'ð—º'=>1,'ð—»'=>1,'ð—¼'=>1,'ð—½'=>1,'ð—¾'=>1,'ð—¿'=>1,'ð˜€'=>1,'ð˜'=>1,'ð˜‚'=>1,'ð˜ƒ'=>1,'ð˜„'=>1,'ð˜…'=>1,'ð˜†'=>1,'ð˜‡'=>1,'ð˜ˆ'=>1,'ð˜‰'=>1,'ð˜Š'=>1,'ð˜‹'=>1,'ð˜Œ'=>1,'ð˜'=>1,'ð˜Ž'=>1,'ð˜'=>1,'ð˜'=>1,'ð˜‘'=>1,'ð˜’'=>1,'ð˜“'=>1,'ð˜”'=>1,'ð˜•'=>1,'ð˜–'=>1,'ð˜—'=>1,'ð˜˜'=>1,'ð˜™'=>1,'ð˜š'=>1,'ð˜›'=>1,'ð˜œ'=>1,'ð˜'=>1,'ð˜ž'=>1,'ð˜Ÿ'=>1,'ð˜ '=>1,'ð˜¡'=>1,'ð˜¢'=>1,'ð˜£'=>1,'ð˜¤'=>1,'ð˜¥'=>1,'ð˜¦'=>1,'ð˜§'=>1,'ð˜¨'=>1,'ð˜©'=>1,'ð˜ª'=>1,'ð˜«'=>1,'ð˜¬'=>1,'ð˜­'=>1,'ð˜®'=>1,'ð˜¯'=>1,'ð˜°'=>1,'ð˜±'=>1,'ð˜²'=>1,'ð˜³'=>1,'ð˜´'=>1,'ð˜µ'=>1,'ð˜¶'=>1,'ð˜·'=>1,'ð˜¸'=>1,'ð˜¹'=>1,'ð˜º'=>1,'ð˜»'=>1,'ð˜¼'=>1,'ð˜½'=>1,'ð˜¾'=>1,'ð˜¿'=>1,'ð™€'=>1,'ð™'=>1,'ð™‚'=>1,'ð™ƒ'=>1,'ð™„'=>1,'ð™…'=>1,'ð™†'=>1,'ð™‡'=>1,'ð™ˆ'=>1,'ð™‰'=>1,'ð™Š'=>1,'ð™‹'=>1,'ð™Œ'=>1,'ð™'=>1,'ð™Ž'=>1,'ð™'=>1,'ð™'=>1,'ð™‘'=>1,'ð™’'=>1,'ð™“'=>1,'ð™”'=>1,'ð™•'=>1,'ð™–'=>1,'ð™—'=>1,'ð™˜'=>1,'ð™™'=>1,'ð™š'=>1,'ð™›'=>1,'ð™œ'=>1,'ð™'=>1,'ð™ž'=>1,'ð™Ÿ'=>1,'ð™ '=>1,'ð™¡'=>1,'ð™¢'=>1,'ð™£'=>1,'ð™¤'=>1,'ð™¥'=>1,'ð™¦'=>1,'ð™§'=>1,'ð™¨'=>1,'ð™©'=>1,'ð™ª'=>1,'ð™«'=>1,'ð™¬'=>1,'ð™­'=>1,'ð™®'=>1,'ð™¯'=>1,'ð™°'=>1,'ð™±'=>1,'ð™²'=>1,'ð™³'=>1,'ð™´'=>1,'ð™µ'=>1,'ð™¶'=>1,'ð™·'=>1,'ð™¸'=>1,'ð™¹'=>1,'ð™º'=>1,'ð™»'=>1,'ð™¼'=>1,'ð™½'=>1,'ð™¾'=>1,'ð™¿'=>1,'ðš€'=>1,'ðš'=>1,'ðš‚'=>1,'ðšƒ'=>1,'ðš„'=>1,'ðš…'=>1,'ðš†'=>1,'ðš‡'=>1,'ðšˆ'=>1,'ðš‰'=>1,'ðšŠ'=>1,'ðš‹'=>1,'ðšŒ'=>1,'ðš'=>1,'ðšŽ'=>1,'ðš'=>1,'ðš'=>1,'ðš‘'=>1,'ðš’'=>1,'ðš“'=>1,'ðš”'=>1,'ðš•'=>1,'ðš–'=>1,'ðš—'=>1,'ðš˜'=>1,'ðš™'=>1,'ðšš'=>1,'ðš›'=>1,'ðšœ'=>1,'ðš'=>1,'ðšž'=>1,'ðšŸ'=>1,'ðš '=>1,'ðš¡'=>1,'ðš¢'=>1,'ðš£'=>1,'ðš¤'=>1,'ðš¥'=>1,'ðš¨'=>1,'ðš©'=>1,'ðšª'=>1,'ðš«'=>1,'ðš¬'=>1,'ðš­'=>1,'ðš®'=>1,'ðš¯'=>1,'ðš°'=>1,'ðš±'=>1,'ðš²'=>1,'ðš³'=>1,'ðš´'=>1,'ðšµ'=>1,'ðš¶'=>1,'ðš·'=>1,'ðš¸'=>1,'ðš¹'=>1,'ðšº'=>1,'ðš»'=>1,'ðš¼'=>1,'ðš½'=>1,'ðš¾'=>1,'ðš¿'=>1,'ð›€'=>1,'ð›'=>1,'ð›‚'=>1,'ð›ƒ'=>1,'ð›„'=>1,'ð›…'=>1,'ð›†'=>1,'ð›‡'=>1,'ð›ˆ'=>1,'ð›‰'=>1,'ð›Š'=>1,'ð›‹'=>1,'ð›Œ'=>1,'ð›'=>1,'ð›Ž'=>1,'ð›'=>1,'ð›'=>1,'ð›‘'=>1,'ð›’'=>1,'ð›“'=>1,'ð›”'=>1,'ð›•'=>1,'ð›–'=>1,'ð›—'=>1,'ð›˜'=>1,'ð›™'=>1,'ð›š'=>1,'ð››'=>1,'ð›œ'=>1,'ð›'=>1,'ð›ž'=>1,'ð›Ÿ'=>1,'ð› '=>1,'ð›¡'=>1,'ð›¢'=>1,'ð›£'=>1,'ð›¤'=>1,'ð›¥'=>1,'ð›¦'=>1,'ð›§'=>1,'ð›¨'=>1,'ð›©'=>1,'ð›ª'=>1,'ð›«'=>1,'ð›¬'=>1,'ð›­'=>1,'ð›®'=>1,'ð›¯'=>1,'ð›°'=>1,'ð›±'=>1,'ð›²'=>1,'ð›³'=>1,'ð›´'=>1,'ð›µ'=>1,'ð›¶'=>1,'ð›·'=>1,'ð›¸'=>1,'ð›¹'=>1,'ð›º'=>1,'ð›»'=>1,'ð›¼'=>1,'ð›½'=>1,'ð›¾'=>1,'ð›¿'=>1,'ðœ€'=>1,'ðœ'=>1,'ðœ‚'=>1,'ðœƒ'=>1,'ðœ„'=>1,'ðœ…'=>1,'ðœ†'=>1,'ðœ‡'=>1,'ðœˆ'=>1,'ðœ‰'=>1,'ðœŠ'=>1,'ðœ‹'=>1,'ðœŒ'=>1,'ðœ'=>1,'ðœŽ'=>1,'ðœ'=>1,'ðœ'=>1,'ðœ‘'=>1,'ðœ’'=>1,'ðœ“'=>1,'ðœ”'=>1,'ðœ•'=>1,'ðœ–'=>1,'ðœ—'=>1,'ðœ˜'=>1,'ðœ™'=>1,'ðœš'=>1,'ðœ›'=>1,'ðœœ'=>1,'ðœ'=>1,'ðœž'=>1,'ðœŸ'=>1,'ðœ '=>1,'ðœ¡'=>1,'ðœ¢'=>1,'ðœ£'=>1,'ðœ¤'=>1,'ðœ¥'=>1,'ðœ¦'=>1,'ðœ§'=>1,'ðœ¨'=>1,'ðœ©'=>1,'ðœª'=>1,'ðœ«'=>1,'ðœ¬'=>1,'ðœ­'=>1,'ðœ®'=>1,'ðœ¯'=>1,'ðœ°'=>1,'ðœ±'=>1,'ðœ²'=>1,'ðœ³'=>1,'ðœ´'=>1,'ðœµ'=>1,'ðœ¶'=>1,'ðœ·'=>1,'ðœ¸'=>1,'ðœ¹'=>1,'ðœº'=>1,'ðœ»'=>1,'ðœ¼'=>1,'ðœ½'=>1,'ðœ¾'=>1,'ðœ¿'=>1,'ð€'=>1,'ð'=>1,'ð‚'=>1,'ðƒ'=>1,'ð„'=>1,'ð…'=>1,'ð†'=>1,'ð‡'=>1,'ðˆ'=>1,'ð‰'=>1,'ðŠ'=>1,'ð‹'=>1,'ðŒ'=>1,'ð'=>1,'ðŽ'=>1,'ð'=>1,'ð'=>1,'ð‘'=>1,'ð’'=>1,'ð“'=>1,'ð”'=>1,'ð•'=>1,'ð–'=>1,'ð—'=>1,'ð˜'=>1,'ð™'=>1,'ðš'=>1,'ð›'=>1,'ðœ'=>1,'ð'=>1,'ðž'=>1,'ðŸ'=>1,'ð '=>1,'ð¡'=>1,'ð¢'=>1,'ð£'=>1,'ð¤'=>1,'ð¥'=>1,'ð¦'=>1,'ð§'=>1,'ð¨'=>1,'ð©'=>1,'ðª'=>1,'ð«'=>1,'ð¬'=>1,'ð­'=>1,'ð®'=>1,'ð¯'=>1,'ð°'=>1,'ð±'=>1,'ð²'=>1,'ð³'=>1,'ð´'=>1,'ðµ'=>1,'ð¶'=>1,'ð·'=>1,'ð¸'=>1,'ð¹'=>1,'ðº'=>1,'ð»'=>1,'ð¼'=>1,'ð½'=>1,'ð¾'=>1,'ð¿'=>1,'ðž€'=>1,'ðž'=>1,'ðž‚'=>1,'ðžƒ'=>1,'ðž„'=>1,'ðž…'=>1,'ðž†'=>1,'ðž‡'=>1,'ðžˆ'=>1,'ðž‰'=>1,'ðžŠ'=>1,'ðž‹'=>1,'ðžŒ'=>1,'ðž'=>1,'ðžŽ'=>1,'ðž'=>1,'ðž'=>1,'ðž‘'=>1,'ðž’'=>1,'ðž“'=>1,'ðž”'=>1,'ðž•'=>1,'ðž–'=>1,'ðž—'=>1,'ðž˜'=>1,'ðž™'=>1,'ðžš'=>1,'ðž›'=>1,'ðžœ'=>1,'ðž'=>1,'ðžž'=>1,'ðžŸ'=>1,'ðž '=>1,'ðž¡'=>1,'ðž¢'=>1,'ðž£'=>1,'ðž¤'=>1,'ðž¥'=>1,'ðž¦'=>1,'ðž§'=>1,'ðž¨'=>1,'ðž©'=>1,'ðžª'=>1,'ðž«'=>1,'ðž¬'=>1,'ðž­'=>1,'ðž®'=>1,'ðž¯'=>1,'ðž°'=>1,'ðž±'=>1,'ðž²'=>1,'ðž³'=>1,'ðž´'=>1,'ðžµ'=>1,'ðž¶'=>1,'ðž·'=>1,'ðž¸'=>1,'ðž¹'=>1,'ðžº'=>1,'ðž»'=>1,'ðž¼'=>1,'ðž½'=>1,'ðž¾'=>1,'ðž¿'=>1,'ðŸ€'=>1,'ðŸ'=>1,'ðŸ‚'=>1,'ðŸƒ'=>1,'ðŸ„'=>1,'ðŸ…'=>1,'ðŸ†'=>1,'ðŸ‡'=>1,'ðŸˆ'=>1,'ðŸ‰'=>1,'ðŸŠ'=>1,'ðŸ‹'=>1,'ðŸŽ'=>1,'ðŸ'=>1,'ðŸ'=>1,'ðŸ‘'=>1,'ðŸ’'=>1,'ðŸ“'=>1,'ðŸ”'=>1,'ðŸ•'=>1,'ðŸ–'=>1,'ðŸ—'=>1,'ðŸ˜'=>1,'ðŸ™'=>1,'ðŸš'=>1,'ðŸ›'=>1,'ðŸœ'=>1,'ðŸ'=>1,'ðŸž'=>1,'ðŸŸ'=>1,'ðŸ '=>1,'ðŸ¡'=>1,'ðŸ¢'=>1,'ðŸ£'=>1,'ðŸ¤'=>1,'ðŸ¥'=>1,'ðŸ¦'=>1,'ðŸ§'=>1,'ðŸ¨'=>1,'ðŸ©'=>1,'ðŸª'=>1,'ðŸ«'=>1,'ðŸ¬'=>1,'ðŸ­'=>1,'ðŸ®'=>1,'ðŸ¯'=>1,'ðŸ°'=>1,'ðŸ±'=>1,'ðŸ²'=>1,'ðŸ³'=>1,'ðŸ´'=>1,'ðŸµ'=>1,'ðŸ¶'=>1,'ðŸ·'=>1,'ðŸ¸'=>1,'ðŸ¹'=>1,'ðŸº'=>1,'ðŸ»'=>1,'ðŸ¼'=>1,'ðŸ½'=>1,'ðŸ¾'=>1,'ðŸ¿'=>1,'丽'=>1,'ð¯ '=>1,'乁'=>1,'𠄢'=>1,'你'=>1,'侮'=>1,'侻'=>1,'倂'=>1,'偺'=>1,'備'=>1,'僧'=>1,'像'=>1,'㒞'=>1,'ð¯ '=>1,'免'=>1,'ð¯ '=>1,'ð¯ '=>1,'具'=>1,'𠔜'=>1,'㒹'=>1,'內'=>1,'再'=>1,'𠕋'=>1,'冗'=>1,'冤'=>1,'仌'=>1,'冬'=>1,'况'=>1,'𩇟'=>1,'ð¯ '=>1,'刃'=>1,'㓟'=>1,'刻'=>1,'剆'=>1,'割'=>1,'剷'=>1,'㔕'=>1,'勇'=>1,'勉'=>1,'勤'=>1,'勺'=>1,'包'=>1,'匆'=>1,'北'=>1,'卉'=>1,'卑'=>1,'博'=>1,'即'=>1,'卽'=>1,'卿'=>1,'卿'=>1,'卿'=>1,'𠨬'=>1,'灰'=>1,'及'=>1,'叟'=>1,'𠭣'=>1,'叫'=>1,'叱'=>1,'吆'=>1,'咞'=>1,'吸'=>1,'呈'=>1,'周'=>1,'咢'=>1,'ð¯¡'=>1,'唐'=>1,'啓'=>1,'啣'=>1,'善'=>1,'善'=>1,'喙'=>1,'喫'=>1,'喳'=>1,'嗂'=>1,'圖'=>1,'嘆'=>1,'ð¯¡'=>1,'噑'=>1,'ð¯¡'=>1,'ð¯¡'=>1,'壮'=>1,'城'=>1,'埴'=>1,'堍'=>1,'型'=>1,'堲'=>1,'報'=>1,'墬'=>1,'𡓤'=>1,'売'=>1,'壷'=>1,'夆'=>1,'ð¯¡'=>1,'夢'=>1,'奢'=>1,'𡚨'=>1,'𡛪'=>1,'姬'=>1,'娛'=>1,'娧'=>1,'姘'=>1,'婦'=>1,'㛮'=>1,'㛼'=>1,'嬈'=>1,'嬾'=>1,'嬾'=>1,'𡧈'=>1,'寃'=>1,'寘'=>1,'寧'=>1,'寳'=>1,'𡬘'=>1,'寿'=>1,'将'=>1,'当'=>1,'尢'=>1,'㞁'=>1,'屠'=>1,'屮'=>1,'峀'=>1,'岍'=>1,'𡷤'=>1,'嵃'=>1,'𡷦'=>1,'嵮'=>1,'嵫'=>1,'嵼'=>1,'ð¯¢'=>1,'巢'=>1,'㠯'=>1,'巽'=>1,'帨'=>1,'帽'=>1,'幩'=>1,'㡢'=>1,'𢆃'=>1,'㡼'=>1,'庰'=>1,'庳'=>1,'ð¯¢'=>1,'廊'=>1,'ð¯¢'=>1,'ð¯¢'=>1,'𢌱'=>1,'𢌱'=>1,'舁'=>1,'弢'=>1,'弢'=>1,'㣇'=>1,'𣊸'=>1,'𦇚'=>1,'形'=>1,'彫'=>1,'㣣'=>1,'徚'=>1,'ð¯¢'=>1,'志'=>1,'忹'=>1,'悁'=>1,'㤺'=>1,'㤜'=>1,'悔'=>1,'𢛔'=>1,'惇'=>1,'慈'=>1,'慌'=>1,'慎'=>1,'慌'=>1,'慺'=>1,'憎'=>1,'憲'=>1,'憤'=>1,'憯'=>1,'懞'=>1,'懲'=>1,'懶'=>1,'成'=>1,'戛'=>1,'扝'=>1,'抱'=>1,'拔'=>1,'捐'=>1,'𢬌'=>1,'挽'=>1,'拼'=>1,'捨'=>1,'掃'=>1,'揤'=>1,'𢯱'=>1,'搢'=>1,'揅'=>1,'ð¯£'=>1,'㨮'=>1,'摩'=>1,'摾'=>1,'撝'=>1,'摷'=>1,'㩬'=>1,'敏'=>1,'敬'=>1,'𣀊'=>1,'旣'=>1,'書'=>1,'ð¯£'=>1,'㬙'=>1,'ð¯£'=>1,'ð¯£'=>1,'㫤'=>1,'冒'=>1,'冕'=>1,'最'=>1,'暜'=>1,'肭'=>1,'䏙'=>1,'朗'=>1,'望'=>1,'朡'=>1,'杞'=>1,'杓'=>1,'ð¯£'=>1,'㭉'=>1,'柺'=>1,'枅'=>1,'桒'=>1,'梅'=>1,'𣑭'=>1,'梎'=>1,'栟'=>1,'椔'=>1,'㮝'=>1,'楂'=>1,'榣'=>1,'槪'=>1,'檨'=>1,'𣚣'=>1,'櫛'=>1,'㰘'=>1,'次'=>1,'𣢧'=>1,'歔'=>1,'㱎'=>1,'歲'=>1,'殟'=>1,'殺'=>1,'殻'=>1,'𣪍'=>1,'𡴋'=>1,'𣫺'=>1,'汎'=>1,'𣲼'=>1,'沿'=>1,'泍'=>1,'汧'=>1,'洖'=>1,'派'=>1,'ð¯¤'=>1,'流'=>1,'浩'=>1,'浸'=>1,'涅'=>1,'𣴞'=>1,'洴'=>1,'港'=>1,'湮'=>1,'㴳'=>1,'滋'=>1,'滇'=>1,'ð¯¤'=>1,'淹'=>1,'ð¯¤'=>1,'ð¯¤'=>1,'𣾎'=>1,'濆'=>1,'瀹'=>1,'瀞'=>1,'瀛'=>1,'㶖'=>1,'灊'=>1,'災'=>1,'灷'=>1,'炭'=>1,'𠔥'=>1,'煅'=>1,'ð¯¤'=>1,'熜'=>1,'𤎫'=>1,'爨'=>1,'爵'=>1,'牐'=>1,'𤘈'=>1,'犀'=>1,'犕'=>1,'𤜵'=>1,'𤠔'=>1,'獺'=>1,'王'=>1,'㺬'=>1,'玥'=>1,'㺸'=>1,'㺸'=>1,'瑇'=>1,'瑜'=>1,'瑱'=>1,'璅'=>1,'瓊'=>1,'㼛'=>1,'甤'=>1,'𤰶'=>1,'甾'=>1,'𤲒'=>1,'異'=>1,'𢆟'=>1,'瘐'=>1,'𤾡'=>1,'𤾸'=>1,'𥁄'=>1,'㿼'=>1,'䀈'=>1,'直'=>1,'ð¯¥'=>1,'𥃲'=>1,'𥄙'=>1,'𥄳'=>1,'眞'=>1,'真'=>1,'真'=>1,'睊'=>1,'䀹'=>1,'瞋'=>1,'䁆'=>1,'䂖'=>1,'ð¯¥'=>1,'硎'=>1,'ð¯¥'=>1,'ð¯¥'=>1,'䃣'=>1,'𥘦'=>1,'祖'=>1,'𥚚'=>1,'𥛅'=>1,'福'=>1,'秫'=>1,'䄯'=>1,'穀'=>1,'穊'=>1,'穏'=>1,'𥥼'=>1,'ð¯¥'=>1,'𥪧'=>1,'竮'=>1,'䈂'=>1,'𥮫'=>1,'篆'=>1,'築'=>1,'䈧'=>1,'𥲀'=>1,'糒'=>1,'䊠'=>1,'糨'=>1,'糣'=>1,'紀'=>1,'𥾆'=>1,'絣'=>1,'䌁'=>1,'緇'=>1,'縂'=>1,'繅'=>1,'䌴'=>1,'𦈨'=>1,'𦉇'=>1,'䍙'=>1,'𦋙'=>1,'罺'=>1,'𦌾'=>1,'羕'=>1,'翺'=>1,'者'=>1,'𦓚'=>1,'𦔣'=>1,'聠'=>1,'𦖨'=>1,'聰'=>1,'𣍟'=>1,'ð¯¦'=>1,'育'=>1,'脃'=>1,'䐋'=>1,'脾'=>1,'媵'=>1,'𦞧'=>1,'𦞵'=>1,'𣎓'=>1,'𣎜'=>1,'舁'=>1,'舄'=>1,'ð¯¦'=>1,'䑫'=>1,'ð¯¦'=>1,'ð¯¦'=>1,'芝'=>1,'劳'=>1,'花'=>1,'芳'=>1,'芽'=>1,'苦'=>1,'𦬼'=>1,'若'=>1,'茝'=>1,'荣'=>1,'莭'=>1,'茣'=>1,'ð¯¦'=>1,'菧'=>1,'著'=>1,'荓'=>1,'菊'=>1,'菌'=>1,'菜'=>1,'𦰶'=>1,'𦵫'=>1,'𦳕'=>1,'䔫'=>1,'蓱'=>1,'蓳'=>1,'蔖'=>1,'𧏊'=>1,'蕤'=>1,'𦼬'=>1,'䕝'=>1,'䕡'=>1,'𦾱'=>1,'𧃒'=>1,'䕫'=>1,'虐'=>1,'虜'=>1,'虧'=>1,'虩'=>1,'蚩'=>1,'蚈'=>1,'蜎'=>1,'蛢'=>1,'蝹'=>1,'蜨'=>1,'蝫'=>1,'螆'=>1,'䗗'=>1,'蟡'=>1,'ð¯§'=>1,'䗹'=>1,'衠'=>1,'衣'=>1,'𧙧'=>1,'裗'=>1,'裞'=>1,'䘵'=>1,'裺'=>1,'㒻'=>1,'𧢮'=>1,'𧥦'=>1,'ð¯§'=>1,'䛇'=>1,'ð¯§'=>1,'ð¯§'=>1,'變'=>1,'豕'=>1,'𧲨'=>1,'貫'=>1,'賁'=>1,'贛'=>1,'起'=>1,'𧼯'=>1,'𠠄'=>1,'跋'=>1,'趼'=>1,'跰'=>1,'ð¯§'=>1,'軔'=>1,'輸'=>1,'𨗒'=>1,'𨗭'=>1,'邔'=>1,'郱'=>1,'鄑'=>1,'𨜮'=>1,'鄛'=>1,'鈸'=>1,'鋗'=>1,'鋘'=>1,'鉼'=>1,'鏹'=>1,'鐕'=>1,'𨯺'=>1,'開'=>1,'䦕'=>1,'閷'=>1,'𨵷'=>1,'䧦'=>1,'雃'=>1,'嶲'=>1,'霣'=>1,'𩅅'=>1,'𩈚'=>1,'䩮'=>1,'䩶'=>1,'韠'=>1,'𩐊'=>1,'䪲'=>1,'𩒖'=>1,'頋'=>1,'頋'=>1,'頩'=>1,'ð¯¨'=>1,'飢'=>1,'䬳'=>1,'餩'=>1,'馧'=>1,'駂'=>1,'駾'=>1,'䯎'=>1,'𩬰'=>1,'鬒'=>1,'鱀'=>1,'鳽'=>1,'ð¯¨'=>1,'䳭'=>1,'ð¯¨'=>1,'ð¯¨'=>1,'䳸'=>1,'𪄅'=>1,'𪈎'=>1,'𪊑'=>1,'麻'=>1,'䵖'=>1,'黹'=>1,'黾'=>1,'鼅'=>1,'鼏'=>1,'鼖'=>1,'鼻'=>1,'ð¯¨'=>1,'Ì€'=>0,'Ì'=>0,'Ì‚'=>0,'̃'=>0,'Ì„'=>0,'̆'=>0,'̇'=>0,'̈'=>0,'̉'=>0,'ÌŠ'=>0,'Ì‹'=>0,'ÌŒ'=>0,'Ì'=>0,'Ì‘'=>0,'Ì“'=>0,'Ì”'=>0,'Ì›'=>0,'Ì£'=>0,'̤'=>0,'Ì¥'=>0,'̦'=>0,'̧'=>0,'̨'=>0,'Ì­'=>0,'Ì®'=>0,'̰'=>0,'̱'=>0,'̸'=>0,'Í‚'=>0,'Í…'=>0,'Ù“'=>0,'Ù”'=>0,'Ù•'=>0,'़'=>0,'া'=>0,'à§—'=>0,'ା'=>0,'à­–'=>0,'à­—'=>0,'ா'=>0,'ௗ'=>0,'à±–'=>0,'ೂ'=>0,'ೕ'=>0,'à³–'=>0,'à´¾'=>0,'ൗ'=>0,'à·Š'=>0,'à·'=>0,'à·Ÿ'=>0,'ီ'=>0,'á…¡'=>0,'á…¢'=>0,'á…£'=>0,'á…¤'=>0,'á…¥'=>0,'á…¦'=>0,'á…§'=>0,'á…¨'=>0,'á…©'=>0,'á…ª'=>0,'á…«'=>0,'á…¬'=>0,'á…­'=>0,'á…®'=>0,'á…¯'=>0,'á…°'=>0,'á…±'=>0,'á…²'=>0,'á…³'=>0,'á…´'=>0,'á…µ'=>0,'ᆨ'=>0,'ᆩ'=>0,'ᆪ'=>0,'ᆫ'=>0,'ᆬ'=>0,'ᆭ'=>0,'ᆮ'=>0,'ᆯ'=>0,'ᆰ'=>0,'ᆱ'=>0,'ᆲ'=>0,'ᆳ'=>0,'ᆴ'=>0,'ᆵ'=>0,'ᆶ'=>0,'ᆷ'=>0,'ᆸ'=>0,'ᆹ'=>0,'ᆺ'=>0,'ᆻ'=>0,'ᆼ'=>0,'ᆽ'=>0,'ᆾ'=>0,'ᆿ'=>0,'ᇀ'=>0,'á‡'=>0,'ᇂ'=>0,'ᬵ'=>0,'ã‚™'=>0,'゚'=>0); diff --git a/phpBB/includes/utf/data/utf_normalizer_common.php b/phpBB/includes/utf/data/utf_normalizer_common.php deleted file mode 100644 index 2eb7feac69..0000000000 --- a/phpBB/includes/utf/data/utf_normalizer_common.php +++ /dev/null @@ -1,4 +0,0 @@ -44032,'á„'=>44620,'á„‚'=>45208,'ᄃ'=>45796,'á„„'=>46384,'á„…'=>46972,'ᄆ'=>47560,'ᄇ'=>48148,'ᄈ'=>48736,'ᄉ'=>49324,'ᄊ'=>49912,'á„‹'=>50500,'ᄌ'=>51088,'á„'=>51676,'ᄎ'=>52264,'á„'=>52852,'á„'=>53440,'á„‘'=>54028,'á„’'=>54616,'á…¡'=>0,'á…¢'=>28,'á…£'=>56,'á…¤'=>84,'á…¥'=>112,'á…¦'=>140,'á…§'=>168,'á…¨'=>196,'á…©'=>224,'á…ª'=>252,'á…«'=>280,'á…¬'=>308,'á…­'=>336,'á…®'=>364,'á…¯'=>392,'á…°'=>420,'á…±'=>448,'á…²'=>476,'á…³'=>504,'á…´'=>532,'á…µ'=>560,'ᆧ'=>0,'ᆨ'=>1,'ᆩ'=>2,'ᆪ'=>3,'ᆫ'=>4,'ᆬ'=>5,'ᆭ'=>6,'ᆮ'=>7,'ᆯ'=>8,'ᆰ'=>9,'ᆱ'=>10,'ᆲ'=>11,'ᆳ'=>12,'ᆴ'=>13,'ᆵ'=>14,'ᆶ'=>15,'ᆷ'=>16,'ᆸ'=>17,'ᆹ'=>18,'ᆺ'=>19,'ᆻ'=>20,'ᆼ'=>21,'ᆽ'=>22,'ᆾ'=>23,'ᆿ'=>24,'ᇀ'=>25,'á‡'=>26,'ᇂ'=>27); -$GLOBALS['utf_jamo_type']=array('á„€'=>0,'á„'=>0,'á„‚'=>0,'ᄃ'=>0,'á„„'=>0,'á„…'=>0,'ᄆ'=>0,'ᄇ'=>0,'ᄈ'=>0,'ᄉ'=>0,'ᄊ'=>0,'á„‹'=>0,'ᄌ'=>0,'á„'=>0,'ᄎ'=>0,'á„'=>0,'á„'=>0,'á„‘'=>0,'á„’'=>0,'á…¡'=>1,'á…¢'=>1,'á…£'=>1,'á…¤'=>1,'á…¥'=>1,'á…¦'=>1,'á…§'=>1,'á…¨'=>1,'á…©'=>1,'á…ª'=>1,'á…«'=>1,'á…¬'=>1,'á…­'=>1,'á…®'=>1,'á…¯'=>1,'á…°'=>1,'á…±'=>1,'á…²'=>1,'á…³'=>1,'á…´'=>1,'á…µ'=>1,'ᆧ'=>2,'ᆨ'=>2,'ᆩ'=>2,'ᆪ'=>2,'ᆫ'=>2,'ᆬ'=>2,'ᆭ'=>2,'ᆮ'=>2,'ᆯ'=>2,'ᆰ'=>2,'ᆱ'=>2,'ᆲ'=>2,'ᆳ'=>2,'ᆴ'=>2,'ᆵ'=>2,'ᆶ'=>2,'ᆷ'=>2,'ᆸ'=>2,'ᆹ'=>2,'ᆺ'=>2,'ᆻ'=>2,'ᆼ'=>2,'ᆽ'=>2,'ᆾ'=>2,'ᆿ'=>2,'ᇀ'=>2,'á‡'=>2,'ᇂ'=>2); -$GLOBALS['utf_combining_class']=array('Ì€'=>230,'Ì'=>230,'Ì‚'=>230,'̃'=>230,'Ì„'=>230,'Ì…'=>230,'̆'=>230,'̇'=>230,'̈'=>230,'̉'=>230,'ÌŠ'=>230,'Ì‹'=>230,'ÌŒ'=>230,'Ì'=>230,'ÌŽ'=>230,'Ì'=>230,'Ì'=>230,'Ì‘'=>230,'Ì’'=>230,'Ì“'=>230,'Ì”'=>230,'Ì•'=>232,'Ì–'=>220,'Ì—'=>220,'̘'=>220,'Ì™'=>220,'Ìš'=>232,'Ì›'=>216,'Ìœ'=>220,'Ì'=>220,'Ìž'=>220,'ÌŸ'=>220,'Ì '=>220,'Ì¡'=>202,'Ì¢'=>202,'Ì£'=>220,'̤'=>220,'Ì¥'=>220,'̦'=>220,'̧'=>202,'̨'=>202,'Ì©'=>220,'̪'=>220,'Ì«'=>220,'̬'=>220,'Ì­'=>220,'Ì®'=>220,'̯'=>220,'̰'=>220,'̱'=>220,'̲'=>220,'̳'=>220,'Ì´'=>1,'̵'=>1,'̶'=>1,'Ì·'=>1,'̸'=>1,'̹'=>220,'̺'=>220,'Ì»'=>220,'̼'=>220,'̽'=>230,'̾'=>230,'Ì¿'=>230,'Í€'=>230,'Í'=>230,'Í‚'=>230,'̓'=>230,'Í„'=>230,'Í…'=>240,'͆'=>230,'͇'=>220,'͈'=>220,'͉'=>220,'ÍŠ'=>230,'Í‹'=>230,'ÍŒ'=>230,'Í'=>220,'ÍŽ'=>220,'Í'=>230,'Í‘'=>230,'Í’'=>230,'Í“'=>220,'Í”'=>220,'Í•'=>220,'Í–'=>220,'Í—'=>230,'͘'=>232,'Í™'=>220,'Íš'=>220,'Í›'=>230,'Íœ'=>233,'Í'=>234,'Íž'=>234,'ÍŸ'=>233,'Í '=>234,'Í¡'=>234,'Í¢'=>233,'Í£'=>230,'ͤ'=>230,'Í¥'=>230,'ͦ'=>230,'ͧ'=>230,'ͨ'=>230,'Í©'=>230,'ͪ'=>230,'Í«'=>230,'ͬ'=>230,'Í­'=>230,'Í®'=>230,'ͯ'=>230,'Òƒ'=>230,'Ò„'=>230,'Ò…'=>230,'Ò†'=>230,'Ö‘'=>220,'Ö’'=>230,'Ö“'=>230,'Ö”'=>230,'Ö•'=>230,'Ö–'=>220,'Ö—'=>230,'Ö˜'=>230,'Ö™'=>230,'Öš'=>222,'Ö›'=>220,'Öœ'=>230,'Ö'=>230,'Öž'=>230,'ÖŸ'=>230,'Ö '=>230,'Ö¡'=>230,'Ö¢'=>220,'Ö£'=>220,'Ö¤'=>220,'Ö¥'=>220,'Ö¦'=>220,'Ö§'=>220,'Ö¨'=>230,'Ö©'=>230,'Öª'=>220,'Ö«'=>230,'Ö¬'=>230,'Ö­'=>222,'Ö®'=>228,'Ö¯'=>230,'Ö°'=>10,'Ö±'=>11,'Ö²'=>12,'Ö³'=>13,'Ö´'=>14,'Öµ'=>15,'Ö¶'=>16,'Ö·'=>17,'Ö¸'=>18,'Ö¹'=>19,'Öº'=>19,'Ö»'=>20,'Ö¼'=>21,'Ö½'=>22,'Ö¿'=>23,'×'=>24,'ׂ'=>25,'ׄ'=>230,'×…'=>220,'ׇ'=>18,'Ø'=>230,'Ø‘'=>230,'Ø’'=>230,'Ø“'=>230,'Ø”'=>230,'Ø•'=>230,'Ù‹'=>27,'ÙŒ'=>28,'Ù'=>29,'ÙŽ'=>30,'Ù'=>31,'Ù'=>32,'Ù‘'=>33,'Ù’'=>34,'Ù“'=>230,'Ù”'=>230,'Ù•'=>220,'Ù–'=>220,'Ù—'=>230,'Ù˜'=>230,'Ù™'=>230,'Ùš'=>230,'Ù›'=>230,'Ùœ'=>220,'Ù'=>230,'Ùž'=>230,'Ù°'=>35,'Û–'=>230,'Û—'=>230,'Û˜'=>230,'Û™'=>230,'Ûš'=>230,'Û›'=>230,'Ûœ'=>230,'ÛŸ'=>230,'Û '=>230,'Û¡'=>230,'Û¢'=>230,'Û£'=>220,'Û¤'=>230,'Û§'=>230,'Û¨'=>230,'Ûª'=>220,'Û«'=>230,'Û¬'=>230,'Û­'=>220,'Ü‘'=>36,'ܰ'=>230,'ܱ'=>220,'ܲ'=>230,'ܳ'=>230,'Ü´'=>220,'ܵ'=>230,'ܶ'=>230,'Ü·'=>220,'ܸ'=>220,'ܹ'=>220,'ܺ'=>230,'Ü»'=>220,'ܼ'=>220,'ܽ'=>230,'ܾ'=>220,'Ü¿'=>230,'Ý€'=>230,'Ý'=>230,'Ý‚'=>220,'݃'=>230,'Ý„'=>220,'Ý…'=>230,'݆'=>220,'݇'=>230,'݈'=>220,'݉'=>230,'ÝŠ'=>230,'ß«'=>230,'߬'=>230,'ß­'=>230,'ß®'=>230,'߯'=>230,'ß°'=>230,'ß±'=>230,'ß²'=>220,'ß³'=>230,'़'=>7,'à¥'=>9,'॑'=>230,'॒'=>220,'॓'=>230,'॔'=>230,'়'=>7,'à§'=>9,'਼'=>7,'à©'=>9,'઼'=>7,'à«'=>9,'଼'=>7,'à­'=>9,'à¯'=>9,'à±'=>9,'ౕ'=>84,'à±–'=>91,'಼'=>7,'à³'=>9,'àµ'=>9,'à·Š'=>9,'ุ'=>103,'ู'=>103,'ฺ'=>9,'่'=>107,'้'=>107,'๊'=>107,'๋'=>107,'ຸ'=>118,'ູ'=>118,'່'=>122,'້'=>122,'໊'=>122,'໋'=>122,'༘'=>220,'༙'=>220,'༵'=>220,'༷'=>220,'༹'=>216,'ཱ'=>129,'ི'=>130,'ུ'=>132,'ེ'=>130,'ཻ'=>130,'ོ'=>130,'ཽ'=>130,'ྀ'=>130,'ྂ'=>230,'ྃ'=>230,'྄'=>9,'྆'=>230,'྇'=>230,'࿆'=>220,'့'=>7,'္'=>9,'áŸ'=>230,'᜔'=>9,'᜴'=>9,'្'=>9,'áŸ'=>230,'ᢩ'=>228,'᤹'=>222,'᤺'=>230,'᤻'=>220,'ᨗ'=>230,'ᨘ'=>220,'᬴'=>7,'á­„'=>9,'á­«'=>230,'á­¬'=>220,'á­­'=>230,'á­®'=>230,'á­¯'=>230,'á­°'=>230,'á­±'=>230,'á­²'=>230,'á­³'=>230,'á·€'=>230,'á·'=>230,'á·‚'=>220,'á·ƒ'=>230,'á·„'=>230,'á·…'=>230,'á·†'=>230,'á·‡'=>230,'á·ˆ'=>230,'á·‰'=>230,'á·Š'=>220,'á·¾'=>230,'á·¿'=>220,'âƒ'=>230,'⃑'=>230,'⃒'=>1,'⃓'=>1,'⃔'=>230,'⃕'=>230,'⃖'=>230,'⃗'=>230,'⃘'=>1,'⃙'=>1,'⃚'=>1,'⃛'=>230,'⃜'=>230,'⃡'=>230,'⃥'=>1,'⃦'=>1,'⃧'=>230,'⃨'=>220,'⃩'=>230,'⃪'=>1,'⃫'=>1,'⃬'=>220,'⃭'=>220,'⃮'=>220,'⃯'=>220,'〪'=>218,'〫'=>228,'〬'=>232,'〭'=>222,'〮'=>224,'〯'=>224,'ã‚™'=>8,'゚'=>8,'ê †'=>9,'ﬞ'=>26,'︠'=>230,'︡'=>230,'︢'=>230,'︣'=>230,'ð¨'=>220,'ð¨'=>230,'ð¨¸'=>230,'ð¨¹'=>1,'ð¨º'=>220,'ð¨¿'=>9,'ð…¥'=>216,'ð…¦'=>216,'ð…§'=>1,'ð…¨'=>1,'ð…©'=>1,'ð…­'=>226,'ð…®'=>216,'ð…¯'=>216,'ð…°'=>216,'ð…±'=>216,'ð…²'=>216,'ð…»'=>220,'ð…¼'=>220,'ð…½'=>220,'ð…¾'=>220,'ð…¿'=>220,'ð†€'=>220,'ð†'=>220,'ð†‚'=>220,'ð†…'=>230,'ð††'=>230,'ð†‡'=>230,'ð†ˆ'=>230,'ð†‰'=>230,'ð†Š'=>220,'ð†‹'=>220,'ð†ª'=>230,'ð†«'=>230,'ð†¬'=>230,'ð†­'=>230,'ð‰‚'=>230,'ð‰ƒ'=>230,'ð‰„'=>230); diff --git a/phpBB/includes/utf/utf_normalizer.php b/phpBB/includes/utf/utf_normalizer.php deleted file mode 100644 index bbb23a6617..0000000000 --- a/phpBB/includes/utf/utf_normalizer.php +++ /dev/null @@ -1,1509 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -/** -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Some Unicode characters encoded in UTF-8 -* -* Preserved for compatibility -*/ -define('UTF8_REPLACEMENT', "\xEF\xBF\xBD"); -define('UTF8_MAX', "\xF4\x8F\xBF\xBF"); -define('UTF8_FFFE', "\xEF\xBF\xBE"); -define('UTF8_FFFF', "\xEF\xBF\xBF"); -define('UTF8_SURROGATE_FIRST', "\xED\xA0\x80"); -define('UTF8_SURROGATE_LAST', "\xED\xBF\xBF"); -define('UTF8_HANGUL_FIRST', "\xEA\xB0\x80"); -define('UTF8_HANGUL_LAST', "\xED\x9E\xA3"); - -define('UTF8_CJK_FIRST', "\xE4\xB8\x80"); -define('UTF8_CJK_LAST', "\xE9\xBE\xBB"); -define('UTF8_CJK_B_FIRST', "\xF0\xA0\x80\x80"); -define('UTF8_CJK_B_LAST', "\xF0\xAA\x9B\x96"); - -// Unset global variables -unset($GLOBALS['utf_jamo_index'], $GLOBALS['utf_jamo_type'], $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_combining_class'], $GLOBALS['utf_canonical_comp'], $GLOBALS['utf_canonical_decomp'], $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']); - -// NFC_QC and NFKC_QC values -define('UNICODE_QC_MAYBE', 0); -define('UNICODE_QC_NO', 1); - -// Contains all the ASCII characters appearing in UTF-8, sorted by frequency -define('UTF8_ASCII_RANGE', "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"); - -// Contains all the tail bytes that can appear in the composition of a UTF-8 char -define('UTF8_TRAILING_BYTES', "\xA9\xA0\xA8\x80\xAA\x99\xA7\xBB\xAB\x89\x94\x82\xB4\xA2\xAE\x83\xB0\xB9\xB8\x93\xAF\xBC\xB3\x81\xA4\xB2\x9C\xA1\xB5\xBE\xBD\xBA\x98\xAD\xB1\x84\x95\xA6\xB6\x88\x8D\x90\xB7\xBF\x92\x85\xA5\x97\x8C\x86\xA3\x8E\x9F\x8F\x87\x91\x9D\xAC\x9E\x8B\x96\x9B\x8A\x9A"); - -// Constants used by the Hangul [de]composition algorithms -define('UNICODE_HANGUL_SBASE', 0xAC00); -define('UNICODE_HANGUL_LBASE', 0x1100); -define('UNICODE_HANGUL_VBASE', 0x1161); -define('UNICODE_HANGUL_TBASE', 0x11A7); -define('UNICODE_HANGUL_SCOUNT', 11172); -define('UNICODE_HANGUL_LCOUNT', 19); -define('UNICODE_HANGUL_VCOUNT', 21); -define('UNICODE_HANGUL_TCOUNT', 28); -define('UNICODE_HANGUL_NCOUNT', 588); -define('UNICODE_JAMO_L', 0); -define('UNICODE_JAMO_V', 1); -define('UNICODE_JAMO_T', 2); - -/** -* Unicode normalization routines -*/ -class utf_normalizer -{ - /** - * Validate, cleanup and normalize a string - * - * The ultimate convenience function! Clean up invalid UTF-8 sequences, - * and convert to Normal Form C, canonical composition. - * - * @param string &$str The dirty string - * @return string The same string, all shiny and cleaned-up - */ - static function cleanup(&$str) - { - // The string below is the list of all autorized characters, sorted by frequency in latin text - $pos = strspn($str, "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x0D"); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings with no special chars return immediately - return; - } - - // Note: we do not check for $GLOBALS['utf_canonical_decomp']. It is assumed they are always loaded together - if (!isset($GLOBALS['utf_nfc_qc'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx); - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); - } - - // Replace any byte in the range 0x00..0x1F, except for \r, \n and \t - // We replace those characters with a 0xFF byte, which is illegal in UTF-8 and will in turn be replaced with a UTF replacement char - $str = strtr( - $str, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", - "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" - ); - - $str = utf_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFC - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - static function nfc(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_nfc_qc'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx); - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); - } - - $str = utf_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFKC - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - static function nfkc(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_nfkc_qc'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_nfkc_qc.' . $phpEx); - } - - if (!isset($GLOBALS['utf_compatibility_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx); - } - - $str = utf_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']); - } - - /** - * Validate and normalize a UTF string to NFD - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - static function nfd(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); - } - - $str = utf_normalizer::decompose($str, $pos, $len, $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFKD - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - static function nfkd(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_compatibility_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx); - } - - $str = utf_normalizer::decompose($str, $pos, $len, $GLOBALS['utf_compatibility_decomp']); - } - - - /** - * Recompose a UTF string - * - * @param string $str Unchecked UTF string - * @param integer $pos Position of the first UTF char (in bytes) - * @param integer $len Length of the string (in bytes) - * @param array &$qc Quick-check array, passed by reference but never modified - * @param array &$decomp_map Decomposition mapping, passed by reference but never modified - * @return string The string, validated and recomposed - * - * @access private - */ - static function recompose($str, $pos, $len, &$qc, &$decomp_map) - { - global $utf_combining_class, $utf_canonical_comp, $utf_jamo_type, $utf_jamo_index; - - // Load some commonly-used tables - if (!isset($utf_jamo_index, $utf_jamo_type, $utf_combining_class)) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.' . $phpEx); - } - - // Load the canonical composition table - if (!isset($utf_canonical_comp)) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_comp.' . $phpEx); - } - - // Buffer the last ASCII char before the UTF-8 stuff if applicable - $tmp = ''; - $i = $tmp_pos = $last_cc = 0; - - $buffer = ($pos) ? array(++$i => $str[$pos - 1]) : array(); - - // UTF char length array - // This array is used to determine the length of a UTF character. - // Be $c the result of ($str[$pos] & "\xF0") --where $str is the string we're operating on and $pos - // the position of the cursor--, if $utf_len_mask[$c] does not exist, the byte is an ASCII char. - // Otherwise, if $utf_len_mask[$c] is greater than 0, we have a the leading byte of a multibyte character - // whose length is $utf_len_mask[$c] and if it is equal to 0, the byte is a trailing byte. - $utf_len_mask = array( - // Leading bytes masks - "\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4, - // Trailing bytes masks - "\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0 - ); - - $extra_check = array( - "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1, - "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1, - "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1 - ); - - $utf_validation_mask = array( - 2 => "\xE0\xC0", - 3 => "\xF0\xC0\xC0", - 4 => "\xF8\xC0\xC0\xC0" - ); - - $utf_validation_check = array( - 2 => "\xC0\x80", - 3 => "\xE0\x80\x80", - 4 => "\xF0\x80\x80\x80" - ); - - // Main loop - do - { - // STEP 0: Capture the current char and buffer it - $c = $str[$pos]; - $c_mask = $c & "\xF0"; - - if (isset($utf_len_mask[$c_mask])) - { - // Byte at $pos is either a leading byte or a missplaced trailing byte - if ($utf_len = $utf_len_mask[$c_mask]) - { - // Capture the char - $buffer[++$i & 7] = $utf_char = substr($str, $pos, $utf_len); - - // Let's find out if a thorough check is needed - if (isset($qc[$utf_char])) - { - // If the UTF char is in the qc array then it may not be in normal form. We do nothing here, the actual processing is below this "if" block - } - else if (isset($utf_combining_class[$utf_char])) - { - if ($utf_combining_class[$utf_char] < $last_cc) - { - // A combining character that is NOT canonically ordered - } - else - { - // A combining character that IS canonically ordered, skip to the next char - $last_cc = $utf_combining_class[$utf_char]; - - $pos += $utf_len; - continue; - } - } - else - { - // At this point, $utf_char holds a UTF char that we know is not a NF[K]C_QC and is not a combining character. - // It can be a singleton, a canonical composite, a replacement char or an even an ill-formed bunch of bytes. Let's find out - $last_cc = 0; - - // Check that we have the correct number of trailing bytes - if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len]) - { - // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char - // has been encoded in a five- or six- byte sequence - if ($utf_char[0] >= "\xF8") - { - if ($utf_char[0] < "\xFC") - { - $trailing_bytes = 4; - } - else if ($utf_char[0] > "\xFD") - { - $trailing_bytes = 0; - } - else - { - $trailing_bytes = 5; - } - } - else - { - $trailing_bytes = $utf_len - 1; - } - - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += strspn($str, UTF8_TRAILING_BYTES, ++$pos, $trailing_bytes); - $tmp_pos = $pos; - - continue; - } - - if (isset($extra_check[$c])) - { - switch ($c) - { - // Note: 0xED is quite common in Korean - case "\xED": - if ($utf_char >= "\xED\xA0\x80") - { - // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF) - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - // Note: 0xEF is quite common in Japanese - case "\xEF": - if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF") - { - // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF) - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - case "\xC0": - case "\xC1": - if ($utf_char <= "\xC1\xBF") - { - // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - case "\xE0": - if ($utf_char <= "\xE0\x9F\xBF") - { - // Unicode char U+0000..U+07FF encoded in 3 bytes - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - case "\xF0": - if ($utf_char <= "\xF0\x8F\xBF\xBF") - { - // Unicode char U+0000..U+FFFF encoded in 4 bytes - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - default: - // Five- and six- byte sequences do not need being checked for here anymore - if ($utf_char > UTF8_MAX) - { - // Out of the Unicode range - if ($utf_char[0] < "\xF8") - { - $trailing_bytes = 3; - } - else if ($utf_char[0] < "\xFC") - { - $trailing_bytes = 4; - } - else if ($utf_char[0] > "\xFD") - { - $trailing_bytes = 0; - } - else - { - $trailing_bytes = 5; - } - - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += strspn($str, UTF8_TRAILING_BYTES, ++$pos, $trailing_bytes); - $tmp_pos = $pos; - continue 2; - } - break; - } - } - - // The char is a valid starter, move the cursor and go on - $pos += $utf_len; - continue; - } - } - else - { - // A trailing byte came out of nowhere, we will advance the cursor and treat the this byte and all following trailing bytes as if - // each of them was a Unicode replacement char - $spn = strspn($str, UTF8_TRAILING_BYTES, $pos); - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(UTF8_REPLACEMENT, $spn); - - $pos += $spn; - $tmp_pos = $pos; - continue; - } - - // STEP 1: Decompose current char - - // We have found a character that is either: - // - in the NFC_QC/NFKC_QC list - // - a non-starter char that is not canonically ordered - // - // We are going to capture the shortest UTF sequence that satisfies these two conditions: - // - // 1 - If the sequence does not start at the begginning of the string, it must begin with a starter, - // and that starter must not have the NF[K]C_QC property equal to "MAYBE" - // - // 2 - If the sequence does not end at the end of the string, it must end with a non-starter and be - // immediately followed by a starter that is not on the QC list - // - $utf_seq = array(); - $last_cc = 0; - $lpos = $pos; - $pos += $utf_len; - - if (isset($decomp_map[$utf_char])) - { - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $_utf_len =& $utf_len_mask[$decomp_map[$utf_char][$_pos] & "\xF0"]; - - if (isset($_utf_len)) - { - $utf_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $utf_seq[] = $decomp_map[$utf_char][$_pos]; - ++$_pos; - } - } - while ($_pos < $_len); - } - else - { - // The char is not decomposable - $utf_seq = array($utf_char); - } - - // STEP 2: Capture the starter - - // Check out the combining class of the first character of the UTF sequence - $k = 0; - if (isset($utf_combining_class[$utf_seq[0]]) || $qc[$utf_char] == UNICODE_QC_MAYBE) - { - // Not a starter, inspect previous characters - // The last 8 characters are kept in a buffer so that we don't have to capture them everytime. - // This is enough for all real-life strings but even if it wasn't, we can capture characters in backward mode, - // although it is slower than this method. - // - // In the following loop, $j starts at the previous buffered character ($i - 1, because current character is - // at offset $i) and process them in backward mode until we find a starter. - // - // $k is the index on each UTF character inside of our UTF sequence. At this time, $utf_seq contains one or more - // characters numbered 0 to n. $k starts at 0 and for each char we prepend we pre-decrement it and for numbering - $starter_found = 0; - $j_min = max(1, $i - 7); - - for ($j = $i - 1; $j >= $j_min && $lpos > $tmp_pos; --$j) - { - $utf_char = $buffer[$j & 7]; - $lpos -= strlen($utf_char); - - if (isset($decomp_map[$utf_char])) - { - // The char is a composite, decompose for storage - $decomp_seq = array(); - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $decomp_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $decomp_seq[] = $c; - ++$_pos; - } - } - while ($_pos < $_len); - - // Prepend the UTF sequence with our decomposed sequence - if (isset($decomp_seq[1])) - { - // The char expanded into several chars - $decomp_cnt = sizeof($decomp_seq); - - foreach ($decomp_seq as $decomp_i => $decomp_char) - { - $utf_seq[$k + $decomp_i - $decomp_cnt] = $decomp_char; - } - $k -= $decomp_cnt; - } - else - { - // Decomposed to a single char, easier to prepend - $utf_seq[--$k] = $decomp_seq[0]; - } - } - else - { - $utf_seq[--$k] = $utf_char; - } - - if (!isset($utf_combining_class[$utf_seq[$k]])) - { - // We have found our starter - $starter_found = 1; - break; - } - } - - if (!$starter_found && $lpos > $tmp_pos) - { - // The starter was not found in the buffer, let's rewind some more - do - { - // $utf_len_mask contains the masks of both leading bytes and trailing bytes. If $utf_en > 0 then it's a leading byte, otherwise it's a trailing byte. - $c = $str[--$lpos]; - $c_mask = $c & "\xF0"; - - if (isset($utf_len_mask[$c_mask])) - { - // UTF byte - if ($utf_len = $utf_len_mask[$c_mask]) - { - // UTF *leading* byte - $utf_char = substr($str, $lpos, $utf_len); - - if (isset($decomp_map[$utf_char])) - { - // Decompose the character - $decomp_seq = array(); - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $decomp_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $decomp_seq[] = $c; - ++$_pos; - } - } - while ($_pos < $_len); - - // Prepend the UTF sequence with our decomposed sequence - if (isset($decomp_seq[1])) - { - // The char expanded into several chars - $decomp_cnt = sizeof($decomp_seq); - foreach ($decomp_seq as $decomp_i => $utf_char) - { - $utf_seq[$k + $decomp_i - $decomp_cnt] = $utf_char; - } - $k -= $decomp_cnt; - } - else - { - // Decomposed to a single char, easier to prepend - $utf_seq[--$k] = $decomp_seq[0]; - } - } - else - { - $utf_seq[--$k] = $utf_char; - } - } - } - else - { - // ASCII char - $utf_seq[--$k] = $c; - } - } - while ($lpos > $tmp_pos); - } - } - - // STEP 3: Capture following combining modifiers - - while ($pos < $len) - { - $c_mask = $str[$pos] & "\xF0"; - - if (isset($utf_len_mask[$c_mask])) - { - if ($utf_len = $utf_len_mask[$c_mask]) - { - $utf_char = substr($str, $pos, $utf_len); - } - else - { - // A trailing byte came out of nowhere - // Trailing bytes are replaced with Unicode replacement chars, we will just ignore it for now, break out of the loop - // as if it was a starter (replacement chars ARE starters) and let the next loop replace it - break; - } - - if (isset($utf_combining_class[$utf_char]) || isset($qc[$utf_char])) - { - // Combining character, add it to the sequence and move the cursor - if (isset($decomp_map[$utf_char])) - { - // Decompose the character - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $utf_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $utf_seq[] = $c; - ++$_pos; - } - } - while ($_pos < $_len); - } - else - { - $utf_seq[] = $utf_char; - } - - $pos += $utf_len; - } - else - { - // Combining class 0 and no QC, break out of the loop - // Note: we do not know if that character is valid. If it's not, the next iteration will replace it - break; - } - } - else - { - // ASCII chars are starters - break; - } - } - - // STEP 4: Sort and combine - - // Here we sort... - $k_max = $k + sizeof($utf_seq); - - if (!$k && $k_max == 1) - { - // There is only one char in the UTF sequence, add it then jump to the next iteration of main loop - // Note: the two commented lines below can be enabled under PHP5 for a very small performance gain in most cases -// if (substr_compare($str, $utf_seq[0], $lpos, $pos - $lpos)) -// { - $tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $utf_seq[0]; - $tmp_pos = $pos; -// } - - continue; - } - - // ...there we combine - if (isset($utf_combining_class[$utf_seq[$k]])) - { - $starter = $nf_seq = ''; - } - else - { - $starter = $utf_seq[$k++]; - $nf_seq = ''; - } - $utf_sort = array(); - - // We add an empty char at the end of the UTF char sequence. It will act as a starter and trigger the sort/combine routine - // at the end of the string without altering it - $utf_seq[] = ''; - - do - { - $utf_char = $utf_seq[$k++]; - - if (isset($utf_combining_class[$utf_char])) - { - $utf_sort[$utf_combining_class[$utf_char]][] = $utf_char; - } - else - { - if (empty($utf_sort)) - { - // No combining characters... check for a composite of the two starters - if (isset($utf_canonical_comp[$starter . $utf_char])) - { - // Good ol' composite character - $starter = $utf_canonical_comp[$starter . $utf_char]; - } - else if (isset($utf_jamo_type[$utf_char])) - { - // Current char is a composable jamo - if (isset($utf_jamo_type[$starter]) && $utf_jamo_type[$starter] == UNICODE_JAMO_L && $utf_jamo_type[$utf_char] == UNICODE_JAMO_V) - { - // We have a L jamo followed by a V jamo, we are going to prefetch the next char to see if it's a T jamo - if (isset($utf_jamo_type[$utf_seq[$k]]) && $utf_jamo_type[$utf_seq[$k]] == UNICODE_JAMO_T) - { - // L+V+T jamos, combine to a LVT Hangul syllable ($k is incremented) - $cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char] + $utf_jamo_index[$utf_seq[$k]]; - ++$k; - } - else - { - // L+V jamos, combine to a LV Hangul syllable - $cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char]; - } - - $starter = chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); - } - else - { - // Non-composable jamo, just add it to the sequence - $nf_seq .= $starter; - $starter = $utf_char; - } - } - else - { - // No composite, just add the first starter to the sequence then continue with the other one - $nf_seq .= $starter; - $starter = $utf_char; - } - } - else - { - ksort($utf_sort); - - // For each class of combining characters - foreach ($utf_sort as $cc => $utf_chars) - { - $j = 0; - - do - { - // Look for a composite - if (isset($utf_canonical_comp[$starter . $utf_chars[$j]])) - { - // Found a composite, replace the starter - $starter = $utf_canonical_comp[$starter . $utf_chars[$j]]; - unset($utf_sort[$cc][$j]); - } - else - { - // No composite, all following characters in that class are blocked - break; - } - } - while (isset($utf_sort[$cc][++$j])); - } - - // Add the starter to the normalized sequence, followed by non-starters in canonical order - $nf_seq .= $starter; - - foreach ($utf_sort as $utf_chars) - { - if (!empty($utf_chars)) - { - $nf_seq .= implode('', $utf_chars); - } - } - - // Reset the array and go on - $utf_sort = array(); - $starter = $utf_char; - } - } - } - while ($k <= $k_max); - - $tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $nf_seq; - $tmp_pos = $pos; - } - else - { - // Only a ASCII char can make the program get here - // - // First we skip the current byte with ++$pos, then we quickly skip following ASCII chars with strspn(). - // - // The first two "if"'s here can be removed, with the consequences of being faster on latin text (lots of ASCII) and slower on - // multi-byte text (where the only ASCII chars are spaces and punctuation) - if (++$pos != $len) - { - if ($str[$pos] < "\x80") - { - $pos += strspn($str, UTF8_ASCII_RANGE, ++$pos); - $buffer[++$i & 7] = $str[$pos - 1]; - } - else - { - $buffer[++$i & 7] = $c; - } - } - } - } - while ($pos < $len); - - // Now is time to return the string - if ($tmp_pos) - { - // If the $tmp_pos cursor is not at the beggining of the string then at least one character was not in normal form. Replace $str with the fixed version - if ($tmp_pos == $len) - { - // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str - return $tmp; - } - else - { - // The rightmost chunk of $str has not been appended to $tmp yet - return $tmp . substr($str, $tmp_pos); - } - } - - // The string was already in normal form - return $str; - } - - /** - * Decompose a UTF string - * - * @param string $str UTF string - * @param integer $pos Position of the first UTF char (in bytes) - * @param integer $len Length of the string (in bytes) - * @param array &$decomp_map Decomposition mapping, passed by reference but never modified - * @return string The string, decomposed and sorted canonically - * - * @access private - */ - static function decompose($str, $pos, $len, &$decomp_map) - { - global $utf_combining_class; - - // Load some commonly-used tables - if (!isset($utf_combining_class)) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.' . $phpEx); - } - - // UTF char length array - $utf_len_mask = array( - // Leading bytes masks - "\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4, - // Trailing bytes masks - "\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0 - ); - - // Some extra checks are triggered on the first byte of a UTF sequence - $extra_check = array( - "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1, - "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1, - "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1 - ); - - // These masks are used to check if a UTF sequence is well formed. Here are the only 3 lengths we acknowledge: - // - 2-byte: 110? ???? 10?? ???? - // - 3-byte: 1110 ???? 10?? ???? 10?? ???? - // - 4-byte: 1111 0??? 10?? ???? 10?? ???? 10?? ???? - // Note that 5- and 6- byte sequences are automatically discarded - $utf_validation_mask = array( - 2 => "\xE0\xC0", - 3 => "\xF0\xC0\xC0", - 4 => "\xF8\xC0\xC0\xC0" - ); - - $utf_validation_check = array( - 2 => "\xC0\x80", - 3 => "\xE0\x80\x80", - 4 => "\xF0\x80\x80\x80" - ); - - $tmp = ''; - $starter_pos = $pos; - $tmp_pos = $last_cc = $sort = $dump = 0; - $utf_sort = array(); - - // Main loop - do - { - // STEP 0: Capture the current char - - $cur_mask = $str[$pos] & "\xF0"; - if (isset($utf_len_mask[$cur_mask])) - { - if ($utf_len = $utf_len_mask[$cur_mask]) - { - // Multibyte char - $utf_char = substr($str, $pos, $utf_len); - $pos += $utf_len; - } - else - { - // A trailing byte came out of nowhere, we will treat it and all following trailing bytes as if each of them was a Unicode - // replacement char and we will advance the cursor - $spn = strspn($str, UTF8_TRAILING_BYTES, $pos); - - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= str_repeat(UTF8_REPLACEMENT, $spn); - $dump = $sort = 0; - } - else - { - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(UTF8_REPLACEMENT, $spn); - } - - $pos += $spn; - $tmp_pos = $starter_pos = $pos; - - $utf_sort = array(); - $last_cc = 0; - - continue; - } - - // STEP 1: Decide what to do with current char - - // Now, in that order: - // - check if that character is decomposable - // - check if that character is a non-starter - // - check if that character requires extra checks to be performed - if (isset($decomp_map[$utf_char])) - { - // Decompose the char - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $_utf_char = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - - if (isset($utf_combining_class[$_utf_char])) - { - // The character decomposed to a non-starter, buffer it for sorting - $utf_sort[$utf_combining_class[$_utf_char]][] = $_utf_char; - - if ($utf_combining_class[$_utf_char] < $last_cc) - { - // Not canonically ordered, will require sorting - $sort = $dump = 1; - } - else - { - $dump = 1; - $last_cc = $utf_combining_class[$_utf_char]; - } - } - else - { - // This character decomposition contains a starter, dump the buffer and continue - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $_utf_char; - $dump = $sort = 0; - } - else - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos) . $_utf_char; - } - - $tmp_pos = $starter_pos = $pos; - $utf_sort = array(); - $last_cc = 0; - } - } - else - { - // This character decomposition contains an ASCII char, which is a starter. Dump the buffer and continue - ++$_pos; - - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $c; - $dump = $sort = 0; - } - else - { - $tmp .= substr($str, $tmp_pos, $pos - $utf_len - $tmp_pos) . $c; - } - - $tmp_pos = $starter_pos = $pos; - $utf_sort = array(); - $last_cc = 0; - } - } - while ($_pos < $_len); - } - else if (isset($utf_combining_class[$utf_char])) - { - // Combining character - if ($utf_combining_class[$utf_char] < $last_cc) - { - // Not in canonical order - $sort = $dump = 1; - } - else - { - $last_cc = $utf_combining_class[$utf_char]; - } - - $utf_sort[$utf_combining_class[$utf_char]][] = $utf_char; - } - else - { - // Non-decomposable starter, check out if it's a Hangul syllable - if ($utf_char < UTF8_HANGUL_FIRST || $utf_char > UTF8_HANGUL_LAST) - { - // Nope, regular UTF char, check that we have the correct number of trailing bytes - if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len]) - { - // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char - // has been encoded in a five- or six- byte sequence. - // Move the cursor back to its original position then advance it to the position it should really be at - $pos -= $utf_len; - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - // Add a replacement char then another replacement char for every trailing byte. - // - // @todo I'm not entirely sure that's how we're supposed to mark invalidated byte sequences, check this - $spn = strspn($str, UTF8_TRAILING_BYTES, ++$pos); - $tmp .= str_repeat(UTF8_REPLACEMENT, $spn + 1); - - $dump = $sort = 0; - - $pos += $spn; - $tmp_pos = $pos; - continue; - } - - if (isset($extra_check[$utf_char[0]])) - { - switch ($utf_char[0]) - { - // Note: 0xED is quite common in Korean - case "\xED": - if ($utf_char >= "\xED\xA0\x80") - { - // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF) - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - // Note: 0xEF is quite common in Japanese - case "\xEF": - if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF") - { - // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF) - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - case "\xC0": - case "\xC1": - if ($utf_char <= "\xC1\xBF") - { - // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - case "\xE0": - if ($utf_char <= "\xE0\x9F\xBF") - { - // Unicode char U+0000..U+07FF encoded in 3 bytes - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - case "\xF0": - if ($utf_char <= "\xF0\x8F\xBF\xBF") - { - // Unicode char U+0000..U+FFFF encoded in 4 bytes - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - default: - if ($utf_char > UTF8_MAX) - { - // Out of the Unicode range - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - } - } - } - else - { - // Hangul syllable - $idx = (((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F)) - UNICODE_HANGUL_SBASE; - - // LIndex can only range from 0 to 18, therefore it cannot influence the first two bytes of the L Jamo, which allows us to hardcode them (based on LBase). - // - // The same goes for VIndex, but for TIndex there's a catch: the value of the third byte could exceed 0xBF and we would have to increment the second byte - if ($t_index = $idx % UNICODE_HANGUL_TCOUNT) - { - if ($t_index < 25) - { - $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x86\x00"; - $utf_char[8] = chr(0xA7 + $t_index); - } - else - { - $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x87\x00"; - $utf_char[8] = chr(0x67 + $t_index); - } - } - else - { - $utf_char = "\xE1\x84\x00\xE1\x85\x00"; - } - - $utf_char[2] = chr(0x80 + (int) ($idx / UNICODE_HANGUL_NCOUNT)); - $utf_char[5] = chr(0xA1 + (int) (($idx % UNICODE_HANGUL_NCOUNT) / UNICODE_HANGUL_TCOUNT)); - - // Just like other decompositions, the resulting Jamos must be dumped to the tmp string - $dump = 1; - } - - // Do we need to dump stuff to the tmp string? - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $utf_char; - $dump = $sort = 0; - $tmp_pos = $pos; - } - - $last_cc = 0; - $utf_sort = array(); - $starter_pos = $pos; - } - } - else - { - // ASCII char, which happens to be a starter (as any other ASCII char) - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $str[$pos]; - $dump = $sort = 0; - $tmp_pos = ++$pos; - - $pos += strspn($str, UTF8_ASCII_RANGE, $pos); - } - else - { - $pos += strspn($str, UTF8_ASCII_RANGE, ++$pos); - } - - $last_cc = 0; - $utf_sort = array(); - $starter_pos = $pos; - } - } - while ($pos < $len); - - // Now is time to return the string - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - return $tmp; - } - else if ($tmp_pos) - { - // If the $tmp_pos cursor was moved then at least one character was not in normal form. Replace $str with the fixed version - if ($tmp_pos == $len) - { - // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str - return $tmp; - } - else - { - // The rightmost chunk of $str has not been appended to $tmp yet - return $tmp . substr($str, $tmp_pos); - } - } - - // The string was already in normal form - return $str; - } -} diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php index e60a40a195..19963287e5 100644 --- a/phpBB/includes/utf/utf_tools.php +++ b/phpBB/includes/utf/utf_tools.php @@ -867,7 +867,6 @@ function utf8_recode($string, $encoding) // Trigger an error?! Fow now just give bad data :-( trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR); - //return $string; // use utf_normalizer::cleanup() ? } /** @@ -1611,14 +1610,8 @@ function utf8_case_fold_nfkc($text, $option = 'full') // do the case fold $text = utf8_case_fold($text, $option); - if (!class_exists('utf_normalizer')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); - } - // convert to NFKC - utf_normalizer::nfkc($text); + Normalizer::normalize($text, Normalizer::NFKC); // FC_NFKC_Closure, http://www.unicode.org/Public/5.0.0/ucd/DerivedNormalizationProps.txt $text = strtr($text, $fc_nfkc_closure); @@ -1714,106 +1707,56 @@ function utf8_case_fold_nfc($text, $option = 'full') return $text; } -if (extension_loaded('intl')) +/** +* wrapper around PHP's native normalizer from intl +* previously a PECL extension, included in the core since PHP 5.3.0 +* http://php.net/manual/en/normalizer.normalize.php +* +* @param mixed $strings a string or an array of strings to normalize +* @return mixed the normalized content, preserving array keys if array given. +*/ +function utf8_normalize_nfc($strings) { - /** - * wrapper around PHP's native normalizer from intl - * previously a PECL extension, included in the core since PHP 5.3.0 - * http://php.net/manual/en/normalizer.normalize.php - * - * @param mixed $strings a string or an array of strings to normalize - * @return mixed the normalized content, preserving array keys if array given. - */ - function utf8_normalize_nfc($strings) + if (empty($strings)) { - if (empty($strings)) + return $strings; + } + + if (!is_array($strings)) + { + if (Normalizer::isNormalized($strings)) { return $strings; } - - if (!is_array($strings)) + return (string) Normalizer::normalize($strings); + } + else + { + foreach ($strings as $key => $string) { - if (Normalizer::isNormalized($strings)) + if (is_array($string)) { - return $strings; - } - return (string) Normalizer::normalize($strings); - } - else - { - foreach ($strings as $key => $string) - { - if (is_array($string)) + foreach ($string as $_key => $_string) { - foreach ($string as $_key => $_string) - { - if (Normalizer::isNormalized($strings[$key][$_key])) - { - continue; - } - $strings[$key][$_key] = (string) Normalizer::normalize($strings[$key][$_key]); - } - } - else - { - if (Normalizer::isNormalized($strings[$key])) + if (Normalizer::isNormalized($strings[$key][$_key])) { continue; } - $strings[$key] = (string) Normalizer::normalize($strings[$key]); + $strings[$key][$_key] = (string) Normalizer::normalize($strings[$key][$_key]); } } - } - - return $strings; - } -} -else -{ - /** - * A wrapper function for the normalizer which takes care of including the class if - * required and modifies the passed strings to be in NFC (Normalization Form Composition). - * - * @param mixed $strings a string or an array of strings to normalize - * @return mixed the normalized content, preserving array keys if array given. - */ - function utf8_normalize_nfc($strings) - { - if (empty($strings)) - { - return $strings; - } - - if (!class_exists('utf_normalizer')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); - } - - if (!is_array($strings)) - { - utf_normalizer::nfc($strings); - } - else if (is_array($strings)) - { - foreach ($strings as $key => $string) + else { - if (is_array($string)) + if (Normalizer::isNormalized($strings[$key])) { - foreach ($string as $_key => $_string) - { - utf_normalizer::nfc($strings[$key][$_key]); - } - } - else - { - utf_normalizer::nfc($strings[$key]); + continue; } + $strings[$key] = (string) Normalizer::normalize($strings[$key]); } } - - return $strings; } + + return $strings; } /** diff --git a/phpBB/install/data/confusables.php b/phpBB/install/data/confusables.php index e3e8c41e62..992207c1ef 100644 --- a/phpBB/install/data/confusables.php +++ b/phpBB/install/data/confusables.php @@ -633,14 +633,8 @@ function utf8_new_case_fold_nfkc($text, $option = 'full') // do the case fold $text = utf8_new_case_fold($text, $option); - if (!class_exists('utf_normalizer')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); - } - // convert to NFKC - utf_new_normalizer::nfkc($text); + $text = Normalizer::normalize($text, Normalizer::NFKC); // FC_NFKC_Closure, http://www.unicode.org/Public/5.0.0/ucd/DerivedNormalizationProps.txt $text = strtr($text, $fc_nfkc_closure); diff --git a/phpBB/install/data/new_normalizer.php b/phpBB/install/data/new_normalizer.php deleted file mode 100644 index 52652a4f6d..0000000000 --- a/phpBB/install/data/new_normalizer.php +++ /dev/null @@ -1,197 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* A wrapper function for the normalizer which takes care of including the class if required and modifies the passed strings -* to be in NFC (Normalization Form Composition). -* -* @param mixed $strings a string or an array of strings to normalize -* @return mixed the normalized content, preserving array keys if array given. -*/ -function utf8_new_normalize_nfc($strings) -{ - if (empty($strings)) - { - return $strings; - } - - if (!is_array($strings)) - { - utf_new_normalizer::nfc($strings); - } - else if (is_array($strings)) - { - foreach ($strings as $key => $string) - { - if (is_array($string)) - { - foreach ($string as $_key => $_string) - { - utf_new_normalizer::nfc($strings[$key][$_key]); - } - } - else - { - utf_new_normalizer::nfc($strings[$key]); - } - } - } - - return $strings; -} - -class utf_new_normalizer -{ - /** - * Validate, cleanup and normalize a string - * - * The ultimate convenience function! Clean up invalid UTF-8 sequences, - * and convert to Normal Form C, canonical composition. - * - * @param string &$str The dirty string - * @return string The same string, all shiny and cleaned-up - */ - function cleanup(&$str) - { - // The string below is the list of all autorized characters, sorted by frequency in latin text - $pos = strspn($str, "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x0D"); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings with no special chars return immediately - return; - } - - // Note: we do not check for $GLOBALS['utf_canonical_decomp']. It is assumed they are always loaded together - if (!isset($GLOBALS['utf_nfc_qc'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx); - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); - } - - // Replace any byte in the range 0x00..0x1F, except for \r, \n and \t - // We replace those characters with a 0xFF byte, which is illegal in UTF-8 and will in turn be replaced with a UTF replacement char - $str = strtr( - $str, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", - "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" - ); - - $str = utf_new_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFC - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - function nfc(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_nfc_qc'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx); - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); - } - - $str = utf_new_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFKC - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - function nfkc(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_nfkc_qc'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_nfkc_qc.' . $phpEx); - } - - if (!isset($GLOBALS['utf_compatibility_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx); - } - - $str = utf_new_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']); - } - - /** - * Recompose a UTF string - * - * @param string $str Unchecked UTF string - * @param integer $pos Position of the first UTF char (in bytes) - * @param integer $len Length of the string (in bytes) - * @param array &$qc Quick-check array, passed by reference but never modified - * @param array &$decomp_map Decomposition mapping, passed by reference but never modified - * @return string The string, validated and recomposed - * - * @access private - */ - function recompose($str, $pos, $len, &$qc, &$decomp_map) - { - global $utf_canonical_comp; - - // Load the canonical composition table - if (!isset($utf_canonical_comp)) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_comp.' . $phpEx); - } - - return utf_normalizer::recompose($str, $pos, $len, $qc, $decomp_map); - } -} diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 80fd40a944..0dc86c2051 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -74,7 +74,6 @@ require($phpbb_root_path . 'includes/functions.' . $phpEx); require($phpbb_root_path . 'includes/functions_content.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); -include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); // Set PHP error handler to ours diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 51bfb1c913..3dd73adc60 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -102,7 +102,6 @@ phpbb_require_updated('includes/functions.' . $phpEx); phpbb_require_updated('includes/functions_content.' . $phpEx, true); phpbb_include_updated('includes/functions_admin.' . $phpEx); -phpbb_include_updated('includes/utf/utf_normalizer.' . $phpEx); phpbb_include_updated('includes/utf/utf_tools.' . $phpEx); phpbb_require_updated('includes/functions_install.' . $phpEx); diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index 34947b176d..ea239c0b36 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -18,6 +18,13 @@ namespace phpbb\search; */ class fulltext_native extends \phpbb\search\base { + const UTF8_HANGUL_FIRST = "\xEA\xB0\x80"; + const UTF8_HANGUL_LAST = "\xED\x9E\xA3"; + const UTF8_CJK_FIRST = "\xE4\xB8\x80"; + const UTF8_CJK_LAST = "\xE9\xBE\xBB"; + const UTF8_CJK_B_FIRST = "\xF0\xA0\x80\x80"; + const UTF8_CJK_B_LAST = "\xF0\xAA\x9B\x96"; + /** * Associative array holding index stats * @var array @@ -93,7 +100,7 @@ class fulltext_native extends \phpbb\search\base protected $user; /** - * Initialises the fulltext_native search backend with min/max word length and makes sure the UTF-8 normalizer is loaded + * Initialises the fulltext_native search backend with min/max word length * * @param boolean|string &$error is passed by reference and should either be set to false on success or an error message on failure */ @@ -110,10 +117,6 @@ class fulltext_native extends \phpbb\search\base /** * Load the UTF tools */ - if (!class_exists('utf_normalizer')) - { - include($this->phpbb_root_path . 'includes/utf/utf_normalizer.' . $this->php_ext); - } if (!function_exists('utf8_decode_ncr')) { include($this->phpbb_root_path . 'includes/utf/utf_tools.' . $this->php_ext); @@ -1175,9 +1178,9 @@ class fulltext_native extends \phpbb\search\base * Note: this could be optimized. If the codepoint is lower than Hangul's range * we know that it will also be lower than CJK ranges */ - if ((strncmp($word, UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, UTF8_HANGUL_LAST, 3) > 0) - && (strncmp($word, UTF8_CJK_FIRST, 3) < 0 || strncmp($word, UTF8_CJK_LAST, 3) > 0) - && (strncmp($word, UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, UTF8_CJK_B_LAST, 4) > 0)) + if ((strncmp($word, self::UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, self::UTF8_HANGUL_LAST, 3) > 0) + && (strncmp($word, self::UTF8_CJK_FIRST, 3) < 0 || strncmp($word, self::UTF8_CJK_LAST, 3) > 0) + && (strncmp($word, self::UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, self::UTF8_CJK_B_LAST, 4) > 0)) { $word = strtok(' '); continue; @@ -1544,8 +1547,6 @@ class fulltext_native extends \phpbb\search\base * @param string $allowed_chars String of special chars to allow * @param string $encoding Text encoding * @return string Cleaned up text, only alphanumeric chars are left - * - * @todo \normalizer::cleanup being able to be used? */ protected function cleanup($text, $allowed_chars = null, $encoding = 'utf-8') { @@ -1572,12 +1573,9 @@ class fulltext_native extends \phpbb\search\base $text = htmlspecialchars_decode(utf8_decode_ncr($text), ENT_QUOTES); /** - * Load the UTF-8 normalizer - * - * If we use it more widely, an instance of that class should be held in a - * a global variable instead + * Normalize to NFC */ - \utf_normalizer::nfc($text); + $text = \Normalizer::normalize($text); /** * The first thing we do is: @@ -1670,9 +1668,9 @@ class fulltext_native extends \phpbb\search\base $utf_char = substr($text, $pos, $utf_len); $pos += $utf_len; - if (($utf_char >= UTF8_HANGUL_FIRST && $utf_char <= UTF8_HANGUL_LAST) - || ($utf_char >= UTF8_CJK_FIRST && $utf_char <= UTF8_CJK_LAST) - || ($utf_char >= UTF8_CJK_B_FIRST && $utf_char <= UTF8_CJK_B_LAST)) + if (($utf_char >= self::UTF8_HANGUL_FIRST && $utf_char <= self::UTF8_HANGUL_LAST) + || ($utf_char >= self::UTF8_CJK_FIRST && $utf_char <= self::UTF8_CJK_LAST) + || ($utf_char >= self::UTF8_CJK_B_FIRST && $utf_char <= self::UTF8_CJK_B_LAST)) { /** * All characters within these ranges are valid diff --git a/tests/RUNNING_TESTS.md b/tests/RUNNING_TESTS.md index afd7caa709..b082197166 100644 --- a/tests/RUNNING_TESTS.md +++ b/tests/RUNNING_TESTS.md @@ -120,8 +120,9 @@ directory (above phpBB): Slow tests -------------- -Certain tests, such as the UTF-8 normalizer or the DNS tests tend to be slow. -Thus these tests are in the `slow` group, which is excluded by default. If you +Certain tests, such as the DNS tests tend to be slow. +Thus these tests are in the `slow` group, which is excluded by default. You can +enable slow tests by copying the phpunit.xml.all file to phpunit.xml. If you only want the slow tests, run: $ phpBB/vendor/bin/phpunit --group slow diff --git a/tests/utf/normalizer_test.php b/tests/utf/normalizer_test.php deleted file mode 100644 index 50eafda859..0000000000 --- a/tests/utf/normalizer_test.php +++ /dev/null @@ -1,327 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_normalizer.php'; - -/** -* @group slow -*/ -class phpbb_utf_normalizer_test extends phpbb_test_case -{ - static private $data_dir; - - static public function setUpBeforeClass() - { - self::$data_dir = dirname(__file__) . '/../tmp'; - self::download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt', self::$data_dir); - self::download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt', self::$data_dir); - } - - public function test_normalizer() - { - $test_suite = array( - /** - * NFC - * c2 == NFC(c1) == NFC(c2) == NFC(c3) - * c4 == NFC(c4) == NFC(c5) - */ - 'NFC' => array( - 'c2' => array('c1', 'c2', 'c3'), - 'c4' => array('c4', 'c5') - ), - - /** - * NFD - * c3 == NFD(c1) == NFD(c2) == NFD(c3) - * c5 == NFD(c4) == NFD(c5) - */ - 'NFD' => array( - 'c3' => array('c1', 'c2', 'c3'), - 'c5' => array('c4', 'c5') - ), - - /** - * NFKC - * c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5) - */ - 'NFKC' => array( - 'c4' => array('c1', 'c2', 'c3', 'c4', 'c5') - ), - - /** - * NFKD - * c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5) - */ - 'NFKD' => array( - 'c5' => array('c1', 'c2', 'c3', 'c4', 'c5') - ) - ); - - $tested_chars = array(); - - $fp = fopen(self::$data_dir . '/NormalizationTest.txt', 'rb'); - while (!feof($fp)) - { - $line = fgets($fp); - - if ($line[0] == '@') - { - continue; - } - - if (!strpos(' 0123456789ABCDEF', $line[0])) - { - continue; - } - - list($c1, $c2, $c3, $c4, $c5) = explode(';', $line); - - if (!strpos($c1, ' ')) - { - /** - * We are currently testing a single character, we add it to the list of - * characters we have processed so that we can exclude it when testing - * for invariants - */ - $tested_chars[$c1] = 1; - } - - foreach ($test_suite as $form => $serie) - { - foreach ($serie as $expected => $tests) - { - $hex_expected = ${$expected}; - $utf_expected = $this->hexseq_to_utf($hex_expected); - - foreach ($tests as $test) - { - $utf_result = $utf_expected; - call_user_func_array(array('utf_normalizer', $form), array(&$utf_result)); - - $hex_result = $this->utf_to_hexseq($utf_result); - $this->assertEquals($utf_expected, $utf_result, "$expected == $form($test) ($hex_expected != $hex_result)"); - } - } - } - } - fclose($fp); - - return $tested_chars; - } - - /** - * @depends test_normalizer - */ - public function test_invariants(array $tested_chars) - { - $fp = fopen(self::$data_dir . '/UnicodeData.txt', 'rb'); - - while (!feof($fp)) - { - $line = fgets($fp, 1024); - - if (!$pos = strpos($line, ';')) - { - continue; - } - - $hex_tested = $hex_expected = substr($line, 0, $pos); - - if (isset($tested_chars[$hex_tested])) - { - continue; - } - - $utf_expected = $this->hex_to_utf($hex_expected); - - if ($utf_expected >= UTF8_SURROGATE_FIRST - && $utf_expected <= UTF8_SURROGATE_LAST) - { - /** - * Surrogates are illegal on their own, we expect the normalizer - * to return a replacement char - */ - $utf_expected = UTF8_REPLACEMENT; - $hex_expected = $this->utf_to_hexseq($utf_expected); - } - - foreach (array('nfc', 'nfkc', 'nfd', 'nfkd') as $form) - { - $utf_result = $utf_expected; - call_user_func_array(array('utf_normalizer', $form), array(&$utf_result)); - $hex_result = $this->utf_to_hexseq($utf_result); - - $this->assertEquals($utf_expected, $utf_result, "$hex_expected == $form($hex_tested) ($hex_expected != $hex_result)"); - } - } - fclose($fp); - } - - /** - * Convert a UTF string to a sequence of codepoints in hexadecimal - * - * @param string $utf UTF string - * @return integer Unicode codepoints in hex - */ - protected function utf_to_hexseq($str) - { - $pos = 0; - $len = strlen($str); - $ret = array(); - - while ($pos < $len) - { - $c = $str[$pos]; - switch ($c & "\xF0") - { - case "\xC0": - case "\xD0": - $utf_char = substr($str, $pos, 2); - $pos += 2; - break; - - case "\xE0": - $utf_char = substr($str, $pos, 3); - $pos += 3; - break; - - case "\xF0": - $utf_char = substr($str, $pos, 4); - $pos += 4; - break; - - default: - $utf_char = $c; - ++$pos; - } - - $hex = dechex($this->utf_to_cp($utf_char)); - - if (!isset($hex[3])) - { - $hex = substr('000' . $hex, -4); - } - - $ret[] = $hex; - } - - return strtr(implode(' ', $ret), 'abcdef', 'ABCDEF'); - } - - /** - * Convert a UTF-8 char to its codepoint - * - * @param string $utf_char UTF-8 char - * @return integer Unicode codepoint - */ - protected function utf_to_cp($utf_char) - { - switch (strlen($utf_char)) - { - case 1: - return ord($utf_char); - - case 2: - return ((ord($utf_char[0]) & 0x1F) << 6) | (ord($utf_char[1]) & 0x3F); - - case 3: - return ((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F); - - case 4: - return ((ord($utf_char[0]) & 0x07) << 18) | ((ord($utf_char[1]) & 0x3F) << 12) | ((ord($utf_char[2]) & 0x3F) << 6) | (ord($utf_char[3]) & 0x3F); - - default: - throw new RuntimeException('UTF-8 chars can only be 1-4 bytes long'); - } - } - - /** - * Return a UTF string formed from a sequence of codepoints in hexadecimal - * - * @param string $seq Sequence of codepoints, separated with a space - * @return string UTF-8 string - */ - protected function hexseq_to_utf($seq) - { - return implode('', array_map(array($this, 'hex_to_utf'), explode(' ', $seq))); - } - - /** - * Convert a codepoint in hexadecimal to a UTF-8 char - * - * @param string $hex Codepoint, in hexadecimal - * @return string UTF-8 char - */ - protected function hex_to_utf($hex) - { - return $this->cp_to_utf(hexdec($hex)); - } - - /** - * Convert a codepoint to a UTF-8 char - * - * @param integer $cp Unicode codepoint - * @return string UTF-8 string - */ - protected function cp_to_utf($cp) - { - if ($cp > 0xFFFF) - { - return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); - } - else if ($cp > 0x7FF) - { - return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); - } - else if ($cp > 0x7F) - { - return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F)); - } - else - { - return chr($cp); - } - } - - // chunked download helper - static protected function download($url, $to) - { - $target = $to . '/' . basename($url); - - if (file_exists($target)) - { - return; - } - - if (!$fpr = fopen($url, 'rb')) - { - echo "Failed to download $url\n"; - return; - } - - if (!$fpw = fopen($target, 'wb')) - { - echo "Failed to open $target for writing\n"; - return; - } - - $chunk = 32768; - - while (!feof($fpr)) - { - fwrite($fpw, fread($fpr, $chunk)); - } - fclose($fpr); - fclose($fpw); - } -} From a2300eb3aa428a080314caf0c0b60556f6701ffa Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 20 Nov 2013 14:04:06 +0100 Subject: [PATCH 0025/1676] [feature/patchwork-utf8] Remove utf8_str_replace --- phpBB/includes/utf/utf_tools.php | 47 -------------------------------- phpBB/phpbb/db/driver/driver.php | 8 +++--- 2 files changed, 4 insertions(+), 51 deletions(-) diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php index 19963287e5..2fbc1ce520 100644 --- a/phpBB/includes/utf/utf_tools.php +++ b/phpBB/includes/utf/utf_tools.php @@ -1902,50 +1902,3 @@ function utf8_basename($filename) return $filename; } - -/** -* UTF8-safe str_replace() function -* -* @param string $search The value to search for -* @param string $replace The replacement string -* @param string $subject The target string -* @return string The resultant string -*/ -function utf8_str_replace($search, $replace, $subject) -{ - if (!is_array($search)) - { - $search = array($search); - if (is_array($replace)) - { - $replace = (string) $replace; - trigger_error('Array to string conversion', E_USER_NOTICE); - } - } - - $length = sizeof($search); - - if (!is_array($replace)) - { - $replace = array_fill(0, $length, $replace); - } - else - { - $replace = array_pad($replace, $length, ''); - } - - for ($i = 0; $i < $length; $i++) - { - $search_length = utf8_strlen($search[$i]); - $replace_length = utf8_strlen($replace[$i]); - - $offset = 0; - while (($start = utf8_strpos($subject, $search[$i], $offset)) !== false) - { - $subject = utf8_substr($subject, 0, $start) . $replace[$i] . utf8_substr($subject, $start + $search_length); - $offset = $start + $replace_length; - } - } - - return $subject; -} diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 4be315a154..8d360fc3e2 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -363,8 +363,8 @@ abstract class driver implements driver_interface */ function sql_like_expression($expression) { - $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression); - $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); + $expression = str_replace(array('_', '%'), array("\_", "\%"), $expression); + $expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\''); } @@ -374,8 +374,8 @@ abstract class driver implements driver_interface */ function sql_not_like_expression($expression) { - $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression); - $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); + $expression = str_replace(array('_', '%'), array("\_", "\%"), $expression); + $expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); return $this->_sql_not_like_expression('NOT LIKE \'' . $this->sql_escape($expression) . '\''); } From d1a879a56c71de0aa9c7bb7c102d36057c674aa1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 20 Nov 2013 14:14:26 +0100 Subject: [PATCH 0026/1676] [feature/patchwork-utf8] Rely on mbstring, use patchwork/utf8 as fallback --- phpBB/includes/utf/utf_tools.php | 584 ++++--------------------------- 1 file changed, 66 insertions(+), 518 deletions(-) diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php index 2fbc1ce520..da241b2cbd 100644 --- a/phpBB/includes/utf/utf_tools.php +++ b/phpBB/includes/utf/utf_tools.php @@ -21,6 +21,13 @@ if (!defined('IN_PHPBB')) // Enforce ASCII only string handling setlocale(LC_CTYPE, 'C'); +/** +* Setup the UTF-8 portability layer +*/ +Patchwork\Utf8\Bootup::initUtf8Encode(); +Patchwork\Utf8\Bootup::initMbstring(); +Patchwork\Utf8\Bootup::initIntl(); + /** * UTF-8 tools * @@ -29,544 +36,85 @@ setlocale(LC_CTYPE, 'C'); * */ -if (!extension_loaded('xml')) +/** +* UTF-8 aware alternative to strrpos +* @ignore +*/ +function utf8_strrpos($str, $needle, $offset = null) { - /** - * Implementation of PHP's native utf8_encode for people without XML support - * This function exploits some nice things that ISO-8859-1 and UTF-8 have in common - * - * @param string $str ISO-8859-1 encoded data - * @return string UTF-8 encoded data - */ - function utf8_encode($str) + // Emulate behaviour of strrpos rather than raising warning + if (empty($str)) { - $out = ''; - for ($i = 0, $len = strlen($str); $i < $len; $i++) - { - $letter = $str[$i]; - $num = ord($letter); - if ($num < 0x80) - { - $out .= $letter; - } - else if ($num < 0xC0) - { - $out .= "\xC2" . $letter; - } - else - { - $out .= "\xC3" . chr($num - 64); - } - } - return $out; + return false; } - /** - * Implementation of PHP's native utf8_decode for people without XML support - * - * @param string $str UTF-8 encoded data - * @return string ISO-8859-1 encoded data - */ - function utf8_decode($str) + if (is_null($offset)) { - $pos = 0; - $len = strlen($str); - $ret = ''; - - while ($pos < $len) - { - $ord = ord($str[$pos]) & 0xF0; - if ($ord === 0xC0 || $ord === 0xD0) - { - $charval = ((ord($str[$pos]) & 0x1F) << 6) | (ord($str[$pos + 1]) & 0x3F); - $pos += 2; - $ret .= (($charval < 256) ? chr($charval) : '?'); - } - else if ($ord === 0xE0) - { - $ret .= '?'; - $pos += 3; - } - else if ($ord === 0xF0) - { - $ret .= '?'; - $pos += 4; - } - else - { - $ret .= $str[$pos]; - ++$pos; - } - } - return $ret; + return mb_strrpos($str, $needle); + } + else + { + return mb_strrpos($str, $needle, $offset); } } -// mbstring is old and has it's functions around for older versions of PHP. -// if mbstring is not loaded, we go into native mode. -if (extension_loaded('mbstring')) +/** +* UTF-8 aware alternative to strpos +* @ignore +*/ +function utf8_strpos($str, $needle, $offset = null) { - mb_internal_encoding('UTF-8'); - - /** - * UTF-8 aware alternative to strrpos - * Find position of last occurrence of a char in a string - */ - /** - * UTF-8 aware alternative to strrpos - * @ignore - */ - function utf8_strrpos($str, $needle, $offset = null) + if (is_null($offset)) { - // Emulate behaviour of strrpos rather than raising warning - if (empty($str)) - { - return false; - } - - if (is_null($offset)) - { - return mb_strrpos($str, $needle); - } - else - { - return mb_strrpos($str, $needle, $offset); - } + return mb_strpos($str, $needle); } - - /** - * UTF-8 aware alternative to strpos - * @ignore - */ - function utf8_strpos($str, $needle, $offset = null) + else { - if (is_null($offset)) - { - return mb_strpos($str, $needle); - } - else - { - return mb_strpos($str, $needle, $offset); - } - } - - /** - * UTF-8 aware alternative to strtolower - * @ignore - */ - function utf8_strtolower($str) - { - return mb_strtolower($str); - } - - /** - * UTF-8 aware alternative to strtoupper - * @ignore - */ - function utf8_strtoupper($str) - { - return mb_strtoupper($str); - } - - /** - * UTF-8 aware alternative to substr - * @ignore - */ - function utf8_substr($str, $offset, $length = null) - { - if (is_null($length)) - { - return mb_substr($str, $offset); - } - else - { - return mb_substr($str, $offset, $length); - } - } - - /** - * Return the length (in characters) of a UTF-8 string - * @ignore - */ - function utf8_strlen($text) - { - return mb_strlen($text, 'utf-8'); + return mb_strpos($str, $needle, $offset); } } -else + +/** +* UTF-8 aware alternative to strtolower +* @ignore +*/ +function utf8_strtolower($str) { - /** - * UTF-8 aware alternative to strrpos - * Find position of last occurrence of a char in a string - * - * @author Harry Fuecks - * @param string $str haystack - * @param string $needle needle - * @param integer $offset (optional) offset (from left) - * @return mixed integer position or FALSE on failure - */ - function utf8_strrpos($str, $needle, $offset = null) + return mb_strtolower($str); +} + +/** +* UTF-8 aware alternative to strtoupper +* @ignore +*/ +function utf8_strtoupper($str) +{ + return mb_strtoupper($str); +} + +/** +* UTF-8 aware alternative to substr +* @ignore +*/ +function utf8_substr($str, $offset, $length = null) +{ + if (is_null($length)) { - if (is_null($offset)) - { - $ar = explode($needle, $str); - - if (sizeof($ar) > 1) - { - // Pop off the end of the string where the last match was made - array_pop($ar); - $str = join($needle, $ar); - - return utf8_strlen($str); - } - return false; - } - else - { - if (!is_int($offset)) - { - trigger_error('utf8_strrpos expects parameter 3 to be long', E_USER_ERROR); - return false; - } - - $str = utf8_substr($str, $offset); - - if (false !== ($pos = utf8_strrpos($str, $needle))) - { - return $pos + $offset; - } - - return false; - } + return mb_substr($str, $offset); } - - /** - * UTF-8 aware alternative to strpos - * Find position of first occurrence of a string - * - * @author Harry Fuecks - * @param string $str haystack - * @param string $needle needle - * @param integer $offset offset in characters (from left) - * @return mixed integer position or FALSE on failure - */ - function utf8_strpos($str, $needle, $offset = null) + else { - if (is_null($offset)) - { - $ar = explode($needle, $str); - if (sizeof($ar) > 1) - { - return utf8_strlen($ar[0]); - } - return false; - } - else - { - if (!is_int($offset)) - { - trigger_error('utf8_strpos: Offset must be an integer', E_USER_ERROR); - return false; - } - - $str = utf8_substr($str, $offset); - - if (false !== ($pos = utf8_strpos($str, $needle))) - { - return $pos + $offset; - } - - return false; - } + return mb_substr($str, $offset, $length); } +} - /** - * UTF-8 aware alternative to strtolower - * Make a string lowercase - * Note: The concept of a characters "case" only exists is some alphabets - * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does - * not exist in the Chinese alphabet, for example. See Unicode Standard - * Annex #21: Case Mappings - * - * @param string - * @return string string in lowercase - */ - function utf8_strtolower($string) - { - static $utf8_upper_to_lower = array( - "\xC3\x80" => "\xC3\xA0", "\xC3\x81" => "\xC3\xA1", - "\xC3\x82" => "\xC3\xA2", "\xC3\x83" => "\xC3\xA3", "\xC3\x84" => "\xC3\xA4", "\xC3\x85" => "\xC3\xA5", - "\xC3\x86" => "\xC3\xA6", "\xC3\x87" => "\xC3\xA7", "\xC3\x88" => "\xC3\xA8", "\xC3\x89" => "\xC3\xA9", - "\xC3\x8A" => "\xC3\xAA", "\xC3\x8B" => "\xC3\xAB", "\xC3\x8C" => "\xC3\xAC", "\xC3\x8D" => "\xC3\xAD", - "\xC3\x8E" => "\xC3\xAE", "\xC3\x8F" => "\xC3\xAF", "\xC3\x90" => "\xC3\xB0", "\xC3\x91" => "\xC3\xB1", - "\xC3\x92" => "\xC3\xB2", "\xC3\x93" => "\xC3\xB3", "\xC3\x94" => "\xC3\xB4", "\xC3\x95" => "\xC3\xB5", - "\xC3\x96" => "\xC3\xB6", "\xC3\x98" => "\xC3\xB8", "\xC3\x99" => "\xC3\xB9", "\xC3\x9A" => "\xC3\xBA", - "\xC3\x9B" => "\xC3\xBB", "\xC3\x9C" => "\xC3\xBC", "\xC3\x9D" => "\xC3\xBD", "\xC3\x9E" => "\xC3\xBE", - "\xC4\x80" => "\xC4\x81", "\xC4\x82" => "\xC4\x83", "\xC4\x84" => "\xC4\x85", "\xC4\x86" => "\xC4\x87", - "\xC4\x88" => "\xC4\x89", "\xC4\x8A" => "\xC4\x8B", "\xC4\x8C" => "\xC4\x8D", "\xC4\x8E" => "\xC4\x8F", - "\xC4\x90" => "\xC4\x91", "\xC4\x92" => "\xC4\x93", "\xC4\x96" => "\xC4\x97", "\xC4\x98" => "\xC4\x99", - "\xC4\x9A" => "\xC4\x9B", "\xC4\x9C" => "\xC4\x9D", "\xC4\x9E" => "\xC4\x9F", "\xC4\xA0" => "\xC4\xA1", - "\xC4\xA2" => "\xC4\xA3", "\xC4\xA4" => "\xC4\xA5", "\xC4\xA6" => "\xC4\xA7", "\xC4\xA8" => "\xC4\xA9", - "\xC4\xAA" => "\xC4\xAB", "\xC4\xAE" => "\xC4\xAF", "\xC4\xB4" => "\xC4\xB5", "\xC4\xB6" => "\xC4\xB7", - "\xC4\xB9" => "\xC4\xBA", "\xC4\xBB" => "\xC4\xBC", "\xC4\xBD" => "\xC4\xBE", "\xC5\x81" => "\xC5\x82", - "\xC5\x83" => "\xC5\x84", "\xC5\x85" => "\xC5\x86", "\xC5\x87" => "\xC5\x88", "\xC5\x8A" => "\xC5\x8B", - "\xC5\x8C" => "\xC5\x8D", "\xC5\x90" => "\xC5\x91", "\xC5\x94" => "\xC5\x95", "\xC5\x96" => "\xC5\x97", - "\xC5\x98" => "\xC5\x99", "\xC5\x9A" => "\xC5\x9B", "\xC5\x9C" => "\xC5\x9D", "\xC5\x9E" => "\xC5\x9F", - "\xC5\xA0" => "\xC5\xA1", "\xC5\xA2" => "\xC5\xA3", "\xC5\xA4" => "\xC5\xA5", "\xC5\xA6" => "\xC5\xA7", - "\xC5\xA8" => "\xC5\xA9", "\xC5\xAA" => "\xC5\xAB", "\xC5\xAC" => "\xC5\xAD", "\xC5\xAE" => "\xC5\xAF", - "\xC5\xB0" => "\xC5\xB1", "\xC5\xB2" => "\xC5\xB3", "\xC5\xB4" => "\xC5\xB5", "\xC5\xB6" => "\xC5\xB7", - "\xC5\xB8" => "\xC3\xBF", "\xC5\xB9" => "\xC5\xBA", "\xC5\xBB" => "\xC5\xBC", "\xC5\xBD" => "\xC5\xBE", - "\xC6\xA0" => "\xC6\xA1", "\xC6\xAF" => "\xC6\xB0", "\xC8\x98" => "\xC8\x99", "\xC8\x9A" => "\xC8\x9B", - "\xCE\x86" => "\xCE\xAC", "\xCE\x88" => "\xCE\xAD", "\xCE\x89" => "\xCE\xAE", "\xCE\x8A" => "\xCE\xAF", - "\xCE\x8C" => "\xCF\x8C", "\xCE\x8E" => "\xCF\x8D", "\xCE\x8F" => "\xCF\x8E", "\xCE\x91" => "\xCE\xB1", - "\xCE\x92" => "\xCE\xB2", "\xCE\x93" => "\xCE\xB3", "\xCE\x94" => "\xCE\xB4", "\xCE\x95" => "\xCE\xB5", - "\xCE\x96" => "\xCE\xB6", "\xCE\x97" => "\xCE\xB7", "\xCE\x98" => "\xCE\xB8", "\xCE\x99" => "\xCE\xB9", - "\xCE\x9A" => "\xCE\xBA", "\xCE\x9B" => "\xCE\xBB", "\xCE\x9C" => "\xCE\xBC", "\xCE\x9D" => "\xCE\xBD", - "\xCE\x9E" => "\xCE\xBE", "\xCE\x9F" => "\xCE\xBF", "\xCE\xA0" => "\xCF\x80", "\xCE\xA1" => "\xCF\x81", - "\xCE\xA3" => "\xCF\x83", "\xCE\xA4" => "\xCF\x84", "\xCE\xA5" => "\xCF\x85", "\xCE\xA6" => "\xCF\x86", - "\xCE\xA7" => "\xCF\x87", "\xCE\xA8" => "\xCF\x88", "\xCE\xA9" => "\xCF\x89", "\xCE\xAA" => "\xCF\x8A", - "\xCE\xAB" => "\xCF\x8B", "\xD0\x81" => "\xD1\x91", "\xD0\x82" => "\xD1\x92", "\xD0\x83" => "\xD1\x93", - "\xD0\x84" => "\xD1\x94", "\xD0\x85" => "\xD1\x95", "\xD0\x86" => "\xD1\x96", "\xD0\x87" => "\xD1\x97", - "\xD0\x88" => "\xD1\x98", "\xD0\x89" => "\xD1\x99", "\xD0\x8A" => "\xD1\x9A", "\xD0\x8B" => "\xD1\x9B", - "\xD0\x8C" => "\xD1\x9C", "\xD0\x8E" => "\xD1\x9E", "\xD0\x8F" => "\xD1\x9F", "\xD0\x90" => "\xD0\xB0", - "\xD0\x91" => "\xD0\xB1", "\xD0\x92" => "\xD0\xB2", "\xD0\x93" => "\xD0\xB3", "\xD0\x94" => "\xD0\xB4", - "\xD0\x95" => "\xD0\xB5", "\xD0\x96" => "\xD0\xB6", "\xD0\x97" => "\xD0\xB7", "\xD0\x98" => "\xD0\xB8", - "\xD0\x99" => "\xD0\xB9", "\xD0\x9A" => "\xD0\xBA", "\xD0\x9B" => "\xD0\xBB", "\xD0\x9C" => "\xD0\xBC", - "\xD0\x9D" => "\xD0\xBD", "\xD0\x9E" => "\xD0\xBE", "\xD0\x9F" => "\xD0\xBF", "\xD0\xA0" => "\xD1\x80", - "\xD0\xA1" => "\xD1\x81", "\xD0\xA2" => "\xD1\x82", "\xD0\xA3" => "\xD1\x83", "\xD0\xA4" => "\xD1\x84", - "\xD0\xA5" => "\xD1\x85", "\xD0\xA6" => "\xD1\x86", "\xD0\xA7" => "\xD1\x87", "\xD0\xA8" => "\xD1\x88", - "\xD0\xA9" => "\xD1\x89", "\xD0\xAA" => "\xD1\x8A", "\xD0\xAB" => "\xD1\x8B", "\xD0\xAC" => "\xD1\x8C", - "\xD0\xAD" => "\xD1\x8D", "\xD0\xAE" => "\xD1\x8E", "\xD0\xAF" => "\xD1\x8F", "\xD2\x90" => "\xD2\x91", - "\xE1\xB8\x82" => "\xE1\xB8\x83", "\xE1\xB8\x8A" => "\xE1\xB8\x8B", "\xE1\xB8\x9E" => "\xE1\xB8\x9F", "\xE1\xB9\x80" => "\xE1\xB9\x81", - "\xE1\xB9\x96" => "\xE1\xB9\x97", "\xE1\xB9\xA0" => "\xE1\xB9\xA1", "\xE1\xB9\xAA" => "\xE1\xB9\xAB", "\xE1\xBA\x80" => "\xE1\xBA\x81", - "\xE1\xBA\x82" => "\xE1\xBA\x83", "\xE1\xBA\x84" => "\xE1\xBA\x85", "\xE1\xBB\xB2" => "\xE1\xBB\xB3" - ); - - return strtr(strtolower($string), $utf8_upper_to_lower); - } - - /** - * UTF-8 aware alternative to strtoupper - * Make a string uppercase - * Note: The concept of a characters "case" only exists is some alphabets - * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does - * not exist in the Chinese alphabet, for example. See Unicode Standard - * Annex #21: Case Mappings - * - * @param string - * @return string string in uppercase - */ - function utf8_strtoupper($string) - { - static $utf8_lower_to_upper = array( - "\xC3\xA0" => "\xC3\x80", "\xC3\xA1" => "\xC3\x81", - "\xC3\xA2" => "\xC3\x82", "\xC3\xA3" => "\xC3\x83", "\xC3\xA4" => "\xC3\x84", "\xC3\xA5" => "\xC3\x85", - "\xC3\xA6" => "\xC3\x86", "\xC3\xA7" => "\xC3\x87", "\xC3\xA8" => "\xC3\x88", "\xC3\xA9" => "\xC3\x89", - "\xC3\xAA" => "\xC3\x8A", "\xC3\xAB" => "\xC3\x8B", "\xC3\xAC" => "\xC3\x8C", "\xC3\xAD" => "\xC3\x8D", - "\xC3\xAE" => "\xC3\x8E", "\xC3\xAF" => "\xC3\x8F", "\xC3\xB0" => "\xC3\x90", "\xC3\xB1" => "\xC3\x91", - "\xC3\xB2" => "\xC3\x92", "\xC3\xB3" => "\xC3\x93", "\xC3\xB4" => "\xC3\x94", "\xC3\xB5" => "\xC3\x95", - "\xC3\xB6" => "\xC3\x96", "\xC3\xB8" => "\xC3\x98", "\xC3\xB9" => "\xC3\x99", "\xC3\xBA" => "\xC3\x9A", - "\xC3\xBB" => "\xC3\x9B", "\xC3\xBC" => "\xC3\x9C", "\xC3\xBD" => "\xC3\x9D", "\xC3\xBE" => "\xC3\x9E", - "\xC3\xBF" => "\xC5\xB8", "\xC4\x81" => "\xC4\x80", "\xC4\x83" => "\xC4\x82", "\xC4\x85" => "\xC4\x84", - "\xC4\x87" => "\xC4\x86", "\xC4\x89" => "\xC4\x88", "\xC4\x8B" => "\xC4\x8A", "\xC4\x8D" => "\xC4\x8C", - "\xC4\x8F" => "\xC4\x8E", "\xC4\x91" => "\xC4\x90", "\xC4\x93" => "\xC4\x92", "\xC4\x97" => "\xC4\x96", - "\xC4\x99" => "\xC4\x98", "\xC4\x9B" => "\xC4\x9A", "\xC4\x9D" => "\xC4\x9C", "\xC4\x9F" => "\xC4\x9E", - "\xC4\xA1" => "\xC4\xA0", "\xC4\xA3" => "\xC4\xA2", "\xC4\xA5" => "\xC4\xA4", "\xC4\xA7" => "\xC4\xA6", - "\xC4\xA9" => "\xC4\xA8", "\xC4\xAB" => "\xC4\xAA", "\xC4\xAF" => "\xC4\xAE", "\xC4\xB5" => "\xC4\xB4", - "\xC4\xB7" => "\xC4\xB6", "\xC4\xBA" => "\xC4\xB9", "\xC4\xBC" => "\xC4\xBB", "\xC4\xBE" => "\xC4\xBD", - "\xC5\x82" => "\xC5\x81", "\xC5\x84" => "\xC5\x83", "\xC5\x86" => "\xC5\x85", "\xC5\x88" => "\xC5\x87", - "\xC5\x8B" => "\xC5\x8A", "\xC5\x8D" => "\xC5\x8C", "\xC5\x91" => "\xC5\x90", "\xC5\x95" => "\xC5\x94", - "\xC5\x97" => "\xC5\x96", "\xC5\x99" => "\xC5\x98", "\xC5\x9B" => "\xC5\x9A", "\xC5\x9D" => "\xC5\x9C", - "\xC5\x9F" => "\xC5\x9E", "\xC5\xA1" => "\xC5\xA0", "\xC5\xA3" => "\xC5\xA2", "\xC5\xA5" => "\xC5\xA4", - "\xC5\xA7" => "\xC5\xA6", "\xC5\xA9" => "\xC5\xA8", "\xC5\xAB" => "\xC5\xAA", "\xC5\xAD" => "\xC5\xAC", - "\xC5\xAF" => "\xC5\xAE", "\xC5\xB1" => "\xC5\xB0", "\xC5\xB3" => "\xC5\xB2", "\xC5\xB5" => "\xC5\xB4", - "\xC5\xB7" => "\xC5\xB6", "\xC5\xBA" => "\xC5\xB9", "\xC5\xBC" => "\xC5\xBB", "\xC5\xBE" => "\xC5\xBD", - "\xC6\xA1" => "\xC6\xA0", "\xC6\xB0" => "\xC6\xAF", "\xC8\x99" => "\xC8\x98", "\xC8\x9B" => "\xC8\x9A", - "\xCE\xAC" => "\xCE\x86", "\xCE\xAD" => "\xCE\x88", "\xCE\xAE" => "\xCE\x89", "\xCE\xAF" => "\xCE\x8A", - "\xCE\xB1" => "\xCE\x91", "\xCE\xB2" => "\xCE\x92", "\xCE\xB3" => "\xCE\x93", "\xCE\xB4" => "\xCE\x94", - "\xCE\xB5" => "\xCE\x95", "\xCE\xB6" => "\xCE\x96", "\xCE\xB7" => "\xCE\x97", "\xCE\xB8" => "\xCE\x98", - "\xCE\xB9" => "\xCE\x99", "\xCE\xBA" => "\xCE\x9A", "\xCE\xBB" => "\xCE\x9B", "\xCE\xBC" => "\xCE\x9C", - "\xCE\xBD" => "\xCE\x9D", "\xCE\xBE" => "\xCE\x9E", "\xCE\xBF" => "\xCE\x9F", "\xCF\x80" => "\xCE\xA0", - "\xCF\x81" => "\xCE\xA1", "\xCF\x83" => "\xCE\xA3", "\xCF\x84" => "\xCE\xA4", "\xCF\x85" => "\xCE\xA5", - "\xCF\x86" => "\xCE\xA6", "\xCF\x87" => "\xCE\xA7", "\xCF\x88" => "\xCE\xA8", "\xCF\x89" => "\xCE\xA9", - "\xCF\x8A" => "\xCE\xAA", "\xCF\x8B" => "\xCE\xAB", "\xCF\x8C" => "\xCE\x8C", "\xCF\x8D" => "\xCE\x8E", - "\xCF\x8E" => "\xCE\x8F", "\xD0\xB0" => "\xD0\x90", "\xD0\xB1" => "\xD0\x91", "\xD0\xB2" => "\xD0\x92", - "\xD0\xB3" => "\xD0\x93", "\xD0\xB4" => "\xD0\x94", "\xD0\xB5" => "\xD0\x95", "\xD0\xB6" => "\xD0\x96", - "\xD0\xB7" => "\xD0\x97", "\xD0\xB8" => "\xD0\x98", "\xD0\xB9" => "\xD0\x99", "\xD0\xBA" => "\xD0\x9A", - "\xD0\xBB" => "\xD0\x9B", "\xD0\xBC" => "\xD0\x9C", "\xD0\xBD" => "\xD0\x9D", "\xD0\xBE" => "\xD0\x9E", - "\xD0\xBF" => "\xD0\x9F", "\xD1\x80" => "\xD0\xA0", "\xD1\x81" => "\xD0\xA1", "\xD1\x82" => "\xD0\xA2", - "\xD1\x83" => "\xD0\xA3", "\xD1\x84" => "\xD0\xA4", "\xD1\x85" => "\xD0\xA5", "\xD1\x86" => "\xD0\xA6", - "\xD1\x87" => "\xD0\xA7", "\xD1\x88" => "\xD0\xA8", "\xD1\x89" => "\xD0\xA9", "\xD1\x8A" => "\xD0\xAA", - "\xD1\x8B" => "\xD0\xAB", "\xD1\x8C" => "\xD0\xAC", "\xD1\x8D" => "\xD0\xAD", "\xD1\x8E" => "\xD0\xAE", - "\xD1\x8F" => "\xD0\xAF", "\xD1\x91" => "\xD0\x81", "\xD1\x92" => "\xD0\x82", "\xD1\x93" => "\xD0\x83", - "\xD1\x94" => "\xD0\x84", "\xD1\x95" => "\xD0\x85", "\xD1\x96" => "\xD0\x86", "\xD1\x97" => "\xD0\x87", - "\xD1\x98" => "\xD0\x88", "\xD1\x99" => "\xD0\x89", "\xD1\x9A" => "\xD0\x8A", "\xD1\x9B" => "\xD0\x8B", - "\xD1\x9C" => "\xD0\x8C", "\xD1\x9E" => "\xD0\x8E", "\xD1\x9F" => "\xD0\x8F", "\xD2\x91" => "\xD2\x90", - "\xE1\xB8\x83" => "\xE1\xB8\x82", "\xE1\xB8\x8B" => "\xE1\xB8\x8A", "\xE1\xB8\x9F" => "\xE1\xB8\x9E", "\xE1\xB9\x81" => "\xE1\xB9\x80", - "\xE1\xB9\x97" => "\xE1\xB9\x96", "\xE1\xB9\xA1" => "\xE1\xB9\xA0", "\xE1\xB9\xAB" => "\xE1\xB9\xAA", "\xE1\xBA\x81" => "\xE1\xBA\x80", - "\xE1\xBA\x83" => "\xE1\xBA\x82", "\xE1\xBA\x85" => "\xE1\xBA\x84", "\xE1\xBB\xB3" => "\xE1\xBB\xB2" - ); - - return strtr(strtoupper($string), $utf8_lower_to_upper); - } - - /** - * UTF-8 aware alternative to substr - * Return part of a string given character offset (and optionally length) - * - * Note arguments: comparied to substr - if offset or length are - * not integers, this version will not complain but rather massages them - * into an integer. - * - * Note on returned values: substr documentation states false can be - * returned in some cases (e.g. offset > string length) - * mb_substr never returns false, it will return an empty string instead. - * This adopts the mb_substr approach - * - * Note on implementation: PCRE only supports repetitions of less than - * 65536, in order to accept up to MAXINT values for offset and length, - * we'll repeat a group of 65535 characters when needed. - * - * Note on implementation: calculating the number of characters in the - * string is a relatively expensive operation, so we only carry it out when - * necessary. It isn't necessary for +ve offsets and no specified length - * - * @author Chris Smith - * @param string $str - * @param integer $offset number of UTF-8 characters offset (from left) - * @param integer $length (optional) length in UTF-8 characters from offset - * @return mixed string or FALSE if failure - */ - function utf8_substr($str, $offset, $length = NULL) - { - // generates E_NOTICE - // for PHP4 objects, but not PHP5 objects - $str = (string) $str; - $offset = (int) $offset; - if (!is_null($length)) - { - $length = (int) $length; - } - - // handle trivial cases - if ($length === 0 || ($offset < 0 && $length < 0 && $length < $offset)) - { - return ''; - } - - // normalise negative offsets (we could use a tail - // anchored pattern, but they are horribly slow!) - if ($offset < 0) - { - // see notes - $strlen = utf8_strlen($str); - $offset = $strlen + $offset; - if ($offset < 0) - { - $offset = 0; - } - } - - $op = ''; - $lp = ''; - - // establish a pattern for offset, a - // non-captured group equal in length to offset - if ($offset > 0) - { - $ox = (int) ($offset / 65535); - $oy = $offset % 65535; - - if ($ox) - { - $op = '(?:.{65535}){' . $ox . '}'; - } - - $op = '^(?:' . $op . '.{' . $oy . '})'; - } - else - { - // offset == 0; just anchor the pattern - $op = '^'; - } - - // establish a pattern for length - if (is_null($length)) - { - // the rest of the string - $lp = '(.*)$'; - } - else - { - if (!isset($strlen)) - { - // see notes - $strlen = utf8_strlen($str); - } - - // another trivial case - if ($offset > $strlen) - { - return ''; - } - - if ($length > 0) - { - // reduce any length that would - // go passed the end of the string - $length = min($strlen - $offset, $length); - - $lx = (int) ($length / 65535); - $ly = $length % 65535; - - // negative length requires a captured group - // of length characters - if ($lx) - { - $lp = '(?:.{65535}){' . $lx . '}'; - } - $lp = '(' . $lp . '.{'. $ly . '})'; - } - else if ($length < 0) - { - if ($length < ($offset - $strlen)) - { - return ''; - } - - $lx = (int) ((-$length) / 65535); - $ly = (-$length) % 65535; - - // negative length requires ... capture everything - // except a group of -length characters - // anchored at the tail-end of the string - if ($lx) - { - $lp = '(?:.{65535}){' . $lx . '}'; - } - $lp = '(.*)(?:' . $lp . '.{' . $ly . '})$'; - } - } - - if (!preg_match('#' . $op . $lp . '#us', $str, $match)) - { - return ''; - } - - return $match[1]; - } - - /** - * Return the length (in characters) of a UTF-8 string - * - * @param string $text UTF-8 string - * @return integer Length (in chars) of given string - */ - function utf8_strlen($text) - { - // Since utf8_decode is replacing multibyte characters to ? strlen works fine - return strlen(utf8_decode($text)); - } +/** +* Return the length (in characters) of a UTF-8 string +* @ignore +*/ +function utf8_strlen($text) +{ + return mb_strlen($text, 'utf-8'); } /** From d266c7ae268cfc61bc90b622f71710abda9b3606 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Tue, 11 Nov 2014 13:59:16 +0100 Subject: [PATCH 0027/1676] [develop] Update / Fix composer.lock hash. --- phpBB/composer.lock | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index ea177f537a..6824c82243 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "1344b97ad0b4c8eb75a384a545065333", + "hash": "3c4d83fc3d00d6d76787dbb1d89ee405", "packages": [ { "name": "lusitanian/oauth", @@ -2313,11 +2313,17 @@ "time": "2014-09-23 05:25:11" } ], - "aliases": [], + "aliases": [ + + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": [ + + ], "platform": { "php": ">=5.3.3" }, - "platform-dev": [] + "platform-dev": [ + + ] } From a5bfc76a73a213a388126d0f697ba64f27a4b00d Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 14 Sep 2014 21:18:20 +0200 Subject: [PATCH 0028/1676] [ticket/13063] Introduces a new \phpbb\routing\router class PHPBB3-13063 --- phpBB/config/services.yml | 21 +- phpBB/phpbb/cache/driver/base.php | 1 + phpBB/phpbb/controller/helper.php | 17 +- phpBB/phpbb/controller/provider.php | 92 ------ .../phpbb/event/kernel_request_subscriber.php | 82 ----- phpBB/phpbb/routing/router.php | 304 ++++++++++++++++++ tests/controller/common_helper_route.php | 23 +- tests/controller/controller_test.php | 8 +- tests/mock/controller_helper.php | 5 +- tests/mock/router.php | 27 ++ tests/pagination/pagination_test.php | 8 +- 11 files changed, 379 insertions(+), 209 deletions(-) delete mode 100644 phpBB/phpbb/controller/provider.php delete mode 100644 phpBB/phpbb/event/kernel_request_subscriber.php create mode 100644 phpBB/phpbb/routing/router.php create mode 100644 tests/mock/router.php diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index 6be694a14c..de4744cd45 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -73,7 +73,7 @@ services: - @template - @user - @config - - @controller.provider + - @router - @ext.manager - @symfony_request - @request @@ -89,11 +89,6 @@ services: - %core.root_path% - @template - controller.provider: - class: phpbb\controller\provider - calls: - - [find, [%core.root_path%]] - ext.manager: class: phpbb\extension\manager arguments: @@ -157,6 +152,20 @@ services: - null - %core.disable_super_globals% + router: + class: phpbb\routing\router + arguments: + - @ext.manager + - %core.root_path% + - %core.php_ext% + + router.listener: + class: Symfony\Component\HttpKernel\EventListener\RouterListener + arguments: + - @router + tags: + - { name: kernel.event_subscriber } + # WARNING: The Symfony request does not escape the input and should be used very carefully # prefer the phpbb request (service @request) as possible symfony_request: diff --git a/phpBB/phpbb/cache/driver/base.php b/phpBB/phpbb/cache/driver/base.php index b357431589..c83b928a12 100644 --- a/phpBB/phpbb/cache/driver/base.php +++ b/phpBB/phpbb/cache/driver/base.php @@ -50,6 +50,7 @@ abstract class base implements \phpbb\cache\driver\driver_interface } else if (strpos($filename, 'container_') === 0 || strpos($filename, 'url_matcher') === 0 || + strpos($filename, 'url_generator') === 0 || strpos($filename, 'sql_') === 0 || strpos($filename, 'data_') === 0) { diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index 52e6947c2c..f4535af711 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -14,7 +14,6 @@ namespace phpbb\controller; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RequestContext; @@ -41,6 +40,11 @@ class helper */ protected $config; + /** + * @var \phpbb\routing\router phpBB router + */ + protected $router; + /* @var \phpbb\symfony_request */ protected $symfony_request; @@ -70,7 +74,7 @@ class helper * @param \phpbb\template\template $template Template object * @param \phpbb\user $user User object * @param \phpbb\config\config $config Config object - * @param \phpbb\controller\provider $provider Path provider + * @param \phpbb\routing\router $router phpBB router * @param \phpbb\extension\manager $manager Extension manager object * @param \phpbb\symfony_request $symfony_request Symfony Request object * @param \phpbb\request\request_interface $request phpBB request object @@ -78,18 +82,17 @@ class helper * @param string $phpbb_root_path phpBB root path * @param string $php_ext PHP file extension */ - public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\controller\provider $provider, \phpbb\extension\manager $manager, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\extension\manager $manager, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext) { $this->template = $template; $this->user = $user; $this->config = $config; + $this->router = $router; $this->symfony_request = $symfony_request; $this->request = $request; $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - $provider->find_routing_files($manager->get_finder()); - $this->route_collection = $provider->find($phpbb_root_path)->get_routes(); } /** @@ -162,8 +165,8 @@ class helper $context->setBaseUrl($base_url); - $url_generator = new UrlGenerator($this->route_collection, $context); - $route_url = $url_generator->generate($route, $params, $reference_type); + $this->router->setContext($context); + $route_url = $this->router->generate($route, $params, $reference_type); if ($is_amp) { diff --git a/phpBB/phpbb/controller/provider.php b/phpBB/phpbb/controller/provider.php deleted file mode 100644 index 7e26848290..0000000000 --- a/phpBB/phpbb/controller/provider.php +++ /dev/null @@ -1,92 +0,0 @@ - -* @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\controller; - -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\Loader\YamlFileLoader; -use Symfony\Component\Config\FileLocator; - -/** -* Controller interface -*/ -class provider -{ - /** - * YAML file(s) containing route information - * @var array - */ - protected $routing_files; - - /** - * Collection of the routes in phpBB and all found extensions - * @var RouteCollection - */ - protected $routes; - - /** - * Construct method - * - * @param array $routing_files Array of strings containing paths - * to YAML files holding route information - */ - public function __construct($routing_files = array()) - { - $this->routing_files = $routing_files; - } - - /** - * Find the list of routing files - * - * @param \phpbb\finder $finder - * @return null - */ - public function find_routing_files(\phpbb\finder $finder) - { - // We hardcode the path to the core config directory - // because the finder cannot find it - $this->routing_files = array_merge($this->routing_files, array('config/routing.yml'), array_keys($finder - ->directory('/config') - ->suffix('routing.yml') - ->find() - )); - } - - /** - * Find a list of controllers - * - * @param string $base_path Base path to prepend to file paths - * @return provider - */ - public function find($base_path = '') - { - $this->routes = new RouteCollection; - foreach ($this->routing_files as $file_path) - { - $loader = new YamlFileLoader(new FileLocator(phpbb_realpath($base_path))); - $this->routes->addCollection($loader->load($file_path)); - } - - return $this; - } - - /** - * Get the list of routes - * - * @return RouteCollection Get the route collection - */ - public function get_routes() - { - return $this->routes; - } -} diff --git a/phpBB/phpbb/event/kernel_request_subscriber.php b/phpBB/phpbb/event/kernel_request_subscriber.php deleted file mode 100644 index ee9f29a59d..0000000000 --- a/phpBB/phpbb/event/kernel_request_subscriber.php +++ /dev/null @@ -1,82 +0,0 @@ - -* @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\event; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\HttpKernel\EventListener\RouterListener; -use Symfony\Component\Routing\RequestContext; - -class kernel_request_subscriber implements EventSubscriberInterface -{ - /** - * Extension manager object - * @var \phpbb\extension\manager - */ - protected $manager; - - /** - * PHP file extension - * @var string - */ - protected $php_ext; - - /** - * Root path - * @var string - */ - protected $root_path; - - /** - * Construct method - * - * @param \phpbb\extension\manager $manager Extension manager object - * @param string $root_path Root path - * @param string $php_ext PHP file extension - */ - public function __construct(\phpbb\extension\manager $manager, $root_path, $php_ext) - { - $this->root_path = $root_path; - $this->php_ext = $php_ext; - $this->manager = $manager; - } - - /** - * This listener is run when the KernelEvents::REQUEST event is triggered - * - * This is responsible for setting up the routing information - * - * @param GetResponseEvent $event - * @throws \BadMethodCallException - * @return null - */ - public function on_kernel_request(GetResponseEvent $event) - { - $request = $event->getRequest(); - $context = new RequestContext(); - $context->fromRequest($request); - - $matcher = phpbb_get_url_matcher($this->manager, $context, $this->root_path, $this->php_ext); - $router_listener = new RouterListener($matcher, $context); - $router_listener->onKernelRequest($event); - } - - public static function getSubscribedEvents() - { - return array( - KernelEvents::REQUEST => 'on_kernel_request', - ); - } -} diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php new file mode 100644 index 0000000000..cebf19e702 --- /dev/null +++ b/phpBB/phpbb/routing/router.php @@ -0,0 +1,304 @@ + +* @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\routing; + +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; +use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\Generator\UrlGenerator; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RouterInterface; +use Symfony\Component\Routing\Loader\YamlFileLoader; +use Symfony\Component\Config\FileLocator; +use phpbb\extension\manager; + +/** +* Integration of all pieces of the routing system for easier use. +*/ +class router implements RouterInterface +{ + /** + * @var manager Extension manager + */ + protected $extension_manager; + + /** + * @var string phpBB root path + */ + protected $phpbb_root_path; + + /** + * @var string PHP file extensions + */ + protected $php_ext; + + /** + * @var array YAML file(s) containing route information + */ + protected $routing_files; + + /** + * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface|null + */ + protected $matcher; + + /** + * @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface|null + */ + protected $generator; + + /** + * @var RequestContext + */ + protected $context; + + /** + * @var RouteCollection|null + */ + protected $route_collection; + + /** + * Construct method + * + * @param manager $extension_manager The extension manager + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP file extension + * @param array $routing_files Array of strings containing paths + * to YAML files holding route information + */ + public function __construct(manager $extension_manager, $phpbb_root_path, $php_ext, $routing_files = array()) + { + $this->extension_manager = $extension_manager; + $this->routing_files = $routing_files; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + $this->context = new RequestContext(); + } + + /** + * Find the list of routing files + * + * @param \phpbb\finder $finder + * @return router + */ + public function find_routing_files(\phpbb\finder $finder) + { + if ($this->routing_files === null || empty($this->routing_files)) + { + // We hardcode the path to the core config directory + // because the finder cannot find it + $this->routing_files = array_merge($this->routing_files, array('config/routing.yml'), array_keys($finder + ->directory('/config') + ->suffix('routing.yml') + ->find() + )); + } + + return $this; + } + + /** + * Find a list of controllers + * + * @param string $base_path Base path to prepend to file paths + * @return router + */ + public function find($base_path = '') + { + if ($this->route_collection === null || $this->route_collection->count() === 0) + { + $this->route_collection = new RouteCollection; + foreach ($this->routing_files as $file_path) + { + $loader = new YamlFileLoader(new FileLocator(phpbb_realpath($base_path))); + $this->route_collection->addCollection($loader->load($file_path)); + } + } + + return $this; + } + + /** + * Get the list of routes + * + * @return RouteCollection Get the route collection + */ + public function get_routes() + { + if ($this->route_collection == null || empty($this->routing_files)) + { + $this->find_routing_files($this->extension_manager->get_finder()) + ->find($this->phpbb_root_path); + } + + return $this->route_collection; + } + + /** + * {@inheritdoc} + */ + public function getRouteCollection() + { + return $this->get_routes(); + } + + /** + * {@inheritdoc} + */ + public function setContext(RequestContext $context) + { + $this->context = $context; + + if ($this->matcher !== null) + { + $this->get_matcher()->setContext($context); + } + if ($this->generator !== null) + { + $this->get_generator()->setContext($context); + } + } + + /** + * {@inheritdoc} + */ + public function getContext() + { + return $this->context; + } + + /** + * {@inheritdoc} + */ + public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) + { + return $this->get_generator()->generate($name, $parameters, $referenceType); + } + + /** + * {@inheritdoc} + */ + public function match($pathinfo) + { + return $this->get_matcher()->match($pathinfo); + } + + /** + * Gets the UrlMatcher instance associated with this Router. + * + * @return \Symfony\Component\Routing\Matcher\UrlMatcherInterface A UrlMatcherInterface instance + */ + public function get_matcher() + { + if ($this->matcher !== null) + { + return $this->matcher; + } + + if (defined('DEBUG')) + { + $this->create_new_url_matcher(); + } + else + { + $this->create_dumped_url_matcher(); + } + + return $this->matcher; + } + /** + * Creates a new dumped URL Matcher (dump it if necessary) + */ + protected function create_dumped_url_matcher() + { + if (!file_exists($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext)) + { + $dumper = new PhpMatcherDumper($this->get_routes()); + + $options = array( + 'class' => 'phpbb_url_matcher', + ); + + $dump = $dumper->dump($options); + file_put_contents($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext, $dump); + } + + require_once($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext); + + $this->matcher = new phpbb_url_matcher($this->context); + } + + /** + * Creates a new URL Matcher + */ + protected function create_new_url_matcher() + { + $this->matcher = new UrlMatcher($this->get_routes(), $this->context); + } + + /** + * Gets the UrlGenerator instance associated with this Router. + * + * @return \Symfony\Component\Routing\Generator\UrlGeneratorInterface A UrlGeneratorInterface instance + */ + public function get_generator() + { + if ($this->generator !== null) + { + return $this->generator; + } + + if (defined('DEBUG')) + { + $this->create_new_url_generator(); + } + else + { + $this->create_dumped_url_generator(); + } + + return $this->generator; + } + + /** + * Creates a new dumped URL Generator (dump it if necessary) + */ + protected function create_dumped_url_generator() + { + if (!file_exists($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext)) + { + $dumper = new PhpGeneratorDumper($this->get_routes()); + + $options = array( + 'class' => 'phpbb_url_generator', + ); + + $dump = $dumper->dump($options); + file_put_contents($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext, $dump); + } + + require_once($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext); + + $this->generator = new phpbb_url_generator($this->context); + } + + /** + * Creates a new URL Generator + */ + protected function create_new_url_generator() + { + $this->generator = new UrlGenerator($this->get_routes(), $this->context); + } +} diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index 5e15eb3ee1..1234c372fe 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -119,9 +119,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case new phpbb_mock_cache() ); $finder->set_extensions(array_keys($this->extension_manager->all_enabled())); - $this->provider = new \phpbb\controller\provider(); - $this->provider->find_routing_files($finder); - $this->provider->find(dirname(__FILE__) . '/'); + $this->router = new phpbb_mock_router($this->extension_manager, dirname(__FILE__) . '/', 'php'); + $this->router->find_routing_files($finder); + $this->router->find(dirname(__FILE__) . '/'); // Set correct current phpBB root path $this->root_path = $this->get_phpbb_root_path(); } @@ -161,7 +161,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case */ public function test_helper_url_no_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id)); } @@ -201,7 +202,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id)); } @@ -241,7 +242,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_absolute($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL)); } @@ -281,7 +282,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_relative_path($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH)); } @@ -321,7 +322,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_network($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH)); } //TODO @@ -361,7 +362,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_absolute_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL)); } @@ -401,7 +402,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_relative_path_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH)); } @@ -441,7 +442,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_network_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH)); } } diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php index 62feee3fed..cd90dda751 100644 --- a/tests/controller/controller_test.php +++ b/tests/controller/controller_test.php @@ -33,11 +33,11 @@ class phpbb_controller_controller_test extends phpbb_test_case )); } - public function test_provider() + public function test_router_find_files() { - $provider = new \phpbb\controller\provider(); - $provider->find_routing_files($this->extension_manager->get_finder()); - $routes = $provider->find(__DIR__)->get_routes(); + $router = new \phpbb\routing\router($this->extension_manager, dirname(__FILE__) . '/', 'php'); + $router->find_routing_files($this->extension_manager->get_finder()); + $routes = $router->find(__DIR__)->get_routes(); // This will need to be updated if any new routes are defined $this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('core_controller')); diff --git a/tests/mock/controller_helper.php b/tests/mock/controller_helper.php index ae3e7bf432..7e4a808906 100644 --- a/tests/mock/controller_helper.php +++ b/tests/mock/controller_helper.php @@ -13,7 +13,7 @@ class phpbb_mock_controller_helper extends \phpbb\controller\helper { - public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\controller\provider $provider, \phpbb\extension\manager $manager, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext, $phpbb_root_path_ext) + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext, $phpbb_root_path_ext) { $this->template = $template; $this->user = $user; @@ -23,8 +23,7 @@ class phpbb_mock_controller_helper extends \phpbb\controller\helper $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - $provider->find_routing_files($manager->get_finder()); - $this->route_collection = $provider->find($phpbb_root_path_ext)->get_routes(); + $this->router = $router; } public function get_current_url() diff --git a/tests/mock/router.php b/tests/mock/router.php new file mode 100644 index 0000000000..01faa338c5 --- /dev/null +++ b/tests/mock/router.php @@ -0,0 +1,27 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_mock_router extends \phpbb\routing\router +{ + public function get_matcher() + { + $this->create_new_url_matcher(); + return parent::get_matcher(); + } + + public function get_generator() + { + $this->create_new_url_generator(); + return parent::get_generator(); + } +} diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index 494c667198..de939e280d 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -44,9 +44,9 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case $finder->set_extensions(array_keys($manager->all_enabled())); $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $provider = new \phpbb\controller\provider(); - $provider->find_routing_files($finder); - $provider->find(dirname(__FILE__) . '/'); + $router = new phpbb_mock_router($manager, dirname(__FILE__) . '/', 'php'); + $router->find_routing_files($finder); + $router->find(dirname(__FILE__) . '/'); $request = new phpbb_mock_request(); $request->overwrite('SCRIPT_NAME', '/app.php', \phpbb\request\request_interface::SERVER); @@ -57,7 +57,7 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case $request ); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $provider, $manager, $symfony_request, $request, $filesystem, '', 'php', dirname(__FILE__) . '/'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $router, $manager, $symfony_request, $request, $filesystem, '', 'php', dirname(__FILE__) . '/'); $this->pagination = new \phpbb\pagination($this->template, $this->user, $this->helper, $phpbb_dispatcher); } From f81d8c53fc8b4bc0fd0eae834d4edb317e897766 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 3 Oct 2014 22:39:18 +0200 Subject: [PATCH 0029/1676] [ticket/13063] Adds Twig routing extension PHPBB3-13063 --- build/build.xml | 6 ++ phpBB/composer.json | 1 + phpBB/composer.lock | 205 +++++++++++++++++++++++++++++++++++++++--- phpBB/config/twig.yml | 7 ++ 4 files changed, 208 insertions(+), 11 deletions(-) diff --git a/build/build.xml b/build/build.xml index 8f4089c74f..5d143886af 100644 --- a/build/build.xml +++ b/build/build.xml @@ -382,6 +382,12 @@ + + + + + + diff --git a/phpBB/composer.json b/phpBB/composer.json index c6fcb281b9..4d31eefa2b 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -34,6 +34,7 @@ "symfony/event-dispatcher": "2.5.*", "symfony/http-kernel": "2.5.*", "symfony/routing": "2.5.*", + "symfony/twig-bridge": "2.5.*", "symfony/yaml": "2.5.*", "twig/twig": "1.13.*" }, diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 03c5b4a05f..62e7c83272 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "3c4d83fc3d00d6d76787dbb1d89ee405", + "hash": "2faf4ba24774c0d51cff4b78d4a81a68", "packages": [ { "name": "lusitanian/oauth", @@ -673,6 +673,194 @@ ], "time": "2014-09-22 15:28:36" }, + { + "name": "symfony/security-core", + "version": "v2.5.6", + "target-dir": "Symfony/Component/Security/Core", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-core.git", + "reference": "fc79ba84f7db4a11d8313c87e8845096278d4144" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-core/zipball/fc79ba84f7db4a11d8313c87e8845096278d4144", + "reference": "fc79ba84f7db4a11d8313c87e8845096278d4144", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "ircmaxell/password-compat": "1.0.*", + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.1", + "symfony/expression-language": "~2.4", + "symfony/http-foundation": "~2.4", + "symfony/validator": "~2.5" + }, + "suggest": { + "ircmaxell/password-compat": "For using the BCrypt password encoder in PHP <5.5", + "symfony/event-dispatcher": "", + "symfony/expression-language": "For using the expression voter", + "symfony/http-foundation": "", + "symfony/validator": "For using the user password constraint" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Security\\Core\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Security Component - Core Library", + "homepage": "http://symfony.com", + "time": "2014-09-28 15:22:14" + }, + { + "name": "symfony/security-csrf", + "version": "v2.5.6", + "target-dir": "Symfony/Component/Security/Csrf", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-csrf.git", + "reference": "08711832eb9c7b08b513318357391693411e9478" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/08711832eb9c7b08b513318357391693411e9478", + "reference": "08711832eb9c7b08b513318357391693411e9478", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/security-core": "~2.4" + }, + "require-dev": { + "symfony/http-foundation": "~2.1" + }, + "suggest": { + "symfony/http-foundation": "For using the class SessionTokenStorage." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Security\\Csrf\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Security Component - CSRF Library", + "homepage": "http://symfony.com", + "time": "2014-05-12 09:28:39" + }, + { + "name": "symfony/twig-bridge", + "version": "v2.5.6", + "target-dir": "Symfony/Bridge/Twig", + "source": { + "type": "git", + "url": "https://github.com/symfony/TwigBridge.git", + "reference": "8850738d9f51436494f87d1e4669f4e870a5fe83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/TwigBridge/zipball/8850738d9f51436494f87d1e4669f4e870a5fe83", + "reference": "8850738d9f51436494f87d1e4669f4e870a5fe83", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/security-csrf": "~2.4", + "twig/twig": "~1.12" + }, + "require-dev": { + "symfony/console": "~2.2", + "symfony/expression-language": "~2.4", + "symfony/form": "~2.5,<2.6.0", + "symfony/http-kernel": "~2.2", + "symfony/routing": "~2.2", + "symfony/security": "~2.4", + "symfony/stopwatch": "~2.2", + "symfony/templating": "~2.1", + "symfony/translation": "~2.2", + "symfony/yaml": "~2.0" + }, + "suggest": { + "symfony/expression-language": "For using the ExpressionExtension", + "symfony/form": "For using the FormExtension", + "symfony/http-kernel": "For using the HttpKernelExtension", + "symfony/routing": "For using the RoutingExtension", + "symfony/security": "For using the SecurityExtension", + "symfony/stopwatch": "For using the StopwatchExtension", + "symfony/templating": "For using the TwigEngine", + "symfony/translation": "For using the TranslationExtension", + "symfony/yaml": "For using the YamlExtension" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Bridge\\Twig\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Twig Bridge", + "homepage": "http://symfony.com", + "time": "2014-10-24 05:49:22" + }, { "name": "symfony/yaml", "version": "v2.5.5", @@ -1159,7 +1347,8 @@ "authors": [ { "name": "Michiel Rook", - "email": "mrook@php.net" + "email": "mrook@php.net", + "role": "Lead" }, { "name": "Phing Community", @@ -2309,17 +2498,11 @@ "time": "2014-09-23 05:25:11" } ], - "aliases": [ - - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": [ - - ], + "stability-flags": [], "platform": { "php": ">=5.3.3" }, - "platform-dev": [ - - ] + "platform-dev": [] } diff --git a/phpBB/config/twig.yml b/phpBB/config/twig.yml index eb3e6c0924..0745d8b47e 100644 --- a/phpBB/config/twig.yml +++ b/phpBB/config/twig.yml @@ -34,3 +34,10 @@ services: - @user tags: - { name: twig.extension } + + template.twig.extensions.routing: + class: Symfony\Bridge\Twig\Extension\RoutingExtension + arguments: + - @router + tags: + - { name: twig.extension } From dec8b0de47433a02653f630d98a45a414415d72c Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 7 Nov 2014 15:28:07 +0100 Subject: [PATCH 0030/1676] [ticket/13063] Remove kernel_request_subscriber service definition PHPBB3-13063 --- phpBB/config/event.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/phpBB/config/event.yml b/phpBB/config/event.yml index 599b3cbb40..1ccef78f9b 100644 --- a/phpBB/config/event.yml +++ b/phpBB/config/event.yml @@ -11,15 +11,6 @@ services: - %core.php_ext% - @cache.driver - kernel_request_subscriber: - class: phpbb\event\kernel_request_subscriber - arguments: - - @ext.manager - - %core.root_path% - - %core.php_ext% - tags: - - { name: kernel.event_subscriber } - kernel_exception_subscriber: class: phpbb\event\kernel_exception_subscriber arguments: From fdcd6e81cd4ae530036fd18ad184c0d2423c6949 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 20 Nov 2014 16:37:45 +0100 Subject: [PATCH 0031/1676] [ticket/13063] Fix tests after rebase PHPBB3-13063 --- phpBB/phpbb/controller/helper.php | 3 +-- tests/controller/common_helper_route.php | 32 ++++++++++++------------ tests/pagination/pagination_test.php | 2 +- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index f4535af711..cc327882e0 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -75,14 +75,13 @@ class helper * @param \phpbb\user $user User object * @param \phpbb\config\config $config Config object * @param \phpbb\routing\router $router phpBB router - * @param \phpbb\extension\manager $manager Extension manager object * @param \phpbb\symfony_request $symfony_request Symfony Request object * @param \phpbb\request\request_interface $request phpBB request object * @param \phpbb\filesystem $filesystem The filesystem object * @param string $phpbb_root_path phpBB root path * @param string $php_ext PHP file extension */ - public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\extension\manager $manager, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext) { $this->template = $template; $this->user = $user; diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index 1234c372fe..028a73d70d 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -162,8 +162,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_no_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); - $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id)); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id), $description); } public function helper_url_data_with_rewrite() @@ -202,8 +202,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); - $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id)); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id), $description); } public function helper_url_data_absolute() @@ -242,8 +242,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_absolute($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); - $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL)); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description); } public function helper_url_data_relative_path() @@ -282,8 +282,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_relative_path($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); - $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH)); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description); } public function helper_url_data_network() @@ -322,8 +322,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_network($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); - $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH)); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description); } //TODO public function helper_url_data_absolute_with_rewrite() @@ -362,8 +362,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_absolute_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); - $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL)); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description); } public function helper_url_data_relative_path_with_rewrite() @@ -402,8 +402,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_relative_path_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); - $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH)); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description); } public function helper_url_data_network_with_rewrite() @@ -442,7 +442,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_network_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); - $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH)); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description); } } diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index de939e280d..04f7b807a7 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -57,7 +57,7 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case $request ); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $router, $manager, $symfony_request, $request, $filesystem, '', 'php', dirname(__FILE__) . '/'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $router, $symfony_request, $request, $filesystem, '', 'php', dirname(__FILE__) . '/'); $this->pagination = new \phpbb\pagination($this->template, $this->user, $this->helper, $phpbb_dispatcher); } From 2573dd18ca3327d0b5209a8d465f7911034c1302 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 20 Nov 2014 16:47:24 +0100 Subject: [PATCH 0032/1676] [ticket/13063] Fix coding style PHPBB3-13063 --- phpBB/phpbb/routing/router.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index cebf19e702..f721837bba 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -72,11 +72,10 @@ class router implements RouterInterface /** * Construct method * - * @param manager $extension_manager The extension manager - * @param string $phpbb_root_path phpBB root path - * @param string $php_ext PHP file extension - * @param array $routing_files Array of strings containing paths - * to YAML files holding route information + * @param manager $extension_manager The extension manager + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP file extension + * @param array $routing_files Array of strings containing paths to YAML files holding route information */ public function __construct(manager $extension_manager, $phpbb_root_path, $php_ext, $routing_files = array()) { From 8be2f119af6164ee103330a15123d977fc1c07ea Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 20 Nov 2014 18:12:28 +0100 Subject: [PATCH 0033/1676] [ticket/13063] Fix functional tests errors PHPBB3-13063 --- phpBB/config/services.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index de4744cd45..f6dbae4a76 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -74,7 +74,6 @@ services: - @user - @config - @router - - @ext.manager - @symfony_request - @request - @filesystem From c22562f5cdb3db9482a7c6bc2398ebb12cbcfb8b Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 30 May 2014 14:57:19 +0200 Subject: [PATCH 0034/1676] [ticket/12620] Allow the user to define multiples environments PHPBB3-12620 --- phpBB/common.php | 5 ++++ phpBB/config/config_debug.yml | 2 ++ phpBB/config/config_productive.yml | 2 ++ phpBB/config/services.yml | 30 +++++++++---------- phpBB/config/{auth.yml => services_auth.yml} | 0 .../{avatar.yml => services_avatar.yml} | 0 .../{captcha.yml => services_captcha.yml} | 0 .../{console.yml => services_console.yml} | 0 .../{content.yml => services_content.yml} | 0 phpBB/config/{cron.yml => services_cron.yml} | 0 phpBB/config/{db.yml => services_db.yml} | 0 .../config/{event.yml => services_event.yml} | 0 phpBB/config/{feed.yml => services_feed.yml} | 0 ...sser.yml => services_mimetype_guesser.yml} | 0 ...fication.yml => services_notification.yml} | 0 .../{password.yml => services_password.yml} | 0 ...ilefield.yml => services_profilefield.yml} | 0 phpBB/config/{twig.yml => services_twig.yml} | 0 phpBB/config/{user.yml => services_user.yml} | 0 phpBB/includes/functions_install.php | 4 +-- phpBB/phpbb/di/extension/core.php | 2 +- 21 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 phpBB/config/config_debug.yml create mode 100644 phpBB/config/config_productive.yml rename phpBB/config/{auth.yml => services_auth.yml} (100%) rename phpBB/config/{avatar.yml => services_avatar.yml} (100%) rename phpBB/config/{captcha.yml => services_captcha.yml} (100%) rename phpBB/config/{console.yml => services_console.yml} (100%) rename phpBB/config/{content.yml => services_content.yml} (100%) rename phpBB/config/{cron.yml => services_cron.yml} (100%) rename phpBB/config/{db.yml => services_db.yml} (100%) rename phpBB/config/{event.yml => services_event.yml} (100%) rename phpBB/config/{feed.yml => services_feed.yml} (100%) rename phpBB/config/{mimetype_guesser.yml => services_mimetype_guesser.yml} (100%) rename phpBB/config/{notification.yml => services_notification.yml} (100%) rename phpBB/config/{password.yml => services_password.yml} (100%) rename phpBB/config/{profilefield.yml => services_profilefield.yml} (100%) rename phpBB/config/{twig.yml => services_twig.yml} (100%) rename phpBB/config/{user.yml => services_user.yml} (100%) diff --git a/phpBB/common.php b/phpBB/common.php index 0782bd7321..d4549dc2d4 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -29,6 +29,11 @@ $phpbb_class_loader->register(); $phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx); extract($phpbb_config_php_file->get_all()); +if (!defined('ENVIRONMENT')) +{ + @define('ENVIRONMENT', 'productive'); +} + if (!defined('PHPBB_INSTALLED')) { // Redirect the user to the installer diff --git a/phpBB/config/config_debug.yml b/phpBB/config/config_debug.yml new file mode 100644 index 0000000000..6982aa4f83 --- /dev/null +++ b/phpBB/config/config_debug.yml @@ -0,0 +1,2 @@ +imports: + - { resource: services.yml } diff --git a/phpBB/config/config_productive.yml b/phpBB/config/config_productive.yml new file mode 100644 index 0000000000..6982aa4f83 --- /dev/null +++ b/phpBB/config/config_productive.yml @@ -0,0 +1,2 @@ +imports: + - { resource: services.yml } diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index f6dbae4a76..3f36a5178a 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -1,19 +1,19 @@ imports: - - { resource: auth.yml } - - { resource: avatar.yml } - - { resource: captcha.yml } - - { resource: console.yml } - - { resource: content.yml } - - { resource: cron.yml } - - { resource: db.yml } - - { resource: event.yml } - - { resource: feed.yml } - - { resource: mimetype_guesser.yml } - - { resource: notification.yml } - - { resource: password.yml } - - { resource: profilefield.yml } - - { resource: twig.yml } - - { resource: user.yml } + - { resource: services_auth.yml } + - { resource: services_avatar.yml } + - { resource: services_captcha.yml } + - { resource: services_console.yml } + - { resource: services_content.yml } + - { resource: services_cron.yml } + - { resource: services_db.yml } + - { resource: services_event.yml } + - { resource: services_feed.yml } + - { resource: services_mimetype_guesser.yml } + - { resource: services_notification.yml } + - { resource: services_password.yml } + - { resource: services_profilefield.yml } + - { resource: services_twig.yml } + - { resource: services_user.yml } - { resource: tables.yml } - { resource: parameters.yml } diff --git a/phpBB/config/auth.yml b/phpBB/config/services_auth.yml similarity index 100% rename from phpBB/config/auth.yml rename to phpBB/config/services_auth.yml diff --git a/phpBB/config/avatar.yml b/phpBB/config/services_avatar.yml similarity index 100% rename from phpBB/config/avatar.yml rename to phpBB/config/services_avatar.yml diff --git a/phpBB/config/captcha.yml b/phpBB/config/services_captcha.yml similarity index 100% rename from phpBB/config/captcha.yml rename to phpBB/config/services_captcha.yml diff --git a/phpBB/config/console.yml b/phpBB/config/services_console.yml similarity index 100% rename from phpBB/config/console.yml rename to phpBB/config/services_console.yml diff --git a/phpBB/config/content.yml b/phpBB/config/services_content.yml similarity index 100% rename from phpBB/config/content.yml rename to phpBB/config/services_content.yml diff --git a/phpBB/config/cron.yml b/phpBB/config/services_cron.yml similarity index 100% rename from phpBB/config/cron.yml rename to phpBB/config/services_cron.yml diff --git a/phpBB/config/db.yml b/phpBB/config/services_db.yml similarity index 100% rename from phpBB/config/db.yml rename to phpBB/config/services_db.yml diff --git a/phpBB/config/event.yml b/phpBB/config/services_event.yml similarity index 100% rename from phpBB/config/event.yml rename to phpBB/config/services_event.yml diff --git a/phpBB/config/feed.yml b/phpBB/config/services_feed.yml similarity index 100% rename from phpBB/config/feed.yml rename to phpBB/config/services_feed.yml diff --git a/phpBB/config/mimetype_guesser.yml b/phpBB/config/services_mimetype_guesser.yml similarity index 100% rename from phpBB/config/mimetype_guesser.yml rename to phpBB/config/services_mimetype_guesser.yml diff --git a/phpBB/config/notification.yml b/phpBB/config/services_notification.yml similarity index 100% rename from phpBB/config/notification.yml rename to phpBB/config/services_notification.yml diff --git a/phpBB/config/password.yml b/phpBB/config/services_password.yml similarity index 100% rename from phpBB/config/password.yml rename to phpBB/config/services_password.yml diff --git a/phpBB/config/profilefield.yml b/phpBB/config/services_profilefield.yml similarity index 100% rename from phpBB/config/profilefield.yml rename to phpBB/config/services_profilefield.yml diff --git a/phpBB/config/twig.yml b/phpBB/config/services_twig.yml similarity index 100% rename from phpBB/config/twig.yml rename to phpBB/config/services_twig.yml diff --git a/phpBB/config/user.yml b/phpBB/config/services_user.yml similarity index 100% rename from phpBB/config/user.yml rename to phpBB/config/services_user.yml diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 28cc603bdb..2be8e6e860 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -453,11 +453,11 @@ function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_cont if ($debug) { - $config_data .= "@define('DEBUG', true);\n"; + $config_data .= "@define('ENVIRONMENT', 'debug');\n"; } else { - $config_data .= "// @define('DEBUG', true);\n"; + $config_data .= "@define('ENVIRONMENT', 'productive');\n"; } if ($debug_container) diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index ca4fa5c082..d203cc7049 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -50,7 +50,7 @@ class core extends Extension public function load(array $config, ContainerBuilder $container) { $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path))); - $loader->load('services.yml'); + $loader->load('config_' . ENVIRONMENT . '.yml'); } /** From 1a6e1ecf6f96acb7eb3fc0cc6233773ecb5125a8 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 30 May 2014 15:18:11 +0200 Subject: [PATCH 0035/1676] [ticket/12620] Fix tests PHPBB3-12620 --- tests/di/create_container_test.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php index 4ae6017989..c98d3ff6bc 100644 --- a/tests/di/create_container_test.php +++ b/tests/di/create_container_test.php @@ -13,6 +13,8 @@ namespace { + define('ENVIRONMENT', 'productive'); + require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_di_container_test extends \phpbb_test_case From 873260589eaa7ac2d7e520ebe321cb8bb2609ce0 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 30 May 2014 15:29:09 +0200 Subject: [PATCH 0036/1676] [ticket/12620] Display error message when the environment isn't available PHPBB3-12620 --- phpBB/common.php | 23 +++++++++++++++++-- ...config_debug.yml => environment_debug.yml} | 0 ...ductive.yml => environment_productive.yml} | 0 phpBB/phpbb/di/extension/core.php | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) rename phpBB/config/{config_debug.yml => environment_debug.yml} (100%) rename phpBB/config/{config_productive.yml => environment_productive.yml} (100%) diff --git a/phpBB/common.php b/phpBB/common.php index d4549dc2d4..586c2f080f 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -96,11 +96,30 @@ set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handle $phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx); $phpbb_class_loader_ext->register(); +if (ENVIRONMENT == 'debug' && !class_exists('Goutte\Client', true)) +{ + trigger_error( + 'Composer dependencies have not been set up for the development environment yet, run ' . + "'php ../composer.phar install --dev' from the phpBB directory to do so.", + E_USER_ERROR + ); +} phpbb_load_extensions_autoloaders($phpbb_root_path); // Set up container -$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); -$phpbb_container = $phpbb_container_builder->get_container(); +$phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx); +try +{ + $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); + $phpbb_container = $phpbb_container_builder->get_container(); +} +catch (InvalidArgumentException $e) +{ + trigger_error( + 'The requested environment ' . ENVIRONMENT . ' is not available.', + E_USER_ERROR + ); +} $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); diff --git a/phpBB/config/config_debug.yml b/phpBB/config/environment_debug.yml similarity index 100% rename from phpBB/config/config_debug.yml rename to phpBB/config/environment_debug.yml diff --git a/phpBB/config/config_productive.yml b/phpBB/config/environment_productive.yml similarity index 100% rename from phpBB/config/config_productive.yml rename to phpBB/config/environment_productive.yml diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index d203cc7049..5fb8d9ad34 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -50,7 +50,7 @@ class core extends Extension public function load(array $config, ContainerBuilder $container) { $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path))); - $loader->load('config_' . ENVIRONMENT . '.yml'); + $loader->load('environment_' . ENVIRONMENT . '.yml'); } /** From 70201ee8fa084da667b0b1a308d48d2f3c8a541b Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 30 May 2014 15:37:45 +0200 Subject: [PATCH 0037/1676] [ticket/12620] Rename debug to development PHPBB3-12620 --- .../{environment_debug.yml => environment_development.yml} | 0 phpBB/includes/functions_install.php | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename phpBB/config/{environment_debug.yml => environment_development.yml} (100%) diff --git a/phpBB/config/environment_debug.yml b/phpBB/config/environment_development.yml similarity index 100% rename from phpBB/config/environment_debug.yml rename to phpBB/config/environment_development.yml diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 2be8e6e860..1b63414cec 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -453,7 +453,7 @@ function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_cont if ($debug) { - $config_data .= "@define('ENVIRONMENT', 'debug');\n"; + $config_data .= "@define('ENVIRONMENT', 'development');\n"; } else { From 733ae584dd09a0d922fa8f56a0bdc7b3ae359266 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 30 May 2014 15:41:54 +0200 Subject: [PATCH 0038/1676] [ticket/12620] Improve error message PHPBB3-12620 --- phpBB/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/common.php b/phpBB/common.php index 586c2f080f..47c9085d5f 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -99,7 +99,7 @@ $phpbb_class_loader_ext->register(); if (ENVIRONMENT == 'debug' && !class_exists('Goutte\Client', true)) { trigger_error( - 'Composer dependencies have not been set up for the development environment yet, run ' . + 'Composer development dependencies have not been set up for the development environment yet, run ' . "'php ../composer.phar install --dev' from the phpBB directory to do so.", E_USER_ERROR ); From c4842fe119a2947c3d6c34239f83d4d887a39f00 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 30 May 2014 16:18:11 +0200 Subject: [PATCH 0039/1676] [ticket/12620] Fix functional tests PHPBB3-12620 --- phpBB/includes/functions_install.php | 1 + phpBB/install/index.php | 1 + 2 files changed, 2 insertions(+) diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 1b63414cec..4ed44da0b1 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -472,6 +472,7 @@ function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_cont if ($debug_test) { $config_data .= "@define('DEBUG_TEST', true);\n"; + $config_data .= "@define('DEBUG', true);\n"; // Mandatory for the functional tests, will be removed by PHPBB3-12623 } return $config_data; diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 3dd73adc60..00a35b4690 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -16,6 +16,7 @@ */ define('IN_PHPBB', true); define('IN_INSTALL', true); +define('ENVIRONMENT', 'productive'); /**#@-*/ $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../'; From 7fa3b4c6860d85c7616e2182241eefe9515dc8a8 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 30 May 2014 18:33:56 +0200 Subject: [PATCH 0040/1676] [ticket/12620] Rename productive to production PHPBB3-12620 --- phpBB/common.php | 2 +- .../{environment_productive.yml => environment_production.yml} | 0 phpBB/includes/functions_install.php | 2 +- phpBB/install/index.php | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename phpBB/config/{environment_productive.yml => environment_production.yml} (100%) diff --git a/phpBB/common.php b/phpBB/common.php index 47c9085d5f..a1142e4af4 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -31,7 +31,7 @@ extract($phpbb_config_php_file->get_all()); if (!defined('ENVIRONMENT')) { - @define('ENVIRONMENT', 'productive'); + @define('ENVIRONMENT', 'production'); } if (!defined('PHPBB_INSTALLED')) diff --git a/phpBB/config/environment_productive.yml b/phpBB/config/environment_production.yml similarity index 100% rename from phpBB/config/environment_productive.yml rename to phpBB/config/environment_production.yml diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 4ed44da0b1..e0ecda3bfa 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -457,7 +457,7 @@ function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_cont } else { - $config_data .= "@define('ENVIRONMENT', 'productive');\n"; + $config_data .= "@define('ENVIRONMENT', 'production');\n"; } if ($debug_container) diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 00a35b4690..8edc447492 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -16,7 +16,7 @@ */ define('IN_PHPBB', true); define('IN_INSTALL', true); -define('ENVIRONMENT', 'productive'); +define('ENVIRONMENT', 'production'); /**#@-*/ $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../'; From 943e27dffa1ecea1c34e9ae5b11c49186f30e046 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 30 May 2014 22:55:27 +0200 Subject: [PATCH 0041/1676] [ticket/12620] Fix functional tests PHPBB3-12620 --- tests/di/create_container_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php index c98d3ff6bc..2ddbf68f39 100644 --- a/tests/di/create_container_test.php +++ b/tests/di/create_container_test.php @@ -13,7 +13,7 @@ namespace { - define('ENVIRONMENT', 'productive'); + define('ENVIRONMENT', 'production'); require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; From 8664d3229a511eb320fef3df6a852d1a20852dae Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 20 Jun 2014 18:49:19 +0200 Subject: [PATCH 0042/1676] [ticket/12620] Split the environments into differents folders PHPBB3-12620 --- phpBB/config/{ => default}/services.yml | 0 phpBB/config/{ => default}/services_auth.yml | 0 .../default/services_auth_providers.yml | 86 ++++ .../config/{ => default}/services_avatar.yml | 0 phpBB/config/default/services_avatars.yml | 60 +++ .../config/{ => default}/services_captcha.yml | 0 .../config/{ => default}/services_console.yml | 0 .../config/{ => default}/services_content.yml | 0 phpBB/config/{ => default}/services_cron.yml | 0 phpBB/config/default/services_cron_tasks.yml | 125 ++++++ phpBB/config/{ => default}/services_db.yml | 0 phpBB/config/{ => default}/services_event.yml | 0 phpBB/config/{ => default}/services_feed.yml | 0 phpBB/config/default/services_migrator.yml | 60 +++ .../services_mimetype_guesser.yml | 0 .../default/services_mimetype_guessers.yml | 43 ++ .../{ => default}/services_notification.yml | 0 .../config/default/services_notifications.yml | 368 ++++++++++++++++++ .../{ => default}/services_password.yml | 0 phpBB/config/default/services_passwords.yml | 128 ++++++ .../{ => default}/services_profilefield.yml | 0 .../config/default/services_profilefields.yml | 101 +++++ phpBB/config/{ => default}/services_twig.yml | 0 phpBB/config/{ => default}/services_user.yml | 0 phpBB/config/{ => default}/tables.yml | 0 phpBB/config/development/environment.yml | 2 + phpBB/config/environment_development.yml | 2 - phpBB/config/environment_production.yml | 2 - phpBB/config/production/environment.yml | 2 + phpBB/phpbb/di/extension/core.php | 2 +- 30 files changed, 976 insertions(+), 5 deletions(-) rename phpBB/config/{ => default}/services.yml (100%) rename phpBB/config/{ => default}/services_auth.yml (100%) create mode 100644 phpBB/config/default/services_auth_providers.yml rename phpBB/config/{ => default}/services_avatar.yml (100%) create mode 100644 phpBB/config/default/services_avatars.yml rename phpBB/config/{ => default}/services_captcha.yml (100%) rename phpBB/config/{ => default}/services_console.yml (100%) rename phpBB/config/{ => default}/services_content.yml (100%) rename phpBB/config/{ => default}/services_cron.yml (100%) create mode 100644 phpBB/config/default/services_cron_tasks.yml rename phpBB/config/{ => default}/services_db.yml (100%) rename phpBB/config/{ => default}/services_event.yml (100%) rename phpBB/config/{ => default}/services_feed.yml (100%) create mode 100644 phpBB/config/default/services_migrator.yml rename phpBB/config/{ => default}/services_mimetype_guesser.yml (100%) create mode 100644 phpBB/config/default/services_mimetype_guessers.yml rename phpBB/config/{ => default}/services_notification.yml (100%) create mode 100644 phpBB/config/default/services_notifications.yml rename phpBB/config/{ => default}/services_password.yml (100%) create mode 100644 phpBB/config/default/services_passwords.yml rename phpBB/config/{ => default}/services_profilefield.yml (100%) create mode 100644 phpBB/config/default/services_profilefields.yml rename phpBB/config/{ => default}/services_twig.yml (100%) rename phpBB/config/{ => default}/services_user.yml (100%) rename phpBB/config/{ => default}/tables.yml (100%) create mode 100644 phpBB/config/development/environment.yml delete mode 100644 phpBB/config/environment_development.yml delete mode 100644 phpBB/config/environment_production.yml create mode 100644 phpBB/config/production/environment.yml diff --git a/phpBB/config/services.yml b/phpBB/config/default/services.yml similarity index 100% rename from phpBB/config/services.yml rename to phpBB/config/default/services.yml diff --git a/phpBB/config/services_auth.yml b/phpBB/config/default/services_auth.yml similarity index 100% rename from phpBB/config/services_auth.yml rename to phpBB/config/default/services_auth.yml diff --git a/phpBB/config/default/services_auth_providers.yml b/phpBB/config/default/services_auth_providers.yml new file mode 100644 index 0000000000..89303a684a --- /dev/null +++ b/phpBB/config/default/services_auth_providers.yml @@ -0,0 +1,86 @@ +services: + auth.provider_collection: + class: phpbb\auth\provider_collection + arguments: + - @service_container + - @config + tags: + - { name: service_collection, tag: auth.provider } + auth.provider.db: + class: phpbb\auth\provider\db + arguments: + - @dbal.conn + - @config + - @passwords.manager + - @request + - @user + - @service_container + - %core.root_path% + - %core.php_ext% + tags: + - { name: auth.provider } + auth.provider.apache: + class: phpbb\auth\provider\apache + arguments: + - @dbal.conn + - @config + - @passwords.manager + - @request + - @user + - %core.root_path% + - %core.php_ext% + tags: + - { name: auth.provider } + auth.provider.ldap: + class: phpbb\auth\provider\ldap + arguments: + - @dbal.conn + - @config + - @passwords.manager + - @user + tags: + - { name: auth.provider } + auth.provider.oauth: + class: phpbb\auth\provider\oauth\oauth + arguments: + - @dbal.conn + - @config + - @passwords.manager + - @request + - @user + - %tables.auth_provider_oauth_token_storage% + - %tables.auth_provider_oauth_account_assoc% + - @auth.provider.oauth.service_collection + - %tables.users% + - @service_container + - %core.root_path% + - %core.php_ext% + tags: + - { name: auth.provider } + auth.provider.oauth.service_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: auth.provider.oauth.service } + auth.provider.oauth.service.bitly: + class: phpbb\auth\provider\oauth\service\bitly + arguments: + - @config + - @request + tags: + - { name: auth.provider.oauth.service } + auth.provider.oauth.service.facebook: + class: phpbb\auth\provider\oauth\service\facebook + arguments: + - @config + - @request + tags: + - { name: auth.provider.oauth.service } + auth.provider.oauth.service.google: + class: phpbb\auth\provider\oauth\service\google + arguments: + - @config + - @request + tags: + - { name: auth.provider.oauth.service } diff --git a/phpBB/config/services_avatar.yml b/phpBB/config/default/services_avatar.yml similarity index 100% rename from phpBB/config/services_avatar.yml rename to phpBB/config/default/services_avatar.yml diff --git a/phpBB/config/default/services_avatars.yml b/phpBB/config/default/services_avatars.yml new file mode 100644 index 0000000000..8e5b1fdbfe --- /dev/null +++ b/phpBB/config/default/services_avatars.yml @@ -0,0 +1,60 @@ +services: + avatar.driver.gravatar: + class: phpbb\avatar\driver\gravatar + arguments: + - @config + - %core.root_path% + - %core.php_ext% + - @path_helper + - @cache.driver + calls: + - [set_name, [avatar.driver.gravatar]] + tags: + - { name: avatar.driver } + + avatar.driver.local: + class: phpbb\avatar\driver\local + arguments: + - @config + - %core.root_path% + - %core.php_ext% + - @path_helper + - @cache.driver + calls: + - [set_name, [avatar.driver.local]] + tags: + - { name: avatar.driver } + + avatar.driver.remote: + class: phpbb\avatar\driver\remote + arguments: + - @config + - %core.root_path% + - %core.php_ext% + - @path_helper + - @cache.driver + calls: + - [set_name, [avatar.driver.remote]] + tags: + - { name: avatar.driver } + + avatar.driver.upload: + class: phpbb\avatar\driver\upload + arguments: + - @config + - %core.root_path% + - %core.php_ext% + - @path_helper + - @mimetype.guesser + - @cache.driver + calls: + - [set_name, [avatar.driver.upload]] + tags: + - { name: avatar.driver } + + avatar.driver_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: avatar.driver } diff --git a/phpBB/config/services_captcha.yml b/phpBB/config/default/services_captcha.yml similarity index 100% rename from phpBB/config/services_captcha.yml rename to phpBB/config/default/services_captcha.yml diff --git a/phpBB/config/services_console.yml b/phpBB/config/default/services_console.yml similarity index 100% rename from phpBB/config/services_console.yml rename to phpBB/config/default/services_console.yml diff --git a/phpBB/config/services_content.yml b/phpBB/config/default/services_content.yml similarity index 100% rename from phpBB/config/services_content.yml rename to phpBB/config/default/services_content.yml diff --git a/phpBB/config/services_cron.yml b/phpBB/config/default/services_cron.yml similarity index 100% rename from phpBB/config/services_cron.yml rename to phpBB/config/default/services_cron.yml diff --git a/phpBB/config/default/services_cron_tasks.yml b/phpBB/config/default/services_cron_tasks.yml new file mode 100644 index 0000000000..acf9a48bf9 --- /dev/null +++ b/phpBB/config/default/services_cron_tasks.yml @@ -0,0 +1,125 @@ +services: + cron.task.core.prune_all_forums: + class: phpbb\cron\task\core\prune_all_forums + arguments: + - %core.root_path% + - %core.php_ext% + - @config + - @dbal.conn + calls: + - [set_name, [cron.task.core.prune_all_forums]] + tags: + - { name: cron.task } + + cron.task.core.prune_forum: + class: phpbb\cron\task\core\prune_forum + arguments: + - %core.root_path% + - %core.php_ext% + - @config + - @dbal.conn + calls: + - [set_name, [cron.task.core.prune_forum]] + tags: + - { name: cron.task } + + cron.task.core.prune_shadow_topics: + class: phpbb\cron\task\core\prune_shadow_topics + arguments: + - %core.root_path% + - %core.php_ext% + - @config + - @dbal.conn + - @log + - @user + calls: + - [set_name, [cron.task.core.prune_shadow_topics]] + tags: + - { name: cron.task } + + cron.task.core.prune_notifications: + class: phpbb\cron\task\core\prune_notifications + arguments: + - @config + - @notification_manager + calls: + - [set_name, [cron.task.core.prune_notifications]] + tags: + - { name: cron.task } + + cron.task.core.queue: + class: phpbb\cron\task\core\queue + arguments: + - %core.root_path% + - %core.php_ext% + - @config + calls: + - [set_name, [cron.task.core.queue]] + tags: + - { name: cron.task } + + cron.task.core.tidy_cache: + class: phpbb\cron\task\core\tidy_cache + arguments: + - @config + - @cache.driver + calls: + - [set_name, [cron.task.core.tidy_cache]] + tags: + - { name: cron.task } + + cron.task.core.tidy_database: + class: phpbb\cron\task\core\tidy_database + arguments: + - %core.root_path% + - %core.php_ext% + - @config + calls: + - [set_name, [cron.task.core.tidy_database]] + tags: + - { name: cron.task } + + cron.task.core.tidy_plupload: + class: phpbb\cron\task\core\tidy_plupload + arguments: + - %core.root_path% + - @config + calls: + - [set_name, [cron.task.core.tidy_plupload]] + tags: + - { name: cron.task } + + cron.task.core.tidy_search: + class: phpbb\cron\task\core\tidy_search + arguments: + - %core.root_path% + - %core.php_ext% + - @auth + - @config + - @dbal.conn + - @user + calls: + - [set_name, [cron.task.core.tidy_search]] + tags: + - { name: cron.task } + + cron.task.core.tidy_sessions: + class: phpbb\cron\task\core\tidy_sessions + arguments: + - @config + - @user + calls: + - [set_name, [cron.task.core.tidy_sessions]] + tags: + - { name: cron.task } + + cron.task.core.tidy_warnings: + class: phpbb\cron\task\core\tidy_warnings + arguments: + - %core.root_path% + - %core.php_ext% + - @config + calls: + - [set_name, [cron.task.core.tidy_warnings]] + tags: + - { name: cron.task } diff --git a/phpBB/config/services_db.yml b/phpBB/config/default/services_db.yml similarity index 100% rename from phpBB/config/services_db.yml rename to phpBB/config/default/services_db.yml diff --git a/phpBB/config/services_event.yml b/phpBB/config/default/services_event.yml similarity index 100% rename from phpBB/config/services_event.yml rename to phpBB/config/default/services_event.yml diff --git a/phpBB/config/services_feed.yml b/phpBB/config/default/services_feed.yml similarity index 100% rename from phpBB/config/services_feed.yml rename to phpBB/config/default/services_feed.yml diff --git a/phpBB/config/default/services_migrator.yml b/phpBB/config/default/services_migrator.yml new file mode 100644 index 0000000000..cd04eea5c2 --- /dev/null +++ b/phpBB/config/default/services_migrator.yml @@ -0,0 +1,60 @@ +services: + migrator: + class: phpbb\db\migrator + arguments: + - @config + - @dbal.conn + - @dbal.tools + - %tables.migrations% + - %core.root_path% + - %core.php_ext% + - %core.table_prefix% + - @migrator.tool_collection + - @migrator.helper + + migrator.helper: + class: phpbb\db\migration\helper + + migrator.tool_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: migrator.tool } + + migrator.tool.config: + class: phpbb\db\migration\tool\config + arguments: + - @config + tags: + - { name: migrator.tool } + + migrator.tool.config_text: + class: phpbb\db\migration\tool\config_text + arguments: + - @config_text + tags: + - { name: migrator.tool } + + migrator.tool.module: + class: phpbb\db\migration\tool\module + arguments: + - @dbal.conn + - @cache + - @user + - %core.root_path% + - %core.php_ext% + - %tables.modules% + tags: + - { name: migrator.tool } + + migrator.tool.permission: + class: phpbb\db\migration\tool\permission + arguments: + - @dbal.conn + - @cache + - @auth + - %core.root_path% + - %core.php_ext% + tags: + - { name: migrator.tool } diff --git a/phpBB/config/services_mimetype_guesser.yml b/phpBB/config/default/services_mimetype_guesser.yml similarity index 100% rename from phpBB/config/services_mimetype_guesser.yml rename to phpBB/config/default/services_mimetype_guesser.yml diff --git a/phpBB/config/default/services_mimetype_guessers.yml b/phpBB/config/default/services_mimetype_guessers.yml new file mode 100644 index 0000000000..0115146deb --- /dev/null +++ b/phpBB/config/default/services_mimetype_guessers.yml @@ -0,0 +1,43 @@ +parameters: + mimetype.guesser.priority.lowest: -2 + mimetype.guesser.priority.low: -1 + mimetype.guesser.priority.default: 0 + mimetype.guesser.priority.high: 1 + mimetype.guesser.priority.highest: 2 + +services: + mimetype.fileinfo_mimetype_guesser: + class: Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser + tags: + - { name: mimetype.guessers } + + mimetype.filebinary_mimetype_guesser: + class: Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser + tags: + - { name: mimetype.guessers } + + mimetype.content_guesser: + class: phpbb\mimetype\content_guesser + calls: + - [set_priority, [%mimetype.guesser.priority.low%]] + tags: + - { name: mimetype.guessers } + + mimetype.extension_guesser: + class: phpbb\mimetype\extension_guesser + calls: + - [set_priority, [%mimetype.guesser.priority.lowest%]] + tags: + - { name: mimetype.guessers } + + mimetype.guesser_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: mimetype.guessers } + + mimetype.guesser: + class: phpbb\mimetype\guesser + arguments: + - @mimetype.guesser_collection diff --git a/phpBB/config/services_notification.yml b/phpBB/config/default/services_notification.yml similarity index 100% rename from phpBB/config/services_notification.yml rename to phpBB/config/default/services_notification.yml diff --git a/phpBB/config/default/services_notifications.yml b/phpBB/config/default/services_notifications.yml new file mode 100644 index 0000000000..5675e76a99 --- /dev/null +++ b/phpBB/config/default/services_notifications.yml @@ -0,0 +1,368 @@ +services: + notification.type_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: notification.type } + + notification.method_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: notification.method } + + notification.type.approve_post: + class: phpbb\notification\type\approve_post + scope: prototype # scope MUST be prototype for this to work! # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.approve_topic: + class: phpbb\notification\type\approve_topic + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.bookmark: + class: phpbb\notification\type\bookmark + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.disapprove_post: + class: phpbb\notification\type\disapprove_post + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.disapprove_topic: + class: phpbb\notification\type\disapprove_topic + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.group_request: + class: phpbb\notification\type\group_request + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.group_request_approved: + class: phpbb\notification\type\group_request_approved + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.pm: + class: phpbb\notification\type\pm + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.post: + class: phpbb\notification\type\post + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.post_in_queue: + class: phpbb\notification\type\post_in_queue + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.quote: + class: phpbb\notification\type\quote + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.report_pm: + class: phpbb\notification\type\report_pm + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.report_pm_closed: + class: phpbb\notification\type\report_pm_closed + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.report_post: + class: phpbb\notification\type\report_post + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.report_post_closed: + class: phpbb\notification\type\report_post_closed + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.topic: + class: phpbb\notification\type\topic + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.topic_in_queue: + class: phpbb\notification\type\topic_in_queue + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.type.admin_activate_user: + class: phpbb\notification\type\admin_activate_user + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + - %tables.user_notifications% + tags: + - { name: notification.type } + + notification.method.email: + class: phpbb\notification\method\email + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + tags: + - { name: notification.method } + + notification.method.jabber: + class: phpbb\notification\method\jabber + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + tags: + - { name: notification.method } diff --git a/phpBB/config/services_password.yml b/phpBB/config/default/services_password.yml similarity index 100% rename from phpBB/config/services_password.yml rename to phpBB/config/default/services_password.yml diff --git a/phpBB/config/default/services_passwords.yml b/phpBB/config/default/services_passwords.yml new file mode 100644 index 0000000000..3dc217286f --- /dev/null +++ b/phpBB/config/default/services_passwords.yml @@ -0,0 +1,128 @@ +parameters: + passwords.algorithms: + - passwords.driver.bcrypt_2y + - passwords.driver.bcrypt + - passwords.driver.salted_md5 + - passwords.driver.phpass + +services: + passwords.driver.bcrypt: + class: phpbb\passwords\driver\bcrypt + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.bcrypt_2y: + class: phpbb\passwords\driver\bcrypt_2y + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.bcrypt_wcf2: + class: phpbb\passwords\driver\bcrypt_wcf2 + arguments: + - @passwords.driver.bcrypt + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.salted_md5: + class: phpbb\passwords\driver\salted_md5 + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.phpass: + class: phpbb\passwords\driver\phpass + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.convert_password: + class: phpbb\passwords\driver\convert_password + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.sha1_smf: + class: phpbb\passwords\driver\sha1_smf + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.sha1_wcf1: + class: phpbb\passwords\driver\sha1_wcf1 + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.sha1: + class: phpbb\passwords\driver\sha1 + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.md5_phpbb2: + class: phpbb\passwords\driver\md5_phpbb2 + arguments: + - @request + - @passwords.driver.salted_md5 + - %core.root_path% + - %core.php_ext% + tags: + - { name: passwords.driver } + + passwords.driver.md5_mybb: + class: phpbb\passwords\driver\md5_mybb + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.md5_vb: + class: phpbb\passwords\driver\md5_vb + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: passwords.driver } + + passwords.driver_helper: + class: phpbb\passwords\driver\helper + arguments: + - @config + + passwords.manager: + class: phpbb\passwords\manager + arguments: + - @config + - @passwords.driver_collection + - @passwords.helper + - %passwords.algorithms% + + passwords.helper: + class: phpbb\passwords\helper diff --git a/phpBB/config/services_profilefield.yml b/phpBB/config/default/services_profilefield.yml similarity index 100% rename from phpBB/config/services_profilefield.yml rename to phpBB/config/default/services_profilefield.yml diff --git a/phpBB/config/default/services_profilefields.yml b/phpBB/config/default/services_profilefields.yml new file mode 100644 index 0000000000..ce2a84b12b --- /dev/null +++ b/phpBB/config/default/services_profilefields.yml @@ -0,0 +1,101 @@ +services: + profilefields.manager: + class: phpbb\profilefields\manager + arguments: + - @auth + - @dbal.conn + - @dispatcher + - @request + - @template + - @profilefields.type_collection + - @user + - %tables.profile_fields% + - %tables.profile_fields_language% + - %tables.profile_fields_data% + + profilefields.lang_helper: + class: phpbb\profilefields\lang_helper + arguments: + - @dbal.conn + - %tables.profile_fields_options_language% + + profilefields.type_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: profilefield.type } + + profilefields.type.bool: + class: phpbb\profilefields\type\type_bool + arguments: + - @profilefields.lang_helper + - @request + - @template + - @user + tags: + - { name: profilefield.type } + + profilefields.type.date: + class: phpbb\profilefields\type\type_date + arguments: + - @request + - @template + - @user + tags: + - { name: profilefield.type } + + profilefields.type.dropdown: + class: phpbb\profilefields\type\type_dropdown + arguments: + - @profilefields.lang_helper + - @request + - @template + - @user + tags: + - { name: profilefield.type } + + profilefields.type.googleplus: + class: phpbb\profilefields\type\type_googleplus + arguments: + - @request + - @template + - @user + tags: + - { name: profilefield.type } + + profilefields.type.int: + class: phpbb\profilefields\type\type_int + arguments: + - @request + - @template + - @user + tags: + - { name: profilefield.type } + + profilefields.type.string: + class: phpbb\profilefields\type\type_string + arguments: + - @request + - @template + - @user + tags: + - { name: profilefield.type } + + profilefields.type.text: + class: phpbb\profilefields\type\type_text + arguments: + - @request + - @template + - @user + tags: + - { name: profilefield.type } + + profilefields.type.url: + class: phpbb\profilefields\type\type_url + arguments: + - @request + - @template + - @user + tags: + - { name: profilefield.type } diff --git a/phpBB/config/services_twig.yml b/phpBB/config/default/services_twig.yml similarity index 100% rename from phpBB/config/services_twig.yml rename to phpBB/config/default/services_twig.yml diff --git a/phpBB/config/services_user.yml b/phpBB/config/default/services_user.yml similarity index 100% rename from phpBB/config/services_user.yml rename to phpBB/config/default/services_user.yml diff --git a/phpBB/config/tables.yml b/phpBB/config/default/tables.yml similarity index 100% rename from phpBB/config/tables.yml rename to phpBB/config/default/tables.yml diff --git a/phpBB/config/development/environment.yml b/phpBB/config/development/environment.yml new file mode 100644 index 0000000000..6342885067 --- /dev/null +++ b/phpBB/config/development/environment.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../default/services.yml } diff --git a/phpBB/config/environment_development.yml b/phpBB/config/environment_development.yml deleted file mode 100644 index 6982aa4f83..0000000000 --- a/phpBB/config/environment_development.yml +++ /dev/null @@ -1,2 +0,0 @@ -imports: - - { resource: services.yml } diff --git a/phpBB/config/environment_production.yml b/phpBB/config/environment_production.yml deleted file mode 100644 index 6982aa4f83..0000000000 --- a/phpBB/config/environment_production.yml +++ /dev/null @@ -1,2 +0,0 @@ -imports: - - { resource: services.yml } diff --git a/phpBB/config/production/environment.yml b/phpBB/config/production/environment.yml new file mode 100644 index 0000000000..6342885067 --- /dev/null +++ b/phpBB/config/production/environment.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../default/services.yml } diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index 5fb8d9ad34..cff0a1e76e 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -50,7 +50,7 @@ class core extends Extension public function load(array $config, ContainerBuilder $container) { $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path))); - $loader->load('environment_' . ENVIRONMENT . '.yml'); + $loader->load(ENVIRONMENT . '/environment.yml'); } /** From 42c9fd5c76aa6f2757ed3366729b2d0e48c3333d Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 20 Jun 2014 18:56:55 +0200 Subject: [PATCH 0043/1676] [ticket/12620] Add inheritance between environments PHPBB3-12620 --- phpBB/config/default/parameters.yml | 0 phpBB/config/development/environment.yml | 3 ++- phpBB/config/development/parameters.yml | 2 ++ phpBB/config/development/services.yml | 2 ++ phpBB/config/production/environment.yml | 3 ++- phpBB/config/production/parameters.yml | 2 ++ phpBB/config/production/services.yml | 2 ++ 7 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 phpBB/config/default/parameters.yml create mode 100644 phpBB/config/development/parameters.yml create mode 100644 phpBB/config/development/services.yml create mode 100644 phpBB/config/production/parameters.yml create mode 100644 phpBB/config/production/services.yml diff --git a/phpBB/config/default/parameters.yml b/phpBB/config/default/parameters.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/phpBB/config/development/environment.yml b/phpBB/config/development/environment.yml index 6342885067..40a3c7a683 100644 --- a/phpBB/config/development/environment.yml +++ b/phpBB/config/development/environment.yml @@ -1,2 +1,3 @@ imports: - - { resource: ../default/services.yml } + - { resource: services.yml } + - { resource: parameters.yml } diff --git a/phpBB/config/development/parameters.yml b/phpBB/config/development/parameters.yml new file mode 100644 index 0000000000..02743729f9 --- /dev/null +++ b/phpBB/config/development/parameters.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../default/parameters.yml } diff --git a/phpBB/config/development/services.yml b/phpBB/config/development/services.yml new file mode 100644 index 0000000000..6342885067 --- /dev/null +++ b/phpBB/config/development/services.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../default/services.yml } diff --git a/phpBB/config/production/environment.yml b/phpBB/config/production/environment.yml index 6342885067..40a3c7a683 100644 --- a/phpBB/config/production/environment.yml +++ b/phpBB/config/production/environment.yml @@ -1,2 +1,3 @@ imports: - - { resource: ../default/services.yml } + - { resource: services.yml } + - { resource: parameters.yml } diff --git a/phpBB/config/production/parameters.yml b/phpBB/config/production/parameters.yml new file mode 100644 index 0000000000..02743729f9 --- /dev/null +++ b/phpBB/config/production/parameters.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../default/parameters.yml } diff --git a/phpBB/config/production/services.yml b/phpBB/config/production/services.yml new file mode 100644 index 0000000000..6342885067 --- /dev/null +++ b/phpBB/config/production/services.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../default/services.yml } From d2822af6d7fb6e1d8d67d9c8b758ecedb1d67b58 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 9 Aug 2014 16:46:16 +0200 Subject: [PATCH 0044/1676] [ticket/12620] Rebased to the latest develop-ascraeus PHPBB3-12620 --- phpBB/common.php | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/common.php b/phpBB/common.php index a1142e4af4..2332802f30 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -107,7 +107,6 @@ if (ENVIRONMENT == 'debug' && !class_exists('Goutte\Client', true)) phpbb_load_extensions_autoloaders($phpbb_root_path); // Set up container -$phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx); try { $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); From 3f678af5f34d9fd9a635d6ce82bd41285ff71be1 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 10 Aug 2014 12:06:50 +0200 Subject: [PATCH 0045/1676] [ticket/12620] Update tests PHPBB3-12620 --- .../fixtures/config/{services.yml => production/environment.yml} | 0 .../other_config/{services.yml => production/environment.yml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/di/fixtures/config/{services.yml => production/environment.yml} (100%) rename tests/di/fixtures/other_config/{services.yml => production/environment.yml} (100%) diff --git a/tests/di/fixtures/config/services.yml b/tests/di/fixtures/config/production/environment.yml similarity index 100% rename from tests/di/fixtures/config/services.yml rename to tests/di/fixtures/config/production/environment.yml diff --git a/tests/di/fixtures/other_config/services.yml b/tests/di/fixtures/other_config/production/environment.yml similarity index 100% rename from tests/di/fixtures/other_config/services.yml rename to tests/di/fixtures/other_config/production/environment.yml From 143dfa28c62bce5292c9840766f56d9f288980b5 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 15 Aug 2014 19:15:18 +0200 Subject: [PATCH 0046/1676] [ticket/12620] Rebased on develop PHPBB3-12620 --- phpBB/config/default/parameters.yml | 20 ++++++++++++++++++++ phpBB/config/parameters.yml | 20 -------------------- 2 files changed, 20 insertions(+), 20 deletions(-) delete mode 100644 phpBB/config/parameters.yml diff --git a/phpBB/config/default/parameters.yml b/phpBB/config/default/parameters.yml index e69de29bb2..8ecc1428f4 100644 --- a/phpBB/config/default/parameters.yml +++ b/phpBB/config/default/parameters.yml @@ -0,0 +1,20 @@ +parameters: + # Disable the usage of the super globals (_GET, _POST, _SERVER...) + core.disable_super_globals: true + + # Datetime class to use + datetime.class: \phpbb\datetime + + # Mimetype guesser priorities + mimetype.guesser.priority.lowest: -2 + mimetype.guesser.priority.low: -1 + mimetype.guesser.priority.default: 0 + mimetype.guesser.priority.high: 1 + mimetype.guesser.priority.highest: 2 + + # List of default password driver types + passwords.algorithms: + - passwords.driver.bcrypt_2y + - passwords.driver.bcrypt + - passwords.driver.salted_md5 + - passwords.driver.phpass diff --git a/phpBB/config/parameters.yml b/phpBB/config/parameters.yml deleted file mode 100644 index 8ecc1428f4..0000000000 --- a/phpBB/config/parameters.yml +++ /dev/null @@ -1,20 +0,0 @@ -parameters: - # Disable the usage of the super globals (_GET, _POST, _SERVER...) - core.disable_super_globals: true - - # Datetime class to use - datetime.class: \phpbb\datetime - - # Mimetype guesser priorities - mimetype.guesser.priority.lowest: -2 - mimetype.guesser.priority.low: -1 - mimetype.guesser.priority.default: 0 - mimetype.guesser.priority.high: 1 - mimetype.guesser.priority.highest: 2 - - # List of default password driver types - passwords.algorithms: - - passwords.driver.bcrypt_2y - - passwords.driver.bcrypt - - passwords.driver.salted_md5 - - passwords.driver.phpass From b697273aaa53d9f9f4a3d4a53cc6267e906953cd Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 4 Sep 2014 17:06:39 +0200 Subject: [PATCH 0047/1676] [ticket/12620] Use PHPBB_ENVIRONMENT PHPBB3-12620 --- phpBB/common.php | 8 ++++---- phpBB/includes/functions_install.php | 4 ++-- phpBB/install/index.php | 2 +- phpBB/phpbb/di/extension/core.php | 2 +- tests/di/create_container_test.php | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/phpBB/common.php b/phpBB/common.php index 2332802f30..85568ab10e 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -29,9 +29,9 @@ $phpbb_class_loader->register(); $phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx); extract($phpbb_config_php_file->get_all()); -if (!defined('ENVIRONMENT')) +if (!defined('PHPBB_ENVIRONMENT')) { - @define('ENVIRONMENT', 'production'); + @define('PHPBB_ENVIRONMENT', 'production'); } if (!defined('PHPBB_INSTALLED')) @@ -96,7 +96,7 @@ set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handle $phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx); $phpbb_class_loader_ext->register(); -if (ENVIRONMENT == 'debug' && !class_exists('Goutte\Client', true)) +if (PHPBB_ENVIRONMENT == 'debug' && !class_exists('Goutte\Client', true)) { trigger_error( 'Composer development dependencies have not been set up for the development environment yet, run ' . @@ -115,7 +115,7 @@ try catch (InvalidArgumentException $e) { trigger_error( - 'The requested environment ' . ENVIRONMENT . ' is not available.', + 'The requested environment ' . PHPBB_ENVIRONMENT . ' is not available.', E_USER_ERROR ); } diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index e0ecda3bfa..cdd9c7864b 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -453,11 +453,11 @@ function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_cont if ($debug) { - $config_data .= "@define('ENVIRONMENT', 'development');\n"; + $config_data .= "@define('PHPBB_ENVIRONMENT', 'development');\n"; } else { - $config_data .= "@define('ENVIRONMENT', 'production');\n"; + $config_data .= "@define('PHPBB_ENVIRONMENT', 'production');\n"; } if ($debug_container) diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 8edc447492..1cc588071b 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -16,7 +16,7 @@ */ define('IN_PHPBB', true); define('IN_INSTALL', true); -define('ENVIRONMENT', 'production'); +define('PHPBB_ENVIRONMENT', 'production'); /**#@-*/ $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../'; diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index cff0a1e76e..7787602aba 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -50,7 +50,7 @@ class core extends Extension public function load(array $config, ContainerBuilder $container) { $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path))); - $loader->load(ENVIRONMENT . '/environment.yml'); + $loader->load(PHPBB_ENVIRONMENT . '/environment.yml'); } /** diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php index 2ddbf68f39..ecfe504775 100644 --- a/tests/di/create_container_test.php +++ b/tests/di/create_container_test.php @@ -13,7 +13,7 @@ namespace { - define('ENVIRONMENT', 'production'); + define('PHPBB_ENVIRONMENT', 'production'); require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; From 0306fefe04ca987caa1a04bcc105ba76e8d01d9a Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 5 Sep 2014 01:59:55 +0200 Subject: [PATCH 0048/1676] [ticket/12620] Move the routing file to the environments PHPBB3-12620 --- phpBB/config/{ => default}/routing.yml | 0 phpBB/config/development/routing.yml | 2 ++ phpBB/config/production/routing.yml | 2 ++ 3 files changed, 4 insertions(+) rename phpBB/config/{ => default}/routing.yml (100%) create mode 100644 phpBB/config/development/routing.yml create mode 100644 phpBB/config/production/routing.yml diff --git a/phpBB/config/routing.yml b/phpBB/config/default/routing.yml similarity index 100% rename from phpBB/config/routing.yml rename to phpBB/config/default/routing.yml diff --git a/phpBB/config/development/routing.yml b/phpBB/config/development/routing.yml new file mode 100644 index 0000000000..9ee3e5ae3a --- /dev/null +++ b/phpBB/config/development/routing.yml @@ -0,0 +1,2 @@ +core.default: + resource: "../default/routing.yml" diff --git a/phpBB/config/production/routing.yml b/phpBB/config/production/routing.yml new file mode 100644 index 0000000000..9ee3e5ae3a --- /dev/null +++ b/phpBB/config/production/routing.yml @@ -0,0 +1,2 @@ +core.default: + resource: "../default/routing.yml" From 0bf3d2d962c33ffa606d38e91d04665b78fbd8bc Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 5 Sep 2014 02:29:15 +0200 Subject: [PATCH 0049/1676] [ticket/12620] Add the support of the environments for the ext services We look for an environment.yml file in the config/PHPBB_ENVIRONMENT/ directory of the extensionss. If the directory does not exist we look for the environment.yml file in the 'default' environment and finally for the services.yml file in the config/ directory. PHPBB3-12620 --- phpBB/phpbb/di/extension/ext.php | 28 +++++++++++++++++-- tests/di/create_container_test.php | 4 +++ .../environment.yml} | 0 .../config/production/environment.yml | 2 ++ .../ext/vendor/enabled-3/config/services.yml | 2 ++ .../{services.yml => default/environment.yml} | 0 6 files changed, 33 insertions(+), 3 deletions(-) rename tests/di/fixtures/ext/vendor/disabled/config/{services.yml => production/environment.yml} (100%) create mode 100644 tests/di/fixtures/ext/vendor/enabled-2/config/production/environment.yml create mode 100644 tests/di/fixtures/ext/vendor/enabled-3/config/services.yml rename tests/di/fixtures/ext/vendor/enabled/config/{services.yml => default/environment.yml} (100%) diff --git a/phpBB/phpbb/di/extension/ext.php b/phpBB/phpbb/di/extension/ext.php index 718c992d2e..330303ca0c 100644 --- a/phpBB/phpbb/di/extension/ext.php +++ b/phpBB/phpbb/di/extension/ext.php @@ -45,10 +45,32 @@ class ext extends Extension { foreach ($this->paths as $path) { - if (file_exists($path . '/config/services.yml')) + $services_directory = false; + $services_file = false; + + if (file_exists($path . 'config/' . PHPBB_ENVIRONMENT . '/environment.yml')) { - $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($path . '/config'))); - $loader->load('services.yml'); + $services_directory = $path . 'config/' . PHPBB_ENVIRONMENT; + $services_file = 'environment.yml'; + } + else if (!is_dir($path . 'config/' . PHPBB_ENVIRONMENT)) + { + if (file_exists($path . 'config/default/environment.yml')) + { + $services_directory = $path . 'config/default'; + $services_file = 'environment.yml'; + } + else if (!is_dir($path . 'config/default') && file_exists($path . '/config/services.yml')) + { + $services_directory = $path . 'config'; + $services_file = 'services.yml'; + } + } + + if ($services_directory && $services_file) + { + $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($services_directory))); + $loader->load($services_file); } } } diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php index ecfe504775..ec9828debb 100644 --- a/tests/di/create_container_test.php +++ b/tests/di/create_container_test.php @@ -59,6 +59,8 @@ namespace // Checks use_extensions $this->assertTrue($container->hasParameter('enabled')); + $this->assertTrue($container->hasParameter('enabled_2')); + $this->assertTrue($container->hasParameter('enabled_3')); $this->assertFalse($container->hasParameter('disabled')); $this->assertFalse($container->hasParameter('available')); @@ -201,6 +203,8 @@ namespace phpbb\db\driver { return array( array('ext_name' => 'vendor/enabled'), + array('ext_name' => 'vendor/enabled-2'), + array('ext_name' => 'vendor/enabled-3'), ); } } diff --git a/tests/di/fixtures/ext/vendor/disabled/config/services.yml b/tests/di/fixtures/ext/vendor/disabled/config/production/environment.yml similarity index 100% rename from tests/di/fixtures/ext/vendor/disabled/config/services.yml rename to tests/di/fixtures/ext/vendor/disabled/config/production/environment.yml diff --git a/tests/di/fixtures/ext/vendor/enabled-2/config/production/environment.yml b/tests/di/fixtures/ext/vendor/enabled-2/config/production/environment.yml new file mode 100644 index 0000000000..feeb5a7a2d --- /dev/null +++ b/tests/di/fixtures/ext/vendor/enabled-2/config/production/environment.yml @@ -0,0 +1,2 @@ +parameters: + enabled_2: true diff --git a/tests/di/fixtures/ext/vendor/enabled-3/config/services.yml b/tests/di/fixtures/ext/vendor/enabled-3/config/services.yml new file mode 100644 index 0000000000..0dae35d2bd --- /dev/null +++ b/tests/di/fixtures/ext/vendor/enabled-3/config/services.yml @@ -0,0 +1,2 @@ +parameters: + enabled_3: true diff --git a/tests/di/fixtures/ext/vendor/enabled/config/services.yml b/tests/di/fixtures/ext/vendor/enabled/config/default/environment.yml similarity index 100% rename from tests/di/fixtures/ext/vendor/enabled/config/services.yml rename to tests/di/fixtures/ext/vendor/enabled/config/default/environment.yml From 7cd0fd83b8047f40edfb69a427b14997801ef25b Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 5 Sep 2014 03:03:20 +0200 Subject: [PATCH 0050/1676] [ticket/12620] Fix tests PHPBB3-12620 --- tests/bootstrap.php | 2 ++ tests/controller/config/{ => production}/routing.yml | 0 tests/pagination/config/{ => production}/routing.yml | 0 3 files changed, 2 insertions(+) rename tests/controller/config/{ => production}/routing.yml (100%) rename tests/pagination/config/{ => production}/routing.yml (100%) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 0e81f4372a..229a6ee82b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,6 +12,8 @@ */ define('IN_PHPBB', true); +define('PHPBB_ENVIRONMENT', 'production'); + $phpbb_root_path = 'phpBB/'; $phpEx = 'php'; require_once $phpbb_root_path . 'includes/startup.php'; diff --git a/tests/controller/config/routing.yml b/tests/controller/config/production/routing.yml similarity index 100% rename from tests/controller/config/routing.yml rename to tests/controller/config/production/routing.yml diff --git a/tests/pagination/config/routing.yml b/tests/pagination/config/production/routing.yml similarity index 100% rename from tests/pagination/config/routing.yml rename to tests/pagination/config/production/routing.yml From 014eed385bf761d9e3f0992835f44f58bf055afd Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 5 Sep 2014 16:33:57 +0200 Subject: [PATCH 0051/1676] [ticket/12620] Add support of the environments for the ext routing files PHPBB3-12620 --- phpBB/bin/phpbbcli.php | 6 ++++++ phpBB/includes/functions_url_matcher.php | 4 ++-- tests/controller/common_helper_route.php | 6 ------ tests/controller/controller_test.php | 8 ++++++++ .../vendor2/bar/config/production/routing.yml | 3 +++ .../ext/vendor2/bar/config/services.yml | 3 +++ .../controller/ext/vendor2/bar/controller.php | 18 ++++++++++++++++++ 7 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 tests/controller/ext/vendor2/bar/config/production/routing.yml create mode 100644 tests/controller/ext/vendor2/bar/config/services.yml create mode 100644 tests/controller/ext/vendor2/bar/controller.php diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index ca425ad0c4..14681e25ee 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -21,6 +21,12 @@ if (php_sapi_name() != 'cli') } define('IN_PHPBB', true); + +if (!defined('PHPBB_ENVIRONMENT')) +{ + @define('PHPBB_ENVIRONMENT', 'production'); +} + $phpbb_root_path = __DIR__ . '/../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); require($phpbb_root_path . 'includes/startup.' . $phpEx); diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php index b965046aad..3d977a5daf 100644 --- a/phpBB/includes/functions_url_matcher.php +++ b/phpBB/includes/functions_url_matcher.php @@ -58,7 +58,7 @@ function phpbb_get_url_matcher(\phpbb\extension\manager $manager, RequestContext function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $root_path, $php_ext) { $provider = new \phpbb\controller\provider(); - $provider->find_routing_files($manager->get_finder()); + $provider->find_routing_files($manager->all_enabled()); $routes = $provider->find($root_path)->get_routes(); $dumper = new PhpMatcherDumper($routes); $cached_url_matcher_dump = $dumper->dump(array( @@ -78,7 +78,7 @@ function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $roo function phpbb_create_url_matcher(\phpbb\extension\manager $manager, RequestContext $context, $root_path) { $provider = new \phpbb\controller\provider(); - $provider->find_routing_files($manager->get_finder()); + $provider->find_routing_files($manager->all_enabled()); $routes = $provider->find($root_path)->get_routes(); return new UrlMatcher($routes, $context); } diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index 028a73d70d..5baa846ec3 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -113,12 +113,6 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case ) ); - $finder = new \phpbb\finder( - new \phpbb\filesystem(), - dirname(__FILE__) . '/', - new phpbb_mock_cache() - ); - $finder->set_extensions(array_keys($this->extension_manager->all_enabled())); $this->router = new phpbb_mock_router($this->extension_manager, dirname(__FILE__) . '/', 'php'); $this->router->find_routing_files($finder); $this->router->find(dirname(__FILE__) . '/'); diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php index cd90dda751..637e9685e6 100644 --- a/tests/controller/controller_test.php +++ b/tests/controller/controller_test.php @@ -30,6 +30,11 @@ class phpbb_controller_controller_test extends phpbb_test_case 'ext_active' => '1', 'ext_path' => 'ext/vendor2/foo/', ), + 'vendor2/bar' => array( + 'ext_name' => 'vendor2/bar', + 'ext_active' => '1', + 'ext_path' => 'ext/vendor2/bar/', + ), )); } @@ -49,6 +54,9 @@ class phpbb_controller_controller_test extends phpbb_test_case $this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('controller2')); $this->assertEquals('/foo/bar', $routes->get('controller2')->getPath()); + $this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('controller3')); + $this->assertEquals('/bar', $routes->get('controller3')->getPath()); + $this->assertNull($routes->get('controller_noroute')); } diff --git a/tests/controller/ext/vendor2/bar/config/production/routing.yml b/tests/controller/ext/vendor2/bar/config/production/routing.yml new file mode 100644 index 0000000000..85c93b453f --- /dev/null +++ b/tests/controller/ext/vendor2/bar/config/production/routing.yml @@ -0,0 +1,3 @@ +controller3: + pattern: /bar + defaults: { _controller: bar.controller:handle } diff --git a/tests/controller/ext/vendor2/bar/config/services.yml b/tests/controller/ext/vendor2/bar/config/services.yml new file mode 100644 index 0000000000..05a8a1994d --- /dev/null +++ b/tests/controller/ext/vendor2/bar/config/services.yml @@ -0,0 +1,3 @@ +services: + bar.controller: + class: bar\controller diff --git a/tests/controller/ext/vendor2/bar/controller.php b/tests/controller/ext/vendor2/bar/controller.php new file mode 100644 index 0000000000..ad35f5a051 --- /dev/null +++ b/tests/controller/ext/vendor2/bar/controller.php @@ -0,0 +1,18 @@ + Date: Mon, 29 Sep 2014 15:39:15 +0200 Subject: [PATCH 0052/1676] [ticket/12620] Fix download/file.php and app.php outside of the root_path PHPBB3-12620 --- phpBB/download/file.php | 5 +++++ phpBB/includes/functions_url_matcher.php | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/phpBB/download/file.php b/phpBB/download/file.php index 77fb455bc1..4b8309c70e 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -42,6 +42,11 @@ if (isset($_GET['avatar'])) $phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx); extract($phpbb_config_php_file->get_all()); + if (!defined('PHPBB_ENVIRONMENT')) + { + @define('PHPBB_ENVIRONMENT', 'production'); + } + if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type)) { exit; diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php index 3d977a5daf..3bbc1cc924 100644 --- a/phpBB/includes/functions_url_matcher.php +++ b/phpBB/includes/functions_url_matcher.php @@ -57,9 +57,9 @@ function phpbb_get_url_matcher(\phpbb\extension\manager $manager, RequestContext */ function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $root_path, $php_ext) { - $provider = new \phpbb\controller\provider(); + $provider = new \phpbb\controller\provider($root_path); $provider->find_routing_files($manager->all_enabled()); - $routes = $provider->find($root_path)->get_routes(); + $routes = $provider->find()->get_routes(); $dumper = new PhpMatcherDumper($routes); $cached_url_matcher_dump = $dumper->dump(array( 'class' => 'phpbb_url_matcher', @@ -77,9 +77,9 @@ function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $roo */ function phpbb_create_url_matcher(\phpbb\extension\manager $manager, RequestContext $context, $root_path) { - $provider = new \phpbb\controller\provider(); + $provider = new \phpbb\controller\provider($root_path); $provider->find_routing_files($manager->all_enabled()); - $routes = $provider->find($root_path)->get_routes(); + $routes = $provider->find()->get_routes(); return new UrlMatcher($routes, $context); } From aa061aa7c9187009f220e62252a53b49dad7644a Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 29 Sep 2014 16:06:56 +0200 Subject: [PATCH 0053/1676] [ticket/12620] Uses a cache directory per environment PHPBB3-12620 --- phpBB/config/default/services_twig.yml | 2 +- phpBB/includes/functions_url_matcher.php | 33 +++--------- phpBB/phpbb/cache/driver/file.php | 7 ++- phpBB/phpbb/di/container_builder.php | 68 +++++++++++++++++++----- 4 files changed, 69 insertions(+), 41 deletions(-) diff --git a/phpBB/config/default/services_twig.yml b/phpBB/config/default/services_twig.yml index 0745d8b47e..06ce5bc15c 100644 --- a/phpBB/config/default/services_twig.yml +++ b/phpBB/config/default/services_twig.yml @@ -1,5 +1,5 @@ parameters: - core.template.cache_path: %core.root_path%cache/twig/ + core.template.cache_path: %core.root_path%cache/%environment%/twig/ services: template.twig.environment: diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php index 3bbc1cc924..c06f4f6cb1 100644 --- a/phpBB/includes/functions_url_matcher.php +++ b/phpBB/includes/functions_url_matcher.php @@ -11,6 +11,7 @@ * */ +use Symfony\Component\Config\ConfigCache; use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\RequestContext; @@ -34,14 +35,10 @@ if (!defined('IN_PHPBB')) */ function phpbb_get_url_matcher(\phpbb\extension\manager $manager, RequestContext $context, $root_path, $php_ext) { - if (defined('DEBUG')) + $config_cache = new ConfigCache($root_path . 'cache/' . PHPBB_ENVIRONMENT . '/url_matcher.' . $php_ext, defined('DEBUG')); + if (!$config_cache->isFresh()) { - return phpbb_create_url_matcher($manager, $context, $root_path); - } - - if (!phpbb_url_matcher_dumped($root_path, $php_ext)) - { - phpbb_create_dumped_url_matcher($manager, $root_path, $php_ext); + phpbb_create_dumped_url_matcher($manager, $root_path, $config_cache); } return phpbb_load_url_matcher($context, $root_path, $php_ext); @@ -52,10 +49,10 @@ function phpbb_get_url_matcher(\phpbb\extension\manager $manager, RequestContext * * @param \phpbb\extension\manager $manager Extension manager * @param string $root_path Root path -* @param string $php_ext PHP file extension + * @param ConfigCache $config_cache The config cache * @return null */ -function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $root_path, $php_ext) +function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $root_path, $config_cache) { $provider = new \phpbb\controller\provider($root_path); $provider->find_routing_files($manager->all_enabled()); @@ -65,7 +62,7 @@ function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $roo 'class' => 'phpbb_url_matcher', )); - file_put_contents($root_path . 'cache/url_matcher.' . $php_ext, $cached_url_matcher_dump); + $config_cache->write($cached_url_matcher_dump, $routes->getResources()); } /** @@ -93,20 +90,6 @@ function phpbb_create_url_matcher(\phpbb\extension\manager $manager, RequestCont */ function phpbb_load_url_matcher(RequestContext $context, $root_path, $php_ext) { - require($root_path . 'cache/url_matcher.' . $php_ext); + require($root_path . 'cache/' . PHPBB_ENVIRONMENT . '/url_matcher.' . $php_ext); return new phpbb_url_matcher($context); } - -/** -* Determine whether we have our dumped URL matcher -* -* The class is automatically dumped to the cache directory -* -* @param string $root_path Root path -* @param string $php_ext PHP file extension -* @return bool True if it exists, false if not -*/ -function phpbb_url_matcher_dumped($root_path, $php_ext) -{ - return file_exists($root_path . 'cache/url_matcher.' . $php_ext); -} diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php index adfe87b740..d3708fe9a0 100644 --- a/phpBB/phpbb/cache/driver/file.php +++ b/phpBB/phpbb/cache/driver/file.php @@ -28,7 +28,12 @@ class file extends \phpbb\cache\driver\base function __construct($cache_dir = null) { global $phpbb_root_path; - $this->cache_dir = !is_null($cache_dir) ? $cache_dir : $phpbb_root_path . 'cache/'; + $this->cache_dir = !is_null($cache_dir) ? $cache_dir : $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'; + + if (!is_dir($this->cache_dir)) + { + @mkdir($this->cache_dir, 0777, true); + } } /** diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 638c13e86d..b264b0182f 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -13,16 +13,21 @@ namespace phpbb\di; +use Symfony\Component\Config\ConfigCache; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass; class container_builder { - /** @var string phpBB Root Path */ + /** + * @var string phpBB Root Path + */ protected $phpbb_root_path; - /** @var string php file extension */ + /** + * @var string php file extension + */ protected $php_ext; /** @@ -111,6 +116,11 @@ class container_builder */ protected $config_php_file; + /** + * @var string + */ + protected $cache_dir; + /** * Constructor * @@ -133,18 +143,16 @@ class container_builder public function get_container() { $container_filename = $this->get_container_filename(); - if (!defined('DEBUG_CONTAINER') && $this->dump_container && file_exists($container_filename)) + $config_cache = new ConfigCache($container_filename, defined('DEBUG')); + if ($this->dump_container && $config_cache->isFresh()) { require($container_filename); $this->container = new \phpbb_cache_container(); } else { - if ($this->config_path === null) - { - $this->config_path = $this->phpbb_root_path . 'config'; - } - $container_extensions = array(new \phpbb\di\extension\core($this->config_path)); + + $container_extensions = array(new \phpbb\di\extension\core($this->get_config_path())); if ($this->use_extensions) { @@ -178,9 +186,9 @@ class container_builder $this->container->compile(); } - if ($this->dump_container && !defined('DEBUG_CONTAINER')) + if ($this->dump_container) { - $this->dump_container($container_filename); + $this->dump_container($config_cache); } } @@ -266,6 +274,16 @@ class container_builder $this->config_path = $config_path; } + /** + * Returns the path to the container configuration (default: root_path/config) + * + * @return string + */ + protected function get_config_path() + { + return $this->config_path ?: $this->phpbb_root_path . 'config'; + } + /** * Set custom parameters to inject into the container. * @@ -276,12 +294,32 @@ class container_builder $this->custom_parameters = $custom_parameters; } + /** + * Set the path to the cache directory. + * + * @param string $cache_dir Path to the cache directory + */ + public function set_cache_dir($cache_dir) + { + $this->cache_dir = $cache_dir; + } + + /** + * Returns the path to the cache directory (default: root_path/cache/environment). + * + * @return string Path to the cache directory. + */ + protected function get_cache_dir() + { + return $this->cache_dir ?: $this->phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'; + } + /** * Dump the container to the disk. * - * @param string $container_filename The name of the file. + * @param ConfigCache $cache The config cache */ - protected function dump_container($container_filename) + protected function dump_container($cache) { $dumper = new PhpDumper($this->container); $cached_container_dump = $dumper->dump(array( @@ -289,7 +327,7 @@ class container_builder 'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder', )); - file_put_contents($container_filename, $cached_container_dump); + $cache->write($cached_container_dump, $this->container->getResources()); } /** @@ -386,6 +424,8 @@ class container_builder ); } + $this->custom_parameters['environment'] = PHPBB_ENVIRONMENT; + foreach ($this->custom_parameters as $key => $value) { $this->container->setParameter($key, $value); @@ -400,6 +440,6 @@ class container_builder protected function get_container_filename() { $filename = str_replace(array('/', '.'), array('slash', 'dot'), $this->phpbb_root_path); - return $this->phpbb_root_path . 'cache/container_' . $filename . '.' . $this->php_ext; + return $this->get_cache_dir() . 'container_' . $filename . '.' . $this->php_ext; } } From 74cd97e75b1dce43a05d8e15e9fbccf01e833b57 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 2 Oct 2014 00:45:22 +0200 Subject: [PATCH 0054/1676] [ticket/12620] Updates test environment (production => development) PHPBB3-12620 --- tests/bootstrap.php | 2 +- tests/controller/config/{production => development}/routing.yml | 0 .../vendor2/bar/config/{production => development}/routing.yml | 0 .../fixtures/config/{production => development}/environment.yml | 0 .../disabled/config/{production => development}/environment.yml | 0 .../config/{production => development}/environment.yml | 0 .../other_config/{production => development}/environment.yml | 0 tests/pagination/config/{production => development}/routing.yml | 0 8 files changed, 1 insertion(+), 1 deletion(-) rename tests/controller/config/{production => development}/routing.yml (100%) rename tests/controller/ext/vendor2/bar/config/{production => development}/routing.yml (100%) rename tests/di/fixtures/config/{production => development}/environment.yml (100%) rename tests/di/fixtures/ext/vendor/disabled/config/{production => development}/environment.yml (100%) rename tests/di/fixtures/ext/vendor/enabled-2/config/{production => development}/environment.yml (100%) rename tests/di/fixtures/other_config/{production => development}/environment.yml (100%) rename tests/pagination/config/{production => development}/routing.yml (100%) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 229a6ee82b..2fc8858585 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,7 +12,7 @@ */ define('IN_PHPBB', true); -define('PHPBB_ENVIRONMENT', 'production'); +define('PHPBB_ENVIRONMENT', 'development'); $phpbb_root_path = 'phpBB/'; $phpEx = 'php'; diff --git a/tests/controller/config/production/routing.yml b/tests/controller/config/development/routing.yml similarity index 100% rename from tests/controller/config/production/routing.yml rename to tests/controller/config/development/routing.yml diff --git a/tests/controller/ext/vendor2/bar/config/production/routing.yml b/tests/controller/ext/vendor2/bar/config/development/routing.yml similarity index 100% rename from tests/controller/ext/vendor2/bar/config/production/routing.yml rename to tests/controller/ext/vendor2/bar/config/development/routing.yml diff --git a/tests/di/fixtures/config/production/environment.yml b/tests/di/fixtures/config/development/environment.yml similarity index 100% rename from tests/di/fixtures/config/production/environment.yml rename to tests/di/fixtures/config/development/environment.yml diff --git a/tests/di/fixtures/ext/vendor/disabled/config/production/environment.yml b/tests/di/fixtures/ext/vendor/disabled/config/development/environment.yml similarity index 100% rename from tests/di/fixtures/ext/vendor/disabled/config/production/environment.yml rename to tests/di/fixtures/ext/vendor/disabled/config/development/environment.yml diff --git a/tests/di/fixtures/ext/vendor/enabled-2/config/production/environment.yml b/tests/di/fixtures/ext/vendor/enabled-2/config/development/environment.yml similarity index 100% rename from tests/di/fixtures/ext/vendor/enabled-2/config/production/environment.yml rename to tests/di/fixtures/ext/vendor/enabled-2/config/development/environment.yml diff --git a/tests/di/fixtures/other_config/production/environment.yml b/tests/di/fixtures/other_config/development/environment.yml similarity index 100% rename from tests/di/fixtures/other_config/production/environment.yml rename to tests/di/fixtures/other_config/development/environment.yml diff --git a/tests/pagination/config/production/routing.yml b/tests/pagination/config/development/routing.yml similarity index 100% rename from tests/pagination/config/production/routing.yml rename to tests/pagination/config/development/routing.yml From 6cbb60d13f75da6d9b6c6d60555ea119df79b5c0 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 4 Oct 2014 16:30:34 +0200 Subject: [PATCH 0055/1676] [ticket/12620] Adds a yaml config file PHPBB3-12620 --- phpBB/common.php | 8 --- phpBB/config/default/config.yml | 0 .../default/{ => container}/parameters.yml | 0 .../default/{ => container}/services.yml | 0 .../services_auth_providers.yml | 0 .../{ => container}/services_avatars.yml | 0 .../{ => container}/services_captcha.yml | 0 .../{ => container}/services_console.yml | 0 .../{ => container}/services_cron_tasks.yml | 0 .../default/{ => container}/services_feed.yml | 0 .../{ => container}/services_migrator.yml | 0 .../services_mimetype_guessers.yml | 0 .../services_notifications.yml | 0 .../{ => container}/services_passwords.yml | 0 .../services_profilefields.yml | 0 .../default/{ => container}/services_twig.yml | 2 +- .../config/default/{ => container}/tables.yml | 0 phpBB/config/development/config.yml | 5 ++ .../{ => container}/environment.yml | 0 .../development/container/parameters.yml | 2 + .../config/development/container/services.yml | 2 + phpBB/config/development/parameters.yml | 2 - phpBB/config/development/services.yml | 2 - phpBB/config/production/config.yml | 2 + .../{ => container}/environment.yml | 0 .../production/container/parameters.yml | 2 + .../config/production/container/services.yml | 2 + phpBB/config/production/parameters.yml | 2 - phpBB/config/production/services.yml | 2 - phpBB/phpbb/di/container_builder.php | 63 +++++++++++++------ .../di/extension/container_configuration.php | 38 +++++++++++ phpBB/phpbb/di/extension/core.php | 39 ++++++++++-- phpBB/phpbb/di/extension/ext.php | 8 +-- .../{ => container}/environment.yml | 0 .../{ => container}/environment.yml | 0 .../{ => container}/environment.yml | 0 .../default/{ => container}/environment.yml | 0 .../{ => container}/environment.yml | 0 38 files changed, 136 insertions(+), 45 deletions(-) create mode 100644 phpBB/config/default/config.yml rename phpBB/config/default/{ => container}/parameters.yml (100%) rename phpBB/config/default/{ => container}/services.yml (100%) rename phpBB/config/default/{ => container}/services_auth_providers.yml (100%) rename phpBB/config/default/{ => container}/services_avatars.yml (100%) rename phpBB/config/default/{ => container}/services_captcha.yml (100%) rename phpBB/config/default/{ => container}/services_console.yml (100%) rename phpBB/config/default/{ => container}/services_cron_tasks.yml (100%) rename phpBB/config/default/{ => container}/services_feed.yml (100%) rename phpBB/config/default/{ => container}/services_migrator.yml (100%) rename phpBB/config/default/{ => container}/services_mimetype_guessers.yml (100%) rename phpBB/config/default/{ => container}/services_notifications.yml (100%) rename phpBB/config/default/{ => container}/services_passwords.yml (100%) rename phpBB/config/default/{ => container}/services_profilefields.yml (100%) rename phpBB/config/default/{ => container}/services_twig.yml (93%) rename phpBB/config/default/{ => container}/tables.yml (100%) create mode 100644 phpBB/config/development/config.yml rename phpBB/config/development/{ => container}/environment.yml (100%) create mode 100644 phpBB/config/development/container/parameters.yml create mode 100644 phpBB/config/development/container/services.yml delete mode 100644 phpBB/config/development/parameters.yml delete mode 100644 phpBB/config/development/services.yml create mode 100644 phpBB/config/production/config.yml rename phpBB/config/production/{ => container}/environment.yml (100%) create mode 100644 phpBB/config/production/container/parameters.yml create mode 100644 phpBB/config/production/container/services.yml delete mode 100644 phpBB/config/production/parameters.yml delete mode 100644 phpBB/config/production/services.yml create mode 100644 phpBB/phpbb/di/extension/container_configuration.php rename tests/di/fixtures/config/development/{ => container}/environment.yml (100%) rename tests/di/fixtures/ext/vendor/disabled/config/development/{ => container}/environment.yml (100%) rename tests/di/fixtures/ext/vendor/enabled-2/config/development/{ => container}/environment.yml (100%) rename tests/di/fixtures/ext/vendor/enabled/config/default/{ => container}/environment.yml (100%) rename tests/di/fixtures/other_config/development/{ => container}/environment.yml (100%) diff --git a/phpBB/common.php b/phpBB/common.php index 85568ab10e..2fa0c46b22 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -96,14 +96,6 @@ set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handle $phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx); $phpbb_class_loader_ext->register(); -if (PHPBB_ENVIRONMENT == 'debug' && !class_exists('Goutte\Client', true)) -{ - trigger_error( - 'Composer development dependencies have not been set up for the development environment yet, run ' . - "'php ../composer.phar install --dev' from the phpBB directory to do so.", - E_USER_ERROR - ); -} phpbb_load_extensions_autoloaders($phpbb_root_path); // Set up container diff --git a/phpBB/config/default/config.yml b/phpBB/config/default/config.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/phpBB/config/default/parameters.yml b/phpBB/config/default/container/parameters.yml similarity index 100% rename from phpBB/config/default/parameters.yml rename to phpBB/config/default/container/parameters.yml diff --git a/phpBB/config/default/services.yml b/phpBB/config/default/container/services.yml similarity index 100% rename from phpBB/config/default/services.yml rename to phpBB/config/default/container/services.yml diff --git a/phpBB/config/default/services_auth_providers.yml b/phpBB/config/default/container/services_auth_providers.yml similarity index 100% rename from phpBB/config/default/services_auth_providers.yml rename to phpBB/config/default/container/services_auth_providers.yml diff --git a/phpBB/config/default/services_avatars.yml b/phpBB/config/default/container/services_avatars.yml similarity index 100% rename from phpBB/config/default/services_avatars.yml rename to phpBB/config/default/container/services_avatars.yml diff --git a/phpBB/config/default/services_captcha.yml b/phpBB/config/default/container/services_captcha.yml similarity index 100% rename from phpBB/config/default/services_captcha.yml rename to phpBB/config/default/container/services_captcha.yml diff --git a/phpBB/config/default/services_console.yml b/phpBB/config/default/container/services_console.yml similarity index 100% rename from phpBB/config/default/services_console.yml rename to phpBB/config/default/container/services_console.yml diff --git a/phpBB/config/default/services_cron_tasks.yml b/phpBB/config/default/container/services_cron_tasks.yml similarity index 100% rename from phpBB/config/default/services_cron_tasks.yml rename to phpBB/config/default/container/services_cron_tasks.yml diff --git a/phpBB/config/default/services_feed.yml b/phpBB/config/default/container/services_feed.yml similarity index 100% rename from phpBB/config/default/services_feed.yml rename to phpBB/config/default/container/services_feed.yml diff --git a/phpBB/config/default/services_migrator.yml b/phpBB/config/default/container/services_migrator.yml similarity index 100% rename from phpBB/config/default/services_migrator.yml rename to phpBB/config/default/container/services_migrator.yml diff --git a/phpBB/config/default/services_mimetype_guessers.yml b/phpBB/config/default/container/services_mimetype_guessers.yml similarity index 100% rename from phpBB/config/default/services_mimetype_guessers.yml rename to phpBB/config/default/container/services_mimetype_guessers.yml diff --git a/phpBB/config/default/services_notifications.yml b/phpBB/config/default/container/services_notifications.yml similarity index 100% rename from phpBB/config/default/services_notifications.yml rename to phpBB/config/default/container/services_notifications.yml diff --git a/phpBB/config/default/services_passwords.yml b/phpBB/config/default/container/services_passwords.yml similarity index 100% rename from phpBB/config/default/services_passwords.yml rename to phpBB/config/default/container/services_passwords.yml diff --git a/phpBB/config/default/services_profilefields.yml b/phpBB/config/default/container/services_profilefields.yml similarity index 100% rename from phpBB/config/default/services_profilefields.yml rename to phpBB/config/default/container/services_profilefields.yml diff --git a/phpBB/config/default/services_twig.yml b/phpBB/config/default/container/services_twig.yml similarity index 93% rename from phpBB/config/default/services_twig.yml rename to phpBB/config/default/container/services_twig.yml index 06ce5bc15c..fc5f9ba6a1 100644 --- a/phpBB/config/default/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -1,5 +1,5 @@ parameters: - core.template.cache_path: %core.root_path%cache/%environment%/twig/ + core.template.cache_path: %core.root_path%cache/%core.environment%/twig/ services: template.twig.environment: diff --git a/phpBB/config/default/tables.yml b/phpBB/config/default/container/tables.yml similarity index 100% rename from phpBB/config/default/tables.yml rename to phpBB/config/default/container/tables.yml diff --git a/phpBB/config/development/config.yml b/phpBB/config/development/config.yml new file mode 100644 index 0000000000..1c17b08931 --- /dev/null +++ b/phpBB/config/development/config.yml @@ -0,0 +1,5 @@ +imports: + - { resource: ../default/config.yml } + +core: + require_dev_dependencies: true diff --git a/phpBB/config/development/environment.yml b/phpBB/config/development/container/environment.yml similarity index 100% rename from phpBB/config/development/environment.yml rename to phpBB/config/development/container/environment.yml diff --git a/phpBB/config/development/container/parameters.yml b/phpBB/config/development/container/parameters.yml new file mode 100644 index 0000000000..0447646806 --- /dev/null +++ b/phpBB/config/development/container/parameters.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../../default/container/parameters.yml } diff --git a/phpBB/config/development/container/services.yml b/phpBB/config/development/container/services.yml new file mode 100644 index 0000000000..b302f0f966 --- /dev/null +++ b/phpBB/config/development/container/services.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../../default/container/services.yml } diff --git a/phpBB/config/development/parameters.yml b/phpBB/config/development/parameters.yml deleted file mode 100644 index 02743729f9..0000000000 --- a/phpBB/config/development/parameters.yml +++ /dev/null @@ -1,2 +0,0 @@ -imports: - - { resource: ../default/parameters.yml } diff --git a/phpBB/config/development/services.yml b/phpBB/config/development/services.yml deleted file mode 100644 index 6342885067..0000000000 --- a/phpBB/config/development/services.yml +++ /dev/null @@ -1,2 +0,0 @@ -imports: - - { resource: ../default/services.yml } diff --git a/phpBB/config/production/config.yml b/phpBB/config/production/config.yml new file mode 100644 index 0000000000..979dbbcdd9 --- /dev/null +++ b/phpBB/config/production/config.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../default/config.yml } diff --git a/phpBB/config/production/environment.yml b/phpBB/config/production/container/environment.yml similarity index 100% rename from phpBB/config/production/environment.yml rename to phpBB/config/production/container/environment.yml diff --git a/phpBB/config/production/container/parameters.yml b/phpBB/config/production/container/parameters.yml new file mode 100644 index 0000000000..0447646806 --- /dev/null +++ b/phpBB/config/production/container/parameters.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../../default/container/parameters.yml } diff --git a/phpBB/config/production/container/services.yml b/phpBB/config/production/container/services.yml new file mode 100644 index 0000000000..b302f0f966 --- /dev/null +++ b/phpBB/config/production/container/services.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../../default/container/services.yml } diff --git a/phpBB/config/production/parameters.yml b/phpBB/config/production/parameters.yml deleted file mode 100644 index 02743729f9..0000000000 --- a/phpBB/config/production/parameters.yml +++ /dev/null @@ -1,2 +0,0 @@ -imports: - - { resource: ../default/parameters.yml } diff --git a/phpBB/config/production/services.yml b/phpBB/config/production/services.yml deleted file mode 100644 index 6342885067..0000000000 --- a/phpBB/config/production/services.yml +++ /dev/null @@ -1,2 +0,0 @@ -imports: - - { resource: ../default/services.yml } diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index b264b0182f..45dbaaf303 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -14,9 +14,13 @@ namespace phpbb\di; use Symfony\Component\Config\ConfigCache; +use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass; +use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; class container_builder { @@ -151,7 +155,6 @@ class container_builder } else { - $container_extensions = array(new \phpbb\di\extension\core($this->get_config_path())); if ($this->use_extensions) @@ -179,7 +182,8 @@ class container_builder } } - $this->inject_custom_parameters(); + $loader = new YamlFileLoader($this->container, new FileLocator(phpbb_realpath($this->get_config_path()))); + $loader->load(PHPBB_ENVIRONMENT . '/config.yml'); if ($this->compile_container) { @@ -400,36 +404,59 @@ class container_builder */ protected function create_container(array $extensions) { - $container = new ContainerBuilder(); + $container = new ContainerBuilder(new ParameterBag($this->get_core_parameters())); + + $extensions_alias = array(); foreach ($extensions as $extension) { $container->registerExtension($extension); - $container->loadFromExtension($extension->getAlias()); + $extensions_alias[] = $extension->getAlias(); + //$container->loadFromExtension($extension->getAlias()); } + $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions_alias)); + return $container; } /** - * Inject the customs parameters into the container - */ - protected function inject_custom_parameters() + * Returns the core parameters. + * + * @return array An array of core parameters + */ + protected function get_core_parameters() { - if ($this->custom_parameters === null) + return array_merge( + array( + 'core.root_path' => $this->phpbb_root_path, + 'core.php_ext' => $this->php_ext, + 'core.environment' => PHPBB_ENVIRONMENT, + 'core.debug' => DEBUG, + ), + $this->get_env_parameters() + ); + } + + /** + * Gets the environment parameters. + * + * Only the parameters starting with "PHPBB__" are considered. + * + * @return array An array of parameters + */ + protected function get_env_parameters() + { + $parameters = array(); + foreach ($_SERVER as $key => $value) { - $this->custom_parameters = array( - 'core.root_path' => $this->phpbb_root_path, - 'core.php_ext' => $this->php_ext, - ); + if (0 === strpos($key, 'PHPBB__')) + { + $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value; + } } - $this->custom_parameters['environment'] = PHPBB_ENVIRONMENT; - - foreach ($this->custom_parameters as $key => $value) - { - $this->container->setParameter($key, $value); - } + return $parameters; } /** diff --git a/phpBB/phpbb/di/extension/container_configuration.php b/phpBB/phpbb/di/extension/container_configuration.php new file mode 100644 index 0000000000..1f1c077472 --- /dev/null +++ b/phpBB/phpbb/di/extension/container_configuration.php @@ -0,0 +1,38 @@ + +* @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\di\extension; + +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; + +class container_configuration implements ConfigurationInterface +{ + + /** + * Generates the configuration tree builder. + * + * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder + */ + public function getConfigTreeBuilder() + { + $treeBuilder = new TreeBuilder(); + $rootNode = $treeBuilder->root('core'); + $rootNode + ->children() + ->booleanNode('require_dev_dependencies')->defaultValue(false)->end() + ->end() + ; + return $treeBuilder; + } +} diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index 7787602aba..62fcf46ad5 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -13,10 +13,11 @@ namespace phpbb\di\extension; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; -use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; /** * Container core extension @@ -42,15 +43,41 @@ class core extends Extension /** * Loads a specific configuration. * - * @param array $config An array of configuration values + * @param array $configs An array of configuration values * @param ContainerBuilder $container A ContainerBuilder instance * * @throws \InvalidArgumentException When provided tag is not defined in this extension */ - public function load(array $config, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container) { $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path))); - $loader->load(PHPBB_ENVIRONMENT . '/environment.yml'); + $loader->load(PHPBB_ENVIRONMENT . '/container/environment.yml'); + + $config = $this->getConfiguration($configs, $container); + $config = $this->processConfiguration($config, $configs); + + if ($config['require_dev_dependencies']) + { + if (!class_exists('Goutte\Client', true)) + { + trigger_error( + 'Composer development dependencies have not been set up for the ' . $container->getParameter('core.environment') . ' environment yet, run ' . + "'php ../composer.phar install --dev' from the phpBB directory to do so.", + E_USER_ERROR + ); + } + } + } + + /** + * {@inheritdoc} + */ + public function getConfiguration(array $config, ContainerBuilder $container) + { + $r = new \ReflectionClass('\phpbb\di\extension\container_configuration'); + $container->addResource(new FileResource($r->getFileName())); + + return new container_configuration(); } /** diff --git a/phpBB/phpbb/di/extension/ext.php b/phpBB/phpbb/di/extension/ext.php index 330303ca0c..021e862118 100644 --- a/phpBB/phpbb/di/extension/ext.php +++ b/phpBB/phpbb/di/extension/ext.php @@ -48,16 +48,16 @@ class ext extends Extension $services_directory = false; $services_file = false; - if (file_exists($path . 'config/' . PHPBB_ENVIRONMENT . '/environment.yml')) + if (file_exists($path . 'config/' . PHPBB_ENVIRONMENT . '/container/environment.yml')) { - $services_directory = $path . 'config/' . PHPBB_ENVIRONMENT; + $services_directory = $path . 'config/' . PHPBB_ENVIRONMENT . '/container/'; $services_file = 'environment.yml'; } else if (!is_dir($path . 'config/' . PHPBB_ENVIRONMENT)) { - if (file_exists($path . 'config/default/environment.yml')) + if (file_exists($path . 'config/default/container/environment.yml')) { - $services_directory = $path . 'config/default'; + $services_directory = $path . 'config/default/container/'; $services_file = 'environment.yml'; } else if (!is_dir($path . 'config/default') && file_exists($path . '/config/services.yml')) diff --git a/tests/di/fixtures/config/development/environment.yml b/tests/di/fixtures/config/development/container/environment.yml similarity index 100% rename from tests/di/fixtures/config/development/environment.yml rename to tests/di/fixtures/config/development/container/environment.yml diff --git a/tests/di/fixtures/ext/vendor/disabled/config/development/environment.yml b/tests/di/fixtures/ext/vendor/disabled/config/development/container/environment.yml similarity index 100% rename from tests/di/fixtures/ext/vendor/disabled/config/development/environment.yml rename to tests/di/fixtures/ext/vendor/disabled/config/development/container/environment.yml diff --git a/tests/di/fixtures/ext/vendor/enabled-2/config/development/environment.yml b/tests/di/fixtures/ext/vendor/enabled-2/config/development/container/environment.yml similarity index 100% rename from tests/di/fixtures/ext/vendor/enabled-2/config/development/environment.yml rename to tests/di/fixtures/ext/vendor/enabled-2/config/development/container/environment.yml diff --git a/tests/di/fixtures/ext/vendor/enabled/config/default/environment.yml b/tests/di/fixtures/ext/vendor/enabled/config/default/container/environment.yml similarity index 100% rename from tests/di/fixtures/ext/vendor/enabled/config/default/environment.yml rename to tests/di/fixtures/ext/vendor/enabled/config/default/container/environment.yml diff --git a/tests/di/fixtures/other_config/development/environment.yml b/tests/di/fixtures/other_config/development/container/environment.yml similarity index 100% rename from tests/di/fixtures/other_config/development/environment.yml rename to tests/di/fixtures/other_config/development/container/environment.yml From 3a167aa0c3eaec6c4b9d322460480786234e0419 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 4 Oct 2014 17:30:10 +0200 Subject: [PATCH 0056/1676] [ticket/12620] Creates one di extension per phpBB extension PHPBB3-12620 --- phpBB/phpbb/di/container_builder.php | 12 +- phpBB/phpbb/di/extension/ext.php | 89 ------------ phpBB/phpbb/extension/di/extension_base.php | 137 ++++++++++++++++++ .../di/fixtures/config/development/config.yml | 2 + 4 files changed, 150 insertions(+), 90 deletions(-) delete mode 100644 phpBB/phpbb/di/extension/ext.php create mode 100644 phpBB/phpbb/extension/di/extension_base.php create mode 100644 tests/di/fixtures/config/development/config.yml diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 45dbaaf303..5ad9336695 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -160,7 +160,17 @@ class container_builder if ($this->use_extensions) { $installed_exts = $this->get_installed_extensions(); - $container_extensions[] = new \phpbb\di\extension\ext($installed_exts); + foreach ($installed_exts as $ext_name => $path) + { + $extension_class = '\\' . str_replace('/', '\\', $ext_name) . '\\di\extension'; + + if (!class_exists($extension_class)) + { + $extension_class = '\phpbb\extension\di\extension_base'; + } + + $container_extensions[] = new $extension_class($ext_name, $path); + } } if ($this->inject_config) diff --git a/phpBB/phpbb/di/extension/ext.php b/phpBB/phpbb/di/extension/ext.php deleted file mode 100644 index 021e862118..0000000000 --- a/phpBB/phpbb/di/extension/ext.php +++ /dev/null @@ -1,89 +0,0 @@ - -* @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\di\extension; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; -use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; -use Symfony\Component\Config\FileLocator; - -/** -* Container ext extension -*/ -class ext extends Extension -{ - protected $paths = array(); - - public function __construct($enabled_extensions) - { - foreach ($enabled_extensions as $ext => $path) - { - $this->paths[] = $path; - } - } - - /** - * Loads a specific configuration. - * - * @param array $config An array of configuration values - * @param ContainerBuilder $container A ContainerBuilder instance - * - * @throws \InvalidArgumentException When provided tag is not defined in this extension - */ - public function load(array $config, ContainerBuilder $container) - { - foreach ($this->paths as $path) - { - $services_directory = false; - $services_file = false; - - if (file_exists($path . 'config/' . PHPBB_ENVIRONMENT . '/container/environment.yml')) - { - $services_directory = $path . 'config/' . PHPBB_ENVIRONMENT . '/container/'; - $services_file = 'environment.yml'; - } - else if (!is_dir($path . 'config/' . PHPBB_ENVIRONMENT)) - { - if (file_exists($path . 'config/default/container/environment.yml')) - { - $services_directory = $path . 'config/default/container/'; - $services_file = 'environment.yml'; - } - else if (!is_dir($path . 'config/default') && file_exists($path . '/config/services.yml')) - { - $services_directory = $path . 'config'; - $services_file = 'services.yml'; - } - } - - if ($services_directory && $services_file) - { - $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($services_directory))); - $loader->load($services_file); - } - } - } - - /** - * Returns the recommended alias to use in XML. - * - * This alias is also the mandatory prefix to use when using YAML. - * - * @return string The alias - */ - public function getAlias() - { - return 'ext'; - } -} diff --git a/phpBB/phpbb/extension/di/extension_base.php b/phpBB/phpbb/extension/di/extension_base.php new file mode 100644 index 0000000000..74026bd53a --- /dev/null +++ b/phpBB/phpbb/extension/di/extension_base.php @@ -0,0 +1,137 @@ + +* @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\extension\di; + +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; + +/** +* Container core extension +*/ +class extension_base extends Extension +{ + /** + * Name of the extension (vendor/name) + * + * @var string + */ + protected $extension_name; + + /** + * Path to the extension. + * + * @var string + */ + protected $ext_path; + + /** + * Constructor + * + * @param string $extension_name Name of the extension (vendor/name) + * @param string $ext_path Path to the extension + */ + public function __construct($extension_name, $ext_path) + { + $this->extension_name = $extension_name; + $this->ext_path = $ext_path; + } + + /** + * Loads a specific configuration. + * + * @param array $configs An array of configuration values + * @param ContainerBuilder $container A ContainerBuilder instance + * + * @throws \InvalidArgumentException When provided tag is not defined in this extension + */ + public function load(array $configs, ContainerBuilder $container) + { + $this->load_services($container); + } + + /** + * Loads the services.yml file. + * + * @param ContainerBuilder $container A ContainerBuilder instance + */ + protected function load_services(ContainerBuilder $container) + { + $services_directory = false; + $services_file = false; + + if (file_exists($this->ext_path . 'config/' . $container->getParameter('core.environment') . '/container/environment.yml')) + { + $services_directory = $this->ext_path . 'config/' . $container->getParameter('core.environment') . '/container/'; + $services_file = 'environment.yml'; + } + else if (!is_dir($this->ext_path . 'config/' . $container->getParameter('core.environment'))) + { + if (file_exists($this->ext_path . 'config/default/container/environment.yml')) + { + $services_directory = $this->ext_path . 'config/default/container/'; + $services_file = 'environment.yml'; + } + else if (!is_dir($this->ext_path . 'config/default') && file_exists($this->ext_path . '/config/services.yml')) + { + $services_directory = $this->ext_path . 'config'; + $services_file = 'services.yml'; + } + } + + if ($services_directory && $services_file) + { + $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($services_directory))); + $loader->load($services_file); + } + } + + /** + * {@inheritdoc} + */ + public function getConfiguration(array $config, ContainerBuilder $container) + { + $reflected = new \ReflectionClass($this); + $namespace = $reflected->getNamespaceName(); + + $class = $namespace . '\\di\configuration'; + if (class_exists($class)) + { + $r = new \ReflectionClass($class); + $container->addResource(new FileResource($r->getFileName())); + + if (!method_exists($class, '__construct')) + { + $configuration = new $class(); + + return $configuration; + } + } + + } + + /** + * Returns the recommended alias to use in XML. + * + * This alias is also the mandatory prefix to use when using YAML. + * + * @return string The alias + */ + public function getAlias() + { + return str_replace('/', '_', $this->extension_name); + } +} diff --git a/tests/di/fixtures/config/development/config.yml b/tests/di/fixtures/config/development/config.yml new file mode 100644 index 0000000000..fcfa84f68b --- /dev/null +++ b/tests/di/fixtures/config/development/config.yml @@ -0,0 +1,2 @@ +core: + require_dev_dependencies: true From 0b61e3540de353f2bf0a6904a87727e4efe9c5fa Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 4 Oct 2014 17:47:36 +0200 Subject: [PATCH 0057/1676] [ticket/12620] Fix tests PHPBB3-12620 --- phpBB/phpbb/di/container_builder.php | 16 ++++++++++++++++ tests/di/create_container_test.php | 1 - .../fixtures/other_config/development/config.yml | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/di/fixtures/other_config/development/config.yml diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 5ad9336695..6216dad978 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -195,6 +195,8 @@ class container_builder $loader = new YamlFileLoader($this->container, new FileLocator(phpbb_realpath($this->get_config_path()))); $loader->load(PHPBB_ENVIRONMENT . '/config.yml'); + $this->inject_custom_parameters(); + if ($this->compile_container) { $this->container->compile(); @@ -430,6 +432,20 @@ class container_builder return $container; } + /** + * Inject the customs parameters into the container + */ + protected function inject_custom_parameters() + { + if ($this->custom_parameters !== null) + { + foreach ($this->custom_parameters as $key => $value) + { + $this->container->setParameter($key, $value); + } + } + } + /** * Returns the core parameters. * diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php index ec9828debb..4e47751999 100644 --- a/tests/di/create_container_test.php +++ b/tests/di/create_container_test.php @@ -146,7 +146,6 @@ namespace $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); $this->assertTrue($container->hasParameter('my_parameter')); - $this->assertFalse($container->hasParameter('core.root_path')); } } } diff --git a/tests/di/fixtures/other_config/development/config.yml b/tests/di/fixtures/other_config/development/config.yml new file mode 100644 index 0000000000..fcfa84f68b --- /dev/null +++ b/tests/di/fixtures/other_config/development/config.yml @@ -0,0 +1,2 @@ +core: + require_dev_dependencies: true From c98efc53a80150b6f9189c9b194855c748e9b03d Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 7 Nov 2014 14:27:00 +0100 Subject: [PATCH 0058/1676] [ticket/12620] Fix rebase (move config file to the right directory) PHPBB3-12620 --- .../default/{ => container}/services_auth.yml | 0 .../container/services_auth_providers.yml | 86 ---- .../{ => container}/services_avatar.yml | 0 .../default/container/services_avatars.yml | 60 --- .../{ => container}/services_content.yml | 0 .../default/{ => container}/services_cron.yml | 0 .../default/container/services_cron_tasks.yml | 125 ------ .../default/{ => container}/services_db.yml | 0 .../{ => container}/services_event.yml | 0 .../services_mimetype_guesser.yml | 0 .../container/services_mimetype_guessers.yml | 43 -- .../{ => container}/services_notification.yml | 0 .../container/services_notifications.yml | 368 ------------------ .../{ => container}/services_password.yml | 0 .../default/container/services_passwords.yml | 128 ------ .../{ => container}/services_profilefield.yml | 0 .../container/services_profilefields.yml | 101 ----- .../default/{ => container}/services_user.yml | 0 18 files changed, 911 deletions(-) rename phpBB/config/default/{ => container}/services_auth.yml (100%) delete mode 100644 phpBB/config/default/container/services_auth_providers.yml rename phpBB/config/default/{ => container}/services_avatar.yml (100%) delete mode 100644 phpBB/config/default/container/services_avatars.yml rename phpBB/config/default/{ => container}/services_content.yml (100%) rename phpBB/config/default/{ => container}/services_cron.yml (100%) delete mode 100644 phpBB/config/default/container/services_cron_tasks.yml rename phpBB/config/default/{ => container}/services_db.yml (100%) rename phpBB/config/default/{ => container}/services_event.yml (100%) rename phpBB/config/default/{ => container}/services_mimetype_guesser.yml (100%) delete mode 100644 phpBB/config/default/container/services_mimetype_guessers.yml rename phpBB/config/default/{ => container}/services_notification.yml (100%) delete mode 100644 phpBB/config/default/container/services_notifications.yml rename phpBB/config/default/{ => container}/services_password.yml (100%) delete mode 100644 phpBB/config/default/container/services_passwords.yml rename phpBB/config/default/{ => container}/services_profilefield.yml (100%) delete mode 100644 phpBB/config/default/container/services_profilefields.yml rename phpBB/config/default/{ => container}/services_user.yml (100%) diff --git a/phpBB/config/default/services_auth.yml b/phpBB/config/default/container/services_auth.yml similarity index 100% rename from phpBB/config/default/services_auth.yml rename to phpBB/config/default/container/services_auth.yml diff --git a/phpBB/config/default/container/services_auth_providers.yml b/phpBB/config/default/container/services_auth_providers.yml deleted file mode 100644 index 89303a684a..0000000000 --- a/phpBB/config/default/container/services_auth_providers.yml +++ /dev/null @@ -1,86 +0,0 @@ -services: - auth.provider_collection: - class: phpbb\auth\provider_collection - arguments: - - @service_container - - @config - tags: - - { name: service_collection, tag: auth.provider } - auth.provider.db: - class: phpbb\auth\provider\db - arguments: - - @dbal.conn - - @config - - @passwords.manager - - @request - - @user - - @service_container - - %core.root_path% - - %core.php_ext% - tags: - - { name: auth.provider } - auth.provider.apache: - class: phpbb\auth\provider\apache - arguments: - - @dbal.conn - - @config - - @passwords.manager - - @request - - @user - - %core.root_path% - - %core.php_ext% - tags: - - { name: auth.provider } - auth.provider.ldap: - class: phpbb\auth\provider\ldap - arguments: - - @dbal.conn - - @config - - @passwords.manager - - @user - tags: - - { name: auth.provider } - auth.provider.oauth: - class: phpbb\auth\provider\oauth\oauth - arguments: - - @dbal.conn - - @config - - @passwords.manager - - @request - - @user - - %tables.auth_provider_oauth_token_storage% - - %tables.auth_provider_oauth_account_assoc% - - @auth.provider.oauth.service_collection - - %tables.users% - - @service_container - - %core.root_path% - - %core.php_ext% - tags: - - { name: auth.provider } - auth.provider.oauth.service_collection: - class: phpbb\di\service_collection - arguments: - - @service_container - tags: - - { name: service_collection, tag: auth.provider.oauth.service } - auth.provider.oauth.service.bitly: - class: phpbb\auth\provider\oauth\service\bitly - arguments: - - @config - - @request - tags: - - { name: auth.provider.oauth.service } - auth.provider.oauth.service.facebook: - class: phpbb\auth\provider\oauth\service\facebook - arguments: - - @config - - @request - tags: - - { name: auth.provider.oauth.service } - auth.provider.oauth.service.google: - class: phpbb\auth\provider\oauth\service\google - arguments: - - @config - - @request - tags: - - { name: auth.provider.oauth.service } diff --git a/phpBB/config/default/services_avatar.yml b/phpBB/config/default/container/services_avatar.yml similarity index 100% rename from phpBB/config/default/services_avatar.yml rename to phpBB/config/default/container/services_avatar.yml diff --git a/phpBB/config/default/container/services_avatars.yml b/phpBB/config/default/container/services_avatars.yml deleted file mode 100644 index 8e5b1fdbfe..0000000000 --- a/phpBB/config/default/container/services_avatars.yml +++ /dev/null @@ -1,60 +0,0 @@ -services: - avatar.driver.gravatar: - class: phpbb\avatar\driver\gravatar - arguments: - - @config - - %core.root_path% - - %core.php_ext% - - @path_helper - - @cache.driver - calls: - - [set_name, [avatar.driver.gravatar]] - tags: - - { name: avatar.driver } - - avatar.driver.local: - class: phpbb\avatar\driver\local - arguments: - - @config - - %core.root_path% - - %core.php_ext% - - @path_helper - - @cache.driver - calls: - - [set_name, [avatar.driver.local]] - tags: - - { name: avatar.driver } - - avatar.driver.remote: - class: phpbb\avatar\driver\remote - arguments: - - @config - - %core.root_path% - - %core.php_ext% - - @path_helper - - @cache.driver - calls: - - [set_name, [avatar.driver.remote]] - tags: - - { name: avatar.driver } - - avatar.driver.upload: - class: phpbb\avatar\driver\upload - arguments: - - @config - - %core.root_path% - - %core.php_ext% - - @path_helper - - @mimetype.guesser - - @cache.driver - calls: - - [set_name, [avatar.driver.upload]] - tags: - - { name: avatar.driver } - - avatar.driver_collection: - class: phpbb\di\service_collection - arguments: - - @service_container - tags: - - { name: service_collection, tag: avatar.driver } diff --git a/phpBB/config/default/services_content.yml b/phpBB/config/default/container/services_content.yml similarity index 100% rename from phpBB/config/default/services_content.yml rename to phpBB/config/default/container/services_content.yml diff --git a/phpBB/config/default/services_cron.yml b/phpBB/config/default/container/services_cron.yml similarity index 100% rename from phpBB/config/default/services_cron.yml rename to phpBB/config/default/container/services_cron.yml diff --git a/phpBB/config/default/container/services_cron_tasks.yml b/phpBB/config/default/container/services_cron_tasks.yml deleted file mode 100644 index acf9a48bf9..0000000000 --- a/phpBB/config/default/container/services_cron_tasks.yml +++ /dev/null @@ -1,125 +0,0 @@ -services: - cron.task.core.prune_all_forums: - class: phpbb\cron\task\core\prune_all_forums - arguments: - - %core.root_path% - - %core.php_ext% - - @config - - @dbal.conn - calls: - - [set_name, [cron.task.core.prune_all_forums]] - tags: - - { name: cron.task } - - cron.task.core.prune_forum: - class: phpbb\cron\task\core\prune_forum - arguments: - - %core.root_path% - - %core.php_ext% - - @config - - @dbal.conn - calls: - - [set_name, [cron.task.core.prune_forum]] - tags: - - { name: cron.task } - - cron.task.core.prune_shadow_topics: - class: phpbb\cron\task\core\prune_shadow_topics - arguments: - - %core.root_path% - - %core.php_ext% - - @config - - @dbal.conn - - @log - - @user - calls: - - [set_name, [cron.task.core.prune_shadow_topics]] - tags: - - { name: cron.task } - - cron.task.core.prune_notifications: - class: phpbb\cron\task\core\prune_notifications - arguments: - - @config - - @notification_manager - calls: - - [set_name, [cron.task.core.prune_notifications]] - tags: - - { name: cron.task } - - cron.task.core.queue: - class: phpbb\cron\task\core\queue - arguments: - - %core.root_path% - - %core.php_ext% - - @config - calls: - - [set_name, [cron.task.core.queue]] - tags: - - { name: cron.task } - - cron.task.core.tidy_cache: - class: phpbb\cron\task\core\tidy_cache - arguments: - - @config - - @cache.driver - calls: - - [set_name, [cron.task.core.tidy_cache]] - tags: - - { name: cron.task } - - cron.task.core.tidy_database: - class: phpbb\cron\task\core\tidy_database - arguments: - - %core.root_path% - - %core.php_ext% - - @config - calls: - - [set_name, [cron.task.core.tidy_database]] - tags: - - { name: cron.task } - - cron.task.core.tidy_plupload: - class: phpbb\cron\task\core\tidy_plupload - arguments: - - %core.root_path% - - @config - calls: - - [set_name, [cron.task.core.tidy_plupload]] - tags: - - { name: cron.task } - - cron.task.core.tidy_search: - class: phpbb\cron\task\core\tidy_search - arguments: - - %core.root_path% - - %core.php_ext% - - @auth - - @config - - @dbal.conn - - @user - calls: - - [set_name, [cron.task.core.tidy_search]] - tags: - - { name: cron.task } - - cron.task.core.tidy_sessions: - class: phpbb\cron\task\core\tidy_sessions - arguments: - - @config - - @user - calls: - - [set_name, [cron.task.core.tidy_sessions]] - tags: - - { name: cron.task } - - cron.task.core.tidy_warnings: - class: phpbb\cron\task\core\tidy_warnings - arguments: - - %core.root_path% - - %core.php_ext% - - @config - calls: - - [set_name, [cron.task.core.tidy_warnings]] - tags: - - { name: cron.task } diff --git a/phpBB/config/default/services_db.yml b/phpBB/config/default/container/services_db.yml similarity index 100% rename from phpBB/config/default/services_db.yml rename to phpBB/config/default/container/services_db.yml diff --git a/phpBB/config/default/services_event.yml b/phpBB/config/default/container/services_event.yml similarity index 100% rename from phpBB/config/default/services_event.yml rename to phpBB/config/default/container/services_event.yml diff --git a/phpBB/config/default/services_mimetype_guesser.yml b/phpBB/config/default/container/services_mimetype_guesser.yml similarity index 100% rename from phpBB/config/default/services_mimetype_guesser.yml rename to phpBB/config/default/container/services_mimetype_guesser.yml diff --git a/phpBB/config/default/container/services_mimetype_guessers.yml b/phpBB/config/default/container/services_mimetype_guessers.yml deleted file mode 100644 index 0115146deb..0000000000 --- a/phpBB/config/default/container/services_mimetype_guessers.yml +++ /dev/null @@ -1,43 +0,0 @@ -parameters: - mimetype.guesser.priority.lowest: -2 - mimetype.guesser.priority.low: -1 - mimetype.guesser.priority.default: 0 - mimetype.guesser.priority.high: 1 - mimetype.guesser.priority.highest: 2 - -services: - mimetype.fileinfo_mimetype_guesser: - class: Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser - tags: - - { name: mimetype.guessers } - - mimetype.filebinary_mimetype_guesser: - class: Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser - tags: - - { name: mimetype.guessers } - - mimetype.content_guesser: - class: phpbb\mimetype\content_guesser - calls: - - [set_priority, [%mimetype.guesser.priority.low%]] - tags: - - { name: mimetype.guessers } - - mimetype.extension_guesser: - class: phpbb\mimetype\extension_guesser - calls: - - [set_priority, [%mimetype.guesser.priority.lowest%]] - tags: - - { name: mimetype.guessers } - - mimetype.guesser_collection: - class: phpbb\di\service_collection - arguments: - - @service_container - tags: - - { name: service_collection, tag: mimetype.guessers } - - mimetype.guesser: - class: phpbb\mimetype\guesser - arguments: - - @mimetype.guesser_collection diff --git a/phpBB/config/default/services_notification.yml b/phpBB/config/default/container/services_notification.yml similarity index 100% rename from phpBB/config/default/services_notification.yml rename to phpBB/config/default/container/services_notification.yml diff --git a/phpBB/config/default/container/services_notifications.yml b/phpBB/config/default/container/services_notifications.yml deleted file mode 100644 index 5675e76a99..0000000000 --- a/phpBB/config/default/container/services_notifications.yml +++ /dev/null @@ -1,368 +0,0 @@ -services: - notification.type_collection: - class: phpbb\di\service_collection - arguments: - - @service_container - tags: - - { name: service_collection, tag: notification.type } - - notification.method_collection: - class: phpbb\di\service_collection - arguments: - - @service_container - tags: - - { name: service_collection, tag: notification.method } - - notification.type.approve_post: - class: phpbb\notification\type\approve_post - scope: prototype # scope MUST be prototype for this to work! # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.approve_topic: - class: phpbb\notification\type\approve_topic - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.bookmark: - class: phpbb\notification\type\bookmark - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.disapprove_post: - class: phpbb\notification\type\disapprove_post - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.disapprove_topic: - class: phpbb\notification\type\disapprove_topic - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.group_request: - class: phpbb\notification\type\group_request - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.group_request_approved: - class: phpbb\notification\type\group_request_approved - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.pm: - class: phpbb\notification\type\pm - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.post: - class: phpbb\notification\type\post - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.post_in_queue: - class: phpbb\notification\type\post_in_queue - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.quote: - class: phpbb\notification\type\quote - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.report_pm: - class: phpbb\notification\type\report_pm - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.report_pm_closed: - class: phpbb\notification\type\report_pm_closed - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.report_post: - class: phpbb\notification\type\report_post - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.report_post_closed: - class: phpbb\notification\type\report_post_closed - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.topic: - class: phpbb\notification\type\topic - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.topic_in_queue: - class: phpbb\notification\type\topic_in_queue - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.admin_activate_user: - class: phpbb\notification\type\admin_activate_user - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.notifications% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.method.email: - class: phpbb\notification\method\email - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - tags: - - { name: notification.method } - - notification.method.jabber: - class: phpbb\notification\method\jabber - scope: prototype # scope MUST be prototype for this to work! - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - tags: - - { name: notification.method } diff --git a/phpBB/config/default/services_password.yml b/phpBB/config/default/container/services_password.yml similarity index 100% rename from phpBB/config/default/services_password.yml rename to phpBB/config/default/container/services_password.yml diff --git a/phpBB/config/default/container/services_passwords.yml b/phpBB/config/default/container/services_passwords.yml deleted file mode 100644 index 3dc217286f..0000000000 --- a/phpBB/config/default/container/services_passwords.yml +++ /dev/null @@ -1,128 +0,0 @@ -parameters: - passwords.algorithms: - - passwords.driver.bcrypt_2y - - passwords.driver.bcrypt - - passwords.driver.salted_md5 - - passwords.driver.phpass - -services: - passwords.driver.bcrypt: - class: phpbb\passwords\driver\bcrypt - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.bcrypt_2y: - class: phpbb\passwords\driver\bcrypt_2y - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.bcrypt_wcf2: - class: phpbb\passwords\driver\bcrypt_wcf2 - arguments: - - @passwords.driver.bcrypt - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.salted_md5: - class: phpbb\passwords\driver\salted_md5 - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.phpass: - class: phpbb\passwords\driver\phpass - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.convert_password: - class: phpbb\passwords\driver\convert_password - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.sha1_smf: - class: phpbb\passwords\driver\sha1_smf - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.sha1_wcf1: - class: phpbb\passwords\driver\sha1_wcf1 - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.sha1: - class: phpbb\passwords\driver\sha1 - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.md5_phpbb2: - class: phpbb\passwords\driver\md5_phpbb2 - arguments: - - @request - - @passwords.driver.salted_md5 - - %core.root_path% - - %core.php_ext% - tags: - - { name: passwords.driver } - - passwords.driver.md5_mybb: - class: phpbb\passwords\driver\md5_mybb - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver.md5_vb: - class: phpbb\passwords\driver\md5_vb - arguments: - - @config - - @passwords.driver_helper - tags: - - { name: passwords.driver } - - passwords.driver_collection: - class: phpbb\di\service_collection - arguments: - - @service_container - tags: - - { name: service_collection, tag: passwords.driver } - - passwords.driver_helper: - class: phpbb\passwords\driver\helper - arguments: - - @config - - passwords.manager: - class: phpbb\passwords\manager - arguments: - - @config - - @passwords.driver_collection - - @passwords.helper - - %passwords.algorithms% - - passwords.helper: - class: phpbb\passwords\helper diff --git a/phpBB/config/default/services_profilefield.yml b/phpBB/config/default/container/services_profilefield.yml similarity index 100% rename from phpBB/config/default/services_profilefield.yml rename to phpBB/config/default/container/services_profilefield.yml diff --git a/phpBB/config/default/container/services_profilefields.yml b/phpBB/config/default/container/services_profilefields.yml deleted file mode 100644 index ce2a84b12b..0000000000 --- a/phpBB/config/default/container/services_profilefields.yml +++ /dev/null @@ -1,101 +0,0 @@ -services: - profilefields.manager: - class: phpbb\profilefields\manager - arguments: - - @auth - - @dbal.conn - - @dispatcher - - @request - - @template - - @profilefields.type_collection - - @user - - %tables.profile_fields% - - %tables.profile_fields_language% - - %tables.profile_fields_data% - - profilefields.lang_helper: - class: phpbb\profilefields\lang_helper - arguments: - - @dbal.conn - - %tables.profile_fields_options_language% - - profilefields.type_collection: - class: phpbb\di\service_collection - arguments: - - @service_container - tags: - - { name: service_collection, tag: profilefield.type } - - profilefields.type.bool: - class: phpbb\profilefields\type\type_bool - arguments: - - @profilefields.lang_helper - - @request - - @template - - @user - tags: - - { name: profilefield.type } - - profilefields.type.date: - class: phpbb\profilefields\type\type_date - arguments: - - @request - - @template - - @user - tags: - - { name: profilefield.type } - - profilefields.type.dropdown: - class: phpbb\profilefields\type\type_dropdown - arguments: - - @profilefields.lang_helper - - @request - - @template - - @user - tags: - - { name: profilefield.type } - - profilefields.type.googleplus: - class: phpbb\profilefields\type\type_googleplus - arguments: - - @request - - @template - - @user - tags: - - { name: profilefield.type } - - profilefields.type.int: - class: phpbb\profilefields\type\type_int - arguments: - - @request - - @template - - @user - tags: - - { name: profilefield.type } - - profilefields.type.string: - class: phpbb\profilefields\type\type_string - arguments: - - @request - - @template - - @user - tags: - - { name: profilefield.type } - - profilefields.type.text: - class: phpbb\profilefields\type\type_text - arguments: - - @request - - @template - - @user - tags: - - { name: profilefield.type } - - profilefields.type.url: - class: phpbb\profilefields\type\type_url - arguments: - - @request - - @template - - @user - tags: - - { name: profilefield.type } diff --git a/phpBB/config/default/services_user.yml b/phpBB/config/default/container/services_user.yml similarity index 100% rename from phpBB/config/default/services_user.yml rename to phpBB/config/default/container/services_user.yml From acc91a2bbf28656d4a6917b457ba3dd6b4e02e37 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 11 Nov 2014 17:59:41 +0100 Subject: [PATCH 0059/1676] [ticket/12620] Use the container to get the environment name PHPBB3-12620 --- phpBB/includes/functions_url_matcher.php | 8 ++++++-- phpBB/phpbb/cache/driver/file.php | 5 +++-- phpBB/phpbb/di/container_builder.php | 16 +++++++++++++--- phpBB/phpbb/di/extension/core.php | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php index c06f4f6cb1..4f5ead6253 100644 --- a/phpBB/includes/functions_url_matcher.php +++ b/phpBB/includes/functions_url_matcher.php @@ -35,7 +35,9 @@ if (!defined('IN_PHPBB')) */ function phpbb_get_url_matcher(\phpbb\extension\manager $manager, RequestContext $context, $root_path, $php_ext) { - $config_cache = new ConfigCache($root_path . 'cache/' . PHPBB_ENVIRONMENT . '/url_matcher.' . $php_ext, defined('DEBUG')); + global $phpbb_container; + + $config_cache = new ConfigCache($root_path . 'cache/' . $phpbb_container->getParameter('core.environment') . '/url_matcher.' . $php_ext, defined('DEBUG')); if (!$config_cache->isFresh()) { phpbb_create_dumped_url_matcher($manager, $root_path, $config_cache); @@ -90,6 +92,8 @@ function phpbb_create_url_matcher(\phpbb\extension\manager $manager, RequestCont */ function phpbb_load_url_matcher(RequestContext $context, $root_path, $php_ext) { - require($root_path . 'cache/' . PHPBB_ENVIRONMENT . '/url_matcher.' . $php_ext); + global $phpbb_container; + + require($root_path . 'cache/' . $phpbb_container->getParameter('core.environment') . '/url_matcher.' . $php_ext); return new phpbb_url_matcher($context); } diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php index d3708fe9a0..114959c06c 100644 --- a/phpBB/phpbb/cache/driver/file.php +++ b/phpBB/phpbb/cache/driver/file.php @@ -27,8 +27,9 @@ class file extends \phpbb\cache\driver\base */ function __construct($cache_dir = null) { - global $phpbb_root_path; - $this->cache_dir = !is_null($cache_dir) ? $cache_dir : $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'; + global $phpbb_root_path, $phpbb_container; + + $this->cache_dir = !is_null($cache_dir) ? $cache_dir : $phpbb_root_path . 'cache/' . $phpbb_container->getParameter('core.environment') . '/'; if (!is_dir($this->cache_dir)) { diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 6216dad978..c665c8444c 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -193,7 +193,7 @@ class container_builder } $loader = new YamlFileLoader($this->container, new FileLocator(phpbb_realpath($this->get_config_path()))); - $loader->load(PHPBB_ENVIRONMENT . '/config.yml'); + $loader->load($this->container->getParameter('core.environment') . '/config.yml'); $this->inject_custom_parameters(); @@ -327,7 +327,7 @@ class container_builder */ protected function get_cache_dir() { - return $this->cache_dir ?: $this->phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'; + return $this->cache_dir ?: $this->phpbb_root_path . 'cache/' . $this->get_environment() . '/'; } /** @@ -457,7 +457,7 @@ class container_builder array( 'core.root_path' => $this->phpbb_root_path, 'core.php_ext' => $this->php_ext, - 'core.environment' => PHPBB_ENVIRONMENT, + 'core.environment' => $this->get_environment(), 'core.debug' => DEBUG, ), $this->get_env_parameters() @@ -495,4 +495,14 @@ class container_builder $filename = str_replace(array('/', '.'), array('slash', 'dot'), $this->phpbb_root_path); return $this->get_cache_dir() . 'container_' . $filename . '.' . $this->php_ext; } + + /** + * Return the name of the current environment. + * + * @return string + */ + protected function get_environment() + { + return PHPBB_ENVIRONMENT; + } } diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index 62fcf46ad5..ce0d4a869c 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -51,7 +51,7 @@ class core extends Extension public function load(array $configs, ContainerBuilder $container) { $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path))); - $loader->load(PHPBB_ENVIRONMENT . '/container/environment.yml'); + $loader->load($container->getParameter('core.environment') . '/container/environment.yml'); $config = $this->getConfiguration($configs, $container); $config = $this->processConfiguration($config, $configs); From 0a1db77ea85116adf24f9d3f0b92a44f818a107f Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 11 Nov 2014 19:10:43 +0100 Subject: [PATCH 0060/1676] [ticket/12620] Add a test using a custom DI extension in an extension PHPBB3-12620 --- phpBB/phpbb/di/container_builder.php | 2 +- tests/di/create_container_test.php | 3 ++ .../ext/vendor/enabled_4/di/extension.php | 31 +++++++++++++++++++ .../ext/vendor/enabled_4/environment.yml | 2 ++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/di/fixtures/ext/vendor/enabled_4/di/extension.php create mode 100644 tests/di/fixtures/ext/vendor/enabled_4/environment.yml diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index c665c8444c..62bba5baf9 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -162,7 +162,7 @@ class container_builder $installed_exts = $this->get_installed_extensions(); foreach ($installed_exts as $ext_name => $path) { - $extension_class = '\\' . str_replace('/', '\\', $ext_name) . '\\di\extension'; + $extension_class = '\\' . str_replace('/', '\\', $ext_name) . '\\di\\extension'; if (!class_exists($extension_class)) { diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php index 4e47751999..9cc714db40 100644 --- a/tests/di/create_container_test.php +++ b/tests/di/create_container_test.php @@ -16,6 +16,7 @@ namespace define('PHPBB_ENVIRONMENT', 'production'); require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + require_once dirname(__FILE__) . '/fixtures/ext/vendor/enabled_4/di/extension.php'; class phpbb_di_container_test extends \phpbb_test_case { @@ -61,6 +62,7 @@ namespace $this->assertTrue($container->hasParameter('enabled')); $this->assertTrue($container->hasParameter('enabled_2')); $this->assertTrue($container->hasParameter('enabled_3')); + $this->assertTrue($container->hasParameter('enabled_4')); $this->assertFalse($container->hasParameter('disabled')); $this->assertFalse($container->hasParameter('available')); @@ -204,6 +206,7 @@ namespace phpbb\db\driver array('ext_name' => 'vendor/enabled'), array('ext_name' => 'vendor/enabled-2'), array('ext_name' => 'vendor/enabled-3'), + array('ext_name' => 'vendor/enabled_4'), ); } } diff --git a/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php b/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php new file mode 100644 index 0000000000..8342625687 --- /dev/null +++ b/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php @@ -0,0 +1,31 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace vendor\enabled_4\di; + +use phpbb\extension\di\extension_base; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + +/** +* Container core extension +*/ +class extension extends extension_base +{ + protected function load_services(ContainerBuilder $container) + { + $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->ext_path))); + $loader->load('environment.yml'); + } +} diff --git a/tests/di/fixtures/ext/vendor/enabled_4/environment.yml b/tests/di/fixtures/ext/vendor/enabled_4/environment.yml new file mode 100644 index 0000000000..d0affe4fd6 --- /dev/null +++ b/tests/di/fixtures/ext/vendor/enabled_4/environment.yml @@ -0,0 +1,2 @@ +parameters: + enabled_4: true From 6019e51fedbb90f84a17155f1076af9aec37b65b Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 16 Nov 2014 17:28:44 +0100 Subject: [PATCH 0061/1676] [ticket/12620] Fix coding style PHPBB3-12620 --- phpBB/includes/functions_url_matcher.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php index 4f5ead6253..448f1b19a2 100644 --- a/phpBB/includes/functions_url_matcher.php +++ b/phpBB/includes/functions_url_matcher.php @@ -50,8 +50,7 @@ function phpbb_get_url_matcher(\phpbb\extension\manager $manager, RequestContext * Create a new UrlMatcher class and dump it into the cache file * * @param \phpbb\extension\manager $manager Extension manager -* @param string $root_path Root path - * @param ConfigCache $config_cache The config cache +* @param string $root_path Root path* @param ConfigCache $config_cache The config cache * @return null */ function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $root_path, $config_cache) From 91daa736639fca67b2d330d0f20aabbd55eec2cf Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 19 Nov 2014 18:08:31 +0100 Subject: [PATCH 0062/1676] [ticket/12620] Fix session tests PHPBB3-12620 --- tests/session/testable_factory.php | 1 + tests/test_framework/phpbb_functional_test_case.php | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php index 3e25286480..505eb7006f 100644 --- a/tests/session/testable_factory.php +++ b/tests/session/testable_factory.php @@ -96,6 +96,7 @@ class phpbb_session_testable_factory 'auth.provider.db', new phpbb_mock_auth_provider() ); + $phpbb_container->setParameter('core.environment', PHPBB_ENVIRONMENT); $provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config); $provider_collection->add('auth.provider.db'); $phpbb_container->set( diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index cdb3d01524..9391795e32 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -204,6 +204,11 @@ class phpbb_functional_test_case extends phpbb_test_case { if (!$this->cache) { + global $phpbb_container; + + $phpbb_container = new phpbb_mock_container_builder(); + $phpbb_container->setParameter('core.environment', PHPBB_ENVIRONMENT); + $this->cache = new \phpbb\cache\driver\file; } From dd4f2387fd2f4df0e1513c251c9044f5bef60618 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 19 Nov 2014 19:50:07 +0100 Subject: [PATCH 0063/1676] [ticket/12620] Use the test environment for the tests PHPBB3-12620 --- build/build.xml | 2 ++ phpBB/config/test/config.yml | 5 +++++ phpBB/config/test/container/environment.yml | 3 +++ phpBB/config/test/container/parameters.yml | 2 ++ phpBB/config/test/container/services.yml | 2 ++ phpBB/config/test/routing.yml | 2 ++ tests/bootstrap.php | 2 +- tests/controller/config/{development => test}/routing.yml | 0 .../ext/vendor2/bar/config/{development => test}/routing.yml | 0 tests/di/create_container_test.php | 2 -- tests/di/fixtures/config/{development => test}/config.yml | 0 .../config/{development => test}/container/environment.yml | 0 .../config/{development => test}/container/environment.yml | 0 .../config/{development => test}/container/environment.yml | 0 .../fixtures/other_config/{development => test}/config.yml | 0 .../{development => test}/container/environment.yml | 0 tests/pagination/config/{development => test}/routing.yml | 0 17 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 phpBB/config/test/config.yml create mode 100644 phpBB/config/test/container/environment.yml create mode 100644 phpBB/config/test/container/parameters.yml create mode 100644 phpBB/config/test/container/services.yml create mode 100644 phpBB/config/test/routing.yml rename tests/controller/config/{development => test}/routing.yml (100%) rename tests/controller/ext/vendor2/bar/config/{development => test}/routing.yml (100%) rename tests/di/fixtures/config/{development => test}/config.yml (100%) rename tests/di/fixtures/config/{development => test}/container/environment.yml (100%) rename tests/di/fixtures/ext/vendor/disabled/config/{development => test}/container/environment.yml (100%) rename tests/di/fixtures/ext/vendor/enabled-2/config/{development => test}/container/environment.yml (100%) rename tests/di/fixtures/other_config/{development => test}/config.yml (100%) rename tests/di/fixtures/other_config/{development => test}/container/environment.yml (100%) rename tests/pagination/config/{development => test}/routing.yml (100%) diff --git a/build/build.xml b/build/build.xml index 5d143886af..16798f0e97 100644 --- a/build/build.xml +++ b/build/build.xml @@ -283,6 +283,8 @@ + + diff --git a/phpBB/config/test/config.yml b/phpBB/config/test/config.yml new file mode 100644 index 0000000000..1c17b08931 --- /dev/null +++ b/phpBB/config/test/config.yml @@ -0,0 +1,5 @@ +imports: + - { resource: ../default/config.yml } + +core: + require_dev_dependencies: true diff --git a/phpBB/config/test/container/environment.yml b/phpBB/config/test/container/environment.yml new file mode 100644 index 0000000000..40a3c7a683 --- /dev/null +++ b/phpBB/config/test/container/environment.yml @@ -0,0 +1,3 @@ +imports: + - { resource: services.yml } + - { resource: parameters.yml } diff --git a/phpBB/config/test/container/parameters.yml b/phpBB/config/test/container/parameters.yml new file mode 100644 index 0000000000..0447646806 --- /dev/null +++ b/phpBB/config/test/container/parameters.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../../default/container/parameters.yml } diff --git a/phpBB/config/test/container/services.yml b/phpBB/config/test/container/services.yml new file mode 100644 index 0000000000..b302f0f966 --- /dev/null +++ b/phpBB/config/test/container/services.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../../default/container/services.yml } diff --git a/phpBB/config/test/routing.yml b/phpBB/config/test/routing.yml new file mode 100644 index 0000000000..9ee3e5ae3a --- /dev/null +++ b/phpBB/config/test/routing.yml @@ -0,0 +1,2 @@ +core.default: + resource: "../default/routing.yml" diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 2fc8858585..ace48ea035 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,7 +12,7 @@ */ define('IN_PHPBB', true); -define('PHPBB_ENVIRONMENT', 'development'); +define('PHPBB_ENVIRONMENT', 'test'); $phpbb_root_path = 'phpBB/'; $phpEx = 'php'; diff --git a/tests/controller/config/development/routing.yml b/tests/controller/config/test/routing.yml similarity index 100% rename from tests/controller/config/development/routing.yml rename to tests/controller/config/test/routing.yml diff --git a/tests/controller/ext/vendor2/bar/config/development/routing.yml b/tests/controller/ext/vendor2/bar/config/test/routing.yml similarity index 100% rename from tests/controller/ext/vendor2/bar/config/development/routing.yml rename to tests/controller/ext/vendor2/bar/config/test/routing.yml diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php index 9cc714db40..d52fb6b085 100644 --- a/tests/di/create_container_test.php +++ b/tests/di/create_container_test.php @@ -13,8 +13,6 @@ namespace { - define('PHPBB_ENVIRONMENT', 'production'); - require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; require_once dirname(__FILE__) . '/fixtures/ext/vendor/enabled_4/di/extension.php'; diff --git a/tests/di/fixtures/config/development/config.yml b/tests/di/fixtures/config/test/config.yml similarity index 100% rename from tests/di/fixtures/config/development/config.yml rename to tests/di/fixtures/config/test/config.yml diff --git a/tests/di/fixtures/config/development/container/environment.yml b/tests/di/fixtures/config/test/container/environment.yml similarity index 100% rename from tests/di/fixtures/config/development/container/environment.yml rename to tests/di/fixtures/config/test/container/environment.yml diff --git a/tests/di/fixtures/ext/vendor/disabled/config/development/container/environment.yml b/tests/di/fixtures/ext/vendor/disabled/config/test/container/environment.yml similarity index 100% rename from tests/di/fixtures/ext/vendor/disabled/config/development/container/environment.yml rename to tests/di/fixtures/ext/vendor/disabled/config/test/container/environment.yml diff --git a/tests/di/fixtures/ext/vendor/enabled-2/config/development/container/environment.yml b/tests/di/fixtures/ext/vendor/enabled-2/config/test/container/environment.yml similarity index 100% rename from tests/di/fixtures/ext/vendor/enabled-2/config/development/container/environment.yml rename to tests/di/fixtures/ext/vendor/enabled-2/config/test/container/environment.yml diff --git a/tests/di/fixtures/other_config/development/config.yml b/tests/di/fixtures/other_config/test/config.yml similarity index 100% rename from tests/di/fixtures/other_config/development/config.yml rename to tests/di/fixtures/other_config/test/config.yml diff --git a/tests/di/fixtures/other_config/development/container/environment.yml b/tests/di/fixtures/other_config/test/container/environment.yml similarity index 100% rename from tests/di/fixtures/other_config/development/container/environment.yml rename to tests/di/fixtures/other_config/test/container/environment.yml diff --git a/tests/pagination/config/development/routing.yml b/tests/pagination/config/test/routing.yml similarity index 100% rename from tests/pagination/config/development/routing.yml rename to tests/pagination/config/test/routing.yml From ac0ff219c61bd187dd3fbde5b6808624bd8ef077 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 19 Nov 2014 20:04:00 +0100 Subject: [PATCH 0064/1676] [ticket/12620] Move the routing.yml file to routing/environment.yml PHPBB3-12620 --- phpBB/config/default/{ => routing}/routing.yml | 0 phpBB/config/development/{routing.yml => routing/environment.yml} | 0 phpBB/config/production/{routing.yml => routing/environment.yml} | 0 phpBB/config/test/{routing.yml => routing/environment.yml} | 0 .../config/test/{routing.yml => routing/environment.yml} | 0 .../bar/config/test/{routing.yml => routing/environment.yml} | 0 .../config/test/{routing.yml => routing/environment.yml} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename phpBB/config/default/{ => routing}/routing.yml (100%) rename phpBB/config/development/{routing.yml => routing/environment.yml} (100%) rename phpBB/config/production/{routing.yml => routing/environment.yml} (100%) rename phpBB/config/test/{routing.yml => routing/environment.yml} (100%) rename tests/controller/config/test/{routing.yml => routing/environment.yml} (100%) rename tests/controller/ext/vendor2/bar/config/test/{routing.yml => routing/environment.yml} (100%) rename tests/pagination/config/test/{routing.yml => routing/environment.yml} (100%) diff --git a/phpBB/config/default/routing.yml b/phpBB/config/default/routing/routing.yml similarity index 100% rename from phpBB/config/default/routing.yml rename to phpBB/config/default/routing/routing.yml diff --git a/phpBB/config/development/routing.yml b/phpBB/config/development/routing/environment.yml similarity index 100% rename from phpBB/config/development/routing.yml rename to phpBB/config/development/routing/environment.yml diff --git a/phpBB/config/production/routing.yml b/phpBB/config/production/routing/environment.yml similarity index 100% rename from phpBB/config/production/routing.yml rename to phpBB/config/production/routing/environment.yml diff --git a/phpBB/config/test/routing.yml b/phpBB/config/test/routing/environment.yml similarity index 100% rename from phpBB/config/test/routing.yml rename to phpBB/config/test/routing/environment.yml diff --git a/tests/controller/config/test/routing.yml b/tests/controller/config/test/routing/environment.yml similarity index 100% rename from tests/controller/config/test/routing.yml rename to tests/controller/config/test/routing/environment.yml diff --git a/tests/controller/ext/vendor2/bar/config/test/routing.yml b/tests/controller/ext/vendor2/bar/config/test/routing/environment.yml similarity index 100% rename from tests/controller/ext/vendor2/bar/config/test/routing.yml rename to tests/controller/ext/vendor2/bar/config/test/routing/environment.yml diff --git a/tests/pagination/config/test/routing.yml b/tests/pagination/config/test/routing/environment.yml similarity index 100% rename from tests/pagination/config/test/routing.yml rename to tests/pagination/config/test/routing/environment.yml From 48950be82bca0c85347f5aa1585de44c369780c6 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 19 Nov 2014 20:54:14 +0100 Subject: [PATCH 0065/1676] [ticket/12620] Fix tests PHPBB3-12620 --- phpBB/config/development/routing/environment.yml | 2 +- phpBB/config/production/routing/environment.yml | 2 +- phpBB/config/test/routing/environment.yml | 2 +- phpBB/includes/functions_install.php | 10 +--------- phpBB/includes/functions_url_matcher.php | 8 ++++++-- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/phpBB/config/development/routing/environment.yml b/phpBB/config/development/routing/environment.yml index 9ee3e5ae3a..0cddfb7521 100644 --- a/phpBB/config/development/routing/environment.yml +++ b/phpBB/config/development/routing/environment.yml @@ -1,2 +1,2 @@ core.default: - resource: "../default/routing.yml" + resource: "../../default/routing/routing.yml" diff --git a/phpBB/config/production/routing/environment.yml b/phpBB/config/production/routing/environment.yml index 9ee3e5ae3a..0cddfb7521 100644 --- a/phpBB/config/production/routing/environment.yml +++ b/phpBB/config/production/routing/environment.yml @@ -1,2 +1,2 @@ core.default: - resource: "../default/routing.yml" + resource: "../../default/routing/routing.yml" diff --git a/phpBB/config/test/routing/environment.yml b/phpBB/config/test/routing/environment.yml index 9ee3e5ae3a..0cddfb7521 100644 --- a/phpBB/config/test/routing/environment.yml +++ b/phpBB/config/test/routing/environment.yml @@ -1,2 +1,2 @@ core.default: - resource: "../default/routing.yml" + resource: "../../default/routing/routing.yml" diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index cdd9c7864b..ef4e3166e3 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -450,15 +450,7 @@ function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_cont $config_data .= "\n@define('PHPBB_INSTALLED', true);\n"; $config_data .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n"; - - if ($debug) - { - $config_data .= "@define('PHPBB_ENVIRONMENT', 'development');\n"; - } - else - { - $config_data .= "@define('PHPBB_ENVIRONMENT', 'production');\n"; - } + $config_data .= "@define('PHPBB_ENVIRONMENT', 'test');\n"; if ($debug_container) { diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php index 448f1b19a2..19aebd1fbc 100644 --- a/phpBB/includes/functions_url_matcher.php +++ b/phpBB/includes/functions_url_matcher.php @@ -55,7 +55,9 @@ function phpbb_get_url_matcher(\phpbb\extension\manager $manager, RequestContext */ function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $root_path, $config_cache) { - $provider = new \phpbb\controller\provider($root_path); + global $phpbb_container; + + $provider = new \phpbb\controller\provider($phpbb_container->getParameter('core.environment'), $root_path); $provider->find_routing_files($manager->all_enabled()); $routes = $provider->find()->get_routes(); $dumper = new PhpMatcherDumper($routes); @@ -75,7 +77,9 @@ function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $roo */ function phpbb_create_url_matcher(\phpbb\extension\manager $manager, RequestContext $context, $root_path) { - $provider = new \phpbb\controller\provider($root_path); + global $phpbb_container; + + $provider = new \phpbb\controller\provider($phpbb_container->getParameter('core.environment'), $root_path); $provider->find_routing_files($manager->all_enabled()); $routes = $provider->find()->get_routes(); return new UrlMatcher($routes, $context); From 93f61a4a7d34f8ad565bdc1605784284994ecdfc Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 20 Nov 2014 18:38:32 +0100 Subject: [PATCH 0066/1676] [ticket/12620] Use the right environment while installing PHPBB3-12620 --- phpBB/includes/functions_install.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index ef4e3166e3..a60ddd40c5 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -450,7 +450,19 @@ function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_cont $config_data .= "\n@define('PHPBB_INSTALLED', true);\n"; $config_data .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n"; - $config_data .= "@define('PHPBB_ENVIRONMENT', 'test');\n"; + + if ($debug_test) + { + $config_data .= "@define('PHPBB_ENVIRONMENT', 'test');\n"; + } + else if ($debug) + { + $config_data .= "@define('PHPBB_ENVIRONMENT', 'development');\n"; + } + else + { + $config_data .= "@define('PHPBB_ENVIRONMENT', 'production');\n"; + } if ($debug_container) { From 677b5b2cd4937ee6c777728082084c661223dee8 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 20 Nov 2014 22:40:37 +0100 Subject: [PATCH 0067/1676] [ticket/12620] Fix rebase PHPBB3-12620 --- phpBB/config/default/container/services.yml | 1 + phpBB/phpbb/controller/helper.php | 5 +- phpBB/phpbb/di/container_builder.php | 2 +- phpBB/phpbb/di/extension/core.php | 40 ++--- phpBB/phpbb/extension/di/extension_base.php | 4 +- phpBB/phpbb/routing/router.php | 180 +++++++++++--------- tests/avatar/driver/barfoo.php | 52 +++--- tests/avatar/driver/foobar.php | 52 +++--- tests/controller/common_helper_route.php | 6 +- tests/controller/controller_test.php | 4 +- tests/pagination/pagination_test.php | 10 +- 11 files changed, 188 insertions(+), 168 deletions(-) diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 3f36a5178a..6cf9180cc0 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -157,6 +157,7 @@ services: - @ext.manager - %core.root_path% - %core.php_ext% + - %core.environment% router.listener: class: Symfony\Component\HttpKernel\EventListener\RouterListener diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index cc327882e0..2bc8e6b9d0 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -41,8 +41,9 @@ class helper protected $config; /** - * @var \phpbb\routing\router phpBB router - */ + * phpBB router + * @var \phpbb\routing\router + */ protected $router; /* @var \phpbb\symfony_request */ diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 62bba5baf9..125ae28e9b 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -19,7 +19,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass; +use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; class container_builder diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index ce0d4a869c..72d46fb05b 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -25,29 +25,29 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension; class core extends Extension { /** - * Config path - * @var string - */ + * Config path + * @var string + */ protected $config_path; /** - * Constructor - * - * @param string $config_path Config path - */ + * Constructor + * + * @param string $config_path Config path + */ public function __construct($config_path) { $this->config_path = $config_path; } /** - * Loads a specific configuration. - * - * @param array $configs An array of configuration values - * @param ContainerBuilder $container A ContainerBuilder instance - * - * @throws \InvalidArgumentException When provided tag is not defined in this extension - */ + * Loads a specific configuration. + * + * @param array $configs An array of configuration values + * @param ContainerBuilder $container A ContainerBuilder instance + * + * @throws \InvalidArgumentException When provided tag is not defined in this extension + */ public function load(array $configs, ContainerBuilder $container) { $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path))); @@ -81,12 +81,12 @@ class core extends Extension } /** - * Returns the recommended alias to use in XML. - * - * This alias is also the mandatory prefix to use when using YAML. - * - * @return string The alias - */ + * Returns the recommended alias to use in XML. + * + * This alias is also the mandatory prefix to use when using YAML. + * + * @return string The alias + */ public function getAlias() { return 'core'; diff --git a/phpBB/phpbb/extension/di/extension_base.php b/phpBB/phpbb/extension/di/extension_base.php index 74026bd53a..30cc37dbb6 100644 --- a/phpBB/phpbb/extension/di/extension_base.php +++ b/phpBB/phpbb/extension/di/extension_base.php @@ -20,8 +20,8 @@ use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\HttpKernel\DependencyInjection\Extension; /** -* Container core extension -*/ + * Container core extension + */ class extension_base extends Extension { /** diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index f721837bba..0617e94c93 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -25,95 +25,119 @@ use Symfony\Component\Config\FileLocator; use phpbb\extension\manager; /** -* Integration of all pieces of the routing system for easier use. -*/ + * Integration of all pieces of the routing system for easier use. + */ class router implements RouterInterface { /** - * @var manager Extension manager - */ + * Extension manager + * + * @var manager + */ protected $extension_manager; /** - * @var string phpBB root path - */ + * phpBB root path + * + * @var string + */ protected $phpbb_root_path; /** - * @var string PHP file extensions - */ + * PHP file extensions + * + * @var string + */ protected $php_ext; /** - * @var array YAML file(s) containing route information - */ + * Name of the current environment + * + * @var string + */ + protected $environment; + + /** + * YAML file(s) containing route information + * + * @var array + */ protected $routing_files; /** - * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface|null - */ + * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface|null + */ protected $matcher; /** - * @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface|null - */ + * @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface|null + */ protected $generator; /** - * @var RequestContext - */ + * @var RequestContext + */ protected $context; /** - * @var RouteCollection|null - */ + * @var RouteCollection|null + */ protected $route_collection; /** - * Construct method - * - * @param manager $extension_manager The extension manager - * @param string $phpbb_root_path phpBB root path - * @param string $php_ext PHP file extension - * @param array $routing_files Array of strings containing paths to YAML files holding route information - */ - public function __construct(manager $extension_manager, $phpbb_root_path, $php_ext, $routing_files = array()) + * Construct method + * + * @param manager $extension_manager Extension manager + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP file extension + * @param string $environment Name of the current environment + * @param array $routing_files Array of strings containing paths to YAML files holding route information + */ + public function __construct(manager $extension_manager, $phpbb_root_path, $php_ext, $environment, $routing_files = array()) { $this->extension_manager = $extension_manager; $this->routing_files = $routing_files; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; + $this->environment = $environment; $this->context = new RequestContext(); } /** - * Find the list of routing files - * - * @param \phpbb\finder $finder - * @return router - */ - public function find_routing_files(\phpbb\finder $finder) + * Find the list of routing files + * + * @param array $paths Array of paths where to look for routing files. + * @return null + */ + public function find_routing_files(array $paths) { - if ($this->routing_files === null || empty($this->routing_files)) + $this->routing_files = array($this->phpbb_root_path . 'config/' . $this->environment . '/routing/environment.yml'); + foreach ($paths as $path) { - // We hardcode the path to the core config directory - // because the finder cannot find it - $this->routing_files = array_merge($this->routing_files, array('config/routing.yml'), array_keys($finder - ->directory('/config') - ->suffix('routing.yml') - ->find() - )); + if (file_exists($path . 'config/' . $this->environment . '/routing/environment.yml')) + { + $this->routing_files[] = $path . 'config/' . $this->environment . '/routing/environment.yml'; + } + else if (!is_dir($path . 'config/' . $this->environment)) + { + if (file_exists($path . 'config/default/routing/environment.yml')) + { + $this->routing_files[] = $path . 'config/default/routing/environment.yml'; + } + else if (!is_dir($path . 'config/default/routing') && file_exists($path . 'config/routing.yml')) + { + $this->routing_files[] = $path . 'config/routing.yml'; + } + } } - - return $this; } /** - * Find a list of controllers - * - * @param string $base_path Base path to prepend to file paths - * @return router - */ + * Find a list of controllers + * + * @param string $base_path Base path to prepend to file paths + * @return router + */ public function find($base_path = '') { if ($this->route_collection === null || $this->route_collection->count() === 0) @@ -130,15 +154,15 @@ class router implements RouterInterface } /** - * Get the list of routes - * - * @return RouteCollection Get the route collection - */ + * Get the list of routes + * + * @return RouteCollection Get the route collection + */ public function get_routes() { if ($this->route_collection == null || empty($this->routing_files)) { - $this->find_routing_files($this->extension_manager->get_finder()) + $this->find_routing_files($this->extension_manager->all_enabled()) ->find($this->phpbb_root_path); } @@ -146,16 +170,16 @@ class router implements RouterInterface } /** - * {@inheritdoc} - */ + * {@inheritdoc} + */ public function getRouteCollection() { return $this->get_routes(); } /** - * {@inheritdoc} - */ + * {@inheritdoc} + */ public function setContext(RequestContext $context) { $this->context = $context; @@ -171,34 +195,34 @@ class router implements RouterInterface } /** - * {@inheritdoc} - */ + * {@inheritdoc} + */ public function getContext() { return $this->context; } /** - * {@inheritdoc} - */ + * {@inheritdoc} + */ public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) { return $this->get_generator()->generate($name, $parameters, $referenceType); } /** - * {@inheritdoc} - */ + * {@inheritdoc} + */ public function match($pathinfo) { return $this->get_matcher()->match($pathinfo); } /** - * Gets the UrlMatcher instance associated with this Router. - * - * @return \Symfony\Component\Routing\Matcher\UrlMatcherInterface A UrlMatcherInterface instance - */ + * Gets the UrlMatcher instance associated with this Router. + * + * @return \Symfony\Component\Routing\Matcher\UrlMatcherInterface A UrlMatcherInterface instance + */ public function get_matcher() { if ($this->matcher !== null) @@ -218,8 +242,8 @@ class router implements RouterInterface return $this->matcher; } /** - * Creates a new dumped URL Matcher (dump it if necessary) - */ + * Creates a new dumped URL Matcher (dump it if necessary) + */ protected function create_dumped_url_matcher() { if (!file_exists($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext)) @@ -240,18 +264,18 @@ class router implements RouterInterface } /** - * Creates a new URL Matcher - */ + * Creates a new URL Matcher + */ protected function create_new_url_matcher() { $this->matcher = new UrlMatcher($this->get_routes(), $this->context); } /** - * Gets the UrlGenerator instance associated with this Router. - * - * @return \Symfony\Component\Routing\Generator\UrlGeneratorInterface A UrlGeneratorInterface instance - */ + * Gets the UrlGenerator instance associated with this Router. + * + * @return \Symfony\Component\Routing\Generator\UrlGeneratorInterface A UrlGeneratorInterface instance + */ public function get_generator() { if ($this->generator !== null) @@ -272,8 +296,8 @@ class router implements RouterInterface } /** - * Creates a new dumped URL Generator (dump it if necessary) - */ + * Creates a new dumped URL Generator (dump it if necessary) + */ protected function create_dumped_url_generator() { if (!file_exists($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext)) @@ -294,8 +318,8 @@ class router implements RouterInterface } /** - * Creates a new URL Generator - */ + * Creates a new URL Generator + */ protected function create_new_url_generator() { $this->generator = new UrlGenerator($this->get_routes(), $this->context); diff --git a/tests/avatar/driver/barfoo.php b/tests/avatar/driver/barfoo.php index 0bf30b8a91..067bb3ef97 100644 --- a/tests/avatar/driver/barfoo.php +++ b/tests/avatar/driver/barfoo.php @@ -1,26 +1,26 @@ -router = new phpbb_mock_router($this->extension_manager, dirname(__FILE__) . '/', 'php'); - $this->router->find_routing_files($finder); + $this->router = new phpbb_mock_router($this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); + $this->router->find_routing_files($this->extension_manager->all_enabled()); $this->router->find(dirname(__FILE__) . '/'); // Set correct current phpBB root path $this->root_path = $this->get_phpbb_root_path(); @@ -319,7 +319,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description); } -//TODO + public function helper_url_data_absolute_with_rewrite() { return array( diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php index 637e9685e6..354a902831 100644 --- a/tests/controller/controller_test.php +++ b/tests/controller/controller_test.php @@ -40,8 +40,8 @@ class phpbb_controller_controller_test extends phpbb_test_case public function test_router_find_files() { - $router = new \phpbb\routing\router($this->extension_manager, dirname(__FILE__) . '/', 'php'); - $router->find_routing_files($this->extension_manager->get_finder()); + $router = new \phpbb\routing\router($this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); + $router->find_routing_files($this->extension_manager->all_enabled()); $routes = $router->find(__DIR__)->get_routes(); // This will need to be updated if any new routes are defined diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index 04f7b807a7..1b9e8c751c 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -36,16 +36,10 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case $filesystem = new \phpbb\filesystem(); $manager = new phpbb_mock_extension_manager(dirname(__FILE__) . '/', array()); - $finder = new \phpbb\finder( - $filesystem, - dirname(__FILE__) . '/', - new phpbb_mock_cache() - ); - $finder->set_extensions(array_keys($manager->all_enabled())); $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $router = new phpbb_mock_router($manager, dirname(__FILE__) . '/', 'php'); - $router->find_routing_files($finder); + $router = new phpbb_mock_router($manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); + $router->find_routing_files($manager->all_enabled()); $router->find(dirname(__FILE__) . '/'); $request = new phpbb_mock_request(); From f5c5f7df755dd930fef4de6f62e42d4a2a54219e Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 21 Nov 2014 08:26:19 +0100 Subject: [PATCH 0068/1676] [ticket/12620] Fix functionnal tests PHPBB3-12620 --- phpBB/phpbb/routing/router.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 0617e94c93..1003708540 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -107,7 +107,7 @@ class router implements RouterInterface * Find the list of routing files * * @param array $paths Array of paths where to look for routing files. - * @return null + * @return router */ public function find_routing_files(array $paths) { @@ -130,6 +130,8 @@ class router implements RouterInterface } } } + + return $this; } /** From 5e2896bb00089518547d2863fd119cd8a4bcf518 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 21 Nov 2014 16:42:01 +0100 Subject: [PATCH 0069/1676] [ticket/12620] Remove the old includes/functions_url_matcher.php file PHPBB3-12620 --- phpBB/includes/functions_url_matcher.php | 102 ----------------------- 1 file changed, 102 deletions(-) delete mode 100644 phpBB/includes/functions_url_matcher.php diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php deleted file mode 100644 index 19aebd1fbc..0000000000 --- a/phpBB/includes/functions_url_matcher.php +++ /dev/null @@ -1,102 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; -use Symfony\Component\Routing\Matcher\UrlMatcher; -use Symfony\Component\Routing\RequestContext; - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Create a new UrlMatcher class and dump it into the cache file -* -* @param \phpbb\extension\manager $manager Extension manager -* @param RequestContext $context Symfony RequestContext object -* @param string $root_path Root path -* @param string $php_ext PHP file extension -* @return null -*/ -function phpbb_get_url_matcher(\phpbb\extension\manager $manager, RequestContext $context, $root_path, $php_ext) -{ - global $phpbb_container; - - $config_cache = new ConfigCache($root_path . 'cache/' . $phpbb_container->getParameter('core.environment') . '/url_matcher.' . $php_ext, defined('DEBUG')); - if (!$config_cache->isFresh()) - { - phpbb_create_dumped_url_matcher($manager, $root_path, $config_cache); - } - - return phpbb_load_url_matcher($context, $root_path, $php_ext); -} - -/** -* Create a new UrlMatcher class and dump it into the cache file -* -* @param \phpbb\extension\manager $manager Extension manager -* @param string $root_path Root path* @param ConfigCache $config_cache The config cache -* @return null -*/ -function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $root_path, $config_cache) -{ - global $phpbb_container; - - $provider = new \phpbb\controller\provider($phpbb_container->getParameter('core.environment'), $root_path); - $provider->find_routing_files($manager->all_enabled()); - $routes = $provider->find()->get_routes(); - $dumper = new PhpMatcherDumper($routes); - $cached_url_matcher_dump = $dumper->dump(array( - 'class' => 'phpbb_url_matcher', - )); - - $config_cache->write($cached_url_matcher_dump, $routes->getResources()); -} - -/** -* Create a non-cached UrlMatcher -* -* @param \phpbb\extension\manager $manager Extension manager -* @param RequestContext $context Symfony RequestContext object -* @return UrlMatcher -*/ -function phpbb_create_url_matcher(\phpbb\extension\manager $manager, RequestContext $context, $root_path) -{ - global $phpbb_container; - - $provider = new \phpbb\controller\provider($phpbb_container->getParameter('core.environment'), $root_path); - $provider->find_routing_files($manager->all_enabled()); - $routes = $provider->find()->get_routes(); - return new UrlMatcher($routes, $context); -} - -/** -* Load the cached phpbb_url_matcher class -* -* @param RequestContext $context Symfony RequestContext object -* @param string $root_path Root path -* @param string $php_ext PHP file extension -* @return phpbb_url_matcher -*/ -function phpbb_load_url_matcher(RequestContext $context, $root_path, $php_ext) -{ - global $phpbb_container; - - require($root_path . 'cache/' . $phpbb_container->getParameter('core.environment') . '/url_matcher.' . $php_ext); - return new phpbb_url_matcher($context); -} From 54d529994029564d5cecbec2aaac36a0544552a0 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 21 Nov 2014 17:38:13 +0100 Subject: [PATCH 0070/1676] [ticket/12620] Fix tests PHPBB3-12620 --- phpBB/app.php | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/app.php b/phpBB/app.php index d9250adc75..10909f7103 100644 --- a/phpBB/app.php +++ b/phpBB/app.php @@ -21,7 +21,6 @@ define('IN_PHPBB', true); $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './'; $phpEx = substr(strrchr(__FILE__, '.'), 1); include($phpbb_root_path . 'common.' . $phpEx); -include($phpbb_root_path . 'includes/functions_url_matcher.' . $phpEx); // Start session management $user->session_begin(); From 5d3f0a9abbfe9678a9b5b480d1bbdfae69384018 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 22 Nov 2014 00:13:13 +0100 Subject: [PATCH 0071/1676] [ticket/13359] Add phpbb\template\twig\environment to template constructor PHPBB3-13359 --- tests/template/template_includecss_test.php | 30 ++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/template/template_includecss_test.php b/tests/template/template_includecss_test.php index 49bd9dec8b..a8db74c3f1 100644 --- a/tests/template/template_includecss_test.php +++ b/tests/template/template_includecss_test.php @@ -15,6 +15,12 @@ require_once dirname(__FILE__) . '/template_test_case_with_tree.php'; class phpbb_template_template_includecss_test extends phpbb_template_template_test_case_with_tree { + /** @var \phpbb\path_helper */ + protected $phpbb_path_helper; + + /** @var string */ + protected $parent_template_path; + protected function setup_engine(array $new_config = array()) { global $phpbb_root_path, $phpEx, $user; @@ -34,11 +40,32 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te $this->template_path = $this->test_path . '/templates'; $this->parent_template_path = $this->test_path . '/parent_templates'; + $container = new phpbb_mock_container_builder(); + $cache_path = $phpbb_root_path . 'cache/twig'; + $context = new \phpbb\template\context(); + $loader = new \phpbb\template\twig\loader(''); + $twig = new \phpbb\template\twig\environment( + $config, + $this->phpbb_path_helper, + $container, + $cache_path, + null, + $loader, + array( + 'cache' => false, + 'debug' => false, + 'auto_reload' => true, + 'autoescape' => false, + ) + ); $this->template = new phpbb\template\twig\twig( $this->phpbb_path_helper, $config, $user, - new phpbb\template\context(), + $context, + $twig, + $cache_path, + array(new \phpbb\template\twig\extension($context, $this->user)), new phpbb_mock_extension_manager( dirname(__FILE__) . '/', array( @@ -50,6 +77,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te ) ) ); + $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $this->template->set_custom_style('tests', array($this->template_path, $this->parent_template_path)); } From 6850169095f099d8fd9f3886e60237134c77ddb4 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 22 Nov 2014 12:33:45 +0100 Subject: [PATCH 0072/1676] [ticket/13266] Enable the debug extension in the development environment PHPBB3-13266 --- phpBB/config/default/container/services_twig.yml | 3 +++ phpBB/config/development/config.yml | 3 +++ phpBB/phpbb/di/extension/container_configuration.php | 8 +++++++- phpBB/phpbb/di/extension/core.php | 6 ++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index fc5f9ba6a1..25382a95a1 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -41,3 +41,6 @@ services: - @router tags: - { name: twig.extension } + + template.twig.extensions.debug: + class: Twig_Extension_Debug diff --git a/phpBB/config/development/config.yml b/phpBB/config/development/config.yml index 1c17b08931..f451eebe13 100644 --- a/phpBB/config/development/config.yml +++ b/phpBB/config/development/config.yml @@ -3,3 +3,6 @@ imports: core: require_dev_dependencies: true + + twig: + enable_debug_extension: true diff --git a/phpBB/phpbb/di/extension/container_configuration.php b/phpBB/phpbb/di/extension/container_configuration.php index 1f1c077472..ee58ec2b74 100644 --- a/phpBB/phpbb/di/extension/container_configuration.php +++ b/phpBB/phpbb/di/extension/container_configuration.php @@ -30,7 +30,13 @@ class container_configuration implements ConfigurationInterface $rootNode = $treeBuilder->root('core'); $rootNode ->children() - ->booleanNode('require_dev_dependencies')->defaultValue(false)->end() + ->booleanNode('require_dev_dependencies')->defaultValue(false)->end() + ->arrayNode('twig') + ->addDefaultsIfNotSet() + ->children() + ->booleanNode('enable_debug_extension')->defaultValue(false)->end() + ->end() + ->end() ->end() ; return $treeBuilder; diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index 72d46fb05b..451efc8e35 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -67,6 +67,12 @@ class core extends Extension ); } } + + if ($config['twig']['enable_debug_extension']) + { + $definition = $container->getDefinition('template.twig.extensions.debug'); + $definition->addTag('twig.extension'); + } } /** From fd94027b40184b4c9eae10c6e5c1f8bee2c2a974 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 25 Nov 2014 12:23:16 +0100 Subject: [PATCH 0073/1676] [ticket/13372] Fix Url Generator/Matcher generation PHPBB3-13372 --- phpBB/phpbb/routing/router.php | 45 +++++++++++++--------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 1003708540..c9c50534a2 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -13,6 +13,7 @@ namespace phpbb\routing; +use Symfony\Component\Config\ConfigCache; use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; use Symfony\Component\Routing\Matcher\UrlMatcher; @@ -232,14 +233,7 @@ class router implements RouterInterface return $this->matcher; } - if (defined('DEBUG')) - { - $this->create_new_url_matcher(); - } - else - { - $this->create_dumped_url_matcher(); - } + $this->create_dumped_url_matcher(); return $this->matcher; } @@ -248,21 +242,22 @@ class router implements RouterInterface */ protected function create_dumped_url_matcher() { - if (!file_exists($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext)) + $cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_matcher.{$this->php_ext}", defined('DEBUG')); + if (!$cache->isFresh()) { $dumper = new PhpMatcherDumper($this->get_routes()); $options = array( - 'class' => 'phpbb_url_matcher', + 'class' => 'phpbb_url_matcher', + 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', ); - $dump = $dumper->dump($options); - file_put_contents($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext, $dump); + $cache->write($dumper->dump($options), $this->get_routes()->getResources()); } - require_once($this->phpbb_root_path . 'cache/url_matcher.' . $this->php_ext); + require_once $cache; - $this->matcher = new phpbb_url_matcher($this->context); + $this->matcher = new \phpbb_url_matcher($this->context); } /** @@ -285,14 +280,7 @@ class router implements RouterInterface return $this->generator; } - if (defined('DEBUG')) - { - $this->create_new_url_generator(); - } - else - { - $this->create_dumped_url_generator(); - } + $this->create_dumped_url_generator(); return $this->generator; } @@ -302,21 +290,22 @@ class router implements RouterInterface */ protected function create_dumped_url_generator() { - if (!file_exists($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext)) + $cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_generator.{$this->php_ext}", defined('DEBUG')); + if (!$cache->isFresh()) { $dumper = new PhpGeneratorDumper($this->get_routes()); $options = array( - 'class' => 'phpbb_url_generator', + 'class' => 'phpbb_url_generator', + 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', ); - $dump = $dumper->dump($options); - file_put_contents($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext, $dump); + $cache->write($dumper->dump($options), $this->get_routes()->getResources()); } - require_once($this->phpbb_root_path . 'cache/url_generator.' . $this->php_ext); + require_once $cache; - $this->generator = new phpbb_url_generator($this->context); + $this->generator = new \phpbb_url_generator($this->context); } /** From f4576c969ab3c3619564e8be7b71547049846bd5 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 25 Nov 2014 12:48:48 +0100 Subject: [PATCH 0074/1676] [ticket/13372] Fix require_once CS PHPBB3-13372 --- phpBB/phpbb/routing/router.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index c9c50534a2..40a829b73f 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -255,7 +255,7 @@ class router implements RouterInterface $cache->write($dumper->dump($options), $this->get_routes()->getResources()); } - require_once $cache; + require_once($cache); $this->matcher = new \phpbb_url_matcher($this->context); } @@ -303,7 +303,7 @@ class router implements RouterInterface $cache->write($dumper->dump($options), $this->get_routes()->getResources()); } - require_once $cache; + require_once($cache); $this->generator = new \phpbb_url_generator($this->context); } From 10594779b9f0e334ea9db982ee9f980a8d8f87b7 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 22 Nov 2014 02:07:08 +0100 Subject: [PATCH 0075/1676] [ticket/13421] Add an interface for \phpbb\db\tools PHPBB3-13421 --- phpBB/phpbb/db/tools.php | 22 ++-- phpBB/phpbb/db/tools_interface.php | 202 +++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+), 11 deletions(-) create mode 100644 phpBB/phpbb/db/tools_interface.php diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php index c8d25f23a2..ee2b6e843b 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/db/tools.php @@ -17,7 +17,7 @@ namespace phpbb\db; * Database Tools for handling cross-db actions such as altering columns, etc. * Currently not supported is returning SQL for creating tables. */ -class tools +class tools implements tools_interface { /** * Current sql layer @@ -1081,11 +1081,11 @@ class tools /** * Gets a list of columns of a table. * - * @param string $table Table name + * @param string $table_name Table name * * @return array Array of column names (all lower case) */ - function sql_list_columns($table) + function sql_list_columns($table_name) { $columns = array(); @@ -1093,7 +1093,7 @@ class tools { case 'mysql_40': case 'mysql_41': - $sql = "SHOW COLUMNS FROM $table"; + $sql = "SHOW COLUMNS FROM $table_name"; break; // PostgreSQL has a way of doing this in a much simpler way but would @@ -1101,7 +1101,7 @@ class tools case 'postgres': $sql = "SELECT a.attname FROM pg_class c, pg_attribute a - WHERE c.relname = '{$table}' + WHERE c.relname = '{$table_name}' AND a.attnum > 0 AND a.attrelid = c.oid"; break; @@ -1113,13 +1113,13 @@ class tools $sql = "SELECT c.name FROM syscolumns c LEFT JOIN sysobjects o ON c.id = o.id - WHERE o.name = '{$table}'"; + WHERE o.name = '{$table_name}'"; break; case 'oracle': $sql = "SELECT column_name FROM user_tab_columns - WHERE LOWER(table_name) = '" . strtolower($table) . "'"; + WHERE LOWER(table_name) = '" . strtolower($table_name) . "'"; break; case 'sqlite': @@ -1127,7 +1127,7 @@ class tools $sql = "SELECT sql FROM sqlite_master WHERE type = 'table' - AND name = '{$table}'"; + AND name = '{$table_name}'"; $result = $this->db->sql_query($sql); @@ -1175,14 +1175,14 @@ class tools /** * Check whether a specified column exist in a table * - * @param string $table Table to check + * @param string $table_name Table to check * @param string $column_name Column to check * * @return bool True if column exists, false otherwise */ - function sql_column_exists($table, $column_name) + function sql_column_exists($table_name, $column_name) { - $columns = $this->sql_list_columns($table); + $columns = $this->sql_list_columns($table_name); return isset($columns[$column_name]); } diff --git a/phpBB/phpbb/db/tools_interface.php b/phpBB/phpbb/db/tools_interface.php new file mode 100644 index 0000000000..d0ecac779e --- /dev/null +++ b/phpBB/phpbb/db/tools_interface.php @@ -0,0 +1,202 @@ + +* @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; + +/** + * Interface for a Database Tools for handling cross-db actions such as altering columns, etc. + */ +interface tools_interface +{ + /** + * Handle passed database update array. + * Expected structure... + * Key being one of the following + * drop_tables: Drop tables + * add_tables: Add tables + * change_columns: Column changes (only type, not name) + * add_columns: Add columns to a table + * drop_keys: Dropping keys + * drop_columns: Removing/Dropping columns + * add_primary_keys: adding primary keys + * add_unique_index: adding an unique index + * add_index: adding an index (can be column:index_size if you need to provide size) + * + * The values are in this format: + * {TABLE NAME} => array( + * {COLUMN NAME} => array({COLUMN TYPE}, {DEFAULT VALUE}, {OPTIONAL VARIABLES}), + * {KEY/INDEX NAME} => array({COLUMN NAMES}), + * ) + * + * + * @param array $schema_changes + * @return null + */ + public function perform_schema_changes($schema_changes); + + /** + * Gets a list of tables in the database. + * + * @return array Array of table names (all lower case) + */ + public function sql_list_tables(); + + /** + * Check if table exists + * + * @param string $table_name The table name to check for + * @return bool true if table exists, else false + */ + public function sql_table_exists($table_name); + + /** + * Create SQL Table + * + * @param string $table_name The table name to create + * @param array $table_data Array containing table data. + * @return array|true Statements to run, or true if the statements have been executed + */ + public function sql_create_table($table_name, $table_data); + + /** + * Drop Table + * + * @param string $table_name The table name to drop + * @return array|true Statements to run, or true if the statements have been executed + */ + public function sql_table_drop($table_name); + + /** + * Gets a list of columns of a table. + * + * @param string $table_name Table name + * @return array Array of column names (all lower case) + */ + public function sql_list_columns($table_name); + + /** + * Check whether a specified column exist in a table + * + * @param string $table_name Table to check + * @param string $column_name Column to check + * @return bool True if column exists, false otherwise + */ + public function sql_column_exists($table_name, $column_name); + + /** + * Add new column + * + * @param string $table_name Table to modify + * @param string $column_name Name of the column to add + * @param array $column_data Column data + * @param bool $inline Whether the query should actually be run, + * or return a string for adding the column + * @return array|true Statements to run, or true if the statements have been executed + */ + public function sql_column_add($table_name, $column_name, $column_data, $inline = false); + + /** + * Change column type (not name!) + * + * @param string $table_name Table to modify + * @param string $column_name Name of the column to modify + * @param array $column_data Column data + * @param bool $inline Whether the query should actually be run, + * or return a string for modifying the column + * @return array|true Statements to run, or true if the statements have been executed + */ + public function sql_column_change($table_name, $column_name, $column_data, $inline = false); + + /** + * Drop column + * + * @param string $table_name Table to modify + * @param string $column_name Name of the column to drop + * @param bool $inline Whether the query should actually be run, + * or return a string for deleting the column + * @return array|true Statements to run, or true if the statements have been executed + */ + public function sql_column_remove($table_name, $column_name, $inline = false); + + /** + * List all of the indices that belong to a table + * + * NOTE: does not list + * - UNIQUE indices + * - PRIMARY keys + * + * @param string $table_name Table to check + * @return array Array with index names + */ + public function sql_list_index($table_name); + + /** + * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes. + * + * @param string $table_name Table to check the index at + * @param string $index_name The index name to check + * @return bool True if index exists, else false + */ + public function sql_index_exists($table_name, $index_name); + + /** + * Add index + * + * @param string $table_name Table to modify + * @param string $index_name Name of the index to create + * @param string|array $column Either a string with a column name, or an array with columns + * @return array|true Statements to run, or true if the statements have been executed + */ + public function sql_create_index($table_name, $index_name, $column); + + /** + * Drop Index + * + * @param string $table_name Table to modify + * @param string $index_name Name of the index to delete + * @return array|true Statements to run, or true if the statements have been executed + */ + public function sql_index_drop($table_name, $index_name); + + /** + * Check if a specified index exists in table. + * + * NOTE: Does not return normal and PRIMARY KEY indexes + * + * @param string $table_name Table to check the index at + * @param string $index_name The index name to check + * @return bool True if index exists, else false + */ + public function sql_unique_index_exists($table_name, $index_name); + + /** + * Add unique index + * + * @param string $table_name Table to modify + * @param string $index_name Name of the unique index to create + * @param string|array $column Either a string with a column name, or an array with columns + * @return array|true Statements to run, or true if the statements have been executed + */ + public function sql_create_unique_index($table_name, $index_name, $column); + + /** + * Add primary key + * + * @param string $table_name Table to modify + * @param string|array $column Either a string with a column name, or an array with columns + * @param bool $inline Whether the query should actually be run, + * or return a string for creating the key + * @return array|true Statements to run, or true if the statements have been executed + */ + public function sql_create_primary_key($table_name, $column, $inline = false); +} From 536bdf036b6fc2a715f5dc3eec759fe360c2b1cf Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 22 Nov 2014 02:11:21 +0100 Subject: [PATCH 0076/1676] [ticket/13421] Inherit docs PHPBB3-13421 --- phpBB/phpbb/db/tools.php | 119 +++++++++++---------------------------- 1 file changed, 34 insertions(+), 85 deletions(-) diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php index ee2b6e843b..e9d2382910 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/db/tools.php @@ -371,10 +371,8 @@ class tools implements tools_interface } /** - * Gets a list of tables in the database. - * - * @return array Array of table names (all lower case) - */ + * {@inheritDoc} + */ function sql_list_tables() { switch ($this->db->get_sql_layer()) @@ -431,12 +429,8 @@ class tools implements tools_interface } /** - * Check if table exists - * - * - * @param string $table_name The table name to check for - * @return bool true if table exists, else false - */ + * {@inheritDoc} + */ function sql_table_exists($table_name) { $this->db->sql_return_on_error(true); @@ -453,12 +447,8 @@ class tools implements tools_interface } /** - * Create SQL Table - * - * @param string $table_name The table name to create - * @param array $table_data Array containing table data. - * @return array Statements if $return_statements is true. - */ + * {@inheritDoc} + */ function sql_create_table($table_name, $table_data) { // holds the DDL for a column @@ -679,27 +669,8 @@ class tools implements tools_interface } /** - * Handle passed database update array. - * Expected structure... - * Key being one of the following - * drop_tables: Drop tables - * add_tables: Add tables - * change_columns: Column changes (only type, not name) - * add_columns: Add columns to a table - * drop_keys: Dropping keys - * drop_columns: Removing/Dropping columns - * add_primary_keys: adding primary keys - * add_unique_index: adding an unique index - * add_index: adding an index (can be column:index_size if you need to provide size) - * - * The values are in this format: - * {TABLE NAME} => array( - * {COLUMN NAME} => array({COLUMN TYPE}, {DEFAULT VALUE}, {OPTIONAL VARIABLES}), - * {KEY/INDEX NAME} => array({COLUMN NAMES}), - * ) - * - * For more information have a look at /develop/create_schema_files.php (only available through SVN) - */ + * {@inheritDoc} + */ function perform_schema_changes($schema_changes) { if (empty($schema_changes)) @@ -1079,12 +1050,8 @@ class tools implements tools_interface } /** - * Gets a list of columns of a table. - * - * @param string $table_name Table name - * - * @return array Array of column names (all lower case) - */ + * {@inheritDoc} + */ function sql_list_columns($table_name) { $columns = array(); @@ -1173,13 +1140,8 @@ class tools implements tools_interface } /** - * Check whether a specified column exist in a table - * - * @param string $table_name Table to check - * @param string $column_name Column to check - * - * @return bool True if column exists, false otherwise - */ + * {@inheritDoc} + */ function sql_column_exists($table_name, $column_name) { $columns = $this->sql_list_columns($table_name); @@ -1188,13 +1150,8 @@ class tools implements tools_interface } /** - * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes. - * - * @param string $table_name Table to check the index at - * @param string $index_name The index name to check - * - * @return bool True if index exists, else false - */ + * {@inheritDoc} + */ function sql_index_exists($table_name, $index_name) { if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative') @@ -1285,13 +1242,8 @@ class tools implements tools_interface } /** - * Check if a specified index exists in table. Does not return PRIMARY KEY indexes. - * - * @param string $table_name Table to check the index at - * @param string $index_name The index name to check - * - * @return bool True if index exists, else false - */ + * {@inheritDoc} + */ function sql_unique_index_exists($table_name, $index_name) { if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative') @@ -1684,8 +1636,8 @@ class tools implements tools_interface } /** - * Add new column - */ + * {@inheritDoc} + */ function sql_column_add($table_name, $column_name, $column_data, $inline = false) { $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); @@ -1802,8 +1754,8 @@ class tools implements tools_interface } /** - * Drop column - */ + * {@inheritDoc} + */ function sql_column_remove($table_name, $column_name, $inline = false) { $statements = array(); @@ -1931,8 +1883,8 @@ class tools implements tools_interface } /** - * Drop Index - */ + * {@inheritDoc} + */ function sql_index_drop($table_name, $index_name) { $statements = array(); @@ -1961,8 +1913,8 @@ class tools implements tools_interface } /** - * Drop Table - */ + * {@inheritDoc} + */ function sql_table_drop($table_name) { $statements = array(); @@ -2014,8 +1966,8 @@ class tools implements tools_interface } /** - * Add primary key - */ + * {@inheritDoc} + */ function sql_create_primary_key($table_name, $column, $inline = false) { $statements = array(); @@ -2098,8 +2050,8 @@ class tools implements tools_interface } /** - * Add unique index - */ + * {@inheritDoc} + */ function sql_create_unique_index($table_name, $index_name, $column) { $statements = array(); @@ -2135,8 +2087,8 @@ class tools implements tools_interface } /** - * Add index - */ + * {@inheritDoc} + */ function sql_create_index($table_name, $index_name, $column) { $statements = array(); @@ -2188,11 +2140,8 @@ class tools implements tools_interface } /** - * List all of the indices that belong to a table, - * does not count: - * * UNIQUE indices - * * PRIMARY keys - */ + * {@inheritDoc} + */ function sql_list_index($table_name) { $index_array = array(); @@ -2287,8 +2236,8 @@ class tools implements tools_interface } /** - * Change column type (not name!) - */ + * {@inheritDoc} + */ function sql_column_change($table_name, $column_name, $column_data, $inline = false) { $original_column_data = $column_data; From d78bb2865b27aa753b165fdc8aaa73ed82eaeac8 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 22 Nov 2014 02:15:06 +0100 Subject: [PATCH 0077/1676] [ticket/13421] Always require the interface when possible PHPBB3-13421 --- phpBB/phpbb/db/migration/migration.php | 6 +++--- phpBB/phpbb/db/migrator.php | 4 ++-- phpBB/phpbb/search/fulltext_sphinx.php | 2 +- tests/dbal/db_tools_test.php | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/phpBB/phpbb/db/migration/migration.php b/phpBB/phpbb/db/migration/migration.php index 5f120333e1..6cf7685350 100644 --- a/phpBB/phpbb/db/migration/migration.php +++ b/phpBB/phpbb/db/migration/migration.php @@ -28,7 +28,7 @@ abstract class migration /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var \phpbb\db\tools */ + /** @var \phpbb\db\tools_interface */ protected $db_tools; /** @var string */ @@ -51,12 +51,12 @@ abstract class migration * * @param \phpbb\config\config $config * @param \phpbb\db\driver\driver_interface $db - * @param \phpbb\db\tools $db_tools + * @param \phpbb\db\tools_interface $db_tools * @param string $phpbb_root_path * @param string $php_ext * @param string $table_prefix */ - public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix) + public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools_interface $db_tools, $phpbb_root_path, $php_ext, $table_prefix) { $this->config = $config; $this->db = $db; diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php index d03496eae3..c0d42ab6ac 100644 --- a/phpBB/phpbb/db/migrator.php +++ b/phpBB/phpbb/db/migrator.php @@ -24,7 +24,7 @@ class migrator /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var \phpbb\db\tools */ + /** @var \phpbb\db\tools_interface */ protected $db_tools; /** @var \phpbb\db\migration\helper */ @@ -84,7 +84,7 @@ class migrator /** * Constructor of the database migrator */ - public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper) + public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools_interface $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper) { $this->config = $config; $this->db = $db; diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php index eb53ca6d40..7be1b487ab 100644 --- a/phpBB/phpbb/search/fulltext_sphinx.php +++ b/phpBB/phpbb/search/fulltext_sphinx.php @@ -85,7 +85,7 @@ class fulltext_sphinx /** * Database Tools object - * @var \phpbb\db\tools + * @var \phpbb\db\tools_interface */ protected $db_tools; diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index 51f9daacfb..d34a2249ef 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -17,7 +17,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case { /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var \phpbb\db\tools */ + /** @var \phpbb\db\tools_interface */ protected $tools; protected $table_exists; protected $table_data; From ec90f2b380a598a3dbf7ada0e95878d9d1b85cbe Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 6 Dec 2014 16:34:02 +0100 Subject: [PATCH 0078/1676] [ticket/13421] Move tools to subdirectory PHPBB3-13421 --- phpBB/config/default/container/services_db.yml | 2 +- phpBB/develop/create_schema_files.php | 4 ++-- phpBB/develop/mysql_upgrader.php | 4 ++-- phpBB/includes/acp/acp_database.php | 2 +- phpBB/includes/functions_install.php | 2 +- phpBB/install/convertors/functions_phpbb20.php | 2 +- phpBB/install/install_install.php | 4 ++-- phpBB/phpbb/captcha/plugins/qa.php | 4 ++-- phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php | 2 +- phpBB/phpbb/db/migration/migration.php | 6 +++--- phpBB/phpbb/db/migration/schema_generator.php | 4 ++-- phpBB/phpbb/db/migrator.php | 4 ++-- phpBB/phpbb/db/{ => tools}/tools.php | 2 +- phpBB/phpbb/db/{ => tools}/tools_interface.php | 2 +- phpBB/phpbb/search/fulltext_sphinx.php | 6 +++--- tests/dbal/auto_increment_test.php | 2 +- tests/dbal/db_tools_test.php | 8 ++++---- tests/dbal/migrator_test.php | 2 +- tests/extension/manager_test.php | 2 +- tests/extension/metadata_manager_test.php | 2 +- tests/migrator/convert_timezones_test.php | 6 +++--- tests/migrator/schema_generator_test.php | 2 +- tests/notification/convert_test.php | 2 +- tests/test_framework/phpbb_database_test_case.php | 2 +- .../phpbb_database_test_connection_manager.php | 4 ++-- tests/test_framework/phpbb_functional_test_case.php | 2 +- 26 files changed, 42 insertions(+), 42 deletions(-) rename phpBB/phpbb/db/{ => tools}/tools.php (99%) rename phpBB/phpbb/db/{ => tools}/tools_interface.php (99%) diff --git a/phpBB/config/default/container/services_db.yml b/phpBB/config/default/container/services_db.yml index b3f1b485ea..77a1b59d22 100644 --- a/phpBB/config/default/container/services_db.yml +++ b/phpBB/config/default/container/services_db.yml @@ -10,7 +10,7 @@ services: - [sql_connect, [%dbal.dbhost%, %dbal.dbuser%, %dbal.dbpasswd%, %dbal.dbname%, %dbal.dbport%, false, %dbal.new_link%]] dbal.tools: - class: phpbb\db\tools + class: phpbb\db\tools\tools arguments: - @dbal.conn diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 7ef86ad7fc..e4102a02e7 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -49,9 +49,9 @@ $classes = $finder->core_path('phpbb/') ->get_classes(); $db = new \phpbb\db\driver\sqlite(); -$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix); +$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix); $schema_data = $schema_generator->get_schema(); -$dbms_type_map = phpbb\db\tools::get_dbms_type_map(); +$dbms_type_map = phpbb\db\tools\tools::get_dbms_type_map(); $fp = fopen($schema_path . 'schema.json', 'wb'); fwrite($fp, json_encode($schema_data, JSON_PRETTY_PRINT)); diff --git a/phpBB/develop/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php index 5c558f0b8e..ff4e38fb0a 100644 --- a/phpBB/develop/mysql_upgrader.php +++ b/phpBB/develop/mysql_upgrader.php @@ -63,9 +63,9 @@ echo "USE $dbname;$newline$newline"; @set_time_limit(0); require($phpbb_root_path . 'includes/db/schema_data.' . $phpEx); -require($phpbb_root_path . 'phpbb/db/tools.' . $phpEx); +require($phpbb_root_path . 'phpbb/db/tools/tools.' . $phpEx); -$dbms_type_map = phpbb\db\tools::get_dbms_type_map(); +$dbms_type_map = phpbb\db\tools\tools::get_dbms_type_map(); foreach ($schema_data as $table_name => $table_data) { diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 0c52f82459..7de108c88a 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -29,7 +29,7 @@ class acp_database global $cache, $db, $user, $auth, $template, $table_prefix; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - $this->db_tools = new \phpbb\db\tools($db); + $this->db_tools = new \phpbb\db\tools\tools($db); $user->add_lang('acp/database'); diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index a60ddd40c5..956e5a5180 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -188,7 +188,7 @@ function dbms_select($default = '', $only_20x_options = false) */ function get_tables(&$db) { - $db_tools = new \phpbb\db\tools($db); + $db_tools = new \phpbb\db\tools\tools($db); return $db_tools->sql_list_tables(); } diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php index 817c007274..7794b5ca67 100644 --- a/phpBB/install/convertors/functions_phpbb20.php +++ b/phpBB/install/convertors/functions_phpbb20.php @@ -1926,7 +1926,7 @@ function phpbb_check_username_collisions() function phpbb_convert_timezone($timezone) { global $config, $db, $phpbb_root_path, $phpEx, $table_prefix; - $timezone_migration = new \phpbb\db\migration\data\v310\timezone($config, $db, new \phpbb\db\tools($db), $phpbb_root_path, $phpEx, $table_prefix); + $timezone_migration = new \phpbb\db\migration\data\v310\timezone($config, $db, new \phpbb\db\tools\tools($db), $phpbb_root_path, $phpEx, $table_prefix); return $timezone_migration->convert_phpbb30_timezone($timezone, 0); } diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 103262b516..4ef6df172a 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -1197,7 +1197,7 @@ class install_install extends module ->get_classes(); $sqlite_db = new \phpbb\db\driver\sqlite(); - $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $sqlite_db, new \phpbb\db\tools($sqlite_db, true), $phpbb_root_path, $phpEx, $table_prefix); + $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $sqlite_db, new \phpbb\db\tools\tools($sqlite_db, true), $phpbb_root_path, $phpEx, $table_prefix); $db_table_schema = $schema_generator->get_schema(); } @@ -1209,7 +1209,7 @@ class install_install extends module define('CONFIG_TABLE', $data['table_prefix'] . 'config'); } - $db_tools = new \phpbb\db\tools($db); + $db_tools = new \phpbb\db\tools\tools($db); foreach ($db_table_schema as $table_name => $table_data) { $db_tools->sql_create_table( diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index a7ba994cc3..ca242a96dc 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -115,7 +115,7 @@ class qa { global $db; - $db_tool = new \phpbb\db\tools($db); + $db_tool = new \phpbb\db\tools\tools($db); return $db_tool->sql_table_exists($this->table_captcha_questions); } @@ -308,7 +308,7 @@ class qa { global $db; - $db_tool = new \phpbb\db\tools($db); + $db_tool = new \phpbb\db\tools\tools($db); $tables = array($this->table_captcha_questions, $this->table_captcha_answers, $this->table_qa_confirm); diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php index 06e46d522f..5f928df47c 100644 --- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php @@ -34,7 +34,7 @@ class release_3_0_9_rc1 extends \phpbb\db\migration\migration // this column was removed from the database updater // after 3.0.9-RC3 was released. It might still exist // in 3.0.9-RCX installations and has to be dropped as - // soon as the db_tools class is capable of properly + // soon as the \phpbb\db\tools\tools class is capable of properly // removing a primary key. // 'attempt_id' => array('UINT', NULL, 'auto_increment'), 'attempt_ip' => array('VCHAR:40', ''), diff --git a/phpBB/phpbb/db/migration/migration.php b/phpBB/phpbb/db/migration/migration.php index 6cf7685350..2304c8e44c 100644 --- a/phpBB/phpbb/db/migration/migration.php +++ b/phpBB/phpbb/db/migration/migration.php @@ -28,7 +28,7 @@ abstract class migration /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var \phpbb\db\tools_interface */ + /** @var \phpbb\db\tools\tools_interface */ protected $db_tools; /** @var string */ @@ -51,12 +51,12 @@ abstract class migration * * @param \phpbb\config\config $config * @param \phpbb\db\driver\driver_interface $db - * @param \phpbb\db\tools_interface $db_tools + * @param \phpbb\db\tools\tools_interface $db_tools * @param string $phpbb_root_path * @param string $php_ext * @param string $table_prefix */ - public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools_interface $db_tools, $phpbb_root_path, $php_ext, $table_prefix) + public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools\tools_interface $db_tools, $phpbb_root_path, $php_ext, $table_prefix) { $this->config = $config; $this->db = $db; diff --git a/phpBB/phpbb/db/migration/schema_generator.php b/phpBB/phpbb/db/migration/schema_generator.php index 91d8307d91..7003844bc4 100644 --- a/phpBB/phpbb/db/migration/schema_generator.php +++ b/phpBB/phpbb/db/migration/schema_generator.php @@ -24,7 +24,7 @@ class schema_generator /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var \phpbb\db\tools */ + /** @var \phpbb\db\tools\tools_interface */ protected $db_tools; /** @var array */ @@ -48,7 +48,7 @@ class schema_generator /** * Constructor */ - public function __construct(array $class_names, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix) + public function __construct(array $class_names, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools\tools_interface $db_tools, $phpbb_root_path, $php_ext, $table_prefix) { $this->config = $config; $this->db = $db; diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php index c0d42ab6ac..bb79c0dd68 100644 --- a/phpBB/phpbb/db/migrator.php +++ b/phpBB/phpbb/db/migrator.php @@ -24,7 +24,7 @@ class migrator /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var \phpbb\db\tools_interface */ + /** @var \phpbb\db\tools\tools_interface */ protected $db_tools; /** @var \phpbb\db\migration\helper */ @@ -84,7 +84,7 @@ class migrator /** * Constructor of the database migrator */ - public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools_interface $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper) + public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools\tools_interface $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper) { $this->config = $config; $this->db = $db; diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools/tools.php similarity index 99% rename from phpBB/phpbb/db/tools.php rename to phpBB/phpbb/db/tools/tools.php index e9d2382910..63c43c07ef 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\db; +namespace phpbb\db\tools; /** * Database Tools for handling cross-db actions such as altering columns, etc. diff --git a/phpBB/phpbb/db/tools_interface.php b/phpBB/phpbb/db/tools/tools_interface.php similarity index 99% rename from phpBB/phpbb/db/tools_interface.php rename to phpBB/phpbb/db/tools/tools_interface.php index d0ecac779e..f153f73a54 100644 --- a/phpBB/phpbb/db/tools_interface.php +++ b/phpBB/phpbb/db/tools/tools_interface.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\db; +namespace phpbb\db\tools; /** * Interface for a Database Tools for handling cross-db actions such as altering columns, etc. diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php index 7be1b487ab..2765d05b94 100644 --- a/phpBB/phpbb/search/fulltext_sphinx.php +++ b/phpBB/phpbb/search/fulltext_sphinx.php @@ -85,7 +85,7 @@ class fulltext_sphinx /** * Database Tools object - * @var \phpbb\db\tools_interface + * @var \phpbb\db\tools\tools_interface */ protected $db_tools; @@ -135,8 +135,8 @@ class fulltext_sphinx $this->db = $db; $this->auth = $auth; - // Initialize \phpbb\db\tools object - $this->db_tools = new \phpbb\db\tools($this->db); + // Initialize \phpbb\db\tools\tools object + $this->db_tools = new \phpbb\db\tools\tools($this->db); if(!$this->config['fulltext_sphinx_id']) { diff --git a/tests/dbal/auto_increment_test.php b/tests/dbal/auto_increment_test.php index 1ed8ea29e3..057bcb5bac 100644 --- a/tests/dbal/auto_increment_test.php +++ b/tests/dbal/auto_increment_test.php @@ -30,7 +30,7 @@ class phpbb_dbal_auto_increment_test extends phpbb_database_test_case parent::setUp(); $this->db = $this->new_dbal(); - $this->tools = new \phpbb\db\tools($this->db); + $this->tools = new \phpbb\db\tools\tools($this->db); $this->table_data = array( 'COLUMNS' => array( diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index d34a2249ef..7d01376062 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -17,7 +17,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case { /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var \phpbb\db\tools_interface */ + /** @var \phpbb\db\tools\tools_interface */ protected $tools; protected $table_exists; protected $table_data; @@ -32,7 +32,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case parent::setUp(); $this->db = $this->new_dbal(); - $this->tools = new \phpbb\db\tools($this->db); + $this->tools = new \phpbb\db\tools\tools($this->db); $this->table_data = array( 'COLUMNS' => array( @@ -340,7 +340,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case public function test_perform_schema_changes_drop_tables() { - $db_tools = $this->getMock('\phpbb\db\tools', array( + $db_tools = $this->getMock('\phpbb\db\tools\tools', array( 'sql_table_exists', 'sql_table_drop', ), array(&$this->db)); @@ -366,7 +366,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case public function test_perform_schema_changes_drop_columns() { - $db_tools = $this->getMock('\phpbb\db\tools', array( + $db_tools = $this->getMock('\phpbb\db\tools\tools', array( 'sql_column_exists', 'sql_column_remove', ), array(&$this->db)); diff --git a/tests/dbal/migrator_test.php b/tests/dbal/migrator_test.php index 10a9444d63..e4fb442818 100644 --- a/tests/dbal/migrator_test.php +++ b/tests/dbal/migrator_test.php @@ -38,7 +38,7 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case parent::setUp(); $this->db = $this->new_dbal(); - $this->db_tools = new \phpbb\db\tools($this->db); + $this->db_tools = new \phpbb\db\tools\tools($this->db); $this->config = new \phpbb\config\db($this->db, new phpbb_mock_cache, 'phpbb_config'); diff --git a/tests/extension/manager_test.php b/tests/extension/manager_test.php index 5c7cad89f6..ab93edd939 100644 --- a/tests/extension/manager_test.php +++ b/tests/extension/manager_test.php @@ -150,7 +150,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case $config = new \phpbb\config\config(array('version' => PHPBB_VERSION)); $db = $this->new_dbal(); - $db_tools = new \phpbb\db\tools($db); + $db_tools = new \phpbb\db\tools\tools($db); $phpbb_root_path = __DIR__ . './../../phpBB/'; $php_ext = 'php'; $table_prefix = 'phpbb_'; diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index b7a6cd3c5b..2d6df3a3f3 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -41,7 +41,7 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case 'version' => '3.1.0', )); $this->db = $this->new_dbal(); - $this->db_tools = new \phpbb\db\tools($this->db); + $this->db_tools = new \phpbb\db\tools\tools($this->db); $this->phpbb_root_path = dirname(__FILE__) . '/'; $this->phpEx = 'php'; $this->user = new \phpbb\user('\phpbb\datetime'); diff --git a/tests/migrator/convert_timezones_test.php b/tests/migrator/convert_timezones_test.php index 7501ed2ed0..80a43b4035 100644 --- a/tests/migrator/convert_timezones_test.php +++ b/tests/migrator/convert_timezones_test.php @@ -18,7 +18,7 @@ class phpbb_migrator_convert_timezones_test extends phpbb_database_test_case public function getDataSet() { $this->db = $this->new_dbal(); - $db_tools = new \phpbb\db\tools($this->db); + $db_tools = new \phpbb\db\tools\tools($this->db); // user_dst doesn't exist anymore, must re-add it to test this $db_tools->sql_column_add('phpbb_users', 'user_dst', array('BOOL', 1)); @@ -59,7 +59,7 @@ class phpbb_migrator_convert_timezones_test extends phpbb_database_test_case $this->migration = new \phpbb\db\migration\data\v310\timezone( new \phpbb\config\config(array()), $this->db, - new \phpbb\db\tools($this->db), + new \phpbb\db\tools\tools($this->db), $phpbb_root_path, $phpEx, 'phpbb_' @@ -90,7 +90,7 @@ class phpbb_migrator_convert_timezones_test extends phpbb_database_test_case } $this->db->sql_freeresult($result); - $db_tools = new \phpbb\db\tools($this->db); + $db_tools = new \phpbb\db\tools\tools($this->db); // Remove the user_dst field again $db_tools->sql_column_remove('phpbb_users', 'user_dst'); diff --git a/tests/migrator/schema_generator_test.php b/tests/migrator/schema_generator_test.php index 9adf518a5d..1e3b489426 100644 --- a/tests/migrator/schema_generator_test.php +++ b/tests/migrator/schema_generator_test.php @@ -30,7 +30,7 @@ class schema_generator_test extends phpbb_test_case $this->config = new \phpbb\config\config(array()); $this->db = new \phpbb\db\driver\sqlite(); - $this->db_tools = new \phpbb\db\tools($this->db); + $this->db_tools = new \phpbb\db\tools\tools($this->db); $this->table_prefix = 'phpbb_'; } diff --git a/tests/notification/convert_test.php b/tests/notification/convert_test.php index 32ab34c9bc..ad6e5849d3 100644 --- a/tests/notification/convert_test.php +++ b/tests/notification/convert_test.php @@ -32,7 +32,7 @@ class phpbb_notification_convert_test extends phpbb_database_test_case $this->migration = new \phpbb\db\migration\data\v310\notification_options_reconvert( new \phpbb\config\config(array()), $this->db, - new \phpbb\db\tools($this->db), + new \phpbb\db\tools\tools($this->db), $phpbb_root_path, $phpEx, 'phpbb_' diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index fc1a3632f4..f630f4ab52 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -77,7 +77,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test global $table_prefix; $db = new \phpbb\db\driver\sqlite(); - $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix); + $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix); file_put_contents(self::$schema_file, json_encode($schema_generator->get_schema())); } diff --git a/tests/test_framework/phpbb_database_test_connection_manager.php b/tests/test_framework/phpbb_database_test_connection_manager.php index 5d643e43e2..ba641c6fb7 100644 --- a/tests/test_framework/phpbb_database_test_connection_manager.php +++ b/tests/test_framework/phpbb_database_test_connection_manager.php @@ -370,11 +370,11 @@ class phpbb_database_test_connection_manager ->get_classes(); $db = new \phpbb\db\driver\sqlite(); - $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix); + $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix); $db_table_schema = $schema_generator->get_schema(); } - $db_tools = new \phpbb\db\tools($db, true); + $db_tools = new \phpbb\db\tools\tools($db, true); foreach ($db_table_schema as $table_name => $table_data) { $queries = $db_tools->sql_create_table( diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 9391795e32..0ea6c5b7cb 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -230,7 +230,7 @@ class phpbb_functional_test_case extends phpbb_test_case $config = new \phpbb\config\config(array()); $db = $this->get_db(); - $db_tools = new \phpbb\db\tools($db); + $db_tools = new \phpbb\db\tools\tools($db); $migrator = new \phpbb\db\migrator( $config, From 11b6bc5722a6a4aed1cd45ce65f2d9cf16ae7dd5 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 10 Jan 2015 15:43:18 +0100 Subject: [PATCH 0079/1676] [ticket/13487] Add factory for db tool class This allows us to split up the large file one by one easily. PHPBB3-13487 --- .../config/default/container/services_db.yml | 5 +++ phpBB/phpbb/db/tools/factory.php | 35 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 phpBB/phpbb/db/tools/factory.php diff --git a/phpBB/config/default/container/services_db.yml b/phpBB/config/default/container/services_db.yml index 77a1b59d22..afae757ee7 100644 --- a/phpBB/config/default/container/services_db.yml +++ b/phpBB/config/default/container/services_db.yml @@ -9,8 +9,13 @@ services: calls: - [sql_connect, [%dbal.dbhost%, %dbal.dbuser%, %dbal.dbpasswd%, %dbal.dbname%, %dbal.dbport%, false, %dbal.new_link%]] +# ----- DB Tools ----- + dbal.tools.factory: + class: phpbb\db\tools\factory + dbal.tools: class: phpbb\db\tools\tools + factory: ["@dbal.tools.factory", get] arguments: - @dbal.conn diff --git a/phpBB/phpbb/db/tools/factory.php b/phpBB/phpbb/db/tools/factory.php new file mode 100644 index 0000000000..60db2ade03 --- /dev/null +++ b/phpBB/phpbb/db/tools/factory.php @@ -0,0 +1,35 @@ + +* @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\tools; + +/** + * A factory which serves the suitable tools instance for the given dbal + */ +class factory +{ + /** + * @param mixed $db_driver + * @param bool $return_statements + * @return \phpbb\db\tools\tools_interface + */ + public function get($db_driver, $return_statements = false) + { + if ($db_driver instanceof \phpbb\db\driver\driver_interface) + { + return new \phpbb\db\tools\tools($db_driver, $return_statements); + } + + throw new \InvalidArgumentException('Invalid database driver given'); + } +} From 63da128ee5891971cc9e4f283572e0198174d692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88tan=20Muller?= Date: Tue, 30 Dec 2014 02:22:13 +0100 Subject: [PATCH 0080/1676] [ticket/12487] Update PHP code PHPBB3-12487 --- phpBB/includes/acp/acp_search.php | 12 +++---- phpBB/includes/functions.php | 40 +++--------------------- phpBB/includes/functions_jabber.php | 3 +- phpBB/includes/functions_messenger.php | 16 ++-------- phpBB/includes/startup.php | 43 ++++++++------------------ 5 files changed, 25 insertions(+), 89 deletions(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index eddc6871f8..4a418f43e5 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -303,8 +303,7 @@ class acp_search } else { - $starttime = explode(' ', microtime()); - $starttime = $starttime[1] + $starttime[0]; + $starttime = microtime(true); $row_count = 0; while (still_on_time() && $post_counter <= $this->max_post_id) { @@ -336,8 +335,7 @@ class acp_search if ($post_counter <= $this->max_post_id) { - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; + $totaltime = microtime(true) - $starttime; $rows_per_second = $row_count / $totaltime; meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter)); trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter, $rows_per_second)); @@ -376,8 +374,7 @@ class acp_search } $db->sql_freeresult($result); - $starttime = explode(' ', microtime()); - $starttime = $starttime[1] + $starttime[0]; + $starttime = microtime(true); $row_count = 0; while (still_on_time() && $post_counter <= $this->max_post_id) { @@ -426,8 +423,7 @@ class acp_search if ($post_counter <= $this->max_post_id) { - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; + $totaltime = microtime(true) - $starttime; $rows_per_second = $row_count / $totaltime; meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter)); trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 321394639b..65dfa7f5af 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -376,8 +376,7 @@ function still_on_time($extra_time = 15) { static $max_execution_time, $start_time; - $time = explode(' ', microtime()); - $current_time = $time[0] + $time[1]; + $current_time = microtime(true); if (empty($max_execution_time)) { @@ -802,7 +801,7 @@ function phpbb_own_realpath($path) $max = sizeof($bits) - 1; - // Check if we are able to resolve symlinks, Windows cannot. + // Check if we are able to resolve symlinks, Windows (prior to Vista and Server 2008) cannot. $symlink_resolve = (function_exists('readlink')) ? true : false; foreach ($bits as $i => $bit) @@ -3659,38 +3658,12 @@ function phpbb_checkdnsrr($host, $type = 'MX') return (@gethostbyname($host_fqdn) == $host_fqdn) ? false : true; } - // checkdnsrr() is available on Windows since PHP 5.3, - // but until 5.3.3 it only works for MX records - // See: http://bugs.php.net/bug.php?id=51844 - - // Call checkdnsrr() if - // we're looking for an MX record or - // we're not on Windows or - // we're running a PHP version where #51844 has been fixed - - // checkdnsrr() supports AAAA since 5.0.0 - // checkdnsrr() supports TXT since 5.2.4 - if ( - ($type == 'MX' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.3', '>=')) && - ($type != 'AAAA' || version_compare(PHP_VERSION, '5.0.0', '>=')) && - ($type != 'TXT' || version_compare(PHP_VERSION, '5.2.4', '>=')) && - function_exists('checkdnsrr') - ) + if (function_exists('checkdnsrr')) { return checkdnsrr($host_fqdn, $type); } - // dns_get_record() is available since PHP 5; since PHP 5.3 also on Windows, - // but on Windows it does not work reliable for AAAA records before PHP 5.3.1 - - // Call dns_get_record() if - // we're not looking for an AAAA record or - // we're not on Windows or - // we're running a PHP version where AAAA lookups work reliable - if ( - ($type != 'AAAA' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.1', '>=')) && - function_exists('dns_get_record') - ) + if (function_exists('dns_get_record')) { // dns_get_record() expects an integer as second parameter // We have to convert the string $type to the corresponding integer constant. @@ -3837,11 +3810,6 @@ function msg_handler($errno, $msg_text, $errfile, $errline) $msg_text = $msg_long_text; } - if (!defined('E_DEPRECATED')) - { - define('E_DEPRECATED', 8192); - } - switch ($errno) { case E_NOTICE: diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php index bd2e9e93ac..a38888a861 100644 --- a/phpBB/includes/functions_jabber.php +++ b/phpBB/includes/functions_jabber.php @@ -87,8 +87,7 @@ class jabber */ static public function can_use_ssl() { - // Will not work with PHP >= 5.2.1 or < 5.2.3RC2 until timeout problem with ssl hasn't been fixed (http://bugs.php.net/41236) - return ((version_compare(PHP_VERSION, '5.2.1', '<') || version_compare(PHP_VERSION, '5.2.3RC2', '>=')) && @extension_loaded('openssl')) ? true : false; + return @extension_loaded('openssl'); } /** diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index bb38e96a53..1a9b1f9e11 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -33,8 +33,6 @@ class messenger /** @var \phpbb\template\template */ protected $template; - var $eol = "\n"; - /** * Constructor */ @@ -44,10 +42,6 @@ class messenger $this->use_queue = (!$config['email_package_size']) ? false : $use_queue; $this->subject = ''; - - // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) - $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; - $this->eol = (!$this->eol) ? "\n" : $this->eol; } /** @@ -497,7 +491,7 @@ class messenger $this->from = $board_contact; } - $encode_eol = ($config['smtp_delivery']) ? "\r\n" : $this->eol; + $encode_eol = ($config['smtp_delivery']) ? "\r\n" : PHP_EOL; // Build to, cc and bcc strings $to = $cc = $bcc = ''; @@ -529,7 +523,7 @@ class messenger } else { - $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, $this->eol, $err_msg); + $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, PHP_EOL, $err_msg); } if (!$result) @@ -686,10 +680,6 @@ class queue $this->data = array(); $this->cache_file = "{$phpbb_root_path}cache/queue.$phpEx"; - - // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) - $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; - $this->eol = (!$this->eol) ? "\n" : $this->eol; } /** @@ -822,7 +812,7 @@ class queue } else { - $result = phpbb_mail($to, $subject, $msg, $headers, $this->eol, $err_msg); + $result = phpbb_mail($to, $subject, $msg, $headers, PHP_EOL, $err_msg); } if (!$result) diff --git a/phpBB/includes/startup.php b/phpBB/includes/startup.php index 2885c80541..c90fd79366 100644 --- a/phpBB/includes/startup.php +++ b/phpBB/includes/startup.php @@ -19,10 +19,6 @@ if (!defined('IN_PHPBB')) } // Report all errors, except notices and deprecation messages -if (!defined('E_DEPRECATED')) -{ - define('E_DEPRECATED', 8192); -} $level = E_ALL & ~E_NOTICE & ~E_DEPRECATED; error_reporting($level); @@ -105,33 +101,21 @@ else define('STRIP', (get_magic_quotes_gpc()) ? true : false); } -// Prevent date/time functions from throwing E_WARNING on PHP 5.3 by setting a default timezone -if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) -{ - // For PHP 5.1.0 the date/time functions have been rewritten - // and setting a timezone is required prior to calling any date/time function. +// In PHP 5.3.0 the error level has been raised to E_WARNING which causes problems +// because we show E_WARNING errors and do not set a default timezone. +// This is because we have our own timezone handling and work in UTC only anyway. - // Since PHP 5.2.0 calls to date/time functions without having a timezone set - // result in E_STRICT errors being thrown. - // Note: We already exclude E_STRICT errors - // (to be exact: they are not included in E_ALL in PHP 5.2) +// So what we basically want to do is set our timezone to UTC, +// but we don't know what other scripts (such as bridges) are involved, +// so we check whether a timezone is already set by calling date_default_timezone_get(). - // In PHP 5.3.0 the error level has been raised to E_WARNING which causes problems - // because we show E_WARNING errors and do not set a default timezone. - // This is because we have our own timezone handling and work in UTC only anyway. +// Unfortunately, date_default_timezone_get() itself might throw E_WARNING +// if no timezone has been set, so we have to keep it quiet with @. - // So what we basically want to do is set our timezone to UTC, - // but we don't know what other scripts (such as bridges) are involved, - // so we check whether a timezone is already set by calling date_default_timezone_get(). - - // Unfortunately, date_default_timezone_get() itself might throw E_WARNING - // if no timezone has been set, so we have to keep it quiet with @. - - // date_default_timezone_get() tries to guess the correct timezone first - // and then falls back to UTC when everything fails. - // We just set the timezone to whatever date_default_timezone_get() returns. - date_default_timezone_set(@date_default_timezone_get()); -} +// date_default_timezone_get() tries to guess the correct timezone first +// and then falls back to UTC when everything fails. +// We just set the timezone to whatever date_default_timezone_get() returns. +date_default_timezone_set(@date_default_timezone_get()); // Autoloading of dependencies. // Three options are supported: @@ -168,5 +152,4 @@ else require($phpbb_root_path . 'vendor/autoload.php'); } -$starttime = explode(' ', microtime()); -$starttime = $starttime[1] + $starttime[0]; +$starttime = microtime(true); From 35d37fdff44365ccb01e1599759d2a5c02084184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88tan=20Muller?= Date: Sun, 11 Jan 2015 21:09:21 +0100 Subject: [PATCH 0081/1676] [ticket/13498] Update calls to `get_user_avatar()` PHPBB3-13498 --- phpBB/phpbb/user_loader.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/phpBB/phpbb/user_loader.php b/phpBB/phpbb/user_loader.php index 24e663b150..0b192e4452 100644 --- a/phpBB/phpbb/user_loader.php +++ b/phpBB/phpbb/user_loader.php @@ -175,7 +175,7 @@ class user_loader /** * Get avatar * - * @param int $user_id User ID of the user you want to retreive the avatar for + * @param int $user_id User ID of the user you want to retrieve the avatar for * @param bool $query Should we query the database if this user has not yet been loaded? * Typically this should be left as false and you should make sure * you load users ahead of time with load_users() @@ -188,12 +188,14 @@ class user_loader return ''; } - if (!function_exists('get_user_avatar')) - { - include($this->phpbb_root_path . 'includes/functions_display.' . $this->php_ext); - } + $row = array( + 'avatar' => $user['user_avatar'], + 'avatar_type' => $user['user_avatar_type'], + 'avatar_width' => $user['user_avatar_width'], + 'avatar_height' => $user['user_avatar_height'], + ); - return get_user_avatar($user['user_avatar'], $user['user_avatar_type'], $user['user_avatar_width'], $user['user_avatar_height']); + return phpbb_get_avatar($row, 'USER_AVATAR'); } /** From b5544b2f471ce4c93b08d19919ab062725545ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88tan=20Muller?= Date: Sat, 3 Jan 2015 11:39:29 +0100 Subject: [PATCH 0082/1676] [ticket/13450] Type-hint return value of $phpbb_container->get() PHPBB3-13450 --- phpBB/app.php | 3 +++ phpBB/bin/phpbbcli.php | 1 + phpBB/common.php | 2 ++ phpBB/cron.php | 2 ++ phpBB/download/file.php | 11 ++++++++++ phpBB/feed.php | 2 ++ phpBB/includes/acp/acp_attachments.php | 3 +++ phpBB/includes/acp/acp_board.php | 5 ++++- phpBB/includes/acp/acp_captcha.php | 1 + phpBB/includes/acp/acp_contact.php | 1 + phpBB/includes/acp/acp_forums.php | 1 + phpBB/includes/acp/acp_groups.php | 6 ++++-- phpBB/includes/acp/acp_icons.php | 3 ++- phpBB/includes/acp/acp_inactive.php | 2 ++ phpBB/includes/acp/acp_logs.php | 3 +++ phpBB/includes/acp/acp_main.php | 1 + phpBB/includes/acp/acp_permission_roles.php | 2 ++ phpBB/includes/acp/acp_permissions.php | 4 ++++ phpBB/includes/acp/acp_profile.php | 7 +++++++ phpBB/includes/acp/acp_update.php | 1 + phpBB/includes/acp/acp_users.php | 10 +++++++++- phpBB/includes/acp/auth.php | 4 ++++ phpBB/includes/compatibility_globals.php | 20 +++++++++++++++++++ phpBB/includes/functions.php | 12 ++++++++++- phpBB/includes/functions_admin.php | 3 +++ phpBB/includes/functions_compatibility.php | 3 +++ phpBB/includes/functions_display.php | 2 ++ phpBB/includes/functions_mcp.php | 1 + phpBB/includes/functions_posting.php | 7 ++++++- phpBB/includes/functions_privmsgs.php | 4 ++++ phpBB/includes/functions_user.php | 11 ++++++++++ phpBB/includes/mcp/mcp_forum.php | 2 ++ phpBB/includes/mcp/mcp_logs.php | 1 + phpBB/includes/mcp/mcp_main.php | 3 +++ phpBB/includes/mcp/mcp_notes.php | 2 ++ phpBB/includes/mcp/mcp_pm_reports.php | 4 +++- phpBB/includes/mcp/mcp_queue.php | 8 ++++++++ phpBB/includes/mcp/mcp_reports.php | 5 ++++- phpBB/includes/mcp/mcp_topic.php | 6 ++++-- phpBB/includes/mcp/mcp_warn.php | 3 ++- phpBB/includes/ucp/ucp_activate.php | 1 + phpBB/includes/ucp/ucp_attachments.php | 1 + phpBB/includes/ucp/ucp_auth_link.php | 1 + phpBB/includes/ucp/ucp_groups.php | 2 ++ phpBB/includes/ucp/ucp_login_link.php | 1 + phpBB/includes/ucp/ucp_main.php | 4 +++- phpBB/includes/ucp/ucp_notifications.php | 3 +++ phpBB/includes/ucp/ucp_pm_compose.php | 3 ++- phpBB/includes/ucp/ucp_pm_viewfolder.php | 1 + phpBB/includes/ucp/ucp_pm_viewmessage.php | 1 + phpBB/includes/ucp/ucp_profile.php | 3 +++ phpBB/includes/ucp/ucp_register.php | 4 ++++ phpBB/includes/ucp/ucp_remind.php | 1 + phpBB/index.php | 1 + .../install/convertors/functions_phpbb20.php | 1 + phpBB/install/database_update.php | 16 +++++++++++++++ phpBB/install/index.php | 9 +++++++++ phpBB/install/install_convert.php | 2 ++ phpBB/install/install_install.php | 4 ++++ phpBB/install/install_update.php | 4 ++++ phpBB/memberlist.php | 6 ++++++ phpBB/phpbb/auth/auth.php | 1 + phpBB/phpbb/auth/provider/db.php | 1 + .../migration/data/v30x/release_3_0_5_rc1.php | 1 + .../migration/profilefield_base_migration.php | 2 ++ phpBB/phpbb/session.php | 4 ++++ phpBB/posting.php | 4 ++++ phpBB/report.php | 1 + phpBB/search.php | 3 +++ phpBB/viewforum.php | 3 +++ phpBB/viewonline.php | 3 +++ phpBB/viewtopic.php | 3 +++ 72 files changed, 253 insertions(+), 14 deletions(-) diff --git a/phpBB/app.php b/phpBB/app.php index 10909f7103..4873fb10c3 100644 --- a/phpBB/app.php +++ b/phpBB/app.php @@ -27,7 +27,10 @@ $user->session_begin(); $auth->acl($user->data); $user->setup('app'); +/* @var $http_kernel \Symfony\Component\HttpKernel\HttpKernel */ $http_kernel = $phpbb_container->get('http_kernel'); + +/* @var $symfony_request \phpbb\symfony_request */ $symfony_request = $phpbb_container->get('symfony_request'); $response = $http_kernel->handle($symfony_request); $response->send(); diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index 14681e25ee..fc78e5d04a 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -64,6 +64,7 @@ $phpbb_container = $phpbb_container_builder->get_container(); $phpbb_container->get('request')->enable_super_globals(); require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx); +/* @var $user \phpbb\user */ $user = $phpbb_container->get('user'); $user->add_lang('acp/common'); $user->add_lang('cli'); diff --git a/phpBB/common.php b/phpBB/common.php index 2fa0c46b22..e6c2352113 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -120,6 +120,8 @@ require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx); // Add own hook handler require($phpbb_root_path . 'includes/hooks/index.' . $phpEx); $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display'))); + +/* @var $phpbb_hook_finder \phpbb\hook\finder */ $phpbb_hook_finder = $phpbb_container->get('hook_finder'); foreach ($phpbb_hook_finder->find() as $hook) diff --git a/phpBB/cron.php b/phpBB/cron.php index 3f022b1db8..56e27ad9c1 100644 --- a/phpBB/cron.php +++ b/phpBB/cron.php @@ -47,9 +47,11 @@ $cron_type = request_var('cron_type', ''); // Comment this line out for debugging so the page does not return an image. output_image(); +/* @var $cron_lock \phpbb\lock\db */ $cron_lock = $phpbb_container->get('cron.lock_db'); if ($cron_lock->acquire()) { + /* @var $cron \phpbb\cron\manager */ $cron = $phpbb_container->get('cron.manager'); $task = $cron->find_task($cron_type); diff --git a/phpBB/download/file.php b/phpBB/download/file.php index 4b8309c70e..047f5210df 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -71,27 +71,38 @@ if (isset($_GET['avatar'])) $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); // set up caching + /* @var $cache \phpbb\cache\service */ $cache = $phpbb_container->get('cache'); + /* @var $phpbb_dispatcher \phpbb\event\dispatcher */ $phpbb_dispatcher = $phpbb_container->get('dispatcher'); + + /* @var $request \phpbb\request\request_interface */ $request = $phpbb_container->get('request'); + + /* @var $db \phpbb\db\driver\driver_interface */ $db = $phpbb_container->get('dbal.conn'); + + /* @var $phpbb_log \phpbb\log\log_interface */ $phpbb_log = $phpbb_container->get('log'); unset($dbpasswd); request_var('', 0, false, false, $request); + /* @var $config \phpbb\config\config */ $config = $phpbb_container->get('config'); set_config(null, null, null, $config); set_config_count(null, null, null, $config); // load extensions + /* @var $phpbb_extension_manager \phpbb\extension\manager */ $phpbb_extension_manager = $phpbb_container->get('ext.manager'); // worst-case default $browser = strtolower($request->header('User-Agent', 'msie 6.0')); + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $filename = request_var('avatar', ''); diff --git a/phpBB/feed.php b/phpBB/feed.php index e0c0b01db6..75877efd04 100644 --- a/phpBB/feed.php +++ b/phpBB/feed.php @@ -65,10 +65,12 @@ if ($forum_id || $topic_id || $mode) } // This boards URL +/* @var $phpbb_feed_helper \phpbb\feed\helper */ $phpbb_feed_helper = $phpbb_container->get('feed.helper'); $board_url = $phpbb_feed_helper->get_board_url(); // Get correct feed object +/* @var $phpbb_feed_factory \phpbb\feed\factory */ $phpbb_feed_factory = $phpbb_container->get('feed.factory'); $feed = $phpbb_feed_factory->get_feed($mode, $forum_id, $topic_id); diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 2372c1f73c..6e3000d8e6 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -1147,6 +1147,7 @@ class acp_attachments $total_size = $stats['upload_dir_size']; // Make sure $start is set to the last page if it exceeds the amount + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $start = $pagination->validate_start($start, $attachments_per_page, $num_files); @@ -1346,6 +1347,8 @@ class acp_attachments else { $this->set_attachment_stats($this->get_attachment_stats()); + + /* @var $log \phpbb\log\log_interface */ $log = $this->phpbb_container->get('log'); $log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_RESYNC_FILES_STATS'); } diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 63e2647f02..3893091f17 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -115,6 +115,7 @@ class acp_board break; case 'avatar': + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_all_drivers(); @@ -553,6 +554,7 @@ class acp_board if ($mode == 'auth') { // Retrieve a list of auth plugins and check their config values + /* @var $auth_providers \phpbb\auth\provider_collection */ $auth_providers = $phpbb_container->get('auth.provider_collection'); $updated_auth_settings = false; @@ -720,8 +722,9 @@ class acp_board { global $phpbb_root_path, $phpEx, $phpbb_container; - $auth_plugins = array(); + /* @var $auth_providers \phpbb\auth\provider_collection */ $auth_providers = $phpbb_container->get('auth.provider_collection'); + $auth_plugins = array(); foreach ($auth_providers as $key => $value) { diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index fa8d8fb6a9..19cd609c73 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -30,6 +30,7 @@ class acp_captcha $user->add_lang('acp/board'); + /* @var $factory \phpbb\captcha\factory */ $factory = $phpbb_container->get('captcha.factory'); $captchas = $factory->get_captcha_types(); diff --git a/phpBB/includes/acp/acp_contact.php b/phpBB/includes/acp/acp_contact.php index 4e46df21e0..2aa6620835 100644 --- a/phpBB/includes/acp/acp_contact.php +++ b/phpBB/includes/acp/acp_contact.php @@ -48,6 +48,7 @@ class acp_contact include($phpbb_root_path . 'includes/message_parser.' . $phpEx); } + /* @var $config_text \phpbb\config\db_text */ $config_text = $phpbb_container->get('config_text'); $contact_admin_data = $config_text->get_array(array( diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index adf5de44f5..fd9d70f679 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -1050,6 +1050,7 @@ class acp_forums else { // Instantiate passwords manager + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); $forum_data_sql['forum_password'] = $passwords_manager->hash($forum_data_sql['forum_password']); diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index edfada1bf1..1293c92509 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -320,6 +320,7 @@ class acp_groups if ($config['allow_avatar']) { + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); @@ -801,8 +802,9 @@ class acp_groups trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); } - $this->page_title = 'GROUP_MEMBERS'; + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $this->page_title = 'GROUP_MEMBERS'; // Grab the leaders - always, on every page... $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_colour, u.user_posts, u.group_id, ug.group_leader, ug.user_pending @@ -989,7 +991,7 @@ class acp_groups } else if ($field && in_array($field, array('legend', 'teampage'))) { - + /* @var $group_position \phpbb\groupposition\groupposition_interface */ $group_position = $phpbb_container->get('groupposition.' . $field); } diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index 9265415dd1..ebdacfe0b8 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -903,9 +903,10 @@ class acp_icons ) ); - $spacer = false; + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $pagination_start = request_var('start', 0); + $spacer = false; $item_count = $this->item_count($table); diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index e96c42de05..9e681b9181 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -50,6 +50,8 @@ class acp_inactive $form_key = 'acp_inactive'; add_form_key($form_key); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // We build the sort key and per page settings here, because they may be needed later diff --git a/phpBB/includes/acp/acp_logs.php b/phpBB/includes/acp/acp_logs.php index 80dee1d620..642b05b08b 100644 --- a/phpBB/includes/acp/acp_logs.php +++ b/phpBB/includes/acp/acp_logs.php @@ -47,6 +47,8 @@ class acp_logs $this->tpl_name = 'acp_logs'; $this->log_type = constant('LOG_' . strtoupper($mode)); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // Delete entries if requested and able @@ -72,6 +74,7 @@ class acp_logs $conditions['keywords'] = $keywords; } + /* @var $phpbb_log \phpbb\log\log_interface */ $phpbb_log = $phpbb_container->get('log'); $phpbb_log->delete($mode, $conditions); } diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 48ca05a118..6cd2468f6d 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -429,6 +429,7 @@ class acp_main )); } + /* @var $version_helper \phpbb\version_helper */ $version_helper = $phpbb_container->get('version_helper'); try { diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php index cd3616208d..6c5650fe5e 100644 --- a/phpBB/includes/acp/acp_permission_roles.php +++ b/phpBB/includes/acp/acp_permission_roles.php @@ -299,6 +299,7 @@ class acp_permission_roles trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); } + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); $template->assign_vars(array( @@ -471,6 +472,7 @@ class acp_permission_roles { global $template, $user, $phpbb_container; + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); $content_array = $categories = array(); diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index cb408e304f..0010c6e4a4 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -23,6 +23,10 @@ class acp_permissions { var $u_action; var $permission_dropdown; + + /** + * @var $phpbb_permissions \phpbb\permissions + */ protected $permissions; function main($id, $mode) diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 046281596c..c85cc2a67d 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -25,6 +25,10 @@ class acp_profile var $edit_lang_id; var $lang_defs; + + /** + * @var \phpbb\di\service_collection + */ protected $type_collection; function main($id, $mode) @@ -51,6 +55,7 @@ class acp_profile trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); } + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $this->type_collection = $phpbb_container->get('profilefields.type_collection'); @@ -112,6 +117,7 @@ class acp_profile $db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id"); $db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id"); + /* @var $db_tools \phpbb\db\tools */ $db_tools = $phpbb_container->get('dbal.tools'); $db_tools->sql_column_remove(PROFILE_FIELDS_DATA_TABLE, 'pf_' . $field_ident); @@ -881,6 +887,7 @@ class acp_profile { $field_ident = 'pf_' . $field_ident; + /* @var $db_tools \phpbb\db\tools */ $db_tools = $phpbb_container->get('dbal.tools'); $db_tools->sql_column_add(PROFILE_FIELDS_DATA_TABLE, $field_ident, array($profile_field->get_database_column_type(), null)); } diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php index 0167a06dbb..83604b8261 100644 --- a/phpBB/includes/acp/acp_update.php +++ b/phpBB/includes/acp/acp_update.php @@ -33,6 +33,7 @@ class acp_update $this->tpl_name = 'acp_update'; $this->page_title = 'ACP_VERSION_CHECK'; + /* @var $version_helper \phpbb\version_helper */ $version_helper = $phpbb_container->get('version_helper'); try { diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index d28a083292..4e7576c875 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -418,6 +418,7 @@ class acp_users { if ($config['require_activation'] == USER_ACTIVATION_ADMIN) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); @@ -481,6 +482,7 @@ class acp_users } // Delete old avatar if present + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $phpbb_avatar_manager->handle_avatar_delete($db, $user, $phpbb_avatar_manager->clean_row($user_row, 'user'), USERS_TABLE, 'user_'); @@ -831,6 +833,7 @@ class acp_users } // Instantiate passwords manager + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); // Which updates do we need to do? @@ -1105,6 +1108,8 @@ class acp_users $deleteall = (isset($_POST['delall'])) ? true : false; $marked = request_var('mark', array(0)); $message = utf8_normalize_nfc(request_var('message', '', true)); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // Sort keys @@ -1347,6 +1352,7 @@ class acp_users include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $cp_data = $cp_error = array(); @@ -1741,6 +1747,7 @@ class acp_users if ($config['allow_avatar']) { + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); @@ -1986,11 +1993,12 @@ class acp_users break; case 'attach': + /* @var $pagination \phpbb\pagination */ + $pagination = $phpbb_container->get('pagination'); $start = request_var('start', 0); $deletemark = (isset($_POST['delmarked'])) ? true : false; $marked = request_var('mark', array(0)); - $pagination = $phpbb_container->get('pagination'); // Sort keys $sort_key = request_var('sk', 'a'); diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index 905e981cdc..644b1ac7a5 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -267,6 +267,8 @@ class auth_admin extends \phpbb\auth\auth function display_mask($mode, $permission_type, &$hold_ary, $user_mode = 'user', $local = false, $group_display = true) { global $template, $user, $db, $phpbb_root_path, $phpEx, $phpbb_container; + + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); // Define names for template loops, might be able to be set @@ -1108,6 +1110,7 @@ class auth_admin extends \phpbb\auth\auth { global $template, $user, $phpbb_admin_path, $phpEx, $phpbb_container; + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); @reset($category_array); @@ -1186,6 +1189,7 @@ class auth_admin extends \phpbb\auth\auth { global $user, $phpbb_container; + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); foreach ($key_sort_array as $forum_id) diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php index 54c9287c96..8d91d60b62 100644 --- a/phpBB/includes/compatibility_globals.php +++ b/phpBB/includes/compatibility_globals.php @@ -19,29 +19,49 @@ if (!defined('IN_PHPBB')) } // set up caching +/* @var $cache \phpbb\cache\service */ $cache = $phpbb_container->get('cache'); // Instantiate some basic classes +/* @var $phpbb_dispatcher \phpbb\event\dispatcher */ $phpbb_dispatcher = $phpbb_container->get('dispatcher'); + +/* @var $request \phpbb\request\request_interface */ $request = $phpbb_container->get('request'); + +/* @var $user \phpbb\user */ $user = $phpbb_container->get('user'); + +/* @var $auth \phpbb\auth\auth */ $auth = $phpbb_container->get('auth'); + +/* @var $db \phpbb\db\driver\driver_interface */ $db = $phpbb_container->get('dbal.conn'); // make sure request_var uses this request instance request_var('', 0, false, false, $request); // "dependency injection" for a function // Grab global variables, re-cache if necessary +/* @var $config phpbb\config\db */ $config = $phpbb_container->get('config'); set_config(null, null, null, $config); set_config_count(null, null, null, $config); +/* @var $phpbb_log \phpbb\log\log_interface */ $phpbb_log = $phpbb_container->get('log'); + +/* @var $symfony_request \phpbb\symfony_request */ $symfony_request = $phpbb_container->get('symfony_request'); + +/* @var $phpbb_filesystem \phpbb\filesystem */ $phpbb_filesystem = $phpbb_container->get('filesystem'); + +/* @var $phpbb_path_helper \phpbb\path_helper */ $phpbb_path_helper = $phpbb_container->get('path_helper'); // load extensions +/* @var $phpbb_extension_manager \phpbb\extension\manager */ $phpbb_extension_manager = $phpbb_container->get('ext.manager'); +/* @var $template \phpbb\template\template */ $template = $phpbb_container->get('template'); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 321394639b..212630a101 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1159,7 +1159,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ if ($forum_id === false || !sizeof($forum_id)) { // Mark all forums read (index page) - + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); // Mark all topic notifications read for this user @@ -1226,6 +1226,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $forum_id = array($forum_id); } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->mark_notifications_read_by_parent(array( @@ -1348,6 +1349,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ return; } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); // Mark post notifications read for this user in this topic @@ -1799,6 +1801,7 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti // Handle update of unapproved topics info. // Only update for moderators having m_approve permission for the forum. + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // Check the forum for any left unread topics. @@ -2954,6 +2957,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa $s_hidden_fields['credential'] = $credential; } + /* @var $provider_collection \phpbb\auth\provider_collection */ $provider_collection = $phpbb_container->get('auth.provider_collection'); $auth_provider = $provider_collection->get_provider(); @@ -3057,6 +3061,7 @@ function login_forum_box($forum_data) } $db->sql_freeresult($result); + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); if ($passwords_manager->check($password, $forum_data['forum_password'])) @@ -4746,6 +4751,7 @@ function phpbb_get_avatar($row, $alt, $ignore_config = false) 'height' => $row['avatar_height'], ); + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $driver = $phpbb_avatar_manager->get_driver($row['avatar_type'], $ignore_config); $html = ''; @@ -4931,6 +4937,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = // This path is sent with the base template paths in the assign_vars() // call below. We need to correct it in case we are accessing from a // controller because the web paths will be incorrect otherwise. + /* @var $phpbb_path_helper \phpbb\path_helper */ $phpbb_path_helper = $phpbb_container->get('path_helper'); $corrected_path = $phpbb_path_helper->get_web_root_path(); $web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $corrected_path; @@ -4969,6 +4976,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = $notifications = false; if ($config['load_notifications'] && $user->data['user_id'] != ANONYMOUS && $user->data['user_type'] != USER_IGNORE) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $notifications = $phpbb_notifications->load_notifications(array( @@ -5299,6 +5307,8 @@ function page_footer($run_cron = true, $display_template = true, $exit_handler = if ($call_cron) { global $phpbb_container; + + /* @var $cron \phpbb\cron\manager */ $cron = $phpbb_container->get('cron.manager'); $task = $cron->find_one_ready_task(); diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index b016659541..cfd5aaa0c5 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -715,6 +715,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s set_config_count('num_topics', $approved_topics * (-1), true); } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications(array( @@ -979,6 +980,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false); } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications($delete_notifications_types, $post_ids); @@ -3005,6 +3007,7 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port global $phpbb_container; // Get file downloader and assign $errstr and $errno + /* @var $file_downloader \phpbb\file_downloader */ $file_downloader = $phpbb_container->get('file_downloader'); $file_data = $file_downloader->get($host, $directory, $filename, $port, $timeout); diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 43952ae57a..c2da02456b 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -59,6 +59,7 @@ function phpbb_hash($password) { global $phpbb_container; + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); return $passwords_manager->hash($password); } @@ -77,6 +78,7 @@ function phpbb_check_hash($password, $hash) { global $phpbb_container; + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); return $passwords_manager->check($password, $hash); } @@ -97,6 +99,7 @@ function phpbb_clean_path($path) if (!$phpbb_path_helper && $phpbb_container) { + /* @var $phpbb_path_helper \phpbb\path_helper */ $phpbb_path_helper = $phpbb_container->get('path_helper'); } else if (!$phpbb_path_helper) diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 31cf43e599..2810a23c05 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -153,6 +153,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $forum_tracking_info = array(); $branch_root_id = $root_data['forum_id']; + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); while ($row = $db->sql_fetchrow($result)) @@ -1134,6 +1135,7 @@ function display_user_activity(&$userdata) $active_f_row = $active_t_row = array(); if (!empty($forum_ary)) { + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // Obtain active forum diff --git a/phpBB/includes/functions_mcp.php b/phpBB/includes/functions_mcp.php index 811d49f1de..8d09a3dea2 100644 --- a/phpBB/includes/functions_mcp.php +++ b/phpBB/includes/functions_mcp.php @@ -301,6 +301,7 @@ function phpbb_get_forum_data($forum_id, $acl_list = 'f_list', $read_tracking = WHERE " . $db->sql_in_set('f.forum_id', $forum_id); $result = $db->sql_query($sql); + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); while ($row = $db->sql_fetchrow($result)) diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 22ade15b48..199a564210 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -27,8 +27,9 @@ function generate_smilies($mode, $forum_id) global $db, $user, $config, $template, $phpbb_dispatcher; global $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_path_helper; - $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id); $start = request_var('start', 0); if ($mode == 'window') @@ -1039,6 +1040,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id global $user, $auth, $db, $template, $bbcode, $cache; global $config, $phpbb_root_path, $phpEx, $phpbb_container; + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $sql_sort = ($mode == 'post_review') ? 'ASC' : 'DESC'; @@ -1276,6 +1278,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ $db->sql_freeresult($result); } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // (Soft) delete the post @@ -2094,6 +2097,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED); $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED); + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $phpbb_content_visibility->set_post_visibility($post_visibility, $data['post_id'], $data['topic_id'], $data['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest); } @@ -2272,6 +2276,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'post_subject' => $subject, )); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); if ($post_visibility == ITEM_APPROVED) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 838c6a0fec..2bc5ef5afc 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -881,6 +881,7 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id) global $db, $user, $phpbb_container; + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->mark_notifications_read('notification.type.pm', $msg_id, $user_id); @@ -1130,6 +1131,7 @@ function delete_pm($user_id, $msg_ids, $folder_id) $user->data['user_unread_privmsg'] -= $num_unread; } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.pm', array_keys($delete_rows)); @@ -1243,6 +1245,7 @@ function phpbb_delete_users_pms($user_ids) $db->sql_transaction('begin'); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); if (!empty($undelivered_msg)) @@ -1925,6 +1928,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) 'recipients' => $recipients, )); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); if ($mode == 'edit') diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index f79a8998c4..191c61cf80 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -281,6 +281,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) { $cp_data['user_id'] = (int) $user_id; + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $cp->build_insert_sql_array($cp_data)); @@ -366,6 +367,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) // Subscribe user to notifications if necessary if (!empty($notifications_data)) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); foreach ($notifications_data as $subscription) { @@ -2249,8 +2251,12 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow $current_legend = \phpbb\groupposition\legend::GROUP_DISABLED; $current_teampage = \phpbb\groupposition\teampage::GROUP_DISABLED; + /* @var $legend \phpbb\groupposition\legend */ $legend = $phpbb_container->get('groupposition.legend'); + + /* @var $teampage \phpbb\groupposition\teampage */ $teampage = $phpbb_container->get('groupposition.teampage'); + if ($group_id) { try @@ -2564,6 +2570,7 @@ function group_delete($group_id, $group_name = false) // Delete group from legend and teampage try { + /* @var $legend \phpbb\groupposition\legend */ $legend = $phpbb_container->get('groupposition.legend'); $legend->delete_group($group_id); unset($legend); @@ -2577,6 +2584,7 @@ function group_delete($group_id, $group_name = false) try { + /* @var $teampage \phpbb\groupposition\teampage */ $teampage = $phpbb_container->get('groupposition.teampage'); $teampage->delete_group($group_id); unset($teampage); @@ -2720,6 +2728,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, if ($pending) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); foreach ($add_id_ary as $user_id) @@ -2879,6 +2888,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, group_update_listings($group_id); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.group_request', $user_id_ary, $group_id); @@ -3043,6 +3053,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna AND " . $db->sql_in_set('user_id', $user_id_ary); $db->sql_query($sql); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->add_notifications('notification.type.group_request_approved', array( diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index c18ca1aa1d..8d2cc478f3 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -77,6 +77,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) break; } + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $selected_ids = ''; @@ -157,6 +158,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) $read_tracking_join = $read_tracking_select = ''; } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $sql = 'SELECT t.topic_id diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php index 9c76f0df90..db55010adb 100644 --- a/phpBB/includes/mcp/mcp_logs.php +++ b/phpBB/includes/mcp/mcp_logs.php @@ -65,6 +65,7 @@ class mcp_logs $this->tpl_name = 'mcp_logs'; $this->page_title = 'MCP_LOGS'; + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_'))); diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 227ae84bd6..bb3f8c3d2e 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -703,6 +703,7 @@ function mcp_restore_topic($topic_ids) $data = phpbb_get_topic_data($topic_ids); + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); foreach ($data as $topic_id => $row) { @@ -788,6 +789,7 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' // Only soft delete non-shadow topics if ($is_soft) { + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $return = $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), $soft_delete_reason); if (!empty($return)) @@ -948,6 +950,7 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', ); } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); foreach ($topic_info as $topic_id => $topic_data) { diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php index 465ee63a98..dd7a61fb53 100644 --- a/phpBB/includes/mcp/mcp_notes.php +++ b/phpBB/includes/mcp/mcp_notes.php @@ -83,6 +83,8 @@ class mcp_notes $st = request_var('st', 0); $sk = request_var('sk', 'b'); $sd = request_var('sd', 'd'); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); add_form_key('mcp_notes'); diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php index d76bedba98..bd0edafa84 100644 --- a/phpBB/includes/mcp/mcp_pm_reports.php +++ b/phpBB/includes/mcp/mcp_pm_reports.php @@ -41,8 +41,9 @@ class mcp_pm_reports include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); - $start = request_var('start', 0); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $start = request_var('start', 0); $this->page_title = 'MCP_PM_REPORTS'; @@ -93,6 +94,7 @@ class mcp_pm_reports trigger_error('NO_REPORT'); } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->mark_notifications_read_by_parent('notification.type.report_pm', $report_id, $user->data['user_id']); diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index f9c00da3ec..d4bb9e402f 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -156,6 +156,7 @@ class mcp_queue $post_id = request_var('p', 0); $topic_id = request_var('t', 0); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); if ($topic_id) @@ -340,6 +341,8 @@ class mcp_queue $topic_id = $request->variable('t', 0); $forum_info = array(); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); if ($topic_id) @@ -679,6 +682,7 @@ class mcp_queue ); } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); foreach ($topic_info as $topic_id => $topic_data) { @@ -693,6 +697,7 @@ class mcp_queue // Only send out the mails, when the posts are being approved if ($action == 'approve') { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); // Handle notifications @@ -866,6 +871,7 @@ class mcp_queue { $notify_poster = ($action == 'approve' && isset($_REQUEST['notify_poster'])) ? true : false; + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $first_post_ids = array(); @@ -909,6 +915,7 @@ class mcp_queue $db->sql_freeresult($result); // Handle notifications + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); foreach ($topic_info as $topic_id => $topic_data) @@ -1168,6 +1175,7 @@ class mcp_queue } } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $lang_reasons = array(); diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 804d48ea97..26f6a532c9 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -90,6 +90,7 @@ class mcp_reports trigger_error('NO_REPORT'); } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->mark_notifications_read('notification.type.report_post', $post_id, $user->data['user_id']); @@ -323,9 +324,10 @@ class mcp_reports $forum_list = array($forum_id); } + /* @var $pagination \phpbb\pagination */ + $pagination = $phpbb_container->get('pagination'); $forum_list[] = 0; $forum_data = array(); - $pagination = $phpbb_container->get('pagination'); $forum_options = ''; foreach ($forum_list_reports as $row) @@ -645,6 +647,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) } unset($close_report_posts, $close_report_topics); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); foreach ($reports as $report) diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 1698b080c9..08002fa952 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -29,8 +29,9 @@ function mcp_topic_view($id, $mode, $action) $url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . phpbb_extra_url()); - $user->add_lang('viewtopic'); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $user->add_lang('viewtopic'); $topic_id = request_var('t', 0); $topic_info = phpbb_get_topic_data(array($topic_id), false, true); @@ -116,8 +117,9 @@ function mcp_topic_view($id, $mode, $action) $sort_by_sql = $sort_order_sql = array(); phpbb_mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $topic_info['forum_id'], $topic_id, $where_sql); - $limit_time_sql = ($sort_days) ? 'AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); + $limit_time_sql = ($sort_days) ? 'AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; if ($total == -1) { diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php index d724b8703b..7c0bb12250 100644 --- a/phpBB/includes/mcp/mcp_warn.php +++ b/phpBB/includes/mcp/mcp_warn.php @@ -134,8 +134,9 @@ class mcp_warn global $phpEx, $phpbb_root_path, $config, $phpbb_container; global $template, $db, $user, $auth; - $user->add_lang('memberlist'); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $user->add_lang('memberlist'); $start = request_var('start', 0); $st = request_var('st', 0); diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 6e357b260a..bc44d70e3e 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -110,6 +110,7 @@ class ucp_activate if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !$update_password) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); diff --git a/phpBB/includes/ucp/ucp_attachments.php b/phpBB/includes/ucp/ucp_attachments.php index 42724209aa..1b17425c1f 100644 --- a/phpBB/includes/ucp/ucp_attachments.php +++ b/phpBB/includes/ucp/ucp_attachments.php @@ -123,6 +123,7 @@ class ucp_attachments $db->sql_freeresult($result); // Ensure start is a valid value + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $start = $pagination->validate_start($start, $config['topics_per_page'], $num_attachments); diff --git a/phpBB/includes/ucp/ucp_auth_link.php b/phpBB/includes/ucp/ucp_auth_link.php index 748f0fdec2..08aacdef3a 100644 --- a/phpBB/includes/ucp/ucp_auth_link.php +++ b/phpBB/includes/ucp/ucp_auth_link.php @@ -38,6 +38,7 @@ class ucp_auth_link $error = array(); + /* @var $provider_collection \phpbb\auth\provider_collection */ $provider_collection = $phpbb_container->get('auth.provider_collection'); $auth_provider = $provider_collection->get_provider(); diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index b9606945b4..6f4ad0a502 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -464,6 +464,7 @@ class ucp_groups if ($config['allow_avatar']) { + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); @@ -826,6 +827,7 @@ class ucp_groups $s_action_options .= ''; } + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $base_url = $this->u_action . "&action=$action&g=$group_id"; $start = $pagination->validate_start($start, $config['topics_per_page'], $total_members); diff --git a/phpBB/includes/ucp/ucp_login_link.php b/phpBB/includes/ucp/ucp_login_link.php index bfe4804286..902fbaafcf 100644 --- a/phpBB/includes/ucp/ucp_login_link.php +++ b/phpBB/includes/ucp/ucp_login_link.php @@ -57,6 +57,7 @@ class ucp_login_link } // Use the auth_provider requested even if different from configured + /* @var $provider_collection \phpbb\auth\provider_collection */ $provider_collection = $phpbb_container->get('auth.provider_collection'); $auth_provider = $provider_collection->get_provider($request->variable('auth_provider', '')); diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index a1624e78ec..b49f4d2ea0 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -645,9 +645,10 @@ class ucp_main { global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx, $phpbb_container; + /* @var $pagination \phpbb\pagination */ + $pagination = $phpbb_container->get('pagination'); $table = ($mode == 'subscribed') ? TOPICS_WATCH_TABLE : BOOKMARKS_TABLE; $start = request_var('start', 0); - $pagination = $phpbb_container->get('pagination'); // Grab icons $icons = $cache->obtain_icons(); @@ -769,6 +770,7 @@ class ucp_main } } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); foreach ($topic_list as $topic_id) diff --git a/phpBB/includes/ucp/ucp_notifications.php b/phpBB/includes/ucp/ucp_notifications.php index b0aeaba227..b778ffdf12 100644 --- a/phpBB/includes/ucp/ucp_notifications.php +++ b/phpBB/includes/ucp/ucp_notifications.php @@ -34,7 +34,10 @@ class ucp_notifications $form_time = $request->variable('form_time', 0); $form_time = ($form_time <= 0 || $form_time > time()) ? time() : $form_time; + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); switch ($mode) diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index f3b59186a6..fabcb54170 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -458,8 +458,9 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $icon_id = 0; } - $message_parser = new parse_message(); + /* @var $plupload \phpbb\plupload\plupload */ $plupload = $phpbb_container->get('plupload'); + $message_parser = new parse_message(); $message_parser->set_plupload($plupload); $message_parser->message = ($action == 'reply') ? '' : $message_text; diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index 19acd9ecb9..7b9b834ebe 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -406,6 +406,7 @@ function get_pm_from($folder_id, $folder, $user_id) $sort_key = request_var('sk', 't'); $sort_dir = request_var('sd', 'd'); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // PM ordering options diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index 888c2e6825..6fa80cb64d 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -65,6 +65,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) // Load the custom profile fields if ($config['load_cpf_pm']) { + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $profile_fields = $cp->grab_profile_fields_data($author_id); diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index a36b67f515..d230f3865f 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -84,6 +84,7 @@ class ucp_profile } // Instantiate passwords manager + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); // Only check the new password against the previous password if there have been no errors @@ -261,6 +262,7 @@ class ucp_profile trigger_error('NO_AUTH_PROFILEINFO'); } + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $cp_data = $cp_error = array(); @@ -520,6 +522,7 @@ class ucp_profile if ($config['allow_avatar'] && $auth->acl_get('u_chgavatar')) { + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 14f6a8bc02..0ff3028e75 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -77,6 +77,7 @@ class ucp_register } } + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $error = $cp_data = $cp_error = array(); @@ -88,6 +89,7 @@ class ucp_register if (!empty($login_link_data)) { // Confirm that we have all necessary data + /* @var $provider_collection \phpbb\auth\provider_collection */ $provider_collection = $phpbb_container->get('auth.provider_collection'); $auth_provider = $provider_collection->get_provider($request->variable('auth_provider', '')); @@ -298,6 +300,7 @@ class ucp_register } // Instantiate passwords manager + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); $user_row = array( @@ -389,6 +392,7 @@ class ucp_register if ($config['require_activation'] == USER_ACTIVATION_ADMIN) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->add_notifications('notification.type.admin_activate_user', array( 'user_id' => $user_id, diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php index 415bf0e84d..8c96955b14 100644 --- a/phpBB/includes/ucp/ucp_remind.php +++ b/phpBB/includes/ucp/ucp_remind.php @@ -92,6 +92,7 @@ class ucp_remind $user_actkey = gen_rand_string(mt_rand(6, 10)); // Instantiate passwords manager + /* @var $manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); $sql = 'UPDATE ' . USERS_TABLE . " diff --git a/phpBB/index.php b/phpBB/index.php index df6932f6c0..132cbd444f 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -42,6 +42,7 @@ if (($mark_notification = $request->variable('mark_notification', 0))) if (check_link_hash($request->variable('hash', ''), 'mark_notification_read')) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $notification = $phpbb_notifications->load_notifications(array( diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php index 7794b5ca67..089c569280 100644 --- a/phpBB/install/convertors/functions_phpbb20.php +++ b/phpBB/install/convertors/functions_phpbb20.php @@ -1974,6 +1974,7 @@ function phpbb_convert_password_hash($hash) { global $phpbb_container; + /* @var $manager \phpbb\passwords\manager */ $manager = $phpbb_container->get('passwords.manager'); $hash = $manager->hash($hash, '$H$'); diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 0dc86c2051..c5ddf9e6e9 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -87,20 +87,33 @@ $phpbb_container_builder->set_dump_container(false); $phpbb_container = $phpbb_container_builder->get_container(); // set up caching +/* @var $cache \phpbb\cache\service */ $cache = $phpbb_container->get('cache'); // Instantiate some basic classes +/* @var $phpbb_dispatcher \phpbb\event\dispatcher */ $phpbb_dispatcher = $phpbb_container->get('dispatcher'); + +/* @var $request \phpbb\request\request_interface */ $request = $phpbb_container->get('request'); + +/* @var $user \phpbb\user */ $user = $phpbb_container->get('user'); + +/* @var $auth \phpbb\auth\auth */ $auth = $phpbb_container->get('auth'); + +/* @var $db \phpbb\db\driver\driver_interface */ $db = $phpbb_container->get('dbal.conn'); + +/* @var $phpbb_log \phpbb\log\log_interface */ $phpbb_log = $phpbb_container->get('log'); // make sure request_var uses this request instance request_var('', 0, false, false, $request); // "dependency injection" for a function // Grab global variables, re-cache if necessary +/* @var $config \phpbb\config\config */ $config = $phpbb_container->get('config'); set_config(null, null, null, $config); set_config_count(null, null, null, $config); @@ -120,6 +133,7 @@ if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx)) require($phpbb_root_path . 'includes/hooks/index.' . $phpEx); $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display'))); + /* @var $phpbb_hook_finder \phpbb\hook\finder */ $phpbb_hook_finder = $phpbb_container->get('hook_finder'); foreach ($phpbb_hook_finder->find() as $hook) { @@ -172,11 +186,13 @@ define('IN_DB_UPDATE', true); // End startup code +/* @var $migrator \phpbb\db\migrator */ $migrator = $phpbb_container->get('migrator'); $migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($user, new \phpbb\db\html_migrator_output_handler($user), $phpbb_root_path . 'store/migrations_' . time() . '.log')); $migrator->create_migrations_table(); +/* @var $phpbb_extension_manager \phpbb\extension\manager */ $phpbb_extension_manager = $phpbb_container->get('ext.manager'); $migrations = $phpbb_extension_manager diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 1cc588071b..495f49ee49 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -143,7 +143,10 @@ $phpbb_container->compile(); $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); +/* @var $phpbb_dispatcher \phpbb\event\dispatcher */ $phpbb_dispatcher = $phpbb_container->get('dispatcher'); + +/* @var $request \phpbb\request\request_interface */ $request = $phpbb_container->get('request'); // make sure request_var uses this request instance @@ -250,6 +253,7 @@ if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx)) require($phpbb_root_path . 'includes/hooks/index.' . $phpEx); $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display'))); + /* @var $phpbb_hook_finder \phpbb\hook\finder */ $phpbb_hook_finder = $phpbb_container->get('hook_finder'); foreach ($phpbb_hook_finder->find() as $hook) { @@ -266,8 +270,13 @@ $config = new \phpbb\config\config(array( 'load_tplcompile' => '1' )); +/* @var $symfony_request \phpbb\symfony_request */ $symfony_request = $phpbb_container->get('symfony_request'); + +/* @var $phpbb_filesystem \phpbb\filesystem */ $phpbb_filesystem = $phpbb_container->get('filesystem'); + +/* @var $phpbb_path_helper \phpbb\path_helper */ $phpbb_path_helper = $phpbb_container->get('path_helper'); $cache_path = $phpbb_root_path . 'cache/'; diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index 6a892a7373..40defe754a 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -131,6 +131,7 @@ class install_convert extends module $phpbb_container = $phpbb_container_builder->get_container(); // Create cache + /* @var $cache \phpbb\cache\service */ $cache = $phpbb_container->get('cache'); switch ($sub) @@ -1603,6 +1604,7 @@ class install_convert extends module phpbb_cache_moderators($db, $cache, $auth); // And finally, add a note to the log + /* @var $phpbb_log \phpbb\log\log_interface */ $phpbb_log = $phpbb_container->get('log'); add_log('admin', 'LOG_INSTALL_CONVERTED', $convert->convertor_data['forum_name'], $config['version']); diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index a55121f6aa..500992feac 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -108,7 +108,10 @@ class install_install extends module $phpbb_container = $phpbb_container_builder->get_container(); // Sets the global variables + /* @var $cache \phpbb\cache\service */ $cache = $phpbb_container->get('cache'); + + /* @var $phpbb_log \phpbb\log\log_interface */ $phpbb_log = $phpbb_container->get('log'); $this->build_search_index($mode, $sub); @@ -1517,6 +1520,7 @@ class install_install extends module // modules require an extension manager if (empty($phpbb_extension_manager)) { + /* @var $phpbb_extension_manager \phpbb\extension\manager */ $phpbb_extension_manager = $phpbb_container->get('ext.manager'); } diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index bd8d3751e1..8f233b7efe 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -84,6 +84,7 @@ class install_update extends module $phpbb_container = $phpbb_container_builder->get_container(); // Writes into global $cache + /* @var $cache \phpbb\cache\service */ $cache = $phpbb_container->get('cache'); $this->tpl_name = 'install_update'; @@ -161,6 +162,7 @@ class install_update extends module )); // Get current and latest version + /* @var $version_helper \phpbb\version_helper */ $version_helper = $phpbb_container->get('version_helper'); try { @@ -519,6 +521,8 @@ class install_update extends module if ($all_up_to_date) { global $phpbb_container; + + /* @var $phpbb_log \phpbb\log\log_interface */ $phpbb_log = $phpbb_container->get('log'); // Add database update to log diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index e64dab635b..10301a75ae 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -638,6 +638,7 @@ switch ($mode) $profile_fields = array(); if ($config['load_cpf_viewprofile']) { + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $profile_fields = $cp->grab_profile_fields_data($user_id); $profile_fields = (isset($profile_fields[$user_id])) ? $cp->generate_profile_fields_template_data($profile_fields[$user_id]) : array(); @@ -805,6 +806,8 @@ switch ($mode) { trigger_error('NO_EMAIL'); } + + /** @var $form \phpbb\message\form */ $form = $phpbb_container->get('message.form.' . $form_name); $form->bind($request); @@ -860,6 +863,8 @@ switch ($mode) // The basic memberlist $page_title = $user->lang['MEMBERLIST']; $template_html = 'memberlist_body.html'; + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // Sorting @@ -1366,6 +1371,7 @@ switch ($mode) // Load custom profile fields if ($config['load_cpf_memberlist']) { + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $cp_row = $cp->generate_profile_fields_template_headlines('field_show_on_ml'); diff --git a/phpBB/phpbb/auth/auth.php b/phpBB/phpbb/auth/auth.php index b59f0e60ec..92c19fd5f7 100644 --- a/phpBB/phpbb/auth/auth.php +++ b/phpBB/phpbb/auth/auth.php @@ -929,6 +929,7 @@ class auth { global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container; + /* @var $provider_collection \phpbb\auth\provider_collection */ $provider_collection = $phpbb_container->get('auth.provider_collection'); $provider = $provider_collection->get_provider(); diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php index d8c5fb72de..1adf85ee05 100644 --- a/phpBB/phpbb/auth/provider/db.php +++ b/phpBB/phpbb/auth/provider/db.php @@ -155,6 +155,7 @@ class db extends \phpbb\auth\provider\base // Every auth module is able to define what to do by itself... if ($show_captcha) { + /* @var $captcha_factory \phpbb\captcha\factory */ $captcha_factory = $this->phpbb_container->get('captcha.factory'); $captcha = $captcha_factory->get_instance($this->config['captcha_plugin']); $captcha->init(CONFIRM_LOGIN); diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php index 2cc7786046..20543463ab 100644 --- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php @@ -57,6 +57,7 @@ class release_3_0_5_rc1 extends \phpbb\db\migration\migration { global $phpbb_container; + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); $sql = 'SELECT user_id, user_password FROM ' . $this->table_prefix . 'users diff --git a/phpBB/phpbb/db/migration/profilefield_base_migration.php b/phpBB/phpbb/db/migration/profilefield_base_migration.php index 9000949a7d..bc3d2e9ee5 100644 --- a/phpBB/phpbb/db/migration/profilefield_base_migration.php +++ b/phpBB/phpbb/db/migration/profilefield_base_migration.php @@ -238,6 +238,8 @@ abstract class profilefield_base_migration extends \phpbb\db\migration\migration if ($profile_row === null) { global $phpbb_container; + + /* @var $manager \phpbb\profilefields\manager */ $manager = $phpbb_container->get('profilefields.manager'); $profile_row = $manager->build_insert_sql_array(array()); } diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 0a6a18ffbe..5b9fb6d835 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -409,6 +409,7 @@ class session $session_expired = false; // Check whether the session is still valid if we have one + /* @var $provider_collection \phpbb\auth\provider_collection */ $provider_collection = $phpbb_container->get('auth.provider_collection'); $provider = $provider_collection->get_provider(); @@ -578,6 +579,7 @@ class session } } + /* @var $provider_collection \phpbb\auth\provider_collection */ $provider_collection = $phpbb_container->get('auth.provider_collection'); $provider = $provider_collection->get_provider(); $this->data = $provider->autologin(); @@ -910,6 +912,7 @@ class session $db->sql_query($sql); // Allow connecting logout with external auth method logout + /* @var $provider_collection \phpbb\auth\provider_collection */ $provider_collection = $phpbb_container->get('auth.provider_collection'); $provider = $provider_collection->get_provider(); $provider->logout($this->data, $new_session); @@ -1036,6 +1039,7 @@ class session } // only called from CRON; should be a safe workaround until the infrastructure gets going + /* @var $captcha_factory \phpbb\captcha\factory */ $captcha_factory = $phpbb_container->get('captcha.factory'); $captcha_factory->garbage_collect($config['captcha_plugin']); diff --git a/phpBB/posting.php b/phpBB/posting.php index 10c3b696e6..b6af63038a 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -116,6 +116,7 @@ if (in_array($mode, array('post', 'reply', 'quote', 'edit', 'delete')) && !$foru trigger_error('NO_FORUM'); } +/* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // We need to know some basic information in all cases before we do anything. @@ -561,7 +562,10 @@ if ($mode == 'edit') $orig_poll_options_size = sizeof($post_data['poll_options']); $message_parser = new parse_message(); +/* @var $plupload \phpbb\plupload\plupload */ $plupload = $phpbb_container->get('plupload'); + +/* @var $mimetype_guesser \phpbb\mimetype\guesser */ $mimetype_guesser = $phpbb_container->get('mimetype.guesser'); $message_parser->set_plupload($plupload); $message_parser->set_mimetype_guesser($mimetype_guesser); diff --git a/phpBB/report.php b/phpBB/report.php index 3ea6bb40c5..36c4c9abc8 100644 --- a/phpBB/report.php +++ b/phpBB/report.php @@ -228,6 +228,7 @@ if ($submit && $reason_id) $db->sql_query($sql); $report_id = $db->sql_nextid(); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); if ($post_id) diff --git a/phpBB/search.php b/phpBB/search.php index 164d834ff2..7cab6bca6c 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -123,7 +123,10 @@ $sort_by_text = array('a' => $user->lang['SORT_AUTHOR'], 't' => $user->lang['SOR $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); +/* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); + +/* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); if ($keywords || $author || $author_id || $search_id || $submit) diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index 92ac9171cb..097adbf97b 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -37,6 +37,7 @@ $sort_days = request_var('st', $default_sort_days); $sort_key = request_var('sk', $default_sort_key); $sort_dir = request_var('sd', $default_sort_dir); +/* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // Check if the user has actually sent a forum ID with his/her request @@ -146,6 +147,7 @@ else } } +/* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // Dump out the page header and load viewforum template @@ -218,6 +220,7 @@ if ($forum_data['forum_topics_per_page']) // Do the forum Prune thang - cron type job ... if (!$config['use_system_cron']) { + /* @var $cron \phpbb\cron\manager */ $cron = $phpbb_container->get('cron.manager'); $task = $cron->find_task('cron.task.core.prune_forum'); diff --git a/phpBB/viewonline.php b/phpBB/viewonline.php index 9589fb54e2..ad8bdac91b 100644 --- a/phpBB/viewonline.php +++ b/phpBB/viewonline.php @@ -43,7 +43,10 @@ if (!$auth->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel')) login_box('', $user->lang['LOGIN_EXPLAIN_VIEWONLINE']); } +/* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + +/* @var $viewonline_helper \phpbb\viewonline_helper */ $viewonline_helper = $phpbb_container->get('viewonline_helper'); $sort_key_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_JOINED'], 'c' => $user->lang['SORT_LOCATION']); diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 5f897e8d94..6ea9bc611e 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -48,6 +48,7 @@ $sort_dir = request_var('sd', $default_sort_dir); $update = request_var('update', false); +/* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $s_can_vote = false; @@ -62,6 +63,7 @@ if (!$topic_id && !$post_id) trigger_error('NO_TOPIC'); } +/* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // Find topic id if user requested a newer or older topic @@ -1314,6 +1316,7 @@ $db->sql_freeresult($result); // Load custom profile fields if ($config['load_cpf_viewtopic']) { + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); // Grab all profile fields from users in id cache for later use - similar to the poster cache From 17daaaf441c4972932a4fa3632eaa20132a8763e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88tan=20Muller?= Date: Mon, 12 Jan 2015 22:43:03 +0100 Subject: [PATCH 0083/1676] [ticket/13499] Move `get_remote_file()` to `functions_compatibility.php` PHPBB3-13499 --- phpBB/includes/functions_admin.php | 20 -------------------- phpBB/includes/functions_compatibility.php | 20 ++++++++++++++++++++ tests/functions/get_remote_file_test.php | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index cfd5aaa0c5..bb7022fff3 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -2997,26 +2997,6 @@ function get_database_size() return $database_size; } -/** -* Retrieve contents from remotely stored file -* -* @deprecated 3.1.2 Use file_downloader instead -*/ -function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 6) -{ - global $phpbb_container; - - // Get file downloader and assign $errstr and $errno - /* @var $file_downloader \phpbb\file_downloader */ - $file_downloader = $phpbb_container->get('file_downloader'); - - $file_data = $file_downloader->get($host, $directory, $filename, $port, $timeout); - $errstr = $file_downloader->get_error_string(); - $errno = $file_downloader->get_error_number(); - - return $file_data; -} - /* * Tidy Warnings * Remove all warnings which have now expired from the database diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index c2da02456b..561c72183a 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -198,3 +198,23 @@ function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank $rank_img = $rank_data['img']; $rank_img_src = $rank_data['img_src']; } + +/** + * Retrieve contents from remotely stored file + * + * @deprecated 3.1.2 Use file_downloader instead + */ +function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 6) +{ + global $phpbb_container; + + // Get file downloader and assign $errstr and $errno + /* @var $file_downloader \phpbb\file_downloader */ + $file_downloader = $phpbb_container->get('file_downloader'); + + $file_data = $file_downloader->get($host, $directory, $filename, $port, $timeout); + $errstr = $file_downloader->get_error_string(); + $errno = $file_downloader->get_error_number(); + + return $file_data; +} diff --git a/tests/functions/get_remote_file_test.php b/tests/functions/get_remote_file_test.php index d412dce164..8e9ad1105a 100644 --- a/tests/functions/get_remote_file_test.php +++ b/tests/functions/get_remote_file_test.php @@ -12,7 +12,7 @@ */ require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_compatibility.php'; /** * @group slow From 6842831d6baa59425ec83cc2ebbae377942824ce Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 17 Jan 2015 11:05:18 +0100 Subject: [PATCH 0084/1676] [ticket/13513] Use paths relative to the phpBB root in the router PHPBB3-13513 --- phpBB/phpbb/extension/manager.php | 17 +++++++++++------ phpBB/phpbb/routing/router.php | 14 +++++++------- tests/controller/common_helper_route.php | 2 +- tests/controller/controller_test.php | 2 +- tests/pagination/pagination_test.php | 2 +- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 76f0e3558e..880973d5fb 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -464,15 +464,17 @@ class manager * All enabled and disabled extensions are considered configured. A purged * extension that is no longer in the database is not configured. * + * @param bool $phpbb_relative Whether the path should be relative to phpbb root + * * @return array An array with extension names as keys and and the * database stored extension information as values */ - public function all_configured() + public function all_configured($phpbb_relative = true) { $configured = array(); foreach ($this->extensions as $name => $data) { - $data['ext_path'] = $this->phpbb_root_path . $data['ext_path']; + $data['ext_path'] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path']; $configured[$name] = $data; } return $configured; @@ -480,18 +482,19 @@ class manager /** * Retrieves all enabled extensions. + * @param bool $phpbb_relative Whether the path should be relative to phpbb root * * @return array An array with extension names as keys and and the * database stored extension information as values */ - public function all_enabled() + public function all_enabled($phpbb_relative = true) { $enabled = array(); foreach ($this->extensions as $name => $data) { if ($data['ext_active']) { - $enabled[$name] = $this->phpbb_root_path . $data['ext_path']; + $enabled[$name] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path']; } } return $enabled; @@ -500,17 +503,19 @@ class manager /** * Retrieves all disabled extensions. * + * @param bool $phpbb_relative Whether the path should be relative to phpbb root + * * @return array An array with extension names as keys and and the * database stored extension information as values */ - public function all_disabled() + public function all_disabled($phpbb_relative = true) { $disabled = array(); foreach ($this->extensions as $name => $data) { if (!$data['ext_active']) { - $disabled[$name] = $this->phpbb_root_path . $data['ext_path']; + $disabled[$name] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path']; } } return $disabled; diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 1003708540..601d774129 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -106,25 +106,25 @@ class router implements RouterInterface /** * Find the list of routing files * - * @param array $paths Array of paths where to look for routing files. + * @param array $paths Array of paths where to look for routing files (they must be relative to the phpBB root path). * @return router */ public function find_routing_files(array $paths) { - $this->routing_files = array($this->phpbb_root_path . 'config/' . $this->environment . '/routing/environment.yml'); + $this->routing_files = array('config/' . $this->environment . '/routing/environment.yml'); foreach ($paths as $path) { - if (file_exists($path . 'config/' . $this->environment . '/routing/environment.yml')) + if (file_exists($this->phpbb_root_path . $path . 'config/' . $this->environment . '/routing/environment.yml')) { $this->routing_files[] = $path . 'config/' . $this->environment . '/routing/environment.yml'; } - else if (!is_dir($path . 'config/' . $this->environment)) + else if (!is_dir($this->phpbb_root_path . $path . 'config/' . $this->environment)) { - if (file_exists($path . 'config/default/routing/environment.yml')) + if (file_exists($this->phpbb_root_path . $path . 'config/default/routing/environment.yml')) { $this->routing_files[] = $path . 'config/default/routing/environment.yml'; } - else if (!is_dir($path . 'config/default/routing') && file_exists($path . 'config/routing.yml')) + else if (!is_dir($this->phpbb_root_path . $path . 'config/default/routing') && file_exists($this->phpbb_root_path . $path . 'config/routing.yml')) { $this->routing_files[] = $path . 'config/routing.yml'; } @@ -164,7 +164,7 @@ class router implements RouterInterface { if ($this->route_collection == null || empty($this->routing_files)) { - $this->find_routing_files($this->extension_manager->all_enabled()) + $this->find_routing_files($this->extension_manager->all_enabled(false)) ->find($this->phpbb_root_path); } diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index 19d40cf071..3f98d51f16 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -114,7 +114,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case ); $this->router = new phpbb_mock_router($this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); - $this->router->find_routing_files($this->extension_manager->all_enabled()); + $this->router->find_routing_files($this->extension_manager->all_enabled(false)); $this->router->find(dirname(__FILE__) . '/'); // Set correct current phpBB root path $this->root_path = $this->get_phpbb_root_path(); diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php index 354a902831..86615fe4dc 100644 --- a/tests/controller/controller_test.php +++ b/tests/controller/controller_test.php @@ -41,7 +41,7 @@ class phpbb_controller_controller_test extends phpbb_test_case public function test_router_find_files() { $router = new \phpbb\routing\router($this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); - $router->find_routing_files($this->extension_manager->all_enabled()); + $router->find_routing_files($this->extension_manager->all_enabled(false)); $routes = $router->find(__DIR__)->get_routes(); // This will need to be updated if any new routes are defined diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index 1b9e8c751c..7d928d8820 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -39,7 +39,7 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); $router = new phpbb_mock_router($manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); - $router->find_routing_files($manager->all_enabled()); + $router->find_routing_files($manager->all_enabled(false)); $router->find(dirname(__FILE__) . '/'); $request = new phpbb_mock_request(); From 7fc586080bf5e7b6e90dcf44526200d7c9356d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88tan=20Muller?= Date: Mon, 5 Jan 2015 22:21:31 +0100 Subject: [PATCH 0085/1676] [ticket/13468] Update calls to `add_log()` PHPBB3-13468 --- phpBB/develop/create_search_index.php | 2 +- phpBB/includes/acp/acp_attachments.php | 29 +++---- phpBB/includes/acp/acp_bbcodes.php | 6 +- phpBB/includes/acp/acp_board.php | 4 +- phpBB/includes/acp/acp_bots.php | 6 +- phpBB/includes/acp/acp_captcha.php | 4 +- phpBB/includes/acp/acp_database.php | 8 +- phpBB/includes/acp/acp_disallow.php | 6 +- phpBB/includes/acp/acp_email.php | 6 +- phpBB/includes/acp/acp_forums.php | 33 ++++---- phpBB/includes/acp/acp_inactive.php | 12 +-- phpBB/includes/acp/acp_jabber.php | 4 +- phpBB/includes/acp/acp_language.php | 8 +- phpBB/includes/acp/acp_main.php | 18 ++--- phpBB/includes/acp/acp_modules.php | 16 ++-- phpBB/includes/acp/acp_permission_roles.php | 6 +- phpBB/includes/acp/acp_permissions.php | 6 +- phpBB/includes/acp/acp_profile.php | 14 ++-- phpBB/includes/acp/acp_prune.php | 9 ++- phpBB/includes/acp/acp_ranks.php | 8 +- phpBB/includes/acp/acp_reasons.php | 6 +- phpBB/includes/acp/acp_search.php | 12 +-- phpBB/includes/acp/acp_styles.php | 13 ++- phpBB/includes/acp/acp_users.php | 85 +++++++++++++------- phpBB/includes/acp/acp_words.php | 7 +- phpBB/includes/functions.php | 64 +++------------ phpBB/includes/functions_admin.php | 8 +- phpBB/includes/functions_compatibility.php | 54 ++++++++++++- phpBB/includes/functions_messenger.php | 4 +- phpBB/includes/functions_posting.php | 36 +++++++-- phpBB/includes/functions_user.php | 54 ++++++++----- phpBB/includes/mcp/mcp_forum.php | 17 +++- phpBB/includes/mcp/mcp_main.php | 75 +++++++++++++---- phpBB/includes/mcp/mcp_notes.php | 17 ++-- phpBB/includes/mcp/mcp_post.php | 10 ++- phpBB/includes/mcp/mcp_queue.php | 33 ++++++-- phpBB/includes/mcp/mcp_reports.php | 14 +++- phpBB/includes/mcp/mcp_topic.php | 23 ++++-- phpBB/includes/mcp/mcp_warn.php | 15 +++- phpBB/includes/ucp/ucp_activate.php | 14 +++- phpBB/includes/ucp/ucp_groups.php | 22 +++-- phpBB/includes/ucp/ucp_profile.php | 20 ++++- phpBB/install/database_update.php | 2 +- phpBB/install/install_convert.php | 4 +- phpBB/install/install_install.php | 4 +- phpBB/phpbb/captcha/plugins/gd.php | 4 +- phpBB/phpbb/captcha/plugins/qa.php | 4 +- phpBB/phpbb/captcha/plugins/recaptcha.php | 4 +- phpBB/phpbb/cron/task/core/tidy_plupload.php | 8 +- phpBB/phpbb/db/migration/tool/module.php | 4 +- phpBB/phpbb/log/log.php | 8 +- phpBB/phpbb/log/log_interface.php | 16 ++-- phpBB/phpbb/search/fulltext_sphinx.php | 4 +- phpBB/phpbb/session.php | 13 ++- phpBB/posting.php | 6 +- phpBB/ucp.php | 4 +- tests/dbal/migrator_tool_module_test.php | 2 +- tests/log/function_add_log_test.php | 2 +- 58 files changed, 568 insertions(+), 329 deletions(-) diff --git a/phpBB/develop/create_search_index.php b/phpBB/develop/create_search_index.php index 9b79a35a84..6ef200699c 100644 --- a/phpBB/develop/create_search_index.php +++ b/phpBB/develop/create_search_index.php @@ -132,7 +132,7 @@ else $search->tidy(); -add_log('admin', 'LOG_SEARCH_INDEX_CREATED', $search_name); +$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($search_name)); echo $user->lang['SEARCH_INDEX_CREATED'] . "\n"; echo 'Peak Memory Usage: ' . get_formatted_filesize(memory_get_peak_usage()) . "\n"; diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index fa5df3d418..223b4de2d6 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -43,7 +43,7 @@ class acp_attachments function main($id, $mode) { global $db, $user, $auth, $template, $cache, $phpbb_container; - global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; + global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx, $phpbb_log; $this->id = $id; $this->db = $db; @@ -198,7 +198,7 @@ class acp_attachments if ($submit) { - add_log('admin', 'LOG_CONFIG_ATTACH'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_ATTACH'); // Check Settings $this->test_upload($error, $this->new_config['upload_path'], false); @@ -359,7 +359,7 @@ class acp_attachments WHERE extension_id = ' . $row['extension_id']; $db->sql_query($sql); - add_log('admin', 'LOG_ATTACH_EXT_UPDATE', $row['extension']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXT_UPDATE', false, array($row['extension'])); } } $db->sql_freeresult($result); @@ -386,7 +386,7 @@ class acp_attachments WHERE ' . $db->sql_in_set('extension_id', $extension_id_list); $db->sql_query($sql); - add_log('admin', 'LOG_ATTACH_EXT_DEL', $extension_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXT_DEL', false, array($extension_list)); } } @@ -418,7 +418,8 @@ class acp_attachments ); $db->sql_query('INSERT INTO ' . EXTENSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); - add_log('admin', 'LOG_ATTACH_EXT_ADD', $add_extension); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXT_ADD', false, array($add_extension)); } } } @@ -583,7 +584,7 @@ class acp_attachments } $group_name = (isset($user->lang['EXT_GROUP_' . $group_name])) ? $user->lang['EXT_GROUP_' . $group_name] : $group_name; - add_log('admin', 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), $group_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), false, array($group_name)); } $extension_list = request_var('extensions', array(0)); @@ -648,7 +649,7 @@ class acp_attachments WHERE group_id = $group_id"; $db->sql_query($sql); - add_log('admin', 'LOG_ATTACH_EXTGROUP_DEL', $group_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXTGROUP_DEL', false, array($group_name)); $cache->destroy('_extensions'); @@ -938,7 +939,7 @@ class acp_attachments WHERE ' . $db->sql_in_set('attach_id', array_keys($delete_files)); $db->sql_query($sql); - add_log('admin', 'LOG_ATTACH_ORPHAN_DEL', implode(', ', $delete_files)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_ORPHAN_DEL', false, array(implode(', ', $delete_files))); $notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode($user->lang['COMMA_SEPARATOR'], $delete_files)); } @@ -1029,7 +1030,7 @@ class acp_attachments $space_taken += $row['filesize']; $files_added++; - add_log('admin', 'LOG_ATTACH_FILEUPLOAD', $post_row['post_id'], $row['real_filename']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_FILEUPLOAD', false, array($post_row['post_id'], $row['real_filename'])); } $db->sql_freeresult($result); @@ -1095,7 +1096,8 @@ class acp_attachments { $error[] = $user->lang['FILES_GONE']; } - add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode(', ', $deleted_filenames)); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACHMENTS_DELETED', false, array(implode(', ', $deleted_filenames))); $notify[] = sprintf($user->lang['LOG_ATTACHMENTS_DELETED'], implode($user->lang['COMMA_SEPARATOR'], $deleted_filenames)); } else @@ -1527,8 +1529,7 @@ class acp_attachments */ function perform_site_list() { - global $db, $user; - global $request; + global $db, $user, $request, $phpbb_log; if (isset($_REQUEST['securesubmit'])) { @@ -1679,7 +1680,7 @@ class acp_attachments { // Update log $log_entry = ($ip_exclude) ? 'LOG_DOWNLOAD_EXCLUDE_IP' : 'LOG_DOWNLOAD_IP'; - add_log('admin', $log_entry, $ip_list_log); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_entry, false, array($ip_list_log)); } trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action)); @@ -1708,7 +1709,7 @@ class acp_attachments WHERE ' . $db->sql_in_set('site_id', $unip_sql); $db->sql_query($sql); - add_log('admin', 'LOG_DOWNLOAD_REMOVE_IP', $l_unip_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DOWNLOAD_REMOVE_IP', false, array($l_unip_list)); } trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action)); diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index e245eea069..0e82d233c7 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -26,7 +26,7 @@ class acp_bbcodes function main($id, $mode) { global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; $user->add_lang('acp/posting'); @@ -285,7 +285,7 @@ class acp_bbcodes $log_action = 'LOG_BBCODE_EDIT'; } - add_log('admin', $log_action, $data['bbcode_tag']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($data['bbcode_tag'])); trigger_error($user->lang[$lang] . adm_back_link($this->u_action)); } @@ -319,7 +319,7 @@ class acp_bbcodes { $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); $cache->destroy('sql', BBCODES_TABLE); - add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($row['bbcode_tag'])); if ($request->is_ajax()) { diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 3893091f17..86566dc705 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -32,7 +32,7 @@ class acp_board { global $db, $user, $auth, $template; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - global $cache, $phpbb_container, $phpbb_dispatcher; + global $cache, $phpbb_container, $phpbb_dispatcher, $phpbb_log; $user->add_lang('acp/board'); @@ -615,7 +615,7 @@ class acp_board if ($submit) { - add_log('admin', 'LOG_CONFIG_' . strtoupper($mode)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_' . strtoupper($mode)); $message = $user->lang('CONFIG_UPDATED'); $message_type = E_USER_NOTICE; diff --git a/phpBB/includes/acp/acp_bots.php b/phpBB/includes/acp/acp_bots.php index 1ea320e674..d630b2ed2d 100644 --- a/phpBB/includes/acp/acp_bots.php +++ b/phpBB/includes/acp/acp_bots.php @@ -25,7 +25,7 @@ class acp_bots function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache, $request; + global $config, $db, $user, $auth, $template, $cache, $request, $phpbb_log; global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; $action = request_var('action', ''); @@ -124,7 +124,7 @@ class acp_bots $cache->destroy('_bots'); - add_log('admin', 'LOG_BOT_DELETE', implode(', ', $bot_name_ary)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_DELETE', false, array(implode(', ', $bot_name_ary))); trigger_error($user->lang['BOT_DELETED'] . adm_back_link($this->u_action)); } else @@ -292,7 +292,7 @@ class acp_bots $cache->destroy('_bots'); - add_log('admin', 'LOG_BOT_' . $log, $bot_row['bot_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_' . $log, false, array($bot_row['bot_name'])); trigger_error($user->lang['BOT_' . $log] . adm_back_link($this->u_action)); } diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index 19cd609c73..c87fa51f88 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -25,7 +25,7 @@ class acp_captcha function main($id, $mode) { - global $db, $user, $auth, $template; + global $db, $user, $auth, $template, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container; $user->add_lang('acp/board'); @@ -86,7 +86,7 @@ class acp_captcha $new_captcha = $factory->get_instance($config['captcha_plugin']); $new_captcha->install(); - add_log('admin', 'LOG_CONFIG_VISUAL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL'); } else { diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 7de108c88a..6454b30ec3 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -27,7 +27,7 @@ class acp_database function main($id, $mode) { global $cache, $db, $user, $auth, $template, $table_prefix; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; $this->db_tools = new \phpbb\db\tools\tools($db); @@ -165,7 +165,7 @@ class acp_database $extractor->write_end(); - add_log('admin', 'LOG_DB_BACKUP'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_BACKUP'); if ($download == true) { @@ -242,7 +242,7 @@ class acp_database if (confirm_box(true)) { unlink($file_name); - add_log('admin', 'LOG_DB_DELETE'); + $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)); } else @@ -395,7 +395,7 @@ class acp_database // Purge the cache due to updated data $cache->purge(); - add_log('admin', 'LOG_DB_RESTORE'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_RESTORE'); trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action)); break; } diff --git a/phpBB/includes/acp/acp_disallow.php b/phpBB/includes/acp/acp_disallow.php index 4c8f3cc65b..adcaa13e4d 100644 --- a/phpBB/includes/acp/acp_disallow.php +++ b/phpBB/includes/acp/acp_disallow.php @@ -25,7 +25,7 @@ class acp_disallow function main($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; include($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -74,7 +74,7 @@ class acp_disallow $cache->destroy('_disallowed_usernames'); $message = $user->lang['DISALLOW_SUCCESSFUL']; - add_log('admin', 'LOG_DISALLOW_ADD', str_replace('%', '*', $disallowed_user)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DISALLOW_ADD', false, array(str_replace('%', '*', $disallowed_user))); trigger_error($message . adm_back_link($this->u_action)); } @@ -93,7 +93,7 @@ class acp_disallow $cache->destroy('_disallowed_usernames'); - add_log('admin', 'LOG_DISALLOW_DELETE'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DISALLOW_DELETE'); trigger_error($user->lang['DISALLOWED_DELETED'] . adm_back_link($this->u_action)); } diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index fcc2bd7641..0025e10ea2 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -25,7 +25,7 @@ class acp_email function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache; + global $config, $db, $user, $auth, $template, $cache, $phpbb_log; global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $phpbb_dispatcher; $user->add_lang('acp/email'); @@ -263,7 +263,7 @@ class acp_email { if (!empty($usernames)) { - add_log('admin', 'LOG_MASS_EMAIL', implode(', ', utf8_normalize_nfc($usernames))); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MASS_EMAIL', false, array(implode(', ', utf8_normalize_nfc($usernames)))); } else { @@ -277,7 +277,7 @@ class acp_email $group_name = $user->lang['ALL_USERS']; } - add_log('admin', 'LOG_MASS_EMAIL', $group_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MASS_EMAIL', false, array($group_name)); } } diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index fd9d70f679..fdf22da2be 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -27,7 +27,7 @@ class acp_forums function main($id, $mode) { global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher; - global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; + global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx, $phpbb_log; $user->add_lang('acp/forums'); $this->tpl_name = 'acp_forums'; @@ -266,7 +266,7 @@ class acp_forums if ($move_forum_name !== false) { - add_log('admin', 'LOG_FORUM_' . strtoupper($action), $row['forum_name'], $move_forum_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_' . strtoupper($action), false, array($row['forum_name'], $move_forum_name)); $cache->destroy('sql', FORUMS_TABLE); } @@ -377,7 +377,8 @@ class acp_forums sync('forum', 'forum_id', $forum_id, false, true); - add_log('admin', 'LOG_FORUM_SYNC', $row['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_SYNC', false, array($row['forum_name'])); + $cache->destroy('sql', FORUMS_TABLE); $template->assign_var('L_FORUM_RESYNCED', sprintf($user->lang['FORUM_RESYNCED'], $row['forum_name'])); @@ -945,7 +946,7 @@ class acp_forums */ function update_forum_data(&$forum_data) { - global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher; + global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log; $errors = array(); @@ -1127,7 +1128,7 @@ class acp_forums $forum_data['forum_id'] = $db->sql_nextid(); - add_log('admin', 'LOG_FORUM_ADD', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_ADD', false, array($forum_data['forum_name'])); } else { @@ -1344,7 +1345,7 @@ class acp_forums // Add it back $forum_data['forum_id'] = $forum_id; - add_log('admin', 'LOG_FORUM_EDIT', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_EDIT', false, array($forum_data['forum_name'])); } /** @@ -1546,7 +1547,7 @@ class acp_forums */ function delete_forum($forum_id, $action_posts = 'delete', $action_subforums = 'delete', $posts_to_id = 0, $subforums_to_id = 0) { - global $db, $user, $cache; + global $db, $user, $cache, $phpbb_log; $forum_data = $this->get_forum_info($forum_id); @@ -1743,39 +1744,39 @@ class acp_forums switch ($log_action) { case 'MOVE_POSTS_MOVE_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS', $posts_to_name, $subforums_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS', false, array($posts_to_name, $subforums_to_name, $forum_data['forum_name'])); break; case 'MOVE_POSTS_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS', $posts_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS', false, array($posts_to_name, $forum_data['forum_name'])); break; case 'POSTS_MOVE_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS', false, array($subforums_to_name, $forum_data['forum_name'])); break; case '_MOVE_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_FORUMS', false, array($subforums_to_name, $forum_data['forum_name'])); break; case 'MOVE_POSTS_': - add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS', $posts_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS', false, array($posts_to_name, $forum_data['forum_name'])); break; case 'POSTS_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_POSTS_FORUMS', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS_FORUMS', false, array($forum_data['forum_name'])); break; case '_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_FORUMS', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_FORUMS', false, array($forum_data['forum_name'])); break; case 'POSTS_': - add_log('admin', 'LOG_FORUM_DEL_POSTS', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS', false, array($forum_data['forum_name'])); break; default: - add_log('admin', 'LOG_FORUM_DEL_FORUM', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_FORUM', false, array($forum_data['forum_name'])); break; } diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index 9e681b9181..4b747b62d9 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -31,7 +31,7 @@ class acp_inactive function main($id, $mode) { - global $config, $db, $user, $auth, $template, $phpbb_container; + global $config, $db, $user, $auth, $template, $phpbb_container, $phpbb_log; global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; include($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -137,8 +137,10 @@ class acp_inactive { foreach ($inactive_users as $row) { - add_log('admin', 'LOG_USER_ACTIVE', $row['username']); - add_log('user', $row['user_id'], 'LOG_USER_ACTIVE_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE', false, array($row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE_USER', false, array( + 'reportee_id' => $row['user_id'] + )); } trigger_error(sprintf($user->lang['LOG_INACTIVE_ACTIVATE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action))); @@ -161,7 +163,7 @@ class acp_inactive user_delete('retain', $mark, true); - add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INACTIVE_' . strtoupper($action), false, array(implode(', ', $user_affected))); trigger_error(sprintf($user->lang['LOG_INACTIVE_DELETE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action))); } @@ -233,7 +235,7 @@ class acp_inactive WHERE ' . $db->sql_in_set('user_id', $user_ids); $db->sql_query($sql); - add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INACTIVE_REMIND', false, array(implode(', ', $usernames))); trigger_error(sprintf($user->lang['LOG_INACTIVE_REMIND'], implode($user->lang['COMMA_SEPARATOR'], $usernames) . ' ' . adm_back_link($this->u_action))); } diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php index 8d2e9d41a3..6033237b9d 100644 --- a/phpBB/includes/acp/acp_jabber.php +++ b/phpBB/includes/acp/acp_jabber.php @@ -29,7 +29,7 @@ class acp_jabber function main($id, $mode) { - global $db, $user, $auth, $template; + global $db, $user, $auth, $template, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('acp/board'); @@ -111,7 +111,7 @@ class acp_jabber set_config('jab_package_size', $jab_package_size); set_config('jab_use_ssl', $jab_use_ssl); - add_log('admin', 'LOG_' . $log); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . $log); trigger_error($message . adm_back_link($this->u_action)); } diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 60e338ae7c..fe39dcba47 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -31,7 +31,7 @@ class acp_language function main($id, $mode) { - global $config, $db, $user, $template; + global $config, $db, $user, $template, $phpbb_log; global $phpbb_root_path, $phpEx, $request; include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -90,7 +90,7 @@ class acp_language SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE lang_id = ' . $lang_id); - add_log('admin', 'LOG_LANGUAGE_PACK_UPDATED', $sql_ary['lang_english_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_UPDATED', false, array($sql_ary['lang_english_name'])); trigger_error($user->lang['LANGUAGE_DETAILS_UPDATED'] . adm_back_link($this->u_action)); break; @@ -224,7 +224,7 @@ class acp_language $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id; $db->sql_query($sql); - add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_DELETED', false, array($row['lang_english_name'])); trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action)); } @@ -329,7 +329,7 @@ class acp_language } $db->sql_freeresult($result); - add_log('admin', 'LOG_LANGUAGE_PACK_INSTALLED', $lang_pack['name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_INSTALLED', false, array($lang_pack['name'])); $message = sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']); $message .= ($notify_cpf_update) ? '

    ' . $user->lang['LANGUAGE_PACK_CPF_UPDATE'] : ''; diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 6cd2468f6d..3248f95819 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -25,7 +25,7 @@ class acp_main function main($id, $mode) { - global $config, $db, $cache, $user, $auth, $template, $request; + global $config, $db, $cache, $user, $auth, $template, $request, $phpbb_log; global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher; // Show restore permissions notice @@ -123,7 +123,7 @@ class acp_main set_config('record_online_users', 1, true); set_config('record_online_date', time(), true); - add_log('admin', 'LOG_RESET_ONLINE'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESET_ONLINE'); if ($request->is_ajax()) { @@ -178,7 +178,7 @@ class acp_main } update_last_username(); - add_log('admin', 'LOG_RESYNC_STATS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_STATS'); if ($request->is_ajax()) { @@ -215,7 +215,7 @@ class acp_main // Still no maximum post id? Then we are finished if (!$max_post_id) { - add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POSTCOUNTS'); break; } @@ -245,7 +245,7 @@ class acp_main $start += $step; } - add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POSTCOUNTS'); if ($request->is_ajax()) { @@ -260,7 +260,7 @@ class acp_main } set_config('board_startdate', time() - 1); - add_log('admin', 'LOG_RESET_DATE'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESET_DATE'); if ($request->is_ajax()) { @@ -340,7 +340,7 @@ class acp_main } } - add_log('admin', 'LOG_RESYNC_POST_MARKING'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POST_MARKING'); if ($request->is_ajax()) { @@ -356,7 +356,7 @@ class acp_main $auth->acl_clear_prefetch(); phpbb_cache_moderators($db, $cache, $auth); - add_log('admin', 'LOG_PURGE_CACHE'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PURGE_CACHE'); if ($request->is_ajax()) { @@ -407,7 +407,7 @@ class acp_main $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $reinsert_ary); $db->sql_query($sql); - add_log('admin', 'LOG_PURGE_SESSIONS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PURGE_SESSIONS'); if ($request->is_ajax()) { diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index ea6b388328..b20c90f69c 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -37,7 +37,7 @@ class acp_modules function main($id, $mode) { - global $db, $user, $auth, $template, $module, $request; + global $db, $user, $auth, $template, $module, $request, $phpbb_log; global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; // Set a global define for modules we might include (the author is able to prevent execution of code by checking this constant) @@ -138,7 +138,7 @@ class acp_modules AND module_id = $module_id"; $db->sql_query($sql); - add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname'])); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($this->lang_name($row['module_langname']))); $this->remove_cache_file(); break; @@ -167,7 +167,7 @@ class acp_modules if ($move_module_name !== false) { - add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']), $move_module_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($this->lang_name($row['module_langname']), $move_module_name)); $this->remove_cache_file(); } @@ -771,7 +771,7 @@ class acp_modules */ function update_module_data(&$module_data, $run_inline = false) { - global $db, $user; + global $db, $user, $phpbb_log; if (!isset($module_data['module_id'])) { @@ -835,7 +835,7 @@ class acp_modules if (!$run_inline) { - add_log('admin', 'LOG_MODULE_ADD', $this->lang_name($module_data['module_langname'])); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($this->lang_name($module_data['module_langname']))); } } else @@ -869,7 +869,7 @@ class acp_modules if (!$run_inline) { - add_log('admin', 'LOG_MODULE_EDIT', $this->lang_name($module_data['module_langname'])); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_EDIT', false, array($this->lang_name($module_data['module_langname']))); } } @@ -964,7 +964,7 @@ class acp_modules */ function delete_module($module_id) { - global $db, $user; + global $db, $user, $phpbb_log; $row = $this->get_module_row($module_id); @@ -998,7 +998,7 @@ class acp_modules AND left_id > {$row['right_id']}"; $db->sql_query($sql); - add_log('admin', 'LOG_MODULE_REMOVED', $this->lang_name($row['module_langname'])); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_REMOVED', false, array($this->lang_name($row['module_langname']))); return array(); diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php index 6c5650fe5e..f7e2065572 100644 --- a/phpBB/includes/acp/acp_permission_roles.php +++ b/phpBB/includes/acp/acp_permission_roles.php @@ -28,7 +28,7 @@ class acp_permission_roles { global $db, $user, $auth, $template, $cache, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - global $request; + global $request, $phpbb_log; include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); @@ -109,7 +109,7 @@ class acp_permission_roles $this->remove_role($role_id, $permission_type); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; - add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_REMOVED', $role_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($permission_type) . 'ROLE_REMOVED', false, array($role_name)); trigger_error($user->lang['ROLE_DELETED'] . adm_back_link($this->u_action)); } else @@ -212,7 +212,7 @@ class acp_permission_roles $this->auth_admin->acl_set_role($role_id, $auth_settings); $role_name = (!empty($user->lang[$role_name])) ? $user->lang[$role_name] : $role_name; - add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), $role_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), false, array($role_name)); trigger_error($user->lang['ROLE_' . strtoupper($action) . '_SUCCESS'] . adm_back_link($this->u_action)); diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index 0010c6e4a4..802d4999e9 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -909,7 +909,7 @@ class acp_permissions */ function log_action($mode, $action, $permission_type, $ug_type, $ug_id, $forum_id) { - global $db, $user; + global $db, $user, $phpbb_log; if (!is_array($ug_id)) { @@ -937,7 +937,7 @@ class acp_permissions if ($forum_id[0] == 0) { - add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_ug_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), false, array($l_ug_list)); } else { @@ -954,7 +954,7 @@ class acp_permissions } $db->sql_freeresult($result); - add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_forum_list, $l_ug_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), false, array($l_forum_list, $l_ug_list)); } } diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index c85cc2a67d..9a24978f58 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -35,7 +35,7 @@ class acp_profile { global $config, $db, $user, $auth, $template, $cache; global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; - global $request, $phpbb_container; + global $request, $phpbb_container, $phpbb_log; include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -143,7 +143,7 @@ class acp_profile $db->sql_transaction('commit'); - add_log('admin', 'LOG_PROFILE_FIELD_REMOVED', $field_ident); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_REMOVED', false, array($field_ident)); trigger_error($user->lang['REMOVED_PROFILE_FIELD'] . adm_back_link($this->u_action)); } else @@ -184,7 +184,7 @@ class acp_profile $field_ident = (string) $db->sql_fetchfield('field_ident'); $db->sql_freeresult($result); - add_log('admin', 'LOG_PROFILE_FIELD_ACTIVATE', $field_ident); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_ACTIVATE', false, array($field_ident)); if ($request->is_ajax()) { @@ -220,7 +220,7 @@ class acp_profile )); } - add_log('admin', 'LOG_PROFILE_FIELD_DEACTIVATE', $field_ident); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_DEACTIVATE', false, array($field_ident)); trigger_error($user->lang['PROFILE_FIELD_DEACTIVATED'] . adm_back_link($this->u_action)); @@ -816,7 +816,7 @@ class acp_profile */ function save_profile_field(&$cp, $field_type, $action = 'create') { - global $db, $config, $user, $phpbb_container; + global $db, $config, $user, $phpbb_container, $phpbb_log; $field_id = request_var('field_id', 0); @@ -1086,12 +1086,12 @@ class acp_profile if ($action == 'edit') { - add_log('admin', 'LOG_PROFILE_FIELD_EDIT', $cp->vars['field_ident'] . ':' . $cp->vars['lang_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_EDIT', false, array($cp->vars['field_ident'] . ':' . $cp->vars['lang_name'])); trigger_error($user->lang['CHANGED_PROFILE_FIELD'] . adm_back_link($this->u_action)); } else { - add_log('admin', 'LOG_PROFILE_FIELD_CREATE', substr($field_ident, 3) . ':' . $cp->vars['lang_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_CREATE', false, array(substr($field_ident, 3) . ':' . $cp->vars['lang_name'])); trigger_error($user->lang['ADDED_PROFILE_FIELD'] . adm_back_link($this->u_action)); } } diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php index 59f15c4890..1e2c1fa9a5 100644 --- a/phpBB/includes/acp/acp_prune.php +++ b/phpBB/includes/acp/acp_prune.php @@ -51,7 +51,7 @@ class acp_prune */ function prune_forums($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $all_forums = request_var('all_forums', 0); @@ -153,7 +153,8 @@ class acp_prune // Sync all pruned forums at once sync('forum', 'forum_id', $prune_ids, true, true); - add_log('admin', 'LOG_PRUNE', $log_data); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PRUNE', false, array($log_data)); } $db->sql_freeresult($result); @@ -228,7 +229,7 @@ class acp_prune */ function prune_users($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('memberlist'); @@ -268,7 +269,7 @@ class acp_prune } } - add_log('admin', $l_log, implode(', ', $usernames)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $l_log, false, array(implode(', ', $usernames))); $msg = $user->lang['USER_' . strtoupper($action) . '_SUCCESS']; } else diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php index 5885de57ec..b09d57056e 100644 --- a/phpBB/includes/acp/acp_ranks.php +++ b/phpBB/includes/acp/acp_ranks.php @@ -26,7 +26,7 @@ class acp_ranks function main($id, $mode) { global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; $user->add_lang('acp/posting'); @@ -89,14 +89,14 @@ class acp_ranks $sql = 'UPDATE ' . RANKS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE rank_id = $rank_id"; $message = $user->lang['RANK_UPDATED']; - add_log('admin', 'LOG_RANK_UPDATED', $rank_title); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_UPDATED', false, array($rank_title)); } else { $sql = 'INSERT INTO ' . RANKS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); $message = $user->lang['RANK_ADDED']; - add_log('admin', 'LOG_RANK_ADDED', $rank_title); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_ADDED', false, array($rank_title)); } $db->sql_query($sql); @@ -133,7 +133,7 @@ class acp_ranks $cache->destroy('_ranks'); - add_log('admin', 'LOG_RANK_REMOVED', $rank_title); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_REMOVED', false, array($rank_title)); if ($request->is_ajax()) { diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php index 3d7ccf422c..bb177dd85d 100644 --- a/phpBB/includes/acp/acp_reasons.php +++ b/phpBB/includes/acp/acp_reasons.php @@ -27,7 +27,7 @@ class acp_reasons { global $db, $user, $auth, $template, $cache; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - global $request; + global $request, $phpbb_log; $user->add_lang(array('mcp', 'acp/posting')); @@ -139,7 +139,7 @@ class acp_reasons $log = 'UPDATED'; } - add_log('admin', 'LOG_REASON_' . $log, $reason_row['reason_title']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_REASON_' . $log, false, array($reason_row['reason_title'])); trigger_error($user->lang['REASON_' . $log] . adm_back_link($this->u_action)); } } @@ -264,7 +264,7 @@ class acp_reasons $db->sql_query('DELETE FROM ' . REPORTS_REASONS_TABLE . ' WHERE reason_id = ' . $reason_id); - add_log('admin', 'LOG_REASON_REMOVED', $reason_row['reason_title']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_REASON_REMOVED', false, array($reason_row['reason_title'])); trigger_error($user->lang['REASON_REMOVED'] . adm_back_link($this->u_action)); } else diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 4a418f43e5..9ae6627650 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -50,7 +50,7 @@ class acp_search function settings($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $submit = (isset($_POST['submit'])) ? true : false; @@ -143,7 +143,7 @@ class acp_search $extra_message = ''; if ($updated) { - add_log('admin', 'LOG_CONFIG_SEARCH'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH'); } if (isset($cfg_array['search_type']) && in_array($cfg_array['search_type'], $search_types, true) && ($cfg_array['search_type'] != $config['search_type'])) @@ -161,7 +161,7 @@ class acp_search if (!$updated) { - add_log('admin', 'LOG_CONFIG_SEARCH'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH'); } $extra_message = '
    ' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '
    » ' . $user->lang['GO_TO_SEARCH_INDEX'] . ''; } @@ -232,7 +232,7 @@ class acp_search function index($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $action = request_var('action', ''); @@ -347,7 +347,7 @@ class acp_search $this->state = array(''); $this->save_state(); - add_log('admin', 'LOG_SEARCH_INDEX_REMOVED', $name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_REMOVED', false, array($name)); trigger_error($user->lang['SEARCH_INDEX_REMOVED'] . adm_back_link($this->u_action) . $this->close_popup_js()); break; @@ -435,7 +435,7 @@ class acp_search $this->state = array(''); $this->save_state(); - add_log('admin', 'LOG_SEARCH_INDEX_CREATED', $name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($name)); trigger_error($user->lang['SEARCH_INDEX_CREATED'] . adm_back_link($this->u_action) . $this->close_popup_js()); break; } diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 6bd27a8bca..c297a46ec9 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -260,6 +260,8 @@ class acp_styles */ protected function action_uninstall_confirmed($ids, $delete_files) { + global $user, $phpbb_log; + $default = $this->default_style; $uninstalled = array(); $messages = array(); @@ -319,7 +321,7 @@ class acp_styles // Log action if (count($uninstalled)) { - add_log('admin', 'LOG_STYLE_DELETE', implode(', ', $uninstalled)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_STYLE_DELETE', false, array(implode(', ', $uninstalled))); } // Clear cache @@ -391,6 +393,8 @@ class acp_styles */ protected function action_details() { + global $user, $phpbb_log; + $id = $this->request->variable('id', 0); if (!$id) { @@ -522,7 +526,8 @@ class acp_styles $this->cache->purge(); } } - add_log('admin', 'LOG_STYLE_EDIT_DETAILS', $style['style_name']); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_STYLE_EDIT_DETAILS', false, array($style['style_name'])); } // Update default style @@ -1119,6 +1124,8 @@ class acp_styles */ protected function install_style($style) { + global $user, $phpbb_log; + // Generate row $sql_ary = array(); foreach ($style as $key => $value) @@ -1140,7 +1147,7 @@ class acp_styles $this->db->sql_transaction('commit'); - add_log('admin', 'LOG_STYLE_ADD', $sql_ary['style_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_STYLE_ADD', false, array($sql_ary['style_name'])); return $id; } diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 4e7576c875..de4664a711 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -34,7 +34,7 @@ class acp_users global $config, $db, $user, $auth, $template, $cache; global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads; global $phpbb_dispatcher, $request; - global $phpbb_container; + global $phpbb_container, $phpbb_log; $user->add_lang(array('posting', 'ucp', 'acp/users')); $this->tpl_name = 'acp_users'; @@ -220,7 +220,7 @@ class acp_users { user_delete($delete_type, $user_id, $user_row['username']); - add_log('admin', 'LOG_USER_DELETED', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DELETED', false, array($user_row['username'])); trigger_error($user->lang['USER_DELETED'] . adm_back_link($this->u_action)); } else @@ -381,8 +381,10 @@ class acp_users $messenger->send(NOTIFY_EMAIL); - add_log('admin', 'LOG_USER_REACTIVATE', $user_row['username']); - add_log('user', $user_id, 'LOG_USER_REACTIVATE_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE', false, array($user_row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE_USER', false, array( + 'reportee_id' => $user_id + )); trigger_error($user->lang['FORCE_REACTIVATION_SUCCESS'] . adm_back_link($this->u_action . '&u=' . $user_id)); } @@ -443,8 +445,10 @@ class acp_users $message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED'; $log = ($user_row['user_type'] == USER_INACTIVE) ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE'; - add_log('admin', $log, $user_row['username']); - add_log('user', $user_id, $log . '_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($user_row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, $log . '_USER', false, array( + 'reportee_id' => $user_id + )); trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&u=' . $user_id)); @@ -467,8 +471,10 @@ class acp_users WHERE user_id = $user_id"; $db->sql_query($sql); - add_log('admin', 'LOG_USER_DEL_SIG', $user_row['username']); - add_log('user', $user_id, 'LOG_USER_DEL_SIG_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_SIG', false, array($user_row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_SIG_USER', false, array( + 'reportee_id' => $user_id + )); trigger_error($user->lang['USER_ADMIN_SIG_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); @@ -486,8 +492,10 @@ class acp_users $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $phpbb_avatar_manager->handle_avatar_delete($db, $user, $phpbb_avatar_manager->clean_row($user_row, 'user'), USERS_TABLE, 'user_'); - add_log('admin', 'LOG_USER_DEL_AVATAR', $user_row['username']); - add_log('user', $user_id, 'LOG_USER_DEL_AVATAR_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_AVATAR', false, array($user_row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_AVATAR_USER', false, array( + 'reportee_id' => $user_id + )); trigger_error($user->lang['USER_ADMIN_AVATAR_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); break; @@ -499,7 +507,7 @@ class acp_users // Delete posts, attachments, etc. delete_posts('poster_id', $user_id); - add_log('admin', 'LOG_USER_DEL_POSTS', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_POSTS', false, array($user_row['username'])); trigger_error($user->lang['USER_POSTS_DELETED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } else @@ -521,7 +529,7 @@ class acp_users { delete_attachments('user', $user_id); - add_log('admin', 'LOG_USER_DEL_ATTACH', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_ATTACH', false, array($user_row['username'])); trigger_error($user->lang['USER_ATTACHMENTS_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } else @@ -567,7 +575,7 @@ class acp_users delete_pm($user_id, $msg_ids, PRIVMSGS_OUTBOX); - add_log('admin', 'LOG_USER_DEL_OUTBOX', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_OUTBOX', false, array($user_row['username'])); $lang = 'EMPTIED'; } @@ -738,8 +746,11 @@ class acp_users sync('forum', 'forum_id', $forum_id_ary, false, true); } - add_log('admin', 'LOG_USER_MOVE_POSTS', $user_row['username'], $forum_info['forum_name']); - add_log('user', $user_id, 'LOG_USER_MOVE_POSTS_USER', $forum_info['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS', false, array($user_row['username'], $forum_info['forum_name'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS_USER', false, array( + 'reportee_id' => $user_id, + $forum_info['forum_name'] + )); trigger_error($user->lang['USER_POSTS_MOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); @@ -751,7 +762,7 @@ class acp_users { remove_newly_registered($user_id, $user_row); - add_log('admin', 'LOG_USER_REMOVED_NR', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REMOVED_NR', false, array($user_row['username'])); trigger_error($user->lang['USER_LIFTED_NR'] . adm_back_link($this->u_action . '&u=' . $user_id)); } else @@ -906,7 +917,11 @@ class acp_users $sql_ary['username'] = $update_username; $sql_ary['username_clean'] = utf8_clean_string($update_username); - add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $user_row['username'], $update_username); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_NAME', false, array( + 'reportee_id' => $user_id, + $user_row['username'], + $update_username + )); } if ($update_email !== false) @@ -916,7 +931,12 @@ class acp_users 'user_email_hash' => phpbb_email_hash($update_email), ); - add_log('user', $user_id, 'LOG_USER_UPDATE_EMAIL', $user_row['username'], $user_row['user_email'], $update_email); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_EMAIL', false, array( + 'reportee_id' => $user_id, + $user_row['username'], + $user_row['user_email'], + $update_email + )); } if ($update_password) @@ -927,7 +947,11 @@ class acp_users ); $user->reset_login_keys($user_id); - add_log('user', $user_id, 'LOG_USER_NEW_PASSWORD', $user_row['username']); + + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array( + 'reportee_id' => $user_id, + $user_row['username'] + )); } if (sizeof($sql_ary)) @@ -946,7 +970,7 @@ class acp_users // Let the users permissions being updated $auth->acl_clear_prefetch($user_id); - add_log('admin', 'LOG_USER_USER_UPDATE', $data['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_USER_UPDATE', false, array($data['username'])); trigger_error($user->lang['USER_OVERVIEW_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } @@ -1145,7 +1169,7 @@ class acp_users $where_sql"; $db->sql_query($sql); - add_log('admin', 'LOG_CLEAR_USER', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CLEAR_USER', false, array($user_row['username'])); } } @@ -1156,9 +1180,16 @@ class acp_users trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); } - add_log('admin', 'LOG_USER_FEEDBACK', $user_row['username']); - add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $user_row['username']); - add_log('user', $user_id, 'LOG_USER_GENERAL', $message); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array($user_row['username'])); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $user_row['username'] + )); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GENERAL', false, array( + 'reportee_id' => $user_id, + $message + )); trigger_error($user->lang['USER_FEEDBACK_ADDED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } @@ -1259,11 +1290,11 @@ class acp_users if ($log_warnings) { - add_log('admin', 'LOG_WARNINGS_DELETED', $user_row['username'], $num_warnings); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WARNINGS_DELETED', false, array($user_row['username'], $num_warnings)); } else { - add_log('admin', 'LOG_WARNINGS_DELETED_ALL', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WARNINGS_DELETED_ALL', false, array($user_row['username'])); } } } @@ -2041,7 +2072,7 @@ class acp_users $message = (sizeof($log_attachments) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']; - add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode($user->lang['COMMA_SEPARATOR'], $log_attachments)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACHMENTS_DELETED', false, array(implode($user->lang['COMMA_SEPARATOR'], $log_attachments))); trigger_error($message . adm_back_link($this->u_action . '&u=' . $user_id)); } else diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index 272d38bcc8..5f387c98a7 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -28,7 +28,7 @@ class acp_words function main($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('acp/posting'); @@ -117,7 +117,8 @@ class acp_words $cache->destroy('_word_censors'); $log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD'; - add_log('admin', $log_action, $word); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($word)); $message = ($word_id) ? $user->lang['WORD_UPDATED'] : $user->lang['WORD_ADDED']; trigger_error($message . adm_back_link($this->u_action)); @@ -148,7 +149,7 @@ class acp_words $cache->destroy('_word_censors'); - add_log('admin', 'LOG_WORD_DELETE', $deleted_word); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WORD_DELETE', false, array($deleted_word)); trigger_error($user->lang['WORD_REMOVED'] . adm_back_link($this->u_action)); } diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 6a6ec9c84d..9a6206c8d1 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2751,7 +2751,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true) { global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config; - global $request, $phpbb_container, $phpbb_dispatcher; + global $request, $phpbb_container, $phpbb_dispatcher, $phpbb_log; $err = ''; @@ -2768,7 +2768,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions if ($user->data['is_registered']) { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); } trigger_error('NO_AUTH_ADMIN'); } @@ -2784,7 +2784,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { if ($user->data['is_registered']) { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); } trigger_error('NO_AUTH_ADMIN'); } @@ -2806,7 +2806,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa if ($admin && utf8_clean_string($username) != utf8_clean_string($user->data['username'])) { // We log the attempt to use a different username... - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); trigger_error('NO_AUTH_ADMIN_USER_DIFFER'); } @@ -2819,7 +2819,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { if ($result['status'] == LOGIN_SUCCESS) { - add_log('admin', 'LOG_ADMIN_AUTH_SUCCESS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_SUCCESS'); } else { @@ -2827,7 +2827,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions if ($user->data['is_registered']) { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); } } } @@ -3197,52 +3197,6 @@ function parse_cfg_file($filename, $lines = false) return $parsed_items; } -/** -* Add log entry -* -* @param string $mode The mode defines which log_type is used and from which log the entry is retrieved -* @param int $forum_id Mode 'mod' ONLY: forum id of the related item, NOT INCLUDED otherwise -* @param int $topic_id Mode 'mod' ONLY: topic id of the related item, NOT INCLUDED otherwise -* @param int $reportee_id Mode 'user' ONLY: user id of the reportee, NOT INCLUDED otherwise -* @param string $log_operation Name of the operation -* @param array $additional_data More arguments can be added, depending on the log_type -* -* @return int|bool Returns the log_id, if the entry was added to the database, false otherwise. -* -* @deprecated Use $phpbb_log->add() instead -*/ -function add_log() -{ - global $phpbb_log, $user; - - $args = func_get_args(); - $mode = array_shift($args); - - // This looks kind of dirty, but add_log has some additional data before the log_operation - $additional_data = array(); - switch ($mode) - { - case 'admin': - case 'critical': - break; - case 'mod': - $additional_data['forum_id'] = array_shift($args); - $additional_data['topic_id'] = array_shift($args); - break; - case 'user': - $additional_data['reportee_id'] = array_shift($args); - break; - } - - $log_operation = array_shift($args); - $additional_data = array_merge($additional_data, $args); - - $user_id = (empty($user->data)) ? ANONYMOUS : $user->data['user_id']; - $user_ip = (empty($user->ip)) ? '' : $user->ip; - - return $phpbb_log->add($mode, $user_id, $user_ip, $log_operation, time(), $additional_data); -} - /** * Return a nicely formatted backtrace. * @@ -3782,7 +3736,7 @@ function phpbb_checkdnsrr($host, $type = 'MX') function msg_handler($errno, $msg_text, $errfile, $errline) { global $cache, $db, $auth, $template, $config, $user, $request; - global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text; + global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text, $phpbb_log; // Do not display notices if we suppress them via @ if (error_reporting() == 0 && $errno != E_USER_ERROR && $errno != E_USER_WARNING && $errno != E_USER_NOTICE) @@ -3818,7 +3772,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) // we are writing an image - the user won't see the debug, so let's place it in the log if (defined('IMAGE_OUTPUT') || defined('IN_CRON')) { - add_log('critical', 'LOG_IMAGE_GENERATION_ERROR', $errfile, $errline, $msg_text); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_IMAGE_GENERATION_ERROR', false, array($errfile, $errline, $msg_text)); } // echo '

    BACKTRACE
    ' . get_backtrace() . '
    ' . "\n"; } @@ -3880,7 +3834,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) { // let's avoid loops $db->sql_return_on_error(true); - add_log('critical', 'LOG_GENERAL_ERROR', $msg_title, $log_text); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_GENERAL_ERROR', false, array($msg_title, $log_text)); $db->sql_return_on_error(false); } diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index bb7022fff3..5279571c6a 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -316,7 +316,7 @@ function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $incl */ function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perms = true, $add_log = true) { - global $db; + global $db, $user, $phpbb_log; // Only one forum id specified if (!is_array($dest_forum_ids)) @@ -439,7 +439,7 @@ function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perm if ($add_log) { - add_log('admin', 'LOG_FORUM_COPIED_PERMISSIONS', $src_forum_name, implode(', ', $dest_forum_names)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_COPIED_PERMISSIONS', false, array($src_forum_name, implode(', ', $dest_forum_names))); } $db->sql_transaction('commit'); @@ -2409,7 +2409,7 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync */ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_freq) { - global $db; + global $db, $user, $phpbb_log; $sql = 'SELECT forum_name FROM ' . FORUMS_TABLE . " @@ -2430,7 +2430,7 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr WHERE forum_id = $forum_id"; $db->sql_query($sql); - add_log('admin', 'LOG_AUTO_PRUNE', $row['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_AUTO_PRUNE', false, array($row['forum_name'])); } return; diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 561c72183a..014f5d40e3 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -91,7 +91,7 @@ function phpbb_check_hash($password, $hash) * @param string $path Path to clean * @return string Cleaned path * -* @deprecated +* @deprecated 3.1.0 (To be removed: 3.3.0) */ function phpbb_clean_path($path) { @@ -135,7 +135,7 @@ function phpbb_clean_path($path) * * @return string Returns the options for timezone selector only * -* @deprecated +* @deprecated 3.1.0 (To be removed: 3.3.0) */ function tz_select($default = '', $truncate = false) { @@ -149,7 +149,7 @@ function tz_select($default = '', $truncate = false) * via admin_permissions. Changes of usernames and group names * must be carried through for the moderators table. * -* @deprecated 3.1 +* @deprecated 3.1.0 (To be removed: 3.3.0) * @return null */ function cache_moderators() @@ -161,7 +161,7 @@ function cache_moderators() /** * Removes moderators and administrators from foe lists. * -* @deprecated 3.1 +* @deprecated 3.1.0 (To be removed: 3.3.0) * @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore * @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore * @return null @@ -218,3 +218,49 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port return $file_data; } + +/** + * Add log entry + * + * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved + * @param int $forum_id Mode 'mod' ONLY: forum id of the related item, NOT INCLUDED otherwise + * @param int $topic_id Mode 'mod' ONLY: topic id of the related item, NOT INCLUDED otherwise + * @param int $reportee_id Mode 'user' ONLY: user id of the reportee, NOT INCLUDED otherwise + * @param string $log_operation Name of the operation + * @param array $additional_data More arguments can be added, depending on the log_type + * + * @return int|bool Returns the log_id, if the entry was added to the database, false otherwise. + * + * @deprecated 3.1.0 (To be removed: 3.3.0) + */ +function add_log() +{ + global $phpbb_log, $user; + + $args = func_get_args(); + $mode = array_shift($args); + + // This looks kind of dirty, but add_log has some additional data before the log_operation + $additional_data = array(); + switch ($mode) + { + case 'admin': + case 'critical': + break; + case 'mod': + $additional_data['forum_id'] = array_shift($args); + $additional_data['topic_id'] = array_shift($args); + break; + case 'user': + $additional_data['reportee_id'] = array_shift($args); + break; + } + + $log_operation = array_shift($args); + $additional_data = array_merge($additional_data, $args); + + $user_id = (empty($user->data)) ? ANONYMOUS : $user->data['user_id']; + $user_ip = (empty($user->ip)) ? '' : $user->ip; + + return $phpbb_log->add($mode, $user_id, $user_ip, $log_operation, time(), $additional_data); +} diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 1a9b1f9e11..6ea80f2a66 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -349,7 +349,7 @@ class messenger */ function error($type, $msg) { - global $user, $phpEx, $phpbb_root_path, $config, $request; + global $user, $phpEx, $phpbb_root_path, $config, $request, $phpbb_log; // Session doesn't exist, create it if (!isset($user->session_id) || $user->session_id === '') @@ -372,7 +372,7 @@ class messenger } $message .= '
    ' . htmlspecialchars($calling_page) . '

    ' . $msg . '
    '; - add_log('critical', 'LOG_ERROR_' . $type, $message); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_' . $type, false, array($message)); } /** diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 199a564210..9f94064a8f 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1492,7 +1492,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ */ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true) { - global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher; + global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log; /** * Modify the data for post submitting @@ -1665,7 +1665,13 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if ($user->data['user_id'] != $poster_id) { $log_subject = ($subject) ? $subject : $data['topic_title']; - add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, (!empty($username)) ? $username : $user->lang['GUEST'], $data['post_edit_reason']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_EDITED', false, array( + 'forum_id' => $data['forum_id'], + 'topic_id' => $data['topic_id'], + $log_subject, + (!empty($username)) ? $username : $user->lang['GUEST'], + $data['post_edit_reason'] + )); } if (!isset($sql_data[POSTS_TABLE]['sql'])) @@ -2455,7 +2461,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u */ function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false) { - global $config, $db, $user, $phpEx, $phpbb_root_path; + global $config, $db, $user, $phpEx, $phpbb_root_path, $phpbb_log; if ($bump_time === false) { @@ -2534,7 +2540,11 @@ function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false) update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false); } - add_log('mod', $forum_id, $topic_id, 'LOG_BUMP_TOPIC', $post_data['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_BUMP_TOPIC', false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $post_data['topic_title'] + )); $url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p={$post_data['topic_last_post_id']}") . "#p{$post_data['topic_last_post_id']}"; @@ -2572,7 +2582,7 @@ function phpbb_upload_popup($forum_style = 0) function phpbb_handle_post_delete($forum_id, $topic_id, $post_id, &$post_data, $is_soft = false, $delete_reason = '') { global $user, $auth, $config, $request; - global $phpbb_root_path, $phpEx; + global $phpbb_root_path, $phpEx, $phpbb_log; $perm_check = ($is_soft) ? 'softdelete' : 'delete'; @@ -2607,14 +2617,26 @@ function phpbb_handle_post_delete($forum_id, $topic_id, $post_id, &$post_data, $ if ($next_post_id === false) { - add_log('mod', $forum_id, $topic_id, (($is_soft) ? 'LOG_SOFTDELETE_TOPIC' : 'LOG_DELETE_TOPIC'), $post_data['topic_title'], $post_username, $delete_reason); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_TOPIC' : 'LOG_DELETE_TOPIC'), false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $post_data['topic_title'], + $post_username, + $delete_reason + )); $meta_info = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id"); $message = $user->lang['POST_DELETED']; } else { - add_log('mod', $forum_id, $topic_id, (($is_soft) ? 'LOG_SOFTDELETE_POST' : 'LOG_DELETE_POST'), $post_data['post_subject'], $post_username, $delete_reason); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_POST' : 'LOG_DELETE_POST'), false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $post_data['post_subject'], + $post_username, + $delete_reason + )); $meta_info = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p=$next_post_id") . "#p$next_post_id"; $message = $user->lang['POST_DELETED']; diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 191c61cf80..c51ad7b281 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -314,7 +314,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) { global $phpbb_log; - // Because these actions only fill the log unneccessarily we skip the add_log() entry. + // Because these actions only fill the log unnecessarily, we disable it $phpbb_log->disable('admin'); // Add user to "newly registered users" group and set to default group if admin specified so. @@ -798,7 +798,7 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) */ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason = '') { - global $db, $user, $auth, $cache; + global $db, $user, $auth, $cache, $phpbb_log; // Delete stale bans $sql = 'DELETE FROM ' . BANLIST_TABLE . ' @@ -1189,13 +1189,22 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas $log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_'; // Add to admin log, moderator log and user notes - add_log('admin', $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); - add_log('mod', 0, 0, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array($ban_reason, $ban_list_log)); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $ban_reason, + $ban_list_log + )); if ($mode == 'user') { foreach ($banlist_ary as $user_id) { - add_log('user', $user_id, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array( + 'reportee_id' => $user_id, + $ban_reason, + $ban_list_log + )); } } @@ -1215,7 +1224,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas */ function user_unban($mode, $ban) { - global $db, $user, $auth, $cache; + global $db, $user, $auth, $cache, $phpbb_log; // Delete stale bans $sql = 'DELETE FROM ' . BANLIST_TABLE . ' @@ -1273,13 +1282,20 @@ function user_unban($mode, $ban) $db->sql_query($sql); // Add to moderator log, admin log and user notes - add_log('admin', 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); - add_log('mod', 0, 0, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array($l_unban_list)); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $l_unban_list + )); if ($mode == 'user') { foreach ($user_ids_ary as $user_id) { - add_log('user', $user_id, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array( + 'reportee_id' => $user_id, + $l_unban_list + )); } } } @@ -2219,7 +2235,7 @@ function phpbb_avatar_explanation_string() */ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow_desc_bbcode = false, $allow_desc_urls = false, $allow_desc_smilies = false) { - global $phpbb_root_path, $config, $db, $user, $file_upload, $phpbb_container; + global $phpbb_root_path, $config, $db, $user, $file_upload, $phpbb_container, $phpbb_log; $error = array(); @@ -2473,7 +2489,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow } $name = ($type == GROUP_SPECIAL) ? $user->lang['G_' . $name] : $name; - add_log('admin', $log, $name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($name)); group_update_listings($group_id); } @@ -2526,7 +2542,7 @@ function avatar_remove_db($avatar_name) */ function group_delete($group_id, $group_name = false) { - global $db, $cache, $auth, $user, $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_container; + global $db, $cache, $auth, $user, $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_container, $phpbb_log; if (!$group_name) { @@ -2625,7 +2641,7 @@ function group_delete($group_id, $group_name = false) phpbb_cache_moderators($db, $cache, $auth); - add_log('admin', 'LOG_GROUP_DELETE', $group_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_GROUP_DELETE', false, array($group_name)); // Return false - no error return false; @@ -2638,7 +2654,7 @@ function group_delete($group_id, $group_name = false) */ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $default = false, $leader = 0, $pending = 0, $group_attributes = false) { - global $db, $auth, $phpbb_container; + global $db, $auth, $user, $phpbb_container, $phpbb_log; // We need both username and user_id info $result = user_get_id_name($user_id_ary, $username_ary); @@ -2722,7 +2738,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $log = ($leader) ? 'LOG_MODS_ADDED' : (($pending) ? 'LOG_USERS_PENDING' : 'LOG_USERS_ADDED'); - add_log('admin', $log, $group_name, implode(', ', $username_ary)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary))); group_update_listings($group_id); @@ -2754,7 +2770,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, */ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false) { - global $db, $auth, $config, $phpbb_dispatcher, $phpbb_container; + global $db, $auth, $config, $user, $phpbb_dispatcher, $phpbb_container, $phpbb_log; if ($config['coppa_enable']) { @@ -2883,7 +2899,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, if ($group_name) { - add_log('admin', $log, $group_name, implode(', ', $username_ary)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary))); } group_update_listings($group_id); @@ -2982,7 +2998,7 @@ function remove_default_rank($group_id, $user_ids) */ function group_user_attributes($action, $group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $group_attributes = false) { - global $db, $auth, $phpbb_root_path, $phpEx, $config, $phpbb_container; + global $db, $auth, $user, $phpbb_root_path, $phpEx, $config, $phpbb_container, $phpbb_log; // We need both username and user_id info $result = user_get_id_name($user_id_ary, $username_ary); @@ -3117,7 +3133,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna // Clear permissions cache of relevant users $auth->acl_clear_prefetch($user_id_ary); - add_log('admin', $log, $group_name, implode(', ', $username_ary)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary))); group_update_listings($group_id); diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index 8d2cc478f3..be17d7fe47 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -339,7 +339,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) */ function mcp_resync_topics($topic_ids) { - global $auth, $db, $template, $phpEx, $user, $phpbb_root_path; + global $auth, $db, $template, $phpEx, $user, $phpbb_root_path, $phpbb_log; if (!sizeof($topic_ids)) { @@ -364,7 +364,11 @@ function mcp_resync_topics($topic_ids) // Log this action while ($row = $db->sql_fetchrow($result)) { - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_TOPIC_RESYNC', $row['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_RESYNC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + $row['topic_title'] + )); } $db->sql_freeresult($result); @@ -383,7 +387,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_log; if (!sizeof($topic_ids)) { @@ -463,7 +467,12 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) $to_forum_id = $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']); + + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MERGE', false, array( + 'forum_id' => $to_forum_id, + 'topic_id' => $to_topic_id, + $topic_data['topic_title'] + )); // Message and return links $success_msg = 'POSTS_MERGED_SUCCESS'; diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index bb3f8c3d2e..c084f5af52 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -237,7 +237,7 @@ class mcp_main */ function lock_unlock($action, $ids) { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request; + global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_log; if ($action == 'lock' || $action == 'unlock') { @@ -294,7 +294,11 @@ function lock_unlock($action, $ids) foreach ($data as $id => $row) { - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_' . strtoupper($action), $row['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($action), false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + $row['topic_title'] + )); } $success_msg = $l_prefix . ((sizeof($ids) == 1) ? '' : 'S') . '_' . (($action == 'lock' || $action == 'lock_post') ? 'LOCKED' : 'UNLOCKED') . '_SUCCESS'; @@ -321,7 +325,7 @@ function lock_unlock($action, $ids) */ function change_topic_type($action, $topic_ids) { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request; + global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_log; switch ($action) { @@ -396,7 +400,11 @@ function change_topic_type($action, $topic_ids) foreach ($data as $topic_id => $row) { - add_log('mod', $forum_id, $topic_id, 'LOG_TOPIC_TYPE_CHANGED', $row['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_TYPE_CHANGED', false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $row['topic_title'] + )); } } @@ -679,7 +687,7 @@ function mcp_move_topic($topic_ids) */ function mcp_restore_topic($topic_ids) { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container; + global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log; if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_approve'))) { @@ -710,7 +718,12 @@ function mcp_restore_topic($topic_ids) $return = $phpbb_content_visibility->set_topic_visibility(ITEM_APPROVED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), ''); if (!empty($return)) { - add_log('mod', $row['forum_id'], $topic_id, 'LOG_RESTORE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_RESTORE_TOPIC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $topic_id, + $row['topic_title'], + $row['topic_first_poster_name'] + )); } } } @@ -753,7 +766,7 @@ function mcp_restore_topic($topic_ids) */ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_topic') { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container; + global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log; $check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete'; if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array($check_permission))) @@ -782,7 +795,11 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' { if ($row['topic_moved_id']) { - add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_SHADOW_TOPIC', $row['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_SHADOW_TOPIC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $topic_id, + $row['topic_title'] + )); } else { @@ -794,12 +811,24 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' $return = $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), $soft_delete_reason); if (!empty($return)) { - add_log('mod', $row['forum_id'], $topic_id, 'LOG_SOFTDELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name'], $soft_delete_reason); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_TOPIC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $topic_id, + $row['topic_title'], + $row['topic_first_poster_name'], + $soft_delete_reason + )); } } else { - add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name'], $soft_delete_reason); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_TOPIC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $topic_id, + $row['topic_title'], + $row['topic_first_poster_name'], + $soft_delete_reason + )); } } } @@ -893,7 +922,7 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' */ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_post') { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container; + global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log; $check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete'; if (!phpbb_check_ids($post_ids, POSTS_TABLE, 'post_id', array($check_permission))) @@ -965,7 +994,13 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', foreach ($approve_log as $row) { $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username']; - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_SOFTDELETE_POST', $row['post_subject'], $post_username, $soft_delete_reason); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_POST', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + $row['post_subject'], + $post_username, + $soft_delete_reason + )); } $topic_id = $request->variable('t', 0); @@ -1008,7 +1043,13 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', foreach ($post_data as $id => $row) { $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username']; - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_DELETE_POST', $row['post_subject'], $post_username, $soft_delete_reason); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_POST', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + $row['post_subject'], + $post_username, + $soft_delete_reason + )); } // Now delete the posts, topics and forums are automatically resync'ed @@ -1122,7 +1163,7 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', function mcp_fork_topic($topic_ids) { global $auth, $user, $db, $template, $config; - global $phpEx, $phpbb_root_path; + global $phpEx, $phpbb_root_path, $phpbb_log; if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) { @@ -1479,7 +1520,11 @@ function mcp_fork_topic($topic_ids) foreach ($new_topic_id_list as $topic_id => $new_topic_id) { - add_log('mod', $to_forum_id, $new_topic_id, 'LOG_FORK', $topic_row['forum_name']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_FORK', false, array( + 'forum_id' => $to_forum_id, + 'topic_id' => $new_topic_id, + $topic_row['forum_name'] + )); } $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS'; diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php index dd7a61fb53..4fd17ccf48 100644 --- a/phpBB/includes/mcp/mcp_notes.php +++ b/phpBB/includes/mcp/mcp_notes.php @@ -74,7 +74,7 @@ class mcp_notes */ function mcp_notes_user_view($action) { - global $phpEx, $phpbb_root_path, $config; + global $phpEx, $phpbb_root_path, $config, $phpbb_log; global $template, $db, $user, $auth, $phpbb_container; $user_id = request_var('u', 0); @@ -144,7 +144,7 @@ class mcp_notes $where_sql"; $db->sql_query($sql); - add_log('admin', 'LOG_CLEAR_USER', $userrow['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CLEAR_USER', false, array($userrow['username'])); $msg = ($deletemark) ? 'MARKED_NOTES_DELETED' : 'ALL_NOTES_DELETED'; } @@ -162,10 +162,17 @@ class mcp_notes { if (check_form_key('mcp_notes')) { - add_log('admin', 'LOG_USER_FEEDBACK', $userrow['username']); - add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $userrow['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array($userrow['username'])); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $userrow['username'] + )); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GENERAL', false, array( + 'reportee_id' => $user_id, + $usernote + )); - add_log('user', $user_id, 'LOG_USER_GENERAL', $usernote); $msg = $user->lang['USER_FEEDBACK_ADDED']; } else diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 1687409198..c5f89cddef 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -420,7 +420,7 @@ function mcp_post_details($id, $mode, $action) */ function change_poster(&$post_info, $userdata) { - global $auth, $db, $config, $phpbb_root_path, $phpEx, $user; + global $auth, $db, $config, $phpbb_root_path, $phpEx, $user, $phpbb_log; if (empty($userdata) || $userdata['user_id'] == $post_info['user_id']) { @@ -519,5 +519,11 @@ function change_poster(&$post_info, $userdata) $post_info = $post_info[$post_id]; // Now add log entry - add_log('mod', $post_info['forum_id'], $post_info['topic_id'], 'LOG_MCP_CHANGE_POSTER', $post_info['topic_title'], $from_username, $to_username); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MCP_CHANGE_POSTER', false, array( + 'forum_id' => $post_info['forum_id'], + 'topic_id' => $post_info['topic_id'], + $post_info['topic_title'], + $from_username, + $to_username + )); } diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index d4bb9e402f..8884dac315 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -620,7 +620,7 @@ class mcp_queue static public function approve_posts($action, $post_id_list, $id, $mode) { global $db, $template, $user, $config, $request, $phpbb_container; - global $phpEx, $phpbb_root_path; + global $phpEx, $phpbb_root_path, $phpbb_log; if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) { @@ -691,7 +691,11 @@ class mcp_queue foreach ($approve_log as $log_data) { - add_log('mod', $log_data['forum_id'], $log_data['topic_id'], 'LOG_POST_' . strtoupper($action) . 'D', $log_data['post_subject']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_' . strtoupper($action) . 'D', false, array( + 'forum_id' => $log_data['forum_id'], + 'topic_id' => $log_data['topic_id'], + $log_data['post_subject'] + )); } // Only send out the mails, when the posts are being approved @@ -844,7 +848,7 @@ class mcp_queue */ static public function approve_topics($action, $topic_id_list, $id, $mode) { - global $db, $template, $user, $config; + global $db, $template, $user, $config, $phpbb_log; global $phpEx, $phpbb_root_path, $request, $phpbb_container; if (!phpbb_check_ids($topic_id_list, TOPICS_TABLE, 'topic_id', array('m_approve'))) @@ -896,7 +900,11 @@ class mcp_queue foreach ($approve_log as $log_data) { - add_log('mod', $log_data['forum_id'], $log_data['topic_id'], 'LOG_TOPIC_' . strtoupper($action) . 'D', $log_data['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_' . strtoupper($action) . 'D', false, array( + 'forum_id' => $log_data['forum_id'], + 'topic_id' => $log_data['topic_id'], + $log_data['topic_title'] + )); } // Only send out the mails, when the posts are being approved @@ -1016,7 +1024,7 @@ class mcp_queue static public function disapprove_posts($post_id_list, $id, $mode) { global $db, $template, $user, $config, $phpbb_container; - global $phpEx, $phpbb_root_path, $request; + global $phpEx, $phpbb_root_path, $request, $phpbb_log; if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) { @@ -1165,12 +1173,23 @@ class mcp_queue if ($is_disapproving) { $l_log_message = ($log_data['type'] == 'topic') ? 'LOG_TOPIC_DISAPPROVED' : 'LOG_POST_DISAPPROVED'; - add_log('mod', $log_data['forum_id'], $log_data['topic_id'], $l_log_message, $log_data['post_subject'], $disapprove_reason, $log_data['post_username']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, $l_log_message, false, array( + 'forum_id' => $log_data['forum_id'], + 'topic_id' => $log_data['topic_id'], + $log_data['post_subject'], + $disapprove_reason, + $log_data['post_username'] + )); } else { $l_log_message = ($log_data['type'] == 'topic') ? 'LOG_DELETE_TOPIC' : 'LOG_DELETE_POST'; - add_log('mod', $log_data['forum_id'], $log_data['topic_id'], $l_log_message, $log_data['post_subject'], $log_data['post_username']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, $l_log_message, false, array( + 'forum_id' => $log_data['forum_id'], + 'topic_id' => $log_data['topic_id'], + $log_data['post_subject'], + $log_data['post_username'] + )); } } } diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 26f6a532c9..b54703bd9f 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -473,7 +473,7 @@ class mcp_reports */ function close_report($report_id_list, $mode, $action, $pm = false) { - global $db, $template, $user, $config, $auth; + global $db, $template, $user, $config, $auth, $phpbb_log; global $phpEx, $phpbb_root_path, $phpbb_container; $pm_where = ($pm) ? ' AND r.post_id = 0 ' : ' AND r.pm_id = 0 '; @@ -654,12 +654,20 @@ function close_report($report_id_list, $mode, $action, $pm = false) { if ($pm) { - add_log('mod', 0, 0, 'LOG_PM_REPORT_' . strtoupper($action) . 'D', $post_info[$report['pm_id']]['message_subject']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_PM_REPORT_' . strtoupper($action) . 'D', false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $post_info[$report['pm_id']]['message_subject'] + )); $phpbb_notifications->delete_notifications('notification.type.report_pm', $report['pm_id']); } else { - add_log('mod', $post_info[$report['post_id']]['forum_id'], $post_info[$report['post_id']]['topic_id'], 'LOG_REPORT_' . strtoupper($action) . 'D', $post_info[$report['post_id']]['post_subject']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_REPORT_' . strtoupper($action) . 'D', false, array( + 'forum_id' => $post_info[$report['post_id']]['forum_id'], + 'topic_id' => $post_info[$report['post_id']]['topic_id'], + $post_info[$report['post_id']]['post_subject'] + )); $phpbb_notifications->delete_notifications('notification.type.report_post', $report['post_id']); } } diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 08002fa952..d43594c564 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -358,7 +358,7 @@ function mcp_topic_view($id, $mode, $action) */ function split_topic($action, $topic_id, $to_forum_id, $subject) { - global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config; + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config, $phpbb_log; $post_id_list = request_var('post_id_list', array(0)); $forum_id = request_var('forum_id', 0); @@ -510,8 +510,16 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) $topic_info = phpbb_get_topic_data(array($topic_id)); $topic_info = $topic_info[$topic_id]; - add_log('mod', $to_forum_id, $to_topic_id, 'LOG_SPLIT_DESTINATION', $subject); - add_log('mod', $forum_id, $topic_id, 'LOG_SPLIT_SOURCE', $topic_info['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SPLIT_DESTINATION', false, array( + 'forum_id' => $to_forum_id, + 'topic_id' => $to_topic_id, + $subject + )); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SPLIT_SOURCE', false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $topic_info['topic_title'] + )); // Change topic title of first post $sql = 'UPDATE ' . POSTS_TABLE . " @@ -586,7 +594,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) */ function merge_posts($topic_id, $to_topic_id) { - global $db, $template, $user, $phpEx, $phpbb_root_path, $auth; + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $phpbb_log; if (!$to_topic_id) { @@ -645,7 +653,12 @@ function merge_posts($topic_id, $to_topic_id) $to_forum_id = $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']); + + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MERGE', false, array( + 'forum_id' => $to_forum_id, + 'topic_id' => $to_topic_id, + $topic_data['topic_title'] + )); // Message and return links $success_msg = 'POSTS_MERGED_SUCCESS'; diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php index 7c0bb12250..85101da5ec 100644 --- a/phpBB/includes/mcp/mcp_warn.php +++ b/phpBB/includes/mcp/mcp_warn.php @@ -523,7 +523,7 @@ class mcp_warn */ function add_warning($user_row, $warning, $send_pm = true, $post_id = 0) { - global $phpEx, $phpbb_root_path, $config; + global $phpEx, $phpbb_root_path, $config, $phpbb_log; global $template, $db, $user, $auth; if ($send_pm) @@ -557,8 +557,11 @@ function add_warning($user_row, $warning, $send_pm = true, $post_id = 0) submit_pm('post', $user->lang('WARNING_PM_SUBJECT'), $pm_data, false); } - add_log('admin', 'LOG_USER_WARNING', $user_row['username']); - $log_id = add_log('user', $user_row['user_id'], 'LOG_USER_WARNING_BODY', $warning); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_WARNING', false, array($user_row['username'])); + $log_id = $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_WARNING_BODY', false, array( + 'reportee_id' => $user_row['user_id'], + $warning + )); $sql_ary = array( 'user_id' => $user_row['user_id'], @@ -583,5 +586,9 @@ function add_warning($user_row, $warning, $send_pm = true, $post_id = 0) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_USER_WARNING', $user_row['username']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_USER_WARNING', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + $user_row['username'] + )); } diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index bc44d70e3e..4ee9447f00 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -30,7 +30,7 @@ class ucp_activate function main($id, $mode) { global $config, $phpbb_root_path, $phpEx; - global $db, $user, $auth, $template, $phpbb_container; + global $db, $user, $auth, $template, $phpbb_container, $phpbb_log; $user_id = request_var('u', 0); $key = request_var('k', ''); @@ -86,7 +86,10 @@ class ucp_activate WHERE user_id = ' . $user_row['user_id']; $db->sql_query($sql); - add_log('user', $user_row['user_id'], 'LOG_USER_NEW_PASSWORD', $user_row['username']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array( + 'reportee_id' => $user_row['user_id'], + $user_row['username'] + )); } if (!$update_password) @@ -101,10 +104,13 @@ class ucp_activate $db->sql_query($sql); // Create the correct logs - add_log('user', $user_row['user_id'], 'LOG_USER_ACTIVE_USER'); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE_USER', false, array( + 'reportee_id' => $user_row['user_id'] + )); + if ($auth->acl_get('a_user')) { - add_log('admin', 'LOG_USER_ACTIVE', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE', false, array($user_row['username'])); } } diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index 6f4ad0a502..a33828b1cf 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -30,7 +30,7 @@ class ucp_groups { global $config, $phpbb_root_path, $phpEx, $phpbb_admin_path; global $db, $user, $auth, $cache, $template; - global $request, $phpbb_container; + global $request, $phpbb_container, $phpbb_log; $user->add_lang('groups'); @@ -99,7 +99,10 @@ class ucp_groups { group_user_attributes('default', $group_id, $user->data['user_id']); - add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_CHANGE', sprintf($user->lang['USER_GROUP_CHANGE'], $group_row[$user->data['group_id']]['group_name'], $group_row[$group_id]['group_name'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_CHANGE', false, array( + 'reportee_id' => $user->data['user_id'], + sprintf($user->lang['USER_GROUP_CHANGE'], $group_row[$user->data['group_id']]['group_name'], $group_row[$group_id]['group_name']) + )); meta_refresh(3, $this->u_action); trigger_error($user->lang['CHANGED_DEFAULT_GROUP'] . $return_page); @@ -146,7 +149,10 @@ class ucp_groups { group_user_del($group_id, $user->data['user_id']); - add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_RESIGN', $group_row[$group_id]['group_name']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_RESIGN', false, array( + 'reportee_id' => $user->data['user_id'], + $group_row[$group_id]['group_name'] + )); meta_refresh(3, $this->u_action); trigger_error($user->lang[($row['user_pending']) ? 'GROUP_RESIGNED_PENDING' : 'GROUP_RESIGNED_MEMBERSHIP'] . $return_page); @@ -202,7 +208,10 @@ class ucp_groups group_user_add($group_id, $user->data['user_id'], false, false, false, 0, 1); } - add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), $group_row[$group_id]['group_name']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), false, array( + 'reportee_id' => $user->data['user_id'], + $group_row[$group_id]['group_name'] + )); meta_refresh(3, $this->u_action); trigger_error($user->lang[($group_row[$group_id]['group_type'] == GROUP_FREE) ? 'GROUP_JOINED' : 'GROUP_JOINED_PENDING'] . $return_page); @@ -237,7 +246,10 @@ class ucp_groups { group_user_attributes('demote', $group_id, $user->data['user_id']); - add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_DEMOTE', $group_row[$group_id]['group_name']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_DEMOTE', false, array( + 'reportee_id' => $user->data['user_id'], + $group_row[$group_id]['group_name'] + )); meta_refresh(3, $this->u_action); trigger_error($user->lang['USER_GROUP_DEMOTED'] . $return_page); diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index d230f3865f..56be48ff62 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -32,7 +32,7 @@ class ucp_profile function main($id, $mode) { global $cache, $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; - global $request, $phpbb_container; + global $request, $phpbb_container, $phpbb_log; $user->add_lang('posting'); @@ -116,18 +116,30 @@ class ucp_profile if ($auth->acl_get('u_chgname') && $config['allow_namechange'] && $data['username'] != $user->data['username']) { - add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_NAME', $user->data['username'], $data['username']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_NAME', false, array( + 'reportee_id' => $user->data['user_id'], + $user->data['username'], + $data['username'] + )); } if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && !$passwords_manager->check($data['new_password'], $user->data['user_password'])) { $user->reset_login_keys(); - add_log('user', $user->data['user_id'], 'LOG_USER_NEW_PASSWORD', $data['username']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array( + 'reportee_id' => $user->data['user_id'], + $user->data['username'] + )); } if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email']) { - add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_EMAIL', $data['username'], $user->data['user_email'], $data['email']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_EMAIL', false, array( + 'reportee_id' => $user->data['user_id'], + $user->data['username'], + $data['user_email'], + $data['email'] + )); } $message = 'PROFILE_UPDATED'; diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index c5ddf9e6e9..2d9dc097b0 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -246,7 +246,7 @@ while (!$migrator->finished()) if ($orig_version != $config['version']) { - add_log('admin', 'LOG_UPDATE_DATABASE', $orig_version, $config['version']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UPDATE_DATABASE', false, array($orig_version, $config['version'])); } echo $user->lang['DATABASE_UPDATE_COMPLETE'] . '
    '; diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index 40defe754a..55bbcb5e02 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -1604,9 +1604,7 @@ class install_convert extends module phpbb_cache_moderators($db, $cache, $auth); // And finally, add a note to the log - /* @var $phpbb_log \phpbb\log\log_interface */ - $phpbb_log = $phpbb_container->get('log'); - add_log('admin', 'LOG_INSTALL_CONVERTED', $convert->convertor_data['forum_name'], $config['version']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_CONVERTED', false, array($convert->convertor_data['forum_name'], $config['version'])); $url = $this->p_master->module_url . "?mode={$this->mode}&sub=final&language=$language"; diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 500992feac..303d185e84 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -1975,7 +1975,7 @@ class install_install extends module */ function email_admin($mode, $sub) { - global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; $this->page_title = $lang['STAGE_FINAL']; @@ -2016,7 +2016,7 @@ class install_install extends module } // And finally, add a note to the log - add_log('admin', 'LOG_INSTALL_INSTALLED', $config['version']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_INSTALLED', false, array($config['version'])); $template->assign_vars(array( 'TITLE' => $lang['INSTALL_CONGRATS'], diff --git a/phpBB/phpbb/captcha/plugins/gd.php b/phpBB/phpbb/captcha/plugins/gd.php index f6200b5b2f..129fc0c907 100644 --- a/phpBB/phpbb/captcha/plugins/gd.php +++ b/phpBB/phpbb/captcha/plugins/gd.php @@ -53,7 +53,7 @@ class gd extends captcha_abstract function acp_page($id, &$module) { - global $db, $user, $auth, $template; + global $db, $user, $auth, $template, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('acp/board'); @@ -84,7 +84,7 @@ class gd extends captcha_abstract } } - add_log('admin', 'LOG_CONFIG_VISUAL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL'); trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); } else if ($submit) diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index ca242a96dc..a545cccbac 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -611,7 +611,7 @@ class qa */ function acp_page($id, &$module) { - global $db, $user, $auth, $template; + global $db, $user, $auth, $template, $phpbb_log; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('acp/board'); @@ -742,7 +742,7 @@ class qa $this->acp_add_question($data); } - add_log('admin', 'LOG_CONFIG_VISUAL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL'); trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url)); } } diff --git a/phpBB/phpbb/captcha/plugins/recaptcha.php b/phpBB/phpbb/captcha/plugins/recaptcha.php index 584f3afec1..a335dedfce 100644 --- a/phpBB/phpbb/captcha/plugins/recaptcha.php +++ b/phpBB/phpbb/captcha/plugins/recaptcha.php @@ -75,7 +75,7 @@ class recaptcha extends captcha_abstract function acp_page($id, &$module) { - global $config, $db, $template, $user; + global $config, $db, $template, $user, $phpbb_log; $captcha_vars = array( 'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY', @@ -101,7 +101,7 @@ class recaptcha extends captcha_abstract } } - add_log('admin', 'LOG_CONFIG_VISUAL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL'); trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); } else if ($submit) diff --git a/phpBB/phpbb/cron/task/core/tidy_plupload.php b/phpBB/phpbb/cron/task/core/tidy_plupload.php index b6aeecf4b4..d7364374af 100644 --- a/phpBB/phpbb/cron/task/core/tidy_plupload.php +++ b/phpBB/phpbb/cron/task/core/tidy_plupload.php @@ -67,6 +67,8 @@ class tidy_plupload extends \phpbb\cron\task\base */ public function run() { + global $user, $phpbb_log; + // Remove old temporary file (perhaps failed uploads?) $last_valid_timestamp = time() - $this->max_file_age; try @@ -88,13 +90,11 @@ class tidy_plupload extends \phpbb\cron\task\base } catch (\UnexpectedValueException $e) { - add_log( - 'critical', - 'LOG_PLUPLOAD_TIDY_FAILED', + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_PLUPLOAD_TIDY_FAILED', false, array( $this->plupload_upload_path, $e->getMessage(), $e->getTraceAsString() - ); + )); } $this->config->set('plupload_last_gc', time(), true); diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php index 035625b095..b6f0372181 100644 --- a/phpBB/phpbb/db/migration/tool/module.php +++ b/phpBB/phpbb/db/migration/tool/module.php @@ -171,6 +171,8 @@ class module implements \phpbb\db\migration\tool\tool_interface */ public function add($class, $parent = 0, $data = array()) { + global $user, $phpbb_log; + // Allows '' to be sent as 0 $parent = $parent ?: 0; @@ -266,7 +268,7 @@ class module implements \phpbb\db\migration\tool\tool_interface { // Success $module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']); - add_log('admin', 'LOG_MODULE_ADD', $module_log_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($module_log_name)); // Move the module if requested above/below an existing one if (isset($data['before']) && $data['before']) diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php index 0c5205530b..4bb2e7a75a 100644 --- a/phpBB/phpbb/log/log.php +++ b/phpBB/phpbb/log/log.php @@ -27,7 +27,7 @@ class log implements \phpbb\log\log_interface /** * An array with the disabled log types. Logs of such types will not be - * added when add_log() is called. + * added when add() is called. * @var array */ protected $disabled_types; @@ -223,14 +223,14 @@ class log implements \phpbb\log\log_interface return false; } - if ($log_time == false) + if ($log_time === false) { $log_time = time(); } $sql_ary = array( - 'user_id' => $user_id, - 'log_ip' => $log_ip, + 'user_id' => $user_id ? (int) $user_id : ANONYMOUS, + 'log_ip' => empty($log_ip) ? '' : $log_ip, 'log_time' => $log_time, 'log_operation' => $log_operation, ); diff --git a/phpBB/phpbb/log/log_interface.php b/phpBB/phpbb/log/log_interface.php index 5932f722aa..86286e6f88 100644 --- a/phpBB/phpbb/log/log_interface.php +++ b/phpBB/phpbb/log/log_interface.php @@ -32,8 +32,8 @@ interface log_interface * Disable log * * This function allows disabling the log system or parts of it, for this - * page call. When add_log is called and the type is disabled, - * the log will not be added to the database. + * page call. When add() is called and the type is disabled, the log will + * not be added to the database. * * @param mixed $type The log type we want to disable. Empty to * disable all logs. Can also be an array of types. @@ -57,12 +57,12 @@ interface log_interface /** * Adds a log entry to the database * - * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved - * @param int $user_id User ID of the user - * @param string $log_ip IP address of the user - * @param string $log_operation Name of the operation - * @param int $log_time Timestamp when the log entry was added, if empty time() will be used - * @param array $additional_data More arguments can be added, depending on the log_type + * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved + * @param int $user_id User ID of the user + * @param string $log_ip IP address of the user + * @param string $log_operation Name of the operation + * @param int|bool $log_time Timestamp when the log entry was added. If false, time() will be used + * @param array $additional_data More arguments can be added, depending on the log_type * * @return int|bool Returns the log_id, if the entry was added to the database, false otherwise. */ diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php index 2765d05b94..c62bacf470 100644 --- a/phpBB/phpbb/search/fulltext_sphinx.php +++ b/phpBB/phpbb/search/fulltext_sphinx.php @@ -454,6 +454,8 @@ class fulltext_sphinx */ public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) { + global $user, $phpbb_log; + // No keywords? No posts. if (!strlen($this->search_query) && !sizeof($author_ary)) { @@ -601,7 +603,7 @@ class fulltext_sphinx if ($this->sphinx->GetLastError()) { - add_log('critical', 'LOG_SPHINX_ERROR', $this->sphinx->GetLastError()); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_SPHINX_ERROR', false, array($this->sphinx->GetLastError())); if ($this->auth->acl_get('a_')) { trigger_error($this->user->lang('SPHINX_SEARCH_FAILED', $this->sphinx->GetLastError())); diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 5b9fb6d835..114912b2aa 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -215,7 +215,7 @@ class session function session_begin($update_session_page = true) { global $phpEx, $SID, $_SID, $_EXTRA_URL, $db, $config, $phpbb_root_path; - global $request, $phpbb_container; + global $request, $phpbb_container, $user, $phpbb_log; // Give us some basic information $this->time_now = time(); @@ -490,11 +490,18 @@ class session { if ($referer_valid) { - add_log('critical', 'LOG_IP_BROWSER_FORWARDED_CHECK', $u_ip, $s_ip, $u_browser, $s_browser, htmlspecialchars($u_forwarded_for), htmlspecialchars($s_forwarded_for)); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_IP_BROWSER_FORWARDED_CHECK', false, array( + $u_ip, + $s_ip, + $u_browser, + $s_browser, + htmlspecialchars($u_forwarded_for), + htmlspecialchars($s_forwarded_for) + )); } else { - add_log('critical', 'LOG_REFERER_INVALID', $this->referer); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_REFERER_INVALID', false, array($this->referer)); } } } diff --git a/phpBB/posting.php b/phpBB/posting.php index 0f2ea303ea..8b90b3b04a 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1293,7 +1293,11 @@ if ($submit || $preview || $refresh) $user_lock = ($auth->acl_get('f_user_lock', $forum_id) && $user->data['is_registered'] && $user->data['user_id'] == $post_data['topic_poster']) ? 'USER_' : ''; - add_log('mod', $forum_id, $topic_id, 'LOG_' . $user_lock . (($change_topic_status == ITEM_LOCKED) ? 'LOCK' : 'UNLOCK'), $post_data['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_' . $user_lock . (($change_topic_status == ITEM_LOCKED) ? 'LOCK' : 'UNLOCK'), false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $post_data['topic_title'] + )); } // Lock/Unlock Post Edit diff --git a/phpBB/ucp.php b/phpBB/ucp.php index 8c74ca1f3c..b2b15228e6 100644 --- a/phpBB/ucp.php +++ b/phpBB/ucp.php @@ -234,7 +234,7 @@ switch ($mode) redirect(append_sid("{$phpbb_root_path}index.$phpEx")); } - add_log('admin', 'LOG_ACL_TRANSFER_PERMISSIONS', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_TRANSFER_PERMISSIONS', false, array($user_row['username'])); $message = sprintf($user->lang['PERMISSIONS_TRANSFERRED'], $user_row['username']) . '

    ' . sprintf($user->lang['RETURN_INDEX'], '', ''); trigger_error($message); @@ -257,7 +257,7 @@ switch ($mode) $username = $db->sql_fetchfield('username'); $db->sql_freeresult($result); - add_log('admin', 'LOG_ACL_RESTORE_PERMISSIONS', $username); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_RESTORE_PERMISSIONS', false, array($username)); $message = $user->lang['PERMISSIONS_RESTORED'] . '

    ' . sprintf($user->lang['RETURN_INDEX'], '', ''); trigger_error($message); diff --git a/tests/dbal/migrator_tool_module_test.php b/tests/dbal/migrator_tool_module_test.php index 08c3e979b8..fa2a8c33df 100644 --- a/tests/dbal/migrator_tool_module_test.php +++ b/tests/dbal/migrator_tool_module_test.php @@ -27,7 +27,7 @@ class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case parent::setup(); - // Force add_log function to not be used + // Disable the logs $skip_add_log = true; $db = $this->db = $this->new_dbal(); diff --git a/tests/log/function_add_log_test.php b/tests/log/function_add_log_test.php index 63e468498e..78949734a9 100644 --- a/tests/log/function_add_log_test.php +++ b/tests/log/function_add_log_test.php @@ -11,7 +11,7 @@ * */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_compatibility.php'; class phpbb_log_function_add_log_test extends phpbb_database_test_case { From fc412a97ca355b910d6b6e52d4b1a28d0e8ce2c8 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Thu, 29 Jan 2015 01:40:54 -0800 Subject: [PATCH 0086/1676] [ticket/10388] Convert LA usages to L when not in javascript context PHPBB3-10388 --- phpBB/styles/prosilver/template/captcha_recaptcha.html | 2 +- phpBB/styles/prosilver/template/memberlist_body.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/styles/prosilver/template/captcha_recaptcha.html b/phpBB/styles/prosilver/template/captcha_recaptcha.html index fee0f7423e..d3c0ea95d6 100644 --- a/phpBB/styles/prosilver/template/captcha_recaptcha.html +++ b/phpBB/styles/prosilver/template/captcha_recaptcha.html @@ -29,7 +29,7 @@ - + diff --git a/phpBB/styles/prosilver/template/memberlist_body.html b/phpBB/styles/prosilver/template/memberlist_body.html index 512df7b0a7..841f542bbc 100644 --- a/phpBB/styles/prosilver/template/memberlist_body.html +++ b/phpBB/styles/prosilver/template/memberlist_body.html @@ -25,7 +25,7 @@
    user_id @@ -58,5 +64,20 @@ 30 + + 4 + 4 + 0 + + + 5 + 3 + 1 + + + 5 + 2 + 0 +
    diff --git a/tests/functions_privmsgs/get_max_setting_from_group_test.php b/tests/functions_privmsgs/get_max_setting_from_group_test.php index 48d42ec48a..3eb7866802 100644 --- a/tests/functions_privmsgs/get_max_setting_from_group_test.php +++ b/tests/functions_privmsgs/get_max_setting_from_group_test.php @@ -36,9 +36,13 @@ class phpbb_functions_privmsgs_get_max_setting_from_group_test extends phpbb_dat array(1, 0, 'message_limit'), array(2, 2, 'message_limit'), array(3, 0, 'message_limit'), + array(4, 0, 'message_limit'), + array(5, 2, 'message_limit'), array(1, 0, 'max_recipients'), array(2, 4, 'max_recipients'), array(3, 0, 'max_recipients'), + array(4, 5, 'max_recipients'), + array(5, 4, 'max_recipients'), ); } From c76d797cb2c4abb97c4e887b8c175626c7c9ba1e Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 3 Feb 2015 23:17:04 +0100 Subject: [PATCH 0109/1676] [ticket/9109] Improve docblock and fix spelling errors PHPBB3-9109 --- phpBB/includes/functions_privmsgs.php | 1 + phpBB/language/en/acp/groups.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 10a1b8d4ad..0465f3b00f 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -2153,6 +2153,7 @@ function set_user_message_limit() * @param int $user_id * @param string $setting Only 'max_recipients' and 'message_limit' are supported * @return int The maximum setting for all groups of the user, unless one group has '0' + * @throws \InvalidArgumentException If selected group setting is not supported */ function phpbb_get_max_setting_from_group(\phpbb\db\driver\driver_interface $db, $user_id, $setting) { diff --git a/phpBB/language/en/acp/groups.php b/phpBB/language/en/acp/groups.php index 020f171b1b..421075ce5e 100644 --- a/phpBB/language/en/acp/groups.php +++ b/phpBB/language/en/acp/groups.php @@ -83,7 +83,7 @@ $lang = array_merge($lang, array( 'GROUP_MEMBERS' => 'Group members', 'GROUP_MEMBERS_EXPLAIN' => 'This is a complete listing of all the members of this usergroup. It includes separate sections for leaders, pending and existing members. From here you can manage all aspects of who has membership of this group and what their role is. To remove a leader but keep them in the group use Demote rather than delete. Similarly use Promote to make an existing member a leader.', 'GROUP_MESSAGE_LIMIT' => 'Group private message limit per folder', - 'GROUP_MESSAGE_LIMIT_EXPLAIN' => 'This setting overrides the per-user folder message limit. The maximum for all groups of the user is used to determinate the actual value.
    Set this value to 0 to overwrite the setting for all users of this group with the board-wide setting.', + 'GROUP_MESSAGE_LIMIT_EXPLAIN' => 'This setting overrides the per-user folder message limit. The maximum for all groups of the user is used to determine the actual value.
    Set this value to 0 to overwrite the setting for all users of this group with the board-wide setting.', 'GROUP_MODS_ADDED' => 'New group leaders added successfully.', 'GROUP_MODS_DEMOTED' => 'Group leaders demoted successfully.', 'GROUP_MODS_PROMOTED' => 'Group members promoted successfully.', @@ -92,7 +92,7 @@ $lang = array_merge($lang, array( 'GROUP_OPEN' => 'Open', 'GROUP_PENDING' => 'Pending members', 'GROUP_MAX_RECIPIENTS' => 'Maximum number of allowed recipients per private message', - 'GROUP_MAX_RECIPIENTS_EXPLAIN' => 'The maximum number of allowed recipients in a private message. The maximum for all groups of the user is used to determinate the actual value.
    Set this value to 0 to overwrite the setting for all users of this group with the board-wide setting.', + 'GROUP_MAX_RECIPIENTS_EXPLAIN' => 'The maximum number of allowed recipients in a private message. The maximum for all groups of the user is used to determine the actual value.
    Set this value to 0 to overwrite the setting for all users of this group with the board-wide setting.', 'GROUP_OPTIONS_SAVE' => 'Group wide options', 'GROUP_PROMOTE' => 'Promote to group leader', 'GROUP_RANK' => 'Group rank', From 50478e68b093c71022337469bfa04f27382a8efb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88tan=20Muller?= Date: Sun, 11 Jan 2015 20:59:17 +0100 Subject: [PATCH 0110/1676] [ticket/13497] Update calls to `get_tables()` PHPBB3-13497 --- phpBB/includes/functions_compatibility.php | 13 +++++++++++++ phpBB/includes/functions_install.php | 17 +++-------------- phpBB/install/install_convert.php | 4 +++- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 8d9f5018fa..4707238951 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -384,3 +384,16 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false, $ } return $tmp_request->variable($var_name, $default, $multibyte, ($cookie) ? \phpbb\request\request_interface::COOKIE : \phpbb\request\request_interface::REQUEST); } + +/** + * Get tables of a database + * + * @deprecated 3.1.0 (To be removed: 3.3.0) + */ +function get_tables(&$db) +{ + $db_tools_factory = new \phpbb\db\tools\factory(); + $db_tools = $db_tools_factory->get($db); + + return $db_tools->sql_list_tables(); +} diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 4217617b53..8dacd25230 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -181,19 +181,6 @@ function dbms_select($default = '', $only_20x_options = false) return $dbms_options; } -/** -* Get tables of a database -* -* @deprecated -*/ -function get_tables(&$db) -{ - $factory = new \phpbb\db\tools\factory(); - $db_tools = $factory->get($db); - - return $db_tools->sql_list_tables(); -} - /** * Used to test whether we are able to connect to the database the user has specified * and identify any problems (eg there are already tables with the names we want to use @@ -277,7 +264,9 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, $temp_prefix = strtolower($table_prefix); $table_ary = array($temp_prefix . 'attachments', $temp_prefix . 'config', $temp_prefix . 'sessions', $temp_prefix . 'topics', $temp_prefix . 'users'); - $tables = get_tables($db); + $db_tools_factory = new \phpbb\db\tools\factory(); + $db_tools = $db_tools_factory->get($db); + $tables = $db_tools->sql_list_tables(); $tables = array_map('strtolower', $tables); $table_intersect = array_intersect($tables, $table_ary); diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index 622b162828..506bece9c9 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -491,7 +491,9 @@ class install_convert extends module { $prefixes = array(); - $tables_existing = get_tables($src_db); + $db_tools_factory = new \phpbb\db\tools\factory(); + $db_tools = $db_tools_factory->get($src_db); + $tables_existing = $db_tools->sql_list_tables(); $tables_existing = array_map('strtolower', $tables_existing); foreach ($tables_existing as $table_name) { From ec1fb0423dbc0ee64f06e419657e62e4475fe2e9 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 13 Feb 2015 22:46:18 +0100 Subject: [PATCH 0111/1676] [ticket/10748] Split postgres DB tools into it's own class PHPBB3-10748 --- phpBB/phpbb/db/tools/factory.php | 4 + phpBB/phpbb/db/tools/mssql.php | 40 +- phpBB/phpbb/db/tools/postgres.php | 613 ++++++++++++++++++++++++++++++ phpBB/phpbb/db/tools/tools.php | 257 ------------- 4 files changed, 637 insertions(+), 277 deletions(-) create mode 100644 phpBB/phpbb/db/tools/postgres.php diff --git a/phpBB/phpbb/db/tools/factory.php b/phpBB/phpbb/db/tools/factory.php index 24e2a4d875..d204451a63 100644 --- a/phpBB/phpbb/db/tools/factory.php +++ b/phpBB/phpbb/db/tools/factory.php @@ -29,6 +29,10 @@ class factory { return new \phpbb\db\tools\mssql($db_driver, $return_statements); } + else if ($db_driver instanceof \phpbb\db\driver\postgres) + { + return new \phpbb\db\tools\postgres($db_driver, $return_statements); + } else if ($db_driver instanceof \phpbb\db\driver\driver_interface) { return new \phpbb\db\tools\tools($db_driver, $return_statements); diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php index 3a7ac6185d..6e58171040 100644 --- a/phpBB/phpbb/db/tools/mssql.php +++ b/phpBB/phpbb/db/tools/mssql.php @@ -1,35 +1,35 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\tools; /** -* Database Tools for handling cross-db actions such as altering columns, etc. -* Currently not supported is returning SQL for creating tables. -*/ + * Database Tools for handling cross-db actions such as altering columns, etc. + * Currently not supported is returning SQL for creating tables. + */ class mssql extends tools { /** - * Is the used MS SQL Server a SQL Server 2000? - * @var bool - */ + * Is the used MS SQL Server a SQL Server 2000? + * @var bool + */ protected $is_sql_server_2000; /** - * Get the column types for every database we support - * - * @return array - */ + * Get the column types for mssql based databases + * + * @return array + */ public static function get_dbms_type_map() { return array( diff --git a/phpBB/phpbb/db/tools/postgres.php b/phpBB/phpbb/db/tools/postgres.php new file mode 100644 index 0000000000..8b61625c3c --- /dev/null +++ b/phpBB/phpbb/db/tools/postgres.php @@ -0,0 +1,613 @@ + + * @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\tools; + +/** + * Database Tools for handling cross-db actions such as altering columns, etc. + * Currently not supported is returning SQL for creating tables. + */ +class postgres extends tools +{ + /** + * Get the column types for postgres only + * + * @return array + */ + public static function get_dbms_type_map() + { + return array( + 'postgres' => array( + 'INT:' => 'INT4', + 'BINT' => 'INT8', + 'UINT' => 'INT4', // unsigned + 'UINT:' => 'INT4', // unsigned + 'USINT' => 'INT2', // unsigned + 'BOOL' => 'INT2', // unsigned + 'TINT:' => 'INT2', + 'VCHAR' => 'varchar(255)', + 'VCHAR:' => 'varchar(%d)', + 'CHAR:' => 'char(%d)', + 'XSTEXT' => 'varchar(1000)', + 'STEXT' => 'varchar(3000)', + 'TEXT' => 'varchar(8000)', + 'MTEXT' => 'TEXT', + 'XSTEXT_UNI'=> 'varchar(100)', + 'STEXT_UNI' => 'varchar(255)', + 'TEXT_UNI' => 'varchar(4000)', + 'MTEXT_UNI' => 'TEXT', + 'TIMESTAMP' => 'INT4', // unsigned + 'DECIMAL' => 'decimal(5,2)', + 'DECIMAL:' => 'decimal(%d,2)', + 'PDECIMAL' => 'decimal(6,3)', + 'PDECIMAL:' => 'decimal(%d,3)', + 'VCHAR_UNI' => 'varchar(255)', + 'VCHAR_UNI:'=> 'varchar(%d)', + 'VCHAR_CI' => 'varchar_ci', + 'VARBINARY' => 'bytea', + ), + ); + } + + /** + * Constructor. Set DB Object and set {@link $return_statements return_statements}. + * + * @param \phpbb\db\driver\driver_interface $db Database connection + * @param bool $return_statements True if only statements should be returned and no SQL being executed + */ + public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false) + { + parent::__construct($db, $return_statements); + + // Determine mapping database type + $this->sql_layer = 'postgres'; + + $this->dbms_type_map = self::get_dbms_type_map(); + } + + /** + * {@inheritDoc} + */ + function sql_list_tables() + { + $sql = 'SELECT relname + FROM pg_stat_user_tables'; + $result = $this->db->sql_query($sql); + + $tables = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $name = current($row); + $tables[$name] = $name; + } + $this->db->sql_freeresult($result); + + return $tables; + } + + /** + * {@inheritDoc} + */ + function sql_create_table($table_name, $table_data) + { + // holds the DDL for a column + $columns = $statements = array(); + + if ($this->sql_table_exists($table_name)) + { + return $this->_sql_run_sql($statements); + } + + // Begin transaction + $statements[] = 'begin'; + + // Determine if we have created a PRIMARY KEY in the earliest + $primary_key_gen = false; + + // Determine if the table requires a sequence + $create_sequence = false; + + // Begin table sql statement + $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n"; + + // Iterate through the columns to create a table + foreach ($table_data['COLUMNS'] as $column_name => $column_data) + { + // here lies an array, filled with information compiled on the column's data + $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data); + + if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen" + { + trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR); + } + + // here we add the definition of the new column to the list of columns + $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql']; + + // see if we have found a primary key set due to a column definition if we have found it, we can stop looking + if (!$primary_key_gen) + { + $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set']; + } + + // create sequence DDL based off of the existance of auto incrementing columns + if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment']) + { + $create_sequence = $column_name; + } + } + + // this makes up all the columns in the create table statement + $table_sql .= implode(",\n", $columns); + + // we have yet to create a primary key for this table, + // this means that we can add the one we really wanted instead + if (!$primary_key_gen) + { + // Write primary key + if (isset($table_data['PRIMARY_KEY'])) + { + if (!is_array($table_data['PRIMARY_KEY'])) + { + $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']); + } + + $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; + } + } + + // do we need to add a sequence for auto incrementing columns? + if ($create_sequence) + { + $statements[] = "CREATE SEQUENCE {$table_name}_seq;"; + } + + // close the table + $table_sql .= "\n);"; + $statements[] = $table_sql; + + // Write Keys + if (isset($table_data['KEYS'])) + { + foreach ($table_data['KEYS'] as $key_name => $key_data) + { + if (!is_array($key_data[1])) + { + $key_data[1] = array($key_data[1]); + } + + $old_return_statements = $this->return_statements; + $this->return_statements = true; + + $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]); + + foreach ($key_stmts as $key_stmt) + { + $statements[] = $key_stmt; + } + + $this->return_statements = $old_return_statements; + } + } + + // Commit Transaction + $statements[] = 'commit'; + + return $this->_sql_run_sql($statements); + } + + /** + * {@inheritDoc} + */ + function sql_list_columns($table_name) + { + $columns = array(); + + $sql = "SELECT a.attname + FROM pg_class c, pg_attribute a + WHERE c.relname = '{$table_name}' + AND a.attnum > 0 + AND a.attrelid = c.oid"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $column = strtolower(current($row)); + $columns[$column] = $column; + } + $this->db->sql_freeresult($result); + + return $columns; + } + + /** + * {@inheritDoc} + */ + function sql_index_exists($table_name, $index_name) + { + $sql = "SELECT ic.relname as index_name + FROM pg_class bc, pg_class ic, pg_index i + WHERE (bc.oid = i.indrelid) + AND (ic.oid = i.indexrelid) + AND (bc.relname = '" . $table_name . "') + AND (i.indisunique != 't') + AND (i.indisprimary != 't')"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + // This DBMS prefixes index names with the table name + $row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']); + + if (strtolower($row['index_name']) == strtolower($index_name)) + { + $this->db->sql_freeresult($result); + return true; + } + } + $this->db->sql_freeresult($result); + + return false; + } + + /** + * {@inheritDoc} + */ + function sql_unique_index_exists($table_name, $index_name) + { + $sql = "SELECT ic.relname as index_name, i.indisunique + FROM pg_class bc, pg_class ic, pg_index i + WHERE (bc.oid = i.indrelid) + AND (ic.oid = i.indexrelid) + AND (bc.relname = '" . $table_name . "') + AND (i.indisprimary != 't')"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + if ($row['indisunique'] != 't') + { + continue; + } + + // This DBMS prefixes index names with the table name + $row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']); + + if (strtolower($row['index_name']) == strtolower($index_name)) + { + $this->db->sql_freeresult($result); + return true; + } + } + $this->db->sql_freeresult($result); + + return false; + } + + /** + * Function to prepare some column information for better usage + * @access private + */ + function sql_prepare_column_data($table_name, $column_name, $column_data) + { + if (strlen($column_name) > 30) + { + trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR); + } + + // Get type + list($column_type, $orig_column_type) = $this->get_column_type($column_data[0]); + + // Adjust default value if db-dependent specified + if (is_array($column_data[1])) + { + $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default']; + } + + $sql = " {$column_type} "; + + $return_array = array( + 'column_type' => $column_type, + 'auto_increment' => false, + ); + + if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + { + $default_val = "nextval('{$table_name}_seq')"; + $return_array['auto_increment'] = true; + } + else if (!is_null($column_data[1])) + { + $default_val = "'" . $column_data[1] . "'"; + $return_array['null'] = 'NOT NULL'; + $sql .= 'NOT NULL '; + } + else + { + // Integers need to have 0 instead of empty string as default + if (strpos($column_type, 'INT') === 0) + { + $default_val = '0'; + } + else + { + $default_val = "'" . $column_data[1] . "'"; + } + $return_array['null'] = 'NULL'; + $sql .= 'NULL '; + } + + $return_array['default'] = $default_val; + + $sql .= "DEFAULT {$default_val}"; + + // Unsigned? Then add a CHECK contraint + if (in_array($orig_column_type, $this->unsigned_types)) + { + $return_array['constraint'] = "CHECK ({$column_name} >= 0)"; + $sql .= " CHECK ({$column_name} >= 0)"; + } + + $return_array['column_type_sql'] = $sql; + + return $return_array; + } + + /** + * {@inheritDoc} + */ + function sql_column_add($table_name, $column_name, $column_data, $inline = false) + { + $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); + $statements = array(); + + // Does not support AFTER, only through temporary table + if (version_compare($this->db->sql_server_info(true), '8.0', '>=')) + { + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql']; + } + else + { + // old versions cannot add columns with default and null information + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type'] . ' ' . $column_data['constraint']; + + if (isset($column_data['null'])) + { + if ($column_data['null'] == 'NOT NULL') + { + $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET NOT NULL'; + } + } + + if (isset($column_data['default'])) + { + $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default']; + } + } + + return $this->_sql_run_sql($statements); + } + + /** + * {@inheritDoc} + */ + function sql_column_remove($table_name, $column_name, $inline = false) + { + $statements = array(); + + $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"'; + + return $this->_sql_run_sql($statements); + } + + /** + * {@inheritDoc} + */ + function sql_index_drop($table_name, $index_name) + { + $statements = array(); + + $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name; + + return $this->_sql_run_sql($statements); + } + + /** + * {@inheritDoc} + */ + function sql_table_drop($table_name) + { + $statements = array(); + + if (!$this->sql_table_exists($table_name)) + { + return $this->_sql_run_sql($statements); + } + + // the most basic operation, get rid of the table + $statements[] = 'DROP TABLE ' . $table_name; + + // PGSQL does not "tightly" bind sequences and tables, we must guess... + $sql = "SELECT relname + FROM pg_class + WHERE relkind = 'S' + AND relname = '{$table_name}_seq'"; + $result = $this->db->sql_query($sql); + + // We don't even care about storing the results. We already know the answer if we get rows back. + if ($this->db->sql_fetchrow($result)) + { + $statements[] = "DROP SEQUENCE {$table_name}_seq;\n"; + } + $this->db->sql_freeresult($result); + + return $this->_sql_run_sql($statements); + } + + /** + * {@inheritDoc} + */ + function sql_create_primary_key($table_name, $column, $inline = false) + { + $statements = array(); + + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')'; + + return $this->_sql_run_sql($statements); + } + + /** + * {@inheritDoc} + */ + function sql_create_unique_index($table_name, $index_name, $column) + { + $statements = array(); + + $this->check_index_name_length($table_name, $index_name); + + $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + + return $this->_sql_run_sql($statements); + } + + /** + * {@inheritDoc} + */ + function sql_create_index($table_name, $index_name, $column) + { + $statements = array(); + + $this->check_index_name_length($table_name, $index_name); + + // remove index length + $column = preg_replace('#:.*$#', '', $column); + + $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + + return $this->_sql_run_sql($statements); + } + + + /** + * {@inheritDoc} + */ + function sql_list_index($table_name) + { + $index_array = array(); + + $sql = "SELECT ic.relname as index_name + FROM pg_class bc, pg_class ic, pg_index i + WHERE (bc.oid = i.indrelid) + AND (ic.oid = i.indexrelid) + AND (bc.relname = '" . $table_name . "') + AND (i.indisunique != 't') + AND (i.indisprimary != 't')"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']); + + $index_array[] = $row['index_name']; + } + $this->db->sql_freeresult($result); + + return array_map('strtolower', $index_array); + } + + /** + * {@inheritDoc} + */ + function sql_column_change($table_name, $column_name, $column_data, $inline = false) + { + $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); + $statements = array(); + + $sql = 'ALTER TABLE ' . $table_name . ' '; + + $sql_array = array(); + $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type']; + + if (isset($column_data['null'])) + { + if ($column_data['null'] == 'NOT NULL') + { + $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL'; + } + else if ($column_data['null'] == 'NULL') + { + $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL'; + } + } + + if (isset($column_data['default'])) + { + $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default']; + } + + // we don't want to double up on constraints if we change different number data types + if (isset($column_data['constraint'])) + { + $constraint_sql = "SELECT consrc as constraint_data + FROM pg_constraint, pg_class bc + WHERE conrelid = bc.oid + AND bc.relname = '{$table_name}' + AND NOT EXISTS ( + SELECT * + FROM pg_constraint as c, pg_inherits as i + WHERE i.inhrelid = pg_constraint.conrelid + AND c.conname = pg_constraint.conname + AND c.consrc = pg_constraint.consrc + AND c.conrelid = i.inhparent + )"; + + $constraint_exists = false; + + $result = $this->db->sql_query($constraint_sql); + while ($row = $this->db->sql_fetchrow($result)) + { + if (trim($row['constraint_data']) == trim($column_data['constraint'])) + { + $constraint_exists = true; + break; + } + } + $this->db->sql_freeresult($result); + + if (!$constraint_exists) + { + $sql_array[] = 'ADD ' . $column_data['constraint']; + } + } + + $sql .= implode(', ', $sql_array); + + $statements[] = $sql; + + return $this->_sql_run_sql($statements); + } + + /** + * Get a list with existing indexes for the column + * + * @param string $table_name + * @param string $column_name + * @param bool $unique Should we get unique indexes or normal ones + * @return array Array with Index name => columns + */ + public function get_existing_indexes($table_name, $column_name, $unique = false) + { + // Not supported + throw new \Exception('DBMS is not supported'); + } +} diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php index d2bad21a3a..0d1eb63c47 100644 --- a/phpBB/phpbb/db/tools/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -192,36 +192,6 @@ class tools implements tools_interface 'VCHAR_CI' => 'VARCHAR(255)', 'VARBINARY' => 'BLOB', ), - - 'postgres' => array( - 'INT:' => 'INT4', - 'BINT' => 'INT8', - 'UINT' => 'INT4', // unsigned - 'UINT:' => 'INT4', // unsigned - 'USINT' => 'INT2', // unsigned - 'BOOL' => 'INT2', // unsigned - 'TINT:' => 'INT2', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'varchar(1000)', - 'STEXT' => 'varchar(3000)', - 'TEXT' => 'varchar(8000)', - 'MTEXT' => 'TEXT', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT_UNI' => 'varchar(4000)', - 'MTEXT_UNI' => 'TEXT', - 'TIMESTAMP' => 'INT4', // unsigned - 'DECIMAL' => 'decimal(5,2)', - 'DECIMAL:' => 'decimal(%d,2)', - 'PDECIMAL' => 'decimal(6,3)', - 'PDECIMAL:' => 'decimal(%d,3)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VCHAR_CI' => 'varchar_ci', - 'VARBINARY' => 'bytea', - ), ); } @@ -315,11 +285,6 @@ class tools implements tools_interface AND name <> "sqlite_sequence"'; break; - case 'postgres': - $sql = 'SELECT relname - FROM pg_stat_user_tables'; - break; - case 'oracle': $sql = 'SELECT table_name FROM USER_TABLES'; @@ -428,7 +393,6 @@ class tools implements tools_interface { case 'mysql_40': case 'mysql_41': - case 'postgres': case 'sqlite': case 'sqlite3': $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; @@ -457,17 +421,6 @@ class tools implements tools_interface $statements[] = $table_sql; break; - case 'postgres': - // do we need to add a sequence for auto incrementing columns? - if ($create_sequence) - { - $statements[] = "CREATE SEQUENCE {$table_name}_seq;"; - } - - $table_sql .= "\n);"; - $statements[] = $table_sql; - break; - case 'oracle': $table_sql .= "\n)"; $statements[] = $table_sql; @@ -920,16 +873,6 @@ class tools implements tools_interface $sql = "SHOW COLUMNS FROM $table_name"; break; - // PostgreSQL has a way of doing this in a much simpler way but would - // not allow us to support all versions of PostgreSQL - case 'postgres': - $sql = "SELECT a.attname - FROM pg_class c, pg_attribute a - WHERE c.relname = '{$table_name}' - AND a.attnum > 0 - AND a.attrelid = c.oid"; - break; - case 'oracle': $sql = "SELECT column_name FROM user_tab_columns @@ -1003,17 +946,6 @@ class tools implements tools_interface { switch ($this->sql_layer) { - case 'postgres': - $sql = "SELECT ic.relname as index_name - FROM pg_class bc, pg_class ic, pg_index i - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (bc.relname = '" . $table_name . "') - AND (i.indisunique != 't') - AND (i.indisprimary != 't')"; - $col = 'index_name'; - break; - case 'mysql_40': case 'mysql_41': $sql = 'SHOW KEYS @@ -1049,7 +981,6 @@ class tools implements tools_interface switch ($this->sql_layer) { case 'oracle': - case 'postgres': case 'sqlite': case 'sqlite3': $row[$col] = substr($row[$col], strlen($table_name) + 1); @@ -1074,16 +1005,6 @@ class tools implements tools_interface { switch ($this->sql_layer) { - case 'postgres': - $sql = "SELECT ic.relname as index_name, i.indisunique - FROM pg_class bc, pg_class ic, pg_index i - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (bc.relname = '" . $table_name . "') - AND (i.indisprimary != 't')"; - $col = 'index_name'; - break; - case 'mysql_40': case 'mysql_41': $sql = 'SHOW KEYS @@ -1120,11 +1041,6 @@ class tools implements tools_interface continue; } - if ($this->sql_layer == 'postgres' && $row['indisunique'] != 't') - { - continue; - } - // These DBMS prefix index name with the table name switch ($this->sql_layer) { @@ -1140,7 +1056,6 @@ class tools implements tools_interface } break; - case 'postgres': case 'sqlite': case 'sqlite3': $row[$col] = substr($row[$col], strlen($table_name) + 1); @@ -1268,51 +1183,6 @@ class tools implements tools_interface break; - case 'postgres': - $return_array['column_type'] = $column_type; - - $sql .= " {$column_type} "; - - $return_array['auto_increment'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $default_val = "nextval('{$table_name}_seq')"; - $return_array['auto_increment'] = true; - } - else if (!is_null($column_data[1])) - { - $default_val = "'" . $column_data[1] . "'"; - $return_array['null'] = 'NOT NULL'; - $sql .= 'NOT NULL '; - } - else - { - // Integers need to have 0 instead of empty string as default - if (strpos($column_type, 'INT') === 0) - { - $default_val = '0'; - } - else - { - $default_val = "'" . $column_data[1] . "'"; - } - $return_array['null'] = 'NULL'; - $sql .= 'NULL '; - } - - $return_array['default'] = $default_val; - - $sql .= "DEFAULT {$default_val}"; - - // Unsigned? Then add a CHECK contraint - if (in_array($orig_column_type, $this->unsigned_types)) - { - $return_array['constraint'] = "CHECK ({$column_name} >= 0)"; - $sql .= " CHECK ({$column_name} >= 0)"; - } - - break; - case 'sqlite': case 'sqlite3': $return_array['primary_key_set'] = false; @@ -1426,33 +1296,6 @@ class tools implements tools_interface $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql']; break; - case 'postgres': - // Does not support AFTER, only through temporary table - if (version_compare($this->db->sql_server_info(true), '8.0', '>=')) - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql']; - } - else - { - // old versions cannot add columns with default and null information - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type'] . ' ' . $column_data['constraint']; - - if (isset($column_data['null'])) - { - if ($column_data['null'] == 'NOT NULL') - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET NOT NULL'; - } - } - - if (isset($column_data['default'])) - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default']; - } - } - - break; - case 'sqlite': if ($inline && $this->return_statements) { @@ -1535,10 +1378,6 @@ class tools implements tools_interface $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name; break; - case 'postgres': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"'; - break; - case 'sqlite': case 'sqlite3': @@ -1616,7 +1455,6 @@ class tools implements tools_interface break; case 'oracle': - case 'postgres': case 'sqlite': case 'sqlite3': $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name; @@ -1658,22 +1496,6 @@ class tools implements tools_interface } $this->db->sql_freeresult($result); break; - - case 'postgres': - // PGSQL does not "tightly" bind sequences and tables, we must guess... - $sql = "SELECT relname - FROM pg_class - WHERE relkind = 'S' - AND relname = '{$table_name}_seq'"; - $result = $this->db->sql_query($sql); - - // We don't even care about storing the results. We already know the answer if we get rows back. - if ($this->db->sql_fetchrow($result)) - { - $statements[] = "DROP SEQUENCE {$table_name}_seq;\n"; - } - $this->db->sql_freeresult($result); - break; } return $this->_sql_run_sql($statements); @@ -1688,7 +1510,6 @@ class tools implements tools_interface switch ($this->sql_layer) { - case 'postgres': case 'mysql_40': case 'mysql_41': $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')'; @@ -1764,7 +1585,6 @@ class tools implements tools_interface switch ($this->sql_layer) { - case 'postgres': case 'oracle': case 'sqlite': case 'sqlite3': @@ -1797,7 +1617,6 @@ class tools implements tools_interface switch ($this->sql_layer) { - case 'postgres': case 'oracle': case 'sqlite': case 'sqlite3': @@ -1848,17 +1667,6 @@ class tools implements tools_interface switch ($this->sql_layer) { - case 'postgres': - $sql = "SELECT ic.relname as index_name - FROM pg_class bc, pg_class ic, pg_index i - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (bc.relname = '" . $table_name . "') - AND (i.indisunique != 't') - AND (i.indisprimary != 't')"; - $col = 'index_name'; - break; - case 'mysql_40': case 'mysql_41': $sql = 'SHOW KEYS @@ -1893,7 +1701,6 @@ class tools implements tools_interface switch ($this->sql_layer) { case 'oracle': - case 'postgres': case 'sqlite': case 'sqlite3': $row[$col] = substr($row[$col], strlen($table_name) + 1); @@ -2001,69 +1808,6 @@ class tools implements tools_interface $this->return_statements = $old_return_statements; break; - case 'postgres': - $sql = 'ALTER TABLE ' . $table_name . ' '; - - $sql_array = array(); - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type']; - - if (isset($column_data['null'])) - { - if ($column_data['null'] == 'NOT NULL') - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL'; - } - else if ($column_data['null'] == 'NULL') - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL'; - } - } - - if (isset($column_data['default'])) - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default']; - } - - // we don't want to double up on constraints if we change different number data types - if (isset($column_data['constraint'])) - { - $constraint_sql = "SELECT consrc as constraint_data - FROM pg_constraint, pg_class bc - WHERE conrelid = bc.oid - AND bc.relname = '{$table_name}' - AND NOT EXISTS ( - SELECT * - FROM pg_constraint as c, pg_inherits as i - WHERE i.inhrelid = pg_constraint.conrelid - AND c.conname = pg_constraint.conname - AND c.consrc = pg_constraint.consrc - AND c.conrelid = i.inhparent - )"; - - $constraint_exists = false; - - $result = $this->db->sql_query($constraint_sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if (trim($row['constraint_data']) == trim($column_data['constraint'])) - { - $constraint_exists = true; - break; - } - } - $this->db->sql_freeresult($result); - - if (!$constraint_exists) - { - $sql_array[] = 'ADD ' . $column_data['constraint']; - } - } - - $sql .= implode(', ', $sql_array); - - $statements[] = $sql; - break; - case 'sqlite': case 'sqlite3': @@ -2145,7 +1889,6 @@ class tools implements tools_interface { case 'mysql_40': case 'mysql_41': - case 'postgres': case 'sqlite': case 'sqlite3': // Not supported From 8793d2f2c85f5652a50c2fa821ccd755dda3225f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 15 Feb 2015 14:52:12 +0100 Subject: [PATCH 0112/1676] [ticket/13619] Remove unneeded files and folders from vendor in release package PHPBB3-13619 --- build/build.xml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/build/build.xml b/build/build.xml index e934d57335..9d80bba2bf 100644 --- a/build/build.xml +++ b/build/build.xml @@ -310,65 +310,80 @@ + + + + + + + + + + + + + + + @@ -386,18 +401,35 @@ + + + + + + + + + + + + + + + + + From 1e3175cca3296eb04e3342766aa92ec74013431c Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 15 Feb 2015 00:30:30 +0100 Subject: [PATCH 0113/1676] [ticket/10748] Fix class type hinting PHPBB3-10748 --- phpBB/config/default/container/services_db.yml | 4 ++-- phpBB/includes/acp/acp_profile.php | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/phpBB/config/default/container/services_db.yml b/phpBB/config/default/container/services_db.yml index 77ceb0b02c..6afc5a60a9 100644 --- a/phpBB/config/default/container/services_db.yml +++ b/phpBB/config/default/container/services_db.yml @@ -14,10 +14,10 @@ services: class: phpbb\db\tools\factory dbal.tools: - class: phpbb\db\tools\tools + class: phpbb\db\tools\tools_interface factory: ["@dbal.tools.factory", get] arguments: - - @dbal.conn + - @dbal.conn.driver # ----- Migrator ----- migrator: diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index a376b6189e..146e116cfd 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -117,7 +117,7 @@ class acp_profile $db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id"); $db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id"); - /* @var $db_tools \phpbb\db\tools */ + /* @var $db_tools \phpbb\db\tools\tools_interface */ $db_tools = $phpbb_container->get('dbal.tools'); $db_tools->sql_column_remove(PROFILE_FIELDS_DATA_TABLE, 'pf_' . $field_ident); @@ -886,8 +886,7 @@ class acp_profile if ($action == 'create') { $field_ident = 'pf_' . $field_ident; - - /* @var $db_tools \phpbb\db\tools */ + /* @var $db_tools \phpbb\db\tools\tools_interface */ $db_tools = $phpbb_container->get('dbal.tools'); $db_tools->sql_column_add(PROFILE_FIELDS_DATA_TABLE, $field_ident, array($profile_field->get_database_column_type(), null)); } From 0595ab959ca65a99befafc1d885e56a838819c6a Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 22 Feb 2015 20:17:37 +0100 Subject: [PATCH 0114/1676] [ticket/13647] Move FAQ page to a controller PHPBB3-13647 --- phpBB/config/default/container/services.yml | 1 + .../default/container/services_help.yml | 10 ++ phpBB/config/default/routing/help.yml | 3 + phpBB/config/default/routing/routing.yml | 4 + phpBB/faq.php | 90 +--------- phpBB/phpbb/help/controller/help.php | 160 ++++++++++++++++++ 6 files changed, 182 insertions(+), 86 deletions(-) create mode 100644 phpBB/config/default/container/services_help.yml create mode 100644 phpBB/config/default/routing/help.yml create mode 100644 phpBB/phpbb/help/controller/help.php diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index c376726b3b..36f22d72d6 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -8,6 +8,7 @@ imports: - { resource: services_db.yml } - { resource: services_event.yml } - { resource: services_feed.yml } + - { resource: services_help.yml } - { resource: services_mimetype_guesser.yml } - { resource: services_notification.yml } - { resource: services_password.yml } diff --git a/phpBB/config/default/container/services_help.yml b/phpBB/config/default/container/services_help.yml new file mode 100644 index 0000000000..ae3eafe7b0 --- /dev/null +++ b/phpBB/config/default/container/services_help.yml @@ -0,0 +1,10 @@ +services: + phpbb.help.controller: + class: phpbb\help\controller\help + arguments: + - @controller.helper + - @dispatcher + - @template + - @user + - %core.root_path% + - %core.php_ext% diff --git a/phpBB/config/default/routing/help.yml b/phpBB/config/default/routing/help.yml new file mode 100644 index 0000000000..957d6dab55 --- /dev/null +++ b/phpBB/config/default/routing/help.yml @@ -0,0 +1,3 @@ +phpbb_help_controller: + path: /{mode} + defaults: { _controller: phpbb.help.controller:handle } diff --git a/phpBB/config/default/routing/routing.yml b/phpBB/config/default/routing/routing.yml index 94146e1ec2..d6881f1959 100644 --- a/phpBB/config/default/routing/routing.yml +++ b/phpBB/config/default/routing/routing.yml @@ -7,3 +7,7 @@ # The above will be accessed via app.php?controller=foo and it will # instantiate the "foo_service" service and call the "method" method. # + +phpbb_help_routing: + resource: "help.yml" + prefix: /help diff --git a/phpBB/faq.php b/phpBB/faq.php index ddecd28b00..e6a44f588f 100644 --- a/phpBB/faq.php +++ b/phpBB/faq.php @@ -24,90 +24,8 @@ $user->session_begin(); $auth->acl($user->data); $user->setup(); -$mode = $request->variable('mode', ''); +/** @var \phpbb\controller\helper $controller_helper */ +$controller_helper = $phpbb_container->get('controller.helper'); -// Load the appropriate faq file -switch ($mode) -{ - case 'bbcode': - $l_title = $user->lang['BBCODE_GUIDE']; - $user->add_lang('bbcode', false, true); - break; - - default: - $page_title = $user->lang['FAQ_EXPLAIN']; - $ext_name = $lang_file = ''; - - /** - * You can use this event display a custom help page - * - * @event core.faq_mode_validation - * @var string page_title Title of the page - * @var string mode FAQ that is going to be displayed - * @var string lang_file Language file containing the help data - * @var string ext_name Vendor and extension name where the help - * language file can be loaded from - * @since 3.1.4-RC1 - */ - $vars = array( - 'page_title', - 'mode', - 'lang_file', - 'ext_name', - ); - extract($phpbb_dispatcher->trigger_event('core.faq_mode_validation', compact($vars))); - - $l_title = $page_title; - $user->add_lang(($lang_file) ? $lang_file : 'faq', false, true, $ext_name); - break; -} - -// Pull the array data from the lang pack -$switch_column = $found_switch = false; -$help_blocks = array(); -foreach ($user->help as $help_ary) -{ - if ($help_ary[0] == '--') - { - if ($help_ary[1] == '--') - { - $switch_column = true; - $found_switch = true; - continue; - } - - $template->assign_block_vars('faq_block', array( - 'BLOCK_TITLE' => $help_ary[1], - 'SWITCH_COLUMN' => $switch_column, - )); - - if ($switch_column) - { - $switch_column = false; - } - continue; - } - - $template->assign_block_vars('faq_block.faq_row', array( - 'FAQ_QUESTION' => $help_ary[0], - 'FAQ_ANSWER' => $help_ary[1]) - ); -} - -// Lets build a page ... -$template->assign_vars(array( - 'L_FAQ_TITLE' => $l_title, - 'L_BACK_TO_TOP' => $user->lang['BACK_TO_TOP'], - - 'SWITCH_COLUMN_MANUALLY' => (!$found_switch) ? true : false, - 'S_IN_FAQ' => true, -)); - -page_header($l_title); - -$template->set_filenames(array( - 'body' => 'faq_body.html') -); -make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx")); - -page_footer(); +// TODO send "Moved permanently" header +redirect($controller_helper->route('phpbb_help_controller', array('mode' => $request->variable('mode', 'faq')))); diff --git a/phpBB/phpbb/help/controller/help.php b/phpBB/phpbb/help/controller/help.php new file mode 100644 index 0000000000..e9594a0563 --- /dev/null +++ b/phpBB/phpbb/help/controller/help.php @@ -0,0 +1,160 @@ + + * @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\help\controller; + +use phpbb\exception\http_exception; + +class help +{ + /** @var \phpbb\controller\helper */ + protected $helper; + + /** @var \phpbb\event\dispatcher_interface */ + protected $dispatcher; + + /** @var \phpbb\template\template */ + protected $template; + + /** @var \phpbb\user */ + protected $user; + + /** @var string */ + protected $root_path; + + /** @var string */ + protected $php_ext; + + /** + * Constructor + * + * @param \phpbb\controller\helper $helper + * @param \phpbb\event\dispatcher_interface $dispatcher + * @param \phpbb\template\template $template + * @param \phpbb\user $user + * @param string $root_path + * @param string $php_ext + */ + public function __construct(\phpbb\controller\helper $helper, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\template\template $template, \phpbb\user $user, $root_path, $php_ext) + { + $this->helper = $helper; + $this->dispatcher = $dispatcher; + $this->template = $template; + $this->user = $user; + $this->root_path = $root_path; + $this->php_ext = $php_ext; + } + + /** + * Controller for /help/{mode} routes + * + * @param string $mode + * @return \Symfony\Component\HttpFoundation\Response A Symfony Response object + * @throws http_exception when the $mode is not known by any extension + */ + public function handle($mode) + { + switch ($mode) + { + case 'faq': + case 'bbcode': + $page_title = ($mode === 'faq') ? $this->user->lang['FAQ_EXPLAIN'] : $this->user->lang['BBCODE_GUIDE']; + $this->user->add_lang($mode, false, true); + break; + + default: + $page_title = $this->user->lang['FAQ_EXPLAIN']; + $ext_name = $lang_file = ''; + + /** + * You can use this event display a custom help page + * + * @event core.faq_mode_validation + * @var string page_title Title of the page + * @var string mode FAQ that is going to be displayed + * @var string lang_file Language file containing the help data + * @var string ext_name Vendor and extension name where the help + * language file can be loaded from + * @since 3.1.4-RC1 + */ + $vars = array( + 'page_title', + 'mode', + 'lang_file', + 'ext_name', + ); + extract($this->dispatcher->trigger_event('core.faq_mode_validation', compact($vars))); + + if ($ext_name === '' || $lang_file === '') + { + throw new http_exception(501, 'FEATURE_NOT_AVAILABLE'); + } + + $this->user->add_lang($lang_file, false, true, $ext_name); + break; + + } + + $this->template->assign_vars(array( + 'L_FAQ_TITLE' => $page_title, + 'S_IN_FAQ' => true, + )); + + $this->assign_to_template($this->user->help); + + make_jumpbox(append_sid("{$this->root_path}viewforum.{$this->php_ext}")); + return $this->helper->render('faq_body.html', $page_title); + } + + /** + * Assigns the help data to the template blocks + * + * @param array $help_data + * @return null + */ + protected function assign_to_template(array $help_data) + { + // Pull the array data from the lang pack + $switch_column = $found_switch = false; + foreach ($help_data as $help_ary) + { + if ($help_ary[0] == '--') + { + if ($help_ary[1] == '--') + { + $switch_column = true; + $found_switch = true; + continue; + } + + $this->template->assign_block_vars('faq_block', array( + 'BLOCK_TITLE' => $help_ary[1], + 'SWITCH_COLUMN' => $switch_column, + )); + + if ($switch_column) + { + $switch_column = false; + } + continue; + } + + $this->template->assign_block_vars('faq_block.faq_row', array( + 'FAQ_QUESTION' => $help_ary[0], + 'FAQ_ANSWER' => $help_ary[1], + )); + } + + $this->template->assign_var('SWITCH_COLUMN_MANUALLY', !$found_switch); + } +} From 9bd6535a7df400e73d6f6d69d2b4b1a5d5714bcd Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 22 Feb 2015 22:44:31 +0100 Subject: [PATCH 0115/1676] [ticket/13647] Send 301 status PHPBB3-13647 --- phpBB/faq.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/faq.php b/phpBB/faq.php index e6a44f588f..5d8a97bc26 100644 --- a/phpBB/faq.php +++ b/phpBB/faq.php @@ -27,5 +27,5 @@ $user->setup(); /** @var \phpbb\controller\helper $controller_helper */ $controller_helper = $phpbb_container->get('controller.helper'); -// TODO send "Moved permanently" header +send_status_line(301, 'Moved Permanently'); redirect($controller_helper->route('phpbb_help_controller', array('mode' => $request->variable('mode', 'faq')))); From 19a236205f6e0892be4301b422f5da7479e12941 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 22 Feb 2015 22:44:50 +0100 Subject: [PATCH 0116/1676] [ticket/13647] Generate route links for faq PHPBB3-13647 --- phpBB/includes/acp/acp_contact.php | 5 ++++- phpBB/includes/acp/acp_users.php | 5 ++++- phpBB/includes/functions.php | 4 +++- phpBB/includes/ucp/ucp_pm_compose.php | 5 ++++- phpBB/includes/ucp/ucp_profile.php | 5 ++++- phpBB/posting.php | 4 +++- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/phpBB/includes/acp/acp_contact.php b/phpBB/includes/acp/acp_contact.php index 2aa6620835..945add66a4 100644 --- a/phpBB/includes/acp/acp_contact.php +++ b/phpBB/includes/acp/acp_contact.php @@ -105,6 +105,9 @@ class acp_contact $contact_admin_edit = generate_text_for_edit($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_flags); + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + $template->assign_vars(array( 'ERRORS' => $error, 'CONTACT_ENABLED' => $config['contact_admin_form_enable'], @@ -116,7 +119,7 @@ class acp_contact 'S_SMILIES_DISABLE_CHECKED' => !$contact_admin_edit['allow_smilies'], 'S_MAGIC_URL_DISABLE_CHECKED' => !$contact_admin_edit['allow_urls'], - 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '', ''), + 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '', ''), 'SMILIES_STATUS' => $user->lang['SMILIES_ARE_ON'], 'IMG_STATUS' => $user->lang['IMAGES_ARE_ON'], 'FLASH_STATUS' => $user->lang['FLASH_IS_ON'], diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 4cefdc2b4f..976589bac1 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -2019,6 +2019,9 @@ class acp_users $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield); + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + $template->assign_vars(array( 'S_SIGNATURE' => true, @@ -2029,7 +2032,7 @@ class acp_users 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', - 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '', '') : sprintf($user->lang['BBCODE_IS_OFF'], '', ''), + 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 66220d8864..4e8e6f475c 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4816,6 +4816,8 @@ function page_header($page_title = '', $display_online_list = false, $item_id = } } + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); $notification_mark_hash = generate_link_hash('mark_all_notifications_read'); // The following assigns all _common_ variables that may be used at any point in a template. @@ -4869,7 +4871,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = 'U_PROFILE' => append_sid("{$phpbb_root_path}ucp.$phpEx"), 'U_USER_PROFILE' => get_username_string('profile', $user->data['user_id'], $user->data['username'], $user->data['user_colour']), 'U_MODCP' => append_sid("{$phpbb_root_path}mcp.$phpEx", false, true, $user->session_id), - 'U_FAQ' => append_sid("{$phpbb_root_path}faq.$phpEx"), + 'U_FAQ' => $controller_helper->route('phpbb_help_controller', array('mode' => 'faq')), 'U_SEARCH_SELF' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'), 'U_SEARCH_NEW' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'), 'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'), diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 0064fb89fc..fa28bd89a4 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -1120,6 +1120,9 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_pm_attach'] || !$auth->acl_get('u_pm_attach')) ? '' : ' enctype="multipart/form-data"'; + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + // Start assigning vars for main posting page ... $template->assign_vars(array( 'L_POST_A' => $page_title, @@ -1128,7 +1131,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) 'SUBJECT' => (isset($message_subject)) ? $message_subject : '', 'MESSAGE' => $message_text, - 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '', '') : sprintf($user->lang['BBCODE_IS_OFF'], '', ''), + 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), 'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index c69dd7ef78..ff0c1ed0cb 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -536,6 +536,9 @@ class ucp_profile $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield); + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + $template->assign_vars(array( 'ERROR' => (sizeof($error)) ? implode('
    ', $error) : '', 'SIGNATURE' => $decoded_message['text'], @@ -545,7 +548,7 @@ class ucp_profile 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', - 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '', '') : sprintf($user->lang['BBCODE_IS_OFF'], '', ''), + 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], diff --git a/phpBB/posting.php b/phpBB/posting.php index ecd9e9f6c0..9768dc6ea7 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1720,6 +1720,8 @@ if (isset($captcha) && $captcha->is_solved() !== false) $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_attachments'] || !$auth->acl_get('u_attach') || !$auth->acl_get('f_attach', $forum_id)) ? '' : ' enctype="multipart/form-data"'; add_form_key('posting'); +/** @var \phpbb\controller\helper $controller_helper */ +$controller_helper = $phpbb_container->get('controller.helper'); // Build array of variables for main posting page $page_data = array( @@ -1734,7 +1736,7 @@ $page_data = array( 'USERNAME' => ((!$preview && $mode != 'quote') || $preview) ? $post_data['username'] : '', 'SUBJECT' => $post_data['post_subject'], 'MESSAGE' => $post_data['post_text'], - 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '', '') : sprintf($user->lang['BBCODE_IS_OFF'], '', ''), + 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), 'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], From 9c6fba558c3c7f650da89febd90a4a4220667d3d Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 22 Feb 2015 22:57:14 +0100 Subject: [PATCH 0117/1676] [ticket/13647] Switch FAQ handling in view online to controller PHPBB3-13647 --- phpBB/viewonline.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/phpBB/viewonline.php b/phpBB/viewonline.php index ccbdc8d57e..46f67b93fa 100644 --- a/phpBB/viewonline.php +++ b/phpBB/viewonline.php @@ -163,6 +163,9 @@ $result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary)); $prev_id = $prev_ip = $user_list = array(); $logged_visible_online = $logged_hidden_online = $counter = 0; +/** @var \phpbb\controller\helper $controller_helper */ +$controller_helper = $phpbb_container->get('controller.helper'); + while ($row = $db->sql_fetchrow($result)) { if ($row['user_id'] != ANONYMOUS && !isset($prev_id[$row['user_id']])) @@ -287,11 +290,6 @@ while ($row = $db->sql_fetchrow($result)) $location_url = append_sid("{$phpbb_root_path}search.$phpEx"); break; - case 'faq': - $location = $user->lang['VIEWING_FAQ']; - $location_url = append_sid("{$phpbb_root_path}faq.$phpEx"); - break; - case 'viewonline': $location = $user->lang['VIEWING_ONLINE']; $location_url = append_sid("{$phpbb_root_path}viewonline.$phpEx"); @@ -357,6 +355,13 @@ while ($row = $db->sql_fetchrow($result)) default: $location = $user->lang['INDEX']; $location_url = append_sid("{$phpbb_root_path}index.$phpEx"); + + if ($row['session_page'] === 'app.' . $phpEx . '/help/faq' || + $row['session_page'] === 'app.' . $phpEx . '/help/bbcode') + { + $location = $user->lang['VIEWING_FAQ']; + $location_url = $controller_helper->route('phpbb_help_controller', array('mode' => 'faq')); + } break; } From 193c5b86b4b6049a9bf5abc5251d5479493a10df Mon Sep 17 00:00:00 2001 From: MateBartus Date: Sun, 22 Feb 2015 16:22:10 +0100 Subject: [PATCH 0118/1676] [ticket/12466] Move classes from acp_database.php to their own files * Moving classes from acp_database.php to phpbb/db/extractor namespace, also into separate files * Adding DocBlocks and property visibility to classes * Removing globals from code * Passing former globals to base_extractor's constructor * Adding DB extractor as a service, also implementing the extractor interface as well as the extractor factory. PHPBB3-12466 --- .../config/default/container/services_db.yml | 61 + phpBB/includes/acp/acp_database.php | 1662 +---------------- phpBB/phpbb/db/extractor/base_extractor.php | 252 +++ .../extractor_not_initialized_exception.php | 24 + .../exception/invalid_format_exception.php | 22 + .../db/extractor/extractor_interface.php | 80 + phpBB/phpbb/db/extractor/factory.php | 79 + phpBB/phpbb/db/extractor/mssql_extractor.php | 524 ++++++ phpBB/phpbb/db/extractor/mysql_extractor.php | 403 ++++ phpBB/phpbb/db/extractor/oracle_extractor.php | 265 +++ .../phpbb/db/extractor/postgres_extractor.php | 338 ++++ .../phpbb/db/extractor/sqlite3_extractor.php | 151 ++ phpBB/phpbb/db/extractor/sqlite_extractor.php | 149 ++ 13 files changed, 2350 insertions(+), 1660 deletions(-) create mode 100644 phpBB/phpbb/db/extractor/base_extractor.php create mode 100644 phpBB/phpbb/db/extractor/exception/extractor_not_initialized_exception.php create mode 100644 phpBB/phpbb/db/extractor/exception/invalid_format_exception.php create mode 100644 phpBB/phpbb/db/extractor/extractor_interface.php create mode 100644 phpBB/phpbb/db/extractor/factory.php create mode 100644 phpBB/phpbb/db/extractor/mssql_extractor.php create mode 100644 phpBB/phpbb/db/extractor/mysql_extractor.php create mode 100644 phpBB/phpbb/db/extractor/oracle_extractor.php create mode 100644 phpBB/phpbb/db/extractor/postgres_extractor.php create mode 100644 phpBB/phpbb/db/extractor/sqlite3_extractor.php create mode 100644 phpBB/phpbb/db/extractor/sqlite_extractor.php diff --git a/phpBB/config/default/container/services_db.yml b/phpBB/config/default/container/services_db.yml index 6afc5a60a9..ae2707b9a5 100644 --- a/phpBB/config/default/container/services_db.yml +++ b/phpBB/config/default/container/services_db.yml @@ -19,6 +19,67 @@ services: arguments: - @dbal.conn.driver +# ----- DB Extractor ----- + dbal.extractor.factory: + class: phpbb\db\extractor\factory + arguments: + - @dbal.conn.driver + - @service_container + + dbal.extractor: + class: phpbb\db\extractor\extractor_interface + factory: ["@dbal.extractor.factory", get] + +# ----- DB Extractors for different drivers ----- +# Scope MUST be prototype for all the handlers to work correctly. + dbal.extractor.extractors.mssql_extractor: + class: phpbb\db\extractor\mssql_extractor + scope: prototype + arguments: + - %core.root_path% + - @request + - @dbal.conn.driver + + dbal.extractor.extractors.mysql_extractor: + class: phpbb\db\extractor\mysql_extractor + scope: prototype + arguments: + - %core.root_path% + - @request + - @dbal.conn.driver + + dbal.extractor.extractors.oracle_extractor: + class: phpbb\db\extractor\oracle_extractor + scope: prototype + arguments: + - %core.root_path% + - @request + - @dbal.conn.driver + + dbal.extractor.extractors.postgres_extractor: + class: phpbb\db\extractor\postgres_extractor + scope: prototype + arguments: + - %core.root_path% + - @request + - @dbal.conn.driver + + dbal.extractor.extractors.sqlite3_extractor: + class: phpbb\db\extractor\sqlite3_extractor + scope: prototype + arguments: + - %core.root_path% + - @request + - @dbal.conn.driver + + dbal.extractor.extractors.sqlite_extractor: + class: phpbb\db\extractor\sqlite_extractor + scope: prototype + arguments: + - %core.root_path% + - @request + - @dbal.conn.driver + # ----- Migrator ----- migrator: class: phpbb\db\migrator diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 25cddaa5d4..984301a38f 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -90,36 +90,9 @@ class acp_database $time = time(); $filename = 'backup_' . $time . '_' . unique_id(); - switch ($db->get_sql_layer()) - { - case 'mysqli': - case 'mysql4': - case 'mysql': - $extractor = new mysql_extractor($format, $filename, $time, $download, $store); - break; - case 'sqlite': - $extractor = new sqlite_extractor($format, $filename, $time, $download, $store); - break; - - case 'sqlite3': - $extractor = new sqlite3_extractor($format, $filename, $time, $download, $store); - break; - - case 'postgres': - $extractor = new postgres_extractor($format, $filename, $time, $download, $store); - break; - - case 'oracle': - $extractor = new oracle_extractor($format, $filename, $time, $download, $store); - break; - - case 'mssql': - case 'mssql_odbc': - case 'mssqlnative': - $extractor = new mssql_extractor($format, $filename, $time, $download, $store); - break; - } + $extractor = $phpbb_container->get('dbal.extractor'); + $extractor->init_extractor($format, $filename, $time, $download, $store); $extractor->write_start($table_prefix); @@ -461,1637 +434,6 @@ class acp_database } } -class base_extractor -{ - var $fh; - var $fp; - var $write; - var $close; - var $store; - var $download; - var $time; - var $format; - var $run_comp = false; - - function base_extractor($format, $filename, $time, $download = false, $store = false) - { - global $request; - - $this->download = $download; - $this->store = $store; - $this->time = $time; - $this->format = $format; - - switch ($format) - { - case 'text': - $ext = '.sql'; - $open = 'fopen'; - $this->write = 'fwrite'; - $this->close = 'fclose'; - $mimetype = 'text/x-sql'; - break; - case 'bzip2': - $ext = '.sql.bz2'; - $open = 'bzopen'; - $this->write = 'bzwrite'; - $this->close = 'bzclose'; - $mimetype = 'application/x-bzip2'; - break; - case 'gzip': - $ext = '.sql.gz'; - $open = 'gzopen'; - $this->write = 'gzwrite'; - $this->close = 'gzclose'; - $mimetype = 'application/x-gzip'; - break; - } - - if ($download == true) - { - $name = $filename . $ext; - header('Cache-Control: private, no-cache'); - header("Content-Type: $mimetype; name=\"$name\""); - header("Content-disposition: attachment; filename=$name"); - - switch ($format) - { - case 'bzip2': - ob_start(); - break; - - case 'gzip': - if (strpos($request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($request->header('User-Agent')), 'msie') === false) - { - ob_start('ob_gzhandler'); - } - else - { - $this->run_comp = true; - } - break; - } - } - - if ($store == true) - { - global $phpbb_root_path; - $file = $phpbb_root_path . 'store/' . $filename . $ext; - - $this->fp = $open($file, 'w'); - - if (!$this->fp) - { - trigger_error('FILE_WRITE_FAIL', E_USER_ERROR); - } - } - } - - function write_end() - { - static $close; - - if ($this->store) - { - if ($close === null) - { - $close = $this->close; - } - $close($this->fp); - } - - // bzip2 must be written all the way at the end - if ($this->download && $this->format === 'bzip2') - { - $c = ob_get_clean(); - echo bzcompress($c); - } - } - - function flush($data) - { - static $write; - if ($this->store === true) - { - if ($write === null) - { - $write = $this->write; - } - $write($this->fp, $data); - } - - if ($this->download === true) - { - if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp)) - { - echo $data; - } - - // we can write the gzip data as soon as we get it - if ($this->format === 'gzip') - { - if ($this->run_comp) - { - echo gzencode($data); - } - else - { - ob_flush(); - flush(); - } - } - } - } -} - -class mysql_extractor extends base_extractor -{ - function write_start($table_prefix) - { - $sql_data = "#\n"; - $sql_data .= "# phpBB Backup Script\n"; - $sql_data .= "# Dump of tables for $table_prefix\n"; - $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "#\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - static $new_extract; - - if ($new_extract === null) - { - if ($db->get_sql_layer() === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>=')) - { - $new_extract = true; - } - else - { - $new_extract = false; - } - } - - if ($new_extract) - { - $this->new_write_table($table_name); - } - else - { - $this->old_write_table($table_name); - } - } - - function write_data($table_name) - { - global $db; - if ($db->get_sql_layer() === 'mysqli') - { - $this->write_data_mysqli($table_name); - } - else - { - $this->write_data_mysql($table_name); - } - } - - function write_data_mysqli($table_name) - { - global $db; - $sql = "SELECT * - FROM $table_name"; - $result = mysqli_query($db->get_db_connect_id(), $sql, MYSQLI_USE_RESULT); - if ($result != false) - { - $fields_cnt = mysqli_num_fields($result); - - // Get field information - $field = mysqli_fetch_fields($result); - $field_set = array(); - - for ($j = 0; $j < $fields_cnt; $j++) - { - $field_set[] = $field[$j]->name; - } - - $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); - $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); - $fields = implode(', ', $field_set); - $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; - $first_set = true; - $query_len = 0; - $max_len = get_usable_memory(); - - while ($row = mysqli_fetch_row($result)) - { - $values = array(); - if ($first_set) - { - $query = $sql_data . '('; - } - else - { - $query .= ',('; - } - - for ($j = 0; $j < $fields_cnt; $j++) - { - if (!isset($row[$j]) || is_null($row[$j])) - { - $values[$j] = 'NULL'; - } - else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024)) - { - $values[$j] = $row[$j]; - } - else - { - $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; - } - } - $query .= implode(', ', $values) . ')'; - - $query_len += strlen($query); - if ($query_len > $max_len) - { - $this->flush($query . ";\n\n"); - $query = ''; - $query_len = 0; - $first_set = true; - } - else - { - $first_set = false; - } - } - mysqli_free_result($result); - - // check to make sure we have nothing left to flush - if (!$first_set && $query) - { - $this->flush($query . ";\n\n"); - } - } - } - - function write_data_mysql($table_name) - { - global $db; - $sql = "SELECT * - FROM $table_name"; - $result = mysql_unbuffered_query($sql, $db->get_db_connect_id()); - - if ($result != false) - { - $fields_cnt = mysql_num_fields($result); - - // Get field information - $field = array(); - for ($i = 0; $i < $fields_cnt; $i++) - { - $field[] = mysql_fetch_field($result, $i); - } - $field_set = array(); - - for ($j = 0; $j < $fields_cnt; $j++) - { - $field_set[] = $field[$j]->name; - } - - $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); - $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); - $fields = implode(', ', $field_set); - $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; - $first_set = true; - $query_len = 0; - $max_len = get_usable_memory(); - - while ($row = mysql_fetch_row($result)) - { - $values = array(); - if ($first_set) - { - $query = $sql_data . '('; - } - else - { - $query .= ',('; - } - - for ($j = 0; $j < $fields_cnt; $j++) - { - if (!isset($row[$j]) || is_null($row[$j])) - { - $values[$j] = 'NULL'; - } - else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp')) - { - $values[$j] = $row[$j]; - } - else - { - $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; - } - } - $query .= implode(', ', $values) . ')'; - - $query_len += strlen($query); - if ($query_len > $max_len) - { - $this->flush($query . ";\n\n"); - $query = ''; - $query_len = 0; - $first_set = true; - } - else - { - $first_set = false; - } - } - mysql_free_result($result); - - // check to make sure we have nothing left to flush - if (!$first_set && $query) - { - $this->flush($query . ";\n\n"); - } - } - } - - function new_write_table($table_name) - { - global $db; - - $sql = 'SHOW CREATE TABLE ' . $table_name; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - - $sql_data = '# Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; - $this->flush($sql_data . $row['Create Table'] . ";\n\n"); - - $db->sql_freeresult($result); - } - - function old_write_table($table_name) - { - global $db; - - $sql_data = '# Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; - $sql_data .= "CREATE TABLE $table_name(\n"; - $rows = array(); - - $sql = "SHOW FIELDS - FROM $table_name"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $line = ' ' . $row['Field'] . ' ' . $row['Type']; - - if (!is_null($row['Default'])) - { - $line .= " DEFAULT '{$row['Default']}'"; - } - - if ($row['Null'] != 'YES') - { - $line .= ' NOT NULL'; - } - - if ($row['Extra'] != '') - { - $line .= ' ' . $row['Extra']; - } - - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql = "SHOW KEYS - FROM $table_name"; - - $result = $db->sql_query($sql); - - $index = array(); - while ($row = $db->sql_fetchrow($result)) - { - $kname = $row['Key_name']; - - if ($kname != 'PRIMARY') - { - if ($row['Non_unique'] == 0) - { - $kname = "UNIQUE|$kname"; - } - } - - if ($row['Sub_part']) - { - $row['Column_name'] .= '(' . $row['Sub_part'] . ')'; - } - $index[$kname][] = $row['Column_name']; - } - $db->sql_freeresult($result); - - foreach ($index as $key => $columns) - { - $line = ' '; - - if ($key == 'PRIMARY') - { - $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')'; - } - else if (strpos($key, 'UNIQUE') === 0) - { - $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')'; - } - else if (strpos($key, 'FULLTEXT') === 0) - { - $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')'; - } - else - { - $line .= "KEY $key (" . implode(', ', $columns) . ')'; - } - - $rows[] = $line; - } - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n);\n\n"; - - $this->flush($sql_data); - } -} - -class sqlite_extractor extends base_extractor -{ - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION;\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '" . $db->sql_escape($table_name) . "' - ORDER BY type DESC, name;"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // Create Table - $sql_data .= $row['sql'] . ";\n"; - - $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');"); - - $ar = array(); - while ($row = $db->sql_fetchrow($result)) - { - $ar[] = $row; - } - $db->sql_freeresult($result); - - foreach ($ar as $value) - { - if (strpos($value['name'], 'autoindex') !== false) - { - continue; - } - - $result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');"); - - $fields = array(); - while ($row = $db->sql_fetchrow($result)) - { - $fields[] = $row['name']; - } - $db->sql_freeresult($result); - - $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; - } - - $this->flush($sql_data . "\n"); - } - - function write_data($table_name) - { - global $db; - - $col_types = sqlite_fetch_column_types($db->get_db_connect_id(), $table_name); - - $sql = "SELECT * - FROM $table_name"; - $result = sqlite_unbuffered_query($db->get_db_connect_id(), $sql); - $rows = sqlite_fetch_all($result, SQLITE_ASSOC); - $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; - foreach ($rows as $row) - { - foreach ($row as $column_name => $column_data) - { - if (is_null($column_data)) - { - $row[$column_name] = 'NULL'; - } - else if ($column_data == '') - { - $row[$column_name] = "''"; - } - else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false) - { - $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); - } - } - $this->flush($sql_insert . implode(', ', $row) . ");\n"); - } - } - - function write_end() - { - $this->flush("COMMIT;\n"); - parent::write_end(); - } -} - -class sqlite3_extractor extends base_extractor -{ - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION;\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '" . $db->sql_escape($table_name) . "' - ORDER BY name ASC;"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // Create Table - $sql_data .= $row['sql'] . ";\n"; - - $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');"); - - while ($row = $db->sql_fetchrow($result)) - { - if (strpos($row['name'], 'autoindex') !== false) - { - continue; - } - - $result2 = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($row['name']) . "');"); - - $fields = array(); - while ($row2 = $db->sql_fetchrow($result2)) - { - $fields[] = $row2['name']; - } - $db->sql_freeresult($result2); - - $sql_data .= 'CREATE ' . ($row['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $row['name'] . ' ON ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; - } - $db->sql_freeresult($result); - - $this->flush($sql_data . "\n"); - } - - function write_data($table_name) - { - global $db; - - $result = $db->sql_query("PRAGMA table_info('" . $db->sql_escape($table_name) . "');"); - - $col_types = array(); - while ($row = $db->sql_fetchrow($result)) - { - $col_types[$row['name']] = $row['type']; - } - $db->sql_freeresult($result); - - $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; - - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - foreach ($row as $column_name => $column_data) - { - if (is_null($column_data)) - { - $row[$column_name] = 'NULL'; - } - else if ($column_data === '') - { - $row[$column_name] = "''"; - } - else if (stripos($col_types[$column_name], 'text') !== false || stripos($col_types[$column_name], 'char') !== false || stripos($col_types[$column_name], 'blob') !== false) - { - $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); - } - } - $this->flush($sql_insert . implode(', ', $row) . ");\n"); - } - } - - function write_end() - { - $this->flush("COMMIT;\n"); - parent::write_end(); - } -} - -class postgres_extractor extends base_extractor -{ - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION;\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - static $domains_created = array(); - - $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default - FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b - WHERE a.domain_name = b.domain_name - AND b.table_name = '{$table_name}'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if (empty($domains_created[$row['domain_name']])) - { - $domains_created[$row['domain_name']] = true; - //$sql_data = "DROP DOMAIN {$row['domain_name']};\n"; - $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}"; - if (!empty($row['character_maximum_length'])) - { - $sql_data .= '(' . $row['character_maximum_length'] . ')'; - } - $sql_data .= ' NOT NULL'; - if (!empty($row['domain_default'])) - { - $sql_data .= ' DEFAULT ' . $row['domain_default']; - } - $this->flush($sql_data . ";\n"); - } - } - - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - // PGSQL does not "tightly" bind sequences and tables, we must guess... - $sql = "SELECT relname - FROM pg_class - WHERE relkind = 'S' - AND relname = '{$table_name}_seq'"; - $result = $db->sql_query($sql); - // We don't even care about storing the results. We already know the answer if we get rows back. - if ($db->sql_fetchrow($result)) - { - $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n"; - $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n"; - } - $db->sql_freeresult($result); - - $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull - FROM pg_class c, pg_attribute a, pg_type t - WHERE c.relname = '" . $db->sql_escape($table_name) . "' - AND a.attnum > 0 - AND a.attrelid = c.oid - AND a.atttypid = t.oid - ORDER BY a.attnum"; - $result = $db->sql_query($field_query); - - $sql_data .= "CREATE TABLE $table_name(\n"; - $lines = array(); - while ($row = $db->sql_fetchrow($result)) - { - // Get the data from the table - $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault - FROM pg_attrdef d, pg_class c - WHERE (c.relname = '" . $db->sql_escape($table_name) . "') - AND (c.oid = d.adrelid) - AND d.adnum = " . $row['attnum']; - $def_res = $db->sql_query($sql_get_default); - $def_row = $db->sql_fetchrow($def_res); - $db->sql_freeresult($def_res); - - if (empty($def_row)) - { - unset($row['rowdefault']); - } - else - { - $row['rowdefault'] = $def_row['rowdefault']; - } - - if ($row['type'] == 'bpchar') - { - // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement. - $row['type'] = 'char'; - } - - $line = ' ' . $row['field'] . ' ' . $row['type']; - - if (strpos($row['type'], 'char') !== false) - { - if ($row['lengthvar'] > 0) - { - $line .= '(' . ($row['lengthvar'] - 4) . ')'; - } - } - - if (strpos($row['type'], 'numeric') !== false) - { - $line .= '('; - $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff)); - $line .= ')'; - } - - if (isset($row['rowdefault'])) - { - $line .= ' DEFAULT ' . $row['rowdefault']; - } - - if ($row['notnull'] == 't') - { - $line .= ' NOT NULL'; - } - - $lines[] = $line; - } - $db->sql_freeresult($result); - - // Get the listing of primary keys. - $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key - FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (ia.attrelid = i.indexrelid) - AND (ta.attrelid = bc.oid) - AND (bc.relname = '" . $db->sql_escape($table_name) . "') - AND (ta.attrelid = i.indrelid) - AND (ta.attnum = i.indkey[ia.attnum-1]) - ORDER BY index_name, tab_name, column_name"; - - $result = $db->sql_query($sql_pri_keys); - - $index_create = $index_rows = $primary_key = array(); - - // We do this in two steps. It makes placing the comma easier - while ($row = $db->sql_fetchrow($result)) - { - if ($row['primary_key'] == 't') - { - $primary_key[] = $row['column_name']; - $primary_key_name = $row['index_name']; - } - else - { - // We have to store this all this info because it is possible to have a multi-column key... - // we can loop through it again and build the statement - $index_rows[$row['index_name']]['table'] = $table_name; - $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false; - $index_rows[$row['index_name']]['column_names'][] = $row['column_name']; - } - } - $db->sql_freeresult($result); - - if (!empty($index_rows)) - { - foreach ($index_rows as $idx_name => $props) - { - $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");"; - } - } - - if (!empty($primary_key)) - { - $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")"; - } - - // Generate constraint clauses for CHECK constraints - $sql_checks = "SELECT conname as index_name, consrc - FROM pg_constraint, pg_class bc - WHERE conrelid = bc.oid - AND bc.relname = '" . $db->sql_escape($table_name) . "' - AND NOT EXISTS ( - SELECT * - FROM pg_constraint as c, pg_inherits as i - WHERE i.inhrelid = pg_constraint.conrelid - AND c.conname = pg_constraint.conname - AND c.consrc = pg_constraint.consrc - AND c.conrelid = i.inhparent - )"; - $result = $db->sql_query($sql_checks); - - // Add the constraints to the sql file. - while ($row = $db->sql_fetchrow($result)) - { - if (!is_null($row['consrc'])) - { - $lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc']; - } - } - $db->sql_freeresult($result); - - $sql_data .= implode(", \n", $lines); - $sql_data .= "\n);\n"; - - if (!empty($index_create)) - { - $sql_data .= implode("\n", $index_create) . "\n\n"; - } - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $i_num_fields = pg_num_fields($result); - $seq = ''; - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[] = pg_field_type($result, $i); - $ary_name[] = pg_field_name($result, $i); - - $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault - FROM pg_attrdef d, pg_class c - WHERE (c.relname = '{$table_name}') - AND (c.oid = d.adrelid) - AND d.adnum = " . strval($i + 1); - $result2 = $db->sql_query($sql); - if ($row = $db->sql_fetchrow($result2)) - { - // Determine if we must reset the sequences - if (strpos($row['rowdefault'], "nextval('") === 0) - { - $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n"; - } - } - } - - $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n"); - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - if (preg_match('#char|text|bool|bytea#i', $ary_type[$i])) - { - $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val)); - $str_empty = ''; - } - else - { - $str_empty = '\N'; - } - - if (empty($str_val) && $str_val !== '0') - { - $str_val = $str_empty; - } - - $schema_vals[] = $str_val; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $this->flush(implode("\t", $schema_vals) . "\n"); - } - $db->sql_freeresult($result); - $this->flush("\\.\n"); - - // Write out the sequence statements - $this->flush($seq); - } - - function write_end() - { - $this->flush("COMMIT;\n"); - parent::write_end(); - } -} - -class mssql_extractor extends base_extractor -{ - function write_end() - { - $this->flush("COMMIT\nGO\n"); - parent::write_end(); - } - - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION\n"; - $sql_data .= "GO\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - $sql_data .= "GO\n"; - $sql_data .= "\nCREATE TABLE [$table_name] (\n"; - $rows = array(); - - $text_flag = false; - - $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_NAME = '$table_name'"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]"; - - if ($row['DATA_TYPE'] == 'text') - { - $text_flag = true; - } - - if ($row['IS_IDENTITY']) - { - $line .= ' IDENTITY (1 , 1)'; - } - - if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text') - { - $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')'; - } - - if ($row['IS_NULLABLE'] == 'YES') - { - $line .= ' NULL'; - } - else - { - $line .= ' NOT NULL'; - } - - if ($row['COLUMN_DEFAULT']) - { - $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT']; - } - - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n) ON [PRIMARY]"; - - if ($text_flag) - { - $sql_data .= " TEXTIMAGE_ON [PRIMARY]"; - } - - $sql_data .= "\nGO\n\n"; - $rows = array(); - - $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME - FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE - WHERE TABLE_NAME = '$table_name'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if (!sizeof($rows)) - { - $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n"; - $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY CLUSTERED \n\t(\n"; - } - $rows[] = "\t\t[{$row['COLUMN_NAME']}]"; - } - if (sizeof($rows)) - { - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n\t) ON [PRIMARY] \nGO\n"; - } - $db->sql_freeresult($result); - - $index = array(); - $sql = "EXEC sp_statistics '$table_name'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if ($row['TYPE'] == 3) - { - $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']'; - } - } - $db->sql_freeresult($result); - - foreach ($index as $index_name => $column_name) - { - $index[$index_name] = implode(', ', $column_name); - } - - foreach ($index as $index_name => $columns) - { - $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n"; - } - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - - if ($db->get_sql_layer() === 'mssql') - { - $this->write_data_mssql($table_name); - } - else if($db->get_sql_layer() === 'mssqlnative') - { - $this->write_data_mssqlnative($table_name); - } - else - { - $this->write_data_odbc($table_name); - } - } - - function write_data_mssql($table_name) - { - global $db; - $ary_type = $ary_name = array(); - $ident_set = false; - $sql_data = ''; - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $retrieved_data = mssql_num_rows($result); - - $i_num_fields = mssql_num_fields($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[$i] = mssql_field_type($result, $i); - $ary_name[$i] = mssql_field_name($result, $i); - } - - if ($retrieved_data) - { - $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - if (!empty($row2['has_identity'])) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; - $ident_set = true; - } - $db->sql_freeresult($result2); - } - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = $ary_name[$i]; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; - - $this->flush($sql_data); - $sql_data = ''; - } - $db->sql_freeresult($result); - - if ($retrieved_data && $ident_set) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; - } - $this->flush($sql_data); - } - - function write_data_mssqlnative($table_name) - { - global $db; - $ary_type = $ary_name = array(); - $ident_set = false; - $sql_data = ''; - - // Grab all of the data from current table. - $sql = "SELECT * FROM $table_name"; - $db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC)); - $result = $db->sql_query($sql); - - $retrieved_data = $db->mssqlnative_num_rows($result); - - if (!$retrieved_data) - { - $db->sql_freeresult($result); - return; - } - - $sql = "SELECT COLUMN_NAME, DATA_TYPE - FROM INFORMATION_SCHEMA.COLUMNS - WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $db->sql_escape($table_name) . "'"; - $result_fields = $db->sql_query($sql); - - $i_num_fields = 0; - while ($row = $db->sql_fetchrow($result_fields)) - { - $ary_type[$i_num_fields] = $row['DATA_TYPE']; - $ary_name[$i_num_fields] = $row['COLUMN_NAME']; - $i_num_fields++; - } - $db->sql_freeresult($result_fields); - - $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - - if (!empty($row2['has_identity'])) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; - $ident_set = true; - } - $db->sql_freeresult($result2); - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - // defaults to type number - better quote just to be safe, so check for is_int too - if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = $ary_name[$i]; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; - - $this->flush($sql_data); - $sql_data = ''; - } - $db->sql_freeresult($result); - - if ($ident_set) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; - } - $this->flush($sql_data); - } - - function write_data_odbc($table_name) - { - global $db; - $ary_type = $ary_name = array(); - $ident_set = false; - $sql_data = ''; - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $retrieved_data = odbc_num_rows($result); - - if ($retrieved_data) - { - $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - if (!empty($row2['has_identity'])) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; - $ident_set = true; - } - $db->sql_freeresult($result2); - } - - $i_num_fields = odbc_num_fields($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[$i] = odbc_field_type($result, $i + 1); - $ary_name[$i] = odbc_field_name($result, $i + 1); - } - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = $ary_name[$i]; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; - - $this->flush($sql_data); - - $sql_data = ''; - - } - $db->sql_freeresult($result); - - if ($retrieved_data && $ident_set) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; - } - $this->flush($sql_data); - } - -} - -class oracle_extractor extends base_extractor -{ - function write_table($table_name) - { - global $db, $request; - - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name\n/\n"; - $sql_data .= "\nCREATE TABLE $table_name (\n"; - - $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT - FROM ALL_TAB_COLS - WHERE table_name = '{$table_name}'"; - $result = $db->sql_query($sql); - - $rows = array(); - while ($row = $db->sql_fetchrow($result)) - { - $line = ' "' . $row['column_name'] . '" ' . $row['data_type']; - - if ($row['data_type'] !== 'CLOB') - { - if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR') - { - $line .= '(' . $row['data_precision'] . ')'; - } - else - { - $line .= '(' . $row['data_length'] . ')'; - } - } - - if (!empty($row['data_default'])) - { - $line .= ' DEFAULT ' . $row['data_default']; - } - - if ($row['nullable'] == 'N') - { - $line .= ' NOT NULL'; - } - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME - FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B - WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME - AND B.CONSTRAINT_TYPE = 'P' - AND A.TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - - $primary_key = array(); - $contraint_name = ''; - while ($row = $db->sql_fetchrow($result)) - { - $constraint_name = '"' . $row['constraint_name'] . '"'; - $primary_key[] = '"' . $row['column_name'] . '"'; - } - $db->sql_freeresult($result); - - if (sizeof($primary_key)) - { - $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')'; - } - - $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME - FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B - WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME - AND B.CONSTRAINT_TYPE = 'U' - AND A.TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - - $unique = array(); - $contraint_name = ''; - while ($row = $db->sql_fetchrow($result)) - { - $constraint_name = '"' . $row['constraint_name'] . '"'; - $unique[] = '"' . $row['column_name'] . '"'; - } - $db->sql_freeresult($result); - - if (sizeof($unique)) - { - $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')'; - } - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n)\n/\n"; - - $sql = "SELECT A.REFERENCED_NAME, C.* - FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C - WHERE A.REFERENCED_TYPE = 'SEQUENCE' - AND A.NAME = B.TRIGGER_NAME - AND B.TABLE_NAME = '{$table_name}' - AND C.SEQUENCE_NAME = A.REFERENCED_NAME"; - $result = $db->sql_query($sql); - - $type = $request->variable('type', ''); - - while ($row = $db->sql_fetchrow($result)) - { - $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n"; - $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\""; - - if ($type == 'full') - { - $sql_data .= ' START WITH ' . $row['last_number']; - } - - $sql_data .= "\n/\n"; - } - $db->sql_freeresult($result); - - $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY - FROM USER_TRIGGERS - WHERE TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n"; - } - $db->sql_freeresult($result); - - $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME - FROM USER_INDEXES A, USER_IND_COLUMNS B - WHERE A.UNIQUENESS = 'NONUNIQUE' - AND A.INDEX_NAME = B.INDEX_NAME - AND B.TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - - $index = array(); - - while ($row = $db->sql_fetchrow($result)) - { - $index[$row['index_name']][] = $row['column_name']; - } - - foreach ($index as $index_name => $column_names) - { - $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n"; - } - $db->sql_freeresult($result); - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - $ary_type = $ary_name = array(); - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $i_num_fields = ocinumcols($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[$i] = ocicolumntype($result, $i + 1); - $ary_name[$i] = ocicolumnname($result, $i + 1); - } - - $sql_data = ''; - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - // Oracle uses uppercase - we use lowercase - $str_val = $row[strtolower($ary_name[$i])]; - - if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_oracle($str_val); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0') - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = '"' . $ary_name[$i] . '"'; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n"; - - $this->flush($sql_data); - } - $db->sql_freeresult($result); - } - - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $this->flush($sql_data); - } -} - // 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) function get_usable_memory() { diff --git a/phpBB/phpbb/db/extractor/base_extractor.php b/phpBB/phpbb/db/extractor/base_extractor.php new file mode 100644 index 0000000000..547c85f066 --- /dev/null +++ b/phpBB/phpbb/db/extractor/base_extractor.php @@ -0,0 +1,252 @@ + +* @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\extractor; + +use phpbb\db\extractor\exception\invalid_format_exception; +use phpbb\db\extractor\exception\extractor_not_initialized_exception; + +/** + * Abstract base class for database extraction + */ +abstract class base_extractor implements extractor_interface +{ + /** + * @var string phpBB root path + */ + protected $phpbb_root_path; + + /** + * @var \phpbb\request\request_interface + */ + protected $request; + + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var bool + */ + protected $download; + + /** + * @var bool + */ + protected $store; + + /** + * @var int + */ + protected $time; + + /** + * @var string + */ + protected $format; + + /** + * @var resource + */ + protected $fp; + + /** + * @var string + */ + protected $write; + + /** + * @var string + */ + protected $close; + + /** + * @var bool + */ + protected $run_comp; + + /** + * @var bool + */ + protected $is_initialized; + + /** + * Constructor + * + * @param string $phpbb_root_path + * @param \phpbb\request\request_interface $request + * @param \phpbb\db\driver\driver_interface $db + */ + public function __construct($phpbb_root_path, \phpbb\request\request_interface $request, \phpbb\db\driver\driver_interface $db) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->request = $request; + $this->db = $db; + $this->fp = null; + + $this->is_initialized = false; + } + + /** + * {@inheritdoc} + */ + public function init_extractor($format, $filename, $time, $download = false, $store = false) + { + $this->download = $download; + $this->store = $store; + $this->time = $time; + $this->format = $format; + + switch ($format) + { + case 'text': + $ext = '.sql'; + $open = 'fopen'; + $this->write = 'fwrite'; + $this->close = 'fclose'; + $mimetype = 'text/x-sql'; + break; + case 'bzip2': + $ext = '.sql.bz2'; + $open = 'bzopen'; + $this->write = 'bzwrite'; + $this->close = 'bzclose'; + $mimetype = 'application/x-bzip2'; + break; + case 'gzip': + $ext = '.sql.gz'; + $open = 'gzopen'; + $this->write = 'gzwrite'; + $this->close = 'gzclose'; + $mimetype = 'application/x-gzip'; + break; + default: + throw new invalid_format_exception(); + break; + } + + if ($download === true) + { + $name = $filename . $ext; + header('Cache-Control: private, no-cache'); + header("Content-Type: $mimetype; name=\"$name\""); + header("Content-disposition: attachment; filename=$name"); + + switch ($format) + { + case 'bzip2': + ob_start(); + break; + + case 'gzip': + if (strpos($this->request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($this->request->header('User-Agent')), 'msie') === false) + { + ob_start('ob_gzhandler'); + } + else + { + $this->run_comp = true; + } + break; + } + } + + if ($store === true) + { + $file = $this->phpbb_root_path . 'store/' . $filename . $ext; + + $this->fp = $open($file, 'w'); + + if (!$this->fp) + { + trigger_error('FILE_WRITE_FAIL', E_USER_ERROR); + } + } + + $this->is_initialized = true; + } + + /** + * {@inheritdoc} + */ + public function write_end() + { + static $close; + + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + if ($this->store) + { + if ($close === null) + { + $close = $this->close; + } + $close($this->fp); + } + + // bzip2 must be written all the way at the end + if ($this->download && $this->format === 'bzip2') + { + $c = ob_get_clean(); + echo bzcompress($c); + } + } + + /** + * {@inheritdoc} + */ + public function flush($data) + { + static $write; + + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + if ($this->store === true) + { + if ($write === null) + { + $write = $this->write; + } + $write($this->fp, $data); + } + + if ($this->download === true) + { + if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp)) + { + echo $data; + } + + // we can write the gzip data as soon as we get it + if ($this->format === 'gzip') + { + if ($this->run_comp) + { + echo gzencode($data); + } + else + { + ob_flush(); + flush(); + } + } + } + } +} diff --git a/phpBB/phpbb/db/extractor/exception/extractor_not_initialized_exception.php b/phpBB/phpbb/db/extractor/exception/extractor_not_initialized_exception.php new file mode 100644 index 0000000000..62eb434be1 --- /dev/null +++ b/phpBB/phpbb/db/extractor/exception/extractor_not_initialized_exception.php @@ -0,0 +1,24 @@ + +* @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\extractor\exception; + +use phpbb\exception\runtime_exception; + +/** +* This exception is thrown when invalid format is given to the extractor +*/ +class extractor_not_initialized_exception extends runtime_exception +{ + +} diff --git a/phpBB/phpbb/db/extractor/exception/invalid_format_exception.php b/phpBB/phpbb/db/extractor/exception/invalid_format_exception.php new file mode 100644 index 0000000000..6be24cb5dc --- /dev/null +++ b/phpBB/phpbb/db/extractor/exception/invalid_format_exception.php @@ -0,0 +1,22 @@ + +* @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\extractor\exception; + +/** +* This exception is thrown when invalid format is given to the extractor +*/ +class invalid_format_exception extends \InvalidArgumentException +{ + +} diff --git a/phpBB/phpbb/db/extractor/extractor_interface.php b/phpBB/phpbb/db/extractor/extractor_interface.php new file mode 100644 index 0000000000..ff45df9bb7 --- /dev/null +++ b/phpBB/phpbb/db/extractor/extractor_interface.php @@ -0,0 +1,80 @@ + +* @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\extractor; + +/** +* Database extractor interface +*/ +interface extractor_interface +{ + /** + * Start the extraction of the database + * + * This function initialize the database extraction. It is required to call this + * function before calling any other extractor functions. + * + * @param string $format + * @param string $filename + * @param int $time + * @param bool $download + * @param bool $store + * @return null + * @throws \phpbb\db\extractor\exception\invalid_format_exception when $format is invalid + */ + public function init_extractor($format, $filename, $time, $download = false, $store = false); + + /** + * Writes header comments to the database backup + * + * @param string $table_prefix prefix of phpBB database tables + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + public function write_start($table_prefix); + + /** + * Closes file and/or dumps download data + * + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + public function write_end(); + + /** + * Extracts database table structure + * + * @param string $table_name name of the database table + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + public function write_table($table_name); + + /** + * Extracts data from database table + * + * @param string $table_name name of the database table + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + public function write_data($table_name); + + /** + * Writes data to file/download content + * + * @param string $data + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + public function flush($data); +} diff --git a/phpBB/phpbb/db/extractor/factory.php b/phpBB/phpbb/db/extractor/factory.php new file mode 100644 index 0000000000..a1ffb65595 --- /dev/null +++ b/phpBB/phpbb/db/extractor/factory.php @@ -0,0 +1,79 @@ + +* @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\extractor; + +/** +* A factory which serves the suitable extractor instance for the given dbal +*/ +class factory +{ + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + /** + * Extractor factory constructor + * + * @param \phpbb\db\driver\driver_interface $db + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + */ + public function __construct(\phpbb\db\driver\driver_interface $db, \Symfony\Component\DependencyInjection\ContainerInterface $container) + { + $this->db = $db; + $this->container = $container; + } + + /** + * DB extractor factory getter + * + * @return \phpbb\db\extractor\extractor_interface an appropriate instance of the database extractor for the used database driver + * @throws \InvalidArgumentException when the database driver is unknown + */ + public function get() + { + // Return the appropriate DB extractor + if ($this->db instanceof \phpbb\db\driver\mssql || $this->db instanceof \phpbb\db\driver\mssql_base) + { + return $this->container->get('dbal.extractor.extractors.mssql_extractor'); + } + else if ($this->db instanceof \phpbb\db\driver\mysql_base) + { + return $this->container->get('dbal.extractor.extractors.mysql_extractor'); + } + else if ($this->db instanceof \phpbb\db\driver\oracle) + { + return $this->container->get('dbal.extractor.extractors.oracle_extractor'); + } + else if ($this->db instanceof \phpbb\db\driver\postgres) + { + return $this->container->get('dbal.extractor.extractors.postgres_extractor'); + } + else if ($this->db instanceof \phpbb\db\driver\sqlite) + { + return $this->container->get('dbal.extractor.extractors.sqlite_extractor'); + } + else if ($this->db instanceof \phpbb\db\driver\sqlite3) + { + return $this->container->get('dbal.extractor.extractors.sqlite3_extractor'); + } + + throw new \InvalidArgumentException('Invalid database driver given'); + } +} diff --git a/phpBB/phpbb/db/extractor/mssql_extractor.php b/phpBB/phpbb/db/extractor/mssql_extractor.php new file mode 100644 index 0000000000..d0aa78f1f5 --- /dev/null +++ b/phpBB/phpbb/db/extractor/mssql_extractor.php @@ -0,0 +1,524 @@ + +* @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\extractor; + +use phpbb\db\extractor\exception\extractor_not_initialized_exception; + +class mssql_extractor extends base_extractor +{ + /** + * Writes closing line(s) to database backup + * + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + public function write_end() + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $this->flush("COMMIT\nGO\n"); + parent::write_end(); + } + + /** + * {@inheritdoc} + */ + public function write_start($table_prefix) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $table_prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION\n"; + $sql_data .= "GO\n"; + $this->flush($sql_data); + } + + /** + * {@inheritdoc} + */ + public function write_table($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + $sql_data .= "GO\n"; + $sql_data .= "\nCREATE TABLE [$table_name] (\n"; + $rows = array(); + + $text_flag = false; + + $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_NAME = '$table_name'"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]"; + + if ($row['DATA_TYPE'] == 'text') + { + $text_flag = true; + } + + if ($row['IS_IDENTITY']) + { + $line .= ' IDENTITY (1 , 1)'; + } + + if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text') + { + $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')'; + } + + if ($row['IS_NULLABLE'] == 'YES') + { + $line .= ' NULL'; + } + else + { + $line .= ' NOT NULL'; + } + + if ($row['COLUMN_DEFAULT']) + { + $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT']; + } + + $rows[] = $line; + } + $this->db->sql_freeresult($result); + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n) ON [PRIMARY]"; + + if ($text_flag) + { + $sql_data .= " TEXTIMAGE_ON [PRIMARY]"; + } + + $sql_data .= "\nGO\n\n"; + $rows = array(); + + $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME + FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE + WHERE TABLE_NAME = '$table_name'"; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + if (!sizeof($rows)) + { + $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n"; + $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY CLUSTERED \n\t(\n"; + } + $rows[] = "\t\t[{$row['COLUMN_NAME']}]"; + } + if (sizeof($rows)) + { + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n\t) ON [PRIMARY] \nGO\n"; + } + $this->db->sql_freeresult($result); + + $index = array(); + $sql = "EXEC sp_statistics '$table_name'"; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + if ($row['TYPE'] == 3) + { + $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']'; + } + } + $this->db->sql_freeresult($result); + + foreach ($index as $index_name => $column_name) + { + $index[$index_name] = implode(', ', $column_name); + } + + foreach ($index as $index_name => $columns) + { + $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n"; + } + $this->flush($sql_data); + } + + /** + * {@inheritdoc} + */ + public function write_data($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + if ($this->db->get_sql_layer() === 'mssql') + { + $this->write_data_mssql($table_name); + } + else if($this->db->get_sql_layer() === 'mssqlnative') + { + $this->write_data_mssqlnative($table_name); + } + else + { + $this->write_data_odbc($table_name); + } + } + + /** + * Extracts data from database table (for MSSQL driver) + * + * @param string $table_name name of the database table + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + protected function write_data_mssql($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $ary_type = $ary_name = array(); + $ident_set = false; + $sql_data = ''; + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $this->db->sql_query($sql); + + $retrieved_data = mssql_num_rows($result); + + $i_num_fields = mssql_num_fields($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[$i] = mssql_field_type($result, $i); + $ary_name[$i] = mssql_field_name($result, $i); + } + + if ($retrieved_data) + { + $sql = "SELECT 1 as has_identity + FROM INFORMATION_SCHEMA.COLUMNS + WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; + $result2 = $this->db->sql_query($sql); + $row2 = $this->db->sql_fetchrow($result2); + if (!empty($row2['has_identity'])) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; + $ident_set = true; + } + $this->db->sql_freeresult($result2); + } + + while ($row = $this->db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = $ary_name[$i]; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; + + $this->flush($sql_data); + $sql_data = ''; + } + $this->db->sql_freeresult($result); + + if ($retrieved_data && $ident_set) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; + } + $this->flush($sql_data); + } + + /** + * Extracts data from database table (for MSSQL Native driver) + * + * @param string $table_name name of the database table + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + protected function write_data_mssqlnative($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $ary_type = $ary_name = array(); + $ident_set = false; + $sql_data = ''; + + // Grab all of the data from current table. + $sql = "SELECT * FROM $table_name"; + $this->db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC)); + $result = $this->db->sql_query($sql); + + $retrieved_data = $this->db->mssqlnative_num_rows($result); + + if (!$retrieved_data) + { + $this->db->sql_freeresult($result); + return; + } + + $sql = "SELECT COLUMN_NAME, DATA_TYPE + FROM INFORMATION_SCHEMA.COLUMNS + WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $this->db->sql_escape($table_name) . "'"; + $result_fields = $this->db->sql_query($sql); + + $i_num_fields = 0; + while ($row = $this->db->sql_fetchrow($result_fields)) + { + $ary_type[$i_num_fields] = $row['DATA_TYPE']; + $ary_name[$i_num_fields] = $row['COLUMN_NAME']; + $i_num_fields++; + } + $this->db->sql_freeresult($result_fields); + + $sql = "SELECT 1 as has_identity + FROM INFORMATION_SCHEMA.COLUMNS + WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; + $result2 = $this->db->sql_query($sql); + $row2 = $this->db->sql_fetchrow($result2); + + if (!empty($row2['has_identity'])) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; + $ident_set = true; + } + $this->db->sql_freeresult($result2); + + while ($row = $this->db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + // defaults to type number - better quote just to be safe, so check for is_int too + if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = $ary_name[$i]; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; + + $this->flush($sql_data); + $sql_data = ''; + } + $this->db->sql_freeresult($result); + + if ($ident_set) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; + } + $this->flush($sql_data); + } + + /** + * Extracts data from database table (for ODBC driver) + * + * @param string $table_name name of the database table + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + protected function write_data_odbc($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $ary_type = $ary_name = array(); + $ident_set = false; + $sql_data = ''; + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $this->db->sql_query($sql); + + $retrieved_data = odbc_num_rows($result); + + if ($retrieved_data) + { + $sql = "SELECT 1 as has_identity + FROM INFORMATION_SCHEMA.COLUMNS + WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; + $result2 = $this->db->sql_query($sql); + $row2 = $this->db->sql_fetchrow($result2); + if (!empty($row2['has_identity'])) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; + $ident_set = true; + } + $this->db->sql_freeresult($result2); + } + + $i_num_fields = odbc_num_fields($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[$i] = odbc_field_type($result, $i + 1); + $ary_name[$i] = odbc_field_name($result, $i + 1); + } + + while ($row = $this->db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = $ary_name[$i]; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; + + $this->flush($sql_data); + + $sql_data = ''; + + } + $this->db->sql_freeresult($result); + + if ($retrieved_data && $ident_set) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; + } + $this->flush($sql_data); + } +} diff --git a/phpBB/phpbb/db/extractor/mysql_extractor.php b/phpBB/phpbb/db/extractor/mysql_extractor.php new file mode 100644 index 0000000000..34e309c19e --- /dev/null +++ b/phpBB/phpbb/db/extractor/mysql_extractor.php @@ -0,0 +1,403 @@ + +* @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\extractor; + +use phpbb\db\extractor\exception\extractor_not_initialized_exception; + +class mysql_extractor extends base_extractor +{ + /** + * {@inheritdoc} + */ + public function write_start($table_prefix) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = "#\n"; + $sql_data .= "# phpBB Backup Script\n"; + $sql_data .= "# Dump of tables for $table_prefix\n"; + $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "#\n"; + $this->flush($sql_data); + } + + /** + * {@inheritdoc} + */ + public function write_table($table_name) + { + static $new_extract; + + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + if ($new_extract === null) + { + if ($this->db->get_sql_layer() === 'mysqli' || version_compare($this->db->sql_server_info(true), '3.23.20', '>=')) + { + $new_extract = true; + } + else + { + $new_extract = false; + } + } + + if ($new_extract) + { + $this->new_write_table($table_name); + } + else + { + $this->old_write_table($table_name); + } + } + + /** + * {@inheritdoc} + */ + public function write_data($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + if ($this->db->get_sql_layer() === 'mysqli') + { + $this->write_data_mysqli($table_name); + } + else + { + $this->write_data_mysql($table_name); + } + } + + /** + * Extracts data from database table (for MySQLi driver) + * + * @param string $table_name name of the database table + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + protected function write_data_mysqli($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql = "SELECT * + FROM $table_name"; + $result = mysqli_query($this->db->get_db_connect_id(), $sql, MYSQLI_USE_RESULT); + if ($result != false) + { + $fields_cnt = mysqli_num_fields($result); + + // Get field information + $field = mysqli_fetch_fields($result); + $field_set = array(); + + for ($j = 0; $j < $fields_cnt; $j++) + { + $field_set[] = $field[$j]->name; + } + + $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); + $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); + $fields = implode(', ', $field_set); + $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; + $first_set = true; + $query_len = 0; + $max_len = get_usable_memory(); + + while ($row = mysqli_fetch_row($result)) + { + $values = array(); + if ($first_set) + { + $query = $sql_data . '('; + } + else + { + $query .= ',('; + } + + for ($j = 0; $j < $fields_cnt; $j++) + { + if (!isset($row[$j]) || is_null($row[$j])) + { + $values[$j] = 'NULL'; + } + else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024)) + { + $values[$j] = $row[$j]; + } + else + { + $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; + } + } + $query .= implode(', ', $values) . ')'; + + $query_len += strlen($query); + if ($query_len > $max_len) + { + $this->flush($query . ";\n\n"); + $query = ''; + $query_len = 0; + $first_set = true; + } + else + { + $first_set = false; + } + } + mysqli_free_result($result); + + // check to make sure we have nothing left to flush + if (!$first_set && $query) + { + $this->flush($query . ";\n\n"); + } + } + } + + /** + * Extracts data from database table (for MySQL driver) + * + * @param string $table_name name of the database table + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + protected function write_data_mysql($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql = "SELECT * + FROM $table_name"; + $result = mysql_unbuffered_query($sql, $this->db->get_db_connect_id()); + + if ($result != false) + { + $fields_cnt = mysql_num_fields($result); + + // Get field information + $field = array(); + for ($i = 0; $i < $fields_cnt; $i++) + { + $field[] = mysql_fetch_field($result, $i); + } + $field_set = array(); + + for ($j = 0; $j < $fields_cnt; $j++) + { + $field_set[] = $field[$j]->name; + } + + $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); + $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); + $fields = implode(', ', $field_set); + $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; + $first_set = true; + $query_len = 0; + $max_len = get_usable_memory(); + + while ($row = mysql_fetch_row($result)) + { + $values = array(); + if ($first_set) + { + $query = $sql_data . '('; + } + else + { + $query .= ',('; + } + + for ($j = 0; $j < $fields_cnt; $j++) + { + if (!isset($row[$j]) || is_null($row[$j])) + { + $values[$j] = 'NULL'; + } + else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp')) + { + $values[$j] = $row[$j]; + } + else + { + $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; + } + } + $query .= implode(', ', $values) . ')'; + + $query_len += strlen($query); + if ($query_len > $max_len) + { + $this->flush($query . ";\n\n"); + $query = ''; + $query_len = 0; + $first_set = true; + } + else + { + $first_set = false; + } + } + mysql_free_result($result); + + // check to make sure we have nothing left to flush + if (!$first_set && $query) + { + $this->flush($query . ";\n\n"); + } + } + } + + /** + * Extracts database table structure (for MySQLi or MySQL 3.23.20+) + * + * @param string $table_name name of the database table + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + protected function new_write_table($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql = 'SHOW CREATE TABLE ' . $table_name; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + + $sql_data = '# Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; + $this->flush($sql_data . $row['Create Table'] . ";\n\n"); + + $this->db->sql_freeresult($result); + } + + /** + * Extracts database table structure (for MySQL verisons older than 3.23.20) + * + * @param string $table_name name of the database table + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + protected function old_write_table($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = '# Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; + $sql_data .= "CREATE TABLE $table_name(\n"; + $rows = array(); + + $sql = "SHOW FIELDS + FROM $table_name"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $line = ' ' . $row['Field'] . ' ' . $row['Type']; + + if (!is_null($row['Default'])) + { + $line .= " DEFAULT '{$row['Default']}'"; + } + + if ($row['Null'] != 'YES') + { + $line .= ' NOT NULL'; + } + + if ($row['Extra'] != '') + { + $line .= ' ' . $row['Extra']; + } + + $rows[] = $line; + } + $this->db->sql_freeresult($result); + + $sql = "SHOW KEYS + FROM $table_name"; + + $result = $this->db->sql_query($sql); + + $index = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $kname = $row['Key_name']; + + if ($kname != 'PRIMARY') + { + if ($row['Non_unique'] == 0) + { + $kname = "UNIQUE|$kname"; + } + } + + if ($row['Sub_part']) + { + $row['Column_name'] .= '(' . $row['Sub_part'] . ')'; + } + $index[$kname][] = $row['Column_name']; + } + $this->db->sql_freeresult($result); + + foreach ($index as $key => $columns) + { + $line = ' '; + + if ($key == 'PRIMARY') + { + $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')'; + } + else if (strpos($key, 'UNIQUE') === 0) + { + $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')'; + } + else if (strpos($key, 'FULLTEXT') === 0) + { + $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')'; + } + else + { + $line .= "KEY $key (" . implode(', ', $columns) . ')'; + } + + $rows[] = $line; + } + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n);\n\n"; + + $this->flush($sql_data); + } +} diff --git a/phpBB/phpbb/db/extractor/oracle_extractor.php b/phpBB/phpbb/db/extractor/oracle_extractor.php new file mode 100644 index 0000000000..05f7b8ac95 --- /dev/null +++ b/phpBB/phpbb/db/extractor/oracle_extractor.php @@ -0,0 +1,265 @@ + +* @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\extractor; + +use phpbb\db\extractor\exception\extractor_not_initialized_exception; + +class oracle_extractor extends base_extractor +{ + /** + * {@inheritdoc} + */ + public function write_table($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name\n/\n"; + $sql_data .= "\nCREATE TABLE $table_name (\n"; + + $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT + FROM ALL_TAB_COLS + WHERE table_name = '{$table_name}'"; + $result = $this->db->sql_query($sql); + + $rows = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $line = ' "' . $row['column_name'] . '" ' . $row['data_type']; + + if ($row['data_type'] !== 'CLOB') + { + if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR') + { + $line .= '(' . $row['data_precision'] . ')'; + } + else + { + $line .= '(' . $row['data_length'] . ')'; + } + } + + if (!empty($row['data_default'])) + { + $line .= ' DEFAULT ' . $row['data_default']; + } + + if ($row['nullable'] == 'N') + { + $line .= ' NOT NULL'; + } + $rows[] = $line; + } + $this->db->sql_freeresult($result); + + $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME + FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B + WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME + AND B.CONSTRAINT_TYPE = 'P' + AND A.TABLE_NAME = '{$table_name}'"; + $result = $this->db->sql_query($sql); + + $primary_key = array(); + $constraint_name = ''; + while ($row = $this->db->sql_fetchrow($result)) + { + $constraint_name = '"' . $row['constraint_name'] . '"'; + $primary_key[] = '"' . $row['column_name'] . '"'; + } + $this->db->sql_freeresult($result); + + if (sizeof($primary_key)) + { + $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')'; + } + + $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME + FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B + WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME + AND B.CONSTRAINT_TYPE = 'U' + AND A.TABLE_NAME = '{$table_name}'"; + $result = $this->db->sql_query($sql); + + $unique = array(); + $constraint_name = ''; + while ($row = $this->db->sql_fetchrow($result)) + { + $constraint_name = '"' . $row['constraint_name'] . '"'; + $unique[] = '"' . $row['column_name'] . '"'; + } + $this->db->sql_freeresult($result); + + if (sizeof($unique)) + { + $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')'; + } + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n)\n/\n"; + + $sql = "SELECT A.REFERENCED_NAME, C.* + FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C + WHERE A.REFERENCED_TYPE = 'SEQUENCE' + AND A.NAME = B.TRIGGER_NAME + AND B.TABLE_NAME = '{$table_name}' + AND C.SEQUENCE_NAME = A.REFERENCED_NAME"; + $result = $this->db->sql_query($sql); + + $type = $this->request->variable('type', ''); + + while ($row = $this->db->sql_fetchrow($result)) + { + $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n"; + $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\""; + + if ($type == 'full') + { + $sql_data .= ' START WITH ' . $row['last_number']; + } + + $sql_data .= "\n/\n"; + } + $this->db->sql_freeresult($result); + + $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY + FROM USER_TRIGGERS + WHERE TABLE_NAME = '{$table_name}'"; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n"; + } + $this->db->sql_freeresult($result); + + $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME + FROM USER_INDEXES A, USER_IND_COLUMNS B + WHERE A.UNIQUENESS = 'NONUNIQUE' + AND A.INDEX_NAME = B.INDEX_NAME + AND B.TABLE_NAME = '{$table_name}'"; + $result = $this->db->sql_query($sql); + + $index = array(); + + while ($row = $this->db->sql_fetchrow($result)) + { + $index[$row['index_name']][] = $row['column_name']; + } + + foreach ($index as $index_name => $column_names) + { + $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n"; + } + $this->db->sql_freeresult($result); + $this->flush($sql_data); + } + + /** + * {@inheritdoc} + */ + public function write_data($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $ary_type = $ary_name = array(); + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $this->db->sql_query($sql); + + $i_num_fields = ocinumcols($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[$i] = ocicolumntype($result, $i + 1); + $ary_name[$i] = ocicolumnname($result, $i + 1); + } + + $sql_data = ''; + + while ($row = $this->db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + // Oracle uses uppercase - we use lowercase + $str_val = $row[strtolower($ary_name[$i])]; + + if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_oracle($str_val); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0') + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = '"' . $ary_name[$i] . '"'; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n"; + + $this->flush($sql_data); + } + $this->db->sql_freeresult($result); + } + + /** + * {@inheritdoc} + */ + public function write_start($table_prefix) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $table_prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $this->flush($sql_data); + } +} diff --git a/phpBB/phpbb/db/extractor/postgres_extractor.php b/phpBB/phpbb/db/extractor/postgres_extractor.php new file mode 100644 index 0000000000..9eff1f568d --- /dev/null +++ b/phpBB/phpbb/db/extractor/postgres_extractor.php @@ -0,0 +1,338 @@ + +* @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\extractor; + +use phpbb\db\extractor\exception\extractor_not_initialized_exception; + +class postgres_extractor extends base_extractor +{ + /** + * {@inheritdoc} + */ + public function write_start($table_prefix) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $table_prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION;\n"; + $this->flush($sql_data); + } + + /** + * {@inheritdoc} + */ + public function write_table($table_name) + { + static $domains_created = array(); + + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default + FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b + WHERE a.domain_name = b.domain_name + AND b.table_name = '{$table_name}'"; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + if (empty($domains_created[$row['domain_name']])) + { + $domains_created[$row['domain_name']] = true; + //$sql_data = "DROP DOMAIN {$row['domain_name']};\n"; + $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}"; + if (!empty($row['character_maximum_length'])) + { + $sql_data .= '(' . $row['character_maximum_length'] . ')'; + } + $sql_data .= ' NOT NULL'; + if (!empty($row['domain_default'])) + { + $sql_data .= ' DEFAULT ' . $row['domain_default']; + } + $this->flush($sql_data . ";\n"); + } + } + + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + // PGSQL does not "tightly" bind sequences and tables, we must guess... + $sql = "SELECT relname + FROM pg_class + WHERE relkind = 'S' + AND relname = '{$table_name}_seq'"; + $result = $this->db->sql_query($sql); + // We don't even care about storing the results. We already know the answer if we get rows back. + if ($this->db->sql_fetchrow($result)) + { + $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n"; + $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n"; + } + $this->db->sql_freeresult($result); + + $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull + FROM pg_class c, pg_attribute a, pg_type t + WHERE c.relname = '" . $this->db->sql_escape($table_name) . "' + AND a.attnum > 0 + AND a.attrelid = c.oid + AND a.atttypid = t.oid + ORDER BY a.attnum"; + $result = $this->db->sql_query($field_query); + + $sql_data .= "CREATE TABLE $table_name(\n"; + $lines = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + // Get the data from the table + $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault + FROM pg_attrdef d, pg_class c + WHERE (c.relname = '" . $this->db->sql_escape($table_name) . "') + AND (c.oid = d.adrelid) + AND d.adnum = " . $row['attnum']; + $def_res = $this->db->sql_query($sql_get_default); + $def_row = $this->db->sql_fetchrow($def_res); + $this->db->sql_freeresult($def_res); + + if (empty($def_row)) + { + unset($row['rowdefault']); + } + else + { + $row['rowdefault'] = $def_row['rowdefault']; + } + + if ($row['type'] == 'bpchar') + { + // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement. + $row['type'] = 'char'; + } + + $line = ' ' . $row['field'] . ' ' . $row['type']; + + if (strpos($row['type'], 'char') !== false) + { + if ($row['lengthvar'] > 0) + { + $line .= '(' . ($row['lengthvar'] - 4) . ')'; + } + } + + if (strpos($row['type'], 'numeric') !== false) + { + $line .= '('; + $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff)); + $line .= ')'; + } + + if (isset($row['rowdefault'])) + { + $line .= ' DEFAULT ' . $row['rowdefault']; + } + + if ($row['notnull'] == 't') + { + $line .= ' NOT NULL'; + } + + $lines[] = $line; + } + $this->db->sql_freeresult($result); + + // Get the listing of primary keys. + $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key + FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia + WHERE (bc.oid = i.indrelid) + AND (ic.oid = i.indexrelid) + AND (ia.attrelid = i.indexrelid) + AND (ta.attrelid = bc.oid) + AND (bc.relname = '" . $this->db->sql_escape($table_name) . "') + AND (ta.attrelid = i.indrelid) + AND (ta.attnum = i.indkey[ia.attnum-1]) + ORDER BY index_name, tab_name, column_name"; + + $result = $this->db->sql_query($sql_pri_keys); + + $index_create = $index_rows = $primary_key = array(); + + // We do this in two steps. It makes placing the comma easier + while ($row = $this->db->sql_fetchrow($result)) + { + if ($row['primary_key'] == 't') + { + $primary_key[] = $row['column_name']; + $primary_key_name = $row['index_name']; + } + else + { + // We have to store this all this info because it is possible to have a multi-column key... + // we can loop through it again and build the statement + $index_rows[$row['index_name']]['table'] = $table_name; + $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false; + $index_rows[$row['index_name']]['column_names'][] = $row['column_name']; + } + } + $this->db->sql_freeresult($result); + + if (!empty($index_rows)) + { + foreach ($index_rows as $idx_name => $props) + { + $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");"; + } + } + + if (!empty($primary_key)) + { + $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")"; + } + + // Generate constraint clauses for CHECK constraints + $sql_checks = "SELECT conname as index_name, consrc + FROM pg_constraint, pg_class bc + WHERE conrelid = bc.oid + AND bc.relname = '" . $this->db->sql_escape($table_name) . "' + AND NOT EXISTS ( + SELECT * + FROM pg_constraint as c, pg_inherits as i + WHERE i.inhrelid = pg_constraint.conrelid + AND c.conname = pg_constraint.conname + AND c.consrc = pg_constraint.consrc + AND c.conrelid = i.inhparent + )"; + $result = $this->db->sql_query($sql_checks); + + // Add the constraints to the sql file. + while ($row = $this->db->sql_fetchrow($result)) + { + if (!is_null($row['consrc'])) + { + $lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc']; + } + } + $this->db->sql_freeresult($result); + + $sql_data .= implode(", \n", $lines); + $sql_data .= "\n);\n"; + + if (!empty($index_create)) + { + $sql_data .= implode("\n", $index_create) . "\n\n"; + } + $this->flush($sql_data); + } + + /** + * {@inheritdoc} + */ + public function write_data($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $this->db->sql_query($sql); + + $i_num_fields = pg_num_fields($result); + $seq = ''; + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[] = pg_field_type($result, $i); + $ary_name[] = pg_field_name($result, $i); + + $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault + FROM pg_attrdef d, pg_class c + WHERE (c.relname = '{$table_name}') + AND (c.oid = d.adrelid) + AND d.adnum = " . strval($i + 1); + $result2 = $this->db->sql_query($sql); + if ($row = $this->db->sql_fetchrow($result2)) + { + // Determine if we must reset the sequences + if (strpos($row['rowdefault'], "nextval('") === 0) + { + $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n"; + } + } + } + + $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n"); + while ($row = $this->db->sql_fetchrow($result)) + { + $schema_vals = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|bytea#i', $ary_type[$i])) + { + $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val)); + $str_empty = ''; + } + else + { + $str_empty = '\N'; + } + + if (empty($str_val) && $str_val !== '0') + { + $str_val = $str_empty; + } + + $schema_vals[] = $str_val; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $this->flush(implode("\t", $schema_vals) . "\n"); + } + $this->db->sql_freeresult($result); + $this->flush("\\.\n"); + + // Write out the sequence statements + $this->flush($seq); + } + + /** + * Writes closing line(s) to database backup + * + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + public function write_end() + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $this->flush("COMMIT;\n"); + parent::write_end(); + } +} diff --git a/phpBB/phpbb/db/extractor/sqlite3_extractor.php b/phpBB/phpbb/db/extractor/sqlite3_extractor.php new file mode 100644 index 0000000000..ce8da6a652 --- /dev/null +++ b/phpBB/phpbb/db/extractor/sqlite3_extractor.php @@ -0,0 +1,151 @@ + +* @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\extractor; + +use phpbb\db\extractor\exception\extractor_not_initialized_exception; + +class sqlite3_extractor extends base_extractor +{ + /** + * {@inheritdoc} + */ + public function write_start($table_prefix) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $table_prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION;\n"; + $this->flush($sql_data); + } + + /** + * {@inheritdoc} + */ + public function write_table($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . $this->db->sql_escape($table_name) . "' + ORDER BY name ASC;"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + // Create Table + $sql_data .= $row['sql'] . ";\n"; + + $result = $this->db->sql_query("PRAGMA index_list('" . $this->db->sql_escape($table_name) . "');"); + + while ($row = $this->db->sql_fetchrow($result)) + { + if (strpos($row['name'], 'autoindex') !== false) + { + continue; + } + + $result2 = $this->db->sql_query("PRAGMA index_info('" . $this->db->sql_escape($row['name']) . "');"); + + $fields = array(); + while ($row2 = $this->db->sql_fetchrow($result2)) + { + $fields[] = $row2['name']; + } + $this->db->sql_freeresult($result2); + + $sql_data .= 'CREATE ' . ($row['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $row['name'] . ' ON ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; + } + $this->db->sql_freeresult($result); + + $this->flush($sql_data . "\n"); + } + + /** + * {@inheritdoc} + */ + public function write_data($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $result = $this->db->sql_query("PRAGMA table_info('" . $this->db->sql_escape($table_name) . "');"); + + $col_types = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $col_types[$row['name']] = $row['type']; + } + $this->db->sql_freeresult($result); + + $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; + + $sql = "SELECT * + FROM $table_name"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + foreach ($row as $column_name => $column_data) + { + if (is_null($column_data)) + { + $row[$column_name] = 'NULL'; + } + else if ($column_data === '') + { + $row[$column_name] = "''"; + } + else if (stripos($col_types[$column_name], 'text') !== false || stripos($col_types[$column_name], 'char') !== false || stripos($col_types[$column_name], 'blob') !== false) + { + $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); + } + } + $this->flush($sql_insert . implode(', ', $row) . ");\n"); + } + } + + /** + * Writes closing line(s) to database backup + * + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + public function write_end() + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $this->flush("COMMIT;\n"); + parent::write_end(); + } +} diff --git a/phpBB/phpbb/db/extractor/sqlite_extractor.php b/phpBB/phpbb/db/extractor/sqlite_extractor.php new file mode 100644 index 0000000000..2734e23235 --- /dev/null +++ b/phpBB/phpbb/db/extractor/sqlite_extractor.php @@ -0,0 +1,149 @@ + +* @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\extractor; + +use phpbb\db\extractor\exception\extractor_not_initialized_exception; + +class sqlite_extractor extends base_extractor +{ + /** + * {@inheritdoc} + */ + public function write_start($table_prefix) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $table_prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION;\n"; + $this->flush($sql_data); + } + + /** + * {@inheritdoc} + */ + public function write_table($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . $this->db->sql_escape($table_name) . "' + ORDER BY type DESC, name;"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + // Create Table + $sql_data .= $row['sql'] . ";\n"; + + $result = $this->db->sql_query("PRAGMA index_list('" . $this->db->sql_escape($table_name) . "');"); + + $ar = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $ar[] = $row; + } + $this->db->sql_freeresult($result); + + foreach ($ar as $value) + { + if (strpos($value['name'], 'autoindex') !== false) + { + continue; + } + + $result = $this->db->sql_query("PRAGMA index_info('" . $this->db->sql_escape($value['name']) . "');"); + + $fields = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $fields[] = $row['name']; + } + $this->db->sql_freeresult($result); + + $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; + } + + $this->flush($sql_data . "\n"); + } + + /** + * {@inheritdoc} + */ + public function write_data($table_name) + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $col_types = sqlite_fetch_column_types($this->db->get_db_connect_id(), $table_name); + + $sql = "SELECT * + FROM $table_name"; + $result = sqlite_unbuffered_query($this->db->get_db_connect_id(), $sql); + $rows = sqlite_fetch_all($result, SQLITE_ASSOC); + $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; + foreach ($rows as $row) + { + foreach ($row as $column_name => $column_data) + { + if (is_null($column_data)) + { + $row[$column_name] = 'NULL'; + } + else if ($column_data == '') + { + $row[$column_name] = "''"; + } + else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false) + { + $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); + } + } + $this->flush($sql_insert . implode(', ', $row) . ");\n"); + } + } + + /** + * Writes closing line(s) to database backup + * + * @return null + * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() + */ + public function write_end() + { + if (!$this->is_initialized) + { + throw new extractor_not_initialized_exception(); + } + + $this->flush("COMMIT;\n"); + parent::write_end(); + } +} From 7e0d54a331ccb569dafeae8b051db5a34e177b5f Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 27 Feb 2015 22:58:51 +0100 Subject: [PATCH 0119/1676] [ticket/13647] Use the Symfony way for redirecting PHPBB3-13647 --- phpBB/faq.php | 8 ++++++-- phpBB/phpbb/help/controller/help.php | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/phpBB/faq.php b/phpBB/faq.php index 5d8a97bc26..7420bc5a95 100644 --- a/phpBB/faq.php +++ b/phpBB/faq.php @@ -27,5 +27,9 @@ $user->setup(); /** @var \phpbb\controller\helper $controller_helper */ $controller_helper = $phpbb_container->get('controller.helper'); -send_status_line(301, 'Moved Permanently'); -redirect($controller_helper->route('phpbb_help_controller', array('mode' => $request->variable('mode', 'faq')))); +$response = new \Symfony\Component\HttpFoundation\RedirectResponse( + $controller_helper->route('phpbb_help_controller', array( + 'mode' => $request->variable('mode', 'faq'), + ), 301) +); +$response->send(); diff --git a/phpBB/phpbb/help/controller/help.php b/phpBB/phpbb/help/controller/help.php index e9594a0563..9cc3b0c8b4 100644 --- a/phpBB/phpbb/help/controller/help.php +++ b/phpBB/phpbb/help/controller/help.php @@ -97,7 +97,7 @@ class help if ($ext_name === '' || $lang_file === '') { - throw new http_exception(501, 'FEATURE_NOT_AVAILABLE'); + throw new http_exception(404, 'Not Found'); } $this->user->add_lang($lang_file, false, true, $ext_name); From cf39cfc5939f9407082f8f5c1f876ea0ee607a45 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 7 Oct 2014 20:51:08 +0200 Subject: [PATCH 0120/1676] [ticket/13132] Twig: Add loops content to the root context PHPBB3-13132 --- phpBB/phpbb/template/twig/twig.php | 6 + tests/template/template_test.php | 149 +++++++++++++++++- .../templates/loop_advanced_twig.html | 19 +++ .../template/templates/loop_expressions.html | 4 +- .../templates/loop_expressions_twig.html | 11 ++ .../templates/loop_include1_twig.html | 1 + .../template/templates/loop_include_twig.html | 4 + .../template/templates/loop_nested2_twig.html | 6 + .../loop_nested_deep_multilevel_ref_twig.html | 13 ++ .../templates/loop_nested_include1_twig.html | 5 + .../templates/loop_nested_include_twig.html | 4 + .../loop_nested_multilevel_ref_twig.html | 10 ++ .../template/templates/loop_nested_twig.html | 6 + tests/template/templates/loop_reuse_twig.html | 6 + tests/template/templates/loop_size_twig.html | 39 +++++ tests/template/templates/loop_twig.html | 21 +++ .../templates/loop_underscore_twig.html | 21 +++ tests/template/templates/loop_vars_twig.html | 13 ++ 18 files changed, 335 insertions(+), 3 deletions(-) create mode 100644 tests/template/templates/loop_advanced_twig.html create mode 100644 tests/template/templates/loop_expressions_twig.html create mode 100644 tests/template/templates/loop_include1_twig.html create mode 100644 tests/template/templates/loop_include_twig.html create mode 100644 tests/template/templates/loop_nested2_twig.html create mode 100644 tests/template/templates/loop_nested_deep_multilevel_ref_twig.html create mode 100644 tests/template/templates/loop_nested_include1_twig.html create mode 100644 tests/template/templates/loop_nested_include_twig.html create mode 100644 tests/template/templates/loop_nested_multilevel_ref_twig.html create mode 100644 tests/template/templates/loop_nested_twig.html create mode 100644 tests/template/templates/loop_reuse_twig.html create mode 100644 tests/template/templates/loop_size_twig.html create mode 100644 tests/template/templates/loop_twig.html create mode 100644 tests/template/templates/loop_underscore_twig.html create mode 100644 tests/template/templates/loop_vars_twig.html diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php index 605d37e954..0e4c619029 100644 --- a/phpBB/phpbb/template/twig/twig.php +++ b/phpBB/phpbb/template/twig/twig.php @@ -352,6 +352,12 @@ class twig extends \phpbb\template\base // cleanup unset($vars['loops']['.']); + // Inject in the main context the value added by assign_block_vars() to be able to use directly the Twig loops. + foreach ($vars['loops'] as $key => &$value) + { + $vars[$key] = $value; + } + return $vars; } diff --git a/tests/template/template_test.php b/tests/template/template_test.php index bb6b7300cb..b67b49bd35 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -129,6 +129,34 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "loop\nloop\nloop\nloop\nloop#0-block#0\nloop#0-block#1\nloop#1-block#0\nloop#1-block#1", ), + array( + 'loop_twig.html', + array(), + array(), + array(), + "noloop\nnoloop", + ), + array( + 'loop_twig.html', + array(), + array('test_loop' => array(array())), + array(), + "loop\nloop", + ), + array( + 'loop_twig.html', + array(), + array('test_loop' => array(array(), array()), 'test_loop.block' => array(array())), + array(), + "loop\nloop\nloop\nloop", + ), + array( + 'loop_twig.html', + array(), + array('test_loop' => array(array(), array()), 'test_loop.block' => array(array()), 'block' => array(array(), array())), + array(), + "loop\nloop\nloop\nloop\nloop#0-block#0\nloop#0-block#1\nloop#1-block#0\nloop#1-block#1", + ), array( 'loop_vars.html', array(), @@ -150,6 +178,27 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast\n0 - c\n1 - c\nlast inner", ), + array( + 'loop_vars_twig.html', + array(), + array('test_loop' => array(array('VARIABLE' => 'x'))), + array(), + "first\n0 - a\nx - b\nset\nlast", + ), + array( + 'loop_vars_twig.html', + array(), + array('test_loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y'))), + array(), + "first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast", + ), + array( + 'loop_vars_twig.html', + array(), + array('test_loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'test_loop.inner' => array(array(), array())), + array(), + "first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast\n0 - c\n1 - c\nlast inner", + ), array( 'loop_advanced.html', array(), @@ -157,6 +206,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "101234561\nx\n101234561\nx\n101234561\nx\n1234561\nx\n1\nx\n101\nx\n234\nx\n10\nx\n561\nx\n561", ), + array( + 'loop_advanced_twig.html', + array(), + array('test_loop' => array(array(), array(), array(), array(), array(), array(), array())), + array(), + "101234561\nx\n101234561\nx\n101234561\nx\n1234561\nx\n1\nx\n101\nx\n234\nx\n10\nx\n561\nx\n561", + ), array( 'loop_nested2.html', array(), @@ -164,6 +220,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "o0o1m01m11", ), + array( + 'loop_nested2_twig.html', + array(), + array('outer' => array(array(), array()), 'outer.middle' => array(array(), array())), + array(), + "o0o1m01m11", + ), array( 'define.html', array(), @@ -243,6 +306,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array('test_loop'), '', ), + array( + 'loop_vars_twig.html', + array(), + array('test_loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'test_loop.inner' => array(array(), array())), + array('test_loop'), + '', + ), array( 'include_define_variable.html', array('VARIABLE' => 'variable.html'), @@ -274,6 +344,15 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "noloop\nnoloop", ), + array( + // Just like a regular loop but the name begins + // with an underscore + 'loop_underscore_twig.html', + array(), + array(), + array(), + "noloop\nnoloop", + ), array( 'lang.html', array(), @@ -296,6 +375,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "top-level content", ), + array( + 'loop_nested_multilevel_ref_twig.html', + array(), + array(), + array(), + "top-level content", + ), array( 'loop_nested_multilevel_ref.html', array(), @@ -303,6 +389,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "top-level content\nouter x\nouter y\ninner z\nfirst row\n\ninner zz", ), + array( + 'loop_nested_multilevel_ref_twig.html', + array(), + array('outer' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'outer.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))), + array(), + "top-level content\nouter x\nouter y\ninner z\nfirst row\n\ninner zz", + ), array( 'loop_nested_deep_multilevel_ref.html', array(), @@ -310,6 +403,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "top-level content\nouter\nmiddle\ninner z\nfirst row of 2 in inner\n\ninner zz", ), + array( + 'loop_nested_deep_multilevel_ref_twig.html', + array(), + array('outer' => array(array()), 'outer.middle' => array(array()), 'outer.middle.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))), + array(), + "top-level content\nouter\nmiddle\ninner z\nfirst row of 2 in inner\n\ninner zz", + ), array( 'loop_size.html', array(), @@ -317,6 +417,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "nonexistent = 0\n! nonexistent\n\nempty = 0\n! empty\nloop\n\nin loop", ), + array( + 'loop_size_twig.html', + array(), + array('test_loop' => array(array()), 'empty_loop' => array()), + array(), + "nonexistent = 0\n! nonexistent\n\nempty = 0\n! empty\nloop\n\nin loop", + ), array( 'loop_include.html', array(), @@ -324,6 +431,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), "barbarbar1bar1", ), + array( + 'loop_include_twig.html', + array(), + array('test_loop' => array(array('foo' => 'bar'), array('foo' => 'bar1'))), + array(), + "barbarbar1bar1", + ), array( 'loop_nested_include.html', array(), @@ -335,6 +449,17 @@ class phpbb_template_template_test extends phpbb_template_template_test_case "[bar|[bar|]][bar1|[bar1|[bar1|works]]]", array(), ), + array( + 'loop_nested_include_twig.html', + array(), + array( + 'test_loop' => array(array('foo' => 'bar'), array('foo' => 'bar1')), + 'test_loop.inner' => array(array('myinner' => 'works')), + ), + array(), + "[bar|[bar|]][bar1|[bar1|[bar1|works]]]", + array(), + ), /* Does not pass with the current implementation. array( 'loop_reuse.html', @@ -343,8 +468,15 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), // Not entirely sure what should be outputted but the current output of "a" is most certainly wrong "a\nb\nc\nd", + ),*/ + array( + 'loop_reuse_twig.html', + array(), + array('one' => array(array('VAR' => 'a'), array('VAR' => 'b')), 'one.one' => array(array('VAR' => 'c'), array('VAR' => 'd'))), + array(), + // Not entirely sure what should be outputted but the current output of "a" is most certainly wrong + "a\nb\nc\nd", ), - */ array( 'twig.html', array('VARIABLE' => 'FOObar',), @@ -359,6 +491,21 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), 'inner_value', ), + // Disable: needs Twig 1.14.2 + /*array( + 'loop_expressions.html', + array('loop' => array(array(),array(),array(),array(),array(),array()),), + array(), + array(), + 'yesnonoyesnonoyesnoyesnonoyes', + ), + array( + 'loop_expressions_twig.html', + array('loop' => array(array(),array(),array(),array(),array(),array()),), + array(), + array(), + 'yesnonoyesnonoyesnoyesnonoyes', + ),*/ ); } diff --git a/tests/template/templates/loop_advanced_twig.html b/tests/template/templates/loop_advanced_twig.html new file mode 100644 index 0000000000..fd9fcae045 --- /dev/null +++ b/tests/template/templates/loop_advanced_twig.html @@ -0,0 +1,19 @@ +{% for test_loop_inner in test_loop %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(0) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(0,-1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(1,1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(0,1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(2,4) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(0,-7) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(-2,6) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(-2,-1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} diff --git a/tests/template/templates/loop_expressions.html b/tests/template/templates/loop_expressions.html index 6bff53f388..278bce1eca 100644 --- a/tests/template/templates/loop_expressions.html +++ b/tests/template/templates/loop_expressions.html @@ -1,11 +1,11 @@ -onoff +onoff -onoff +onoff diff --git a/tests/template/templates/loop_expressions_twig.html b/tests/template/templates/loop_expressions_twig.html new file mode 100644 index 0000000000..61a36c51e4 --- /dev/null +++ b/tests/template/templates/loop_expressions_twig.html @@ -0,0 +1,11 @@ +{% for loop_inner in loop %} + +{% if loop_inner.S_ROW_NUM is divisible by 4 %}on{% else %}off{% endif %} + +{% endfor %} + +{% for loop_inner in loop %} + +{% if loop_inner.S_ROW_NUM is divisible by 3 %}on{% else %}off{% endif %} + +{% endfor %} diff --git a/tests/template/templates/loop_include1_twig.html b/tests/template/templates/loop_include1_twig.html new file mode 100644 index 0000000000..2ff9f61b02 --- /dev/null +++ b/tests/template/templates/loop_include1_twig.html @@ -0,0 +1 @@ +{{ test_loop_inner.foo }} diff --git a/tests/template/templates/loop_include_twig.html b/tests/template/templates/loop_include_twig.html new file mode 100644 index 0000000000..1a534e2dbc --- /dev/null +++ b/tests/template/templates/loop_include_twig.html @@ -0,0 +1,4 @@ +{% for test_loop_inner in test_loop %} + {{ test_loop_inner.foo }} + {% INCLUDE 'loop_include1_twig.html' %} +{% endfor %} diff --git a/tests/template/templates/loop_nested2_twig.html b/tests/template/templates/loop_nested2_twig.html new file mode 100644 index 0000000000..cf802dc69f --- /dev/null +++ b/tests/template/templates/loop_nested2_twig.html @@ -0,0 +1,6 @@ +{% for outer_inner in outer %} + o{{ outer_inner.S_ROW_COUNT }} + {% for middle in outer_inner.middle %} + m{{ middle.S_ROW_COUNT }}{{ outer_inner.S_ROW_COUNT }} + {% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_nested_deep_multilevel_ref_twig.html b/tests/template/templates/loop_nested_deep_multilevel_ref_twig.html new file mode 100644 index 0000000000..9bc68e6e2e --- /dev/null +++ b/tests/template/templates/loop_nested_deep_multilevel_ref_twig.html @@ -0,0 +1,13 @@ +top-level content +{% for outer_inner in outer %} + outer + {% for middle in outer_inner.middle %} + {{ middle.S_BLOCK_NAME }} + {% for inner in middle.inner %} + inner {{ inner.VARIABLE }} + {% if inner.S_FIRST_ROW %} + first row of {{ inner.S_NUM_ROWS }} in {{ inner.S_BLOCK_NAME }} + {% endif %} + {% endfor %} + {% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_nested_include1_twig.html b/tests/template/templates/loop_nested_include1_twig.html new file mode 100644 index 0000000000..4c2ebb5f15 --- /dev/null +++ b/tests/template/templates/loop_nested_include1_twig.html @@ -0,0 +1,5 @@ +[{{ test_loop_inner.foo }}| +{% for inner in test_loop_inner.inner %} + [{{ test_loop_inner.foo }}| + {{ inner.myinner }}] +{% endfor %}] diff --git a/tests/template/templates/loop_nested_include_twig.html b/tests/template/templates/loop_nested_include_twig.html new file mode 100644 index 0000000000..c92ac922d1 --- /dev/null +++ b/tests/template/templates/loop_nested_include_twig.html @@ -0,0 +1,4 @@ +{% for test_loop_inner in test_loop %} + [{{ test_loop_inner.foo }} + |{% INCLUDE 'loop_nested_include1_twig.html' %}] +{% endfor %} diff --git a/tests/template/templates/loop_nested_multilevel_ref_twig.html b/tests/template/templates/loop_nested_multilevel_ref_twig.html new file mode 100644 index 0000000000..336a57d0bc --- /dev/null +++ b/tests/template/templates/loop_nested_multilevel_ref_twig.html @@ -0,0 +1,10 @@ +top-level content +{% for outer_inner in outer %} + outer {{ outer_inner.VARIABLE }} + {% for inner in outer_inner.inner %} + inner {{ inner.VARIABLE }} + {% if inner.S_FIRST_ROW %} + first row + {% endif %} + {% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_nested_twig.html b/tests/template/templates/loop_nested_twig.html new file mode 100644 index 0000000000..b294226b3a --- /dev/null +++ b/tests/template/templates/loop_nested_twig.html @@ -0,0 +1,6 @@ +{% for outer_inner in outer %} +outer - {{ outer_inner.S_ROW_COUNT }}{% if outer_inner.VARIABLE %} - {{ outer_inner.VARIABLE }}{% endif %}{% if TEST_MORE %}[{{ outer_inner.S_BLOCK_NAME }}|{{ outer_inner.S_NUM_ROWS }}]{% endif %} +{% for middle in outer_inner.middle %} +middle - {{ middle.S_ROW_COUNT }}{% if middle.VARIABLE %} - {{ middle.VARIABLE }}{% endif %}{% if TEST_MORE %}[{{ middle.S_BLOCK_NAME }}|{{ middle.S_NUM_ROWS }}]{% endif %} +{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_reuse_twig.html b/tests/template/templates/loop_reuse_twig.html new file mode 100644 index 0000000000..67452a737f --- /dev/null +++ b/tests/template/templates/loop_reuse_twig.html @@ -0,0 +1,6 @@ +{% for one_inner in one %} + {{ one_inner.VAR }} + {% for one_one_inner in one_inner.one %} + {{ one_one_inner.VAR }} + {% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_size_twig.html b/tests/template/templates/loop_size_twig.html new file mode 100644 index 0000000000..f6d2571e11 --- /dev/null +++ b/tests/template/templates/loop_size_twig.html @@ -0,0 +1,39 @@ +{% if nonexistent_loop|length %} +nonexistent +{% endif %} + +{% if nonexistent_loop|length == 0 %} +nonexistent = 0 +{% endif %} + +{% if ! nonexistent_loop|length %} +! nonexistent +{% endif %} + +{% if empty_loop|length %} +empty +{% endif %} + +{% if empty_loop|length == 0 %} +empty = 0 +{% endif %} + +{% if ! empty_loop|length %} +! empty +{% endif %} + +{% if test_loop|length %} +loop +{% endif %} + +{% if test_loop|length == 0 %} +loop = 0 +{% endif %} + +{% if ! test_loop|length %} +! loop +{% endif %} + +{% for test_loop_inner in test_loop %} +in loop +{% endfor %} diff --git a/tests/template/templates/loop_twig.html b/tests/template/templates/loop_twig.html new file mode 100644 index 0000000000..fb24f331b3 --- /dev/null +++ b/tests/template/templates/loop_twig.html @@ -0,0 +1,21 @@ +{% for test_loop_inner in test_loop %} +loop +{% else %} +noloop +{% endfor %} + +{% if test_loop|length %} +loop +{% else %} +noloop +{% endif %} + +{% if test_loop|length == 2 %} +loop +{% endif %} + +{% for test_loop_inner in test_loop %} +{% for block_inner in block %} +loop#{{ test_loop_inner.S_ROW_COUNT }}-block#{{ block_inner.S_ROW_COUNT }} +{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_underscore_twig.html b/tests/template/templates/loop_underscore_twig.html new file mode 100644 index 0000000000..44b095c882 --- /dev/null +++ b/tests/template/templates/loop_underscore_twig.html @@ -0,0 +1,21 @@ +{% for _underscore_loop_inner in _underscore_loop %} +loop +{% else %} +noloop +{% endfor %} + +{% if _underscore_loop|length %} +loop +{% else %} +noloop +{% endif %} + +{% if _underscore_loop|length == 2 %} +loop +{% endif %} + +{% for _underscore_loop_inner in _underscore_loop %} +{% for block_inner in block %} +loop#{{ loop.S_ROW_COUNT }}-block#{{ block_inner.S_ROW_COUNT }} +{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_vars_twig.html b/tests/template/templates/loop_vars_twig.html new file mode 100644 index 0000000000..af6c63d8e3 --- /dev/null +++ b/tests/template/templates/loop_vars_twig.html @@ -0,0 +1,13 @@ +{% for test_loop_inner in test_loop %} +{% if test_loop_inner.S_FIRST_ROW %}first{% endif %} +{{ test_loop_inner.S_ROW_NUM }} - a +{{ test_loop_inner.VARIABLE }} - b +{% if test_loop_inner.VARIABLE %}set{% endif %} +{% if test_loop_inner.S_LAST_ROW %} +last +{% endif %} +{% for inner_inner in test_loop_inner.inner %} +{{ inner_inner.S_ROW_NUM }} - c +{% if inner_inner.S_LAST_ROW and inner_inner.S_ROW_COUNT and inner_inner.S_NUM_ROWS %}last inner{% endif %} +{% endfor %} +{% endfor %} From 54753e926df28b686937394bc675130647893639 Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Thu, 5 Mar 2015 21:53:48 +0100 Subject: [PATCH 0121/1676] [ticket/13132] Enable twig expressions tests PHPBB3-13132 --- tests/template/template_test.php | 18 ++++++++++++------ tests/template/templates/loop_expressions.html | 4 ++-- .../templates/loop_expressions_twig.html | 4 ++-- .../templates/loop_expressions_twig2.html | 11 +++++++++++ 4 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 tests/template/templates/loop_expressions_twig2.html diff --git a/tests/template/template_test.php b/tests/template/template_test.php index b67b49bd35..33dc4ca551 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -491,21 +491,27 @@ class phpbb_template_template_test extends phpbb_template_template_test_case array(), 'inner_value', ), - // Disable: needs Twig 1.14.2 - /*array( + array( 'loop_expressions.html', + array(), array('loop' => array(array(),array(),array(),array(),array(),array()),), array(), - array(), - 'yesnonoyesnonoyesnoyesnonoyes', + 'yesnononoyesnoyesnonoyesnono', ), array( 'loop_expressions_twig.html', + array(), + array('loop' => array(array(),array(),array(),array(),array(),array()),), + array(), + 'yesnononoyesnoyesnonoyesnono', + ), + array( + 'loop_expressions_twig2.html', array('loop' => array(array(),array(),array(),array(),array(),array()),), array(), array(), - 'yesnonoyesnonoyesnoyesnonoyes', - ),*/ + 'yesnononoyesnoyesnonoyesnono', + ), ); } diff --git a/tests/template/templates/loop_expressions.html b/tests/template/templates/loop_expressions.html index 278bce1eca..ddb9fd52fa 100644 --- a/tests/template/templates/loop_expressions.html +++ b/tests/template/templates/loop_expressions.html @@ -1,11 +1,11 @@ -onoff +yesno -onoff +yesno diff --git a/tests/template/templates/loop_expressions_twig.html b/tests/template/templates/loop_expressions_twig.html index 61a36c51e4..5ca8cc3601 100644 --- a/tests/template/templates/loop_expressions_twig.html +++ b/tests/template/templates/loop_expressions_twig.html @@ -1,11 +1,11 @@ {% for loop_inner in loop %} -{% if loop_inner.S_ROW_NUM is divisible by 4 %}on{% else %}off{% endif %} +{% if loop_inner.S_ROW_NUM is divisible by(4) %}yes{% else %}no{% endif %} {% endfor %} {% for loop_inner in loop %} -{% if loop_inner.S_ROW_NUM is divisible by 3 %}on{% else %}off{% endif %} +{% if loop_inner.S_ROW_NUM is divisible by(3) %}yes{% else %}no{% endif %} {% endfor %} diff --git a/tests/template/templates/loop_expressions_twig2.html b/tests/template/templates/loop_expressions_twig2.html new file mode 100644 index 0000000000..16159ead4c --- /dev/null +++ b/tests/template/templates/loop_expressions_twig2.html @@ -0,0 +1,11 @@ +{% for loop_inner in loop %} + +{% if loop.index0 is divisible by(4) %}yes{% else %}no{% endif %} + +{% endfor %} + +{% for loop_inner in loop %} + +{% if loop.index0 is divisible by(3) %}yes{% else %}no{% endif %} + +{% endfor %} From 5c77e4381945300ba9a1086b99fac12ae48c52a8 Mon Sep 17 00:00:00 2001 From: brunoais Date: Tue, 24 Feb 2015 23:03:11 +0000 Subject: [PATCH 0122/1676] [feature/sql-bool-builder] First working version PHPBB3-13652 --- phpBB/phpbb/db/driver/driver.php | 92 ++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 8d360fc3e2..5822adceab 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -792,6 +792,98 @@ abstract class driver implements driver_interface return $sql; } + + + protected function _process_boolean_tree_first($operations_ary) + { + if ($operations_ary[0] !== 'AND' && + $operations_ary[0] !== 'OR') + { + $operations_ary = array('AND', $operations_ary); + } + return $this->_process_boolean_tree($operations_ary) . "\n"; + } + + protected function _process_boolean_tree($operations_ary) + { + $operation = array_shift($operations_ary); + + foreach ($operations_ary AS &$condition) + { + switch ($condition[0]) + { + case 'AND': + case 'OR': + + $condition = ' ( ' . $this->_process_boolean_tree($condition) . ') '; + + break; + case 'NOT': + + $condition = ' NOT ' . $this->_process_boolean_tree($condition); + + break; + + default: + + switch (sizeof($condition)) + { + case 3: + + // Typical 3 element clause with {left hand} {operator} {right hand} + switch ($condition[1]) + { + case 'IN': + case 'NOT_IN': + + // As this is used with an IN, assume it is a set of elements for sql_in_set() + $condition = $this->sql_in_set($condition[0], $condition[2], $condition[1] === 'NOT_IN', true); + + break; + + default: + + $condition = implode(' ', $condition); + + break; + } + + break; + + case 5: + + // Subquery with {left hand} {operator} {compare kind} {SELECT Kind } {Sub Query} + + $condition = $condition[0] . ' ' . $condition[1] . ' ' . $condition[2] . ' ( '; + $condition .= $this->sql_build_query($condition[3], $condition[4]); + $condition .= ' )'; + + break; + + default: + // This is an unpredicted clause setup. Just join all elements. + $condition = implode(' ', $condition); + + break; + } + + break; + } + + } + + if($operation === 'NOT') + { + $operations_ary = implode("", $operations_ary); + } + else + { + $operations_ary = implode(" \n $operation ", $operations_ary); + } + + return $operations_ary; + } + /** * {@inheritDoc} From b54adaaabed7546254ff8317763214cce3a40237 Mon Sep 17 00:00:00 2001 From: brunoais Date: Wed, 25 Feb 2015 07:54:31 +0000 Subject: [PATCH 0123/1676] [feature/sql-bool-builder] Removed non-necessary spaces PHPBB3-13652 --- phpBB/phpbb/db/driver/driver.php | 58 ++++++++++++++++---------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 5822adceab..cdff6bf9de 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -792,11 +792,11 @@ abstract class driver implements driver_interface return $sql; } - - + + protected function _process_boolean_tree_first($operations_ary) { - if ($operations_ary[0] !== 'AND' && + if ($operations_ary[0] !== 'AND' && $operations_ary[0] !== 'OR') { $operations_ary = array('AND', $operations_ary); @@ -807,71 +807,71 @@ abstract class driver implements driver_interface protected function _process_boolean_tree($operations_ary) { $operation = array_shift($operations_ary); - + foreach ($operations_ary AS &$condition) { switch ($condition[0]) { case 'AND': case 'OR': - + $condition = ' ( ' . $this->_process_boolean_tree($condition) . ') '; - + break; case 'NOT': - + $condition = ' NOT ' . $this->_process_boolean_tree($condition); - + break; - + default: - + switch (sizeof($condition)) { case 3: - + // Typical 3 element clause with {left hand} {operator} {right hand} switch ($condition[1]) - { + { case 'IN': case 'NOT_IN': - + // As this is used with an IN, assume it is a set of elements for sql_in_set() $condition = $this->sql_in_set($condition[0], $condition[2], $condition[1] === 'NOT_IN', true); - + break; - + default: - + $condition = implode(' ', $condition); - + break; } - + break; - + case 5: - + // Subquery with {left hand} {operator} {compare kind} {SELECT Kind } {Sub Query} - + $condition = $condition[0] . ' ' . $condition[1] . ' ' . $condition[2] . ' ( '; $condition .= $this->sql_build_query($condition[3], $condition[4]); $condition .= ' )'; - + break; - + default: // This is an unpredicted clause setup. Just join all elements. $condition = implode(' ', $condition); - + break; } - + break; } - + } - + if($operation === 'NOT') { $operations_ary = implode("", $operations_ary); @@ -880,10 +880,10 @@ abstract class driver implements driver_interface { $operations_ary = implode(" \n $operation ", $operations_ary); } - + return $operations_ary; } - + /** * {@inheritDoc} From 46de94690453e0bd6dfc589682b7c4ede34f1d59 Mon Sep 17 00:00:00 2001 From: brunoais Date: Wed, 25 Feb 2015 07:55:24 +0000 Subject: [PATCH 0124/1676] [feature/sql-bool-builder] Added code to use this feature for the WHERE clause PHPBB3-13652 --- phpBB/phpbb/db/driver/driver.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index cdff6bf9de..0fbbe5ae7c 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -774,7 +774,18 @@ abstract class driver implements driver_interface if (!empty($array['WHERE'])) { - $sql .= ' WHERE ' . $this->_sql_custom_build('WHERE', $array['WHERE']); + $sql .= ' WHERE '; + + if (is_array($array['WHERE'])) + { + $sql_where = $this->_process_boolean_tree_first($array['WHERE']); + } + else + { + $sql_where = $array['WHERE']; + } + + $sql .= $this->_sql_custom_build('WHERE', $sql_where); } if (!empty($array['GROUP_BY'])) From 5c1850e10e0e31e4f72cc16c657e37bb009659df Mon Sep 17 00:00:00 2001 From: brunoais Date: Wed, 25 Feb 2015 09:09:48 +0000 Subject: [PATCH 0125/1676] [feature/sql-bool-builder] AS keyword must be lowercase; AS keyword must be lowercase; expected "as" but found "AS" PHPBB3-13652 --- phpBB/phpbb/db/driver/driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 0fbbe5ae7c..f66f10322b 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -819,7 +819,7 @@ abstract class driver implements driver_interface { $operation = array_shift($operations_ary); - foreach ($operations_ary AS &$condition) + foreach ($operations_ary as &$condition) { switch ($condition[0]) { From 51737be6162584209b483f97daa87ce9d3c039b0 Mon Sep 17 00:00:00 2001 From: brunoais Date: Sat, 28 Feb 2015 18:14:00 +0000 Subject: [PATCH 0126/1676] [feature/sql-bool-builder] Also use parenthesis for the NOT operator Be on the safe side, also use parenthesis for the NOT operator PHPBB3-13652 --- phpBB/phpbb/db/driver/driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index f66f10322b..d2bb5f4f7c 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -831,7 +831,7 @@ abstract class driver implements driver_interface break; case 'NOT': - $condition = ' NOT ' . $this->_process_boolean_tree($condition); + $condition = ' NOT (' . $this->_process_boolean_tree($condition) . ') '; break; From 5d70f612be113336d6a85146369232c87d1b069b Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 1 Mar 2015 11:39:20 +0000 Subject: [PATCH 0127/1676] [feature/sql-bool-builder] Explain better the code in the first Explain what that if and check is for in the first method that is called. PHPBB3-13652 --- phpBB/phpbb/db/driver/driver.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index d2bb5f4f7c..cda2f7f86d 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -807,6 +807,8 @@ abstract class driver implements driver_interface protected function _process_boolean_tree_first($operations_ary) { + // In cases where an array exists but there is no head condition, + // it should be because there's only 1 WHERE clause. This seems the best way to deal with it. if ($operations_ary[0] !== 'AND' && $operations_ary[0] !== 'OR') { From 298d86009ed77a4b75792a6237f987be271ac43c Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 11:40:02 +0000 Subject: [PATCH 0128/1676] [feature/sql-bool-builder] Added LIKE and NOT_LIKE to the comparations PHPBB3-13652 --- phpBB/phpbb/db/driver/driver.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index cda2f7f86d..ce69ef6a52 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -854,6 +854,18 @@ abstract class driver implements driver_interface break; + case 'LIKE': + + $condition = $condition[0] . ' ' . $this->sql_like_expression($condition[2]) . ' '; + + break; + + case 'NOT_LIKE': + + $condition = $condition[0] . ' ' . $this->sql_not_like_expression($condition[2]) . ' '; + + break; + default: $condition = implode(' ', $condition); From 5bc03c961023e01dfb74eff296b12b6169d705e4 Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 17:16:53 +0000 Subject: [PATCH 0129/1676] [feature/sql-bool-builder] Prepare testing class PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 24 +++++++ tests/dbal/fixtures/boolean_processor.xml | 84 +++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 tests/dbal/boolean_processor_test.php create mode 100644 tests/dbal/fixtures/boolean_processor.xml diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php new file mode 100644 index 0000000000..f80e12ad4f --- /dev/null +++ b/tests/dbal/boolean_processor_test.php @@ -0,0 +1,24 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; + +class phpbb_boolean_processor_test extends phpbb_database_test_case +{ + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); + } + +} diff --git a/tests/dbal/fixtures/boolean_processor.xml b/tests/dbal/fixtures/boolean_processor.xml new file mode 100644 index 0000000000..c5da677116 --- /dev/null +++ b/tests/dbal/fixtures/boolean_processor.xml @@ -0,0 +1,84 @@ + + + + ban_id + ban_userid + + 1 + 2 + +
    + + user_id + username + username_clean + user_permissions + user_sig + + 1 + mass email + mass email + + + + + 2 + banned + banned + + + + + 3 + helper + helper + + + + + 4 + GroupBPal + groupbpal + + + + + 5 + GroupBPal2 + groupBPal2 + + + + + 6 + not in group + not in group + + + +
    + + user_id + group_id + + 1 + 1 + + + 2 + 1 + + + 3 + 1 + + + 4 + 2 + + + 5 + 2 + +
    +
    From d10a0ca1ca48d8d348922a806f14f63360179d50 Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 20:25:55 +0000 Subject: [PATCH 0130/1676] [feature/sql-bool-builder] test_triple_and_with_is_null PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index f80e12ad4f..652cb1164b 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -21,4 +21,41 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); } + public function test_triple_and_with_is_null() + { + $db = $this->new_dbal(); + + $db->sql_return_on_error(true); + + $sql_ary = array( + 'SELECT' => 'u.username', + 'FROM' => array( + 'phpbb_users' => 'u', + 'phpbb_user_group' => 'ug', + ), + 'LEFT_JOIN' => array( + array( + 'FROM' => array( + 'phpbb_banlist' => 'b', + ), + 'ON' => 'u.user_id = b.ban_userid', + ), + ), + 'WHERE' => array('AND', + array('ug.group_id', '=', 1), + array('u.user_id', '=', 'ug.user_id'), + array('b.ban_id', 'IS', NULL), + ), + 'ORDER_BY' => 'u.username', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); + $result = $db->sql_query($sql); + + $db->sql_return_on_error(false); + + $this->assertEquals(array( + array('username' => 'helper'), + array('username' => 'mass email'), + ), $db->sql_fetchrowset($result)); + } } From 5d3b22c21e2c31dce80d3a4c84fd5a0a326f944f Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 20:26:24 +0000 Subject: [PATCH 0131/1676] [feature/sql-bool-builder] test_double_and_with_not_of_and PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index 652cb1164b..40efbe8d5a 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -21,6 +21,37 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); } + public function test_double_and_with_not_of_or() + { + $db = $this->new_dbal(); + + $db->sql_return_on_error(true); + + $sql_ary = array( + 'SELECT' => 'u.user_id', + 'FROM' => array( + 'phpbb_users' => 'u', + 'phpbb_user_group' => 'ug', + ), + 'WHERE' => array('AND', + array('NOT', + array('OR', + array('ug.group_id', '=', 1), + array('ug.group_id', '=', 2), + ), + ), + array('u.user_id', '=', 'ug.user_id'), + ), + 'ORDER_BY' => 'u.user_id', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); + $result = $db->sql_query($sql); + + $db->sql_return_on_error(false); + + $this->assertEquals(array(), $db->sql_fetchrowset($result)); + } + public function test_triple_and_with_is_null() { $db = $this->new_dbal(); From e6eab35a641b8795f8a277e28d3eab0937d64b6d Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 20:29:48 +0000 Subject: [PATCH 0132/1676] [feature/sql-bool-builder] test_triple_and_with_in PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index 40efbe8d5a..081a5ac64d 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -21,6 +21,37 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); } + public function test_triple_and_with_in() + { + $db = $this->new_dbal(); + + $db->sql_return_on_error(true); + + $sql_ary = array( + 'SELECT' => 'u.user_id', + 'FROM' => array( + 'phpbb_users' => 'u', + 'phpbb_user_group' => 'ug', + ), + 'WHERE' => array('AND', + array('ug.user_id', 'IN', array(1, 2, 3, 4)), + array('ug.group_id', '=', 1), + array('u.user_id', '=', 'ug.user_id'), + ), + 'ORDER_BY' => 'u.user_id', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); + $result = $db->sql_query($sql); + + $db->sql_return_on_error(false); + + $this->assertEquals(array( + array('user_id' => '1'), + array('user_id' => '2'), + array('user_id' => '3'), + ), $db->sql_fetchrowset($result), + } + public function test_double_and_with_not_of_or() { $db = $this->new_dbal(); From 5f63d685f6b0235badd7723e477754833595d045 Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 20:30:04 +0000 Subject: [PATCH 0133/1676] [feature/sql-bool-builder] test_and_of_or_of_and PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index 081a5ac64d..716e524e9b 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -21,6 +21,52 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); } + public function test_and_of_or_of_and() + { + $db = $this->new_dbal(); + + $db->sql_return_on_error(true); + + $sql_ary = array( + 'SELECT' => 'u.user_id', + 'FROM' => array( + 'phpbb_users' => 'u', + 'phpbb_user_group' => 'ug', + ), + 'LEFT_JOIN' => array( + array( + 'FROM' => array( + 'phpbb_banlist' => 'b', + ), + 'ON' => 'u.user_id = b.ban_userid', + ), + ), + 'WHERE' => array('AND', + array('OR', + array('AND', + array('ug.user_id', 'IN', array(1, 2, 3, 4)), + array('ug.group_id', '=', 2), + ), + array('AND', + array('ug.group_id', '=', 1), + array('b.ban_id', 'IS NOT', NULL), + ), + ), + array('u.user_id', '=', 'ug.user_id'), + ), + 'ORDER_BY' => 'u.user_id', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); + $result = $db->sql_query($sql); + + $db->sql_return_on_error(false); + + $this->assertEquals(array( + array('user_id' => '2'), + array('user_id' => '4'), + ), $db->sql_fetchrowset($result)); + } + public function test_triple_and_with_in() { $db = $this->new_dbal(); From 1754f1832d563074e767f236cbc315eb41c7b7b9 Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 20:30:35 +0000 Subject: [PATCH 0134/1676] [feature/sql-bool-builder] test_single_in PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index 716e524e9b..e615edbdcd 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -21,6 +21,32 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); } + public function test_single_in() + { + $db = $this->new_dbal(); + + $db->sql_return_on_error(true); + + $sql_ary = array( + 'SELECT' => 'u.user_id', + 'FROM' => array( + 'phpbb_users' => 'u', + ), + 'WHERE' => array('u.user_id', 'IN', array(3,4,5)), + 'ORDER_BY' => 'u.user_id', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); + $result = $db->sql_query($sql); + + $db->sql_return_on_error(false); + + $this->assertEquals(array( + array('user_id' => '3'), + array('user_id' => '4'), + array('user_id' => '5'), + ), $db->sql_fetchrowset($result)); + } + public function test_and_of_or_of_and() { $db = $this->new_dbal(); From d60d596f25b0c31526f469cf56c4cdb1e3698bda Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 20:31:19 +0000 Subject: [PATCH 0135/1676] [feature/sql-bool-builder] test_single_not_in PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index e615edbdcd..a94085b77d 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -21,6 +21,32 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); } + public function test_single_not_in() + { + $db = $this->new_dbal(); + + $db->sql_return_on_error(true); + + $sql_ary = array( + 'SELECT' => 'u.user_id', + 'FROM' => array( + 'phpbb_users' => 'u', + ), + 'WHERE' => array('u.user_id', 'NOT_IN', array(3,4,5)), + 'ORDER_BY' => 'u.user_id', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); + $result = $db->sql_query($sql); + + $db->sql_return_on_error(false); + + $this->assertEquals(array( + array('user_id' => '1'), + array('user_id' => '2'), + array('user_id' => '6'), + ), $db->sql_fetchrowset($result)); + } + public function test_single_in() { $db = $this->new_dbal(); From c342531872938797f52f3e6bdfa966d81e3253ce Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 20:31:32 +0000 Subject: [PATCH 0136/1676] [feature/sql-bool-builder] test_single_like PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index a94085b77d..8f57a8e452 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -21,6 +21,31 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); } + public function test_single_like() + { + $db = $this->new_dbal(); + + $db->sql_return_on_error(true); + + $sql_ary = array( + 'SELECT' => 'u.user_id', + 'FROM' => array( + 'phpbb_users' => 'u', + ), + 'WHERE' => array('u.username_clean', 'LIKE', 'gr' . $db->get_any_char()), + 'ORDER_BY' => 'u.user_id', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); + $result = $db->sql_query($sql); + + $db->sql_return_on_error(false); + + $this->assertEquals(array( + array('user_id' => '4'), + array('user_id' => '5'), + ), $db->sql_fetchrowset($result)); + } + public function test_single_not_in() { $db = $this->new_dbal(); From bc6ea5796dcdabd57ff9e6f7640d724df67254c5 Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 20:31:46 +0000 Subject: [PATCH 0137/1676] [feature/sql-bool-builder] test_single_not_like PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index 8f57a8e452..2ba3f6ff22 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -21,6 +21,33 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); } + public function test_single_not_like() + { + $db = $this->new_dbal(); + + $db->sql_return_on_error(true); + + $sql_ary = array( + 'SELECT' => 'u.user_id', + 'FROM' => array( + 'phpbb_users' => 'u', + ), + 'WHERE' => array('u.username_clean', 'NOT_LIKE', 'gr' . $db->get_any_char()), + 'ORDER_BY' => 'u.user_id', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); + $result = $db->sql_query($sql); + + $db->sql_return_on_error(false); + + $this->assertEquals(array( + array('user_id' => '1'), + array('user_id' => '2'), + array('user_id' => '3'), + array('user_id' => '6'), + ), $db->sql_fetchrowset($result)); + } + public function test_single_like() { $db = $this->new_dbal(); From 576eaa0cff7a5e051aa672034e596e90f65fc1a9 Mon Sep 17 00:00:00 2001 From: brunoais Date: Mon, 16 Mar 2015 11:31:51 +0000 Subject: [PATCH 0138/1676] [feature/sql-bool-builder] Adding the IS operator to predicted operators PHPBB3-13652 --- phpBB/phpbb/db/driver/driver.php | 18 ++++++++++++++++++ tests/dbal/boolean_processor_test.php | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index ce69ef6a52..4d78c84c8a 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -866,6 +866,24 @@ abstract class driver implements driver_interface break; + case 'IS_NOT': + + $condition[1] = 'IS NOT'; + + // no break + case 'IS': + + // If the value is NULL, the string of it is the empty string ('') which is not the intended result. + // this should solve that + if ($condition[2] === null) + { + $condition[2] = 'NULL'; + } + + $condition = implode(' ', $condition); + + break; + default: $condition = implode(' ', $condition); diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index 2ba3f6ff22..5e044797f8 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -153,7 +153,7 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case ), array('AND', array('ug.group_id', '=', 1), - array('b.ban_id', 'IS NOT', NULL), + array('b.ban_id', 'IS_NOT', NULL), ), ), array('u.user_id', '=', 'ug.user_id'), From fe132f19e8d5c821fff936d208fbb981aa6ac92d Mon Sep 17 00:00:00 2001 From: brunoais Date: Sun, 15 Mar 2015 21:01:00 +0000 Subject: [PATCH 0139/1676] [feature/sql-bool-builder] Improved tests output to show the SQL error. PHPBB3-13652 --- tests/dbal/boolean_processor_test.php | 47 +++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php index 5e044797f8..8662485ac8 100644 --- a/tests/dbal/boolean_processor_test.php +++ b/tests/dbal/boolean_processor_test.php @@ -45,7 +45,11 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case array('user_id' => '2'), array('user_id' => '3'), array('user_id' => '6'), - ), $db->sql_fetchrowset($result)); + ), $db->sql_fetchrowset($result), + ($result === false) ? + "SQL ERROR:
    " . var_export($sql, true) . "
    " . $db->sql_error() : + var_export($sql, true) . ' ' . var_export($result, true) + ); } public function test_single_like() @@ -70,7 +74,11 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case $this->assertEquals(array( array('user_id' => '4'), array('user_id' => '5'), - ), $db->sql_fetchrowset($result)); + ), $db->sql_fetchrowset($result), + ($result === false) ? + "SQL ERROR:
    " . var_export($sql, true) . "
    " . $db->sql_error() : + var_export($sql, true) . ' ' . var_export($result, true) + ); } public function test_single_not_in() @@ -96,7 +104,11 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case array('user_id' => '1'), array('user_id' => '2'), array('user_id' => '6'), - ), $db->sql_fetchrowset($result)); + ), $db->sql_fetchrowset($result), + ($result === false) ? + "SQL ERROR:
    " . var_export($sql, true) . "
    " . $db->sql_error() : + var_export($sql, true) . ' ' . var_export($result, true) + ); } public function test_single_in() @@ -122,7 +134,11 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case array('user_id' => '3'), array('user_id' => '4'), array('user_id' => '5'), - ), $db->sql_fetchrowset($result)); + ), $db->sql_fetchrowset($result), + ($result === false) ? + "SQL ERROR:
    " . var_export($sql, true) . "
    " . $db->sql_error() : + var_export($sql, true) . ' ' . var_export($result, true) + ); } public function test_and_of_or_of_and() @@ -168,7 +184,11 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case $this->assertEquals(array( array('user_id' => '2'), array('user_id' => '4'), - ), $db->sql_fetchrowset($result)); + ), $db->sql_fetchrowset($result), + ($result === false) ? + "SQL ERROR:
    " . var_export($sql, true) . "
    " . $db->sql_error() : + var_export($sql, true) . ' ' . var_export($result, true) + ); } public function test_triple_and_with_in() @@ -200,6 +220,11 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case array('user_id' => '2'), array('user_id' => '3'), ), $db->sql_fetchrowset($result), + ($result === false) ? + "SQL ERROR:
    " . var_export($sql, true) . "
    " . $db->sql_error() : + var_export($sql, true) . ' ' . var_export($result, true) + ); + } public function test_double_and_with_not_of_or() @@ -230,7 +255,11 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case $db->sql_return_on_error(false); - $this->assertEquals(array(), $db->sql_fetchrowset($result)); + $this->assertEquals(array(), $db->sql_fetchrowset($result), + ($result === false) ? + "SQL ERROR:
    " . var_export($sql, true) . "
    " . $db->sql_error() : + var_export($sql, true) . ' ' . var_export($result, true) + ); } public function test_triple_and_with_is_null() @@ -268,6 +297,10 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case $this->assertEquals(array( array('username' => 'helper'), array('username' => 'mass email'), - ), $db->sql_fetchrowset($result)); + ), $db->sql_fetchrowset($result), + ($result === false) ? + "SQL ERROR:
    " . var_export($sql, true) . "
    " . $db->sql_error() : + var_export($sql, true) . ' ' . var_export($result, true) + ); } } From fd230cd9c59ee90828f48abb6681c96ef3fb8277 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 23 Mar 2015 01:51:04 +0100 Subject: [PATCH 0140/1676] [ticket/13718] Added missing global declaration PHPBB3-13718 --- phpBB/phpbb/captcha/plugins/captcha_abstract.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/captcha/plugins/captcha_abstract.php b/phpBB/phpbb/captcha/plugins/captcha_abstract.php index 2c0b95411e..799947a84e 100644 --- a/phpBB/phpbb/captcha/plugins/captcha_abstract.php +++ b/phpBB/phpbb/captcha/plugins/captcha_abstract.php @@ -117,7 +117,7 @@ abstract class captcha_abstract function get_demo_template($id) { - global $config, $user, $template, $phpbb_admin_path, $phpEx; + global $config, $user, $template, $request, $phpbb_admin_path, $phpEx; $variables = ''; From dbb538afbdce345dfc61b06ec6a84313c1141284 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Fri, 27 Mar 2015 00:02:20 -0700 Subject: [PATCH 0141/1676] [ticket/13725] Coding guidelines: static public PHPBB3-13725 --- phpBB/phpbb/db/tools/tools.php | 2 +- phpBB/phpbb/event/kernel_exception_subscriber.php | 2 +- phpBB/phpbb/event/kernel_terminate_subscriber.php | 2 +- phpBB/phpbb/notification/type/admin_activate_user.php | 6 +++--- phpBB/phpbb/notification/type/approve_post.php | 2 +- phpBB/phpbb/notification/type/approve_topic.php | 2 +- phpBB/phpbb/notification/type/base.php | 2 +- phpBB/phpbb/notification/type/bookmark.php | 2 +- phpBB/phpbb/notification/type/disapprove_post.php | 2 +- phpBB/phpbb/notification/type/disapprove_topic.php | 2 +- phpBB/phpbb/notification/type/group_request.php | 6 +++--- phpBB/phpbb/notification/type/group_request_approved.php | 4 ++-- phpBB/phpbb/notification/type/pm.php | 6 +++--- phpBB/phpbb/notification/type/post.php | 6 +++--- phpBB/phpbb/notification/type/post_in_queue.php | 2 +- phpBB/phpbb/notification/type/quote.php | 2 +- phpBB/phpbb/notification/type/report_pm.php | 4 ++-- phpBB/phpbb/notification/type/report_post.php | 2 +- phpBB/phpbb/notification/type/topic.php | 6 +++--- phpBB/phpbb/notification/type/topic_in_queue.php | 2 +- phpBB/phpbb/notification/type/type_interface.php | 4 ++-- 21 files changed, 34 insertions(+), 34 deletions(-) diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php index 0d1eb63c47..1d7b2ddfff 100644 --- a/phpBB/phpbb/db/tools/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -40,7 +40,7 @@ class tools implements tools_interface * * @return array */ - public static function get_dbms_type_map() + static public function get_dbms_type_map() { return array( 'mysql_41' => array( diff --git a/phpBB/phpbb/event/kernel_exception_subscriber.php b/phpBB/phpbb/event/kernel_exception_subscriber.php index eb7831ad34..0a8a0183dc 100644 --- a/phpBB/phpbb/event/kernel_exception_subscriber.php +++ b/phpBB/phpbb/event/kernel_exception_subscriber.php @@ -106,7 +106,7 @@ class kernel_exception_subscriber implements EventSubscriberInterface $event->setResponse($response); } - public static function getSubscribedEvents() + static public function getSubscribedEvents() { return array( KernelEvents::EXCEPTION => 'on_kernel_exception', diff --git a/phpBB/phpbb/event/kernel_terminate_subscriber.php b/phpBB/phpbb/event/kernel_terminate_subscriber.php index 3a709f73fd..f0d0a2f595 100644 --- a/phpBB/phpbb/event/kernel_terminate_subscriber.php +++ b/phpBB/phpbb/event/kernel_terminate_subscriber.php @@ -32,7 +32,7 @@ class kernel_terminate_subscriber implements EventSubscriberInterface exit_handler(); } - public static function getSubscribedEvents() + static public function getSubscribedEvents() { return array( KernelEvents::TERMINATE => array('on_kernel_terminate', ~PHP_INT_MAX), diff --git a/phpBB/phpbb/notification/type/admin_activate_user.php b/phpBB/phpbb/notification/type/admin_activate_user.php index dfc0157558..73ed612480 100644 --- a/phpBB/phpbb/notification/type/admin_activate_user.php +++ b/phpBB/phpbb/notification/type/admin_activate_user.php @@ -36,7 +36,7 @@ class admin_activate_user extends \phpbb\notification\type\base /** * {@inheritdoc} */ - public static $notification_option = array( + static public $notification_option = array( 'lang' => 'NOTIFICATION_TYPE_ADMIN_ACTIVATE_USER', 'group' => 'NOTIFICATION_GROUP_ADMINISTRATION', ); @@ -52,7 +52,7 @@ class admin_activate_user extends \phpbb\notification\type\base /** * {@inheritdoc} */ - public static function get_item_id($user) + static public function get_item_id($user) { return (int) $user['user_id']; } @@ -60,7 +60,7 @@ class admin_activate_user extends \phpbb\notification\type\base /** * {@inheritdoc} */ - public static function get_item_parent_id($post) + static public function get_item_parent_id($post) { return 0; } diff --git a/phpBB/phpbb/notification/type/approve_post.php b/phpBB/phpbb/notification/type/approve_post.php index a9e635b41a..e6c38b2ede 100644 --- a/phpBB/phpbb/notification/type/approve_post.php +++ b/phpBB/phpbb/notification/type/approve_post.php @@ -50,7 +50,7 @@ class approve_post extends \phpbb\notification\type\post * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'id' => 'moderation_queue', 'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE', 'group' => 'NOTIFICATION_GROUP_POSTING', diff --git a/phpBB/phpbb/notification/type/approve_topic.php b/phpBB/phpbb/notification/type/approve_topic.php index 2f4678359c..5f5b96f335 100644 --- a/phpBB/phpbb/notification/type/approve_topic.php +++ b/phpBB/phpbb/notification/type/approve_topic.php @@ -50,7 +50,7 @@ class approve_topic extends \phpbb\notification\type\topic * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'id' => 'moderation_queue', 'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE', 'group' => 'NOTIFICATION_GROUP_POSTING', diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php index 4ead06071e..1cf0498138 100644 --- a/phpBB/phpbb/notification/type/base.php +++ b/phpBB/phpbb/notification/type/base.php @@ -63,7 +63,7 @@ abstract class base implements \phpbb\notification\type\type_interface * @var bool|array False if the service should use its default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = false; + static public $notification_option = false; /** * The notification_type_id, set upon creation of the class diff --git a/phpBB/phpbb/notification/type/bookmark.php b/phpBB/phpbb/notification/type/bookmark.php index 4f2d34cb60..e6a695e875 100644 --- a/phpBB/phpbb/notification/type/bookmark.php +++ b/phpBB/phpbb/notification/type/bookmark.php @@ -43,7 +43,7 @@ class bookmark extends \phpbb\notification\type\post * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'lang' => 'NOTIFICATION_TYPE_BOOKMARK', 'group' => 'NOTIFICATION_GROUP_POSTING', ); diff --git a/phpBB/phpbb/notification/type/disapprove_post.php b/phpBB/phpbb/notification/type/disapprove_post.php index 6c7bcbcaee..7021cdc837 100644 --- a/phpBB/phpbb/notification/type/disapprove_post.php +++ b/phpBB/phpbb/notification/type/disapprove_post.php @@ -60,7 +60,7 @@ class disapprove_post extends \phpbb\notification\type\approve_post * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'id' => 'moderation_queue', 'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE', 'group' => 'NOTIFICATION_GROUP_POSTING', diff --git a/phpBB/phpbb/notification/type/disapprove_topic.php b/phpBB/phpbb/notification/type/disapprove_topic.php index efa5eb7ecd..419cc5b2a6 100644 --- a/phpBB/phpbb/notification/type/disapprove_topic.php +++ b/phpBB/phpbb/notification/type/disapprove_topic.php @@ -60,7 +60,7 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'id' => 'moderation_queue', 'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE', 'group' => 'NOTIFICATION_GROUP_POSTING', diff --git a/phpBB/phpbb/notification/type/group_request.php b/phpBB/phpbb/notification/type/group_request.php index 4baf516fed..19665624df 100644 --- a/phpBB/phpbb/notification/type/group_request.php +++ b/phpBB/phpbb/notification/type/group_request.php @@ -26,7 +26,7 @@ class group_request extends \phpbb\notification\type\base /** * {@inheritdoc} */ - public static $notification_option = array( + static public $notification_option = array( 'lang' => 'NOTIFICATION_TYPE_GROUP_REQUEST', ); @@ -50,7 +50,7 @@ class group_request extends \phpbb\notification\type\base /** * {@inheritdoc} */ - public static function get_item_id($group) + static public function get_item_id($group) { return (int) $group['user_id']; } @@ -58,7 +58,7 @@ class group_request extends \phpbb\notification\type\base /** * {@inheritdoc} */ - public static function get_item_parent_id($group) + static public function get_item_parent_id($group) { // Group id is the parent return (int) $group['group_id']; diff --git a/phpBB/phpbb/notification/type/group_request_approved.php b/phpBB/phpbb/notification/type/group_request_approved.php index d284046ffa..f282cdd158 100644 --- a/phpBB/phpbb/notification/type/group_request_approved.php +++ b/phpBB/phpbb/notification/type/group_request_approved.php @@ -34,7 +34,7 @@ class group_request_approved extends \phpbb\notification\type\base /** * {@inheritdoc} */ - public static function get_item_id($group) + static public function get_item_id($group) { return (int) $group['group_id']; } @@ -42,7 +42,7 @@ class group_request_approved extends \phpbb\notification\type\base /** * {@inheritdoc} */ - public static function get_item_parent_id($group) + static public function get_item_parent_id($group) { return 0; } diff --git a/phpBB/phpbb/notification/type/pm.php b/phpBB/phpbb/notification/type/pm.php index 330a70c85a..29b4b79216 100644 --- a/phpBB/phpbb/notification/type/pm.php +++ b/phpBB/phpbb/notification/type/pm.php @@ -36,7 +36,7 @@ class pm extends \phpbb\notification\type\base * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'lang' => 'NOTIFICATION_TYPE_PM', ); @@ -53,7 +53,7 @@ class pm extends \phpbb\notification\type\base * * @param array $pm The data from the private message */ - public static function get_item_id($pm) + static public function get_item_id($pm) { return (int) $pm['msg_id']; } @@ -63,7 +63,7 @@ class pm extends \phpbb\notification\type\base * * @param array $pm The data from the pm */ - public static function get_item_parent_id($pm) + static public function get_item_parent_id($pm) { // No parent return 0; diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php index 421eff6372..d6aa8a8af9 100644 --- a/phpBB/phpbb/notification/type/post.php +++ b/phpBB/phpbb/notification/type/post.php @@ -50,7 +50,7 @@ class post extends \phpbb\notification\type\base * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'lang' => 'NOTIFICATION_TYPE_POST', 'group' => 'NOTIFICATION_GROUP_POSTING', ); @@ -68,7 +68,7 @@ class post extends \phpbb\notification\type\base * * @param array $post The data from the post */ - public static function get_item_id($post) + static public function get_item_id($post) { return (int) $post['post_id']; } @@ -78,7 +78,7 @@ class post extends \phpbb\notification\type\base * * @param array $post The data from the post */ - public static function get_item_parent_id($post) + static public function get_item_parent_id($post) { return (int) $post['topic_id']; } diff --git a/phpBB/phpbb/notification/type/post_in_queue.php b/phpBB/phpbb/notification/type/post_in_queue.php index 315b8b0243..e500ad33bc 100644 --- a/phpBB/phpbb/notification/type/post_in_queue.php +++ b/phpBB/phpbb/notification/type/post_in_queue.php @@ -43,7 +43,7 @@ class post_in_queue extends \phpbb\notification\type\post * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'id' => 'notification.type.needs_approval', 'lang' => 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE', 'group' => 'NOTIFICATION_GROUP_MODERATION', diff --git a/phpBB/phpbb/notification/type/quote.php b/phpBB/phpbb/notification/type/quote.php index 508ca92fa0..141f90c7ae 100644 --- a/phpBB/phpbb/notification/type/quote.php +++ b/phpBB/phpbb/notification/type/quote.php @@ -50,7 +50,7 @@ class quote extends \phpbb\notification\type\post * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'lang' => 'NOTIFICATION_TYPE_QUOTE', 'group' => 'NOTIFICATION_GROUP_POSTING', ); diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php index d39143f4b7..1904680d5a 100644 --- a/phpBB/phpbb/notification/type/report_pm.php +++ b/phpBB/phpbb/notification/type/report_pm.php @@ -60,7 +60,7 @@ class report_pm extends \phpbb\notification\type\pm * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'id' => 'notification.type.report', 'lang' => 'NOTIFICATION_TYPE_REPORT', 'group' => 'NOTIFICATION_GROUP_MODERATION', @@ -71,7 +71,7 @@ class report_pm extends \phpbb\notification\type\pm * * @param array $pm The data from the pm */ - public static function get_item_parent_id($pm) + static public function get_item_parent_id($pm) { return (int) $pm['report_id']; } diff --git a/phpBB/phpbb/notification/type/report_post.php b/phpBB/phpbb/notification/type/report_post.php index 027cca716b..b64862078a 100644 --- a/phpBB/phpbb/notification/type/report_post.php +++ b/phpBB/phpbb/notification/type/report_post.php @@ -66,7 +66,7 @@ class report_post extends \phpbb\notification\type\post_in_queue * @var bool|array False if the service should use it's default data * Array of data (including keys 'id' and 'lang') */ - public static $notification_option = array( + static public $notification_option = array( 'id' => 'notification.type.report', 'lang' => 'NOTIFICATION_TYPE_REPORT', 'group' => 'NOTIFICATION_GROUP_MODERATION', diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php index 5f57087b73..a1a17535b5 100644 --- a/phpBB/phpbb/notification/type/topic.php +++ b/phpBB/phpbb/notification/type/topic.php @@ -50,7 +50,7 @@ class topic extends \phpbb\notification\type\base * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'lang' => 'NOTIFICATION_TYPE_TOPIC', 'group' => 'NOTIFICATION_GROUP_POSTING', ); @@ -68,7 +68,7 @@ class topic extends \phpbb\notification\type\base * * @param array $post The data from the post */ - public static function get_item_id($post) + static public function get_item_id($post) { return (int) $post['topic_id']; } @@ -78,7 +78,7 @@ class topic extends \phpbb\notification\type\base * * @param array $post The data from the post */ - public static function get_item_parent_id($post) + static public function get_item_parent_id($post) { return (int) $post['forum_id']; } diff --git a/phpBB/phpbb/notification/type/topic_in_queue.php b/phpBB/phpbb/notification/type/topic_in_queue.php index 4c60c6b858..cfdf748d38 100644 --- a/phpBB/phpbb/notification/type/topic_in_queue.php +++ b/phpBB/phpbb/notification/type/topic_in_queue.php @@ -43,7 +43,7 @@ class topic_in_queue extends \phpbb\notification\type\topic * @var bool|array False if the service should use it's default data * Array of data (including keys 'id', 'lang', and 'group') */ - public static $notification_option = array( + static public $notification_option = array( 'id' => 'notification.type.needs_approval', 'lang' => 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE', 'group' => 'NOTIFICATION_GROUP_MODERATION', diff --git a/phpBB/phpbb/notification/type/type_interface.php b/phpBB/phpbb/notification/type/type_interface.php index 5c5a110836..8844ce1a38 100644 --- a/phpBB/phpbb/notification/type/type_interface.php +++ b/phpBB/phpbb/notification/type/type_interface.php @@ -37,14 +37,14 @@ interface type_interface * * @param array $type_data The type specific data */ - public static function get_item_id($type_data); + static public function get_item_id($type_data); /** * Get the id of the parent * * @param array $type_data The type specific data */ - public static function get_item_parent_id($type_data); + static public function get_item_parent_id($type_data); /** * Is this type available to the current user (defines whether or not it will be shown in the UCP Edit notification options) From 147a713cc066d493b50b82a9d475aa9af940e2b4 Mon Sep 17 00:00:00 2001 From: s9e Date: Sat, 22 Nov 2014 20:00:58 +0100 Subject: [PATCH 0142/1676] [ticket/11768] This commit integrates s9e\TextFormatter This commit integrates s9e\TextFormatter as outlined in http://area51.phpbb.com/phpBB/viewtopic.php?f=108&t=44467 PHPBB3-11768 --- phpBB/composer.lock | 108 +++- phpBB/config/default/container/services.yml | 2 +- .../container/services_text_formatter.yml | 58 ++ phpBB/config/default/container/tables.yml | 4 + phpBB/includes/acp/acp_bbcodes.php | 2 + phpBB/includes/acp/acp_icons.php | 6 +- phpBB/includes/acp/acp_main.php | 5 + phpBB/includes/acp/acp_words.php | 2 + phpBB/includes/functions_content.php | 127 +++-- phpBB/includes/message_parser.php | 131 ++--- phpBB/phpbb/textformatter/cache.php | 37 ++ phpBB/phpbb/textformatter/data_access.php | 233 ++++++++ phpBB/phpbb/textformatter/parser.php | 121 ++++ phpBB/phpbb/textformatter/renderer.php | 136 +++++ phpBB/phpbb/textformatter/s9e/factory.php | 493 ++++++++++++++++ phpBB/phpbb/textformatter/s9e/parser.php | 335 +++++++++++ phpBB/phpbb/textformatter/s9e/renderer.php | 228 ++++++++ phpBB/phpbb/textformatter/s9e/utils.php | 67 +++ phpBB/phpbb/textformatter/utils.php | 62 ++ tests/notification/group_request_test.php | 1 + .../phpbb_test_case_helpers.php | 210 +++++++ .../s9e/default_formatting_test.php | 200 +++++++ tests/text_formatter/s9e/factory_test.php | 182 ++++++ .../s9e/fixtures/default_formatting.xml | 466 +++++++++++++++ .../s9e/fixtures/default_lang.xml | 20 + tests/text_formatter/s9e/fixtures/factory.xml | 115 ++++ .../s9e/fixtures/inttext_token.xml | 27 + .../text_formatter/s9e/fixtures/local_url.xml | 28 + .../s9e/fixtures/smilies_special_chars.xml | 23 + .../s9e/fixtures/style_inheritance.xml | 66 +++ tests/text_formatter/s9e/fixtures/styles.xml | 36 ++ .../fixtures/styles/bar/template/bbcode.html | 40 ++ .../styles/barplus/template/bbcode.html | 40 ++ .../fixtures/styles/foo/template/bbcode.html | 40 ++ tests/text_formatter/s9e/parser_test.php | 162 ++++++ tests/text_formatter/s9e/renderer_test.php | 355 ++++++++++++ tests/text_formatter/s9e/utils_test.php | 157 ++++++ tests/text_processing/decode_message_test.php | 87 +++ tests/text_processing/fixtures/empty.xml | 3 + tests/text_processing/fixtures/smilies.xml | 443 +++++++++++++++ .../generate_text_for_display_test.php | 174 +++++- .../generate_text_for_edit_test.php | 90 +++ .../generate_text_for_storage_test.php | 70 +++ tests/text_processing/message_parser_test.php | 532 ++++++++++++++++++ tests/text_processing/smilies_test.php | 48 ++ tests/text_processing/strip_bbcode_test.php | 38 ++ .../tickets_data/PHPBB3-10002.html | 2 + .../tickets_data/PHPBB3-10002.txt | 2 + .../tickets_data/PHPBB3-10425.html | 3 + .../tickets_data/PHPBB3-10425.txt | 3 + .../tickets_data/PHPBB3-10587.html | 2 + .../tickets_data/PHPBB3-10587.txt | 2 + .../tickets_data/PHPBB3-10922.html | 1 + .../tickets_data/PHPBB3-10922.txt | 1 + .../tickets_data/PHPBB3-10989.html | 8 + .../tickets_data/PHPBB3-10989.txt | 8 + .../tickets_data/PHPBB3-11153.html | 1 + .../tickets_data/PHPBB3-11153.txt | 1 + .../tickets_data/PHPBB3-11153.xml | 28 + .../tickets_data/PHPBB3-12195.html | 1 + .../tickets_data/PHPBB3-12195.txt | 1 + .../tickets_data/PHPBB3-3981.before.php | 17 + .../tickets_data/PHPBB3-3981.html | 1 + .../tickets_data/PHPBB3-3981.txt | 1 + .../tickets_data/PHPBB3-7187.html | 1 + .../tickets_data/PHPBB3-7187.txt | 1 + .../tickets_data/PHPBB3-7187.xml | 33 ++ .../tickets_data/PHPBB3-7275.after.php | 15 + .../tickets_data/PHPBB3-7275.html | 1 + .../tickets_data/PHPBB3-7275.txt | 1 + .../tickets_data/PHPBB3-7275.xml | 49 ++ .../tickets_data/PHPBB3-9377.html | 1 + .../tickets_data/PHPBB3-9377.txt | 1 + .../tickets_data/PHPBB3-9377.xml | 41 ++ tests/text_processing/tickets_test.php | 91 +++ 75 files changed, 5967 insertions(+), 161 deletions(-) create mode 100644 phpBB/config/default/container/services_text_formatter.yml create mode 100644 phpBB/phpbb/textformatter/cache.php create mode 100644 phpBB/phpbb/textformatter/data_access.php create mode 100644 phpBB/phpbb/textformatter/parser.php create mode 100644 phpBB/phpbb/textformatter/renderer.php create mode 100644 phpBB/phpbb/textformatter/s9e/factory.php create mode 100644 phpBB/phpbb/textformatter/s9e/parser.php create mode 100644 phpBB/phpbb/textformatter/s9e/renderer.php create mode 100644 phpBB/phpbb/textformatter/s9e/utils.php create mode 100644 phpBB/phpbb/textformatter/utils.php create mode 100644 tests/text_formatter/s9e/default_formatting_test.php create mode 100644 tests/text_formatter/s9e/factory_test.php create mode 100644 tests/text_formatter/s9e/fixtures/default_formatting.xml create mode 100644 tests/text_formatter/s9e/fixtures/default_lang.xml create mode 100644 tests/text_formatter/s9e/fixtures/factory.xml create mode 100644 tests/text_formatter/s9e/fixtures/inttext_token.xml create mode 100644 tests/text_formatter/s9e/fixtures/local_url.xml create mode 100644 tests/text_formatter/s9e/fixtures/smilies_special_chars.xml create mode 100644 tests/text_formatter/s9e/fixtures/style_inheritance.xml create mode 100644 tests/text_formatter/s9e/fixtures/styles.xml create mode 100644 tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html create mode 100644 tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html create mode 100644 tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html create mode 100644 tests/text_formatter/s9e/parser_test.php create mode 100644 tests/text_formatter/s9e/renderer_test.php create mode 100644 tests/text_formatter/s9e/utils_test.php create mode 100644 tests/text_processing/decode_message_test.php create mode 100644 tests/text_processing/fixtures/empty.xml create mode 100644 tests/text_processing/fixtures/smilies.xml create mode 100644 tests/text_processing/generate_text_for_edit_test.php create mode 100644 tests/text_processing/generate_text_for_storage_test.php create mode 100644 tests/text_processing/message_parser_test.php create mode 100644 tests/text_processing/smilies_test.php create mode 100644 tests/text_processing/strip_bbcode_test.php create mode 100644 tests/text_processing/tickets_data/PHPBB3-10002.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-10002.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-10425.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-10425.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-10587.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-10587.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-10922.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-10922.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-10989.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-10989.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-11153.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-11153.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-11153.xml create mode 100644 tests/text_processing/tickets_data/PHPBB3-12195.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-12195.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-3981.before.php create mode 100644 tests/text_processing/tickets_data/PHPBB3-3981.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-3981.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-7187.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-7187.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-7187.xml create mode 100644 tests/text_processing/tickets_data/PHPBB3-7275.after.php create mode 100644 tests/text_processing/tickets_data/PHPBB3-7275.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-7275.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-7275.xml create mode 100644 tests/text_processing/tickets_data/PHPBB3-9377.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-9377.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-9377.xml create mode 100644 tests/text_processing/tickets_test.php diff --git a/phpBB/composer.lock b/phpBB/composer.lock index b6957aa667..e6dd12e8f0 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -145,7 +145,7 @@ "Psr\\Log\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -163,6 +163,63 @@ ], "time": "2012-12-21 11:40:51" }, + { + "name": "s9e/text-formatter", + "version": "dev-release/php5.3", + "source": { + "type": "git", + "url": "https://github.com/s9e/TextFormatter.git", + "reference": "872ed9d9204986668afc0b3e633be99e397e201b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/872ed9d9204986668afc0b3e633be99e397e201b", + "reference": "872ed9d9204986668afc0b3e633be99e397e201b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-filter": "*", + "php": ">=5.3.3" + }, + "suggest": { + "ext-intl": "Allows international URLs to be accepted by the URL filter", + "ext-json": "Enables the generation of a JavaScript parser", + "ext-mbstring": "Enables some optimizations in the PHP renderer", + "ext-tokenizer": "Enables optimizations in the PHP renderer", + "ext-xsl": "Enables the XSLT renderer", + "ext-zlib": "Enables gzip compression when scraping content via the MediaEmbed plugin" + }, + "type": "library", + "autoload": { + "psr-4": { + "s9e\\TextFormatter\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Multi-purpose text formatting and markup library. Plugins offer support for BBCodes, Markdown, emoticons, HTML, embedding media (YouTube, etc...), enhanced typography and more.", + "keywords": [ + "bbcode", + "bbcodes", + "blog", + "censor", + "embed", + "emoji", + "emoticons", + "engine", + "forum", + "html", + "markdown", + "markup", + "media", + "parser", + "shortcodes" + ], + "time": "2014-11-22 14:23:43" + }, { "name": "symfony/config", "version": "2.7.x-dev", @@ -960,16 +1017,14 @@ "Twig_": "lib/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" + "email": "fabien@symfony.com" }, { "name": "Armin Ronacher", @@ -993,21 +1048,21 @@ "packages-dev": [ { "name": "fabpot/goutte", - "version": "v1.0.7", + "version": "v1.0.3", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/Goutte.git", - "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625" + "url": "https://github.com/fabpot/Goutte.git", + "reference": "75c9f23c4122caf4ea3e87a42a00b471366e707f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/794b196e76bdd37b5155cdecbad311f0a3b07625", - "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625", + "url": "https://api.github.com/repos/fabpot/Goutte/zipball/75c9f23c4122caf4ea3e87a42a00b471366e707f", + "reference": "75c9f23c4122caf4ea3e87a42a00b471366e707f", "shasum": "" }, "require": { "ext-curl": "*", - "guzzle/http": "~3.1", + "guzzle/http": ">=3.0.5,<3.8-dev", "php": ">=5.3.0", "symfony/browser-kit": "~2.1", "symfony/css-selector": "~2.1", @@ -1016,8 +1071,8 @@ "symfony/process": "~2.1" }, "require-dev": { - "guzzle/plugin-history": "~3.1", - "guzzle/plugin-mock": "~3.1" + "guzzle/plugin-history": ">=3.0.5,<3.8-dev", + "guzzle/plugin-mock": ">=3.0.5,<3.8-dev" }, "type": "application", "extra": { @@ -1037,7 +1092,9 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" } ], "description": "A simple PHP Web Scraper", @@ -1045,7 +1102,7 @@ "keywords": [ "scraper" ], - "time": "2014-10-09 15:52:51" + "time": "2013-08-16 06:03:22" }, { "name": "guzzle/common", @@ -1376,8 +1433,7 @@ "authors": [ { "name": "Michiel Rook", - "email": "mrook@php.net", - "role": "Lead" + "email": "mrook@php.net" }, { "name": "Phing Community", @@ -1881,16 +1937,16 @@ }, { "name": "sami/sami", - "version": "v1.4", + "version": "v1.3", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/Sami.git", - "reference": "70f29c781f7bef30181c814b9471b2ceac694454" + "url": "https://github.com/fabpot/Sami.git", + "reference": "76f2ed80b3420f7e2f6dcd5b7218b5a5781f4110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Sami/zipball/70f29c781f7bef30181c814b9471b2ceac694454", - "reference": "70f29c781f7bef30181c814b9471b2ceac694454", + "url": "https://api.github.com/repos/fabpot/Sami/zipball/76f2ed80b3420f7e2f6dcd5b7218b5a5781f4110", + "reference": "76f2ed80b3420f7e2f6dcd5b7218b5a5781f4110", "shasum": "" }, "require": { @@ -1911,7 +1967,7 @@ "type": "application", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -1926,7 +1982,9 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" } ], "description": "Sami, an API documentation generator", @@ -1934,7 +1992,7 @@ "keywords": [ "phpdoc" ], - "time": "2014-06-25 11:24:03" + "time": "2013-11-30 17:16:25" }, { "name": "sebastian/comparator", diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 36f22d72d6..2b4aa52571 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -13,9 +13,9 @@ imports: - { resource: services_notification.yml } - { resource: services_password.yml } - { resource: services_profilefield.yml } + - { resource: services_text_formatter.yml } - { resource: services_twig.yml } - { resource: services_user.yml } - - { resource: tables.yml } - { resource: parameters.yml } diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml new file mode 100644 index 0000000000..7d21e4498e --- /dev/null +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -0,0 +1,58 @@ +parameters: + text_formatter.cache.dir: %core.root_path%cache/ + text_formatter.cache.parser.key: _text_formatter_parser + text_formatter.cache.renderer.key: _text_formatter_renderer + +services: + text_formatter.cache: + alias: text_formatter.s9e.factory + + text_formatter.data_access: + class: phpbb\textformatter\data_access + arguments: + - @dbal.conn + - %tables.bbcodes% + - %tables.smilies% + - %tables.styles% + - %tables.words% + - %core.root_path%styles/ + + text_formatter.parser: + alias: text_formatter.s9e.parser + + text_formatter.renderer: + alias: text_formatter.s9e.renderer + + text_formatter.utils: + alias: text_formatter.s9e.utils + + text_formatter.s9e.factory: + class: phpbb\textformatter\s9e\factory + arguments: + - @text_formatter.data_access + - @cache.driver + - %text_formatter.cache.dir% + - %text_formatter.cache.parser.key% + - %text_formatter.cache.renderer.key% + + text_formatter.s9e.parser: + class: phpbb\textformatter\s9e\parser + arguments: + - @cache.driver + - %text_formatter.cache.parser.key% + - @user + - @service_container + + text_formatter.s9e.renderer: + class: phpbb\textformatter\s9e\renderer + arguments: + - @cache.driver + - %text_formatter.cache.dir% + - %text_formatter.cache.renderer.key% + - @service_container + calls: + - [configure_smilies_path, [@config, @path_helper]] + - [configure_user, [@user, @config, @auth]] + + text_formatter.s9e.utils: + class: phpbb\textformatter\s9e\utils diff --git a/phpBB/config/default/container/tables.yml b/phpBB/config/default/container/tables.yml index 2fe2a33be8..00067d5abe 100644 --- a/phpBB/config/default/container/tables.yml +++ b/phpBB/config/default/container/tables.yml @@ -1,6 +1,7 @@ parameters: tables.auth_provider_oauth_token_storage: %core.table_prefix%oauth_tokens tables.auth_provider_oauth_account_assoc: %core.table_prefix%oauth_accounts + tables.bbcodes: %core.table_prefix%bbcodes tables.captcha_qa_questions: %core.table_prefix%captcha_questions tables.captcha_qa_answers: %core.table_prefix%captcha_answers tables.captcha_qa_confirm: %core.table_prefix%qa_confirm @@ -18,6 +19,9 @@ parameters: tables.profile_fields_options_language: %core.table_prefix%profile_fields_lang tables.profile_fields_language: %core.table_prefix%profile_lang tables.posts: %core.table_prefix%posts + tables.smilies: %core.table_prefix%smilies + tables.styles: %core.table_prefix%styles tables.topics: %core.table_prefix%topics tables.user_notifications: %core.table_prefix%user_notifications tables.users: %core.table_prefix%users + tables.words: %core.table_prefix%words diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index a5cd48c444..327af0e0bc 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -269,6 +269,7 @@ class acp_bbcodes $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary)); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_ADDED'; $log_action = 'LOG_BBCODE_ADD'; @@ -280,6 +281,7 @@ class acp_bbcodes WHERE bbcode_id = ' . $bbcode_id; $db->sql_query($sql); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_EDITED'; $log_action = 'LOG_BBCODE_EDIT'; diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index fdf366097a..5d1756de45 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -28,7 +28,7 @@ class acp_icons function main($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; global $request, $phpbb_container; @@ -486,6 +486,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); $level = ($icons_updated) ? E_USER_NOTICE : E_USER_WARNING; $errormsgs = ''; @@ -661,6 +662,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); trigger_error($user->lang[$lang . '_IMPORT_SUCCESS'] . adm_back_link($this->u_action)); } @@ -783,6 +785,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); if ($request->is_ajax()) { @@ -848,6 +851,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); if ($request->is_ajax()) { diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index c49ccdf479..9a99666c75 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -352,6 +352,11 @@ class acp_main $config->increment('assets_version', 1); $cache->purge(); + // Remove old renderers from the text_formatter service. Since this + // operation is performed after the cache is purged, there is not "current" + // renderer and in effect all renderers will be purged + $phpbb_container->get('text_formatter.cache')->tidy(); + // Clear permissions $auth->acl_clear_prefetch(); phpbb_cache_moderators($db, $cache, $auth); diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index d28aa8e60b..1ba247be4d 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -115,6 +115,7 @@ class acp_words } $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); $log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD'; @@ -148,6 +149,7 @@ class acp_words $db->sql_query($sql); $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WORD_DELETE', false, array($deleted_word)); diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index bdbc8a92fa..60511d89a4 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -389,46 +389,68 @@ function phpbb_clean_search_string($search_string) /** * Decode text whereby text is coming from the db and expected to be pre-parsed content * We are placing this outside of the message parser because we are often in need of it... +* +* NOTE: special chars are kept encoded +* +* @param string &$message Original message, passed by reference +* @param string $bbcode_uid BBCode UID +* @return null */ function decode_message(&$message, $bbcode_uid = '') { - global $config; + global $phpbb_container; - if ($bbcode_uid) + if (preg_match('#^<[rt][ >]#', $message)) { - $match = array('
    ', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); - $replace = array("\n", '', '', '', ''); + $message = htmlspecialchars($phpbb_container->get('text_formatter.utils')->unparse($message), ENT_COMPAT); } else { - $match = array('
    '); - $replace = array("\n"); + if ($bbcode_uid) + { + $match = array('
    ', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); + $replace = array("\n", '', '', '', ''); + } + else + { + $match = array('
    '); + $replace = array("\n"); + } + + $message = str_replace($match, $replace, $message); + + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\2', '\1', '', ''); + + $message = preg_replace($match, $replace, $message); } - - $message = str_replace($match, $replace, $message); - - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); - - $message = preg_replace($match, $replace, $message); } /** -* Strips all bbcode from a text and returns the plain content +* Strips all bbcode from a text in place */ function strip_bbcode(&$text, $uid = '') { - if (!$uid) + global $phpbb_container; + + if (preg_match('#^<[rt][ >]#', $text)) { - $uid = '[0-9a-z]{5,}'; + $text = $phpbb_container->get('text_formatter.utils')->clean_formatting($text); } + else + { + if (!$uid) + { + $uid = '[0-9a-z]{5,}'; + } - $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); + $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\2', '\1', '', ''); - $text = preg_replace($match, $replace, $text); + $text = preg_replace($match, $replace, $text); + } } /** @@ -438,7 +460,7 @@ function strip_bbcode(&$text, $uid = '') function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text = true) { static $bbcode; - global $phpbb_dispatcher; + global $phpbb_dispatcher, $phpbb_container; if ($text === '') { @@ -459,35 +481,57 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text $vars = array('text', 'uid', 'bitfield', 'flags', 'censor_text'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_display_before', compact($vars))); - if ($censor_text) + if (preg_match('#^<[rt][ >]#', $text)) { - $text = censor_text($text); - } + $renderer = $phpbb_container->get('text_formatter.renderer'); - // Parse bbcode if bbcode uid stored and bbcode enabled - if ($uid && ($flags & OPTION_FLAG_BBCODE)) + // Temporarily switch off viewcensors if applicable + $old_censor = $renderer->get_viewcensors(); + if ($old_censor !== $censor_text) + { + $renderer->set_viewcensors($censor_text); + } + + $text = $renderer->render($text); + + // Restore the previous value + if ($old_censor !== $censor_text) + { + $renderer->set_viewcensors($old_censor); + } + } + else { - if (!class_exists('bbcode')) + if ($censor_text) { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $text = censor_text($text); } - if (empty($bbcode)) + // Parse bbcode if bbcode uid stored and bbcode enabled + if ($uid && ($flags & OPTION_FLAG_BBCODE)) { - $bbcode = new bbcode($bitfield); - } - else - { - $bbcode->bbcode($bitfield); + if (!class_exists('bbcode')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + } + + if (empty($bbcode)) + { + $bbcode = new bbcode($bitfield); + } + else + { + $bbcode->bbcode($bitfield); + } + + $bbcode->bbcode_second_pass($text, $uid); } - $bbcode->bbcode_second_pass($text, $uid); + $text = bbcode_nl2br($text); + $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); } - $text = bbcode_nl2br($text); - $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); - /** * Use this event to modify the text after it is parsed * @@ -550,11 +594,6 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb $uid = $bitfield = ''; $flags = (($allow_bbcode) ? OPTION_FLAG_BBCODE : 0) + (($allow_smilies) ? OPTION_FLAG_SMILIES : 0) + (($allow_urls) ? OPTION_FLAG_LINKS : 0); - if ($text === '') - { - return; - } - if (!class_exists('parse_message')) { include($phpbb_root_path . 'includes/message_parser.' . $phpEx); diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index ccb953adbe..e4c35f8bca 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1094,7 +1094,7 @@ class parse_message extends bbcode_firstpass function parse_message($message = '') { // Init BBCode UID - $this->bbcode_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN); + $this->bbcode_uid = ''; $this->message = $message; } @@ -1103,7 +1103,7 @@ class parse_message extends bbcode_firstpass */ function parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post') { - global $config, $db, $user, $phpbb_dispatcher; + global $config, $db, $user, $phpbb_dispatcher, $phpbb_container; $this->mode = $mode; @@ -1132,12 +1132,6 @@ class parse_message extends bbcode_firstpass $this->decode_message(); } - // Do some general 'cleanup' first before processing message, - // e.g. remove excessive newlines(?), smilies(?) - $match = array('#(script|about|applet|activex|chrome):#i'); - $replace = array("\\1:"); - $this->message = preg_replace($match, $replace, trim($this->message)); - // Store message length... $message_length = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message)); @@ -1210,47 +1204,29 @@ class parse_message extends bbcode_firstpass return (!$update_this_message) ? $return_message : $this->warn_msg; } - // Prepare BBcode (just prepares some tags for better parsing) - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->bbcode_init(); - $disallow = array('img', 'flash', 'quote', 'url'); - foreach ($disallow as $bool) - { - if (!${'allow_' . $bool . '_bbcode'}) - { - $this->bbcodes[$bool]['disabled'] = true; - } - } + // Get the parser + $parser = $phpbb_container->get('text_formatter.parser'); - $this->prepare_bbcodes(); - } + // Set the parser's options + ($allow_bbcode) ? $parser->enable_bbcodes() : $parser->disable_bbcodes(); + ($allow_magic_url) ? $parser->enable_magic_url() : $parser->disable_magic_url(); + ($allow_smilies) ? $parser->enable_smilies() : $parser->disable_smilies(); + ($allow_img_bbcode) ? $parser->enable_bbcode('img') : $parser->disable_bbcode('img'); + ($allow_flash_bbcode) ? $parser->enable_bbcode('flash') : $parser->disable_bbcode('flash'); + ($allow_quote_bbcode) ? $parser->enable_bbcode('quote') : $parser->disable_bbcode('quote'); + ($allow_url_bbcode) ? $parser->enable_bbcode('url') : $parser->disable_bbcode('url'); - // Parse smilies - if ($allow_smilies) - { - $this->smilies($config['max_' . $mode . '_smilies']); - } + // Set some config values + $parser->set_vars(array( + 'max_font_size' => $config['max_' . $this->mode . '_font_size'], + 'max_img_height' => $config['max_' . $this->mode . '_img_height'], + 'max_img_width' => $config['max_' . $this->mode . '_img_width'], + 'max_smilies' => $config['max_' . $this->mode . '_smilies'], + 'max_urls' => $config['max_' . $this->mode . '_urls'] + )); - $num_urls = 0; - - // Parse BBCode - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->parse_bbcode(); - $num_urls += $this->parsed_items['url']; - } - - // Parse URL's - if ($allow_magic_url) - { - $this->magic_url(generate_board_url()); - - if ($config['max_' . $mode . '_urls']) - { - $num_urls += preg_match_all('#\(.*?)#s', $template, $matches, PREG_SET_ORDER); + + $fragments = array(); + foreach ($matches as $match) + { + // Normalize the whitespace + $fragment = preg_replace('#>\\n\\t*<#', '><', trim($match[2])); + + $fragments[$match[1]] = $fragment; + } + + // Automatically recompose templates split between *_open and *_close + foreach ($fragments as $fragment_name => $fragment) + { + if (preg_match('#^(\\w+)_close$#', $fragment_name, $match)) + { + $bbcode_name = $match[1]; + + if (isset($fragments[$bbcode_name . '_open'])) + { + $templates[$bbcode_name] = $fragments[$bbcode_name . '_open'] . '' . $fragment; + } + } + } + + // Manually recompose and overwrite irregular templates + $templates['list'] = + ' + + ' . $fragments['ulist_open_default'] . '' . $fragments['ulist_close'] . ' + + + ' . $fragments['olist_open'] . '' . $fragments['olist_close'] . ' + + + ' . $fragments['ulist_open'] . '' . $fragments['ulist_close'] . ' + + '; + + $templates['li'] = $fragments['listitem'] . '' . $fragments['listitem_close']; + + $templates['quote'] = + ' + + ' . $fragments['quote_username_open'] . '' . $fragments['quote_close'] . ' + + + ' . $fragments['quote_open'] . '' . $fragments['quote_close'] . ' + + '; + + // The [attachment] BBCode uses the inline_attachment template to output a comment that + // is post-processed by parse_attachments() + $templates['attachment'] = $fragments['inline_attachment_open'] . ' ia ia ' . $fragments['inline_attachment_close']; + + // Finally save fragments whose names look like the name of a BBCode, e.g. "flash" + foreach ($fragments as $fragment_name => $fragment) + { + if (preg_match('#^\\w+$#', $fragment_name)) + { + $templates[$fragment_name] = $fragment; + } + } + + return $templates; + } + + /** + * Merge the templates from any number of styles into one BBCode template + * + * @param array $style_templates Associative array matching style_ids to their template + * @return string + */ + protected function merge_templates(array $style_templates) + { + // Group identical templates together + $grouped_templates = array(); + foreach ($style_templates as $style_id => $style_template) + { + $grouped_templates[$style_template][] = $style_id; + } + + if (count($grouped_templates) === 1) + { + return $style_template; + } + + // Sort templates by frequency descending + $templates_cnt = array_map('sizeof', $grouped_templates); + array_multisort($grouped_templates, $templates_cnt); + + // Remove the most frequent template from the list; It becomes the default + reset($grouped_templates); + $default_template = key($grouped_templates); + unset($grouped_templates[$default_template]); + + // Build an xsl:choose switch + $template = ''; + foreach ($grouped_templates as $style_template => $style_ids) + { + $template .= '' . $style_template . ''; + } + $template .= '' . $default_template . ''; + + return $template; + } +} diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php new file mode 100644 index 0000000000..10e33f47e6 --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -0,0 +1,335 @@ + +* @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\textformatter\s9e; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use s9e\TextFormatter\Parser\BuiltInFilters; +use s9e\TextFormatter\Parser\Logger; + +/** +* s9e\TextFormatter\Parser adapter +* @package phpBB3 +*/ +class parser extends \phpbb\textformatter\parser +{ + /** + * @var s9e\TextFormatter\Parser + */ + protected $parser; + + /** + * @var phpbb\user User object, used for translating errors + */ + protected $user; + + /** + * Constructor + * + * @param phpbb\cache\driver_interface $cache + * @param string $key Cache key + * @param phpbb\user $user + * @param Symfony\Component\DependencyInjection\ContainerInterface $container + * @return null + */ + public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, ContainerInterface $container) + { + $this->user = $user; + + $parser = $cache->get($key); + if (!$parser) + { + list($parser) = $container->get('text_formatter.s9e.factory')->regenerate(); + } + + $this->parser = $parser; + } + + /** + * {@inheritdoc} + */ + public function parse($text) + { + return $this->parser->parse($text); + } + + /** + * {@inheritdoc} + */ + public function disable_bbcode($name) + { + $this->parser->disableTag(strtoupper($name)); + } + + /** + * {@inheritdoc} + */ + public function disable_bbcodes() + { + $this->parser->disablePlugin('BBCodes'); + } + + /** + * {@inheritdoc} + */ + public function disable_censor() + { + $this->parser->disablePlugin('Censor'); + } + + /** + * {@inheritdoc} + */ + public function disable_magic_url() + { + $this->parser->disablePlugin('Autoemail'); + $this->parser->disablePlugin('Autolink'); + } + + /** + * {@inheritdoc} + */ + public function disable_smilies() + { + $this->parser->disablePlugin('Emoticons'); + } + + /** + * {@inheritdoc} + */ + public function enable_bbcode($name) + { + $this->parser->enableTag(strtoupper($name)); + } + + /** + * {@inheritdoc} + */ + public function enable_bbcodes() + { + $this->parser->enablePlugin('BBCodes'); + } + + /** + * {@inheritdoc} + */ + public function enable_censor() + { + $this->parser->enablePlugin('Censor'); + } + + /** + * {@inheritdoc} + */ + public function enable_magic_url() + { + $this->parser->enablePlugin('Autoemail'); + $this->parser->enablePlugin('Autolink'); + } + + /** + * {@inheritdoc} + */ + public function enable_smilies() + { + $this->parser->enablePlugin('Emoticons'); + } + + /** + * {@inheritdoc} + * + * This will translate the log entries found in s9e\TextFormatter's logger into phpBB error + * messages + */ + public function get_errors() + { + $errors = array(); + + foreach ($this->parser->getLogger()->get() as $entry) + { + list($type, $msg, $context) = $entry; + + if ($msg === 'Tag limit exceeded') + { + if ($context['tagName'] === 'E') + { + $errors[] = $this->user->lang('TOO_MANY_SMILIES', $context['tagLimit']); + } + else if ($context['tagName'] === 'URL') + { + $errors[] = $this->user->lang('TOO_MANY_URLS', $context['tagLimit']); + } + } + else if ($msg === 'MAX_FONT_SIZE_EXCEEDED') + { + $errors[] = $this->user->lang($msg, $context['max_size']); + } + else if (preg_match('/^MAX_(?:FLASH|IMG)_(HEIGHT|WIDTH)_EXCEEDED$/D', $msg, $m)) + { + $errors[] = $this->user->lang($msg, $context['max_' . strtolower($m[1])]); + } + else if ($msg === 'Tag is disabled') + { + $name = strtolower($context['tag']->getName()); + $errors[] = $this->user->lang('UNAUTHORISED_BBCODE', '[' . $name . ']'); + } + else if ($msg === 'UNABLE_GET_IMAGE_SIZE') + { + $errors[] = $this->user->lang[$msg]; + } + } + + return array_unique($errors); + } + + /** + * {@inheritdoc} + */ + public function set_var($name, $value) + { + if ($name === 'max_smilies') + { + $this->parser->setTagLimit('E', $value ?: PHP_INT_MAX); + } + else if ($name === 'max_urls') + { + $this->parser->setTagLimit('URL', $value ?: PHP_INT_MAX); + } + else + { + $this->parser->registeredVars[$name] = $value; + } + } + + /** + * Filter a flash object's height + * + * @see bbcode_firstpass::bbcode_flash() + * + * @param string $height + * @param integer $max_height + * @param s9e\TextFormatter\Parser\Logger $logger + * @return mixed Original value if valid, FALSE otherwise + */ + static public function filter_flash_height($height, $max_height, Logger $logger) + { + if ($max_height && $height > $max_height) + { + $logger->err('MAX_FLASH_HEIGHT_EXCEEDED', array('max_height' => $max_height)); + + return false; + } + + return $height; + } + + /** + * Filter a flash object's width + * + * @see bbcode_firstpass::bbcode_flash() + * + * @param string $width + * @param integer $max_width + * @param s9e\TextFormatter\Parser\Logger $logger + * @return mixed Original value if valid, FALSE otherwise + */ + static public function filter_flash_width($width, $max_width, Logger $logger) + { + if ($max_width && $width > $max_width) + { + $logger->err('MAX_FLASH_WIDTH_EXCEEDED', array('max_width' => $max_width)); + + return false; + } + + return $width; + } + + /** + * Filter the value used in a [size] BBCode + * + * @see bbcode_firstpass::bbcode_size() + * + * @param string $size Original size + * @param integer $max_size Maximum allowed size + * @param s9e\TextFormatter\Parser\Logger $logger + * @return mixed Original value if valid, FALSE otherwise + */ + static public function filter_font_size($size, $max_size, Logger $logger) + { + if ($max_size && $size > $max_size) + { + $logger->err('MAX_FONT_SIZE_EXCEEDED', array('max_size' => $max_size)); + + return false; + } + + if ($size < 1) + { + return false; + } + + return $size; + } + + /** + * Filter an image's URL to enforce restrictions on its dimensions + * + * @see bbcode_firstpass::bbcode_img() + * + * @param string $url Original URL + * @param array $url_config Config used by the URL filter + * @param s9e\TextFormatter\Parser\Logger $logger + * @param integer $max_height Maximum height allowed + * @param integer $max_width Maximum width allowed + * @return string|bool Original value if valid, FALSE otherwise + */ + static public function filter_img_url($url, array $url_config, Logger $logger, $max_height, $max_width) + { + // Validate the URL + $url = BuiltInFilters::filterUrl($url, $url_config, $logger); + + if ($url === false) + { + return false; + } + + if ($max_height || $max_width) + { + $stats = @getimagesize($url); + + if ($stats === false) + { + $logger->err('UNABLE_GET_IMAGE_SIZE'); + + return false; + } + + if ($max_height && $max_height < $stats[1]) + { + $logger->err('MAX_IMG_HEIGHT_EXCEEDED', array('max_height' => $max_height)); + + return false; + } + + if ($max_width && $max_width < $stats[0]) + { + $logger->err('MAX_IMG_WIDTH_EXCEEDED', array('max_width' => $max_width)); + + return false; + } + } + + return $url; + } +} diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php new file mode 100644 index 0000000000..2c8412f961 --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -0,0 +1,228 @@ + +* @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\textformatter\s9e; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** +* s9e\TextFormatter\Renderer adapter +* @package phpBB3 +*/ +class renderer extends \phpbb\textformatter\renderer +{ + /** + * @var s9e\TextFormatter\Renderer + */ + protected $renderer; + + /** + * @var bool Status of the viewcensors option + */ + protected $viewcensors = false; + + /** + * @var bool Status of the viewflash option + */ + protected $viewflash = false; + + /** + * @var bool Status of the viewimg option + */ + protected $viewimg = false; + + /** + * @var bool Status of the viewsmilies option + */ + protected $viewsmilies = false; + + /** + * Constructor + * + * @param phpbb\cache\driver\driver_interface $cache + * @param string $cache_dir Path to the cache dir + * @param string $key Cache key + * @param Symfony\Component\DependencyInjection\ContainerInterface $container + * @return null + */ + public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, ContainerInterface $container) + { + $renderer_data = $cache->get($key); + + if ($renderer_data) + { + $class = $renderer_data['class']; + + if (!class_exists($class, false)) + { + // Try to load the renderer class from its cache file + $cache_file = $cache_dir . $class . '.php'; + + if (file_exists($cache_file)) + { + include($cache_file); + } + } + + if (class_exists($class, false)) + { + $renderer = unserialize($renderer_data['renderer']); + } + } + + if (!isset($renderer)) + { + list(, $renderer) = $container->get('text_formatter.s9e.factory')->regenerate(); + } + + $this->renderer = $renderer; + } + + /** + * {@inheritdoc} + */ + public function configure_user(\phpbb\user $user, \phpbb\config\config $config, \phpbb\auth\auth $auth) + { + parent::configure_user($user, $config, $auth); + + // Set the stylesheet parameters + foreach (array_keys($this->renderer->getParameters()) as $param_name) + { + if (substr($param_name, 0, 2) === 'L_') + { + // L_FOO is set to $user->lang('FOO') + $this->renderer->setParameter($param_name, $user->lang(substr($param_name, 2))); + } + } + + // Set the style id + $this->renderer->setParameter('STYLE_ID', $user->style['style_id']); + } + + /** + * {@inheritdoc} + */ + public function get_viewcensors() + { + return $this->viewcensors; + } + + /** + * {@inheritdoc} + */ + public function get_viewflash() + { + return $this->viewflash; + } + + /** + * {@inheritdoc} + */ + public function get_viewimg() + { + return $this->viewimg; + } + + /** + * {@inheritdoc} + */ + public function get_viewsmilies() + { + return $this->viewsmilies; + } + + /** + * {@inheritdoc} + */ + public function render($text) + { + $html = $this->renderer->render($text); + + /** + * @see bbcode::bbcode_second_pass_code() + */ + $html = preg_replace_callback( + '#()(.*?)()#is', + function ($captures) + { + $code = $captures[2]; + + $code = str_replace("\t", '   ', $code); + $code = str_replace(' ', '  ', $code); + $code = str_replace(' ', '  ', $code); + $code = str_replace("\n ", "\n ", $code); + + // keep space at the beginning + if (!empty($code) && $code[0] == ' ') + { + $code = ' ' . substr($code, 1); + } + + // remove newline at the beginning + if (!empty($code) && $code[0] == "\n") + { + $code = substr($code, 1); + } + + return $captures[1] . $code . $captures[3]; + }, + $html + ); + + return $html; + } + + /** + * {@inheritdoc} + */ + public function set_smilies_path($path) + { + $this->renderer->setParameter('T_SMILIES_PATH', $path); + } + + /** + * {@inheritdoc} + */ + public function set_viewcensors($value) + { + $this->viewcensors = $value; + $this->renderer->setParameter('S_VIEWCENSORS', $value); + } + + /** + * {@inheritdoc} + */ + public function set_viewflash($value) + { + $this->viewflash = $value; + $this->renderer->setParameter('S_VIEWFLASH', $value); + } + + /** + * {@inheritdoc} + */ + public function set_viewimg($value) + { + $this->viewimg = $value; + $this->renderer->setParameter('S_VIEWIMG', $value); + } + + /** + * {@inheritdoc} + */ + public function set_viewsmilies($value) + { + $this->viewsmilies = $value; + $this->renderer->setParameter('S_VIEWSMILIES', $value); + } +} diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php new file mode 100644 index 0000000000..19cd3a11c8 --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -0,0 +1,67 @@ + +* @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\textformatter\s9e; + +/** +* Text manipulation utilities +* @package phpBB3 +*/ +class utils extends \phpbb\textformatter\utils +{ + /** + * {@inheritdoc} + */ + public function clean_formatting($text) + { + // Insert a space before and then remove formatting + $text = preg_replace('#<[es]>#', ' $0', $text); + + return \s9e\TextFormatter\Unparser::removeFormatting($text); + } + + /** + * {@inheritdoc} + */ + public function remove_bbcode($text, $bbcode_name, $depth = 0) + { + $dom = new \DOMDocument; + $dom->loadXML($text); + + $xpath = new \DOMXPath($dom); + $nodes = $xpath->query(str_repeat('//' . strtoupper($bbcode_name), 1 + $depth)); + + foreach ($nodes as $node) + { + $node->parentNode->removeChild($node); + } + + return $dom->saveXML($dom->documentElement); + } + + /** + * {@inheritdoc} + */ + public function remove_formatting($text) + { + return \s9e\TextFormatter\Unparser::removeFormatting($text); + } + + /** + * {@inheritdoc} + */ + public function unparse($text) + { + return \s9e\TextFormatter\Unparser::unparse($text); + } +} diff --git a/phpBB/phpbb/textformatter/utils.php b/phpBB/phpbb/textformatter/utils.php new file mode 100644 index 0000000000..c9bed94553 --- /dev/null +++ b/phpBB/phpbb/textformatter/utils.php @@ -0,0 +1,62 @@ + +* @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\textformatter; + +/** +* text_formatter.utils service +* +* Used to manipulate a parsed text +* +* @package phpBB3 +*/ +abstract class utils +{ + /** + * Replace BBCodes and other formatting elements with whitespace + * + * NOTE: preserves smilies as text + * + * @param string $text + * @return string + */ + abstract public function clean_formatting($text); + + /** + * Remove given BBCode at given nesting depth + * + * @param string $text Parsed text + * @param string $bbcode_name BBCode's name + * @param integer $depth Minimum nesting depth (number of parents of the same name) + * @return string + */ + abstract public function remove_bbcode($text, $bbcode_name, $depth = 0); + + /** + * Remove BBCodes and other formatting from a parsed text + * + * NOTE: preserves smilies as text + * + * @param string $text + * @return string + */ + abstract public function remove_formatting($text); + + /** + * Return a parsed text to its original form + * + * @param string $text + * @return string + */ + abstract public function unparse($text); +} diff --git a/tests/notification/group_request_test.php b/tests/notification/group_request_test.php index 0d532882c6..6a56a38c45 100644 --- a/tests/notification/group_request_test.php +++ b/tests/notification/group_request_test.php @@ -51,6 +51,7 @@ class phpbb_notification_group_request_test extends phpbb_tests_notification_bas )); $phpbb_dispatcher = new phpbb_mock_event_dispatcher; $phpbb_log = new \phpbb\log\null(); + $this->get_test_case_helpers()->set_s9e_services(); // Now on to the actual test diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index dee70ad016..d0b1573e61 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -11,6 +11,8 @@ * */ +use Symfony\Component\DependencyInjection\ContainerInterface; + class phpbb_test_case_helpers { protected $expectedTriggerError = false; @@ -298,4 +300,212 @@ class phpbb_test_case_helpers } } } + + /** + * Set working instances of the text_formatter.* services + * + * If no container is passed, the global $phpbb_container will be used and/or + * created if applicable + * + * @param ContainerInterface $container Service container + * @param string $fixture Path to the XML fixture + * @param string $styles_path Path to the styles dir + * @return ContainerInterface + */ + public function set_s9e_services(ContainerInterface $container = null, $fixture = null, $styles_path = null) + { + static $first_run; + global $phpbb_container, $phpbb_root_path, $phpEx; + + $cache_dir = __DIR__ . '/../tmp/'; + + // Remove old cache files on first run + if (!isset($first_run)) + { + $first_run = 1; + + array_map('unlink', array_merge( + glob($cache_dir . 'data_s9e_*'), + glob($cache_dir . 's9e_*') + )); + } + + if (!isset($container)) + { + if (!isset($phpbb_container)) + { + $phpbb_container = new phpbb_mock_container_builder; + } + + $container = $phpbb_container; + } + + if (!isset($fixture)) + { + $fixture = __DIR__ . '/../text_formatter/s9e/fixtures/default_formatting.xml'; + } + + if (!isset($styles_path)) + { + $styles_path = $phpbb_root_path . 'styles/'; + } + + $dataset = new DOMDocument; + $dataset->load($fixture); + + $tables = array( + 'phpbb_bbcodes' => array(), + 'phpbb_smilies' => array(), + 'phpbb_styles' => array(), + 'phpbb_words' => array() + ); + foreach ($dataset->getElementsByTagName('table') as $table) + { + $name = $table->getAttribute('name'); + $columns = array(); + + foreach ($table->getElementsByTagName('column') as $column) + { + $columns[] = $column->textContent; + } + + foreach ($table->getElementsByTagName('row') as $row) + { + $values = array(); + + foreach ($row->getElementsByTagName('value') as $value) + { + $values[] = $value->textContent; + } + + $tables[$name][] = array_combine($columns, $values); + } + } + + // Set up a default style if there's none set + if (empty($tables['phpbb_styles'])) + { + $tables['phpbb_styles'][] = array( + 'style_id' => 1, + 'style_path' => 'prosilver', + 'bbcode_bitfield' => 'kNg=' + ); + } + + // Mock the DAL, make it return data from the fixture + $mb = $this->test_case->getMockBuilder('phpbb\\textformatter\\data_access'); + $mb->setMethods(array('get_bbcodes', 'get_smilies', 'get_styles', 'get_words')); + $mb->setConstructorArgs(array( + $this->test_case->getMock('phpbb\\db\\driver\\driver'), + 'phpbb_bbcodes', + 'phpbb_smilies', + 'phpbb_styles', + 'phpbb_words', + $styles_path + )); + + $dal = $mb->getMock(); + $container->set('text_formatter.data_access', $dal); + + $dal->expects($this->test_case->any()) + ->method('get_bbcodes') + ->will($this->test_case->returnValue($tables['phpbb_bbcodes'])); + $dal->expects($this->test_case->any()) + ->method('get_smilies') + ->will($this->test_case->returnValue($tables['phpbb_smilies'])); + $dal->expects($this->test_case->any()) + ->method('get_styles') + ->will($this->test_case->returnValue($tables['phpbb_styles'])); + $dal->expects($this->test_case->any()) + ->method('get_words') + ->will($this->test_case->returnValue($tables['phpbb_words'])); + + // Cache the parser and renderer with a key based on this method's arguments + $cache = new \phpbb\cache\driver\file($cache_dir); + $prefix = '_s9e_' . md5(serialize(func_get_args())); + $cache_key_parser = $prefix . '_parser'; + $cache_key_renderer = $prefix . '_renderer'; + + // Create a path_helper + if (!$container->has('path_helper')) + { + $container->set( + 'path_helper', + new \phpbb\path_helper( + new \phpbb\symfony_request( + new phpbb_mock_request() + ), + new \phpbb\filesystem(), + $this->test_case->getMock('\phpbb\request\request'), + $phpbb_root_path, + $phpEx + ) + ); + } + + // Create and register the text_formatter.s9e.factory service + $factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $cache_dir, $cache_key_parser, $cache_key_renderer); + $container->set('text_formatter.s9e.factory', $factory); + + // Create a user if none was provided, and add the common lang strings + if ($container->has('user')) + { + $user = $container->get('user'); + } + else + { + $user = new \phpbb\user('\phpbb\datetime'); + $user->optionset('viewcensors', true); + $user->optionset('viewflash', true); + $user->optionset('viewimg', true); + $user->optionset('viewsmilies', true); + } + $user->add_lang('common'); + + if (!isset($user->style)) + { + $user->style = array('style_id' => 1); + } + + // Create and register the text_formatter.s9e.parser service and its alias + $parser = new \phpbb\textformatter\s9e\parser( + $cache, + $cache_key_parser, + $user, + $container + ); + + $container->set('text_formatter.parser', $parser); + $container->set('text_formatter.s9e.parser', $parser); + + // Create and register the text_formatter.s9e.renderer service and its alias + $renderer = new \phpbb\textformatter\s9e\renderer( + $cache, + $cache_dir, + $cache_key_renderer, + $container + ); + + $root_path = ($container->hasParameter('core.root_path')) + ? $container->getParameter('core.root_path') + : './'; + $config = ($container->has('config')) + ? $container->get('config') + : new \phpbb\config\config(array('smilies_path' => 'images/smilies', 'allow_nocensors' => false)); + $auth = ($container->has('auth')) ? $container->get('auth') : new \phpbb\auth\auth; + + // Calls configured in services.yml + $renderer->configure_smilies_path($config, $container->get('path_helper')); + $renderer->configure_user($user, $config, $auth); + + $container->set('text_formatter.renderer', $renderer); + $container->set('text_formatter.s9e.renderer', $renderer); + + // Create and register the text_formatter.s9e.utils service and its alias + $utils = new \phpbb\textformatter\s9e\utils; + $container->set('text_formatter.utils', $utils); + $container->set('text_formatter.s9e.utils', $utils); + + return $container; + } } diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php new file mode 100644 index 0000000000..be258868dd --- /dev/null +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -0,0 +1,200 @@ +get_test_case_helpers()->set_s9e_services(null, $fixture); + + $parser = $container->get('text_formatter.parser'); + $renderer = $container->get('text_formatter.renderer'); + + $parsed_text = $parser->parse($original); + + $this->assertSame($expected, $renderer->render($parsed_text)); + } + + public function get_default_formatting_tests() + { + return array( + array( + '[b]bold[/b]', + 'bold' + ), + array( + '[u]underlined[/u]', + 'underlined' + ), + array( + '[i]italic[/i]', + 'italic' + ), + array( + '[color=#FF0000]colored[/color]', + 'colored' + ), + array( + '[color=red]colored[/color]', + 'colored' + ), + array( + '[size=75]smaller[/size]', + 'smaller' + ), + array( + '[quote]quoted[/quote]', + '
    quoted
    ' + ), + array( + '[quote="username"]quoted[/quote]', + '
    username wrote:quoted
    ' + ), + array( + '[code]unparsed code[/code]', + '

    CODE: Select all

    unparsed code
    ' + ), + array( + '[list]no item[/list]', + '
      ' + ), + array( + '[*]unparsed', + '[*]unparsed' + ), + array( + '[list][*]item[/list]', + '
      • item
      ' + ), + array( + '[list][*]item[/*][/list]', + '
      • item
      ' + ), + array( + '[list=1][*]item[/list]', + '
      1. item
      ' + ), + array( + '[list=a][*]item[/list]', + '
      1. item
      ' + ), + array( + '[list=i][*]item[/list]', + '
      1. item
      ' + ), + array( + '[list=I][*]item[/list]', + '
      1. item
      ' + ), + array( + '[list=disc][*]item[/list]', + '
      • item
      ' + ), + array( + '[list=circle][*]item[/list]', + '
      • item
      ' + ), + array( + '[list=square][*]item[/list]', + '
      • item
      ' + ), + array( + '[img]https://area51.phpbb.com/images/area51.png[/img]', + 'Image' + ), + array( + '[url]https://area51.phpbb.com/[/url]', + 'https://area51.phpbb.com/' + ), + array( + '[url=https://area51.phpbb.com/]Area51[/url]', + 'Area51' + ), + array( + '[email]bbcode-test@phpbb.com[/email]', + 'bbcode-test@phpbb.com' + ), + array( + '[email=bbcode-test@phpbb.com]Email[/email]', + 'Email' + ), + array( + '[attachment=0]filename[/attachment]', + '
      filename
      ' + ), + array( + // PHPBB3-1401 - correct: parsed + '[quote="[test]test"]test [ test[/quote]', + '
      [test]test wrote:test [ test
      ' + ), + array( + // PHPBB3-6117 - correct: parsed + '[quote]test[/quote] test ] and [ test [quote]test[/quote]', + '
      test
      test ] and [ test
      test
      ' + ), + array( + // PHPBB3-6200 - correct: parsed + '[quote="["]test[/quote]', + '
      [ wrote:test
      ' + ), + array( + // PHPBB3-9364 - quoted: "test[/[/b]quote] test" / non-quoted: "[/quote] test" - also failed if layout distorted + '[quote]test[/[/b]quote] test [/quote][/quote] test', + '
      test[/[/b]quote] test
      [/quote] test' + ), + array( + // PHPBB3-8096 - first quote tag parsed, second quote tag unparsed + '[quote="a"]a[/quote][quote="a]a[/quote]', + '
      a wrote:a
      [quote="a]a[/quote]' + ), + array( + // Allow textual bbcodes in textual bbcodes + '[b]bold [i]bold + italic[/i][/b]', + 'bold bold + italic' + ), + array( + // Allow textual bbcodes in url with description + '[url=https://area51.phpbb.com/]Area51 [i]italic[/i][/url]', + 'Area51 italic' + ), + array( + // Allow url with description in textual bbcodes + '[i]italic [url=https://area51.phpbb.com/]Area51[/url][/i]', + 'italic Area51' + ), + array( + // Do not parse textual bbcodes in code + '[code]unparsed code [b]bold [i]bold + italic[/i][/b][/code]', + '

      CODE: Select all

      unparsed code [b]bold [i]bold + italic[/i][/b]
      ' + ), + array( + // Do not parse quote bbcodes in code + '[code]unparsed code [quote="username"]quoted[/quote][/code]', + '

      CODE: Select all

      unparsed code [quote="username"]quoted[/quote]
      ' + ), +/* + array( + // Textual bbcode nesting into textual bbcode + '[b]bold [i]bold + italic[/b] italic[/i]', + 'bold bold + italic italic' + ), +*/ + array( + "[code]\tline1\n line2[/code]", + '

      CODE: Select all

         line1
      ' . "\n" . '  line2
      ' + ), + ); + } +} diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php new file mode 100644 index 0000000000..2ea4b3031b --- /dev/null +++ b/tests/text_formatter/s9e/factory_test.php @@ -0,0 +1,182 @@ +createXMLDataSet(__DIR__ . '/fixtures/factory.xml'); + } + + public function get_cache_dir() + { + return __DIR__ . '/../../tmp/'; + } + + public function get_factory() + { + global $phpbb_root_path; + + $this->cache = new phpbb_mock_cache; + + $dal = new \phpbb\textformatter\data_access( + $this->new_dbal(), + 'phpbb_bbcodes', + 'phpbb_smilies', + 'phpbb_styles', + 'phpbb_words', + $phpbb_root_path . 'styles/' + ); + + $factory = new \phpbb\textformatter\s9e\factory( + $dal, + $this->cache, + $this->get_cache_dir(), + '_foo_parser', + '_foo_renderer' + ); + + return $factory; + } + + public function test_get_configurator() + { + $configurator = $this->get_factory()->get_configurator(); + + $this->assertInstanceOf('s9e\\TextFormatter\\Configurator', $configurator); + + $this->assertTrue(isset($configurator->plugins['Autoemail'])); + $this->assertTrue(isset($configurator->plugins['Autolink'])); + + $this->assertTrue(isset($configurator->BBCodes['B'])); + $this->assertTrue(isset($configurator->BBCodes['CODE'])); + $this->assertTrue(isset($configurator->BBCodes['COLOR'])); + $this->assertTrue(isset($configurator->BBCodes['EMAIL'])); + $this->assertTrue(isset($configurator->BBCodes['FLASH'])); + $this->assertTrue(isset($configurator->BBCodes['I'])); + $this->assertTrue(isset($configurator->BBCodes['IMG'])); + $this->assertTrue(isset($configurator->BBCodes['LIST'])); + $this->assertTrue(isset($configurator->BBCodes['*'])); + $this->assertTrue(isset($configurator->BBCodes['QUOTE'])); + $this->assertTrue(isset($configurator->BBCodes['SIZE'])); + $this->assertTrue(isset($configurator->BBCodes['U'])); + $this->assertTrue(isset($configurator->BBCodes['URL'])); + + // This custom BBCode should be set + $this->assertTrue(isset($configurator->BBCodes['CUSTOM'])); + + // This unsafe custom BBCode will trigger an exception and should be ignored + $this->assertFalse(isset($configurator->BBCodes['UNSAFE'])); + + $this->assertTrue(isset($configurator->Emoticons[':D'])); + } + + public function test_regenerate() + { + list($parser, $renderer) = $this->get_factory()->regenerate(); + + $this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser); + $this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer); + + $this->assertEquals($parser, $this->cache->get('_foo_parser'), 'The parser was not cached'); + $this->assertEquals( + array( + 'class' => get_class($renderer), + 'renderer' => serialize($renderer) + ), + $this->cache->get('_foo_renderer'), + 'The renderer was not cached' + ); + + $file = $this->get_cache_dir() . get_class($renderer) . '.php'; + $this->assertFileExists($file); + unlink($file); + } + + public function test_tidy() + { + $factory = $this->get_factory(); + + // Create a fake "old" cache file + $old_file = $this->get_cache_dir() . 's9e_foo.php'; + touch($old_file); + + // Create a current renderer + list($parser, $renderer) = $factory->regenerate(); + $new_file = $this->get_cache_dir() . get_class($renderer) . '.php'; + + // Tidy the cache + $factory->tidy(); + + $this->assertFileExists($new_file, 'The current renderer has been deleted'); + $this->assertFileNotExists($old_file, 'The old renderer has not been deleted'); + + unlink($new_file); + } + + public function test_local_url() + { + global $config, $user, $request; + + $config = array( + 'force_server_vars' => true, + 'server_protocol' => 'http://', + 'server_name' => 'path', + 'server_port' => 80, + 'script_path' => '/to', + 'cookie_secure' => false + ); + $user = new phpbb_mock_user; + $request = new phpbb_mock_request; + + $fixture = __DIR__ . '/fixtures/local_url.xml'; + $renderer = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.renderer'); + + $this->assertSame( + 'http://path/to/foo', + $renderer->render('[local]foo[/local]') + ); + } + + public function test_smilies_special_chars() + { + // Use a smiley that contains every special chars in every field + $fixture = __DIR__ . '/fixtures/smilies_special_chars.xml'; + $renderer = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.renderer'); + + $this->assertSame( + '"\'<&>', + $renderer->render('"\'<&>') + ); + } + + /** + * @testdox {INTTEXT} is supported in custom BBCodes + */ + public function test_inttext_token() + { + $fixture = __DIR__ . '/fixtures/inttext_token.xml'; + $container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture); + $parser = $container->get('text_formatter.parser'); + $renderer = $container->get('text_formatter.renderer'); + + $original = '[spoiler=ɎɆS]text[/spoiler]'; + $expected = '
      ɎɆS
      text
      '; + $this->assertSame($expected, $renderer->render($parser->parse($original))); + + $original = '[spoiler=N:O:P:E]text[/spoiler]'; + $expected = $original; + $this->assertSame($expected, $renderer->render($parser->parse($original))); + } +} diff --git a/tests/text_formatter/s9e/fixtures/default_formatting.xml b/tests/text_formatter/s9e/fixtures/default_formatting.xml new file mode 100644 index 0000000000..2b7236fb30 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/default_formatting.xml @@ -0,0 +1,466 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 1 + :D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 1 + 1 + + + 2 + :-D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 2 + 1 + + + 3 + :grin: + Very Happy + icon_e_biggrin.gif + 15 + 17 + 3 + 1 + + + 4 + :) + Smile + icon_e_smile.gif + 15 + 17 + 4 + 1 + + + 5 + :-) + Smile + icon_e_smile.gif + 15 + 17 + 5 + 1 + + + 6 + :smile: + Smile + icon_e_smile.gif + 15 + 17 + 6 + 1 + + + 7 + ;) + Wink + icon_e_wink.gif + 15 + 17 + 7 + 1 + + + 8 + ;-) + Wink + icon_e_wink.gif + 15 + 17 + 8 + 1 + + + 9 + :wink: + Wink + icon_e_wink.gif + 15 + 17 + 9 + 1 + + + 10 + :( + Sad + icon_e_sad.gif + 15 + 17 + 10 + 1 + + + 11 + :-( + Sad + icon_e_sad.gif + 15 + 17 + 11 + 1 + + + 12 + :sad: + Sad + icon_e_sad.gif + 15 + 17 + 12 + 1 + + + 13 + :o + Surprised + icon_e_surprised.gif + 15 + 17 + 13 + 1 + + + 14 + :-o + Surprised + icon_e_surprised.gif + 15 + 17 + 14 + 1 + + + 15 + :eek: + Surprised + icon_e_surprised.gif + 15 + 17 + 15 + 1 + + + 16 + :shock: + Shocked + icon_eek.gif + 15 + 17 + 16 + 1 + + + 17 + :? + Confused + icon_e_confused.gif + 15 + 17 + 17 + 1 + + + 18 + :-? + Confused + icon_e_confused.gif + 15 + 17 + 18 + 1 + + + 19 + :???: + Confused + icon_e_confused.gif + 15 + 17 + 19 + 1 + + + 20 + 8-) + Cool + icon_cool.gif + 15 + 17 + 20 + 1 + + + 21 + :cool: + Cool + icon_cool.gif + 15 + 17 + 21 + 1 + + + 22 + :lol: + Laughing + icon_lol.gif + 15 + 17 + 22 + 1 + + + 23 + :x + Mad + icon_mad.gif + 15 + 17 + 23 + 1 + + + 24 + :-x + Mad + icon_mad.gif + 15 + 17 + 24 + 1 + + + 25 + :mad: + Mad + icon_mad.gif + 15 + 17 + 25 + 1 + + + 26 + :P + Razz + icon_razz.gif + 15 + 17 + 26 + 1 + + + 27 + :-P + Razz + icon_razz.gif + 15 + 17 + 27 + 1 + + + 28 + :razz: + Razz + icon_razz.gif + 15 + 17 + 28 + 1 + + + 29 + :oops: + Embarrassed + icon_redface.gif + 15 + 17 + 29 + 1 + + + 30 + :cry: + Crying or Very Sad + icon_cry.gif + 15 + 17 + 30 + 1 + + + 31 + :evil: + Evil or Very Mad + icon_evil.gif + 15 + 17 + 31 + 1 + + + 32 + :twisted: + Twisted Evil + icon_twisted.gif + 15 + 17 + 32 + 1 + + + 33 + :roll: + Rolling Eyes + icon_rolleyes.gif + 15 + 17 + 33 + 1 + + + 34 + :!: + Exclamation + icon_exclaim.gif + 15 + 17 + 34 + 1 + + + 35 + :?: + Question + icon_question.gif + 15 + 17 + 35 + 1 + + + 36 + :idea: + Idea + icon_idea.gif + 15 + 17 + 36 + 1 + + + 37 + :arrow: + Arrow + icon_arrow.gif + 15 + 17 + 37 + 1 + + + 38 + :| + Neutral + icon_neutral.gif + 15 + 17 + 38 + 1 + + + 39 + :-| + Neutral + icon_neutral.gif + 15 + 17 + 39 + 1 + + + 40 + :mrgreen: + Mr. Green + icon_mrgreen.gif + 15 + 17 + 40 + 1 + + + 41 + :geek: + Geek + icon_e_geek.gif + 17 + 17 + 41 + 1 + + + 42 + :ugeek: + Uber Geek + icon_e_ugeek.gif + 17 + 18 + 42 + 1 + +
      + + + style_id + style_name + style_copyright + style_active + style_path + bbcode_bitfield + style_parent_id + style_parent_tree + + 1 + prosilver + &copy; phpBB Group + 1 + prosilver + kNg= + 0 + + +
      + + + word_id + word + replacement + + + 1 + apple + banana + +
      +
      diff --git a/tests/text_formatter/s9e/fixtures/default_lang.xml b/tests/text_formatter/s9e/fixtures/default_lang.xml new file mode 100644 index 0000000000..2cfde4aab2 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/default_lang.xml @@ -0,0 +1,20 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + + + 13 + foo + + 1 + [foo]{TEXT}[/foo] + {L_FOO_BAR} + +
      +
      diff --git a/tests/text_formatter/s9e/fixtures/factory.xml b/tests/text_formatter/s9e/fixtures/factory.xml new file mode 100644 index 0000000000..9ae52e9747 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/factory.xml @@ -0,0 +1,115 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + custom + + 1 + [custom]{TEXT}[/custom] + <span style="color:red">{TEXT}</span> + !\[custom\](.*?)\[/custom\]!ies + '[custom:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/custom:$uid]' + !\[custom:$uid\](.*?)\[/custom:$uid\]!s + <span style="color:red">${1}</span> + + + 14 + unsafe + + 1 + [unsafe]{TEXT}[/unsafe] + <script>{TEXT}</script> + !\[unsafe\](.*?)\[/unsafe\]!ies + '[unsafe:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/unsafe:$uid]' + !\[unsafe:$uid\](.*?)\[/unsafe:$uid\]!s + <script>${1}</script> + +
      + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 1 + :D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 2 + 1 + + + 4 + :) + Smile + icon_e_smile.gif + 15 + 17 + 4 + 1 + + + 10 + :( + Sad + icon_e_sad.gif + 15 + 17 + 10 + 1 + +
      + + + style_id + style_name + style_copyright + style_active + style_path + bbcode_bitfield + style_parent_id + style_parent_tree + + + 1 + prosilver + &copy; phpBB Group + 1 + prosilver + kNg= + 0 + + +
      + + + word_id + word + replacement + + + 1 + apple + banana + +
      +
      diff --git a/tests/text_formatter/s9e/fixtures/inttext_token.xml b/tests/text_formatter/s9e/fixtures/inttext_token.xml new file mode 100644 index 0000000000..30b971f315 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/inttext_token.xml @@ -0,0 +1,27 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + spoiler= + + 1 + [spoiler={INTTEXT}]{TEXT}[/spoiler] +
      {INTTEXT}
      {TEXT}
      ]]>
      + + +
      ${1}
      ${2}
      ]]>
      +
      +
      +
      diff --git a/tests/text_formatter/s9e/fixtures/local_url.xml b/tests/text_formatter/s9e/fixtures/local_url.xml new file mode 100644 index 0000000000..9db2bf4710 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/local_url.xml @@ -0,0 +1,28 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + local + + 1 + [local]{LOCAL_URL}[/local] + {LOCAL_URL}]]> + + bbcode_specialchars('${1}').'[/local:$uid]']]> + + http://path/to/phpBB/${1}]]> + +
      +
      diff --git a/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml b/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml new file mode 100644 index 0000000000..d3a7cfa4f7 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml @@ -0,0 +1,23 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 1 + "'<&> + "'<&> + "'<&>.png + 15 + 17 + 2 + 1 + +
      +
      diff --git a/tests/text_formatter/s9e/fixtures/style_inheritance.xml b/tests/text_formatter/s9e/fixtures/style_inheritance.xml new file mode 100644 index 0000000000..a692d0ef2d --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/style_inheritance.xml @@ -0,0 +1,66 @@ + + + + style_id + style_name + style_copyright + style_active + style_path + bbcode_bitfield + style_parent_id + style_parent_tree + + + 1 + foo + + 1 + foo + + QA== + 0 + + + + 2 + fooplus + + 1 + fooplus + QA== + 1 + + + + 3 + fooplusplus + + 1 + fooplusplus + QA== + 2 + + + + 4 + bar + + 1 + bar + + QA== + 0 + + + + 5 + barplus + + 1 + barplus + QA== + 4 + + +
      +
      diff --git a/tests/text_formatter/s9e/fixtures/styles.xml b/tests/text_formatter/s9e/fixtures/styles.xml new file mode 100644 index 0000000000..8004412aea --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles.xml @@ -0,0 +1,36 @@ + + + + style_id + style_name + style_copyright + style_active + style_path + bbcode_bitfield + style_parent_id + style_parent_tree + + + 1 + foo + + 1 + foo + + QA== + 0 + + + + 2 + bar + + 1 + bar + + QA== + 0 + + +
      +
      diff --git a/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html new file mode 100644 index 0000000000..a17446581a --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html @@ -0,0 +1,40 @@ +
        +
          +
        + +
          +
        + +
      • +
      • + +
        {USERNAME} {L_WROTE}{L_COLON} +
        +
        + +

        {L_CODE}{L_COLON} {L_SELECT_ALL_CODE}

        +
        + +
        +
        + + + + + + + + + + +{TEXT} + +{TEXT} + +{L_IMAGE} + +{DESCRIPTION} + +{DESCRIPTION} + + diff --git a/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html new file mode 100644 index 0000000000..cd2f0acae3 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html @@ -0,0 +1,40 @@ +
          +
            +
          + +
            +
          + +
        • +
        • + +
          {USERNAME} {L_WROTE}{L_COLON} +
          +
          + +

          {L_CODE}{L_COLON} {L_SELECT_ALL_CODE}

          +
          + +
          +
          + + + + + + + + + + +{TEXT} + +{TEXT} + +{L_IMAGE} + +{DESCRIPTION} + +{DESCRIPTION} + + diff --git a/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html new file mode 100644 index 0000000000..909c09df5a --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html @@ -0,0 +1,40 @@ +
            +
              +
            + +
              +
            + +
          • +
          • + +
            {USERNAME} {L_WROTE}{L_COLON} +
            +
            + +

            {L_CODE}{L_COLON} {L_SELECT_ALL_CODE}

            +
            + +
            +
            + + + + + + + + + + +{TEXT} + +{TEXT} + +{L_IMAGE} + +{DESCRIPTION} + +{DESCRIPTION} + + diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php new file mode 100644 index 0000000000..528305a11c --- /dev/null +++ b/tests/text_formatter/s9e/parser_test.php @@ -0,0 +1,162 @@ +getMockBuilder('s9e\\TextFormatter\\Parser') + ->disableOriginalConstructor() + ->getMock(); + + $cache = $this->getMock('phpbb_mock_cache'); + $cache->expects($this->once()) + ->method('get') + ->with('_foo_parser') + ->will($this->returnValue($mock)); + + $parser = new \phpbb\textformatter\s9e\parser( + $cache, + '_foo_parser', + $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), + new phpbb_mock_container_builder + ); + } + + public function test_use_from_cache() + { + $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') + ->disableOriginalConstructor() + ->getMock(); + + $mock->expects($this->once()) + ->method('parse') + ->with('test') + ->will($this->returnValue('test')); + + $cache = new phpbb_mock_cache; + $cache->put('_foo_parser', $mock); + + $parser = new \phpbb\textformatter\s9e\parser( + $cache, + '_foo_parser', + $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), + new phpbb_mock_container_builder + ); + + $this->assertSame('test', $parser->parse('test')); + } + + public function test_regenerate_on_cache_miss() + { + $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') + ->disableOriginalConstructor() + ->getMock(); + + $mock->expects($this->once()) + ->method('parse') + ->with('test') + ->will($this->returnValue('test')); + + $factory = $this->getMock('stdClass', array('regenerate')); + $factory->expects($this->once()) + ->method('regenerate') + ->will($this->returnValue(array($mock, false))); + + $container = new phpbb_mock_container_builder; + $container->set('text_formatter.s9e.factory', $factory); + + $parser = new \phpbb\textformatter\s9e\parser( + new phpbb_mock_cache, + '_foo_parser', + $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), + $container + ); + + $this->assertSame('test', $parser->parse('test')); + } + + /** + * @dataProvider get_options_tests() + */ + public function test_options($adapter_method, $adapter_arg, $concrete_method, $concrete_arg) + { + $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') + ->setMethods(array($concrete_method)) + ->disableOriginalConstructor() + ->getMock(); + foreach ((array) $concrete_arg as $i => $concrete_arg) + { + $mock->expects($this->at($i)) + ->method($concrete_method) + ->with($concrete_arg); + } + + $cache = new phpbb_mock_cache; + $cache->put('_foo_parser', $mock); + + $parser = new \phpbb\textformatter\s9e\parser( + $cache, + '_foo_parser', + $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), + new phpbb_mock_container_builder + ); + + call_user_func_array(array($parser, $adapter_method), (array) $adapter_arg); + } + + public function get_options_tests() + { + return array( + array( + 'disable_bbcode', 'url', + 'disableTag', 'URL' + ), + array( + 'disable_bbcodes', null, + 'disablePlugin', 'BBCodes' + ), + array( + 'disable_censor', null, + 'disablePlugin', 'Censor' + ), + array( + 'disable_magic_url', null, + 'disablePlugin', array('Autoemail', 'Autolink') + ), + array( + 'disable_smilies', null, + 'disablePlugin', 'Emoticons' + ), + array( + 'enable_bbcode', 'url', + 'enableTag', 'URL' + ), + array( + 'enable_bbcodes', null, + 'enablePlugin', 'BBCodes' + ), + array( + 'enable_censor', null, + 'enablePlugin', 'Censor' + ), + array( + 'enable_magic_url', null, + 'enablePlugin', array('Autoemail', 'Autolink') + ), + array( + 'enable_smilies', null, + 'enablePlugin', 'Emoticons' + ) + ); + } +} diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php new file mode 100644 index 0000000000..76babbfdf3 --- /dev/null +++ b/tests/text_formatter/s9e/renderer_test.php @@ -0,0 +1,355 @@ +get_cache_dir() . 'renderer_foo.php', + 'getMockForAbstractClass('s9e\\TextFormatter\\Renderer'); + + $cache = $this->getMock('phpbb_mock_cache'); + $cache->expects($this->once()) + ->method('get') + ->with('_foo_renderer') + ->will($this->returnValue(array('class' => 'renderer_foo', 'renderer' => serialize($mock)))); + + $container = new phpbb_mock_container_builder; + $container->set('text_formatter.s9e.factory', $factory); + + $renderer = new \phpbb\textformatter\s9e\renderer( + $cache, + $this->get_cache_dir(), + '_foo_renderer', + $container + ); + } + + public function test_regenerate_on_cache_miss() + { + $mock = $this->getMockForAbstractClass('s9e\\TextFormatter\\Renderer'); + + $cache = $this->getMock('phpbb_mock_cache'); + $cache->expects($this->once()) + ->method('get') + ->with('_foo_renderer') + ->will($this->returnValue(false)); + + $factory = $this->getMock('stdClass', array('regenerate')); + $factory->expects($this->once()) + ->method('regenerate') + ->will($this->returnValue(array($mock, false))); + + $container = new phpbb_mock_container_builder; + $container->set('text_formatter.s9e.factory', $factory); + + $renderer = new \phpbb\textformatter\s9e\renderer( + $cache, + $this->get_cache_dir(), + '_foo_renderer', + $container + ); + } + + /** + * @dataProvider get_options_cases + */ + public function test_options($original, $expected, $calls) + { + $container = new phpbb_mock_container_builder; + $this->get_test_case_helpers()->set_s9e_services($container); + + $renderer = $container->get('text_formatter.renderer'); + + foreach ($calls as $method => $arg) + { + $renderer->$method($arg); + } + + $this->assertSame($expected, $renderer->render($original)); + } + + public function get_options_cases() + { + return array( + array( + 'apple', + 'banana', + array('set_viewcensors' => true) + ), + array( + 'apple', + 'apple', + array('set_viewcensors' => false) + ), + array( + '[flash=123,456]http://example.org/foo.swf[/flash]', + '', + array('set_viewflash' => true) + ), + array( + '[img]http://example.org/foo.png[/img]', + 'Image', + array('set_viewimg' => true) + ), + array( + ':)', + ':)', + array('set_viewsmilies' => true) + ), + array( + ':)', + ':)', + array('set_viewsmilies' => false) + ), + ); + } + + /** + * @dataProvider get_default_options_cases + */ + public function test_default_options($original, $expected, $setup = null) + { + $container = new phpbb_mock_container_builder; + + if (isset($setup)) + { + $setup($container, $this); + } + + $this->get_test_case_helpers()->set_s9e_services($container); + + $this->assertSame($expected, $container->get('text_formatter.renderer')->render($original)); + } + + public function get_default_options_cases() + { + return array( + array( + 'apple', + 'banana' + ), + array( + 'apple', + 'banana', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewcensors', false); + + $phpbb_container->set('user', $user); + } + ), + array( + 'apple', + 'banana', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewcensors', false); + + $config = new \phpbb\config\config(array('allow_nocensors' => true)); + + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $config); + } + ), + array( + 'apple', + 'apple', + function ($phpbb_container, $test) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewcensors', false); + + $config = new \phpbb\config\config(array('allow_nocensors' => true)); + + $auth = $test->getMock('phpbb\\auth\\auth'); + $auth->expects($test->any()) + ->method('acl_get') + ->with('u_chgcensors') + ->will($test->returnValue(true)); + + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $config); + $phpbb_container->set('auth', $auth); + } + ), + array( + '[flash=123,456]http://localhost/foo.swf[/flash]', + '' + ), + array( + '[flash=123,456]http://localhost/foo.swf[/flash]', + 'http://localhost/foo.swf', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewflash', false); + + $phpbb_container->set('user', $user); + } + ), + array( + '[img]http://localhost/mrgreen.gif[/img]', + 'Image' + ), + array( + '[img]http://localhost/mrgreen.gif[/img]', + 'http://localhost/mrgreen.gif', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewimg', false); + + $phpbb_container->set('user', $user); + } + ), + array( + ':)', + ':)' + ), + array( + ':)', + ':)', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('smilies', false); + + $phpbb_container->set('user', $user); + } + ), + ); + } + + public function test_default_lang() + { + global $phpbb_container; + $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/default_lang.xml'); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + + $this->assertSame('FOO_BAR', $renderer->render('')); + } + + /** + * @dataProvider get_option_names + */ + public function test_get_option($option_name) + { + global $phpbb_container; + $this->get_test_case_helpers()->set_s9e_services(); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + + $renderer->{'set_' . $option_name}(false); + $this->assertFalse($renderer->{'get_' . $option_name}()); + $renderer->{'set_' . $option_name}(true); + $this->assertTrue($renderer->{'get_' . $option_name}()); + } + + public function get_option_names() + { + return array( + array('viewcensors'), + array('viewflash'), + array('viewimg'), + array('viewsmilies') + ); + } + + public function test_styles() + { + global $phpbb_container; + + $tests = array( + 1 => 'bold', + 2 => 'bold' + ); + + foreach ($tests as $style_id => $expected) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->style = array('style_id' => $style_id); + + $phpbb_container = new phpbb_mock_container_builder; + $phpbb_container->set('user', $user); + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/styles.xml', __DIR__ . '/fixtures/styles/'); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + $this->assertSame( + $expected, + $renderer->render('[b]bold[/b]') + ); + } + } + + public function test_style_inheritance1() + { + global $phpbb_container; + + // Style 3 inherits from 2 which inherits from 1. Only style 1 has a bbcode.html + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->style = array('style_id' => 3); + + $phpbb_container = new phpbb_mock_container_builder; + $phpbb_container->set('user', $user); + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/style_inheritance.xml', __DIR__ . '/fixtures/styles/'); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + $this->assertSame( + 'bold', + $renderer->render('[b]bold[/b]') + ); + } + + public function test_style_inheritance2() + { + global $phpbb_container; + + // Style 5 inherits from 4, but both have a bbcode.html + $tests = array( + 4 => 'bold', + 5 => 'bold' + ); + + foreach ($tests as $style_id => $expected) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->style = array('style_id' => $style_id); + + $phpbb_container = new phpbb_mock_container_builder; + $phpbb_container->set('user', $user); + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/style_inheritance.xml', __DIR__ . '/fixtures/styles/'); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + $this->assertSame( + $expected, + $renderer->render('[b]bold[/b]') + ); + } + } +} diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php new file mode 100644 index 0000000000..510beba817 --- /dev/null +++ b/tests/text_formatter/s9e/utils_test.php @@ -0,0 +1,157 @@ +get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + + $this->assertSame($expected, $utils->unparse($original)); + } + + public function get_unparse_tests() + { + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + "Multi
            \nline
            ", + "Multi\nline" + ), + array( + '[b]bold[/b]', + '[b]bold[/b]' + ) + ); + } + + /** + * @dataProvider get_remove_formatting_tests + */ + public function test_remove_formatting($original, $expected) + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + + $this->assertSame($expected, $utils->remove_formatting($original)); + } + + public function get_remove_formatting_tests() + { + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + "Multi
            \nline
            ", + "Multi\nline" + ), + array( + '[b]bold[/b]', + 'bold' + ) + ); + } + + /** + * @dataProvider get_clean_formatting_tests + */ + public function test_clean_formatting($original, $expected) + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + + $this->assertSame($expected, $utils->clean_formatting($original)); + } + + public function get_clean_formatting_tests() + { + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + "Multi
            \nline
            ", + "Multi\nline" + ), + array( + '[b]bold[/b]', + ' bold ' + ) + ); + } + + /** + * @dataProvider get_remove_bbcode_tests + */ + public function test_remove_bbcode($original, $name, $depth, $expected) + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + + $this->assertSame($expected, $utils->remove_bbcode($original, $name, $depth)); + } + + public function get_remove_bbcode_tests() + { + return array( + array( + 'Plain text', + 'b', + 1, + 'Plain text' + ), + array( + '[quote="u0"][quote="u1"][quote="u2"]q2[/quote] +q1[/quote] +q0[/quote] +[b]bold[/b]', + 'quote', + 0, + ' +[b]bold[/b]' + ), + array( + '[quote="u0"][quote="u1"][quote="u2"]q2[/quote] +q1[/quote] +q0[/quote] +[b]bold[/b]', + 'quote', + 1, + '[quote="u0"] +q0[/quote] +[b]bold[/b]' + ), + array( + '[quote="u0"][quote="u1"][quote="u2"]q2[/quote] +q1[/quote] +q0[/quote] +[b]bold[/b]', + 'quote', + 2, + '[quote="u0"][quote="u1"] +q1[/quote] +q0[/quote] +[b]bold[/b]' + ), + ); + } +} diff --git a/tests/text_processing/decode_message_test.php b/tests/text_processing/decode_message_test.php new file mode 100644 index 0000000000..855b3c6c57 --- /dev/null +++ b/tests/text_processing/decode_message_test.php @@ -0,0 +1,87 @@ +assertSame($expected, $actual); + } + + public function get_legacy_tests() + { + return array( + array( + "&<>"'", + "&<>"'" + ), + array( + ':)', + ':)' + ), + /** + * Fails as per PHPBB3-8420 + * @link http://tracker.phpbb.com/browse/PHPBB3-8420 + * + array( + '[url=http://example.com:2cpxwbdy]:arrow: here[/url:2cpxwbdy]', + '[url=http://example.com] :arrow: here[/url]', + '2cpxwbdy' + ), + */ + ); + } + + /** + * @dataProvider get_text_formatter_tests + */ + public function test_text_formatter($original, $expected) + { + $this->get_test_case_helpers()->set_s9e_services(); + + $actual = $original; + decode_message($actual); + + $this->assertSame($expected, $actual); + } + + public function get_text_formatter_tests() + { + return array( + array( + "&<>\"'", + "&<>"'" + ), + array( + ':)', + ':)' + ), + array( + "a
            \nb
            ", + "a\nb" + ), + /** + * @link http://tracker.phpbb.com/browse/PHPBB3-8420 + */ + array( + '[url=http://example.com] :arrow: here[/url]', + '[url=http://example.com] :arrow: here[/url]' + ), + ); + } +} diff --git a/tests/text_processing/fixtures/empty.xml b/tests/text_processing/fixtures/empty.xml new file mode 100644 index 0000000000..d8206ad124 --- /dev/null +++ b/tests/text_processing/fixtures/empty.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/text_processing/fixtures/smilies.xml b/tests/text_processing/fixtures/smilies.xml new file mode 100644 index 0000000000..25b2e60836 --- /dev/null +++ b/tests/text_processing/fixtures/smilies.xml @@ -0,0 +1,443 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 1 + :D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 1 + 1 + + + 2 + :-D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 2 + 1 + + + 3 + :grin: + Very Happy + icon_e_biggrin.gif + 15 + 17 + 3 + 1 + + + 4 + :) + Smile + icon_e_smile.gif + 15 + 17 + 4 + 1 + + + 5 + :-) + Smile + icon_e_smile.gif + 15 + 17 + 5 + 1 + + + 6 + :smile: + Smile + icon_e_smile.gif + 15 + 17 + 6 + 1 + + + 7 + ;) + Wink + icon_e_wink.gif + 15 + 17 + 7 + 1 + + + 8 + ;-) + Wink + icon_e_wink.gif + 15 + 17 + 8 + 1 + + + 9 + :wink: + Wink + icon_e_wink.gif + 15 + 17 + 9 + 1 + + + 10 + :( + Sad + icon_e_sad.gif + 15 + 17 + 10 + 1 + + + 11 + :-( + Sad + icon_e_sad.gif + 15 + 17 + 11 + 1 + + + 12 + :sad: + Sad + icon_e_sad.gif + 15 + 17 + 12 + 1 + + + 13 + :o + Surprised + icon_e_surprised.gif + 15 + 17 + 13 + 1 + + + 14 + :-o + Surprised + icon_e_surprised.gif + 15 + 17 + 14 + 1 + + + 15 + :eek: + Surprised + icon_e_surprised.gif + 15 + 17 + 15 + 1 + + + 16 + :shock: + Shocked + icon_eek.gif + 15 + 17 + 16 + 1 + + + 17 + :? + Confused + icon_e_confused.gif + 15 + 17 + 17 + 1 + + + 18 + :-? + Confused + icon_e_confused.gif + 15 + 17 + 18 + 1 + + + 19 + :???: + Confused + icon_e_confused.gif + 15 + 17 + 19 + 1 + + + 20 + 8-) + Cool + icon_cool.gif + 15 + 17 + 20 + 1 + + + 21 + :cool: + Cool + icon_cool.gif + 15 + 17 + 21 + 1 + + + 22 + :lol: + Laughing + icon_lol.gif + 15 + 17 + 22 + 1 + + + 23 + :x + Mad + icon_mad.gif + 15 + 17 + 23 + 1 + + + 24 + :-x + Mad + icon_mad.gif + 15 + 17 + 24 + 1 + + + 25 + :mad: + Mad + icon_mad.gif + 15 + 17 + 25 + 1 + + + 26 + :P + Razz + icon_razz.gif + 15 + 17 + 26 + 1 + + + 27 + :-P + Razz + icon_razz.gif + 15 + 17 + 27 + 1 + + + 28 + :razz: + Razz + icon_razz.gif + 15 + 17 + 28 + 1 + + + 29 + :oops: + Embarrassed + icon_redface.gif + 15 + 17 + 29 + 1 + + + 30 + :cry: + Crying or Very Sad + icon_cry.gif + 15 + 17 + 30 + 1 + + + 31 + :evil: + Evil or Very Mad + icon_evil.gif + 15 + 17 + 31 + 1 + + + 32 + :twisted: + Twisted Evil + icon_twisted.gif + 15 + 17 + 32 + 1 + + + 33 + :roll: + Rolling Eyes + icon_rolleyes.gif + 15 + 17 + 33 + 1 + + + 34 + :!: + Exclamation + icon_exclaim.gif + 15 + 17 + 34 + 1 + + + 35 + :?: + Question + icon_question.gif + 15 + 17 + 35 + 1 + + + 36 + :idea: + Idea + icon_idea.gif + 15 + 17 + 36 + 1 + + + 37 + :arrow: + Arrow + icon_arrow.gif + 15 + 17 + 37 + 1 + + + 38 + :| + Neutral + icon_neutral.gif + 15 + 17 + 38 + 1 + + + 39 + :-| + Neutral + icon_neutral.gif + 15 + 17 + 39 + 1 + + + 40 + :mrgreen: + Mr. Green + icon_mrgreen.gif + 15 + 17 + 40 + 1 + + + 41 + :geek: + Geek + icon_e_geek.gif + 17 + 17 + 41 + 1 + + + 42 + :ugeek: + Uber Geek + icon_e_ugeek.gif + 17 + 18 + 42 + 1 + + + 43 + 8) + 8) + custom.gif + 17 + 18 + 42 + 1 + +
            +
            diff --git a/tests/text_processing/generate_text_for_display_test.php b/tests/text_processing/generate_text_for_display_test.php index 057416da33..fe83938c0b 100644 --- a/tests/text_processing/generate_text_for_display_test.php +++ b/tests/text_processing/generate_text_for_display_test.php @@ -11,10 +11,8 @@ * */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -require_once dirname(__FILE__) . '/../mock/user.php'; -require_once dirname(__FILE__) . '/../mock/cache.php'; +require_once __DIR__ . '/../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_case { @@ -24,21 +22,175 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca parent::setUp(); - $cache = new phpbb_mock_cache; + $phpbb_dispatcher = new phpbb_mock_event_dispatcher; + $config = new \phpbb\config\config(array()); + set_config(null, null, null, $config); + } - $user = new phpbb_mock_user; + /** + * @dataProvider get_legacy_tests + */ + public function test_legacy($original, $expected, $uid = '', $bitfield = '', $flags = 0, $censor_text = true) + { + global $cache, $user; + + $cache = new phpbb_mock_cache; + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewcensors', true); + $user->optionset('viewflash', true); + $user->optionset('viewimg', true); + $user->optionset('viewsmilies', true); + + $actual = generate_text_for_display($original, $uid, $bitfield, $flags, $censor_text); + + $this->assertSame($expected, $actual); + } + + public function get_legacy_tests() + { + return array( + array( + '', + '' + ), + array( + '0', + '0' + ), + ); + } + + public function test_censor_is_restored() + { + global $phpbb_container; + + $phpbb_container = new phpbb_mock_container_builder; + + $user = new \phpbb\user('\\phpbb\\datetime'); $user->optionset('viewcensors', false); - $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); + $config = new \phpbb\config\config(array('allow_nocensors' => true)); + + $auth = $this->getMock('phpbb\\auth\\auth'); + $auth->expects($this->any()) + ->method('acl_get') + ->with('u_chgcensors') + ->will($this->returnValue(true)); + + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $config); + $phpbb_container->set('auth', $auth); + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container); + $renderer = $phpbb_container->get('text_formatter.renderer'); + + $original = 'apple'; + + $renderer->set_viewcensors(false); + $this->assertSame('apple', $renderer->render($original)); + $renderer->set_viewcensors(true); + $this->assertSame('banana', $renderer->render($original)); + $this->assertSame('apple', generate_text_for_display($original, '', '', 0, false)); + $this->assertSame('banana', $renderer->render($original), 'The original setting was not restored'); + + $renderer->set_viewcensors(false); + $this->assertSame('apple', $renderer->render($original)); + $this->assertSame('banana', generate_text_for_display($original, '', '', 0, truee)); + $this->assertSame('apple', $renderer->render($original), 'The original setting was not restored'); } - public function test_empty_string() + /** + * @dataProvider get_text_formatter_tests + */ + public function test_text_formatter($original, $expected, $censor_text = true, $setup = null) { - $this->assertSame('', generate_text_for_display('', '', '', 0)); + global $phpbb_container; + + $phpbb_container = new phpbb_mock_container_builder; + + if (isset($setup)) + { + $setup($phpbb_container, $this); + } + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container); + + $this->assertSame($expected, generate_text_for_display($original, '', '', 0, $censor_text)); } - public function test_zero_string() + public function get_text_formatter_tests() { - $this->assertSame('0', generate_text_for_display('0', '', '', 0)); + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + 'Hello [url=http://example.org]world[/url]', + 'Hello world' + ), + array( + '&<>"\'', + '&<>"\'' + ), + array( + 'apple', + 'banana', + true + ), + array( + 'apple', + 'apple', + false + ), + array( + '[flash=123,456]http://localhost/foo.swf[/flash]', + '' + ), + array( + '[flash=123,456]http://localhost/foo.swf[/flash]', + 'http://localhost/foo.swf', + true, + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewflash', false); + + $phpbb_container->set('user', $user); + } + ), + array( + '[img]http://localhost/mrgreen.gif[/img]', + 'Image' + ), + array( + '[img]http://localhost/mrgreen.gif[/img]', + 'http://localhost/mrgreen.gif', + true, + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewimg', false); + + $phpbb_container->set('user', $user); + } + ), + array( + ':)', + ':)' + ), + array( + ':)', + ':)', + true, + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('smilies', false); + + $phpbb_container->set('user', $user); + } + ), + ); } } diff --git a/tests/text_processing/generate_text_for_edit_test.php b/tests/text_processing/generate_text_for_edit_test.php new file mode 100644 index 0000000000..85b3a6a0ab --- /dev/null +++ b/tests/text_processing/generate_text_for_edit_test.php @@ -0,0 +1,90 @@ +optionset('viewcensors', false); + + $return = generate_text_for_edit($original, $uid, $flags); + + $this->assertSame($expected, $return['text']); + } + + public function get_legacy_tests() + { + return array( + array( + '', + '' + ), + array( + '0', + '0' + ), + array( + 'Hello [url=http://example.org:1f4coh9x]world[/url:1f4coh9x] :)', + 'Hello [url=http://example.org]world[/url] :)', + '1f4coh9x', + 0 + ), + array( + "&<>"'", + "&<>"'" + ) + ); + } + + /** + * @dataProvider get_text_formatter_tests + */ + public function test_text_formatter($original, $expected) + { + global $phpbb_dispatcher; + $phpbb_dispatcher = new phpbb_mock_event_dispatcher; + $this->get_test_case_helpers()->set_s9e_services(); + + $return = generate_text_for_edit($original, '', 0); + + $this->assertSame($expected, $return['text']); + } + + public function get_text_formatter_tests() + { + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + 'Hello [url=http://example.org]world[/url] :)', + 'Hello [url=http://example.org]world[/url] :)' + ), + array( + '&<>"\'', + "&<>"'" + ) + ); + } +} diff --git a/tests/text_processing/generate_text_for_storage_test.php b/tests/text_processing/generate_text_for_storage_test.php new file mode 100644 index 0000000000..0bacaacfb8 --- /dev/null +++ b/tests/text_processing/generate_text_for_storage_test.php @@ -0,0 +1,70 @@ +set('config', $config); + $this->get_test_case_helpers()->set_s9e_services($phpbb_container); + + $phpbb_dispatcher = new phpbb_mock_event_dispatcher; + } + + /** + * @dataProvider get_text_formatter_tests + */ + public function test_text_formatter($original, $expected, $allow_bbcode = true, $allow_urls = true, $allow_smilies = true, $setup = null) + { + $actual = $original; + $uid = ''; + $bitfield = ''; + $flags = 0; + + if (isset($setup)) + { + $setup(); + } + + generate_text_for_storage($actual, $uid, $bitfield, $flags, $allow_bbcode, $allow_urls, $allow_smilies); + + $this->assertSame($expected, $actual); + } + + public function get_text_formatter_tests() + { + return array( + array( + 'Hello world', + 'Hello world' + ), + array( + 'Hello [url=http://example.org]world[/url] :)', + 'Hello [url=http://example.org]world[/url] :)' + ), + array( + '&<>"\'', + '&<>"\'' + ), + ); + } +} diff --git a/tests/text_processing/message_parser_test.php b/tests/text_processing/message_parser_test.php new file mode 100644 index 0000000000..59af2553f8 --- /dev/null +++ b/tests/text_processing/message_parser_test.php @@ -0,0 +1,532 @@ + 999)); + + $map = array( + array('MAX_FLASH_HEIGHT_EXCEEDED', 123, 'Your flash files may only be up to 123 pixels high.'), + array('MAX_FLASH_WIDTH_EXCEEDED', 456, 'Your flash files may only be up to 456 pixels wide.'), + array('MAX_FONT_SIZE_EXCEEDED', 120, 'You may only use fonts up to size 120.'), + array('MAX_FONT_SIZE_EXCEEDED', 200, 'You may only use fonts up to size 200.'), + array('MAX_IMG_HEIGHT_EXCEEDED', 12, 'Your images may only be up to 12 pixels high.'), + array('MAX_IMG_WIDTH_EXCEEDED', 34, 'Your images may only be up to 34 pixels wide.'), + array('TOO_MANY_SMILIES', 3, 'Your message contains too many smilies. The maximum number of smilies allowed is 3.'), + array('TOO_MANY_URLS', 2, 'Your message contains too many URLs. The maximum number of URLs allowed is 2.'), + array('UNAUTHORISED_BBCODE', '[flash]', 'You cannot use certain BBCodes: [flash].'), + array('UNAUTHORISED_BBCODE', '[img]', 'You cannot use certain BBCodes: [img].'), + array('UNAUTHORISED_BBCODE', '[quote]', 'You cannot use certain BBCodes: [quote].'), + array('UNAUTHORISED_BBCODE', '[url]', 'You cannot use certain BBCodes: [url].'), + ); + + $user = $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(); + $user->expects($this->any()) + ->method('lang') + ->will($this->returnValueMap($map)); + + $user->lang = array( + 'NO_POLL_TITLE' => 'You have to enter a poll title.', + 'POLL_TITLE_TOO_LONG' => 'The poll title must contain fewer than 100 characters.', + 'POLL_TITLE_COMP_TOO_LONG' => 'The parsed size of your poll title is too large, consider removing BBCodes or smilies.', + 'TOO_FEW_POLL_OPTIONS' => 'You must enter at least two poll options.', + 'TOO_MANY_POLL_OPTIONS' => 'You have tried to enter too many poll options.', + 'TOO_MANY_USER_OPTIONS' => 'You cannot specify more options per user than existing poll options.', + 'UNABLE_GET_IMAGE_SIZE' => 'It was not possible to determine the dimensions of the image.' + ); + + $phpbb_container = new phpbb_mock_container_builder; + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $config); + + if (isset($setup)) + { + $setup($parser, $phpbb_container, $this); + } + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container); + } + + /** + * @dataProvider get_test_polls + */ + public function test_parse_poll($poll, $expected, $warn_msg = array()) + { + $this->prepare_s9e_services(); + + $message_parser = new parse_message('Me[i]s[/i]sage'); + + // Add some default values + $poll += array( + 'poll_length' => 123, + 'poll_start' => 123, + 'poll_last_vote' => 123, + 'poll_vote_change' => true, + 'enable_bbcode' => true, + 'enable_urls' => true, + 'enable_smilies' => true, + 'img_status' => true + ); + + $message_parser->parse_poll($poll); + $this->assertSame($expected, array_intersect_key($poll, $expected)); + + $this->assertSame( + 'Me[i]s[/i]sage', + $message_parser->parse(true, true, true, true, true, true, true, false) + ); + + $this->assertSame($warn_msg, $message_parser->warn_msg); + } + + public function get_test_polls() + { + return array( + array( + array( + 'poll_title' => 'foo [b]bar[/b] baz', + 'poll_option_text' => "[i]foo[/i]\nbar\n[i]baz[/i]", + 'poll_max_options' => 3, + 'poll_options_size' => 3 + ), + array( + 'poll_title' => 'foo [b]bar[/b] baz', + 'poll_option_text' => "[i]foo[/i]\nbar\n[i]baz[/i]", + 'poll_options' => array( + '[i]foo[/i]', + 'bar', + '[i]baz[/i]' + ) + ) + ), + array( + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[quote]quote[/quote]\n:)", + 'poll_max_options' => 2, + 'poll_options_size' => 2 + ), + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[quote]quote[/quote]\n:)", + 'poll_options' => array( + '[quote]quote[/quote]', + ':)' + ) + ), + array('You cannot use certain BBCodes: [quote].') + ), + array( + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[flash=12,34]http://example.org/x.swf[/flash]\n:)", + 'poll_max_options' => 2, + 'poll_options_size' => 2 + ), + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[flash=12,34]http://example.org/x.swf[/flash]\n:)", + 'poll_options' => array( + '[flash=12,34]http://example.org/x.swf[/flash]', + ':)' + ) + ), + array('You cannot use certain BBCodes: [flash].') + ), + array( + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[b]x\ny[/b]", + 'poll_max_options' => 2, + 'poll_options_size' => 2 + ), + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[b]x\ny[/b]", + 'poll_options' => array( + '[b]x', + 'y[/b]', + ) + ) + ), + ); + } + + /** + * @dataProvider get_test_cases + */ + public function test_options($original, $expected, array $args, $setup = null, $warn_msg = array()) + { + $this->prepare_s9e_services($setup); + + $message_parser = new parse_message($original); + call_user_func_array(array($message_parser, 'parse'), $args); + + $this->assertSame($expected, $message_parser->message); + $this->assertSame($warn_msg, $message_parser->warn_msg); + } + + public function get_test_cases() + { + return array( + array( + '[b]bold[/b]', + '[b]bold[/b]', + array(true, true, true, true, true, true, true) + ), + array( + '[b]bold[/b]', + '[b]bold[/b]', + array(false, true, true, true, true, true, true) + ), + array( + 'http://example.org', + 'http://example.org', + array(true, true, true, true, true, true, true) + ), + array( + 'http://example.org', + 'http://example.org', + array(true, false, true, true, true, true, true) + ), + array( + ':)', + ':)', + array(true, true, true, true, true, true, true) + ), + array( + ':)', + ':)', + array(true, true, false, true, true, true, true) + ), + array( + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + array(true, true, true, true, true, true, true) + ), + array( + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + array(true, true, true, false, true, true, true), + null, + array('You cannot use certain BBCodes: [img].') + ), + array( + '[flash=12,34]http://example.org/foo.swf[/flash]', + '[flash=12,34]http://example.org/foo.swf[/flash]', + array(true, true, true, true, true, true, true) + ), + array( + '[flash=12,34]http://example.org/foo.swf[/flash]', + '[flash=12,34]http://example.org/foo.swf[/flash]', + array(true, true, true, true, false, true, true), + null, + array('You cannot use certain BBCodes: [flash].') + ), + array( + '[quote="foo"]bar :)[/quote]', + '[quote="foo"]bar :)[/quote]', + array(true, true, true, true, true, true, true) + ), + array( + '[quote="foo"]bar :)[/quote]', + '[quote="foo"]bar :)[/quote]', + array(true, true, true, true, true, false, true), + null, + array('You cannot use certain BBCodes: [quote].') + ), + array( + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + array(true, true, true, true, true, true, true) + ), + array( + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + array(true, true, true, true, true, true, false), + null, + array('You cannot use certain BBCodes: [url].') + ), + array( + '[size=200]200[/size]', + '[size=200]200[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_font_size', 200); + } + ), + array( + '[size=200]200[/size]', + '[size=200]200[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_font_size', 0); + } + ), + array( + '[size=2000]2000[/size]', + '[size=2000]2000[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_font_size', 200); + }, + array('You may only use fonts up to size 200.') + ), + array( + '[size=0]0[/size]', + '[size=0]0[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_font_size', 200); + } + ), + array( + '[size=200]200[/size]', + '[size=200]200[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_font_size', 200); + } + ), + array( + '[size=200]200[/size]', + '[size=200]200[/size]', + array(true, true, true, true, true, true, true, true, 'sig'), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_font_size', 120); + }, + array('You may only use fonts up to size 120.') + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 12); + }, + array('Your images may only be up to 12 pixels high.') + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_width', 34); + }, + array('Your images may only be up to 34 pixels wide.') + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 0); + $phpbb_container->get('config')->set('max_post_img_width', 0); + } + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 100); + $phpbb_container->get('config')->set('max_post_img_width', 100); + } + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_img_height', 12); + $phpbb_container->get('config')->set('max_sig_img_width', 34); + } + ), + array( + '[img]http://example.org/404.png[/img]', + '[img]http://example.org/404.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 12); + }, + array('It was not possible to determine the dimensions of the image.') + ), + array( + '[flash=999,999]http://example.org/foo.swf[/flash]', + '[flash=999,999]http://example.org/foo.swf[/flash]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 123); + }, + array('Your flash files may only be up to 123 pixels high.') + ), + array( + '[flash=999,999]http://example.org/foo.swf[/flash]', + '[flash=999,999]http://example.org/foo.swf[/flash]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_width', 456); + }, + array('Your flash files may only be up to 456 pixels wide.') + ), + array( + ':) :) :)', + ':) :) :)', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_smilies', 3); + } + ), + array( + ':) :) :) :)', + ':) :) :) :)', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_smilies', 3); + }, + array('Your message contains too many smilies. The maximum number of smilies allowed is 3.') + ), + array( + ':) :) :) :)', + ':) :) :) :)', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_smilies', 0); + } + ), + array( + ':) :) :) :)', + ':) :) :) :)', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_smilies', 3); + } + ), + array( + ':) :) :) :)', + ':) :) :) :)', + array(true, true, true, true, true, true, true, true, 'sig'), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_smilies', 3); + }, + array('Your message contains too many smilies. The maximum number of smilies allowed is 3.') + ), + array( + 'http://example.org http://example.org http://example.org', + 'http://example.org http://example.org http://example.org', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_urls', 2); + }, + array('Your message contains too many URLs. The maximum number of URLs allowed is 2.') + ), + array( + 'http://example.org http://example.org http://example.org', + 'http://example.org http://example.org http://example.org', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_urls', 0); + } + ), + array( + 'http://example.org http://example.org http://example.org', + 'http://example.org http://example.org http://example.org', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_urls', 2); + } + ), + ); + } +} + +class phpbb_text_processing_message_parser_test_proxy +{ + protected $response; + + public function stream_open($url) + { + if (strpos($url, '100x100')) + { + // Return a 100 x 100 PNG image + $this->response = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAGQAAABkAQAAAABYmaj5AAAAE0lEQVR4AWOgKxgFo2AUjIJRAAAFeAABHs0ozQAAAABJRU5ErkJggg=='); + } + else + { + $this->response = '404 not found'; + } + + return true; + } + + public function stream_stat() + { + return false; + } + + public function stream_read($len) + { + $chunk = substr($this->response, 0, $len); + $this->response = substr($this->response, $len); + + return $chunk; + } + + public function stream_eof() + { + return ($this->response === false); + } +} diff --git a/tests/text_processing/smilies_test.php b/tests/text_processing/smilies_test.php new file mode 100644 index 0000000000..cd35c25525 --- /dev/null +++ b/tests/text_processing/smilies_test.php @@ -0,0 +1,48 @@ +get_test_case_helpers()->set_s9e_services(null, __DIR__ . '/fixtures/smilies.xml'); + $parser = $container->get('text_formatter.parser'); + $renderer = $container->get('text_formatter.renderer'); + + $this->assertSame($expected, $renderer->render($parser->parse($original))); + } + + public function get_text_formatter_tests() + { + return array( + array( + ':) beginning', + ':) beginning' + ), + array( + 'end :)', + 'end :)' + ), + array( + ':)', + ':)' + ), + array( + 'xx (18) 8) xx', + 'xx (18) 8) xx' + ), + ); + } +} diff --git a/tests/text_processing/strip_bbcode_test.php b/tests/text_processing/strip_bbcode_test.php new file mode 100644 index 0000000000..d0dda89167 --- /dev/null +++ b/tests/text_processing/strip_bbcode_test.php @@ -0,0 +1,38 @@ +assertSame($expected, $actual, '20m4ill1'); + } + + public function test_s9e() + { + $phpbb_container = $this->get_test_case_helpers()->set_s9e_services(); + + $original = '[b]bold[/b]'; + $expected = ' bold '; + + $actual = $original; + strip_bbcode($actual); + + $this->assertSame($expected, $actual); + } +} diff --git a/tests/text_processing/tickets_data/PHPBB3-10002.html b/tests/text_processing/tickets_data/PHPBB3-10002.html new file mode 100644 index 0000000000..82990b2253 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10002.html @@ -0,0 +1,2 @@ +
            • one +
              • two
            \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10002.txt b/tests/text_processing/tickets_data/PHPBB3-10002.txt new file mode 100644 index 0000000000..fe2f29073f --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10002.txt @@ -0,0 +1,2 @@ +[quote][list][*]one +[quote][list][*]two[/list][/quote] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10425.html b/tests/text_processing/tickets_data/PHPBB3-10425.html new file mode 100644 index 0000000000..522b2f8858 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10425.html @@ -0,0 +1,3 @@ +http://ar.wikipedia.org/wiki/Ø§Ù„ØµÙØ­Ø©_الرئيسية
            +http://ar.wikipedia.org/wiki/Ø§Ù„ØµÙØ­Ø©_الرئيسية
            +link \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10425.txt b/tests/text_processing/tickets_data/PHPBB3-10425.txt new file mode 100644 index 0000000000..d93c0446b6 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10425.txt @@ -0,0 +1,3 @@ +http://ar.wikipedia.org/wiki/Ø§Ù„ØµÙØ­Ø©_الرئيسية +[url]http://ar.wikipedia.org/wiki/Ø§Ù„ØµÙØ­Ø©_الرئيسية[/url] +[url=http://ar.wikipedia.org/wiki/Ø§Ù„ØµÙØ­Ø©_الرئيسية]link[/url] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10587.html b/tests/text_processing/tickets_data/PHPBB3-10587.html new file mode 100644 index 0000000000..dd0a483244 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10587.html @@ -0,0 +1,2 @@ +http://www.tx-gaming.net/warzone/tournament.php?tourney[id]=34&action=brackets
            +link \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10587.txt b/tests/text_processing/tickets_data/PHPBB3-10587.txt new file mode 100644 index 0000000000..f81a35eb5f --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10587.txt @@ -0,0 +1,2 @@ +[url]http://www.tx-gaming.net/warzone/tournament.php?tourney[id]=34&action=brackets[/url] +[url="http://www.tx-gaming.net/warzone/tournament.php?tourney[id]=34&action=brackets"]link[/url] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.html b/tests/text_processing/tickets_data/PHPBB3-10922.html new file mode 100644 index 0000000000..cdf8316df0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10922.html @@ -0,0 +1 @@ +user@example.org... \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.txt b/tests/text_processing/tickets_data/PHPBB3-10922.txt new file mode 100644 index 0000000000..348f8a1541 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10922.txt @@ -0,0 +1 @@ +[email]user@example.org[/email][email=user@example.org]...[/email] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10989.html b/tests/text_processing/tickets_data/PHPBB3-10989.html new file mode 100644 index 0000000000..f003ad3dfa --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10989.html @@ -0,0 +1,8 @@ +
            Lorem wrote:[quote="Lorem"
            Suspendisse iaculis porta tempor. Nulla.
            + Nullam a tortor sit amet.
            + Proin ac mi eget magna. + +
            Lorem wrote:Quisque fermentum tortor quis odio scelerisque consequat fermentum urna gravida. In semper vehicula condimentum. Donec suscipit ante imperdiet augue rhoncus.
            + +
            +Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas quis odio orci, sit amet semper. \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10989.txt b/tests/text_processing/tickets_data/PHPBB3-10989.txt new file mode 100644 index 0000000000..dc2430f210 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10989.txt @@ -0,0 +1,8 @@ +[quote="Lorem"][quote="Lorem"[quote] Suspendisse iaculis porta tempor. Nulla.[/quote] + Nullam a tortor sit amet.[/quote] + Proin ac mi eget magna. + +[quote="Lorem"]Quisque fermentum tortor quis odio scelerisque consequat fermentum urna gravida. In semper vehicula condimentum. Donec suscipit ante imperdiet augue rhoncus.[/quote] + + +Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas quis odio orci, sit amet semper. \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.html b/tests/text_processing/tickets_data/PHPBB3-11153.html new file mode 100644 index 0000000000..0f67ac4bc0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11153.html @@ -0,0 +1 @@ +... \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.txt b/tests/text_processing/tickets_data/PHPBB3-11153.txt new file mode 100644 index 0000000000..d2794978d9 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11153.txt @@ -0,0 +1 @@ +[myemail=user@example.org]...[/myemail] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.xml b/tests/text_processing/tickets_data/PHPBB3-11153.xml new file mode 100644 index 0000000000..a7fc69520b --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11153.xml @@ -0,0 +1,28 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + myemail + + 1 + [myemail={EMAIL}]{TEXT}[/myemail] + {TEXT}]]> + + bbcode_specialchars('${1}').':$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${2}')).'[/myemail:$uid]']]> + + ${2}]]> + +
            +
            diff --git a/tests/text_processing/tickets_data/PHPBB3-12195.html b/tests/text_processing/tickets_data/PHPBB3-12195.html new file mode 100644 index 0000000000..d8e0f8d523 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-12195.html @@ -0,0 +1 @@ +Image \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-12195.txt b/tests/text_processing/tickets_data/PHPBB3-12195.txt new file mode 100644 index 0000000000..b66dbd5d96 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-12195.txt @@ -0,0 +1 @@ +[url=//example.org/][img]//example.org/img.png[/img][/url] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.before.php b/tests/text_processing/tickets_data/PHPBB3-3981.before.php new file mode 100644 index 0000000000..20c96d163c --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-3981.before.php @@ -0,0 +1,17 @@ +markTestSkipped('International URLs need idn_to_ascii()'); + } +} diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.html b/tests/text_processing/tickets_data/PHPBB3-3981.html new file mode 100644 index 0000000000..e5f1b4561d --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-3981.html @@ -0,0 +1 @@ +http://www.ööö.com \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.txt b/tests/text_processing/tickets_data/PHPBB3-3981.txt new file mode 100644 index 0000000000..976823f1d1 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-3981.txt @@ -0,0 +1 @@ +[url]http://www.ööö.com[/url] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.html b/tests/text_processing/tickets_data/PHPBB3-7187.html new file mode 100644 index 0000000000..9138779d29 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7187.html @@ -0,0 +1 @@ +
            :geek: :ugeek:
            \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.txt b/tests/text_processing/tickets_data/PHPBB3-7187.txt new file mode 100644 index 0000000000..584151a083 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7187.txt @@ -0,0 +1 @@ +[quote]:geek: :ugeek:[/quote] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.xml b/tests/text_processing/tickets_data/PHPBB3-7187.xml new file mode 100644 index 0000000000..d270b12619 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7187.xml @@ -0,0 +1,33 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 41 + :geek: + Geek + icon_e_geek.gif + 17 + 17 + 41 + 1 + + + 42 + :ugeek: + Uber Geek + icon_e_ugeek.gif + 17 + 18 + 42 + 1 + +
            +
            diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.after.php b/tests/text_processing/tickets_data/PHPBB3-7275.after.php new file mode 100644 index 0000000000..a824cb9b84 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.after.php @@ -0,0 +1,15 @@ +assertSame($original, $parsed_text); +} diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.html b/tests/text_processing/tickets_data/PHPBB3-7275.html new file mode 100644 index 0000000000..12502833fd --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.html @@ -0,0 +1 @@ +
            :)
            \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.txt b/tests/text_processing/tickets_data/PHPBB3-7275.txt new file mode 100644 index 0000000000..8de97d67e0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.txt @@ -0,0 +1 @@ +[center]:)[/center] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.xml b/tests/text_processing/tickets_data/PHPBB3-7275.xml new file mode 100644 index 0000000000..9e979afffb --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.xml @@ -0,0 +1,49 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + center + + 1 + [center]{TEXT}[/center] + {TEXT}]]> + !\[center\](.*?)\[/center\]!ies + + !\[center:$uid\](.*?)\[/center:$uid\]!s + ${1}]]> + +
            + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 4 + :) + Smile + icon_e_smile.gif + 15 + 17 + 4 + 1 + +
            +
            diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.html b/tests/text_processing/tickets_data/PHPBB3-9377.html new file mode 100644 index 0000000000..dcfb79c173 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9377.html @@ -0,0 +1 @@ +red blue red \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.txt b/tests/text_processing/tickets_data/PHPBB3-9377.txt new file mode 100644 index 0000000000..dfd71492c5 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9377.txt @@ -0,0 +1 @@ +[red]red [blue]blue[/blue] red[/red] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.xml b/tests/text_processing/tickets_data/PHPBB3-9377.xml new file mode 100644 index 0000000000..1d8ee3d53f --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9377.xml @@ -0,0 +1,41 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + red + + 1 + [red]{TEXT}[/red] + <span style="color:red">{TEXT}</span> + !\[red\](.*?)\[/red\]!ies + '[red:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/red:$uid]' + !\[red:$uid\](.*?)\[/red:$uid\]!s + <span style="color:red">${1}</span> + + + + 14 + blue + + 1 + [blue]{TEXT}[/blue] + <span style="color:blue">{TEXT}</span> + !\[blue\](.*?)\[/blue\]!ies + '[blue:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/blue:$uid]' + !\[blue:$uid\](.*?)\[/blue:$uid\]!s + <span style="color:blue">${1}</span> + +
            +
            diff --git a/tests/text_processing/tickets_test.php b/tests/text_processing/tickets_test.php new file mode 100644 index 0000000000..d2072a10f5 --- /dev/null +++ b/tests/text_processing/tickets_test.php @@ -0,0 +1,91 @@ +get_test_case_helpers()->set_s9e_services($phpbb_container, $fixture); + + $parser = $phpbb_container->get('text_formatter.parser'); + $renderer = $phpbb_container->get('text_formatter.renderer'); + + if (isset($before_assert)) + { + $test = $this; + $before_assert(get_defined_vars()); + } + + $parsed_text = $parser->parse($original); + + $this->assertSame($expected, $renderer->render($parsed_text)); + + if (isset($after_assert)) + { + $test = $this; + $after_assert(get_defined_vars()); + } + } + + public function get_tickets_data() + { + $tests = array(); + + foreach (glob(__DIR__ . '/tickets_data/*.txt') as $txt_filename) + { + $ticket_id = basename($txt_filename, '.txt'); + $html_filename = substr($txt_filename, 0, -3) . 'html'; + $xml_filename = substr($txt_filename, 0, -3) . 'xml'; + $before_filename = substr($txt_filename, 0, -3) . 'before.php'; + $after_filename = substr($txt_filename, 0, -3) . 'after.php'; + + if (!file_exists($xml_filename)) + { + $xml_filename = __DIR__ . '/../fixtures/empty.xml'; + } + + $before_assert = null; + if (file_exists($before_filename)) + { + include($before_filename); + $before_assert = 'before_assert_' . strtolower(str_replace('-', '_', $ticket_id)); + } + + $after_assert = null; + if (file_exists($after_filename)) + { + include($after_filename); + $after_assert = 'after_assert_' . strtolower(str_replace('-', '_', $ticket_id)); + } + + $tests[] = array( + $ticket_id, + file_get_contents($txt_filename), + file_get_contents($html_filename), + $xml_filename, + $before_assert, + $after_assert + ); + } + + return $tests; + } +} From 261f7eec9c781eedae612418343e7a08341be9ce Mon Sep 17 00:00:00 2001 From: s9e Date: Sat, 22 Nov 2014 20:07:09 +0100 Subject: [PATCH 0143/1676] [ticket/11768] Updated composer.lock PHPBB3-11768 --- phpBB/composer.lock | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index e6dd12e8f0..0489eac83a 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -1048,21 +1048,21 @@ "packages-dev": [ { "name": "fabpot/goutte", - "version": "v1.0.3", + "version": "v1.0.7", "source": { "type": "git", - "url": "https://github.com/fabpot/Goutte.git", - "reference": "75c9f23c4122caf4ea3e87a42a00b471366e707f" + "url": "https://github.com/FriendsOfPHP/Goutte.git", + "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fabpot/Goutte/zipball/75c9f23c4122caf4ea3e87a42a00b471366e707f", - "reference": "75c9f23c4122caf4ea3e87a42a00b471366e707f", + "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/794b196e76bdd37b5155cdecbad311f0a3b07625", + "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625", "shasum": "" }, "require": { "ext-curl": "*", - "guzzle/http": ">=3.0.5,<3.8-dev", + "guzzle/http": "~3.1", "php": ">=5.3.0", "symfony/browser-kit": "~2.1", "symfony/css-selector": "~2.1", @@ -1071,8 +1071,8 @@ "symfony/process": "~2.1" }, "require-dev": { - "guzzle/plugin-history": ">=3.0.5,<3.8-dev", - "guzzle/plugin-mock": ">=3.0.5,<3.8-dev" + "guzzle/plugin-history": "~3.1", + "guzzle/plugin-mock": "~3.1" }, "type": "application", "extra": { @@ -1092,9 +1092,7 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" + "email": "fabien@symfony.com" } ], "description": "A simple PHP Web Scraper", @@ -1102,7 +1100,7 @@ "keywords": [ "scraper" ], - "time": "2013-08-16 06:03:22" + "time": "2014-10-09 15:52:51" }, { "name": "guzzle/common", @@ -1937,16 +1935,16 @@ }, { "name": "sami/sami", - "version": "v1.3", + "version": "v1.4", "source": { "type": "git", - "url": "https://github.com/fabpot/Sami.git", - "reference": "76f2ed80b3420f7e2f6dcd5b7218b5a5781f4110" + "url": "https://github.com/FriendsOfPHP/Sami.git", + "reference": "70f29c781f7bef30181c814b9471b2ceac694454" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fabpot/Sami/zipball/76f2ed80b3420f7e2f6dcd5b7218b5a5781f4110", - "reference": "76f2ed80b3420f7e2f6dcd5b7218b5a5781f4110", + "url": "https://api.github.com/repos/FriendsOfPHP/Sami/zipball/70f29c781f7bef30181c814b9471b2ceac694454", + "reference": "70f29c781f7bef30181c814b9471b2ceac694454", "shasum": "" }, "require": { @@ -1967,7 +1965,7 @@ "type": "application", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -1982,9 +1980,7 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" + "email": "fabien@symfony.com" } ], "description": "Sami, an API documentation generator", @@ -1992,7 +1988,7 @@ "keywords": [ "phpdoc" ], - "time": "2013-11-30 17:16:25" + "time": "2014-06-25 11:24:03" }, { "name": "sebastian/comparator", From d779ae340ad893ae4d4ac8a03dccdad3e11c1799 Mon Sep 17 00:00:00 2001 From: s9e Date: Mon, 24 Nov 2014 18:54:04 +0100 Subject: [PATCH 0144/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 0489eac83a..027cbf36ae 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "872ed9d9204986668afc0b3e633be99e397e201b" + "reference": "001dc34bccf85b75a374e2da96d363c470c798a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/872ed9d9204986668afc0b3e633be99e397e201b", - "reference": "872ed9d9204986668afc0b3e633be99e397e201b", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/001dc34bccf85b75a374e2da96d363c470c798a2", + "reference": "001dc34bccf85b75a374e2da96d363c470c798a2", "shasum": "" }, "require": { @@ -218,7 +218,7 @@ "parser", "shortcodes" ], - "time": "2014-11-22 14:23:43" + "time": "2014-11-24 17:50:45" }, { "name": "symfony/config", From ca9f5344097eff5efef4ab6392109c9df737cf25 Mon Sep 17 00:00:00 2001 From: s9e Date: Thu, 8 Jan 2015 02:02:58 +0100 Subject: [PATCH 0145/1676] [ticket/11768] Restored blank line from develop PHPBB3-11768 --- phpBB/config/default/container/services.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 2b4aa52571..4f1aba953f 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -16,6 +16,7 @@ imports: - { resource: services_text_formatter.yml } - { resource: services_twig.yml } - { resource: services_user.yml } + - { resource: tables.yml } - { resource: parameters.yml } From cf39b02891d5ab021e4abc0932e1bb964cbd680c Mon Sep 17 00:00:00 2001 From: s9e Date: Thu, 8 Jan 2015 11:28:23 +0100 Subject: [PATCH 0146/1676] [ticket/11768] Updated annotations to pass sniff PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 2 +- phpBB/phpbb/textformatter/s9e/parser.php | 10 +++++----- phpBB/phpbb/textformatter/s9e/renderer.php | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 8d61f2caac..39697f6d4b 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -145,7 +145,7 @@ class factory implements \phpbb\textformatter\cache /** * Generate and return a new configured instance of s9e\TextFormatter\Configurator * - * @return s9e\TextFormatter\Configurator + * @return Configurator */ public function get_configurator() { diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 10e33f47e6..58cef8fa9e 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -39,7 +39,7 @@ class parser extends \phpbb\textformatter\parser * @param phpbb\cache\driver_interface $cache * @param string $key Cache key * @param phpbb\user $user - * @param Symfony\Component\DependencyInjection\ContainerInterface $container + * @param ContainerInterface $container * @return null */ public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, ContainerInterface $container) @@ -218,7 +218,7 @@ class parser extends \phpbb\textformatter\parser * * @param string $height * @param integer $max_height - * @param s9e\TextFormatter\Parser\Logger $logger + * @param Logger $logger * @return mixed Original value if valid, FALSE otherwise */ static public function filter_flash_height($height, $max_height, Logger $logger) @@ -240,7 +240,7 @@ class parser extends \phpbb\textformatter\parser * * @param string $width * @param integer $max_width - * @param s9e\TextFormatter\Parser\Logger $logger + * @param Logger $logger * @return mixed Original value if valid, FALSE otherwise */ static public function filter_flash_width($width, $max_width, Logger $logger) @@ -262,7 +262,7 @@ class parser extends \phpbb\textformatter\parser * * @param string $size Original size * @param integer $max_size Maximum allowed size - * @param s9e\TextFormatter\Parser\Logger $logger + * @param Logger $logger * @return mixed Original value if valid, FALSE otherwise */ static public function filter_font_size($size, $max_size, Logger $logger) @@ -289,7 +289,7 @@ class parser extends \phpbb\textformatter\parser * * @param string $url Original URL * @param array $url_config Config used by the URL filter - * @param s9e\TextFormatter\Parser\Logger $logger + * @param Logger $logger * @param integer $max_height Maximum height allowed * @param integer $max_width Maximum width allowed * @return string|bool Original value if valid, FALSE otherwise diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 2c8412f961..c724be7cfe 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -50,9 +50,9 @@ class renderer extends \phpbb\textformatter\renderer * Constructor * * @param phpbb\cache\driver\driver_interface $cache - * @param string $cache_dir Path to the cache dir - * @param string $key Cache key - * @param Symfony\Component\DependencyInjection\ContainerInterface $container + * @param string $cache_dir Path to the cache dir + * @param string $key Cache key + * @param ContainerInterface $container * @return null */ public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, ContainerInterface $container) From dc303cbc993755ec446fcc3f060659668e5073f8 Mon Sep 17 00:00:00 2001 From: s9e Date: Fri, 16 Jan 2015 02:31:14 +0100 Subject: [PATCH 0147/1676] [ticket/11768] Toggled Unicode modifier in relative URL filter get_preg_expression('relative_url') returns an expression that requires it PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 39697f6d4b..06bee34767 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -163,13 +163,11 @@ class factory implements \phpbb\textformatter\cache // Create custom filters for BBCode tokens that are supported in phpBB but not in // s9e\TextFormatter - $filter = new RegexpFilter('#^' . get_preg_expression('relative_url') . '$#D'); + $filter = new RegexpFilter('#^' . get_preg_expression('relative_url') . '$#Du'); $configurator->attributeFilters->add('#local_url', $filter); $configurator->attributeFilters->add('#relative_url', $filter); - $regexp = (phpbb_pcre_utf8_support()) - ? '!^([\p{L}\p{N}\-+,_. ]+)$!uD' - : '!^([a-zA-Z0-9\-+,_. ]+)$!uD'; + $regexp = '!^([\p{L}\p{N}\-+,_. ]+)$!Du'; $configurator->attributeFilters->add('#inttext', new RegexpFilter($regexp)); // Create custom filters for Flash restrictions, which use the same values as the image From e0bb446c57d692b3e968a7a3ccd9d726f0779391 Mon Sep 17 00:00:00 2001 From: s9e Date: Fri, 16 Jan 2015 03:54:42 +0100 Subject: [PATCH 0148/1676] [ticket/11768] Reorganized code for readability No functional change intended PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 06bee34767..d000262bec 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -167,8 +167,9 @@ class factory implements \phpbb\textformatter\cache $configurator->attributeFilters->add('#local_url', $filter); $configurator->attributeFilters->add('#relative_url', $filter); - $regexp = '!^([\p{L}\p{N}\-+,_. ]+)$!Du'; - $configurator->attributeFilters->add('#inttext', new RegexpFilter($regexp)); + // INTTEXT regexp from acp_bbcodes + $filter = new RegexpFilter('!^([\p{L}\p{N}\-+,_. ]+)$!Du'); + $configurator->attributeFilters->add('#inttext', $filter); // Create custom filters for Flash restrictions, which use the same values as the image // restrictions but have their own error message From 72fb380c9fbb0d6fa51236bdc179ba7ef6126a5a Mon Sep 17 00:00:00 2001 From: s9e Date: Wed, 4 Feb 2015 23:07:58 +0100 Subject: [PATCH 0149/1676] [ticket/11768] Updated constructors with explicit dependencies The trade-off is that an instance of phpbb\textformatter\s9e\factory and phpbb\textformatter\data_access is created on any page that uses the parser or the renderer, even when neither need to be regenerated. It has no measureable impact on performance and costs ~20KB of RAM. PHPBB3-11768 --- .../default/container/services_text_formatter.yml | 4 ++-- phpBB/phpbb/textformatter/s9e/parser.php | 6 +++--- phpBB/phpbb/textformatter/s9e/renderer.php | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index 7d21e4498e..3d5fb3766d 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -41,7 +41,7 @@ services: - @cache.driver - %text_formatter.cache.parser.key% - @user - - @service_container + - @text_formatter.s9e.factory text_formatter.s9e.renderer: class: phpbb\textformatter\s9e\renderer @@ -49,7 +49,7 @@ services: - @cache.driver - %text_formatter.cache.dir% - %text_formatter.cache.renderer.key% - - @service_container + - @text_formatter.s9e.factory calls: - [configure_smilies_path, [@config, @path_helper]] - [configure_user, [@user, @config, @auth]] diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 58cef8fa9e..d9f693ba18 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -39,17 +39,17 @@ class parser extends \phpbb\textformatter\parser * @param phpbb\cache\driver_interface $cache * @param string $key Cache key * @param phpbb\user $user - * @param ContainerInterface $container + * @param factory $factory * @return null */ - public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, ContainerInterface $container) + public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, factory $factory) { $this->user = $user; $parser = $cache->get($key); if (!$parser) { - list($parser) = $container->get('text_formatter.s9e.factory')->regenerate(); + list($parser) = $factory->regenerate(); } $this->parser = $parser; diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index c724be7cfe..9fe538e35d 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -49,13 +49,13 @@ class renderer extends \phpbb\textformatter\renderer /** * Constructor * - * @param phpbb\cache\driver\driver_interface $cache - * @param string $cache_dir Path to the cache dir - * @param string $key Cache key - * @param ContainerInterface $container + * @param \phpbb\cache\driver\driver_interface $cache + * @param string $cache_dir Path to the cache dir + * @param string $key Cache key + * @param factory $factory * @return null */ - public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, ContainerInterface $container) + public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, factory $factory) { $renderer_data = $cache->get($key); @@ -82,7 +82,7 @@ class renderer extends \phpbb\textformatter\renderer if (!isset($renderer)) { - list(, $renderer) = $container->get('text_formatter.s9e.factory')->regenerate(); + list(, $renderer) = $factory->regenerate(); } $this->renderer = $renderer; From c4a58bce890869f3d44d145cd43cb036ad99ac74 Mon Sep 17 00:00:00 2001 From: s9e Date: Wed, 4 Feb 2015 23:27:04 +0100 Subject: [PATCH 0150/1676] [ticket/11768] Updated test case helper with new signature PHPBB3-11768 --- tests/test_framework/phpbb_test_case_helpers.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index d0b1573e61..3423d83bb1 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -472,7 +472,7 @@ class phpbb_test_case_helpers $cache, $cache_key_parser, $user, - $container + $factory ); $container->set('text_formatter.parser', $parser); @@ -483,7 +483,7 @@ class phpbb_test_case_helpers $cache, $cache_dir, $cache_key_renderer, - $container + $factory ); $root_path = ($container->hasParameter('core.root_path')) From 90d1a431bde5aaed1e925c3124d081576c759376 Mon Sep 17 00:00:00 2001 From: s9e Date: Thu, 5 Feb 2015 00:01:10 +0100 Subject: [PATCH 0151/1676] [ticket/11768] Updated tests to use the new constructor signature PHPBB3-11768 --- tests/text_formatter/s9e/parser_test.php | 29 ++++++++++++++++------ tests/text_formatter/s9e/renderer_test.php | 17 +++++++------ 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index 528305a11c..aee906e213 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -24,11 +24,16 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case ->with('_foo_parser') ->will($this->returnValue($mock)); + $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') + ->disableOriginalConstructor() + ->getMock(); + $factory->expects($this->never())->method('regenerate'); + $parser = new \phpbb\textformatter\s9e\parser( $cache, '_foo_parser', $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), - new phpbb_mock_container_builder + $factory ); } @@ -46,11 +51,16 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $cache = new phpbb_mock_cache; $cache->put('_foo_parser', $mock); + $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') + ->disableOriginalConstructor() + ->getMock(); + $factory->expects($this->never())->method('regenerate'); + $parser = new \phpbb\textformatter\s9e\parser( $cache, '_foo_parser', $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), - new phpbb_mock_container_builder + $factory ); $this->assertSame('test', $parser->parse('test')); @@ -67,19 +77,18 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case ->with('test') ->will($this->returnValue('test')); - $factory = $this->getMock('stdClass', array('regenerate')); + $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') + ->disableOriginalConstructor() + ->getMock(); $factory->expects($this->once()) ->method('regenerate') ->will($this->returnValue(array($mock, false))); - $container = new phpbb_mock_container_builder; - $container->set('text_formatter.s9e.factory', $factory); - $parser = new \phpbb\textformatter\s9e\parser( new phpbb_mock_cache, '_foo_parser', $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), - $container + $factory ); $this->assertSame('test', $parser->parse('test')); @@ -104,11 +113,15 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $cache = new phpbb_mock_cache; $cache->put('_foo_parser', $mock); + $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') + ->disableOriginalConstructor() + ->getMock(); + $parser = new \phpbb\textformatter\s9e\parser( $cache, '_foo_parser', $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), - new phpbb_mock_container_builder + $factory ); call_user_func_array(array($parser, $adapter_method), (array) $adapter_arg); diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index 76babbfdf3..977c165177 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -33,14 +33,16 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case ->with('_foo_renderer') ->will($this->returnValue(array('class' => 'renderer_foo', 'renderer' => serialize($mock)))); - $container = new phpbb_mock_container_builder; - $container->set('text_formatter.s9e.factory', $factory); + $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') + ->disableOriginalConstructor() + ->getMock(); + $factory->expects($this->never())->method('regenerate'); $renderer = new \phpbb\textformatter\s9e\renderer( $cache, $this->get_cache_dir(), '_foo_renderer', - $container + $factory ); } @@ -54,19 +56,18 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case ->with('_foo_renderer') ->will($this->returnValue(false)); - $factory = $this->getMock('stdClass', array('regenerate')); + $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') + ->disableOriginalConstructor() + ->getMock(); $factory->expects($this->once()) ->method('regenerate') ->will($this->returnValue(array($mock, false))); - $container = new phpbb_mock_container_builder; - $container->set('text_formatter.s9e.factory', $factory); - $renderer = new \phpbb\textformatter\s9e\renderer( $cache, $this->get_cache_dir(), '_foo_renderer', - $container + $factory ); } From 3b115a903a5651f05ac388dea774d1b4022e2ed8 Mon Sep 17 00:00:00 2001 From: s9e Date: Thu, 5 Feb 2015 00:59:29 +0100 Subject: [PATCH 0152/1676] [ticket/11768] Removed unused use statements PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/parser.php | 1 - phpBB/phpbb/textformatter/s9e/renderer.php | 2 -- 2 files changed, 3 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index d9f693ba18..3b490131f2 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -13,7 +13,6 @@ namespace phpbb\textformatter\s9e; -use Symfony\Component\DependencyInjection\ContainerInterface; use s9e\TextFormatter\Parser\BuiltInFilters; use s9e\TextFormatter\Parser\Logger; diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 9fe538e35d..eea01f82af 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -13,8 +13,6 @@ namespace phpbb\textformatter\s9e; -use Symfony\Component\DependencyInjection\ContainerInterface; - /** * s9e\TextFormatter\Renderer adapter * @package phpBB3 From cfbf02bcbad7b00fb81d45260f2fb4bdcbe2ed7f Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 8 Feb 2015 13:35:07 +0100 Subject: [PATCH 0153/1676] [ticket/11768] Re-added the code that got lost in rebase PHPBB3-11768 --- phpBB/composer.json | 1 + phpBB/composer.lock | 11 ++++++----- phpBB/includes/acp/acp_bbcodes.php | 3 ++- phpBB/includes/acp/acp_words.php | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/phpBB/composer.json b/phpBB/composer.json index dcb4000d34..2c734847cf 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -28,6 +28,7 @@ "php": ">=5.3.9", "lusitanian/oauth": "0.2.*", "patchwork/utf8": "1.1.*", + "s9e/text-formatter": "dev-release/php5.3", "symfony/config": "2.7.*@dev", "symfony/console": "2.7.*@dev", "symfony/dependency-injection": "2.7.*@dev", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 027cbf36ae..c619b74f15 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "2038bc8bd0fea66b22774ca7bca11a79", + "hash": "25df57c9c90534dcc86d31175b248719", "packages": [ { "name": "lusitanian/oauth", @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "001dc34bccf85b75a374e2da96d363c470c798a2" + "reference": "3659ed8d9209a4a42f23f7169dbcc0a114fd601f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/001dc34bccf85b75a374e2da96d363c470c798a2", - "reference": "001dc34bccf85b75a374e2da96d363c470c798a2", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/3659ed8d9209a4a42f23f7169dbcc0a114fd601f", + "reference": "3659ed8d9209a4a42f23f7169dbcc0a114fd601f", "shasum": "" }, "require": { @@ -218,7 +218,7 @@ "parser", "shortcodes" ], - "time": "2014-11-24 17:50:45" + "time": "2015-02-06 19:38:34" }, { "name": "symfony/config", @@ -2584,6 +2584,7 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { + "s9e/text-formatter": 20, "symfony/config": 20, "symfony/console": 20, "symfony/dependency-injection": 20, diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index 327af0e0bc..d451b4d899 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -25,7 +25,7 @@ class acp_bbcodes function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher; + global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; $user->add_lang('acp/posting'); @@ -321,6 +321,7 @@ class acp_bbcodes { $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($row['bbcode_tag'])); if ($request->is_ajax()) diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index 1ba247be4d..ea8d47a109 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -28,7 +28,7 @@ class acp_words function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_log, $request; + global $db, $user, $auth, $template, $cache, $phpbb_log, $request, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('acp/posting'); From 6540918ffa3d7203da1f55dc2d08674b378663f3 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 10 Feb 2015 02:24:06 +0100 Subject: [PATCH 0154/1676] [ticket/11768] Added test files PHPBB3-11768 --- tests/text_processing/tickets_data/PHPBB3-10122.html | 1 + tests/text_processing/tickets_data/PHPBB3-10122.txt | 1 + 2 files changed, 2 insertions(+) create mode 100644 tests/text_processing/tickets_data/PHPBB3-10122.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-10122.txt diff --git a/tests/text_processing/tickets_data/PHPBB3-10122.html b/tests/text_processing/tickets_data/PHPBB3-10122.html new file mode 100644 index 0000000000..f0fb6115b2 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10122.html @@ -0,0 +1 @@ +
            • This is my indented text
            \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10122.txt b/tests/text_processing/tickets_data/PHPBB3-10122.txt new file mode 100644 index 0000000000..a5e059df66 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10122.txt @@ -0,0 +1 @@ +[list=none][*]This is my indented text[/list] \ No newline at end of file From 63753bbf1a7a695938c7196fb7c1d9318d7a7375 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 13 Feb 2015 11:17:44 +0100 Subject: [PATCH 0155/1676] [ticket/11768] Uncommented disabled test PHPBB3-11768 --- tests/text_formatter/s9e/default_formatting_test.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index be258868dd..a7d3235c12 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -184,13 +184,11 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case '[code]unparsed code [quote="username"]quoted[/quote][/code]', '

            CODE: Select all

            unparsed code [quote="username"]quoted[/quote]
            ' ), -/* array( // Textual bbcode nesting into textual bbcode '[b]bold [i]bold + italic[/b] italic[/i]', 'bold bold + italic italic' ), -*/ array( "[code]\tline1\n line2[/code]", '

            CODE: Select all

               line1
            ' . "\n" . '  line2
            ' From f6e3e41717e71fb43ea63785cfe7980e33be3fbf Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 13 Feb 2015 11:28:51 +0100 Subject: [PATCH 0156/1676] [ticket/11768] Added support for magic links that start with "www." PHPBB3-11768 --- phpBB/composer.lock | 9 +++++---- phpBB/phpbb/textformatter/s9e/factory.php | 2 +- tests/text_formatter/s9e/default_formatting_test.php | 8 ++++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index c619b74f15..7538a8a83c 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,17 +169,18 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "3659ed8d9209a4a42f23f7169dbcc0a114fd601f" + "reference": "2cfaacd8619ecaebb6de5674b94580689f062f66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/3659ed8d9209a4a42f23f7169dbcc0a114fd601f", - "reference": "3659ed8d9209a4a42f23f7169dbcc0a114fd601f", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/2cfaacd8619ecaebb6de5674b94580689f062f66", + "reference": "2cfaacd8619ecaebb6de5674b94580689f062f66", "shasum": "" }, "require": { "ext-dom": "*", "ext-filter": "*", + "lib-pcre": ">=7.2", "php": ">=5.3.3" }, "suggest": { @@ -218,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-02-06 19:38:34" + "time": "2015-02-13 10:24:14" }, { "name": "symfony/config", diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index d000262bec..77b1a1c916 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -280,7 +280,7 @@ class factory implements \phpbb\textformatter\cache // Load the magic links plugins. We do that after BBCodes so that they use the same tags $configurator->plugins->load('Autoemail'); - $configurator->plugins->load('Autolink'); + $configurator->plugins->load('Autolink', array('matchWww' => true)); // Register some vars with a default value. Those should be set at runtime by whatever calls // the parser diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index a7d3235c12..99a89a8d2e 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -193,6 +193,14 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case "[code]\tline1\n line2[/code]", '

            CODE: Select all

               line1
            ' . "\n" . '  line2
            ' ), + array( + '... http://example.org ...', + '... http://example.org ...' + ), + array( + '... www.example.org ...', + '... www.example.org ...' + ), ); } } From 6bd86a8e8a7c8e2ccf90d02343132c085978cd44 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 15 Feb 2015 03:08:36 +0100 Subject: [PATCH 0157/1676] [ticket/11768] Updated phpbb\textformatter\s9e\factory::regenerate() Returns an associative array rather than a numerically-indexed array. Feels cleaner and more extensible. PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 4 ++-- phpBB/phpbb/textformatter/s9e/parser.php | 2 +- phpBB/phpbb/textformatter/s9e/renderer.php | 2 +- tests/text_formatter/s9e/factory_test.php | 4 ++-- tests/text_formatter/s9e/parser_test.php | 2 +- tests/text_formatter/s9e/renderer_test.php | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 77b1a1c916..ed99bba4a1 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -294,7 +294,7 @@ class factory implements \phpbb\textformatter\cache /** * Regenerate and cache a new parser and renderer * - * @return array Array with two elements: an instance of the parser, an instance of the renderer + * @return array Associative array with at least two elements: "parser" and "renderer" */ public function regenerate() { @@ -315,7 +315,7 @@ class factory implements \phpbb\textformatter\cache ); $this->cache->put($this->cache_key_renderer, $renderer_data); - return array($parser, $renderer); + return array('parser' => $parser, 'renderer' => $renderer); } /** diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 3b490131f2..8e78a18d40 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -48,7 +48,7 @@ class parser extends \phpbb\textformatter\parser $parser = $cache->get($key); if (!$parser) { - list($parser) = $factory->regenerate(); + extract($factory->regenerate()); } $this->parser = $parser; diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index eea01f82af..943056e6ca 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -80,7 +80,7 @@ class renderer extends \phpbb\textformatter\renderer if (!isset($renderer)) { - list(, $renderer) = $factory->regenerate(); + extract($factory->regenerate()); } $this->renderer = $renderer; diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index 2ea4b3031b..9542da8d9a 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -84,7 +84,7 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case public function test_regenerate() { - list($parser, $renderer) = $this->get_factory()->regenerate(); + extract($this->get_factory()->regenerate()); $this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser); $this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer); @@ -113,7 +113,7 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case touch($old_file); // Create a current renderer - list($parser, $renderer) = $factory->regenerate(); + extract($factory->regenerate()); $new_file = $this->get_cache_dir() . get_class($renderer) . '.php'; // Tidy the cache diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index aee906e213..f422e5425a 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -82,7 +82,7 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case ->getMock(); $factory->expects($this->once()) ->method('regenerate') - ->will($this->returnValue(array($mock, false))); + ->will($this->returnValue(array('parser' => $mock))); $parser = new \phpbb\textformatter\s9e\parser( new phpbb_mock_cache, diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index 977c165177..464bcf8eed 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -61,7 +61,7 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case ->getMock(); $factory->expects($this->once()) ->method('regenerate') - ->will($this->returnValue(array($mock, false))); + ->will($this->returnValue(array('parser' => $mock))); $renderer = new \phpbb\textformatter\s9e\renderer( $cache, From 42c1297345cf7b025a82a7c1de7b7f6714de7cb8 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 17 Feb 2015 00:17:57 +0100 Subject: [PATCH 0158/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 7538a8a83c..f006de8b8b 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "2cfaacd8619ecaebb6de5674b94580689f062f66" + "reference": "6d0fad50f73f386a45ec6fefdc8d039df93637ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/2cfaacd8619ecaebb6de5674b94580689f062f66", - "reference": "2cfaacd8619ecaebb6de5674b94580689f062f66", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/6d0fad50f73f386a45ec6fefdc8d039df93637ab", + "reference": "6d0fad50f73f386a45ec6fefdc8d039df93637ab", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-02-13 10:24:14" + "time": "2015-02-16 09:55:05" }, { "name": "symfony/config", From 6578e1c6ec7172016fbfa375dd2fce5cb20f3ce1 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 17 Feb 2015 09:18:31 +0100 Subject: [PATCH 0159/1676] [ticket/11768] Added limited support for [url] in [quote] author PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 23 +++++++++++++++++-- .../s9e/default_formatting_test.php | 12 ++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index ed99bba4a1..47da3e3eb7 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -74,7 +74,14 @@ class factory implements \phpbb\textformatter\cache 'img' => '[IMG src={IMAGEURL;useContent}]', 'list' => '[LIST type={HASHMAP=1:decimal,a:lower-alpha,A:upper-alpha,i:lower-roman,I:upper-roman;optional;postFilter=#simpletext}]{TEXT}[/LIST]', 'li' => '[* $tagName=LI]{TEXT}[/*]', - 'quote' => '[QUOTE author={TEXT1;optional}]{TEXT2}[/QUOTE]', + 'quote' => + "[QUOTE + author={TEXT1;optional} + url={URL;optional} + author={PARSE=/^\\[url=(?'url'.*?)](?'author'.*)\\[\\/url]$/i} + author={PARSE=/^\\[url](?'author'(?'url'.*?))\\[\\/url]$/i} + author={PARSE=/(?'url'https?:\\/\\/[^[\\]]+)/i} + ]{TEXT2}[/QUOTE]", 'size' => '[SIZE={FONTSIZE}]{TEXT}[/SIZE]', 'u' => '[U]{TEXT}[/U]', 'url' => '[URL={URL;useContent}]{TEXT}[/URL]', @@ -424,6 +431,15 @@ class factory implements \phpbb\textformatter\cache $templates['li'] = $fragments['listitem'] . '' . $fragments['listitem_close']; + $fragments['quote_username_open'] = str_replace( + '{USERNAME}', + ' + ' . str_replace('{DESCRIPTION}', '{USERNAME}', $fragments['url']) . ' + {USERNAME} + ', + $fragments['quote_username_open'] + ); + $templates['quote'] = ' @@ -438,7 +454,7 @@ class factory implements \phpbb\textformatter\cache // is post-processed by parse_attachments() $templates['attachment'] = $fragments['inline_attachment_open'] . ' ia ia ' . $fragments['inline_attachment_close']; - // Finally save fragments whose names look like the name of a BBCode, e.g. "flash" + // Add fragments as templates foreach ($fragments as $fragment_name => $fragment) { if (preg_match('#^\\w+$#', $fragment_name)) @@ -447,6 +463,9 @@ class factory implements \phpbb\textformatter\cache } } + // Keep only templates that are named after an existing BBCode + $templates = array_intersect_key($templates, $this->default_definitions); + return $templates; } diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 99a89a8d2e..b28c8b157e 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -201,6 +201,18 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case '... www.example.org ...', '... www.example.org ...' ), + array( + '[quote="[url=http://example.org]xxx[/url]"]...[/quote]', + '
            xxx wrote:...
            ' + ), + array( + '[quote="[url]http://example.org[/url]"]...[/quote]', + '
            ' + ), + array( + '[quote="http://example.org"]...[/quote]', + '
            ' + ), ); } } From f721b85a7835c18459b310e4db74cc0f654b05ec Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 19 Feb 2015 06:05:39 +0100 Subject: [PATCH 0160/1676] [ticket/11768] Replaced the Censor plugin ...with something that is run at rendering time. PHPBB3-11768 --- phpBB/composer.lock | 8 ++--- phpBB/phpbb/textformatter/s9e/factory.php | 38 ++++++++++++---------- phpBB/phpbb/textformatter/s9e/renderer.php | 21 +++++++++++- tests/text_formatter/s9e/parser_test.php | 8 ----- tests/text_formatter/s9e/renderer_test.php | 12 +++---- 5 files changed, 50 insertions(+), 37 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index f006de8b8b..73b41a9e60 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "6d0fad50f73f386a45ec6fefdc8d039df93637ab" + "reference": "0a6bfe116bf348acf209e0d50bd3b3fad86d219e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/6d0fad50f73f386a45ec6fefdc8d039df93637ab", - "reference": "6d0fad50f73f386a45ec6fefdc8d039df93637ab", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/0a6bfe116bf348acf209e0d50bd3b3fad86d219e", + "reference": "0a6bfe116bf348acf209e0d50bd3b3fad86d219e", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-02-16 09:55:05" + "time": "2015-02-19 04:58:59" }, { "name": "symfony/config", diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 47da3e3eb7..557645b0d6 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -264,25 +264,15 @@ class factory implements \phpbb\textformatter\cache } // Load the censored words - foreach ($this->dal->get_words() as $row) + $censor = $this->dal->get_words(); + if (!empty($censor)) { - $configurator->Censor->add($row['word'], $row['replacement']); - } - - if (isset($configurator->Censor)) - { - // Replace the template with a template that applies only when $S_VIEWCENSORS is set - $tag = $configurator->Censor->getTag(); - $tag->template = - ' - - - - - - - **** - '; + // Use a namespaced tag to avoid collisions + $configurator->plugins->load('Censor', array('tagName' => 'censor:tag')); + foreach ($censor as $row) + { + $configurator->Censor->add($row['word'], $row['replacement']); + } } // Load the magic links plugins. We do that after BBCodes so that they use the same tags @@ -307,6 +297,14 @@ class factory implements \phpbb\textformatter\cache { $configurator = $this->get_configurator(); + // Get the censor helper and remove the Censor plugin if applicable + if (isset($configurator->Censor)) + { + $censor = $configurator->Censor->getHelper(); + unset($configurator->Censor); + unset($configurator->tags['censor:tag']); + } + // Create $parser and $renderer extract($configurator->finalize()); @@ -320,6 +318,10 @@ class factory implements \phpbb\textformatter\cache 'class' => get_class($renderer), 'renderer' => serialize($renderer) ); + if (isset($censor)) + { + $renderer_data['censor'] = $censor; + } $this->cache->put($this->cache_key_renderer, $renderer_data); return array('parser' => $parser, 'renderer' => $renderer); diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 943056e6ca..3ec5f38029 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -19,6 +19,11 @@ namespace phpbb\textformatter\s9e; */ class renderer extends \phpbb\textformatter\renderer { + /** + * @var s9e\TextFormatter\Plugins\Censor\Helper + */ + protected $censor; + /** * @var s9e\TextFormatter\Renderer */ @@ -56,7 +61,6 @@ class renderer extends \phpbb\textformatter\renderer public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, factory $factory) { $renderer_data = $cache->get($key); - if ($renderer_data) { $class = $renderer_data['class']; @@ -76,6 +80,11 @@ class renderer extends \phpbb\textformatter\renderer { $renderer = unserialize($renderer_data['renderer']); } + + if (isset($renderer_data['censor'])) + { + $censor = $renderer_data['censor']; + } } if (!isset($renderer)) @@ -83,6 +92,11 @@ class renderer extends \phpbb\textformatter\renderer extract($factory->regenerate()); } + if (isset($censor)) + { + $this->censor = $censor; + } + $this->renderer = $renderer; } @@ -146,6 +160,11 @@ class renderer extends \phpbb\textformatter\renderer { $html = $this->renderer->render($text); + if (isset($this->censor) && $this->viewcensors) + { + $html = $this->censor->censorHtml($html, true); + } + /** * @see bbcode::bbcode_second_pass_code() */ diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index f422e5425a..09af6c22ad 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -138,10 +138,6 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case 'disable_bbcodes', null, 'disablePlugin', 'BBCodes' ), - array( - 'disable_censor', null, - 'disablePlugin', 'Censor' - ), array( 'disable_magic_url', null, 'disablePlugin', array('Autoemail', 'Autolink') @@ -158,10 +154,6 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case 'enable_bbcodes', null, 'enablePlugin', 'BBCodes' ), - array( - 'enable_censor', null, - 'enablePlugin', 'Censor' - ), array( 'enable_magic_url', null, 'enablePlugin', array('Autoemail', 'Autolink') diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index 464bcf8eed..fbf17c8f68 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -93,12 +93,12 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case { return array( array( - 'apple', + 'apple', 'banana', array('set_viewcensors' => true) ), array( - 'apple', + 'apple', 'apple', array('set_viewcensors' => false) ), @@ -146,11 +146,11 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case { return array( array( - 'apple', + 'apple', 'banana' ), array( - 'apple', + 'apple', 'banana', function ($phpbb_container) { @@ -161,7 +161,7 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case } ), array( - 'apple', + 'apple', 'banana', function ($phpbb_container) { @@ -175,7 +175,7 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case } ), array( - 'apple', + 'apple', 'apple', function ($phpbb_container, $test) { From 93c53ed52da7ec2e26bf97b3cc5bba1f1ca403bb Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 19 Feb 2015 06:31:56 +0100 Subject: [PATCH 0161/1676] [ticket/11768] Fixed test PHPBB3-11768 --- tests/text_formatter/s9e/factory_test.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index 9542da8d9a..7c26443579 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -89,15 +89,11 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case $this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser); $this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer); + $renderer_data = $this->cache->get('_foo_renderer'); $this->assertEquals($parser, $this->cache->get('_foo_parser'), 'The parser was not cached'); - $this->assertEquals( - array( - 'class' => get_class($renderer), - 'renderer' => serialize($renderer) - ), - $this->cache->get('_foo_renderer'), - 'The renderer was not cached' - ); + $this->assertEquals(get_class($renderer), $renderer_data['class']); + $this->assertEquals(serialize($renderer), $renderer_data['renderer']); + $this->assertInstanceOf('s9e\\TextFormatter\\Plugins\\Censor\\Helper', $renderer_data['censor']); $file = $this->get_cache_dir() . get_class($renderer) . '.php'; $this->assertFileExists($file); From 3e5ee87b15c70fbfc246b6d8f6d18a186d11d83a Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 20 Feb 2015 06:03:05 +0100 Subject: [PATCH 0162/1676] [ticket/11768] Allowed text in places where text is not valid HTML PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 3 +++ tests/text_formatter/s9e/default_formatting_test.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 557645b0d6..a6639976c4 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -162,6 +162,9 @@ class factory implements \phpbb\textformatter\cache // Convert newlines to br elements by default $configurator->rootRules->enableAutoLineBreaks(); + // Don't automatically ignore text in places where text is not allowed + $configurator->rulesGenerator->remove('IgnoreTextIfDisallowed'); + // Set the rendering engine and configure it to save to the cache dir $configurator->rendering->engine = 'PHP'; $configurator->rendering->engine->cacheDir = $this->cache_dir; diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index b28c8b157e..94d46a58b7 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -68,7 +68,7 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case ), array( '[list]no item[/list]', - '
              ' + '
                no item
              ' ), array( '[*]unparsed', From 414dcae422d21693aad746b4a7a0d49517e478d9 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 21 Feb 2015 11:59:54 +0100 Subject: [PATCH 0163/1676] [ticket/11768] Updated the cache dir to point to the current environment PHPBB3-11768 --- phpBB/config/default/container/services_text_formatter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index 3d5fb3766d..ec5421695d 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -1,5 +1,5 @@ parameters: - text_formatter.cache.dir: %core.root_path%cache/ + text_formatter.cache.dir: %core.root_path%cache/%core.environment%/ text_formatter.cache.parser.key: _text_formatter_parser text_formatter.cache.renderer.key: _text_formatter_renderer From c1ba3a678d5a565b74d893c57eb5133623702350 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 23 Feb 2015 19:03:41 +0100 Subject: [PATCH 0164/1676] [ticket/11768] Added methods to access the library's parser/renderer PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/parser.php | 10 ++++++++++ phpBB/phpbb/textformatter/s9e/renderer.php | 10 ++++++++++ tests/text_formatter/s9e/parser_test.php | 8 ++++++++ tests/text_formatter/s9e/renderer_test.php | 7 +++++++ 4 files changed, 35 insertions(+) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 8e78a18d40..b717dea962 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -191,6 +191,16 @@ class parser extends \phpbb\textformatter\parser return array_unique($errors); } + /** + * Return the instance of s9e\TextFormatter\Parser used by this object + * + * @return s9e\TextFormatter\Parser + */ + public function get_parser() + { + return $this->parser; + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 3ec5f38029..3ccb40cc2d 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -121,6 +121,16 @@ class renderer extends \phpbb\textformatter\renderer $this->renderer->setParameter('STYLE_ID', $user->style['style_id']); } + /** + * Return the instance of s9e\TextFormatter\Renderer used by this object + * + * @return s9e\TextFormatter\Renderer + */ + public function get_renderer() + { + return $this->renderer; + } + /** * {@inheritdoc} */ diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index 09af6c22ad..a3c86e8350 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -7,6 +7,7 @@ * */ require_once __DIR__ . '/../../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../../phpBB/includes/functions_content.php'; require_once __DIR__ . '/../../mock/user.php'; require_once __DIR__ . '/../../mock/cache.php'; @@ -164,4 +165,11 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case ) ); } + + public function test_get_parser() + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $parser = $container->get('text_formatter.parser'); + $this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser->get_parser()); + } } diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index fbf17c8f68..486b17d03f 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -353,4 +353,11 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case ); } } + + public function test_get_renderer() + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $renderer = $container->get('text_formatter.renderer'); + $this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer->get_renderer()); + } } From 73ce09b73a97e351197005ac89113d3451b41da0 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 23 Feb 2015 19:34:10 +0100 Subject: [PATCH 0165/1676] [ticket/11768] Fixed censored words being escaped twice PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index a6639976c4..9af34ab90a 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -274,7 +274,8 @@ class factory implements \phpbb\textformatter\cache $configurator->plugins->load('Censor', array('tagName' => 'censor:tag')); foreach ($censor as $row) { - $configurator->Censor->add($row['word'], $row['replacement']); + // NOTE: words are stored as HTML, we need to decode them to plain text + $configurator->Censor->add(htmlspecialchars_decode($row['word']), htmlspecialchars_decode($row['replacement'])); } } From 5fe74cd3944387831fb1949198409481a1358ee5 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 23 Feb 2015 19:35:49 +0100 Subject: [PATCH 0166/1676] [ticket/11768] Updated censor to apply to XML values PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/renderer.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 3ccb40cc2d..54382d7d1e 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -168,13 +168,14 @@ class renderer extends \phpbb\textformatter\renderer */ public function render($text) { - $html = $this->renderer->render($text); - if (isset($this->censor) && $this->viewcensors) { - $html = $this->censor->censorHtml($html, true); + // NOTE: censorHtml() is XML-safe + $text = $this->censor->censorHtml($text, true); } + $html = $this->renderer->render($text); + /** * @see bbcode::bbcode_second_pass_code() */ From baadc2a6e52437d9d5912c828a337a3c2866c9eb Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 00:38:35 +0100 Subject: [PATCH 0167/1676] [ticket/11768] Removed unused annotations PHPBB3-11768 --- phpBB/phpbb/textformatter/cache.php | 6 ------ phpBB/phpbb/textformatter/data_access.php | 4 ---- phpBB/phpbb/textformatter/parser.php | 4 ---- phpBB/phpbb/textformatter/renderer.php | 4 ---- phpBB/phpbb/textformatter/s9e/factory.php | 1 - phpBB/phpbb/textformatter/s9e/parser.php | 1 - phpBB/phpbb/textformatter/s9e/renderer.php | 1 - phpBB/phpbb/textformatter/s9e/utils.php | 1 - phpBB/phpbb/textformatter/utils.php | 4 ---- 9 files changed, 26 deletions(-) diff --git a/phpBB/phpbb/textformatter/cache.php b/phpBB/phpbb/textformatter/cache.php index c92683217e..a2f7ff7d7b 100644 --- a/phpBB/phpbb/textformatter/cache.php +++ b/phpBB/phpbb/textformatter/cache.php @@ -14,14 +14,8 @@ namespace phpbb\textformatter; /** -* text_formatter.cache service -* * Currently only used to signal that something that could effect the rendering has changed. * BBCodes, smilies, censored words, templates, etc... -* -* @todo functionality should be moved to data_access -* -* @package phpBB3 */ interface cache { diff --git a/phpBB/phpbb/textformatter/data_access.php b/phpBB/phpbb/textformatter/data_access.php index ec6bf9f88e..2576b734f4 100644 --- a/phpBB/phpbb/textformatter/data_access.php +++ b/phpBB/phpbb/textformatter/data_access.php @@ -14,14 +14,10 @@ namespace phpbb\textformatter; /** -* text_formatter.data_access service -* * Data access layer that fetchs BBCodes, smilies and censored words from the database. * To be extended to include insert/update/delete operations. * * Also used to get templates. -* -* @package phpBB3 */ class data_access { diff --git a/phpBB/phpbb/textformatter/parser.php b/phpBB/phpbb/textformatter/parser.php index c595a459bd..6746ccada5 100644 --- a/phpBB/phpbb/textformatter/parser.php +++ b/phpBB/phpbb/textformatter/parser.php @@ -13,10 +13,6 @@ namespace phpbb\textformatter; -/** -* text_formatter.parser service -* @package phpBB3 -*/ abstract class parser { /** diff --git a/phpBB/phpbb/textformatter/renderer.php b/phpBB/phpbb/textformatter/renderer.php index fb731a5294..808beda0a5 100644 --- a/phpBB/phpbb/textformatter/renderer.php +++ b/phpBB/phpbb/textformatter/renderer.php @@ -13,10 +13,6 @@ namespace phpbb\textformatter; -/** -* text_formatter.renderer service -* @package phpBB3 -*/ abstract class renderer { /** diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 9af34ab90a..20ed692850 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -18,7 +18,6 @@ use s9e\TextFormatter\Configurator\Items\AttributeFilters\Regexp as RegexpFilter /** * Creates s9e\TextFormatter objects -* @package phpBB3 */ class factory implements \phpbb\textformatter\cache { diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index b717dea962..977097462b 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -18,7 +18,6 @@ use s9e\TextFormatter\Parser\Logger; /** * s9e\TextFormatter\Parser adapter -* @package phpBB3 */ class parser extends \phpbb\textformatter\parser { diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 54382d7d1e..ab0b032eb4 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -15,7 +15,6 @@ namespace phpbb\textformatter\s9e; /** * s9e\TextFormatter\Renderer adapter -* @package phpBB3 */ class renderer extends \phpbb\textformatter\renderer { diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index 19cd3a11c8..57e836d2d4 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -15,7 +15,6 @@ namespace phpbb\textformatter\s9e; /** * Text manipulation utilities -* @package phpBB3 */ class utils extends \phpbb\textformatter\utils { diff --git a/phpBB/phpbb/textformatter/utils.php b/phpBB/phpbb/textformatter/utils.php index c9bed94553..13942b9248 100644 --- a/phpBB/phpbb/textformatter/utils.php +++ b/phpBB/phpbb/textformatter/utils.php @@ -14,11 +14,7 @@ namespace phpbb\textformatter; /** -* text_formatter.utils service -* * Used to manipulate a parsed text -* -* @package phpBB3 */ abstract class utils { From b12043d4b076b1e214fd85da28358ba829d47a76 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 00:43:46 +0100 Subject: [PATCH 0168/1676] [ticket/11768] Renamed get_words() to get_censored_words() PHPBB3-11768 --- phpBB/phpbb/textformatter/data_access.php | 2 +- phpBB/phpbb/textformatter/s9e/factory.php | 2 +- tests/test_framework/phpbb_test_case_helpers.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/textformatter/data_access.php b/phpBB/phpbb/textformatter/data_access.php index 2576b734f4..008e1fd5c0 100644 --- a/phpBB/phpbb/textformatter/data_access.php +++ b/phpBB/phpbb/textformatter/data_access.php @@ -217,7 +217,7 @@ class data_access * * @return array */ - public function get_words() + public function get_censored_words() { $sql = 'SELECT word, replacement FROM ' . $this->words_table; $result = $this->db->sql_query($sql); diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 20ed692850..ce9d34e247 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -266,7 +266,7 @@ class factory implements \phpbb\textformatter\cache } // Load the censored words - $censor = $this->dal->get_words(); + $censor = $this->dal->get_censored_words(); if (!empty($censor)) { // Use a namespaced tag to avoid collisions diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 3423d83bb1..8e49dca40c 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -394,7 +394,7 @@ class phpbb_test_case_helpers // Mock the DAL, make it return data from the fixture $mb = $this->test_case->getMockBuilder('phpbb\\textformatter\\data_access'); - $mb->setMethods(array('get_bbcodes', 'get_smilies', 'get_styles', 'get_words')); + $mb->setMethods(array('get_bbcodes', 'get_censored_words', 'get_smilies', 'get_styles')); $mb->setConstructorArgs(array( $this->test_case->getMock('phpbb\\db\\driver\\driver'), 'phpbb_bbcodes', @@ -417,7 +417,7 @@ class phpbb_test_case_helpers ->method('get_styles') ->will($this->test_case->returnValue($tables['phpbb_styles'])); $dal->expects($this->test_case->any()) - ->method('get_words') + ->method('get_censored_words') ->will($this->test_case->returnValue($tables['phpbb_words'])); // Cache the parser and renderer with a key based on this method's arguments From 694e515f7c812a470a9a1890aa49ba6ad59385fb Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 00:52:31 +0100 Subject: [PATCH 0169/1676] [ticket/11768] Replaced \phpbb\textformatter\parser with an interface PHPBB3-11768 --- phpBB/phpbb/textformatter/parser.php | 36 ++++++++++-------------- phpBB/phpbb/textformatter/s9e/parser.php | 13 ++++++++- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/phpBB/phpbb/textformatter/parser.php b/phpBB/phpbb/textformatter/parser.php index 6746ccada5..922226cf44 100644 --- a/phpBB/phpbb/textformatter/parser.php +++ b/phpBB/phpbb/textformatter/parser.php @@ -13,7 +13,7 @@ namespace phpbb\textformatter; -abstract class parser +interface parser { /** * Parse given text @@ -21,7 +21,7 @@ abstract class parser * @param string $text * @return string */ - abstract public function parse($text); + public function parse($text); /** * Disable a specific BBCode @@ -29,27 +29,27 @@ abstract class parser * @param string $name BBCode name * @return null */ - abstract public function disable_bbcode($name); + public function disable_bbcode($name); /** * Disable BBCodes in general */ - abstract public function disable_bbcodes(); + public function disable_bbcodes(); /** * Disable the censor */ - abstract public function disable_censor(); + public function disable_censor(); /** * Disable magic URLs */ - abstract public function disable_magic_url(); + public function disable_magic_url(); /** * Disable smilies */ - abstract public function disable_smilies(); + public function disable_smilies(); /** * Enable a specific BBCode @@ -57,34 +57,34 @@ abstract class parser * @param string $name BBCode name * @return null */ - abstract public function enable_bbcode($name); + public function enable_bbcode($name); /** * Enable BBCodes in general */ - abstract public function enable_bbcodes(); + public function enable_bbcodes(); /** * Enable the censor */ - abstract public function enable_censor(); + public function enable_censor(); /** * Enable magic URLs */ - abstract public function enable_magic_url(); + public function enable_magic_url(); /** * Enable smilies */ - abstract public function enable_smilies(); + public function enable_smilies(); /** * Get the list of errors that were generated during last parsing * * @return array */ - abstract public function get_errors(); + public function get_errors(); /** * Set a variable to be used by the parser @@ -99,7 +99,7 @@ abstract class parser * @param mixed $value * @return null */ - abstract public function set_var($name, $value); + public function set_var($name, $value); /** * Set multiple variables to be used by the parser @@ -107,11 +107,5 @@ abstract class parser * @param array Associative array of [name => value] * @return null */ - public function set_vars(array $vars) - { - foreach ($vars as $name => $value) - { - $this->set_var($name, $value); - } - } + public function set_vars(array $vars); } diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 977097462b..de51929994 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -19,7 +19,7 @@ use s9e\TextFormatter\Parser\Logger; /** * s9e\TextFormatter\Parser adapter */ -class parser extends \phpbb\textformatter\parser +class parser implements \phpbb\textformatter\parser { /** * @var s9e\TextFormatter\Parser @@ -219,6 +219,17 @@ class parser extends \phpbb\textformatter\parser } } + /** + * {@inheritdoc} + */ + public function set_vars(array $vars) + { + foreach ($vars as $name => $value) + { + $this->set_var($name, $value); + } + } + /** * Filter a flash object's height * From 3d9596be79cc68bc4caa2263c0bd996606ab3543 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 00:54:37 +0100 Subject: [PATCH 0170/1676] [ticket/11768] Updated renderer annotation PHPBB3-11768 --- phpBB/phpbb/textformatter/renderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/renderer.php b/phpBB/phpbb/textformatter/renderer.php index 808beda0a5..1b0a36715f 100644 --- a/phpBB/phpbb/textformatter/renderer.php +++ b/phpBB/phpbb/textformatter/renderer.php @@ -18,7 +18,7 @@ abstract class renderer /** * Render given text * - * @param string $text Text, as parsed by the text_formatter.parser service + * @param string $text Text, as parsed by something that implements \phpbb\textformatter\parser * @return string */ abstract public function render($text); From 825bc45983f961b4d84f5d869dc0cb6111902aa7 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 00:56:14 +0100 Subject: [PATCH 0171/1676] [ticket/11768] Removed comments PHPBB3-11768 --- phpBB/phpbb/textformatter/renderer.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/phpBB/phpbb/textformatter/renderer.php b/phpBB/phpbb/textformatter/renderer.php index 1b0a36715f..a2375d206b 100644 --- a/phpBB/phpbb/textformatter/renderer.php +++ b/phpBB/phpbb/textformatter/renderer.php @@ -26,8 +26,6 @@ abstract class renderer /** * Automatically set the smilies path based on config * - * Called by the service container - * * @param phpbb\config\config $config * @param phpbb\path_helper $path_helper * @return null @@ -46,7 +44,6 @@ abstract class renderer * Configure this renderer as per the user's settings * * Should set the locale as well as the viewcensor/viewflash/viewimg/viewsmilies options. - * Called by the service container * * @param phpbb\user $user * @param phpbb\config\config $config From 458cf95b1e0614b8dbecaca36c57f21e8a3a7bb7 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 00:58:38 +0100 Subject: [PATCH 0172/1676] [ticket/11768] Replaced class names in annotations with their FQN PHPBB3-11768 --- phpBB/phpbb/textformatter/renderer.php | 10 +++++----- phpBB/phpbb/textformatter/s9e/factory.php | 6 +++--- phpBB/phpbb/textformatter/s9e/parser.php | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/phpBB/phpbb/textformatter/renderer.php b/phpBB/phpbb/textformatter/renderer.php index a2375d206b..d3594bb4ae 100644 --- a/phpBB/phpbb/textformatter/renderer.php +++ b/phpBB/phpbb/textformatter/renderer.php @@ -26,8 +26,8 @@ abstract class renderer /** * Automatically set the smilies path based on config * - * @param phpbb\config\config $config - * @param phpbb\path_helper $path_helper + * @param \phpbb\config\config $config + * @param \phpbb\path_helper $path_helper * @return null */ public function configure_smilies_path(\phpbb\config\config $config, \phpbb\path_helper $path_helper) @@ -45,9 +45,9 @@ abstract class renderer * * Should set the locale as well as the viewcensor/viewflash/viewimg/viewsmilies options. * - * @param phpbb\user $user - * @param phpbb\config\config $config - * @param phpbb\auth\auth $auth + * @param \phpbb\user $user + * @param \phpbb\config\config $config + * @param \phpbb\auth\auth $auth * @return null */ public function configure_user(\phpbb\user $user, \phpbb\config\config $config, \phpbb\auth\auth $auth) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index ce9d34e247..ebed2521b2 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -22,7 +22,7 @@ use s9e\TextFormatter\Configurator\Items\AttributeFilters\Regexp as RegexpFilter class factory implements \phpbb\textformatter\cache { /** - * @var phpbb_cache_driver_interface $cache + * @var \phpbb\cache\driver_interface $cache */ protected $cache; @@ -102,8 +102,8 @@ class factory implements \phpbb\textformatter\cache /** * Constructor * - * @param phpbb\textformatter\data_access $dal - * @param phpbb\cache\driver\driver_interface $cache + * @param \phpbb\textformatter\data_access $dal + * @param \phpbb\cache\driver\driver_interface $cache * @param string $cache_dir Path to the cache dir * @param string $cache_key_parser Cache key used for the parser * @param string $cache_key_renderer Cache key used for the renderer diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index de51929994..4362a7870e 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -34,9 +34,9 @@ class parser implements \phpbb\textformatter\parser /** * Constructor * - * @param phpbb\cache\driver_interface $cache + * @param \phpbb\cache\driver_interface $cache * @param string $key Cache key - * @param phpbb\user $user + * @param \phpbb\user $user * @param factory $factory * @return null */ From 70b7e57497e8822dc237268c54d859125cdea4d0 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 00:59:44 +0100 Subject: [PATCH 0173/1676] [ticket/11768] Renamed property PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index ebed2521b2..a0817a9a4f 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -57,7 +57,7 @@ class factory implements \phpbb\textformatter\cache /** * @var \phpbb\textformatter\data_access */ - protected $dal; + protected $data_access; /** * @var array Default BBCode definitions @@ -102,21 +102,21 @@ class factory implements \phpbb\textformatter\cache /** * Constructor * - * @param \phpbb\textformatter\data_access $dal + * @param \phpbb\textformatter\data_access $data_access * @param \phpbb\cache\driver\driver_interface $cache * @param string $cache_dir Path to the cache dir * @param string $cache_key_parser Cache key used for the parser * @param string $cache_key_renderer Cache key used for the renderer * @return null */ - public function __construct(\phpbb\textformatter\data_access $dal, \phpbb\cache\driver\driver_interface $cache, $cache_dir, $cache_key_parser, $cache_key_renderer) + public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, $cache_dir, $cache_key_parser, $cache_key_renderer) { $this->cache = $cache; $this->cache_dir = $cache_dir; $this->cache_key_parser = $cache_key_parser; $this->cache_key_renderer = $cache_key_renderer; - $this->dal = $dal; + $this->data_access = $data_access; } /** @@ -222,7 +222,7 @@ class factory implements \phpbb\textformatter\cache } // Load custom BBCodes - foreach ($this->dal->get_bbcodes() as $row) + foreach ($this->data_access->get_bbcodes() as $row) { // Insert the board's URL before {LOCAL_URL} tokens $tpl = preg_replace_callback( @@ -247,7 +247,7 @@ class factory implements \phpbb\textformatter\cache } // Load smilies - foreach ($this->dal->get_smilies() as $row) + foreach ($this->data_access->get_smilies() as $row) { $configurator->Emoticons->add( $row['code'], @@ -266,7 +266,7 @@ class factory implements \phpbb\textformatter\cache } // Load the censored words - $censor = $this->dal->get_censored_words(); + $censor = $this->data_access->get_censored_words(); if (!empty($censor)) { // Use a namespaced tag to avoid collisions @@ -339,7 +339,7 @@ class factory implements \phpbb\textformatter\cache { // For each BBCode, build an associative array matching style_ids to their template $templates = array(); - foreach ($this->dal->get_styles_templates() as $style_id => $data) + foreach ($this->data_access->get_styles_templates() as $style_id => $data) { foreach ($this->extract_templates($data['template']) as $bbcode_name => $template) { From 0dd5e62382047f9e256eb148ab199c04a05914b2 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 01:10:58 +0100 Subject: [PATCH 0174/1676] [ticket/11768] Replaced headers in test files PHPBB3-11768 --- tests/text_formatter/s9e/default_formatting_test.php | 10 +++++++--- tests/text_formatter/s9e/factory_test.php | 10 +++++++--- tests/text_formatter/s9e/parser_test.php | 10 +++++++--- tests/text_formatter/s9e/renderer_test.php | 10 +++++++--- tests/text_formatter/s9e/utils_test.php | 10 +++++++--- tests/text_processing/generate_text_for_edit_test.php | 10 +++++++--- .../text_processing/generate_text_for_storage_test.php | 10 +++++++--- tests/text_processing/smilies_test.php | 10 +++++++--- .../tickets_data/PHPBB3-3981.before.php | 10 +++++++--- .../text_processing/tickets_data/PHPBB3-7275.after.php | 10 +++++++--- tests/text_processing/tickets_test.php | 10 +++++++--- 11 files changed, 77 insertions(+), 33 deletions(-) diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 94d46a58b7..79232562cf 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ require_once __DIR__ . '/../../../phpBB/includes/functions.php'; diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index 7c26443579..2930826a78 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ require_once __DIR__ . '/../../../phpBB/includes/functions.php'; diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index a3c86e8350..4b1a23e254 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ require_once __DIR__ . '/../../../phpBB/includes/functions.php'; diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index 486b17d03f..aa0b036c87 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ require_once __DIR__ . '/../../../phpBB/includes/functions.php'; diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index 510beba817..3de9b707c5 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ diff --git a/tests/text_processing/generate_text_for_edit_test.php b/tests/text_processing/generate_text_for_edit_test.php index 85b3a6a0ab..d1db1c6ce1 100644 --- a/tests/text_processing/generate_text_for_edit_test.php +++ b/tests/text_processing/generate_text_for_edit_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ diff --git a/tests/text_processing/generate_text_for_storage_test.php b/tests/text_processing/generate_text_for_storage_test.php index 0bacaacfb8..2a33e2e7be 100644 --- a/tests/text_processing/generate_text_for_storage_test.php +++ b/tests/text_processing/generate_text_for_storage_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ diff --git a/tests/text_processing/smilies_test.php b/tests/text_processing/smilies_test.php index cd35c25525..3bbe065d36 100644 --- a/tests/text_processing/smilies_test.php +++ b/tests/text_processing/smilies_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.before.php b/tests/text_processing/tickets_data/PHPBB3-3981.before.php index 20c96d163c..1c326b52af 100644 --- a/tests/text_processing/tickets_data/PHPBB3-3981.before.php +++ b/tests/text_processing/tickets_data/PHPBB3-3981.before.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.after.php b/tests/text_processing/tickets_data/PHPBB3-7275.after.php index a824cb9b84..99f41d7839 100644 --- a/tests/text_processing/tickets_data/PHPBB3-7275.after.php +++ b/tests/text_processing/tickets_data/PHPBB3-7275.after.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ diff --git a/tests/text_processing/tickets_test.php b/tests/text_processing/tickets_test.php index d2072a10f5..1f7aa58ebb 100644 --- a/tests/text_processing/tickets_test.php +++ b/tests/text_processing/tickets_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ From ed29972e76d4dfd9a670582421c8dff0f470411e Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 01:28:48 +0100 Subject: [PATCH 0175/1676] [ticket/11768] Removed require_once calls that target mock classes PHPBB3-11768 --- tests/text_formatter/s9e/factory_test.php | 2 -- tests/text_formatter/s9e/parser_test.php | 2 -- tests/text_formatter/s9e/renderer_test.php | 1 - tests/text_processing/generate_text_for_edit_test.php | 2 -- tests/text_processing/generate_text_for_storage_test.php | 1 - tests/text_processing/tickets_test.php | 1 - 6 files changed, 9 deletions(-) diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index 2930826a78..d78765b7d5 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -12,8 +12,6 @@ */ require_once __DIR__ . '/../../../phpBB/includes/functions.php'; require_once __DIR__ . '/../../../phpBB/includes/functions_content.php'; -require_once __DIR__ . '/../../mock/user.php'; -require_once __DIR__ . '/../../mock/cache.php'; require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php'; class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index 4b1a23e254..725ff42bfd 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -12,8 +12,6 @@ */ require_once __DIR__ . '/../../../phpBB/includes/functions.php'; require_once __DIR__ . '/../../../phpBB/includes/functions_content.php'; -require_once __DIR__ . '/../../mock/user.php'; -require_once __DIR__ . '/../../mock/cache.php'; class phpbb_textformatter_s9e_parser_test extends phpbb_test_case { diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index aa0b036c87..17d358c3ce 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -12,7 +12,6 @@ */ require_once __DIR__ . '/../../../phpBB/includes/functions.php'; require_once __DIR__ . '/../../../phpBB/includes/functions_content.php'; -require_once __DIR__ . '/../../mock/cache.php'; class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case { diff --git a/tests/text_processing/generate_text_for_edit_test.php b/tests/text_processing/generate_text_for_edit_test.php index d1db1c6ce1..105e8da86b 100644 --- a/tests/text_processing/generate_text_for_edit_test.php +++ b/tests/text_processing/generate_text_for_edit_test.php @@ -13,8 +13,6 @@ require_once __DIR__ . '/../../phpBB/includes/functions.php'; require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; -require_once __DIR__ . '/../mock/user.php'; -require_once __DIR__ . '/../mock/cache.php'; class phpbb_text_processing_generate_text_for_edit_test extends phpbb_test_case { diff --git a/tests/text_processing/generate_text_for_storage_test.php b/tests/text_processing/generate_text_for_storage_test.php index 2a33e2e7be..ffa06e4e02 100644 --- a/tests/text_processing/generate_text_for_storage_test.php +++ b/tests/text_processing/generate_text_for_storage_test.php @@ -14,7 +14,6 @@ require_once __DIR__ . '/../../phpBB/includes/functions.php'; require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php'; -require_once __DIR__ . '/../mock/container_builder.php'; class phpbb_text_processing_generate_text_for_storage_test extends phpbb_test_case { diff --git a/tests/text_processing/tickets_test.php b/tests/text_processing/tickets_test.php index 1f7aa58ebb..8c48a3f4a9 100644 --- a/tests/text_processing/tickets_test.php +++ b/tests/text_processing/tickets_test.php @@ -14,7 +14,6 @@ require_once __DIR__ . '/../../phpBB/includes/functions.php'; require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php'; -require_once __DIR__ . '/../mock/container_builder.php'; class phpbb_text_processing_tickets_test extends phpbb_test_case { From 462696aa4787112b67b2ea8febf6a9f40a461baa Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 01:42:54 +0100 Subject: [PATCH 0176/1676] [ticket/11768] Replaced headers in test files PHPBB3-11768 --- tests/text_processing/decode_message_test.php | 10 +++++++--- tests/text_processing/message_parser_test.php | 10 +++++++--- tests/text_processing/strip_bbcode_test.php | 10 +++++++--- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/tests/text_processing/decode_message_test.php b/tests/text_processing/decode_message_test.php index 855b3c6c57..c9c1da52d5 100644 --- a/tests/text_processing/decode_message_test.php +++ b/tests/text_processing/decode_message_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ diff --git a/tests/text_processing/message_parser_test.php b/tests/text_processing/message_parser_test.php index 59af2553f8..cdbd6c0ca7 100644 --- a/tests/text_processing/message_parser_test.php +++ b/tests/text_processing/message_parser_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ diff --git a/tests/text_processing/strip_bbcode_test.php b/tests/text_processing/strip_bbcode_test.php index d0dda89167..827d8d4a52 100644 --- a/tests/text_processing/strip_bbcode_test.php +++ b/tests/text_processing/strip_bbcode_test.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ From 6cb3fb614022fe4e56a6651ffad4f476056ae520 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 01:44:48 +0100 Subject: [PATCH 0177/1676] [ticket/11768] Replaced FQNs in annotations PHPBB3-11768 --- phpBB/phpbb/textformatter/data_access.php | 2 +- phpBB/phpbb/textformatter/s9e/parser.php | 4 ++-- phpBB/phpbb/textformatter/s9e/renderer.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/textformatter/data_access.php b/phpBB/phpbb/textformatter/data_access.php index 008e1fd5c0..bc33791e15 100644 --- a/phpBB/phpbb/textformatter/data_access.php +++ b/phpBB/phpbb/textformatter/data_access.php @@ -27,7 +27,7 @@ class data_access protected $bbcodes_table; /** - * @var phpbb_db_driver + * @var \phpbb_db_driver */ protected $db; diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 4362a7870e..bf0e715ada 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -22,12 +22,12 @@ use s9e\TextFormatter\Parser\Logger; class parser implements \phpbb\textformatter\parser { /** - * @var s9e\TextFormatter\Parser + * @var \s9e\TextFormatter\Parser */ protected $parser; /** - * @var phpbb\user User object, used for translating errors + * @var \phpbb\user User object, used for translating errors */ protected $user; diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index ab0b032eb4..7b2fef5f4b 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -19,12 +19,12 @@ namespace phpbb\textformatter\s9e; class renderer extends \phpbb\textformatter\renderer { /** - * @var s9e\TextFormatter\Plugins\Censor\Helper + * @var \s9e\TextFormatter\Plugins\Censor\Helper */ protected $censor; /** - * @var s9e\TextFormatter\Renderer + * @var \s9e\TextFormatter\Renderer */ protected $renderer; From d37f2d10f02b6a7a2b12e4b21284df310f39d3e6 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 02:14:09 +0100 Subject: [PATCH 0178/1676] [ticket/11768] Removed the cached renderer We don't need to cache an instance of the renderer, we can just instantiate it every time we need one. PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 9 ++------- phpBB/phpbb/textformatter/s9e/renderer.php | 2 +- tests/text_formatter/s9e/factory_test.php | 1 - tests/text_formatter/s9e/renderer_test.php | 2 +- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index a0817a9a4f..a7cf2d89b8 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -314,13 +314,8 @@ class factory implements \phpbb\textformatter\cache // Cache the parser as-is $this->cache->put($this->cache_key_parser, $parser); - // We need to cache the name of the renderer's generated class so that we can load the class - // before the renderer is unserialized. That's why we save them together, with the renderer - // in serialized form - $renderer_data = array( - 'class' => get_class($renderer), - 'renderer' => serialize($renderer) - ); + // We need to cache the name of the renderer's generated class + $renderer_data = array('class' => get_class($renderer)); if (isset($censor)) { $renderer_data['censor'] = $censor; diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 7b2fef5f4b..71c207e6fc 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -77,7 +77,7 @@ class renderer extends \phpbb\textformatter\renderer if (class_exists($class, false)) { - $renderer = unserialize($renderer_data['renderer']); + $renderer = new $class; } if (isset($renderer_data['censor'])) diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index d78765b7d5..a1378514b4 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -94,7 +94,6 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case $renderer_data = $this->cache->get('_foo_renderer'); $this->assertEquals($parser, $this->cache->get('_foo_parser'), 'The parser was not cached'); $this->assertEquals(get_class($renderer), $renderer_data['class']); - $this->assertEquals(serialize($renderer), $renderer_data['renderer']); $this->assertInstanceOf('s9e\\TextFormatter\\Plugins\\Censor\\Helper', $renderer_data['censor']); $file = $this->get_cache_dir() . get_class($renderer) . '.php'; diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index 17d358c3ce..248b38206a 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -34,7 +34,7 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case $cache->expects($this->once()) ->method('get') ->with('_foo_renderer') - ->will($this->returnValue(array('class' => 'renderer_foo', 'renderer' => serialize($mock)))); + ->will($this->returnValue(array('class' => 'renderer_foo'))); $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') ->disableOriginalConstructor() From 5fe8c6b6f5080c7e174882d279beb2b84ddd01ab Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 02:24:51 +0100 Subject: [PATCH 0179/1676] [ticket/11768] Removed unused var PHPBB3-11768 --- tests/text_formatter/s9e/renderer_test.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index 248b38206a..b93fd8bbe6 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -28,8 +28,6 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case 'getMockForAbstractClass('s9e\\TextFormatter\\Renderer'); - $cache = $this->getMock('phpbb_mock_cache'); $cache->expects($this->once()) ->method('get') From 40340004aac7ac1752c90a1dbca1faa486e668b9 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 02:52:40 +0100 Subject: [PATCH 0180/1676] [ticket/11768] Replaced some references PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index a7cf2d89b8..66dba14ac0 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -354,20 +354,18 @@ class factory implements \phpbb\textformatter\cache } // Replace custom tokens and normalize templates - foreach ($templates as $bbcode_name => &$style_templates) + foreach ($templates as $bbcode_name => $style_templates) { - foreach ($style_templates as &$template) + foreach ($style_templates as $i => $template) { if (isset($this->custom_tokens[$bbcode_name])) { $template = strtr($template, $this->custom_tokens[$bbcode_name]); } - $template = $configurator->templateNormalizer->normalizeTemplate($template); + $templates[$bbcode_name][$i] = $configurator->templateNormalizer->normalizeTemplate($template); } - unset($template); } - unset($style_templates); $bbcodes = array(); foreach ($this->default_definitions as $bbcode_name => $usage) From dc9a28d346370b38c10def92358170a5cef23b36 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 03:07:23 +0100 Subject: [PATCH 0181/1676] [ticket/11768] Replaced extract() calls PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 5 +++-- phpBB/phpbb/textformatter/s9e/parser.php | 3 ++- phpBB/phpbb/textformatter/s9e/renderer.php | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 66dba14ac0..a5b3527822 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -308,8 +308,9 @@ class factory implements \phpbb\textformatter\cache unset($configurator->tags['censor:tag']); } - // Create $parser and $renderer - extract($configurator->finalize()); + $objects = $configurator->finalize(); + $parser = $objects['parser']; + $renderer = $objects['renderer']; // Cache the parser as-is $this->cache->put($this->cache_key_parser, $parser); diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index bf0e715ada..be717bb1c9 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -47,7 +47,8 @@ class parser implements \phpbb\textformatter\parser $parser = $cache->get($key); if (!$parser) { - extract($factory->regenerate()); + $objects = $factory->regenerate(); + $parser = $objects['parser']; } $this->parser = $parser; diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 71c207e6fc..5468af450f 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -88,7 +88,8 @@ class renderer extends \phpbb\textformatter\renderer if (!isset($renderer)) { - extract($factory->regenerate()); + $objects = $factory->regenerate(); + $renderer = $objects['renderer']; } if (isset($censor)) From 78b544920c0d3984dd814cfe59f43c46feac6f12 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 04:18:17 +0100 Subject: [PATCH 0182/1676] [ticket/11768] Added support for creating unsafe BBCodes PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 3 +- tests/text_formatter/s9e/factory_test.php | 18 ++++++++++-- .../s9e/fixtures/unsafe_bbcode.xml | 28 +++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index a5b3527822..9327da4b4f 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -15,6 +15,7 @@ namespace phpbb\textformatter\s9e; use s9e\TextFormatter\Configurator; use s9e\TextFormatter\Configurator\Items\AttributeFilters\Regexp as RegexpFilter; +use s9e\TextFormatter\Configurator\Items\UnsafeTemplate; /** * Creates s9e\TextFormatter objects @@ -236,7 +237,7 @@ class factory implements \phpbb\textformatter\cache try { - $configurator->BBCodes->addCustom($row['bbcode_match'], $tpl); + $configurator->BBCodes->addCustom($row['bbcode_match'], new UnsafeTemplate($tpl)); } catch (\Exception $e) { diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index a1378514b4..8df841605d 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -78,9 +78,6 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case // This custom BBCode should be set $this->assertTrue(isset($configurator->BBCodes['CUSTOM'])); - // This unsafe custom BBCode will trigger an exception and should be ignored - $this->assertFalse(isset($configurator->BBCodes['UNSAFE'])); - $this->assertTrue(isset($configurator->Emoticons[':D'])); } @@ -176,4 +173,19 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case $expected = $original; $this->assertSame($expected, $renderer->render($parser->parse($original))); } + + /** + * @testdox Accepts unsafe custom BBCodes + */ + public function test_unsafe_bbcode() + { + $fixture = __DIR__ . '/fixtures/unsafe_bbcode.xml'; + $container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture); + $parser = $container->get('text_formatter.parser'); + $renderer = $container->get('text_formatter.renderer'); + + $original = '[xss=javascript:alert(1)]text[/xss]'; + $expected = 'text'; + $this->assertSame($expected, $renderer->render($parser->parse($original))); + } } diff --git a/tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml b/tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml new file mode 100644 index 0000000000..55a2e689b6 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml @@ -0,0 +1,28 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + xss= + + 1 + [xss={TEXT1}]{TEXT2}[/xss] + {TEXT2}]]> + + + + ${2}]]> + +
              +
              From aed9ece1bcf5dfb55037b01306da5f6cda8e6824 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 04:19:21 +0100 Subject: [PATCH 0183/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 73b41a9e60..a56036cf8f 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "0a6bfe116bf348acf209e0d50bd3b3fad86d219e" + "reference": "ad2faea5ccbfd2e98cb617abd4c53d263cb84c45" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/0a6bfe116bf348acf209e0d50bd3b3fad86d219e", - "reference": "0a6bfe116bf348acf209e0d50bd3b3fad86d219e", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/ad2faea5ccbfd2e98cb617abd4c53d263cb84c45", + "reference": "ad2faea5ccbfd2e98cb617abd4c53d263cb84c45", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-02-19 04:58:59" + "time": "2015-03-02 08:49:17" }, { "name": "symfony/config", From 1a133d548712f16801ed2a8617aa7eed7f30688c Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 3 Mar 2015 23:38:37 +0100 Subject: [PATCH 0184/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index a56036cf8f..f9c113ded6 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "ad2faea5ccbfd2e98cb617abd4c53d263cb84c45" + "reference": "ddd653042fccea77b4ead018492ca7de9196bc77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/ad2faea5ccbfd2e98cb617abd4c53d263cb84c45", - "reference": "ad2faea5ccbfd2e98cb617abd4c53d263cb84c45", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/ddd653042fccea77b4ead018492ca7de9196bc77", + "reference": "ddd653042fccea77b4ead018492ca7de9196bc77", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-02 08:49:17" + "time": "2015-03-03 22:19:32" }, { "name": "symfony/config", From ec77ff7838e317deb5facacfae31402af08a9902 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 5 Mar 2015 00:06:52 +0100 Subject: [PATCH 0185/1676] [ticket/11768] Invalidate the text_formatter cache whenever a style is installed The acp_styles module purges the cache every time a style is uninstalled, modified or made default, but it does not purge the cache when a new style is installed. Here we invalidate the text_formatter cache (not purge the whole cache) so that new styles take effect immediately. PHPBB3-11768 --- phpBB/includes/acp/acp_styles.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 45f224f8b1..904769f0d1 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -53,6 +53,9 @@ class acp_styles /** @var \phpbb\auth\auth */ protected $auth; + /** @var \phpbb\textformatter\cache */ + protected $text_formatter_cache; + /** @var string */ protected $phpbb_root_path; @@ -61,7 +64,7 @@ class acp_styles public function main($id, $mode) { - global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config; + global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config, $phpbb_container; $this->db = $db; $this->user = $user; @@ -69,6 +72,7 @@ class acp_styles $this->request = $request; $this->cache = $cache; $this->auth = $auth; + $this->text_formatter_cache = $phpbb_container->get('text_formatter.cache'); $this->config = $config; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $phpEx; @@ -216,6 +220,12 @@ class acp_styles } } + // Invalidate the text formatter's cache for the new styles to take effect + if (!empty($installed_names)) + { + $this->text_formatter_cache->invalidate(); + } + // Show message if (!count($messages)) { From 8411db62576a73beb921d58953bb5b767d4ee079 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 6 Mar 2015 10:21:15 +0100 Subject: [PATCH 0186/1676] [ticket/11768] Renamed interfaces PHPBB3-11768 --- .../{cache.php => cache_interface.php} | 2 +- phpBB/phpbb/textformatter/data_access.php | 2 +- .../{parser.php => parser_interface.php} | 2 +- phpBB/phpbb/textformatter/renderer.php | 129 ------------------ .../textformatter/renderer_interface.php | 92 +++++++++++++ phpBB/phpbb/textformatter/s9e/factory.php | 2 +- phpBB/phpbb/textformatter/s9e/parser.php | 2 +- phpBB/phpbb/textformatter/s9e/renderer.php | 35 ++++- 8 files changed, 129 insertions(+), 137 deletions(-) rename phpBB/phpbb/textformatter/{cache.php => cache_interface.php} (96%) rename phpBB/phpbb/textformatter/{parser.php => parser_interface.php} (98%) delete mode 100644 phpBB/phpbb/textformatter/renderer.php create mode 100644 phpBB/phpbb/textformatter/renderer_interface.php diff --git a/phpBB/phpbb/textformatter/cache.php b/phpBB/phpbb/textformatter/cache_interface.php similarity index 96% rename from phpBB/phpbb/textformatter/cache.php rename to phpBB/phpbb/textformatter/cache_interface.php index a2f7ff7d7b..f6b5f195c7 100644 --- a/phpBB/phpbb/textformatter/cache.php +++ b/phpBB/phpbb/textformatter/cache_interface.php @@ -17,7 +17,7 @@ namespace phpbb\textformatter; * Currently only used to signal that something that could effect the rendering has changed. * BBCodes, smilies, censored words, templates, etc... */ -interface cache +interface cache_interface { /** * Invalidate and/or regenerate this text formatter's cache(s) diff --git a/phpBB/phpbb/textformatter/data_access.php b/phpBB/phpbb/textformatter/data_access.php index bc33791e15..2dfba27960 100644 --- a/phpBB/phpbb/textformatter/data_access.php +++ b/phpBB/phpbb/textformatter/data_access.php @@ -27,7 +27,7 @@ class data_access protected $bbcodes_table; /** - * @var \phpbb_db_driver + * @var \phpbb_db_driver_interface */ protected $db; diff --git a/phpBB/phpbb/textformatter/parser.php b/phpBB/phpbb/textformatter/parser_interface.php similarity index 98% rename from phpBB/phpbb/textformatter/parser.php rename to phpBB/phpbb/textformatter/parser_interface.php index 922226cf44..37d538470d 100644 --- a/phpBB/phpbb/textformatter/parser.php +++ b/phpBB/phpbb/textformatter/parser_interface.php @@ -13,7 +13,7 @@ namespace phpbb\textformatter; -interface parser +interface parser_interface { /** * Parse given text diff --git a/phpBB/phpbb/textformatter/renderer.php b/phpBB/phpbb/textformatter/renderer.php deleted file mode 100644 index d3594bb4ae..0000000000 --- a/phpBB/phpbb/textformatter/renderer.php +++ /dev/null @@ -1,129 +0,0 @@ - -* @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\textformatter; - -abstract class renderer -{ - /** - * Render given text - * - * @param string $text Text, as parsed by something that implements \phpbb\textformatter\parser - * @return string - */ - abstract public function render($text); - - /** - * Automatically set the smilies path based on config - * - * @param \phpbb\config\config $config - * @param \phpbb\path_helper $path_helper - * @return null - */ - public function configure_smilies_path(\phpbb\config\config $config, \phpbb\path_helper $path_helper) - { - /** - * @see smiley_text() - */ - $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $path_helper->get_web_root_path(); - - $this->set_smilies_path($root_path . $config['smilies_path']); - } - - /** - * Configure this renderer as per the user's settings - * - * Should set the locale as well as the viewcensor/viewflash/viewimg/viewsmilies options. - * - * @param \phpbb\user $user - * @param \phpbb\config\config $config - * @param \phpbb\auth\auth $auth - * @return null - */ - public function configure_user(\phpbb\user $user, \phpbb\config\config $config, \phpbb\auth\auth $auth) - { - $censor = $user->optionget('viewcensors') || !$config['allow_nocensors'] || !$auth->acl_get('u_chgcensors'); - - $this->set_viewcensors($censor); - $this->set_viewflash($user->optionget('viewflash')); - $this->set_viewimg($user->optionget('viewimg')); - $this->set_viewsmilies($user->optionget('viewsmilies')); - } - - /** - * Set the smilies' path - * - * @return null - */ - abstract public function set_smilies_path($path); - - /** - * Return the value of the "viewcensors" option - * - * @return bool Option's value - */ - abstract public function get_viewcensors(); - - /** - * Return the value of the "viewflash" option - * - * @return bool Option's value - */ - abstract public function get_viewflash(); - - /** - * Return the value of the "viewimg" option - * - * @return bool Option's value - */ - abstract public function get_viewimg(); - - /** - * Return the value of the "viewsmilies" option - * - * @return bool Option's value - */ - abstract public function get_viewsmilies(); - - /** - * Set the "viewcensors" option - * - * @param bool $value Option's value - * @return null - */ - abstract public function set_viewcensors($value); - - /** - * Set the "viewflash" option - * - * @param bool $value Option's value - * @return null - */ - abstract public function set_viewflash($value); - - /** - * Set the "viewimg" option - * - * @param bool $value Option's value - * @return null - */ - abstract public function set_viewimg($value); - - /** - * Set the "viewsmilies" option - * - * @param bool $value Option's value - * @return null - */ - abstract public function set_viewsmilies($value); -} diff --git a/phpBB/phpbb/textformatter/renderer_interface.php b/phpBB/phpbb/textformatter/renderer_interface.php new file mode 100644 index 0000000000..609b0bb642 --- /dev/null +++ b/phpBB/phpbb/textformatter/renderer_interface.php @@ -0,0 +1,92 @@ + +* @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\textformatter; + +interface renderer_interface +{ + /** + * Render given text + * + * @param string $text Text, as parsed by something that implements \phpbb\textformatter\parser + * @return string + */ + public function render($text); + + /** + * Set the smilies' path + * + * @return null + */ + public function set_smilies_path($path); + + /** + * Return the value of the "viewcensors" option + * + * @return bool Option's value + */ + public function get_viewcensors(); + + /** + * Return the value of the "viewflash" option + * + * @return bool Option's value + */ + public function get_viewflash(); + + /** + * Return the value of the "viewimg" option + * + * @return bool Option's value + */ + public function get_viewimg(); + + /** + * Return the value of the "viewsmilies" option + * + * @return bool Option's value + */ + public function get_viewsmilies(); + + /** + * Set the "viewcensors" option + * + * @param bool $value Option's value + * @return null + */ + public function set_viewcensors($value); + + /** + * Set the "viewflash" option + * + * @param bool $value Option's value + * @return null + */ + public function set_viewflash($value); + + /** + * Set the "viewimg" option + * + * @param bool $value Option's value + * @return null + */ + public function set_viewimg($value); + + /** + * Set the "viewsmilies" option + * + * @param bool $value Option's value + * @return null + */ + public function set_viewsmilies($value); +} diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 9327da4b4f..aa37beeef6 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -20,7 +20,7 @@ use s9e\TextFormatter\Configurator\Items\UnsafeTemplate; /** * Creates s9e\TextFormatter objects */ -class factory implements \phpbb\textformatter\cache +class factory implements \phpbb\textformatter\cache_interface { /** * @var \phpbb\cache\driver_interface $cache diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index be717bb1c9..4775175f73 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -19,7 +19,7 @@ use s9e\TextFormatter\Parser\Logger; /** * s9e\TextFormatter\Parser adapter */ -class parser implements \phpbb\textformatter\parser +class parser implements \phpbb\textformatter\parser_interface { /** * @var \s9e\TextFormatter\Parser diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 5468af450f..0b3c63fb91 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -16,7 +16,7 @@ namespace phpbb\textformatter\s9e; /** * s9e\TextFormatter\Renderer adapter */ -class renderer extends \phpbb\textformatter\renderer +class renderer implements \phpbb\textformatter\renderer_interface { /** * @var \s9e\TextFormatter\Plugins\Censor\Helper @@ -101,11 +101,40 @@ class renderer extends \phpbb\textformatter\renderer } /** - * {@inheritdoc} + * Automatically set the smilies path based on config + * + * @param \phpbb\config\config $config + * @param \phpbb\path_helper $path_helper + * @return null + */ + public function configure_smilies_path(\phpbb\config\config $config, \phpbb\path_helper $path_helper) + { + /** + * @see smiley_text() + */ + $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $path_helper->get_web_root_path(); + + $this->set_smilies_path($root_path . $config['smilies_path']); + } + + /** + * Configure this renderer as per the user's settings + * + * Should set the locale as well as the viewcensor/viewflash/viewimg/viewsmilies options. + * + * @param \phpbb\user $user + * @param \phpbb\config\config $config + * @param \phpbb\auth\auth $auth + * @return null */ public function configure_user(\phpbb\user $user, \phpbb\config\config $config, \phpbb\auth\auth $auth) { - parent::configure_user($user, $config, $auth); + $censor = $user->optionget('viewcensors') || !$config['allow_nocensors'] || !$auth->acl_get('u_chgcensors'); + + $this->set_viewcensors($censor); + $this->set_viewflash($user->optionget('viewflash')); + $this->set_viewimg($user->optionget('viewimg')); + $this->set_viewsmilies($user->optionget('viewsmilies')); // Set the stylesheet parameters foreach (array_keys($this->renderer->getParameters()) as $param_name) From a611366bd398c02b47aa71b0fdaa9c16765d0f6b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 6 Mar 2015 10:24:03 +0100 Subject: [PATCH 0187/1676] [ticket/11768] Whitespace [ci skip] PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/renderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 0b3c63fb91..42567098d9 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -129,7 +129,7 @@ class renderer implements \phpbb\textformatter\renderer_interface */ public function configure_user(\phpbb\user $user, \phpbb\config\config $config, \phpbb\auth\auth $auth) { - $censor = $user->optionget('viewcensors') || !$config['allow_nocensors'] || !$auth->acl_get('u_chgcensors'); + $censor = $user->optionget('viewcensors') || !$config['allow_nocensors'] || !$auth->acl_get('u_chgcensors'); $this->set_viewcensors($censor); $this->set_viewflash($user->optionget('viewflash')); From 44fc3d64dafdadd1959ab53dd7e0d1be67c75c1b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 6 Mar 2015 10:46:59 +0100 Subject: [PATCH 0188/1676] [ticket/11768] Made capturing code blocks a bit more flexible PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/renderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 42567098d9..c896c9f1c7 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -209,7 +209,7 @@ class renderer implements \phpbb\textformatter\renderer_interface * @see bbcode::bbcode_second_pass_code() */ $html = preg_replace_callback( - '#()(.*?)()#is', + '#(]*>)(.*?)()#is', function ($captures) { $code = $captures[2]; From 20a1646fc6336635cee89426e3a60bb22cb138de Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 6 Mar 2015 10:50:05 +0100 Subject: [PATCH 0189/1676] [ticket/11768] Renamed utils PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/utils.php | 2 +- .../textformatter/{utils.php => utils_interface.php} | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) rename phpBB/phpbb/textformatter/{utils.php => utils_interface.php} (80%) diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index 57e836d2d4..df4ae4b9ec 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -16,7 +16,7 @@ namespace phpbb\textformatter\s9e; /** * Text manipulation utilities */ -class utils extends \phpbb\textformatter\utils +class utils implements \phpbb\textformatter\utils_interface { /** * {@inheritdoc} diff --git a/phpBB/phpbb/textformatter/utils.php b/phpBB/phpbb/textformatter/utils_interface.php similarity index 80% rename from phpBB/phpbb/textformatter/utils.php rename to phpBB/phpbb/textformatter/utils_interface.php index 13942b9248..45610f7ecb 100644 --- a/phpBB/phpbb/textformatter/utils.php +++ b/phpBB/phpbb/textformatter/utils_interface.php @@ -16,7 +16,7 @@ namespace phpbb\textformatter; /** * Used to manipulate a parsed text */ -abstract class utils +interface utils_interface { /** * Replace BBCodes and other formatting elements with whitespace @@ -26,7 +26,7 @@ abstract class utils * @param string $text * @return string */ - abstract public function clean_formatting($text); + public function clean_formatting($text); /** * Remove given BBCode at given nesting depth @@ -36,7 +36,7 @@ abstract class utils * @param integer $depth Minimum nesting depth (number of parents of the same name) * @return string */ - abstract public function remove_bbcode($text, $bbcode_name, $depth = 0); + public function remove_bbcode($text, $bbcode_name, $depth = 0); /** * Remove BBCodes and other formatting from a parsed text @@ -46,7 +46,7 @@ abstract class utils * @param string $text * @return string */ - abstract public function remove_formatting($text); + public function remove_formatting($text); /** * Return a parsed text to its original form @@ -54,5 +54,5 @@ abstract class utils * @param string $text * @return string */ - abstract public function unparse($text); + public function unparse($text); } From 89d87a99db403d7045406b869a92258e61122f67 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 6 Mar 2015 11:11:07 +0100 Subject: [PATCH 0190/1676] [ticket/11768] Replaced array access with call to $user->lang() PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/parser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 4775175f73..f3e437b163 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -184,7 +184,7 @@ class parser implements \phpbb\textformatter\parser_interface } else if ($msg === 'UNABLE_GET_IMAGE_SIZE') { - $errors[] = $this->user->lang[$msg]; + $errors[] = $this->user->lang($msg); } } From 1b4bdff3b3d01cd422f7a49a1de14b3edbd76804 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 6 Mar 2015 13:00:03 +0100 Subject: [PATCH 0191/1676] [ticket/11768] Fixed test double PHPBB3-11768 --- tests/text_processing/message_parser_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/text_processing/message_parser_test.php b/tests/text_processing/message_parser_test.php index cdbd6c0ca7..691c0d5b8a 100644 --- a/tests/text_processing/message_parser_test.php +++ b/tests/text_processing/message_parser_test.php @@ -53,6 +53,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case array('UNAUTHORISED_BBCODE', '[img]', 'You cannot use certain BBCodes: [img].'), array('UNAUTHORISED_BBCODE', '[quote]', 'You cannot use certain BBCodes: [quote].'), array('UNAUTHORISED_BBCODE', '[url]', 'You cannot use certain BBCodes: [url].'), + array('UNABLE_GET_IMAGE_SIZE', 'It was not possible to determine the dimensions of the image.'), ); $user = $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(); @@ -67,7 +68,6 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case 'TOO_FEW_POLL_OPTIONS' => 'You must enter at least two poll options.', 'TOO_MANY_POLL_OPTIONS' => 'You have tried to enter too many poll options.', 'TOO_MANY_USER_OPTIONS' => 'You cannot specify more options per user than existing poll options.', - 'UNABLE_GET_IMAGE_SIZE' => 'It was not possible to determine the dimensions of the image.' ); $phpbb_container = new phpbb_mock_container_builder; From 40c54898ccd80744ba159784d631328e0338bad2 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 6 Mar 2015 13:08:18 +0100 Subject: [PATCH 0192/1676] [ticket/11768] Updated various annotations PHPBB3-11768 --- phpBB/phpbb/textformatter/data_access.php | 15 +++++++-------- phpBB/phpbb/textformatter/parser_interface.php | 2 +- phpBB/phpbb/textformatter/s9e/factory.php | 13 ++++++------- phpBB/phpbb/textformatter/s9e/parser.php | 11 +++++------ phpBB/phpbb/textformatter/s9e/renderer.php | 11 +++++------ 5 files changed, 24 insertions(+), 28 deletions(-) diff --git a/phpBB/phpbb/textformatter/data_access.php b/phpBB/phpbb/textformatter/data_access.php index 2dfba27960..8938d66935 100644 --- a/phpBB/phpbb/textformatter/data_access.php +++ b/phpBB/phpbb/textformatter/data_access.php @@ -27,7 +27,7 @@ class data_access protected $bbcodes_table; /** - * @var \phpbb_db_driver_interface + * @var \phpbb\db\driver\driver_interface */ protected $db; @@ -54,13 +54,12 @@ class data_access /** * Constructor * - * @param \phpbb\db\driver\driver_interface $db Database connection - * @param string $bbcodes_table Name of the BBCodes table - * @param string $smilies_table Name of the smilies table - * @param string $styles_table Name of the styles table - * @param string $words_table Name of the words table - * @param string $styles_path Path to the styles dir - * @return null + * @param \phpbb\db\driver\driver_interface $db Database connection + * @param string $bbcodes_table Name of the BBCodes table + * @param string $smilies_table Name of the smilies table + * @param string $styles_table Name of the styles table + * @param string $words_table Name of the words table + * @param string $styles_path Path to the styles dir */ public function __construct(\phpbb\db\driver\driver_interface $db, $bbcodes_table, $smilies_table, $styles_table, $words_table, $styles_path) { diff --git a/phpBB/phpbb/textformatter/parser_interface.php b/phpBB/phpbb/textformatter/parser_interface.php index 37d538470d..3cb9f8e977 100644 --- a/phpBB/phpbb/textformatter/parser_interface.php +++ b/phpBB/phpbb/textformatter/parser_interface.php @@ -104,7 +104,7 @@ interface parser_interface /** * Set multiple variables to be used by the parser * - * @param array Associative array of [name => value] + * @param array $vars Associative array of [name => value] * @return null */ public function set_vars(array $vars); diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index aa37beeef6..f3df2ad7a5 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -23,7 +23,7 @@ use s9e\TextFormatter\Configurator\Items\UnsafeTemplate; class factory implements \phpbb\textformatter\cache_interface { /** - * @var \phpbb\cache\driver_interface $cache + * @var \phpbb\cache\driver\driver_interface */ protected $cache; @@ -103,12 +103,11 @@ class factory implements \phpbb\textformatter\cache_interface /** * Constructor * - * @param \phpbb\textformatter\data_access $data_access - * @param \phpbb\cache\driver\driver_interface $cache - * @param string $cache_dir Path to the cache dir - * @param string $cache_key_parser Cache key used for the parser - * @param string $cache_key_renderer Cache key used for the renderer - * @return null + * @param \phpbb\textformatter\data_access $data_access + * @param \phpbb\cache\driver\driver_interface $cache + * @param string $cache_dir Path to the cache dir + * @param string $cache_key_parser Cache key used for the parser + * @param string $cache_key_renderer Cache key used for the renderer */ public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, $cache_dir, $cache_key_parser, $cache_key_renderer) { diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index f3e437b163..2f4a03d4c2 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -34,11 +34,10 @@ class parser implements \phpbb\textformatter\parser_interface /** * Constructor * - * @param \phpbb\cache\driver_interface $cache - * @param string $key Cache key - * @param \phpbb\user $user - * @param factory $factory - * @return null + * @param \phpbb\cache\driver_interface $cache + * @param string $key Cache key + * @param \phpbb\user $user + * @param factory $factory */ public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, factory $factory) { @@ -194,7 +193,7 @@ class parser implements \phpbb\textformatter\parser_interface /** * Return the instance of s9e\TextFormatter\Parser used by this object * - * @return s9e\TextFormatter\Parser + * @return \s9e\TextFormatter\Parser */ public function get_parser() { diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index c896c9f1c7..882a19b4ac 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -51,11 +51,10 @@ class renderer implements \phpbb\textformatter\renderer_interface /** * Constructor * - * @param \phpbb\cache\driver\driver_interface $cache - * @param string $cache_dir Path to the cache dir - * @param string $key Cache key - * @param factory $factory - * @return null + * @param \phpbb\cache\driver\driver_interface $cache + * @param string $cache_dir Path to the cache dir + * @param string $key Cache key + * @param factory $factory */ public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, factory $factory) { @@ -153,7 +152,7 @@ class renderer implements \phpbb\textformatter\renderer_interface /** * Return the instance of s9e\TextFormatter\Renderer used by this object * - * @return s9e\TextFormatter\Renderer + * @return \s9e\TextFormatter\Renderer */ public function get_renderer() { From b021225148d8ba14e106dd24a25128e3be36992a Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 6 Mar 2015 13:11:33 +0100 Subject: [PATCH 0193/1676] [ticket/11768] Removed unused var PHPBB3-11768 --- tests/test_framework/phpbb_test_case_helpers.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 8e49dca40c..e584c238a2 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -486,9 +486,6 @@ class phpbb_test_case_helpers $factory ); - $root_path = ($container->hasParameter('core.root_path')) - ? $container->getParameter('core.root_path') - : './'; $config = ($container->has('config')) ? $container->get('config') : new \phpbb\config\config(array('smilies_path' => 'images/smilies', 'allow_nocensors' => false)); From 709d5023324da66543bbea2f62e4d50bddc49246 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 8 Mar 2015 21:49:53 +0100 Subject: [PATCH 0194/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index f9c113ded6..23160ae541 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "ddd653042fccea77b4ead018492ca7de9196bc77" + "reference": "195202e24258fd38b5c655cc4f3d757688ada7ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/ddd653042fccea77b4ead018492ca7de9196bc77", - "reference": "ddd653042fccea77b4ead018492ca7de9196bc77", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/195202e24258fd38b5c655cc4f3d757688ada7ad", + "reference": "195202e24258fd38b5c655cc4f3d757688ada7ad", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-03 22:19:32" + "time": "2015-03-08 18:49:11" }, { "name": "symfony/config", From b46bf9f02f8d1810bdb95d64603632b6fab06960 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 9 Mar 2015 12:07:10 +0100 Subject: [PATCH 0195/1676] [ticket/11768] Updated merge_templates(). No functional change intended PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index f3df2ad7a5..b053fd6468 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -480,7 +480,7 @@ class factory implements \phpbb\textformatter\cache_interface $grouped_templates = array(); foreach ($style_templates as $style_id => $style_template) { - $grouped_templates[$style_template][] = $style_id; + $grouped_templates[$style_template][] = '$STYLE_ID=' . $style_id; } if (count($grouped_templates) === 1) @@ -499,9 +499,9 @@ class factory implements \phpbb\textformatter\cache_interface // Build an xsl:choose switch $template = ''; - foreach ($grouped_templates as $style_template => $style_ids) + foreach ($grouped_templates as $style_template => $exprs) { - $template .= '' . $style_template . ''; + $template .= '' . $style_template . ''; } $template .= '' . $default_template . ''; From 37106bae7a4e3e67143dde9a86f03b3190ed0f4c Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 14 Mar 2015 03:13:04 +0100 Subject: [PATCH 0196/1676] [ticket/11768] Reverted change to bbcode_uid On the off-chance some other routine expect bbcode_uid to never be empty. PHPBB3-11768 --- phpBB/includes/message_parser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index e4c35f8bca..6af1677b58 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1094,7 +1094,7 @@ class parse_message extends bbcode_firstpass function parse_message($message = '') { // Init BBCode UID - $this->bbcode_uid = ''; + $this->bbcode_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN); $this->message = $message; } From 4398da234ec75cb95ddab82a0fb8f3567790a60b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 16 Mar 2015 03:03:02 +0100 Subject: [PATCH 0197/1676] [ticket/11768] Updated merge_templates(). No functional change intended PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index b053fd6468..01209d352a 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -471,11 +471,21 @@ class factory implements \phpbb\textformatter\cache_interface /** * Merge the templates from any number of styles into one BBCode template * + * When multiple templates are available for the same BBCode (because of multiple styles) we + * merge them into a single template that uses an xsl:choose construct that determines which + * style to use at rendering time. + * * @param array $style_templates Associative array matching style_ids to their template * @return string */ protected function merge_templates(array $style_templates) { + // Return the template as-is if there's only one style or all styles share the same template + if (count(array_unique($style_templates)) === 1) + { + return end($style_templates); + } + // Group identical templates together $grouped_templates = array(); foreach ($style_templates as $style_id => $style_template) @@ -483,11 +493,6 @@ class factory implements \phpbb\textformatter\cache_interface $grouped_templates[$style_template][] = '$STYLE_ID=' . $style_id; } - if (count($grouped_templates) === 1) - { - return $style_template; - } - // Sort templates by frequency descending $templates_cnt = array_map('sizeof', $grouped_templates); array_multisort($grouped_templates, $templates_cnt); From 718ace2121dc5e58bb1c09d730a867cde20518eb Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 16 Mar 2015 03:32:20 +0100 Subject: [PATCH 0198/1676] [ticket/11768] Updated annotation [ci skip] PHPBB3-11768 --- phpBB/includes/acp/acp_styles.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 904769f0d1..b652fd6587 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -53,7 +53,7 @@ class acp_styles /** @var \phpbb\auth\auth */ protected $auth; - /** @var \phpbb\textformatter\cache */ + /** @var \phpbb\textformatter\cache_interface */ protected $text_formatter_cache; /** @var string */ From 8971805e57c2af152ef62e16c8e5eb67bf343756 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 16 Mar 2015 12:43:10 +0100 Subject: [PATCH 0199/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 23160ae541..0c5ff71011 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "195202e24258fd38b5c655cc4f3d757688ada7ad" + "reference": "e6d6fb3518f8e3f202310b9cafe2c660970a5dbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/195202e24258fd38b5c655cc4f3d757688ada7ad", - "reference": "195202e24258fd38b5c655cc4f3d757688ada7ad", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/e6d6fb3518f8e3f202310b9cafe2c660970a5dbe", + "reference": "e6d6fb3518f8e3f202310b9cafe2c660970a5dbe", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-08 18:49:11" + "time": "2015-03-16 11:12:04" }, { "name": "symfony/config", From f4f5bdbaee48d0ed341ec9b720579a4f751916fc Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 19 Mar 2015 11:38:44 +0100 Subject: [PATCH 0200/1676] [ticket/11768] Removed whitespace No functional change intended PHPBB3-11768 --- tests/text_formatter/s9e/factory_test.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index 8df841605d..7dfa512b28 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -29,9 +29,7 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case public function get_factory() { global $phpbb_root_path; - $this->cache = new phpbb_mock_cache; - $dal = new \phpbb\textformatter\data_access( $this->new_dbal(), 'phpbb_bbcodes', @@ -40,7 +38,6 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case 'phpbb_words', $phpbb_root_path . 'styles/' ); - $factory = new \phpbb\textformatter\s9e\factory( $dal, $this->cache, @@ -122,7 +119,6 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case public function test_local_url() { global $config, $user, $request; - $config = array( 'force_server_vars' => true, 'server_protocol' => 'http://', From 49b9e8e4eafff93f25a99bf263982fe79b7f0549 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 19 Mar 2015 12:45:12 +0100 Subject: [PATCH 0201/1676] [ticket/11768] Added configurator events PHPBB3-11768 --- .../container/services_text_formatter.yml | 1 + phpBB/phpbb/textformatter/s9e/factory.php | 30 +++++++++++++- .../phpbb_test_case_helpers.php | 18 ++++++++- tests/text_formatter/s9e/factory_test.php | 39 +++++++++++++++++++ 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index ec5421695d..05188a5fba 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -31,6 +31,7 @@ services: arguments: - @text_formatter.data_access - @cache.driver + - @dispatcher - %text_formatter.cache.dir% - %text_formatter.cache.parser.key% - %text_formatter.cache.renderer.key% diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 01209d352a..4504a329af 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -100,23 +100,29 @@ class factory implements \phpbb\textformatter\cache_interface 'email' => '', ); + /** + * @var \phpbb\event\dispatcher_interface + */ + protected $dispatcher; + /** * Constructor * * @param \phpbb\textformatter\data_access $data_access * @param \phpbb\cache\driver\driver_interface $cache + * @param \phpbb\event\dispatcher_interface $dispatcher * @param string $cache_dir Path to the cache dir * @param string $cache_key_parser Cache key used for the parser * @param string $cache_key_renderer Cache key used for the renderer */ - public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, $cache_dir, $cache_key_parser, $cache_key_renderer) + public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, \phpbb\event\dispatcher_interface $dispatcher, $cache_dir, $cache_key_parser, $cache_key_renderer) { $this->cache = $cache; $this->cache_dir = $cache_dir; $this->cache_key_parser = $cache_key_parser; $this->cache_key_renderer = $cache_key_renderer; - $this->data_access = $data_access; + $this->dispatcher = $dispatcher; } /** @@ -158,6 +164,16 @@ class factory implements \phpbb\textformatter\cache_interface // Create a new Configurator $configurator = new Configurator; + /** + * Modify the s9e\TextFormatter configurator before the default settings are set + * + * @event core.text_formatter_s9e_configure_before + * @var \s9e\TextFormatter\Configurator configurator Configurator instance + * @since 3.2.0-a1 + */ + $vars = array('configurator'); + extract($this->dispatcher->trigger_event('core.text_formatter_s9e_configure_before', compact($vars))); + // Convert newlines to br elements by default $configurator->rootRules->enableAutoLineBreaks(); @@ -288,6 +304,16 @@ class factory implements \phpbb\textformatter\cache_interface $configurator->registeredVars['max_img_height'] = 0; $configurator->registeredVars['max_img_width'] = 0; + /** + * Modify the s9e\TextFormatter configurator after the default settings are set + * + * @event core.text_formatter_s9e_configure_after + * @var \s9e\TextFormatter\Configurator configurator Configurator instance + * @since 3.2.0-a1 + */ + $vars = array('configurator'); + extract($this->dispatcher->trigger_event('core.text_formatter_s9e_configure_after', compact($vars))); + return $configurator; } diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index e584c238a2..5c6da94014 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -315,7 +315,7 @@ class phpbb_test_case_helpers public function set_s9e_services(ContainerInterface $container = null, $fixture = null, $styles_path = null) { static $first_run; - global $phpbb_container, $phpbb_root_path, $phpEx; + global $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx; $cache_dir = __DIR__ . '/../tmp/'; @@ -443,8 +443,22 @@ class phpbb_test_case_helpers ); } + // Create an event dispatcher + if ($container->has('dispatcher')) + { + $dispatcher = $container->get('dispatcher'); + } + else if (isset($phpbb_dispatcher)) + { + $dispatcher = $phpbb_dispatcher; + } + else + { + $dispatcher = new phpbb_mock_event_dispatcher; + } + // Create and register the text_formatter.s9e.factory service - $factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $cache_dir, $cache_key_parser, $cache_key_renderer); + $factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $dispatcher, $cache_dir, $cache_key_parser, $cache_key_renderer); $container->set('text_formatter.s9e.factory', $factory); // Create a user if none was provided, and add the common lang strings diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index 7dfa512b28..9f7551ef14 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -16,6 +16,13 @@ require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php'; class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case { + public function setUp() + { + $this->cache = new phpbb_mock_cache; + $this->dispatcher = new phpbb_mock_event_dispatcher; + parent::setUp(); + } + public function getDataSet() { return $this->createXMLDataSet(__DIR__ . '/fixtures/factory.xml'); @@ -41,6 +48,7 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case $factory = new \phpbb\textformatter\s9e\factory( $dal, $this->cache, + $this->dispatcher, $this->get_cache_dir(), '_foo_parser', '_foo_renderer' @@ -184,4 +192,35 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case $expected = 'text'; $this->assertSame($expected, $renderer->render($parser->parse($original))); } + + /** + * @testdox get_configurator() triggers events before and after configuration + */ + public function test_configure_events() + { + $this->dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); + $this->dispatcher + ->expects($this->at(0)) + ->method('trigger_event') + ->with( + 'core.text_formatter_s9e_configure_before', + $this->callback(array($this, 'configure_event_callback')) + ) + ->will($this->returnArgument(1)); + $this->dispatcher + ->expects($this->at(1)) + ->method('trigger_event') + ->with( + 'core.text_formatter_s9e_configure_after', + $this->callback(array($this, 'configure_event_callback')) + ) + ->will($this->returnArgument(1)); + + $this->get_factory()->get_configurator(); + } + + public function configure_event_callback($vars) + { + return isset($vars['configurator']) && $vars['configurator'] instanceof \s9e\TextFormatter\Configurator; + } } From 3cd5ca8de12f645f3c8664942f0328e18d5a2789 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 21 Mar 2015 12:28:52 +0100 Subject: [PATCH 0202/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 0c5ff71011..d5809144a6 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "e6d6fb3518f8e3f202310b9cafe2c660970a5dbe" + "reference": "1a4d347bec744ff2959708fcf24fa40848a66861" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/e6d6fb3518f8e3f202310b9cafe2c660970a5dbe", - "reference": "e6d6fb3518f8e3f202310b9cafe2c660970a5dbe", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/1a4d347bec744ff2959708fcf24fa40848a66861", + "reference": "1a4d347bec744ff2959708fcf24fa40848a66861", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-16 11:12:04" + "time": "2015-03-21 11:18:30" }, { "name": "symfony/config", From 69dae16ba79a82714b3fa24955c5cbc6e372a388 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 21 Mar 2015 12:32:17 +0100 Subject: [PATCH 0203/1676] [ticket/11768] Preserve comments in custom BBCodes PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/factory.php | 4 +++ tests/text_formatter/s9e/factory_test.php | 15 ++++++++++ .../s9e/fixtures/preserve_comments.xml | 28 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/text_formatter/s9e/fixtures/preserve_comments.xml diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 4504a329af..bad9190973 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -180,6 +180,10 @@ class factory implements \phpbb\textformatter\cache_interface // Don't automatically ignore text in places where text is not allowed $configurator->rulesGenerator->remove('IgnoreTextIfDisallowed'); + // Don't remove comments and instead convert them to xsl:comment elements + $configurator->templateNormalizer->remove('RemoveComments'); + $configurator->templateNormalizer->add('TransposeComments'); + // Set the rendering engine and configure it to save to the cache dir $configurator->rendering->engine = 'PHP'; $configurator->rendering->engine->cacheDir = $this->cache_dir; diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index 9f7551ef14..8382097544 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -178,6 +178,21 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case $this->assertSame($expected, $renderer->render($parser->parse($original))); } + /** + * @testdox Preserves comments in custom BBCodes + */ + public function test_preserve_comments() + { + $fixture = __DIR__ . '/fixtures/preserve_comments.xml'; + $container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture); + $parser = $container->get('text_formatter.parser'); + $renderer = $container->get('text_formatter.renderer'); + + $original = '[X]'; + $expected = ''; + $this->assertSame($expected, $renderer->render($parser->parse($original))); + } + /** * @testdox Accepts unsafe custom BBCodes */ diff --git a/tests/text_formatter/s9e/fixtures/preserve_comments.xml b/tests/text_formatter/s9e/fixtures/preserve_comments.xml new file mode 100644 index 0000000000..f81d366aad --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/preserve_comments.xml @@ -0,0 +1,28 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + X + + 1 + [X][/X] + ]]> + + + + + +
              +
              From c165eaa37ccfa817c3ba1373255efc131f7be509 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 23 Mar 2015 12:34:22 +0100 Subject: [PATCH 0204/1676] [ticket/11768] Removed superfluous whitespace [ci skip] PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/renderer.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 882a19b4ac..75de54d942 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -62,7 +62,6 @@ class renderer implements \phpbb\textformatter\renderer_interface if ($renderer_data) { $class = $renderer_data['class']; - if (!class_exists($class, false)) { // Try to load the renderer class from its cache file @@ -73,12 +72,10 @@ class renderer implements \phpbb\textformatter\renderer_interface include($cache_file); } } - if (class_exists($class, false)) { $renderer = new $class; } - if (isset($renderer_data['censor'])) { $censor = $renderer_data['censor']; From 5b2d3fddfda75bcc212c8b9c88ab0d9ccc28b1d5 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 23 Mar 2015 21:32:10 +0100 Subject: [PATCH 0205/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index d5809144a6..789540534e 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "1a4d347bec744ff2959708fcf24fa40848a66861" + "reference": "59248bbc7edc139e11ff50cc42c2eeddffcb41c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/1a4d347bec744ff2959708fcf24fa40848a66861", - "reference": "1a4d347bec744ff2959708fcf24fa40848a66861", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/59248bbc7edc139e11ff50cc42c2eeddffcb41c5", + "reference": "59248bbc7edc139e11ff50cc42c2eeddffcb41c5", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-21 11:18:30" + "time": "2015-03-23 20:24:43" }, { "name": "symfony/config", From 37fedc656fbdeb36b098375201042eed4c7e7229 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 23 Mar 2015 21:34:49 +0100 Subject: [PATCH 0206/1676] [ticket/11768] Updated the text_formatter.s9e.utils service Made it use s9e\TextFormatter\Utils. Refactored some tests to make them more readable. PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/utils.php | 17 ++---------- tests/text_formatter/s9e/utils_test.php | 37 +++++++++---------------- 2 files changed, 16 insertions(+), 38 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index df4ae4b9ec..29dcfcdf58 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -26,7 +26,7 @@ class utils implements \phpbb\textformatter\utils_interface // Insert a space before and then remove formatting $text = preg_replace('#<[es]>#', ' $0', $text); - return \s9e\TextFormatter\Unparser::removeFormatting($text); + return \s9e\TextFormatter\Utils::removeFormatting($text); } /** @@ -34,18 +34,7 @@ class utils implements \phpbb\textformatter\utils_interface */ public function remove_bbcode($text, $bbcode_name, $depth = 0) { - $dom = new \DOMDocument; - $dom->loadXML($text); - - $xpath = new \DOMXPath($dom); - $nodes = $xpath->query(str_repeat('//' . strtoupper($bbcode_name), 1 + $depth)); - - foreach ($nodes as $node) - { - $node->parentNode->removeChild($node); - } - - return $dom->saveXML($dom->documentElement); + return \s9e\TextFormatter\Utils::removeTag($text, strtoupper($bbcode_name), $depth); } /** @@ -53,7 +42,7 @@ class utils implements \phpbb\textformatter\utils_interface */ public function remove_formatting($text) { - return \s9e\TextFormatter\Unparser::removeFormatting($text); + return \s9e\TextFormatter\Utils::removeFormatting($text); } /** diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index 3de9b707c5..6f0ef54182 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -109,52 +109,41 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case public function test_remove_bbcode($original, $name, $depth, $expected) { $container = $this->get_test_case_helpers()->set_s9e_services(); + $parser = $container->get('text_formatter.parser'); $utils = $container->get('text_formatter.utils'); - $this->assertSame($expected, $utils->remove_bbcode($original, $name, $depth)); + $parsed = $parser->parse($original); + $actual = $utils->unparse($utils->remove_bbcode($parsed, $name, $depth)); + + $this->assertSame($expected, $actual); } public function get_remove_bbcode_tests() { return array( array( - 'Plain text', + 'Plain text', 'b', 1, - 'Plain text' + 'Plain text' ), array( - '[quote="u0"][quote="u1"][quote="u2"]q2[/quote] -q1[/quote] -q0[/quote] -[b]bold[/b]', + '[quote="u0"][quote="u1"][quote="u2"]q2[/quote]q1[/quote]q0[/quote][b]bold[/b]', 'quote', 0, - ' -[b]bold[/b]' + '[b]bold[/b]', ), array( - '[quote="u0"][quote="u1"][quote="u2"]q2[/quote] -q1[/quote] -q0[/quote] -[b]bold[/b]', + '[quote="u0"][quote="u1"][quote="u2"]q2[/quote]q1[/quote]q0[/quote][b]bold[/b]', 'quote', 1, - '[quote="u0"] -q0[/quote] -[b]bold[/b]' + '[quote="u0"]q0[/quote][b]bold[/b]', ), array( - '[quote="u0"][quote="u1"][quote="u2"]q2[/quote] -q1[/quote] -q0[/quote] -[b]bold[/b]', + '[quote="u0"][quote="u1"][quote="u2"]q2[/quote]q1[/quote]q0[/quote][b]bold[/b]', 'quote', 2, - '[quote="u0"][quote="u1"] -q1[/quote] -q0[/quote] -[b]bold[/b]' + '[quote="u0"][quote="u1"]q1[/quote]q0[/quote][b]bold[/b]', ), ); } From 2a462bb7e43b848d0277bd27e14ca4d645230eeb Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 25 Mar 2015 01:13:31 +0100 Subject: [PATCH 0207/1676] [ticket/11768] Removed get_parser() / get_renderer() accessors There's no need to access the s9e\TextFormatter objects outside of events. PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/parser.php | 10 ---------- phpBB/phpbb/textformatter/s9e/renderer.php | 10 ---------- tests/text_formatter/s9e/parser_test.php | 7 ------- tests/text_formatter/s9e/renderer_test.php | 7 ------- 4 files changed, 34 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 2f4a03d4c2..6fda94d7ba 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -190,16 +190,6 @@ class parser implements \phpbb\textformatter\parser_interface return array_unique($errors); } - /** - * Return the instance of s9e\TextFormatter\Parser used by this object - * - * @return \s9e\TextFormatter\Parser - */ - public function get_parser() - { - return $this->parser; - } - /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 75de54d942..b68c9dd9be 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -146,16 +146,6 @@ class renderer implements \phpbb\textformatter\renderer_interface $this->renderer->setParameter('STYLE_ID', $user->style['style_id']); } - /** - * Return the instance of s9e\TextFormatter\Renderer used by this object - * - * @return \s9e\TextFormatter\Renderer - */ - public function get_renderer() - { - return $this->renderer; - } - /** * {@inheritdoc} */ diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index 725ff42bfd..71433e209f 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -167,11 +167,4 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case ) ); } - - public function test_get_parser() - { - $container = $this->get_test_case_helpers()->set_s9e_services(); - $parser = $container->get('text_formatter.parser'); - $this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser->get_parser()); - } } diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index b93fd8bbe6..ce2fccd9b7 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -354,11 +354,4 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case ); } } - - public function test_get_renderer() - { - $container = $this->get_test_case_helpers()->set_s9e_services(); - $renderer = $container->get('text_formatter.renderer'); - $this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer->get_renderer()); - } } From a7a53d5a30d4736f8114721c0d7019d64d24cda2 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 25 Mar 2015 01:39:19 +0100 Subject: [PATCH 0208/1676] [ticket/11768] Added core.text_formatter_s9e_parser_setup event PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/parser.php | 31 ++++++++++-- .../phpbb_test_case_helpers.php | 5 +- tests/text_formatter/s9e/parser_test.php | 47 +++++++++++++++++-- 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 6fda94d7ba..37900d3d7c 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -21,6 +21,11 @@ use s9e\TextFormatter\Parser\Logger; */ class parser implements \phpbb\textformatter\parser_interface { + /** + * @var \phpbb\event\dispatcher_interface + */ + protected $dispatcher; + /** * @var \s9e\TextFormatter\Parser */ @@ -38,19 +43,39 @@ class parser implements \phpbb\textformatter\parser_interface * @param string $key Cache key * @param \phpbb\user $user * @param factory $factory + * @param \phpbb\event\dispatcher_interface $dispatcher */ - public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, factory $factory) + public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, factory $factory, \phpbb\event\dispatcher_interface $dispatcher) { - $this->user = $user; - $parser = $cache->get($key); if (!$parser) { $objects = $factory->regenerate(); $parser = $objects['parser']; } + $self = $this; + /** + * Configure the parser service + * + * Can be used to: + * - toggle features according to the user's preferences, + * - toggle BBCodes according to the user's permissions, + * - register variables or custom parsers in the s9e\TextFormatter + * - configure the s9e\TextFormatter parser + * + * @event core.text_formatter_s9e_parser_setup + * @var \s9e\TextFormatter\Parser parser s9e\TextFormatter parser instance + * @var \phpbb\textformatter\s9e\parser self This parser service + * @var \phpbb\user user Current user + * @since 3.2.0-a1 + */ + $vars = array('parser', 'self', 'user'); + extract($dispatcher->trigger_event('core.text_formatter_s9e_parser_setup', compact($vars))); + + $this->dispatcher = $dispatcher; $this->parser = $parser; + $this->user = $user; } /** diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 5c6da94014..d43138d780 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -425,6 +425,7 @@ class phpbb_test_case_helpers $prefix = '_s9e_' . md5(serialize(func_get_args())); $cache_key_parser = $prefix . '_parser'; $cache_key_renderer = $prefix . '_renderer'; + $container->set('cache.driver', $cache); // Create a path_helper if (!$container->has('path_helper')) @@ -473,6 +474,7 @@ class phpbb_test_case_helpers $user->optionset('viewflash', true); $user->optionset('viewimg', true); $user->optionset('viewsmilies', true); + $container->set('user', $user); } $user->add_lang('common'); @@ -486,7 +488,8 @@ class phpbb_test_case_helpers $cache, $cache_key_parser, $user, - $factory + $factory, + $dispatcher ); $container->set('text_formatter.parser', $parser); diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index 71433e209f..03b29bef12 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -36,7 +36,8 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $cache, '_foo_parser', $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), - $factory + $factory, + new phpbb_mock_event_dispatcher ); } @@ -63,7 +64,8 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $cache, '_foo_parser', $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), - $factory + $factory, + new phpbb_mock_event_dispatcher ); $this->assertSame('test', $parser->parse('test')); @@ -91,7 +93,8 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case new phpbb_mock_cache, '_foo_parser', $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), - $factory + $factory, + new phpbb_mock_event_dispatcher ); $this->assertSame('test', $parser->parse('test')); @@ -124,7 +127,8 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $cache, '_foo_parser', $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), - $factory + $factory, + new phpbb_mock_event_dispatcher ); call_user_func_array(array($parser, $adapter_method), (array) $adapter_arg); @@ -167,4 +171,39 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case ) ); } + + /** + * @testdox The constructor triggers a core.text_formatter_s9e_parser_setup event + */ + public function test_setup_event() + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); + $dispatcher + ->expects($this->once()) + ->method('trigger_event') + ->with( + 'core.text_formatter_s9e_parser_setup', + $this->callback(array($this, 'setup_event_callback')) + ) + ->will($this->returnArgument(1)); + + new \phpbb\textformatter\s9e\parser( + $container->get('cache.driver'), + '_foo_parser', + $container->get('user'), + $container->get('text_formatter.s9e.factory'), + $dispatcher + ); + } + + public function setup_event_callback($vars) + { + return isset($vars['parser']) + && $vars['parser'] instanceof \s9e\TextFormatter\Parser + && isset($vars['self']) + && $vars['self'] instanceof \phpbb\textformatter\s9e\parser + && isset($vars['user']) + && $vars['user'] instanceof \phpbb\user; + } } From 7f9639fd248a1f690ac55ddab8939ec84309f129 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 25 Mar 2015 02:22:18 +0100 Subject: [PATCH 0209/1676] [ticket/11768] Fixed service config PHPBB3-11768 --- phpBB/config/default/container/services_text_formatter.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index 05188a5fba..e95cafcc7e 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -43,6 +43,7 @@ services: - %text_formatter.cache.parser.key% - @user - @text_formatter.s9e.factory + - @dispatcher text_formatter.s9e.renderer: class: phpbb\textformatter\s9e\renderer From c89188132114b4d9ff483c5b1579c53cdeb69703 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 25 Mar 2015 03:44:24 +0100 Subject: [PATCH 0210/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 789540534e..706dd4ba63 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "59248bbc7edc139e11ff50cc42c2eeddffcb41c5" + "reference": "ad4384b2c792cf55c456de018a525bbaea106fc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/59248bbc7edc139e11ff50cc42c2eeddffcb41c5", - "reference": "59248bbc7edc139e11ff50cc42c2eeddffcb41c5", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/ad4384b2c792cf55c456de018a525bbaea106fc0", + "reference": "ad4384b2c792cf55c456de018a525bbaea106fc0", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-23 20:24:43" + "time": "2015-03-25 02:37:49" }, { "name": "symfony/config", From af4f9b860f50a562a03f55efad1da7e0854bdfda Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 26 Mar 2015 04:39:36 +0100 Subject: [PATCH 0211/1676] [ticket/11768] Added core.text_formatter_s9e_renderer_setup event PHPBB3-11768 --- .../container/services_text_formatter.yml | 1 + phpBB/phpbb/textformatter/s9e/renderer.php | 23 +++++++++-- .../phpbb_test_case_helpers.php | 4 +- tests/text_formatter/s9e/renderer_test.php | 39 ++++++++++++++++++- 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index e95cafcc7e..972be31b31 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -52,6 +52,7 @@ services: - %text_formatter.cache.dir% - %text_formatter.cache.renderer.key% - @text_formatter.s9e.factory + - @dispatcher calls: - [configure_smilies_path, [@config, @path_helper]] - [configure_user, [@user, @config, @auth]] diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index b68c9dd9be..7b8b382074 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -23,6 +23,11 @@ class renderer implements \phpbb\textformatter\renderer_interface */ protected $censor; + /** + * @var \phpbb\event\dispatcher_interface + */ + protected $dispatcher; + /** * @var \s9e\TextFormatter\Renderer */ @@ -55,8 +60,9 @@ class renderer implements \phpbb\textformatter\renderer_interface * @param string $cache_dir Path to the cache dir * @param string $key Cache key * @param factory $factory + * @param \phpbb\event\dispatcher_interface $dispatcher */ - public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, factory $factory) + public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, factory $factory, \phpbb\event\dispatcher_interface $dispatcher) { $renderer_data = $cache->get($key); if ($renderer_data) @@ -81,18 +87,29 @@ class renderer implements \phpbb\textformatter\renderer_interface $censor = $renderer_data['censor']; } } - if (!isset($renderer)) { $objects = $factory->regenerate(); $renderer = $objects['renderer']; } + $self = $this; + + /** + * Configure the renderer service + * + * @event core.text_formatter_s9e_renderer_setup + * @var \s9e\TextFormatter\Renderer renderer s9e\TextFormatter renderer instance + * @var \phpbb\textformatter\s9e\renderer self This renderer service + * @since 3.2.0-a1 + */ + $vars = array('renderer', 'self'); + extract($dispatcher->trigger_event('core.text_formatter_s9e_renderer_setup', compact($vars))); if (isset($censor)) { $this->censor = $censor; } - + $this->dispatcher = $dispatcher; $this->renderer = $renderer; } diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index d43138d780..09fec38013 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -426,6 +426,7 @@ class phpbb_test_case_helpers $cache_key_parser = $prefix . '_parser'; $cache_key_renderer = $prefix . '_renderer'; $container->set('cache.driver', $cache); + $container->setParameter('cache.dir', $cache_dir); // Create a path_helper if (!$container->has('path_helper')) @@ -500,7 +501,8 @@ class phpbb_test_case_helpers $cache, $cache_dir, $cache_key_renderer, - $factory + $factory, + $dispatcher ); $config = ($container->has('config')) diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index ce2fccd9b7..ab89d42620 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -43,7 +43,8 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case $cache, $this->get_cache_dir(), '_foo_renderer', - $factory + $factory, + new phpbb_mock_event_dispatcher ); } @@ -68,7 +69,8 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case $cache, $this->get_cache_dir(), '_foo_renderer', - $factory + $factory, + new phpbb_mock_event_dispatcher ); } @@ -354,4 +356,37 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case ); } } + + /** + * @testdox The constructor triggers a core.text_formatter_s9e_renderer_setup event + */ + public function test_setup_event() + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); + $dispatcher + ->expects($this->once()) + ->method('trigger_event') + ->with( + 'core.text_formatter_s9e_renderer_setup', + $this->callback(array($this, 'setup_event_callback')) + ) + ->will($this->returnArgument(1)); + + new \phpbb\textformatter\s9e\renderer( + $container->get('cache.driver'), + $container->getParameter('cache.dir'), + '_foo_renderer', + $container->get('text_formatter.s9e.factory'), + $dispatcher + ); + } + + public function setup_event_callback($vars) + { + return isset($vars['renderer']) + && $vars['renderer'] instanceof \s9e\TextFormatter\Renderer + && isset($vars['self']) + && $vars['self'] instanceof \phpbb\textformatter\s9e\renderer; + } } From a04fca86ee4fec3cb615f358f3dc914564d9a9b1 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 26 Mar 2015 05:10:25 +0100 Subject: [PATCH 0212/1676] [ticket/11768] Added renderer events Added core.text_formatter_s9e_render_before and core.text_formatter_s9e_render_after PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/renderer.php | 30 ++++++++++-- tests/text_formatter/s9e/renderer_test.php | 54 ++++++++++++++++++++++ 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 7b8b382074..484b067d47 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -198,15 +198,28 @@ class renderer implements \phpbb\textformatter\renderer_interface /** * {@inheritdoc} */ - public function render($text) + public function render($xml) { + $self = $this; + + /** + * Modify a parsed text before it is rendered + * + * @event core.text_formatter_s9e_render_before + * @var \phpbb\textformatter\s9e\renderer self This renderer service + * @var string xml The parsed text, in its XML form + * @since 3.2.0-a1 + */ + $vars = array('self', 'xml'); + extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_before', compact($vars))); + if (isset($this->censor) && $this->viewcensors) { // NOTE: censorHtml() is XML-safe - $text = $this->censor->censorHtml($text, true); + $xml = $this->censor->censorHtml($xml, true); } - $html = $this->renderer->render($text); + $html = $this->renderer->render($xml); /** * @see bbcode::bbcode_second_pass_code() @@ -239,6 +252,17 @@ class renderer implements \phpbb\textformatter\renderer_interface $html ); + /** + * Modify a rendered text + * + * @event core.text_formatter_s9e_render_after + * @var string html The renderer text's HTML + * @var \phpbb\textformatter\s9e\renderer self This renderer service + * @since 3.2.0-a1 + */ + $vars = array('html', 'self'); + extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_after', compact($vars))); + return $html; } diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index ab89d42620..c69a93dbc1 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -389,4 +389,58 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case && isset($vars['self']) && $vars['self'] instanceof \phpbb\textformatter\s9e\renderer; } + + /** + * @testdox render() triggers a core.text_formatter_s9e_render_before and core.text_formatter_s9e_render_after events + */ + public function test_render_event() + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); + $dispatcher + ->expects($this->any()) + ->method('trigger_event') + ->will($this->returnArgument(1)); + $dispatcher + ->expects($this->at(1)) + ->method('trigger_event') + ->with( + 'core.text_formatter_s9e_render_before', + $this->callback(array($this, 'render_before_event_callback')) + ) + ->will($this->returnArgument(1)); + $dispatcher + ->expects($this->at(2)) + ->method('trigger_event') + ->with( + 'core.text_formatter_s9e_render_after', + $this->callback(array($this, 'render_after_event_callback')) + ) + ->will($this->returnArgument(1)); + + $renderer = new \phpbb\textformatter\s9e\renderer( + $container->get('cache.driver'), + $container->getParameter('cache.dir'), + '_foo_renderer', + $container->get('text_formatter.s9e.factory'), + $dispatcher + ); + $renderer->render('...'); + } + + public function render_before_event_callback($vars) + { + return isset($vars['self']) + && $vars['self'] instanceof \phpbb\textformatter\s9e\renderer + && isset($vars['xml']) + && $vars['xml'] === '...'; + } + + public function render_after_event_callback($vars) + { + return isset($vars['html']) + && $vars['html'] === '...' + && isset($vars['self']) + && $vars['self'] instanceof \phpbb\textformatter\s9e\renderer; + } } From f75f63b264b2005faedb699dd867bd1d9c429a09 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 26 Mar 2015 05:20:23 +0100 Subject: [PATCH 0213/1676] [ticket/11768] Added parser events Added core.text_formatter_s9e_parse_before and core.text_formatter_s9e_parse_after PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/parser.php | 28 ++++++++++- phpBB/phpbb/textformatter/s9e/renderer.php | 2 +- tests/text_formatter/s9e/parser_test.php | 54 ++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 37900d3d7c..f220dd3e64 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -83,7 +83,33 @@ class parser implements \phpbb\textformatter\parser_interface */ public function parse($text) { - return $this->parser->parse($text); + $self = $this; + + /** + * Modify a text before it is parsed + * + * @event core.text_formatter_s9e_parse_before + * @var \phpbb\textformatter\s9e\parser self This parser service + * @var string text The original text + * @since 3.2.0-a1 + */ + $vars = array('self', 'text'); + extract($this->dispatcher->trigger_event('core.text_formatter_s9e_parse_before', compact($vars))); + + $xml = $this->parser->parse($text); + + /** + * Modify a parsed text in its XML form + * + * @event core.text_formatter_s9e_parse_after + * @var \phpbb\textformatter\s9e\parser self This parser service + * @var string xml The parsed text, in XML + * @since 3.2.0-a1 + */ + $vars = array('self', 'xml'); + extract($this->dispatcher->trigger_event('core.text_formatter_s9e_parse_after', compact($vars))); + + return $xml; } /** diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 484b067d47..272cc5e6f3 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -256,7 +256,7 @@ class renderer implements \phpbb\textformatter\renderer_interface * Modify a rendered text * * @event core.text_formatter_s9e_render_after - * @var string html The renderer text's HTML + * @var string html The rendered text's HTML * @var \phpbb\textformatter\s9e\renderer self This renderer service * @since 3.2.0-a1 */ diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index 03b29bef12..74182bda47 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -206,4 +206,58 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case && isset($vars['user']) && $vars['user'] instanceof \phpbb\user; } + + /** + * @testdox parse() triggers a core.text_formatter_s9e_parse_before and core.text_formatter_s9e_parse_after events + */ + public function test_parse_event() + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); + $dispatcher + ->expects($this->any()) + ->method('trigger_event') + ->will($this->returnArgument(1)); + $dispatcher + ->expects($this->at(1)) + ->method('trigger_event') + ->with( + 'core.text_formatter_s9e_parse_before', + $this->callback(array($this, 'parse_before_event_callback')) + ) + ->will($this->returnArgument(1)); + $dispatcher + ->expects($this->at(2)) + ->method('trigger_event') + ->with( + 'core.text_formatter_s9e_parse_after', + $this->callback(array($this, 'parse_after_event_callback')) + ) + ->will($this->returnArgument(1)); + + $parser = new \phpbb\textformatter\s9e\parser( + $container->get('cache.driver'), + '_foo_parser', + $container->get('user'), + $container->get('text_formatter.s9e.factory'), + $dispatcher + ); + $parser->parse('...'); + } + + public function parse_before_event_callback($vars) + { + return isset($vars['self']) + && $vars['self'] instanceof \phpbb\textformatter\s9e\parser + && isset($vars['text']) + && $vars['text'] === '...'; + } + + public function parse_after_event_callback($vars) + { + return isset($vars['self']) + && $vars['self'] instanceof \phpbb\textformatter\s9e\parser + && isset($vars['xml']) + && $vars['xml'] === '...'; + } } From 55c3fc02cfe1ce151bfb65c31ec72fc75f9d7872 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 26 Mar 2015 15:28:04 +0100 Subject: [PATCH 0214/1676] [ticket/11768] Updated utils service Updated docblocks. Removed remove_formatting() because it overlaps with clean_formatting() PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/utils.php | 41 +++++++++++-------- phpBB/phpbb/textformatter/utils_interface.php | 22 +++------- tests/text_formatter/s9e/utils_test.php | 29 ------------- 3 files changed, 29 insertions(+), 63 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index 29dcfcdf58..2018bbf519 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -19,37 +19,42 @@ namespace phpbb\textformatter\s9e; class utils implements \phpbb\textformatter\utils_interface { /** - * {@inheritdoc} + * Replace BBCodes and other formatting elements with whitespace + * + * NOTE: preserves smilies as text + * + * @param string $xml Parsed text + * @return string Plain text */ - public function clean_formatting($text) + public function clean_formatting($xml) { // Insert a space before and then remove formatting - $text = preg_replace('#<[es]>#', ' $0', $text); + $xml = preg_replace('#<[es]>#', ' $0', $xml); - return \s9e\TextFormatter\Utils::removeFormatting($text); + return \s9e\TextFormatter\Utils::removeFormatting($xml); } /** - * {@inheritdoc} + * Remove given BBCode and its content, at given nesting depth + * + * @param string $xml Parsed text + * @param string $bbcode_name BBCode's name + * @param integer $depth Minimum nesting depth (number of parents of the same name) + * @return string Parsed text */ - public function remove_bbcode($text, $bbcode_name, $depth = 0) + public function remove_bbcode($xml, $bbcode_name, $depth = 0) { - return \s9e\TextFormatter\Utils::removeTag($text, strtoupper($bbcode_name), $depth); + return \s9e\TextFormatter\Utils::removeTag($xml, strtoupper($bbcode_name), $depth); } /** - * {@inheritdoc} + * Return a parsed text to its original form + * + * @param string $xml Parsed text + * @return string Original plain text */ - public function remove_formatting($text) + public function unparse($xml) { - return \s9e\TextFormatter\Utils::removeFormatting($text); - } - - /** - * {@inheritdoc} - */ - public function unparse($text) - { - return \s9e\TextFormatter\Unparser::unparse($text); + return \s9e\TextFormatter\Unparser::unparse($xml); } } diff --git a/phpBB/phpbb/textformatter/utils_interface.php b/phpBB/phpbb/textformatter/utils_interface.php index 45610f7ecb..132dc8ece4 100644 --- a/phpBB/phpbb/textformatter/utils_interface.php +++ b/phpBB/phpbb/textformatter/utils_interface.php @@ -23,36 +23,26 @@ interface utils_interface * * NOTE: preserves smilies as text * - * @param string $text - * @return string + * @param string $text Parsed text + * @return string Plain text */ public function clean_formatting($text); /** - * Remove given BBCode at given nesting depth + * Remove given BBCode and its content, at given nesting depth * * @param string $text Parsed text * @param string $bbcode_name BBCode's name * @param integer $depth Minimum nesting depth (number of parents of the same name) - * @return string + * @return string Parsed text */ public function remove_bbcode($text, $bbcode_name, $depth = 0); - /** - * Remove BBCodes and other formatting from a parsed text - * - * NOTE: preserves smilies as text - * - * @param string $text - * @return string - */ - public function remove_formatting($text); - /** * Return a parsed text to its original form * - * @param string $text - * @return string + * @param string $text Parsed text + * @return string Original plain text */ public function unparse($text); } diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index 6f0ef54182..69f8682cac 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -45,35 +45,6 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case ); } - /** - * @dataProvider get_remove_formatting_tests - */ - public function test_remove_formatting($original, $expected) - { - $container = $this->get_test_case_helpers()->set_s9e_services(); - $utils = $container->get('text_formatter.utils'); - - $this->assertSame($expected, $utils->remove_formatting($original)); - } - - public function get_remove_formatting_tests() - { - return array( - array( - 'Plain text', - 'Plain text' - ), - array( - "Multi
              \nline
              ", - "Multi\nline" - ), - array( - '[b]bold[/b]', - 'bold' - ) - ); - } - /** * @dataProvider get_clean_formatting_tests */ From c1bc05a8605ef34c12f42d0ac14e45cca6fbace3 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 26 Mar 2015 17:07:58 +0100 Subject: [PATCH 0215/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- phpBB/phpbb/textformatter/s9e/factory.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 706dd4ba63..610a2b5510 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "ad4384b2c792cf55c456de018a525bbaea106fc0" + "reference": "564074d68ec4295b7b9746e5f712366af947d3d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/ad4384b2c792cf55c456de018a525bbaea106fc0", - "reference": "ad4384b2c792cf55c456de018a525bbaea106fc0", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/564074d68ec4295b7b9746e5f712366af947d3d7", + "reference": "564074d68ec4295b7b9746e5f712366af947d3d7", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-25 02:37:49" + "time": "2015-03-26 15:45:58" }, { "name": "symfony/config", diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index bad9190973..9576abe1f0 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -14,7 +14,7 @@ namespace phpbb\textformatter\s9e; use s9e\TextFormatter\Configurator; -use s9e\TextFormatter\Configurator\Items\AttributeFilters\Regexp as RegexpFilter; +use s9e\TextFormatter\Configurator\Items\AttributeFilters\RegexpFilter; use s9e\TextFormatter\Configurator\Items\UnsafeTemplate; /** From 0f30301a0cf01c609cdcd5e4d777a47872a4dcba Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 26 Mar 2015 18:32:13 +0100 Subject: [PATCH 0216/1676] [ticket/11768] Moved parser/renderer setup events Moved down the setup events to make them happen after the service is configured and ready to be used PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/parser.php | 8 ++++---- phpBB/phpbb/textformatter/s9e/renderer.php | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index f220dd3e64..ab81a0ab4f 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -53,6 +53,10 @@ class parser implements \phpbb\textformatter\parser_interface $objects = $factory->regenerate(); $parser = $objects['parser']; } + + $this->dispatcher = $dispatcher; + $this->parser = $parser; + $this->user = $user; $self = $this; /** @@ -72,10 +76,6 @@ class parser implements \phpbb\textformatter\parser_interface */ $vars = array('parser', 'self', 'user'); extract($dispatcher->trigger_event('core.text_formatter_s9e_parser_setup', compact($vars))); - - $this->dispatcher = $dispatcher; - $this->parser = $parser; - $this->user = $user; } /** diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 272cc5e6f3..28498150b3 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -92,6 +92,13 @@ class renderer implements \phpbb\textformatter\renderer_interface $objects = $factory->regenerate(); $renderer = $objects['renderer']; } + + if (isset($censor)) + { + $this->censor = $censor; + } + $this->dispatcher = $dispatcher; + $this->renderer = $renderer; $self = $this; /** @@ -104,13 +111,6 @@ class renderer implements \phpbb\textformatter\renderer_interface */ $vars = array('renderer', 'self'); extract($dispatcher->trigger_event('core.text_formatter_s9e_renderer_setup', compact($vars))); - - if (isset($censor)) - { - $this->censor = $censor; - } - $this->dispatcher = $dispatcher; - $this->renderer = $renderer; } /** From 3e04e643df4ca5463450df5d94f3caca3e5596c0 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 27 Mar 2015 01:12:57 +0100 Subject: [PATCH 0217/1676] [ticket/11768] Restored get_parser() / get_renderer() PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/parser.php | 10 ++++++++++ phpBB/phpbb/textformatter/s9e/renderer.php | 10 ++++++++++ tests/text_formatter/s9e/parser_test.php | 7 +++++++ tests/text_formatter/s9e/renderer_test.php | 7 +++++++ 4 files changed, 34 insertions(+) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index ab81a0ab4f..fb6ef03c1c 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -241,6 +241,16 @@ class parser implements \phpbb\textformatter\parser_interface return array_unique($errors); } + /** + * Return the instance of s9e\TextFormatter\Parser used by this object + * + * @return \s9e\TextFormatter\Parser + */ + public function get_parser() + { + return $this->parser; + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 28498150b3..02461b3849 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -163,6 +163,16 @@ class renderer implements \phpbb\textformatter\renderer_interface $this->renderer->setParameter('STYLE_ID', $user->style['style_id']); } + /** + * Return the instance of s9e\TextFormatter\Renderer used by this object + * + * @return \s9e\TextFormatter\Renderer + */ + public function get_renderer() + { + return $this->renderer; + } + /** * {@inheritdoc} */ diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index 74182bda47..2904df25b4 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -260,4 +260,11 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case && isset($vars['xml']) && $vars['xml'] === '...'; } + + public function test_get_parser() + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $parser = $container->get('text_formatter.parser'); + $this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser->get_parser()); + } } diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index c69a93dbc1..8835a80d9d 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -443,4 +443,11 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case && isset($vars['self']) && $vars['self'] instanceof \phpbb\textformatter\s9e\renderer; } + + public function test_get_renderer() + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $renderer = $container->get('text_formatter.renderer'); + $this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer->get_renderer()); + } } From d8e7e11ee3a5c49e80a4ec3e0bdf2011ba5e9ce7 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 27 Mar 2015 01:29:09 +0100 Subject: [PATCH 0218/1676] [ticket/11768] Renamed service vars The name of the variable that holds the service instance is now consistent across events. PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/parser.php | 17 ++++++++--------- phpBB/phpbb/textformatter/s9e/renderer.php | 17 ++++++++--------- tests/text_formatter/s9e/parser_test.php | 12 +++++------- tests/text_formatter/s9e/renderer_test.php | 12 +++++------- 4 files changed, 26 insertions(+), 32 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index fb6ef03c1c..77328ee4d9 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -57,7 +57,7 @@ class parser implements \phpbb\textformatter\parser_interface $this->dispatcher = $dispatcher; $this->parser = $parser; $this->user = $user; - $self = $this; + $parser = $this; /** * Configure the parser service @@ -69,12 +69,11 @@ class parser implements \phpbb\textformatter\parser_interface * - configure the s9e\TextFormatter parser * * @event core.text_formatter_s9e_parser_setup - * @var \s9e\TextFormatter\Parser parser s9e\TextFormatter parser instance - * @var \phpbb\textformatter\s9e\parser self This parser service + * @var \phpbb\textformatter\s9e\parser parser This parser service * @var \phpbb\user user Current user * @since 3.2.0-a1 */ - $vars = array('parser', 'self', 'user'); + $vars = array('parser', 'user'); extract($dispatcher->trigger_event('core.text_formatter_s9e_parser_setup', compact($vars))); } @@ -83,17 +82,17 @@ class parser implements \phpbb\textformatter\parser_interface */ public function parse($text) { - $self = $this; + $parser = $this; /** * Modify a text before it is parsed * * @event core.text_formatter_s9e_parse_before - * @var \phpbb\textformatter\s9e\parser self This parser service + * @var \phpbb\textformatter\s9e\parser parser This parser service * @var string text The original text * @since 3.2.0-a1 */ - $vars = array('self', 'text'); + $vars = array('parser', 'text'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_parse_before', compact($vars))); $xml = $this->parser->parse($text); @@ -102,11 +101,11 @@ class parser implements \phpbb\textformatter\parser_interface * Modify a parsed text in its XML form * * @event core.text_formatter_s9e_parse_after - * @var \phpbb\textformatter\s9e\parser self This parser service + * @var \phpbb\textformatter\s9e\parser parser This parser service * @var string xml The parsed text, in XML * @since 3.2.0-a1 */ - $vars = array('self', 'xml'); + $vars = array('parser', 'xml'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_parse_after', compact($vars))); return $xml; diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 02461b3849..168b13e692 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -99,17 +99,16 @@ class renderer implements \phpbb\textformatter\renderer_interface } $this->dispatcher = $dispatcher; $this->renderer = $renderer; - $self = $this; + $renderer = $this; /** * Configure the renderer service * * @event core.text_formatter_s9e_renderer_setup - * @var \s9e\TextFormatter\Renderer renderer s9e\TextFormatter renderer instance - * @var \phpbb\textformatter\s9e\renderer self This renderer service + * @var \phpbb\textformatter\s9e\renderer renderer This renderer service * @since 3.2.0-a1 */ - $vars = array('renderer', 'self'); + $vars = array('renderer'); extract($dispatcher->trigger_event('core.text_formatter_s9e_renderer_setup', compact($vars))); } @@ -210,17 +209,17 @@ class renderer implements \phpbb\textformatter\renderer_interface */ public function render($xml) { - $self = $this; + $renderer = $this; /** * Modify a parsed text before it is rendered * * @event core.text_formatter_s9e_render_before - * @var \phpbb\textformatter\s9e\renderer self This renderer service + * @var \phpbb\textformatter\s9e\renderer renderer This renderer service * @var string xml The parsed text, in its XML form * @since 3.2.0-a1 */ - $vars = array('self', 'xml'); + $vars = array('renderer', 'xml'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_before', compact($vars))); if (isset($this->censor) && $this->viewcensors) @@ -267,10 +266,10 @@ class renderer implements \phpbb\textformatter\renderer_interface * * @event core.text_formatter_s9e_render_after * @var string html The rendered text's HTML - * @var \phpbb\textformatter\s9e\renderer self This renderer service + * @var \phpbb\textformatter\s9e\renderer renderer This renderer service * @since 3.2.0-a1 */ - $vars = array('html', 'self'); + $vars = array('html', 'renderer'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_after', compact($vars))); return $html; diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index 2904df25b4..71966f9d36 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -200,9 +200,7 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case public function setup_event_callback($vars) { return isset($vars['parser']) - && $vars['parser'] instanceof \s9e\TextFormatter\Parser - && isset($vars['self']) - && $vars['self'] instanceof \phpbb\textformatter\s9e\parser + && $vars['parser'] instanceof \phpbb\textformatter\s9e\parser && isset($vars['user']) && $vars['user'] instanceof \phpbb\user; } @@ -247,16 +245,16 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case public function parse_before_event_callback($vars) { - return isset($vars['self']) - && $vars['self'] instanceof \phpbb\textformatter\s9e\parser + return isset($vars['parser']) + && $vars['parser'] instanceof \phpbb\textformatter\s9e\parser && isset($vars['text']) && $vars['text'] === '...'; } public function parse_after_event_callback($vars) { - return isset($vars['self']) - && $vars['self'] instanceof \phpbb\textformatter\s9e\parser + return isset($vars['parser']) + && $vars['parser'] instanceof \phpbb\textformatter\s9e\parser && isset($vars['xml']) && $vars['xml'] === '...'; } diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index 8835a80d9d..91458541d3 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -385,9 +385,7 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case public function setup_event_callback($vars) { return isset($vars['renderer']) - && $vars['renderer'] instanceof \s9e\TextFormatter\Renderer - && isset($vars['self']) - && $vars['self'] instanceof \phpbb\textformatter\s9e\renderer; + && $vars['renderer'] instanceof \phpbb\textformatter\s9e\renderer; } /** @@ -430,8 +428,8 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case public function render_before_event_callback($vars) { - return isset($vars['self']) - && $vars['self'] instanceof \phpbb\textformatter\s9e\renderer + return isset($vars['renderer']) + && $vars['renderer'] instanceof \phpbb\textformatter\s9e\renderer && isset($vars['xml']) && $vars['xml'] === '...'; } @@ -440,8 +438,8 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case { return isset($vars['html']) && $vars['html'] === '...' - && isset($vars['self']) - && $vars['self'] instanceof \phpbb\textformatter\s9e\renderer; + && isset($vars['renderer']) + && $vars['renderer'] instanceof \phpbb\textformatter\s9e\renderer; } public function test_get_renderer() From 76088d64a69ac8fdd10b8a633e72eefc1e36321b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 27 Mar 2015 01:52:26 +0100 Subject: [PATCH 0219/1676] [ticket/11768] Moved the routine that replaces tabs with spaces ...to its own method. Also added a quick stripos() check for performance. PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/renderer.php | 44 ++++++++++++++-------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 168b13e692..7c58cd3d03 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -229,12 +229,37 @@ class renderer implements \phpbb\textformatter\renderer_interface } $html = $this->renderer->render($xml); + if (stripos($html, 'replace_tabs_in_code($html); + } /** - * @see bbcode::bbcode_second_pass_code() + * Modify a rendered text + * + * @event core.text_formatter_s9e_render_after + * @var string html The rendered text's HTML + * @var \phpbb\textformatter\s9e\renderer renderer This renderer service + * @since 3.2.0-a1 */ - $html = preg_replace_callback( - '#(]*>)(.*?)()#is', + $vars = array('html', 'renderer'); + extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_after', compact($vars))); + + return $html; + } + + /** + * Replace tabs in code elements + * + * @see bbcode::bbcode_second_pass_code() + * + * @param string $html Original HTML + * @return string Modified HTML + */ + protected function replace_tabs_in_code($html) + { + return preg_replace_callback( + '((]*>)(.*?)())is', function ($captures) { $code = $captures[2]; @@ -260,19 +285,6 @@ class renderer implements \phpbb\textformatter\renderer_interface }, $html ); - - /** - * Modify a rendered text - * - * @event core.text_formatter_s9e_render_after - * @var string html The rendered text's HTML - * @var \phpbb\textformatter\s9e\renderer renderer This renderer service - * @since 3.2.0-a1 - */ - $vars = array('html', 'renderer'); - extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_after', compact($vars))); - - return $html; } /** From 09c19718c0d1ebb8c40aac846760172ed2f13c26 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 27 Mar 2015 13:02:10 +0100 Subject: [PATCH 0220/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 610a2b5510..b6208221a2 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "564074d68ec4295b7b9746e5f712366af947d3d7" + "reference": "febd66b686fa35691e181037a97cb33336a6c57a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/564074d68ec4295b7b9746e5f712366af947d3d7", - "reference": "564074d68ec4295b7b9746e5f712366af947d3d7", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/febd66b686fa35691e181037a97cb33336a6c57a", + "reference": "febd66b686fa35691e181037a97cb33336a6c57a", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-26 15:45:58" + "time": "2015-03-27 11:57:24" }, { "name": "symfony/config", From 1d90daf96963de3349cecc54d36ae421a24e0612 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 29 Mar 2015 23:00:29 +0200 Subject: [PATCH 0221/1676] [ticket/11768] Added some default template parameters PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/renderer.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 7c58cd3d03..7c69f37371 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -158,8 +158,13 @@ class renderer implements \phpbb\textformatter\renderer_interface } } - // Set the style id - $this->renderer->setParameter('STYLE_ID', $user->style['style_id']); + // Set this user's style id and other parameters + $this->renderer->setParameters(array( + 'S_IS_BOT' => $user->data['is_bot'], + 'S_REGISTERED_USER' => $user->data['is_registered'], + 'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS), + 'STYLE_ID' => $user->style['style_id'], + )); } /** From b24e0f4f69b6436b3a654502d44d15333b0dfdc3 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 30 Mar 2015 03:31:38 +0200 Subject: [PATCH 0222/1676] [ticket/11768] Stylistic change. No functional change intended PHPBB3-11768 --- phpBB/phpbb/textformatter/s9e/renderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 7c69f37371..8999f1d25f 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -151,7 +151,7 @@ class renderer implements \phpbb\textformatter\renderer_interface // Set the stylesheet parameters foreach (array_keys($this->renderer->getParameters()) as $param_name) { - if (substr($param_name, 0, 2) === 'L_') + if (strpos($param_name, 'L_') === 0) { // L_FOO is set to $user->lang('FOO') $this->renderer->setParameter($param_name, $user->lang(substr($param_name, 2))); From 4e80565fe7862da4ea1948c6ece1099a59a1020f Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 31 Mar 2015 02:29:16 +0200 Subject: [PATCH 0223/1676] [ticket/11768] Updated s9e\TextFormatter PHPBB3-11768 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index b6208221a2..8a634a1ffd 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "febd66b686fa35691e181037a97cb33336a6c57a" + "reference": "4e0d311a3c56d0db4a7789e31457053be8148283" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/febd66b686fa35691e181037a97cb33336a6c57a", - "reference": "febd66b686fa35691e181037a97cb33336a6c57a", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/4e0d311a3c56d0db4a7789e31457053be8148283", + "reference": "4e0d311a3c56d0db4a7789e31457053be8148283", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-27 11:57:24" + "time": "2015-03-30 22:52:16" }, { "name": "symfony/config", From 477f7823e5f51b083c13881d221835ae34c15b8f Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 6 Apr 2015 12:08:55 +0200 Subject: [PATCH 0224/1676] [ticket/13522] Fix globals for 3.2 in Q&A tests PHPBB3-13522 --- tests/captcha/qa_test.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/captcha/qa_test.php b/tests/captcha/qa_test.php index 1f2f9f3070..4aa5e714f5 100644 --- a/tests/captcha/qa_test.php +++ b/tests/captcha/qa_test.php @@ -27,14 +27,16 @@ class phpbb_captcha_qa_test extends \phpbb_database_test_case public function setUp() { - global $db; + global $db, $request, $phpbb_container; $db = $this->new_dbal(); parent::setUp(); - $this->request = new \phpbb_mock_request(); - request_var(false, false, false, false, $this->request); + $request = new \phpbb_mock_request(); + $phpbb_container = new \phpbb_mock_container_builder(); + $factory = new \phpbb\db\tools\factory(); + $phpbb_container->set('dbal.tools', $factory->get($db)); $this->qa = new \phpbb\captcha\plugins\qa('phpbb_captcha_questions', 'phpbb_captcha_answers', 'phpbb_qa_confirm'); } @@ -87,7 +89,8 @@ class phpbb_captcha_qa_test extends \phpbb_database_test_case */ public function test_acp_get_question_input($value, $expected) { - $this->request->overwrite('answers', $value); + global $request; + $request->overwrite('answers', $value); $this->assertEquals($expected, $this->qa->acp_get_question_input()); } From a089ff5eb0dcdab83c6c2e64cb0e7cb618aec41f Mon Sep 17 00:00:00 2001 From: MateBartus Date: Wed, 25 Feb 2015 21:13:20 +0100 Subject: [PATCH 0225/1676] [ticket/13654] Moving reporting into controller Moving report.php's content into different services and controllers to better comply with the MVC model. Also implementing: * Replacement for reasons_display() * Adding assign_meta_refresh_var() to \controller\helper * Adding separate routes for easy configuration * Updating unit tests to expect to correct results * Add BC tests PHPBB3-13654 --- phpBB/config/default/container/services.yml | 1 + .../default/container/services_report.yml | 53 +++ phpBB/config/default/routing/report.yml | 17 + phpBB/config/default/routing/routing.yml | 3 + phpBB/includes/functions_display.php | 27 +- phpBB/includes/mcp/mcp_queue.php | 7 +- phpBB/includes/ucp/ucp_pm_viewmessage.php | 2 +- phpBB/phpbb/controller/helper.php | 14 + phpBB/phpbb/report/controller/report.php | 319 +++++++++++++++++ .../exception/already_reported_exception.php | 19 ++ .../exception/empty_report_exception.php | 22 ++ .../exception/entity_not_found_exception.php | 19 ++ .../factory_invalid_argument_exception.php | 21 ++ .../exception/invalid_report_exception.php | 21 ++ .../pm_reporting_disabled_exception.php | 22 ++ .../report_permission_denied_exception.php | 19 ++ phpBB/phpbb/report/handler_factory.php | 56 +++ phpBB/phpbb/report/report_handler.php | 104 ++++++ .../phpbb/report/report_handler_interface.php | 43 +++ phpBB/phpbb/report/report_handler_pm.php | 137 ++++++++ phpBB/phpbb/report/report_handler_post.php | 175 ++++++++++ .../report/report_reason_list_provider.php | 78 +++++ phpBB/report.php | 320 +----------------- phpBB/viewtopic.php | 2 +- .../controllers_compatibility_test.php | 43 +++ tests/functional/report_post_captcha_test.php | 7 +- 26 files changed, 1208 insertions(+), 343 deletions(-) create mode 100644 phpBB/config/default/container/services_report.yml create mode 100644 phpBB/config/default/routing/report.yml create mode 100644 phpBB/phpbb/report/controller/report.php create mode 100644 phpBB/phpbb/report/exception/already_reported_exception.php create mode 100644 phpBB/phpbb/report/exception/empty_report_exception.php create mode 100644 phpBB/phpbb/report/exception/entity_not_found_exception.php create mode 100644 phpBB/phpbb/report/exception/factory_invalid_argument_exception.php create mode 100644 phpBB/phpbb/report/exception/invalid_report_exception.php create mode 100644 phpBB/phpbb/report/exception/pm_reporting_disabled_exception.php create mode 100644 phpBB/phpbb/report/exception/report_permission_denied_exception.php create mode 100644 phpBB/phpbb/report/handler_factory.php create mode 100644 phpBB/phpbb/report/report_handler.php create mode 100644 phpBB/phpbb/report/report_handler_interface.php create mode 100644 phpBB/phpbb/report/report_handler_pm.php create mode 100644 phpBB/phpbb/report/report_handler_post.php create mode 100644 phpBB/phpbb/report/report_reason_list_provider.php create mode 100644 tests/functional/controllers_compatibility_test.php diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 4f1aba953f..c964302b86 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -13,6 +13,7 @@ imports: - { resource: services_notification.yml } - { resource: services_password.yml } - { resource: services_profilefield.yml } + - { resource: services_report.yml } - { resource: services_text_formatter.yml } - { resource: services_twig.yml } - { resource: services_user.yml } diff --git a/phpBB/config/default/container/services_report.yml b/phpBB/config/default/container/services_report.yml new file mode 100644 index 0000000000..4bf929429e --- /dev/null +++ b/phpBB/config/default/container/services_report.yml @@ -0,0 +1,53 @@ +services: +# ----- Report controller ----- + phpbb.report.controller: + class: phpbb\report\controller\report + arguments: + - @config + - @user + - @template + - @controller.helper + - @request + - @captcha.factory + - @phpbb.report.handler_factory + - @phpbb.report.report_reason_list_provider + - %core.root_path% + - %core.php_ext% + +# ----- Report handler factory ----- + phpbb.report.handler_factory: + class: phpbb\report\handler_factory + arguments: + - @service_container + +# ----- Report UI provider ----- + phpbb.report.report_reason_list_provider: + class: phpbb\report\report_reason_list_provider + arguments: + - @dbal.conn.driver + - @template + - @user + +# ----- Report handlers ----- +# Scope MUST be prototype for all the handlers to work correctly. + phpbb.report.handlers.report_handler_pm: + class: phpbb\report\report_handler_pm + scope: prototype + arguments: + - @dbal.conn.driver + - @dispatcher + - @config + - @auth + - @user + - @notification_manager + + phpbb.report.handlers.report_handler_post: + class: phpbb\report\report_handler_post + scope: prototype + arguments: + - @dbal.conn.driver + - @dispatcher + - @config + - @auth + - @user + - @notification_manager diff --git a/phpBB/config/default/routing/report.yml b/phpBB/config/default/routing/report.yml new file mode 100644 index 0000000000..dbe2d853c0 --- /dev/null +++ b/phpBB/config/default/routing/report.yml @@ -0,0 +1,17 @@ +phpbb_report_pm_controller: + path: /pm/{id}/report + methods: [GET, POST] + defaults: + _controller: phpbb.report.controller:handle + mode: "pm" + requirements: + id: \d+ + +phpbb_report_post_controller: + path: /post/{id}/report + methods: [GET, POST] + defaults: + _controller: phpbb.report.controller:handle + mode: "post" + requirements: + id: \d+ diff --git a/phpBB/config/default/routing/routing.yml b/phpBB/config/default/routing/routing.yml index d6881f1959..b7e7a69b4f 100644 --- a/phpBB/config/default/routing/routing.yml +++ b/phpBB/config/default/routing/routing.yml @@ -11,3 +11,6 @@ phpbb_help_routing: resource: "help.yml" prefix: /help + +phpbb_report_routing: + resource: "report.yml" diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index a6c9c529d6..64d20924d9 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -1097,33 +1097,14 @@ function display_custom_bbcodes() /** * Display reasons +* +* @deprecated 3.2.0-dev */ function display_reasons($reason_id = 0) { - global $db, $user, $template; + global $phpbb_container; - $sql = 'SELECT * - FROM ' . REPORTS_REASONS_TABLE . ' - ORDER BY reason_order ASC'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - // If the reason is defined within the language file, we will use the localized version, else just use the database entry... - if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) - { - $row['reason_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; - $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; - } - - $template->assign_block_vars('reason', array( - 'ID' => $row['reason_id'], - 'TITLE' => $row['reason_title'], - 'DESCRIPTION' => $row['reason_description'], - 'S_SELECTED' => ($row['reason_id'] == $reason_id) ? true : false) - ); - } - $db->sql_freeresult($result); + $phpbb_container->get('phpbb.report.report_reason_list_provider')->display_reasons($reason_id); } /** diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index 84db205fec..5cc158de5f 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -1402,11 +1402,6 @@ class mcp_queue } else { - if (!function_exists('display_reasons')) - { - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - } - $show_notify = false; foreach ($post_info as $post_data) @@ -1426,7 +1421,7 @@ class mcp_queue $confirm_template = 'mcp_approve.html'; if ($is_disapproving) { - display_reasons($reason_id); + $phpbb_container->get('phpbb.report.report_reason_list_provider')->display_reasons($reason_id); } else { diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index 52948cea19..44564ed562 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -232,7 +232,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&mode=compose&action=delete&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_EMAIL' => $user_info['email'], - 'U_REPORT' => ($config['allow_pm_report']) ? append_sid("{$phpbb_root_path}report.$phpEx", "pm=" . $message_row['msg_id']) : '', + 'U_REPORT' => ($config['allow_pm_report']) ? $phpbb_container->get('controller.helper')->route('phpbb_report_pm_controller', array('id' => $message_row['msg_id'])) : '', 'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_EDIT' => (($message_row['message_time'] > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&mode=compose&action=edit&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $message_row['msg_id'] : '', diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index 340b29306a..74e6cb7034 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -223,6 +223,20 @@ class helper return $this->render('message_body.html', $this->user->lang($title), $code); } + /** + * Assigns automatic refresh time meta tag in template + * + * @param int $time time in seconds, when redirection should occur + * @param string $url the URL where the user should be redirected + * @return null + */ + public function assign_meta_refresh_var($time, $url) + { + $this->template->assign_vars(array( + 'META' => '', + )); + } + /** * Return the current url * diff --git a/phpBB/phpbb/report/controller/report.php b/phpBB/phpbb/report/controller/report.php new file mode 100644 index 0000000000..f703d1cc60 --- /dev/null +++ b/phpBB/phpbb/report/controller/report.php @@ -0,0 +1,319 @@ + + * @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\report\controller; + +use phpbb\exception\http_exception; +use Symfony\Component\HttpFoundation\RedirectResponse; + +class report +{ + /** + * @var \phpbb\config\db + */ + protected $config; + + /** + * @var \phpbb\user + */ + protected $user; + + /** + * @var \phpbb\template\template + */ + protected $template; + + /** + * @var \phpbb\controller\helper + */ + protected $helper; + + /** + * @var \phpbb\request\request_interface + */ + protected $request; + + /** + * @var \phpbb\captcha\factory + */ + protected $captcha_factory; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var string + */ + protected $php_ext; + + /** + * @var \phpbb\report\report_handler_interface + */ + protected $report_handler; + + /** + * @var \phpbb\report\report_reason_list_provider + */ + protected $report_reason_provider; + + public function __construct(\phpbb\config\db $config, \phpbb\user $user, \phpbb\template\template $template, \phpbb\controller\helper $helper, \phpbb\request\request_interface $request, \phpbb\captcha\factory $captcha_factory, \phpbb\report\handler_factory $report_factory, \phpbb\report\report_reason_list_provider $ui_provider, $phpbb_root_path, $php_ext) + { + $this->config = $config; + $this->user = $user; + $this->template = $template; + $this->helper = $helper; + $this->request = $request; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + $this->captcha_factory = $captcha_factory; + $this->report_handler = $report_factory; + + // User interface factory + $this->report_reason_provider = $ui_provider; + } + + /** + * Controller for /path_to_entities/{id}/report routes + * + * Because of how phpBB organizes routes $mode must be set in the route config. + * + * @param int $id ID of the entity to report + * @param string $mode + * @return \Symfony\Component\HttpFoundation\Response a Symfony response object + * @throws \phpbb\exception\http_exception when $mode or $id is invalid for some reason + */ + public function handle($id, $mode) + { + // Get report handler + $this->report_handler = $this->report_handler->get_instance($mode); + + $this->user->add_lang('mcp'); + + $user_notify = ($this->user->data['is_registered']) ? $this->request->variable('notify', 0) : false; + $reason_id = $this->request->variable('reason_id', 0); + $report_text = $this->request->variable('report_text', '', true); + + $submit = $this->request->variable('submit', ''); + $cancel = $this->request->variable('cancel', ''); + + $error = array(); + $s_hidden_fields = ''; + + $redirect_url = append_sid( + $this->phpbb_root_path . ( ($mode === 'pm') ? 'ucp' : 'viewtopic' ) . ".{$this->php_ext}", + ($mode == 'pm') ? "i=pm&mode=view&p=$id" : "p=$id" + ); + $redirect_url .= ($mode === 'post') ? "#p$id" : ''; + + // Set up CAPTCHA if necessary + if ($this->config['enable_post_confirm'] && !$this->user->data['is_registered']) + { + $captcha = $this->captcha_factory->get_instance($this->config['captcha_plugin']); + $captcha->init(CONFIRM_REPORT); + } + + //Has the report been cancelled? + if (!empty($cancel)) + { + return new RedirectResponse($redirect_url, 302); + } + + // Check CAPTCHA, if the form was submited + if (!empty($submit) && isset($captcha)) + { + $captcha_template_array = $this->check_captcha($captcha); + $error = $captcha_template_array['error']; + $s_hidden_fields = $captcha_template_array['hidden_fields']; + } + + // Handle request + try + { + if (!empty($submit) && sizeof($error) === 0) + { + $this->report_handler->add_report( + (int) $id, + (int) $reason_id, + (string) $report_text, + (int) $user_notify + ); + + // Send success message + switch ($mode) + { + case 'pm': + $lang_return = $this->user->lang['RETURN_PM']; + $lang_success = $this->user->lang['PM_REPORTED_SUCCESS']; + break; + case 'post': + $lang_return = $this->user->lang['RETURN_TOPIC']; + $lang_success = $this->user->lang['POST_REPORTED_SUCCESS']; + break; + } + + $this->helper->assign_meta_refresh_var(3, $redirect_url); + $message = $lang_success . '

              ' . sprintf($lang_return, '', ''); + return $this->helper->message($message); + } + else + { + $this->report_handler->validate_report_request($id); + } + } + catch (\phpbb\report\exception\pm_reporting_disabled_exception $exception) + { + throw new http_exception(404, 'PAGE_NOT_FOUND'); + } + catch (\phpbb\report\exception\already_reported_exception $exception) + { + switch ($mode) + { + case 'pm': + $message = $this->user->lang['ALREADY_REPORTED_PM']; + $message .= '

              ' . sprintf($this->user->lang['RETURN_PM'], '', ''); + break; + case 'post': + $message = $this->user->lang['ALREADY_REPORTED']; + $message .= '

              ' . sprintf($this->user->lang['RETURN_TOPIC'], '', ''); + break; + } + + return $this->helper->message($message); + } + catch (\phpbb\report\exception\report_permission_denied_exception $exception) + { + $message = $exception->getMessage(); + if (isset($this->user->lang[$message])) + { + $message = $this->user->lang[$message]; + } + + throw new http_exception(403, $message); + } + catch (\phpbb\report\exception\entity_not_found_exception $exception) + { + $message = $exception->getMessage(); + if (isset($this->user->lang[$message])) + { + $message = $this->user->lang[$message]; + } + + throw new http_exception(404, $message); + } + catch (\phpbb\report\exception\empty_report_exception $exception) + { + $error[] = $this->user->lang['EMPTY_REPORT']; + } + catch (\phpbb\report\exception\invalid_report_exception $exception) + { + return $this->helper->message($exception->getMessage()); + } + + // Setting up an rendering template + $page_title = ($mode === 'pm') ? $this->user->lang['REPORT_MESSAGE'] : $this->user->lang['REPORT_POST']; + $this->assign_template_data( + $mode, + $id, + $reason_id, + $report_text, + $user_notify, + $error, + $s_hidden_fields, + ( isset($captcha) ? $captcha : false ) + ); + + return $this->helper->render('report_body.html', $page_title); + } + + /** + * Assigns template variables + * + * @param int $mode + * @param int $id + * @param int $reason_id + * @param string $report_text + * @param mixed $user_notify + * @param array $error + * @param string $s_hidden_fields + * @param mixed $captcha + * @return null + */ + protected function assign_template_data($mode, $id, $reason_id, $report_text, $user_notify, $error = array(), $s_hidden_fields = '', $captcha = false) + { + if ($captcha !== false && $captcha->is_solved() === false) + { + $this->template->assign_vars(array( + 'S_CONFIRM_CODE' => true, + 'CAPTCHA_TEMPLATE' => $captcha->get_template(), + )); + } + + $this->report_reason_provider->display_reasons($reason_id); + + switch ($mode) + { + case 'pm': + $report_route = $this->helper->route('phpbb_report_pm_controller', array('id' => $id)); + break; + case 'post': + $report_route = $this->helper->route('phpbb_report_post_controller', array('id' => $id)); + break; + } + + $this->template->assign_vars(array( + 'ERROR' => (sizeof($error) > 0) ? implode('
              ', $error) : '', + 'S_REPORT_POST' => ($mode === 'pm') ? false : true, + 'REPORT_TEXT' => $report_text, + 'S_HIDDEN_FIELDS' => (!empty($s_hidden_fields)) ? $s_hidden_fields : null, + 'S_REPORT_ACTION' => $report_route, + + 'S_NOTIFY' => $user_notify, + 'S_CAN_NOTIFY' => ($this->user->data['is_registered']) ? true : false, + 'S_IN_REPORT' => true, + )); + } + + /** + * Check CAPTCHA + * + * @param object $captcha A phpBB CAPTCHA object + * @return array template variables which ensures that CAPTCHA's work correctly + */ + protected function check_captcha($captcha) + { + $error = array(); + $captcha_hidden_fields = ''; + + $visual_confirmation_response = $captcha->validate(); + if ($visual_confirmation_response) + { + $error[] = $visual_confirmation_response; + } + + if (sizeof($error) === 0) + { + $captcha->reset(); + } + else if ($captcha->is_solved() !== false) + { + $captcha_hidden_fields = build_hidden_fields($captcha->get_hidden_fields()); + } + + return array( + 'error' => $error, + 'hidden_fields' => $captcha_hidden_fields, + ); + } +} diff --git a/phpBB/phpbb/report/exception/already_reported_exception.php b/phpBB/phpbb/report/exception/already_reported_exception.php new file mode 100644 index 0000000000..54174044fe --- /dev/null +++ b/phpBB/phpbb/report/exception/already_reported_exception.php @@ -0,0 +1,19 @@ + + * @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\report\exception; + +class already_reported_exception extends invalid_report_exception +{ + +} diff --git a/phpBB/phpbb/report/exception/empty_report_exception.php b/phpBB/phpbb/report/exception/empty_report_exception.php new file mode 100644 index 0000000000..8c968dca80 --- /dev/null +++ b/phpBB/phpbb/report/exception/empty_report_exception.php @@ -0,0 +1,22 @@ + + * @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\report\exception; + +class empty_report_exception extends invalid_report_exception +{ + public function __construct() + { + parent::__construct('EMPTY_REPORT'); + } +} diff --git a/phpBB/phpbb/report/exception/entity_not_found_exception.php b/phpBB/phpbb/report/exception/entity_not_found_exception.php new file mode 100644 index 0000000000..732aa58a13 --- /dev/null +++ b/phpBB/phpbb/report/exception/entity_not_found_exception.php @@ -0,0 +1,19 @@ + + * @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\report\exception; + +class entity_not_found_exception extends invalid_report_exception +{ + +} diff --git a/phpBB/phpbb/report/exception/factory_invalid_argument_exception.php b/phpBB/phpbb/report/exception/factory_invalid_argument_exception.php new file mode 100644 index 0000000000..19de91eea3 --- /dev/null +++ b/phpBB/phpbb/report/exception/factory_invalid_argument_exception.php @@ -0,0 +1,21 @@ + + * @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\report\exception; + +use \phpbb\exception\runtime_exception; + +class factory_invalid_argument_exception extends runtime_exception +{ + +} diff --git a/phpBB/phpbb/report/exception/invalid_report_exception.php b/phpBB/phpbb/report/exception/invalid_report_exception.php new file mode 100644 index 0000000000..03ff0a872d --- /dev/null +++ b/phpBB/phpbb/report/exception/invalid_report_exception.php @@ -0,0 +1,21 @@ + + * @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\report\exception; + +use \phpbb\exception\runtime_exception; + +class invalid_report_exception extends runtime_exception +{ + +} diff --git a/phpBB/phpbb/report/exception/pm_reporting_disabled_exception.php b/phpBB/phpbb/report/exception/pm_reporting_disabled_exception.php new file mode 100644 index 0000000000..2c8ab8cf84 --- /dev/null +++ b/phpBB/phpbb/report/exception/pm_reporting_disabled_exception.php @@ -0,0 +1,22 @@ + + * @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\report\exception; + +class pm_reporting_disabled_exception extends invalid_report_exception +{ + public function __construct() + { + + } +} diff --git a/phpBB/phpbb/report/exception/report_permission_denied_exception.php b/phpBB/phpbb/report/exception/report_permission_denied_exception.php new file mode 100644 index 0000000000..c7069288b8 --- /dev/null +++ b/phpBB/phpbb/report/exception/report_permission_denied_exception.php @@ -0,0 +1,19 @@ + + * @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\report\exception; + +class report_permission_denied_exception extends invalid_report_exception +{ + +} diff --git a/phpBB/phpbb/report/handler_factory.php b/phpBB/phpbb/report/handler_factory.php new file mode 100644 index 0000000000..ec229aac54 --- /dev/null +++ b/phpBB/phpbb/report/handler_factory.php @@ -0,0 +1,56 @@ + + * @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\report; + +use phpbb\report\exception\factory_invalid_argument_exception; + +class handler_factory +{ + /** + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + /** + * Constructor + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + */ + public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container) + { + $this->container = $container; + } + + /** + * Return a new instance of an appropriate report handler + * + * @param string $type + * @return \phpbb\report\report_handler_interface + * @throws \phpbb\report\exception\factory_invalid_argument_exception if $type is not valid + */ + public function get_instance($type) + { + switch ($type) + { + case 'pm': + return $this->container->get('phpbb.report.handlers.report_handler_pm'); + break; + case 'post': + return $this->container->get('phpbb.report.handlers.report_handler_post'); + break; + } + + throw new factory_invalid_argument_exception(); + } +} diff --git a/phpBB/phpbb/report/report_handler.php b/phpBB/phpbb/report/report_handler.php new file mode 100644 index 0000000000..126a206dbf --- /dev/null +++ b/phpBB/phpbb/report/report_handler.php @@ -0,0 +1,104 @@ + + * @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\report; + +abstract class report_handler implements report_handler_interface +{ + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \phpbb\event\dispatcher_interface + */ + protected $dispatcher; + + /** + * @var \phpbb\config\db + */ + protected $config; + + /** + * @var \phpbb\auth\auth + */ + protected $auth; + + /** + * @var \phpbb\user + */ + protected $user; + + /** + * @var \phpbb\notification\manager + */ + protected $notifications; + + /** + * @var array + */ + protected $report_data; + + /** + * Construtor + * + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\event\dispatcher_interface $dispatcher + * @param \phpbb\config\db $config + * @param \phpbb\auth\auth $auth + * @param \phpbb\user $user + * @param \phpbb\notification\manager $notification + */ + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\config\db $config, \phpbb\auth\auth $auth, \phpbb\user $user, \phpbb\notification\manager $notification) + { + $this->db = $db; + $this->dispatcher = $dispatcher; + $this->config = $config; + $this->auth = $auth; + $this->user = $user; + $this->notifications = $notification; + $this->report_data = array(); + } + + /** + * Creates a report entity in the database + * + * @param array $report_data + * @return int the ID of the created entity + */ + protected function create_report(array $report_data) + { + $sql_ary = array( + 'reason_id' => (int) $report_data['reason_id'], + 'post_id' => $report_data['post_id'], + 'pm_id' => $report_data['pm_id'], + 'user_id' => (int) $this->user->data['user_id'], + 'user_notify' => (int) $report_data['user_notify'], + 'report_closed' => 0, + 'report_time' => (int) time(), + 'report_text' => (string) $report_data['report_text'], + 'reported_post_text' => $report_data['reported_post_text'], + 'reported_post_uid' => $report_data['reported_post_uid'], + 'reported_post_bitfield' => $report_data['reported_post_bitfield'], + 'reported_post_enable_bbcode' => $report_data['reported_post_enable_bbcode'], + 'reported_post_enable_smilies' => $report_data['reported_post_enable_smilies'], + 'reported_post_enable_magic_url' => $report_data['reported_post_enable_magic_url'], + ); + + $sql = 'INSERT INTO ' . REPORTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary); + $this->db->sql_query($sql); + + return $this->db->sql_nextid(); + } +} diff --git a/phpBB/phpbb/report/report_handler_interface.php b/phpBB/phpbb/report/report_handler_interface.php new file mode 100644 index 0000000000..8dafc392d0 --- /dev/null +++ b/phpBB/phpbb/report/report_handler_interface.php @@ -0,0 +1,43 @@ + + * @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\report; + +interface report_handler_interface +{ + /** + * Reports a message + * + * @param int $id + * @param int $reason_id + * @param string $report_text + * @param int $user_notify + * @return null + * @throws \phpbb\report\exception\empty_report_exception when the given report is empty + * @throws \phpbb\report\exception\already_reported_exception when the entity is already reported + * @throws \phpbb\report\exception\entity_not_found_exception when the entity does not exist or the user does not have viewing permissions for it + * @throws \phpbb\report\exception\invalid_report_exception when the entity cannot be reported for some other reason + */ + public function add_report($id, $reason_id, $report_text, $user_notify); + + /** + * Checks if the message is reportable + * + * @param int $id + * @return null + * @throws \phpbb\report\exception\already_reported_exception when the entity is already reported + * @throws \phpbb\report\exception\entity_not_found_exception when the entity does not exist or the user does not have viewing permissions for it + * @throws \phpbb\report\exception\invalid_report_exception when the entity cannot be reported for some other reason + */ + public function validate_report_request($id); +} diff --git a/phpBB/phpbb/report/report_handler_pm.php b/phpBB/phpbb/report/report_handler_pm.php new file mode 100644 index 0000000000..2f2a697efc --- /dev/null +++ b/phpBB/phpbb/report/report_handler_pm.php @@ -0,0 +1,137 @@ + + * @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\report; + +use phpbb\report\exception\empty_report_exception; +use phpbb\report\exception\already_reported_exception; +use phpbb\report\exception\pm_reporting_disabled_exception; +use phpbb\report\exception\entity_not_found_exception; + +class report_handler_pm extends report_handler +{ + /** + * {@inheritdoc} + * @throws \phpbb\report\exception\pm_reporting_disabled_exception when PM reporting is disabled on the board + */ + public function add_report($id, $reason_id, $report_text, $user_notify) + { + // Cast the input variables + $id = (int) $id; + $reason_id = (int) $reason_id; + $report_text = (string) $report_text; + $user_notify = (int) $user_notify; + + $this->validate_report_request($id); + + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . " + WHERE reason_id = $reason_id"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if (!$row || (empty($report_text) && strtolower($row['reason_title']) === 'other')) + { + throw new empty_report_exception(); + } + + $report_data = array( + 'reason_id' => $reason_id, + 'post_id' => 0, + 'pm_id' => $id, + 'user_notify' => $user_notify, + 'report_text' => $report_text, + 'reported_post_text' => $this->report_data['message_text'], + 'reported_post_uid' => $this->report_data['bbcode_bitfield'], + 'reported_post_bitfield' => $this->report_data['bbcode_uid'], + 'reported_post_enable_bbcode' => $this->report_data['enable_bbcode'], + 'reported_post_enable_smilies' => $this->report_data['enable_smilies'], + 'reported_post_enable_magic_url' => $this->report_data['enable_magic_url'], + ); + + $report_id = $this->create_report($report_data); + + $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' + SET message_reported = 1 + WHERE msg_id = ' . $id; + $this->db->sql_query($sql); + + $sql_ary = array( + 'msg_id' => $id, + 'user_id' => ANONYMOUS, + 'author_id' => (int) $this->report_data['author_id'], + 'pm_deleted' => 0, + 'pm_new' => 0, + 'pm_unread' => 0, + 'pm_replied' => 0, + 'pm_marked' => 0, + 'pm_forwarded' => 0, + 'folder_id' => PRIVMSGS_INBOX, + ); + + $sql = 'INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary); + $this->db->sql_query($sql); + + $this->notifications->add_notifications('notification.type.report_pm', array_merge($this->report_data, $row, array( + 'report_text' => $report_text, + 'from_user_id' => $this->report_data['author_id'], + 'report_id' => $report_id, + ))); + } + + /** + * {@inheritdoc} + * @throws \phpbb\report\exception\pm_reporting_disabled_exception when PM reporting is disabled on the board + */ + public function validate_report_request($id) + { + $id = (int) $id; + + // Check if reporting PMs is enabled + if (!$this->config['allow_pm_report']) + { + throw new pm_reporting_disabled_exception(); + } + else if ($id <= 0) + { + throw new entity_not_found_exception('NO_POST_SELECTED'); + } + + // Grab all relevant data + $sql = 'SELECT p.*, pt.* + FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . " pt + WHERE p.msg_id = $id + AND p.msg_id = pt.msg_id + AND (p.author_id = " . $this->user->data['user_id'] . " + OR pt.user_id = " . $this->user->data['user_id'] . ")"; + $result = $this->db->sql_query($sql); + $report_data = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + // Check if message exists + if (!$report_data) + { + $this->user->add_lang('ucp'); + throw new entity_not_found_exception('NO_MESSAGE'); + } + + // Check if message is already reported + if ($report_data['message_reported']) + { + throw new already_reported_exception(); + } + + $this->report_data = $report_data; + } +} diff --git a/phpBB/phpbb/report/report_handler_post.php b/phpBB/phpbb/report/report_handler_post.php new file mode 100644 index 0000000000..ce4ed67d27 --- /dev/null +++ b/phpBB/phpbb/report/report_handler_post.php @@ -0,0 +1,175 @@ + + * @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\report; + +use phpbb\report\exception\invalid_report_exception; +use phpbb\report\exception\empty_report_exception; +use phpbb\report\exception\already_reported_exception; +use phpbb\report\exception\entity_not_found_exception; +use phpbb\report\exception\report_permission_denied_exception; + +class report_handler_post extends report_handler +{ + /** + * @var array + */ + protected $forum_data; + + /** + * {@inheritdoc} + * @throws \phpbb\report\exception\report_permission_denied_exception when the user does not have permission to report the post + */ + public function add_report($id, $reason_id, $report_text, $user_notify) + { + // Cast the input variables + $id = (int) $id; + $reason_id = (int) $reason_id; + $report_text = (string) $report_text; + $user_notify = (int) $user_notify; + + $this->validate_report_request($id); + + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . " + WHERE reason_id = $reason_id"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if (!$row || (empty($report_text) && strtolower($row['reason_title']) === 'other')) + { + throw new empty_report_exception(); + } + + $report_data = array( + 'reason_id' => $reason_id, + 'post_id' => $id, + 'pm_id' => 0, + 'user_notify' => $user_notify, + 'report_text' => $report_text, + 'reported_post_text' => $this->report_data['post_text'], + 'reported_post_uid' => $this->report_data['bbcode_bitfield'], + 'reported_post_bitfield' => $this->report_data['bbcode_uid'], + 'reported_post_enable_bbcode' => $this->report_data['enable_bbcode'], + 'reported_post_enable_smilies' => $this->report_data['enable_smilies'], + 'reported_post_enable_magic_url' => $this->report_data['enable_magic_url'], + ); + + $report_id = $this->create_report($report_data); + + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_reported = 1 + WHERE post_id = ' . $id; + $this->db->sql_query($sql); + + if (!$this->report_data['topic_reported']) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_reported = 1 + WHERE topic_id = ' . $this->report_data['topic_id'] . ' + OR topic_moved_id = ' . $this->report_data['topic_id']; + $this->db->sql_query($sql); + } + + $this->notifications->add_notifications('notification.type.report_post', array_merge($this->report_data, $row, $this->forum_data, array( + 'report_text' => $report_text, + ))); + } + + /** + * {@inheritdoc} + * @throws \phpbb\report\exception\report_permission_denied_exception when the user does not have permission to report the post + */ + public function validate_report_request($id) + { + $id = (int) $id; + + // Check if id is valid + if ($id <= 0) + { + throw new entity_not_found_exception('NO_POST_SELECTED'); + } + + // Grab all relevant data + $sql = 'SELECT t.*, p.* + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t + WHERE p.post_id = $id + AND p.topic_id = t.topic_id"; + $result = $this->db->sql_query($sql); + $report_data = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if (!$report_data) + { + throw new entity_not_found_exception('POST_NOT_EXIST'); + } + + $forum_id = (int) $report_data['forum_id']; + + $sql = 'SELECT * + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $forum_id; + $result = $this->db->sql_query($sql); + $forum_data = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if (!$forum_data) + { + throw new invalid_report_exception('FORUM_NOT_EXIST'); + } + + $acl_check_ary = array( + 'f_list' => 'POST_NOT_EXIST', + 'f_read' => 'USER_CANNOT_READ', + 'f_report' => 'USER_CANNOT_REPORT' + ); + + /** + * This event allows you to do extra auth checks and verify if the user + * has the required permissions + * + * @event core.report_post_auth + * @var array forum_data All data available from the forums table on this post's forum + * @var array report_data All data available from the topics and the posts tables on this post (and its topic) + * @var array acl_check_ary An array with the ACL to be tested. The evaluation is made in the same order as the array is sorted + * The key is the ACL name and the value is the language key for the error message. + * @since 3.1.3-RC1 + */ + $vars = array( + 'forum_data', + 'report_data', + 'acl_check_ary', + ); + extract($this->dispatcher->trigger_event('core.report_post_auth', compact($vars))); + + $this->auth->acl($this->user->data); + + foreach ($acl_check_ary as $acl => $error) + { + if (!$this->auth->acl_get($acl, $forum_id)) + { + throw new report_permission_denied_exception($error); + } + } + unset($acl_check_ary); + + if ($report_data['post_reported']) + { + throw new already_reported_exception(); + } + + $this->report_data = $report_data; + $this->forum_data = $forum_data; + } +} diff --git a/phpBB/phpbb/report/report_reason_list_provider.php b/phpBB/phpbb/report/report_reason_list_provider.php new file mode 100644 index 0000000000..388a61d577 --- /dev/null +++ b/phpBB/phpbb/report/report_reason_list_provider.php @@ -0,0 +1,78 @@ + + * @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\report; + +class report_reason_list_provider +{ + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \phpbb\template\template + */ + protected $template; + + /** + * @var \phpbb\user + */ + protected $user; + + /** + * Constructor + * + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\template\template $template + * @param \phpbb\user $user + */ + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\template\template $template, \phpbb\user $user) + { + $this->db = $db; + $this->template = $template; + $this->user = $user; + } + + /** + * Sets template variables to render report reasons select HTML input + * + * @param int $reason_id + * @return null + */ + public function display_reasons($reason_id = 0) + { + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . ' + ORDER BY reason_order ASC'; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + // If the reason is defined within the language file, we will use the localized version, else just use the database entry... + if (isset($this->user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($this->user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) + { + $row['reason_description'] = $this->user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; + $row['reason_title'] = $this->user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; + } + + $this->template->assign_block_vars('reason', array( + 'ID' => $row['reason_id'], + 'TITLE' => $row['reason_title'], + 'DESCRIPTION' => $row['reason_description'], + 'S_SELECTED' => ($row['reason_id'] == $reason_id) ? true : false, + )); + } + $this->db->sql_freeresult($result); + } +} diff --git a/phpBB/report.php b/phpBB/report.php index d6d1ca17c8..bb26b972aa 100644 --- a/phpBB/report.php +++ b/phpBB/report.php @@ -11,6 +11,8 @@ * */ +use Symfony\Component\HttpFoundation\RedirectResponse; + /** * @ignore */ @@ -18,322 +20,22 @@ define('IN_PHPBB', true); $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './'; $phpEx = substr(strrchr(__FILE__, '.'), 1); include($phpbb_root_path . 'common.' . $phpEx); -include($phpbb_root_path . 'includes/functions_display.' . $phpEx); // Start session management $user->session_begin(); $auth->acl($user->data); -$user->setup('mcp'); -$forum_id = $request->variable('f', 0); $post_id = $request->variable('p', 0); $pm_id = $request->variable('pm', 0); -$reason_id = $request->variable('reason_id', 0); -$report_text = $request->variable('report_text', '', true); -$user_notify = ($user->data['is_registered']) ? $request->variable('notify', 0) : false; -$submit = (isset($_POST['submit'])) ? true : false; +$redirect_route_name = ($pm_id === 0) ? 'phpbb_report_post_controller' : 'phpbb_report_pm_controller'; -if (!$post_id && (!$pm_id || !$config['allow_pm_report'])) -{ - trigger_error('NO_POST_SELECTED'); -} - -if ($post_id) -{ - $redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&p=$post_id") . "#p$post_id"; - $return_forum_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id"); - $pm_id = 0; -} -else -{ - $redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=view&p=$pm_id"); - $return_forum_url = ''; - $post_id = 0; - $forum_id = 0; -} - -// Has the report been cancelled? -if (isset($_POST['cancel'])) -{ - redirect($redirect_url); -} - -if ($post_id) -{ - // Grab all relevant data - $sql = 'SELECT t.*, p.* - FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t - WHERE p.post_id = $post_id - AND p.topic_id = t.topic_id"; - $result = $db->sql_query($sql); - $report_data = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$report_data) - { - trigger_error('POST_NOT_EXIST'); - } - - $forum_id = (int) $report_data['forum_id']; - $topic_id = (int) $report_data['topic_id']; - $reported_post_text = $report_data['post_text']; - $reported_post_bitfield = $report_data['bbcode_bitfield']; - $reported_post_uid = $report_data['bbcode_uid']; - $reported_post_enable_bbcode = $report_data['enable_bbcode']; - $reported_post_enable_smilies = $report_data['enable_smilies']; - $reported_post_enable_magic_url = $report_data['enable_magic_url']; - - $sql = 'SELECT * - FROM ' . FORUMS_TABLE . ' - WHERE forum_id = ' . $forum_id; - $result = $db->sql_query($sql); - $forum_data = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$forum_data) - { - trigger_error('FORUM_NOT_EXIST'); - } - - // Check required permissions - $acl_check_ary = array('f_list' => 'POST_NOT_EXIST', 'f_read' => 'USER_CANNOT_READ', 'f_report' => 'USER_CANNOT_REPORT'); - - /** - * This event allows you to do extra auth checks and verify if the user - * has the required permissions - * - * @event core.report_post_auth - * @var array forum_data All data available from the forums table on this post's forum - * @var array report_data All data available from the topics and the posts tables on this post (and its topic) - * @var array acl_check_ary An array with the ACL to be tested. The evaluation is made in the same order as the array is sorted - * The key is the ACL name and the value is the language key for the error message. - * @since 3.1.3-RC1 - */ - $vars = array( - 'forum_data', - 'report_data', - 'acl_check_ary', - ); - extract($phpbb_dispatcher->trigger_event('core.report_post_auth', compact($vars))); - - foreach ($acl_check_ary as $acl => $error) - { - if (!$auth->acl_get($acl, $forum_id)) - { - trigger_error($error); - } - } - unset($acl_check_ary); - - if ($report_data['post_reported']) - { - $message = $user->lang['ALREADY_REPORTED']; - $message .= '

              ' . sprintf($user->lang['RETURN_TOPIC'], '', ''); - $message .= '

              ' . sprintf($user->lang['RETURN_FORUM'], '', ''); - trigger_error($message); - } -} -else -{ - // Grab all relevant data - $sql = 'SELECT p.*, pt.* - FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . " pt - WHERE p.msg_id = $pm_id - AND p.msg_id = pt.msg_id - AND (p.author_id = " . $user->data['user_id'] . " OR pt.user_id = " . $user->data['user_id'] . ")"; - $result = $db->sql_query($sql); - $report_data = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$report_data) - { - $user->add_lang('ucp'); - trigger_error('NO_MESSAGE'); - } - - if ($report_data['message_reported']) - { - $message = $user->lang['ALREADY_REPORTED_PM']; - $message .= '

              ' . sprintf($user->lang['RETURN_PM'], '', ''); - trigger_error($message); - } - - $reported_post_text = $report_data['message_text']; - $reported_post_bitfield = $report_data['bbcode_bitfield']; - $reported_post_uid = $report_data['bbcode_uid']; - $reported_post_enable_bbcode = $report_data['enable_bbcode']; - $reported_post_enable_smilies = $report_data['enable_smilies']; - $reported_post_enable_magic_url = $report_data['enable_magic_url']; -} - -if ($config['enable_post_confirm'] && !$user->data['is_registered']) -{ - $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']); - $captcha->init(CONFIRM_REPORT); -} - -$error = array(); -$s_hidden_fields = ''; - -// Submit report? -if ($submit && $reason_id) -{ - if (isset($captcha)) - { - $visual_confirmation_response = $captcha->validate(); - if ($visual_confirmation_response) - { - $error[] = $visual_confirmation_response; - } - } - - $sql = 'SELECT * - FROM ' . REPORTS_REASONS_TABLE . " - WHERE reason_id = $reason_id"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$row || (!$report_text && strtolower($row['reason_title']) == 'other')) - { - $error[] = $user->lang('EMPTY_REPORT'); - } - - if (!sizeof($error)) - { - if (isset($captcha)) - { - $captcha->reset(); - } - - $sql_ary = array( - 'reason_id' => (int) $reason_id, - 'post_id' => $post_id, - 'pm_id' => $pm_id, - 'user_id' => (int) $user->data['user_id'], - 'user_notify' => (int) $user_notify, - 'report_closed' => 0, - 'report_time' => (int) time(), - 'report_text' => (string) $report_text, - 'reported_post_text' => $reported_post_text, - 'reported_post_uid' => $reported_post_uid, - 'reported_post_bitfield' => $reported_post_bitfield, - 'reported_post_enable_bbcode' => $reported_post_enable_bbcode, - 'reported_post_enable_smilies' => $reported_post_enable_smilies, - 'reported_post_enable_magic_url' => $reported_post_enable_magic_url, - ); - - $sql = 'INSERT INTO ' . REPORTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); - $db->sql_query($sql); - $report_id = $db->sql_nextid(); - - /* @var $phpbb_notifications \phpbb\notification\manager */ - $phpbb_notifications = $phpbb_container->get('notification_manager'); - - if ($post_id) - { - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_reported = 1 - WHERE post_id = ' . $post_id; - $db->sql_query($sql); - - if (!$report_data['topic_reported']) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_reported = 1 - WHERE topic_id = ' . $report_data['topic_id'] . ' - OR topic_moved_id = ' . $report_data['topic_id']; - $db->sql_query($sql); - } - - $lang_return = $user->lang['RETURN_TOPIC']; - $lang_success = $user->lang['POST_REPORTED_SUCCESS']; - - $phpbb_notifications->add_notifications('notification.type.report_post', array_merge($report_data, $row, $forum_data, array( - 'report_text' => $report_text, - ))); - } - else - { - $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' - SET message_reported = 1 - WHERE msg_id = ' . $pm_id; - $db->sql_query($sql); - - $sql_ary = array( - 'msg_id' => $pm_id, - 'user_id' => ANONYMOUS, - 'author_id' => (int) $report_data['author_id'], - 'pm_deleted' => 0, - 'pm_new' => 0, - 'pm_unread' => 0, - 'pm_replied' => 0, - 'pm_marked' => 0, - 'pm_forwarded' => 0, - 'folder_id' => PRIVMSGS_INBOX, - ); - - $sql = 'INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); - $db->sql_query($sql); - - $lang_return = $user->lang['RETURN_PM']; - $lang_success = $user->lang['PM_REPORTED_SUCCESS']; - - $phpbb_notifications->add_notifications('notification.type.report_pm', array_merge($report_data, $row, array( - 'report_text' => $report_text, - 'from_user_id' => $report_data['author_id'], - 'report_id' => $report_id, - ))); - } - - meta_refresh(3, $redirect_url); - - $message = $lang_success . '

              ' . sprintf($lang_return, '', ''); - if ($return_forum_url) - { - $message .= '

              ' . sprintf($user->lang['RETURN_FORUM'], '', ''); - } - trigger_error($message); - } - else if (isset($captcha) && $captcha->is_solved() !== false) - { - $s_hidden_fields .= build_hidden_fields($captcha->get_hidden_fields()); - } -} - -// Generate the reasons -display_reasons($reason_id); - -$page_title = ($pm_id) ? $user->lang['REPORT_MESSAGE'] : $user->lang['REPORT_POST']; - -if (isset($captcha) && $captcha->is_solved() === false) -{ - $template->assign_vars(array( - 'S_CONFIRM_CODE' => true, - 'CAPTCHA_TEMPLATE' => $captcha->get_template(), - )); -} - -$template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('
              ', $error) : '', - 'S_REPORT_POST' => ($pm_id) ? false : true, - 'REPORT_TEXT' => $report_text, - 'S_REPORT_ACTION' => append_sid("{$phpbb_root_path}report.$phpEx", 'f=' . $forum_id . '&p=' . $post_id . '&pm=' . $pm_id), - 'S_HIDDEN_FIELDS' => (sizeof($s_hidden_fields)) ? $s_hidden_fields : null, - - 'S_NOTIFY' => $user_notify, - 'S_CAN_NOTIFY' => ($user->data['is_registered']) ? true : false, - 'S_IN_REPORT' => true, -)); - -generate_forum_nav($forum_data); - -// Start output of page -page_header($page_title); - -$template->set_filenames(array( - 'body' => 'report_body.html') +/** @var \phpbb\controller\helper $controller_helper */ +$controller_helper = $phpbb_container->get('controller.helper'); +$response = new RedirectResponse( + $controller_helper->route($redirect_route_name, array( + 'id' => ($pm_id === 0) ? $post_id : $pm_id, + )), + 301 ); - -page_footer(); +$response->send(); diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 76e7a59d5d..7b225ef3db 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -1832,7 +1832,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) 'U_JABBER' => $user_cache[$poster_id]['jabber'], 'U_APPROVE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&p={$row['post_id']}&f=$forum_id&redirect=" . urlencode(str_replace('&', '&', $viewtopic_url . '&p=' . $row['post_id'] . '#p' . $row['post_id']))), - 'U_REPORT' => ($auth->acl_get('f_report', $forum_id)) ? append_sid("{$phpbb_root_path}report.$phpEx", 'f=' . $forum_id . '&p=' . $row['post_id']) : '', + 'U_REPORT' => ($auth->acl_get('f_report', $forum_id)) ? $phpbb_container->get('controller.helper')->route('phpbb_report_post_controller', array('id' => $row['post_id'])) : '', 'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', 'U_MCP_APPROVE' => ($auth->acl_get('m_approve', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', 'U_MCP_RESTORE' => ($auth->acl_get('m_approve', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=' . (($topic_data['topic_visibility'] != ITEM_DELETED) ? 'deleted_posts' : 'deleted_topics') . '&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', diff --git a/tests/functional/controllers_compatibility_test.php b/tests/functional/controllers_compatibility_test.php new file mode 100644 index 0000000000..7ba0b0d991 --- /dev/null +++ b/tests/functional/controllers_compatibility_test.php @@ -0,0 +1,43 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @group functional +*/ + +class phpbb_functional_controllers_compatibility_test extends phpbb_functional_test_case +{ + public function test_report_compatibility() + { + $this->assert301('report.php?f=1&p=1', 'app.php/post/1/report'); + $this->assert301('report.php?p=1', 'app.php/post/1/report'); + $this->assert301('report.php?pm=1', 'app.php/pm/1/report'); + } + + protected function assert301($from, $to) + { + self::$client->followRedirects(false); + self::request('GET', $from, array(), false); + + // Fix sid issues + $location = self::$client->getResponse()->getHeader('Location'); + $location = preg_replace('#sid=[^&]+(&(amp;)?)?#', '', $location); + if (substr($location, -1) === '?') + { + $location = substr($location, 0, -1); + } + + $this->assertEquals(301, self::$client->getResponse()->getStatus()); + $this->assertStringEndsWith($to, $location); + } +} diff --git a/tests/functional/report_post_captcha_test.php b/tests/functional/report_post_captcha_test.php index 93a03bd931..36a1a9ee4d 100644 --- a/tests/functional/report_post_captcha_test.php +++ b/tests/functional/report_post_captcha_test.php @@ -18,12 +18,13 @@ class phpbb_functional_report_post_captcha_test extends phpbb_functional_test_ca { public function test_guest_report_post() { - $crawler = self::request('GET', 'report.php?f=2&p=1'); + $crawler = self::request('GET', 'app.php/post/1/report', array(), false); + $this->assert_response_html(403); $this->add_lang('mcp'); $this->assertContains($this->lang('USER_CANNOT_REPORT'), $crawler->filter('html')->text()); $this->set_reporting_guest(1); - $crawler = self::request('GET', 'report.php?f=2&p=1'); + $crawler = self::request('GET', 'app.php/post/1/report'); $this->assertContains($this->lang('CONFIRM_CODE'), $crawler->filter('html')->text()); $this->set_reporting_guest(-1); } @@ -31,7 +32,7 @@ class phpbb_functional_report_post_captcha_test extends phpbb_functional_test_ca public function test_user_report_post() { $this->login(); - $crawler = self::request('GET', 'report.php?f=2&p=1'); + $crawler = self::request('GET', 'app.php/post/1/report'); $this->assertNotContains($this->lang('CONFIRM_CODE'), $crawler->filter('html')->text()); $this->add_lang('mcp'); From 4bdef6fd21a5dcab455b0cd1ee2652de606929c3 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Thu, 12 Mar 2015 00:25:00 +0100 Subject: [PATCH 0226/1676] [ticket/13697] Moving filesystem related functions to filesystem service * Moving filesystem service to \phpbb\filesystem namespace * Wraping Symfony's Filesystem component * Moving filesystem related functions from includes/functions.php into \phpbb\filesystem\filesystem Functions moved (and deprecated): - phpbb_chmod - phpbb_is_writable - phpbb_is_absolute - phpbb_own_realpath - phpbb_realpath * Adding interface for filesystem service PHPBB3-13697 --- phpBB/common.php | 2 +- phpBB/composer.json | 2 +- phpBB/config/default/container/services.yml | 3 +- .../default/container/services_avatar.yml | 1 + .../default/container/services_console.yml | 1 + .../default/container/services_twig.yml | 2 + phpBB/develop/create_schema_files.php | 2 +- phpBB/develop/mysql_upgrader.php | 2 +- phpBB/includes/acp/acp_attachments.php | 18 +- phpBB/includes/acp/acp_main.php | 4 +- phpBB/includes/bbcode.php | 6 +- phpBB/includes/compatibility_globals.php | 2 +- phpBB/includes/functions.php | 448 +-------- phpBB/includes/functions_acp.php | 4 +- phpBB/includes/functions_compatibility.php | 87 +- phpBB/includes/functions_compress.php | 69 +- phpBB/includes/functions_convert.php | 16 +- phpBB/includes/functions_install.php | 4 +- phpBB/includes/functions_messenger.php | 32 +- phpBB/includes/functions_posting.php | 15 +- phpBB/includes/functions_upload.php | 32 +- phpBB/install/database_update.php | 5 +- phpBB/install/index.php | 2 +- phpBB/install/install_convert.php | 6 +- phpBB/install/install_install.php | 43 +- phpBB/install/install_update.php | 6 +- phpBB/phpbb/avatar/driver/upload.php | 15 +- phpBB/phpbb/cache/driver/base.php | 8 +- phpBB/phpbb/cache/driver/file.php | 25 +- phpBB/phpbb/console/command/db/migrate.php | 8 +- phpBB/phpbb/controller/helper.php | 6 +- .../log_wrapper_migrator_output_handler.php | 11 +- phpBB/phpbb/di/container_builder.php | 3 +- phpBB/phpbb/di/extension/core.php | 3 +- phpBB/phpbb/extension/di/extension_base.php | 3 +- phpBB/phpbb/extension/manager.php | 4 +- phpBB/phpbb/filesystem.php | 35 +- .../exception/filesystem_exception.php | 42 + phpBB/phpbb/filesystem/filesystem.php | 916 ++++++++++++++++++ .../phpbb/filesystem/filesystem_interface.php | 284 ++++++ phpBB/phpbb/finder.php | 4 +- phpBB/phpbb/path_helper.php | 6 +- phpBB/phpbb/routing/router.php | 11 +- phpBB/phpbb/session.php | 4 +- phpBB/phpbb/template/twig/loader.php | 22 +- phpBB/phpbb/viewonline_helper.php | 6 +- tests/avatar/manager_test.php | 6 +- tests/controller/common_helper_route.php | 6 +- tests/controller/controller_test.php | 2 +- tests/dbal/connect_test.php | 4 +- tests/dbal/migrator_test.php | 2 +- .../ext/vendor/enabled_4/di/extension.php | 3 +- tests/error_collector_test.php | 9 + tests/extension/finder_test.php | 4 +- tests/extension/manager_test.php | 2 +- tests/extension/metadata_manager_test.php | 6 +- tests/filesystem/clean_path_test.php | 2 +- .../is_absolute_test.php | 40 +- tests/filesystem/realpath_test.php | 90 ++ tests/functional/fileupload_remote_test.php | 11 +- tests/functions/build_url_test.php | 2 +- tests/mock/controller_helper.php | 2 +- tests/mock/extension_manager.php | 2 +- tests/pagination/pagination_test.php | 4 +- tests/path_helper/path_helper_test.php | 10 +- tests/security/base.php | 2 +- tests/security/redirect_test.php | 2 +- tests/session/check_ban_test.php | 5 +- tests/session/extract_page_test.php | 2 +- tests/template/includephp_test.php | 3 +- tests/template/template_allfolder_test.php | 4 +- tests/template/template_events_test.php | 4 +- tests/template/template_includecss_test.php | 4 +- tests/template/template_test_case.php | 8 +- .../template/template_test_case_with_tree.php | 4 +- .../phpbb_database_test_case.php | 2 +- ...phpbb_database_test_connection_manager.php | 2 +- .../phpbb_functional_test_case.php | 2 +- .../phpbb_session_test_case.php | 2 +- tests/upload/filespec_test.php | 9 +- tests/upload/fileupload_test.php | 22 +- tests/viewonline/helper_test.php | 2 +- 82 files changed, 1859 insertions(+), 657 deletions(-) create mode 100644 phpBB/phpbb/filesystem/exception/filesystem_exception.php create mode 100644 phpBB/phpbb/filesystem/filesystem.php create mode 100644 phpBB/phpbb/filesystem/filesystem_interface.php rename tests/{functions => filesystem}/is_absolute_test.php (60%) create mode 100644 tests/filesystem/realpath_test.php diff --git a/phpBB/common.php b/phpBB/common.php index e819c75efc..633a37f25b 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -59,7 +59,7 @@ if (!defined('PHPBB_INSTALLED')) // Eliminate . and .. from the path require($phpbb_root_path . 'phpbb/filesystem.' . $phpEx); - $phpbb_filesystem = new phpbb\filesystem(); + $phpbb_filesystem = new phpbb\filesystem\filesystem(); $script_path = $phpbb_filesystem->clean_path($script_path); $url = (($secure) ? 'https://' : 'http://') . $server_name; diff --git a/phpBB/composer.json b/phpBB/composer.json index dcb4000d34..64d47af172 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -32,6 +32,7 @@ "symfony/console": "2.7.*@dev", "symfony/dependency-injection": "2.7.*@dev", "symfony/event-dispatcher": "2.7.*@dev", + "symfony/filesystem": "2.7.*@dev", "symfony/http-kernel": "2.7.*@dev", "symfony/routing": "2.7.*@dev", "symfony/security-core": "2.7.*@dev", @@ -51,7 +52,6 @@ "symfony/css-selector": "2.7.*@dev", "symfony/debug": "2.7.*@dev", "symfony/dom-crawler": "2.7.*@dev", - "symfony/filesystem": "2.7.*@dev", "symfony/finder": "2.7.*@dev", "symfony/http-foundation": "2.7.*@dev", "symfony/process": "2.7.*@dev" diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 36f22d72d6..db07183832 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -103,7 +103,7 @@ services: - @cache.driver filesystem: - class: phpbb\filesystem + class: phpbb\filesystem\filesystem file_downloader: class: phpbb\file_downloader @@ -159,6 +159,7 @@ services: router: class: phpbb\routing\router arguments: + - @filesystem - @ext.manager - %core.root_path% - %core.php_ext% diff --git a/phpBB/config/default/container/services_avatar.yml b/phpBB/config/default/container/services_avatar.yml index 5292489715..e80d57cb59 100644 --- a/phpBB/config/default/container/services_avatar.yml +++ b/phpBB/config/default/container/services_avatar.yml @@ -58,6 +58,7 @@ services: - @config - %core.root_path% - %core.php_ext% + - @filesystem - @path_helper - @mimetype.guesser - @cache.driver diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 1e18a7dd37..f0ae6c8ab4 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -84,6 +84,7 @@ services: - @config - @cache - @log + - @filesystem - %core.root_path% tags: - { name: console.command } diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index 25382a95a1..5d7bf0eff3 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -19,6 +19,8 @@ services: template.twig.loader: class: phpbb\template\twig\loader + arguments: + - @filesystem template.twig.extensions.collection: class: phpbb\di\service_collection diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 8dce97144d..f6bfd6a52f 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -43,7 +43,7 @@ require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx); $phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx); $phpbb_class_loader->register(); -$finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path); +$finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path); $classes = $finder->core_path('phpbb/') ->directory('/db/migration/data') ->get_classes(); diff --git a/phpBB/develop/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php index 543b520caa..276c010e84 100644 --- a/phpBB/develop/mysql_upgrader.php +++ b/phpBB/develop/mysql_upgrader.php @@ -62,7 +62,7 @@ echo "USE $dbname;$newline$newline"; @set_time_limit(0); -$finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path); +$finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path); $classes = $finder->core_path('phpbb/') ->directory('/db/migration/data') ->get_classes(); diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 78488b4048..7413152e7a 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -36,13 +36,16 @@ class acp_attachments /** @var \phpbb\user */ protected $user; + /** @var \phpbb\filesystem\filesystem_interface */ + protected $filesystem; + public $id; public $u_action; protected $new_config; function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_container; + global $db, $user, $auth, $template, $cache, $phpbb_container, $phpbb_filesystem; global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx, $phpbb_log, $request; $this->id = $id; @@ -51,6 +54,7 @@ class acp_attachments $this->template = $template; $this->user = $user; $this->phpbb_container = $phpbb_container; + $this->filesystem = $phpbb_filesystem; $user->add_lang(array('posting', 'viewtopic', 'acp/attachments')); @@ -1501,7 +1505,15 @@ class acp_attachments if (!file_exists($phpbb_root_path . $upload_dir)) { @mkdir($phpbb_root_path . $upload_dir, 0777); - phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -1517,7 +1529,7 @@ class acp_attachments return; } - if (!phpbb_is_writable($phpbb_root_path . $upload_dir)) + if (!$this->filesystem->is_writable($phpbb_root_path . $upload_dir)) { $error[] = sprintf($user->lang['NO_WRITE_UPLOAD'], $upload_dir); return; diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index c49ccdf479..21c6edfccf 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -26,7 +26,7 @@ class acp_main function main($id, $mode) { global $config, $db, $cache, $user, $auth, $template, $request, $phpbb_log; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher, $phpbb_filesystem; // Show restore permissions notice if ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) @@ -644,7 +644,7 @@ class acp_main } } - if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx)) + if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && $phpbb_filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx)) { // World-Writable? (000x) $template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002)); diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index ee911b5ec5..53675637a0 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -129,7 +129,7 @@ class bbcode */ function bbcode_cache_init() { - global $phpbb_root_path, $phpEx, $config, $user, $phpbb_dispatcher, $phpbb_extension_manager, $phpbb_path_helper, $phpbb_container; + global $phpbb_root_path, $phpEx, $config, $user, $phpbb_dispatcher, $phpbb_extension_manager, $phpbb_path_helper, $phpbb_container, $phpbb_filesystem; if (empty($this->template_filename)) { @@ -146,7 +146,9 @@ class bbcode $phpbb_container, $phpbb_container->getParameter('core.root_path') . 'cache/', $phpbb_container->get('ext.manager'), - new \phpbb\template\twig\loader() + new \phpbb\template\twig\loader( + $phpbb_filesystem + ) ), $phpbb_container->getParameter('core.root_path') . 'cache/', $phpbb_container->get('template.twig.extensions.collection'), diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php index b0919aefb3..5c18793655 100644 --- a/phpBB/includes/compatibility_globals.php +++ b/phpBB/includes/compatibility_globals.php @@ -48,7 +48,7 @@ $phpbb_log = $phpbb_container->get('log'); /* @var $symfony_request \phpbb\symfony_request */ $symfony_request = $phpbb_container->get('symfony_request'); -/* @var $phpbb_filesystem \phpbb\filesystem */ +/* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */ $phpbb_filesystem = $phpbb_container->get('filesystem'); /* @var $phpbb_path_helper \phpbb\path_helper */ diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 949d33c566..957b475616 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -311,448 +311,6 @@ function phpbb_version_compare($version1, $version2, $operator = null) } } -/** -* Global function for chmodding directories and files for internal use -* -* This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. -* The function determines owner and group from common.php file and sets the same to the provided file. -* The function uses bit fields to build the permissions. -* The function sets the appropiate execute bit on directories. -* -* Supported constants representing bit fields are: -* -* CHMOD_ALL - all permissions (7) -* CHMOD_READ - read permission (4) -* CHMOD_WRITE - write permission (2) -* CHMOD_EXECUTE - execute permission (1) -* -* NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. -* -* @param string $filename The file/directory to be chmodded -* @param int $perms Permissions to set -* -* @return bool true on success, otherwise false -*/ -function phpbb_chmod($filename, $perms = CHMOD_READ) -{ - static $_chmod_info; - - // Return if the file no longer exists. - if (!file_exists($filename)) - { - return false; - } - - // Determine some common vars - if (empty($_chmod_info)) - { - if (!function_exists('fileowner') || !function_exists('filegroup')) - { - // No need to further determine owner/group - it is unknown - $_chmod_info['process'] = false; - } - else - { - global $phpbb_root_path, $phpEx; - - // Determine owner/group of common.php file and the filename we want to change here - $common_php_owner = @fileowner($phpbb_root_path . 'common.' . $phpEx); - $common_php_group = @filegroup($phpbb_root_path . 'common.' . $phpEx); - - // And the owner and the groups PHP is running under. - $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; - $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; - - // If we are unable to get owner/group, then do not try to set them by guessing - if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) - { - $_chmod_info['process'] = false; - } - else - { - $_chmod_info = array( - 'process' => true, - 'common_owner' => $common_php_owner, - 'common_group' => $common_php_group, - 'php_uid' => $php_uid, - 'php_gids' => $php_gids, - ); - } - } - } - - if ($_chmod_info['process']) - { - $file_uid = @fileowner($filename); - $file_gid = @filegroup($filename); - - // Change owner - if (@chown($filename, $_chmod_info['common_owner'])) - { - clearstatcache(); - $file_uid = @fileowner($filename); - } - - // Change group - if (@chgrp($filename, $_chmod_info['common_group'])) - { - clearstatcache(); - $file_gid = @filegroup($filename); - } - - // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something - if ($file_uid != $_chmod_info['common_owner'] || $file_gid != $_chmod_info['common_group']) - { - $_chmod_info['process'] = false; - } - } - - // Still able to process? - if ($_chmod_info['process']) - { - if ($file_uid == $_chmod_info['php_uid']) - { - $php = 'owner'; - } - else if (in_array($file_gid, $_chmod_info['php_gids'])) - { - $php = 'group'; - } - else - { - // Since we are setting the everyone bit anyway, no need to do expensive operations - $_chmod_info['process'] = false; - } - } - - // We are not able to determine or change something - if (!$_chmod_info['process']) - { - $php = 'other'; - } - - // Owner always has read/write permission - $owner = CHMOD_READ | CHMOD_WRITE; - if (is_dir($filename)) - { - $owner |= CHMOD_EXECUTE; - - // Only add execute bit to the permission if the dir needs to be readable - if ($perms & CHMOD_READ) - { - $perms |= CHMOD_EXECUTE; - } - } - - switch ($php) - { - case 'owner': - $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); - - clearstatcache(); - - if (is_readable($filename) && phpbb_is_writable($filename)) - { - break; - } - - case 'group': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); - - clearstatcache(); - - if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename))) - { - break; - } - - case 'other': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); - - clearstatcache(); - - if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename))) - { - break; - } - - default: - return false; - break; - } - - return $result; -} - -/** -* Test if a file/directory is writable -* -* This function calls the native is_writable() when not running under -* Windows and it is not disabled. -* -* @param string $file Path to perform write test on -* @return bool True when the path is writable, otherwise false. -*/ -function phpbb_is_writable($file) -{ - if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable')) - { - if (file_exists($file)) - { - // Canonicalise path to absolute path - $file = phpbb_realpath($file); - - if (is_dir($file)) - { - // Test directory by creating a file inside the directory - $result = @tempnam($file, 'i_w'); - - if (is_string($result) && file_exists($result)) - { - unlink($result); - - // Ensure the file is actually in the directory (returned realpathed) - return (strpos($result, $file) === 0) ? true : false; - } - } - else - { - $handle = @fopen($file, 'r+'); - - if (is_resource($handle)) - { - fclose($handle); - return true; - } - } - } - else - { - // file does not exist test if we can write to the directory - $dir = dirname($file); - - if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir)) - { - return true; - } - } - - return false; - } - else - { - return is_writable($file); - } -} - -/** -* Checks if a path ($path) is absolute or relative -* -* @param string $path Path to check absoluteness of -* @return boolean -*/ -function phpbb_is_absolute($path) -{ - return (isset($path[0]) && $path[0] == '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false; -} - -/** -* @author Chris Smith -* @copyright 2006 Project Minerva Team -* @param string $path The path which we should attempt to resolve. -* @return mixed -*/ -function phpbb_own_realpath($path) -{ - global $request; - - // Now to perform funky shizzle - - // Switch to use UNIX slashes - $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); - $path_prefix = ''; - - // Determine what sort of path we have - if (phpbb_is_absolute($path)) - { - $absolute = true; - - if ($path[0] == '/') - { - // Absolute path, *NIX style - $path_prefix = ''; - } - else - { - // Absolute path, Windows style - // Remove the drive letter and colon - $path_prefix = $path[0] . ':'; - $path = substr($path, 2); - } - } - else - { - // Relative Path - // Prepend the current working directory - if (function_exists('getcwd')) - { - // This is the best method, hopefully it is enabled! - $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path; - $absolute = true; - if (preg_match('#^[a-z]:#i', $path)) - { - $path_prefix = $path[0] . ':'; - $path = substr($path, 2); - } - else - { - $path_prefix = ''; - } - } - else if ($request->server('SCRIPT_FILENAME')) - { - // Warning: If chdir() has been used this will lie! - // Warning: This has some problems sometime (CLI can create them easily) - $filename = htmlspecialchars_decode($request->server('SCRIPT_FILENAME')); - $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($filename)) . '/' . $path; - $absolute = true; - $path_prefix = ''; - } - else - { - // We have no way of getting the absolute path, just run on using relative ones. - $absolute = false; - $path_prefix = '.'; - } - } - - // Remove any repeated slashes - $path = preg_replace('#/{2,}#', '/', $path); - - // Remove the slashes from the start and end of the path - $path = trim($path, '/'); - - // Break the string into little bits for us to nibble on - $bits = explode('/', $path); - - // Remove any . in the path, renumber array for the loop below - $bits = array_values(array_diff($bits, array('.'))); - - // Lets get looping, run over and resolve any .. (up directory) - for ($i = 0, $max = sizeof($bits); $i < $max; $i++) - { - // @todo Optimise - if ($bits[$i] == '..' ) - { - if (isset($bits[$i - 1])) - { - if ($bits[$i - 1] != '..') - { - // We found a .. and we are able to traverse upwards, lets do it! - unset($bits[$i]); - unset($bits[$i - 1]); - $i -= 2; - $max -= 2; - $bits = array_values($bits); - } - } - else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute - { - // We have an absolute path trying to descend above the root of the filesystem - // ... Error! - return false; - } - } - } - - // Prepend the path prefix - array_unshift($bits, $path_prefix); - - $resolved = ''; - - $max = sizeof($bits) - 1; - - // Check if we are able to resolve symlinks, Windows (prior to Vista and Server 2008) cannot. - $symlink_resolve = (function_exists('readlink')) ? true : false; - - foreach ($bits as $i => $bit) - { - if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit"))) - { - // Path Exists - if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit"))) - { - // Resolved a symlink. - $resolved = $link . (($i == $max) ? '' : '/'); - continue; - } - } - else - { - // Something doesn't exist here! - // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic - // return false; - } - $resolved .= $bit . (($i == $max) ? '' : '/'); - } - - // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it - // because we must be inside that basedir, the question is where... - // @internal The slash in is_dir() gets around an open_basedir restriction - if (!@file_exists($resolved) || (!@is_dir($resolved . '/') && !is_file($resolved))) - { - return false; - } - - // Put the slashes back to the native operating systems slashes - $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved); - - // Check for DIRECTORY_SEPARATOR at the end (and remove it!) - if (substr($resolved, -1) == DIRECTORY_SEPARATOR) - { - return substr($resolved, 0, -1); - } - - return $resolved; // We got here, in the end! -} - -if (!function_exists('realpath')) -{ - /** - * A wrapper for realpath - * @ignore - */ - function phpbb_realpath($path) - { - return phpbb_own_realpath($path); - } -} -else -{ - /** - * A wrapper for realpath - */ - function phpbb_realpath($path) - { - $realpath = realpath($path); - - // Strangely there are provider not disabling realpath but returning strange values. :o - // We at least try to cope with them. - if ($realpath === $path || $realpath === false) - { - return phpbb_own_realpath($path); - } - - // Check for DIRECTORY_SEPARATOR at the end (and remove it!) - if (substr($realpath, -1) == DIRECTORY_SEPARATOR) - { - $realpath = substr($realpath, 0, -1); - } - - return $realpath; - } -} - // functions used for building option fields /** @@ -1029,7 +587,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ /** * This event is used for performing actions directly before marking forums, * topics or posts as read. - * + * * It is also possible to prevent the marking. For that, the $should_markread parameter * should be set to FALSE. * @@ -3913,11 +3471,13 @@ function msg_handler($errno, $msg_text, $errfile, $errline) */ function phpbb_filter_root_path($errfile) { + global $phpbb_filesystem; + static $root_path; if (empty($root_path)) { - $root_path = phpbb_realpath(dirname(__FILE__) . '/../'); + $root_path = $phpbb_filesystem->realpath(dirname(__FILE__) . '/../'); } return str_replace(array($root_path, '\\'), array('[ROOT]', '/'), $errfile); diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index a53a54368e..6d59b513af 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -405,7 +405,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) */ function validate_config_vars($config_vars, &$cfg_array, &$error) { - global $phpbb_root_path, $user, $phpbb_dispatcher; + global $phpbb_root_path, $user, $phpbb_dispatcher, $phpbb_filesystem; $type = 0; $min = 1; @@ -586,7 +586,7 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) // Check if the path is writable if ($config_definition['validate'] == 'wpath' || $config_definition['validate'] == 'rwpath' || $config_definition['validate'] === 'absolute_path_writable') { - if (file_exists($path) && !phpbb_is_writable($path)) + if (file_exists($path) && !$phpbb_filesystem->is_writable($path)) { $error[] = sprintf($user->lang['DIRECTORY_NOT_WRITABLE'], $cfg_array[$config_name]); } diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 4707238951..2d064e37cb 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -117,7 +117,7 @@ function phpbb_clean_path($path) new phpbb\symfony_request( $request ), - new phpbb\filesystem(), + new phpbb\filesystem\filesystem(), $request, $phpbb_root_path, $phpEx @@ -397,3 +397,88 @@ function get_tables(&$db) return $db_tools->sql_list_tables(); } + +/** + * Global function for chmodding directories and files for internal use + * + * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. + * The function determines owner and group from common.php file and sets the same to the provided file. + * The function uses bit fields to build the permissions. + * The function sets the appropiate execute bit on directories. + * + * Supported constants representing bit fields are: + * + * CHMOD_ALL - all permissions (7) + * CHMOD_READ - read permission (4) + * CHMOD_WRITE - write permission (2) + * CHMOD_EXECUTE - execute permission (1) + * + * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. + * + * @param string $filename The file/directory to be chmodded + * @param int $perms Permissions to set + * + * @return bool true on success, otherwise false + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::phpbb_chmod() instead + */ +function phpbb_chmod($filename, $perms = CHMOD_READ) +{ + global $phpbb_filesystem; + + try + { + $phpbb_filesystem->phpbb_chmod($filename, $perms); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + return false; + } + + return true; +} + +/** + * Test if a file/directory is writable + * + * This function calls the native is_writable() when not running under + * Windows and it is not disabled. + * + * @param string $file Path to perform write test on + * @return bool True when the path is writable, otherwise false. + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_writable() instead + */ +function phpbb_is_writable($file) +{ + global $phpbb_filesystem; + + return $phpbb_filesystem->is_writable($file); +} + +/** + * Checks if a path ($path) is absolute or relative + * + * @param string $path Path to check absoluteness of + * @return boolean + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_absolute_path() instead + */ +function phpbb_is_absolute($path) +{ + global $phpbb_filesystem; + + return $phpbb_filesystem->is_absolute_path($path); +} + +/** + * A wrapper for realpath + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::realpath() instead + */ +function phpbb_realpath($path) +{ + global $phpbb_filesystem; + + return $phpbb_filesystem->realpath($path); +} diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php index a7ee29dd91..e768a0f47b 100644 --- a/phpBB/includes/functions_compress.php +++ b/phpBB/includes/functions_compress.php @@ -184,7 +184,7 @@ class compress } /** -* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux, +* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux, * Marc Delisle, http://www.phpmyadmin.net/ * * Zip extraction function by Alexandre Tedeschi, alexandrebr at gmail dot com @@ -203,12 +203,20 @@ class compress_zip extends compress var $old_offset = 0; var $datasec_len = 0; + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + /** * Constructor */ function compress_zip($mode, $file) { + global $phpbb_filesystem; + $this->fp = @fopen($file, $mode . 'b'); + $this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem(); if (!$this->fp) { @@ -286,7 +294,15 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } } @@ -315,7 +331,15 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } } @@ -538,11 +562,18 @@ class compress_tar extends compress var $type = ''; var $wrote = false; + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + /** * Constructor */ function compress_tar($mode, $file, $type = '') { + global $phpbb_filesystem; + $type = (!$type) ? $file : $type; $this->isgz = preg_match('#(\.tar\.gz|\.tgz)$#', $type); $this->isbz = preg_match('#\.tar\.bz2$#', $type); @@ -551,6 +582,8 @@ class compress_tar extends compress $this->file = &$file; $this->type = &$type; $this->open(); + + $this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem(); } /** @@ -601,7 +634,15 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } } @@ -628,7 +669,15 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -637,7 +686,15 @@ class compress_tar extends compress { trigger_error("Couldn't create file $filename"); } - phpbb_chmod($target_filename, CHMOD_READ); + + try + { + $this->filesystem->phpbb_chmod($target_filename, CHMOD_READ); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } // Grab the file contents fwrite($fp, ($filesize) ? $fzread($this->fp, ($filesize + 511) &~ 511) : '', $filesize); diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php index ea7816077d..ad693f4019 100644 --- a/phpBB/includes/functions_convert.php +++ b/phpBB/includes/functions_convert.php @@ -2316,7 +2316,10 @@ function convert_bbcode($message, $convert_size = true, $extended_bbcodes = fals function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $source_relative_path = true) { - global $convert, $phpbb_root_path, $config, $user, $db; + global $convert, $phpbb_root_path, $config, $user, $db, $phpbb_filesystem; + + /** @var \phpbb\filesystem\filesystem_interface $filesystem */ + $filesystem = $phpbb_filesystem; if (substr($trg, -1) == '/') { @@ -2349,7 +2352,7 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour } } - if (!phpbb_is_writable($path)) + if (!$filesystem->is_writable($path)) { @chmod($path, 0777); } @@ -2370,7 +2373,10 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_failure = true, $source_relative_path = true) { - global $convert, $phpbb_root_path, $config, $user, $db; + global $convert, $phpbb_root_path, $config, $user, $db, $phpbb_filesystem; + + /** @var \phpbb\filesystem\filesystem_interface $filesystem */ + $filesystem = $phpbb_filesystem; $dirlist = $filelist = $bad_dirs = array(); $src = path($src, $source_relative_path); @@ -2384,7 +2390,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_ @chmod($trg_path, 0777); } - if (!phpbb_is_writable($trg_path)) + if (!$filesystem->is_writable($trg_path)) { $bad_dirs[] = path($config['script_path']) . $trg; } @@ -2451,7 +2457,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_ @chmod($trg_path . $dir, 0777); } - if (!phpbb_is_writable($trg_path . $dir)) + if (!$filesystem->is_writable($trg_path . $dir)) { $bad_dirs[] = $trg . $dir; $bad_dirs[] = $trg_path . $dir; diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 8dacd25230..d9d073e984 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -189,7 +189,7 @@ function dbms_select($default = '', $only_20x_options = false) */ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport, $prefix_may_exist = false, $load_dbal = true, $unicode_check = true) { - global $phpbb_root_path, $phpEx, $config, $lang; + global $phpbb_root_path, $phpEx, $config, $lang, $phpbb_filesystem; $dbms = $dbms_details['DRIVER']; @@ -205,7 +205,7 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, } // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea - if (($dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite' || $dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite3') && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0) + if (($dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite' || $dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite3') && stripos($phpbb_filesystem->realpath($dbhost), $phpbb_filesystem->realpath('../')) === 0) { $error[] = $lang['INST_ERR_DB_FORUM_PATH']; return false; diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 3aa3f3d03f..b0861585ba 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -623,7 +623,7 @@ class messenger */ protected function setup_template() { - global $config, $phpbb_path_helper, $user, $phpbb_extension_manager, $phpbb_container; + global $config, $phpbb_path_helper, $user, $phpbb_extension_manager, $phpbb_container, $phpbb_filesystem; if ($this->template instanceof \phpbb\template\template) { @@ -641,7 +641,9 @@ class messenger $phpbb_container, $phpbb_container->getParameter('core.root_path') . 'cache/', $phpbb_container->get('ext.manager'), - new \phpbb\template\twig\loader() + new \phpbb\template\twig\loader( + $phpbb_filesystem + ) ), $phpbb_container->getParameter('core.root_path') . 'cache/', $phpbb_container->get('template.twig.extensions.collection'), @@ -671,15 +673,21 @@ class queue var $cache_file = ''; var $eol = "\n"; + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + /** * constructor */ function queue() { - global $phpEx, $phpbb_root_path; + global $phpEx, $phpbb_root_path, $phpbb_filesystem; $this->data = array(); $this->cache_file = "{$phpbb_root_path}cache/queue.$phpEx"; + $this->filesystem = $phpbb_filesystem; } /** @@ -865,7 +873,14 @@ class queue fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); fclose($fp); - phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -907,7 +922,14 @@ class queue fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); fclose($fp); - phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } $lock->release(); diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 9c6ddffe9f..4233395574 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -407,14 +407,14 @@ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null) { global $auth, $user, $config, $db, $cache; - global $phpbb_root_path, $phpEx, $phpbb_dispatcher; + global $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_filesystem; $filedata = array( 'error' => array() ); include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); - $upload = new fileupload(); + $upload = new fileupload($phpbb_filesystem); if ($config['check_attachment_content'] && isset($config['mime_triggers'])) { @@ -668,7 +668,7 @@ function get_supported_image_types($type = false) */ function create_thumbnail($source, $destination, $mimetype) { - global $config; + global $config, $phpbb_filesystem; $min_filesize = (int) $config['img_min_thumb_filesize']; $img_filesize = (file_exists($source)) ? @filesize($source) : false; @@ -820,7 +820,14 @@ function create_thumbnail($source, $destination, $mimetype) return false; } - phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } return true; } diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index f179b2fd70..21a6de7a41 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -46,6 +46,11 @@ class filespec var $upload = ''; + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + /** * The plupload object * @var \phpbb\plupload\plupload @@ -62,7 +67,7 @@ class filespec * File Class * @access private */ - function filespec($upload_ary, $upload_namespace, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null) + function filespec($upload_ary, $upload_namespace, \phpbb\filesystem\filesystem_interface $phpbb_filesystem, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null) { if (!isset($upload_ary)) { @@ -97,6 +102,7 @@ class filespec $this->upload = $upload_namespace; $this->plupload = $plupload; $this->mimetype_guesser = $mimetype_guesser; + $this->filesystem = $phpbb_filesystem; } /** @@ -374,7 +380,14 @@ class filespec return false; } - phpbb_chmod($this->destination_file, $chmod); + try + { + $this->filesystem->phpbb_chmod($this->destination_file, $chmod); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } // Try to get real filesize from destination folder @@ -499,9 +512,15 @@ class fileupload /** @var int Timeout for remote upload */ var $upload_timeout = 6; + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + /** * Init file upload class. * + * @param \phpbb\filesystem\filesystem_interface $filesystem * @param string $error_prefix Used error messages will get prefixed by this string * @param array $allowed_extensions Array of allowed extensions, for example array('jpg', 'jpeg', 'gif', 'png') * @param int $max_filesize Maximum filesize @@ -513,13 +532,14 @@ class fileupload * contain any of its values. Defaults to false. * */ - function fileupload($error_prefix = '', $allowed_extensions = false, $max_filesize = false, $min_width = false, $min_height = false, $max_width = false, $max_height = false, $disallowed_content = false) + function fileupload(\phpbb\filesystem\filesystem_interface $filesystem, $error_prefix = '', $allowed_extensions = false, $max_filesize = false, $min_width = false, $min_height = false, $max_width = false, $max_height = false, $disallowed_content = false) { $this->set_allowed_extensions($allowed_extensions); $this->set_max_filesize($max_filesize); $this->set_allowed_dimensions($min_width, $min_height, $max_width, $max_height); $this->set_error_prefix($error_prefix); $this->set_disallowed_content($disallowed_content); + $this->filesystem = $filesystem; } /** @@ -613,7 +633,7 @@ class fileupload } } - $file = new filespec($upload, $this, $mimetype_guesser, $plupload); + $file = new filespec($upload, $this, $this->filesystem, $mimetype_guesser, $plupload); if ($file->init_error) { @@ -694,7 +714,7 @@ class fileupload $upload['type'] = $filedata['type']; } - $file = new filespec($upload, $this, $mimetype_guesser); + $file = new filespec($upload, $this, $this->filesystem, $mimetype_guesser); if ($file->init_error) { @@ -932,7 +952,7 @@ class fileupload $upload_ary['tmp_name'] = $filename; - $file = new filespec($upload_ary, $this, $mimetype_guesser); + $file = new filespec($upload_ary, $this, $this->filesystem, $mimetype_guesser); $this->common_checks($file); return $file; diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index ba6f0b3ba9..4746bb11f2 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -183,7 +183,10 @@ define('IN_DB_UPDATE', true); /* @var $migrator \phpbb\db\migrator */ $migrator = $phpbb_container->get('migrator'); -$migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($user, new \phpbb\db\html_migrator_output_handler($user), $phpbb_root_path . 'store/migrations_' . time() . '.log')); + +/** @var \phpbb\filesystem\filesystem_interface $filesystem */ +$filesystem = $phpbb_container->get('filesystem'); +$migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($user, new \phpbb\db\html_migrator_output_handler($user), $phpbb_root_path . 'store/migrations_' . time() . '.log', $filesystem)); $migrator->create_migrations_table(); diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 811034f064..dd3590e854 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -270,7 +270,7 @@ $config = new \phpbb\config\config(array( /* @var $symfony_request \phpbb\symfony_request */ $symfony_request = $phpbb_container->get('symfony_request'); -/* @var $phpbb_filesystem \phpbb\filesystem */ +/* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */ $phpbb_filesystem = $phpbb_container->get('filesystem'); /* @var $phpbb_path_helper \phpbb\path_helper */ diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index 506bece9c9..e268565be3 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -96,6 +96,9 @@ class install_convert extends module /** @var string */ protected $php_ext; + /** @var \phpbb\filesystem\filesystem_interface */ + protected $filesystem; + /** * Variables used while converting, they are accessible from the global variable $convert */ @@ -116,6 +119,7 @@ class install_convert extends module $this->template = $template; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $phpEx; + $this->filesystem = new \phpbb\filesystem\filesystem(); if (!$this->check_phpbb_installed()) { @@ -859,7 +863,7 @@ class install_convert extends module $this->p_master->error($user->lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__); } - if (!$local_path || !phpbb_is_writable($phpbb_root_path . $local_path)) + if (!$local_path || !$this->filesystem->is_writable($phpbb_root_path . $local_path)) { if (!$local_path) { diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index e38c9c5bdf..8f39328adb 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -43,9 +43,15 @@ if (!empty($setmodules)) */ class install_install extends module { + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + function install_install(&$p_master) { $this->p_master = &$p_master; + $this->filesystem = new \phpbb\filesystem\filesystem(); } function main($mode, $sub) @@ -466,13 +472,29 @@ class install_install extends module if (!file_exists($phpbb_root_path . $dir)) { @mkdir($phpbb_root_path . $dir, 0777); - phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } // Now really check if (file_exists($phpbb_root_path . $dir) && is_dir($phpbb_root_path . $dir)) { - phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + $exists = true; } @@ -514,7 +536,7 @@ class install_install extends module $write = $exists = true; if (file_exists($phpbb_root_path . $dir)) { - if (!phpbb_is_writable($phpbb_root_path . $dir)) + if (!$this->filesystem->is_writable($phpbb_root_path . $dir)) { $write = false; } @@ -892,7 +914,7 @@ class install_install extends module $config_data = phpbb_create_config_file_data($data, $available_dbms[$data['dbms']]['DRIVER']); // Attempt to write out the config file directly. If it works, this is the easiest way to do it ... - if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx)) || phpbb_is_writable($phpbb_root_path)) + if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && $this->filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx)) || $this->filesystem->is_writable($phpbb_root_path)) { // Assume it will work ... if nothing goes wrong below $written = true; @@ -914,7 +936,14 @@ class install_install extends module if ($written) { // We may revert back to chmod() if we see problems with users not able to change their config.php file directly - phpbb_chmod($phpbb_root_path . 'config.' . $phpEx, CHMOD_READ); + try + { + $this->filesystem->phpbb_chmod($phpbb_root_path . 'config.' . $phpEx, CHMOD_READ); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -1195,7 +1224,7 @@ class install_install extends module include($phpbb_root_path . 'includes/constants.' . $phpEx); } - $finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path, null, $phpEx); + $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx); $classes = $finder->core_path('phpbb/db/migration/data/') ->get_classes(); @@ -2031,7 +2060,7 @@ class install_install extends module { global $config, $phpbb_root_path; - if (!phpbb_is_writable($phpbb_root_path . 'images/avatars/upload/')) + if (!$this->filesystem->is_writable($phpbb_root_path . 'images/avatars/upload/')) { $config->set('allow_avatar', 0); $config->set('allow_avatar_upload', 0); diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index 0ec6897607..410a8afb66 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -55,6 +55,8 @@ class install_update extends module var $update_to_version; + protected $filesystem; + // Set to false var $test_update = false; @@ -87,6 +89,8 @@ class install_update extends module /* @var $cache \phpbb\cache\service */ $cache = $phpbb_container->get('cache'); + $this->filesystem = $phpbb_container->get('filesystem'); + $this->tpl_name = 'install_update'; $this->page_title = 'UPDATE_INSTALLATION'; @@ -961,7 +965,7 @@ class install_update extends module // Now init the connection if ($update_mode == 'download') { - if (function_exists('phpbb_is_writable') && !phpbb_is_writable($phpbb_root_path . 'store/')) + if ($this->filesystem->is_writable($phpbb_root_path . 'store/')) { trigger_error(sprintf('The directory “%s†is not writable.', $phpbb_root_path . 'store/'), E_USER_ERROR); } diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index 003b23659f..2ad84c087d 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -18,6 +18,11 @@ namespace phpbb\avatar\driver; */ class upload extends \phpbb\avatar\driver\driver { + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + /** * @var \phpbb\mimetype\guesser */ @@ -29,15 +34,17 @@ class upload extends \phpbb\avatar\driver\driver * @param \phpbb\config\config $config phpBB configuration * @param string $phpbb_root_path Path to the phpBB root * @param string $php_ext PHP file extension - * @param \phpbb_path_helper $path_helper phpBB path helper + * @param \phpbb\filesystem\filesystem_interface phpBB filesystem helper + * @param \phpbb\path_helper $path_helper phpBB path helper * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser * @param \phpbb\cache\driver\driver_interface $cache Cache driver */ - public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\mimetype\guesser $mimetype_guesser, \phpbb\cache\driver\driver_interface $cache = null) + public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\path_helper $path_helper, \phpbb\mimetype\guesser $mimetype_guesser, \phpbb\cache\driver\driver_interface $cache = null) { $this->config = $config; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; + $this->filesystem = $filesystem; $this->path_helper = $path_helper; $this->mimetype_guesser = $mimetype_guesser; $this->cache = $cache; @@ -88,7 +95,7 @@ class upload extends \phpbb\avatar\driver\driver include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext); } - $upload = new \fileupload('AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false)); + $upload = new \fileupload($this->filesystem, 'AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false)); $url = $request->variable('avatar_upload_url', ''); $upload_file = $request->file('avatar_upload_file'); @@ -209,6 +216,6 @@ class upload extends \phpbb\avatar\driver\driver */ protected function can_upload() { - return (file_exists($this->phpbb_root_path . $this->config['avatar_path']) && phpbb_is_writable($this->phpbb_root_path . $this->config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')); + return (file_exists($this->phpbb_root_path . $this->config['avatar_path']) && $this->filesystem->is_writable($this->phpbb_root_path . $this->config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')); } } diff --git a/phpBB/phpbb/cache/driver/base.php b/phpBB/phpbb/cache/driver/base.php index c83b928a12..55cd4668de 100644 --- a/phpBB/phpbb/cache/driver/base.php +++ b/phpBB/phpbb/cache/driver/base.php @@ -177,13 +177,9 @@ abstract class base implements \phpbb\cache\driver\driver_interface */ function remove_file($filename, $check = false) { - if (!function_exists('phpbb_is_writable')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/functions.' . $phpEx); - } + global $phpbb_filesystem; - if ($check && !phpbb_is_writable($this->cache_dir)) + if ($check && !$phpbb_filesystem->is_writable($this->cache_dir)) { // E_USER_ERROR - not using language entry - intended. trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php index 32086458ee..bb055d3acf 100644 --- a/phpBB/phpbb/cache/driver/file.php +++ b/phpBB/phpbb/cache/driver/file.php @@ -20,6 +20,11 @@ class file extends \phpbb\cache\driver\base { var $var_expires = array(); + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + /** * Set cache path * @@ -30,6 +35,7 @@ class file extends \phpbb\cache\driver\base global $phpbb_root_path, $phpbb_container; $this->cache_dir = !is_null($cache_dir) ? $cache_dir : $phpbb_root_path . 'cache/' . $phpbb_container->getParameter('core.environment') . '/'; + $this->filesystem = new \phpbb\filesystem\filesystem(); if (!is_dir($this->cache_dir)) { @@ -69,14 +75,8 @@ class file extends \phpbb\cache\driver\base if (!$this->_write('data_global')) { - if (!function_exists('phpbb_is_writable')) - { - global $phpbb_root_path; - include($phpbb_root_path . 'includes/functions.' . $phpEx); - } - // Now, this occurred how often? ... phew, just tell the user then... - if (!phpbb_is_writable($this->cache_dir)) + if (!$this->filesystem->is_writable($this->cache_dir)) { // We need to use die() here, because else we may encounter an infinite loop (the message handler calls $cache->unload()) die('Fatal: ' . $this->cache_dir . ' is NOT writable.'); @@ -574,13 +574,14 @@ class file extends \phpbb\cache\driver\base fclose($handle); - if (!function_exists('phpbb_chmod')) + try { - global $phpbb_root_path; - include($phpbb_root_path . 'includes/functions.' . $phpEx); + $this->filesystem->phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing } - - phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE); $return_value = true; } diff --git a/phpBB/phpbb/console/command/db/migrate.php b/phpBB/phpbb/console/command/db/migrate.php index 87c2a057d1..2490bf1310 100644 --- a/phpBB/phpbb/console/command/db/migrate.php +++ b/phpBB/phpbb/console/command/db/migrate.php @@ -35,13 +35,17 @@ class migrate extends \phpbb\console\command\command /** @var string phpBB root path */ protected $phpbb_root_path; - function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, $phpbb_root_path) + /** @var \phpbb\filesystem\filesystem_interface */ + protected $filesystem; + + function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path) { $this->migrator = $migrator; $this->extension_manager = $extension_manager; $this->config = $config; $this->cache = $cache; $this->log = $log; + $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; parent::__construct($user); $this->user->add_lang(array('common', 'install', 'migrator')); @@ -57,7 +61,7 @@ class migrate extends \phpbb\console\command\command protected function execute(InputInterface $input, OutputInterface $output) { - $this->migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($this->user, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log')); + $this->migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($this->user, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem)); $this->migrator->create_migrations_table(); diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index 2790ea4277..1e1cf5e4e8 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -53,7 +53,7 @@ class helper protected $request; /** - * @var \phpbb\filesystem The filesystem object + * @var \phpbb\filesystem\filesystem_interface The filesystem object */ protected $filesystem; @@ -78,11 +78,11 @@ class helper * @param \phpbb\routing\router $router phpBB router * @param \phpbb\symfony_request $symfony_request Symfony Request object * @param \phpbb\request\request_interface $request phpBB request object - * @param \phpbb\filesystem $filesystem The filesystem object + * @param \phpbb\filesystem\filesystem_interface $filesystem The filesystem object * @param string $phpbb_root_path phpBB root path * @param string $php_ext PHP file extension */ - public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext) { $this->template = $template; $this->user = $user; diff --git a/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php b/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php index 94c293dc45..4c85bf4d67 100644 --- a/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php +++ b/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php @@ -37,17 +37,24 @@ class log_wrapper_migrator_output_handler implements migrator_output_handler_int */ protected $file_handle = false; + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + /** * Constructor * * @param user $user User object * @param migrator_output_handler_interface $migrator Migrator output handler * @param string $log_file File to log to + * @param \phpbb\filesystem\filesystem_interface phpBB filesystem object */ - public function __construct(user $user, migrator_output_handler_interface $migrator, $log_file) + public function __construct(user $user, migrator_output_handler_interface $migrator, $log_file, \phpbb\filesystem\filesystem_interface $filesystem) { $this->user = $user; $this->migrator = $migrator; + $this->filesystem = $filesystem; $this->file_open($log_file); } @@ -58,7 +65,7 @@ class log_wrapper_migrator_output_handler implements migrator_output_handler_int */ protected function file_open($file) { - if (phpbb_is_writable(dirname($file))) + if ($this->filesystem->is_writable(dirname($file))) { $this->file_handle = fopen($file, 'w'); } diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 125ae28e9b..2a410db9bd 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -192,7 +192,8 @@ class container_builder } } - $loader = new YamlFileLoader($this->container, new FileLocator(phpbb_realpath($this->get_config_path()))); + $filesystem = new \phpbb\filesystem\filesystem(); + $loader = new YamlFileLoader($this->container, new FileLocator($filesystem->realpath($this->get_config_path()))); $loader->load($this->container->getParameter('core.environment') . '/config.yml'); $this->inject_custom_parameters(); diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index 451efc8e35..c71dc61280 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -50,7 +50,8 @@ class core extends Extension */ public function load(array $configs, ContainerBuilder $container) { - $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path))); + $filesystem = new \phpbb\filesystem\filesystem(); + $loader = new YamlFileLoader($container, new FileLocator($filesystem->realpath($this->config_path))); $loader->load($container->getParameter('core.environment') . '/container/environment.yml'); $config = $this->getConfiguration($configs, $container); diff --git a/phpBB/phpbb/extension/di/extension_base.php b/phpBB/phpbb/extension/di/extension_base.php index 30cc37dbb6..ba74615e70 100644 --- a/phpBB/phpbb/extension/di/extension_base.php +++ b/phpBB/phpbb/extension/di/extension_base.php @@ -94,7 +94,8 @@ class extension_base extends Extension if ($services_directory && $services_file) { - $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($services_directory))); + $filesystem = new \phpbb\filesystem\filesystem(); + $loader = new YamlFileLoader($container, new FileLocator($filesystem->realpath($services_directory))); $loader->load($services_file); } } diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 880973d5fb..40fda74065 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -39,7 +39,7 @@ class manager * @param ContainerInterface $container A container * @param \phpbb\db\driver\driver_interface $db A database connection * @param \phpbb\config\config $config Config object - * @param \phpbb\filesystem $filesystem + * @param \phpbb\filesystem\filesystem_interface $filesystem * @param \phpbb\user $user User object * @param string $extension_table The name of the table holding extensions * @param string $phpbb_root_path Path to the phpbb includes directory. @@ -47,7 +47,7 @@ class manager * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null * @param string $cache_name The name of the cache variable, defaults to _ext */ - public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem $filesystem, \phpbb\user $user, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext') + public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\user $user, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext') { $this->cache = $cache; $this->cache_name = $cache_name; diff --git a/phpBB/phpbb/filesystem.php b/phpBB/phpbb/filesystem.php index 77517082e5..af56d78845 100644 --- a/phpBB/phpbb/filesystem.php +++ b/phpBB/phpbb/filesystem.php @@ -14,37 +14,8 @@ namespace phpbb; /** -* A class with various functions that are related to paths, files and the filesystem -*/ -class filesystem + * @deprecated 3.2.0-dev (To be removed 3.3.0) use \phpbb\filesystem\filesystem instead + */ +class filesystem extends \phpbb\filesystem\filesystem { - /** - * Eliminates useless . and .. components from specified path. - * - * @param string $path Path to clean - * @return string Cleaned path - */ - public function clean_path($path) - { - $exploded = explode('/', $path); - $filtered = array(); - foreach ($exploded as $part) - { - if ($part === '.' && !empty($filtered)) - { - continue; - } - - if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '.' && $filtered[sizeof($filtered) - 1] !== '..') - { - array_pop($filtered); - } - else - { - $filtered[] = $part; - } - } - $path = implode('/', $filtered); - return $path; - } } diff --git a/phpBB/phpbb/filesystem/exception/filesystem_exception.php b/phpBB/phpbb/filesystem/exception/filesystem_exception.php new file mode 100644 index 0000000000..d68fa9adf3 --- /dev/null +++ b/phpBB/phpbb/filesystem/exception/filesystem_exception.php @@ -0,0 +1,42 @@ + + * @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\filesystem\exception; + +class filesystem_exception extends \phpbb\exception\runtime_exception +{ + /** + * Constructor + * + * @param string $message The Exception message to throw (must be a language variable). + * @param string $filename The file that caused the error. + * @param array $parameters The parameters to use with the language var. + * @param \Exception $previous The previous runtime_exception used for the runtime_exception chaining. + * @param integer $code The Exception code. + */ + public function __construct($message = "", $filename = '', $parameters = array(), \Exception $previous = null, $code = 0) + { + parent::__construct($message, array_merge(array('filename' => $filename), $parameters), $previous, $code); + } + + /** + * Returns the filename that triggered the error + * + * @return string + */ + public function get_filename() + { + $parameters = parent::get_parameters(); + return $parameters['filename']; + } +} diff --git a/phpBB/phpbb/filesystem/filesystem.php b/phpBB/phpbb/filesystem/filesystem.php new file mode 100644 index 0000000000..370dff77e5 --- /dev/null +++ b/phpBB/phpbb/filesystem/filesystem.php @@ -0,0 +1,916 @@ + + * @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\filesystem; + +use phpbb\filesystem\exception\filesystem_exception; + +/** + * A class with various functions that are related to paths, files and the filesystem + */ +class filesystem implements filesystem_interface +{ + /** + * Store some information about file ownership for phpBB's chmod function + * + * @var array + */ + protected $chmod_info; + + /** + * Stores current working directory + * + * @var string|bool current working directory or false if it cannot be recovered + */ + protected $working_directory; + + /** + * Symfony's Filesystem component + * + * @var \Symfony\Component\Filesystem\Filesystem + */ + protected $symfony_filesystem; + + /** + * Constructor + */ + public function __construct() + { + $this->chmod_info = array(); + $this->symfony_filesystem = new \Symfony\Component\Filesystem\Filesystem(); + $this->working_directory = null; + } + + /** + * {@inheritdoc} + */ + public function chgrp($files, $group, $recursive = false) + { + try + { + $this->symfony_filesystem->chgrp($files, $group, $recursive); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + // Try to recover filename + // By the time this is written that is at the end of the message + $error = trim($e->getMessage()); + $file = substr($error, strrpos($error, ' ')); + + throw new filesystem_exception('CANNOT_CHANGE_FILE_GROUP', $file, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function chmod($files, $perms = null, $recursive = false, $force_chmod_link = false) + { + if (is_null($perms)) + { + // Default to read permission for compatibility reasons + $perms = self::CHMOD_READ; + } + + // Check if we got a permission flag + if ($perms > self::CHMOD_ALL) + { + $file_perm = $perms; + + // Extract permissions + //$owner = ($file_perm >> 6) & 7; // This will be ignored + $group = ($file_perm >> 3) & 7; + $other = ($file_perm >> 0) & 7; + + // Does any permissions provided? if so we add execute bit for directories + $group = ($group !== 0) ? ($group | self::CHMOD_EXECUTE) : $group; + $other = ($other !== 0) ? ($other | self::CHMOD_EXECUTE) : $other; + + // Compute directory permissions + $dir_perm = (self::CHMOD_ALL << 6) + ($group << 3) + ($other << 3); + } + else + { + // Add execute bit to owner if execute bit is among perms + $owner_perm = (self::CHMOD_READ | self::CHMOD_WRITE) | ($perms & self::CHMOD_EXECUTE); + $file_perm = ($owner_perm << 6) + ($perms << 3) + ($perms << 0); + + // Compute directory permissions + $perm = ($perms !== 0) ? ($perms | self::CHMOD_EXECUTE) : $perms; + $dir_perm = (($owner_perm | self::CHMOD_EXECUTE) << 6) + ($perm << 3) + ($perm << 0); + } + + // Symfony's filesystem component does not support extra execution flags on directories + // so we need to implement it again + foreach ($this->to_iterator($files) as $file) + { + if ($recursive && is_dir($file) && !is_link($file)) + { + $this->chmod(new \FilesystemIterator($file), $perms, true); + } + + // Don't chmod links as mostly those require 0777 and that cannot be changed + if (is_dir($file) || (is_link($file) && $force_chmod_link)) + { + if (true !== @chmod($file, $dir_perm)) + { + throw new filesystem_exception('CANNOT_CHANGE_FILE_PERMISSIONS', $file, array()); + } + } + else if (is_file($file)) + { + if (true !== @chmod($file, $file_perm)) + { + throw new filesystem_exception('CANNOT_CHANGE_FILE_PERMISSIONS', $file, array()); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function chown($files, $user, $recursive = false) + { + try + { + $this->symfony_filesystem->chown($files, $user, $recursive); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + // Try to recover filename + // By the time this is written that is at the end of the message + $error = trim($e->getMessage()); + $file = substr($error, strrpos($error, ' ')); + + throw new filesystem_exception('CANNOT_CHANGE_FILE_GROUP', $file, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function clean_path($path) + { + $exploded = explode('/', $path); + $filtered = array(); + foreach ($exploded as $part) + { + if ($part === '.' && !empty($filtered)) + { + continue; + } + + if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '.' && $filtered[sizeof($filtered) - 1] !== '..') + { + array_pop($filtered); + } + else + { + $filtered[] = $part; + } + } + $path = implode('/', $filtered); + return $path; + } + + /** + * {@inheritdoc} + */ + public function copy($origin_file, $target_file, $override = false) + { + try + { + $this->symfony_filesystem->copy($origin_file, $target_file, $override); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + throw new filesystem_exception('CANNOT_COPY_FILES', '', array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function dump_file($filename, $content) + { + try + { + $this->symfony_filesystem->dumpFile($filename, $content); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + throw new filesystem_exception('CANNOT_DUMP_FILE', $filename, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function exists($files) + { + return $this->symfony_filesystem->exists($files); + } + + /** + * {@inheritdoc} + */ + public function is_absolute_path($path) + { + return (isset($path[0]) && $path[0] === '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false; + } + + /** + * {@inheritdoc} + */ + public function is_readable($files, $recursive = false) + { + foreach ($this->to_iterator($files) as $file) + { + if ($recursive && is_dir($file) && !is_link($file)) + { + if (!$this->is_readable(new \FilesystemIterator($file), true)) + { + return false; + } + } + + if (!is_readable($file)) + { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function is_writable($files, $recursive = false) + { + if (defined('PHP_WINDOWS_VERSION_MAJOR') || !function_exists('is_writable')) + { + foreach ($this->to_iterator($files) as $file) + { + if ($recursive && is_dir($file) && !is_link($file)) + { + if (!$this->is_writable(new \FilesystemIterator($file), true)) + { + return false; + } + } + + if (!$this->phpbb_is_writable($file)) + { + return false; + } + } + } + else + { + // use built in is_writable + foreach ($this->to_iterator($files) as $file) + { + if ($recursive && is_dir($file) && !is_link($file)) + { + if (!$this->is_writable(new \FilesystemIterator($file), true)) + { + return false; + } + } + + if (!is_writable($file)) + { + return false; + } + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function make_path_relative($end_path, $start_path) + { + return $this->symfony_filesystem->makePathRelative($end_path, $start_path); + } + + /** + * {@inheritdoc} + */ + public function mirror($origin_dir, $target_dir, \Traversable $iterator = null, $options = array()) + { + try + { + $this->symfony_filesystem->mirror($origin_dir, $target_dir, $iterator, $options); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + $msg = $e->getMessage(); + $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"')); + + throw new filesystem_exception('CANNOT_MIRROR_DIRECTORY', $filename, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function mkdir($dirs, $mode = 0777) + { + try + { + $this->symfony_filesystem->mkdir($dirs, $mode); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + $msg = $e->getMessage(); + $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"')); + + throw new filesystem_exception('CANNOT_CREATE_DIRECTORY', $filename, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function phpbb_chmod($files, $perms = null, $recursive = false, $force_chmod_link = false) + { + if (is_null($perms)) + { + // Default to read permission for compatibility reasons + $perms = self::CHMOD_READ; + } + + if (empty($this->chmod_info)) + { + if (!function_exists('fileowner') || !function_exists('filegroup')) + { + $this->chmod_info['process'] = false; + } + else + { + $common_php_owner = @fileowner(__FILE__); + $common_php_group = @filegroup(__FILE__); + + // And the owner and the groups PHP is running under. + $php_uid = (function_exists('posic_getuid')) ? @posix_getuid() : false; + $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; + + // If we are unable to get owner/group, then do not try to set them by guessing + if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) + { + $this->chmod_info['process'] = false; + } + else + { + $this->chmod_info = array( + 'process' => true, + 'common_owner' => $common_php_owner, + 'common_group' => $common_php_group, + 'php_uid' => $php_uid, + 'php_gids' => $php_gids, + ); + } + } + } + + if ($this->chmod_info['process']) + { + try + { + foreach ($this->to_iterator($files) as $file) + { + $file_uid = @fileowner($file); + $file_gid = @filegroup($file); + + // Change owner + if ($file_uid !== $this->chmod_info['common_owner']) + { + $this->chown($file, $this->chmod_info['common_owner'], $recursive); + } + + // Change group + if ($file_gid !== $this->chmod_info['common_group']) + { + $this->chgrp($file, $this->chmod_info['common_group'], $recursive); + } + + clearstatcache(); + $file_uid = @fileowner($file); + $file_gid = @filegroup($file); + } + } + catch (filesystem_exception $e) + { + $this->chmod_info['process'] = false; + } + } + + // Still able to process? + if ($this->chmod_info['process']) + { + if ($file_uid === $this->chmod_info['php_uid']) + { + $php = 'owner'; + } + else if (in_array($file_gid, $this->chmod_info['php_gids'])) + { + $php = 'group'; + } + else + { + // Since we are setting the everyone bit anyway, no need to do expensive operations + $this->chmod_info['process'] = false; + } + } + + // We are not able to determine or change something + if (!$this->chmod_info['process']) + { + $php = 'other'; + } + + switch ($php) + { + case 'owner': + try + { + $this->chmod($files, $perms, $recursive, $force_chmod_link); + clearstatcache(); + if ($this->is_readable($files) && $this->is_writable($files)) + { + break; + } + } + catch (filesystem_exception $e) + { + // Do nothing + } + case 'group': + try + { + $this->chmod($files, $perms, $recursive, $force_chmod_link); + clearstatcache(); + if ((!($perms & self::CHMOD_READ) || $this->is_readable($files, $recursive)) && (!($perms & self::CHMOD_WRITE) || $this->is_writable($files, $recursive))) + { + break; + } + } + catch (filesystem_exception $e) + { + // Do nothing + } + case 'other': + default: + $this->chmod($files, $perms, $recursive, $force_chmod_link); + break; + } + } + + /** + * {@inheritdoc} + */ + public function realpath($path) + { + if (!function_exists('realpath')) + { + return $this->phpbb_own_realpath($path); + } + + $realpath = realpath($path); + + // Strangely there are provider not disabling realpath but returning strange values. :o + // We at least try to cope with them. + if ((!$this->is_absolute_path($path) && $realpath === $path) || $realpath === false) + { + return $this->phpbb_own_realpath($path); + } + + // Check for DIRECTORY_SEPARATOR at the end (and remove it!) + if (substr($realpath, -1) === DIRECTORY_SEPARATOR) + { + $realpath = substr($realpath, 0, -1); + } + + return $realpath; + } + + /** + * {@inheritdoc} + */ + public function remove($files) + { + try + { + $this->symfony_filesystem->remove($files); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + // Try to recover filename + // By the time this is written that is at the end of the message + $error = trim($e->getMessage()); + $file = substr($error, strrpos($error, ' ')); + + throw new filesystem_exception('CANNOT_DELETE_FILES', $file, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function rename($origin, $target, $overwrite = false) + { + try + { + $this->symfony_filesystem->rename($origin, $target, $overwrite); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + $msg = $e->getMessage(); + $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"')); + + throw new filesystem_exception('CANNOT_RENAME_FILE', $filename, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function symlink($origin_dir, $target_dir, $copy_on_windows = false) + { + try + { + $this->symfony_filesystem->symlink($origin_dir, $target_dir, $copy_on_windows); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + throw new filesystem_exception('CANNOT_CREATE_SYMLINK', $origin_dir, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function touch($files, $time = null, $access_time = null) + { + try + { + $this->symfony_filesystem->touch($files, $time, $access_time); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + // Try to recover filename + // By the time this is written that is at the end of the message + $error = trim($e->getMessage()); + $file = substr($error, strrpos($error, ' ')); + + throw new filesystem_exception('CANNOT_TOUCH_FILES', $file, array(), $e); + } + } + + /** + * phpBB's implementation of is_writable + * + * @todo Investigate if is_writable is still buggy + * + * @param string $file file/directory to check if writable + * + * @return bool true if the given path is writable + */ + protected function phpbb_is_writable($file) + { + if (file_exists($file)) + { + // Canonicalise path to absolute path + $file = $this->realpath($file); + + if (is_dir($file)) + { + // Test directory by creating a file inside the directory + $result = @tempnam($file, 'i_w'); + + if (is_string($result) && file_exists($result)) + { + unlink($result); + + // Ensure the file is actually in the directory (returned realpathed) + return (strpos($result, $file) === 0) ? true : false; + } + } + else + { + $handle = @fopen($file, 'w'); + + if (is_resource($handle)) + { + fclose($handle); + return true; + } + } + } + else + { + // file does not exist test if we can write to the directory + $dir = dirname($file); + + if (file_exists($dir) && is_dir($dir) && $this->phpbb_is_writable($dir)) + { + return true; + } + } + + return false; + } + + /** + * Try to resolve real path when PHP's realpath failes to do so + * + * @param string $path + * @return bool|string + */ + protected function phpbb_own_realpath($path) + { + // Replace all directory separators with '/' + $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); + + $is_absolute_path = false; + $path_prefix = ''; + + if ($this->is_absolute_path($path)) + { + $is_absolute_path = true; + } + else + { + // Resolve working directory and store it + if (is_null($this->working_directory)) + { + if (function_exists('getcwd')) + { + $this->working_directory = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()); + } + + // + // From this point on we really just guessing + // If chdir were called we screwed + // + else if (function_exists('debug_backtrace')) + { + $call_stack = debug_backtrace(0); + $this->working_directory = str_replace(DIRECTORY_SEPARATOR, '/', dirname($call_stack[sizeof($call_stack) - 1]['file'])); + } + else + { + // + // Assuming that the working directory is phpBB root + // we could use this as a fallback, when phpBB will use controllers + // everywhere this will be a safe assumption + // + //$dir_parts = explode(DIRECTORY_SEPARATOR, __DIR__); + //$namespace_parts = explode('\\', trim(__NAMESPACE__, '\\')); + + //$namespace_part_count = sizeof($namespace_parts); + + // Check if we still loading from root + //if (array_slice($dir_parts, -$namespace_part_count) === $namespace_parts) + //{ + // $this->working_directory = implode('/', array_slice($dir_parts, 0, -$namespace_part_count)); + //} + //else + //{ + // $this->working_directory = false; + //} + + $this->working_directory = false; + } + } + + if ($this->working_directory !== false) + { + $is_absolute_path = true; + $path = $this->working_directory . '/' . $path; + } + } + + if ($is_absolute_path) + { + if (defined('PHP_WINDOWS_VERSION_MAJOR')) + { + $path_prefix = $path[0] . ':'; + $path = substr($path, 2); + } + else + { + $path_prefix = ''; + } + } + + $resolved_path = $this->resolve_path($path, $path_prefix, $is_absolute_path); + if ($resolved_path === false) + { + return false; + } + + if (!@file_exists($resolved_path) || (!@is_dir($resolved_path . '/') && !is_file($resolved_path))) + { + return false; + } + + // Return OS specific directory separators + $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved_path); + + // Check for DIRECTORY_SEPARATOR at the end (and remove it!) + if (substr($resolved, -1) === DIRECTORY_SEPARATOR) + { + return substr($resolved, 0, -1); + } + + return $resolved; + } + + /** + * Convert file(s) to \Traversable object + * + * This is the same function as Symfony's toIterator, but that is private + * so we cannot use it. + * + * @param string|array|\Traversable $files filename/list of filenames + * @return \Traversable + */ + protected function to_iterator($files) + { + if (!$files instanceof \Traversable) + { + $files = new \ArrayObject(is_array($files) ? $files : array($files)); + } + + return $files; + } + + /** + * Try to resolve symlinks in path + * + * @param string $path The path to resolve + * @param string $prefix The path prefix (on windows the drive letter) + * @param bool $absolute Whether or not the path is absolute + * @param bool $return_array Whether or not to return path parts + * + * @return string|array|bool returns the resolved path or an array of parts of the path if $return_array is true + * or false if path cannot be resolved + */ + protected function resolve_path($path, $prefix = '', $absolute = false, $return_array = false) + { + if ($return_array) + { + $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); + } + + trim ($path, '/'); + $path_parts = explode('/', $path); + $resolved = array(); + $resolved_path = $prefix; + $file_found = false; + + foreach ($path_parts as $path_part) + { + if ($file_found) + { + return false; + } + + if (empty($path_part) || ($path_part === '.' && ($absolute || !empty($resolved)))) + { + continue; + } + else if ($absolute && $path_part === '..') + { + if (empty($resolved)) + { + // No directories above root + return false; + } + + array_pop($resolved); + $resolved_path = false; + } + else if ($path_part === '..' && !empty($resolved) && !in_array($resolved[sizeof($resolved) - 1], array('.', '..'))) + { + array_pop($resolved); + $resolved_path = false; + } + else + { + if ($resolved_path === false) + { + if (empty($resolved)) + { + $resolved_path = ($absolute) ? $prefix . '/' . $path_part : $path_part; + } + else + { + $tmp_array = $resolved; + if ($absolute) + { + array_unshift($tmp_array, $prefix); + } + + $resolved_path = implode('/', $tmp_array); + } + } + + $current_path = $resolved_path . '/' . $path_part; + + // Resolve symlinks + if (is_link($current_path)) + { + if (!function_exists('readlink')) + { + return false; + } + + $link = readlink($current_path); + + // Is link has an absolute path in it? + if ($this->is_absolute_path($link)) + { + if (defined('PHP_WINDOWS_VERSION_MAJOR')) + { + $prefix = $link[0] . ':'; + $link = substr($link, 2); + } + else + { + $prefix = ''; + } + + $resolved = $this->resolve_path($link, $prefix, true, true); + $absolute = true; + } + else + { + $resolved = $this->resolve_path($resolved_path . '/' . $link, $prefix, $absolute, true); + } + + if (!$resolved) + { + return false; + } + + $resolved_path = false; + } + else if (is_dir($current_path . '/')) + { + $resolved[] = $path_part; + $resolved_path = $current_path; + } + else if (is_file($current_path)) + { + $resolved[] = $path_part; + $resolved_path = $current_path; + $file_found = true; + } + else + { + return false; + } + } + } + + // If at the end of the path there were a .. or . + // we need to build the path again. + // Only doing this when a string is expected in return + if ($resolved_path === false && $return_array === false) + { + if (empty($resolved)) + { + $resolved_path = ($absolute) ? $prefix . '/' : './'; + } + else + { + $tmp_array = $resolved; + if ($absolute) + { + array_unshift($tmp_array, $prefix); + } + + $resolved_path = implode('/', $tmp_array); + } + } + + return ($return_array) ? $resolved : $resolved_path; + } +} diff --git a/phpBB/phpbb/filesystem/filesystem_interface.php b/phpBB/phpbb/filesystem/filesystem_interface.php new file mode 100644 index 0000000000..21ad8252f8 --- /dev/null +++ b/phpBB/phpbb/filesystem/filesystem_interface.php @@ -0,0 +1,284 @@ + + * @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\filesystem; + +/** + * Interface for phpBB's filesystem service + */ +interface filesystem_interface +{ + /** + * chmod all permissions flag + * + * @var int + */ + const CHMOD_ALL = 7; + + /** + * chmod read permissions flag + * + * @var int + */ + const CHMOD_READ = 4; + + /** + * chmod write permissions flag + * + * @var int + */ + const CHMOD_WRITE = 2; + + /** + * chmod execute permissions flag + * + * @var int + */ + const CHMOD_EXECUTE = 1; + + /** + * Change owner group of files/directories + * + * @param string|array|\Traversable $files The file(s)/directorie(s) to change group + * @param string $group The group that should own the files/directories + * @param bool $recursive If the group should be changed recursively + * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function chgrp($files, $group, $recursive = false); + + /** + * Global function for chmodding directories and files for internal use + * + * The function accepts filesystem_interface::CHMOD_ flags in the permission argument + * or the user can specify octal values (or any integer if it makes sense). All directories will have + * an execution bit appended, if the user group (owner, group or other) has any bit specified. + * + * @param string|array|\Traversable $file The file/directory to be chmodded + * @param int $perms Permissions to set + * @param bool $recursive If the permissions should be changed recursively + * @param bool $force_chmod_link Try to apply permissions to symlinks as well + * + * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function chmod($files, $perms = null, $recursive = false, $force_chmod_link = false); + + /** + * Change owner group of files/directories + * + * @param string|array|\Traversable $files The file(s)/directorie(s) to change group + * @param string $user The owner user name + * @param bool $recursive Whether change the owner recursively or not + * + * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function chown($files, $user, $recursive = false); + + /** + * Eliminates useless . and .. components from specified path. + * + * @param string $path Path to clean + * + * @return string Cleaned path + */ + public function clean_path($path); + + /** + * Copies a file. + * + * This method only copies the file if the origin file is newer than the target file. + * + * By default, if the target already exists, it is not overridden. + * + * @param string $origin_file The original filename + * @param string $target_file The target filename + * @param bool $override Whether to override an existing file or not + * + * @throws \phpbb\filesystem\exception\filesystem_exception When the file cannot be copied + */ + public function copy($origin_file, $target_file, $override = false); + + /** + * Atomically dumps content into a file. + * + * @param string $filename The file to be written to. + * @param string $content The data to write into the file. + * + * @throws \phpbb\filesystem\exception\filesystem_exception When the file cannot be written + */ + public function dump_file($filename, $content); + + /** + * Checks the existence of files or directories. + * + * @param string|array|\Traversable $files files/directories to check + * + * @return bool Returns true if all files/directories exist, false otherwise + */ + public function exists($files); + + /** + * Checks if a path is absolute or not + * + * @param string $path Path to check + * + * @return bool true if the path is absolute, false otherwise + */ + public function is_absolute_path($path); + + /** + * Checks if files/directories are readable + * + * @param string|array|\Traversable $files files/directories to check + * @param bool $recursive Whether or not directories should be checked recursively + * + * @return bool True when the files/directories are readable, otherwise false. + */ + public function is_readable($files, $recursive = false); + + /** + * Test if a file/directory is writable + * + * @param string|array|\Traversable $files files/directories to perform write test on + * @param bool $recursive Whether or not directories should be checked recursively + * + * @return bool True when the files/directories are writable, otherwise false. + */ + public function is_writable($files, $recursive = false); + + /** + * Given an existing path, convert it to a path relative to a given starting path + * + * @param string $end_path Absolute path of target + * @param string $start_path Absolute path where traversal begins + * + * @return string Path of target relative to starting path + */ + public function make_path_relative($end_path, $start_path); + + /** + * Mirrors a directory to another. + * + * @param string $origin_dir The origin directory + * @param string $target_dir The target directory + * @param \Traversable $iterator A Traversable instance + * @param array $options An array of boolean options + * Valid options are: + * - $options['override'] Whether to override an existing file on copy or not (see copy()) + * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink()) + * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) + * + * @throws \phpbb\filesystem\exception\filesystem_exception When the file cannot be copied. + * The filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function mirror($origin_dir, $target_dir, \Traversable $iterator = null, $options = array()); + + /** + * Creates a directory recursively. + * + * @param string|array|\Traversable $dirs The directory path + * @param int $mode The directory mode + * + * @throws \phpbb\filesystem\exception\filesystem_exception On any directory creation failure + * The filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function mkdir($dirs, $mode = 0777); + + /** + * Global function for chmodding directories and files for internal use + * + * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. + * The function determines owner and group from common.php file and sets the same to the provided file. + * The function uses bit fields to build the permissions. + * The function sets the appropiate execute bit on directories. + * + * Supported constants representing bit fields are: + * + * filesystem_interface::CHMOD_ALL - all permissions (7) + * filesystem_interface::CHMOD_READ - read permission (4) + * filesystem_interface::CHMOD_WRITE - write permission (2) + * filesystem_interface::CHMOD_EXECUTE - execute permission (1) + * + * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. + * + * @param string|array|\Traversable $file The file/directory to be chmodded + * @param int $perms Permissions to set + * @param bool $recursive If the permissions should be changed recursively + * @param bool $force_chmod_link Try to apply permissions to symlinks as well + * + * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function phpbb_chmod($file, $perms = null, $recursive = false, $force_chmod_link = false); + + /** + * A wrapper for PHP's realpath + * + * Try to resolve realpath when PHP's realpath is not available, or + * known to be buggy. + * + * @param string $path Path to resolve + * + * @return string Resolved path + */ + public function realpath($path); + + /** + * Removes files or directories. + * + * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove + * + * @throws \phpbb\filesystem\exception\filesystem_exception When removal fails. + * The filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function remove($files); + + /** + * Renames a file or a directory. + * + * @param string $origin The origin filename or directory + * @param string $target The new filename or directory + * @param bool $overwrite Whether to overwrite the target if it already exists + * + * @throws \phpbb\filesystem\exception\filesystem_exception When target file or directory already exists, + * or origin cannot be renamed. + */ + public function rename($origin, $target, $overwrite = false); + + /** + * Creates a symbolic link or copy a directory. + * + * @param string $origin_dir The origin directory path + * @param string $target_dir The symbolic link name + * @param bool $copy_on_windows Whether to copy files if on Windows + * + * @throws \phpbb\filesystem\exception\filesystem_exception When symlink fails + */ + public function symlink($origin_dir, $target_dir, $copy_on_windows = false); + + /** + * Sets access and modification time of file. + * + * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create + * @param int $time The touch time as a Unix timestamp + * @param int $access_time The access time as a Unix timestamp + * + * @throws \phpbb\filesystem\exception\filesystem_exception When touch fails + */ + public function touch($files, $time = null, $access_time = null); +} diff --git a/phpBB/phpbb/finder.php b/phpBB/phpbb/finder.php index 28f28825ba..58bc27084e 100644 --- a/phpBB/phpbb/finder.php +++ b/phpBB/phpbb/finder.php @@ -48,14 +48,14 @@ class finder /** * Creates a new finder instance with its dependencies * - * @param \phpbb\filesystem $filesystem Filesystem instance + * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem instance * @param string $phpbb_root_path Path to the phpbb root directory * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null * @param string $php_ext php file extension * @param string $cache_name The name of the cache variable, defaults to * _ext_finder */ - public function __construct(\phpbb\filesystem $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder') + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder') { $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php index 5400c1c5a6..7b0d6f0fba 100644 --- a/phpBB/phpbb/path_helper.php +++ b/phpBB/phpbb/path_helper.php @@ -21,7 +21,7 @@ class path_helper /** @var \phpbb\symfony_request */ protected $symfony_request; - /** @var \phpbb\filesystem */ + /** @var \phpbb\filesystem\filesystem_interface */ protected $filesystem; /** @var \phpbb\request\request_interface */ @@ -43,13 +43,13 @@ class path_helper * Constructor * * @param \phpbb\symfony_request $symfony_request - * @param \phpbb\filesystem $filesystem + * @param \phpbb\filesystem\filesystem_interface $filesystem * @param \phpbb\request\request_interface $request * @param string $phpbb_root_path Relative path to phpBB root * @param string $php_ext PHP file extension * @param mixed $adm_relative_path Relative path admin path to adm/ root */ - public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem $filesystem, \phpbb\request\request_interface $request, $phpbb_root_path, $php_ext, $adm_relative_path = null) + public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\request\request_interface $request, $phpbb_root_path, $php_ext, $adm_relative_path = null) { $this->symfony_request = $symfony_request; $this->filesystem = $filesystem; diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 4ccd3cf5e3..5313106b0a 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -85,17 +85,24 @@ class router implements RouterInterface */ protected $route_collection; + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + /** * Construct method * + * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem helper * @param manager $extension_manager Extension manager * @param string $phpbb_root_path phpBB root path * @param string $php_ext PHP file extension * @param string $environment Name of the current environment * @param array $routing_files Array of strings containing paths to YAML files holding route information */ - public function __construct(manager $extension_manager, $phpbb_root_path, $php_ext, $environment, $routing_files = array()) + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, manager $extension_manager, $phpbb_root_path, $php_ext, $environment, $routing_files = array()) { + $this->filesystem = $filesystem; $this->extension_manager = $extension_manager; $this->routing_files = $routing_files; $this->phpbb_root_path = $phpbb_root_path; @@ -148,7 +155,7 @@ class router implements RouterInterface $this->route_collection = new RouteCollection; foreach ($this->routing_files as $file_path) { - $loader = new YamlFileLoader(new FileLocator(phpbb_realpath($base_path))); + $loader = new YamlFileLoader(new FileLocator($this->filesystem->realpath($base_path))); $this->route_collection->addCollection($loader->load($file_path)); } } diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index d49f88b676..6154f384f3 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -92,8 +92,8 @@ class session } // current directory within the phpBB root (for example: adm) - $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($root_path))); - $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./'))); + $root_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath($root_path))); + $page_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath('./'))); $intersection = array_intersect_assoc($root_dirs, $page_dirs); $root_dirs = array_diff_assoc($root_dirs, $intersection); diff --git a/phpBB/phpbb/template/twig/loader.php b/phpBB/phpbb/template/twig/loader.php index 2f8ffaa776..df8183c019 100644 --- a/phpBB/phpbb/template/twig/loader.php +++ b/phpBB/phpbb/template/twig/loader.php @@ -20,6 +20,24 @@ class loader extends \Twig_Loader_Filesystem { protected $safe_directories = array(); + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** + * Constructor + * + * @param \phpbb\filesystem\filesystem_interface $filesystem + * @param string|array $paths + */ + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $paths = array()) + { + $this->filesystem = $filesystem; + + parent::__construct($paths); + } + /** * Set safe directories * @@ -49,7 +67,7 @@ class loader extends \Twig_Loader_Filesystem */ public function addSafeDirectory($directory) { - $directory = phpbb_realpath($directory); + $directory = $this->filesystem->realpath($directory); if ($directory !== false) { @@ -118,7 +136,7 @@ class loader extends \Twig_Loader_Filesystem // can now check if we're within a "safe" directory // Find the real path of the directory the file is in - $directory = phpbb_realpath(dirname($file)); + $directory = $this->filesystem->realpath(dirname($file)); if ($directory === false) { diff --git a/phpBB/phpbb/viewonline_helper.php b/phpBB/phpbb/viewonline_helper.php index b722f9d911..89915f2228 100644 --- a/phpBB/phpbb/viewonline_helper.php +++ b/phpBB/phpbb/viewonline_helper.php @@ -18,13 +18,13 @@ namespace phpbb; */ class viewonline_helper { - /** @var \phpbb\filesystem */ + /** @var \phpbb\filesystem\filesystem_interface */ protected $filesystem; /** - * @param \phpbb\filesystem $filesystem + * @param \phpbb\filesystem\filesystem_interface $filesystem phpBB's filesystem service */ - public function __construct(\phpbb\filesystem $filesystem) + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem) { $this->filesystem = $filesystem; } diff --git a/tests/avatar/manager_test.php b/tests/avatar/manager_test.php index a109a7b5de..4befbfc1fc 100644 --- a/tests/avatar/manager_test.php +++ b/tests/avatar/manager_test.php @@ -35,6 +35,8 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case ->method('get') ->will($this->returnArgument(0)); + $filesystem = new \phpbb\filesystem\filesystem(); + // Prepare dependencies for avatar manager and driver $this->config = new \phpbb\config\config(array()); $cache = $this->getMock('\phpbb\cache\driver\driver_interface'); @@ -42,7 +44,7 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + $filesystem, $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -76,7 +78,7 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case } else { - $cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $guesser, $cache)); + $cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $filesystem, $path_helper, $guesser, $cache)); } $cur_avatar->expects($this->any()) ->method('get_name') diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index 3f98d51f16..91b0cda68d 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -69,7 +69,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case $this->symfony_request = new \phpbb\symfony_request( $this->request ); - $this->filesystem = new \phpbb\filesystem(); + $this->filesystem = new \phpbb\filesystem\filesystem(); $this->phpbb_path_helper = new \phpbb\path_helper( $this->symfony_request, $this->filesystem, @@ -84,7 +84,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case $container = new phpbb_mock_container_builder(); $cache_path = $phpbb_root_path . 'cache/twig'; $context = new \phpbb\template\context(); - $loader = new \phpbb\template\twig\loader(''); + $loader = new \phpbb\template\twig\loader($this->filesystem, ''); $twig = new \phpbb\template\twig\environment( $this->config, $this->phpbb_path_helper, @@ -113,7 +113,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case ) ); - $this->router = new phpbb_mock_router($this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); + $this->router = new phpbb_mock_router($this->filesystem, $this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); $this->router->find_routing_files($this->extension_manager->all_enabled(false)); $this->router->find(dirname(__FILE__) . '/'); // Set correct current phpBB root path diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php index 86615fe4dc..a837e25f66 100644 --- a/tests/controller/controller_test.php +++ b/tests/controller/controller_test.php @@ -40,7 +40,7 @@ class phpbb_controller_controller_test extends phpbb_test_case public function test_router_find_files() { - $router = new \phpbb\routing\router($this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); + $router = new \phpbb\routing\router(new \phpbb\filesystem\filesystem(), $this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); $router->find_routing_files($this->extension_manager->all_enabled(false)); $routes = $router->find(__DIR__)->get_routes(); diff --git a/tests/dbal/connect_test.php b/tests/dbal/connect_test.php index 1ae34bd2b6..edf57189cb 100644 --- a/tests/dbal/connect_test.php +++ b/tests/dbal/connect_test.php @@ -22,7 +22,9 @@ class phpbb_dbal_connect_test extends phpbb_database_test_case public function test_failing_connect() { - global $phpbb_root_path, $phpEx; + global $phpbb_root_path, $phpEx, $phpbb_filesystem; + + $phpbb_filesystem = new phpbb\filesystem\filesystem(); $config = $this->get_database_config(); diff --git a/tests/dbal/migrator_test.php b/tests/dbal/migrator_test.php index 6416a2fcf7..d550ca55a2 100644 --- a/tests/dbal/migrator_test.php +++ b/tests/dbal/migrator_test.php @@ -69,7 +69,7 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case $container, $this->db, $this->config, - new phpbb\filesystem(), + new phpbb\filesystem\filesystem(), $user, 'phpbb_ext', dirname(__FILE__) . '/../../phpBB/', diff --git a/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php b/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php index 8342625687..8e5ed6c52c 100644 --- a/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php +++ b/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php @@ -25,7 +25,8 @@ class extension extends extension_base { protected function load_services(ContainerBuilder $container) { - $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->ext_path))); + $filesystem = new \phpbb\filesystem\filesystem(); + $loader = new YamlFileLoader($container, new FileLocator($filesystem->realpath($this->ext_path))); $loader->load('environment.yml'); } } diff --git a/tests/error_collector_test.php b/tests/error_collector_test.php index b92c4fa6bb..ddbe2e3af1 100644 --- a/tests/error_collector_test.php +++ b/tests/error_collector_test.php @@ -15,6 +15,15 @@ require_once dirname(__FILE__) . '/../phpBB/includes/functions.php'; class phpbb_error_collector_test extends phpbb_test_case { + public function setUp() + { + parent::setUp(); + + global $phpbb_filesystem; + + $phpbb_filesystem = new \phpbb\filesystem\filesystem(); + } + public function test_collection() { $collector = new \phpbb\error_collector(E_ALL | E_STRICT); // php set_error_handler() default diff --git a/tests/extension/finder_test.php b/tests/extension/finder_test.php index 2116cc057b..463b69e9a9 100644 --- a/tests/extension/finder_test.php +++ b/tests/extension/finder_test.php @@ -244,7 +244,7 @@ class phpbb_extension_finder_test extends phpbb_test_case public function test_get_classes_create_cache() { $cache = new phpbb_mock_cache; - $finder = new \phpbb\finder(new \phpbb\filesystem(), dirname(__FILE__) . '/', $cache, 'php', '_custom_cache_name'); + $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), dirname(__FILE__) . '/', $cache, 'php', '_custom_cache_name'); $finder->set_extensions(array_keys($this->extension_manager->all_enabled())); $files = $finder->suffix('_class.php')->get_files(); @@ -284,7 +284,7 @@ class phpbb_extension_finder_test extends phpbb_test_case ); $finder = new \phpbb\finder( - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), dirname(__FILE__) . '/', new phpbb_mock_cache(array( '_ext_finder' => array( diff --git a/tests/extension/manager_test.php b/tests/extension/manager_test.php index 0126216701..b76203b32a 100644 --- a/tests/extension/manager_test.php +++ b/tests/extension/manager_test.php @@ -177,7 +177,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case $container, $db, $config, - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $user, 'phpbb_ext', dirname(__FILE__) . '/', diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index 8514ed3dbd..db573ae0c3 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -51,12 +51,12 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $container = new phpbb_mock_container_builder(); $cache_path = $this->phpbb_root_path . 'cache/twig'; $context = new \phpbb\template\context(); - $loader = new \phpbb\template\twig\loader(''); + $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $phpbb_path_helper =new \phpbb\path_helper( new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $this->phpbb_root_path, $this->phpEx @@ -98,7 +98,7 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $container, $this->db, $this->config, - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->user, 'phpbb_ext', $this->phpbb_root_path, diff --git a/tests/filesystem/clean_path_test.php b/tests/filesystem/clean_path_test.php index c585b17155..d2dec424b4 100644 --- a/tests/filesystem/clean_path_test.php +++ b/tests/filesystem/clean_path_test.php @@ -18,7 +18,7 @@ class phpbb_filesystem_clean_path_test extends phpbb_test_case public function setUp() { parent::setUp(); - $this->filesystem = new \phpbb\filesystem(); + $this->filesystem = new \phpbb\filesystem\filesystem(); } public function clean_path_data() diff --git a/tests/functions/is_absolute_test.php b/tests/filesystem/is_absolute_test.php similarity index 60% rename from tests/functions/is_absolute_test.php rename to tests/filesystem/is_absolute_test.php index afa4b9b59f..7a50989b74 100644 --- a/tests/functions/is_absolute_test.php +++ b/tests/filesystem/is_absolute_test.php @@ -1,20 +1,28 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; - -class phpbb_functions_is_absolute_test extends phpbb_test_case +class phpbb_filesystem_is_absolute_test extends phpbb_test_case { + /** @var \phpbb\filesystem\filesystem_interface */ + protected $filesystem; + + public function setUp() + { + parent::setUp(); + + $this->filesystem = new \phpbb\filesystem\filesystem(); + } + static public function is_absolute_data() { return array( @@ -51,10 +59,10 @@ class phpbb_functions_is_absolute_test extends phpbb_test_case } /** - * @dataProvider is_absolute_data - */ + * @dataProvider is_absolute_data + */ public function test_is_absolute($path, $expected) { - $this->assertEquals($expected, phpbb_is_absolute($path)); + $this->assertEquals($expected, $this->filesystem->is_absolute_path($path)); } } diff --git a/tests/filesystem/realpath_test.php b/tests/filesystem/realpath_test.php new file mode 100644 index 0000000000..d994935f94 --- /dev/null +++ b/tests/filesystem/realpath_test.php @@ -0,0 +1,90 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_filesystem_realpath_test extends phpbb_test_case +{ + static protected $filesystem_own_realpath; + + /** @var \phpbb\filesystem\filesystem_interface */ + protected $filesystem; + + static public function setUpBeforeClass() + { + parent::setUpBeforeClass(); + + $reflection_class = new ReflectionClass('\phpbb\filesystem\filesystem'); + self::$filesystem_own_realpath = $reflection_class->getMethod('phpbb_own_realpath'); + self::$filesystem_own_realpath->setAccessible(true); + } + + public function setUp() + { + parent::setUp(); + + $this->filesystem = new \phpbb\filesystem\filesystem(); + } + + public function realpath_resolve_absolute_without_symlinks_data() + { + return array( + // Constant data + array(__DIR__, __DIR__), + array(__DIR__ . '/../filesystem/../filesystem', __DIR__), + array(__DIR__ . '/././', __DIR__), + array(__DIR__ . '/non_existent', false), + + array(__FILE__, __FILE__), + array(__FILE__ . '../', false), + ); + } + + public function realpath_resolve_relative_without_symlinks_data() + { + if (!function_exists('getcwd')) + { + return array(); + } + + $filesystem = new \phpbb\filesystem\filesystem(); + $relative_path = $filesystem->make_path_relative(__DIR__, getcwd()); + + return array( + array($relative_path, __DIR__), + array($relative_path . '../filesystem/../filesystem', __DIR__), + array($relative_path . '././', __DIR__), + + array($relative_path . 'realpath_test.php', __FILE__), + ); + } + + /** + * @dataProvider realpath_resolve_absolute_without_symlinks_data + */ + public function test_realpath_absolute_without_links($path, $expected) + { + $this->assertEquals($expected, self::$filesystem_own_realpath->invoke($this->filesystem, $path)); + } + + /** + * @dataProvider realpath_resolve_relative_without_symlinks_data + */ + public function test_realpath_relative_without_links($path, $expected) + { + if (!function_exists('getcwd')) + { + $this->markTestSkipped('phpbb_own_realpath() cannot be tested with relative paths: getcwd is not available.'); + } + + $this->assertEquals($expected, self::$filesystem_own_realpath->invoke($this->filesystem, $path)); + } +} diff --git a/tests/functional/fileupload_remote_test.php b/tests/functional/fileupload_remote_test.php index 6ece150b23..4aa1a83b30 100644 --- a/tests/functional/fileupload_remote_test.php +++ b/tests/functional/fileupload_remote_test.php @@ -18,6 +18,8 @@ require_once __DIR__ . '/../../phpBB/includes/functions_upload.php'; */ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case { + protected $filesystem; + public function setUp() { parent::setUp(); @@ -38,6 +40,7 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case $user = new phpbb_mock_user(); $user->lang = new phpbb_mock_lang(); + $this->filesystem = new \phpbb\filesystem\filesystem(); } public function tearDown() @@ -49,21 +52,21 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case public function test_invalid_extension() { - $upload = new fileupload('', array('jpg'), 100); + $upload = new fileupload($this->filesystem, '', array('jpg'), 100); $file = $upload->remote_upload(self::$root_url . 'develop/blank.gif'); $this->assertEquals('URL_INVALID', $file->error[0]); } public function test_empty_file() { - $upload = new fileupload('', array('jpg'), 100); + $upload = new fileupload($this->filesystem, '', array('jpg'), 100); $file = $upload->remote_upload(self::$root_url . 'develop/blank.jpg'); $this->assertEquals('EMPTY_REMOTE_DATA', $file->error[0]); } public function test_successful_upload() { - $upload = new fileupload('', array('gif'), 1000); + $upload = new fileupload($this->filesystem, '', array('gif'), 1000); $file = $upload->remote_upload(self::$root_url . 'styles/prosilver/theme/images/forum_read.gif'); $this->assertEquals(0, sizeof($file->error)); $this->assertTrue(file_exists($file->filename)); @@ -71,7 +74,7 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case public function test_too_large() { - $upload = new fileupload('', array('gif'), 100); + $upload = new fileupload($this->filesystem, '', array('gif'), 100); $file = $upload->remote_upload(self::$root_url . 'styles/prosilver/theme/images/forum_read.gif'); $this->assertEquals(1, sizeof($file->error)); $this->assertEquals('WRONG_FILESIZE', $file->error[0]); diff --git a/tests/functions/build_url_test.php b/tests/functions/build_url_test.php index a59b94c744..3e19b51f02 100644 --- a/tests/functions/build_url_test.php +++ b/tests/functions/build_url_test.php @@ -29,7 +29,7 @@ class phpbb_build_url_test extends phpbb_test_case new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $phpbb_root_path, 'php' diff --git a/tests/mock/controller_helper.php b/tests/mock/controller_helper.php index 7e4a808906..1d9f5dc5bf 100644 --- a/tests/mock/controller_helper.php +++ b/tests/mock/controller_helper.php @@ -13,7 +13,7 @@ class phpbb_mock_controller_helper extends \phpbb\controller\helper { - public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext, $phpbb_root_path_ext) + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext, $phpbb_root_path_ext) { $this->template = $template; $this->user = $user; diff --git a/tests/mock/extension_manager.php b/tests/mock/extension_manager.php index 3b759fbbc2..2ce61c5149 100644 --- a/tests/mock/extension_manager.php +++ b/tests/mock/extension_manager.php @@ -18,7 +18,7 @@ class phpbb_mock_extension_manager extends \phpbb\extension\manager $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = 'php'; $this->extensions = $extensions; - $this->filesystem = new \phpbb\filesystem(); + $this->filesystem = new \phpbb\filesystem\filesystem(); $this->container = $container; } } diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index 6679d48c01..c705e67135 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -34,11 +34,11 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case ->method('lang') ->will($this->returnCallback(array($this, 'return_callback_implode'))); - $filesystem = new \phpbb\filesystem(); + $filesystem = new \phpbb\filesystem\filesystem(); $manager = new phpbb_mock_extension_manager(dirname(__FILE__) . '/', array()); $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $router = new phpbb_mock_router($manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); + $router = new phpbb_mock_router($filesystem, $manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); $router->find_routing_files($manager->all_enabled(false)); $router->find(dirname(__FILE__) . '/'); diff --git a/tests/path_helper/path_helper_test.php b/tests/path_helper/path_helper_test.php index 73f0e6bafc..007441bc92 100644 --- a/tests/path_helper/path_helper_test.php +++ b/tests/path_helper/path_helper_test.php @@ -21,14 +21,14 @@ class phpbb_path_helper_test extends phpbb_test_case { parent::setUp(); - $filesystem = new \phpbb\filesystem(); + $filesystem = new \phpbb\filesystem\filesystem(); $this->set_phpbb_root_path($filesystem); $this->path_helper = new \phpbb\path_helper( new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $this->phpbb_root_path, 'php' @@ -56,7 +56,7 @@ class phpbb_path_helper_test extends phpbb_test_case public function basic_update_web_root_path_data() { - $filesystem = new \phpbb\filesystem(); + $filesystem = new \phpbb\filesystem\filesystem(); $this->set_phpbb_root_path($filesystem); return array( @@ -90,7 +90,7 @@ class phpbb_path_helper_test extends phpbb_test_case public function update_web_root_path_data() { - $this->set_phpbb_root_path(new \phpbb\filesystem()); + $this->set_phpbb_root_path(new \phpbb\filesystem\filesystem()); return array( array( @@ -158,7 +158,7 @@ class phpbb_path_helper_test extends phpbb_test_case $path_helper = new \phpbb\path_helper( $symfony_request, - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $this->phpbb_root_path, 'php' diff --git a/tests/security/base.php b/tests/security/base.php index 330408b448..5888a2bf2a 100644 --- a/tests/security/base.php +++ b/tests/security/base.php @@ -46,7 +46,7 @@ abstract class phpbb_security_test_base extends phpbb_test_case $request = new phpbb_mock_request(array(), array(), array(), $this->server); $symfony_request = new \phpbb\symfony_request($request); - $phpbb_filesystem = new \phpbb\filesystem(); + $phpbb_filesystem = new \phpbb\filesystem\filesystem(); // Set no user and trick a bit to circumvent errors $user = new \phpbb\user('\phpbb\datetime'); diff --git a/tests/security/redirect_test.php b/tests/security/redirect_test.php index 21fb103ed1..3c67a1e98a 100644 --- a/tests/security/redirect_test.php +++ b/tests/security/redirect_test.php @@ -62,7 +62,7 @@ class phpbb_security_redirect_test extends phpbb_security_test_base new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $this->phpbb_root_path, 'php' diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php index 561b7faf49..04da5f08b9 100644 --- a/tests/session/check_ban_test.php +++ b/tests/session/check_ban_test.php @@ -42,7 +42,10 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case parent::setUp(); // Get session here so that config is mocked correctly $this->session = $this->session_factory->get_session($this->db); - global $cache, $config, $phpbb_root_path, $phpEx; + global $cache, $config, $phpbb_root_path, $phpEx, $phpbb_filesystem; + + $phpbb_filesystem = new \phpbb\filesystem\filesystem(); + $this->backup_cache = $cache; // Change the global cache object for this test because // the mock cache object does not hit the database as is needed diff --git a/tests/session/extract_page_test.php b/tests/session/extract_page_test.php index f0d1cdb60e..96445ef9b3 100644 --- a/tests/session/extract_page_test.php +++ b/tests/session/extract_page_test.php @@ -145,7 +145,7 @@ class phpbb_session_extract_page_test extends phpbb_session_test_case { global $symfony_request, $request, $phpbb_filesystem; - $phpbb_filesystem = new \phpbb\filesystem(); + $phpbb_filesystem = new \phpbb\filesystem\filesystem(); $server['HTTP_HOST'] = 'localhost'; $server['SERVER_NAME'] = 'localhost'; diff --git a/tests/template/includephp_test.php b/tests/template/includephp_test.php index fdddbef4f2..722e10e42d 100644 --- a/tests/template/includephp_test.php +++ b/tests/template/includephp_test.php @@ -39,8 +39,9 @@ class phpbb_template_includephp_test extends phpbb_template_template_test_case { global $phpbb_root_path; + $filesystem = new \phpbb\filesystem\filesystem(); $path_to_php = str_replace('\\', '/', dirname(__FILE__)) . '/templates/_dummy_include.php.inc'; - $this->assertTrue(phpbb_is_absolute($path_to_php)); + $this->assertTrue($filesystem->is_absolute_path($path_to_php)); $template_text = "Path is absolute.\n"; $cache_dir = $phpbb_root_path . 'cache/'; diff --git a/tests/template/template_allfolder_test.php b/tests/template/template_allfolder_test.php index e87688a57c..f739a78d84 100644 --- a/tests/template/template_allfolder_test.php +++ b/tests/template/template_allfolder_test.php @@ -34,7 +34,7 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -54,7 +54,7 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case $container = new phpbb_mock_container_builder(); $cache_path = $phpbb_root_path . 'cache/twig'; $context = new \phpbb\template\context(); - $loader = new \phpbb\template\twig\loader(''); + $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, $path_helper, diff --git a/tests/template/template_events_test.php b/tests/template/template_events_test.php index e8ffea8d11..6d1b7253e3 100644 --- a/tests/template/template_events_test.php +++ b/tests/template/template_events_test.php @@ -142,7 +142,7 @@ Zeta test event in all', new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -151,7 +151,7 @@ Zeta test event in all', $container = new phpbb_mock_container_builder(); $cache_path = $phpbb_root_path . 'cache/twig'; $context = new \phpbb\template\context(); - $loader = new \phpbb\template\twig\loader(''); + $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, $path_helper, diff --git a/tests/template/template_includecss_test.php b/tests/template/template_includecss_test.php index 96980e17c6..7a73d1f888 100644 --- a/tests/template/template_includecss_test.php +++ b/tests/template/template_includecss_test.php @@ -32,7 +32,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -43,7 +43,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te $container = new phpbb_mock_container_builder(); $cache_path = $phpbb_root_path . 'cache/twig'; $context = new \phpbb\template\context(); - $loader = new \phpbb\template\twig\loader(''); + $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, $this->phpbb_path_helper, diff --git a/tests/template/template_test_case.php b/tests/template/template_test_case.php index f9ea8cfaba..29ff669efc 100644 --- a/tests/template/template_test_case.php +++ b/tests/template/template_test_case.php @@ -71,7 +71,7 @@ class phpbb_template_template_test_case extends phpbb_test_case new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -82,7 +82,7 @@ class phpbb_template_template_test_case extends phpbb_test_case $container = new phpbb_mock_container_builder(); $cache_path = $phpbb_root_path . 'cache/twig'; $context = new \phpbb\template\context(); - $loader = new \phpbb\template\twig\loader(''); + $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, $path_helper, @@ -108,6 +108,10 @@ class phpbb_template_template_test_case extends phpbb_test_case $this->setup_engine(); $this->template->clear_cache(); + + global $phpbb_filesystem; + + $phpbb_filesystem = new \phpbb\filesystem\filesystem(); } protected function tearDown() diff --git a/tests/template/template_test_case_with_tree.php b/tests/template/template_test_case_with_tree.php index c634e2051a..eab83f379a 100644 --- a/tests/template/template_test_case_with_tree.php +++ b/tests/template/template_test_case_with_tree.php @@ -26,7 +26,7 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem(), + new \phpbb\filesystem\filesystem(), $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -38,7 +38,7 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat $container = new phpbb_mock_container_builder(); $cache_path = $phpbb_root_path . 'cache/twig'; $context = new \phpbb\template\context(); - $loader = new \phpbb\template\twig\loader(''); + $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, $this->phpbb_path_helper, diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index 903158d3c6..4d0460ebeb 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -58,7 +58,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test $setup_extensions = static::setup_extensions(); - $finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path, null, $phpEx); + $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx); $finder->core_path('phpbb/db/migration/data/'); if (!empty($setup_extensions)) { diff --git a/tests/test_framework/phpbb_database_test_connection_manager.php b/tests/test_framework/phpbb_database_test_connection_manager.php index 4f38ccc0d8..5136af5ad1 100644 --- a/tests/test_framework/phpbb_database_test_connection_manager.php +++ b/tests/test_framework/phpbb_database_test_connection_manager.php @@ -365,7 +365,7 @@ class phpbb_database_test_connection_manager { global $phpbb_root_path, $phpEx, $table_prefix; - $finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path, null, $phpEx); + $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx); $classes = $finder->core_path('phpbb/db/migration/data/') ->get_classes(); diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 495413593b..daa570caf6 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -254,7 +254,7 @@ class phpbb_functional_test_case extends phpbb_test_case $container, $db, $config, - new phpbb\filesystem(), + new phpbb\filesystem\filesystem(), $user, self::$config['table_prefix'] . 'ext', dirname(__FILE__) . '/', diff --git a/tests/test_framework/phpbb_session_test_case.php b/tests/test_framework/phpbb_session_test_case.php index 1bf0277fe0..1c1930e88d 100644 --- a/tests/test_framework/phpbb_session_test_case.php +++ b/tests/test_framework/phpbb_session_test_case.php @@ -34,7 +34,7 @@ abstract class phpbb_session_test_case extends phpbb_database_test_case $symfony_request = new \phpbb\symfony_request( new phpbb_mock_request() ); - $phpbb_filesystem = new \phpbb\filesystem(); + $phpbb_filesystem = new \phpbb\filesystem\filesystem(); $phpbb_path_helper = new \phpbb\path_helper( $symfony_request, $phpbb_filesystem, diff --git a/tests/upload/filespec_test.php b/tests/upload/filespec_test.php index 05547dcd00..8fbb437ef0 100644 --- a/tests/upload/filespec_test.php +++ b/tests/upload/filespec_test.php @@ -23,6 +23,7 @@ class phpbb_filespec_test extends phpbb_test_case const UPLOAD_MAX_FILESIZE = 1000; private $config; + private $filesystem; public $path; protected function setUp() @@ -30,7 +31,7 @@ class phpbb_filespec_test extends phpbb_test_case // Global $config required by unique_id // Global $user required by filespec::additional_checks and // filespec::move_file - global $config, $user; + global $config, $user, $phpbb_filesystem; if (!is_array($config)) { @@ -75,6 +76,8 @@ class phpbb_filespec_test extends phpbb_test_case $guessers[2]->set_priority(-2); $guessers[3]->set_priority(-2); $this->mimetype_guesser = new \phpbb\mimetype\guesser($guessers); + + $this->filesystem = $phpbb_filesystem = new \phpbb\filesystem\filesystem(); } private function get_filespec($override = array()) @@ -88,7 +91,7 @@ class phpbb_filespec_test extends phpbb_test_case 'error' => '', ); - return new filespec(array_merge($upload_ary, $override), null, $this->mimetype_guesser); + return new filespec(array_merge($upload_ary, $override), null, $this->filesystem, $this->mimetype_guesser); } protected function tearDown() @@ -198,7 +201,7 @@ class phpbb_filespec_test extends phpbb_test_case $filespec = $this->get_filespec(); $filespec->clean_filename('unique', self::PREFIX); $name = $filespec->realname; - + $this->assertEquals(strlen($name), 32 + strlen(self::PREFIX)); $this->assertRegExp('#^[A-Za-z0-9]+$#', substr($name, strlen(self::PREFIX))); $this->assertFalse(isset($filenames[$name])); diff --git a/tests/upload/fileupload_test.php b/tests/upload/fileupload_test.php index fcfb84125d..9de384b64f 100644 --- a/tests/upload/fileupload_test.php +++ b/tests/upload/fileupload_test.php @@ -20,12 +20,14 @@ class phpbb_fileupload_test extends phpbb_test_case { private $path; + private $filesystem; + protected function setUp() { // Global $config required by unique_id // Global $user required by several functions dealing with translations // Global $request required by form_upload, local_upload and is_valid - global $config, $user, $request; + global $config, $user, $request, $phpbb_filesystem; if (!is_array($config)) { @@ -40,6 +42,8 @@ class phpbb_fileupload_test extends phpbb_test_case $request = new phpbb_mock_request(); + $this->filesystem = $phpbb_filesystem = new \phpbb\filesystem\filesystem(); + $this->path = __DIR__ . '/fixture/'; } @@ -65,7 +69,7 @@ class phpbb_fileupload_test extends phpbb_test_case public function test_common_checks_invalid_extension() { - $upload = new fileupload('', array('png'), 100); + $upload = new fileupload($this->filesystem, '', array('png'), 100); $file = $this->gen_valid_filespec(); $upload->common_checks($file); $this->assertEquals('DISALLOWED_EXTENSION', $file->error[0]); @@ -73,7 +77,7 @@ class phpbb_fileupload_test extends phpbb_test_case public function test_common_checks_invalid_filename() { - $upload = new fileupload('', array('jpg'), 100); + $upload = new fileupload($this->filesystem, '', array('jpg'), 100); $file = $this->gen_valid_filespec(); $file->realname = 'invalid?'; $upload->common_checks($file); @@ -82,7 +86,7 @@ class phpbb_fileupload_test extends phpbb_test_case public function test_common_checks_too_large() { - $upload = new fileupload('', array('jpg'), 100); + $upload = new fileupload($this->filesystem, '', array('jpg'), 100); $file = $this->gen_valid_filespec(); $file->filesize = 1000; $upload->common_checks($file); @@ -91,7 +95,7 @@ class phpbb_fileupload_test extends phpbb_test_case public function test_common_checks_valid_file() { - $upload = new fileupload('', array('jpg'), 1000); + $upload = new fileupload($this->filesystem, '', array('jpg'), 1000); $file = $this->gen_valid_filespec(); $upload->common_checks($file); $this->assertEquals(0, sizeof($file->error)); @@ -99,7 +103,7 @@ class phpbb_fileupload_test extends phpbb_test_case public function test_local_upload() { - $upload = new fileupload('', array('jpg'), 1000); + $upload = new fileupload($this->filesystem, '', array('jpg'), 1000); copy($this->path . 'jpg', $this->path . 'jpg.jpg'); $file = $upload->local_upload($this->path . 'jpg.jpg'); @@ -109,7 +113,7 @@ class phpbb_fileupload_test extends phpbb_test_case public function test_move_existent_file() { - $upload = new fileupload('', array('jpg'), 1000); + $upload = new fileupload($this->filesystem, '', array('jpg'), 1000); copy($this->path . 'jpg', $this->path . 'jpg.jpg'); $file = $upload->local_upload($this->path . 'jpg.jpg'); @@ -121,7 +125,7 @@ class phpbb_fileupload_test extends phpbb_test_case public function test_move_existent_file_overwrite() { - $upload = new fileupload('', array('jpg'), 1000); + $upload = new fileupload($this->filesystem, '', array('jpg'), 1000); copy($this->path . 'jpg', $this->path . 'jpg.jpg'); copy($this->path . 'jpg', $this->path . 'copies/jpg.jpg'); @@ -134,7 +138,7 @@ class phpbb_fileupload_test extends phpbb_test_case public function test_valid_dimensions() { - $upload = new fileupload('', false, false, 1, 1, 100, 100); + $upload = new fileupload($this->filesystem, '', false, false, 1, 1, 100, 100); $file1 = $this->gen_valid_filespec(); $file2 = $this->gen_valid_filespec(); diff --git a/tests/viewonline/helper_test.php b/tests/viewonline/helper_test.php index bbbed59de7..6540d33287 100644 --- a/tests/viewonline/helper_test.php +++ b/tests/viewonline/helper_test.php @@ -17,7 +17,7 @@ class phpbb_viewonline_helper_test extends phpbb_test_case { parent::setUp(); - $this->viewonline_helper = new \phpbb\viewonline_helper(new \phpbb\filesystem()); + $this->viewonline_helper = new \phpbb\viewonline_helper(new \phpbb\filesystem\filesystem()); } public function session_pages_data() From f23fe9e69d5a49d983af1a06297c162bb2b97f05 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Thu, 16 Apr 2015 23:28:52 +0200 Subject: [PATCH 0227/1676] [ticket/13766] Add style_parent_id in textformater's data_access::get_styles() PHPBB3-13766 --- phpBB/phpbb/textformatter/data_access.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/data_access.php b/phpBB/phpbb/textformatter/data_access.php index 8938d66935..2103bf8e60 100644 --- a/phpBB/phpbb/textformatter/data_access.php +++ b/phpBB/phpbb/textformatter/data_access.php @@ -115,7 +115,7 @@ class data_access */ protected function get_styles() { - $sql = 'SELECT style_id, style_path, bbcode_bitfield FROM ' . $this->styles_table; + $sql = 'SELECT style_id, style_path, style_parent_id, bbcode_bitfield FROM ' . $this->styles_table; $result = $this->db->sql_query($sql); $rows = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); From 14333f6ebc52661e6dae1c5575e6f5a94b107f6d Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 19 Apr 2015 13:54:21 +0200 Subject: [PATCH 0228/1676] [ticket/13767] Remove vendor/s9e/text-formatter/.git during build PHPBB3-13767 --- build/build.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/build.xml b/build/build.xml index 9d80bba2bf..2e65539035 100644 --- a/build/build.xml +++ b/build/build.xml @@ -319,6 +319,8 @@ + + From 9939ced81ffa4b0ab0fdb61c8d25a5c64e5611b2 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 19 Apr 2015 17:33:06 +0200 Subject: [PATCH 0229/1676] [ticket/13768] Update to symfony 2.8.*@dev PHPBB3-13768 --- phpBB/composer.json | 40 +++--- phpBB/composer.lock | 290 +++++++++++++++++++++++++------------------- 2 files changed, 185 insertions(+), 145 deletions(-) diff --git a/phpBB/composer.json b/phpBB/composer.json index a11bcad391..46c0e9b361 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -25,36 +25,36 @@ "phpbb/phpbb-core": "self.version" }, "require": { - "php": ">=5.3.9", "lusitanian/oauth": "0.2.*", "patchwork/utf8": "1.1.*", + "php": ">=5.3.9", "s9e/text-formatter": "dev-release/php5.3", - "symfony/config": "2.7.*@dev", - "symfony/console": "2.7.*@dev", - "symfony/dependency-injection": "2.7.*@dev", - "symfony/event-dispatcher": "2.7.*@dev", - "symfony/filesystem": "2.7.*@dev", - "symfony/http-kernel": "2.7.*@dev", - "symfony/routing": "2.7.*@dev", - "symfony/security-core": "2.7.*@dev", - "symfony/security-csrf": "2.7.*@dev", - "symfony/twig-bridge": "2.7.*@dev", - "symfony/yaml": "2.7.*@dev", + "symfony/config": "2.8.*@dev", + "symfony/console": "2.8.*@dev", + "symfony/dependency-injection": "2.8.*@dev", + "symfony/event-dispatcher": "2.8.*@dev", + "symfony/filesystem": "2.8.*@dev", + "symfony/http-kernel": "2.8.*@dev", + "symfony/routing": "2.8.*@dev", + "symfony/security-core": "2.8.*@dev", + "symfony/security-csrf": "2.8.*@dev", + "symfony/twig-bridge": "2.8.*@dev", + "symfony/yaml": "2.8.*@dev", "twig/twig": "1.*" }, "require-dev": { "fabpot/goutte": "1.0.*", + "phing/phing": "2.4.*", "phpunit/dbunit": "1.3.*", "phpunit/phpunit": "4.1.*", - "phing/phing": "2.4.*", "sami/sami": "1.*", "squizlabs/php_codesniffer": "1.*", - "symfony/browser-kit": "2.7.*@dev", - "symfony/css-selector": "2.7.*@dev", - "symfony/debug": "2.7.*@dev", - "symfony/dom-crawler": "2.7.*@dev", - "symfony/finder": "2.7.*@dev", - "symfony/http-foundation": "2.7.*@dev", - "symfony/process": "2.7.*@dev" + "symfony/browser-kit": "2.8.*@dev", + "symfony/css-selector": "2.8.*@dev", + "symfony/debug": "2.8.*@dev", + "symfony/dom-crawler": "2.8.*@dev", + "symfony/finder": "2.8.*@dev", + "symfony/http-foundation": "2.8.*@dev", + "symfony/process": "2.8.*@dev" } } diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 8a634a1ffd..8365acf5f3 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "25df57c9c90534dcc86d31175b248719", + "hash": "91cc998d47b703a7bc4f726217d7a3a9", "packages": [ { "name": "lusitanian/oauth", @@ -145,7 +145,7 @@ "Psr\\Log\\": "" } }, - "notification-url": "http://packagist.org/downloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -223,27 +223,30 @@ }, { "name": "symfony/config", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Config", "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "1624dd47e1f4dc89ae4e7ca4a0476325042f8e82" + "reference": "c9a779b0f02f0fdf41cc4decc4fb451005365086" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/1624dd47e1f4dc89ae4e7ca4a0476325042f8e82", - "reference": "1624dd47e1f4dc89ae4e7ca4a0476325042f8e82", + "url": "https://api.github.com/repos/symfony/Config/zipball/c9a779b0f02f0fdf41cc4decc4fb451005365086", + "reference": "c9a779b0f02f0fdf41cc4decc4fb451005365086", "shasum": "" }, "require": { "php": ">=5.3.9", "symfony/filesystem": "~2.3|~3.0.0" }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -267,21 +270,21 @@ ], "description": "Symfony Config Component", "homepage": "http://symfony.com", - "time": "2015-01-25 04:39:35" + "time": "2015-04-11 08:55:16" }, { "name": "symfony/console", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "9f041fb5735b0d25d117e77ab8597a8376c74fbd" + "reference": "32f19477d488649a77227d57a7f5775b17cb336b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/9f041fb5735b0d25d117e77ab8597a8376c74fbd", - "reference": "9f041fb5735b0d25d117e77ab8597a8376c74fbd", + "url": "https://api.github.com/repos/symfony/Console/zipball/32f19477d488649a77227d57a7f5775b17cb336b", + "reference": "32f19477d488649a77227d57a7f5775b17cb336b", "shasum": "" }, "require": { @@ -290,6 +293,7 @@ "require-dev": { "psr/log": "~1.0", "symfony/event-dispatcher": "~2.1|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/process": "~2.1|~3.0.0" }, "suggest": { @@ -300,7 +304,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -324,21 +328,21 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2015-01-25 05:59:26" + "time": "2015-04-11 08:55:16" }, { "name": "symfony/debug", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Debug", "source": { "type": "git", "url": "https://github.com/symfony/Debug.git", - "reference": "39a94beb5ea7f5f39854e7c8ab8dfda95e831f5d" + "reference": "2b867c246f3fb653611c9acdc3fdac9cc1957e3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Debug/zipball/39a94beb5ea7f5f39854e7c8ab8dfda95e831f5d", - "reference": "39a94beb5ea7f5f39854e7c8ab8dfda95e831f5d", + "url": "https://api.github.com/repos/symfony/Debug/zipball/2b867c246f3fb653611c9acdc3fdac9cc1957e3f", + "reference": "2b867c246f3fb653611c9acdc3fdac9cc1957e3f", "shasum": "" }, "require": { @@ -349,9 +353,10 @@ "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" }, "require-dev": { - "symfony/class-loader": "~2.2", + "symfony/class-loader": "~2.2|~3.0.0", "symfony/http-foundation": "~2.1|~3.0.0", - "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2|~3.0.0" + "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0" }, "suggest": { "symfony/http-foundation": "", @@ -360,7 +365,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -384,21 +389,21 @@ ], "description": "Symfony Debug Component", "homepage": "http://symfony.com", - "time": "2015-01-25 04:39:35" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/dependency-injection", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/DependencyInjection", "source": { "type": "git", "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "acf2e8e27c53b8af7963ca00809ccde1d1e977f4" + "reference": "ae47d9690326b0e970598a8f5b6710ece8f5fee4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/acf2e8e27c53b8af7963ca00809ccde1d1e977f4", - "reference": "acf2e8e27c53b8af7963ca00809ccde1d1e977f4", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/ae47d9690326b0e970598a8f5b6710ece8f5fee4", + "reference": "ae47d9690326b0e970598a8f5b6710ece8f5fee4", "shasum": "" }, "require": { @@ -410,6 +415,7 @@ "require-dev": { "symfony/config": "~2.2|~3.0.0", "symfony/expression-language": "~2.6|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/yaml": "~2.1|~3.0.0" }, "suggest": { @@ -420,7 +426,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -444,21 +450,21 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "http://symfony.com", - "time": "2015-01-25 04:39:35" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/event-dispatcher", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "7a26717d431dfb092198d7c55f06788b2de5aaf7" + "reference": "15bbd5beed94cca89ffcce18fb76eeac38937240" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/7a26717d431dfb092198d7c55f06788b2de5aaf7", - "reference": "7a26717d431dfb092198d7c55f06788b2de5aaf7", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/15bbd5beed94cca89ffcce18fb76eeac38937240", + "reference": "15bbd5beed94cca89ffcce18fb76eeac38937240", "shasum": "" }, "require": { @@ -469,6 +475,7 @@ "symfony/config": "~2.0,>=2.0.5|~3.0.0", "symfony/dependency-injection": "~2.6|~3.0.0", "symfony/expression-language": "~2.6|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/stopwatch": "~2.3|~3.0.0" }, "suggest": { @@ -478,7 +485,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -502,30 +509,33 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "http://symfony.com", - "time": "2015-01-16 15:11:56" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/filesystem", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "e681ca515e1e668a551b089177867e62e03d7d2d" + "reference": "59a58a369bafa7c2ded4e0b08d726482be7a7e6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/e681ca515e1e668a551b089177867e62e03d7d2d", - "reference": "e681ca515e1e668a551b089177867e62e03d7d2d", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/59a58a369bafa7c2ded4e0b08d726482be7a7e6b", + "reference": "59a58a369bafa7c2ded4e0b08d726482be7a7e6b", "shasum": "" }, "require": { "php": ">=5.3.9" }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -549,33 +559,34 @@ ], "description": "Symfony Filesystem Component", "homepage": "http://symfony.com", - "time": "2015-01-09 06:51:41" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/http-foundation", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/HttpFoundation", "source": { "type": "git", "url": "https://github.com/symfony/HttpFoundation.git", - "reference": "ee7cee860e05ba4e12c9a8a1775d4e5ae3f790cb" + "reference": "75b824419347be1926b3bb9ad14bb3c09d0b5141" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/ee7cee860e05ba4e12c9a8a1775d4e5ae3f790cb", - "reference": "ee7cee860e05ba4e12c9a8a1775d4e5ae3f790cb", + "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/75b824419347be1926b3bb9ad14bb3c09d0b5141", + "reference": "75b824419347be1926b3bb9ad14bb3c09d0b5141", "shasum": "" }, "require": { "php": ">=5.3.9" }, "require-dev": { - "symfony/expression-language": "~2.4|~3.0.0" + "symfony/expression-language": "~2.4|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -602,40 +613,44 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "http://symfony.com", - "time": "2015-01-25 04:39:35" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/http-kernel", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/HttpKernel", "source": { "type": "git", "url": "https://github.com/symfony/HttpKernel.git", - "reference": "37c51b8a642385cac387f9f913f47c0137effac7" + "reference": "53e7ff047f0b19edea9bae99bd1de6e1c35139c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/37c51b8a642385cac387f9f913f47c0137effac7", - "reference": "37c51b8a642385cac387f9f913f47c0137effac7", + "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/53e7ff047f0b19edea9bae99bd1de6e1c35139c5", + "reference": "53e7ff047f0b19edea9bae99bd1de6e1c35139c5", "shasum": "" }, "require": { "php": ">=5.3.9", "psr/log": "~1.0", - "symfony/debug": "~2.6,>=2.6.2|~3.0.0", + "symfony/debug": "~2.6,>=2.6.2", "symfony/event-dispatcher": "~2.5.9|~2.6,>=2.6.2|~3.0.0", "symfony/http-foundation": "~2.5,>=2.5.4|~3.0.0" }, + "conflict": { + "symfony/config": "<2.7" + }, "require-dev": { "symfony/browser-kit": "~2.3|~3.0.0", "symfony/class-loader": "~2.1|~3.0.0", - "symfony/config": "~2.0,>=2.0.5|~3.0.0", + "symfony/config": "~2.7", "symfony/console": "~2.3|~3.0.0", "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0", "symfony/dependency-injection": "~2.2|~3.0.0", "symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", "symfony/finder": "~2.0,>=2.0.5|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/process": "~2.0,>=2.0.5|~3.0.0", "symfony/routing": "~2.2|~3.0.0", "symfony/stopwatch": "~2.3|~3.0.0", @@ -655,7 +670,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -679,33 +694,37 @@ ], "description": "Symfony HttpKernel Component", "homepage": "http://symfony.com", - "time": "2015-01-25 04:39:35" + "time": "2015-04-11 08:55:16" }, { "name": "symfony/routing", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Routing", "source": { "type": "git", "url": "https://github.com/symfony/Routing.git", - "reference": "0c68965f72d650be4f51f199f5d69469df75aa30" + "reference": "cc81fccd24bce7fde640d2e4b070fe76b60f0f6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Routing/zipball/0c68965f72d650be4f51f199f5d69469df75aa30", - "reference": "0c68965f72d650be4f51f199f5d69469df75aa30", + "url": "https://api.github.com/repos/symfony/Routing/zipball/cc81fccd24bce7fde640d2e4b070fe76b60f0f6a", + "reference": "cc81fccd24bce7fde640d2e4b070fe76b60f0f6a", "shasum": "" }, "require": { "php": ">=5.3.9" }, + "conflict": { + "symfony/config": "<2.7" + }, "require-dev": { "doctrine/annotations": "~1.0", "doctrine/common": "~2.2", "psr/log": "~1.0", - "symfony/config": "~2.2|~3.0.0", + "symfony/config": "~2.7|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", "symfony/http-foundation": "~2.3|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/yaml": "~2.0,>=2.0.5|~3.0.0" }, "suggest": { @@ -717,7 +736,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -747,21 +766,21 @@ "uri", "url" ], - "time": "2015-01-23 17:16:45" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/security-core", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Security/Core", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "abe4db6553a89be8c827b7a86dac144e25726cda" + "reference": "992d40a1cd8b2647dce652b63a27fd18ff74e243" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/abe4db6553a89be8c827b7a86dac144e25726cda", - "reference": "abe4db6553a89be8c827b7a86dac144e25726cda", + "url": "https://api.github.com/repos/symfony/security-core/zipball/992d40a1cd8b2647dce652b63a27fd18ff74e243", + "reference": "992d40a1cd8b2647dce652b63a27fd18ff74e243", "shasum": "" }, "require": { @@ -773,6 +792,7 @@ "symfony/event-dispatcher": "~2.1|~3.0.0", "symfony/expression-language": "~2.6|~3.0.0", "symfony/http-foundation": "~2.4|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/translation": "~2.0,>=2.0.5|~3.0.0", "symfony/validator": "~2.5,>=2.5.5|~3.0.0" }, @@ -786,7 +806,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -810,21 +830,21 @@ ], "description": "Symfony Security Component - Core Library", "homepage": "http://symfony.com", - "time": "2015-01-25 04:39:35" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/security-csrf", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Security/Csrf", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", - "reference": "3f875078e322bf1fb6a546a607fe9adaab212f6c" + "reference": "80cf46a34308e7374700889a3af115ef5d772d23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/3f875078e322bf1fb6a546a607fe9adaab212f6c", - "reference": "3f875078e322bf1fb6a546a607fe9adaab212f6c", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/80cf46a34308e7374700889a3af115ef5d772d23", + "reference": "80cf46a34308e7374700889a3af115ef5d772d23", "shasum": "" }, "require": { @@ -832,7 +852,8 @@ "symfony/security-core": "~2.4|~3.0.0" }, "require-dev": { - "symfony/http-foundation": "~2.1|~3.0.0" + "symfony/http-foundation": "~2.1|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0" }, "suggest": { "symfony/http-foundation": "For using the class SessionTokenStorage." @@ -840,7 +861,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -864,44 +885,46 @@ ], "description": "Symfony Security Component - CSRF Library", "homepage": "http://symfony.com", - "time": "2015-01-09 06:51:41" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/twig-bridge", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Bridge/Twig", "source": { "type": "git", "url": "https://github.com/symfony/TwigBridge.git", - "reference": "bd5f5e3cde85eb2dfa074134bc9ac66b30ca6fc7" + "reference": "f05d28fb139db14d9793aee9b01244dc654810c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/TwigBridge/zipball/bd5f5e3cde85eb2dfa074134bc9ac66b30ca6fc7", - "reference": "bd5f5e3cde85eb2dfa074134bc9ac66b30ca6fc7", + "url": "https://api.github.com/repos/symfony/TwigBridge/zipball/f05d28fb139db14d9793aee9b01244dc654810c2", + "reference": "f05d28fb139db14d9793aee9b01244dc654810c2", "shasum": "" }, "require": { "php": ">=5.3.9", - "symfony/security-csrf": "~2.6|~3.0.0", "twig/twig": "~1.18" }, "require-dev": { - "symfony/console": "~2.4|~3.0.0", + "symfony/asset": "~2.7|~3.0.0", + "symfony/console": "~2.7|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", "symfony/finder": "~2.3|~3.0.0", - "symfony/form": "~2.6|~3.0.0", + "symfony/form": "~2.7|~3.0.0", "symfony/http-kernel": "~2.3|~3.0.0", "symfony/intl": "~2.3|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/routing": "~2.2|~3.0.0", "symfony/security": "~2.6|~3.0.0", "symfony/stopwatch": "~2.2|~3.0.0", "symfony/templating": "~2.1|~3.0.0", - "symfony/translation": "~2.2|~3.0.0", + "symfony/translation": "~2.7|~3.0.0", "symfony/var-dumper": "~2.6|~3.0.0", "symfony/yaml": "~2.0,>=2.0.5|~3.0.0" }, "suggest": { + "symfony/asset": "For using the AssetExtension", "symfony/expression-language": "For using the ExpressionExtension", "symfony/finder": "", "symfony/form": "For using the FormExtension", @@ -917,7 +940,7 @@ "type": "symfony-bridge", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -941,30 +964,33 @@ ], "description": "Symfony Twig Bridge", "homepage": "http://symfony.com", - "time": "2015-02-02 16:43:28" + "time": "2015-04-11 08:55:16" }, { "name": "symfony/yaml", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "02ba3dc638c5d3f0ab3b47ddb74f98c11dcc0c60" + "reference": "fdded56dde4ca9efce6322887bf5eaa7bb0aae3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/02ba3dc638c5d3f0ab3b47ddb74f98c11dcc0c60", - "reference": "02ba3dc638c5d3f0ab3b47ddb74f98c11dcc0c60", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/fdded56dde4ca9efce6322887bf5eaa7bb0aae3e", + "reference": "fdded56dde4ca9efce6322887bf5eaa7bb0aae3e", "shasum": "" }, "require": { "php": ">=5.3.9" }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -988,7 +1014,7 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2015-01-25 04:39:35" + "time": "2015-04-10 08:56:33" }, { "name": "twig/twig", @@ -1018,14 +1044,16 @@ "Twig_": "lib/" } }, - "notification-url": "http://packagist.org/downloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" }, { "name": "Armin Ronacher", @@ -2330,17 +2358,17 @@ }, { "name": "symfony/browser-kit", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/BrowserKit", "source": { "type": "git", "url": "https://github.com/symfony/BrowserKit.git", - "reference": "432c0593d5367b1bb8aa893cb2272172934ad371" + "reference": "e7ac73ecdd97f5b114152eb670607e96db7a2e17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/432c0593d5367b1bb8aa893cb2272172934ad371", - "reference": "432c0593d5367b1bb8aa893cb2272172934ad371", + "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/e7ac73ecdd97f5b114152eb670607e96db7a2e17", + "reference": "e7ac73ecdd97f5b114152eb670607e96db7a2e17", "shasum": "" }, "require": { @@ -2349,6 +2377,7 @@ }, "require-dev": { "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/process": "~2.0,>=2.0.5|~3.0.0" }, "suggest": { @@ -2357,7 +2386,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -2381,30 +2410,33 @@ ], "description": "Symfony BrowserKit Component", "homepage": "http://symfony.com", - "time": "2015-01-09 06:51:41" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/css-selector", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/CssSelector", "source": { "type": "git", "url": "https://github.com/symfony/CssSelector.git", - "reference": "1f8617c67bef17192d28c0f2dda3a04b632629bb" + "reference": "c315f95be51278f548d36664d51a8425e19e2cda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/CssSelector/zipball/1f8617c67bef17192d28c0f2dda3a04b632629bb", - "reference": "1f8617c67bef17192d28c0f2dda3a04b632629bb", + "url": "https://api.github.com/repos/symfony/CssSelector/zipball/c315f95be51278f548d36664d51a8425e19e2cda", + "reference": "c315f95be51278f548d36664d51a8425e19e2cda", "shasum": "" }, "require": { "php": ">=5.3.9" }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -2432,28 +2464,29 @@ ], "description": "Symfony CssSelector Component", "homepage": "http://symfony.com", - "time": "2015-01-09 06:51:41" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/dom-crawler", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/DomCrawler", "source": { "type": "git", "url": "https://github.com/symfony/DomCrawler.git", - "reference": "57ef66b6d806d9d1b9234e27da304ee5d1e54641" + "reference": "c7bd5b7d8444175f04e4278fa220fd3470c851fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/57ef66b6d806d9d1b9234e27da304ee5d1e54641", - "reference": "57ef66b6d806d9d1b9234e27da304ee5d1e54641", + "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/c7bd5b7d8444175f04e4278fa220fd3470c851fe", + "reference": "c7bd5b7d8444175f04e4278fa220fd3470c851fe", "shasum": "" }, "require": { "php": ">=5.3.9" }, "require-dev": { - "symfony/css-selector": "~2.3|~3.0.0" + "symfony/css-selector": "~2.3|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0" }, "suggest": { "symfony/css-selector": "" @@ -2461,7 +2494,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -2485,30 +2518,33 @@ ], "description": "Symfony DomCrawler Component", "homepage": "http://symfony.com", - "time": "2015-01-09 13:24:18" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/finder", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "0c737de96a94d14a51738d285ad426a102baac0e" + "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/0c737de96a94d14a51738d285ad426a102baac0e", - "reference": "0c737de96a94d14a51738d285ad426a102baac0e", + "url": "https://api.github.com/repos/symfony/Finder/zipball/ad159e0da47e9ffe719bafdc004159ad6e395567", + "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567", "shasum": "" }, "require": { "php": ">=5.3.9" }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -2532,30 +2568,33 @@ ], "description": "Symfony Finder Component", "homepage": "http://symfony.com", - "time": "2015-01-09 06:51:41" + "time": "2015-04-10 08:56:33" }, { "name": "symfony/process", - "version": "2.7.x-dev", + "version": "2.8.x-dev", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "f3ab493718070b936e21b202422466db35c1c298" + "reference": "5c73c03223e922c3c5f2c4128984e82a44089bbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/f3ab493718070b936e21b202422466db35c1c298", - "reference": "f3ab493718070b936e21b202422466db35c1c298", + "url": "https://api.github.com/repos/symfony/Process/zipball/5c73c03223e922c3c5f2c4128984e82a44089bbc", + "reference": "5c73c03223e922c3c5f2c4128984e82a44089bbc", "shasum": "" }, "require": { "php": ">=5.3.9" }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -2579,7 +2618,7 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2015-01-25 04:39:35" + "time": "2015-04-10 08:56:33" } ], "aliases": [], @@ -2590,6 +2629,7 @@ "symfony/console": 20, "symfony/dependency-injection": 20, "symfony/event-dispatcher": 20, + "symfony/filesystem": 20, "symfony/http-kernel": 20, "symfony/routing": 20, "symfony/security-core": 20, @@ -2600,12 +2640,12 @@ "symfony/css-selector": 20, "symfony/debug": 20, "symfony/dom-crawler": 20, - "symfony/filesystem": 20, "symfony/finder": 20, "symfony/http-foundation": 20, "symfony/process": 20 }, "prefer-stable": false, + "prefer-lowest": false, "platform": { "php": ">=5.3.9" }, From de5a5c41f8e8e47d0740fa97d3d83d57168b18b4 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 19 Apr 2015 17:41:29 +0200 Subject: [PATCH 0230/1676] [ticket/13768] Fix deprecations PHPBB3-13768 --- phpBB/phpbb/di/container_builder.php | 2 +- phpBB/phpbb/routing/router.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 2a410db9bd..99576f9020 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -150,7 +150,7 @@ class container_builder $config_cache = new ConfigCache($container_filename, defined('DEBUG')); if ($this->dump_container && $config_cache->isFresh()) { - require($container_filename); + require($config_cache->getPath()); $this->container = new \phpbb_cache_container(); } else diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 5313106b0a..7444f06253 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -262,7 +262,7 @@ class router implements RouterInterface $cache->write($dumper->dump($options), $this->get_routes()->getResources()); } - require_once($cache); + require_once($cache->getPath()); $this->matcher = new \phpbb_url_matcher($this->context); } @@ -310,7 +310,7 @@ class router implements RouterInterface $cache->write($dumper->dump($options), $this->get_routes()->getResources()); } - require_once($cache); + require_once($cache->getPath()); $this->generator = new \phpbb_url_generator($this->context); } From 72596429bd2088c06b4d74adc633ad785cfab77b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 22 Apr 2015 22:35:47 +0200 Subject: [PATCH 0231/1676] [ticket/13774] Updated s9e\TextFormatter PHPBB3-13774 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 8365acf5f3..adc109b0ee 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "4e0d311a3c56d0db4a7789e31457053be8148283" + "reference": "5b7d4c40bdef53f26ca6b09e85163f28e852f16b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/4e0d311a3c56d0db4a7789e31457053be8148283", - "reference": "4e0d311a3c56d0db4a7789e31457053be8148283", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/5b7d4c40bdef53f26ca6b09e85163f28e852f16b", + "reference": "5b7d4c40bdef53f26ca6b09e85163f28e852f16b", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-03-30 22:52:16" + "time": "2015-04-22 15:15:46" }, { "name": "symfony/config", From 2fa99602c6f6431e99468ca13f4a58344a401c24 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 8 Feb 2015 20:46:14 +0100 Subject: [PATCH 0232/1676] [ticket/8672] Add class for retrieving imagesize without download getimagesize() always downloads the complete file before checking the actual image dimensions. This class will be able to do the same without having to download possibly large files. PHPBB3-8672 --- phpBB/config/default/container/services.yml | 3 + .../default/container/services_avatar.yml | 3 + phpBB/includes/functions_upload.php | 24 +- phpBB/includes/message_parser.php | 9 +- phpBB/phpbb/avatar/driver/driver.php | 7 +- phpBB/phpbb/avatar/driver/gravatar.php | 12 +- phpBB/phpbb/avatar/driver/local.php | 8 +- phpBB/phpbb/avatar/driver/remote.php | 35 +- phpBB/phpbb/upload/imagesize.php | 549 ++++++++++++++++++ tests/avatar/manager_test.php | 5 +- tests/upload/fixture/bmp | Bin 0 -> 64 bytes tests/upload/fixture/iff | Bin 0 -> 120 bytes tests/upload/fixture/iff_maya | Bin 0 -> 88 bytes tests/upload/fixture/jp2 | Bin 0 -> 528 bytes tests/upload/fixture/jpx | Bin 0 -> 528 bytes tests/upload/fixture/psd | Bin 0 -> 6374 bytes tests/upload/fixture/tif_compressed | Bin 0 -> 236 bytes tests/upload/fixture/tif_msb | Bin 0 -> 222 bytes tests/upload/fixture/wbmp | Bin 0 -> 5 bytes tests/upload/imagesize_test.php | 99 ++++ 20 files changed, 707 insertions(+), 47 deletions(-) create mode 100644 phpBB/phpbb/upload/imagesize.php create mode 100644 tests/upload/fixture/bmp create mode 100644 tests/upload/fixture/iff create mode 100644 tests/upload/fixture/iff_maya create mode 100644 tests/upload/fixture/jp2 create mode 100644 tests/upload/fixture/jpx create mode 100644 tests/upload/fixture/psd create mode 100644 tests/upload/fixture/tif_compressed create mode 100644 tests/upload/fixture/tif_msb create mode 100644 tests/upload/fixture/wbmp create mode 100644 tests/upload/imagesize_test.php diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index a7a7703982..11bc6728a6 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -202,6 +202,9 @@ services: template_context: class: phpbb\template\context + upload_imagesize: + class: phpbb\upload\imagesize + version_helper: class: phpbb\version_helper scope: prototype diff --git a/phpBB/config/default/container/services_avatar.yml b/phpBB/config/default/container/services_avatar.yml index e80d57cb59..c74bef3d66 100644 --- a/phpBB/config/default/container/services_avatar.yml +++ b/phpBB/config/default/container/services_avatar.yml @@ -17,6 +17,7 @@ services: class: phpbb\avatar\driver\gravatar arguments: - @config + - @upload_imagesize - %core.root_path% - %core.php_ext% - @path_helper @@ -30,6 +31,7 @@ services: class: phpbb\avatar\driver\local arguments: - @config + - @upload_imagesize - %core.root_path% - %core.php_ext% - @path_helper @@ -43,6 +45,7 @@ services: class: phpbb\avatar\driver\remote arguments: - @config + - @upload_imagesize - %core.root_path% - %core.php_ext% - @path_helper diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index 21a6de7a41..f605f89d4d 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -400,28 +400,28 @@ class filespec { $this->width = $this->height = 0; - if (($this->image_info = @getimagesize($this->destination_file)) !== false) - { - $this->width = $this->image_info[0]; - $this->height = $this->image_info[1]; + // Get imagesize class + $imagesize = new \phpbb\upload\imagesize(); - if (!empty($this->image_info['mime'])) - { - $this->mimetype = $this->image_info['mime']; - } + $this->image_info = $imagesize->get_imagesize($this->destination_file, $this->mimetype); + + if ($this->image_info !== false) + { + $this->width = $this->image_info['width']; + $this->height = $this->image_info['height']; // Check image type $types = fileupload::image_types(); - if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]])) + if (!isset($types[$this->image_info['type']]) || !in_array($this->extension, $types[$this->image_info['type']])) { - if (!isset($types[$this->image_info[2]])) + if (!isset($types[$this->image_info['type']])) { - $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype); + $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info['type'], $this->mimetype); } else { - $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension); + $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info['type']][0], $this->extension); } } diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 8353ae6843..3d263748cb 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -339,22 +339,23 @@ class bbcode_firstpass extends bbcode if ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width']) { - $stats = @getimagesize(htmlspecialchars_decode($in)); + $imagesize = new \phpbb\upload\imagesize(); + $size_info = $imagesize->get_imagesize(htmlspecialchars_decode($in)); - if ($stats === false) + if ($size_info === false) { $error = true; $this->warn_msg[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; } else { - if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $stats[1]) + if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $size_info['height']) { $error = true; $this->warn_msg[] = $user->lang('MAX_IMG_HEIGHT_EXCEEDED', (int) $config['max_' . $this->mode . '_img_height']); } - if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $stats[0]) + if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $size_info['width']) { $error = true; $this->warn_msg[] = $user->lang('MAX_IMG_WIDTH_EXCEEDED', (int) $config['max_' . $this->mode . '_img_width']); diff --git a/phpBB/phpbb/avatar/driver/driver.php b/phpBB/phpbb/avatar/driver/driver.php index b3ced7edf7..aa92ba2012 100644 --- a/phpBB/phpbb/avatar/driver/driver.php +++ b/phpBB/phpbb/avatar/driver/driver.php @@ -30,6 +30,9 @@ abstract class driver implements \phpbb\avatar\driver\driver_interface */ protected $config; + /** @var \phpbb\upload\imagesize */ + protected $imagesize; + /** * Current $phpbb_root_path * @var string @@ -73,14 +76,16 @@ abstract class driver implements \phpbb\avatar\driver\driver_interface * Construct a driver object * * @param \phpbb\config\config $config phpBB configuration + * @param \phpbb\upload\imagesize $imagesize phpBB imagesize class * @param string $phpbb_root_path Path to the phpBB root * @param string $php_ext PHP file extension * @param \phpbb\path_helper $path_helper phpBB path helper * @param \phpbb\cache\driver\driver_interface $cache Cache driver */ - public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\cache\driver\driver_interface $cache = null) + public function __construct(\phpbb\config\config $config, \phpbb\upload\imagesize $imagesize, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\cache\driver\driver_interface $cache = null) { $this->config = $config; + $this->imagesize = $imagesize; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; $this->path_helper = $path_helper; diff --git a/phpBB/phpbb/avatar/driver/gravatar.php b/phpBB/phpbb/avatar/driver/gravatar.php index 2082e0fd02..73effadc18 100644 --- a/phpBB/phpbb/avatar/driver/gravatar.php +++ b/phpBB/phpbb/avatar/driver/gravatar.php @@ -98,8 +98,8 @@ class gravatar extends \phpbb\avatar\driver\driver return false; } - // Make sure getimagesize works... - if (function_exists('getimagesize') && ($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0)) + // Get image dimensions if they are not set + if ($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) { /** * default to the minimum of the maximum allowed avatar size if the size @@ -108,20 +108,20 @@ class gravatar extends \phpbb\avatar\driver\driver $row['avatar_width'] = $row['avatar_height'] = min($this->config['avatar_max_width'], $this->config['avatar_max_height']); $url = $this->get_gravatar_url($row); - if (($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) && (($image_data = getimagesize($url)) === false)) + if (($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) && (($image_data = $this->imagesize->get_imagesize($url)) === false)) { $error[] = 'UNABLE_GET_IMAGE_SIZE'; return false; } - if (!empty($image_data) && ($image_data[0] <= 0 || $image_data[1] <= 0)) + if (!empty($image_data) && ($image_data['width'] <= 0 || $image_data['width'] <= 0)) { $error[] = 'AVATAR_NO_SIZE'; return false; } - $row['avatar_width'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_width'] : $image_data[0]; - $row['avatar_height'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_height'] : $image_data[1]; + $row['avatar_width'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_width'] : $image_data['width']; + $row['avatar_height'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_height'] : $image_data['height']; } if ($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) diff --git a/phpBB/phpbb/avatar/driver/local.php b/phpBB/phpbb/avatar/driver/local.php index 36087f8ba0..abb07469de 100644 --- a/phpBB/phpbb/avatar/driver/local.php +++ b/phpBB/phpbb/avatar/driver/local.php @@ -172,13 +172,15 @@ class local extends \phpbb\avatar\driver\driver // Match all images in the gallery folder if (preg_match('#^[^&\'"<>]+\.(?:' . implode('|', $this->allowed_extensions) . ')$#i', $image) && is_file($file_path . '/' . $image)) { - if (function_exists('getimagesize')) + $dims = $this->imagesize->get_imagesize($file_path . '/' . $image); + + if ($dims === false) { - $dims = getimagesize($file_path . '/' . $image); + $dims = array(0, 0); } else { - $dims = array(0, 0); + $dims = array($dims['width'], $dims['height']); } $cat = ($path == $file_path) ? $user->lang['NO_AVATAR_CATEGORY'] : str_replace("$path/", '', $file_path); $avatar_list[$cat][$image] = array( diff --git a/phpBB/phpbb/avatar/driver/remote.php b/phpBB/phpbb/avatar/driver/remote.php index 4b0ee3f06f..d04f95905d 100644 --- a/phpBB/phpbb/avatar/driver/remote.php +++ b/phpBB/phpbb/avatar/driver/remote.php @@ -92,25 +92,22 @@ class remote extends \phpbb\avatar\driver\driver return false; } - // Make sure getimagesize works... - if (function_exists('getimagesize')) + // Get image dimensions + if (($width <= 0 || $height <= 0) && (($image_data = $this->imagesize->get_imagesize($url)) === false)) { - if (($width <= 0 || $height <= 0) && (($image_data = @getimagesize($url)) === false)) - { - $error[] = 'UNABLE_GET_IMAGE_SIZE'; - return false; - } - - if (!empty($image_data) && ($image_data[0] <= 0 || $image_data[1] <= 0)) - { - $error[] = 'AVATAR_NO_SIZE'; - return false; - } - - $width = ($width && $height) ? $width : $image_data[0]; - $height = ($width && $height) ? $height : $image_data[1]; + $error[] = 'UNABLE_GET_IMAGE_SIZE'; + return false; } + if (!empty($image_data) && ($image_data['width'] <= 0 || $image_data['height'] <= 0)) + { + $error[] = 'AVATAR_NO_SIZE'; + return false; + } + + $width = ($width && $height) ? $width : $image_data['width']; + $height = ($width && $height) ? $height : $image_data['height']; + if ($width <= 0 || $height <= 0) { $error[] = 'AVATAR_NO_SIZE'; @@ -172,15 +169,15 @@ class remote extends \phpbb\avatar\driver\driver return false; } - if (!empty($image_data) && (!isset($types[$image_data[2]]) || !in_array($extension, $types[$image_data[2]]))) + if (!empty($image_data) && (!isset($types[$image_data['type']]) || !in_array($extension, $types[$image_data['type']]))) { - if (!isset($types[$image_data[2]])) + if (!isset($types[$image_data['type']])) { $error[] = 'UNABLE_GET_IMAGE_SIZE'; } else { - $error[] = array('IMAGE_FILETYPE_MISMATCH', $types[$image_data[2]][0], $extension); + $error[] = array('IMAGE_FILETYPE_MISMATCH', $types[$image_data['type']][0], $extension); } return false; diff --git a/phpBB/phpbb/upload/imagesize.php b/phpBB/phpbb/upload/imagesize.php new file mode 100644 index 0000000000..3ef258f0a2 --- /dev/null +++ b/phpBB/phpbb/upload/imagesize.php @@ -0,0 +1,549 @@ + + * @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\upload; + +/** + * This class handles the retrieval of image dimensions + */ +class imagesize +{ + /** @var int 4-byte long size */ + const LONG_SIZE = 4; + + /** @var int 2-byte short size */ + const SHORT_SIZE = 2; + + /** @var string PNG header */ + const PNG_HEADER = "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"; + + /** @var int PNG IHDR offset */ + const PNG_IHDR_OFFSET = 12; + + /** @var string GIF87a header */ + const GIF87A_HEADER = "\x47\x49\x46\x38\x37\x61"; + + /** @var string GIF89a header */ + const GIF89A_HEADER = "\x47\x49\x46\x38\x39\x61"; + + /** @var int GIF header size */ + const GIF_HEADER_SIZE = 6; + + /** @var int JPG max header size. Headers can be bigger, but we'll abort + * going throught he header after this */ + const JPG_MAX_HEADER_SIZE = 24576; + + /** @var string PSD signature */ + const PSD_SIGNATURE = "8BPS"; + + /** @var int PSD header size */ + const PSD_HEADER_SIZE = 22; + + /** @var int PSD dimensions info offset */ + const PSD_DIMENSIONS_OFFSET = 14; + + /** @var int BMP header size needed for retrieving dimensions */ + const BMP_HEADER_SIZE = 26; + + /** @var string BMP signature */ + const BMP_SIGNATURE = "\x42\x4D"; + + /** qvar int BMP dimensions offset */ + const BMP_DIMENSIONS_OFFSET = 18; + + /** @var int TIF header size. The header might be larger but the dimensions + * should be in the first 512 bytes */ + const TIF_HEADER_SIZE = 512; + + /** @var int TIF tag for image height */ + const TIF_TAG_IMAGE_HEIGHT = 257; + + /** @var int TIF tag for image width */ + const TIF_TAG_IMAGE_WIDTH = 256; + + /** @var int TIF tag type for short */ + const TIF_TAG_TYPE_SHORT = 3; + + /** @var int TIF IFD entry size */ + const TIF_IFD_ENTRY_SIZE = 12; + + /** @var int IFF header size. Grab more than what should be needed to make + * sure we have the necessary data */ + const IFF_HEADER_SIZE = 32; + + /** @var string JPEG 2000 signature */ + const JPEG_2000_SIGNATURE = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A"; + + /** @var array Size info that is returned */ + protected $size = array(); + + /** @var string Data retrieved from remote */ + protected $data = ''; + + /** + * Get image dimensions of supplied image + * + * @param string $file Path to image that should be checked + * @param string $type Mimetype of image + * @return array|bool Array with image dimensions if successful, false if not + */ + public function get_imagesize($file, $type = '') + { + // Reset values + $this->reset_values(); + + // Treat image type as unknown if extension or mime type is unknown + if (!preg_match('/\.([a-z0-9]+)$/i', $file, $match) && empty($type)) + { + $this->get_imagesize_unknown_type($file); + } + else + { + $extension = (isset($match[1])) ? $match[1] : preg_replace('/.+\/([a-z0-9-.]+)$/i', '$1', $type); + + // Reset size info + $this->size = array(); + + switch ($extension) + { + case 'png': + $this->get_png_size($file); + break; + + case 'gif': + $this->get_gif_size($file); + break; + + case 'jpeg': + case 'jpg': + case 'jpe': + case 'jif': + case 'jfif': + case 'jfi': + $this->get_jpeg_size($file); + break; + + case 'jp2': + case 'j2k': + case 'jpf': + case 'jpg2': + case 'jpx': + case 'jpm': + $this->get_jp2_size($file); + break; + + case 'psd': + case 'photoshop': + $this->get_psd_size($file); + break; + + case 'bmp': + $this->get_bmp_size($file); + break; + + case 'tif': + case 'tiff': + // get_tif_size() sets mime type + $this->get_tif_size($file); + break; + + case 'wbm': + case 'wbmp': + case 'vnd.wap.wbmp': + $this->get_wbmp_size($file); + break; + + case 'iff': + case 'x-iff': + $this->get_iff_size($file); + break; + + default: + return false; + } + } + + return sizeof($this->size) > 1 ? $this->size : false; + } + + /** + * Get dimensions of image if type is unknown + * + * @param string $filename Path to file + */ + protected function get_imagesize_unknown_type($filename) + { + // Grab the maximum amount of bytes we might need + $data = $this->get_image($filename, 0, self::JPG_MAX_HEADER_SIZE, false); + + if ($data !== false) + { + $class_methods = preg_grep('/get_([a-z0-9]+)_size/i', get_class_methods($this)); + + foreach ($class_methods as $method) + { + call_user_func_array(array($this, $method), array($filename)); + + if (sizeof($this->size) > 1) + { + break; + } + } + } + } + + /** + * Reset values to default + */ + protected function reset_values() + { + $this->size = array(); + $this->data = ''; + } + + /** + * Set mime type based on supplied image + * + * @param int $type Type of image + */ + protected function set_image_type($type) + { + $this->size['type'] = $type; + } + + /** + * Get image from specified path/source + * + * @param string $filename Path to image + * @param int $offset Offset at which reading of the image should start + * @param int $length Maximum length that should be read + * @param bool $force_length True if the length needs to be the specified + * length, false if not. Default: true + * + * @return bool|string Image data or false if result was empty + */ + protected function get_image($filename, $offset, $length, $force_length = true) + { + if (empty($this->data)) + { + $this->data = @file_get_contents($filename, null, null, $offset, $length); + } + + // Force length to expected one. Return false if data length + // is smaller than expected length + if ($force_length === true) + { + return (strlen($this->data) < $length) ? false : substr($this->data, $offset, $length) ; + } + + return empty($this->data) ? false : $this->data; + } + + /** + * Get dimensions of PNG image + * + * @param string $filename Filename of image + * + * @return array|bool Array with image dimensions if successful, false if not + */ + protected function get_png_size($filename) + { + // Retrieve image data including the header, the IHDR tag, and the + // following 2 chunks for the image width and height + $data = $this->get_image($filename, 0, self::PNG_IHDR_OFFSET + 3 * self::LONG_SIZE); + + // Check if header fits expected format specified by RFC 2083 + if (substr($data, 0, self::PNG_IHDR_OFFSET - self::LONG_SIZE) !== self::PNG_HEADER || substr($data, self::PNG_IHDR_OFFSET, self::LONG_SIZE) !== 'IHDR') + { + return; + } + + $this->size = unpack('Nwidth/Nheight', substr($data, self::PNG_IHDR_OFFSET + self::LONG_SIZE, self::LONG_SIZE * 2)); + + $this->set_image_type(IMAGETYPE_PNG); + } + + /** + * Get dimensions of GIF image + * + * @param string $filename Filename of image + * + * @return array|bool Array with image dimensions if successful, false if not + */ + protected function get_gif_size($filename) + { + // Get data needed for reading image dimensions as outlined by GIF87a + // and GIF89a specifications + $data = $this->get_image($filename, 0, self::GIF_HEADER_SIZE + self::SHORT_SIZE * 2); + + $type = substr($data, 0, self::GIF_HEADER_SIZE); + if ($type !== self::GIF87A_HEADER && $type !== self::GIF89A_HEADER) + { + return; + } + + $this->size = unpack('vwidth/vheight', substr($data, self::GIF_HEADER_SIZE, self::SHORT_SIZE * 2)); + + $this->set_image_type(IMAGETYPE_GIF); + } + + /** + * Get dimensions of JPG image + * + * @param string $filename Filename of image + * + * @return array|bool Array with image dimensions if successful, false if not + */ + protected function get_jpeg_size($filename) + { + // Do not force the data length + $data = $this->get_image($filename, 0, self::JPG_MAX_HEADER_SIZE, false); + + // Check if file is jpeg + if ($data[0] !== "\xFF" || $data[1] !== "\xD8") + { + return; + } + + // Look through file for SOF marker + for ($i = 2 * self::SHORT_SIZE; $i < strlen($data); $i++) + { + if ($data[$i] === "\xFF" && in_array($data[$i+1], array("\xC0", "\xC1", "\xC2", "\xC3", "\xC5", "\xC6", "\xC7", "\xC8", "\xC9", "\xCA", "\xCB", "\xCD", "\xCE", "\xCF"))) + { + // Extract size info from SOF marker + list(, $unpacked) = unpack("H*", substr($data, $i + self::SHORT_SIZE, 7)); + + // Get width and height from unpacked size info + $this->size = array( + 'width' => hexdec(substr($unpacked, 10, 4)), + 'height' => hexdec(substr($unpacked, 6, 4)), + ); + + break; + } + } + + $this->set_image_type(IMAGETYPE_JPEG); + } + + /** + * Get dimensions of PSD image + * + * @param string $filename Filename of image + * + * @return array|bool Array with image dimensions if successful, false if not + */ + protected function get_psd_size($filename) + { + $data = $this->get_image($filename, 0, self::PSD_HEADER_SIZE); + + if ($data === false) + { + return; + } + + // Offset for version info is length of header but version is only a + // 16-bit unsigned value + $version = unpack('n', substr($data, self::LONG_SIZE, 2)); + + // Check if supplied file is a PSD file + if (substr($data, 0, self::LONG_SIZE) !== self::PSD_SIGNATURE || $version[1] !== 1) + { + return; + } + + $this->size = unpack('Nheight/Nwidth', substr($data, self::PSD_DIMENSIONS_OFFSET, 2 * self::LONG_SIZE)); + + $this->set_image_type(IMAGETYPE_PSD); + } + + /** + * Get dimensions of BMP image + * + * @param string $filename Filename of image + * + * @return array|bool Array with image dimensions if successful, false if not + */ + protected function get_bmp_size($filename) + { + $data = $this->get_image($filename, 0, self::BMP_HEADER_SIZE); + + // Check if supplied file is a BMP file + if (substr($data, 0, 2) !== self::BMP_SIGNATURE) + { + return; + } + + $this->size = unpack('lwidth/lheight', substr($data, self::BMP_DIMENSIONS_OFFSET, 2 * self::LONG_SIZE)); + + $this->set_image_type(IMAGETYPE_BMP); + } + + /** + * Get dimensions of TIF/TIFF image + * + * @param string $filename Filename of image + * + * @return array|bool Array with image dimensions if successful, false if not + */ + protected function get_tif_size($filename) + { + // Do not force length of header + $data = $this->get_image($filename, 0, self::TIF_HEADER_SIZE, false); + + $signature = substr($data, 0, self::SHORT_SIZE); + + if ($signature !== "II" && $signature !== "MM") + { + return; + } + + if ($signature === "II") + { + $type_long = 'V'; + $type_short = 'v'; + $this->set_image_type(IMAGETYPE_TIFF_II); + } + else + { + $type_long = 'N'; + $type_short = 'n'; + $this->set_image_type(IMAGETYPE_TIFF_MM); + } + + // Get offset of IFD + list(, $offset) = unpack($type_long, substr($data, self::LONG_SIZE, self::LONG_SIZE)); + + // Get size of IFD + list(, $size_ifd) = unpack($type_short, substr($data, $offset, self::SHORT_SIZE)); + + // Skip 2 bytes that define the IFD size + $offset += self::SHORT_SIZE; + + // Filter through IFD + for ($i = 0; $i < $size_ifd; $i++) + { + // Get IFD tag + $type = unpack($type_short, substr($data, $offset, self::SHORT_SIZE)); + + // Get field type of tag + $field_type = unpack($type_short . 'type', substr($data, $offset + self::SHORT_SIZE, self::SHORT_SIZE)); + + // Get IFD entry + $ifd_value = substr($data, $offset + 2 * self::LONG_SIZE, self::LONG_SIZE); + + // Get actual dimensions from IFD + if ($type[1] === self::TIF_TAG_IMAGE_HEIGHT) + { + $this->size = array_merge($this->size, ($field_type['type'] === self::TIF_TAG_TYPE_SHORT) ? unpack($type_short . 'height', $ifd_value) : unpack($type_long . 'height', $ifd_value)); + } + else if ($type[1] === self::TIF_TAG_IMAGE_WIDTH) + { + $this->size = array_merge($this->size, ($field_type['type'] === self::TIF_TAG_TYPE_SHORT) ? unpack($type_short .'width', $ifd_value) : unpack($type_long . 'width', $ifd_value)); + } + + $offset += self::TIF_IFD_ENTRY_SIZE; + } + } + + /** + * Get dimensions of WBMP image + * + * @param string $filename Filename of image + * + * @return array|bool Array with image dimensions if successful, false if not + */ + protected function get_wbmp_size($filename) + { + $data = $this->get_image($filename, 0, self::LONG_SIZE); + + // Check if image is WBMP + if (ord($data[0]) !== 0 || ord($data[1]) !== 0 || $data === substr(self::JPEG_2000_SIGNATURE, 0, 4)) + { + return; + } + + $this->size = unpack('Cwidth/Cheight', substr($data, self::SHORT_SIZE, self::SHORT_SIZE)); + + $this->set_image_type(IMAGETYPE_WBMP); + } + + /** + * Get dimensions of IFF image + * + * @param string $filename Filename of image + * + * @return array|bool Array with image dimensions if successful, false if not + */ + protected function get_iff_size($filename) + { + $data = $this->get_image($filename, 0, self::IFF_HEADER_SIZE); + + $signature = substr($data, 0, self::LONG_SIZE ); + + // Check if image is IFF + if ($signature !== 'FORM' && $signature !== 'FOR4') + { + return; + } + + // Amiga version of IFF + if ($signature === 'FORM') + { + $btmhd_position = strpos($data, 'BMHD'); + $this->size = unpack('nwidth/nheight', substr($data, $btmhd_position + 2 * self::LONG_SIZE, self::LONG_SIZE)); + } + // Maya version + else + { + $btmhd_position = strpos($data, 'BHD'); + $this->size = unpack('Nwidth/Nheight', substr($data, $btmhd_position + 2 * self::LONG_SIZE - 1, self::LONG_SIZE * 2)); + } + + $this->set_image_type(IMAGETYPE_IFF); + } + + /** + * Get dimensions of JPEG 2000 image + * + * @param string $filename Filename of image + * + * @return array|bool Array with image dimensions if successful, false if not + */ + protected function get_jp2_size($filename) + { + $data = $this->get_image($filename, 0, self::JPG_MAX_HEADER_SIZE, false); + + // Check if file is jpeg 2000 + if (substr($data, 0, strlen(self::JPEG_2000_SIGNATURE)) !== self::JPEG_2000_SIGNATURE) + { + return; + } + + // Get SOC position before starting to search for SIZ + $soc_position = strpos($data, "\xFF\x4F"); + + // Make sure we do not get SIZ before SOC + $data = substr($data, $soc_position); + + $siz_position = strpos($data, "\xFF\x51"); + + // Remove SIZ and everything before + $data = substr($data, $siz_position + self::SHORT_SIZE); + + // Acquire size info from data + $this->size = unpack('Nwidth/Nheight', substr($data, self::LONG_SIZE, self::LONG_SIZE * 2)); + + $this->set_image_type(IMAGETYPE_JPEG2000); + } +} diff --git a/tests/avatar/manager_test.php b/tests/avatar/manager_test.php index 4befbfc1fc..14c88c8da5 100644 --- a/tests/avatar/manager_test.php +++ b/tests/avatar/manager_test.php @@ -57,9 +57,10 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case new \phpbb\mimetype\content_guesser, ); $guesser = new \phpbb\mimetype\guesser($guessers); + $imagesize = new \phpbb\upload\imagesize(); // $this->avatar_foobar will be needed later on - $this->avatar_foobar = $this->getMock('\phpbb\avatar\driver\foobar', array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $cache)); + $this->avatar_foobar = $this->getMock('\phpbb\avatar\driver\foobar', array('get_name'), array($this->config, $imagesize, $phpbb_root_path, $phpEx, $path_helper, $cache)); $this->avatar_foobar->expects($this->any()) ->method('get_name') ->will($this->returnValue('avatar.driver.foobar')); @@ -74,7 +75,7 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case { if ($driver !== 'upload') { - $cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $cache)); + $cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $imagesize, $phpbb_root_path, $phpEx, $path_helper, $cache)); } else { diff --git a/tests/upload/fixture/bmp b/tests/upload/fixture/bmp new file mode 100644 index 0000000000000000000000000000000000000000..04bff561abb60aa55c55dffabbc966bc06f70b2a GIT binary patch literal 64 pcmZ?rbzp!1Ga#h_#7scU2*wgXl7WE>h=sTz7%TuJ{(}LC2LOG{2Z#Uw literal 0 HcmV?d00001 diff --git a/tests/upload/fixture/iff b/tests/upload/fixture/iff new file mode 100644 index 0000000000000000000000000000000000000000..24eda8f593f270038b1de32859587e2c04b5b6e0 GIT binary patch literal 120 ycmZ?s5AtPTU?}kPaq@NY^>6{QMHrYE7=bi{1ejuE1o55xT_S-(9*hSVsDc2^pBJY9 literal 0 HcmV?d00001 diff --git a/tests/upload/fixture/iff_maya b/tests/upload/fixture/iff_maya new file mode 100644 index 0000000000000000000000000000000000000000..b6fb85101b80e427a136e1ea30c81728e92c3f3e GIT binary patch literal 88 zcmZ?s4>Dn3Ud?Tzqu{_GB%r{c%OSwPV#UiO!S&KnbaR>aDaUhsg)A)YCw0zTTrcix(^`K+D{LmS+HI zvCNE=A|TBO#7qp#?Cc;01AlUUP7xzmPyoo4DoQO@0MbH0I+KtyzyowFBO@y_GXvxQ7zSYn2M><`Wb}Um11N477(^M^{!c!?g@a*3Ljzn;kP#>d Yltc(Hp$jmh3$UOIumS}dfQH@#09mnxvH$=8 literal 0 HcmV?d00001 diff --git a/tests/upload/fixture/jpx b/tests/upload/fixture/jpx new file mode 100644 index 0000000000000000000000000000000000000000..adca6ecf0e6fba37b18af99b02ab533a83709e34 GIT binary patch literal 528 zcmZQzVBpCLP*C9IYUg5LV30{GsVvAUFj4@r89;PaK}8Y}gZQ~cMX7~M|NsB^z`)AD z*ucQR>d?Tzqu{_GB%r{c%OSwPV#UiO!S&KnbaR>aDaUhsg)A)YCw0zTTrcix(^`K+D{LmS+HI zvCNE=A|TBO#7qp#?Cc;01AlUUP7xzmPyoo4DoQO@0MbH0I+KtyzyowFBO@y_GXvxQ7zSYn2M><`Wb}Um11N477(^M^{!c!?g@a*3Ljzn;kP#>d Yltc(Hp$jmh3$UOIumS}dfQH@#09mnxvH$=8 literal 0 HcmV?d00001 diff --git a/tests/upload/fixture/psd b/tests/upload/fixture/psd new file mode 100644 index 0000000000000000000000000000000000000000..d1bc9a6a709d5b1a64b513f8c243af06db190a86 GIT binary patch literal 6374 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 bloZTR9eK9341(~U+uGVjhwqQ}SHu4UQ3u5M literal 0 HcmV?d00001 diff --git a/tests/upload/fixture/tif_compressed b/tests/upload/fixture/tif_compressed new file mode 100644 index 0000000000000000000000000000000000000000..133b50c4f0948c97c9bbf7f12c9e0980f5e202fc GIT binary patch literal 236 zcmebD)MDUZU|?8yLfIfWCLo&`NS^~@W~ewTkj;jqUXT%D z&J&=x5RzU|C>x|-3`txZs-7JvF2%?Sw)YBPx# literal 0 HcmV?d00001 diff --git a/tests/upload/fixture/wbmp b/tests/upload/fixture/wbmp new file mode 100644 index 0000000000000000000000000000000000000000..708c86ccee4dd58a627667b1fc88eb484b16ad71 GIT binary patch literal 5 McmZQzU}8J~007MZ!~g&Q literal 0 HcmV?d00001 diff --git a/tests/upload/imagesize_test.php b/tests/upload/imagesize_test.php new file mode 100644 index 0000000000..2ce712e5c1 --- /dev/null +++ b/tests/upload/imagesize_test.php @@ -0,0 +1,99 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +require_once(__DIR__ . '/../../phpBB/includes/functions.php'); + +class phpbb_upload_imagesize_test extends \phpbb_test_case +{ + /** @var \phpbb\upload\imagesize */ + protected $imagesize; + + /** @var string Path to fixtures */ + protected $path; + + public function setUp() + { + parent::setUp(); + $this->imagesize = new \phpbb\upload\imagesize(); + $this->path = __DIR__ . '/fixture/'; + } + + public function data_get_imagesize() + { + return array( + array('foobar', 'image/bmp', false), + array('png', 'image/png', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_PNG)), + array('gif', 'image/png', false), + array('png', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_PNG)), + array('gif', 'image/gif', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_GIF)), + array('jpg', 'image/gif', false), + array('gif', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_GIF)), + array('jpg', 'image/jpg', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)), + array('jpg', 'image/jpeg', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)), + array('png', 'image/jpg', false), + array('jpg', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)), + array('psd', 'image/psd', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)), + array('psd', 'image/photoshop', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)), + array('jpg', 'image/psd', false), + array('psd', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)), + array('bmp', 'image/bmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_BMP)), + array('png', 'image/bmp', false), + array('bmp', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_BMP)), + array('tif', 'image/tif', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)), + array('png', 'image/tif', false), + array('tif', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)), + array('tif_compressed', 'image/tif', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)), + array('png', 'image/tiff', false), + array('tif_compressed', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)), + array('tif_msb', 'image/tif', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_MM)), + array('tif_msb', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_MM)), + array('wbmp', 'image/wbmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)), + array('wbmp', 'image/vnd.wap.wbmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)), + array('png', 'image/vnd.wap.wbmp', false), + array('wbmp', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)), + array('iff', 'image/iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), + array('iff', 'image/x-iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), + array('iff_maya', 'iamge/iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), + array('png', 'image/iff', false), + array('png', 'image/x-iff', false), + array('iff', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), + array('iff_maya', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), + array('jp2', 'image/jp2', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), + array('jp2', 'image/jpx', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), + array('jp2', 'image/jpm', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), + array('jpg', 'image/jp2', false), + array('jpx', 'image/jpx', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), + array('jp2', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), + array('jpx', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), + ); + } + + /** + * @dataProvider data_get_imagesize + */ + public function test_get_imagesize($file, $mime_type, $expected) + { + $this->assertEquals($expected, $this->imagesize->get_imagesize($this->path . $file, $mime_type)); + } + + public function test_get_imagesize_remote() + { + $this->assertSame(array( + 'width' => 80, + 'height' => 80, + 'type' => IMAGETYPE_JPEG, + ), + $this->imagesize->get_imagesize('https://secure.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0.jpg')); + } +} From 245d042e43374e6467f447507783a68fae186ef1 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 6 Apr 2015 21:32:22 +0200 Subject: [PATCH 0233/1676] [ticket/8672] Updated the text_formatter.s9e service PHPBB3-8672 --- phpBB/phpbb/textformatter/s9e/parser.php | 14 +++++--------- tests/test_framework/phpbb_test_case_helpers.php | 4 ++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 77328ee4d9..0582f235e0 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -367,7 +367,6 @@ class parser implements \phpbb\textformatter\parser_interface { // Validate the URL $url = BuiltInFilters::filterUrl($url, $url_config, $logger); - if ($url === false) { return false; @@ -375,26 +374,23 @@ class parser implements \phpbb\textformatter\parser_interface if ($max_height || $max_width) { - $stats = @getimagesize($url); - - if ($stats === false) + $imagesize = new \phpbb\upload\imagesize(); + $size_info = $imagesize->get_imagesize($url); + if ($size_info === false) { $logger->err('UNABLE_GET_IMAGE_SIZE'); - return false; } - if ($max_height && $max_height < $stats[1]) + if ($max_height && $max_height < $size_info['height']) { $logger->err('MAX_IMG_HEIGHT_EXCEEDED', array('max_height' => $max_height)); - return false; } - if ($max_width && $max_width < $stats[0]) + if ($max_width && $max_width < $size_info['width']) { $logger->err('MAX_IMG_WIDTH_EXCEEDED', array('max_width' => $max_width)); - return false; } } diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 09fec38013..0f9b049f44 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -458,6 +458,10 @@ class phpbb_test_case_helpers { $dispatcher = new phpbb_mock_event_dispatcher; } + if (!isset($phpbb_dispatcher)) + { + $phpbb_dispatcher = $dispatcher; + } // Create and register the text_formatter.s9e.factory service $factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $dispatcher, $cache_dir, $cache_key_parser, $cache_key_renderer); From 3fc7a352ff308ff4b5a038e807a6f803572242d5 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 7 Apr 2015 16:11:36 +0200 Subject: [PATCH 0234/1676] [ticket/8672] Add fast-image-size library to composer.json PHPBB3-8672 --- phpBB/composer.json | 1 + phpBB/composer.lock | 51 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/phpBB/composer.json b/phpBB/composer.json index 46c0e9b361..31462b81eb 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -26,6 +26,7 @@ }, "require": { "lusitanian/oauth": "0.2.*", + "marc1706/fast-image-size": "1.0.*", "patchwork/utf8": "1.1.*", "php": ">=5.3.9", "s9e/text-formatter": "dev-release/php5.3", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index adc109b0ee..3bff2429d6 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -69,6 +69,57 @@ ], "time": "2013-08-29 21:40:04" }, + { + "name": "marc1706/fast-image-size", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/marc1706/fast-image-size.git", + "reference": "99fb3c4aab631a39db7e8638450b59f562a47bb1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/99fb3c4aab631a39db7e8638450b59f562a47bb1", + "reference": "99fb3c4aab631a39db7e8638450b59f562a47bb1", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "fastImageSize\\": "lib", + "fastImageSize\\tests\\": "tests" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marc Alexander", + "email": "admin@m-a-styles.de", + "homepage": "https://www.m-a-styles.de", + "role": "Developer" + } + ], + "description": "fast-image-size is a PHP library that does almost everything PHP's getimagesize() does but without the large overhead of downloading the complete file.", + "homepage": "https://www.m-a-styles.de", + "keywords": [ + "fast", + "getimagesize", + "image", + "imagesize", + "php", + "size" + ], + "time": "2015-04-07 13:37:04" + }, { "name": "patchwork/utf8", "version": "v1.1.26", From 39d6180c6814996dde84cfcd8c0150bba37354ac Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 7 Apr 2015 16:19:36 +0200 Subject: [PATCH 0235/1676] [ticket/8672] Use fastImageSize in classes PHPBB3-8672 --- phpBB/config/default/container/services.yml | 2 +- phpBB/includes/functions_upload.php | 4 ++-- phpBB/includes/message_parser.php | 4 ++-- phpBB/phpbb/avatar/driver/driver.php | 6 +++--- phpBB/phpbb/avatar/driver/gravatar.php | 2 +- phpBB/phpbb/avatar/driver/local.php | 2 +- phpBB/phpbb/avatar/driver/remote.php | 2 +- phpBB/phpbb/textformatter/s9e/parser.php | 4 ++-- tests/avatar/manager_test.php | 2 +- tests/upload/imagesize_test.php | 8 ++++---- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 11bc6728a6..682eaeb200 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -203,7 +203,7 @@ services: class: phpbb\template\context upload_imagesize: - class: phpbb\upload\imagesize + class: fastImageSize\fastImageSize version_helper: class: phpbb\version_helper diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index f605f89d4d..ea82a23082 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -401,9 +401,9 @@ class filespec $this->width = $this->height = 0; // Get imagesize class - $imagesize = new \phpbb\upload\imagesize(); + $imagesize = new \fastImageSize\fastImageSize(); - $this->image_info = $imagesize->get_imagesize($this->destination_file, $this->mimetype); + $this->image_info = $imagesize->getImageSize($this->destination_file, $this->mimetype); if ($this->image_info !== false) { diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 3d263748cb..bc53336a3f 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -339,8 +339,8 @@ class bbcode_firstpass extends bbcode if ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width']) { - $imagesize = new \phpbb\upload\imagesize(); - $size_info = $imagesize->get_imagesize(htmlspecialchars_decode($in)); + $imagesize = new \fastImageSize\fastImageSize(); + $size_info = $imagesize->getImageSize(htmlspecialchars_decode($in)); if ($size_info === false) { diff --git a/phpBB/phpbb/avatar/driver/driver.php b/phpBB/phpbb/avatar/driver/driver.php index aa92ba2012..b6fd380bda 100644 --- a/phpBB/phpbb/avatar/driver/driver.php +++ b/phpBB/phpbb/avatar/driver/driver.php @@ -30,7 +30,7 @@ abstract class driver implements \phpbb\avatar\driver\driver_interface */ protected $config; - /** @var \phpbb\upload\imagesize */ + /** @var \fastImageSize\fastImageSize */ protected $imagesize; /** @@ -76,13 +76,13 @@ abstract class driver implements \phpbb\avatar\driver\driver_interface * Construct a driver object * * @param \phpbb\config\config $config phpBB configuration - * @param \phpbb\upload\imagesize $imagesize phpBB imagesize class + * @param \fastImageSize\fastImageSize $imagesize fastImageSize class * @param string $phpbb_root_path Path to the phpBB root * @param string $php_ext PHP file extension * @param \phpbb\path_helper $path_helper phpBB path helper * @param \phpbb\cache\driver\driver_interface $cache Cache driver */ - public function __construct(\phpbb\config\config $config, \phpbb\upload\imagesize $imagesize, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\cache\driver\driver_interface $cache = null) + public function __construct(\phpbb\config\config $config, \fastImageSize\fastImageSize $imagesize, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\cache\driver\driver_interface $cache = null) { $this->config = $config; $this->imagesize = $imagesize; diff --git a/phpBB/phpbb/avatar/driver/gravatar.php b/phpBB/phpbb/avatar/driver/gravatar.php index 73effadc18..badbd9421d 100644 --- a/phpBB/phpbb/avatar/driver/gravatar.php +++ b/phpBB/phpbb/avatar/driver/gravatar.php @@ -108,7 +108,7 @@ class gravatar extends \phpbb\avatar\driver\driver $row['avatar_width'] = $row['avatar_height'] = min($this->config['avatar_max_width'], $this->config['avatar_max_height']); $url = $this->get_gravatar_url($row); - if (($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) && (($image_data = $this->imagesize->get_imagesize($url)) === false)) + if (($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) && (($image_data = $this->imagesize->getImageSize($url)) === false)) { $error[] = 'UNABLE_GET_IMAGE_SIZE'; return false; diff --git a/phpBB/phpbb/avatar/driver/local.php b/phpBB/phpbb/avatar/driver/local.php index abb07469de..88a139f81e 100644 --- a/phpBB/phpbb/avatar/driver/local.php +++ b/phpBB/phpbb/avatar/driver/local.php @@ -172,7 +172,7 @@ class local extends \phpbb\avatar\driver\driver // Match all images in the gallery folder if (preg_match('#^[^&\'"<>]+\.(?:' . implode('|', $this->allowed_extensions) . ')$#i', $image) && is_file($file_path . '/' . $image)) { - $dims = $this->imagesize->get_imagesize($file_path . '/' . $image); + $dims = $this->imagesize->getImageSize($file_path . '/' . $image); if ($dims === false) { diff --git a/phpBB/phpbb/avatar/driver/remote.php b/phpBB/phpbb/avatar/driver/remote.php index d04f95905d..90443c9b4e 100644 --- a/phpBB/phpbb/avatar/driver/remote.php +++ b/phpBB/phpbb/avatar/driver/remote.php @@ -93,7 +93,7 @@ class remote extends \phpbb\avatar\driver\driver } // Get image dimensions - if (($width <= 0 || $height <= 0) && (($image_data = $this->imagesize->get_imagesize($url)) === false)) + if (($width <= 0 || $height <= 0) && (($image_data = $this->imagesize->getImageSize($url)) === false)) { $error[] = 'UNABLE_GET_IMAGE_SIZE'; return false; diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 0582f235e0..e46a0578d2 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -374,8 +374,8 @@ class parser implements \phpbb\textformatter\parser_interface if ($max_height || $max_width) { - $imagesize = new \phpbb\upload\imagesize(); - $size_info = $imagesize->get_imagesize($url); + $imagesize = new \fastImageSize\fastImageSize(); + $size_info = $imagesize->getImageSize($url); if ($size_info === false) { $logger->err('UNABLE_GET_IMAGE_SIZE'); diff --git a/tests/avatar/manager_test.php b/tests/avatar/manager_test.php index 14c88c8da5..638ba0aaff 100644 --- a/tests/avatar/manager_test.php +++ b/tests/avatar/manager_test.php @@ -57,7 +57,7 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case new \phpbb\mimetype\content_guesser, ); $guesser = new \phpbb\mimetype\guesser($guessers); - $imagesize = new \phpbb\upload\imagesize(); + $imagesize = new \fastImageSize\fastImageSize(); // $this->avatar_foobar will be needed later on $this->avatar_foobar = $this->getMock('\phpbb\avatar\driver\foobar', array('get_name'), array($this->config, $imagesize, $phpbb_root_path, $phpEx, $path_helper, $cache)); diff --git a/tests/upload/imagesize_test.php b/tests/upload/imagesize_test.php index 2ce712e5c1..bfea4b819d 100644 --- a/tests/upload/imagesize_test.php +++ b/tests/upload/imagesize_test.php @@ -16,7 +16,7 @@ require_once(__DIR__ . '/../../phpBB/includes/functions.php'); class phpbb_upload_imagesize_test extends \phpbb_test_case { - /** @var \phpbb\upload\imagesize */ + /** @var \fastImageSize\fastImageSize */ protected $imagesize; /** @var string Path to fixtures */ @@ -25,7 +25,7 @@ class phpbb_upload_imagesize_test extends \phpbb_test_case public function setUp() { parent::setUp(); - $this->imagesize = new \phpbb\upload\imagesize(); + $this->imagesize = new \fastImageSize\fastImageSize(); $this->path = __DIR__ . '/fixture/'; } @@ -84,7 +84,7 @@ class phpbb_upload_imagesize_test extends \phpbb_test_case */ public function test_get_imagesize($file, $mime_type, $expected) { - $this->assertEquals($expected, $this->imagesize->get_imagesize($this->path . $file, $mime_type)); + $this->assertEquals($expected, $this->imagesize->getImageSize($this->path . $file, $mime_type)); } public function test_get_imagesize_remote() @@ -94,6 +94,6 @@ class phpbb_upload_imagesize_test extends \phpbb_test_case 'height' => 80, 'type' => IMAGETYPE_JPEG, ), - $this->imagesize->get_imagesize('https://secure.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0.jpg')); + $this->imagesize->getImageSize('https://secure.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0.jpg')); } } From f92d8944704161668e3fa2a868711730fbcc777d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 7 Apr 2015 16:47:10 +0200 Subject: [PATCH 0236/1676] [ticket/8672] Remove outdated imagesize class PHPBB3-8672 --- phpBB/phpbb/upload/imagesize.php | 549 ------------------------------- 1 file changed, 549 deletions(-) delete mode 100644 phpBB/phpbb/upload/imagesize.php diff --git a/phpBB/phpbb/upload/imagesize.php b/phpBB/phpbb/upload/imagesize.php deleted file mode 100644 index 3ef258f0a2..0000000000 --- a/phpBB/phpbb/upload/imagesize.php +++ /dev/null @@ -1,549 +0,0 @@ - - * @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\upload; - -/** - * This class handles the retrieval of image dimensions - */ -class imagesize -{ - /** @var int 4-byte long size */ - const LONG_SIZE = 4; - - /** @var int 2-byte short size */ - const SHORT_SIZE = 2; - - /** @var string PNG header */ - const PNG_HEADER = "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"; - - /** @var int PNG IHDR offset */ - const PNG_IHDR_OFFSET = 12; - - /** @var string GIF87a header */ - const GIF87A_HEADER = "\x47\x49\x46\x38\x37\x61"; - - /** @var string GIF89a header */ - const GIF89A_HEADER = "\x47\x49\x46\x38\x39\x61"; - - /** @var int GIF header size */ - const GIF_HEADER_SIZE = 6; - - /** @var int JPG max header size. Headers can be bigger, but we'll abort - * going throught he header after this */ - const JPG_MAX_HEADER_SIZE = 24576; - - /** @var string PSD signature */ - const PSD_SIGNATURE = "8BPS"; - - /** @var int PSD header size */ - const PSD_HEADER_SIZE = 22; - - /** @var int PSD dimensions info offset */ - const PSD_DIMENSIONS_OFFSET = 14; - - /** @var int BMP header size needed for retrieving dimensions */ - const BMP_HEADER_SIZE = 26; - - /** @var string BMP signature */ - const BMP_SIGNATURE = "\x42\x4D"; - - /** qvar int BMP dimensions offset */ - const BMP_DIMENSIONS_OFFSET = 18; - - /** @var int TIF header size. The header might be larger but the dimensions - * should be in the first 512 bytes */ - const TIF_HEADER_SIZE = 512; - - /** @var int TIF tag for image height */ - const TIF_TAG_IMAGE_HEIGHT = 257; - - /** @var int TIF tag for image width */ - const TIF_TAG_IMAGE_WIDTH = 256; - - /** @var int TIF tag type for short */ - const TIF_TAG_TYPE_SHORT = 3; - - /** @var int TIF IFD entry size */ - const TIF_IFD_ENTRY_SIZE = 12; - - /** @var int IFF header size. Grab more than what should be needed to make - * sure we have the necessary data */ - const IFF_HEADER_SIZE = 32; - - /** @var string JPEG 2000 signature */ - const JPEG_2000_SIGNATURE = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A"; - - /** @var array Size info that is returned */ - protected $size = array(); - - /** @var string Data retrieved from remote */ - protected $data = ''; - - /** - * Get image dimensions of supplied image - * - * @param string $file Path to image that should be checked - * @param string $type Mimetype of image - * @return array|bool Array with image dimensions if successful, false if not - */ - public function get_imagesize($file, $type = '') - { - // Reset values - $this->reset_values(); - - // Treat image type as unknown if extension or mime type is unknown - if (!preg_match('/\.([a-z0-9]+)$/i', $file, $match) && empty($type)) - { - $this->get_imagesize_unknown_type($file); - } - else - { - $extension = (isset($match[1])) ? $match[1] : preg_replace('/.+\/([a-z0-9-.]+)$/i', '$1', $type); - - // Reset size info - $this->size = array(); - - switch ($extension) - { - case 'png': - $this->get_png_size($file); - break; - - case 'gif': - $this->get_gif_size($file); - break; - - case 'jpeg': - case 'jpg': - case 'jpe': - case 'jif': - case 'jfif': - case 'jfi': - $this->get_jpeg_size($file); - break; - - case 'jp2': - case 'j2k': - case 'jpf': - case 'jpg2': - case 'jpx': - case 'jpm': - $this->get_jp2_size($file); - break; - - case 'psd': - case 'photoshop': - $this->get_psd_size($file); - break; - - case 'bmp': - $this->get_bmp_size($file); - break; - - case 'tif': - case 'tiff': - // get_tif_size() sets mime type - $this->get_tif_size($file); - break; - - case 'wbm': - case 'wbmp': - case 'vnd.wap.wbmp': - $this->get_wbmp_size($file); - break; - - case 'iff': - case 'x-iff': - $this->get_iff_size($file); - break; - - default: - return false; - } - } - - return sizeof($this->size) > 1 ? $this->size : false; - } - - /** - * Get dimensions of image if type is unknown - * - * @param string $filename Path to file - */ - protected function get_imagesize_unknown_type($filename) - { - // Grab the maximum amount of bytes we might need - $data = $this->get_image($filename, 0, self::JPG_MAX_HEADER_SIZE, false); - - if ($data !== false) - { - $class_methods = preg_grep('/get_([a-z0-9]+)_size/i', get_class_methods($this)); - - foreach ($class_methods as $method) - { - call_user_func_array(array($this, $method), array($filename)); - - if (sizeof($this->size) > 1) - { - break; - } - } - } - } - - /** - * Reset values to default - */ - protected function reset_values() - { - $this->size = array(); - $this->data = ''; - } - - /** - * Set mime type based on supplied image - * - * @param int $type Type of image - */ - protected function set_image_type($type) - { - $this->size['type'] = $type; - } - - /** - * Get image from specified path/source - * - * @param string $filename Path to image - * @param int $offset Offset at which reading of the image should start - * @param int $length Maximum length that should be read - * @param bool $force_length True if the length needs to be the specified - * length, false if not. Default: true - * - * @return bool|string Image data or false if result was empty - */ - protected function get_image($filename, $offset, $length, $force_length = true) - { - if (empty($this->data)) - { - $this->data = @file_get_contents($filename, null, null, $offset, $length); - } - - // Force length to expected one. Return false if data length - // is smaller than expected length - if ($force_length === true) - { - return (strlen($this->data) < $length) ? false : substr($this->data, $offset, $length) ; - } - - return empty($this->data) ? false : $this->data; - } - - /** - * Get dimensions of PNG image - * - * @param string $filename Filename of image - * - * @return array|bool Array with image dimensions if successful, false if not - */ - protected function get_png_size($filename) - { - // Retrieve image data including the header, the IHDR tag, and the - // following 2 chunks for the image width and height - $data = $this->get_image($filename, 0, self::PNG_IHDR_OFFSET + 3 * self::LONG_SIZE); - - // Check if header fits expected format specified by RFC 2083 - if (substr($data, 0, self::PNG_IHDR_OFFSET - self::LONG_SIZE) !== self::PNG_HEADER || substr($data, self::PNG_IHDR_OFFSET, self::LONG_SIZE) !== 'IHDR') - { - return; - } - - $this->size = unpack('Nwidth/Nheight', substr($data, self::PNG_IHDR_OFFSET + self::LONG_SIZE, self::LONG_SIZE * 2)); - - $this->set_image_type(IMAGETYPE_PNG); - } - - /** - * Get dimensions of GIF image - * - * @param string $filename Filename of image - * - * @return array|bool Array with image dimensions if successful, false if not - */ - protected function get_gif_size($filename) - { - // Get data needed for reading image dimensions as outlined by GIF87a - // and GIF89a specifications - $data = $this->get_image($filename, 0, self::GIF_HEADER_SIZE + self::SHORT_SIZE * 2); - - $type = substr($data, 0, self::GIF_HEADER_SIZE); - if ($type !== self::GIF87A_HEADER && $type !== self::GIF89A_HEADER) - { - return; - } - - $this->size = unpack('vwidth/vheight', substr($data, self::GIF_HEADER_SIZE, self::SHORT_SIZE * 2)); - - $this->set_image_type(IMAGETYPE_GIF); - } - - /** - * Get dimensions of JPG image - * - * @param string $filename Filename of image - * - * @return array|bool Array with image dimensions if successful, false if not - */ - protected function get_jpeg_size($filename) - { - // Do not force the data length - $data = $this->get_image($filename, 0, self::JPG_MAX_HEADER_SIZE, false); - - // Check if file is jpeg - if ($data[0] !== "\xFF" || $data[1] !== "\xD8") - { - return; - } - - // Look through file for SOF marker - for ($i = 2 * self::SHORT_SIZE; $i < strlen($data); $i++) - { - if ($data[$i] === "\xFF" && in_array($data[$i+1], array("\xC0", "\xC1", "\xC2", "\xC3", "\xC5", "\xC6", "\xC7", "\xC8", "\xC9", "\xCA", "\xCB", "\xCD", "\xCE", "\xCF"))) - { - // Extract size info from SOF marker - list(, $unpacked) = unpack("H*", substr($data, $i + self::SHORT_SIZE, 7)); - - // Get width and height from unpacked size info - $this->size = array( - 'width' => hexdec(substr($unpacked, 10, 4)), - 'height' => hexdec(substr($unpacked, 6, 4)), - ); - - break; - } - } - - $this->set_image_type(IMAGETYPE_JPEG); - } - - /** - * Get dimensions of PSD image - * - * @param string $filename Filename of image - * - * @return array|bool Array with image dimensions if successful, false if not - */ - protected function get_psd_size($filename) - { - $data = $this->get_image($filename, 0, self::PSD_HEADER_SIZE); - - if ($data === false) - { - return; - } - - // Offset for version info is length of header but version is only a - // 16-bit unsigned value - $version = unpack('n', substr($data, self::LONG_SIZE, 2)); - - // Check if supplied file is a PSD file - if (substr($data, 0, self::LONG_SIZE) !== self::PSD_SIGNATURE || $version[1] !== 1) - { - return; - } - - $this->size = unpack('Nheight/Nwidth', substr($data, self::PSD_DIMENSIONS_OFFSET, 2 * self::LONG_SIZE)); - - $this->set_image_type(IMAGETYPE_PSD); - } - - /** - * Get dimensions of BMP image - * - * @param string $filename Filename of image - * - * @return array|bool Array with image dimensions if successful, false if not - */ - protected function get_bmp_size($filename) - { - $data = $this->get_image($filename, 0, self::BMP_HEADER_SIZE); - - // Check if supplied file is a BMP file - if (substr($data, 0, 2) !== self::BMP_SIGNATURE) - { - return; - } - - $this->size = unpack('lwidth/lheight', substr($data, self::BMP_DIMENSIONS_OFFSET, 2 * self::LONG_SIZE)); - - $this->set_image_type(IMAGETYPE_BMP); - } - - /** - * Get dimensions of TIF/TIFF image - * - * @param string $filename Filename of image - * - * @return array|bool Array with image dimensions if successful, false if not - */ - protected function get_tif_size($filename) - { - // Do not force length of header - $data = $this->get_image($filename, 0, self::TIF_HEADER_SIZE, false); - - $signature = substr($data, 0, self::SHORT_SIZE); - - if ($signature !== "II" && $signature !== "MM") - { - return; - } - - if ($signature === "II") - { - $type_long = 'V'; - $type_short = 'v'; - $this->set_image_type(IMAGETYPE_TIFF_II); - } - else - { - $type_long = 'N'; - $type_short = 'n'; - $this->set_image_type(IMAGETYPE_TIFF_MM); - } - - // Get offset of IFD - list(, $offset) = unpack($type_long, substr($data, self::LONG_SIZE, self::LONG_SIZE)); - - // Get size of IFD - list(, $size_ifd) = unpack($type_short, substr($data, $offset, self::SHORT_SIZE)); - - // Skip 2 bytes that define the IFD size - $offset += self::SHORT_SIZE; - - // Filter through IFD - for ($i = 0; $i < $size_ifd; $i++) - { - // Get IFD tag - $type = unpack($type_short, substr($data, $offset, self::SHORT_SIZE)); - - // Get field type of tag - $field_type = unpack($type_short . 'type', substr($data, $offset + self::SHORT_SIZE, self::SHORT_SIZE)); - - // Get IFD entry - $ifd_value = substr($data, $offset + 2 * self::LONG_SIZE, self::LONG_SIZE); - - // Get actual dimensions from IFD - if ($type[1] === self::TIF_TAG_IMAGE_HEIGHT) - { - $this->size = array_merge($this->size, ($field_type['type'] === self::TIF_TAG_TYPE_SHORT) ? unpack($type_short . 'height', $ifd_value) : unpack($type_long . 'height', $ifd_value)); - } - else if ($type[1] === self::TIF_TAG_IMAGE_WIDTH) - { - $this->size = array_merge($this->size, ($field_type['type'] === self::TIF_TAG_TYPE_SHORT) ? unpack($type_short .'width', $ifd_value) : unpack($type_long . 'width', $ifd_value)); - } - - $offset += self::TIF_IFD_ENTRY_SIZE; - } - } - - /** - * Get dimensions of WBMP image - * - * @param string $filename Filename of image - * - * @return array|bool Array with image dimensions if successful, false if not - */ - protected function get_wbmp_size($filename) - { - $data = $this->get_image($filename, 0, self::LONG_SIZE); - - // Check if image is WBMP - if (ord($data[0]) !== 0 || ord($data[1]) !== 0 || $data === substr(self::JPEG_2000_SIGNATURE, 0, 4)) - { - return; - } - - $this->size = unpack('Cwidth/Cheight', substr($data, self::SHORT_SIZE, self::SHORT_SIZE)); - - $this->set_image_type(IMAGETYPE_WBMP); - } - - /** - * Get dimensions of IFF image - * - * @param string $filename Filename of image - * - * @return array|bool Array with image dimensions if successful, false if not - */ - protected function get_iff_size($filename) - { - $data = $this->get_image($filename, 0, self::IFF_HEADER_SIZE); - - $signature = substr($data, 0, self::LONG_SIZE ); - - // Check if image is IFF - if ($signature !== 'FORM' && $signature !== 'FOR4') - { - return; - } - - // Amiga version of IFF - if ($signature === 'FORM') - { - $btmhd_position = strpos($data, 'BMHD'); - $this->size = unpack('nwidth/nheight', substr($data, $btmhd_position + 2 * self::LONG_SIZE, self::LONG_SIZE)); - } - // Maya version - else - { - $btmhd_position = strpos($data, 'BHD'); - $this->size = unpack('Nwidth/Nheight', substr($data, $btmhd_position + 2 * self::LONG_SIZE - 1, self::LONG_SIZE * 2)); - } - - $this->set_image_type(IMAGETYPE_IFF); - } - - /** - * Get dimensions of JPEG 2000 image - * - * @param string $filename Filename of image - * - * @return array|bool Array with image dimensions if successful, false if not - */ - protected function get_jp2_size($filename) - { - $data = $this->get_image($filename, 0, self::JPG_MAX_HEADER_SIZE, false); - - // Check if file is jpeg 2000 - if (substr($data, 0, strlen(self::JPEG_2000_SIGNATURE)) !== self::JPEG_2000_SIGNATURE) - { - return; - } - - // Get SOC position before starting to search for SIZ - $soc_position = strpos($data, "\xFF\x4F"); - - // Make sure we do not get SIZ before SOC - $data = substr($data, $soc_position); - - $siz_position = strpos($data, "\xFF\x51"); - - // Remove SIZ and everything before - $data = substr($data, $siz_position + self::SHORT_SIZE); - - // Acquire size info from data - $this->size = unpack('Nwidth/Nheight', substr($data, self::LONG_SIZE, self::LONG_SIZE * 2)); - - $this->set_image_type(IMAGETYPE_JPEG2000); - } -} From 0a6ac0226d6f32e2cc22a584f08f69d128f0fd60 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 8 Apr 2015 15:41:16 +0200 Subject: [PATCH 0237/1676] [ticket/8672] Update fastImageSize to 1.0.1 PHPBB3-8672 --- phpBB/composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 3bff2429d6..5173e3c27b 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -71,16 +71,16 @@ }, { "name": "marc1706/fast-image-size", - "version": "v1.0.0", + "version": "v1.0.1", "source": { "type": "git", "url": "https://github.com/marc1706/fast-image-size.git", - "reference": "99fb3c4aab631a39db7e8638450b59f562a47bb1" + "reference": "8cb57d887542cdbeddd7d7c85eac6b59e4038687" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/99fb3c4aab631a39db7e8638450b59f562a47bb1", - "reference": "99fb3c4aab631a39db7e8638450b59f562a47bb1", + "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/8cb57d887542cdbeddd7d7c85eac6b59e4038687", + "reference": "8cb57d887542cdbeddd7d7c85eac6b59e4038687", "shasum": "" }, "require": { @@ -118,7 +118,7 @@ "php", "size" ], - "time": "2015-04-07 13:37:04" + "time": "2015-04-08 13:05:30" }, { "name": "patchwork/utf8", From 19011cb8429bbc09c1e0354038423c53a8424c5b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 8 Apr 2015 15:41:52 +0200 Subject: [PATCH 0238/1676] [ticket/8672] Add fastImageSize to clean-vendor-dir in build.xml PHPBB3-8672 --- build/build.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build/build.xml b/build/build.xml index 2e65539035..4e54de5f87 100644 --- a/build/build.xml +++ b/build/build.xml @@ -436,6 +436,15 @@ + + + + + + + + + From 2665e68592a8d1061de6d8d06043c6bed7220d88 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 15 Apr 2015 11:32:52 +0200 Subject: [PATCH 0239/1676] [ticket/8672] Update fastImageSize to 1.0.2 PHPBB3-8672 --- phpBB/composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 5173e3c27b..648dffdfbf 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -71,16 +71,16 @@ }, { "name": "marc1706/fast-image-size", - "version": "v1.0.1", + "version": "v1.0.2", "source": { "type": "git", "url": "https://github.com/marc1706/fast-image-size.git", - "reference": "8cb57d887542cdbeddd7d7c85eac6b59e4038687" + "reference": "ab7b594325cdf6b374d50b3934c8d16dd5249a2a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/8cb57d887542cdbeddd7d7c85eac6b59e4038687", - "reference": "8cb57d887542cdbeddd7d7c85eac6b59e4038687", + "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/ab7b594325cdf6b374d50b3934c8d16dd5249a2a", + "reference": "ab7b594325cdf6b374d50b3934c8d16dd5249a2a", "shasum": "" }, "require": { @@ -118,7 +118,7 @@ "php", "size" ], - "time": "2015-04-08 13:05:30" + "time": "2015-04-09 11:19:59" }, { "name": "patchwork/utf8", From 31bcdb23a2a00f704efcd58877802ed5ac4507a9 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 15 Apr 2015 11:33:13 +0200 Subject: [PATCH 0240/1676] [ticket/8672] Remove unnecessary lines from clean-vendor-dir The new version of fastImageSize already makes sure that these files and/or folders do not exist. PHPBB3-8672 --- build/build.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/build/build.xml b/build/build.xml index 4e54de5f87..2e65539035 100644 --- a/build/build.xml +++ b/build/build.xml @@ -436,15 +436,6 @@ - - - - - - - - - From 55c5bc126decffeaa74abdb853eb010cc3dcda8c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 18 Apr 2015 14:01:21 +0200 Subject: [PATCH 0241/1676] [ticket/8672] User $user->lang() instead of sprintf PHPBB3-8672 --- phpBB/includes/functions_upload.php | 4 ++-- tests/upload/filespec_test.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index ea82a23082..ac5313ca06 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -417,11 +417,11 @@ class filespec { if (!isset($types[$this->image_info['type']])) { - $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info['type'], $this->mimetype); + $this->error[] = $user->lang('IMAGE_FILETYPE_INVALID', $this->image_info['type'], $this->mimetype); } else { - $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info['type']][0], $this->extension); + $this->error[] = $user->lang('IMAGE_FILETYPE_MISMATCH', $types[$this->image_info['type']][0], $this->extension); } } diff --git a/tests/upload/filespec_test.php b/tests/upload/filespec_test.php index 8fbb437ef0..f6deb242a2 100644 --- a/tests/upload/filespec_test.php +++ b/tests/upload/filespec_test.php @@ -287,7 +287,7 @@ class phpbb_filespec_test extends phpbb_test_case array('txt_copy', 'txt_as_img', 'image/jpg', 'txt', false, true), array('txt_copy_2', 'txt_moved', 'text/plain', 'txt', false, true), array('jpg_copy', 'jpg_moved', 'image/png', 'jpg', false, true), - array('png_copy', 'png_moved', 'image/png', 'jpg', 'IMAGE_FILETYPE_MISMATCH', true), + array('png_copy', 'png_moved', 'image/png', 'jpg', 'IMAGE_FILETYPE_MISMATCH png jpg', true), ); } From 9088f448633ff42d767afac674324d1e26911ab6 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 24 Apr 2015 13:38:42 +0200 Subject: [PATCH 0242/1676] [ticket/8672] Update hash of lock file PHPBB3-8672 --- phpBB/composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 648dffdfbf..fce3bbc801 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "91cc998d47b703a7bc4f726217d7a3a9", + "hash": "d5368b75d221b5573b30307cb2f25f3b", "packages": [ { "name": "lusitanian/oauth", From 572a905c02de8cdc6d073ce91f7107e9377e73ac Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 25 Apr 2015 23:41:07 +0200 Subject: [PATCH 0243/1676] [ticket/12745] Updated s9e\TextFormatter PHPBB3-12745 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index adc109b0ee..ce7e0072d7 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -169,12 +169,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "5b7d4c40bdef53f26ca6b09e85163f28e852f16b" + "reference": "31fe627a4a82d41098a2db8036287c0693c79f13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/5b7d4c40bdef53f26ca6b09e85163f28e852f16b", - "reference": "5b7d4c40bdef53f26ca6b09e85163f28e852f16b", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/31fe627a4a82d41098a2db8036287c0693c79f13", + "reference": "31fe627a4a82d41098a2db8036287c0693c79f13", "shasum": "" }, "require": { @@ -219,7 +219,7 @@ "parser", "shortcodes" ], - "time": "2015-04-22 15:15:46" + "time": "2015-04-25 20:58:33" }, { "name": "symfony/config", From 25acba225961e037ea1f7e04259eee3dc4f589ee Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 24 Apr 2015 00:21:32 +0200 Subject: [PATCH 0244/1676] [ticket/12745] Added support for Unicode characters outside BMP PHPBB3-12745 --- phpBB/includes/message_parser.php | 9 --------- tests/functional/posting_test.php | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 8353ae6843..3027566f43 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1241,15 +1241,6 @@ class parse_message extends bbcode_firstpass // Parse this message $this->message = $parser->parse(htmlspecialchars_decode($this->message, ENT_QUOTES)); - // Check for out-of-bounds characters that are currently - // not supported by utf8_bin in MySQL - if (preg_match_all('/[\x{10000}-\x{10FFFF}]/u', $this->message, $matches)) - { - $character_list = implode('
              ', $matches[0]); - $this->warn_msg[] = $user->lang('UNSUPPORTED_CHARACTERS_MESSAGE', $character_list); - return $update_this_message ? $this->warn_msg : $return_message; - } - // Check for "empty" message. We do not check here for maximum length, because bbcode, smilies, etc. can add to the length. // The maximum length check happened before any parsings. if ($mode === 'post' && utf8_clean_string($this->message) === '') diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index fd802eed45..8ac734c733 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -43,14 +43,6 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $this->add_lang('posting'); - self::create_post(2, - 1, - 'Unsupported characters', - "This is a test with these weird characters: \xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6", - array(), - 'Your message contains the following unsupported characters' - ); - self::create_post(2, 1, "Unsupported: \xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6", @@ -59,4 +51,14 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case 'Your subject contains the following unsupported characters' ); } + + public function test_supported_unicode_characters() + { + $this->login(); + + $post = $this->create_topic(2, 'Test Topic 1', 'This is a test topic posted by the testing framework.'); + $this->create_post(2, $post['topic_id'], 'Re: Test Topic 1', "This is a test with these weird characters: \xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6"); + $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); + $this->assertContains("\xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6", $crawler->text()); + } } From 98bdcd0cde8155cdcf3161b5794951d1860071ba Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 25 Apr 2015 17:06:16 +0200 Subject: [PATCH 0245/1676] [ticket/12745] Added HTML entity test https://github.com/phpbb/phpbb/pull/3548#issuecomment-96219167 PHPBB3-12745 --- tests/functional/posting_test.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 8ac734c733..7acf375c5d 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -61,4 +61,14 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); $this->assertContains("\xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6", $crawler->text()); } + + public function test_html_entities() + { + $this->login(); + + $post = $this->create_topic(2, 'Test Topic 1', 'This is a test topic posted by the testing framework.'); + $this->create_post(2, $post['topic_id'], 'Re: Test Topic 1', '😀'); + $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); + $this->assertContains('😀', $crawler->text()); + } } From 102b6c2df377759de8b17f3fe6fa7366fb7385dd Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 28 Apr 2015 02:40:33 +0200 Subject: [PATCH 0246/1676] [ticket/10922] Added support for body and subject in email BBCode PHPBB3-10922 --- phpBB/phpbb/textformatter/s9e/factory.php | 15 +++++++++++++-- .../tickets_data/PHPBB3-10922.html | 4 +++- .../text_processing/tickets_data/PHPBB3-10922.txt | 4 +++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 9576abe1f0..a1bd43e40e 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -68,7 +68,7 @@ class factory implements \phpbb\textformatter\cache_interface 'b' => '[B]{TEXT}[/B]', 'code' => '[CODE]{TEXT}[/CODE]', 'color' => '[COLOR={COLOR}]{TEXT}[/COLOR]', - 'email' => '[EMAIL={EMAIL;useContent}]{TEXT}[/EMAIL]', + 'email' => '[EMAIL={EMAIL;useContent} subject={TEXT;optional;postFilter=urlencode} body={TEXT;optional;postFilter=urlencode}]{TEXT}[/EMAIL]', 'flash' => '[FLASH={NUMBER1},{NUMBER2} width={NUMBER1;postFilter=#flashwidth} height={NUMBER2;postFilter=#flashheight} url={URL;useContent} /]', 'i' => '[I]{TEXT}[/I]', 'img' => '[IMG src={IMAGEURL;useContent}]', @@ -97,7 +97,18 @@ class factory implements \phpbb\textformatter\cache_interface 'img' => '{L_IMAGE}', 'size' => '', 'color' => '', - 'email' => '', + 'email' => ' + + mailto: + + + ? + subject= + &body= + + + + ', ); /** diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.html b/tests/text_processing/tickets_data/PHPBB3-10922.html index cdf8316df0..0c74809377 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10922.html +++ b/tests/text_processing/tickets_data/PHPBB3-10922.html @@ -1 +1,3 @@ -user@example.org... \ No newline at end of file +user@example.org
              +...
              +user@example.org
              diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.txt b/tests/text_processing/tickets_data/PHPBB3-10922.txt index 348f8a1541..a8f09c40f2 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10922.txt +++ b/tests/text_processing/tickets_data/PHPBB3-10922.txt @@ -1 +1,3 @@ -[email]user@example.org[/email][email=user@example.org]...[/email] \ No newline at end of file +[email]user@example.org[/email] +[email=user@example.org]...[/email] +[email subject="Hello" body="Sent from phpBB"]user@example.org[/email] From 3f54fd49b5bf421852ceb2a54395d5ed353d2f29 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 28 Apr 2015 02:53:40 +0200 Subject: [PATCH 0247/1676] [ticket/10922] Replaced urlencode() with rawurlencode() RFC-6068 asks for percent-encoding so that seems more correct. Not sure about that one. PHPBB3-10922 --- phpBB/phpbb/textformatter/s9e/factory.php | 2 +- tests/text_processing/tickets_data/PHPBB3-10922.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index a1bd43e40e..e07a1b52ca 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -68,7 +68,7 @@ class factory implements \phpbb\textformatter\cache_interface 'b' => '[B]{TEXT}[/B]', 'code' => '[CODE]{TEXT}[/CODE]', 'color' => '[COLOR={COLOR}]{TEXT}[/COLOR]', - 'email' => '[EMAIL={EMAIL;useContent} subject={TEXT;optional;postFilter=urlencode} body={TEXT;optional;postFilter=urlencode}]{TEXT}[/EMAIL]', + 'email' => '[EMAIL={EMAIL;useContent} subject={TEXT;optional;postFilter=rawurlencode} body={TEXT;optional;postFilter=rawurlencode}]{TEXT}[/EMAIL]', 'flash' => '[FLASH={NUMBER1},{NUMBER2} width={NUMBER1;postFilter=#flashwidth} height={NUMBER2;postFilter=#flashheight} url={URL;useContent} /]', 'i' => '[I]{TEXT}[/I]', 'img' => '[IMG src={IMAGEURL;useContent}]', diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.html b/tests/text_processing/tickets_data/PHPBB3-10922.html index 0c74809377..6ca9eb0aa1 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10922.html +++ b/tests/text_processing/tickets_data/PHPBB3-10922.html @@ -1,3 +1,3 @@ user@example.org
              ...
              -user@example.org
              +user@example.org
              From 6dc14f4cf0ce968315c9deb57c97a1eabb406dad Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 28 Apr 2015 03:23:21 +0200 Subject: [PATCH 0248/1676] [ticket/10922] Added tests PHPBB3-10922 --- tests/text_processing/tickets_data/PHPBB3-10922.html | 2 ++ tests/text_processing/tickets_data/PHPBB3-10922.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.html b/tests/text_processing/tickets_data/PHPBB3-10922.html index 6ca9eb0aa1..7c375e79a6 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10922.html +++ b/tests/text_processing/tickets_data/PHPBB3-10922.html @@ -1,3 +1,5 @@ user@example.org
              ...
              user@example.org
              +user@example.org
              +user@example.org
              diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.txt b/tests/text_processing/tickets_data/PHPBB3-10922.txt index a8f09c40f2..7a0b245528 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10922.txt +++ b/tests/text_processing/tickets_data/PHPBB3-10922.txt @@ -1,3 +1,5 @@ [email]user@example.org[/email] [email=user@example.org]...[/email] [email subject="Hello" body="Sent from phpBB"]user@example.org[/email] +[email subject="Hi there"]user@example.org[/email] +[email body="Hi there"]user@example.org[/email] From d242610d0fa8ba1d5a462ebf084e834bb210934d Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 28 Apr 2015 15:36:51 +0200 Subject: [PATCH 0249/1676] [ticket/10922] Added test data PHPBB3-10922 --- tests/text_processing/tickets_data/PHPBB3-10922.html | 5 ++++- tests/text_processing/tickets_data/PHPBB3-10922.txt | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.html b/tests/text_processing/tickets_data/PHPBB3-10922.html index 7c375e79a6..0fa80b9960 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10922.html +++ b/tests/text_processing/tickets_data/PHPBB3-10922.html @@ -1,5 +1,8 @@ user@example.org
              ...
              -user@example.org
              +...
              user@example.org
              user@example.org
              +user@example.org
              +user@example.org
              +...
              diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.txt b/tests/text_processing/tickets_data/PHPBB3-10922.txt index 7a0b245528..3db0786eca 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10922.txt +++ b/tests/text_processing/tickets_data/PHPBB3-10922.txt @@ -1,5 +1,8 @@ [email]user@example.org[/email] -[email=user@example.org]...[/email] -[email subject="Hello" body="Sent from phpBB"]user@example.org[/email] +[email=user@example.org ]...[/email] +[email=user@example.org subject="Hello"]...[/email] [email subject="Hi there"]user@example.org[/email] [email body="Hi there"]user@example.org[/email] +[email subject="Hello" body="Sent from phpBB"]user@example.org[/email] +[email body="Sent from phpBB" subject="Hello"]user@example.org[/email] +[email body="Sent from phpBB" subject="Hello" email="user@example.org"]...[/email] From 5c78be56ec0d32a7934bdfd83a4fb0242befc1fa Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 28 Apr 2015 16:17:54 +0200 Subject: [PATCH 0250/1676] [ticket/10922] Added test PHPBB3-10922 --- tests/text_processing/tickets_data/PHPBB3-10922.html | 1 + tests/text_processing/tickets_data/PHPBB3-10922.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.html b/tests/text_processing/tickets_data/PHPBB3-10922.html index 0fa80b9960..3ff117f171 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10922.html +++ b/tests/text_processing/tickets_data/PHPBB3-10922.html @@ -1,5 +1,6 @@ user@example.org
              ...
              +...
              ...
              user@example.org
              user@example.org
              diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.txt b/tests/text_processing/tickets_data/PHPBB3-10922.txt index 3db0786eca..e533ce6ed5 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10922.txt +++ b/tests/text_processing/tickets_data/PHPBB3-10922.txt @@ -1,4 +1,5 @@ [email]user@example.org[/email] +[email=user@example.org]...[/email] [email=user@example.org ]...[/email] [email=user@example.org subject="Hello"]...[/email] [email subject="Hi there"]user@example.org[/email] From 2bbd78ec7de941344852c6f8d006f02444ed4f34 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 29 Apr 2015 23:01:19 +0200 Subject: [PATCH 0251/1676] [ticket/10268] Added regression test PHPBB3-10268 --- tests/text_processing/tickets_data/PHPBB3-10268.html | 4 ++++ tests/text_processing/tickets_data/PHPBB3-10268.txt | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 tests/text_processing/tickets_data/PHPBB3-10268.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-10268.txt diff --git a/tests/text_processing/tickets_data/PHPBB3-10268.html b/tests/text_processing/tickets_data/PHPBB3-10268.html new file mode 100644 index 0000000000..c89e63f9a3 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10268.html @@ -0,0 +1,4 @@ +
              +
              +http://phpbb.com
              + http://phpbb.com
              diff --git a/tests/text_processing/tickets_data/PHPBB3-10268.txt b/tests/text_processing/tickets_data/PHPBB3-10268.txt new file mode 100644 index 0000000000..b4e49c9454 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10268.txt @@ -0,0 +1,4 @@ +[quote="http://phpbb.com"]...[/quote] +[quote=" http://phpbb.com"]...[/quote] +[b]http://phpbb.com[/b] +[b] http://phpbb.com[/b] From c56726e9da0cb483f8e0c88aacc4c3b3e84ee8e4 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 29 Apr 2015 23:59:55 +0200 Subject: [PATCH 0252/1676] [ticket/13641] Added regression test PHPBB3-13641 --- .../tickets_data/PHPBB3-13641.html | 1 + .../tickets_data/PHPBB3-13641.txt | 1 + .../tickets_data/PHPBB3-13641.xml | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 tests/text_processing/tickets_data/PHPBB3-13641.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-13641.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-13641.xml diff --git a/tests/text_processing/tickets_data/PHPBB3-13641.html b/tests/text_processing/tickets_data/PHPBB3-13641.html new file mode 100644 index 0000000000..1bd1c06dbb --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13641.html @@ -0,0 +1 @@ +[color=#FF0000] - red \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13641.txt b/tests/text_processing/tickets_data/PHPBB3-13641.txt new file mode 100644 index 0000000000..58f324715e --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13641.txt @@ -0,0 +1 @@ +[c][color=#FF0000][/c] - [color=#FF0000]red[/color] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13641.xml b/tests/text_processing/tickets_data/PHPBB3-13641.xml new file mode 100644 index 0000000000..451c5c69cd --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13641.xml @@ -0,0 +1,28 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + c + + 1 + [c]{TEXT}[/c] + {TEXT}]]> + + + + ${1}]]> + +
              +
              From 71660301d6467d2cb7a0fc08ee74e13912b6bc42 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 30 Apr 2015 00:09:35 +0200 Subject: [PATCH 0253/1676] [ticket/13425] Added regression test PHPBB3-13425 --- .../tickets_data/PHPBB3-13425.html | 1 + .../tickets_data/PHPBB3-13425.txt | 1 + .../tickets_data/PHPBB3-13425.xml | 23 +++++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/text_processing/tickets_data/PHPBB3-13425.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-13425.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-13425.xml diff --git a/tests/text_processing/tickets_data/PHPBB3-13425.html b/tests/text_processing/tickets_data/PHPBB3-13425.html new file mode 100644 index 0000000000..9a042dc558 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13425.html @@ -0,0 +1 @@ +
              :lol: starts with a smiley
              \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13425.txt b/tests/text_processing/tickets_data/PHPBB3-13425.txt new file mode 100644 index 0000000000..8456410df5 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13425.txt @@ -0,0 +1 @@ +[quote]:lol: starts with a smiley[/quote] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13425.xml b/tests/text_processing/tickets_data/PHPBB3-13425.xml new file mode 100644 index 0000000000..cbdcaa7fb7 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13425.xml @@ -0,0 +1,23 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 22 + :lol: + Laughing + icon_lol.gif + 15 + 17 + 22 + 1 + +
              +
              From abb4a2f6de615f0a371925b1d99733b2d536e771 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 30 Apr 2015 00:21:43 +0200 Subject: [PATCH 0254/1676] [ticket/8419] Added regression test PHPBB3-8419 --- .../tickets_data/PHPBB3-8419.html | 1 + .../tickets_data/PHPBB3-8419.txt | 1 + .../tickets_data/PHPBB3-8419.xml | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 tests/text_processing/tickets_data/PHPBB3-8419.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-8419.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-8419.xml diff --git a/tests/text_processing/tickets_data/PHPBB3-8419.html b/tests/text_processing/tickets_data/PHPBB3-8419.html new file mode 100644 index 0000000000..38df626a94 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-8419.html @@ -0,0 +1 @@ +tę przykład \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-8419.txt b/tests/text_processing/tickets_data/PHPBB3-8419.txt new file mode 100644 index 0000000000..dac47823b6 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-8419.txt @@ -0,0 +1 @@ +[ort]tę [/ort]przykład \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-8419.xml b/tests/text_processing/tickets_data/PHPBB3-8419.xml new file mode 100644 index 0000000000..2f1df345f9 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-8419.xml @@ -0,0 +1,28 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + myemail + + 1 + [ort]{TEXT}[/ort] + {TEXT}]]> + + + + ${1}]]> + +
              +
              From 66ad8051271eb0b5ea6368214ed1058b1fd3b818 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 30 Apr 2015 00:35:32 +0200 Subject: [PATCH 0255/1676] [ticket/9073] Added regression test PHPBB3-9073 --- .../text_processing/tickets_data/PHPBB3-9073.html | 2 ++ tests/text_processing/tickets_data/PHPBB3-9073.txt | 2 ++ tests/text_processing/tickets_data/PHPBB3-9073.xml | 14 ++++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 tests/text_processing/tickets_data/PHPBB3-9073.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-9073.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-9073.xml diff --git a/tests/text_processing/tickets_data/PHPBB3-9073.html b/tests/text_processing/tickets_data/PHPBB3-9073.html new file mode 100644 index 0000000000..ff1f9fd0ce --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9073.html @@ -0,0 +1,2 @@ +http://www.xxxx-xx-xxxx.com/
              +http://www.xxxx-xx-xxxx.com/
              diff --git a/tests/text_processing/tickets_data/PHPBB3-9073.txt b/tests/text_processing/tickets_data/PHPBB3-9073.txt new file mode 100644 index 0000000000..2c271173ce --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9073.txt @@ -0,0 +1,2 @@ +http://www.some-ad-site.com/ +[url]http://www.some-ad-site.com/[/url] diff --git a/tests/text_processing/tickets_data/PHPBB3-9073.xml b/tests/text_processing/tickets_data/PHPBB3-9073.xml new file mode 100644 index 0000000000..d635d51ed1 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9073.xml @@ -0,0 +1,14 @@ + + + + word_id + word + replacement + + + 1 + http://www.some-ad-site.com* + http://www.xxxx-xx-xxxx.com + +
              +
              From 57072a1e28061ff51148c7d6a0c47664f0060639 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Wed, 29 Apr 2015 00:13:29 +0200 Subject: [PATCH 0256/1676] [ticket/13793] Remove translation on throwing exceptions PHPBB3-13793 --- phpBB/config/default/container/services.yml | 2 -- phpBB/includes/acp/acp_extensions.php | 14 ++++++---- phpBB/phpbb/controller/exception.php | 2 +- phpBB/phpbb/controller/resolver.php | 18 ++++--------- phpBB/phpbb/extension/exception.php | 6 +---- phpBB/phpbb/extension/manager.php | 7 ++--- phpBB/phpbb/extension/metadata_manager.php | 26 +++++++------------ phpBB/phpbb/notification/exception.php | 6 +---- phpBB/phpbb/notification/manager.php | 2 +- tests/controller/controller_test.php | 2 +- tests/dbal/migrator_test.php | 2 -- tests/extension/manager_test.php | 2 -- tests/extension/metadata_manager_test.php | 23 +++++++++------- .../phpbb_functional_test_case.php | 2 -- 14 files changed, 44 insertions(+), 70 deletions(-) diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 682eaeb200..11032408d7 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -86,7 +86,6 @@ services: controller.resolver: class: phpbb\controller\resolver arguments: - - @user - @service_container - %core.root_path% - @template @@ -98,7 +97,6 @@ services: - @dbal.conn - @config - @filesystem - - @user - %tables.ext% - %core.root_path% - %core.php_ext% diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 0c9bc0deab..cbef13dfd0 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -70,7 +70,7 @@ class acp_extensions // If they've specified an extension, let's load the metadata manager and validate it. if ($ext_name) { - $md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $template, $user, $phpbb_root_path); + $md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $template, $phpbb_root_path); try { @@ -78,7 +78,8 @@ class acp_extensions } catch(\phpbb\extension\exception $e) { - trigger_error($e, E_USER_WARNING); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + trigger_error($message, E_USER_WARNING); } } @@ -354,8 +355,9 @@ class acp_extensions } catch(\phpbb\extension\exception $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message), 'S_VERSIONCHECK' => false, )); } @@ -410,8 +412,9 @@ class acp_extensions } catch(\phpbb\extension\exception $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message), 'S_VERSIONCHECK' => false, )); } @@ -469,8 +472,9 @@ class acp_extensions } catch(\phpbb\extension\exception $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message), 'S_VERSIONCHECK' => false, )); } diff --git a/phpBB/phpbb/controller/exception.php b/phpBB/phpbb/controller/exception.php index 437558b06a..e227c7c37b 100644 --- a/phpBB/phpbb/controller/exception.php +++ b/phpBB/phpbb/controller/exception.php @@ -16,6 +16,6 @@ namespace phpbb\controller; /** * Controller exception class */ -class exception extends \RuntimeException +class exception extends \phpbb\exception\runtime_exception { } diff --git a/phpBB/phpbb/controller/resolver.php b/phpBB/phpbb/controller/resolver.php index 948a6a218c..4f432c3323 100644 --- a/phpBB/phpbb/controller/resolver.php +++ b/phpBB/phpbb/controller/resolver.php @@ -22,12 +22,6 @@ use Symfony\Component\HttpFoundation\Request; */ class resolver implements ControllerResolverInterface { - /** - * User object - * @var \phpbb\user - */ - protected $user; - /** * ContainerInterface object * @var ContainerInterface @@ -55,14 +49,12 @@ class resolver implements ControllerResolverInterface /** * Construct method * - * @param \phpbb\user $user User Object * @param ContainerInterface $container ContainerInterface object * @param string $phpbb_root_path Relative path to phpBB root * @param \phpbb\template\template $template */ - public function __construct(\phpbb\user $user, ContainerInterface $container, $phpbb_root_path, \phpbb\template\template $template = null) + public function __construct(ContainerInterface $container, $phpbb_root_path, \phpbb\template\template $template = null) { - $this->user = $user; $this->container = $container; $this->template = $template; $this->type_cast_helper = new \phpbb\request\type_cast_helper(); @@ -82,20 +74,20 @@ class resolver implements ControllerResolverInterface if (!$controller) { - throw new \phpbb\controller\exception($this->user->lang['CONTROLLER_NOT_SPECIFIED']); + throw new \phpbb\controller\exception('CONTROLLER_NOT_SPECIFIED'); } // Require a method name along with the service name if (stripos($controller, ':') === false) { - throw new \phpbb\controller\exception($this->user->lang['CONTROLLER_METHOD_NOT_SPECIFIED']); + throw new \phpbb\controller\exception('CONTROLLER_METHOD_NOT_SPECIFIED'); } list($service, $method) = explode(':', $controller); if (!$this->container->has($service)) { - throw new \phpbb\controller\exception($this->user->lang('CONTROLLER_SERVICE_UNDEFINED', $service)); + throw new \phpbb\controller\exception('CONTROLLER_SERVICE_UNDEFINED', array($service)); } $controller_object = $this->container->get($service); @@ -166,7 +158,7 @@ class resolver implements ControllerResolverInterface } else { - throw new \phpbb\controller\exception($this->user->lang('CONTROLLER_ARGUMENT_VALUE_MISSING', $param->getPosition() + 1, get_class($object) . ':' . $method, $param->name)); + throw new \phpbb\controller\exception('CONTROLLER_ARGUMENT_VALUE_MISSING', array($param->getPosition() + 1, get_class($object) . ':' . $method, $param->name)); } } diff --git a/phpBB/phpbb/extension/exception.php b/phpBB/phpbb/extension/exception.php index 3f7d251a4e..9050449bf1 100644 --- a/phpBB/phpbb/extension/exception.php +++ b/phpBB/phpbb/extension/exception.php @@ -16,10 +16,6 @@ namespace phpbb\extension; /** * Exception class for metadata */ -class exception extends \UnexpectedValueException +class exception extends \phpbb\exception\runtime_exception { - public function __toString() - { - return $this->getMessage(); - } } diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 40fda74065..98d2d27278 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -26,7 +26,6 @@ class manager protected $db; protected $config; protected $cache; - protected $user; protected $php_ext; protected $extensions; protected $extension_table; @@ -40,14 +39,13 @@ class manager * @param \phpbb\db\driver\driver_interface $db A database connection * @param \phpbb\config\config $config Config object * @param \phpbb\filesystem\filesystem_interface $filesystem - * @param \phpbb\user $user User object * @param string $extension_table The name of the table holding extensions * @param string $phpbb_root_path Path to the phpbb includes directory. * @param string $php_ext php file extension, defaults to php * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null * @param string $cache_name The name of the cache variable, defaults to _ext */ - public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\user $user, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext') + public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem\filesystem_interface $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext') { $this->cache = $cache; $this->cache_name = $cache_name; @@ -58,7 +56,6 @@ class manager $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - $this->user = $user; $this->extensions = ($this->cache) ? $this->cache->get($this->cache_name) : false; @@ -154,7 +151,7 @@ class manager */ public function create_extension_metadata_manager($name, \phpbb\template\template $template) { - return new \phpbb\extension\metadata_manager($name, $this->config, $this, $template, $this->user, $this->phpbb_root_path); + return new \phpbb\extension\metadata_manager($name, $this->config, $this, $template, $this->phpbb_root_path); } /** diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index a64d88fe39..4f080647c8 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -36,12 +36,6 @@ class metadata_manager */ protected $template; - /** - * phpBB User instance - * @var \phpbb\user - */ - protected $user; - /** * phpBB root path * @var string @@ -73,15 +67,13 @@ class metadata_manager * @param \phpbb\config\config $config phpBB Config instance * @param \phpbb\extension\manager $extension_manager An instance of the phpBB extension manager * @param \phpbb\template\template $template phpBB Template instance - * @param \phpbb\user $user User instance * @param string $phpbb_root_path Path to the phpbb includes directory. */ - public function __construct($ext_name, \phpbb\config\config $config, \phpbb\extension\manager $extension_manager, \phpbb\template\template $template, \phpbb\user $user, $phpbb_root_path) + public function __construct($ext_name, \phpbb\config\config $config, \phpbb\extension\manager $extension_manager, \phpbb\template\template $template, $phpbb_root_path) { $this->config = $config; $this->extension_manager = $extension_manager; $this->template = $template; - $this->user = $user; $this->phpbb_root_path = $phpbb_root_path; $this->ext_name = $ext_name; @@ -149,7 +141,7 @@ class metadata_manager if (!file_exists($this->metadata_file)) { - throw new \phpbb\extension\exception($this->user->lang('FILE_NOT_FOUND', $this->metadata_file)); + throw new \phpbb\extension\exception('FILE_NOT_FOUND', array($this->metadata_file)); } } @@ -163,18 +155,18 @@ class metadata_manager { if (!file_exists($this->metadata_file)) { - throw new \phpbb\extension\exception($this->user->lang('FILE_NOT_FOUND', $this->metadata_file)); + throw new \phpbb\extension\exception('FILE_NOT_FOUND', array($this->metadata_file)); } else { if (!($file_contents = file_get_contents($this->metadata_file))) { - throw new \phpbb\extension\exception($this->user->lang('FILE_CONTENT_ERR', $this->metadata_file)); + throw new \phpbb\extension\exception('FILE_CONTENT_ERR', array($this->metadata_file)); } if (($metadata = json_decode($file_contents, true)) === null) { - throw new \phpbb\extension\exception($this->user->lang('FILE_JSON_DECODE_ERR', $this->metadata_file)); + throw new \phpbb\extension\exception('FILE_JSON_DECODE_ERR', array($this->metadata_file)); } array_walk_recursive($metadata, array($this, 'sanitize_json')); @@ -246,12 +238,12 @@ class metadata_manager { if (!isset($this->metadata[$name])) { - throw new \phpbb\extension\exception($this->user->lang('META_FIELD_NOT_SET', $name)); + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array($name)); } if (!preg_match($fields[$name], $this->metadata[$name])) { - throw new \phpbb\extension\exception($this->user->lang('META_FIELD_INVALID', $name)); + throw new \phpbb\extension\exception('META_FIELD_INVALID', array($name)); } } break; @@ -270,14 +262,14 @@ class metadata_manager { if (empty($this->metadata['authors'])) { - throw new \phpbb\extension\exception($this->user->lang('META_FIELD_NOT_SET', 'authors')); + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('authors')); } foreach ($this->metadata['authors'] as $author) { if (!isset($author['name'])) { - throw new \phpbb\extension\exception($this->user->lang('META_FIELD_NOT_SET', 'author name')); + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('author name')); } } diff --git a/phpBB/phpbb/notification/exception.php b/phpBB/phpbb/notification/exception.php index 83c4526df7..e416438061 100644 --- a/phpBB/phpbb/notification/exception.php +++ b/phpBB/phpbb/notification/exception.php @@ -17,10 +17,6 @@ namespace phpbb\notification; * Notifications exception */ -class exception extends \Exception +class exception extends \phpbb\exception\runtime_exception { - public function __toString() - { - return $this->getMessage(); - } } diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index db92170dd8..38d7a13165 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -943,7 +943,7 @@ class manager { if (!isset($this->notification_types[$notification_type_name]) && !isset($this->notification_types['notification.type.' . $notification_type_name])) { - throw new \phpbb\notification\exception($this->user->lang('NOTIFICATION_TYPE_NOT_EXIST', $notification_type_name)); + throw new \phpbb\notification\exception('NOTIFICATION_TYPE_NOT_EXIST', array($notification_type_name)); } $sql = 'INSERT INTO ' . $this->notification_types_table . ' ' . $this->db->sql_build_array('INSERT', array( diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php index a837e25f66..5c0290ee6f 100644 --- a/tests/controller/controller_test.php +++ b/tests/controller/controller_test.php @@ -82,7 +82,7 @@ class phpbb_controller_controller_test extends phpbb_test_case include(__DIR__.'/phpbb/controller/foo.php'); } - $resolver = new \phpbb\controller\resolver(new \phpbb\user('\phpbb\datetime'), $container, dirname(__FILE__) . '/'); + $resolver = new \phpbb\controller\resolver($container, dirname(__FILE__) . '/'); $symfony_request = new Request(); $symfony_request->attributes->set('_controller', 'foo.controller:handle'); diff --git a/tests/dbal/migrator_test.php b/tests/dbal/migrator_test.php index d550ca55a2..f52e6ea63d 100644 --- a/tests/dbal/migrator_test.php +++ b/tests/dbal/migrator_test.php @@ -63,14 +63,12 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case ); $container->set('migrator', $this->migrator); $container->set('dispatcher', new phpbb_mock_event_dispatcher()); - $user = new \phpbb\user('\phpbb\datetime'); $this->extension_manager = new \phpbb\extension\manager( $container, $this->db, $this->config, new phpbb\filesystem\filesystem(), - $user, 'phpbb_ext', dirname(__FILE__) . '/../../phpBB/', 'php', diff --git a/tests/extension/manager_test.php b/tests/extension/manager_test.php index b76203b32a..a24b0cf178 100644 --- a/tests/extension/manager_test.php +++ b/tests/extension/manager_test.php @@ -155,7 +155,6 @@ class phpbb_extension_manager_test extends phpbb_database_test_case $phpbb_root_path = __DIR__ . './../../phpBB/'; $php_ext = 'php'; $table_prefix = 'phpbb_'; - $user = new \phpbb\user('\phpbb\user'); $container = new phpbb_mock_container_builder(); @@ -178,7 +177,6 @@ class phpbb_extension_manager_test extends phpbb_database_test_case $db, $config, new \phpbb\filesystem\filesystem(), - $user, 'phpbb_ext', dirname(__FILE__) . '/', $php_ext, diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index db573ae0c3..c269eee987 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -99,7 +99,6 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $this->db, $this->config, new \phpbb\filesystem\filesystem(), - $this->user, 'phpbb_ext', $this->phpbb_root_path, $this->phpEx, @@ -120,7 +119,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case } catch (\phpbb\extension\exception $e) { - $this->assertEquals((string) $e, $this->user->lang('FILE_NOT_FOUND', $this->phpbb_root_path . $this->extension_manager->get_extension_path($ext_name) . 'composer.json')); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $this->assertEquals($message, $this->user->lang('FILE_NOT_FOUND', $this->phpbb_root_path . $this->extension_manager->get_extension_path($ext_name) . 'composer.json')); } } @@ -137,7 +137,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case } catch (\phpbb\extension\exception $e) { - $this->fail($e); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $this->fail($message); } $json = json_decode(file_get_contents($this->phpbb_root_path . 'ext/vendor2/foo/composer.json'), true); @@ -169,7 +170,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case } catch(\phpbb\extension\exception $e) { - $this->assertEquals((string) $e, $this->user->lang('META_FIELD_NOT_SET', $field_name)); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', $field_name)); } } @@ -183,7 +185,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case } catch (\phpbb\extension\exception $e) { - $this->assertEquals((string) $e, $this->user->lang('META_FIELD_NOT_SET', 'authors')); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', 'authors')); } $manager->merge_metadata(array( @@ -199,7 +202,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case } catch (\phpbb\extension\exception $e) { - $this->assertEquals((string) $e, $this->user->lang('META_FIELD_NOT_SET', 'author name')); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', 'author name')); } } @@ -232,7 +236,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case } catch(\phpbb\extension\exception $e) { - $this->assertEquals((string) $e, $this->user->lang('META_FIELD_INVALID', $field_name)); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $this->assertEquals($message, $this->user->lang('META_FIELD_INVALID', $field_name)); } } @@ -256,7 +261,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case } catch(\phpbb\extension\exception $e) { - $this->fail($e); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $this->fail($message); } } @@ -352,7 +358,6 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $this->config, $this->extension_manager, $this->template, - $this->user, $this->phpbb_root_path ); } diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index daa570caf6..c1ec287477 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -248,14 +248,12 @@ class phpbb_functional_test_case extends phpbb_test_case ); $container->set('migrator', $migrator); $container->set('dispatcher', new phpbb_mock_event_dispatcher()); - $user = new \phpbb\user('\phpbb\datetime'); $extension_manager = new \phpbb\extension\manager( $container, $db, $config, new phpbb\filesystem\filesystem(), - $user, self::$config['table_prefix'] . 'ext', dirname(__FILE__) . '/', $phpEx, From e5a167e6c2fb3159c1b8ac1587e39994ef4fb553 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 2 May 2015 01:53:11 +0200 Subject: [PATCH 0257/1676] [ticket/13805] Updated generate_text_for_storage() to match message_parser PHPBB3-13805 --- phpBB/includes/functions_content.php | 16 ++- .../generate_text_for_storage_test.php | 120 +++++++++++++++++- 2 files changed, 129 insertions(+), 7 deletions(-) diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 60511d89a4..5cebc54eb2 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -560,10 +560,14 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text * @param bool $allow_bbcode If BBCode is allowed (i.e. if BBCode is parsed) * @param bool $allow_urls If urls is allowed * @param bool $allow_smilies If smilies are allowed +* @param bool $allow_img_bbcode +* @param bool $allow_flash_bbcode +* @param bool $allow_quote_bbcode +* @param bool $allow_url_bbcode * * @return array An array of string with the errors that occurred while parsing */ -function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false) +function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true) { global $phpbb_root_path, $phpEx, $phpbb_dispatcher; @@ -578,6 +582,10 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb * @var bool allow_bbcode Whether or not to parse BBCode * @var bool allow_urls Whether or not to parse URLs * @var bool allow_smilies Whether or not to parse Smilies + * @var bool allow_img_bbcode Whether or not to parse the [img] BBCode + * @var bool allow_flash_bbcode Whether or not to parse the [flash] BBCode + * @var bool allow_quote_bbcode Whether or not to parse the [quote] BBCode + * @var bool allow_url_bbcode Whether or not to parse the [url] BBCode * @since 3.1.0-a1 */ $vars = array( @@ -588,6 +596,10 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb 'allow_bbcode', 'allow_urls', 'allow_smilies', + 'allow_img_bbcode', + 'allow_flash_bbcode', + 'allow_quote_bbcode', + 'allow_url_bbcode', ); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_storage_before', compact($vars))); @@ -600,7 +612,7 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb } $message_parser = new parse_message($text); - $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies); + $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode); $text = $message_parser->message; $uid = $message_parser->bbcode_uid; diff --git a/tests/text_processing/generate_text_for_storage_test.php b/tests/text_processing/generate_text_for_storage_test.php index ffa06e4e02..474f6d8f0f 100644 --- a/tests/text_processing/generate_text_for_storage_test.php +++ b/tests/text_processing/generate_text_for_storage_test.php @@ -12,6 +12,7 @@ */ require_once __DIR__ . '/../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../phpBB/includes/functions_compatibility.php'; require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php'; @@ -36,7 +37,7 @@ class phpbb_text_processing_generate_text_for_storage_test extends phpbb_test_ca /** * @dataProvider get_text_formatter_tests */ - public function test_text_formatter($original, $expected, $allow_bbcode = true, $allow_urls = true, $allow_smilies = true, $setup = null) + public function test_text_formatter($original, $expected, $allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode, $setup = null) { $actual = $original; $uid = ''; @@ -48,7 +49,7 @@ class phpbb_text_processing_generate_text_for_storage_test extends phpbb_test_ca $setup(); } - generate_text_for_storage($actual, $uid, $bitfield, $flags, $allow_bbcode, $allow_urls, $allow_smilies); + generate_text_for_storage($actual, $uid, $bitfield, $flags, $allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode); $this->assertSame($expected, $actual); } @@ -58,15 +59,124 @@ class phpbb_text_processing_generate_text_for_storage_test extends phpbb_test_ca return array( array( 'Hello world', - 'Hello world' + 'Hello world', + true, + true, + true, + true, + true, + true, + true, ), array( 'Hello [url=http://example.org]world[/url] :)', - 'Hello [url=http://example.org]world[/url] :)' + 'Hello [url=http://example.org]world[/url] :)', + true, + true, + true, + true, + true, + true, + true, ), array( '&<>"\'', - '&<>"\'' + '&<>"\'', + true, + true, + true, + true, + true, + true, + true, + ), + array( + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + false, + false, + false, + false, + false, + false, + false, + ), + array( + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + true, + false, + false, + false, + false, + false, + false, + ), + array( + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + false, + true, + false, + false, + false, + false, + true, + ), + array( + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + false, + false, + true, + false, + false, + false, + false, + ), + array( + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + true, + false, + false, + true, + false, + false, + false, + ), + array( + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + true, + false, + false, + false, + true, + false, + false, + ), + array( + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + true, + false, + false, + false, + false, + true, + false, + ), + array( + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', + true, + false, + false, + false, + false, + false, + true, ), ); } From 179a4700221aa49071b07d638c44b9326c7a14a8 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Tue, 14 Apr 2015 02:31:23 +0200 Subject: [PATCH 0258/1676] [ticket/13762] Moving language related functionality into a separate class PHPBB3-13762 --- phpBB/composer.json | 2 +- phpBB/config/default/container/services.yml | 1 + .../default/container/services_language.yml | 22 + .../default/container/services_user.yml | 1 + phpBB/includes/acp/acp_extensions.php | 8 +- phpBB/includes/acp/acp_language.php | 38 +- phpBB/includes/functions.php | 180 +----- phpBB/includes/functions_compatibility.php | 19 + phpBB/includes/functions_user.php | 2 +- phpBB/install/index.php | 8 +- .../captcha/plugins/captcha_abstract.php | 2 +- .../invalid_plural_rule_exception.php | 22 + .../language/exception/language_exception.php | 22 + .../exception/language_file_not_found.php | 22 + phpBB/phpbb/language/language.php | 562 ++++++++++++++++++ phpBB/phpbb/language/language_file_helper.php | 71 +++ phpBB/phpbb/language/language_file_loader.php | 212 +++++++ phpBB/phpbb/user.php | 336 ++++------- tests/auth/provider_apache_test.php | 4 +- tests/auth/provider_db_test.php | 4 +- .../provider_oauth_token_storage_test.php | 4 +- tests/avatar/manager_test.php | 11 +- tests/console/cache/purge_test.php | 7 +- tests/console/config/config_test.php | 7 +- tests/console/cron/cron_list_test.php | 7 +- tests/console/cron/run_test.php | 5 +- tests/content_visibility/delete_post_test.php | 4 +- .../get_forums_visibility_sql_test.php | 4 +- .../get_global_visibility_sql_test.php | 4 +- .../get_visibility_sql_test.php | 4 +- .../set_post_visibility_test.php | 8 +- .../set_topic_visibility_test.php | 4 +- tests/controller/common_helper_route.php | 4 +- tests/datetime/from_format_test.php | 12 +- tests/dbal/migrator_tool_module_test.php | 4 +- tests/event/exception_listener_test.php | 6 +- tests/extension/metadata_manager_test.php | 20 +- tests/functions/generate_string_list.php | 9 +- tests/groupposition/legend_test.php | 42 +- tests/groupposition/teampage_test.php | 48 +- tests/language/language_test.php | 210 +++++++ tests/log/add_test.php | 8 +- tests/log/delete_test.php | 4 +- tests/log/function_add_log_test.php | 5 +- tests/notification/base.php | 7 +- tests/notification/submit_post_base.php | 5 +- tests/notification/user_list_trim_test.php | 14 +- tests/pagination/pagination_test.php | 7 +- tests/plupload/plupload_test.php | 6 +- tests/profilefields/type_bool_test.php | 7 +- tests/profilefields/type_date_test.php | 7 +- tests/profilefields/type_dropdown_test.php | 7 +- tests/profilefields/type_googleplus_test.php | 6 +- tests/profilefields/type_int_test.php | 7 +- tests/profilefields/type_string_test.php | 7 +- tests/profilefields/type_url_test.php | 7 +- tests/security/base.php | 4 +- tests/template/template_allfolder_test.php | 5 +- tests/template/template_test_case.php | 22 +- .../phpbb_functional_test_case.php | 10 +- .../phpbb_test_case_helpers.php | 4 +- tests/text_formatter/s9e/renderer_test.php | 54 +- .../generate_text_for_display_test.php | 30 +- tests/user/lang_test.php | 119 ---- tests/version/version_fetch_test.php | 4 +- tests/version/version_helper_remote_test.php | 6 +- tests/version/version_test.php | 18 +- 67 files changed, 1663 insertions(+), 679 deletions(-) create mode 100644 phpBB/config/default/container/services_language.yml create mode 100644 phpBB/phpbb/language/exception/invalid_plural_rule_exception.php create mode 100644 phpBB/phpbb/language/exception/language_exception.php create mode 100644 phpBB/phpbb/language/exception/language_file_not_found.php create mode 100644 phpBB/phpbb/language/language.php create mode 100644 phpBB/phpbb/language/language_file_helper.php create mode 100644 phpBB/phpbb/language/language_file_loader.php create mode 100644 tests/language/language_test.php delete mode 100644 tests/user/lang_test.php diff --git a/phpBB/composer.json b/phpBB/composer.json index 31462b81eb..419779e5f7 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -35,6 +35,7 @@ "symfony/dependency-injection": "2.8.*@dev", "symfony/event-dispatcher": "2.8.*@dev", "symfony/filesystem": "2.8.*@dev", + "symfony/finder": "2.8.*@dev", "symfony/http-kernel": "2.8.*@dev", "symfony/routing": "2.8.*@dev", "symfony/security-core": "2.8.*@dev", @@ -54,7 +55,6 @@ "symfony/css-selector": "2.8.*@dev", "symfony/debug": "2.8.*@dev", "symfony/dom-crawler": "2.8.*@dev", - "symfony/finder": "2.8.*@dev", "symfony/http-foundation": "2.8.*@dev", "symfony/process": "2.8.*@dev" } diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 11032408d7..670ea3bd61 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -9,6 +9,7 @@ imports: - { resource: services_event.yml } - { resource: services_feed.yml } - { resource: services_help.yml } + - { resource: services_language.yml } - { resource: services_mimetype_guesser.yml } - { resource: services_notification.yml } - { resource: services_password.yml } diff --git a/phpBB/config/default/container/services_language.yml b/phpBB/config/default/container/services_language.yml new file mode 100644 index 0000000000..aa3631ded1 --- /dev/null +++ b/phpBB/config/default/container/services_language.yml @@ -0,0 +1,22 @@ +services: + language.helper.language_file: + class: phpbb\language\language_file_helper + arguments: + - %core.root_path% + + language: + class: phpbb\language\language + arguments: + - @language.loader + + language.loader_abstract: + abstract: true + class: phpbb\language\language_file_loader + arguments: + - %core.root_path% + - %core.php_ext% + + language.loader: + parent: language.loader_abstract + calls: + - [set_extension_manager, ["@ext.manager"]] diff --git a/phpBB/config/default/container/services_user.yml b/phpBB/config/default/container/services_user.yml index 1ca853ea45..ff114f022a 100644 --- a/phpBB/config/default/container/services_user.yml +++ b/phpBB/config/default/container/services_user.yml @@ -8,6 +8,7 @@ services: user: class: phpbb\user arguments: + - @language - %datetime.class% user_loader: diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index cbef13dfd0..0373a3b115 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -76,7 +76,7 @@ class acp_extensions { $md_manager->get_metadata('all'); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); trigger_error($message, E_USER_WARNING); @@ -353,7 +353,7 @@ class acp_extensions $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( @@ -410,7 +410,7 @@ class acp_extensions $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $disabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( @@ -470,7 +470,7 @@ class acp_extensions $available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $available_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 3fd118b0dd..e7ee7f47d6 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -31,7 +31,7 @@ class acp_language function main($id, $mode) { - global $config, $db, $user, $template, $phpbb_log; + global $config, $db, $user, $template, $phpbb_log, $phpbb_container; global $phpbb_root_path, $phpEx, $request; include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -377,37 +377,19 @@ class acp_language $db->sql_freeresult($result); $new_ary = $iso = array(); - $dp = @opendir("{$phpbb_root_path}language"); - if ($dp) + /** @var \phpbb\language\language_file_helper $language_helper */ + $language_helper = $phpbb_container->get('language.helper.language_file'); + $iso = $language_helper->get_available_languages(); + + foreach ($iso as $lang_array) { - while (($file = readdir($dp)) !== false) - { - if ($file[0] == '.' || !is_dir($phpbb_root_path . 'language/' . $file)) - { - continue; - } + $lang_iso = $lang_array['iso']; - if (file_exists("{$phpbb_root_path}language/$file/iso.txt")) - { - if (!in_array($file, $installed)) - { - if ($iso = file("{$phpbb_root_path}language/$file/iso.txt")) - { - if (sizeof($iso) == 3) - { - $new_ary[$file] = array( - 'iso' => $file, - 'name' => trim($iso[0]), - 'local_name'=> trim($iso[1]), - 'author' => trim($iso[2]) - ); - } - } - } - } + if (!in_array($lang_iso, $installed)) + { + $new_ary[$lang_iso] = $lang_array; } - closedir($dp); } unset($installed); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 98b5af372a..2ed0eff81c 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1719,7 +1719,7 @@ function redirect($url, $return = false, $disable_cd_check = false) $failover_flag = false; - if (empty($user->lang)) + if (!$user->is_setup()) { $user->add_lang('common'); } @@ -2243,7 +2243,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa $err = ''; // Make sure user->setup() has been called - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } @@ -3268,7 +3268,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) case E_USER_ERROR: - if (!empty($user) && !empty($user->lang)) + if (!empty($user) && $user->is_setup()) { $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text; $msg_title = (!isset($msg_title)) ? $user->lang['GENERAL_ERROR'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title); @@ -3388,7 +3388,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) // We re-init the auth array to get correct results on login/logout $auth->acl($user->data); - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } @@ -3761,178 +3761,6 @@ function phpbb_optionset($bit, $set, $data) return $data; } -/** -* Determine which plural form we should use. -* For some languages this is not as simple as for English. -* -* @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules -* @param $number int|float The number we want to get the plural case for. Float numbers are floored. -* @return int The plural-case we need to use for the number plural-rule combination -*/ -function phpbb_get_plural_form($rule, $number) -{ - $number = (int) $number; - - if ($rule > 15 || $rule < 0) - { - trigger_error('INVALID_PLURAL_RULE'); - } - - /** - * The following plural rules are based on a list published by the Mozilla Developer Network - * https://developer.mozilla.org/en/Localization_and_Plurals - */ - switch ($rule) - { - case 0: - /** - * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao - * 1 - everything: 0, 1, 2, ... - */ - return 1; - - case 1: - /** - * Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish), Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek), Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan) - * 1 - 1 - * 2 - everything else: 0, 2, 3, ... - */ - return ($number == 1) ? 1 : 2; - - case 2: - /** - * Families: Romanic (French, Brazilian Portuguese) - * 1 - 0, 1 - * 2 - everything else: 2, 3, ... - */ - return (($number == 0) || ($number == 1)) ? 1 : 2; - - case 3: - /** - * Families: Baltic (Latvian) - * 1 - 0 - * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ... - * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ... - */ - return ($number == 0) ? 1 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 2 : 3); - - case 4: - /** - * Families: Celtic (Scottish Gaelic) - * 1 - is 1 or 11: 1, 11 - * 2 - is 2 or 12: 2, 12 - * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19 - * 4 - everything else: 0, 20, 21, ... - */ - return ($number == 1 || $number == 11) ? 1 : (($number == 2 || $number == 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4)); - - case 5: - /** - * Families: Romanic (Romanian) - * 1 - 1 - * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ... - * 3 - everything else: 20, 21, ... - */ - return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3); - - case 6: - /** - * Families: Baltic (Lithuanian) - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... - * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ... - * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3); - - case 7: - /** - * Families: Slavic (Croatian, Serbian, Russian, Ukrainian) - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... - * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... - * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3); - - case 8: - /** - * Families: Slavic (Slovak, Czech) - * 1 - 1 - * 2 - 2, 3, 4 - * 3 - everything else: 0, 5, 6, 7, ... - */ - return ($number == 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3); - - case 9: - /** - * Families: Slavic (Polish) - * 1 - 1 - * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ... - * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ... - */ - return ($number == 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3); - - case 10: - /** - * Families: Slavic (Slovenian, Sorbian) - * 1 - ends in 01: 1, 101, 201, ... - * 2 - ends in 02: 2, 102, 202, ... - * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ... - * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ... - */ - return ($number % 100 == 1) ? 1 : (($number % 100 == 2) ? 2 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 3 : 4)); - - case 11: - /** - * Families: Celtic (Irish Gaeilge) - * 1 - 1 - * 2 - 2 - * 3 - is 3-6: 3, 4, 5, 6 - * 4 - is 7-10: 7, 8, 9, 10 - * 5 - everything else: 0, 11, 12, ... - */ - return ($number == 1) ? 1 : (($number == 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5))); - - case 12: - /** - * Families: Semitic (Arabic) - * 1 - 1 - * 2 - 2 - * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ... - * 4 - ends in 11-99: 11, ... 99, 111, 112, ... - * 5 - everything else: 100, 101, 102, 200, 201, 202, ... - * 6 - 0 - */ - return ($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : (($number != 0) ? 5 : 6)))); - - case 13: - /** - * Families: Semitic (Maltese) - * 1 - 1 - * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ... - * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ... - * 4 - everything else: 20, 21, ... - */ - return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4)); - - case 14: - /** - * Families: Slavic (Macedonian) - * 1 - ends in 1: 1, 11, 21, ... - * 2 - ends in 2: 2, 12, 22, ... - * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ... - */ - return ($number % 10 == 1) ? 1 : (($number % 10 == 2) ? 2 : 3); - - case 15: - /** - * Families: Icelandic - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ... - * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2; - } -} - /** * Login using http authenticate. * diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 2d064e37cb..8655203754 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -482,3 +482,22 @@ function phpbb_realpath($path) return $phpbb_filesystem->realpath($path); } + +/** + * Determine which plural form we should use. + * For some languages this is not as simple as for English. + * + * @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules + * @param $number int|float The number we want to get the plural case for. Float numbers are floored. + * @return int The plural-case we need to use for the number plural-rule combination + * + * @deprecated 3.2.0-dev (To be removed: 3.3.0) + */ +function phpbb_get_plural_form($rule, $number) +{ + global $phpbb_container; + + /** @var \phpbb\language\language $language */ + $language = $phpbb_container->get('language'); + return $language->get_plural_form($number, $rule); +} diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index c7234bb8e8..e8c2fbcbfa 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -3384,7 +3384,7 @@ function get_group_name($group_id) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if (!$row || ($row['group_type'] == GROUP_SPECIAL && empty($user->lang))) + if (!$row || ($row['group_type'] == GROUP_SPECIAL && !$user->is_setup())) { return ''; } diff --git a/phpBB/install/index.php b/phpBB/install/index.php index dd3590e854..df1229c9f2 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -241,7 +241,8 @@ $sub = $request->variable('sub', ''); // Set PHP error handler to ours set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler'); -$user = new \phpbb\user('\phpbb\datetime'); +$lang_service = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +$user = new \phpbb\user($lang_service, '\phpbb\datetime'); $auth = new \phpbb\auth\auth(); // Add own hook handler, if present. :o @@ -287,14 +288,15 @@ $twig_environment = new \phpbb\template\twig\environment( ); $phpbb_container->set('template.twig.environment', $twig_environment); +$twig_context = new \phpbb\template\context(); $template = new \phpbb\template\twig\twig( $phpbb_path_helper, $config, $user, - new \phpbb\template\context(), + $twig_context, $twig_environment, $cache_path, - array($phpbb_container->get('template.twig.extensions.phpbb')) + array(new \phpbb\template\twig\extension($twig_context, $user)) ); $paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style'); diff --git a/phpBB/phpbb/captcha/plugins/captcha_abstract.php b/phpBB/phpbb/captcha/plugins/captcha_abstract.php index 799947a84e..b29f144f97 100644 --- a/phpBB/phpbb/captcha/plugins/captcha_abstract.php +++ b/phpBB/phpbb/captcha/plugins/captcha_abstract.php @@ -195,7 +195,7 @@ abstract class captcha_abstract { global $config, $db, $user; - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } diff --git a/phpBB/phpbb/language/exception/invalid_plural_rule_exception.php b/phpBB/phpbb/language/exception/invalid_plural_rule_exception.php new file mode 100644 index 0000000000..94e3466208 --- /dev/null +++ b/phpBB/phpbb/language/exception/invalid_plural_rule_exception.php @@ -0,0 +1,22 @@ + + * @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\language\exception; + +/** + * Thrown when nonexistent plural rule is specified + */ +class invalid_plural_rule_exception extends language_exception +{ + +} diff --git a/phpBB/phpbb/language/exception/language_exception.php b/phpBB/phpbb/language/exception/language_exception.php new file mode 100644 index 0000000000..b1258414aa --- /dev/null +++ b/phpBB/phpbb/language/exception/language_exception.php @@ -0,0 +1,22 @@ + + * @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\language\exception; + +/** + * Base exception class for language exceptions + */ +class language_exception extends \phpbb\exception\runtime_exception +{ + +} diff --git a/phpBB/phpbb/language/exception/language_file_not_found.php b/phpBB/phpbb/language/exception/language_file_not_found.php new file mode 100644 index 0000000000..89364267eb --- /dev/null +++ b/phpBB/phpbb/language/exception/language_file_not_found.php @@ -0,0 +1,22 @@ + + * @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\language\exception; + +/** + * This exception is thrown when the language file is not found + */ +class language_file_not_found extends language_exception +{ + +} diff --git a/phpBB/phpbb/language/language.php b/phpBB/phpbb/language/language.php new file mode 100644 index 0000000000..9c9a3b8df1 --- /dev/null +++ b/phpBB/phpbb/language/language.php @@ -0,0 +1,562 @@ + + * @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\language; + +use phpbb\language\exception\invalid_plural_rule_exception; + +/** + * Wrapper class for loading translations + */ +class language +{ + /** + * Global fallback language + * + * ISO code of the language to fallback to when the specified language entries + * cannot be found. + * + * @var string + */ + const FALLBACK_LANGUAGE = 'en'; + + /** + * @var array List of common language files + */ + protected $common_language_files; + + /** + * @var bool + */ + protected $common_language_files_loaded; + + /** + * @var string ISO code of the default board language + */ + protected $default_language; + + /** + * @var string ISO code of the User's language + */ + protected $user_language; + + /** + * @var array Language fallback array (the order is important) + */ + protected $language_fallback; + + /** + * @var array Array of language variables + */ + protected $lang; + + /** + * @var array Loaded language sets + */ + protected $loaded_language_sets; + + /** + * @var \phpbb\language\language_file_loader Language file loader + */ + protected $loader; + + /** + * Constructor + * + * @param \phpbb\language\language_file_loader $loader Language file loader + */ + public function __construct(language_file_loader $loader) + { + $this->loader = $loader; + + // Set up default information + $this->user_language = false; + $this->default_language = false; + $this->lang = array( + // For BC with user::help array + '__help' => array(), + ); + $this->loaded_language_sets = array( + 'core' => array(), + 'ext' => array(), + ); + + // Common language files + $this->common_language_files = array( + 'common', + ); + $this->common_language_files_loaded = false; + + $this->language_fallback = array(self::FALLBACK_LANGUAGE); + } + + /** + * Function to set user's language to display. + * + * @param string $user_lang_iso ISO code of the User's language + */ + public function set_user_language($user_lang_iso) + { + $this->user_language = $user_lang_iso; + + $this->set_fallback_array(); + } + + /** + * Function to set the board's default language to display. + * + * @param string $default_lang_iso ISO code of the board's default language + */ + public function set_default_language($default_lang_iso) + { + $this->default_language = $default_lang_iso; + + $this->set_fallback_array(); + } + + /** + * Returns language array + * + * Note: This function is needed for the BC purposes, until \phpbb\user::lang[] is + * not removed. + * + * @return array Array of loaded language strings + */ + public function get_lang_array() + { + // Load common language files if they not loaded yet + if (!$this->common_language_files_loaded) + { + $this->load_common_language_files(); + } + + return $this->lang; + } + + /** + * Add Language Items + * + * Note: $use_help is assigned where needed (only use them to force inclusion). + * + * Examples: + * + * $component = array('posting'); + * $component = array('posting', 'viewtopic') + * $component = 'posting' + * + * + * @param string|array $component The name of the language component to load + * @param string|null $extension_name Name of the extension to load component from, or null for core file + */ + public function add_lang($component, $extension_name = null) + { + // Load common language files if they not loaded yet + // This needs to be here to correctly merge language arrays + if (!$this->common_language_files_loaded) + { + $this->load_common_language_files(); + } + + if (!is_array($component)) + { + if (!is_null($extension_name)) + { + $this->load_extension($extension_name, $component); + } + else + { + $this->load_core_file($component); + } + } + else + { + foreach ($component as $lang_file) + { + $this->add_lang($lang_file, $extension_name); + } + } + } + + /** + * Advanced language substitution + * + * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms. + * Params are the language key and the parameters to be substituted. + * This function/functionality is inspired by SHS` and Ashe. + * + * Example call: $user->lang('NUM_POSTS_IN_QUEUE', 1); + * + * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry: + * Example: $user->lang(array('datetime', 'AGO'), 1) uses $user->lang['datetime']['AGO'] as language entry. + * + * @return string Return localized string or the language key if the translation is not available + */ + public function lang() + { + // Load common language files if they not loaded yet + if (!$this->common_language_files_loaded) + { + $this->load_common_language_files(); + } + + $args = func_get_args(); + $key = $args[0]; + + if (is_array($key)) + { + $lang = &$this->lang[array_shift($key)]; + + foreach ($key as $_key) + { + $lang = &$lang[$_key]; + } + } + else + { + $lang = &$this->lang[$key]; + } + + // Return if language string does not exist + if (!isset($lang) || (!is_string($lang) && !is_array($lang))) + { + return $key; + } + + // If the language entry is a string, we simply mimic sprintf() behaviour + if (is_string($lang)) + { + if (sizeof($args) == 1) + { + return $lang; + } + + // Replace key with language entry and simply pass along... + $args[0] = $lang; + return call_user_func_array('sprintf', $args); + } + else if (sizeof($lang) == 0) + { + // If the language entry is an empty array, we just return the language key + return $args[0]; + } + + // It is an array... now handle different nullar/singular/plural forms + $key_found = false; + + // We now get the first number passed and will select the key based upon this number + for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++) + { + if (is_int($args[$i]) || is_float($args[$i])) + { + if ($args[$i] == 0 && isset($lang[0])) + { + // We allow each translation using plural forms to specify a version for the case of 0 things, + // so that "0 users" may be displayed as "No users". + $key_found = 0; + break; + } + else + { + $use_plural_form = $this->get_plural_form($args[$i]); + if (isset($lang[$use_plural_form])) + { + // The key we should use exists, so we use it. + $key_found = $use_plural_form; + } + else + { + // If the key we need to use does not exist, we fall back to the previous one. + $numbers = array_keys($lang); + + foreach ($numbers as $num) + { + if ($num > $use_plural_form) + { + break; + } + + $key_found = $num; + } + } + break; + } + } + } + + // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form) + if ($key_found === false) + { + $numbers = array_keys($lang); + $key_found = end($numbers); + } + + // Use the language string we determined and pass it to sprintf() + $args[0] = $lang[$key_found]; + return call_user_func_array('sprintf', $args); + } + + /** + * Loads common language files + */ + protected function load_common_language_files() + { + if (!$this->common_language_files_loaded) + { + foreach ($this->common_language_files as $lang_file) + { + $this->load_core_file($lang_file); + } + + $this->common_language_files_loaded = true; + } + } + + /** + * Determine which plural form we should use. + * + * For some languages this is not as simple as for English. + * + * @param int|float $number The number we want to get the plural case for. Float numbers are floored. + * @param int|bool $force_rule False to use the plural rule of the language package + * or an integer to force a certain plural rule + * + * @return int The plural-case we need to use for the number plural-rule combination + * + * @throws \phpbb\language\exception\invalid_plural_rule_exception When $force_rule has an invalid value + */ + public function get_plural_form($number, $force_rule = false) + { + $number = (int) $number; + $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1); + + if ($plural_rule > 15 || $plural_rule < 0) + { + throw new invalid_plural_rule_exception('INVALID_PLURAL_RULE', array( + 'plural_rule' => $plural_rule, + )); + } + + /** + * The following plural rules are based on a list published by the Mozilla Developer Network + * https://developer.mozilla.org/en/Localization_and_Plurals + */ + switch ($plural_rule) + { + case 0: + /** + * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao + * 1 - everything: 0, 1, 2, ... + */ + return 1; + + case 1: + /** + * Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish), Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek), Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan) + * 1 - 1 + * 2 - everything else: 0, 2, 3, ... + */ + return ($number === 1) ? 1 : 2; + + case 2: + /** + * Families: Romanic (French, Brazilian Portuguese) + * 1 - 0, 1 + * 2 - everything else: 2, 3, ... + */ + return (($number === 0) || ($number === 1)) ? 1 : 2; + + case 3: + /** + * Families: Baltic (Latvian) + * 1 - 0 + * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ... + * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ... + */ + return ($number === 0) ? 1 : ((($number % 10 === 1) && ($number % 100 != 11)) ? 2 : 3); + + case 4: + /** + * Families: Celtic (Scottish Gaelic) + * 1 - is 1 or 11: 1, 11 + * 2 - is 2 or 12: 2, 12 + * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19 + * 4 - everything else: 0, 20, 21, ... + */ + return ($number === 1 || $number === 11) ? 1 : (($number === 2 || $number === 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4)); + + case 5: + /** + * Families: Romanic (Romanian) + * 1 - 1 + * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ... + * 3 - everything else: 20, 21, ... + */ + return ($number === 1) ? 1 : ((($number === 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3); + + case 6: + /** + * Families: Baltic (Lithuanian) + * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... + * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ... + * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ... + */ + return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3); + + case 7: + /** + * Families: Slavic (Croatian, Serbian, Russian, Ukrainian) + * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... + * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... + * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ... + */ + return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3); + + case 8: + /** + * Families: Slavic (Slovak, Czech) + * 1 - 1 + * 2 - 2, 3, 4 + * 3 - everything else: 0, 5, 6, 7, ... + */ + return ($number === 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3); + + case 9: + /** + * Families: Slavic (Polish) + * 1 - 1 + * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ... + * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ... + */ + return ($number === 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3); + + case 10: + /** + * Families: Slavic (Slovenian, Sorbian) + * 1 - ends in 01: 1, 101, 201, ... + * 2 - ends in 02: 2, 102, 202, ... + * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ... + * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ... + */ + return ($number % 100 === 1) ? 1 : (($number % 100 === 2) ? 2 : ((($number % 100 === 3) || ($number % 100 === 4)) ? 3 : 4)); + + case 11: + /** + * Families: Celtic (Irish Gaeilge) + * 1 - 1 + * 2 - 2 + * 3 - is 3-6: 3, 4, 5, 6 + * 4 - is 7-10: 7, 8, 9, 10 + * 5 - everything else: 0, 11, 12, ... + */ + return ($number === 1) ? 1 : (($number === 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5))); + + case 12: + /** + * Families: Semitic (Arabic) + * 1 - 1 + * 2 - 2 + * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ... + * 4 - ends in 11-99: 11, ... 99, 111, 112, ... + * 5 - everything else: 100, 101, 102, 200, 201, 202, ... + * 6 - 0 + */ + return ($number === 1) ? 1 : (($number === 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : (($number != 0) ? 5 : 6)))); + + case 13: + /** + * Families: Semitic (Maltese) + * 1 - 1 + * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ... + * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ... + * 4 - everything else: 20, 21, ... + */ + return ($number === 1) ? 1 : ((($number === 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4)); + + case 14: + /** + * Families: Slavic (Macedonian) + * 1 - ends in 1: 1, 11, 21, ... + * 2 - ends in 2: 2, 12, 22, ... + * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ... + */ + return ($number % 10 === 1) ? 1 : (($number % 10 === 2) ? 2 : 3); + + case 15: + /** + * Families: Icelandic + * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ... + * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ... + */ + return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : 2; + } + } + + /** + * Returns language fallback data + * + * @return array + */ + protected function set_fallback_array() + { + $fallback_array = array(); + + if ($this->user_language !== false) + { + $fallback_array[] = $this->user_language; + } + + if ($this->default_language !== false) + { + $fallback_array[] = $this->default_language; + } + + $fallback_array[] = self::FALLBACK_LANGUAGE; + + $this->language_fallback = $fallback_array; + } + + /** + * Load core language file + * + * @param string $component Name of the component to load + */ + protected function load_core_file($component) + { + // Check if the component is already loaded + if (isset($this->loaded_language_sets['core'][$component])) + { + return; + } + + $this->loader->load($component, $this->language_fallback, $this->lang); + $this->loaded_language_sets['core'][$component] = true; + } + + /** + * Load extension language file + * + * @param string $extension_name Name of the extension to load language from + * @param string $component Name of the component to load + */ + protected function load_extension($extension_name, $component) + { + // Check if the component is already loaded + if (isset($this->loaded_language_sets['ext'][$extension_name][$component])) + { + return; + } + + $this->loader->load_extension($extension_name, $component, $this->language_fallback, $this->lang); + $this->loaded_language_sets['ext'][$extension_name][$component] = true; + } +} diff --git a/phpBB/phpbb/language/language_file_helper.php b/phpBB/phpbb/language/language_file_helper.php new file mode 100644 index 0000000000..18d7b62e21 --- /dev/null +++ b/phpBB/phpbb/language/language_file_helper.php @@ -0,0 +1,71 @@ + + * @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\language; + +use Symfony\Component\Finder\Finder; + +/** + * Helper class for language file related functions + */ +class language_file_helper +{ + /** + * @var string Path to phpBB's root + */ + protected $phpbb_root_path; + + /** + * Constructor + * + * @param string $phpbb_root_path Path to phpBB's root + */ + public function __construct($phpbb_root_path) + { + $this->phpbb_root_path = $phpbb_root_path; + } + + /** + * Returns available languages + * + * @return array + */ + public function get_available_languages() + { + // Find available language packages + $finder = new Finder(); + $finder->files() + ->name('iso.txt') + ->depth('== 1') + ->in($this->phpbb_root_path . 'language'); + + $available_languages = array(); + foreach ($finder as $file) + { + $path = $file->getRelativePath(); + $info = explode("\n", $file->getContents()); + + $available_languages[] = array( + // Get the name of the directory containing iso.txt + 'iso' => $path, + + // Recover data from file + 'name' => trim($info[0]), + 'local_name' => trim($info[1]), + 'author' => trim($info[2]) + ); + } + + return $available_languages; + } +} diff --git a/phpBB/phpbb/language/language_file_loader.php b/phpBB/phpbb/language/language_file_loader.php new file mode 100644 index 0000000000..510a29279a --- /dev/null +++ b/phpBB/phpbb/language/language_file_loader.php @@ -0,0 +1,212 @@ + + * @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\language; + +use \phpbb\language\exception\language_file_not_found; + +/** + * Language file loader + */ +class language_file_loader +{ + /** + * @var string Path to phpBB's root + */ + protected $phpbb_root_path; + + /** + * @var string Extension of PHP files + */ + protected $php_ext; + + /** + * @var \phpbb\extension\manager Extension manager + */ + protected $extension_manager; + + /** + * Constructor + * + * @param string $phpbb_root_path Path to phpBB's root + * @param string $php_ext Extension of PHP files + */ + public function __construct($phpbb_root_path, $php_ext) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + + $this->extension_manager = null; + } + + /** + * Extension manager setter + * + * @param \phpbb\extension\manager $extension_manager Extension manager + */ + public function set_extension_manager(\phpbb\extension\manager $extension_manager) + { + $this->extension_manager = $extension_manager; + } + + /** + * Loads language array for the given component + * + * @param string $component Name of the language component + * @param string|array $locale ISO code of the language to load, or array of ISO codes if you want to + * specify additional language fallback steps + * @param array $lang Array reference containing language strings + */ + public function load($component, $locale, &$lang) + { + $locale = (array) $locale; + + // Determine path to language directory + $path = $this->phpbb_root_path . 'language/'; + + $this->load_file($path, $component, $locale, $lang); + } + + /** + * Loads language array for the given extension component + * + * @param string $extension Name of the extension + * @param string $component Name of the language component + * @param string|array $locale ISO code of the language to load, or array of ISO codes if you want to + * specify additional language fallback steps + * @param array $lang Array reference containing language strings + */ + public function load_extension($extension, $component, $locale, &$lang) + { + // Check if extension manager was loaded + if ($this->extension_manager === null) + { + // If not, let's return + return; + } + + $locale = (array) $locale; + + // Determine path to language directory + $path = $this->extension_manager->get_extension_path($extension, true) . 'language/'; + + $this->load_file($path, $component, $locale, $lang); + } + + /** + * Prepares language file loading + * + * @param string $path Path to search for file in + * @param string $component Name of the language component + * @param array $locale Array containing language fallback options + * @param array $lang Array reference of language strings + */ + protected function load_file($path, $component, $locale, &$lang) + { + // This is BC stuff and not the best idea as it makes language fallback + // implementation quite hard like below. + if (strpos($this->phpbb_root_path . $component, $path) === 0) + { + // Filter out the path + $path_diff = str_replace($path, '', dirname($this->phpbb_root_path . $component)); + $language_file = basename($component, '.' . $this->php_ext); + $component = ''; + + // This step is needed to resolve language/en/subdir style $component + // $path already points to the language base directory so we need to eliminate + // the first directory from the path (that should be the language directory) + $path_diff_parts = explode('/', $path_diff); + + if (sizeof($path_diff_parts) > 1) + { + array_shift($path_diff_parts); + $component = implode('/', $path_diff_parts) . '/'; + } + + $component .= $language_file; + } + + // Determine filename + $filename = $component . '.' . $this->php_ext; + + // Determine path to file + $file_path = $this->get_language_file_path($path, $filename, $locale); + + // Load language array + $this->load_language_file($file_path, $lang); + } + + /** + * This function implements language fallback logic + * + * @param string $path Path to language directory + * @param string $filename Filename to load language strings from + * + * @return string Relative path to language file + * + * @throws \phpbb\language\exception\language_file_not_exists When the path to the file cannot be resolved + */ + protected function get_language_file_path($path, $filename, $locales) + { + // Language fallback logic + foreach ($locales as $locale) + { + $language_file_path = $path . $locale . '/' . $filename; + + // If we are in install, try to use the updated version, when available + if (defined('IN_INSTALL')) + { + $install_language_path = str_replace('language/', 'install/update/new/language/', $language_file_path); + if (file_exists($install_language_path)) + { + return $install_language_path; + } + } + + if (file_exists($language_file_path)) + { + return $language_file_path; + } + } + + // The language file is not exist + throw new language_file_not_found('Language file ' . $language_file_path . ' couldn\'t be opened.'); + } + + /** + * Loads language file + * + * @param string $path Path to language file to load + * @param array $lang Reference of the array of language strings + */ + protected function load_language_file($path, &$lang) + { + // BC code for language files with help + $help = array(); + + // Do not suppress error if in DEBUG mode + if (defined('DEBUG')) + { + include $path; + } + else + { + @include $path; + } + + if (!empty($help)) + { + $lang['__help'] = array_merge($lang['__help'], $help); + } + } +} diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php index 882e9cef26..c33070d6f4 100644 --- a/phpBB/phpbb/user.php +++ b/phpBB/phpbb/user.php @@ -21,8 +21,11 @@ namespace phpbb; */ class user extends \phpbb\session { - var $lang = array(); - var $help = array(); + /** + * @var \phpbb\language\language + */ + protected $language; + var $style = array(); var $date_format; @@ -42,35 +45,63 @@ class user extends \phpbb\session var $img_lang; var $img_array = array(); + /** @var bool */ + protected $is_setup_flag; + // Able to add new options (up to id 31) var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17); /** * Constructor to set the lang path + * * @param string $datetime_class Class name of datetime class + * @param \phpbb\language\language $lang phpBB's Language loader */ - function __construct($datetime_class) + function __construct(\phpbb\language\language $lang, $datetime_class) { global $phpbb_root_path; $this->lang_path = $phpbb_root_path . 'language/'; + $this->language = $lang; $this->datetime = $datetime_class; + + $this->is_setup_flag = false; } /** - * Function to set custom language path (able to use directory outside of phpBB) - * - * @param string $lang_path New language path used. - * @access public - */ - function set_custom_lang_path($lang_path) + * Returns whether user::setup was called + * + * @return bool + */ + public function is_setup() { - $this->lang_path = $lang_path; + return $this->is_setup_flag; + } - if (substr($this->lang_path, -1) != '/') + /** + * Magic getter for BC compatibility + * + * Implement array access for user::lang. + * + * @param string $param_name Name of the BC component the user want to access + * + * @return array The appropriate array + * + * @deprecated 3.2.0-dev (To be removed: 4.0.0) + */ + public function __get($param_name) + { + if ($param_name === 'lang') { - $this->lang_path .= '/'; + return $this->language->get_lang_array(); } + else if ($param_name === 'help') + { + $help_array = $this->language->get_lang_array(); + return $help_array['__help']; + } + + return array(); } /** @@ -81,6 +112,8 @@ class user extends \phpbb\session global $db, $request, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache; global $phpbb_dispatcher; + $this->language->set_default_language($config['default_lang']); + if ($this->data['user_id'] != ANONYMOUS) { $user_lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); @@ -98,6 +131,7 @@ class user extends \phpbb\session { $lang_override = $request->variable($config['cookie_name'] . '_lang', '', true, \phpbb\request\request_interface::COOKIE); } + if ($lang_override) { $use_lang = basename($lang_override); @@ -108,6 +142,7 @@ class user extends \phpbb\session { $user_lang_name = basename($config['default_lang']); } + $user_date_format = $config['default_dateformat']; $user_timezone = $config['board_timezone']; @@ -187,6 +222,8 @@ class user extends \phpbb\session $this->lang_name = $user_lang_name; $this->date_format = $user_date_format; + $this->language->set_user_language($user_lang_name); + try { $this->timezone = new \DateTimeZone($user_timezone); @@ -197,17 +234,6 @@ class user extends \phpbb\session $this->timezone = new \DateTimeZone('UTC'); } - // We include common language file here to not load it every time a custom language file is included - $lang = &$this->lang; - - // Do not suppress error if in DEBUG mode - $include_result = (defined('DEBUG')) ? (include $this->lang_path . $this->lang_name . "/common.$phpEx") : (@include $this->lang_path . $this->lang_name . "/common.$phpEx"); - - if ($include_result === false) - { - die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened."); - } - $this->add_lang($lang_set); unset($lang_set); @@ -393,6 +419,8 @@ class user extends \phpbb\session } } + $this->is_setup_flag = true; + return; } @@ -406,103 +434,13 @@ class user extends \phpbb\session * * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry: * Example: $user->lang(array('datetime', 'AGO'), 1) uses $user->lang['datetime']['AGO'] as language entry. + * + * @deprecated 3.2.0-dev (To be removed 4.0.0) */ function lang() { $args = func_get_args(); - $key = $args[0]; - - if (is_array($key)) - { - $lang = &$this->lang[array_shift($key)]; - - foreach ($key as $_key) - { - $lang = &$lang[$_key]; - } - } - else - { - $lang = &$this->lang[$key]; - } - - // Return if language string does not exist - if (!isset($lang) || (!is_string($lang) && !is_array($lang))) - { - return $key; - } - - // If the language entry is a string, we simply mimic sprintf() behaviour - if (is_string($lang)) - { - if (sizeof($args) == 1) - { - return $lang; - } - - // Replace key with language entry and simply pass along... - $args[0] = $lang; - return call_user_func_array('sprintf', $args); - } - else if (sizeof($lang) == 0) - { - // If the language entry is an empty array, we just return the language key - return $args[0]; - } - - // It is an array... now handle different nullar/singular/plural forms - $key_found = false; - - // We now get the first number passed and will select the key based upon this number - for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++) - { - if (is_int($args[$i]) || is_float($args[$i])) - { - if ($args[$i] == 0 && isset($lang[0])) - { - // We allow each translation using plural forms to specify a version for the case of 0 things, - // so that "0 users" may be displayed as "No users". - $key_found = 0; - break; - } - else - { - $use_plural_form = $this->get_plural_form($args[$i]); - if (isset($lang[$use_plural_form])) - { - // The key we should use exists, so we use it. - $key_found = $use_plural_form; - } - else - { - // If the key we need to use does not exist, we fall back to the previous one. - $numbers = array_keys($lang); - - foreach ($numbers as $num) - { - if ($num > $use_plural_form) - { - break; - } - - $key_found = $num; - } - } - break; - } - } - } - - // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form) - if ($key_found === false) - { - $numbers = array_keys($lang); - $key_found = end($numbers); - } - - // Use the language string we determined and pass it to sprintf() - $args[0] = $lang[$key_found]; - return call_user_func_array('sprintf', $args); + return call_user_func_array(array($this->language, 'lang'), $args); } /** @@ -512,24 +450,22 @@ class user extends \phpbb\session * @param $number int|float The number we want to get the plural case for. Float numbers are floored. * @param $force_rule mixed False to use the plural rule of the language package * or an integer to force a certain plural rule - * @return int The plural-case we need to use for the number plural-rule combination + * @return int|bool The plural-case we need to use for the number plural-rule combination, false if $force_rule + * was invalid. + * + * @deprecated: 3.2.0-dev (To be removed: 3.3.0) */ function get_plural_form($number, $force_rule = false) { - $number = (int) $number; - - // Default to English system - $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1); - - return phpbb_get_plural_form($plural_rule, $number); + return $this->language->get_plural_form($number, $force_rule); } /** * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion) * * @param mixed $lang_set specifies the language entries to include - * @param bool $use_db internal variable for recursion, do not use - * @param bool $use_help internal variable for recursion, do not use + * @param bool $use_db internal variable for recursion, do not use @deprecated 3.2.0-dev (To be removed: 3.3.0) + * @param bool $use_help internal variable for recursion, do not use @deprecated 3.2.0-dev (To be removed: 3.3.0) * @param string $ext_name The extension to load language from, or empty for core files * * Examples: @@ -540,11 +476,14 @@ class user extends \phpbb\session * $lang_set = 'posting' * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting')) * + * + * Note: $use_db and $use_help should be removed. The old function was kept for BC purposes, + * so the BC logic is handled here. + * + * @deprecated: 3.2.0-dev (To be removed: 3.3.0) */ function add_lang($lang_set, $use_db = false, $use_help = false, $ext_name = '') { - global $phpEx; - if (is_array($lang_set)) { foreach ($lang_set as $key => $lang_file) @@ -555,6 +494,7 @@ class user extends \phpbb\session if ($key == 'db') { + // This is never used $this->add_lang($lang_file, true, $use_help, $ext_name); } else if ($key == 'help') @@ -563,7 +503,7 @@ class user extends \phpbb\session } else if (!is_array($lang_file)) { - $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help, $ext_name); + $this->set_lang($lang_file, $use_help, $ext_name); } else { @@ -574,10 +514,39 @@ class user extends \phpbb\session } else if ($lang_set) { - $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help, $ext_name); + $this->set_lang($lang_set, $use_help, $ext_name); } } + /** + * BC function for loading language files + * + * @deprecated 3.2.0-dev (To be removed: 3.3.0) + */ + private function set_lang($lang_set, $use_help, $ext_name) + { + if (empty($ext_name)) + { + $ext_name = null; + } + + if ($use_help && strpos($lang_set, '/') !== false) + { + $component = dirname($lang_set) . '/help_' . basename($lang_set); + + if ($component[0] === '/') + { + $component = substr($component, 1); + } + } + else + { + $component = (($use_help) ? 'help_' : '') . $lang_set; + } + + $this->language->add_lang($component, $ext_name); + } + /** * Add Language Items from an extension - use_db and use_help are assigned where needed (only use them to force inclusion) * @@ -585,6 +554,10 @@ class user extends \phpbb\session * @param mixed $lang_set specifies the language entries to include * @param bool $use_db internal variable for recursion, do not use * @param bool $use_help internal variable for recursion, do not use + * + * Note: $use_db and $use_help should be removed. Kept for BC purposes. + * + * @deprecated: 3.2.0-dev (To be removed: 3.3.0) */ function add_lang_ext($ext_name, $lang_set, $use_db = false, $use_help = false) { @@ -596,109 +569,6 @@ class user extends \phpbb\session $this->add_lang($lang_set, $use_db, $use_help, $ext_name); } - /** - * Set language entry (called by add_lang) - * @access private - */ - function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false, $ext_name = '') - { - global $phpbb_root_path, $phpEx; - - // Make sure the language name is set (if the user setup did not happen it is not set) - if (!$this->lang_name) - { - global $config; - $this->lang_name = basename($config['default_lang']); - } - - // $lang == $this->lang - // $help == $this->help - // - add appropriate variables here, name them as they are used within the language file... - if (!$use_db) - { - if ($use_help && strpos($lang_file, '/') !== false) - { - $filename = dirname($lang_file) . '/help_' . basename($lang_file); - } - else - { - $filename = (($use_help) ? 'help_' : '') . $lang_file; - } - - if ($ext_name) - { - global $phpbb_extension_manager; - $ext_path = $phpbb_extension_manager->get_extension_path($ext_name, true); - - $lang_path = $ext_path . 'language/'; - } - else - { - $lang_path = $this->lang_path; - } - - if (strpos($phpbb_root_path . $filename, $lang_path . $this->lang_name . '/') === 0) - { - $language_filename = $phpbb_root_path . $filename; - } - else - { - $language_filename = $lang_path . $this->lang_name . '/' . $filename . '.' . $phpEx; - } - - // If we are in install, try to use the updated version, when available - $install_language_filename = str_replace('language/', 'install/update/new/language/', $language_filename); - if (defined('IN_INSTALL') && file_exists($install_language_filename)) - { - $language_filename = $install_language_filename; - } - - if (!file_exists($language_filename)) - { - global $config; - - if ($this->lang_name == 'en') - { - // The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en. - $language_filename = str_replace($lang_path . 'en', $lang_path . $this->data['user_lang'], $language_filename); - trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); - } - else if ($this->lang_name == basename($config['default_lang'])) - { - // Fall back to the English Language - $reset_lang_name = $this->lang_name; - $this->lang_name = 'en'; - $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name); - $this->lang_name = $reset_lang_name; - } - else if ($this->lang_name == $this->data['user_lang']) - { - // Fall back to the board default language - $reset_lang_name = $this->lang_name; - $this->lang_name = basename($config['default_lang']); - $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name); - $this->lang_name = $reset_lang_name; - } - - return; - } - - // Do not suppress error if in DEBUG mode - $include_result = (defined('DEBUG')) ? (include $language_filename) : (@include $language_filename); - - if ($include_result === false) - { - trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); - } - } - else if ($use_db) - { - // Get Database Language Strings - // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed - // For example: help:faq, posting - } - } - /** * Format user date * @@ -808,7 +678,7 @@ class user extends \phpbb\session if ($alt) { - $alt = $this->lang($alt); + $alt = $this->language->lang($alt); $title = ' title="' . $alt . '"'; } return '' . $alt . ''; diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php index 68ad7b2c19..60423acbc1 100644 --- a/tests/auth/provider_apache_test.php +++ b/tests/auth/provider_apache_test.php @@ -28,8 +28,10 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case $db = $this->new_dbal(); $config = new \phpbb\config\config(array()); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); $this->request = $this->getMock('\phpbb\request\request'); - $this->user = new \phpbb\user('\phpbb\datetime'); + $this->user = new \phpbb\user($lang, '\phpbb\datetime'); $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php index 09ca0816bf..38dbfa1fcb 100644 --- a/tests/auth/provider_db_test.php +++ b/tests/auth/provider_db_test.php @@ -38,8 +38,10 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case 'ip_login_limit_use_forwarded' => 0, 'max_login_attempts' => 0, )); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); $request = $this->getMock('\phpbb\request\request'); - $user = new \phpbb\user('\phpbb\datetime'); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), diff --git a/tests/auth/provider_oauth_token_storage_test.php b/tests/auth/provider_oauth_token_storage_test.php index 71b49ff439..78b936ee8e 100644 --- a/tests/auth/provider_oauth_token_storage_test.php +++ b/tests/auth/provider_oauth_token_storage_test.php @@ -31,7 +31,9 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c global $phpbb_root_path, $phpEx; $this->db = $this->new_dbal(); - $this->user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $this->user = new \phpbb\user($lang, '\phpbb\datetime'); $this->service_name = 'auth.provider.oauth.service.testing'; $this->token_storage_table = 'phpbb_oauth_tokens'; diff --git a/tests/avatar/manager_test.php b/tests/avatar/manager_test.php index 638ba0aaff..71f40c0b13 100644 --- a/tests/avatar/manager_test.php +++ b/tests/avatar/manager_test.php @@ -94,7 +94,9 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case // Set up avatar manager $this->manager = new \phpbb\avatar\manager($this->config, $avatar_drivers, $phpbb_container); $this->db = $this->new_dbal(); - $this->user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $this->user = new \phpbb\user($lang, '\phpbb\datetime'); } protected function avatar_drivers() @@ -277,7 +279,12 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case public function test_localize_errors() { - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + global $phpbb_root_path, $phpEx; + + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime') + ); $lang_array = array( array('FOOBAR_OFF', 'foobar_off'), array('FOOBAR_EXPLAIN', 'FOOBAR_EXPLAIN %s'), diff --git a/tests/console/cache/purge_test.php b/tests/console/cache/purge_test.php index 96988c1028..172fb0ecf3 100644 --- a/tests/console/cache/purge_test.php +++ b/tests/console/cache/purge_test.php @@ -32,6 +32,8 @@ class phpbb_console_command_cache_purge_test extends phpbb_test_case protected function setUp() { + global $phpbb_root_path, $phpEx; + if (file_exists($this->cache_dir)) { // cache directory possibly left after aborted @@ -45,7 +47,10 @@ class phpbb_console_command_cache_purge_test extends phpbb_test_case $this->db = $this->getMock('\phpbb\db\driver\driver_interface'); $this->config = new \phpbb\config\config(array('assets_version' => 1)); - $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $this->user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime') + ); } public function test_purge() diff --git a/tests/console/config/config_test.php b/tests/console/config/config_test.php index 7c098af004..076316217d 100644 --- a/tests/console/config/config_test.php +++ b/tests/console/config/config_test.php @@ -22,9 +22,14 @@ class phpbb_console_command_config_test extends phpbb_test_case public function setUp() { + global $phpbb_root_path, $phpEx; + $this->config = new \phpbb\config\config(array()); - $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $this->user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime') + ); $this->user->method('lang')->will($this->returnArgument(0)); } diff --git a/tests/console/cron/cron_list_test.php b/tests/console/cron/cron_list_test.php index 22423304be..3bbe2078ba 100644 --- a/tests/console/cron/cron_list_test.php +++ b/tests/console/cron/cron_list_test.php @@ -32,7 +32,12 @@ class phpbb_console_command_cron_list_test extends phpbb_test_case protected function setUp() { - $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + global $phpbb_root_path, $phpEx; + + $this->user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $this->user->method('lang')->will($this->returnArgument(0)); } diff --git a/tests/console/cron/run_test.php b/tests/console/cron/run_test.php index 8638648898..51ea49b282 100644 --- a/tests/console/cron/run_test.php +++ b/tests/console/cron/run_test.php @@ -41,7 +41,10 @@ class phpbb_console_command_cron_run_test extends phpbb_database_test_case $config = $this->config = new \phpbb\config\config(array('cron_lock' => '0')); $this->lock = new \phpbb\lock\db('cron_lock', $this->config, $this->db); - $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $this->user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $this->user->method('lang')->will($this->returnArgument(0)); $this->task = new phpbb_cron_task_simple(); diff --git a/tests/content_visibility/delete_post_test.php b/tests/content_visibility/delete_post_test.php index dc966c37ae..b59b6493d4 100644 --- a/tests/content_visibility/delete_post_test.php +++ b/tests/content_visibility/delete_post_test.php @@ -309,7 +309,9 @@ class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case ->will($this->returnValueMap(array( array('m_approve', 1, true), ))); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); diff --git a/tests/content_visibility/get_forums_visibility_sql_test.php b/tests/content_visibility/get_forums_visibility_sql_test.php index 28e463ecb5..6c5066119e 100644 --- a/tests/content_visibility/get_forums_visibility_sql_test.php +++ b/tests/content_visibility/get_forums_visibility_sql_test.php @@ -134,7 +134,9 @@ class phpbb_content_visibility_get_forums_visibility_sql_test extends phpbb_data ->method('acl_getf') ->with($this->stringContains('_'), $this->anything()) ->will($this->returnValueMap($permissions)); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $config = new phpbb\config\config(array()); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/content_visibility/get_global_visibility_sql_test.php b/tests/content_visibility/get_global_visibility_sql_test.php index 586bae8668..9ae4182673 100644 --- a/tests/content_visibility/get_global_visibility_sql_test.php +++ b/tests/content_visibility/get_global_visibility_sql_test.php @@ -134,7 +134,9 @@ class phpbb_content_visibility_get_global_visibility_sql_test extends phpbb_data ->method('acl_getf') ->with($this->stringContains('_'), $this->anything()) ->will($this->returnValueMap($permissions)); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $config = new phpbb\config\config(array()); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/content_visibility/get_visibility_sql_test.php b/tests/content_visibility/get_visibility_sql_test.php index 9ae2d2fdc4..aaaf64330e 100644 --- a/tests/content_visibility/get_visibility_sql_test.php +++ b/tests/content_visibility/get_visibility_sql_test.php @@ -81,7 +81,9 @@ class phpbb_content_visibility_get_visibility_sql_test extends phpbb_database_te ->method('acl_get') ->with($this->stringContains('_'), $this->anything()) ->will($this->returnValueMap($permissions)); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $config = new phpbb\config\config(array()); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/content_visibility/set_post_visibility_test.php b/tests/content_visibility/set_post_visibility_test.php index 36ebf58374..6375ce8f6d 100644 --- a/tests/content_visibility/set_post_visibility_test.php +++ b/tests/content_visibility/set_post_visibility_test.php @@ -124,7 +124,9 @@ class phpbb_content_visibility_set_post_visibility_test extends phpbb_database_t $cache = new phpbb_mock_cache; $db = $this->new_dbal(); $auth = $this->getMock('\phpbb\auth\auth'); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $config = new phpbb\config\config(array()); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); @@ -175,7 +177,9 @@ class phpbb_content_visibility_set_post_visibility_test extends phpbb_database_t $cache = new phpbb_mock_cache; $db = $this->new_dbal(); $auth = $this->getMock('\phpbb\auth\auth'); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $config = new phpbb\config\config(array()); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/content_visibility/set_topic_visibility_test.php b/tests/content_visibility/set_topic_visibility_test.php index 6c34f42167..f4d65f9ce3 100644 --- a/tests/content_visibility/set_topic_visibility_test.php +++ b/tests/content_visibility/set_topic_visibility_test.php @@ -88,7 +88,9 @@ class phpbb_content_visibility_set_topic_visibility_test extends phpbb_database_ $cache = new phpbb_mock_cache; $db = $this->new_dbal(); $auth = $this->getMock('\phpbb\auth\auth'); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $config = new phpbb\config\config(array()); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index f1f369cce6..3e4b5fd38d 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -84,7 +84,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case ); $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $this->user = new \phpbb\user($lang, '\phpbb\datetime');; $container = new phpbb_mock_container_builder(); $cache_path = $phpbb_root_path . 'cache/twig'; diff --git a/tests/datetime/from_format_test.php b/tests/datetime/from_format_test.php index 8968619bb5..7ecb546768 100644 --- a/tests/datetime/from_format_test.php +++ b/tests/datetime/from_format_test.php @@ -37,7 +37,11 @@ class phpbb_datetime_from_format_test extends phpbb_test_case */ public function test_from_format($timezone, $format, $expected) { - $user = new \phpbb\user('\phpbb\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->timezone = new DateTimeZone($timezone); $user->lang['datetime'] = array( 'TODAY' => 'Today', @@ -107,7 +111,11 @@ class phpbb_datetime_from_format_test extends phpbb_test_case */ public function test_relative_format_date($timestamp, $forcedate, $expected) { - $user = new \phpbb\user('\phpbb\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->timezone = new DateTimeZone('UTC'); $user->lang['datetime'] = array( 'TODAY' => 'Today', diff --git a/tests/dbal/migrator_tool_module_test.php b/tests/dbal/migrator_tool_module_test.php index fa2a8c33df..a665c8c13e 100644 --- a/tests/dbal/migrator_tool_module_test.php +++ b/tests/dbal/migrator_tool_module_test.php @@ -32,7 +32,9 @@ class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case $db = $this->db = $this->new_dbal(); $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\null(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx); - $user = $this->user = new \phpbb\user('\phpbb\user'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = $this->user = new \phpbb\user($lang, '\phpbb\datetime'); $cache = new phpbb_mock_cache; $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); diff --git a/tests/event/exception_listener_test.php b/tests/event/exception_listener_test.php index 4d3453cd83..608cde4f9b 100644 --- a/tests/event/exception_listener_test.php +++ b/tests/event/exception_listener_test.php @@ -79,7 +79,11 @@ class exception_listener extends phpbb_test_case ->disableOriginalConstructor() ->getMock(); - $user = new \phpbb\user('\phpbb\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->add_lang('common'); $exception_listener = new \phpbb\event\kernel_exception_subscriber($template, $user); diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index c269eee987..101ab8616c 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -45,7 +45,6 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $this->db_tools = $factory->get($this->db); $this->phpbb_root_path = dirname(__FILE__) . '/'; $this->phpEx = 'php'; - $this->user = new \phpbb\user('\phpbb\datetime'); $this->table_prefix = 'phpbb_'; $container = new phpbb_mock_container_builder(); @@ -75,8 +74,6 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case 'autoescape' => false, ) ); - $this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $this->user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); - $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $container = new phpbb_mock_container_builder(); @@ -104,6 +101,16 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $this->phpEx, $this->cache ); + + global $phpbb_root_path; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $this->phpEx); + $lang_loader->set_extension_manager($this->extension_manager); + $lang = new \phpbb\language\language($lang_loader); + $this->user = new \phpbb\user($lang, '\phpbb\datetime'); + + $this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $this->user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); + $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); } // Should fail from missing composer.json @@ -168,7 +175,7 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $manager->validate($field_name); $this->fail('Exception not triggered'); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', $field_name)); @@ -234,7 +241,7 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $manager->validate($field_name); $this->fail('Exception not triggered'); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->assertEquals($message, $this->user->lang('META_FIELD_INVALID', $field_name)); @@ -259,10 +266,9 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case { $this->assertEquals(true, $manager->validate('enable')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); - $this->fail($message); } } diff --git a/tests/functions/generate_string_list.php b/tests/functions/generate_string_list.php index cd1e37618a..bcf0c09fe4 100644 --- a/tests/functions/generate_string_list.php +++ b/tests/functions/generate_string_list.php @@ -22,7 +22,12 @@ class phpbb_generate_string_list_test extends phpbb_test_case { parent::setUp(); - $this->user = new \phpbb\user('\phpbb\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); + $this->user = $user; $this->user->data = array('user_lang' => 'en'); $this->user->add_lang('common'); } @@ -36,7 +41,7 @@ class phpbb_generate_string_list_test extends phpbb_test_case ), array( array('A'), - 'A', + 'A', ), array( array(2 => 'A', 3 => 'B'), diff --git a/tests/groupposition/legend_test.php b/tests/groupposition/legend_test.php index fe003e93a7..566a8a2935 100644 --- a/tests/groupposition/legend_test.php +++ b/tests/groupposition/legend_test.php @@ -33,11 +33,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case */ public function test_get_group_value($group_id, $expected, $throws_exception) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); if ($throws_exception) @@ -51,11 +53,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case public function test_get_group_count() { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\legend($db, $user); @@ -91,11 +95,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case */ public function test_add_group($group_id, $expected_added, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\legend($db, $user); @@ -179,11 +185,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case */ public function test_delete_group($group_id, $skip_group, $expected_deleted, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\legend($db, $user); @@ -234,11 +242,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case */ public function test_move_up($group_id, $excepted_moved, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\legend($db, $user); @@ -289,11 +299,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case */ public function test_move_down($group_id, $excepted_moved, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\legend($db, $user); @@ -387,11 +399,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case */ public function test_move($group_id, $increment, $excepted_moved, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\legend($db, $user); diff --git a/tests/groupposition/teampage_test.php b/tests/groupposition/teampage_test.php index 1e61e3ebfb..dff52f7a43 100644 --- a/tests/groupposition/teampage_test.php +++ b/tests/groupposition/teampage_test.php @@ -35,11 +35,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case */ public function test_get_group_value($group_id, $expected, $throws_exception) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); if ($throws_exception) @@ -53,11 +55,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case public function test_get_group_count() { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -137,11 +141,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case */ public function test_add_group_teampage($group_id, $parent_id, $expected_added, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -180,11 +186,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case */ public function test_add_category_teampage($group_name, $expected_added, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -247,11 +255,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case */ public function test_delete_group($group_id, $expected_deleted, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -299,11 +309,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case */ public function test_delete_teampage($teampage_id, $expected_deleted, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -462,11 +474,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case */ public function test_move($group_id, $move_delta, $excepted_moved, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -625,11 +639,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case */ public function test_move_teampage($teampage_id, $move_delta, $excepted_moved, $expected) { - global $cache; + global $cache, $phpbb_root_path, $phpEx; $cache = new phpbb_mock_cache; $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = array(); $test_class = new \phpbb\groupposition\teampage($db, $user, $cache); diff --git a/tests/language/language_test.php b/tests/language/language_test.php new file mode 100644 index 0000000000..95de403bd4 --- /dev/null +++ b/tests/language/language_test.php @@ -0,0 +1,210 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_language_test extends phpbb_test_case +{ + /** @var \phpbb\language\language */ + protected $lang; + + public function setUp() + { + global $phpbb_root_path, $phpEx; + + // Set up language service + $this->lang = new \phpbb\language\language( + new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx) + ); + + // Set up language data for testing + $reflection_class = new ReflectionClass('\phpbb\language\language'); + + // Set default language files loaded flag to true + $loaded_flag = $reflection_class->getProperty('common_language_files_loaded'); + $loaded_flag->setAccessible(true); + $loaded_flag->setValue($this->lang, true); + + // Set up test language data + $lang_array = $reflection_class->getProperty('lang'); + $lang_array->setAccessible(true); + $lang_array->setValue($this->lang, $this->get_test_data_set()); + } + + public function test_lang() + { + // No param + $this->assertEquals($this->lang->lang('FOO'), 'BAR'); + $this->assertEquals($this->lang->lang('EMPTY'), ''); + $this->assertEquals($this->lang->lang('ZERO'), '0'); + + // Invalid index + $this->assertEquals($this->lang->lang('VOID'), 'VOID'); + + // Unnecessary param + $this->assertEquals($this->lang->lang('FOO', 2), 'BAR'); + $this->assertEquals($this->lang->lang('FOO', 2, 3), 'BAR'); + $this->assertEquals($this->lang->lang('FOO', 2, 3, 'BARZ'), 'BAR'); + + // String + $this->assertEquals($this->lang->lang('STR', 24, 'x', 42), '24 x, 42 topics'); + $this->assertEquals($this->lang->lang('STR2', 64), '64 foos'); + + // Array + $this->assertEquals($this->lang->lang('ARRY', 0), 'No posts'); + $this->assertEquals($this->lang->lang('ARRY', 1), '1 post'); + $this->assertEquals($this->lang->lang('ARRY', 2), '2 posts'); + $this->assertEquals($this->lang->lang('ARRY', 123), '123 posts'); + + // Empty array returns the language key + $this->assertEquals($this->lang->lang('ARRY_EMPTY', 123), 'ARRY_EMPTY'); + + // No 0 key defined + $this->assertEquals($this->lang->lang('ARRY_NO_ZERO', 0), '0 posts'); + $this->assertEquals($this->lang->lang('ARRY_NO_ZERO', 1), '1 post'); + $this->assertEquals($this->lang->lang('ARRY_NO_ZERO', 2), '2 posts'); + + // Array with missing keys + $this->assertEquals($this->lang->lang('ARRY_MISSING', 2), '2 post'); + + // Floats as array key + $this->assertEquals($this->lang->lang('ARRY_FLOAT', 1.3), '1 post'); + $this->assertEquals($this->lang->lang('ARRY_FLOAT', 2.0), '2.0 posts'); + $this->assertEquals($this->lang->lang('ARRY_FLOAT', 2.51), '2.5 posts'); + + // Use sub key, if first paramenter is an array + $this->assertEquals($this->lang->lang(array('dateformat', 'AGO'), 2), '2 seconds'); + + // ticket PHPBB3-9949 - use first int to determinate the plural-form to use + $this->assertEquals($this->lang->lang('ARRY', 1, 2), '1 post'); + $this->assertEquals($this->lang->lang('ARRY', 1, 's', 2), '1 post'); + } + + public function test_lang_plural_rules() + { + $this->assertEquals($this->lang->lang('PLURAL_ARRY', 0), '0 is 0'); + $this->assertEquals($this->lang->lang('PLURAL_ARRY', 1), '1 is 1'); + $this->assertEquals($this->lang->lang('PLURAL_ARRY', 103), '103 ends with 01-10'); + $this->assertEquals($this->lang->lang('PLURAL_ARRY', 15), '15 ends with 11-19'); + $this->assertEquals($this->lang->lang('PLURAL_ARRY', 300), '300 is part of the last rule'); + } + + public function test_lang_bc() + { + $user = new \phpbb\user($this->lang, '\phpbb\datetime'); + + // Test lang array access + $this->assertEquals($user->lang['FOO'], 'BAR'); + + // No param + $this->assertEquals($user->lang('FOO'), 'BAR'); + $this->assertEquals($user->lang('EMPTY'), ''); + $this->assertEquals($user->lang('ZERO'), '0'); + + // Invalid index + $this->assertEquals($user->lang('VOID'), 'VOID'); + + // Unnecessary param + $this->assertEquals($user->lang('FOO', 2), 'BAR'); + $this->assertEquals($user->lang('FOO', 2, 3), 'BAR'); + $this->assertEquals($user->lang('FOO', 2, 3, 'BARZ'), 'BAR'); + + // String + $this->assertEquals($user->lang('STR', 24, 'x', 42), '24 x, 42 topics'); + $this->assertEquals($user->lang('STR2', 64), '64 foos'); + + // Array + $this->assertEquals($user->lang('ARRY', 0), 'No posts'); + $this->assertEquals($user->lang('ARRY', 1), '1 post'); + $this->assertEquals($user->lang('ARRY', 2), '2 posts'); + $this->assertEquals($user->lang('ARRY', 123), '123 posts'); + + // Empty array returns the language key + $this->assertEquals($user->lang('ARRY_EMPTY', 123), 'ARRY_EMPTY'); + + // No 0 key defined + $this->assertEquals($user->lang('ARRY_NO_ZERO', 0), '0 posts'); + $this->assertEquals($user->lang('ARRY_NO_ZERO', 1), '1 post'); + $this->assertEquals($user->lang('ARRY_NO_ZERO', 2), '2 posts'); + + // Array with missing keys + $this->assertEquals($user->lang('ARRY_MISSING', 2), '2 post'); + + // Floats as array key + $this->assertEquals($user->lang('ARRY_FLOAT', 1.3), '1 post'); + $this->assertEquals($user->lang('ARRY_FLOAT', 2.0), '2.0 posts'); + $this->assertEquals($user->lang('ARRY_FLOAT', 2.51), '2.5 posts'); + + // Use sub key, if first paramenter is an array + $this->assertEquals($user->lang(array('dateformat', 'AGO'), 2), '2 seconds'); + + // ticket PHPBB3-9949 - use first int to determinate the plural-form to use + $this->assertEquals($user->lang('ARRY', 1, 2), '1 post'); + $this->assertEquals($user->lang('ARRY', 1, 's', 2), '1 post'); + } + + public function test_lang_plural_rules_bc() + { + $user = new \phpbb\user($this->lang, '\phpbb\datetime'); + + // ticket PHPBB3-10345 - different plural rules, not just 0/1/2+ + $this->assertEquals($user->lang('PLURAL_ARRY', 0), '0 is 0'); + $this->assertEquals($user->lang('PLURAL_ARRY', 1), '1 is 1'); + $this->assertEquals($user->lang('PLURAL_ARRY', 103), '103 ends with 01-10'); + $this->assertEquals($user->lang('PLURAL_ARRY', 15), '15 ends with 11-19'); + $this->assertEquals($user->lang('PLURAL_ARRY', 300), '300 is part of the last rule'); + } + + protected function get_test_data_set() + { + return array( + 'FOO' => 'BAR', + 'BARZ' => 'PENG', + 'EMPTY' => '', + 'ZERO' => '0', + 'STR' => '%d %s, %d topics', + 'STR2' => '%d foos', + 'ARRY' => array( + 0 => 'No posts', // 0 + 1 => '1 post', // 1 + 2 => '%d posts', // 2+ + ), + 'ARRY_NO_ZERO' => array( + 1 => '1 post', // 1 + 2 => '%d posts', // 0, 2+ + ), + 'ARRY_MISSING' => array( + 1 => '%d post', // 1 + //Missing second plural + ), + 'ARRY_FLOAT' => array( + 1 => '1 post', // 1.x + 2 => '%1$.1f posts', // 0.x, 2+.x + ), + 'ARRY_EMPTY' => array( + ), + 'dateformat' => array( + 'AGO' => array( + 1 => '%d second', + 2 => '%d seconds', + ), + ), + 'PLURAL_RULE' => 13, + 'PLURAL_ARRY' => array( + 0 => '%d is 0', // 0 + 1 => '%d is 1', // 1 + 2 => '%d ends with 01-10', // ending with 01-10 + 3 => '%d ends with 11-19', // ending with 11-19 + 4 => '%d is part of the last rule', // everything else + ), + ); + } +} diff --git a/tests/log/add_test.php b/tests/log/add_test.php index bacc0c76f7..cfc592a464 100644 --- a/tests/log/add_test.php +++ b/tests/log/add_test.php @@ -27,7 +27,9 @@ class phpbb_log_add_test extends phpbb_database_test_case $db = $this->new_dbal(); $cache = new phpbb_mock_cache; $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $auth = $this->getMock('\phpbb\auth\auth'); $log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); @@ -56,7 +58,9 @@ class phpbb_log_add_test extends phpbb_database_test_case $db = $this->new_dbal(); $cache = new phpbb_mock_cache; $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $auth = $this->getMock('\phpbb\auth\auth'); $log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); diff --git a/tests/log/delete_test.php b/tests/log/delete_test.php index ec43182a0c..fe4c3835cb 100644 --- a/tests/log/delete_test.php +++ b/tests/log/delete_test.php @@ -30,7 +30,9 @@ class phpbb_log_delete_test extends phpbb_database_test_case $db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->data['user_id'] = 1; $auth = $this->getMock('\phpbb\auth\auth'); diff --git a/tests/log/function_add_log_test.php b/tests/log/function_add_log_test.php index 78949734a9..cdfeb52996 100644 --- a/tests/log/function_add_log_test.php +++ b/tests/log/function_add_log_test.php @@ -161,7 +161,10 @@ class phpbb_log_function_add_log_test extends phpbb_database_test_case $db = $this->new_dbal(); $cache = new phpbb_mock_cache; $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $auth = $this->getMock('\phpbb\auth\auth'); $phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); diff --git a/tests/notification/base.php b/tests/notification/base.php index 162feae557..c9d57a5934 100644 --- a/tests/notification/base.php +++ b/tests/notification/base.php @@ -56,7 +56,10 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case 'allow_topic_notify' => true, 'allow_forum_notify' => true, )); - $user = $this->user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); + $this->user = $user; $this->user_loader = new \phpbb\user_loader($this->db, $phpbb_root_path, $phpEx, 'phpbb_users'); $auth = $this->auth = new phpbb_mock_notifications_auth(); $cache = $this->cache = new \phpbb\cache\service( @@ -66,7 +69,7 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case $phpbb_root_path, $phpEx ); - + $this->phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $phpbb_container = $this->container = new phpbb_mock_container_builder(); diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php index 2d621f82d3..1412fb8509 100644 --- a/tests/notification/submit_post_base.php +++ b/tests/notification/submit_post_base.php @@ -83,7 +83,10 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); // User - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $user->ip = ''; $user->data = array( 'user_id' => 2, diff --git a/tests/notification/user_list_trim_test.php b/tests/notification/user_list_trim_test.php index 5886c49512..bcbdc81ef0 100644 --- a/tests/notification/user_list_trim_test.php +++ b/tests/notification/user_list_trim_test.php @@ -51,7 +51,9 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case array('u_viewprofile', 1, false), ))); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->data = array('user_lang' => 'en'); $user->add_lang('common'); @@ -71,7 +73,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case 'topic_title' => 'Test', 'poster_id' => 2, 'post_username' => 'A', - 'responders' => null, + 'responders' => null, ), 'Reply from A in topic:', ), @@ -82,7 +84,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case 'post_username' => 'A', 'responders' => array( array('username' => '', 'poster_id' => 3), - ), + ), ), 'Reply from A and B in topic:', ), @@ -94,7 +96,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case 'responders' => array( array('username' => '', 'poster_id' => 3), array('username' => '', 'poster_id' => 4), - ), + ), ), 'Reply from A, B, and C in topic:', ), @@ -107,7 +109,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case array('username' => '', 'poster_id' => 3), array('username' => '', 'poster_id' => 4), array('username' => '', 'poster_id' => 5), - ), + ), ), 'Reply from A, B, C, and D in topic:', ), @@ -121,7 +123,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case array('username' => '', 'poster_id' => 4), array('username' => '', 'poster_id' => 5), array('username' => '', 'poster_id' => 6), - ), + ), ), 'Reply from A, B, C, and 2 others in topic:', ), diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index c705e67135..4916665a72 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -26,10 +26,13 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case { parent::setUp(); - global $phpbb_dispatcher; + global $phpbb_dispatcher, $phpbb_root_path, $phpEx; $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $this->user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $this->user->expects($this->any()) ->method('lang') ->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/plupload/plupload_test.php b/tests/plupload/plupload_test.php index 2f47bf2b39..aa7793567d 100644 --- a/tests/plupload/plupload_test.php +++ b/tests/plupload/plupload_test.php @@ -34,6 +34,10 @@ class phpbb_plupload_test extends phpbb_test_case */ public function test_generate_resize_string($config_width, $config_height, $expected) { + global $phpbb_root_path, $phpEx; + + $lang = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); + $config = new \phpbb\config\config(array( 'img_max_width' => $config_width, 'img_max_height' => $config_height, @@ -43,7 +47,7 @@ class phpbb_plupload_test extends phpbb_test_case '', $config, new phpbb_mock_request, - new \phpbb\user('\phpbb\datetime'), + new \phpbb\user($lang, '\phpbb\datetime'), new \phpbb\php\ini, new \phpbb\mimetype\guesser(array(new \phpbb\mimetype\extension_guesser)) ); diff --git a/tests/profilefields/type_bool_test.php b/tests/profilefields/type_bool_test.php index 41c40ddb4b..10239172c3 100644 --- a/tests/profilefields/type_bool_test.php +++ b/tests/profilefields/type_bool_test.php @@ -25,7 +25,12 @@ class phpbb_profilefield_type_bool_test extends phpbb_test_case */ public function setUp() { - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + global $phpbb_root_path, $phpEx; + + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $user->expects($this->any()) ->method('lang') ->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/profilefields/type_date_test.php b/tests/profilefields/type_date_test.php index 123955198e..e0807b2f9b 100644 --- a/tests/profilefields/type_date_test.php +++ b/tests/profilefields/type_date_test.php @@ -25,7 +25,12 @@ class phpbb_profilefield_type_date_test extends phpbb_test_case */ public function setUp() { - $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + global $phpbb_root_path, $phpEx; + + $this->user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $this->user->expects($this->any()) ->method('lang') ->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/profilefields/type_dropdown_test.php b/tests/profilefields/type_dropdown_test.php index 3845a8e96b..ab02353fb9 100644 --- a/tests/profilefields/type_dropdown_test.php +++ b/tests/profilefields/type_dropdown_test.php @@ -25,7 +25,12 @@ class phpbb_profilefield_type_dropdown_test extends phpbb_test_case */ public function setUp() { - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + global $phpbb_root_path, $phpEx; + + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $user->expects($this->any()) ->method('lang') ->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/profilefields/type_googleplus_test.php b/tests/profilefields/type_googleplus_test.php index f3db6ef01f..6faf939231 100644 --- a/tests/profilefields/type_googleplus_test.php +++ b/tests/profilefields/type_googleplus_test.php @@ -21,7 +21,11 @@ class phpbb_profilefield_type_googleplus_test extends phpbb_test_case { parent::setUp(); - $user = new \phpbb\user('\phpbb\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->add_lang('ucp'); $request = $this->getMock('\phpbb\request\request'); $template = $this->getMock('\phpbb\template\template'); diff --git a/tests/profilefields/type_int_test.php b/tests/profilefields/type_int_test.php index 07b22525e2..33f3f575c8 100644 --- a/tests/profilefields/type_int_test.php +++ b/tests/profilefields/type_int_test.php @@ -24,7 +24,12 @@ class phpbb_profilefield_type_int_test extends phpbb_test_case */ public function setUp() { - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + global $phpbb_root_path, $phpEx; + + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $user->expects($this->any()) ->method('lang') ->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/profilefields/type_string_test.php b/tests/profilefields/type_string_test.php index 0417afbfab..447ab32a00 100644 --- a/tests/profilefields/type_string_test.php +++ b/tests/profilefields/type_string_test.php @@ -28,9 +28,12 @@ class phpbb_profilefield_type_string_test extends phpbb_test_case */ public function setUp() { - global $request, $user, $cache; + global $request, $user, $cache, $phpbb_root_path, $phpEx; - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $cache = new phpbb_mock_cache; $user->expects($this->any()) ->method('lang') diff --git a/tests/profilefields/type_url_test.php b/tests/profilefields/type_url_test.php index cc37f04f30..a0f93fe1f6 100644 --- a/tests/profilefields/type_url_test.php +++ b/tests/profilefields/type_url_test.php @@ -26,7 +26,12 @@ class phpbb_profilefield_type_url_test extends phpbb_test_case */ public function setUp() { - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + global $phpbb_root_path, $phpEx; + + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $user->expects($this->any()) ->method('lang') ->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/security/base.php b/tests/security/base.php index 5888a2bf2a..d2abdbc362 100644 --- a/tests/security/base.php +++ b/tests/security/base.php @@ -49,7 +49,9 @@ abstract class phpbb_security_test_base extends phpbb_test_case $phpbb_filesystem = new \phpbb\filesystem\filesystem(); // Set no user and trick a bit to circumvent errors - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->lang = true; $user->browser = $this->server['HTTP_USER_AGENT']; $user->referer = ''; diff --git a/tests/template/template_allfolder_test.php b/tests/template/template_allfolder_test.php index f739a78d84..63f35bc758 100644 --- a/tests/template/template_allfolder_test.php +++ b/tests/template/template_allfolder_test.php @@ -28,7 +28,10 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case $defaults = $this->config_defaults(); $config = new \phpbb\config\config(array_merge($defaults, $new_config)); - $this->user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); + $this->user = $user; $path_helper = new \phpbb\path_helper( new \phpbb\symfony_request( diff --git a/tests/template/template_test_case.php b/tests/template/template_test_case.php index 29ff669efc..7e2020ba09 100644 --- a/tests/template/template_test_case.php +++ b/tests/template/template_test_case.php @@ -15,6 +15,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_template_template_test_case extends phpbb_test_case { + protected $lang; protected $template; protected $template_path; protected $user; @@ -24,6 +25,17 @@ class phpbb_template_template_test_case extends phpbb_test_case // Keep the contents of the cache for debugging? const PRESERVE_CACHE = true; + static protected $language_reflection_lang; + + static public function setUpBeforeClass() + { + parent::setUpBeforeClass(); + + $reflection = new ReflectionClass('\phpbb\language\language'); + self::$language_reflection_lang = $reflection->getProperty('lang'); + self::$language_reflection_lang->setAccessible(true); + } + protected function display($handle) { ob_start(); @@ -65,7 +77,10 @@ class phpbb_template_template_test_case extends phpbb_test_case $defaults = $this->config_defaults(); $config = new \phpbb\config\config(array_merge($defaults, $new_config)); - $this->user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $this->lang = $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); + $this->user = $user; $path_helper = new \phpbb\path_helper( new \phpbb\symfony_request( @@ -145,7 +160,10 @@ class phpbb_template_template_test_case extends phpbb_test_case { foreach ($lang_vars as $name => $value) { - $this->user->lang[$name] = $value; + self::$language_reflection_lang->setValue($this->lang, array_merge( + self::$language_reflection_lang->getValue($this->lang), + array($name => $value) + )); } } diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index c1ec287477..2be6c46a6d 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -614,7 +614,10 @@ class phpbb_functional_test_case extends phpbb_test_case $db = $this->get_db(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $auth = $this->getMock('\phpbb\auth\auth'); $phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); @@ -653,7 +656,10 @@ class phpbb_functional_test_case extends phpbb_test_case $db = $this->get_db(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $auth = $this->getMock('\phpbb\auth\auth'); $phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 0f9b049f44..685014d3e4 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -474,7 +474,9 @@ class phpbb_test_case_helpers } else { - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewcensors', true); $user->optionset('viewflash', true); $user->optionset('viewimg', true); diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index 91458541d3..3c0bbb96c7 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -157,7 +157,11 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case 'banana', function ($phpbb_container) { - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewcensors', false); $phpbb_container->set('user', $user); @@ -168,7 +172,11 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case 'banana', function ($phpbb_container) { - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewcensors', false); $config = new \phpbb\config\config(array('allow_nocensors' => true)); @@ -182,7 +190,11 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case 'apple', function ($phpbb_container, $test) { - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewcensors', false); $config = new \phpbb\config\config(array('allow_nocensors' => true)); @@ -207,7 +219,11 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case 'http://localhost/foo.swf', function ($phpbb_container) { - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewflash', false); $phpbb_container->set('user', $user); @@ -222,7 +238,11 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case 'http://localhost/mrgreen.gif', function ($phpbb_container) { - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewimg', false); $phpbb_container->set('user', $user); @@ -237,7 +257,11 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case ':)', function ($phpbb_container) { - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('smilies', false); $phpbb_container->set('user', $user); @@ -291,9 +315,13 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case 2 => 'bold' ); + global $phpbb_root_path, $phpEx; + foreach ($tests as $style_id => $expected) { - $user = new \phpbb\user('\\phpbb\\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->style = array('style_id' => $style_id); $phpbb_container = new phpbb_mock_container_builder; @@ -311,10 +339,12 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case public function test_style_inheritance1() { - global $phpbb_container; + global $phpbb_container, $phpbb_root_path, $phpEx; // Style 3 inherits from 2 which inherits from 1. Only style 1 has a bbcode.html - $user = new \phpbb\user('\\phpbb\\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->style = array('style_id' => 3); $phpbb_container = new phpbb_mock_container_builder; @@ -331,7 +361,7 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case public function test_style_inheritance2() { - global $phpbb_container; + global $phpbb_container, $phpbb_root_path, $phpEx; // Style 5 inherits from 4, but both have a bbcode.html $tests = array( @@ -341,7 +371,9 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case foreach ($tests as $style_id => $expected) { - $user = new \phpbb\user('\\phpbb\\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->style = array('style_id' => $style_id); $phpbb_container = new phpbb_mock_container_builder; diff --git a/tests/text_processing/generate_text_for_display_test.php b/tests/text_processing/generate_text_for_display_test.php index fe83938c0b..f2b0d6c78b 100644 --- a/tests/text_processing/generate_text_for_display_test.php +++ b/tests/text_processing/generate_text_for_display_test.php @@ -34,8 +34,12 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca { global $cache, $user; + global $phpbb_root_path, $phpEx; + $cache = new phpbb_mock_cache; - $user = new \phpbb\user('\\phpbb\\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewcensors', true); $user->optionset('viewflash', true); $user->optionset('viewimg', true); @@ -66,7 +70,11 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca $phpbb_container = new phpbb_mock_container_builder; - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewcensors', false); $config = new \phpbb\config\config(array('allow_nocensors' => true)); @@ -153,7 +161,11 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca true, function ($phpbb_container) { - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewflash', false); $phpbb_container->set('user', $user); @@ -169,7 +181,11 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca true, function ($phpbb_container) { - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('viewimg', false); $phpbb_container->set('user', $user); @@ -185,7 +201,11 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca true, function ($phpbb_container) { - $user = new \phpbb\user('\\phpbb\\datetime'); + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $user->optionset('smilies', false); $phpbb_container->set('user', $user); diff --git a/tests/user/lang_test.php b/tests/user/lang_test.php deleted file mode 100644 index bb11bb63cb..0000000000 --- a/tests/user/lang_test.php +++ /dev/null @@ -1,119 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; - -class phpbb_user_lang_test extends phpbb_test_case -{ - public function test_user_lang_sprintf() - { - $user = new \phpbb\user('\phpbb\datetime'); - $user->lang = array( - 'FOO' => 'BAR', - 'BARZ' => 'PENG', - 'EMPTY' => '', - 'ZERO' => '0', - 'STR' => '%d %s, %d topics', - 'STR2' => '%d foos', - 'ARRY' => array( - 0 => 'No posts', // 0 - 1 => '1 post', // 1 - 2 => '%d posts', // 2+ - ), - 'ARRY_NO_ZERO' => array( - 1 => '1 post', // 1 - 2 => '%d posts', // 0, 2+ - ), - 'ARRY_MISSING' => array( - 1 => '%d post', // 1 - //Missing second plural - ), - 'ARRY_FLOAT' => array( - 1 => '1 post', // 1.x - 2 => '%1$.1f posts', // 0.x, 2+.x - ), - 'ARRY_EMPTY' => array( - ), - 'dateformat' => array( - 'AGO' => array( - 1 => '%d second', - 2 => '%d seconds', - ), - ), - ); - - // No param - $this->assertEquals($user->lang('FOO'), 'BAR'); - $this->assertEquals($user->lang('EMPTY'), ''); - $this->assertEquals($user->lang('ZERO'), '0'); - - // Invalid index - $this->assertEquals($user->lang('VOID'), 'VOID'); - - // Unnecessary param - $this->assertEquals($user->lang('FOO', 2), 'BAR'); - $this->assertEquals($user->lang('FOO', 2, 3), 'BAR'); - $this->assertEquals($user->lang('FOO', 2, 3, 'BARZ'), 'BAR'); - - // String - $this->assertEquals($user->lang('STR', 24, 'x', 42), '24 x, 42 topics'); - $this->assertEquals($user->lang('STR2', 64), '64 foos'); - - // Array - $this->assertEquals($user->lang('ARRY', 0), 'No posts'); - $this->assertEquals($user->lang('ARRY', 1), '1 post'); - $this->assertEquals($user->lang('ARRY', 2), '2 posts'); - $this->assertEquals($user->lang('ARRY', 123), '123 posts'); - - // Empty array returns the language key - $this->assertEquals($user->lang('ARRY_EMPTY', 123), 'ARRY_EMPTY'); - - // No 0 key defined - $this->assertEquals($user->lang('ARRY_NO_ZERO', 0), '0 posts'); - $this->assertEquals($user->lang('ARRY_NO_ZERO', 1), '1 post'); - $this->assertEquals($user->lang('ARRY_NO_ZERO', 2), '2 posts'); - - // Array with missing keys - $this->assertEquals($user->lang('ARRY_MISSING', 2), '2 post'); - - // Floats as array key - $this->assertEquals($user->lang('ARRY_FLOAT', 1.3), '1 post'); - $this->assertEquals($user->lang('ARRY_FLOAT', 2.0), '2.0 posts'); - $this->assertEquals($user->lang('ARRY_FLOAT', 2.51), '2.5 posts'); - - // Use sub key, if first paramenter is an array - $this->assertEquals($user->lang(array('dateformat', 'AGO'), 2), '2 seconds'); - - // ticket PHPBB3-9949 - use first int to determinate the plural-form to use - $this->assertEquals($user->lang('ARRY', 1, 2), '1 post'); - $this->assertEquals($user->lang('ARRY', 1, 's', 2), '1 post'); - - // ticket PHPBB3-10345 - different plural rules, not just 0/1/2+ - $user = new \phpbb\user('\phpbb\datetime'); - $user->lang = array( - 'PLURAL_RULE' => 13, - 'ARRY' => array( - 0 => '%d is 0', // 0 - 1 => '%d is 1', // 1 - 2 => '%d ends with 01-10', // ending with 01-10 - 3 => '%d ends with 11-19', // ending with 11-19 - 4 => '%d is part of the last rule', // everything else - ), - ); - $this->assertEquals($user->lang('ARRY', 0), '0 is 0'); - $this->assertEquals($user->lang('ARRY', 1), '1 is 1'); - $this->assertEquals($user->lang('ARRY', 103), '103 ends with 01-10'); - $this->assertEquals($user->lang('ARRY', 15), '15 ends with 11-19'); - $this->assertEquals($user->lang('ARRY', 300), '300 is part of the last rule'); - } -} diff --git a/tests/version/version_fetch_test.php b/tests/version/version_fetch_test.php index cfc87183cf..6ecc9b7223 100644 --- a/tests/version/version_fetch_test.php +++ b/tests/version/version_fetch_test.php @@ -28,13 +28,15 @@ class phpbb_version_helper_fetch_test extends phpbb_test_case ->disableOriginalConstructor() ->getMock(); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $this->version_helper = new \phpbb\version_helper( $this->cache, new \phpbb\config\config(array( 'version' => '3.1.0', )), new \phpbb\file_downloader(), - new \phpbb\user('\phpbb\datetime') + new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime') ); } diff --git a/tests/version/version_helper_remote_test.php b/tests/version/version_helper_remote_test.php index 65ae7646b9..05ae320713 100644 --- a/tests/version/version_helper_remote_test.php +++ b/tests/version/version_helper_remote_test.php @@ -37,13 +37,15 @@ class version_helper_remote_test extends \phpbb_test_case ->will($this->returnValue(false)); $this->file_downloader = new phpbb_mock_file_downloader(); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $this->version_helper = new \phpbb\version_helper( $this->cache, $config, $this->file_downloader, - new \phpbb\user('\phpbb\datetime') + new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime') ); - $this->user = new \phpbb\user('\phpbb\datetime'); + $this->user = new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime'); $this->user->add_lang('acp/common'); } diff --git a/tests/version/version_test.php b/tests/version/version_test.php index 528f1602d6..05577f6a18 100644 --- a/tests/version/version_test.php +++ b/tests/version/version_test.php @@ -25,13 +25,15 @@ class phpbb_version_helper_test extends phpbb_test_case ->disableOriginalConstructor() ->getMock(); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $this->version_helper = new \phpbb\version_helper( $this->cache, new \phpbb\config\config(array( 'version' => '3.1.0', )), new \phpbb\file_downloader(), - new \phpbb\user('\phpbb\datetime') + new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime') ); } @@ -199,6 +201,11 @@ class phpbb_version_helper_test extends phpbb_test_case */ public function test_get_suggested_updates($current_version, $versions, $expected) { + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $version_helper = $this ->getMockBuilder('\phpbb\version_helper') ->setMethods(array( @@ -210,7 +217,7 @@ class phpbb_version_helper_test extends phpbb_test_case 'version' => $current_version, )), new \phpbb\file_downloader(), - new \phpbb\user('\phpbb\datetime'), + new \phpbb\user($lang, '\phpbb\datetime'), )) ->getMock() ; @@ -310,6 +317,11 @@ class phpbb_version_helper_test extends phpbb_test_case */ public function test_get_latest_on_current_branch($current_version, $versions, $expected) { + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $version_helper = $this ->getMockBuilder('\phpbb\version_helper') ->setMethods(array( @@ -321,7 +333,7 @@ class phpbb_version_helper_test extends phpbb_test_case 'version' => $current_version, )), new \phpbb\file_downloader(), - new \phpbb\user('\phpbb\datetime'), + new \phpbb\user($lang, '\phpbb\datetime'), )) ->getMock() ; From 9f1f6f96ceaf0870dabd0cf68c40292682c04aa2 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Tue, 28 Apr 2015 22:52:43 +0200 Subject: [PATCH 0259/1676] [ticket/13762] Optional DI injectable default language module array PHPBB3-13762 --- phpBB/phpbb/language/language.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/language/language.php b/phpBB/phpbb/language/language.php index 9c9a3b8df1..3298908365 100644 --- a/phpBB/phpbb/language/language.php +++ b/phpBB/phpbb/language/language.php @@ -73,9 +73,10 @@ class language /** * Constructor * - * @param \phpbb\language\language_file_loader $loader Language file loader + * @param \phpbb\language\language_file_loader $loader Language file loader + * @param array|null $common_modules Array of common language modules to load (optional) */ - public function __construct(language_file_loader $loader) + public function __construct(language_file_loader $loader, $common_modules = null) { $this->loader = $loader; @@ -92,9 +93,17 @@ class language ); // Common language files - $this->common_language_files = array( - 'common', - ); + if (is_array($common_modules)) + { + $this->common_language_files = $common_modules; + } + else + { + $this->common_language_files = array( + 'common', + ); + } + $this->common_language_files_loaded = false; $this->language_fallback = array(self::FALLBACK_LANGUAGE); From 9a99c9e4b10eba614517e335527c332761b473a4 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Wed, 29 Apr 2015 01:00:13 +0200 Subject: [PATCH 0260/1676] [ticket/13762] Replace user service with lang in twig extension PHPBB3-13762 --- phpBB/config/default/container/services_twig.yml | 2 +- phpBB/phpbb/template/twig/extension.php | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index 5d7bf0eff3..6b54311f41 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -33,7 +33,7 @@ services: class: phpbb\template\twig\extension arguments: - @template_context - - @user + - @language tags: - { name: twig.extension } diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php index 14d1258c09..92f87a0331 100644 --- a/phpBB/phpbb/template/twig/extension.php +++ b/phpBB/phpbb/template/twig/extension.php @@ -18,20 +18,20 @@ class extension extends \Twig_Extension /** @var \phpbb\template\context */ protected $context; - /** @var \phpbb\user */ - protected $user; + /** @var \phpbb\language\language */ + protected $language; /** * Constructor * * @param \phpbb\template\context $context - * @param \phpbb\user $user + * @param \phpbb\language\language $language * @return \phpbb\template\twig\extension */ - public function __construct(\phpbb\template\context $context, $user) + public function __construct(\phpbb\template\context $context, $language) { $this->context = $context; - $this->user = $user; + $this->language = $language; } /** @@ -181,6 +181,6 @@ class extension extends \Twig_Extension // LA_ is transformed into lang(\'$1\')|escape('js'), so we should not // need to check for it - return call_user_func_array(array($this->user, 'lang'), $args); + return call_user_func_array(array($this->language, 'lang'), $args); } } From 74dbaac0394f45955553ff46515404fe5b06bfba Mon Sep 17 00:00:00 2001 From: MateBartus Date: Thu, 30 Apr 2015 22:40:17 +0200 Subject: [PATCH 0261/1676] [ticket/13800] Make router's extension manager dependency optional PHPBB3-13800 --- phpBB/config/default/container/services.yml | 20 +------------------ .../default/container/services_routing.yml | 19 ++++++++++++++++++ phpBB/phpbb/routing/router.php | 17 +++++++++------- tests/controller/common_helper_route.php | 2 +- tests/controller/controller_test.php | 2 +- tests/pagination/pagination_test.php | 2 +- 6 files changed, 33 insertions(+), 29 deletions(-) create mode 100644 phpBB/config/default/container/services_routing.yml diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 670ea3bd61..95d624a8ae 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -15,6 +15,7 @@ imports: - { resource: services_password.yml } - { resource: services_profilefield.yml } - { resource: services_report.yml } + - { resource: services_routing.yml } - { resource: services_text_formatter.yml } - { resource: services_twig.yml } - { resource: services_user.yml } @@ -157,25 +158,6 @@ services: - null - %core.disable_super_globals% - router: - class: phpbb\routing\router - arguments: - - @filesystem - - @ext.manager - - %core.root_path% - - %core.php_ext% - - %core.environment% - - router.listener: - class: Symfony\Component\HttpKernel\EventListener\RouterListener - arguments: - - @router - - null - - null - - @request_stack - tags: - - { name: kernel.event_subscriber } - # WARNING: The Symfony request does not escape the input and should be used very carefully # prefer the phpbb request (service @request) as possible symfony_request: diff --git a/phpBB/config/default/container/services_routing.yml b/phpBB/config/default/container/services_routing.yml new file mode 100644 index 0000000000..6749202c0d --- /dev/null +++ b/phpBB/config/default/container/services_routing.yml @@ -0,0 +1,19 @@ +services: + router: + class: phpbb\routing\router + arguments: + - @filesystem + - %core.root_path% + - %core.php_ext% + - %core.environment% + - @ext.manager + + router.listener: + class: Symfony\Component\HttpKernel\EventListener\RouterListener + arguments: + - @router + - null + - null + - @request_stack + tags: + - { name: kernel.event_subscriber } diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 7444f06253..dd5bffe22b 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -94,13 +94,14 @@ class router implements RouterInterface * Construct method * * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem helper - * @param manager $extension_manager Extension manager - * @param string $phpbb_root_path phpBB root path - * @param string $php_ext PHP file extension - * @param string $environment Name of the current environment - * @param array $routing_files Array of strings containing paths to YAML files holding route information + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP file extension + * @param string $environment Name of the current environment + * @param manager|null $extension_manager Extension manager + * @param array $routing_files Array of strings containing paths to YAML files + * holding route information */ - public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, manager $extension_manager, $phpbb_root_path, $php_ext, $environment, $routing_files = array()) + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext, $environment, manager $extension_manager = null, $routing_files = array()) { $this->filesystem = $filesystem; $this->extension_manager = $extension_manager; @@ -172,7 +173,9 @@ class router implements RouterInterface { if ($this->route_collection == null || empty($this->routing_files)) { - $this->find_routing_files($this->extension_manager->all_enabled(false)) + $this->find_routing_files( + ($this->extension_manager !== null) ? $this->extension_manager->all_enabled(false) : array() + ) ->find($this->phpbb_root_path); } diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index 3e4b5fd38d..6910530279 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -120,7 +120,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case ) ); - $this->router = new phpbb_mock_router($this->filesystem, $this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); + $this->router = new phpbb_mock_router($this->filesystem, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $this->extension_manager); $this->router->find_routing_files($this->extension_manager->all_enabled(false)); $this->router->find(dirname(__FILE__) . '/'); // Set correct current phpBB root path diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php index 5c0290ee6f..5781d3ebc1 100644 --- a/tests/controller/controller_test.php +++ b/tests/controller/controller_test.php @@ -40,7 +40,7 @@ class phpbb_controller_controller_test extends phpbb_test_case public function test_router_find_files() { - $router = new \phpbb\routing\router(new \phpbb\filesystem\filesystem(), $this->extension_manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); + $router = new \phpbb\routing\router(new \phpbb\filesystem\filesystem(), dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $this->extension_manager); $router->find_routing_files($this->extension_manager->all_enabled(false)); $routes = $router->find(__DIR__)->get_routes(); diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index 4916665a72..67c3d0a30f 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -41,7 +41,7 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case $manager = new phpbb_mock_extension_manager(dirname(__FILE__) . '/', array()); $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $router = new phpbb_mock_router($filesystem, $manager, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT); + $router = new phpbb_mock_router($filesystem, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $manager); $router->find_routing_files($manager->all_enabled(false)); $router->find(dirname(__FILE__) . '/'); From b3cc20a575da12e7b66f3883dcc7f0eb6ca82ad8 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 4 May 2015 10:09:37 +0200 Subject: [PATCH 0262/1676] [ticket/13782] Rename null driver to dummy for PHP7 compatibility PHPBB3-13782 --- phpBB/install/install_convert.php | 6 +++--- phpBB/install/install_install.php | 6 +++--- phpBB/install/install_update.php | 2 +- phpBB/phpbb/cache/driver/{null.php => dummy.php} | 4 ++-- tests/cache/null_driver_test.php | 2 +- tests/dbal/migrator_tool_module_test.php | 2 +- tests/dbal/migrator_tool_permission_test.php | 2 +- tests/functions_user/group_user_attributes_test.php | 2 +- tests/notification/base.php | 2 +- tests/notification/submit_post_base.php | 2 +- tests/notification/user_list_trim_test.php | 2 +- tests/test_framework/phpbb_functional_test_case.php | 6 +++--- tests/version/version_helper_remote_test.php | 2 +- 13 files changed, 20 insertions(+), 20 deletions(-) rename phpBB/phpbb/cache/driver/{null.php => dummy.php} (96%) diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index e268565be3..408c14e981 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -153,7 +153,7 @@ class install_convert extends module unset($dbpasswd); // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE); + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); // Detect if there is already a conversion in progress at this point and offer to resume // It's quite possible that the user will get disconnected during a large conversion so they need to be able to resume it @@ -392,7 +392,7 @@ class install_convert extends module $this->page_title = $lang['STAGE_SETTINGS']; // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE); + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); $convertor_tag = $request->variable('tag', ''); @@ -639,7 +639,7 @@ class install_convert extends module unset($dbpasswd); // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE); + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); // Override a couple of config variables for the duration $config['max_quote_depth'] = 0; diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 3c37a028cb..be6fa40566 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -1522,7 +1522,7 @@ class install_install extends module include_once($phpbb_root_path . 'phpbb/search/fulltext_native.' . $phpEx); // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE); + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); $error = false; $search = new \phpbb\search\fulltext_native($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); @@ -1937,7 +1937,7 @@ class install_install extends module $data = $this->get_submitted_data(); // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE); + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " @@ -2009,7 +2009,7 @@ class install_install extends module $data = $this->get_submitted_data(); // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE); + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); $user->session_begin(); $auth->login($data['admin_name'], $data['admin_pass1'], false, true, true); diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index 410a8afb66..288e728fce 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -118,7 +118,7 @@ class install_update extends module unset($dbpasswd); // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE); + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); // Force template recompile $config['load_tplcompile'] = 1; diff --git a/phpBB/phpbb/cache/driver/null.php b/phpBB/phpbb/cache/driver/dummy.php similarity index 96% rename from phpBB/phpbb/cache/driver/null.php rename to phpBB/phpbb/cache/driver/dummy.php index 298731ea54..1f74f6dd77 100644 --- a/phpBB/phpbb/cache/driver/null.php +++ b/phpBB/phpbb/cache/driver/dummy.php @@ -14,9 +14,9 @@ namespace phpbb\cache\driver; /** -* ACM Null Caching +* ACM dummy Caching */ -class null extends \phpbb\cache\driver\base +class dummy extends \phpbb\cache\driver\base { /** * Set cache path diff --git a/tests/cache/null_driver_test.php b/tests/cache/null_driver_test.php index b9f96732f5..d5af57b009 100644 --- a/tests/cache/null_driver_test.php +++ b/tests/cache/null_driver_test.php @@ -24,7 +24,7 @@ class phpbb_cache_null_driver_test extends phpbb_database_test_case { parent::setUp(); - $this->driver = new \phpbb\cache\driver\null; + $this->driver = new \phpbb\cache\driver\dummy; } public function test_get_put() diff --git a/tests/dbal/migrator_tool_module_test.php b/tests/dbal/migrator_tool_module_test.php index a665c8c13e..695a7e7a7f 100644 --- a/tests/dbal/migrator_tool_module_test.php +++ b/tests/dbal/migrator_tool_module_test.php @@ -31,7 +31,7 @@ class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case $skip_add_log = true; $db = $this->db = $this->new_dbal(); - $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\null(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx); + $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\dummy(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx); $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); $lang = new \phpbb\language\language($lang_loader); $user = $this->user = new \phpbb\user($lang, '\phpbb\datetime'); diff --git a/tests/dbal/migrator_tool_permission_test.php b/tests/dbal/migrator_tool_permission_test.php index 4453fbf123..3d190e7a11 100644 --- a/tests/dbal/migrator_tool_permission_test.php +++ b/tests/dbal/migrator_tool_permission_test.php @@ -28,7 +28,7 @@ class phpbb_dbal_migrator_tool_permission_test extends phpbb_database_test_case parent::setup(); $db = $this->db = $this->new_dbal(); - $cache = $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\null(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx); + $cache = $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\dummy(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx); $this->auth = new \phpbb\auth\auth(); $this->tool = new \phpbb\db\migration\tool\permission($this->db, $this->cache, $this->auth, $phpbb_root_path, $phpEx); diff --git a/tests/functions_user/group_user_attributes_test.php b/tests/functions_user/group_user_attributes_test.php index 99a15b32bf..6ccada44f8 100644 --- a/tests/functions_user/group_user_attributes_test.php +++ b/tests/functions_user/group_user_attributes_test.php @@ -139,7 +139,7 @@ class phpbb_functions_user_group_user_attributes_test extends phpbb_database_tes $auth = $this->getMock('\phpbb\auth\auth'); $auth->expects($this->any()) ->method('acl_clear_prefetch'); - $cache_driver = new \phpbb\cache\driver\null(); + $cache_driver = new \phpbb\cache\driver\dummy(); $phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); $phpbb_container ->expects($this->any()) diff --git a/tests/notification/base.php b/tests/notification/base.php index c9d57a5934..a1ebecd6f9 100644 --- a/tests/notification/base.php +++ b/tests/notification/base.php @@ -63,7 +63,7 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case $this->user_loader = new \phpbb\user_loader($this->db, $phpbb_root_path, $phpEx, 'phpbb_users'); $auth = $this->auth = new phpbb_mock_notifications_auth(); $cache = $this->cache = new \phpbb\cache\service( - new \phpbb\cache\driver\null(), + new \phpbb\cache\driver\dummy(), $this->config, $this->db, $phpbb_root_path, diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php index 1412fb8509..d7a711e007 100644 --- a/tests/notification/submit_post_base.php +++ b/tests/notification/submit_post_base.php @@ -72,7 +72,7 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c $config = new \phpbb\config\config(array('num_topics' => 1,'num_posts' => 1,)); $cache = new \phpbb\cache\service( - new \phpbb\cache\driver\null(), + new \phpbb\cache\driver\dummy(), $config, $db, $phpbb_root_path, diff --git a/tests/notification/user_list_trim_test.php b/tests/notification/user_list_trim_test.php index bcbdc81ef0..f7b4fcb215 100644 --- a/tests/notification/user_list_trim_test.php +++ b/tests/notification/user_list_trim_test.php @@ -35,7 +35,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case $config = new \phpbb\config\config(array()); $cache = new \phpbb\cache\service( - new \phpbb\cache\driver\null(), + new \phpbb\cache\driver\dummy(), $config, $db, $phpbb_root_path, diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 2be6c46a6d..0fec3c2dff 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -574,7 +574,7 @@ class phpbb_functional_test_case extends phpbb_test_case } $cache = new phpbb_mock_null_cache; - $cache_driver = new \phpbb\cache\driver\null(); + $cache_driver = new \phpbb\cache\driver\dummy(); $phpbb_container = new phpbb_mock_container_builder(); $phpbb_container->set('cache.driver', $cache_driver); $phpbb_notifications = new phpbb_mock_notification_manager(); @@ -623,7 +623,7 @@ class phpbb_functional_test_case extends phpbb_test_case $phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); $cache = new phpbb_mock_null_cache; - $cache_driver = new \phpbb\cache\driver\null(); + $cache_driver = new \phpbb\cache\driver\dummy(); $phpbb_container = new phpbb_mock_container_builder(); $phpbb_container->set('cache.driver', $cache_driver); $phpbb_container->set('notification_manager', new phpbb_mock_notification_manager()); @@ -665,7 +665,7 @@ class phpbb_functional_test_case extends phpbb_test_case $phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); $cache = new phpbb_mock_null_cache; - $cache_driver = new \phpbb\cache\driver\null(); + $cache_driver = new \phpbb\cache\driver\dummy(); $phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); $phpbb_container ->expects($this->any()) diff --git a/tests/version/version_helper_remote_test.php b/tests/version/version_helper_remote_test.php index 05ae320713..724c4c970c 100644 --- a/tests/version/version_helper_remote_test.php +++ b/tests/version/version_helper_remote_test.php @@ -30,7 +30,7 @@ class version_helper_remote_test extends \phpbb_test_case )); $container = new \phpbb_mock_container_builder(); $db = new \phpbb\db\driver\factory($container); - $this->cache = $this->getMock('\phpbb\cache\service', array('get'), array(new \phpbb\cache\driver\null(), $config, $db, '../../', 'php')); + $this->cache = $this->getMock('\phpbb\cache\service', array('get'), array(new \phpbb\cache\driver\dummy(), $config, $db, '../../', 'php')); $this->cache->expects($this->any()) ->method('get') ->with($this->anything()) From 232f71dae43df9794184961431aca81d0e4652da Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 4 May 2015 10:11:28 +0200 Subject: [PATCH 0263/1676] [ticket/13782] Rename null log to dummy for PHP7 compatibility PHPBB3-13782 --- phpBB/phpbb/log/{null.php => dummy.php} | 4 ++-- tests/console/cache/purge_test.php | 2 +- tests/notification/group_request_test.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename phpBB/phpbb/log/{null.php => dummy.php} (95%) diff --git a/phpBB/phpbb/log/null.php b/phpBB/phpbb/log/dummy.php similarity index 95% rename from phpBB/phpbb/log/null.php rename to phpBB/phpbb/log/dummy.php index baa78895ea..5c2d145e15 100644 --- a/phpBB/phpbb/log/null.php +++ b/phpBB/phpbb/log/dummy.php @@ -14,9 +14,9 @@ namespace phpbb\log; /** -* Null logger +* Dummy logger */ -class null implements log_interface +class dummy implements log_interface { /** * {@inheritdoc} diff --git a/tests/console/cache/purge_test.php b/tests/console/cache/purge_test.php index 172fb0ecf3..6c92660580 100644 --- a/tests/console/cache/purge_test.php +++ b/tests/console/cache/purge_test.php @@ -91,7 +91,7 @@ class phpbb_console_command_cache_purge_test extends phpbb_test_case public function get_command_tester() { $application = new Application(); - $application->add(new purge($this->user, $this->cache, $this->db, $this->getMock('\phpbb\auth\auth'), new \phpbb\log\null(), $this->config)); + $application->add(new purge($this->user, $this->cache, $this->db, $this->getMock('\phpbb\auth\auth'), new \phpbb\log\dummy(), $this->config)); $command = $application->find('cache:purge'); $this->command_name = $command->getName(); diff --git a/tests/notification/group_request_test.php b/tests/notification/group_request_test.php index 6a56a38c45..a24808fbbd 100644 --- a/tests/notification/group_request_test.php +++ b/tests/notification/group_request_test.php @@ -50,7 +50,7 @@ class phpbb_notification_group_request_test extends phpbb_tests_notification_bas $this->cache->get_driver() )); $phpbb_dispatcher = new phpbb_mock_event_dispatcher; - $phpbb_log = new \phpbb\log\null(); + $phpbb_log = new \phpbb\log\dummy(); $this->get_test_case_helpers()->set_s9e_services(); // Now on to the actual test From 292d0ab382563143082bd8809ec189d646a31e0e Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 4 May 2015 10:12:41 +0200 Subject: [PATCH 0264/1676] [ticket/13782] Rename null driver test to dummy driver test PHPBB3-13782 --- tests/cache/{null_driver_test.php => dummy_driver_test.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/cache/{null_driver_test.php => dummy_driver_test.php} (96%) diff --git a/tests/cache/null_driver_test.php b/tests/cache/dummy_driver_test.php similarity index 96% rename from tests/cache/null_driver_test.php rename to tests/cache/dummy_driver_test.php index d5af57b009..6cb6b73729 100644 --- a/tests/cache/null_driver_test.php +++ b/tests/cache/dummy_driver_test.php @@ -11,7 +11,7 @@ * */ -class phpbb_cache_null_driver_test extends phpbb_database_test_case +class phpbb_cache_dummy_driver_test extends phpbb_database_test_case { protected $driver; From 0d2c8b5961d461913557795e8d99c0fa0be87448 Mon Sep 17 00:00:00 2001 From: rxu Date: Mon, 4 May 2015 16:51:09 +0700 Subject: [PATCH 0265/1676] [ticket/13814] Prevent phpbb_is_writable() method from truncating files phpbb_is_writable() of filesystem class uses 'w' mode to fopen files which causes checked files to be truncated. Use the 'c' mode instead. PHPBB3-13814 --- phpBB/phpbb/filesystem/filesystem.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/filesystem/filesystem.php b/phpBB/phpbb/filesystem/filesystem.php index 370dff77e5..2112882d1d 100644 --- a/phpBB/phpbb/filesystem/filesystem.php +++ b/phpBB/phpbb/filesystem/filesystem.php @@ -613,7 +613,7 @@ class filesystem implements filesystem_interface } else { - $handle = @fopen($file, 'w'); + $handle = @fopen($file, 'c'); if (is_resource($handle)) { From f821130c3a4a22efd491aaad962cc84a82dde56a Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 25 Nov 2014 17:04:15 +0100 Subject: [PATCH 0266/1676] [ticket/12632] Add twig.debug and twig.auto_reload in config.yml PHPBB3-13206 PHPBB3-12632 --- phpBB/config/default/container/services_twig.yml | 1 + phpBB/config/development/config.yml | 2 ++ .../phpbb/di/extension/container_configuration.php | 2 ++ phpBB/phpbb/di/extension/core.php | 14 ++++++++++++++ phpBB/phpbb/template/twig/environment.php | 2 +- .../fixtures/config/test/container/environment.yml | 11 +++++++++++ .../other_config/test/container/environment.yml | 11 +++++++++++ 7 files changed, 42 insertions(+), 1 deletion(-) diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index 6b54311f41..6214adfac6 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -11,6 +11,7 @@ services: - %core.template.cache_path% - @ext.manager - @template.twig.loader + - [] template.twig.lexer: class: phpbb\template\twig\lexer diff --git a/phpBB/config/development/config.yml b/phpBB/config/development/config.yml index f451eebe13..93ae07fb3f 100644 --- a/phpBB/config/development/config.yml +++ b/phpBB/config/development/config.yml @@ -5,4 +5,6 @@ core: require_dev_dependencies: true twig: + debug: true + auto_reload: true enable_debug_extension: true diff --git a/phpBB/phpbb/di/extension/container_configuration.php b/phpBB/phpbb/di/extension/container_configuration.php index ee58ec2b74..4cc7c7c0d1 100644 --- a/phpBB/phpbb/di/extension/container_configuration.php +++ b/phpBB/phpbb/di/extension/container_configuration.php @@ -34,6 +34,8 @@ class container_configuration implements ConfigurationInterface ->arrayNode('twig') ->addDefaultsIfNotSet() ->children() + ->booleanNode('debug')->defaultValue(null)->end() + ->booleanNode('auto_reload')->defaultValue(null)->end() ->booleanNode('enable_debug_extension')->defaultValue(false)->end() ->end() ->end() diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index c71dc61280..c9e2d4dc5b 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -69,6 +69,20 @@ class core extends Extension } } + // Set the Twig options if defined in the environment + $definition = $container->getDefinition('template.twig.environment'); + $twig_environment_options = $definition->getArgument(6); + if ($config['twig']['debug']) + { + $twig_environment_options['debug'] = true; + } + if ($config['twig']['auto_reload']) + { + $twig_environment_options['auto_reload'] = true; + } + // Replace the 6th argument, the options passed to the environment + $definition->replaceArgument(6, $twig_environment_options); + if ($config['twig']['enable_debug_extension']) { $definition = $container->getDefinition('template.twig.extensions.debug'); diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php index 0ba7a265e4..fcd0566b6e 100644 --- a/phpBB/phpbb/template/twig/environment.php +++ b/phpBB/phpbb/template/twig/environment.php @@ -60,7 +60,7 @@ class environment extends \Twig_Environment $options = array_merge(array( 'cache' => (defined('IN_INSTALL')) ? false : $cache_path, - 'debug' => defined('DEBUG'), + 'debug' => false, 'auto_reload' => (bool) $this->phpbb_config['load_tplcompile'], 'autoescape' => false, ), $options); diff --git a/tests/di/fixtures/config/test/container/environment.yml b/tests/di/fixtures/config/test/container/environment.yml index f2a22ae109..0873078844 100644 --- a/tests/di/fixtures/config/test/container/environment.yml +++ b/tests/di/fixtures/config/test/container/environment.yml @@ -12,3 +12,14 @@ services: dispatcher: class: phpbb\db\driver\container_mock + + template.twig.environment: + class: Exception + arguments: + - ~ + - ~ + - ~ + - ~ + - ~ + - ~ + - [] diff --git a/tests/di/fixtures/other_config/test/container/environment.yml b/tests/di/fixtures/other_config/test/container/environment.yml index c299bfc648..2aa29db2eb 100644 --- a/tests/di/fixtures/other_config/test/container/environment.yml +++ b/tests/di/fixtures/other_config/test/container/environment.yml @@ -12,3 +12,14 @@ services: dispatcher: class: phpbb\db\driver\container_mock + + template.twig.environment: + class: Exception + arguments: + - ~ + - ~ + - ~ + - ~ + - ~ + - ~ + - [] From 3b631cb40d1641dce8789fabd79e3cbc5598747d Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Sun, 22 Feb 2015 16:56:57 +0100 Subject: [PATCH 0267/1676] [ticket/13638] Prepend the assets path phpbb root PHPBB3-13638 --- phpBB/phpbb/template/asset.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/template/asset.php b/phpBB/phpbb/template/asset.php index 4729685459..d9ed861034 100644 --- a/phpBB/phpbb/template/asset.php +++ b/phpBB/phpbb/template/asset.php @@ -153,9 +153,9 @@ class asset public function set_path($path, $urlencode = false) { // Since 1.7.0 Twig returns the real path of the file. We need it to be relative to the working directory. - $real_root_path = realpath('.') . DIRECTORY_SEPARATOR; + $real_root_path = realpath($this->path_helper->get_phpbb_root_path()) . DIRECTORY_SEPARATOR; if ($real_root_path && substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path) { - $path = str_replace('\\', '/', substr($path, strlen($real_root_path))); + $path = $this->path_helper->get_phpbb_root_path() . str_replace('\\', '/', substr($path, strlen($real_root_path))); } if ($urlencode) From f097f84f16f32e8d9c0148907f0ae5743f09619f Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Sun, 22 Feb 2015 18:38:30 +0100 Subject: [PATCH 0268/1676] [ticket/13638] Handle assets outside of phpbb_root_path PHPBB3-13638 --- phpBB/phpbb/template/asset.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/template/asset.php b/phpBB/phpbb/template/asset.php index d9ed861034..aa1689d71a 100644 --- a/phpBB/phpbb/template/asset.php +++ b/phpBB/phpbb/template/asset.php @@ -152,11 +152,23 @@ class asset */ public function set_path($path, $urlencode = false) { - // Since 1.7.0 Twig returns the real path of the file. We need it to be relative to the working directory. - $real_root_path = realpath($this->path_helper->get_phpbb_root_path()) . DIRECTORY_SEPARATOR; - if ($real_root_path && substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path) { + // Since 1.7.0 Twig returns the real path of the file. We need it to be relative. + $real_root_path = phpbb_realpath($this->path_helper->get_phpbb_root_path()) . DIRECTORY_SEPARATOR; + + // If the asset is under the phpBB root path we need to remove its path and then prepend $phpbb_root_path + if ($real_root_path && substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path) + { $path = $this->path_helper->get_phpbb_root_path() . str_replace('\\', '/', substr($path, strlen($real_root_path))); } + else + { + // Else we make the path relative to the current working directory + $real_root_path = phpbb_realpath('.') . DIRECTORY_SEPARATOR; + if ($real_root_path && substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path) + { + $path = str_replace('\\', '/', substr($path, strlen($real_root_path))); + } + } if ($urlencode) { From 321ed2a3dd10231a09dec18a85a783a73ba12ddf Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Sun, 22 Feb 2015 22:43:53 +0100 Subject: [PATCH 0269/1676] [ticket/13638] Add tests PHPBB3-13638 --- tests/template/asset_test.php | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/template/asset_test.php diff --git a/tests/template/asset_test.php b/tests/template/asset_test.php new file mode 100644 index 0000000000..f84ea2e3ee --- /dev/null +++ b/tests/template/asset_test.php @@ -0,0 +1,49 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use phpbb\template\asset; + +class phpbb_template_asset_test extends phpbb_test_case +{ + public function set_path_data() + { + return array( + // array(phpbb_root_path, given path, expected path), + array('.', 'foo/bar', 'foo/bar'), + array('../', 'foo/bar', 'foo/bar'), + array('./phpBB/', 'foo/bar', 'foo/bar'), + array('../', __DIR__ . '/foo/bar', '../phpbb/tests/template/foo/bar'), + array('./', __DIR__ . '/foo/bar', './tests/template/foo/bar'), + array('./phpBB/', __DIR__ . '/foo/bar', 'tests/template/foo/bar'), + ); + } + + /** + * @dataProvider set_path_data + */ + public function test_set_path($phpbb_root_path, $path, $expected) + { + $path_helper = $this->getMockBuilder('\phpbb\path_helper') + ->disableOriginalConstructor() + ->setMethods(array()) + ->getMock(); + + $path_helper->method('get_phpbb_root_path') + ->willReturn($phpbb_root_path); + + $asset = new asset('', $path_helper); + + $asset->set_path($path, true); + $this->assertEquals($expected, $asset->get_path()); + } +} From 51376a43919cba7a5037edb7cc31f18b5950437b Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Mon, 4 May 2015 23:50:16 +0200 Subject: [PATCH 0270/1676] [ticket/13638] Inject $filesystem in \phpbb\template\asset PHPBB3-13638 --- .../default/container/services_twig.yml | 1 + phpBB/includes/bbcode.php | 1 + phpBB/includes/functions_messenger.php | 1 + phpBB/install/index.php | 1 + phpBB/phpbb/template/asset.php | 11 +++++--- phpBB/phpbb/template/twig/environment.php | 25 +++++++++++++++---- .../phpbb/template/twig/node/includeasset.php | 2 +- tests/controller/common_helper_route.php | 1 + tests/extension/metadata_manager_test.php | 6 +++-- tests/template/asset_test.php | 2 +- tests/template/template_allfolder_test.php | 5 +++- tests/template/template_events_test.php | 3 +++ tests/template/template_includecss_test.php | 5 +++- tests/template/template_test_case.php | 5 +++- .../template/template_test_case_with_tree.php | 5 +++- 15 files changed, 58 insertions(+), 16 deletions(-) diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index 6b54311f41..9ab004731e 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -6,6 +6,7 @@ services: class: phpbb\template\twig\environment arguments: - @config + - @filesystem - @path_helper - @service_container - %core.template.cache_path% diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index 53675637a0..150157e275 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -142,6 +142,7 @@ class bbcode new \phpbb\template\context(), new \phpbb\template\twig\environment( $phpbb_container->get('config'), + $phpbb_container->get('filesystem'), $phpbb_container->get('path_helper'), $phpbb_container, $phpbb_container->getParameter('core.root_path') . 'cache/', diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index b0861585ba..4cbe1eb425 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -637,6 +637,7 @@ class messenger new \phpbb\template\context(), new \phpbb\template\twig\environment( $phpbb_container->get('config'), + $phpbb_container->get('filesystem'), $phpbb_container->get('path_helper'), $phpbb_container, $phpbb_container->getParameter('core.root_path') . 'cache/', diff --git a/phpBB/install/index.php b/phpBB/install/index.php index df1229c9f2..657825ca39 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -280,6 +280,7 @@ $cache_path = $phpbb_root_path . 'cache/'; $twig_environment = new \phpbb\template\twig\environment( $config, + $phpbb_filesystem, $phpbb_path_helper, $phpbb_container, $cache_path, diff --git a/phpBB/phpbb/template/asset.php b/phpBB/phpbb/template/asset.php index aa1689d71a..cb00f16549 100644 --- a/phpBB/phpbb/template/asset.php +++ b/phpBB/phpbb/template/asset.php @@ -20,15 +20,20 @@ class asset /** @var \phpbb\path_helper **/ protected $path_helper; + /** @var \phpbb\filesystem\filesystem */ + protected $filesystem; + /** * Constructor * * @param string $url URL * @param \phpbb\path_helper $path_helper Path helper object + * @param \phpbb\filesystem\filesystem $filesystem */ - public function __construct($url, \phpbb\path_helper $path_helper) + public function __construct($url, \phpbb\path_helper $path_helper, \phpbb\filesystem\filesystem $filesystem) { $this->path_helper = $path_helper; + $this->filesystem = $filesystem; $this->set_url($url); } @@ -153,7 +158,7 @@ class asset public function set_path($path, $urlencode = false) { // Since 1.7.0 Twig returns the real path of the file. We need it to be relative. - $real_root_path = phpbb_realpath($this->path_helper->get_phpbb_root_path()) . DIRECTORY_SEPARATOR; + $real_root_path = $this->filesystem->realpath($this->path_helper->get_phpbb_root_path()) . DIRECTORY_SEPARATOR; // If the asset is under the phpBB root path we need to remove its path and then prepend $phpbb_root_path if ($real_root_path && substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path) @@ -163,7 +168,7 @@ class asset else { // Else we make the path relative to the current working directory - $real_root_path = phpbb_realpath('.') . DIRECTORY_SEPARATOR; + $real_root_path = $this->filesystem->realpath('.') . DIRECTORY_SEPARATOR; if ($real_root_path && substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path) { $path = str_replace('\\', '/', substr($path, strlen($real_root_path))); diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php index 0ba7a265e4..e7b8aeab89 100644 --- a/phpBB/phpbb/template/twig/environment.php +++ b/phpBB/phpbb/template/twig/environment.php @@ -18,6 +18,9 @@ class environment extends \Twig_Environment /** @var \phpbb\config\config */ protected $phpbb_config; + /** @var \phpbb\filesystem\filesystem */ + protected $filesystem; + /** @var \phpbb\path_helper */ protected $phpbb_path_helper; @@ -40,6 +43,7 @@ class environment extends \Twig_Environment * Constructor * * @param \phpbb\config\config $phpbb_config The phpBB configuration + * @param \phpbb\filesystem\filesystem $filesystem * @param \phpbb\path_helper $path_helper phpBB path helper * @param \Symfony\Component\DependencyInjection\ContainerInterface $container The dependency injection container * @param string $cache_path The path to the cache directory @@ -47,10 +51,11 @@ class environment extends \Twig_Environment * @param \Twig_LoaderInterface $loader Twig loader interface * @param array $options Array of options to pass to Twig */ - public function __construct($phpbb_config, \phpbb\path_helper $path_helper, \Symfony\Component\DependencyInjection\ContainerInterface $container, $cache_path, \phpbb\extension\manager $extension_manager = null, \Twig_LoaderInterface $loader = null, $options = array()) + public function __construct(\phpbb\config\config $phpbb_config, \phpbb\filesystem\filesystem $filesystem, \phpbb\path_helper $path_helper, \Symfony\Component\DependencyInjection\ContainerInterface $container, $cache_path, \phpbb\extension\manager $extension_manager = null, \Twig_LoaderInterface $loader = null, $options = array()) { $this->phpbb_config = $phpbb_config; + $this->filesystem = $filesystem; $this->phpbb_path_helper = $path_helper; $this->extension_manager = $extension_manager; $this->container = $container; @@ -106,15 +111,25 @@ class environment extends \Twig_Environment } /** - * Get the phpBB root path - * - * @return string - */ + * Get the phpBB root path + * + * @return string + */ public function get_phpbb_root_path() { return $this->phpbb_root_path; } + /** + * Get the filesystem object + * + * @return \phpbb\filesystem\filesystem + */ + public function get_filesystem() + { + return $this->filesystem; + } + /** * Get the web root path * diff --git a/phpBB/phpbb/template/twig/node/includeasset.php b/phpBB/phpbb/template/twig/node/includeasset.php index 15195a226b..324823b8d7 100644 --- a/phpBB/phpbb/template/twig/node/includeasset.php +++ b/phpBB/phpbb/template/twig/node/includeasset.php @@ -39,7 +39,7 @@ abstract class includeasset extends \Twig_Node ->write("\$asset_file = ") ->subcompile($this->getNode('expr')) ->raw(";\n") - ->write("\$asset = new \phpbb\\template\\asset(\$asset_file, \$this->getEnvironment()->get_path_helper());\n") + ->write("\$asset = new \phpbb\\template\\asset(\$asset_file, \$this->getEnvironment()->get_path_helper(), \$this->getEnvironment()->get_filesystem());\n") ->write("if (substr(\$asset_file, 0, 2) !== './' && \$asset->is_relative()) {\n") ->indent() ->write("\$asset_path = \$asset->get_path();") diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index 3e4b5fd38d..b01241e105 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -94,6 +94,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case $loader = new \phpbb\template\twig\loader($this->filesystem, ''); $twig = new \phpbb\template\twig\environment( $this->config, + $this->filesystem, $this->phpbb_path_helper, $container, $cache_path, diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index 101ab8616c..aaaee3b2e5 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -51,17 +51,19 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $cache_path = $this->phpbb_root_path . 'cache/twig'; $context = new \phpbb\template\context(); $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); - $phpbb_path_helper =new \phpbb\path_helper( + $filesystem = new \phpbb\filesystem\filesystem(); + $phpbb_path_helper = new \phpbb\path_helper( new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem\filesystem(), + $filesystem, $this->getMock('\phpbb\request\request'), $this->phpbb_root_path, $this->phpEx ); $twig = new \phpbb\template\twig\environment( $this->config, + $filesystem, $phpbb_path_helper, $container, $cache_path, diff --git a/tests/template/asset_test.php b/tests/template/asset_test.php index f84ea2e3ee..f6ce0fe241 100644 --- a/tests/template/asset_test.php +++ b/tests/template/asset_test.php @@ -41,7 +41,7 @@ class phpbb_template_asset_test extends phpbb_test_case $path_helper->method('get_phpbb_root_path') ->willReturn($phpbb_root_path); - $asset = new asset('', $path_helper); + $asset = new asset('', $path_helper, new phpbb\filesystem\filesystem()); $asset->set_path($path, true); $this->assertEquals($expected, $asset->get_path()); diff --git a/tests/template/template_allfolder_test.php b/tests/template/template_allfolder_test.php index 63f35bc758..14a8e9d463 100644 --- a/tests/template/template_allfolder_test.php +++ b/tests/template/template_allfolder_test.php @@ -33,11 +33,13 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case $user = new \phpbb\user($lang, '\phpbb\datetime'); $this->user = $user; + $filesystem = new \phpbb\filesystem\filesystem(); + $path_helper = new \phpbb\path_helper( new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem\filesystem(), + $filesystem, $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -60,6 +62,7 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, + $filesystem, $path_helper, $container, $cache_path, diff --git a/tests/template/template_events_test.php b/tests/template/template_events_test.php index 6d1b7253e3..285e82188b 100644 --- a/tests/template/template_events_test.php +++ b/tests/template/template_events_test.php @@ -138,6 +138,8 @@ Zeta test event in all', $this->extension_manager = new phpbb_mock_filesystem_extension_manager( dirname(__FILE__) . "/datasets/$dataset/" ); + + $filesystem = new \phpbb\filesystem\filesystem(); $path_helper = new \phpbb\path_helper( new \phpbb\symfony_request( new phpbb_mock_request() @@ -154,6 +156,7 @@ Zeta test event in all', $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, + $filesystem, $path_helper, $container, $cache_path, diff --git a/tests/template/template_includecss_test.php b/tests/template/template_includecss_test.php index 7a73d1f888..8c398d992b 100644 --- a/tests/template/template_includecss_test.php +++ b/tests/template/template_includecss_test.php @@ -28,11 +28,13 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te $defaults = $this->config_defaults(); $config = new \phpbb\config\config(array_merge($defaults, $new_config)); + $filesystem = new \phpbb\filesystem\filesystem(); + $this->phpbb_path_helper = new \phpbb\path_helper( new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem\filesystem(), + $filesystem, $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -46,6 +48,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, + $filesystem, $this->phpbb_path_helper, $container, $cache_path, diff --git a/tests/template/template_test_case.php b/tests/template/template_test_case.php index 7e2020ba09..b1826571af 100644 --- a/tests/template/template_test_case.php +++ b/tests/template/template_test_case.php @@ -82,11 +82,13 @@ class phpbb_template_template_test_case extends phpbb_test_case $user = new \phpbb\user($lang, '\phpbb\datetime'); $this->user = $user; + $filesystem = new \phpbb\filesystem\filesystem(); + $path_helper = new \phpbb\path_helper( new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem\filesystem(), + $filesystem, $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -100,6 +102,7 @@ class phpbb_template_template_test_case extends phpbb_test_case $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, + $filesystem, $path_helper, $container, $cache_path, diff --git a/tests/template/template_test_case_with_tree.php b/tests/template/template_test_case_with_tree.php index eab83f379a..d0c49006fd 100644 --- a/tests/template/template_test_case_with_tree.php +++ b/tests/template/template_test_case_with_tree.php @@ -22,11 +22,13 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat $defaults = $this->config_defaults(); $config = new \phpbb\config\config(array_merge($defaults, $new_config)); + $filesystem = new \phpbb\filesystem\filesystem(); + $this->phpbb_path_helper = new \phpbb\path_helper( new \phpbb\symfony_request( new phpbb_mock_request() ), - new \phpbb\filesystem\filesystem(), + $filesystem, $this->getMock('\phpbb\request\request'), $phpbb_root_path, $phpEx @@ -41,6 +43,7 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); $twig = new \phpbb\template\twig\environment( $config, + $filesystem, $this->phpbb_path_helper, $container, $cache_path, From 7b301e22f32e9209bb4e3ea17a5637a84a4ef908 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Fri, 1 May 2015 19:04:21 +0200 Subject: [PATCH 0271/1676] [ticket/13804] Make template's user dependency optional PHPBB3-13804 --- phpBB/config/default/container/services.yml | 15 ------------ .../default/container/services_twig.yml | 15 ++++++++++++ phpBB/includes/bbcode.php | 2 +- phpBB/includes/functions_messenger.php | 2 +- phpBB/install/index.php | 7 ++++-- .../exception/user_object_not_available.php | 22 +++++++++++++++++ phpBB/phpbb/template/twig/twig.php | 24 ++++++++++++++++--- tests/controller/common_helper_route.php | 2 +- tests/extension/metadata_manager_test.php | 2 +- tests/template/template_allfolder_test.php | 2 +- tests/template/template_events_test.php | 2 +- tests/template/template_includecss_test.php | 2 +- tests/template/template_test_case.php | 2 +- .../template/template_test_case_with_tree.php | 2 +- 14 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 phpBB/phpbb/template/exception/user_object_not_available.php diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 670ea3bd61..73dcf5db4c 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -186,21 +186,6 @@ services: request_stack: class: Symfony\Component\HttpFoundation\RequestStack - template: - class: phpbb\template\twig\twig - arguments: - - @path_helper - - @config - - @user - - @template_context - - @template.twig.environment - - %core.template.cache_path% - - @template.twig.extensions.collection - - @ext.manager - - template_context: - class: phpbb\template\context - upload_imagesize: class: fastImageSize\fastImageSize diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index 9ab004731e..d8e1ae0769 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -47,3 +47,18 @@ services: template.twig.extensions.debug: class: Twig_Extension_Debug + + template: + class: phpbb\template\twig\twig + arguments: + - @path_helper + - @config + - @template_context + - @template.twig.environment + - %core.template.cache_path% + - @user + - @template.twig.extensions.collection + - @ext.manager + + template_context: + class: phpbb\template\context diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index 150157e275..24eaddf067 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -138,7 +138,6 @@ class bbcode $template = new \phpbb\template\twig\twig( $phpbb_container->get('path_helper'), $phpbb_container->get('config'), - $phpbb_container->get('user'), new \phpbb\template\context(), new \phpbb\template\twig\environment( $phpbb_container->get('config'), @@ -152,6 +151,7 @@ class bbcode ) ), $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('user'), $phpbb_container->get('template.twig.extensions.collection'), $phpbb_extension_manager ); diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 4cbe1eb425..6abfb40b01 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -633,7 +633,6 @@ class messenger $this->template = new \phpbb\template\twig\twig( $phpbb_container->get('path_helper'), $phpbb_container->get('config'), - $phpbb_container->get('user'), new \phpbb\template\context(), new \phpbb\template\twig\environment( $phpbb_container->get('config'), @@ -647,6 +646,7 @@ class messenger ) ), $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('user'), $phpbb_container->get('template.twig.extensions.collection'), $phpbb_extension_manager ); diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 657825ca39..056c827669 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -138,6 +138,7 @@ $phpbb_container_builder->set_custom_parameters(array( $phpbb_container = $phpbb_container_builder->get_container(); $phpbb_container->register('dbal.conn.driver')->setSynthetic(true); $phpbb_container->register('template.twig.environment')->setSynthetic(true); +$phpbb_container->register('language.loader')->setSynthetic(true); $phpbb_container->compile(); $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); @@ -288,16 +289,18 @@ $twig_environment = new \phpbb\template\twig\environment( $phpbb_container->get('template.twig.loader') ); +$language_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); $phpbb_container->set('template.twig.environment', $twig_environment); +$phpbb_container->set('language.loader', $language_loader); $twig_context = new \phpbb\template\context(); $template = new \phpbb\template\twig\twig( $phpbb_path_helper, $config, - $user, $twig_context, $twig_environment, $cache_path, - array(new \phpbb\template\twig\extension($twig_context, $user)) + $user, + array($phpbb_container->get('template.twig.extensions.phpbb')) ); $paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style'); diff --git a/phpBB/phpbb/template/exception/user_object_not_available.php b/phpBB/phpbb/template/exception/user_object_not_available.php new file mode 100644 index 0000000000..62fd2743c1 --- /dev/null +++ b/phpBB/phpbb/template/exception/user_object_not_available.php @@ -0,0 +1,22 @@ + + * @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\template\exception; + +/** + * This exception is thrown when the user object was not set but it is required by the called method + */ +class user_object_not_available extends \phpbb\exception\runtime_exception +{ + +} diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php index 0e4c619029..ab349cc740 100644 --- a/phpBB/phpbb/template/twig/twig.php +++ b/phpBB/phpbb/template/twig/twig.php @@ -13,6 +13,8 @@ namespace phpbb\template\twig; +use phpbb\template\exception\user_object_not_available; + /** * Twig Template class. */ @@ -76,14 +78,14 @@ class twig extends \phpbb\template\base * * @param \phpbb\path_helper $path_helper * @param \phpbb\config\config $config - * @param \phpbb\user $user * @param \phpbb\template\context $context template context * @param \phpbb\template\twig\environment $twig_environment * @param string $cache_path + * @param \phpbb\user|null $user * @param array|\ArrayAccess $extensions * @param \phpbb\extension\manager $extension_manager extension manager, if null then template events will not be invoked */ - public function __construct(\phpbb\path_helper $path_helper, $config, $user, \phpbb\template\context $context, \phpbb\template\twig\environment $twig_environment, $cache_path, $extensions = array(), \phpbb\extension\manager $extension_manager = null) + public function __construct(\phpbb\path_helper $path_helper, $config, \phpbb\template\context $context, \phpbb\template\twig\environment $twig_environment, $cache_path, \phpbb\user $user = null, $extensions = array(), \phpbb\extension\manager $extension_manager = null) { $this->path_helper = $path_helper; $this->phpbb_root_path = $path_helper->get_phpbb_root_path(); @@ -126,9 +128,16 @@ class twig extends \phpbb\template\base * Get the style tree of the style preferred by the current user * * @return array Style tree, most specific first + * + * @throws \phpbb\template\exception\user_object_not_available When user service was not set */ public function get_user_style() { + if ($this->user === null) + { + throw new user_object_not_available(); + } + $style_list = array( $this->user->style['style_path'], ); @@ -344,11 +353,20 @@ class twig extends \phpbb\template\base $context_vars['.'][0], // To get normal vars array( 'definition' => new \phpbb\template\twig\definition(), - 'user' => $this->user, 'loops' => $context_vars, // To get loops ) ); + if ($this->user instanceof \phpbb\user) + { + $vars = array_merge( + $vars, + array( + 'user' => $this->user, + ) + ); + } + // cleanup unset($vars['loops']['.']); diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index b01241e105..e2f15d85fa 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -107,7 +107,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case 'autoescape' => false, ) ); - $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $this->config, $this->user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); + $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user))); $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $this->extension_manager = new phpbb_mock_extension_manager( diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index aaaee3b2e5..53bd3d109b 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -111,7 +111,7 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $lang = new \phpbb\language\language($lang_loader); $this->user = new \phpbb\user($lang, '\phpbb\datetime'); - $this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $this->user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); + $this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user))); $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); } diff --git a/tests/template/template_allfolder_test.php b/tests/template/template_allfolder_test.php index 14a8e9d463..9a0f1f512e 100644 --- a/tests/template/template_allfolder_test.php +++ b/tests/template/template_allfolder_test.php @@ -75,7 +75,7 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case 'autoescape' => false, ) ); - $this->template = new \phpbb\template\twig\twig($path_helper, $config, $this->user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager); + $this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager); $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $this->template_path = $this->test_path . '/templates'; diff --git a/tests/template/template_events_test.php b/tests/template/template_events_test.php index 285e82188b..54e08652a1 100644 --- a/tests/template/template_events_test.php +++ b/tests/template/template_events_test.php @@ -169,7 +169,7 @@ Zeta test event in all', 'autoescape' => false, ) ); - $this->template = new \phpbb\template\twig\twig($path_helper, $config, $user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager); + $this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager); $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $this->template->set_custom_style(((!empty($style_names)) ? $style_names : 'silver'), array($this->template_path)); diff --git a/tests/template/template_includecss_test.php b/tests/template/template_includecss_test.php index 8c398d992b..062fc9493b 100644 --- a/tests/template/template_includecss_test.php +++ b/tests/template/template_includecss_test.php @@ -64,10 +64,10 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te $this->template = new phpbb\template\twig\twig( $this->phpbb_path_helper, $config, - $user, $context, $twig, $cache_path, + $this->user, array(new \phpbb\template\twig\extension($context, $this->user)), new phpbb_mock_extension_manager( dirname(__FILE__) . '/', diff --git a/tests/template/template_test_case.php b/tests/template/template_test_case.php index b1826571af..62eea0d361 100644 --- a/tests/template/template_test_case.php +++ b/tests/template/template_test_case.php @@ -115,7 +115,7 @@ class phpbb_template_template_test_case extends phpbb_test_case 'autoescape' => false, ) ); - $this->template = new phpbb\template\twig\twig($path_helper, $config, $user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); + $this->template = new phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user))); $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $this->template->set_custom_style('tests', $this->template_path); } diff --git a/tests/template/template_test_case_with_tree.php b/tests/template/template_test_case_with_tree.php index d0c49006fd..bf5de6b85e 100644 --- a/tests/template/template_test_case_with_tree.php +++ b/tests/template/template_test_case_with_tree.php @@ -56,7 +56,7 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat 'autoescape' => false, ) ); - $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $user, $context, $twig, $cache_path, array(new \phpbb\template\twig\extension($context, $this->user))); + $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user))); $container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); $this->template->set_custom_style('tests', array($this->template_path, $this->parent_template_path)); } From 571f6dc9b53068ac655924616022e92d0e1c1ce9 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 8 May 2015 11:05:01 +0200 Subject: [PATCH 0272/1676] [ticket/13825] Correctly call phpbb_filesystem in create_thumbnail PHPBB3-13825 --- phpBB/includes/functions_posting.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 4233395574..fcab667cb2 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -822,7 +822,7 @@ function create_thumbnail($source, $destination, $mimetype) try { - $this->filesystem->phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); + $phpbb_filesystem->phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); } catch (\phpbb\filesystem\exception\filesystem_exception $e) { From e2bc6c8024eed988ba833ec062b9e856a77ff661 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 10 May 2015 03:04:12 +0200 Subject: [PATCH 0273/1676] [ticket/13828] Renamed testing doubles to avoid PHP7 keywords PHPBB3-13828 --- tests/di/fixtures/config.php | 2 +- tests/notification/submit_post_type_topic_test.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/di/fixtures/config.php b/tests/di/fixtures/config.php index 04e20f63d8..f2e1145efa 100644 --- a/tests/di/fixtures/config.php +++ b/tests/di/fixtures/config.php @@ -8,4 +8,4 @@ $dbname = 'phpbb'; $dbuser = 'root'; $dbpasswd = ''; $table_prefix = 'phpbb_'; -$acm_type = '\phpbb\cache\driver\null'; +$acm_type = '\phpbb\cache\driver\dummy'; diff --git a/tests/notification/submit_post_type_topic_test.php b/tests/notification/submit_post_type_topic_test.php index c095fbc4ba..f14f305517 100644 --- a/tests/notification/submit_post_type_topic_test.php +++ b/tests/notification/submit_post_type_topic_test.php @@ -42,7 +42,7 @@ class phpbb_notification_submit_post_type_topic_test extends phpbb_notification_ ), ))); - $phpbb_log = $this->getMock('\phpbb\log\null'); + $phpbb_log = $this->getMock('\phpbb\log\dummy'); } /** From 281f2ef2dacc7d635646edb3897fba8ff6f66d25 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Mon, 11 May 2015 16:59:26 +0200 Subject: [PATCH 0274/1676] [ticket/13804] Remove unnecessary array_merge PHPBB3-13804 --- phpBB/phpbb/template/twig/twig.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php index ab349cc740..6b3cf32bc8 100644 --- a/phpBB/phpbb/template/twig/twig.php +++ b/phpBB/phpbb/template/twig/twig.php @@ -359,12 +359,7 @@ class twig extends \phpbb\template\base if ($this->user instanceof \phpbb\user) { - $vars = array_merge( - $vars, - array( - 'user' => $this->user, - ) - ); + $vars['user'] = $this->user; } // cleanup From 8b7a42f338ca7315aae11d25e7adb89aaefe7849 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 7 May 2015 16:01:42 +0200 Subject: [PATCH 0275/1676] [ticket/13614] Removed code that relies on phpbb_pcre_utf8_support() Removed all calls to phpbb_pcre_utf8_support() as well as unreachable code. PHPBB3-13614 --- phpBB/includes/acp/acp_bbcodes.php | 8 +-- phpBB/includes/functions.php | 38 ++-------- phpBB/includes/functions_user.php | 112 +++-------------------------- tests/regex/censor_test.php | 12 +--- 4 files changed, 20 insertions(+), 150 deletions(-) diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index d451b4d899..2b438e5670 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -416,8 +416,6 @@ class acp_bbcodes // Allow unicode characters for URL|LOCAL_URL|RELATIVE_URL|INTTEXT tokens $utf8 = preg_match('/(URL|LOCAL_URL|RELATIVE_URL|INTTEXT)/', $bbcode_match); - $utf8_pcre_properties = phpbb_pcre_utf8_support(); - $fp_match = preg_quote($bbcode_match, '!'); $fp_replace = preg_replace('#^\[(.*?)\]#', '[$1:$uid]', $bbcode_match); $fp_replace = preg_replace('#\[/(.*?)\]$#', '[/$1:$uid]', $fp_replace); @@ -448,7 +446,7 @@ class acp_bbcodes '!([a-zA-Z0-9-+.,_ ]+)!' => "$1" ), 'INTTEXT' => array( - ($utf8_pcre_properties) ? '!([\p{L}\p{N}\-+,_. ]+)!u' : '!([a-zA-Z0-9\-+,_. ]+)!u' => "$1" + '!([\p{L}\p{N}\-+,_. ]+)!u' => "$1" ), 'IDENTIFIER' => array( '!([a-zA-Z0-9-_]+)!' => "$1" @@ -468,7 +466,7 @@ class acp_bbcodes 'EMAIL' => '(' . get_preg_expression('email') . ')', 'TEXT' => '(.*?)', 'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)', - 'INTTEXT' => ($utf8_pcre_properties) ? '([\p{L}\p{N}\-+,_. ]+)' : '([a-zA-Z0-9\-+,_. ]+)', + 'INTTEXT' => '([\p{L}\p{N}\-+,_. ]+)', 'IDENTIFIER' => '([a-zA-Z0-9-_]+)', 'COLOR' => '([a-zA-Z]+|#[0-9abcdefABCDEF]+)', 'NUMBER' => '([0-9]+)', @@ -476,7 +474,7 @@ class acp_bbcodes $pad = 0; $modifiers = 'i'; - $modifiers .= ($utf8 && $utf8_pcre_properties) ? 'u' : ''; + $modifiers .= ($utf8) ? 'u' : ''; if (preg_match_all('/\{(' . implode('|', array_keys($tokens)) . ')[0-9]*\}/i', $bbcode_match, $m)) { diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 2ed0eff81c..efb6cec8a5 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2811,31 +2811,19 @@ function get_preg_expression($mode) * Depends on whether installed PHP version supports unicode properties * * @param string $word word template to be replaced -* @param bool $use_unicode whether or not to take advantage of PCRE supporting unicode * * @return string $preg_expr regex to use with word censor */ -function get_censor_preg_expression($word, $use_unicode = true) +function get_censor_preg_expression($word) { // Unescape the asterisk to simplify further conversions $word = str_replace('\*', '*', preg_quote($word, '#')); - if ($use_unicode && phpbb_pcre_utf8_support()) - { - // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes - $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word); + // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes + $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word); - // Generate the final substitution - $preg_expr = '#(?assertRegExp($regex, $subject); - } - - /** - * @dataProvider censor_test_data - */ - public function test_censor_no_unicode($pattern, $subject) - { - $regex = get_censor_preg_expression($pattern, false); + $regex = get_censor_preg_expression($pattern); $this->assertRegExp($regex, $subject); } From f31483242bcafb47cd64150c242bd273ba16f7dd Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 11 May 2015 20:48:05 +0200 Subject: [PATCH 0276/1676] [ticket/13614] Added phpbb_pcre_utf8_support() dummy for BC PHPBB3-13614 --- phpBB/includes/functions_compatibility.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 8655203754..31019061a9 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -501,3 +501,12 @@ function phpbb_get_plural_form($rule, $number) $language = $phpbb_container->get('language'); return $language->get_plural_form($number, $rule); } + +/** +* @return bool Always true +* @deprecated 3.2.0-dev +*/ +function phpbb_pcre_utf8_support() +{ + return true; +} From d48e95bb3a17f111e9d4d8111630be44ef9019e4 Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Sun, 10 May 2015 19:18:10 +0200 Subject: [PATCH 0277/1676] [ticket/13829] Don't fail if the cache isn't writeable PHPBB3-13829 --- phpBB/phpbb/routing/router.php | 63 +++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 7444f06253..f74760fa13 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -14,6 +14,7 @@ namespace phpbb\routing; use Symfony\Component\Config\ConfigCache; +use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; use Symfony\Component\Routing\Matcher\UrlMatcher; @@ -249,22 +250,29 @@ class router implements RouterInterface */ protected function create_dumped_url_matcher() { - $cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_matcher.{$this->php_ext}", defined('DEBUG')); - if (!$cache->isFresh()) + try { - $dumper = new PhpMatcherDumper($this->get_routes()); + $cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_matcher.{$this->php_ext}", defined('DEBUG')); + if (!$cache->isFresh()) + { + $dumper = new PhpMatcherDumper($this->get_routes()); - $options = array( - 'class' => 'phpbb_url_matcher', - 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', - ); + $options = array( + 'class' => 'phpbb_url_matcher', + 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', + ); - $cache->write($dumper->dump($options), $this->get_routes()->getResources()); + $cache->write($dumper->dump($options), $this->get_routes()->getResources()); + } + + require_once($cache->getPath()); + + $this->matcher = new \phpbb_url_matcher($this->context); + } + catch (IOException $e) + { + $this->create_new_url_matcher(); } - - require_once($cache->getPath()); - - $this->matcher = new \phpbb_url_matcher($this->context); } /** @@ -297,22 +305,29 @@ class router implements RouterInterface */ protected function create_dumped_url_generator() { - $cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_generator.{$this->php_ext}", defined('DEBUG')); - if (!$cache->isFresh()) + try { - $dumper = new PhpGeneratorDumper($this->get_routes()); + $cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_generator.{$this->php_ext}", defined('DEBUG')); + if (!$cache->isFresh()) + { + $dumper = new PhpGeneratorDumper($this->get_routes()); - $options = array( - 'class' => 'phpbb_url_generator', - 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', - ); + $options = array( + 'class' => 'phpbb_url_generator', + 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', + ); - $cache->write($dumper->dump($options), $this->get_routes()->getResources()); + $cache->write($dumper->dump($options), $this->get_routes()->getResources()); + } + + require_once($cache->getPath()); + + $this->generator = new \phpbb_url_generator($this->context); + } + catch (IOException $e) + { + $this->create_new_url_generator(); } - - require_once($cache->getPath()); - - $this->generator = new \phpbb_url_generator($this->context); } /** From 737affcbb2f2e4f7ee5d8182a4e8cac599265ef4 Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Thu, 14 May 2015 16:33:39 +0200 Subject: [PATCH 0278/1676] [ticket/13839] Don't be dependent on the phpBB root directory name in tests PHPBB3-13839 --- tests/template/asset_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/template/asset_test.php b/tests/template/asset_test.php index f6ce0fe241..3d2fdd8959 100644 --- a/tests/template/asset_test.php +++ b/tests/template/asset_test.php @@ -22,7 +22,7 @@ class phpbb_template_asset_test extends phpbb_test_case array('.', 'foo/bar', 'foo/bar'), array('../', 'foo/bar', 'foo/bar'), array('./phpBB/', 'foo/bar', 'foo/bar'), - array('../', __DIR__ . '/foo/bar', '../phpbb/tests/template/foo/bar'), + array('../', __DIR__ . '/foo/bar', '../' . basename(dirname(dirname(__DIR__))) . '/tests/template/foo/bar'), array('./', __DIR__ . '/foo/bar', './tests/template/foo/bar'), array('./phpBB/', __DIR__ . '/foo/bar', 'tests/template/foo/bar'), ); From c96e7ef1711932c2236620903bc256b346514dfc Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 26 Apr 2015 19:41:07 +0200 Subject: [PATCH 0279/1676] [ticket/13770] Wither interface for container_builder PHPBB3-13770 --- phpBB/bin/phpbbcli.php | 10 +- phpBB/common.php | 14 +- phpBB/download/file.php | 6 +- phpBB/install/database_update.php | 12 +- phpBB/install/index.php | 18 +- phpBB/install/install_convert.php | 4 +- phpBB/install/install_install.php | 4 +- phpBB/install/install_update.php | 12 +- phpBB/phpbb/di/container_builder.php | 538 +++++++++++++-------------- 9 files changed, 307 insertions(+), 311 deletions(-) diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index fc78e5d04a..d72ca760c8 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -43,21 +43,21 @@ require($phpbb_root_path . 'includes/functions.' . $phpEx); require($phpbb_root_path . 'includes/functions_admin.' . $phpEx); require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); -$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); -$phpbb_container_builder->set_dump_container(false); +$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); +$phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file); + +$phpbb_container_builder->without_cache(); $input = new ArgvInput(); if ($input->hasParameterOption(array('--safe-mode'))) { - $phpbb_container_builder->set_use_extensions(false); - $phpbb_container_builder->set_dump_container(false); + $phpbb_container_builder->without_extensions(); } else { $phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx); $phpbb_class_loader_ext->register(); - phpbb_load_extensions_autoloaders($phpbb_root_path); } $phpbb_container = $phpbb_container_builder->get_container(); diff --git a/phpBB/common.php b/phpBB/common.php index 633a37f25b..70fb34331c 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -96,21 +96,21 @@ set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handle $phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx); $phpbb_class_loader_ext->register(); -phpbb_load_extensions_autoloaders($phpbb_root_path); +\Symfony\Component\Debug\Debug::enable(E_ALL); // Set up container -try -{ - $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); - $phpbb_container = $phpbb_container_builder->get_container(); -} +/*try +{*/ + $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); + $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container(); +/*} catch (InvalidArgumentException $e) { trigger_error( 'The requested environment ' . PHPBB_ENVIRONMENT . ' is not available.', E_USER_ERROR ); -} +}*/ $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); diff --git a/phpBB/download/file.php b/phpBB/download/file.php index 235dd3c95c..9d54b824f8 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -61,11 +61,9 @@ if (isset($_GET['avatar'])) $phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx); $phpbb_class_loader_ext->register(); - phpbb_load_extensions_autoloaders($phpbb_root_path); - // Set up container - $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); - $phpbb_container = $phpbb_container_builder->get_container(); + $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); + $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container(); $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 4746bb11f2..40d07e7990 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -80,11 +80,13 @@ require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler'); // Set up container (must be done here because extensions table may not exist) -$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); -$phpbb_container_builder->set_use_extensions(false); -$phpbb_container_builder->set_use_kernel_pass(false); -$phpbb_container_builder->set_dump_container(false); -$phpbb_container = $phpbb_container_builder->get_container(); +$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); +$phpbb_container = $phpbb_container_builder + ->with_config($phpbb_config_php_file) + ->without_extensions() + ->without_cache() + ->get_container() +; // set up caching /* @var $cache \phpbb\cache\service */ diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 056c827669..19cf27940b 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -116,18 +116,20 @@ $phpbb_class_loader_ext->register(); // Set up container $phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx); -$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); -$phpbb_container_builder->set_use_extensions(false); -$phpbb_container_builder->set_dump_container(false); -$phpbb_container_builder->set_use_custom_pass(false); -$phpbb_container_builder->set_inject_config(false); -$phpbb_container_builder->set_compile_container(false); +$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); +$phpbb_container = $phpbb_container_builder + ->with_config($phpbb_config_php_file) + ->without_extensions() + ->without_cache() + ->without_compiled_container() + ->get_container() +; $other_config_path = $phpbb_root_path . 'install/update/new/config/'; $config_path = file_exists($other_config_path . 'services.yml') ? $other_config_path : $phpbb_root_path . 'config/'; -$phpbb_container_builder->set_config_path($config_path); +$phpbb_container_builder->with_config_path($config_path); -$phpbb_container_builder->set_custom_parameters(array( +$phpbb_container_builder->with_custom_parameters(array( 'core.root_path' => $phpbb_root_path, 'core.adm_relative_path' => $phpbb_adm_relative_path, 'core.php_ext' => $phpEx, diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index 408c14e981..dd9835113b 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -131,8 +131,8 @@ class install_convert extends module // Enable super globals to prevent issues with the new \phpbb\request\request object $request->enable_super_globals(); // Create a normal container now - $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); - $phpbb_container = $phpbb_container_builder->get_container(); + $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); + $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container(); // Create cache /* @var $cache \phpbb\cache\service */ diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index be6fa40566..e8890a3d08 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -110,8 +110,8 @@ class install_install extends module $request->enable_super_globals(); // Create a normal container now - $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); - $phpbb_container = $phpbb_container_builder->get_container(); + $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); + $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container(); // Sets the global variables /* @var $cache \phpbb\cache\service */ diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index 288e728fce..d9ba2e7fe9 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -76,12 +76,16 @@ class install_update extends module $request->enable_super_globals(); // Create a normal container now - $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx); - $phpbb_container_builder->set_dump_container(false); - $phpbb_container_builder->set_use_extensions(false); + $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); + $phpbb_container = $phpbb_container_builder + ->with_config($phpbb_config_php_file) + ->without_cache() + ->without_extensions() + ; + if (file_exists($phpbb_root_path . 'install/update/new/config')) { - $phpbb_container_builder->set_config_path($phpbb_root_path . 'install/update/new/config'); + $phpbb_container_builder->with_config_path($phpbb_root_path . 'install/update/new/config'); } $phpbb_container = $phpbb_container_builder->get_container(); diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 99576f9020..33eb4e59a8 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -13,6 +13,7 @@ namespace phpbb\di; +use phpbb\filesystem\filesystem; use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -24,6 +25,11 @@ use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfiguration class container_builder { + /** + * @var string The environment to use. + */ + protected $environment; + /** * @var string phpBB Root Path */ @@ -35,89 +41,58 @@ class container_builder protected $php_ext; /** - * The container under construction - * - * @var ContainerBuilder - */ + * The container under construction + * + * @var ContainerBuilder + */ protected $container; /** - * @var \phpbb\db\driver\driver_interface - */ - protected $dbal_connection = null; - - /** - * @var array the installed extensions - */ - protected $installed_exts = null; - - /** - * Indicates whether the php config file should be injected into the container (default to true). - * - * @var bool - */ - protected $inject_config = true; - - /** - * Indicates whether extensions should be used (default to true). - * - * @var bool - */ + * Indicates whether extensions should be used (default to true). + * + * @var bool + */ protected $use_extensions = true; /** - * Defines a custom path to find the configuration of the container (default to $this->phpbb_root_path . 'config') - * - * @var string - */ + * Defines a custom path to find the configuration of the container (default to $this->phpbb_root_path . 'config') + * + * @var string + */ protected $config_path = null; /** - * Indicates whether the phpBB compile pass should be used (default to true). - * - * @var bool - */ - protected $use_custom_pass = true; + * Indicates whether the container should be dumped to the filesystem (default to true). + * + * If DEBUG_CONTAINER is set this option is ignored and a new container is build. + * + * @var bool + */ + protected $use_cache = true; /** - * Indicates whether the kernel compile pass should be used (default to true). - * - * @var bool - */ - protected $use_kernel_pass = true; - - /** - * Indicates whether the container should be dumped to the filesystem (default to true). - * - * If DEBUG_CONTAINER is set this option is ignored and a new container is build. - * - * @var bool - */ - protected $dump_container = true; - - /** - * Indicates if the container should be compiled automatically (default to true). - * - * @var bool - */ + * Indicates if the container should be compiled automatically (default to true). + * + * @var bool + */ protected $compile_container = true; /** - * Custom parameters to inject into the container. - * - * Default to true: - * array( - * 'core.root_path', $this->phpbb_root_path, - * 'core.php_ext', $this->php_ext, - * ); - * - * @var array - */ + * Custom parameters to inject into the container. + * + * Default to: + * array( + * 'core.root_path', $this->phpbb_root_path, + * 'core.php_ext', $this->php_ext, + * ); + * + * @var array + */ protected $custom_parameters = null; /** - * @var \phpbb\config_php_file - */ + * @var \phpbb\config_php_file + */ protected $config_php_file; /** @@ -126,169 +101,216 @@ class container_builder protected $cache_dir; /** - * Constructor - * - * @param \phpbb\config_php_file $config_php_file - * @param string $phpbb_root_path Path to the phpbb includes directory. - * @param string $php_ext php file extension - */ - function __construct(\phpbb\config_php_file $config_php_file, $phpbb_root_path, $php_ext) + * @var array + */ + private $container_extensions; + + /** + * Constructor + * + * @param string $phpbb_root_path Path to the phpbb includes directory. + * @param string $php_ext php file extension + */ + function __construct($phpbb_root_path, $php_ext) { - $this->config_php_file = $config_php_file; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; } /** - * Build and return a new Container respecting the current configuration - * - * @return \phpbb_cache_container|ContainerBuilder - */ + * Build and return a new Container respecting the current configuration + * + * @return \phpbb_cache_container|ContainerBuilder + */ public function get_container() { $container_filename = $this->get_container_filename(); $config_cache = new ConfigCache($container_filename, defined('DEBUG')); - if ($this->dump_container && $config_cache->isFresh()) + if ($this->use_cache && $config_cache->isFresh()) { require($config_cache->getPath()); $this->container = new \phpbb_cache_container(); + + return $this->container; } - else + + $this->container_extensions = array(new extension\core($this->get_config_path())); + + if ($this->use_extensions) { - $container_extensions = array(new \phpbb\di\extension\core($this->get_config_path())); - - if ($this->use_extensions) - { - $installed_exts = $this->get_installed_extensions(); - foreach ($installed_exts as $ext_name => $path) - { - $extension_class = '\\' . str_replace('/', '\\', $ext_name) . '\\di\\extension'; - - if (!class_exists($extension_class)) - { - $extension_class = '\phpbb\extension\di\extension_base'; - } - - $container_extensions[] = new $extension_class($ext_name, $path); - } - } - - if ($this->inject_config) - { - $container_extensions[] = new \phpbb\di\extension\config($this->config_php_file); - } - - $this->container = $this->create_container($container_extensions); - - if ($this->use_custom_pass) - { - // Symfony Kernel Listeners - $this->container->addCompilerPass(new \phpbb\di\pass\collection_pass()); - $this->container->addCompilerPass(new RegisterListenersPass('dispatcher', 'event.listener_listener', 'event.listener')); - - if ($this->use_kernel_pass) - { - $this->container->addCompilerPass(new RegisterListenersPass('dispatcher')); - } - } - - $filesystem = new \phpbb\filesystem\filesystem(); - $loader = new YamlFileLoader($this->container, new FileLocator($filesystem->realpath($this->get_config_path()))); - $loader->load($this->container->getParameter('core.environment') . '/config.yml'); - - $this->inject_custom_parameters(); - - if ($this->compile_container) - { - $this->container->compile(); - } - - if ($this->dump_container) - { - $this->dump_container($config_cache); - } + $this->load_extensions(); } - $this->container->set('config.php', $this->config_php_file); + // Inject the config + $this->container_extensions[] = new extension\config($this->config_php_file); + + $this->container = $this->create_container($this->container_extensions); + + // Easy collections through tags + $this->container->addCompilerPass(new pass\collection_pass()); + + // Event listeners "phpBB style" + $this->container->addCompilerPass(new RegisterListenersPass('dispatcher', 'event.listener_listener', 'event.listener')); + + // Event listeners "Symfony style" + $this->container->addCompilerPass(new RegisterListenersPass('dispatcher')); + + $filesystem = new filesystem(); + $loader = new YamlFileLoader($this->container, new FileLocator($filesystem->realpath($this->get_config_path()))); + $loader->load($this->container->getParameter('core.environment') . '/config.yml'); + + $this->inject_custom_parameters(); if ($this->compile_container) { - $this->inject_dbal(); + $this->container->compile(); + + if ($this->use_cache) + { + $this->dump_container($config_cache); + } } return $this->container; } /** - * Set if the extensions should be used. - * - * @param bool $use_extensions - */ - public function set_use_extensions($use_extensions) + * Enable the extensions. + * + * @param string $environment The environment to use + * @return $this + */ + public function with_environment($environment) { - $this->use_extensions = $use_extensions; + $this->environment = $environment; + + return $this; } /** - * Set if the phpBB compile pass have to be used. - * - * @param bool $use_custom_pass - */ - public function set_use_custom_pass($use_custom_pass) + * Enable the extensions. + * + * @return $this + */ + public function with_extensions() { - $this->use_custom_pass = $use_custom_pass; + $this->use_extensions = true; + + return $this; } /** - * Set if the kernel compile pass have to be used. - * - * @param bool $use_kernel_pass - */ - public function set_use_kernel_pass($use_kernel_pass) + * Disable the extensions. + * + * @return $this + */ + public function without_extensions() { - $this->use_kernel_pass = $use_kernel_pass; + $this->use_extensions = false; + + return $this; } /** - * Set if the php config file should be injecting into the container. - * - * @param bool $inject_config - */ - public function set_inject_config($inject_config) + * Enable the caching of the container. + * + * If DEBUG_CONTAINER is set this option is ignored and a new container is build. + * + * @return $this + */ + public function with_cache() { - $this->inject_config = $inject_config; + $this->use_cache = true; + + return $this; } /** - * Set if a dump container should be used. - * - * If DEBUG_CONTAINER is set this option is ignored and a new container is build. - * - * @var bool $dump_container - */ - public function set_dump_container($dump_container) + * Disable the caching of the container. + * + * @return $this + */ + public function without_cache() { - $this->dump_container = $dump_container; + $this->use_cache = false; + + return $this; } /** - * Set if the container should be compiled automatically (default to true). - * - * @var bool $dump_container - */ - public function set_compile_container($compile_container) + * Set the cache directory. + * + * @param string $cache_dir The cache directory. + * @return $this + */ + public function with_cache_dir($cache_dir) { - $this->compile_container = $compile_container; + $this->cache_dir = $cache_dir; + + return $this; } /** - * Set a custom path to find the configuration of the container - * - * @param string $config_path - */ - public function set_config_path($config_path) + * Enable the compilation of the container. + * + * @return $this + */ + public function with_compiled_container() + { + $this->compile_container = true; + + return $this; + } + + /** + * Disable the compilation of the container. + * + * @return $this + */ + public function without_compiled_container() + { + $this->compile_container = false; + + return $this; + } + + /** + * Set a custom path to find the configuration of the container. + * + * @param string $config_path + * @return $this + */ + public function with_config_path($config_path) { $this->config_path = $config_path; + + return $this; + } + + /** + * Set custom parameters to inject into the container. + * + * @param array $custom_parameters + * @return $this + */ + public function with_custom_parameters($custom_parameters) + { + $this->custom_parameters = $custom_parameters; + + return $this; + } + + /** + * Set custom parameters to inject into the container. + * + * @param \phpbb\config_php_file $config_php_file + * @return $this + */ + public function with_config(\phpbb\config_php_file $config_php_file) + { + $this->config_php_file = $config_php_file; + + return $this; } /** @@ -301,26 +323,6 @@ class container_builder return $this->config_path ?: $this->phpbb_root_path . 'config'; } - /** - * Set custom parameters to inject into the container. - * - * @param array $custom_parameters - */ - public function set_custom_parameters($custom_parameters) - { - $this->custom_parameters = $custom_parameters; - } - - /** - * Set the path to the cache directory. - * - * @param string $cache_dir Path to the cache directory - */ - public function set_cache_dir($cache_dir) - { - $this->cache_dir = $cache_dir; - } - /** * Returns the path to the cache directory (default: root_path/cache/environment). * @@ -332,10 +334,61 @@ class container_builder } /** - * Dump the container to the disk. - * - * @param ConfigCache $cache The config cache - */ + * Load the enabled extensions. + */ + protected function load_extensions() + { + if ($this->config_php_file !== null) + { + // Build an intermediate container to load the ext list from the database + $container_builder = new container_builder($this->phpbb_root_path, $this->php_ext); + $ext_container = $container_builder + ->without_cache() + ->without_extensions() + ->with_config($this->config_php_file) + ->with_environment('production') + ->without_compiled_container() + ->get_container() + ; + + $ext_container->register('cache.driver', '\\phpbb\\cache\\driver\\null'); + $ext_container->compile(); + + $extensions = $ext_container->get('ext.manager')->all_enabled(); + + // Load each extension found + foreach ($extensions as $ext_name => $path) + { + $extension_class = '\\' . str_replace('/', '\\', $ext_name) . '\\di\\extension'; + + if (!class_exists($extension_class)) + { + $extension_class = '\\phpbb\\extension\\di\\extension_base'; + } + + $this->container_extensions[] = new $extension_class($ext_name, $path); + + // Load extension autoloader + $filename = $path . 'vendor/autoload.php'; + if (file_exists($filename)) + { + require $filename; + } + } + } + else + { + // To load the extensions we need the database credentials. + // Automatically disable the extensions if we don't have them. + $this->use_extensions = false; + } + } + + /** + * Dump the container to the disk. + * + * @param ConfigCache $cache The config cache + */ protected function dump_container($cache) { $dumper = new PhpDumper($this->container); @@ -348,73 +401,11 @@ class container_builder } /** - * Inject the connection into the container if one was opened. - */ - protected function inject_dbal() - { - if ($this->dbal_connection !== null) - { - $this->container->get('dbal.conn')->set_driver($this->dbal_connection); - } - } - - /** - * Get DB connection. - * - * @return \phpbb\db\driver\driver_interface - */ - protected function get_dbal_connection() - { - if ($this->dbal_connection === null) - { - $dbal_driver_class = $this->config_php_file->convert_30_dbms_to_31($this->config_php_file->get('dbms')); - $this->dbal_connection = new $dbal_driver_class(); - $this->dbal_connection->sql_connect( - $this->config_php_file->get('dbhost'), - $this->config_php_file->get('dbuser'), - $this->config_php_file->get('dbpasswd'), - $this->config_php_file->get('dbname'), - $this->config_php_file->get('dbport'), - defined('PHPBB_DB_NEW_LINK') && PHPBB_DB_NEW_LINK - ); - } - - return $this->dbal_connection; - } - - /** - * Get enabled extensions. - * - * @return array enabled extensions - */ - protected function get_installed_extensions() - { - $db = $this->get_dbal_connection(); - $extension_table = $this->config_php_file->get('table_prefix') . 'ext'; - - $sql = 'SELECT * - FROM ' . $extension_table . ' - WHERE ext_active = 1'; - - $result = $db->sql_query($sql); - $rows = $db->sql_fetchrowset($result); - $db->sql_freeresult($result); - - $exts = array(); - foreach ($rows as $row) - { - $exts[$row['ext_name']] = $this->phpbb_root_path . 'ext/' . $row['ext_name'] . '/'; - } - - return $exts; - } - - /** - * Create the ContainerBuilder object - * - * @param array $extensions Array of Container extension objects - * @return ContainerBuilder object - */ + * Create the ContainerBuilder object + * + * @param array $extensions Array of Container extension objects + * @return ContainerBuilder object + */ protected function create_container(array $extensions) { $container = new ContainerBuilder(new ParameterBag($this->get_core_parameters())); @@ -425,7 +416,6 @@ class container_builder { $container->registerExtension($extension); $extensions_alias[] = $extension->getAlias(); - //$container->loadFromExtension($extension->getAlias()); } $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions_alias)); @@ -487,10 +477,10 @@ class container_builder } /** - * Get the filename under which the dumped container will be stored. - * - * @return string Path for dumped container - */ + * Get the filename under which the dumped container will be stored. + * + * @return string Path for dumped container + */ protected function get_container_filename() { $filename = str_replace(array('/', '.'), array('slash', 'dot'), $this->phpbb_root_path); @@ -504,6 +494,6 @@ class container_builder */ protected function get_environment() { - return PHPBB_ENVIRONMENT; + return $this->environment ?: PHPBB_ENVIRONMENT; } } From 549fe66d90eed1d6a4fee6f5f706c73455d73596 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 26 Apr 2015 21:30:50 +0200 Subject: [PATCH 0280/1676] [ticket/13770] Update tests PHPBB3-13770 --- phpBB/install/index.php | 1 - phpBB/phpbb/di/container_builder.php | 5 +- tests/di/create_container_test.php | 89 +++++-------------- tests/di/fixtures/config.php | 2 +- .../di/fixtures/config/production/config.yml | 2 + .../production/container/environment.yml | 17 ++++ 6 files changed, 44 insertions(+), 72 deletions(-) create mode 100644 tests/di/fixtures/config/production/config.yml create mode 100644 tests/di/fixtures/config/production/container/environment.yml diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 19cf27940b..f935e3d08c 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -118,7 +118,6 @@ $phpbb_class_loader_ext->register(); $phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx); $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); $phpbb_container = $phpbb_container_builder - ->with_config($phpbb_config_php_file) ->without_extensions() ->without_cache() ->without_compiled_container() diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 33eb4e59a8..3886bfdd5d 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -142,7 +142,10 @@ class container_builder } // Inject the config - $this->container_extensions[] = new extension\config($this->config_php_file); + if ($this->config_php_file) + { + $this->container_extensions[] = new extension\config($this->config_php_file); + } $this->container = $this->create_container($this->container_extensions); diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php index d52fb6b085..2d94f1d778 100644 --- a/tests/di/create_container_test.php +++ b/tests/di/create_container_test.php @@ -31,7 +31,8 @@ namespace { $this->phpbb_root_path = dirname(__FILE__) . '/'; $this->config_php = new \phpbb\config_php_file($this->phpbb_root_path . 'fixtures/', 'php'); - $this->builder = new phpbb_mock_phpbb_di_container_builder($this->config_php, $this->phpbb_root_path . 'fixtures/', 'php'); + $this->builder = new phpbb_mock_phpbb_di_container_builder($this->phpbb_root_path . 'fixtures/', 'php'); + $this->builder->with_config($this->config_php); $this->filename = $this->phpbb_root_path . '../tmp/container.php'; if (is_file($this->filename)) @@ -78,9 +79,9 @@ namespace $this->assertTrue($container->isFrozen()); } - public function test_dump_container() + public function test_without_cache() { - $this->builder->set_dump_container(false); + $this->builder->without_cache(); $container = $this->builder->get_container(); $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); @@ -94,9 +95,9 @@ namespace $this->assertTrue($container->isFrozen()); } - public function test_use_extensions() + public function test_without_extensions() { - $this->builder->set_use_extensions(false); + $this->builder->without_extensions(); $container = $this->builder->get_container(); $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); @@ -109,9 +110,9 @@ namespace $this->assertFalse($container->hasParameter('available')); } - public function test_compile_container() + public function test_without_compiled_container() { - $this->builder->set_compile_container(false); + $this->builder->without_compiled_container(); $container = $this->builder->get_container(); $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); @@ -119,19 +120,9 @@ namespace $this->assertFalse($container->isFrozen()); } - public function test_inject_config() + public function test_with_config_path() { - $this->builder->set_inject_config(false); - $container = $this->builder->get_container(); - $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); - - // Checks inject_config - $this->assertFalse($container->hasParameter('dbal.dbhost')); - } - - public function test_set_config_path() - { - $this->builder->set_config_path($this->phpbb_root_path . 'fixtures/other_config/'); + $this->builder->with_config_path($this->phpbb_root_path . 'fixtures/other_config/'); $container = $this->builder->get_container(); $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); @@ -139,9 +130,9 @@ namespace $this->assertFalse($container->hasParameter('core')); } - public function test_set_custom_parameters() + public function test_with_custom_parameters() { - $this->builder->set_custom_parameters(array('my_parameter' => true)); + $this->builder->with_custom_parameters(array('my_parameter' => true)); $container = $this->builder->get_container(); $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); @@ -150,61 +141,21 @@ namespace } } -namespace phpbb\db\driver +namespace phpbb\extension { - class container_mock extends \phpbb\db\driver\driver + class manager_mock extends \phpbb\extension\manager { - public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + public function __construct() { } - public function sql_query($query = '', $cache_ttl = 0) - { - } - - public function sql_fetchrow($query_id = false) - { - } - - public function sql_freeresult($query_id = false) - { - } - - function sql_server_info($raw = false, $use_cache = true) - { - } - - function sql_affectedrows() - { - } - - function sql_rowseek($rownum, &$query_id) - { - } - - function sql_nextid() - { - } - - function sql_escape($msg) - { - } - - function sql_like_expression($expression) - { - } - - function sql_not_like_expression($expression) - { - } - - function sql_fetchrowset($query_id = false) + public function all_enabled($phpbb_relative = true) { return array( - array('ext_name' => 'vendor/enabled'), - array('ext_name' => 'vendor/enabled-2'), - array('ext_name' => 'vendor/enabled-3'), - array('ext_name' => 'vendor/enabled_4'), + 'vendor/enabled' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled/', + 'vendor/enabled-2' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled-2/', + 'vendor/enabled-3' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled-3/', + 'vendor/enabled_4' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled_4/', ); } } diff --git a/tests/di/fixtures/config.php b/tests/di/fixtures/config.php index f2e1145efa..1e9207d924 100644 --- a/tests/di/fixtures/config.php +++ b/tests/di/fixtures/config.php @@ -1,7 +1,7 @@ Date: Sun, 10 May 2015 23:54:49 +0200 Subject: [PATCH 0281/1676] [ticket/13770] Fix tests PHPBB3-13770 --- phpBB/common.php | 10 ++- phpBB/install/index.php | 3 +- phpBB/phpbb/di/container_builder.php | 99 ++++++++++++++++------------ 3 files changed, 61 insertions(+), 51 deletions(-) diff --git a/phpBB/common.php b/phpBB/common.php index 70fb34331c..0b898d9553 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -96,21 +96,19 @@ set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handle $phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx); $phpbb_class_loader_ext->register(); -\Symfony\Component\Debug\Debug::enable(E_ALL); - // Set up container -/*try -{*/ +try +{ $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container(); -/*} +} catch (InvalidArgumentException $e) { trigger_error( 'The requested environment ' . PHPBB_ENVIRONMENT . ' is not available.', E_USER_ERROR ); -}*/ +} $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); diff --git a/phpBB/install/index.php b/phpBB/install/index.php index f935e3d08c..3559a10971 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -117,11 +117,10 @@ $phpbb_class_loader_ext->register(); // Set up container $phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx); $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); -$phpbb_container = $phpbb_container_builder +$phpbb_container_builder ->without_extensions() ->without_cache() ->without_compiled_container() - ->get_container() ; $other_config_path = $phpbb_root_path . 'install/update/new/config/'; diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 3886bfdd5d..9f2e860932 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -21,6 +21,7 @@ use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; +use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; class container_builder @@ -130,48 +131,53 @@ class container_builder { require($config_cache->getPath()); $this->container = new \phpbb_cache_container(); - - return $this->container; } - - $this->container_extensions = array(new extension\core($this->get_config_path())); - - if ($this->use_extensions) + else { - $this->load_extensions(); - } + $this->container_extensions = array(new extension\core($this->get_config_path())); - // Inject the config - if ($this->config_php_file) - { - $this->container_extensions[] = new extension\config($this->config_php_file); - } - - $this->container = $this->create_container($this->container_extensions); - - // Easy collections through tags - $this->container->addCompilerPass(new pass\collection_pass()); - - // Event listeners "phpBB style" - $this->container->addCompilerPass(new RegisterListenersPass('dispatcher', 'event.listener_listener', 'event.listener')); - - // Event listeners "Symfony style" - $this->container->addCompilerPass(new RegisterListenersPass('dispatcher')); - - $filesystem = new filesystem(); - $loader = new YamlFileLoader($this->container, new FileLocator($filesystem->realpath($this->get_config_path()))); - $loader->load($this->container->getParameter('core.environment') . '/config.yml'); - - $this->inject_custom_parameters(); - - if ($this->compile_container) - { - $this->container->compile(); - - if ($this->use_cache) + if ($this->use_extensions) { - $this->dump_container($config_cache); + $this->load_extensions(); } + + // Inject the config + if ($this->config_php_file) + { + $this->container_extensions[] = new extension\config($this->config_php_file); + } + + $this->container = $this->create_container($this->container_extensions); + + // Easy collections through tags + $this->container->addCompilerPass(new pass\collection_pass()); + + // Event listeners "phpBB style" + $this->container->addCompilerPass(new RegisterListenersPass('dispatcher', 'event.listener_listener', 'event.listener')); + + // Event listeners "Symfony style" + $this->container->addCompilerPass(new RegisterListenersPass('dispatcher')); + + $filesystem = new filesystem(); + $loader = new YamlFileLoader($this->container, new FileLocator($filesystem->realpath($this->get_config_path()))); + $loader->load($this->container->getParameter('core.environment') . '/config.yml'); + + $this->inject_custom_parameters(); + + if ($this->compile_container) + { + $this->container->compile(); + + if ($this->use_cache) + { + $this->dump_container($config_cache); + } + } + } + + if ($this->compile_container && $this->config_php_file) + { + $this->container->set('config.php', $this->config_php_file); } return $this->container; @@ -394,13 +400,20 @@ class container_builder */ protected function dump_container($cache) { - $dumper = new PhpDumper($this->container); - $cached_container_dump = $dumper->dump(array( - 'class' => 'phpbb_cache_container', - 'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder', - )); + try + { + $dumper = new PhpDumper($this->container); + $cached_container_dump = $dumper->dump(array( + 'class' => 'phpbb_cache_container', + 'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder', + )); - $cache->write($cached_container_dump, $this->container->getResources()); + $cache->write($cached_container_dump, $this->container->getResources()); + } + catch (IOException $e) + { + // Don't fail if the cache isn't writeable + } } /** From 2b25c5bd35a1a5e668d0f4e644cfabf995e1a537 Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Mon, 11 May 2015 00:19:50 +0200 Subject: [PATCH 0282/1676] [ticket/13770] Use dummy cache driver PHPBB3-13770 --- phpBB/phpbb/di/container_builder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 9f2e860932..4a31339b9a 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -360,7 +360,7 @@ class container_builder ->get_container() ; - $ext_container->register('cache.driver', '\\phpbb\\cache\\driver\\null'); + $ext_container->register('cache.driver', '\\phpbb\\cache\\driver\\dummy'); $ext_container->compile(); $extensions = $ext_container->get('ext.manager')->all_enabled(); From f5ce9f273829ba470a1348b4314cddb58f552da0 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 3 May 2015 16:06:42 +0200 Subject: [PATCH 0283/1676] [ticket/13680] Updated quote notifications Added get_quote_authors() to text_formatter.utils service to retrieve the names used in first-level quotes PHPBB3-13680 --- .../container/services_notification.yml | 2 + phpBB/phpbb/notification/type/quote.php | 31 +++++++++------ phpBB/phpbb/textformatter/s9e/utils.php | 25 ++++++++++++ phpBB/phpbb/textformatter/utils_interface.php | 8 ++++ tests/notification/base.php | 9 ++++- tests/notification/manager_helper.php | 5 +++ tests/notification/submit_post_base.php | 5 +++ .../submit_post_type_quote_test.php | 38 ++++++++++--------- tests/text_formatter/s9e/utils_test.php | 34 +++++++++++++++++ 9 files changed, 126 insertions(+), 31 deletions(-) diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index b17a172fb5..c3bbcddfa6 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -221,6 +221,8 @@ services: - %tables.notification_types% - %tables.notifications% - %tables.user_notifications% + calls: + - [set_utils, [@text_formatter.utils]] tags: - { name: notification.type } diff --git a/phpBB/phpbb/notification/type/quote.php b/phpBB/phpbb/notification/type/quote.php index 141f90c7ae..1b8efe4c8e 100644 --- a/phpBB/phpbb/notification/type/quote.php +++ b/phpBB/phpbb/notification/type/quote.php @@ -20,6 +20,11 @@ namespace phpbb\notification\type; class quote extends \phpbb\notification\type\post { + /** + * @var \phpbb\textformatter\utils_interface + */ + protected $utils; + /** * Get notification type name * @@ -30,13 +35,6 @@ class quote extends \phpbb\notification\type\post return 'notification.type.quote'; } - /** - * regular expression to match to find usernames - * - * @var string - */ - protected static $regular_expression_match = '#\[quote="(.+?)"#'; - /** * Language key used to output the text * @@ -77,17 +75,16 @@ class quote extends \phpbb\notification\type\post 'ignore_users' => array(), ), $options); - $usernames = false; - preg_match_all(self::$regular_expression_match, $post['post_text'], $usernames); + $usernames = $this->utils->get_quote_authors($post['post_text']); - if (empty($usernames[1])) + if (empty($usernames)) { return array(); } - $usernames[1] = array_unique($usernames[1]); + $usernames = array_unique($usernames); - $usernames = array_map('utf8_clean_string', $usernames[1]); + $usernames = array_map('utf8_clean_string', $usernames); $users = array(); @@ -187,4 +184,14 @@ class quote extends \phpbb\notification\type\post 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']), )); } + + /** + * Set the utils service used to retrieve quote authors + * + * @param \phpbb\textformatter\utils_interface $utils + */ + public function set_utils(\phpbb\textformatter\utils_interface $utils) + { + $this->utils = $utils; + } } diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index 2018bbf519..576ab9481c 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -34,6 +34,31 @@ class utils implements \phpbb\textformatter\utils_interface return \s9e\TextFormatter\Utils::removeFormatting($xml); } + /** + * Get a list of quote authors, limited to the first level of quotes + * + * @param string $xml Parsed text + * @return string[] List of authors + */ + public function get_quote_authors($xml) + { + $authors = array(); + if (strpos($xml, 'loadXML($xml); + $xpath = new \DOMXPath($dom); + foreach ($xpath->query('//QUOTE[not(ancestor::QUOTE)]/@author') as $author) + { + $authors[] = $author->textContent; + } + + return $authors; + } + /** * Remove given BBCode and its content, at given nesting depth * diff --git a/phpBB/phpbb/textformatter/utils_interface.php b/phpBB/phpbb/textformatter/utils_interface.php index 132dc8ece4..183c426161 100644 --- a/phpBB/phpbb/textformatter/utils_interface.php +++ b/phpBB/phpbb/textformatter/utils_interface.php @@ -28,6 +28,14 @@ interface utils_interface */ public function clean_formatting($text); + /** + * Get a list of quote authors, limited to the first level of quotes + * + * @param string $text Parsed text + * @return string[] List of authors + */ + public function get_quote_authors($text); + /** * Remove given BBCode and its content, at given nesting depth * diff --git a/tests/notification/base.php b/tests/notification/base.php index a1ebecd6f9..45b0b6f179 100644 --- a/tests/notification/base.php +++ b/tests/notification/base.php @@ -116,7 +116,14 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case { global $phpbb_root_path, $phpEx; - return new $type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_notifications', 'phpbb_user_notifications'); + $instance = new $type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_notifications', 'phpbb_user_notifications'); + + if ($type === 'phpbb\\notification\\type\\quote') + { + $instance->set_utils(new \phpbb\textformatter\s9e\utils); + } + + return $instance; } protected function assert_notifications($expected, $options = array()) diff --git a/tests/notification/manager_helper.php b/tests/notification/manager_helper.php index 75b7275d3a..48bf5b177b 100644 --- a/tests/notification/manager_helper.php +++ b/tests/notification/manager_helper.php @@ -48,6 +48,11 @@ class phpbb_notification_manager_helper extends \phpbb\notification\manager $item = new $item_type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, $this->notifications_table, $this->user_notifications_table); + if ($item_type === 'phpbb\\notification\\type\\quote') + { + $item->set_utils(new \phpbb\textformatter\s9e\utils); + } + $item->set_notification_manager($this); $item->set_initial_data($data); diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php index d7a711e007..04fb6658c3 100644 --- a/tests/notification/submit_post_base.php +++ b/tests/notification/submit_post_base.php @@ -117,6 +117,11 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c $phpbb_root_path, $phpEx, NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE, USER_NOTIFICATIONS_TABLE); + if ($type === 'quote') + { + $class->set_utils(new \phpbb\textformatter\s9e\utils); + } + $phpbb_container->set('notification.type.' . $type, $class); $notification_types_array['notification.type.' . $type] = $class; diff --git a/tests/notification/submit_post_type_quote_test.php b/tests/notification/submit_post_type_quote_test.php index 61e3840773..8ad6a62b09 100644 --- a/tests/notification/submit_post_type_quote_test.php +++ b/tests/notification/submit_post_type_quote_test.php @@ -51,6 +51,8 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_ */ public function submit_post_data() { + $parser = $this->get_test_case_helpers()->set_s9e_services()->get('text_formatter.parser'); + return array( /** * Normal post @@ -65,15 +67,15 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_ */ array( array( - 'message' => implode(' ', array( - '[quote="poster":uid]poster should not be notified[/quote:uid]', - '[quote="test":uid]test should be notified[/quote:uid]', - '[quote="unauthorized":uid]unauthorized to read, should not receive a notification[/quote:uid]', - '[quote="notified":uid]already notified, should not receive a new notification[/quote:uid]', - '[quote="disabled":uid]option disabled, should not receive a notification[/quote:uid]', - '[quote="default":uid]option set to default, should receive a notification[/quote:uid]', - '[quote="doesn\'t exist":uid]user does not exist, should not receive a notification[/quote:uid]', - )), + 'message' => $parser->parse(implode(' ', array( + '[quote="poster"]poster should not be notified[/quote]', + '[quote="test"]test should be notified[/quote]', + '[quote="unauthorized"]unauthorized to read, should not receive a notification[/quote]', + '[quote="notified"]already notified, should not receive a new notification[/quote]', + '[quote="disabled"]option disabled, should not receive a notification[/quote]', + '[quote="default"]option set to default, should receive a notification[/quote]', + '[quote="doesn\'t exist"]user does not exist, should not receive a notification[/quote]', + ))), 'bbcode_uid' => 'uid', ), array( @@ -94,15 +96,15 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_ */ array( array( - 'message' => implode(' ', array( - '[quote="poster":uid]poster should not be notified[/quote:uid]', - '[quote="test":uid]test should be notified[/quote:uid]', - '[quote="unauthorized":uid]unauthorized to read, should not receive a notification[/quote:uid]', - '[quote="notified":uid]already notified, should not receive a new notification[/quote:uid]', - '[quote="disabled":uid]option disabled, should not receive a notification[/quote:uid]', - '[quote="default":uid]option set to default, should receive a notification[/quote:uid]', - '[quote="doesn\'t exist":uid]user does not exist, should not receive a notification[/quote:uid]', - )), + 'message' => $parser->parse(implode(' ', array( + '[quote="poster"]poster should not be notified[/quote]', + '[quote="test"]test should be notified[/quote]', + '[quote="unauthorized"]unauthorized to read, should not receive a notification[/quote]', + '[quote="notified"]already notified, should not receive a new notification[/quote]', + '[quote="disabled"]option disabled, should not receive a notification[/quote]', + '[quote="default"]option set to default, should receive a notification[/quote]', + '[quote="doesn\'t exist"]user does not exist, should not receive a notification[/quote]', + ))), 'bbcode_uid' => 'uid', 'force_approved_state' => false, ), diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index 69f8682cac..78e5869af1 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -74,6 +74,40 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case ); } + /** + * @dataProvider get_quote_authors_tests + */ + public function test_get_quote_authors($original, $expected) + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + $parser = $container->get('text_formatter.parser'); + + $this->assertSame($expected, $utils->get_quote_authors($parser->parse($original))); + } + + public function get_quote_authors_tests() + { + return array( + array( + 'No quotes here', + array() + ), + array( + '[quote="foo"]..[/quote] [quote]..[/quote]', + array('foo') + ), + array( + '[quote="foo"]..[/quote] [quote="bar"]..[/quote]', + array('foo', 'bar') + ), + array( + '[quote="foo"].[quote="baz"]..[/quote].[/quote] [quote="bar"]..[/quote]', + array('foo', 'bar') + ), + ); + } + /** * @dataProvider get_remove_bbcode_tests */ From f7ad2c2b32b309edba006a8d4b58727b50642ea2 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 15 May 2015 02:12:52 +0200 Subject: [PATCH 0284/1676] [ticket/13680] Renamed get_quote_authors to get_outermost_quote_authors PHPBB3-13680 --- phpBB/phpbb/notification/type/quote.php | 2 +- phpBB/phpbb/textformatter/s9e/utils.php | 4 ++-- phpBB/phpbb/textformatter/utils_interface.php | 4 ++-- tests/text_formatter/s9e/utils_test.php | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/phpBB/phpbb/notification/type/quote.php b/phpBB/phpbb/notification/type/quote.php index 1b8efe4c8e..51edfec6f7 100644 --- a/phpBB/phpbb/notification/type/quote.php +++ b/phpBB/phpbb/notification/type/quote.php @@ -75,7 +75,7 @@ class quote extends \phpbb\notification\type\post 'ignore_users' => array(), ), $options); - $usernames = $this->utils->get_quote_authors($post['post_text']); + $usernames = $this->utils->get_outermost_quote_authors($post['post_text']); if (empty($usernames)) { diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index 576ab9481c..e21dedecc4 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -35,12 +35,12 @@ class utils implements \phpbb\textformatter\utils_interface } /** - * Get a list of quote authors, limited to the first level of quotes + * Get a list of quote authors, limited to the outermost quotes * * @param string $xml Parsed text * @return string[] List of authors */ - public function get_quote_authors($xml) + public function get_outermost_quote_authors($xml) { $authors = array(); if (strpos($xml, 'get_test_case_helpers()->set_s9e_services(); $utils = $container->get('text_formatter.utils'); $parser = $container->get('text_formatter.parser'); - $this->assertSame($expected, $utils->get_quote_authors($parser->parse($original))); + $this->assertSame($expected, $utils->get_outermost_quote_authors($parser->parse($original))); } - public function get_quote_authors_tests() + public function get_outermost_quote_authors_tests() { return array( array( From e7321c9e559919f0e5da677ecf6ba6518f433b4c Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 16 May 2015 18:07:08 +0200 Subject: [PATCH 0285/1676] [ticket/13844] Add a little develop script to migrate the files PHPBB3-13844 --- phpBB/develop/lang_migrate_help_lang.php | 312 +++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 phpBB/develop/lang_migrate_help_lang.php diff --git a/phpBB/develop/lang_migrate_help_lang.php b/phpBB/develop/lang_migrate_help_lang.php new file mode 100644 index 0000000000..28a8ee058b --- /dev/null +++ b/phpBB/develop/lang_migrate_help_lang.php @@ -0,0 +1,312 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +// +// Security message: +// +// This script is potentially dangerous. +// Remove or comment the next line (die(".... ) to enable this script. +// Do NOT FORGET to either remove this script or disable it after you have used it. +// +#die("Please read the first lines of this script for instructions on how to enable it"); + +define('IN_PHPBB', true); +$phpEx = substr(strrchr(__FILE__, '.'), 1); +$phpbb_root_path='./../'; +include($phpbb_root_path . 'common.'.$phpEx); + +$help_bbcode = load_help('bbcode'); +$lang_bbcode = array( + 'HELP_BBCODE_BLOCK_INTRO' => $help_bbcode[0][1], + 'HELP_BBCODE_INTRO_BBCODE_QUESTION' => $help_bbcode[1][0], + 'HELP_BBCODE_INTRO_BBCODE_ANSWER' => $help_bbcode[1][1], + + 'HELP_BBCODE_BLOCK_TEXT' => $help_bbcode[2][1], + 'HELP_BBCODE_TEXT_BASIC_QUESTION' => $help_bbcode[3][0], + 'HELP_BBCODE_TEXT_BASIC_ANSWER' => $help_bbcode[3][1], + 'HELP_BBCODE_TEXT_COLOR_QUESTION' => $help_bbcode[4][0], + 'HELP_BBCODE_TEXT_COLOR_ANSWER' => $help_bbcode[4][1], + 'HELP_BBCODE_TEXT_COMBINE_QUESTION' => $help_bbcode[5][0], + 'HELP_BBCODE_TEXT_COMBINE_ANSWER' => $help_bbcode[5][1], + + 'HELP_BBCODE_BLOCK_QUOTES' => $help_bbcode[6][1], + 'HELP_BBCODE_QUOTES_TEXT_QUESTION' => $help_bbcode[7][0], + 'HELP_BBCODE_QUOTES_TEXT_ANSWER' => $help_bbcode[7][1], + 'HELP_BBCODE_QUOTES_CODE_QUESTION' => $help_bbcode[8][0], + 'HELP_BBCODE_QUOTES_CODE_ANSWER' => $help_bbcode[8][1], + + 'HELP_BBCODE_BLOCK_LISTS' => $help_bbcode[9][1], + 'HELP_BBCODE_LISTS_UNORDERER_QUESTION' => $help_bbcode[10][0], + 'HELP_BBCODE_LISTS_UNORDERER_ANSWER' => $help_bbcode[10][1], + 'HELP_BBCODE_LISTS_ORDERER_QUESTION' => $help_bbcode[11][0], + 'HELP_BBCODE_LISTS_ORDERER_ANSWER' => $help_bbcode[11][1], + + 'HELP_BBCODE_BLOCK_LINKS' => $help_bbcode[13][1], + 'HELP_BBCODE_LINKS_BASIC_QUESTION' => $help_bbcode[14][0], + 'HELP_BBCODE_LINKS_BASIC_ANSWER' => $help_bbcode[14][1], + + 'HELP_BBCODE_BLOCK_IMAGES' => $help_bbcode[15][1], + 'HELP_BBCODE_IMAGES_BASIC_QUESTION' => $help_bbcode[16][0], + 'HELP_BBCODE_IMAGES_BASIC_ANSWER' => $help_bbcode[16][1], + 'HELP_BBCODE_IMAGES_ATTACHMENT_QUESTION' => $help_bbcode[17][0], + 'HELP_BBCODE_IMAGES_ATTACHMENT_ANSWER' => $help_bbcode[17][1], + + 'HELP_BBCODE_BLOCK_OTHERS' => $help_bbcode[18][1], + 'HELP_BBCODE_OTHERS_CUSTOM_QUESTION' => $help_bbcode[19][0], + 'HELP_BBCODE_OTHERS_CUSTOM_ANSWER' => $help_bbcode[19][1], +); +write_help('bbcode', $lang_bbcode); + +$help_phpbb = load_help('faq'); +$lang_phpbb = array( + 'HELP_FAQ_BLOCK_LOGIN' => $help_phpbb[0][1], + 'HELP_FAQ_LOGIN_REGISTER_QUESTION' => $help_phpbb[1][0], + 'HELP_FAQ_LOGIN_REGISTER_ANSWER' => $help_phpbb[1][1], + 'HELP_FAQ_LOGIN_COPPA_QUESTION' => $help_phpbb[2][0], + 'HELP_FAQ_LOGIN_COPPA_ANSWER' => $help_phpbb[2][1], + 'HELP_FAQ_LOGIN_CANNOT_REGISTER_QUESTION' => $help_phpbb[3][0], + 'HELP_FAQ_LOGIN_CANNOT_REGISTER_ANSWER' => $help_phpbb[3][1], + 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_QUESTION' => $help_phpbb[4][0], + 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_ANSWER' => $help_phpbb[4][1], + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_QUESTION' => $help_phpbb[5][0], + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANSWER' => $help_phpbb[5][1], + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_QUESTION' => $help_phpbb[6][0], + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_ANSWER' => $help_phpbb[6][1], + 'HELP_FAQ_LOGIN_LOST_PASSWORD_QUESTION' => $help_phpbb[7][0], + 'HELP_FAQ_LOGIN_LOST_PASSWORD_ANSWER' => $help_phpbb[7][1], + 'HELP_FAQ_LOGIN_AUTO_LOGOUT_QUESTION' => $help_phpbb[8][0], + 'HELP_FAQ_LOGIN_AUTO_LOGOUT_ANSWER' => $help_phpbb[8][1], + 'HELP_FAQ_LOGIN_DELETE_COOKIES_QUESTION' => $help_phpbb[9][0], + 'HELP_FAQ_LOGIN_DELETE_COOKIES_ANSWER' => $help_phpbb[9][1], + + 'HELP_FAQ_BLOCK_USERSETTINGS' => $help_phpbb[10][1], + 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_QUESTION' => $help_phpbb[11][0], + 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_ANSWER' => $help_phpbb[11][1], + 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_QUESTION' => $help_phpbb[12][0], + 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_ANSWER' => $help_phpbb[12][1], + 'HELP_FAQ_USERSETTINGS_TIMEZONE_QUESTION' => $help_phpbb[13][0], + 'HELP_FAQ_USERSETTINGS_TIMEZONE_ANSWER' => $help_phpbb[13][1], + 'HELP_FAQ_USERSETTINGS_SERVERTIME_QUESTION' => $help_phpbb[14][0], + 'HELP_FAQ_USERSETTINGS_SERVERTIME_ANSWER' => $help_phpbb[14][1], + 'HELP_FAQ_USERSETTINGS_LANGUAGE_QUESTION' => $help_phpbb[15][0], + 'HELP_FAQ_USERSETTINGS_LANGUAGE_ANSWER' => $help_phpbb[15][1], + 'HELP_FAQ_USERSETTINGS_AVATAR_QUESTION' => $help_phpbb[16][0], + 'HELP_FAQ_USERSETTINGS_AVATAR_ANSWER' => $help_phpbb[16][1], + 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_QUESTION' => $help_phpbb[17][0], + 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_ANSWER' => $help_phpbb[17][1], + 'HELP_FAQ_USERSETTINGS_RANK_QUESTION' => $help_phpbb[18][0], + 'HELP_FAQ_USERSETTINGS_RANK_ANSWER' => $help_phpbb[18][1], + 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_QUESTION' => $help_phpbb[19][0], + 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_ANSWER' => $help_phpbb[19][1], + + 'HELP_FAQ_BLOCK_POSTING' => $help_phpbb[20][1], + 'HELP_FAQ_POSTING_CREATE_QUESTION' => $help_phpbb[21][0], + 'HELP_FAQ_POSTING_CREATE_ANSWER' => $help_phpbb[21][1], + 'HELP_FAQ_POSTING_EDIT_DELETE_QUESTION' => $help_phpbb[22][0], + 'HELP_FAQ_POSTING_EDIT_DELETE_ANSWER' => $help_phpbb[22][1], + 'HELP_FAQ_POSTING_SIGNATURE_QUESTION' => $help_phpbb[23][0], + 'HELP_FAQ_POSTING_SIGNATURE_ANSWER' => $help_phpbb[23][1], + 'HELP_FAQ_POSTING_POLL_CREATE_QUESTION' => $help_phpbb[24][0], + 'HELP_FAQ_POSTING_POLL_CREATE_ANSWER' => $help_phpbb[24][1], + 'HELP_FAQ_POSTING_POLL_ADD_QUESTION' => $help_phpbb[25][0], + 'HELP_FAQ_POSTING_POLL_ADD_ANSWER' => $help_phpbb[25][1], + 'HELP_FAQ_POSTING_POLL_EDIT_QUESTION' => $help_phpbb[26][0], + 'HELP_FAQ_POSTING_POLL_EDIT_ANSWER' => $help_phpbb[26][1], + 'HELP_FAQ_POSTING_FORUM_RESTRICTED_QUESTION' => $help_phpbb[27][0], + 'HELP_FAQ_POSTING_FORUM_RESTRICTED_ANSWER' => $help_phpbb[27][1], + 'HELP_FAQ_POSTING_NO_ATTACHMENTS_QUESTION' => $help_phpbb[28][0], + 'HELP_FAQ_POSTING_NO_ATTACHMENTS_ANSWER' => $help_phpbb[28][1], + 'HELP_FAQ_POSTING_WARNING_QUESTION' => $help_phpbb[29][0], + 'HELP_FAQ_POSTING_WARNING_ANSWER' => $help_phpbb[29][1], + 'HELP_FAQ_POSTING_REPORT_QUESTION' => $help_phpbb[30][0], + 'HELP_FAQ_POSTING_REPORT_ANSWER' => $help_phpbb[30][1], + 'HELP_FAQ_POSTING_DRAFT_QUESTION' => $help_phpbb[31][0], + 'HELP_FAQ_POSTING_DRAFT_ANSWER' => $help_phpbb[31][1], + 'HELP_FAQ_POSTING_QUEUE_QUESTION' => $help_phpbb[32][0], + 'HELP_FAQ_POSTING_QUEUE_ANSWER' => $help_phpbb[32][1], + 'HELP_FAQ_POSTING_BUMP_QUESTION' => $help_phpbb[33][0], + 'HELP_FAQ_POSTING_BUMP_ANSWER' => $help_phpbb[33][1], + + 'HELP_FAQ_BLOCK_FORMATTING' => $help_phpbb[34][1], + 'HELP_FAQ_FORMATTING_BBOCDE_QUESTION' => $help_phpbb[35][0], + 'HELP_FAQ_FORMATTING_BBOCDE_ANSWER' => $help_phpbb[35][1], + 'HELP_FAQ_FORMATTING_HTML_QUESTION' => $help_phpbb[36][0], + 'HELP_FAQ_FORMATTING_HTML_ANSWER' => $help_phpbb[36][1], + 'HELP_FAQ_FORMATTING_SMILIES_QUESTION' => $help_phpbb[37][0], + 'HELP_FAQ_FORMATTING_SMILIES_ANSWER' => $help_phpbb[37][1], + 'HELP_FAQ_FORMATTING_IMAGES_QUESTION' => $help_phpbb[38][0], + 'HELP_FAQ_FORMATTING_IMAGES_ANSWER' => $help_phpbb[38][1], + 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_QUESTION' => $help_phpbb[39][0], + 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_ANSWER' => $help_phpbb[39][1], + 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_QUESTION' => $help_phpbb[40][0], + 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_ANSWER' => $help_phpbb[40][1], + 'HELP_FAQ_FORMATTING_STICKIES_QUESTION' => $help_phpbb[41][0], + 'HELP_FAQ_FORMATTING_STICKIES_ANSWER' => $help_phpbb[41][1], + 'HELP_FAQ_FORMATTING_LOCKED_QUESTION' => $help_phpbb[42][0], + 'HELP_FAQ_FORMATTING_LOCKED_ANSWER' => $help_phpbb[42][1], + 'HELP_FAQ_FORMATTING_ICONS_QUESTION' => $help_phpbb[43][0], + 'HELP_FAQ_FORMATTING_ICONS_ANSWER' => $help_phpbb[43][1], + + 'HELP_FAQ_BLOCK_GROUPS' => $help_phpbb[45][1], + 'HELP_FAQ_GROUPS_ADMINISTRATORS_QUESTION' => $help_phpbb[46][0], + 'HELP_FAQ_GROUPS_ADMINISTRATORS_ANSWER' => $help_phpbb[46][1], + 'HELP_FAQ_GROUPS_MODERATORS_QUESTION' => $help_phpbb[47][0], + 'HELP_FAQ_GROUPS_MODERATORS_ANSWER' => $help_phpbb[47][1], + 'HELP_FAQ_GROUPS_USERGROUPS_QUESTION' => $help_phpbb[48][0], + 'HELP_FAQ_GROUPS_USERGROUPS_ANSWER' => $help_phpbb[48][1], + 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_QUESTION' => $help_phpbb[49][0], + 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_ANSWER' => $help_phpbb[49][1], + 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_QUESTION' => $help_phpbb[50][0], + 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_ANSWER' => $help_phpbb[50][1], + 'HELP_FAQ_GROUPS_COLORS_QUESTION' => $help_phpbb[51][0], + 'HELP_FAQ_GROUPS_COLORS_ANSWER' => $help_phpbb[51][1], + 'HELP_FAQ_GROUPS_DEFAULT_QUESTION' => $help_phpbb[52][0], + 'HELP_FAQ_GROUPS_DEFAULT_ANSWER' => $help_phpbb[52][1], + 'HELP_FAQ_GROUPS_TEAM_QUESTION' => $help_phpbb[53][0], + 'HELP_FAQ_GROUPS_TEAM_ANSWER' => $help_phpbb[53][1], + + 'HELP_FAQ_BLOCK_PMS' => $help_phpbb[54][1], + 'HELP_FAQ_PMS_CANNOT_SEND_QUESTION' => $help_phpbb[55][0], + 'HELP_FAQ_PMS_CANNOT_SEND_ANSWER' => $help_phpbb[55][1], + 'HELP_FAQ_PMS_UNWANTED_QUESTION' => $help_phpbb[56][0], + 'HELP_FAQ_PMS_UNWANTED_ANSWER' => $help_phpbb[56][1], + 'HELP_FAQ_PMS_SPAM_QUESTION' => $help_phpbb[57][0], + 'HELP_FAQ_PMS_SPAM_ANSWER' => $help_phpbb[57][1], + + 'HELP_FAQ_BLOCK_FRIENDS' => $help_phpbb[58][1], + 'HELP_FAQ_FRIENDS_BASIC_QUESTION' => $help_phpbb[59][0], + 'HELP_FAQ_FRIENDS_BASIC_ANSWER' => $help_phpbb[59][1], + 'HELP_FAQ_FRIENDS_MANAGE_QUESTION' => $help_phpbb[60][0], + 'HELP_FAQ_FRIENDS_MANAGE_ANSWER' => $help_phpbb[60][1], + + 'HELP_FAQ_BLOCK_SEARCH' => $help_phpbb[61][1], + 'HELP_FAQ_SEARCH_FORUM_QUESTION' => $help_phpbb[62][0], + 'HELP_FAQ_SEARCH_FORUM_ANSWER' => $help_phpbb[62][1], + 'HELP_FAQ_SEARCH_NO_RESULT_QUESTION' => $help_phpbb[63][0], + 'HELP_FAQ_SEARCH_NO_RESULT_ANSWER' => $help_phpbb[63][1], + 'HELP_FAQ_SEARCH_BLANK_QUESTION' => $help_phpbb[64][0], + 'HELP_FAQ_SEARCH_BLANK_ANSWER' => $help_phpbb[64][1], + 'HELP_FAQ_SEARCH_MEMBERS_QUESTION' => $help_phpbb[65][0], + 'HELP_FAQ_SEARCH_MEMBERS_ANSWER' => $help_phpbb[65][1], + 'HELP_FAQ_SEARCH_OWN_QUESTION' => $help_phpbb[66][0], + 'HELP_FAQ_SEARCH_OWN_ANSWER' => $help_phpbb[66][1], + + 'HELP_FAQ_BLOCK_BOOKMARKS' => $help_phpbb[67][1], + 'HELP_FAQ_BOOKMARKS_DIFFERENCE_QUESTION' => $help_phpbb[68][0], + 'HELP_FAQ_BOOKMARKS_DIFFERENCE_ANSWER' => $help_phpbb[68][1], + 'HELP_FAQ_BOOKMARKS_TOPIC_QUESTION' => $help_phpbb[69][0], + 'HELP_FAQ_BOOKMARKS_TOPIC_ANSWER' => $help_phpbb[69][1], + 'HELP_FAQ_BOOKMARKS_FORUM_QUESTION' => $help_phpbb[70][0], + 'HELP_FAQ_BOOKMARKS_FORUM_ANSWER' => $help_phpbb[70][1], + 'HELP_FAQ_BOOKMARKS_REMOVE_QUESTION' => $help_phpbb[71][0], + 'HELP_FAQ_BOOKMARKS_REMOVE_ANSWER' => $help_phpbb[71][1], + + 'HELP_FAQ_BLOCK_ATTACHMENTS' => $help_phpbb[72][1], + 'HELP_FAQ_ATTACHMENTS_ALLOWED_QUESTION' => $help_phpbb[73][0], + 'HELP_FAQ_ATTACHMENTS_ALLOWED_ANSWER' => $help_phpbb[73][1], + 'HELP_FAQ_ATTACHMENTS_OWN_QUESTION' => $help_phpbb[74][0], + 'HELP_FAQ_ATTACHMENTS_OWN_ANSWER' => $help_phpbb[74][1], + + 'HELP_FAQ_BLOCK_ISSUES' => $help_phpbb[75][1], + 'HELP_FAQ_ISSUES_WHOIS_PHPBB_QUESTION' => $help_phpbb[76][0], + 'HELP_FAQ_ISSUES_WHOIS_PHPBB_ANSWER' => $help_phpbb[76][1], + 'HELP_FAQ_ISSUES_FEATURE_QUESTION' => $help_phpbb[77][0], + 'HELP_FAQ_ISSUES_FEATURE_ANSWER' => $help_phpbb[77][1], + 'HELP_FAQ_ISSUES_LEGAL_QUESTION' => $help_phpbb[78][0], + 'HELP_FAQ_ISSUES_LEGAL_ANSWER' => $help_phpbb[78][1], + 'HELP_FAQ_ISSUES_ADMIN_QUESTION' => $help_phpbb[79][0], + 'HELP_FAQ_ISSUES_ADMIN_ANSWER' => $help_phpbb[79][1], + +); +write_help('phpbb', $lang_phpbb); + +trigger_error('Successfully migrated help_bbcode and help_faq to help/bbcode and help/phpbb'); + +/** + * @param string $help + * @return array + */ +function load_help($help) +{ + global $phpbb_root_path; + include($phpbb_root_path . 'language/en/help_' . $help . '.php'); + return $help; +} + +/** + * @param string $help + * @param array $lang + */ +function write_help($help, array $lang) +{ + global $phpbb_root_path; + $fp = fopen($phpbb_root_path . 'language/en/help/' . $help . '.php', 'wb'); + fwrite($fp, get_language_file_header()); + fwrite($fp, '$lang = array(' . "\n"); + + $last_key = ''; + ksort($lang); + foreach ($lang as $key => $translation) + { + $key_sections = explode('_', $key, 4); + unset($key_sections[3]); + $key_start = implode('_', $key_sections); + + if ($last_key !== '' && $key_start !== $last_key) + { + fwrite($fp, "\n"); + } + fwrite($fp, "\t'" . $key . "'\t=> '" . $translation . "',\n"); + $last_key = $key_start; + } + + fwrite($fp, ');' . "\n"); + #fwrite($fp, $lang); + fclose($fp); +} + +/** + * @return string + */ +function get_language_file_header() +{ + return << + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +/** + * DO NOT CHANGE + */ +if (!defined('IN_PHPBB')) +{ + exit; +} + +if (empty(\$lang) || !is_array(\$lang)) +{ + \$lang = array(); +} + + +EOT; +} From 5586cbbcfe5117e1750ebff507e42b296c729aa1 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 16 May 2015 18:07:35 +0200 Subject: [PATCH 0286/1676] [ticket/13844] Add new versions of the old help_* files PHPBB3-13844 --- phpBB/language/en/help/bbcode.php | 66 +++++++++++ phpBB/language/en/help/faq.php | 186 ++++++++++++++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100644 phpBB/language/en/help/bbcode.php create mode 100644 phpBB/language/en/help/faq.php diff --git a/phpBB/language/en/help/bbcode.php b/phpBB/language/en/help/bbcode.php new file mode 100644 index 0000000000..cfbba0b771 --- /dev/null +++ b/phpBB/language/en/help/bbcode.php @@ -0,0 +1,66 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +/** + * DO NOT CHANGE + */ +if (!defined('IN_PHPBB')) +{ + exit; +} + +if (empty($lang) || !is_array($lang)) +{ + $lang = array(); +} + +$lang = array( + 'HELP_BBCODE_BLOCK_IMAGES' => 'Showing images in posts', + 'HELP_BBCODE_BLOCK_INTRO' => 'Introduction', + 'HELP_BBCODE_BLOCK_LINKS' => 'Creating Links', + 'HELP_BBCODE_BLOCK_LISTS' => 'Generating lists', + 'HELP_BBCODE_BLOCK_OTHERS' => 'Other matters', + 'HELP_BBCODE_BLOCK_QUOTES' => 'Quoting and outputting fixed-width text', + 'HELP_BBCODE_BLOCK_TEXT' => 'Text Formatting', + + 'HELP_BBCODE_IMAGES_ATTACHMENT_ANSWER' => 'Attachments can now be placed in any part of a post by using the new [attachment=][/attachment] BBCode, if the attachments functionality has been enabled by a board administrator and if you are given the appropriate permissions to create attachments. Within the posting screen is a drop-down box (respectively a button) for placing attachments inline.', + 'HELP_BBCODE_IMAGES_ATTACHMENT_QUESTION' => 'Adding attachments into a post', + 'HELP_BBCODE_IMAGES_BASIC_ANSWER' => 'phpBB BBCode incorporates a tag for including images in your posts. Two very important things to remember when using this tag are: many users do not appreciate lots of images being shown in posts and secondly the image you display must already be available on the internet (it cannot exist only on your computer for example, unless you run a webserver!). To display an image you must surround the URL pointing to the image with [img][/img] tags. For example:

              [img]http://www.phpbb.com/theme/images/logos/blue/160x52.png[/img]

              As noted in the URL section above you can wrap an image in a [url][/url] tag if you wish, e.g.

              [url=http://www.phpbb.com/][img]http://www.phpbb.com/theme/images/logos/blue/160x52.png[/img][/url]

              would generate:

              ', + 'HELP_BBCODE_IMAGES_BASIC_QUESTION' => 'Adding an image to a post', + + 'HELP_BBCODE_INTRO_BBCODE_ANSWER' => 'BBCode is a special implementation of HTML. Whether you can actually use BBCode in your posts on the forum is determined by the administrator. In addition you can disable BBCode on a per post basis via the posting form. BBCode itself is similar in style to HTML, tags are enclosed in square brackets [ and ] rather than < and > and it offers greater control over what and how something is displayed. Depending on the template you are using you may find adding BBCode to your posts is made much easier through a clickable interface above the message area on the posting form. Even with this you may find the following guide useful.', + 'HELP_BBCODE_INTRO_BBCODE_QUESTION' => 'What is BBCode?', + + 'HELP_BBCODE_LINKS_BASIC_ANSWER' => 'phpBB BBCode supports a number of ways of creating URIs (Uniform Resource Indicators) better known as URLs.
              • The first of these uses the [url=][/url] tag, whatever you type after the = sign will cause the contents of that tag to act as a URL. For example to link to phpBB.com you could use:

                [url=http://www.phpbb.com/]Visit phpBB![/url]

                This would generate the following link, Visit phpBB! Please notice that the link opens in the same window or a new window depending on the users browser preferences.
              • If you want the URL itself displayed as the link you can do this by simply using:

                [url]http://www.phpbb.com/[/url]

                This would generate the following link, http://www.phpbb.com/
              • Additionally, phpBB features something called Magic Links, this will turn any syntactically correct URL into a link without you needing to specify any tags or even the leading http://. For example typing www.phpbb.com into your message will automatically lead to www.phpbb.com being output when you view the message.
              • The same thing applies equally to email addresses, you can either specify an address explicitly for example:

                [email]no.one@domain.adr[/email]

                which will output no.one@domain.adr or you can just type no.one@domain.adr into your message and it will be automatically converted when you view.
              As with all the BBCode tags you can wrap URLs around any of the other tags such as [img][/img] (see next entry), [b][/b], etc. As with the formatting tags it is up to you to ensure the correct open and close order is following, for example:

              [url=http://www.phpbb.com/][img]http://www.phpbb.com/theme/images/logos/blue/160x52.png[/url][/img]

              is not correct which may lead to your post being deleted so take care.', + 'HELP_BBCODE_LINKS_BASIC_QUESTION' => 'Linking to another site', + + 'HELP_BBCODE_LISTS_ORDERER_ANSWER' => 'The second type of list, an ordered list, gives you control over what is output before each item. To create an ordered list you use [list=1][/list] to create a numbered list or alternatively [list=a][/list] for an alphabetical list. As with the unordered list, items are specified using [*]. For example:

              [list=1]
              [*]Go to the shops
              [*]Buy a new computer
              [*]Swear at computer when it crashes
              [/list]

              will generate the following:
              1. Go to the shops
              2. Buy a new computer
              3. Swear at computer when it crashes
              Whereas for an alphabetical list you would use:

              [list=a]
              [*]The first possible answer
              [*]The second possible answer
              [*]The third possible answer
              [/list]

              giving
              1. The first possible answer
              2. The second possible answer
              3. The third possible answer
              ', + 'HELP_BBCODE_LISTS_ORDERER_QUESTION' => 'Creating an Ordered list', + 'HELP_BBCODE_LISTS_UNORDERER_ANSWER' => 'BBCode supports two types of lists, unordered and ordered. They are essentially the same as their HTML equivalents. An unordered list outputs each item in your list sequentially one after the other indenting each with a bullet character. To create an unordered list you use [list][/list] and define each item within the list using [*]. For example to list your favourite colours you could use:

              [list]
              [*]Red
              [*]Blue
              [*]Yellow
              [/list]

              This would generate the following list:
              • Red
              • Blue
              • Yellow
              ', + 'HELP_BBCODE_LISTS_UNORDERER_QUESTION' => 'Creating an Unordered list', + + 'HELP_BBCODE_OTHERS_CUSTOM_ANSWER' => 'If you are an administrator on this board and have the proper permissions, you can add further BBCodes through the Custom BBCodes section.', + 'HELP_BBCODE_OTHERS_CUSTOM_QUESTION' => 'Can I add my own tags?', + + 'HELP_BBCODE_QUOTES_CODE_ANSWER' => 'If you want to output a piece of code or in fact anything that requires a fixed width, e.g. Courier type font you should enclose the text in [code][/code] tags, e.g.

              [code]echo "This is some code";[/code]

              All formatting used within [code][/code] tags is retained when you later view it. PHP syntax highlighting can be enabled using [code=php][/code] and is recommended when posting PHP code samples as it improves readability.', + 'HELP_BBCODE_QUOTES_CODE_QUESTION' => 'Outputting code or fixed width data', + 'HELP_BBCODE_QUOTES_TEXT_ANSWER' => 'There are two ways you can quote text, with a reference or without.
              • When you utilise the Quote function to reply to a post on the board you should notice that the post text is added to the message window enclosed in a [quote=""][/quote] block. This method allows you to quote with a reference to a person or whatever else you choose to put! For example to quote a piece of text Mr. Blobby wrote you would enter:

                [quote="Mr. Blobby"]The text Mr. Blobby wrote would go here[/quote]

                The resulting output will automatically add "Mr. Blobby wrote:" before the actual text. Remember you must include the quotation marks "" around the name you are quoting, they are not optional.
              • The second method allows you to blindly quote something. To utilise this enclose the text in [quote][/quote] tags. When you view the message it will simply show the text within a quotation block.
              ', + 'HELP_BBCODE_QUOTES_TEXT_QUESTION' => 'Quoting text in replies', + + 'HELP_BBCODE_TEXT_BASIC_ANSWER' => 'BBCode includes tags to allow you to quickly change the basic style of your text. This is achieved in the following ways:
              • To make a piece of text bold enclose it in [b][/b], e.g.

                [b]Hello[/b]

                will become Hello
              • For underlining use [u][/u], for example:

                [u]Good Morning[/u]

                becomes Good Morning
              • To italicise text use [i][/i], e.g.

                This is [i]Great![/i]

                would give This is Great!
              ', + 'HELP_BBCODE_TEXT_BASIC_QUESTION' => 'How to create bold, italic and underlined text', + 'HELP_BBCODE_TEXT_COLOR_ANSWER' => 'To alter the colour or size of your text the following tags can be used. Keep in mind that how the output appears will depend on the viewers browser and system:
              • Changing the colour of text is achieved by wrapping it in [color=][/color]. You can specify either a recognised colour name (eg. red, blue, yellow, etc.) or the hexadecimal triplet alternative, e.g. #FFFFFF, #000000. For example, to create red text you could use:

                [color=red]Hello![/color]

                or

                [color=#FF0000]Hello![/color]

                Both will output Hello!
              • Changing the text size is achieved in a similar way using [size=][/size]. This tag is dependent on the template the user has selected but the recommended format is a numerical value representing the text size in percent, starting at 20 (very small) through to 200 (very large) by default. For example:

                [size=30]SMALL[/size]

                will generally be SMALL

                whereas:

                [size=200]HUGE![/size]

                will be HUGE!
              ', + 'HELP_BBCODE_TEXT_COLOR_QUESTION' => 'How to change the text colour or size', + 'HELP_BBCODE_TEXT_COMBINE_ANSWER' => 'Yes, of course you can, for example to get someones attention you may write:

              [size=200][color=red][b]LOOK AT ME![/b][/color][/size]

              this would output LOOK AT ME!

              We don’t recommend you output lots of text that looks like this though! Remember it is up to you, the poster, to ensure tags are closed correctly. For example the following is incorrect:

              [b][u]This is wrong[/b][/u]', + 'HELP_BBCODE_TEXT_COMBINE_QUESTION' => 'Can I combine formatting tags?', +); diff --git a/phpBB/language/en/help/faq.php b/phpBB/language/en/help/faq.php new file mode 100644 index 0000000000..fdb6f62aee --- /dev/null +++ b/phpBB/language/en/help/faq.php @@ -0,0 +1,186 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +/** + * DO NOT CHANGE + */ +if (!defined('IN_PHPBB')) +{ + exit; +} + +if (empty($lang) || !is_array($lang)) +{ + $lang = array(); +} + +$lang = array( + 'HELP_FAQ_ATTACHMENTS_ALLOWED_ANSWER' => 'Each board administrator can allow or disallow certain attachment types. If you are unsure what is allowed to be uploaded, contact the board administrator for assistance.', + 'HELP_FAQ_ATTACHMENTS_ALLOWED_QUESTION' => 'What attachments are allowed on this board?', + 'HELP_FAQ_ATTACHMENTS_OWN_ANSWER' => 'To find your list of attachments that you have uploaded, go to your User Control Panel and follow the links to the attachments section.', + 'HELP_FAQ_ATTACHMENTS_OWN_QUESTION' => 'How do I find all my attachments?', + + 'HELP_FAQ_BLOCK_ATTACHMENTS' => 'Attachments', + 'HELP_FAQ_BLOCK_BOOKMARKS' => 'Subscriptions and Bookmarks', + 'HELP_FAQ_BLOCK_FORMATTING' => 'Formatting and Topic Types', + 'HELP_FAQ_BLOCK_FRIENDS' => 'Friends and Foes', + 'HELP_FAQ_BLOCK_GROUPS' => 'User Levels and Groups', + 'HELP_FAQ_BLOCK_ISSUES' => 'phpBB Issues', + 'HELP_FAQ_BLOCK_LOGIN' => 'Login and Registration Issues', + 'HELP_FAQ_BLOCK_PMS' => 'Private Messaging', + 'HELP_FAQ_BLOCK_POSTING' => 'Posting Issues', + 'HELP_FAQ_BLOCK_SEARCH' => 'Searching the Forums', + 'HELP_FAQ_BLOCK_USERSETTINGS' => 'User Preferences and settings', + + 'HELP_FAQ_BOOKMARKS_DIFFERENCE_ANSWER' => 'In phpBB 3.0, bookmarking topics worked much like bookmarking in a web browser. You were not alerted when there was an update. As of phpBB 3.1, bookmarking is more like subscribing to a topic. You can be notified when a bookmarked topic is updated. Subscribing, however, will notify you when there is an update to a topic or forum on the board. Notification options for bookmarks and subscriptions can be configured in the User Control Panel, under “Board preferencesâ€.', + 'HELP_FAQ_BOOKMARKS_DIFFERENCE_QUESTION' => 'What is the difference between bookmarking and subscribing?', + 'HELP_FAQ_BOOKMARKS_FORUM_ANSWER' => 'To subscribe to a specific forum, click the “Subscribe forum†link, at the bottom of page, upon entering the forum.', + 'HELP_FAQ_BOOKMARKS_FORUM_QUESTION' => 'How do I subscribe to specific forums?', + 'HELP_FAQ_BOOKMARKS_REMOVE_ANSWER' => 'To remove your subscriptions, go to your User Control Panel and follow the links to your subscriptions.', + 'HELP_FAQ_BOOKMARKS_REMOVE_QUESTION' => 'How do I remove my subscriptions?', + 'HELP_FAQ_BOOKMARKS_TOPIC_ANSWER' => 'You can bookmark or subscribe to a specific topic by clicking the appropriate link in the “Topic tools†menu, conveniently located near the top and bottom of a topic discussion.
              Replying to a topic with the “Notify me when a reply is posted†option checked will also subscribe you to the topic.', + 'HELP_FAQ_BOOKMARKS_TOPIC_QUESTION' => 'How do I bookmark or subscribe to specific topics?', + + 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_ANSWER' => 'Announcements often contain important information for the forum you are currently reading and you should read them whenever possible. Announcements appear at the top of every page in the forum to which they are posted. As with global announcements, announcement permissions are granted by the board administrator.', + 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_QUESTION' => 'What are announcements?', + 'HELP_FAQ_FORMATTING_BBOCDE_ANSWER' => 'BBCode is a special implementation of HTML, offering great formatting control on particular objects in a post. The use of BBCode is granted by the administrator, but it can also be disabled on a per post basis from the posting form. BBCode itself is similar in style to HTML, but tags are enclosed in square brackets [ and ] rather than < and >. For more information on BBCode see the guide which can be accessed from the posting page.', + 'HELP_FAQ_FORMATTING_BBOCDE_QUESTION' => 'What is BBCode?', + 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_ANSWER' => 'Global announcements contain important information and you should read them whenever possible. They will appear at the top of every forum and within your User Control Panel. Global announcement permissions are granted by the board administrator.', + 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_QUESTION' => 'What are global announcements?', + 'HELP_FAQ_FORMATTING_HTML_ANSWER' => 'No. It is not possible to post HTML on this board and have it rendered as HTML. Most formatting which can be carried out using HTML can be applied using BBCode instead.', + 'HELP_FAQ_FORMATTING_HTML_QUESTION' => 'Can I use HTML?', + 'HELP_FAQ_FORMATTING_ICONS_ANSWER' => 'Topic icons are author chosen images associated with posts to indicate their content. The ability to use topic icons depends on the permissions set by the board administrator.', + 'HELP_FAQ_FORMATTING_ICONS_QUESTION' => 'What are topic icons?', + 'HELP_FAQ_FORMATTING_IMAGES_ANSWER' => 'Yes, images can be shown in your posts. If the administrator has allowed attachments, you may be able to upload the image to the board. Otherwise, you must link to an image stored on a publicly accessible web server, e.g. http://www.example.com/my-picture.gif. You cannot link to pictures stored on your own PC (unless it is a publicly accessible server) nor images stored behind authentication mechanisms, e.g. hotmail or yahoo mailboxes, password protected sites, etc. To display the image use the BBCode [img] tag.', + 'HELP_FAQ_FORMATTING_IMAGES_QUESTION' => 'Can I post images?', + 'HELP_FAQ_FORMATTING_LOCKED_ANSWER' => 'Locked topics are topics where users can no longer reply and any poll it contained was automatically ended. Topics may be locked for many reasons and were set this way by either the forum moderator or board administrator. You may also be able to lock your own topics depending on the permissions you are granted by the board administrator.', + 'HELP_FAQ_FORMATTING_LOCKED_QUESTION' => 'What are locked topics?', + 'HELP_FAQ_FORMATTING_SMILIES_ANSWER' => 'Smilies, or Emoticons, are small images which can be used to express a feeling using a short code, e.g. :) denotes happy, while :( denotes sad. The full list of emoticons can be seen in the posting form. Try not to overuse smilies, however, as they can quickly render a post unreadable and a moderator may edit them out or remove the post altogether. The board administrator may also have set a limit to the number of smilies you may use within a post.', + 'HELP_FAQ_FORMATTING_SMILIES_QUESTION' => 'What are Smilies?', + 'HELP_FAQ_FORMATTING_STICKIES_ANSWER' => 'Sticky topics within the forum appear below announcements and only on the first page. They are often quite important so you should read them whenever possible. As with announcements and global announcements, sticky topic permissions are granted by the board administrator.', + 'HELP_FAQ_FORMATTING_STICKIES_QUESTION' => 'What are sticky topics?', + + 'HELP_FAQ_FRIENDS_BASIC_ANSWER' => 'You can use these lists to organise other members of the board. Members added to your friends list will be listed within your User Control Panel for quick access to see their online status and to send them private messages. Subject to template support, posts from these users may also be highlighted. If you add a user to your foes list, any posts they make will be hidden by default.', + 'HELP_FAQ_FRIENDS_BASIC_QUESTION' => 'What are my Friends and Foes lists?', + 'HELP_FAQ_FRIENDS_MANAGE_ANSWER' => 'You can add users to your list in two ways. Within each user’s profile, there is a link to add them to either your Friend or Foe list. Alternatively, from your User Control Panel, you can directly add users by entering their member name. You may also remove users from your list using the same page.', + 'HELP_FAQ_FRIENDS_MANAGE_QUESTION' => 'How can I add / remove users to my Friends or Foes list?', + + 'HELP_FAQ_GROUPS_ADMINISTRATORS_ANSWER' => 'Administrators are members assigned with the highest level of control over the entire board. These members can control all facets of board operation, including setting permissions, banning users, creating usergroups or moderators, etc., dependent upon the board founder and what permissions he or she has given the other administrators. They may also have full moderator capabilities in all forums, depending on the settings put forth by the board founder.', + 'HELP_FAQ_GROUPS_ADMINISTRATORS_QUESTION' => 'What are Administrators?', + 'HELP_FAQ_GROUPS_COLORS_ANSWER' => 'It is possible for the board administrator to assign a colour to the members of a usergroup to make it easy to identify the members of this group.', + 'HELP_FAQ_GROUPS_COLORS_QUESTION' => 'Why do some usergroups appear in a different colour?', + 'HELP_FAQ_GROUPS_DEFAULT_ANSWER' => 'If you are a member of more than one usergroup, your default is used to determine which group colour and group rank should be shown for you by default. The board administrator may grant you permission to change your default usergroup via your User Control Panel.', + 'HELP_FAQ_GROUPS_DEFAULT_QUESTION' => 'What is a “Default usergroup�', + 'HELP_FAQ_GROUPS_MODERATORS_ANSWER' => 'Moderators are individuals (or groups of individuals) who look after the forums from day to day. They have the authority to edit or delete posts and lock, unlock, move, delete and split topics in the forum they moderate. Generally, moderators are present to prevent users from going off-topic or posting abusive or offensive material.', + 'HELP_FAQ_GROUPS_MODERATORS_QUESTION' => 'What are Moderators?', + 'HELP_FAQ_GROUPS_TEAM_ANSWER' => 'This page provides you with a list of board staff, including board administrators and moderators and other details such as the forums they moderate.', + 'HELP_FAQ_GROUPS_TEAM_QUESTION' => 'What is “The team†link?', + 'HELP_FAQ_GROUPS_USERGROUPS_ANSWER' => 'Usergroups are groups of users that divide the community into manageable sections board administrators can work with. Each user can belong to several groups and each group can be assigned individual permissions. This provides an easy way for administrators to change permissions for many users at once, such as changing moderator permissions or granting users access to a private forum.', + 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_ANSWER' => 'You can view all usergroups via the “Usergroups†link within your User Control Panel. If you would like to join one, proceed by clicking the appropriate button. Not all groups have open access, however. Some may require approval to join, some may be closed and some may even have hidden memberships. If the group is open, you can join it by clicking the appropriate button. If a group requires approval to join you may request to join by clicking the appropriate button. The user group leader will need to approve your request and may ask why you want to join the group. Please do not harass a group leader if they reject your request; they will have their reasons.', + 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_QUESTION' => 'Where are the usergroups and how do I join one?', + 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_ANSWER' => 'A usergroup leader is usually assigned when usergroups are initially created by a board administrator. If you are interested in creating a usergroup, your first point of contact should be an administrator; try sending a private message.', + 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_QUESTION' => 'How do I become a usergroup leader?', + 'HELP_FAQ_GROUPS_USERGROUPS_QUESTION' => 'What are usergroups?', + + 'HELP_FAQ_ISSUES_ADMIN_ANSWER' => 'All users of the board can use the “Contact us†form, if the option was enabled by the board administrator.
              Members of the board can also use the “The team†link.', + 'HELP_FAQ_ISSUES_ADMIN_QUESTION' => 'How do I contact a board administrator?', + 'HELP_FAQ_ISSUES_FEATURE_ANSWER' => 'This software was written by and licensed through phpBB Limited. If you believe a feature needs to be added please visit the phpBB Ideas Centre, where you can upvote existing ideas or suggest new features.', + 'HELP_FAQ_ISSUES_FEATURE_QUESTION' => 'Why isn’t X feature available?', + 'HELP_FAQ_ISSUES_LEGAL_ANSWER' => 'Any of the administrators listed on the “The team†page should be an appropriate point of contact for your complaints. If this still gets no response then you should contact the owner of the domain (do a whois lookup) or, if this is running on a free service (e.g. Yahoo!, free.fr, f2s.com, etc.), the management or abuse department of that service. Please note that the phpBB Limited has absolutely no jurisdiction and cannot in any way be held liable over how, where or by whom this board is used. Do not contact the phpBB Limited in relation to any legal (cease and desist, liable, defamatory comment, etc.) matter not directly related to the phpBB.com website or the discrete software of phpBB itself. If you do email phpBB Limited about any third party use of this software then you should expect a terse response or no response at all.', + 'HELP_FAQ_ISSUES_LEGAL_QUESTION' => 'Who do I contact about abusive and/or legal matters related to this board?', + 'HELP_FAQ_ISSUES_WHOIS_PHPBB_ANSWER' => 'This software (in its unmodified form) is produced, released and is copyright phpBB Limited. It is made available under the GNU General Public License, version 2 (GPL-2.0) and may be freely distributed. See About phpBB for more details.', + 'HELP_FAQ_ISSUES_WHOIS_PHPBB_QUESTION' => 'Who wrote this bulletin board?', + + 'HELP_FAQ_LOGIN_AUTO_LOGOUT_ANSWER' => 'If you do not check the Remember me box when you login, the board will only keep you logged in for a preset time. This prevents misuse of your account by anyone else. To stay logged in, check the Remember me box during login. This is not recommended if you access the board from a shared computer, e.g. library, internet cafe, university computer lab, etc. If you do not see this checkbox, it means a board administrator has disabled this feature.', + 'HELP_FAQ_LOGIN_AUTO_LOGOUT_QUESTION' => 'Why do I get logged off automatically?', + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANSWER' => 'There are several reasons why this could occur. First, ensure your username and password are correct. If they are, contact a board administrator to make sure you haven’t been banned. It is also possible the website owner has a configuration error on their end, and they would need to fix it.', + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_ANSWER' => 'It is possible an administrator has deactivated or deleted your account for some reason. Also, many boards periodically remove users who have not posted for a long time to reduce the size of the database. If this has happened, try registering again and being more involved in discussions.', + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_QUESTION' => 'I registered in the past but cannot login any more?!', + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_QUESTION' => 'Why can’t I login?', + 'HELP_FAQ_LOGIN_CANNOT_REGISTER_ANSWER' => 'It is possible a board administrator has disabled registration to prevent new visitors from signing up. A board administrator could have also banned your IP address or disallowed the username you are attempting to register. Contact a board administrator for assistance.', + 'HELP_FAQ_LOGIN_CANNOT_REGISTER_QUESTION' => 'Why can’t I register?', + 'HELP_FAQ_LOGIN_COPPA_ANSWER' => 'COPPA, or the Children’s Online Privacy Protection Act of 1998, is a law in the United States requiring websites which can potentially collect information from minors under the age of 13 to have written parental consent or some other method of legal guardian acknowledgment, allowing the collection of personally identifiable information from a minor under the age of 13. If you are unsure if this applies to you as someone trying to register or to the website you are trying to register on, contact legal counsel for assistance. Please note that phpBB Limited and the owners of this board cannot provide legal advice and is not a point of contact for legal concerns of any kind, except as outlined in question “Who do I contact about abusive and/or legal matters related to this board?â€.', + 'HELP_FAQ_LOGIN_COPPA_QUESTION' => 'What is COPPA?', + 'HELP_FAQ_LOGIN_DELETE_COOKIES_ANSWER' => '“Delete all board cookies†deletes the cookies created by phpBB which keep you authenticated and logged into the board. Cookies also provide functions such as read tracking if they have been enabled by a board administrator. If you are having login or logout problems, deleting board cookies may help.', + 'HELP_FAQ_LOGIN_DELETE_COOKIES_QUESTION' => 'What does the “Delete all board cookies†do?', + 'HELP_FAQ_LOGIN_LOST_PASSWORD_ANSWER' => 'Don’t panic! While your password cannot be retrieved, it can easily be reset. Visit the login page and click I forgot my password. Follow the instructions and you should be able to log in again shortly.
              However, if you are not able to reset your password, contact a board administrator.', + 'HELP_FAQ_LOGIN_LOST_PASSWORD_QUESTION' => 'I’ve lost my password!', + 'HELP_FAQ_LOGIN_REGISTER_ANSWER' => 'You may not have to, it is up to the administrator of the board as to whether you need to register in order to post messages. However; registration will give you access to additional features not available to guest users such as definable avatar images, private messaging, emailing of fellow users, usergroup subscription, etc. It only takes a few moments to register so it is recommended you do so.', + 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_ANSWER' => 'First, check your username and password. If they are correct, then one of two things may have happened. If COPPA support is enabled and you specified being under 13 years old during registration, you will have to follow the instructions you received. Some boards will also require new registrations to be activated, either by yourself or by an administrator before you can logon; this information was present during registration. If you were sent an email, follow the instructions. If you did not receive an email, you may have provided an incorrect email address or the email may have been picked up by a spam filer. If you are sure the email address you provided is correct, try contacting an administrator.', + 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_QUESTION' => 'I registered but cannot login!', + 'HELP_FAQ_LOGIN_REGISTER_QUESTION' => 'Why do I need to register?', + + 'HELP_FAQ_PMS_CANNOT_SEND_ANSWER' => 'There are three reasons for this; you are not registered and/or not logged on, the board administrator has disabled private messaging for the entire board, or the board administrator has prevented you from sending messages. Contact a board administrator for more information.', + 'HELP_FAQ_PMS_CANNOT_SEND_QUESTION' => 'I cannot send private messages!', + 'HELP_FAQ_PMS_SPAM_ANSWER' => 'We are sorry to hear that. The email form feature of this board includes safeguards to try and track users who send such posts, so email the board administrator with a full copy of the email you received. It is very important that this includes the headers that contain the details of the user that sent the email. The board administrator can then take action.', + 'HELP_FAQ_PMS_SPAM_QUESTION' => 'I have received a spamming or abusive email from someone on this board!', + 'HELP_FAQ_PMS_UNWANTED_ANSWER' => 'You can automatically delete private messages from a user by using message rules within your User Control Panel. If you are receiving abusive private messages from a particular user, report the messages to the moderators; they have the power to prevent a user from sending private messages.', + 'HELP_FAQ_PMS_UNWANTED_QUESTION' => 'I keep getting unwanted private messages!', + + 'HELP_FAQ_POSTING_BUMP_ANSWER' => 'By clicking the “Bump topic†link when you are viewing it, you can “bump†the topic to the top of the forum on the first page. However, if you do not see this, then topic bumping may be disabled or the time allowance between bumps has not yet been reached. It is also possible to bump the topic simply by replying to it, however, be sure to follow the board rules when doing so.', + 'HELP_FAQ_POSTING_BUMP_QUESTION' => 'How do I bump my topic?', + 'HELP_FAQ_POSTING_CREATE_ANSWER' => 'To post a new topic in a forum, click "New Topic". To post a reply to a topic, click "Post Reply". You may need to register before you can post a message. A list of your permissions in each forum is available at the bottom of the forum and topic screens. Example: You can post new topics, You can post attachments, etc.', + 'HELP_FAQ_POSTING_CREATE_QUESTION' => 'How do I create a new topic or post a reply?', + 'HELP_FAQ_POSTING_DRAFT_ANSWER' => 'This allows you to save drafts to be completed and submitted at a later date. To reload a saved draft, visit the User Control Panel.', + 'HELP_FAQ_POSTING_DRAFT_QUESTION' => 'What is the “Save†button for in topic posting?', + 'HELP_FAQ_POSTING_EDIT_DELETE_ANSWER' => 'Unless you are a board administrator or moderator, you can only edit or delete your own posts. You can edit a post by clicking the edit button for the relevant post, sometimes for only a limited time after the post was made. If someone has already replied to the post, you will find a small piece of text output below the post when you return to the topic which lists the number of times you edited it along with the date and time. This will only appear if someone has made a reply; it will not appear if a moderator or administrator edited the post, though they may leave a note as to why they’ve edited the post at their own discretion. Please note that normal users cannot delete a post once someone has replied.', + 'HELP_FAQ_POSTING_EDIT_DELETE_QUESTION' => 'How do I edit or delete a post?', + 'HELP_FAQ_POSTING_FORUM_RESTRICTED_ANSWER' => 'Some forums may be limited to certain users or groups. To view, read, post or perform another action you may need special permissions. Contact a moderator or board administrator to grant you access.', + 'HELP_FAQ_POSTING_FORUM_RESTRICTED_QUESTION' => 'Why can’t I access a forum?', + 'HELP_FAQ_POSTING_NO_ATTACHMENTS_ANSWER' => 'Attachment permissions are granted on a per forum, per group, or per user basis. The board administrator may not have allowed attachments to be added for the specific forum you are posting in, or perhaps only certain groups can post attachments. Contact the board administrator if you are unsure about why you are unable to add attachments.', + 'HELP_FAQ_POSTING_NO_ATTACHMENTS_QUESTION' => 'Why can’t I add attachments?', + 'HELP_FAQ_POSTING_POLL_ADD_ANSWER' => 'The limit for poll options is set by the board administrator. If you feel you need to add more options to your poll than the allowed amount, contact the board administrator.', + 'HELP_FAQ_POSTING_POLL_ADD_QUESTION' => 'Why can’t I add more poll options?', + 'HELP_FAQ_POSTING_POLL_CREATE_ANSWER' => 'When posting a new topic or editing the first post of a topic, click the “Poll creation†tab below the main posting form; if you cannot see this, you do not have appropriate permissions to create polls. Enter a title and at least two options in the appropriate fields, making sure each option is on a separate line in the textarea. You can also set the number of options users may select during voting under “Options per userâ€, a time limit in days for the poll (0 for infinite duration) and lastly the option to allow users to amend their votes.', + 'HELP_FAQ_POSTING_POLL_CREATE_QUESTION' => 'How do I create a poll?', + 'HELP_FAQ_POSTING_POLL_EDIT_ANSWER' => 'As with posts, polls can only be edited by the original poster, a moderator or an administrator. To edit a poll, click to edit the first post in the topic; this always has the poll associated with it. If no one has cast a vote, users can delete the poll or edit any poll option. However, if members have already placed votes, only moderators or administrators can edit or delete it. This prevents the poll’s options from being changed mid-way through a poll.', + 'HELP_FAQ_POSTING_POLL_EDIT_QUESTION' => 'How do I edit or delete a poll?', + 'HELP_FAQ_POSTING_QUEUE_ANSWER' => 'The board administrator may have decided that posts in the forum you are posting to require review before submission. It is also possible that the administrator has placed you in a group of users whose posts require review before submission. Please contact the board administrator for further details.', + 'HELP_FAQ_POSTING_QUEUE_QUESTION' => 'Why does my post need to be approved?', + 'HELP_FAQ_POSTING_REPORT_ANSWER' => 'If the board administrator has allowed it, you should see a button for reporting posts next to the post you wish to report. Clicking this will walk you through the steps necessary to report the post.', + 'HELP_FAQ_POSTING_REPORT_QUESTION' => 'How can I report posts to a moderator?', + 'HELP_FAQ_POSTING_SIGNATURE_ANSWER' => 'To add a signature to a post you must first create one via your User Control Panel. Once created, you can check the Attach a signature box on the posting form to add your signature. You can also add a signature by default to all your posts by checking the appropriate radio button in the User Control Panel. If you do so, you can still prevent a signature being added to individual posts by un-checking the add signature box within the posting form.', + 'HELP_FAQ_POSTING_SIGNATURE_QUESTION' => 'How do I add a signature to my post?', + 'HELP_FAQ_POSTING_WARNING_ANSWER' => 'Each board administrator has their own set of rules for their site. If you have broken a rule, you may be issued a warning. Please note that this is the board administrator’s decision, and the phpBB Limited has nothing to do with the warnings on the given site. Contact the board administrator if you are unsure about why you were issued a warning.', + 'HELP_FAQ_POSTING_WARNING_QUESTION' => 'Why did I receive a warning?', + + 'HELP_FAQ_SEARCH_BLANK_ANSWER' => 'Your search returned too many results for the webserver to handle. Use “Advanced search†and be more specific in the terms used and forums that are to be searched.', + 'HELP_FAQ_SEARCH_BLANK_QUESTION' => 'Why does my search return a blank page!?', + 'HELP_FAQ_SEARCH_FORUM_ANSWER' => 'Enter a search term in the search box located on the index, forum or topic pages. Advanced search can be accessed by clicking the “Advance Search†link which is available on all pages on the forum. How to access the search may depend on the style used.', + 'HELP_FAQ_SEARCH_FORUM_QUESTION' => 'How can I search a forum or forums?', + 'HELP_FAQ_SEARCH_MEMBERS_ANSWER' => 'Visit to the “Members†page and click the “Find a member†link.', + 'HELP_FAQ_SEARCH_MEMBERS_QUESTION' => 'How do I search for members?', + 'HELP_FAQ_SEARCH_NO_RESULT_ANSWER' => 'Your search was probably too vague and included many common terms which are not indexed by phpBB. Be more specific and use the options available within Advanced search.', + 'HELP_FAQ_SEARCH_NO_RESULT_QUESTION' => 'Why does my search return no results?', + 'HELP_FAQ_SEARCH_OWN_ANSWER' => 'Your own posts can be retrieved either by clicking the “Show your posts†link within the User Control Panel or by clicking the “Search user’s posts†link via your own profile page or by clicking the “Quick links†menu at the top of the board. To search for your topics, use the Advanced search page and fill in the various options appropriately.', + 'HELP_FAQ_SEARCH_OWN_QUESTION' => 'How can I find my own posts and topics?', + + 'HELP_FAQ_USERSETTINGS_AVATAR_ANSWER' => 'There are two images which may appear along with a username when viewing posts. One of them may be an image associated with your rank, generally in the form of stars, blocks or dots, indicating how many posts you have made or your status on the board. Another, usually larger, image is known as an avatar and is generally unique or personal to each user.', + 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_ANSWER' => 'Within your User Control Panel, under “Profile†you can add an avatar by using one of the four following methods: Gravatar, Gallery, Remote or Upload. It is up to the board administrator to enable avatars and to choose the way in which avatars can be made available. If you are unable to use avatars, contact a board administrator.', + 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_QUESTION' => 'How do I display an avatar?', + 'HELP_FAQ_USERSETTINGS_AVATAR_QUESTION' => 'What are the images next to my username?', + 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_ANSWER' => 'If you are a registered user, all your settings are stored in the board database. To alter them, visit your User Control Panel; a link can usually be found by clicking on your username at the top of board pages. This system will allow you to change all your settings and preferences.', + 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_QUESTION' => 'How do I change my settings?', + 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_ANSWER' => 'Only registered users can send email to other users via the built-in email form, and only if the administrator has enabled this feature. This is to prevent malicious use of the email system by anonymous users.', + 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_QUESTION' => 'When I click the email link for a user it asks me to login?', + 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_ANSWER' => 'Within your User Control Panel, under “Board preferencesâ€, you will find the option Hide your online status. Enable this option and you will only appear to the administrators, moderators and yourself. You will be counted as a hidden user.', + 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_QUESTION' => 'How do I prevent my username appearing in the online user listings?', + 'HELP_FAQ_USERSETTINGS_LANGUAGE_ANSWER' => 'Either the administrator has not installed your language or nobody has translated this board into your language. Try asking a board administrator if they can install the language pack you need. If the language pack does not exist, feel free to create a new translation. More information can be found at the phpBB® website.', + 'HELP_FAQ_USERSETTINGS_LANGUAGE_QUESTION' => 'My language is not in the list!', + 'HELP_FAQ_USERSETTINGS_RANK_ANSWER' => 'Ranks, which appear below your username, indicate the number of posts you have made or identify certain users, e.g. moderators and administrators. In general, you cannot directly change the wording of any board ranks as they are set by the board administrator. Please do not abuse the board by posting unnecessarily just to increase your rank. Most boards will not tolerate this and the moderator or administrator will simply lower your post count.', + 'HELP_FAQ_USERSETTINGS_RANK_QUESTION' => 'What is my rank and how do I change it?', + 'HELP_FAQ_USERSETTINGS_SERVERTIME_ANSWER' => 'If you are sure you have set the timezone correctly and the time is still incorrect, then the time stored on the server clock is incorrect. Please notify an administrator to correct the problem.', + 'HELP_FAQ_USERSETTINGS_SERVERTIME_QUESTION' => 'I changed the timezone and the time is still wrong!', + 'HELP_FAQ_USERSETTINGS_TIMEZONE_ANSWER' => 'It is possible the time displayed is from a timezone different from the one you are in. If this is the case, visit your User Control Panel and change your timezone to match your particular area, e.g. London, Paris, New York, Sydney, etc. Please note that changing the timezone, like most settings, can only be done by registered users. If you are not registered, this is a good time to do so.', + 'HELP_FAQ_USERSETTINGS_TIMEZONE_QUESTION' => 'The times are not correct!', +); From ff7e9dc91262aa43c6153831a33fda13d5324325 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 16 May 2015 18:49:32 +0200 Subject: [PATCH 0287/1676] [ticket/13844] Refactor bbcode help to the new system PHPBB3-13844 --- .../default/container/services_help.yml | 17 ++++ phpBB/config/default/routing/help.yml | 3 + phpBB/phpbb/help/controller/bbcode.php | 85 +++++++++++++++++++ phpBB/phpbb/help/controller/controller.php | 81 ++++++++++++++++++ phpBB/phpbb/help/manager.php | 85 +++++++++++++++++++ 5 files changed, 271 insertions(+) create mode 100644 phpBB/phpbb/help/controller/bbcode.php create mode 100644 phpBB/phpbb/help/controller/controller.php create mode 100644 phpBB/phpbb/help/manager.php diff --git a/phpBB/config/default/container/services_help.yml b/phpBB/config/default/container/services_help.yml index ae3eafe7b0..c37d24b412 100644 --- a/phpBB/config/default/container/services_help.yml +++ b/phpBB/config/default/container/services_help.yml @@ -1,4 +1,10 @@ services: + phpbb.help.manager: + class: phpbb\help\manager + arguments: + - @template + - @language + phpbb.help.controller: class: phpbb\help\controller\help arguments: @@ -8,3 +14,14 @@ services: - @user - %core.root_path% - %core.php_ext% + + phpbb.help.controller.bbcode: + class: phpbb\help\controller\bbcode + arguments: + - @controller.helper + - @dispatcher + - @phpbb.help.manager + - @template + - @language + - %core.root_path% + - %core.php_ext% diff --git a/phpBB/config/default/routing/help.yml b/phpBB/config/default/routing/help.yml index 957d6dab55..9b15040875 100644 --- a/phpBB/config/default/routing/help.yml +++ b/phpBB/config/default/routing/help.yml @@ -1,3 +1,6 @@ phpbb_help_controller: + path: /bbcode + defaults: { _controller: phpbb.help.controller.bbcode:handle } + path: /{mode} defaults: { _controller: phpbb.help.controller:handle } diff --git a/phpBB/phpbb/help/controller/bbcode.php b/phpBB/phpbb/help/controller/bbcode.php new file mode 100644 index 0000000000..e16f99023d --- /dev/null +++ b/phpBB/phpbb/help/controller/bbcode.php @@ -0,0 +1,85 @@ + + * @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\help\controller; + +/** + * BBCode help page + */ +class bbcode extends controller +{ + /** + * @return string The title of the page + */ + public function display() + { + $this->language->add_lang('help/bbcode'); + + $this->manager->add_block( + 'HELP_BBCODE_BLOCK_INTRO', + false, + array( + 'HELP_BBCODE_INTRO_BBCODE_QUESTION' => 'HELP_BBCODE_INTRO_BBCODE_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_BBCODE_BLOCK_TEXT', + false, + array( + 'HELP_BBCODE_TEXT_BASIC_QUESTION' => 'HELP_BBCODE_TEXT_BASIC_ANSWER', + 'HELP_BBCODE_TEXT_COLOR_QUESTION' => 'HELP_BBCODE_TEXT_COLOR_ANSWER', + 'HELP_BBCODE_TEXT_COMBINE_QUESTION' => 'HELP_BBCODE_TEXT_COMBINE_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_BBCODE_BLOCK_QUOTES', + false, + array( + 'HELP_BBCODE_QUOTES_TEXT_QUESTION' => 'HELP_BBCODE_QUOTES_TEXT_ANSWER', + 'HELP_BBCODE_QUOTES_CODE_QUESTION' => 'HELP_BBCODE_QUOTES_CODE_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_BBCODE_BLOCK_LISTS', + false, + array( + 'HELP_BBCODE_LISTS_UNORDERER_QUESTION' => 'HELP_BBCODE_LISTS_UNORDERER_ANSWER', + 'HELP_BBCODE_LISTS_ORDERER_QUESTION' => 'HELP_BBCODE_LISTS_ORDERER_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_BBCODE_BLOCK_LINKS', + true, + array( + 'HELP_BBCODE_LINKS_BASIC_QUESTION' => 'HELP_BBCODE_LINKS_BASIC_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_BBCODE_BLOCK_IMAGES', + false, + array( + 'HELP_BBCODE_IMAGES_BASIC_QUESTION' => 'HELP_BBCODE_IMAGES_BASIC_ANSWER', + 'HELP_BBCODE_IMAGES_ATTACHMENT_QUESTION' => 'HELP_BBCODE_IMAGES_ATTACHMENT_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_BBCODE_BLOCK_OTHERS', + false, + array( + 'HELP_BBCODE_OTHERS_CUSTOM_QUESTION' => 'HELP_BBCODE_OTHERS_CUSTOM_ANSWER', + ) + ); + + return $this->language->lang('BBCODE_GUIDE'); + } +} diff --git a/phpBB/phpbb/help/controller/controller.php b/phpBB/phpbb/help/controller/controller.php new file mode 100644 index 0000000000..743a9c7fde --- /dev/null +++ b/phpBB/phpbb/help/controller/controller.php @@ -0,0 +1,81 @@ + + * @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\help\controller; + +/** + * BBCode help page + */ +abstract class controller +{ + /** @var \phpbb\controller\helper */ + protected $helper; + + /** @var \phpbb\event\dispatcher_interface */ + protected $dispatcher; + + /** @var \phpbb\help\manager */ + protected $manager; + + /** @var \phpbb\template\template */ + protected $template; + + /** @var \phpbb\language\language */ + protected $language; + + /** @var string */ + protected $root_path; + + /** @var string */ + protected $php_ext; + + /** + * Constructor + * + * @param \phpbb\controller\helper $helper + * @param \phpbb\event\dispatcher_interface $dispatcher + * @param \phpbb\help\manager $manager + * @param \phpbb\template\template $template + * @param \phpbb\language\language $language + * @param string $root_path + * @param string $php_ext + */ + public function __construct(\phpbb\controller\helper $helper, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\help\manager $manager, \phpbb\template\template $template, \phpbb\language\language $language, $root_path, $php_ext) + { + $this->helper = $helper; + $this->dispatcher = $dispatcher; + $this->manager = $manager; + $this->template = $template; + $this->language = $language; + $this->root_path = $root_path; + $this->php_ext = $php_ext; + } + + /** + * @return string + */ + abstract protected function display(); + + public function handle() + { + $title = $this->display(); + + $this->template->assign_vars(array( + 'L_FAQ_TITLE' => $title, + 'S_IN_FAQ' => true, + )); + + make_jumpbox(append_sid("{$this->root_path}viewforum.{$this->php_ext}")); + return $this->helper->render('faq_body.html', $title); + } +} diff --git a/phpBB/phpbb/help/manager.php b/phpBB/phpbb/help/manager.php new file mode 100644 index 0000000000..a7320563a8 --- /dev/null +++ b/phpBB/phpbb/help/manager.php @@ -0,0 +1,85 @@ + + * @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\help; + +/** + * Class help page manager + */ +class manager +{ + /** @var \phpbb\template\template */ + protected $template; + + /** @var \phpbb\language\language */ + protected $language; + + /** @var bool */ + protected $switched_column; + + /** + * Constructor + * + * @param \phpbb\template\template $template + * @param \phpbb\language\language $language + */ + public function __construct(\phpbb\template\template $template, \phpbb\language\language $language) + { + $this->template = $template; + $this->language = $language; + } + + /** + * Add a new faq block + * + * @param string $block_name Name or language key with the name of the block + * @param bool $switch_column Switch the column of the menu + */ + public function add_block($block_name, $switch_column = false, $questions = array()) + { + $this->template->assign_block_vars('faq_block', array( + 'BLOCK_TITLE' => $this->language->lang($block_name), + 'SWITCH_COLUMN' => !$this->switched_column && $switch_column, + )); + + foreach ($questions as $question => $answer) + { + $this->add_question($question, $answer); + } + + $this->switched_column = $this->switched_column || $switch_column; + } + + /** + * Add a new faq question + * + * @param string $question Question or language key with the question of the block + * @param string $answer Answer or language key with the answer of the block + */ + public function add_question($question, $answer) + { + $this->template->assign_block_vars('faq_block.faq_row', array( + 'FAQ_QUESTION' => $this->language->lang($question), + 'FAQ_ANSWER' => $this->language->lang($answer), + )); + } + + /** + * Returns whether the block titles switched side + * @return bool + */ + public function switched_column() + { + return $this->switched_column; + } +} From 07231e7943e9ffdba08393be56510e682ab7a7e5 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 16 May 2015 22:06:37 +0200 Subject: [PATCH 0288/1676] [ticket/13844] FAQ in new controller format PHPBB3-13844 --- .../default/container/services_help.yml | 21 +-- phpBB/config/default/routing/help.yml | 7 +- phpBB/develop/lang_migrate_help_lang.php | 2 +- phpBB/faq.php | 7 +- phpBB/includes/acp/acp_contact.php | 2 +- phpBB/includes/acp/acp_users.php | 2 +- phpBB/includes/functions.php | 2 +- phpBB/includes/ucp/ucp_pm_compose.php | 2 +- phpBB/includes/ucp/ucp_profile.php | 2 +- phpBB/phpbb/help/controller/faq.php | 165 ++++++++++++++++++ phpBB/posting.php | 2 +- phpBB/viewonline.php | 2 +- 12 files changed, 192 insertions(+), 24 deletions(-) create mode 100644 phpBB/phpbb/help/controller/faq.php diff --git a/phpBB/config/default/container/services_help.yml b/phpBB/config/default/container/services_help.yml index c37d24b412..29523ffb27 100644 --- a/phpBB/config/default/container/services_help.yml +++ b/phpBB/config/default/container/services_help.yml @@ -5,16 +5,6 @@ services: - @template - @language - phpbb.help.controller: - class: phpbb\help\controller\help - arguments: - - @controller.helper - - @dispatcher - - @template - - @user - - %core.root_path% - - %core.php_ext% - phpbb.help.controller.bbcode: class: phpbb\help\controller\bbcode arguments: @@ -25,3 +15,14 @@ services: - @language - %core.root_path% - %core.php_ext% + + phpbb.help.controller.faq: + class: phpbb\help\controller\faq + arguments: + - @controller.helper + - @dispatcher + - @phpbb.help.manager + - @template + - @language + - %core.root_path% + - %core.php_ext% diff --git a/phpBB/config/default/routing/help.yml b/phpBB/config/default/routing/help.yml index 9b15040875..8d43839d1e 100644 --- a/phpBB/config/default/routing/help.yml +++ b/phpBB/config/default/routing/help.yml @@ -1,6 +1,7 @@ -phpbb_help_controller: +phpbb_help_bbcode_controller: path: /bbcode defaults: { _controller: phpbb.help.controller.bbcode:handle } - path: /{mode} - defaults: { _controller: phpbb.help.controller:handle } +phpbb_help_faq_controller: + path: /faq + defaults: { _controller: phpbb.help.controller.faq:handle } diff --git a/phpBB/develop/lang_migrate_help_lang.php b/phpBB/develop/lang_migrate_help_lang.php index 28a8ee058b..d523493c83 100644 --- a/phpBB/develop/lang_migrate_help_lang.php +++ b/phpBB/develop/lang_migrate_help_lang.php @@ -228,7 +228,7 @@ $lang_phpbb = array( 'HELP_FAQ_ISSUES_ADMIN_ANSWER' => $help_phpbb[79][1], ); -write_help('phpbb', $lang_phpbb); +write_help('faq', $lang_phpbb); trigger_error('Successfully migrated help_bbcode and help_faq to help/bbcode and help/phpbb'); diff --git a/phpBB/faq.php b/phpBB/faq.php index 7420bc5a95..36a33c97a8 100644 --- a/phpBB/faq.php +++ b/phpBB/faq.php @@ -28,8 +28,9 @@ $user->setup(); $controller_helper = $phpbb_container->get('controller.helper'); $response = new \Symfony\Component\HttpFoundation\RedirectResponse( - $controller_helper->route('phpbb_help_controller', array( - 'mode' => $request->variable('mode', 'faq'), - ), 301) + $controller_helper->route( + $request->variable('mode', 'faq') === 'bbcode' ? 'phpbb_help_bbcode_controller' : 'phpbb_help_faq_controller' + ), + 301 ); $response->send(); diff --git a/phpBB/includes/acp/acp_contact.php b/phpBB/includes/acp/acp_contact.php index 945add66a4..1a4d5b95a3 100644 --- a/phpBB/includes/acp/acp_contact.php +++ b/phpBB/includes/acp/acp_contact.php @@ -119,7 +119,7 @@ class acp_contact 'S_SMILIES_DISABLE_CHECKED' => !$contact_admin_edit['allow_smilies'], 'S_MAGIC_URL_DISABLE_CHECKED' => !$contact_admin_edit['allow_urls'], - 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '', ''), + 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '', ''), 'SMILIES_STATUS' => $user->lang['SMILIES_ARE_ON'], 'IMG_STATUS' => $user->lang['IMAGES_ARE_ON'], 'FLASH_STATUS' => $user->lang['FLASH_IS_ON'], diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index fec32146c1..0ec17ccf0c 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -2045,7 +2045,7 @@ class acp_users 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', - 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), + 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 2ed0eff81c..b844d8a378 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4309,7 +4309,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = 'U_PROFILE' => append_sid("{$phpbb_root_path}ucp.$phpEx"), 'U_USER_PROFILE' => get_username_string('profile', $user->data['user_id'], $user->data['username'], $user->data['user_colour']), 'U_MODCP' => append_sid("{$phpbb_root_path}mcp.$phpEx", false, true, $user->session_id), - 'U_FAQ' => $controller_helper->route('phpbb_help_controller', array('mode' => 'faq')), + 'U_FAQ' => $controller_helper->route('phpbb_help_faq_controller'), 'U_SEARCH_SELF' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'), 'U_SEARCH_NEW' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'), 'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'), diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 59952182df..4982b6ad6a 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -1157,7 +1157,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) 'SUBJECT' => (isset($message_subject)) ? $message_subject : '', 'MESSAGE' => $message_text, - 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), + 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), 'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 66eae22a1b..2f4d650ed0 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -572,7 +572,7 @@ class ucp_profile 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', - 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), + 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], diff --git a/phpBB/phpbb/help/controller/faq.php b/phpBB/phpbb/help/controller/faq.php new file mode 100644 index 0000000000..5e45cfe667 --- /dev/null +++ b/phpBB/phpbb/help/controller/faq.php @@ -0,0 +1,165 @@ + + * @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\help\controller; + +/** + * FAQ help page + */ +class faq extends controller +{ + /** + * @return string The title of the page + */ + public function display() + { + $this->language->add_lang('help/faq'); + + $this->manager->add_block( + 'HELP_FAQ_BLOCK_LOGIN', + false, + array( + 'HELP_FAQ_LOGIN_REGISTER_QUESTION' => 'HELP_FAQ_LOGIN_REGISTER_ANSWER', + 'HELP_FAQ_LOGIN_COPPA_QUESTION' => 'HELP_FAQ_LOGIN_COPPA_ANSWER', + 'HELP_FAQ_LOGIN_CANNOT_REGISTER_QUESTION' => 'HELP_FAQ_LOGIN_CANNOT_REGISTER_ANSWER', + 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_QUESTION' => 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_ANSWER', + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_QUESTION' => 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANSWER', + 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_QUESTION' => 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_ANSWER', + 'HELP_FAQ_LOGIN_LOST_PASSWORD_QUESTION' => 'HELP_FAQ_LOGIN_LOST_PASSWORD_ANSWER', + 'HELP_FAQ_LOGIN_AUTO_LOGOUT_QUESTION' => 'HELP_FAQ_LOGIN_AUTO_LOGOUT_ANSWER', + 'HELP_FAQ_LOGIN_DELETE_COOKIES_QUESTION' => 'HELP_FAQ_LOGIN_DELETE_COOKIES_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_USERSETTINGS', + false, + array( + 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_QUESTION' => 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_ANSWER', + 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_QUESTION' => 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_ANSWER', + 'HELP_FAQ_USERSETTINGS_TIMEZONE_QUESTION' => 'HELP_FAQ_USERSETTINGS_TIMEZONE_ANSWER', + 'HELP_FAQ_USERSETTINGS_SERVERTIME_QUESTION' => 'HELP_FAQ_USERSETTINGS_SERVERTIME_ANSWER', + 'HELP_FAQ_USERSETTINGS_LANGUAGE_QUESTION' => 'HELP_FAQ_USERSETTINGS_LANGUAGE_ANSWER', + 'HELP_FAQ_USERSETTINGS_AVATAR_QUESTION' => 'HELP_FAQ_USERSETTINGS_AVATAR_ANSWER', + 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_QUESTION' => 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_ANSWER', + 'HELP_FAQ_USERSETTINGS_RANK_QUESTION' => 'HELP_FAQ_USERSETTINGS_RANK_ANSWER', + 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_QUESTION' => 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_POSTING', + false, + array( + 'HELP_FAQ_POSTING_CREATE_QUESTION' => 'HELP_FAQ_POSTING_CREATE_ANSWER', + 'HELP_FAQ_POSTING_EDIT_DELETE_QUESTION' => 'HELP_FAQ_POSTING_EDIT_DELETE_ANSWER', + 'HELP_FAQ_POSTING_SIGNATURE_QUESTION' => 'HELP_FAQ_POSTING_SIGNATURE_ANSWER', + 'HELP_FAQ_POSTING_POLL_CREATE_QUESTION' => 'HELP_FAQ_POSTING_POLL_CREATE_ANSWER', + 'HELP_FAQ_POSTING_POLL_ADD_QUESTION' => 'HELP_FAQ_POSTING_POLL_ADD_ANSWER', + 'HELP_FAQ_POSTING_POLL_EDIT_QUESTION' => 'HELP_FAQ_POSTING_POLL_EDIT_ANSWER', + 'HELP_FAQ_POSTING_FORUM_RESTRICTED_QUESTION' => 'HELP_FAQ_POSTING_FORUM_RESTRICTED_ANSWER', + 'HELP_FAQ_POSTING_NO_ATTACHMENTS_QUESTION' => 'HELP_FAQ_POSTING_NO_ATTACHMENTS_ANSWER', + 'HELP_FAQ_POSTING_WARNING_QUESTION' => 'HELP_FAQ_POSTING_WARNING_ANSWER', + 'HELP_FAQ_POSTING_REPORT_QUESTION' => 'HELP_FAQ_POSTING_REPORT_ANSWER', + 'HELP_FAQ_POSTING_DRAFT_QUESTION' => 'HELP_FAQ_POSTING_DRAFT_ANSWER', + 'HELP_FAQ_POSTING_QUEUE_QUESTION' => 'HELP_FAQ_POSTING_QUEUE_ANSWER', + 'HELP_FAQ_POSTING_BUMP_QUESTION' => 'HELP_FAQ_POSTING_BUMP_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_FORMATTING', + false, + array( + 'HELP_FAQ_FORMATTING_BBOCDE_QUESTION' => 'HELP_FAQ_FORMATTING_BBOCDE_ANSWER', + 'HELP_FAQ_FORMATTING_HTML_QUESTION' => 'HELP_FAQ_FORMATTING_HTML_ANSWER', + 'HELP_FAQ_FORMATTING_SMILIES_QUESTION' => 'HELP_FAQ_FORMATTING_SMILIES_ANSWER', + 'HELP_FAQ_FORMATTING_IMAGES_QUESTION' => 'HELP_FAQ_FORMATTING_IMAGES_ANSWER', + 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_QUESTION' => 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_ANSWER', + 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_QUESTION' => 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_ANSWER', + 'HELP_FAQ_FORMATTING_STICKIES_QUESTION' => 'HELP_FAQ_FORMATTING_STICKIES_ANSWER', + 'HELP_FAQ_FORMATTING_LOCKED_QUESTION' => 'HELP_FAQ_FORMATTING_LOCKED_ANSWER', + 'HELP_FAQ_FORMATTING_ICONS_QUESTION' => 'HELP_FAQ_FORMATTING_ICONS_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_GROUPS', + true, + array( + 'HELP_FAQ_GROUPS_ADMINISTRATORS_QUESTION' => 'HELP_FAQ_GROUPS_ADMINISTRATORS_ANSWER', + 'HELP_FAQ_GROUPS_MODERATORS_QUESTION' => 'HELP_FAQ_GROUPS_MODERATORS_ANSWER', + 'HELP_FAQ_GROUPS_USERGROUPS_QUESTION' => 'HELP_FAQ_GROUPS_USERGROUPS_ANSWER', + 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_QUESTION' => 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_ANSWER', + 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_QUESTION' => 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_ANSWER', + 'HELP_FAQ_GROUPS_COLORS_QUESTION' => 'HELP_FAQ_GROUPS_COLORS_ANSWER', + 'HELP_FAQ_GROUPS_DEFAULT_QUESTION' => 'HELP_FAQ_GROUPS_DEFAULT_ANSWER', + 'HELP_FAQ_GROUPS_TEAM_QUESTION' => 'HELP_FAQ_GROUPS_TEAM_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_PMS', + false, + array( + 'HELP_FAQ_PMS_CANNOT_SEND_QUESTION' => 'HELP_FAQ_PMS_CANNOT_SEND_ANSWER', + 'HELP_FAQ_PMS_UNWANTED_QUESTION' => 'HELP_FAQ_PMS_UNWANTED_ANSWER', + 'HELP_FAQ_PMS_SPAM_QUESTION' => 'HELP_FAQ_PMS_SPAM_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_FRIENDS', + false, + array( + 'HELP_FAQ_FRIENDS_BASIC_QUESTION' => 'HELP_FAQ_FRIENDS_BASIC_ANSWER', + 'HELP_FAQ_FRIENDS_MANAGE_QUESTION' => 'HELP_FAQ_FRIENDS_MANAGE_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_SEARCH', + false, + array( + 'HELP_FAQ_SEARCH_FORUM_QUESTION' => 'HELP_FAQ_SEARCH_FORUM_ANSWER', + 'HELP_FAQ_SEARCH_NO_RESULT_QUESTION' => 'HELP_FAQ_SEARCH_NO_RESULT_ANSWER', + 'HELP_FAQ_SEARCH_BLANK_QUESTION' => 'HELP_FAQ_SEARCH_BLANK_ANSWER', + 'HELP_FAQ_SEARCH_MEMBERS_QUESTION' => 'HELP_FAQ_SEARCH_MEMBERS_ANSWER', + 'HELP_FAQ_SEARCH_OWN_QUESTION' => 'HELP_FAQ_SEARCH_OWN_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_BOOKMARKS', + false, + array( + 'HELP_FAQ_BOOKMARKS_DIFFERENCE_QUESTION' => 'HELP_FAQ_BOOKMARKS_DIFFERENCE_ANSWER', + 'HELP_FAQ_BOOKMARKS_TOPIC_QUESTION' => 'HELP_FAQ_BOOKMARKS_TOPIC_ANSWER', + 'HELP_FAQ_BOOKMARKS_FORUM_QUESTION' => 'HELP_FAQ_BOOKMARKS_FORUM_ANSWER', + 'HELP_FAQ_BOOKMARKS_REMOVE_QUESTION' => 'HELP_FAQ_BOOKMARKS_REMOVE_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_ATTACHMENTS', + false, + array( + 'HELP_FAQ_ATTACHMENTS_ALLOWED_QUESTION' => 'HELP_FAQ_ATTACHMENTS_ALLOWED_ANSWER', + 'HELP_FAQ_ATTACHMENTS_OWN_QUESTION' => 'HELP_FAQ_ATTACHMENTS_OWN_ANSWER', + ) + ); + $this->manager->add_block( + 'HELP_FAQ_BLOCK_ISSUES', + false, + array( + 'HELP_FAQ_ISSUES_WHOIS_PHPBB_QUESTION' => 'HELP_FAQ_ISSUES_WHOIS_PHPBB_ANSWER', + 'HELP_FAQ_ISSUES_FEATURE_QUESTION' => 'HELP_FAQ_ISSUES_FEATURE_ANSWER', + 'HELP_FAQ_ISSUES_LEGAL_QUESTION' => 'HELP_FAQ_ISSUES_LEGAL_ANSWER', + 'HELP_FAQ_ISSUES_ADMIN_QUESTION' => 'HELP_FAQ_ISSUES_ADMIN_ANSWER', + ) + ); + + return $this->language->lang('FAQ_EXPLAIN'); + } +} diff --git a/phpBB/posting.php b/phpBB/posting.php index 2d01922c80..fd09f5e464 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1743,7 +1743,7 @@ $page_data = array( 'USERNAME' => ((!$preview && $mode != 'quote') || $preview) ? $post_data['username'] : '', 'SUBJECT' => $post_data['post_subject'], 'MESSAGE' => $post_data['post_text'], - 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), + 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '', ''), 'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], diff --git a/phpBB/viewonline.php b/phpBB/viewonline.php index 7bd9d07033..2f58646722 100644 --- a/phpBB/viewonline.php +++ b/phpBB/viewonline.php @@ -376,7 +376,7 @@ while ($row = $db->sql_fetchrow($result)) $row['session_page'] === 'app.' . $phpEx . '/help/bbcode') { $location = $user->lang['VIEWING_FAQ']; - $location_url = $controller_helper->route('phpbb_help_controller', array('mode' => 'faq')); + $location_url = $controller_helper->route('phpbb_help_faq_controller'); } break; } From f6c246f8899edb480c7347cb43e2cbdc96c80d17 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 16 May 2015 23:08:42 +0200 Subject: [PATCH 0289/1676] [ticket/13844] Add a functional test that browses the help pages PHPBB3-13844 --- tests/functional/browse_test.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/functional/browse_test.php b/tests/functional/browse_test.php index b9e74a280f..4f28879687 100644 --- a/tests/functional/browse_test.php +++ b/tests/functional/browse_test.php @@ -34,6 +34,18 @@ class phpbb_functional_browse_test extends phpbb_functional_test_case $this->assertGreaterThan(0, $crawler->filter('.postbody')->count()); } + public function test_help_faq() + { + $crawler = self::request('GET', 'app.php/help/faq'); + $this->assertGreaterThan(0, $crawler->filter('h2.faq-title')->count()); + } + + public function test_help_bbcode() + { + $crawler = self::request('GET', 'app.php/help/bbcode'); + $this->assertGreaterThan(0, $crawler->filter('h2.faq-title')->count()); + } + public function test_feed() { $crawler = self::request('GET', 'feed.php', array(), false); From 80be642a0b77d400dadce7a8a30c50d32c27bf1f Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 16 May 2015 23:13:50 +0200 Subject: [PATCH 0290/1676] [ticket/13844] Fix language file so the tests pass PHPBB3-13844 --- phpBB/develop/lang_migrate_help_lang.php | 4 ++-- phpBB/language/en/help/bbcode.php | 4 ++-- phpBB/language/en/help/faq.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/phpBB/develop/lang_migrate_help_lang.php b/phpBB/develop/lang_migrate_help_lang.php index d523493c83..d5a2573ee0 100644 --- a/phpBB/develop/lang_migrate_help_lang.php +++ b/phpBB/develop/lang_migrate_help_lang.php @@ -252,7 +252,7 @@ function write_help($help, array $lang) global $phpbb_root_path; $fp = fopen($phpbb_root_path . 'language/en/help/' . $help . '.php', 'wb'); fwrite($fp, get_language_file_header()); - fwrite($fp, '$lang = array(' . "\n"); + fwrite($fp, '$lang = array_merge($lang, array(' . "\n"); $last_key = ''; ksort($lang); @@ -270,7 +270,7 @@ function write_help($help, array $lang) $last_key = $key_start; } - fwrite($fp, ');' . "\n"); + fwrite($fp, '));' . "\n"); #fwrite($fp, $lang); fclose($fp); } diff --git a/phpBB/language/en/help/bbcode.php b/phpBB/language/en/help/bbcode.php index cfbba0b771..d3b36d8015 100644 --- a/phpBB/language/en/help/bbcode.php +++ b/phpBB/language/en/help/bbcode.php @@ -24,7 +24,7 @@ if (empty($lang) || !is_array($lang)) $lang = array(); } -$lang = array( +$lang = array_merge($lang, array( 'HELP_BBCODE_BLOCK_IMAGES' => 'Showing images in posts', 'HELP_BBCODE_BLOCK_INTRO' => 'Introduction', 'HELP_BBCODE_BLOCK_LINKS' => 'Creating Links', @@ -63,4 +63,4 @@ $lang = array( 'HELP_BBCODE_TEXT_COLOR_QUESTION' => 'How to change the text colour or size', 'HELP_BBCODE_TEXT_COMBINE_ANSWER' => 'Yes, of course you can, for example to get someones attention you may write:

              [size=200][color=red][b]LOOK AT ME![/b][/color][/size]

              this would output LOOK AT ME!

              We don’t recommend you output lots of text that looks like this though! Remember it is up to you, the poster, to ensure tags are closed correctly. For example the following is incorrect:

              [b][u]This is wrong[/b][/u]', 'HELP_BBCODE_TEXT_COMBINE_QUESTION' => 'Can I combine formatting tags?', -); +)); diff --git a/phpBB/language/en/help/faq.php b/phpBB/language/en/help/faq.php index fdb6f62aee..e59d950948 100644 --- a/phpBB/language/en/help/faq.php +++ b/phpBB/language/en/help/faq.php @@ -24,7 +24,7 @@ if (empty($lang) || !is_array($lang)) $lang = array(); } -$lang = array( +$lang = array_merge($lang, array( 'HELP_FAQ_ATTACHMENTS_ALLOWED_ANSWER' => 'Each board administrator can allow or disallow certain attachment types. If you are unsure what is allowed to be uploaded, contact the board administrator for assistance.', 'HELP_FAQ_ATTACHMENTS_ALLOWED_QUESTION' => 'What attachments are allowed on this board?', 'HELP_FAQ_ATTACHMENTS_OWN_ANSWER' => 'To find your list of attachments that you have uploaded, go to your User Control Panel and follow the links to the attachments section.', @@ -183,4 +183,4 @@ $lang = array( 'HELP_FAQ_USERSETTINGS_SERVERTIME_QUESTION' => 'I changed the timezone and the time is still wrong!', 'HELP_FAQ_USERSETTINGS_TIMEZONE_ANSWER' => 'It is possible the time displayed is from a timezone different from the one you are in. If this is the case, visit your User Control Panel and change your timezone to match your particular area, e.g. London, Paris, New York, Sydney, etc. Please note that changing the timezone, like most settings, can only be done by registered users. If you are not registered, this is a good time to do so.', 'HELP_FAQ_USERSETTINGS_TIMEZONE_QUESTION' => 'The times are not correct!', -); +)); From 8ce0a64a16aa9d1b8edcef684c528cf44bc39cc6 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 17 May 2015 21:18:17 +0200 Subject: [PATCH 0291/1676] [ticket/13844] Remove hacky code for the help array PHPBB3-13844 --- phpBB/phpbb/language/language.php | 7 +------ phpBB/phpbb/language/language_file_loader.php | 12 +++--------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/phpBB/phpbb/language/language.php b/phpBB/phpbb/language/language.php index 3298908365..b2b9f5ce12 100644 --- a/phpBB/phpbb/language/language.php +++ b/phpBB/phpbb/language/language.php @@ -83,10 +83,7 @@ class language // Set up default information $this->user_language = false; $this->default_language = false; - $this->lang = array( - // For BC with user::help array - '__help' => array(), - ); + $this->lang = array(); $this->loaded_language_sets = array( 'core' => array(), 'ext' => array(), @@ -155,8 +152,6 @@ class language /** * Add Language Items * - * Note: $use_help is assigned where needed (only use them to force inclusion). - * * Examples: * * $component = array('posting'); diff --git a/phpBB/phpbb/language/language_file_loader.php b/phpBB/phpbb/language/language_file_loader.php index 510a29279a..9862cfc3aa 100644 --- a/phpBB/phpbb/language/language_file_loader.php +++ b/phpBB/phpbb/language/language_file_loader.php @@ -154,10 +154,12 @@ class language_file_loader * * @return string Relative path to language file * - * @throws \phpbb\language\exception\language_file_not_exists When the path to the file cannot be resolved + * @throws \phpbb\language\exception\language_file_not_found When the path to the file cannot be resolved */ protected function get_language_file_path($path, $filename, $locales) { + $language_file_path = $filename; + // Language fallback logic foreach ($locales as $locale) { @@ -191,9 +193,6 @@ class language_file_loader */ protected function load_language_file($path, &$lang) { - // BC code for language files with help - $help = array(); - // Do not suppress error if in DEBUG mode if (defined('DEBUG')) { @@ -203,10 +202,5 @@ class language_file_loader { @include $path; } - - if (!empty($help)) - { - $lang['__help'] = array_merge($lang['__help'], $help); - } } } From 6dcc14bc5824b3ff74a3cd3acd574ae5e530d1c3 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 17 May 2015 21:45:18 +0200 Subject: [PATCH 0292/1676] [ticket/13844] Add unit tests for the help manager PHPBB3-13844 --- tests/help/manager_test.php | 183 ++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 tests/help/manager_test.php diff --git a/tests/help/manager_test.php b/tests/help/manager_test.php new file mode 100644 index 0000000000..aaf63194fa --- /dev/null +++ b/tests/help/manager_test.php @@ -0,0 +1,183 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_language_test extends phpbb_test_case +{ + /** @var \phpbb\help\manager */ + protected $manager; + /** @var \phpbb\template\template */ + protected $template; + /** @var \phpbb\language\language */ + protected $language; + + public function setUp() + { + $this->template = $this->getMockBuilder('\phpbb\template\template') + ->disableOriginalConstructor() + ->getMock(); + $this->language = $this->getMockBuilder('\phpbb\language\language') + ->disableOriginalConstructor() + ->getMock(); + + $this->manager = new \phpbb\help\manager( + $this->template, + $this->language + ); + } + + public function add_block_data() + { + return array( + array('abc', false, array(), false), + array('def', true, array(), true), + array( + 'abc', + false, + array( + 'question1' => 'answer1', + 'question2' => 'answer2', + 'question3' => 'answer3', + ), + false + ), + ); + } + + /** + * @dataProvider add_block_data + * + * @param string $block_name + * @param bool $switch + * @param array $questions + * @param bool $switch_expected + */ + public function test_add_block($block_name, $switch, $questions, $switch_expected) + { + $this->language->expects($this->at(0)) + ->method('lang') + ->with($block_name) + ->willReturn(strtoupper($block_name)); + $lang_call_count = 1; + foreach ($questions as $question => $answer) + { + $this->language->expects($this->at($lang_call_count)) + ->method('lang') + ->with($question) + ->willReturn(strtoupper($question)); + $lang_call_count++; + + $this->language->expects($this->at($lang_call_count)) + ->method('lang') + ->with($answer) + ->willReturn(strtoupper($answer)); + $lang_call_count++; + } + + $this->template->expects($this->at(0)) + ->method('assign_block_vars') + ->with('faq_block', array( + 'BLOCK_TITLE' => strtoupper($block_name), + 'SWITCH_COLUMN' => $switch_expected, + )); + $template_call_count = 1; + foreach ($questions as $question => $answer) + { + $this->template->expects($this->at($template_call_count)) + ->method('assign_block_vars') + ->with('faq_block.faq_row', array( + 'FAQ_QUESTION' => strtoupper($question), + 'FAQ_ANSWER' => strtoupper($answer), + )); + $template_call_count++; + } + + $this->manager->add_block($block_name, $switch, $questions); + + $this->assertEquals($switch_expected, $this->manager->switched_column()); + } + + public function add_question_data() + { + return array( + array('abc', false, false), + array('def', true, true), + ); + } + + /** + * @dataProvider add_question_data + * + * @param string $question + * @param string $answer + */ + public function test_add_question($question, $answer) + { + $this->language->expects($this->at(0)) + ->method('lang') + ->with($question) + ->willReturn(strtoupper($question)); + $this->language->expects($this->at(1)) + ->method('lang') + ->with($answer) + ->willReturn(strtoupper($answer)); + + $this->template->expects($this->once()) + ->method('assign_block_vars') + ->with('faq_block.faq_row', array( + 'FAQ_QUESTION' => strtoupper($question), + 'FAQ_ANSWER' => strtoupper($answer), + )); + + $this->manager->add_question($question, $answer); + } + + public function test_add_block_double_switch() + { + $block_name = 'abc'; + $switch_expected = true; + + $this->language->expects($this->at(0)) + ->method('lang') + ->with($block_name) + ->willReturn(strtoupper($block_name)); + + $this->template->expects($this->at(0)) + ->method('assign_block_vars') + ->with('faq_block', array( + 'BLOCK_TITLE' => strtoupper($block_name), + 'SWITCH_COLUMN' => $switch_expected, + )); + + $this->manager->add_block($block_name, true); + $this->assertTrue($this->manager->switched_column()); + + // Add a second block with switch + $block_name = 'def'; + $switch_expected = false; + + $this->language->expects($this->at(0)) + ->method('lang') + ->with($block_name) + ->willReturn(strtoupper($block_name)); + + $this->template->expects($this->at(0)) + ->method('assign_block_vars') + ->with('faq_block', array( + 'BLOCK_TITLE' => strtoupper($block_name), + 'SWITCH_COLUMN' => $switch_expected, + )); + + $this->manager->add_block($block_name, true); + $this->assertTrue($this->manager->switched_column()); + } +} From deadc0665298f18a937fc959da449e9098873c0b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 30 Apr 2015 23:01:28 +0200 Subject: [PATCH 0293/1676] [ticket/13801] Removed user dependency from text_formatter.s9e.parser PHPBB3-13801 --- .../container/services_text_formatter.yml | 1 - phpBB/includes/message_parser.php | 4 +++ phpBB/phpbb/textformatter/s9e/parser.php | 27 ++++++------------- .../phpbb_test_case_helpers.php | 2 -- tests/text_formatter/s9e/parser_test.php | 10 +------ 5 files changed, 13 insertions(+), 31 deletions(-) diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index 972be31b31..20436f0f64 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -41,7 +41,6 @@ services: arguments: - @cache.driver - %text_formatter.cache.parser.key% - - @user - @text_formatter.s9e.factory - @dispatcher diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 9fe598d7fb..3edc7fe1c6 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1254,6 +1254,10 @@ class parse_message extends bbcode_firstpass $errors = $parser->get_errors(); if ($errors) { + foreach ($errors as $i => $args) + { + $errors[$i] = call_user_func_array(array($user, 'lang'), $args); + } $this->warn_msg = array_merge($this->warn_msg, $errors); return (!$update_this_message) ? $return_message : $this->warn_msg; diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index e46a0578d2..178669d84f 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -31,21 +31,15 @@ class parser implements \phpbb\textformatter\parser_interface */ protected $parser; - /** - * @var \phpbb\user User object, used for translating errors - */ - protected $user; - /** * Constructor * * @param \phpbb\cache\driver_interface $cache * @param string $key Cache key - * @param \phpbb\user $user * @param factory $factory * @param \phpbb\event\dispatcher_interface $dispatcher */ - public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, factory $factory, \phpbb\event\dispatcher_interface $dispatcher) + public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, factory $factory, \phpbb\event\dispatcher_interface $dispatcher) { $parser = $cache->get($key); if (!$parser) @@ -56,24 +50,20 @@ class parser implements \phpbb\textformatter\parser_interface $this->dispatcher = $dispatcher; $this->parser = $parser; - $this->user = $user; $parser = $this; /** * Configure the parser service * * Can be used to: - * - toggle features according to the user's preferences, - * - toggle BBCodes according to the user's permissions, * - register variables or custom parsers in the s9e\TextFormatter * - configure the s9e\TextFormatter parser * * @event core.text_formatter_s9e_parser_setup * @var \phpbb\textformatter\s9e\parser parser This parser service - * @var \phpbb\user user Current user * @since 3.2.0-a1 */ - $vars = array('parser', 'user'); + $vars = array('parser'); extract($dispatcher->trigger_event('core.text_formatter_s9e_parser_setup', compact($vars))); } @@ -202,7 +192,6 @@ class parser implements \phpbb\textformatter\parser_interface public function get_errors() { $errors = array(); - foreach ($this->parser->getLogger()->get() as $entry) { list($type, $msg, $context) = $entry; @@ -211,29 +200,29 @@ class parser implements \phpbb\textformatter\parser_interface { if ($context['tagName'] === 'E') { - $errors[] = $this->user->lang('TOO_MANY_SMILIES', $context['tagLimit']); + $errors[] = array('TOO_MANY_SMILIES', $context['tagLimit']); } else if ($context['tagName'] === 'URL') { - $errors[] = $this->user->lang('TOO_MANY_URLS', $context['tagLimit']); + $errors[] = array('TOO_MANY_URLS', $context['tagLimit']); } } else if ($msg === 'MAX_FONT_SIZE_EXCEEDED') { - $errors[] = $this->user->lang($msg, $context['max_size']); + $errors[] = array($msg, $context['max_size']); } else if (preg_match('/^MAX_(?:FLASH|IMG)_(HEIGHT|WIDTH)_EXCEEDED$/D', $msg, $m)) { - $errors[] = $this->user->lang($msg, $context['max_' . strtolower($m[1])]); + $errors[] = array($msg, $context['max_' . strtolower($m[1])]); } else if ($msg === 'Tag is disabled') { $name = strtolower($context['tag']->getName()); - $errors[] = $this->user->lang('UNAUTHORISED_BBCODE', '[' . $name . ']'); + $errors[] = array('UNAUTHORISED_BBCODE', '[' . $name . ']'); } else if ($msg === 'UNABLE_GET_IMAGE_SIZE') { - $errors[] = $this->user->lang($msg); + $errors[] = array($msg); } } diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 685014d3e4..210cda9a94 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -494,11 +494,9 @@ class phpbb_test_case_helpers $parser = new \phpbb\textformatter\s9e\parser( $cache, $cache_key_parser, - $user, $factory, $dispatcher ); - $container->set('text_formatter.parser', $parser); $container->set('text_formatter.s9e.parser', $parser); diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php index 71966f9d36..3b72e713e1 100644 --- a/tests/text_formatter/s9e/parser_test.php +++ b/tests/text_formatter/s9e/parser_test.php @@ -35,7 +35,6 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $parser = new \phpbb\textformatter\s9e\parser( $cache, '_foo_parser', - $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), $factory, new phpbb_mock_event_dispatcher ); @@ -63,7 +62,6 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $parser = new \phpbb\textformatter\s9e\parser( $cache, '_foo_parser', - $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), $factory, new phpbb_mock_event_dispatcher ); @@ -92,7 +90,6 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $parser = new \phpbb\textformatter\s9e\parser( new phpbb_mock_cache, '_foo_parser', - $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), $factory, new phpbb_mock_event_dispatcher ); @@ -126,7 +123,6 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $parser = new \phpbb\textformatter\s9e\parser( $cache, '_foo_parser', - $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), $factory, new phpbb_mock_event_dispatcher ); @@ -191,7 +187,6 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case new \phpbb\textformatter\s9e\parser( $container->get('cache.driver'), '_foo_parser', - $container->get('user'), $container->get('text_formatter.s9e.factory'), $dispatcher ); @@ -200,9 +195,7 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case public function setup_event_callback($vars) { return isset($vars['parser']) - && $vars['parser'] instanceof \phpbb\textformatter\s9e\parser - && isset($vars['user']) - && $vars['user'] instanceof \phpbb\user; + && $vars['parser'] instanceof \phpbb\textformatter\s9e\parser; } /** @@ -236,7 +229,6 @@ class phpbb_textformatter_s9e_parser_test extends phpbb_test_case $parser = new \phpbb\textformatter\s9e\parser( $container->get('cache.driver'), '_foo_parser', - $container->get('user'), $container->get('text_formatter.s9e.factory'), $dispatcher ); From 7b552152b416d9f0c2e873f6f70c4d3cec575ea6 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 8 May 2015 14:51:46 +0200 Subject: [PATCH 0294/1676] [ticket/13801] Updated comments for clarity PHPBB3-13801 --- phpBB/includes/message_parser.php | 1 + phpBB/phpbb/textformatter/parser_interface.php | 3 ++- phpBB/phpbb/textformatter/s9e/parser.php | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 3edc7fe1c6..496a7885f1 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1256,6 +1256,7 @@ class parse_message extends bbcode_firstpass { foreach ($errors as $i => $args) { + // Translate each error with $user->lang() $errors[$i] = call_user_func_array(array($user, 'lang'), $args); } $this->warn_msg = array_merge($this->warn_msg, $errors); diff --git a/phpBB/phpbb/textformatter/parser_interface.php b/phpBB/phpbb/textformatter/parser_interface.php index 3cb9f8e977..ad611fb5b4 100644 --- a/phpBB/phpbb/textformatter/parser_interface.php +++ b/phpBB/phpbb/textformatter/parser_interface.php @@ -82,7 +82,8 @@ interface parser_interface /** * Get the list of errors that were generated during last parsing * - * @return array + * @return array[] Array of arrays. Each array contains a lang string at index 0 plus any number + * of optional parameters */ public function get_errors(); diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 178669d84f..ee033f6d21 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -186,7 +186,7 @@ class parser implements \phpbb\textformatter\parser_interface /** * {@inheritdoc} * - * This will translate the log entries found in s9e\TextFormatter's logger into phpBB error + * This will convert the log entries found in s9e\TextFormatter's logger into phpBB error * messages */ public function get_errors() From 5772e06b1aace1d5fbef263217e71ad10347364d Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 17 May 2015 14:09:02 +0200 Subject: [PATCH 0295/1676] [ticket/13801] Updated event description [ci skip] PHPBB3-13801 --- phpBB/phpbb/textformatter/s9e/parser.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index ee033f6d21..b7d0b2b90b 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -56,8 +56,9 @@ class parser implements \phpbb\textformatter\parser_interface * Configure the parser service * * Can be used to: - * - register variables or custom parsers in the s9e\TextFormatter - * - configure the s9e\TextFormatter parser + * - toggle features or BBCodes + * - register variables or custom parsers in the s9e\TextFormatter parser + * - configure the s9e\TextFormatter parser's runtime settings * * @event core.text_formatter_s9e_parser_setup * @var \phpbb\textformatter\s9e\parser parser This parser service From c1777f481101c0a311939f83f2afd38a0c09e394 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 18 May 2015 03:57:48 +0200 Subject: [PATCH 0296/1676] [ticket/11530] Remove extra quotes when depth limit is exceeded PHPBB3-11530 --- phpBB/includes/message_parser.php | 10 ++++ phpBB/posting.php | 13 ++++- tests/functional/posting_test.php | 81 +++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 9fe598d7fb..f018d735a7 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1250,6 +1250,16 @@ class parse_message extends bbcode_firstpass return (!$update_this_message) ? $return_message : $this->warn_msg; } + // Remove quotes that are nested too deep + if ($config['max_quote_depth'] > 0) + { + $this->message = $phpbb_container->get('text_formatter.utils')->remove_bbcode( + $this->message, + 'quote', + $config['max_quote_depth'] + ); + } + // Check for errors $errors = $parser->get_errors(); if ($errors) diff --git a/phpBB/posting.php b/phpBB/posting.php index 2d01922c80..a4fb4d7a8d 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1578,11 +1578,22 @@ if (!sizeof($error) && $preview) } } +// Remove quotes that would become nested too deep before decoding the text +$generate_quote = ($mode == 'quote' && !$submit && !$preview && !$refresh); +if ($generate_quote && $config['max_quote_depth'] > 0 && preg_match('#^<[rt][ >]#', $message_parser->message)) +{ + $message_parser->message = $phpbb_container->get('text_formatter.utils')->remove_bbcode( + $message_parser->message, + 'quote', + $config['max_quote_depth'] - 1 + ); +} + // Decode text for message display $post_data['bbcode_uid'] = ($mode == 'quote' && !$preview && !$refresh && !sizeof($error)) ? $post_data['bbcode_uid'] : $message_parser->bbcode_uid; $message_parser->decode_message($post_data['bbcode_uid']); -if ($mode == 'quote' && !$submit && !$preview && !$refresh) +if ($generate_quote) { if ($config['allow_bbcode']) { diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 7acf375c5d..080ada5bb0 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -71,4 +71,85 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); $this->assertContains('😀', $crawler->text()); } + + /** + * @testdox max_quote_depth is applied to the text populating the posting form + */ + public function test_quote_depth_form() + { + $text = '0[quote]1[quote]2[/quote]1[/quote]0'; + $expected = array( + 0 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]', + 1 => '[quote="admin"]00[/quote]', + 2 => '[quote="admin"]0[quote]11[/quote]0[/quote]', + 3 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]', + ); + + $this->login(); + $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); + $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); + $quote_url = "posting.php?mode=quote&f=2&t={$post['topic_id']}&p={$post['post_id']}&sid={$this->sid}"; + + $this->admin_login(); + foreach ($expected as $quote_depth => $expected_text) + { + $this->set_quote_depth($quote_depth); + $crawler = self::request('GET', $quote_url); + $this->assertContains($expected_text, $crawler->filter('textarea#message')->text()); + } + } + + /** + * @testdox max_quote_depth is applied to the text populating the posting form + */ + public function test_quote_depth_submit() + { + $text = 'depth:0[quote]depth:1[quote]depth:2[quote]depth:3[/quote][/quote][/quote]'; + $contains = array( + 0 => array('depth:0', 'depth:1', 'depth:2', 'depth:3'), + 1 => array('depth:0', 'depth:1'), + 2 => array('depth:0', 'depth:1', 'depth:2'), + 3 => array('depth:0', 'depth:1', 'depth:2', 'depth:3'), + ); + $not_contains = array( + 0 => array(), + 1 => array('depth:2', 'depth:3'), + 2 => array('depth:3'), + 3 => array(), + ); + + $this->login(); + $this->admin_login(); + $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); + + for ($quote_depth = 0; $quote_depth <= 2; ++$quote_depth) + { + $this->set_quote_depth($quote_depth); + + $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); + $url = "viewtopic.php?p={$post['post_id']}&sid={$this->sid}"; + + $crawler = self::request('GET', $url); + $text_content = $crawler->filter('#p' . $post['post_id'])->text(); + foreach ($contains[$quote_depth] as $contains_text) + { + $this->assertContains($contains_text, $text_content); + } + foreach ($not_contains[$quote_depth] as $not_contains_text) + { + $this->assertNotContains($not_contains_text, $text_content); + } + } + } + + protected function set_quote_depth($depth) + { + $crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post'); + $form = $crawler->selectButton('Submit')->form(); + $values = $form->getValues(); + $values['config[max_quote_depth]'] = $depth; + $form->setValues($values); + $crawler = self::submit($form); + $this->assertEquals(1, $crawler->filter('.successbox')->count()); + } } From e67c5850e450d26b7cfeb1e9372a37afa2a7ae1d Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 18 May 2015 06:49:53 +0200 Subject: [PATCH 0297/1676] [ticket/11530] Updated s9e\TextFormatter PHPBB3-11530 --- phpBB/composer.lock | 112 ++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 872509884c..dc7608b37e 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "d5368b75d221b5573b30307cb2f25f3b", + "hash": "c14bcbf5a6c4fd121492568aa3654c07", "packages": [ { "name": "lusitanian/oauth", @@ -220,12 +220,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "31fe627a4a82d41098a2db8036287c0693c79f13" + "reference": "29c5959f4425934a53b6fdb42760d719b95a6e82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/31fe627a4a82d41098a2db8036287c0693c79f13", - "reference": "31fe627a4a82d41098a2db8036287c0693c79f13", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/29c5959f4425934a53b6fdb42760d719b95a6e82", + "reference": "29c5959f4425934a53b6fdb42760d719b95a6e82", "shasum": "" }, "require": { @@ -270,7 +270,7 @@ "parser", "shortcodes" ], - "time": "2015-04-25 20:58:33" + "time": "2015-05-18 04:48:32" }, { "name": "symfony/config", @@ -612,6 +612,56 @@ "homepage": "http://symfony.com", "time": "2015-04-10 08:56:33" }, + { + "name": "symfony/finder", + "version": "2.8.x-dev", + "target-dir": "Symfony/Component/Finder", + "source": { + "type": "git", + "url": "https://github.com/symfony/Finder.git", + "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Finder/zipball/ad159e0da47e9ffe719bafdc004159ad6e395567", + "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Finder\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Finder Component", + "homepage": "http://symfony.com", + "time": "2015-04-10 08:56:33" + }, { "name": "symfony/http-foundation", "version": "2.8.x-dev", @@ -2571,56 +2621,6 @@ "homepage": "http://symfony.com", "time": "2015-04-10 08:56:33" }, - { - "name": "symfony/finder", - "version": "2.8.x-dev", - "target-dir": "Symfony/Component/Finder", - "source": { - "type": "git", - "url": "https://github.com/symfony/Finder.git", - "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/ad159e0da47e9ffe719bafdc004159ad6e395567", - "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Finder\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony Finder Component", - "homepage": "http://symfony.com", - "time": "2015-04-10 08:56:33" - }, { "name": "symfony/process", "version": "2.8.x-dev", @@ -2681,6 +2681,7 @@ "symfony/dependency-injection": 20, "symfony/event-dispatcher": 20, "symfony/filesystem": 20, + "symfony/finder": 20, "symfony/http-kernel": 20, "symfony/routing": 20, "symfony/security-core": 20, @@ -2691,7 +2692,6 @@ "symfony/css-selector": 20, "symfony/debug": 20, "symfony/dom-crawler": 20, - "symfony/finder": 20, "symfony/http-foundation": 20, "symfony/process": 20 }, From 71f5c9c32715b634d315f79aa11df07be2a9676c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 18 May 2015 17:07:02 +0200 Subject: [PATCH 0298/1676] [ticket/13832] Use preg_replace_callback instead of /e modifier PHPBB3-13832 --- phpBB/includes/acp/acp_bbcodes.php | 4 +++- phpBB/includes/bbcode.php | 22 ++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index d451b4d899..9c00e89713 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -491,7 +491,9 @@ class acp_bbcodes if (preg_match_all('/(?lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl); + $bbcode_tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) { + if (!empty($user->lang[$match['1']])) + { + return $user->lang[$match['1']]; + } + else + { + return ucwords(strtolower(str_replace('_', ' ', $match['1']))); + } + }, $bbcode_tpl); if (!empty($rowset[$bbcode_id]['second_pass_replace'])) { @@ -509,7 +518,16 @@ class bbcode 'email' => array('{EMAIL}' => '$1', '{DESCRIPTION}' => '$2') ); - $tpl = preg_replace('/{L_([A-Z0-9_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $tpl); + $tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) { + if (!empty($user->lang[$match['1']])) + { + return $user->lang[$match['1']]; + } + else + { + return ucwords(strtolower(str_replace('_', ' ', $match['1']))); + } + }, $tpl); if (!empty($replacements[$tpl_name])) { From 1076b562dde3cd05351baec0cc01e1ff35c7317a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 18 May 2015 17:48:00 +0200 Subject: [PATCH 0299/1676] [ticket/13832] Do not use e modifier in message_parser PHPBB3-13832 --- phpBB/includes/message_parser.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 9fe598d7fb..0d6960a197 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -744,7 +744,9 @@ class bbcode_firstpass extends bbcode } // To let the parser not catch tokens within quote_username quotes we encode them before we start this... - $in = preg_replace('#quote="(.*?)"\]#ie', "'quote="' . str_replace(array('[', ']', '\\\"'), array('[', ']', '\"'), '\$1') . '"]'", $in); + $in = preg_replace_callback('#quote="(.*?)"\]#i', function ($match) { + return 'quote="' . str_replace(array('[', ']', '\\\"'), array('[', ']', '\"'), $match[1]) . '"]'; + }, $in); $tok = ']'; $out = '['; @@ -1518,7 +1520,9 @@ class parse_message extends bbcode_firstpass ); $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data); - $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message); + $this->message = preg_replace_callback('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#', function ($match) { + return '[attachment='.($match[1] + 1).']' . $match[2] . '[/attachment]'; + }, $this->message); $this->filename_data['filecomment'] = ''; @@ -1586,7 +1590,9 @@ class parse_message extends bbcode_firstpass } unset($this->attachment_data[$index]); - $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "(\\1 == \$index) ? '' : ((\\1 > \$index) ? '[attachment=' . (\\1 - 1) . ']\\2[/attachment]' : '\\0')", $this->message); + $this->message = preg_replace_callback('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#', function ($match) use($index) { + return ($match[1] == $index) ? '' : (($match[1] > $index) ? '[attachment=' . ($match[1] - 1) . ']' . $match[2] . '[/attachment]' : $match[0]); + }, $this->message); // Reindex Array $this->attachment_data = array_values($this->attachment_data); @@ -1630,7 +1636,9 @@ class parse_message extends bbcode_firstpass ); $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data); - $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message); + $this->message = preg_replace_callback('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#', function ($match) { + return '[attachment=' . ($match[1] + 1) . ']' . $match[2] . '[/attachment]'; + }, $this->message); $this->filename_data['filecomment'] = ''; if (isset($this->plupload) && $this->plupload->is_active()) From 8a5c0965d34cfd7027983dd74c33f45d737012d3 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 18 May 2015 19:02:49 +0200 Subject: [PATCH 0300/1676] [ticket/13832] Allow callables for matching bbcodes PHPBB3-13832 --- phpBB/includes/message_parser.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 0d6960a197..0528d0b413 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -83,7 +83,14 @@ class bbcode_firstpass extends bbcode // it should not demand recompilation if (preg_match($regexp, $this->message)) { - $this->message = preg_replace($regexp, $replacement, $this->message); + if (is_callable($replacement)) + { + $this->message = preg_replace_callback($regexp, $replacement, $this->message); + } + else + { + $this->message = preg_replace($regexp, $replacement, $this->message); + } $bitfield->set($bbcode_data['bbcode_id']); } } From 2911c0168331a8f23dd8836d092d5e3fe6cac070 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 18 May 2015 19:03:25 +0200 Subject: [PATCH 0301/1676] [ticket/13832] Remove e modifier from bold bbcode PHPBB3-13832 --- phpBB/includes/message_parser.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 0528d0b413..e4a89b62ca 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -126,10 +126,12 @@ class bbcode_firstpass extends bbcode */ function bbcode_init($allow_custom_bbcode = true) { - global $phpbb_dispatcher; + global $phpbb_dispatcher, $bbcode_class; static $rowset; + $bbcode_class = $this; + // This array holds all bbcode data. BBCodes will be processed in this // order, so it is important to keep [code] in first position and // [quote] in second position. @@ -139,7 +141,7 @@ class bbcode_firstpass extends bbcode 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uise' => "\$this->bbcode_code('\$1', '\$2')")), 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#uise' => "\$this->bbcode_quote('\$0')")), 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uise' => "\$this->bbcode_attachment('\$1', '\$2')")), - 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#uise' => "\$this->bbcode_strong('\$1')")), + 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_strong($match[1]); })), 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#uise' => "\$this->bbcode_italic('\$1')")), 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](?(1)((?s).*(?-s))|(.*))\[/url\]#uiUe' => "\$this->validate_url('\$2', ('\$3') ? '\$3' : '\$4')")), 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#uiUe' => "\$this->bbcode_img('\$1')")), From 1494c54803b3043ded965e9040bbd9116e4b6a53 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 18 May 2015 21:43:25 +0200 Subject: [PATCH 0302/1676] [ticket/13832] Do not use e modifier for bbcodes in message_parser PHPBB3-13832 --- phpBB/includes/message_parser.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index e4a89b62ca..06c3c2c9c2 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -138,19 +138,19 @@ class bbcode_firstpass extends bbcode // To parse multiline URL we enable dotall option setting only for URL text // but not for link itself, thus [url][/url] is not affected. $this->bbcodes = array( - 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uise' => "\$this->bbcode_code('\$1', '\$2')")), - 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#uise' => "\$this->bbcode_quote('\$0')")), - 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uise' => "\$this->bbcode_attachment('\$1', '\$2')")), + 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_code($match[1], $match[2]); })), + 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_quote($match[0]); })), + 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_attachment($match[1], $match[2]); })), 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_strong($match[1]); })), - 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#uise' => "\$this->bbcode_italic('\$1')")), - 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](?(1)((?s).*(?-s))|(.*))\[/url\]#uiUe' => "\$this->validate_url('\$2', ('\$3') ? '\$3' : '\$4')")), - 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#uiUe' => "\$this->bbcode_img('\$1')")), - 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#uise' => "\$this->bbcode_size('\$1', '\$2')")), - 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!uise' => "\$this->bbcode_color('\$1', '\$2')")), - 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#uise' => "\$this->bbcode_underline('\$1')")), - 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#uise' => "\$this->bbcode_parse_list('\$0')")), - 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#uise' => "\$this->validate_email('\$1', '\$2')")), - 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#uie' => "\$this->bbcode_flash('\$1', '\$2', '\$3')")) + 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_italic($match[1]); })), + 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](?(1)((?s).*(?-s))|(.*))\[/url\]#uiU' => function ($match) { global $bbcode_class; return $bbcode_class->validate_url($match[2], ($match[3]) ? $match[3] : $match[4]); })), + 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#uiU' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_img($match[1]); })), + 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_size($match[1], $match[2]); })), + 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_color($match[1], $match[2]); })), + 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_underline($match[1]); })), + 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_parse_list($match[0]); })), + 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->validate_email($match[1], $match[2]); })), + 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#ui' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_flash($match[1], $match[2], $match[3]); })) ); // Zero the parsed items array From 2cc78b2c3b4e918710478f861c1441a3e28c9ad4 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 19 May 2015 11:16:37 +0200 Subject: [PATCH 0303/1676] [ticket/11530] Fixed test description [ci skip] PHPBB3-11530 --- tests/functional/posting_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 080ada5bb0..5c083aef37 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -100,7 +100,7 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case } /** - * @testdox max_quote_depth is applied to the text populating the posting form + * @testdox max_quote_depth is applied to the submitted text */ public function test_quote_depth_submit() { From 579658461115de68aa05c34b0dfd6744a40d0f10 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 19 May 2015 14:15:37 +0200 Subject: [PATCH 0304/1676] [ticket/13832] Fix code sniffer errors in message_parser.php PHPBB3-13832 --- phpBB/includes/message_parser.php | 78 +++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 13 deletions(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 06c3c2c9c2..d40c71c2a9 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -138,19 +138,71 @@ class bbcode_firstpass extends bbcode // To parse multiline URL we enable dotall option setting only for URL text // but not for link itself, thus [url][/url] is not affected. $this->bbcodes = array( - 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_code($match[1], $match[2]); })), - 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_quote($match[0]); })), - 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_attachment($match[1], $match[2]); })), - 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_strong($match[1]); })), - 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_italic($match[1]); })), - 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](?(1)((?s).*(?-s))|(.*))\[/url\]#uiU' => function ($match) { global $bbcode_class; return $bbcode_class->validate_url($match[2], ($match[3]) ? $match[3] : $match[4]); })), - 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#uiU' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_img($match[1]); })), - 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_size($match[1], $match[2]); })), - 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_color($match[1], $match[2]); })), - 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_underline($match[1]); })), - 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_parse_list($match[0]); })), - 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#uis' => function ($match) { global $bbcode_class; return $bbcode_class->validate_email($match[1], $match[2]); })), - 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#ui' => function ($match) { global $bbcode_class; return $bbcode_class->bbcode_flash($match[1], $match[2], $match[3]); })) + 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_code($match[1], $match[2]); + } + )), + 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_quote($match[0]); + } + )), + 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_attachment($match[1], $match[2]); + } + )), + 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_strong($match[1]); + } + )), + 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_italic($match[1]); + } + )), + 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](?(1)((?s).*(?-s))|(.*))\[/url\]#uiU' => function ($match) use($bbcode_class) + { + return $bbcode_class->validate_url($match[2], ($match[3]) ? $match[3] : $match[4]); + } + )), + 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#uiU' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_img($match[1]); + } + )), + 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_size($match[1], $match[2]); + } + )), + 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_color($match[1], $match[2]); + } + )), + 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_underline($match[1]); + } + )), + 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_parse_list($match[0]); + } + )), + 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->validate_email($match[1], $match[2]); + } + )), + 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#ui' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_flash($match[1], $match[2], $match[3]); + } + )) ); // Zero the parsed items array From a430fef05bcf034b790a2603879ada90fa5d1b71 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 19 May 2015 16:29:10 +0200 Subject: [PATCH 0305/1676] [ticket/13832] Use preg_replace_callback in acp_bbcodes PHPBB3-13832 --- phpBB/includes/acp/acp_bbcodes.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index 9c00e89713..0cfe791ad7 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -558,10 +558,18 @@ class acp_bbcodes trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } - $fp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_match); - $fp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_replace); - $sp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_match); - $sp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_replace); + $fp_match = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) { + return strtolower($match[0]); + }, $fp_match); + $fp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) { + return strtolower($match[0]); + }, $fp_replace); + $sp_match = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) { + return strtolower($match[0]); + }, $sp_match); + $sp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) { + return strtolower($match[0]); + }, $sp_replace); return array( 'bbcode_tag' => $bbcode_tag, From 3106195cddec48ec779282d03f2c54c88fc66511 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 19 May 2015 16:29:50 +0200 Subject: [PATCH 0306/1676] [ticket/13832] Use preg_replace_callback in bbcode class PHPBB3-13832 --- phpBB/includes/bbcode.php | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index dce9966efd..0c9869fe25 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -110,7 +110,18 @@ class bbcode $undid_bbcode_specialchars = true; } - $message = preg_replace($preg['search'], $preg['replace'], $message); + foreach ($preg['search'] as $key => $search) + { + if (is_callable($preg['replace'][$key])) + { + $message = preg_replace_callback($search, $preg['replace'][$key], $message); + } + else + { + $message = preg_replace($search, $preg['replace'][$key], $message); + } + } + $preg = array('search' => array(), 'replace' => array()); } } @@ -212,7 +223,9 @@ class bbcode '[/quote:$uid]' => $this->bbcode_tpl('quote_close', $bbcode_id) ), 'preg' => array( - '#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#ise' => "\$this->bbcode_second_pass_quote('\$1', '\$2')" + '#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#is' => function ($match) { + return $this->bbcode_second_pass_quote($match[1], $match[2]); + }, ) ); break; @@ -291,7 +304,9 @@ class bbcode case 8: $this->bbcode_cache[$bbcode_id] = array( 'preg' => array( - '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise' => "\$this->bbcode_second_pass_code('\$1', '\$2')", + '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#is' => function ($match) { + return $this->bbcode_second_pass_code($match[1], $match[2]); + }, ) ); break; @@ -301,7 +316,9 @@ class bbcode 'preg' => array( '#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#' => "\$1", '#(\[list=([^\[]+):$uid\])[\n]{1}#' => "\$1", - '#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_list('\$1')", + '#\[list=([^\[]+):$uid\]#' => function ($match) { + return $this->bbcode_list($match[1]); + }, ), 'str' => array( '[list:$uid]' => $this->bbcode_tpl('ulist_open_default', $bbcode_id), From e8602d4203132502cba0e5bf4bc17a8e0e4281ed Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 19 May 2015 16:30:52 +0200 Subject: [PATCH 0307/1676] [ticket/13832] Use preg_replace_callback in ucp_pm_options PHPBB3-13832 --- phpBB/includes/ucp/ucp_pm_options.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php index 9c21971bf8..1faec590aa 100644 --- a/phpBB/includes/ucp/ucp_pm_options.php +++ b/phpBB/includes/ucp/ucp_pm_options.php @@ -507,7 +507,9 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit $rule_lang = $action_lang = $check_lang = array(); // Build all three language arrays - preg_replace('#^((RULE|ACTION|CHECK)_([A-Z0-9_]+))$#e', "\${strtolower('\\2') . '_lang'}[constant('\\1')] = \$user->lang['PM_\\2']['\\3']", array_keys(get_defined_constants())); + preg_replace_callback('#^((RULE|ACTION|CHECK)_([A-Z0-9_]+))$#', function ($match) use(&$rule_lang, &$action_lang, &$check_lang, $user) { + ${strtolower($match[2]) . '_lang'}[constant($match[1])] = $user->lang['PM_' . $match[2]][$match[3]]; + } , array_keys(get_defined_constants())); /* Rule Ordering: From 358c634153bd5fc5fe6a80a2c129e70adb107093 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 19 May 2015 17:26:01 +0200 Subject: [PATCH 0308/1676] [ticket/13832] Remove unused global from bbcode_init() PHPBB3-13832 --- phpBB/includes/message_parser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index d40c71c2a9..208690c146 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -126,7 +126,7 @@ class bbcode_firstpass extends bbcode */ function bbcode_init($allow_custom_bbcode = true) { - global $phpbb_dispatcher, $bbcode_class; + global $phpbb_dispatcher; static $rowset; From 7a65b0cc4ea172446064d4f83b74438a9dacef09 Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Tue, 19 May 2015 21:59:41 +0200 Subject: [PATCH 0309/1676] [ticket/13849] Fix development environment PHPBB3-13849 --- phpBB/phpbb/di/extension/core.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index c9e2d4dc5b..91b321a684 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -71,7 +71,7 @@ class core extends Extension // Set the Twig options if defined in the environment $definition = $container->getDefinition('template.twig.environment'); - $twig_environment_options = $definition->getArgument(6); + $twig_environment_options = $definition->getArgument(7); if ($config['twig']['debug']) { $twig_environment_options['debug'] = true; @@ -80,8 +80,8 @@ class core extends Extension { $twig_environment_options['auto_reload'] = true; } - // Replace the 6th argument, the options passed to the environment - $definition->replaceArgument(6, $twig_environment_options); + // Replace the 8th argument, the options passed to the environment + $definition->replaceArgument(7, $twig_environment_options); if ($config['twig']['enable_debug_extension']) { From b9ff0bbba4cf357baad32576c01f36a9f2627ffa Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Tue, 19 May 2015 22:42:32 +0200 Subject: [PATCH 0310/1676] [ticket/13849] Fix tests PHPBB3-13849 --- tests/di/fixtures/config/test/container/environment.yml | 1 + tests/di/fixtures/other_config/test/container/environment.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/di/fixtures/config/test/container/environment.yml b/tests/di/fixtures/config/test/container/environment.yml index 0873078844..14c986d123 100644 --- a/tests/di/fixtures/config/test/container/environment.yml +++ b/tests/di/fixtures/config/test/container/environment.yml @@ -22,4 +22,5 @@ services: - ~ - ~ - ~ + - ~ - [] diff --git a/tests/di/fixtures/other_config/test/container/environment.yml b/tests/di/fixtures/other_config/test/container/environment.yml index 2aa29db2eb..e285b1b781 100644 --- a/tests/di/fixtures/other_config/test/container/environment.yml +++ b/tests/di/fixtures/other_config/test/container/environment.yml @@ -22,4 +22,5 @@ services: - ~ - ~ - ~ + - ~ - [] From 91cace06a5b8d0d2b2446429ec404acda0f42e5b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 20 May 2015 08:59:19 +0200 Subject: [PATCH 0311/1676] [ticket/13832] Resolve minor coding issues PHPBB3-13832 --- phpBB/includes/bbcode.php | 18 ++---------------- phpBB/includes/ucp/ucp_pm_options.php | 2 +- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index 0c9869fe25..ac5b3e6390 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -403,14 +403,7 @@ class bbcode // Replace {L_*} lang strings $bbcode_tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) { - if (!empty($user->lang[$match['1']])) - { - return $user->lang[$match['1']]; - } - else - { - return ucwords(strtolower(str_replace('_', ' ', $match['1']))); - } + return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1]))); }, $bbcode_tpl); if (!empty($rowset[$bbcode_id]['second_pass_replace'])) @@ -536,14 +529,7 @@ class bbcode ); $tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) { - if (!empty($user->lang[$match['1']])) - { - return $user->lang[$match['1']]; - } - else - { - return ucwords(strtolower(str_replace('_', ' ', $match['1']))); - } + return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1]))); }, $tpl); if (!empty($replacements[$tpl_name])) diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php index 1faec590aa..b674a457c1 100644 --- a/phpBB/includes/ucp/ucp_pm_options.php +++ b/phpBB/includes/ucp/ucp_pm_options.php @@ -509,7 +509,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit // Build all three language arrays preg_replace_callback('#^((RULE|ACTION|CHECK)_([A-Z0-9_]+))$#', function ($match) use(&$rule_lang, &$action_lang, &$check_lang, $user) { ${strtolower($match[2]) . '_lang'}[constant($match[1])] = $user->lang['PM_' . $match[2]][$match[3]]; - } , array_keys(get_defined_constants())); + }, array_keys(get_defined_constants())); /* Rule Ordering: From 0e5d1decbf64eb1192c0ad697c38f368e8f970e7 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 20 May 2015 09:03:59 +0200 Subject: [PATCH 0312/1676] [ticket/13832] Use preg_replace_callback in check_flash_bbcodes PHPBB3-13832 --- phpBB/develop/check_flash_bbcodes.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/phpBB/develop/check_flash_bbcodes.php b/phpBB/develop/check_flash_bbcodes.php index 6e1b415bb6..2a54724aaa 100644 --- a/phpBB/develop/check_flash_bbcodes.php +++ b/phpBB/develop/check_flash_bbcodes.php @@ -140,8 +140,13 @@ function html_entity_decode_utf8($string) static $trans_tbl; // replace numeric entities - $string = preg_replace('~&#x([0-9a-f]+);~ei', 'code2utf8(hexdec("\\1"))', $string); + $string = preg_replace_callback('~&#x([0-9a-f]+);~i', function ($match) { + return code2utf8(hexdec($match[1])); + }, $string); $string = preg_replace('~&#([0-9]+);~e', 'code2utf8(\\1)', $string); + $string = preg_replace_callback('~&#([0-9]+);~', function ($match) { + return code2utf8($match[1]); + }, $string); // replace literal entities if (!isset($trans_tbl)) From 077051fef56f0d9b504a2593dc84a3d05ef02e18 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 20 May 2015 00:23:42 +0200 Subject: [PATCH 0313/1676] [ticket/13844] Add events PHPBB3-13844 --- .../default/container/services_help.yml | 5 +- phpBB/phpbb/help/controller/controller.php | 7 +-- phpBB/phpbb/help/manager.php | 61 +++++++++++++++++-- tests/help/manager_test.php | 7 ++- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/phpBB/config/default/container/services_help.yml b/phpBB/config/default/container/services_help.yml index 29523ffb27..8b9d497945 100644 --- a/phpBB/config/default/container/services_help.yml +++ b/phpBB/config/default/container/services_help.yml @@ -2,14 +2,14 @@ services: phpbb.help.manager: class: phpbb\help\manager arguments: - - @template + - @dispatcher - @language + - @template phpbb.help.controller.bbcode: class: phpbb\help\controller\bbcode arguments: - @controller.helper - - @dispatcher - @phpbb.help.manager - @template - @language @@ -20,7 +20,6 @@ services: class: phpbb\help\controller\faq arguments: - @controller.helper - - @dispatcher - @phpbb.help.manager - @template - @language diff --git a/phpBB/phpbb/help/controller/controller.php b/phpBB/phpbb/help/controller/controller.php index 743a9c7fde..29494205a9 100644 --- a/phpBB/phpbb/help/controller/controller.php +++ b/phpBB/phpbb/help/controller/controller.php @@ -21,9 +21,6 @@ abstract class controller /** @var \phpbb\controller\helper */ protected $helper; - /** @var \phpbb\event\dispatcher_interface */ - protected $dispatcher; - /** @var \phpbb\help\manager */ protected $manager; @@ -43,17 +40,15 @@ abstract class controller * Constructor * * @param \phpbb\controller\helper $helper - * @param \phpbb\event\dispatcher_interface $dispatcher * @param \phpbb\help\manager $manager * @param \phpbb\template\template $template * @param \phpbb\language\language $language * @param string $root_path * @param string $php_ext */ - public function __construct(\phpbb\controller\helper $helper, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\help\manager $manager, \phpbb\template\template $template, \phpbb\language\language $language, $root_path, $php_ext) + public function __construct(\phpbb\controller\helper $helper, \phpbb\help\manager $manager, \phpbb\template\template $template, \phpbb\language\language $language, $root_path, $php_ext) { $this->helper = $helper; - $this->dispatcher = $dispatcher; $this->manager = $manager; $this->template = $template; $this->language = $language; diff --git a/phpBB/phpbb/help/manager.php b/phpBB/phpbb/help/manager.php index a7320563a8..d6991c0733 100644 --- a/phpBB/phpbb/help/manager.php +++ b/phpBB/phpbb/help/manager.php @@ -18,25 +18,30 @@ namespace phpbb\help; */ class manager { - /** @var \phpbb\template\template */ - protected $template; + /** @var \phpbb\event\dispatcher */ + protected $dispatcher; /** @var \phpbb\language\language */ protected $language; + /** @var \phpbb\template\template */ + protected $template; + /** @var bool */ protected $switched_column; /** * Constructor * - * @param \phpbb\template\template $template + * @param \phpbb\event\dispatcher $dispatcher * @param \phpbb\language\language $language + * @param \phpbb\template\template $template */ - public function __construct(\phpbb\template\template $template, \phpbb\language\language $language) + public function __construct(\phpbb\event\dispatcher $dispatcher, \phpbb\language\language $language, \phpbb\template\template $template) { - $this->template = $template; + $this->dispatcher = $dispatcher; $this->language = $language; + $this->template = $template; } /** @@ -47,6 +52,18 @@ class manager */ public function add_block($block_name, $switch_column = false, $questions = array()) { + /** + * You can use this event to add a block before the current one. + * + * @event core.help_manager_add_block_before + * @var string block_name Language key of the block headline + * @var bool switch_column Should we switch the menu column before this headline + * @var array questions Array with questions + * @since 3.2.0-a1 + */ + $vars = array('block_name', 'switch_column', 'questions'); + extract($this->dispatcher->trigger_event('core.help_manager_add_block_before', compact($vars))); + $this->template->assign_block_vars('faq_block', array( 'BLOCK_TITLE' => $this->language->lang($block_name), 'SWITCH_COLUMN' => !$this->switched_column && $switch_column, @@ -58,6 +75,18 @@ class manager } $this->switched_column = $this->switched_column || $switch_column; + + /** + * You can use this event to add a block after the current one. + * + * @event core.help_manager_add_block_after + * @var string block_name Language key of the block headline + * @var bool switch_column Should we switch the menu column before this headline + * @var array questions Array with questions + * @since 3.2.0-a1 + */ + $vars = array('block_name', 'switch_column', 'questions'); + extract($this->dispatcher->trigger_event('core.help_manager_add_block_after', compact($vars))); } /** @@ -68,10 +97,32 @@ class manager */ public function add_question($question, $answer) { + /** + * You can use this event to add a question before the current one. + * + * @event core.help_manager_add_question_before + * @var string question Language key of the question + * @var string answer Language key of the answer + * @since 3.2.0-a1 + */ + $vars = array('question', 'answer'); + extract($this->dispatcher->trigger_event('core.help_manager_add_question_before', compact($vars))); + $this->template->assign_block_vars('faq_block.faq_row', array( 'FAQ_QUESTION' => $this->language->lang($question), 'FAQ_ANSWER' => $this->language->lang($answer), )); + + /** + * You can use this event to add a question after the current one. + * + * @event core.help_manager_add_question_after + * @var string question Language key of the question + * @var string answer Language key of the answer + * @since 3.2.0-a1 + */ + $vars = array('question', 'answer'); + extract($this->dispatcher->trigger_event('core.help_manager_add_question_after', compact($vars))); } /** diff --git a/tests/help/manager_test.php b/tests/help/manager_test.php index aaf63194fa..68534d9a32 100644 --- a/tests/help/manager_test.php +++ b/tests/help/manager_test.php @@ -11,7 +11,7 @@ * */ -class phpbb_language_test extends phpbb_test_case +class phpbb_help_manager_test extends phpbb_test_case { /** @var \phpbb\help\manager */ protected $manager; @@ -30,8 +30,9 @@ class phpbb_language_test extends phpbb_test_case ->getMock(); $this->manager = new \phpbb\help\manager( - $this->template, - $this->language + new \phpbb_mock_event_dispatcher(), + $this->language, + $this->template ); } From 92078dce3393ea705361e1c3c0a332db778ccb0a Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 29 Apr 2015 23:22:30 +0200 Subject: [PATCH 0314/1676] [ticket/11742] Removed tabs-to-space conversion in [code] PHPBB3-11742 --- phpBB/phpbb/textformatter/s9e/renderer.php | 43 ------------------- phpBB/styles/prosilver/template/bbcode.html | 4 +- .../tickets_data/PHPBB3-11742.html | 1 + .../tickets_data/PHPBB3-11742.txt | 1 + 4 files changed, 4 insertions(+), 45 deletions(-) create mode 100644 tests/text_processing/tickets_data/PHPBB3-11742.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-11742.txt diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 8999f1d25f..51bc44f339 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -234,10 +234,6 @@ class renderer implements \phpbb\textformatter\renderer_interface } $html = $this->renderer->render($xml); - if (stripos($html, 'replace_tabs_in_code($html); - } /** * Modify a rendered text @@ -253,45 +249,6 @@ class renderer implements \phpbb\textformatter\renderer_interface return $html; } - /** - * Replace tabs in code elements - * - * @see bbcode::bbcode_second_pass_code() - * - * @param string $html Original HTML - * @return string Modified HTML - */ - protected function replace_tabs_in_code($html) - { - return preg_replace_callback( - '((]*>)(.*?)())is', - function ($captures) - { - $code = $captures[2]; - - $code = str_replace("\t", '   ', $code); - $code = str_replace(' ', '  ', $code); - $code = str_replace(' ', '  ', $code); - $code = str_replace("\n ", "\n ", $code); - - // keep space at the beginning - if (!empty($code) && $code[0] == ' ') - { - $code = ' ' . substr($code, 1); - } - - // remove newline at the beginning - if (!empty($code) && $code[0] == "\n") - { - $code = substr($code, 1); - } - - return $captures[1] . $code . $captures[3]; - }, - $html - ); - } - /** * {@inheritdoc} */ diff --git a/phpBB/styles/prosilver/template/bbcode.html b/phpBB/styles/prosilver/template/bbcode.html index 3e38d13a32..af8e6ae4b0 100644 --- a/phpBB/styles/prosilver/template/bbcode.html +++ b/phpBB/styles/prosilver/template/bbcode.html @@ -12,8 +12,8 @@
              -

              {L_CODE}{L_COLON} {L_SELECT_ALL_CODE}

              -
              +

              {L_CODE}{L_COLON} {L_SELECT_ALL_CODE}

              
              +
              diff --git a/tests/text_processing/tickets_data/PHPBB3-11742.html b/tests/text_processing/tickets_data/PHPBB3-11742.html new file mode 100644 index 0000000000..e7890eef19 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11742.html @@ -0,0 +1 @@ +

              CODE: Select all

              	tab
              \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11742.txt b/tests/text_processing/tickets_data/PHPBB3-11742.txt new file mode 100644 index 0000000000..db72e5dda0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11742.txt @@ -0,0 +1 @@ +[code] tab[/code] \ No newline at end of file From ad84a40c002990ea723d7b756313820b06e8012a Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 3 May 2015 02:40:15 +0200 Subject: [PATCH 0315/1676] [ticket/11742] Updated default formatting tests to match the new default PHPBB3-11742 --- tests/text_formatter/s9e/default_formatting_test.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 79232562cf..89d2cc53e1 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -68,7 +68,7 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case ), array( '[code]unparsed code[/code]', - '

              CODE: Select all

              unparsed code
              ' + '

              CODE: Select all

              unparsed code
              ' ), array( '[list]no item[/list]', @@ -181,12 +181,12 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case array( // Do not parse textual bbcodes in code '[code]unparsed code [b]bold [i]bold + italic[/i][/b][/code]', - '

              CODE: Select all

              unparsed code [b]bold [i]bold + italic[/i][/b]
              ' + '

              CODE: Select all

              unparsed code [b]bold [i]bold + italic[/i][/b]
              ' ), array( // Do not parse quote bbcodes in code '[code]unparsed code [quote="username"]quoted[/quote][/code]', - '

              CODE: Select all

              unparsed code [quote="username"]quoted[/quote]
              ' + '

              CODE: Select all

              unparsed code [quote="username"]quoted[/quote]
              ' ), array( // Textual bbcode nesting into textual bbcode @@ -195,7 +195,7 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case ), array( "[code]\tline1\n line2[/code]", - '

              CODE: Select all

                 line1
              ' . "\n" . '  line2
              ' + '

              CODE: Select all

              ' . "\tline1\n  line2
              " ), array( '... http://example.org ...', From adbc45b48654f4c89e87f4163481332579d81adc Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 23 May 2015 01:53:32 +0200 Subject: [PATCH 0316/1676] [ticket/11742] Removed whitespace collapsing in codebox [ci skip] PHPBB3-11742 --- phpBB/styles/prosilver/theme/content.css | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 380b285b83..85c3cb9f4c 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -513,7 +513,6 @@ blockquote .codebox { display: block; height: auto; max-height: 200px; - white-space: normal; padding-top: 5px; font: 0.9em Monaco, "Andale Mono","Courier New", Courier, mono; line-height: 1.3em; From ebda279bea6ea3ff5522c7af1556874909a27b18 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 23 May 2015 19:17:55 +0200 Subject: [PATCH 0317/1676] [ticket/11742] Updated s9e\TextFormatter PHPBB3-11742 --- phpBB/composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index dc7608b37e..64927a409a 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -220,12 +220,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "29c5959f4425934a53b6fdb42760d719b95a6e82" + "reference": "0a6016ab96ab1da5be73f7a407f96f57d307b6b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/29c5959f4425934a53b6fdb42760d719b95a6e82", - "reference": "29c5959f4425934a53b6fdb42760d719b95a6e82", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/0a6016ab96ab1da5be73f7a407f96f57d307b6b6", + "reference": "0a6016ab96ab1da5be73f7a407f96f57d307b6b6", "shasum": "" }, "require": { @@ -270,7 +270,7 @@ "parser", "shortcodes" ], - "time": "2015-05-18 04:48:32" + "time": "2015-05-23 17:07:15" }, { "name": "symfony/config", From 3f52429e3d1548ca1faa203047d9326b0e6d4baa Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 23 May 2015 19:18:02 +0200 Subject: [PATCH 0318/1676] [ticket/11742] Added test PHPBB3-11742 --- tests/text_formatter/s9e/default_formatting_test.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 89d2cc53e1..2aa15146aa 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -197,6 +197,10 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case "[code]\tline1\n line2[/code]", '

              CODE: Select all

              ' . "\tline1\n  line2
              " ), + array( + "[code]\n\tline1\n line2[/code]", + '

              CODE: Select all

              ' . "\tline1\n  line2
              " + ), array( '... http://example.org ...', '... http://example.org ...' From 715d365a5e776207e1dddac7e5ccc50aad5621f1 Mon Sep 17 00:00:00 2001 From: David King Date: Sat, 23 May 2015 17:06:25 -0400 Subject: [PATCH 0319/1676] [ticket/13733] Only use migration classes that extension the base migration class. PHPBB3-13733 --- phpBB/phpbb/extension/base.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/phpBB/phpbb/extension/base.php b/phpBB/phpbb/extension/base.php index 5bb530bad4..4bf19b37ed 100644 --- a/phpBB/phpbb/extension/base.php +++ b/phpBB/phpbb/extension/base.php @@ -137,6 +137,14 @@ class base implements \phpbb\extension\extension_interface $migrations = $this->extension_finder->get_classes_from_files($migrations); + foreach ($migrations as $key => $migration) + { + $reflector = new \ReflectionClass($migration); + if (!$reflector->isSubclassOf('\phpbb\db\migration\migration')) { + unset($migrations[$key]); + } + } + return $migrations; } } From 06d31abda948abd6f18bc43a3b31c1e4db9425ae Mon Sep 17 00:00:00 2001 From: David King Date: Sat, 23 May 2015 17:26:45 -0400 Subject: [PATCH 0320/1676] [ticket/13769] Move environment check lower in phpbbcli.php PHPBB3-13769 --- phpBB/bin/phpbbcli.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index fc78e5d04a..4d40c6aba7 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -22,11 +22,6 @@ if (php_sapi_name() != 'cli') define('IN_PHPBB', true); -if (!defined('PHPBB_ENVIRONMENT')) -{ - @define('PHPBB_ENVIRONMENT', 'production'); -} - $phpbb_root_path = __DIR__ . '/../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); require($phpbb_root_path . 'includes/startup.' . $phpEx); @@ -38,6 +33,11 @@ $phpbb_class_loader->register(); $phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx); extract($phpbb_config_php_file->get_all()); +if (!defined('PHPBB_ENVIRONMENT')) +{ + @define('PHPBB_ENVIRONMENT', 'production'); +} + require($phpbb_root_path . 'includes/constants.' . $phpEx); require($phpbb_root_path . 'includes/functions.' . $phpEx); require($phpbb_root_path . 'includes/functions_admin.' . $phpEx); From 9e6f9c8a64d89f48d531c5b24d535025dd04f956 Mon Sep 17 00:00:00 2001 From: David King Date: Sat, 23 May 2015 19:57:32 -0400 Subject: [PATCH 0321/1676] [ticket/13733] Handle nonexistent classes as well PHPBB3-13733 --- phpBB/phpbb/extension/base.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/extension/base.php b/phpBB/phpbb/extension/base.php index 4bf19b37ed..8b4d747eaf 100644 --- a/phpBB/phpbb/extension/base.php +++ b/phpBB/phpbb/extension/base.php @@ -139,8 +139,9 @@ class base implements \phpbb\extension\extension_interface foreach ($migrations as $key => $migration) { - $reflector = new \ReflectionClass($migration); - if (!$reflector->isSubclassOf('\phpbb\db\migration\migration')) { + // If the class doesn't exist OR the class does not extend the migration class + // we need to skip it. + if (!class_exists($migration) || ($reflector = new \ReflectionClass($migration) && !$reflector->isSubclassOf('\phpbb\db\migration\migration'))) { unset($migrations[$key]); } } From 4ecc13af83718e26e02afc9b8516a506ca5a26e1 Mon Sep 17 00:00:00 2001 From: David King Date: Sat, 23 May 2015 20:13:23 -0400 Subject: [PATCH 0322/1676] [ticket/13733] Properly handle nonexistent classes as well PHPBB3-13733 --- phpBB/phpbb/extension/base.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/extension/base.php b/phpBB/phpbb/extension/base.php index 8b4d747eaf..8e717e1beb 100644 --- a/phpBB/phpbb/extension/base.php +++ b/phpBB/phpbb/extension/base.php @@ -139,11 +139,21 @@ class base implements \phpbb\extension\extension_interface foreach ($migrations as $key => $migration) { - // If the class doesn't exist OR the class does not extend the migration class - // we need to skip it. - if (!class_exists($migration) || ($reflector = new \ReflectionClass($migration) && !$reflector->isSubclassOf('\phpbb\db\migration\migration'))) { - unset($migrations[$key]); + // If the class exists and is a subclass of the + // \phpbb\db\migration\migration abstract class + // we skip it. + + // Otherwise, i.e. if it doesn't exist or it is + // not an extend the abstract class, we unset it + if (class_exists($migration)) { + $reflector = new \ReflectionClass($migration); + if ($reflector->isSubclassOf('\phpbb\db\migration\migration')) { + continue; + } + } + + unset($migrations[$key]); } return $migrations; From 65316cffafead1b0529dca50f4c110489615438a Mon Sep 17 00:00:00 2001 From: David King Date: Sat, 23 May 2015 21:13:30 -0400 Subject: [PATCH 0323/1676] [ticket/13733] Allow tests the skip class validation PHPBB3-13733 --- phpBB/phpbb/extension/base.php | 31 ++++++++++++++----------- tests/extension/extension_base_test.php | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/phpBB/phpbb/extension/base.php b/phpBB/phpbb/extension/base.php index 8e717e1beb..ed190f6aa5 100644 --- a/phpBB/phpbb/extension/base.php +++ b/phpBB/phpbb/extension/base.php @@ -121,9 +121,11 @@ class base implements \phpbb\extension\extension_interface /** * Get the list of migration files from this extension * + * @var bool $validate_classes Whether or not to check that the migration + * class exists and extends the base migration class. * @return array */ - protected function get_migration_file_list() + protected function get_migration_file_list($validate_classes = true) { if ($this->migrations !== false) { @@ -137,23 +139,26 @@ class base implements \phpbb\extension\extension_interface $migrations = $this->extension_finder->get_classes_from_files($migrations); - foreach ($migrations as $key => $migration) + if ($validate_classes) { - // If the class exists and is a subclass of the - // \phpbb\db\migration\migration abstract class - // we skip it. + foreach ($migrations as $key => $migration) + { + // If the class exists and is a subclass of the + // \phpbb\db\migration\migration abstract class + // we skip it. + + // Otherwise, i.e. if it doesn't exist or it is + // not an extend the abstract class, we unset it + if (class_exists($migration)) { + $reflector = new \ReflectionClass($migration); + if ($reflector->isSubclassOf('\phpbb\db\migration\migration')) { + continue; + } - // Otherwise, i.e. if it doesn't exist or it is - // not an extend the abstract class, we unset it - if (class_exists($migration)) { - $reflector = new \ReflectionClass($migration); - if ($reflector->isSubclassOf('\phpbb\db\migration\migration')) { - continue; } + unset($migrations[$key]); } - - unset($migrations[$key]); } return $migrations; diff --git a/tests/extension/extension_base_test.php b/tests/extension/extension_base_test.php index eee38186db..898c11d902 100644 --- a/tests/extension/extension_base_test.php +++ b/tests/extension/extension_base_test.php @@ -74,6 +74,6 @@ class phpbb_extension_extension_base_test extends phpbb_test_case public function test_suffix_get_classes($extension_name, $expected) { $extension = $this->extension_manager->get_extension($extension_name); - $this->assertEquals($expected, self::$reflection_method_get_migration_file_list->invoke($extension)); + $this->assertEquals($expected, self::$reflection_method_get_migration_file_list->invoke($extension, false)); } } From c485540f537b61a1e95f72a35dbca40f0f9b1c24 Mon Sep 17 00:00:00 2001 From: David King Date: Sat, 23 May 2015 21:38:59 -0400 Subject: [PATCH 0324/1676] [ticket/13733] Braces on their own lines PHPBB3-13733 --- phpBB/phpbb/extension/base.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/extension/base.php b/phpBB/phpbb/extension/base.php index ed190f6aa5..5ce6983edf 100644 --- a/phpBB/phpbb/extension/base.php +++ b/phpBB/phpbb/extension/base.php @@ -149,9 +149,11 @@ class base implements \phpbb\extension\extension_interface // Otherwise, i.e. if it doesn't exist or it is // not an extend the abstract class, we unset it - if (class_exists($migration)) { + if (class_exists($migration)) + { $reflector = new \ReflectionClass($migration); - if ($reflector->isSubclassOf('\phpbb\db\migration\migration')) { + if ($reflector->isSubclassOf('\phpbb\db\migration\migration')) + { continue; } From 9dc1729e379691c97b319a12912dc48ad779a286 Mon Sep 17 00:00:00 2001 From: David King Date: Sun, 24 May 2015 01:32:01 -0400 Subject: [PATCH 0325/1676] [ticket/13733] Add isInstantiable() check. PHPBB3-13733 --- phpBB/phpbb/extension/base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/extension/base.php b/phpBB/phpbb/extension/base.php index 5ce6983edf..40bd349c4d 100644 --- a/phpBB/phpbb/extension/base.php +++ b/phpBB/phpbb/extension/base.php @@ -152,7 +152,7 @@ class base implements \phpbb\extension\extension_interface if (class_exists($migration)) { $reflector = new \ReflectionClass($migration); - if ($reflector->isSubclassOf('\phpbb\db\migration\migration')) + if ($reflector->isSubclassOf('\phpbb\db\migration\migration') && $reflector->isInstantiable()) { continue; } From 8a077e0e943d87ee1d26b0501f0b9bcc472ab904 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 17 May 2015 20:15:06 +0200 Subject: [PATCH 0326/1676] [ticket/13847] Move quote generation to text_formatter.utils PHPBB3-13847 --- phpBB/phpbb/textformatter/s9e/utils.php | 37 ++++++++++++++ phpBB/phpbb/textformatter/utils_interface.php | 12 +++++ phpBB/posting.php | 6 ++- tests/functional/posting_test.php | 14 +++++ tests/text_formatter/s9e/utils_test.php | 51 +++++++++++++++++++ 5 files changed, 119 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index e21dedecc4..fe33c04da3 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -34,6 +34,43 @@ class utils implements \phpbb\textformatter\utils_interface return \s9e\TextFormatter\Utils::removeFormatting($xml); } + /** + * Return given string between quotes + * + * Will use either single- or double- quotes depending on whichever requires to be escaped. + * Quotes and backslashes are escaped with backslashes where necessary + * + * @param string $str Original string + * @return string Escaped string within quotes + */ + protected function enquote($str) + { + $quote = (strpos($str, '"') === false || strpos($str, "'") !== false) ? '"' : "'"; + + return $quote . addcslashes($str, '\\' . $quote) . $quote; + } + + /** + * {@inheritdoc} + */ + public function generate_quote($text, array $attributes = array()) + { + $quote = '[quote'; + if (isset($attributes['author'])) + { + // Add the author as the BBCode's default attribute + $quote .= '=' . $this->enquote($attributes['author']); + unset($attributes['author']); + } + foreach ($attributes as $name => $value) + { + $quote .= ' ' . $name . '=' . $this->enquote($value); + } + $quote .= ']' . $text . '[/quote]'; + + return $quote; + } + /** * Get a list of quote authors, limited to the outermost quotes * diff --git a/phpBB/phpbb/textformatter/utils_interface.php b/phpBB/phpbb/textformatter/utils_interface.php index 6d3fd13021..41a6ba2345 100644 --- a/phpBB/phpbb/textformatter/utils_interface.php +++ b/phpBB/phpbb/textformatter/utils_interface.php @@ -28,6 +28,18 @@ interface utils_interface */ public function clean_formatting($text); + /** + * Create a quote block for given text + * + * Possible attributes: + * - author + * + * @param string $text Quote's text + * @param array $attributes Quote's attributes + * @return string Quote block to be used in a new post/text + */ + public function generate_quote($text, array $attributes = array()); + /** * Get a list of quote authors, limited to the outermost quotes * diff --git a/phpBB/posting.php b/phpBB/posting.php index a4fb4d7a8d..4d52da2567 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1597,7 +1597,11 @@ if ($generate_quote) { if ($config['allow_bbcode']) { - $message_parser->message = '[quote="' . $post_data['quote_username'] . '"]' . censor_text(trim($message_parser->message)) . "[/quote]\n"; + $message_parser->message = $phpbb_container->get('text_formatter.utils')->generate_quote( + censor_text(trim($message_parser->message)), + array('author' => $post_data['quote_username']) + ); + $message_parser->message .= "\n"; } else { diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 5c083aef37..8677237772 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -72,6 +72,20 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $this->assertContains('😀', $crawler->text()); } + public function test_quote() + { + $text = 'Test post "\' &&amp;'; + $expected = '[quote="admin"]' . $text . '[/quote]'; + + $this->login(); + $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); + $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); + + $crawler = self::request('GET', "posting.php?mode=quote&f=2&t={$post['topic_id']}&p={$post['post_id']}&sid={$this->sid}"); + + $this->assertContains($expected, $crawler->filter('textarea#message')->text()); + } + /** * @testdox max_quote_depth is applied to the text populating the posting form */ diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index b1b937709c..3c92965b49 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -108,6 +108,57 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case ); } + /** + * @dataProvider get_generate_quote_tests + */ + public function test_generate_quote($text, $params, $expected) + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + + $this->assertSame($expected, $utils->generate_quote($text, $params)); + } + + public function get_generate_quote_tests() + { + return array( + array( + '...', + array(), + '[quote]...[/quote]', + ), + array( + '...', + array('author' => 'Brian Kibler'), + '[quote="Brian Kibler"]...[/quote]', + ), + array( + '...', + array('author' => 'Brian "Brian Kibler" Kibler of Brian Kibler Gaming'), + '[quote=\'Brian "Brian Kibler" Kibler of Brian Kibler Gaming\']...[/quote]', + ), + array( + '...', + array('author' => "Brian Kibler Gaming's Brian Kibler"), + '[quote="Brian Kibler Gaming\'s Brian Kibler"]...[/quote]', + ), + array( + '...', + array('author' => "\\\"'"), + '[quote="\\\\\\"\'"]...[/quote]', + ), + array( + '...', + array( + 'author' => 'user', + 'post_id' => 123, + 'url' => 'http://example.org' + ), + '[quote="user" post_id="123" url="http://example.org"]...[/quote]', + ), + ); + } + /** * @dataProvider get_remove_bbcode_tests */ From e50d9186ce15367e8f6e2aab5c04481ca0046ec6 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 19 May 2015 23:10:35 +0200 Subject: [PATCH 0327/1676] [ticket/13847] Changed enquote() logic to use whichever is the shortest Will enclose attribute values in single- or double- quotes depending on whichever requires the least escaping. Characters that need to be escaped are always escaped regardless. PHPBB3-13847 --- phpBB/phpbb/textformatter/s9e/utils.php | 7 ++++--- tests/text_formatter/s9e/utils_test.php | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index fe33c04da3..04df589930 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -37,7 +37,7 @@ class utils implements \phpbb\textformatter\utils_interface /** * Return given string between quotes * - * Will use either single- or double- quotes depending on whichever requires to be escaped. + * Will use either single- or double- quotes depending on whichever requires less escaping. * Quotes and backslashes are escaped with backslashes where necessary * * @param string $str Original string @@ -45,9 +45,10 @@ class utils implements \phpbb\textformatter\utils_interface */ protected function enquote($str) { - $quote = (strpos($str, '"') === false || strpos($str, "'") !== false) ? '"' : "'"; + $singleQuoted = "'" . addcslashes($str, "\\'") . "'"; + $doubleQuoted = '"' . addcslashes($str, '\\"') . '"'; - return $quote . addcslashes($str, '\\' . $quote) . $quote; + return (strlen($singleQuoted) < strlen($doubleQuoted)) ? $singleQuoted : $doubleQuoted; } /** diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index 3c92965b49..555f29cb38 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -147,6 +147,21 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case array('author' => "\\\"'"), '[quote="\\\\\\"\'"]...[/quote]', ), + array( + '...', + array('author' => 'Lots of doubles """ one single \' one backslash \\'), + '[quote=\'Lots of doubles """ one single \\\' one backslash \\\\\']...[/quote]', + ), + array( + '...', + array('author' => "Lots of singles ''' one double \" one backslash \\"), + '[quote="Lots of singles \'\'\' one double \\" one backslash \\\\"]...[/quote]', + ), + array( + '...', + array('author' => 'Defaults to doublequotes """\'\'\''), + '[quote="Defaults to doublequotes \\"\\"\\"\'\'\'"]...[/quote]', + ), array( '...', array( From 2a7a06da2a166b814732bdfa790e53b80da8a612 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 25 May 2015 20:54:30 +0200 Subject: [PATCH 0328/1676] [ticket/13847] Updated ucp_pm_compose to use the utils service ...when quoting a post PHPBB3-13847 --- phpBB/includes/ucp/ucp_pm_compose.php | 6 +++++- tests/functional/private_messages_test.php | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 59952182df..67e53718a0 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -947,7 +947,11 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { $message_link = ''; } - $message_parser->message = $message_link . '[quote="' . $quote_username . '"]' . censor_text(trim($message_parser->message)) . "[/quote]\n"; + $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( + censor_text(trim($message_parser->message)), + array('author' => $quote_username) + ); + $message_parser->message = $message_link . $quote_text . "\n"; } if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh) diff --git a/tests/functional/private_messages_test.php b/tests/functional/private_messages_test.php index 1f6dc3a979..4851fc4c64 100644 --- a/tests/functional/private_messages_test.php +++ b/tests/functional/private_messages_test.php @@ -66,4 +66,18 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case $crawler = self::submit($form); $this->assertContains($this->lang('CONFIG_UPDATED'), $crawler->filter('.successbox')->text()); } + + public function test_quote() + { + $text = 'Test post'; + $expected = '[quote="admin"]' . $text . '[/quote]'; + + $this->login(); + $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); + $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); + + $crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=quotepost&p=' . $post['post_id'] . '&sid=' . $this->sid); + + $this->assertContains($expected, $crawler->filter('textarea#message')->text()); + } } From 64e1824abdb2a9c860e049f10ecc81c051160ff5 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 25 May 2015 21:04:12 +0200 Subject: [PATCH 0329/1676] [ticket/13847] Updated ucp_pm_compose to use utils when forwarding PHPBB3-13847 --- phpBB/includes/ucp/ucp_pm_compose.php | 6 +++++- tests/functional/private_messages_test.php | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 67e53718a0..53be1b3b29 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -979,7 +979,11 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text); $forward_text[] = sprintf($user->lang['FWD_TO'], implode($user->lang['COMMA_SEPARATOR'], $fwd_to_field['to'])); - $message_parser->message = implode("\n", $forward_text) . "\n\n[quote="{$quote_username}"]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]"; + $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( + censor_text(trim($message_parser->message)), + array('author' => $quote_username) + ); + $message_parser->message = implode("\n", $forward_text) . "\n\n" . $quote_text; $message_subject = ((!preg_match('/^Fwd:/', $message_subject)) ? 'Fwd: ' : '') . censor_text($message_subject); } diff --git a/tests/functional/private_messages_test.php b/tests/functional/private_messages_test.php index 4851fc4c64..3f602d62fb 100644 --- a/tests/functional/private_messages_test.php +++ b/tests/functional/private_messages_test.php @@ -67,7 +67,7 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case $this->assertContains($this->lang('CONFIG_UPDATED'), $crawler->filter('.successbox')->text()); } - public function test_quote() + public function test_quote_post() { $text = 'Test post'; $expected = '[quote="admin"]' . $text . '[/quote]'; @@ -80,4 +80,17 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case $this->assertContains($expected, $crawler->filter('textarea#message')->text()); } + + public function test_quote_forward() + { + $text = 'This is a test private message sent by the testing framework.'; + $expected = '[quote="admin"]' . $text . '[/quote]'; + + $this->login(); + $message_id = $this->create_private_message('Test', $text, array(2)); + + $crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=forward&f=0&p=' . $message_id . '&sid=' . $this->sid); + + $this->assertContains($expected, $crawler->filter('textarea#message')->text()); + } } From c30e0610e938b40a8c04463d2b8de5a64ee59210 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 28 May 2015 10:30:36 +0200 Subject: [PATCH 0330/1676] [ticket/13832] Remove remnant of /e modifier code in check_flash_bbcodes PHPBB3-13832 --- phpBB/develop/check_flash_bbcodes.php | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/develop/check_flash_bbcodes.php b/phpBB/develop/check_flash_bbcodes.php index 2a54724aaa..5dc112bfc0 100644 --- a/phpBB/develop/check_flash_bbcodes.php +++ b/phpBB/develop/check_flash_bbcodes.php @@ -143,7 +143,6 @@ function html_entity_decode_utf8($string) $string = preg_replace_callback('~&#x([0-9a-f]+);~i', function ($match) { return code2utf8(hexdec($match[1])); }, $string); - $string = preg_replace('~&#([0-9]+);~e', 'code2utf8(\\1)', $string); $string = preg_replace_callback('~&#([0-9]+);~', function ($match) { return code2utf8($match[1]); }, $string); From 0f040225d629de7d1a6167c7822b21a9a8ec4af5 Mon Sep 17 00:00:00 2001 From: Cesar G Date: Thu, 28 May 2015 11:53:35 +0200 Subject: [PATCH 0331/1676] [ticket/13871] Fix call to undefined member function on non-object error. PHPBB3-13871 --- phpBB/install/database_update.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 4746bb11f2..e6f360d418 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -184,9 +184,9 @@ define('IN_DB_UPDATE', true); /* @var $migrator \phpbb\db\migrator */ $migrator = $phpbb_container->get('migrator'); -/** @var \phpbb\filesystem\filesystem_interface $filesystem */ -$filesystem = $phpbb_container->get('filesystem'); -$migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($user, new \phpbb\db\html_migrator_output_handler($user), $phpbb_root_path . 'store/migrations_' . time() . '.log', $filesystem)); +/** @var \phpbb\filesystem\filesystem_interface $phpbb_filesystem */ +$phpbb_filesystem = $phpbb_container->get('filesystem'); +$migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($user, new \phpbb\db\html_migrator_output_handler($user), $phpbb_root_path . 'store/migrations_' . time() . '.log', $phpbb_filesystem)); $migrator->create_migrations_table(); From e0f7c225bc8f6cf8e62dcfc146bdd630e15b6e22 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 28 May 2015 12:23:45 +0200 Subject: [PATCH 0332/1676] [ticket/13860] Fixed array-to-string conversion PHPBB3-13860 --- phpBB/phpbb/textformatter/s9e/parser.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index b7d0b2b90b..838c211e56 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -227,7 +227,13 @@ class parser implements \phpbb\textformatter\parser_interface } } - return array_unique($errors); + // Deduplicate error messages. array_unique() only works on strings so we have to serialize + if (!empty($errors)) + { + $errors = array_map('unserialize', array_unique(array_map('serialize', $errors))); + } + + return $errors; } /** From 97d05eb2350895f13872c8435f204796938b8b6f Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 28 May 2015 12:23:51 +0200 Subject: [PATCH 0333/1676] [ticket/13860] Fixed PHP notices from undeclared vars/properties PHPBB3-13860 --- tests/text_processing/message_parser_test.php | 53 +++++++++++-------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/tests/text_processing/message_parser_test.php b/tests/text_processing/message_parser_test.php index 691c0d5b8a..bee1b3fca3 100644 --- a/tests/text_processing/message_parser_test.php +++ b/tests/text_processing/message_parser_test.php @@ -61,6 +61,13 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case ->method('lang') ->will($this->returnValueMap($map)); + $user->data = array( + 'is_bot' => false, + 'is_registered' => true, + 'user_id' => 2, + ); + $user->style = array('style_id' => 1); + $user->lang = array( 'NO_POLL_TITLE' => 'You have to enter a poll title.', 'POLL_TITLE_TOO_LONG' => 'The poll title must contain fewer than 100 characters.', @@ -76,7 +83,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case if (isset($setup)) { - $setup($parser, $phpbb_container, $this); + $setup($phpbb_container, $this); } $this->get_test_case_helpers()->set_s9e_services($phpbb_container); @@ -286,7 +293,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[size=200]200[/size]', '[size=200]200[/size]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_font_size', 200); } @@ -295,7 +302,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[size=200]200[/size]', '[size=200]200[/size]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_font_size', 0); } @@ -304,7 +311,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[size=2000]2000[/size]', '[size=2000]2000[/size]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_font_size', 200); }, @@ -314,7 +321,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[size=0]0[/size]', '[size=0]0[/size]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_font_size', 200); } @@ -323,7 +330,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[size=200]200[/size]', '[size=200]200[/size]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_sig_font_size', 200); } @@ -332,7 +339,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[size=200]200[/size]', '[size=200]200[/size]', array(true, true, true, true, true, true, true, true, 'sig'), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_sig_font_size', 120); }, @@ -342,7 +349,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[img]http://example.org/100x100.png[/img]', '[img]http://example.org/100x100.png[/img]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_img_height', 12); }, @@ -352,7 +359,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[img]http://example.org/100x100.png[/img]', '[img]http://example.org/100x100.png[/img]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_img_width', 34); }, @@ -362,7 +369,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[img]http://example.org/100x100.png[/img]', '[img]http://example.org/100x100.png[/img]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_img_height', 0); $phpbb_container->get('config')->set('max_post_img_width', 0); @@ -372,7 +379,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[img]http://example.org/100x100.png[/img]', '[img]http://example.org/100x100.png[/img]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_img_height', 100); $phpbb_container->get('config')->set('max_post_img_width', 100); @@ -382,7 +389,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[img]http://example.org/100x100.png[/img]', '[img]http://example.org/100x100.png[/img]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_sig_img_height', 12); $phpbb_container->get('config')->set('max_sig_img_width', 34); @@ -392,7 +399,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[img]http://example.org/404.png[/img]', '[img]http://example.org/404.png[/img]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_img_height', 12); }, @@ -402,7 +409,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[flash=999,999]http://example.org/foo.swf[/flash]', '[flash=999,999]http://example.org/foo.swf[/flash]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_img_height', 123); }, @@ -412,7 +419,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case '[flash=999,999]http://example.org/foo.swf[/flash]', '[flash=999,999]http://example.org/foo.swf[/flash]', array(true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_img_width', 456); }, @@ -422,7 +429,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case ':) :) :)', ':) :) :)', array(true, true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_smilies', 3); } @@ -431,7 +438,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case ':) :) :) :)', ':) :) :) :)', array(true, true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_smilies', 3); }, @@ -441,7 +448,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case ':) :) :) :)', ':) :) :) :)', array(true, true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_smilies', 0); } @@ -450,7 +457,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case ':) :) :) :)', ':) :) :) :)', array(true, true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_sig_smilies', 3); } @@ -459,7 +466,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case ':) :) :) :)', ':) :) :) :)', array(true, true, true, true, true, true, true, true, 'sig'), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_sig_smilies', 3); }, @@ -469,7 +476,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case 'http://example.org http://example.org http://example.org', 'http://example.org http://example.org http://example.org', array(true, true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_urls', 2); }, @@ -479,7 +486,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case 'http://example.org http://example.org http://example.org', 'http://example.org http://example.org http://example.org', array(true, true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_post_urls', 0); } @@ -488,7 +495,7 @@ class phpbb_text_processing_message_parser_test extends phpbb_test_case 'http://example.org http://example.org http://example.org', 'http://example.org http://example.org http://example.org', array(true, true, true, true, true, true, true, true), - function ($parser, $phpbb_container) + function ($phpbb_container) { $phpbb_container->get('config')->set('max_sig_urls', 2); } From c56e2fa2bf44d85008ee0629c956357eff072033 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 28 May 2015 15:52:18 +0200 Subject: [PATCH 0334/1676] [ticket/13872] Remove subsilver2 from md exporter test PHPBB3-13872 --- tests/event/md_exporter_test.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/event/md_exporter_test.php b/tests/event/md_exporter_test.php index d28e3d611c..a6c1dc78de 100644 --- a/tests/event/md_exporter_test.php +++ b/tests/event/md_exporter_test.php @@ -23,7 +23,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case 'event' => 'acp_bbcodes_actions_append', 'files' => array( 'prosilver' => array(), - 'subsilver2' => array(), 'adm' => array('acp_bbcodes.html'), ), 'since' => '3.1.0-a3', @@ -36,7 +35,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case 'event' => 'acp_bbcodes_actions_prepend', 'files' => array( 'prosilver' => array(), - 'subsilver2' => array(), 'adm' => array('acp_bbcodes.html'), ), 'since' => '3.1.0-a5', @@ -47,7 +45,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case 'event' => 'acp_bbcodes_actions_prepend2', 'files' => array( 'prosilver' => array(), - 'subsilver2' => array(), 'adm' => array('acp_bbcodes.html'), ), 'since' => '3.1.0-a4', @@ -63,7 +60,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case 'event' => 'acp_bbcodes_actions_prepend', 'files' => array( 'prosilver' => array(), - 'subsilver2' => array(), 'adm' => array('acp_bbcodes.html'), ), 'since' => '3.1.0-a5', @@ -74,7 +70,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case 'event' => 'acp_bbcodes_actions_prepend2', 'files' => array( 'prosilver' => array(), - 'subsilver2' => array(), 'adm' => array('acp_bbcodes.html'), ), 'since' => '3.1.0-a4', From 6641ed64785d9e6199bb7b8402b8d3a296c90ae5 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 29 May 2015 14:52:31 +0200 Subject: [PATCH 0335/1676] [ticket/13890] Fix di tests PHPBB3-13890 --- .../config/production/container/environment.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/di/fixtures/config/production/container/environment.yml b/tests/di/fixtures/config/production/container/environment.yml index 6ac07a44d9..9dcf11d865 100644 --- a/tests/di/fixtures/config/production/container/environment.yml +++ b/tests/di/fixtures/config/production/container/environment.yml @@ -15,3 +15,15 @@ services: ext.manager: class: phpbb\extension\manager_mock + + template.twig.environment: + class: Exception + arguments: + - ~ + - ~ + - ~ + - ~ + - ~ + - ~ + - ~ + - [] From 467c794b9779412cf2cc29deb42c232168989486 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 16:05:16 +0200 Subject: [PATCH 0336/1676] [ticket/6466] Use jQuery and custom dropdown for permission roles tooltips PHPBB3-6466 --- phpBB/adm/style/acp_permissions.html | 9 +- phpBB/adm/style/admin.css | 33 +++++++ phpBB/adm/style/permission_mask.html | 13 ++- phpBB/adm/style/tooltip.js | 129 ++++++++++++++------------- phpBB/includes/acp/auth.php | 6 ++ 5 files changed, 119 insertions(+), 71 deletions(-) diff --git a/phpBB/adm/style/acp_permissions.html b/phpBB/adm/style/acp_permissions.html index 6dc9dca2e7..004027df41 100644 --- a/phpBB/adm/style/acp_permissions.html +++ b/phpBB/adm/style/acp_permissions.html @@ -327,14 +327,9 @@

              - - + -
              + {S_HIDDEN_FIELDS} diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index b03cb0ba24..8ae39b7754 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -2435,6 +2435,39 @@ fieldset.permissions .padding { display: none !important; } +.roles-options > .dropdown { + left: auto; + top: 3em; + width: 250px; +} + +.roles-options { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; + width: 250px; +} + +.roles-options > span { + border: 1px solid #DEDEDE; + border-radius: 3px; + padding: 4px; + width: 250px; + display: block; + background: url('../images/arrow_down.gif') no-repeat 245px .7em; +} + +.roles-options li { + list-style: none; +} + +.roles-highlight { + background-color: #1e90ff; + color: #fff; +} + /* Classes for additional tasks ---------------------------------------- */ diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 7b5c071693..5aeafba476 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -40,7 +40,18 @@
              -
              +
              + +
              {L_NO_ROLE_AVAILABLE}
              diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 3a89008706..ec170ef6b2 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -10,7 +10,12 @@ phpBB Development Team: - further adjustements */ -var head_text, tooltip_mode; +(function($) { // Avoid conflicts with other libraries + +"use strict"; + +var head_text, tooltip_mode, tooltips; +tooltips = []; /** * Enable tooltip replacements for links @@ -54,7 +59,7 @@ function enable_tooltips_link(id, headline, sub_id) { * Enable tooltip replacements for selects */ function enable_tooltips_select(id, headline, sub_id) { - var links, i, hold; + var $links, hold; head_text = headline; @@ -66,24 +71,25 @@ function enable_tooltips_select(id, headline, sub_id) { hold.id = '_tooltip_container'; hold.setAttribute('id', '_tooltip_container'); hold.style.position = 'absolute'; - - document.getElementsByTagName('body')[0].appendChild(hold); + $('body').append(hold); if (id === null) { - links = document.getElementsByTagName('option'); + $links = $('.roles-options li'); } else { - links = document.getElementById(id).getElementsByTagName('option'); + $links = $('#' + id + ' .roles-options li'); } - for (i = 0; i < links.length; i++) { + $links.each(function () { + var $this = $(this); + if (sub_id) { - if (links[i].parentNode.id.substr(0, sub_id.length) === sub_id) { - prepare(links[i]); + if ($this.parent().attr('id').substr(0, sub_id.length) === sub_id) { + prepare($this); } } else { - prepare(links[i]); + prepare($this); } - } + }); tooltip_mode = 'select'; } @@ -91,16 +97,15 @@ function enable_tooltips_select(id, headline, sub_id) { /** * Prepare elements to replace */ -function prepare(element) { +function prepare($element) { var tooltip, text, desc, title; - text = element.getAttribute('title'); + text = $element.attr('data-title');; if (text === null || text.length === 0) { return; } - element.removeAttribute('title'); tooltip = create_element('span', 'tooltip'); title = create_element('span', 'top'); @@ -113,12 +118,12 @@ function prepare(element) { set_opacity(tooltip); - element.tooltip = tooltip; - element.onmouseover = show_tooltip; - element.onmouseout = hide_tooltip; + tooltips[$element.attr('data-id')] = tooltip; + $element.on('mouseover', show_tooltip); + $element.on('mouseout', hide_tooltip); if (tooltip_mode === 'link') { - element.onmousemove = locate; + $element.onmousemove = locate; } } @@ -126,8 +131,9 @@ function prepare(element) { * Show tooltip */ function show_tooltip(e) { - document.getElementById('_tooltip_container').appendChild(this.tooltip); - locate(this); + var $this = $(e.target); + $('#_tooltip_container').append(tooltips[$this.attr('data-id')]); + locate($this); } /** @@ -164,52 +170,49 @@ function create_element(tag, c) { * Correct positioning of tooltip container */ function locate(e) { - var posx = 0; - var posy = 0; + var offset; - e = e.parentNode; - - if (e.offsetParent) { - for (posx = 0, posy = 0; e.offsetParent; e = e.offsetParent) { - posx += e.offsetLeft; - posy += e.offsetTop; - } - } else { - posx = e.offsetLeft; - posy = e.offsetTop; - } + e = e.parent(); + offset = e.offset(); if (tooltip_mode === 'link') { - document.getElementById('_tooltip_container').style.top=(posy+20) + 'px'; - document.getElementById('_tooltip_container').style.left=(posx-20) + 'px'; + $('#_tooltip_container').css({ + top: offset.top + 20, + left: offset.left - 20 + }); } else { - document.getElementById('_tooltip_container').style.top=(posy+30) + 'px'; - document.getElementById('_tooltip_container').style.left=(posx-205) + 'px'; + $('#_tooltip_container').css({ + top: offset.top + 30, + left: offset.left - 205 + }); } - -/* - if (e == null) - { - e = window.event; - } - - if (e.pageX || e.pageY) - { - posx = e.pageX; - posy = e.pageY; - } - else if (e.clientX || e.clientY) - { - if (document.documentElement.scrollTop) - { - posx = e.clientX+document.documentElement.scrollLeft; - posy = e.clientY+document.documentElement.scrollTop; - } - else - { - posx = e.clientX+document.body.scrollLeft; - posy = e.clientY+document.body.scrollTop; - } - } -*/ } + +$(function() { + var $options; + + // Enable tooltips + enable_tooltips_select('set-permissions', $('#set-permissions').attr('data-role-description'), 'role'); + + $options = $('.roles-options li'); + + // Prepare highlighting of select options and settings update + $options.each(function () { + $(this).on('mouseover', function (e) { + var $this = $(this); + $options.removeClass('roles-highlight'); + $this.addClass('roles-highlight'); + }).on('click', function (e) { + var $this = $(this); + + // Update settings + set_role_settings($this.attr('data-id'), $this.attr('data-target-id')); + init_colours($this.attr('data-target-id').replace('advanced', '')); + + // Set selected setting + $this.closest('.roles-options').children('span').text($this.text()); + }); + }); +}); + +})(jQuery); // Avoid conflicts with other libraries diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index 644b1ac7a5..0f149ca907 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -480,6 +480,12 @@ class auth_admin extends \phpbb\auth\auth $title = ($role_description) ? ' title="' . $role_description . '"' : ''; $s_role_options .= ''; + $template->assign_block_vars('role_options', array( + 'ID' => $role_id, + 'ROLE_NAME' => $role_name, + 'TITLE' => $role_description, + 'SELECTED' => $role_id == $current_role_id, + )); } if ($s_role_options) From fc00447520d19ac2e0c6667f1c2cf5e7b41913a2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 16:44:12 +0200 Subject: [PATCH 0337/1676] [ticket/6466] Improve behavior of select and properly save role PHPBB3-6466 --- phpBB/adm/style/permission_mask.html | 5 +++-- phpBB/adm/style/tooltip.js | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 5aeafba476..7569867f8c 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -44,12 +44,13 @@ diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index ec170ef6b2..60222e51d5 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -198,7 +198,16 @@ $(function() { // Prepare highlighting of select options and settings update $options.each(function () { - $(this).on('mouseover', function (e) { + var $this = $(this); + var $roles_options = $this.closest('.roles-options'); + + // Correctly show selected option + if (typeof $this.attr('data-selected') !== 'undefined') { + $this.closest('.roles-options').children('span').text($this.text()); + $('') + } + + $this.on('mouseover', function (e) { var $this = $(this); $options.removeClass('roles-highlight'); $this.addClass('roles-highlight'); @@ -210,7 +219,11 @@ $(function() { init_colours($this.attr('data-target-id').replace('advanced', '')); // Set selected setting - $this.closest('.roles-options').children('span').text($this.text()); + $roles_options.children('span').text($this.text()); + $roles_options.children('input[type=hidden]').val($this.attr('data-id')); + + // Trigger hiding of selection options + $('body').trigger('click'); }); }); }); From 66c0e0c6a83fbf091aa078ab06dd6467c8c6aa11 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 4 May 2015 15:10:33 +0200 Subject: [PATCH 0338/1676] [ticket/13388] Integrate routing and di parameters resolution PHPBB3-13388 --- .../default/container/services_routing.yml | 1 + phpBB/phpbb/routing/router.php | 130 +++++++++++++++++- tests/controller/common_helper_route.php | 24 +++- tests/controller/controller_test.php | 5 +- .../ext/vendor2/foo/config/routing.yml | 4 + tests/pagination/pagination_test.php | 2 +- 6 files changed, 156 insertions(+), 10 deletions(-) diff --git a/phpBB/config/default/container/services_routing.yml b/phpBB/config/default/container/services_routing.yml index 6749202c0d..f76b5e5ede 100644 --- a/phpBB/config/default/container/services_routing.yml +++ b/phpBB/config/default/container/services_routing.yml @@ -2,6 +2,7 @@ services: router: class: phpbb\routing\router arguments: + - @service_container - @filesystem - %core.root_path% - %core.php_ext% diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 2f89d4e884..ca9799ba3e 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -15,6 +15,9 @@ namespace phpbb\routing; use Symfony\Component\Config\ConfigCache; use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; use Symfony\Component\Routing\Matcher\UrlMatcher; @@ -91,18 +94,23 @@ class router implements RouterInterface */ protected $filesystem; + /** + * @var ContainerInterface + */ + protected $container; + /** * Construct method * + * @param ContainerInterface $container DI container * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem helper - * @param string $phpbb_root_path phpBB root path - * @param string $php_ext PHP file extension - * @param string $environment Name of the current environment - * @param manager|null $extension_manager Extension manager - * @param array $routing_files Array of strings containing paths to YAML files - * holding route information + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP file extension + * @param string $environment Name of the current environment + * @param manager $extension_manager Extension manager + * @param array $routing_files Array of strings containing paths to YAML files holding route information */ - public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext, $environment, manager $extension_manager = null, $routing_files = array()) + public function __construct(ContainerInterface $container, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext, $environment, manager $extension_manager = null, $routing_files = array()) { $this->filesystem = $filesystem; $this->extension_manager = $extension_manager; @@ -162,9 +170,117 @@ class router implements RouterInterface } } + $this->resolveParameters($this->route_collection); + return $this; } + /** + * Replaces placeholders with service container parameter values in: + * - the route defaults, + * - the route requirements, + * - the route path, + * - the route host, + * - the route schemes, + * - the route methods. + * + * @param RouteCollection $collection + */ + private function resolveParameters(RouteCollection $collection) + { + foreach ($collection as $route) + { + foreach ($route->getDefaults() as $name => $value) + { + $route->setDefault($name, $this->resolve($value)); + } + + foreach ($route->getRequirements() as $name => $value) + { + if ($name === '_scheme' || $name === '_method') + { + continue; // ignore deprecated requirements to not trigger deprecation warnings + } + + $route->setRequirement($name, $this->resolve($value)); + } + + $route->setPath($this->resolve($route->getPath())); + $route->setHost($this->resolve($route->getHost())); + + $schemes = array(); + foreach ($route->getSchemes() as $scheme) + { + $schemes = array_merge($schemes, explode('|', $this->resolve($scheme))); + } + + $route->setSchemes($schemes); + $methods = array(); + foreach ($route->getMethods() as $method) + { + $methods = array_merge($methods, explode('|', $this->resolve($method))); + } + + $route->setMethods($methods); + $route->setCondition($this->resolve($route->getCondition())); + } + } + /** + * Recursively replaces placeholders with the service container parameters. + * + * @param mixed $value The source which might contain "%placeholders%" + * + * @return mixed The source with the placeholders replaced by the container + * parameters. Arrays are resolved recursively. + * + * @throws ParameterNotFoundException When a placeholder does not exist as a container parameter + * @throws RuntimeException When a container value is not a string or a numeric value + */ + private function resolve($value) + { + if (is_array($value)) + { + foreach ($value as $key => $val) + { + $value[$key] = $this->resolve($val); + } + + return $value; + } + + if (!is_string($value)) + { + return $value; + } + + $container = $this->container; + $escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($container, $value) + { + // skip %% + if (!isset($match[1])) + { + return '%%'; + } + + $resolved = $container->getParameter($match[1]); + if (is_string($resolved) || is_numeric($resolved)) + { + return (string) $resolved; + } + + throw new RuntimeException(sprintf( + 'The container parameter "%s", used in the route configuration value "%s", '. + 'must be a string or numeric, but it is of type %s.', + $match[1], + $value, + gettype($resolved) + ) + ); + }, $value); + + return str_replace('%%', '%', $escapedValue); + } + /** * Get the list of routes * diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index 44e5e12ab0..3c74c16bae 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -89,6 +89,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case $this->user = new \phpbb\user($lang, '\phpbb\datetime');; $container = new phpbb_mock_container_builder(); + $container->setParameter('core.environment', PHPBB_ENVIRONMENT); $cache_path = $phpbb_root_path . 'cache/twig'; $context = new \phpbb\template\context(); $loader = new \phpbb\template\twig\loader($this->filesystem, ''); @@ -121,7 +122,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case ) ); - $this->router = new phpbb_mock_router($this->filesystem, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $this->extension_manager); + $this->router = new phpbb_mock_router($container, $this->filesystem, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $this->extension_manager); $this->router->find_routing_files($this->extension_manager->all_enabled(false)); $this->router->find(dirname(__FILE__) . '/'); // Set correct current phpBB root path @@ -155,6 +156,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case array('controller2', array(), true, false, '/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'), array('controller2', array(), false, false, '/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'), array('controller3', array('p' => 3), true, false, '/' . $this->path_to_app() . 'app.php/foo/bar/p-3', 'no params using empty array'), + + // Resolves DI parameters + array('controller4', array(), true, false, '/' . $this->path_to_app() . 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'), ); } @@ -195,6 +199,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case array('controller2', array(), true, false, '/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'), array('controller2', array(), false, false, '/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'), array('controller3', array('p' => 3), true, false, '/' . $this->path_to_app() . 'foo/bar/p-3', 'no params using empty array'), + + // Resolves DI parameters + array('controller4', array(), true, false, '/' . $this->path_to_app() . 'foo/' . PHPBB_ENVIRONMENT, 'di parameter'), ); } @@ -235,6 +242,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case array('controller2', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'), array('controller2', array(), false, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'), array('controller3', array('p' => 3), true, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/bar/p-3', 'no params using empty array'), + + // Resolves DI parameters + array('controller4', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'), ); } @@ -275,6 +285,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case array('controller2', array(), true, false, 'app.php/foo/bar', 'no params using empty array'), array('controller2', array(), false, false, 'app.php/foo/bar', 'no params using empty array'), array('controller3', array('p' => 3), true, false, 'app.php/foo/bar/p-3', 'no params using empty array'), + + // Resolves DI parameters + array('controller4', array(), true, false, 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'), ); } @@ -315,6 +328,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case array('controller2', array(), true, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'), array('controller2', array(), false, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'), array('controller3', array('p' => 3), true, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/bar/p-3', 'no params using empty array'), + + // Resolves DI parameters + array('controller4', array(), true, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'), ); } @@ -355,6 +371,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case array('controller2', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'), array('controller2', array(), false, false, 'http://localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'), array('controller3', array('p' => 3), true, false, 'http://localhost/' . $this->path_to_app() . 'foo/bar/p-3', 'no params using empty array'), + + // Resolves DI parameters + array('controller4', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'foo/' . PHPBB_ENVIRONMENT, 'di parameter'), ); } @@ -435,6 +454,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case array('controller2', array(), true, false, '//localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'), array('controller2', array(), false, false, '//localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'), array('controller3', array('p' => 3), true, false, '//localhost/' . $this->path_to_app() . 'foo/bar/p-3', 'no params using empty array'), + + // Resolves DI parameters + array('controller4', array(), true, false, '//localhost/' . $this->path_to_app() . 'foo/' . PHPBB_ENVIRONMENT, 'di parameter'), ); } diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php index 5781d3ebc1..d0295d66bc 100644 --- a/tests/controller/controller_test.php +++ b/tests/controller/controller_test.php @@ -40,7 +40,10 @@ class phpbb_controller_controller_test extends phpbb_test_case public function test_router_find_files() { - $router = new \phpbb\routing\router(new \phpbb\filesystem\filesystem(), dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $this->extension_manager); + $container = new phpbb_mock_container_builder(); + $container->setParameter('core.environment', PHPBB_ENVIRONMENT); + + $router = new \phpbb\routing\router($container, new \phpbb\filesystem\filesystem(), dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $this->extension_manager); $router->find_routing_files($this->extension_manager->all_enabled(false)); $routes = $router->find(__DIR__)->get_routes(); diff --git a/tests/controller/ext/vendor2/foo/config/routing.yml b/tests/controller/ext/vendor2/foo/config/routing.yml index e3e8ee5f98..7d4ac7be93 100644 --- a/tests/controller/ext/vendor2/foo/config/routing.yml +++ b/tests/controller/ext/vendor2/foo/config/routing.yml @@ -5,3 +5,7 @@ controller1: include_controller2: resource: "routing_2.yml" prefix: /foo + +controller4: + path: /foo/%core.environment% + defaults: { _controller: foo.controller:handle } diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index 67c3d0a30f..07f9ec9c56 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -41,7 +41,7 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case $manager = new phpbb_mock_extension_manager(dirname(__FILE__) . '/', array()); $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $router = new phpbb_mock_router($filesystem, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $manager); + $router = new phpbb_mock_router(new phpbb_mock_container_builder(), $filesystem, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $manager); $router->find_routing_files($manager->all_enabled(false)); $router->find(dirname(__FILE__) . '/'); From 6656567424843d7118aba1eeb5fc0f4eb61a2e5a Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 29 May 2015 16:37:58 +0200 Subject: [PATCH 0339/1676] [ticket/13388] Address comments PHPBB3-13388 --- phpBB/phpbb/routing/router.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index ca9799ba3e..270b54c4ba 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -195,13 +195,12 @@ class router implements RouterInterface $route->setDefault($name, $this->resolve($value)); } + $requirements = $route->getRequirements(); + unset($requirements['_scheme']); + unset($requirements['_method']); + foreach ($route->getRequirements() as $name => $value) { - if ($name === '_scheme' || $name === '_method') - { - continue; // ignore deprecated requirements to not trigger deprecation warnings - } - $route->setRequirement($name, $this->resolve($value)); } From 80375c98f0f39a957b3348c9384fdc52ba27ea36 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 29 May 2015 16:52:21 +0200 Subject: [PATCH 0340/1676] [ticket/13388] Fix rebase PHPBB3-13388 --- phpBB/phpbb/routing/router.php | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 270b54c4ba..1c27e95e4d 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -112,6 +112,7 @@ class router implements RouterInterface */ public function __construct(ContainerInterface $container, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext, $environment, manager $extension_manager = null, $routing_files = array()) { + $this->container = $container; $this->filesystem = $filesystem; $this->extension_manager = $extension_manager; $this->routing_files = $routing_files; From d129ee6c947c6bf494166c47b2d04c7d66e41ab4 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 29 May 2015 16:53:54 +0200 Subject: [PATCH 0341/1676] [ticket/13388] Fix deprecations PHPBB3-13388 --- phpBB/phpbb/routing/router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 1c27e95e4d..75726011c4 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -200,7 +200,7 @@ class router implements RouterInterface unset($requirements['_scheme']); unset($requirements['_method']); - foreach ($route->getRequirements() as $name => $value) + foreach ($requirements as $name => $value) { $route->setRequirement($name, $this->resolve($value)); } From 4d827b5b994f5efa2ec79583a87facb01897727f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 16:56:24 +0200 Subject: [PATCH 0342/1676] [ticket/6466] Remove remnants of old code PHPBB3-6466 --- phpBB/adm/style/permission_mask.html | 6 +++--- phpBB/includes/acp/auth.php | 26 ++++++-------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 7569867f8c..91894ebc77 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -39,7 +39,7 @@
              - + {% if role_options %}
              - + {% else %}
              {L_NO_ROLE_AVAILABLE}
              - + {% endif %}
              diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index 0f149ca907..efb92685f6 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -470,16 +470,12 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; - $s_role_options = ''; - @reset($roles); while (list($role_id, $role_row) = each($roles)) { $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; - $title = ($role_description) ? ' title="' . $role_description . '"' : ''; - $s_role_options .= ''; $template->assign_block_vars('role_options', array( 'ID' => $role_id, 'ROLE_NAME' => $role_name, @@ -488,11 +484,6 @@ class auth_admin extends \phpbb\auth\auth )); } - if ($s_role_options) - { - $s_role_options = '' . $s_role_options; - } - if (!$current_role_id && $mode != 'view') { $s_custom_permissions = false; @@ -513,7 +504,6 @@ class auth_admin extends \phpbb\auth\auth $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array( 'NAME' => $ug_names_ary[$ug_id], - 'S_ROLE_OPTIONS' => $s_role_options, 'UG_ID' => $ug_id, 'S_CUSTOM' => $s_custom_permissions, 'FORUM_ID' => $forum_id) @@ -562,21 +552,18 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; - $s_role_options = ''; - @reset($roles); while (list($role_id, $role_row) = each($roles)) { $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; - $title = ($role_description) ? ' title="' . $role_description . '"' : ''; - $s_role_options .= ''; - } - - if ($s_role_options) - { - $s_role_options = '' . $s_role_options; + $template->assign_block_vars('role_options', array( + 'ID' => $role_id, + 'ROLE_NAME' => $role_name, + 'TITLE' => $role_description, + 'SELECTED' => $role_id == $current_role_id, + )); } if (!$current_role_id && $mode != 'view') @@ -600,7 +587,6 @@ class auth_admin extends \phpbb\auth\auth $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array( 'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'], 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'], - 'S_ROLE_OPTIONS' => $s_role_options, 'S_CUSTOM' => $s_custom_permissions, 'UG_ID' => $ug_id, 'FORUM_ID' => $forum_id) From faa5ab5899afc1023c7b42bd835e98c42d70eaa4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 17:06:14 +0200 Subject: [PATCH 0343/1676] [ticket/6466] Improved code in tooltip.js PHPBB3-6466 --- phpBB/adm/style/tooltip.js | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 60222e51d5..feaa698c9a 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -12,7 +12,7 @@ phpBB Development Team: (function($) { // Avoid conflicts with other libraries -"use strict"; +'use strict'; var head_text, tooltip_mode, tooltips; tooltips = []; @@ -56,7 +56,10 @@ function enable_tooltips_link(id, headline, sub_id) { } /** -* Enable tooltip replacements for selects + * Enable tooltip replacements for selects + * @param {string} id ID tag of select + * @param {string} headline Text that should appear on top of tooltip + * @param {string} sub_id Sub ID that should only be using tooltips (optional) */ function enable_tooltips_select(id, headline, sub_id) { var $links, hold; @@ -76,7 +79,7 @@ function enable_tooltips_select(id, headline, sub_id) { if (id === null) { $links = $('.roles-options li'); } else { - $links = $('#' + id + ' .roles-options li'); + $links = $('.roles-options li', '#' + id); } $links.each(function () { @@ -95,7 +98,9 @@ function enable_tooltips_select(id, headline, sub_id) { } /** -* Prepare elements to replace + * Prepare elements to replace + * + * @param {object} $element Element to prepare for tooltips */ function prepare($element) { var tooltip, text, desc, title; @@ -128,18 +133,22 @@ function prepare($element) { } /** -* Show tooltip + * Show tooltip + * + * @param {object} $element Element passed by .on() */ -function show_tooltip(e) { - var $this = $(e.target); +function show_tooltip($element) { + var $this = $($element.target); $('#_tooltip_container').append(tooltips[$this.attr('data-id')]); locate($this); } /** -* Hide tooltip + * Hide tooltip + * + * @param {object} $element Element passed by .on() */ -function hide_tooltip(e) { +function hide_tooltip($element) { var d = document.getElementById('_tooltip_container'); if (d.childNodes.length > 0) { d.removeChild(d.firstChild); @@ -167,13 +176,15 @@ function create_element(tag, c) { } /** -* Correct positioning of tooltip container + * Correct positioning of tooltip container + * + * @param {object} $element Tooltip element that should be positioned */ -function locate(e) { +function locate($element) { var offset; - e = e.parent(); - offset = e.offset(); + $element = $element.parent(); + offset = $element.offset(); if (tooltip_mode === 'link') { $('#_tooltip_container').css({ From 795776db4b09195e098d5c9dfd1b2fc8b4012be4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 17:07:47 +0200 Subject: [PATCH 0344/1676] [ticket/6466] Removed link tooltip It wasn't being used anymore and didn't work anymore. PHPBB3-6466 --- phpBB/adm/style/tooltip.js | 61 ++++---------------------------------- 1 file changed, 5 insertions(+), 56 deletions(-) diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index feaa698c9a..5850fa43c2 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -14,47 +14,9 @@ phpBB Development Team: 'use strict'; -var head_text, tooltip_mode, tooltips; +var head_text, tooltips; tooltips = []; -/** -* Enable tooltip replacements for links -*/ -function enable_tooltips_link(id, headline, sub_id) { - var links, i, hold; - - head_text = headline; - - if (!document.getElementById || !document.getElementsByTagName) { - return; - } - - hold = document.createElement('span'); - hold.id = '_tooltip_container'; - hold.setAttribute('id', '_tooltip_container'); - hold.style.position = 'absolute'; - - document.getElementsByTagName('body')[0].appendChild(hold); - - if (id === null) { - links = document.getElementsByTagName('a'); - } else { - links = document.getElementById(id).getElementsByTagName('a'); - } - - for (i = 0; i < links.length; i++) { - if (sub_id) { - if (links[i].id.substr(0, sub_id.length) === sub_id) { - prepare(links[i]); - } - } else { - prepare(links[i]); - } - } - - tooltip_mode = 'link'; -} - /** * Enable tooltip replacements for selects * @param {string} id ID tag of select @@ -93,8 +55,6 @@ function enable_tooltips_select(id, headline, sub_id) { prepare($this); } }); - - tooltip_mode = 'select'; } /** @@ -126,10 +86,6 @@ function prepare($element) { tooltips[$element.attr('data-id')] = tooltip; $element.on('mouseover', show_tooltip); $element.on('mouseout', hide_tooltip); - - if (tooltip_mode === 'link') { - $element.onmousemove = locate; - } } /** @@ -186,17 +142,10 @@ function locate($element) { $element = $element.parent(); offset = $element.offset(); - if (tooltip_mode === 'link') { - $('#_tooltip_container').css({ - top: offset.top + 20, - left: offset.left - 20 - }); - } else { - $('#_tooltip_container').css({ - top: offset.top + 30, - left: offset.left - 205 - }); - } + $('#_tooltip_container').css({ + top: offset.top + 30, + left: offset.left - 205 + }); } $(function() { From 75e1cbdc7728329f1c5d7375417e891c8d764fb5 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 17:08:17 +0200 Subject: [PATCH 0345/1676] [ticket/6466] Remove double semicolon PHPBB3-6466 --- phpBB/adm/style/tooltip.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 5850fa43c2..89736e40f7 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -65,7 +65,7 @@ function enable_tooltips_select(id, headline, sub_id) { function prepare($element) { var tooltip, text, desc, title; - text = $element.attr('data-title');; + text = $element.attr('data-title'); if (text === null || text.length === 0) { return; From abf0be4b4c7c646ad35e5943fda1f0bb4a5e2a84 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 17:18:03 +0200 Subject: [PATCH 0346/1676] [ticket/6466] Get rid of useless variables and functions in tooltip.js PHPBB3-6466 --- phpBB/adm/style/admin.css | 1 + phpBB/adm/style/tooltip.js | 41 +++++++++++++------------------------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index 8ae39b7754..145bcfaec1 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -1858,6 +1858,7 @@ li.pagination ul { color: #000; text-align: center; border: 1px solid #AAA; + opacity: .95; } .tooltip span.top { diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 89736e40f7..8e05cec30b 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -14,8 +14,7 @@ phpBB Development Team: 'use strict'; -var head_text, tooltips; -tooltips = []; +var tooltips = []; /** * Enable tooltip replacements for selects @@ -26,12 +25,6 @@ tooltips = []; function enable_tooltips_select(id, headline, sub_id) { var $links, hold; - head_text = headline; - - if (!document.getElementById || !document.getElementsByTagName) { - return; - } - hold = document.createElement('span'); hold.id = '_tooltip_container'; hold.setAttribute('id', '_tooltip_container'); @@ -49,10 +42,10 @@ function enable_tooltips_select(id, headline, sub_id) { if (sub_id) { if ($this.parent().attr('id').substr(0, sub_id.length) === sub_id) { - prepare($this); + prepare($this, headline); } } else { - prepare($this); + prepare($this, headline); } }); } @@ -61,8 +54,9 @@ function enable_tooltips_select(id, headline, sub_id) { * Prepare elements to replace * * @param {object} $element Element to prepare for tooltips + * @param {string} head_text Text heading to display */ -function prepare($element) { +function prepare($element, head_text) { var tooltip, text, desc, title; text = $element.attr('data-title'); @@ -71,17 +65,15 @@ function prepare($element) { return; } - tooltip = create_element('span', 'tooltip'); - title = create_element('span', 'top'); title.appendChild(document.createTextNode(head_text)); - tooltip.appendChild(title); desc = create_element('span', 'bottom'); desc.innerHTML = text; - tooltip.appendChild(desc); - set_opacity(tooltip); + tooltip = create_element('span', 'tooltip'); + tooltip.appendChild(title); + tooltip.appendChild(desc); tooltips[$element.attr('data-id')] = tooltip; $element.on('mouseover', show_tooltip); @@ -112,17 +104,12 @@ function hide_tooltip($element) { } /** -* Set opacity on tooltip element -*/ -function set_opacity(element) { - element.style.filter = 'alpha(opacity:95)'; - element.style.KHTMLOpacity = '0.95'; - element.style.MozOpacity = '0.95'; - element.style.opacity = '0.95'; -} - -/** -* Create new element + * Create new element + * + * @param {string} tag HTML tag + * @param {string} c Element's class + * + * @return {object} Created element */ function create_element(tag, c) { var x = document.createElement(tag); From 120600e055c9220982ff4639f114d6bd60eaa41f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 17:34:42 +0200 Subject: [PATCH 0347/1676] [ticket/6466] Rename functions and clean up code PHPBB3-6466 --- phpBB/adm/style/tooltip.js | 64 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 8e05cec30b..2798592c3d 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -22,7 +22,7 @@ var tooltips = []; * @param {string} headline Text that should appear on top of tooltip * @param {string} sub_id Sub ID that should only be using tooltips (optional) */ -function enable_tooltips_select(id, headline, sub_id) { +phpbb.enableTooltipsSelect = function (id, headline, sub_id) { var $links, hold; hold = document.createElement('span'); @@ -42,13 +42,13 @@ function enable_tooltips_select(id, headline, sub_id) { if (sub_id) { if ($this.parent().attr('id').substr(0, sub_id.length) === sub_id) { - prepare($this, headline); + phpbb.prepareTooltips($this, headline); } } else { - prepare($this, headline); + phpbb.prepareTooltips($this, headline); } }); -} +}; /** * Prepare elements to replace @@ -56,7 +56,7 @@ function enable_tooltips_select(id, headline, sub_id) { * @param {object} $element Element to prepare for tooltips * @param {string} head_text Text heading to display */ -function prepare($element, head_text) { +phpbb.prepareTooltips = function ($element, head_text) { var tooltip, text, desc, title; text = $element.attr('data-title'); @@ -65,43 +65,43 @@ function prepare($element, head_text) { return; } - title = create_element('span', 'top'); + title = phpbb.createElement('span', 'top'); title.appendChild(document.createTextNode(head_text)); - desc = create_element('span', 'bottom'); + desc = phpbb.createElement('span', 'bottom'); desc.innerHTML = text; - tooltip = create_element('span', 'tooltip'); + tooltip = phpbb.createElement('span', 'tooltip'); tooltip.appendChild(title); tooltip.appendChild(desc); tooltips[$element.attr('data-id')] = tooltip; - $element.on('mouseover', show_tooltip); - $element.on('mouseout', hide_tooltip); -} + $element.on('mouseover', phpbb.showTooltip); + $element.on('mouseout', phpbb.hideTooltip); +}; /** * Show tooltip * * @param {object} $element Element passed by .on() */ -function show_tooltip($element) { +phpbb.showTooltip = function ($element) { var $this = $($element.target); $('#_tooltip_container').append(tooltips[$this.attr('data-id')]); - locate($this); -} + phpbb.positionTooltip($this); +}; /** * Hide tooltip * * @param {object} $element Element passed by .on() */ -function hide_tooltip($element) { +phpbb.hideTooltip = function () { var d = document.getElementById('_tooltip_container'); if (d.childNodes.length > 0) { d.removeChild(d.firstChild); } -} +}; /** * Create new element @@ -111,19 +111,19 @@ function hide_tooltip($element) { * * @return {object} Created element */ -function create_element(tag, c) { +phpbb.createElement = function (tag, c) { var x = document.createElement(tag); x.className = c; x.style.display = 'block'; return x; -} +}; /** * Correct positioning of tooltip container * * @param {object} $element Tooltip element that should be positioned */ -function locate($element) { +phpbb.positionTooltip = function ($element) { var offset; $element = $element.parent(); @@ -133,25 +133,22 @@ function locate($element) { top: offset.top + 30, left: offset.left - 205 }); -} +}; -$(function() { - var $options; - - // Enable tooltips - enable_tooltips_select('set-permissions', $('#set-permissions').attr('data-role-description'), 'role'); - - $options = $('.roles-options li'); +/** + * Prepare roles drop down select + */ +phpbb.prepareRolesDropdown = function () { + var $options = $('.roles-options li'); // Prepare highlighting of select options and settings update - $options.each(function () { + $options.each(function (element) { var $this = $(this); var $roles_options = $this.closest('.roles-options'); // Correctly show selected option if (typeof $this.attr('data-selected') !== 'undefined') { $this.closest('.roles-options').children('span').text($this.text()); - $('') } $this.on('mouseover', function (e) { @@ -173,6 +170,15 @@ $(function() { $('body').trigger('click'); }); }); +}; + +// Run onload functions for RolesDropdown and tooltips +$(function() { + // Enable tooltips + phpbb.enableTooltipsSelect('set-permissions', $('#set-permissions').attr('data-role-description'), 'role'); + + // Prepare dropdown + phpbb.prepareRolesDropdown(); }); })(jQuery); // Avoid conflicts with other libraries From c8bb0fd24179f9c2d639e53c896dd28f7d5562f8 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 17:35:53 +0200 Subject: [PATCH 0348/1676] [ticket/6466] Improve code in tooltip.js PHPBB3-6466 --- phpBB/adm/style/tooltip.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 2798592c3d..68750b8663 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -93,8 +93,6 @@ phpbb.showTooltip = function ($element) { /** * Hide tooltip - * - * @param {object} $element Element passed by .on() */ phpbb.hideTooltip = function () { var d = document.getElementById('_tooltip_container'); @@ -142,7 +140,7 @@ phpbb.prepareRolesDropdown = function () { var $options = $('.roles-options li'); // Prepare highlighting of select options and settings update - $options.each(function (element) { + $options.each(function () { var $this = $(this); var $roles_options = $this.closest('.roles-options'); From 0d5f074f54caeeffcc9deea840fb1dc59911a596 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 17:39:03 +0200 Subject: [PATCH 0349/1676] [ticket/6466] Rename variables and remove unused ones PHPBB3-6466 --- phpBB/adm/style/tooltip.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 68750b8663..f78e1da81f 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -20,9 +20,9 @@ var tooltips = []; * Enable tooltip replacements for selects * @param {string} id ID tag of select * @param {string} headline Text that should appear on top of tooltip - * @param {string} sub_id Sub ID that should only be using tooltips (optional) + * @param {string} subId Sub ID that should only be using tooltips (optional) */ -phpbb.enableTooltipsSelect = function (id, headline, sub_id) { +phpbb.enableTooltipsSelect = function (id, headline, subId) { var $links, hold; hold = document.createElement('span'); @@ -31,7 +31,7 @@ phpbb.enableTooltipsSelect = function (id, headline, sub_id) { hold.style.position = 'absolute'; $('body').append(hold); - if (id === null) { + if (!id) { $links = $('.roles-options li'); } else { $links = $('.roles-options li', '#' + id); @@ -40,8 +40,8 @@ phpbb.enableTooltipsSelect = function (id, headline, sub_id) { $links.each(function () { var $this = $(this); - if (sub_id) { - if ($this.parent().attr('id').substr(0, sub_id.length) === sub_id) { + if (subId) { + if ($this.parent().attr('id').substr(0, subId.length) === subId) { phpbb.prepareTooltips($this, headline); } } else { @@ -54,9 +54,9 @@ phpbb.enableTooltipsSelect = function (id, headline, sub_id) { * Prepare elements to replace * * @param {object} $element Element to prepare for tooltips - * @param {string} head_text Text heading to display + * @param {string} headText Text heading to display */ -phpbb.prepareTooltips = function ($element, head_text) { +phpbb.prepareTooltips = function ($element, headText) { var tooltip, text, desc, title; text = $element.attr('data-title'); @@ -66,7 +66,7 @@ phpbb.prepareTooltips = function ($element, head_text) { } title = phpbb.createElement('span', 'top'); - title.appendChild(document.createTextNode(head_text)); + title.appendChild(document.createTextNode(headText)); desc = phpbb.createElement('span', 'bottom'); desc.innerHTML = text; @@ -142,18 +142,18 @@ phpbb.prepareRolesDropdown = function () { // Prepare highlighting of select options and settings update $options.each(function () { var $this = $(this); - var $roles_options = $this.closest('.roles-options'); + var $rolesOptions = $this.closest('.roles-options'); // Correctly show selected option if (typeof $this.attr('data-selected') !== 'undefined') { $this.closest('.roles-options').children('span').text($this.text()); } - $this.on('mouseover', function (e) { + $this.on('mouseover', function () { var $this = $(this); $options.removeClass('roles-highlight'); $this.addClass('roles-highlight'); - }).on('click', function (e) { + }).on('click', function () { var $this = $(this); // Update settings @@ -161,8 +161,8 @@ phpbb.prepareRolesDropdown = function () { init_colours($this.attr('data-target-id').replace('advanced', '')); // Set selected setting - $roles_options.children('span').text($this.text()); - $roles_options.children('input[type=hidden]').val($this.attr('data-id')); + $rolesOptions.children('span').text($this.text()); + $rolesOptions.children('input[type=hidden]').val($this.attr('data-id')); // Trigger hiding of selection options $('body').trigger('click'); From 89cb8a3217edf0f374122e678e48e65a5c86c998 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 29 May 2015 18:06:30 +0200 Subject: [PATCH 0350/1676] [ticket/6466] Minor documentation changes PHPBB3-6466 --- phpBB/adm/style/tooltip.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index f78e1da81f..a52fa36853 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -20,7 +20,7 @@ var tooltips = []; * Enable tooltip replacements for selects * @param {string} id ID tag of select * @param {string} headline Text that should appear on top of tooltip - * @param {string} subId Sub ID that should only be using tooltips (optional) + * @param {string} [subId] Sub ID that should only be using tooltips (optional) */ phpbb.enableTooltipsSelect = function (id, headline, subId) { var $links, hold; @@ -53,7 +53,7 @@ phpbb.enableTooltipsSelect = function (id, headline, subId) { /** * Prepare elements to replace * - * @param {object} $element Element to prepare for tooltips + * @param {jQuery} $element Element to prepare for tooltips * @param {string} headText Text heading to display */ phpbb.prepareTooltips = function ($element, headText) { @@ -119,7 +119,7 @@ phpbb.createElement = function (tag, c) { /** * Correct positioning of tooltip container * - * @param {object} $element Tooltip element that should be positioned + * @param {jQuery} $element Tooltip element that should be positioned */ phpbb.positionTooltip = function ($element) { var offset; From 2e46bef2ecc42a225e53d27c9b7614107b878186 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 30 May 2015 10:54:32 +0200 Subject: [PATCH 0351/1676] [ticket/6466] Remove createElement function from tooltip.js PHPBB3-6466 --- phpBB/adm/style/tooltip.js | 59 ++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index a52fa36853..641d82c80a 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -25,10 +25,13 @@ var tooltips = []; phpbb.enableTooltipsSelect = function (id, headline, subId) { var $links, hold; - hold = document.createElement('span'); - hold.id = '_tooltip_container'; - hold.setAttribute('id', '_tooltip_container'); - hold.style.position = 'absolute'; + hold = $('', { + id: '_tooltip_container', + css: { + position: 'absolute' + } + }); + $('body').append(hold); if (!id) { @@ -57,7 +60,7 @@ phpbb.enableTooltipsSelect = function (id, headline, subId) { * @param {string} headText Text heading to display */ phpbb.prepareTooltips = function ($element, headText) { - var tooltip, text, desc, title; + var $tooltip, text, $desc, $title; text = $element.attr('data-title'); @@ -65,17 +68,32 @@ phpbb.prepareTooltips = function ($element, headText) { return; } - title = phpbb.createElement('span', 'top'); - title.appendChild(document.createTextNode(headText)); + $title = $('', { + class: 'top', + css: { + display: 'block' + } + }) + .append(document.createTextNode(headText)); - desc = phpbb.createElement('span', 'bottom'); - desc.innerHTML = text; + $desc = $('', { + class: 'bottom', + html: text, + css: { + display: 'block' + } + }); - tooltip = phpbb.createElement('span', 'tooltip'); - tooltip.appendChild(title); - tooltip.appendChild(desc); + $tooltip = $('', { + class: 'tooltip', + css: { + display: 'block' + } + }) + .append($title) + .append($desc); - tooltips[$element.attr('data-id')] = tooltip; + tooltips[$element.attr('data-id')] = $tooltip; $element.on('mouseover', phpbb.showTooltip); $element.on('mouseout', phpbb.hideTooltip); }; @@ -101,21 +119,6 @@ phpbb.hideTooltip = function () { } }; -/** - * Create new element - * - * @param {string} tag HTML tag - * @param {string} c Element's class - * - * @return {object} Created element -*/ -phpbb.createElement = function (tag, c) { - var x = document.createElement(tag); - x.className = c; - x.style.display = 'block'; - return x; -}; - /** * Correct positioning of tooltip container * From 44b8dafb233cb07403a303b9c3a5eb72539365d2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 30 May 2015 11:20:04 +0200 Subject: [PATCH 0352/1676] [ticket/6466] Support form reset and do not loose role upon resubmit PHPBB3-6466 --- phpBB/adm/style/permission_mask.html | 2 +- phpBB/adm/style/tooltip.js | 28 ++++++++++++++++++++++++---- phpBB/includes/acp/auth.php | 6 ++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 91894ebc77..347da3181e 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -50,7 +50,7 @@ {% endfor %}
            - +
          {% else %} diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 641d82c80a..68964034f0 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -141,15 +141,20 @@ phpbb.positionTooltip = function ($element) { */ phpbb.prepareRolesDropdown = function () { var $options = $('.roles-options li'); + var $rolesOptions = $options.closest('.roles-options'); + var $span = $rolesOptions.children('span'); // Prepare highlighting of select options and settings update $options.each(function () { var $this = $(this); - var $rolesOptions = $this.closest('.roles-options'); // Correctly show selected option if (typeof $this.attr('data-selected') !== 'undefined') { - $this.closest('.roles-options').children('span').text($this.text()); + $rolesOptions.closest('.roles-options') + .children('span') + .text($this.text()) + .attr('data-default', $this.text()) + .attr('data-default-val', $this.attr('data-id')); } $this.on('mouseover', function () { @@ -164,13 +169,28 @@ phpbb.prepareRolesDropdown = function () { init_colours($this.attr('data-target-id').replace('advanced', '')); // Set selected setting - $rolesOptions.children('span').text($this.text()); - $rolesOptions.children('input[type=hidden]').val($this.attr('data-id')); + $rolesOptions.children('span') + .text($this.text()); + $rolesOptions.children('input[type=hidden]') + .val($this.attr('data-id')); // Trigger hiding of selection options $('body').trigger('click'); }); }); + + // Save default text of drop down if there is no default set yet + if (typeof $span.attr('data-default') === 'undefined') { + $span.attr('data-default', $span.text()); + } + + // Prepare resetting drop down on form reset + $options.closest('form').on('reset', function () { + $span.text($span.attr('data-default')); + $rolesOptions.children('input[type=hidden]') + .val($span.attr('data-id')); + }); + }; // Run onload functions for RolesDropdown and tooltips diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index efb92685f6..b13b1ee040 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -470,6 +470,9 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; + // Output current role id to template + $template->assign_var('S_ROLE_ID', $current_role_id); + @reset($roles); while (list($role_id, $role_row) = each($roles)) { @@ -552,6 +555,9 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; + // Output current role id to template + $template->assign_var('S_ROLE_ID', $current_role_id); + @reset($roles); while (list($role_id, $role_row) = each($roles)) { From 41efc55be99a3a56ed8e1af7ab1bcb0f9d9d88ea Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 30 May 2015 12:27:31 +0200 Subject: [PATCH 0353/1676] [ticket/13896] Fix coding style PHPBB3-13896 --- phpBB/phpbb/language/language_file_loader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/language/language_file_loader.php b/phpBB/phpbb/language/language_file_loader.php index 9862cfc3aa..359202fd63 100644 --- a/phpBB/phpbb/language/language_file_loader.php +++ b/phpBB/phpbb/language/language_file_loader.php @@ -154,7 +154,7 @@ class language_file_loader * * @return string Relative path to language file * - * @throws \phpbb\language\exception\language_file_not_found When the path to the file cannot be resolved + * @throws language_file_not_found When the path to the file cannot be resolved */ protected function get_language_file_path($path, $filename, $locales) { From ea7114e78528f95fae077568573f2b3363f9aab1 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 30 May 2015 13:14:27 +0200 Subject: [PATCH 0354/1676] [ticket/13388] Fix coding style PHPBB3-13388 --- phpBB/phpbb/routing/router.php | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 75726011c4..5af005769f 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -225,6 +225,7 @@ class router implements RouterInterface $route->setCondition($this->resolve($route->getCondition())); } } + /** * Recursively replaces placeholders with the service container parameters. * From de52580a78bcab47a2311f3993fd9952f963d563 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 1 May 2015 05:15:56 +0200 Subject: [PATCH 0355/1676] [ticket/13803] WIP implementation PHPBB3-13803 --- .../container/services_text_reparser.yml | 63 ++++++++++++ phpBB/phpbb/textreparser/base.php | 97 +++++++++++++++++++ phpBB/phpbb/textreparser/forumdescription.php | 63 ++++++++++++ phpBB/phpbb/textreparser/forumrules.php | 63 ++++++++++++ phpBB/phpbb/textreparser/groupdescription.php | 63 ++++++++++++ phpBB/phpbb/textreparser/pmtext.php | 56 +++++++++++ phpBB/phpbb/textreparser/posttext.php | 56 +++++++++++ .../phpbb/textreparser/reparser_interface.php | 32 ++++++ tests/text_reparser/fixtures/posts.xml | 19 ++++ tests/text_reparser/posttext_test.php | 67 +++++++++++++ 10 files changed, 579 insertions(+) create mode 100644 phpBB/config/default/container/services_text_reparser.yml create mode 100644 phpBB/phpbb/textreparser/base.php create mode 100644 phpBB/phpbb/textreparser/forumdescription.php create mode 100644 phpBB/phpbb/textreparser/forumrules.php create mode 100644 phpBB/phpbb/textreparser/groupdescription.php create mode 100644 phpBB/phpbb/textreparser/pmtext.php create mode 100644 phpBB/phpbb/textreparser/posttext.php create mode 100644 phpBB/phpbb/textreparser/reparser_interface.php create mode 100644 tests/text_reparser/fixtures/posts.xml create mode 100644 tests/text_reparser/posttext_test.php diff --git a/phpBB/config/default/container/services_text_reparser.yml b/phpBB/config/default/container/services_text_reparser.yml new file mode 100644 index 0000000000..3113c02f6d --- /dev/null +++ b/phpBB/config/default/container/services_text_reparser.yml @@ -0,0 +1,63 @@ +services: + text_reparser.admin_contact_info: + class: phpbb\textreparser\admincontactinfo + arguments: + - @dbal.conn + tags: + - { name: text_reparser.plugin } + + text_reparser.forum_description: + class: phpbb\textreparser\forumdescription + arguments: + - @dbal.conn + tags: + - { name: text_reparser.plugin } + + text_reparser.forum_rules: + class: phpbb\textreparser\forumrules + arguments: + - @dbal.conn + tags: + - { name: text_reparser.plugin } + + text_reparser.group_description: + class: phpbb\textreparser\groupdescription + arguments: + - @dbal.conn + tags: + - { name: text_reparser.plugin } + + text_reparser.pm_text: + class: phpbb\textreparser\pmtext + arguments: + - @dbal.conn + tags: + - { name: text_reparser.plugin } + + text_reparser.poll_option: + class: phpbb\textreparser\polloption + arguments: + - @dbal.conn + tags: + - { name: text_reparser.plugin } + + text_reparser.poll_title: + class: phpbb\textreparser\polltitle + arguments: + - @dbal.conn + tags: + - { name: text_reparser.plugin } + + text_reparser.post_text: + class: phpbb\textreparser\posttext + arguments: + - @dbal.conn + tags: + - { name: text_reparser.plugin } + + text_reparser.user_signature: + class: phpbb\textreparser\usersignature + arguments: + - @dbal.conn + tags: + - { name: text_reparser.plugin } diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php new file mode 100644 index 0000000000..6aa20d0015 --- /dev/null +++ b/phpBB/phpbb/textreparser/base.php @@ -0,0 +1,97 @@ + +* @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\textreparser; + +abstract class base implements reparser_interface +{ + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * Constructor + * + * @param \phpbb\db\driver\driver_interface $db Database connection + */ + public function __construct(\phpbb\db\driver\driver_interface $db) + { + $this->db = $db; + } + + /** + * {@inheritdoc} + */ + abstract public function get_max_id(); + + /** + * Return all records in given range + * + * @param integer $min_id Lower bound + * @param integer $max_id Upper bound + * @return array Array of record + */ + abstract protected function get_records($min_id, $max_id); + + /** + * {@inheritdoc} + */ + public function reparse_range($min_id, $max_id) + { + foreach ($this->get_records($min_id, $max_id) as $record) + { + $this->reparse_record($record); + } + } + + /** + * Reparse given record + * + * @param array $record Associative array containing the record's data + */ + protected function reparse_record(array $record) + { + $unparsed = array_merge( + $record, + generate_text_for_edit( + $record['text'], + $record['bbcode_uid'], + OPTION_FLAG_BBCODE | OPTION_FLAG_SMILIES | OPTION_FLAG_LINKS + ) + ); + $bitfield = $flags = null; + $parsed_text = $unparsed['text']; + generate_text_for_storage( + $parsed_text, + $unparsed['bbcode_uid'], + $bitfield, + $flags, + $unparsed['enable_bbcode'], + $unparsed['enable_smilies'], + $unparsed['enable_magic_url'] + ); + + // Save the new text if it has changed + if ($parsed_text !== $record['text']) + { + $record['text'] = $parsed_text; + $this->save_record($record); + } + } + + /** + * {@inheritdoc} + */ + abstract protected function save_record(array $record); +} diff --git a/phpBB/phpbb/textreparser/forumdescription.php b/phpBB/phpbb/textreparser/forumdescription.php new file mode 100644 index 0000000000..b715abd825 --- /dev/null +++ b/phpBB/phpbb/textreparser/forumdescription.php @@ -0,0 +1,63 @@ + +* @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\textreparser; + +class forumdescription extends base +{ + /** + * {@inheritdoc} + */ + public function get_max_id() + { + $sql = 'SELECT MAX(forum_id) AS max_id FROM ' . FORUMS_TABLE; + $result = $this->db->sql_query($sql); + $max_id = (int) $this->db->sql_fetchfield('max_id'); + $this->db->sql_freeresult($result); + + return $max_id; + } + + /** + * {@inheritdoc} + */ + protected function get_records($min_id, $max_id) + { + $sql = 'SELECT forum_id AS id, forum_desc AS text, forum_desc_uid AS bbcode_uid + FROM ' . FORUMS_TABLE . ' + WHERE forum_id BETWEEN ' . $min_id . ' AND ' . $max_id; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + // Those fields are not saved to the database, we need to guess their original value + $row['enable_bbcode'] = !empty($row['bbcode_uid']); + $row['enable_smilies'] = (strpos($row['text'], '') !== false); + } + $records = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + return $records; + } + + /** + * {@inheritdoc} + */ + protected function save_record(array $record) + { + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET forum_desc = '" . $this->db->sql_escape($record['text']) . "' + WHERE forum_id = " . $record['id']; + $this->db->sql_query($sql); + } +} diff --git a/phpBB/phpbb/textreparser/forumrules.php b/phpBB/phpbb/textreparser/forumrules.php new file mode 100644 index 0000000000..c0538f6cce --- /dev/null +++ b/phpBB/phpbb/textreparser/forumrules.php @@ -0,0 +1,63 @@ + +* @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\textreparser; + +class forumrules extends base +{ + /** + * {@inheritdoc} + */ + public function get_max_id() + { + $sql = 'SELECT MAX(forum_id) AS max_id FROM ' . FORUMS_TABLE; + $result = $this->db->sql_query($sql); + $max_id = (int) $this->db->sql_fetchfield('max_id'); + $this->db->sql_freeresult($result); + + return $max_id; + } + + /** + * {@inheritdoc} + */ + protected function get_records($min_id, $max_id) + { + $sql = 'SELECT forum_id AS id, forum_rules AS text, forum_rules_uid AS bbcode_uid + FROM ' . FORUMS_TABLE . ' + WHERE forum_id BETWEEN ' . $min_id . ' AND ' . $max_id; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + // Those fields are not saved to the database, we need to guess their original value + $row['enable_bbcode'] = !empty($row['bbcode_uid']); + $row['enable_smilies'] = (strpos($row['text'], '') !== false); + } + $records = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + return $records; + } + + /** + * {@inheritdoc} + */ + protected function save_record(array $record) + { + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET forum_rules = '" . $this->db->sql_escape($record['text']) . "' + WHERE forum_id = " . $record['id']; + $this->db->sql_query($sql); + } +} diff --git a/phpBB/phpbb/textreparser/groupdescription.php b/phpBB/phpbb/textreparser/groupdescription.php new file mode 100644 index 0000000000..608cc806b6 --- /dev/null +++ b/phpBB/phpbb/textreparser/groupdescription.php @@ -0,0 +1,63 @@ + +* @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\textreparser; + +class groupdescription extends base +{ + /** + * {@inheritdoc} + */ + public function get_max_id() + { + $sql = 'SELECT MAX(group_id) AS max_id FROM ' . GROUPS_TABLE; + $result = $this->db->sql_query($sql); + $max_id = (int) $this->db->sql_fetchfield('max_id'); + $this->db->sql_freeresult($result); + + return $max_id; + } + + /** + * {@inheritdoc} + */ + protected function get_records($min_id, $max_id) + { + $sql = 'SELECT group_id AS id, group_desc AS text, group_desc_uid AS bbcode_uid + FROM ' . GROUPS_TABLE . ' + WHERE group_id BETWEEN ' . $min_id . ' AND ' . $max_id; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + // Those fields are not saved to the database, we need to guess their original value + $row['enable_bbcode'] = !empty($row['bbcode_uid']); + $row['enable_smilies'] = (strpos($row['text'], '') !== false); + } + $records = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + return $records; + } + + /** + * {@inheritdoc} + */ + protected function save_record(array $record) + { + $sql = 'UPDATE ' . GROUPS_TABLE . " + SET group_desc = '" . $this->db->sql_escape($record['text']) . "' + WHERE group_id = " . $record['id']; + $this->db->sql_query($sql); + } +} diff --git a/phpBB/phpbb/textreparser/pmtext.php b/phpBB/phpbb/textreparser/pmtext.php new file mode 100644 index 0000000000..e1b27e60fe --- /dev/null +++ b/phpBB/phpbb/textreparser/pmtext.php @@ -0,0 +1,56 @@ + +* @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\textreparser; + +class pmtext extends base +{ + /** + * {@inheritdoc} + */ + public function get_max_id() + { + $sql = 'SELECT MAX(msg_id) AS max_id FROM ' . PRIVMSGS_TABLE; + $result = $this->db->sql_query($sql); + $max_id = (int) $this->db->sql_fetchfield('max_id'); + $this->db->sql_freeresult($result); + + return $max_id; + } + + /** + * {@inheritdoc} + */ + protected function get_records($min_id, $max_id) + { + $sql = 'SELECT msg_id AS id, enable_bbcode, enable_smilies, enable_magic_url, message_text AS text, bbcode_uid + FROM ' . PRIVMSGS_TABLE . ' + WHERE msg_id BETWEEN ' . $min_id . ' AND ' . $max_id; + $result = $this->db->sql_query($sql); + $records = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + return $records; + } + + /** + * {@inheritdoc} + */ + protected function save_record(array $record) + { + $sql = 'UPDATE ' . PRIVMSGS_TABLE . " + SET message_text = '" . $this->db->sql_escape($record['text']) . "' + WHERE msg_id = " . $record['id']; + $this->db->sql_query($sql); + } +} diff --git a/phpBB/phpbb/textreparser/posttext.php b/phpBB/phpbb/textreparser/posttext.php new file mode 100644 index 0000000000..916fc94bfa --- /dev/null +++ b/phpBB/phpbb/textreparser/posttext.php @@ -0,0 +1,56 @@ + +* @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\textreparser; + +class posttext extends base +{ + /** + * {@inheritdoc} + */ + public function get_max_id() + { + $sql = 'SELECT MAX(post_id) AS max_id FROM ' . POSTS_TABLE; + $result = $this->db->sql_query($sql); + $max_id = (int) $this->db->sql_fetchfield('max_id'); + $this->db->sql_freeresult($result); + + return $max_id; + } + + /** + * {@inheritdoc} + */ + protected function get_records($min_id, $max_id) + { + $sql = 'SELECT post_id AS id, enable_bbcode, enable_smilies, enable_magic_url, post_text AS text, bbcode_uid + FROM ' . POSTS_TABLE . ' + WHERE post_id BETWEEN ' . $min_id . ' AND ' . $max_id; + $result = $this->db->sql_query($sql); + $records = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + return $records; + } + + /** + * {@inheritdoc} + */ + protected function save_record(array $record) + { + $sql = 'UPDATE ' . POSTS_TABLE . " + SET post_text = '" . $this->db->sql_escape($record['text']) . "' + WHERE post_id = " . $record['id']; + $this->db->sql_query($sql); + } +} diff --git a/phpBB/phpbb/textreparser/reparser_interface.php b/phpBB/phpbb/textreparser/reparser_interface.php new file mode 100644 index 0000000000..20f8d92b1a --- /dev/null +++ b/phpBB/phpbb/textreparser/reparser_interface.php @@ -0,0 +1,32 @@ + +* @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\textreparser; + +interface reparser_interface +{ + /** + * Return the highest ID for all existing records + * + * @return integer + */ + public function get_max_id(); + + /** + * Reparse all records in given range + * + * @param integer $min_id Lower bound + * @param integer $max_id Upper bound + */ + public function reparse_range($min_id, $max_id); +} diff --git a/tests/text_reparser/fixtures/posts.xml b/tests/text_reparser/fixtures/posts.xml new file mode 100644 index 0000000000..6485293361 --- /dev/null +++ b/tests/text_reparser/fixtures/posts.xml @@ -0,0 +1,19 @@ + + + + post_id + enable_bbcode + enable_smilies + enable_magic_url + post_text + bbcode_uid + + 1 + 1 + 1 + 1 + Plain text + abcd1234 + +
          +
          diff --git a/tests/text_reparser/posttext_test.php b/tests/text_reparser/posttext_test.php new file mode 100644 index 0000000000..4dec53dc63 --- /dev/null +++ b/tests/text_reparser/posttext_test.php @@ -0,0 +1,67 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +require_once __DIR__ . '/../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; +require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; + +class phpbb_textreparser_posttext_test extends phpbb_database_test_case +{ + public function setUp() + { + global $config; + if (!isset($config)) + { + $config = new \phpbb\config\config(array()); + } + $this->get_test_case_helpers()->set_s9e_services(); + parent::setUp(); + } + + public function getDataSet() + { + return $this->createXMLDataSet(__DIR__ . '/fixtures/posts.xml'); + } + + /** + * @dataProvider getReparseTests + */ + public function testReparse($min_id, $max_id, $expected) + { + $db = $this->new_dbal(); + $reparser = new \phpbb\textreparser\posttext($db); + $reparser->reparse_range($min_id, $max_id); + $sql = 'SELECT post_id, post_text + FROM ' . POSTS_TABLE . " + WHERE post_id BETWEEN $min_id AND $max_id"; + $result = $db->sql_query($sql); + $rows = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); + $this->assertEquals($expected, $rows); + } + + public function getReparseTests() + { + return array( + array( + 1, + 1, + array( + array( + 'post_id' => 1, + 'post_text' => 'Plain text' + ) + ) + ), + ); + } +} From e11ae7e9cd5573658b763b1ef72cb889f547f2dd Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 1 May 2015 05:32:48 +0200 Subject: [PATCH 0356/1676] [ticket/13803] Hyphenated class names PHPBB3-13803 --- .../container/services_text_reparser.yml | 18 +++++++++--------- ...umdescription.php => forum_description.php} | 2 +- .../{forumrules.php => forum_rules.php} | 2 +- ...updescription.php => group_description.php} | 2 +- .../textreparser/{pmtext.php => pm_text.php} | 2 +- .../{posttext.php => post_text.php} | 2 +- .../{posttext_test.php => post_text_test.php} | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) rename phpBB/phpbb/textreparser/{forumdescription.php => forum_description.php} (97%) rename phpBB/phpbb/textreparser/{forumrules.php => forum_rules.php} (98%) rename phpBB/phpbb/textreparser/{groupdescription.php => group_description.php} (97%) rename phpBB/phpbb/textreparser/{pmtext.php => pm_text.php} (97%) rename phpBB/phpbb/textreparser/{posttext.php => post_text.php} (97%) rename tests/text_reparser/{posttext_test.php => post_text_test.php} (91%) diff --git a/phpBB/config/default/container/services_text_reparser.yml b/phpBB/config/default/container/services_text_reparser.yml index 3113c02f6d..c458be12ac 100644 --- a/phpBB/config/default/container/services_text_reparser.yml +++ b/phpBB/config/default/container/services_text_reparser.yml @@ -1,62 +1,62 @@ services: text_reparser.admin_contact_info: - class: phpbb\textreparser\admincontactinfo + class: phpbb\textreparser\admin_contact_info arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.forum_description: - class: phpbb\textreparser\forumdescription + class: phpbb\textreparser\forum_description arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.forum_rules: - class: phpbb\textreparser\forumrules + class: phpbb\textreparser\forum_rules arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.group_description: - class: phpbb\textreparser\groupdescription + class: phpbb\textreparser\group_description arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.pm_text: - class: phpbb\textreparser\pmtext + class: phpbb\textreparser\pm_text arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.poll_option: - class: phpbb\textreparser\polloption + class: phpbb\textreparser\poll_option arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.poll_title: - class: phpbb\textreparser\polltitle + class: phpbb\textreparser\poll_title arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.post_text: - class: phpbb\textreparser\posttext + class: phpbb\textreparser\post_text arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.user_signature: - class: phpbb\textreparser\usersignature + class: phpbb\textreparser\user_signature arguments: - @dbal.conn tags: diff --git a/phpBB/phpbb/textreparser/forumdescription.php b/phpBB/phpbb/textreparser/forum_description.php similarity index 97% rename from phpBB/phpbb/textreparser/forumdescription.php rename to phpBB/phpbb/textreparser/forum_description.php index b715abd825..493f8d6c94 100644 --- a/phpBB/phpbb/textreparser/forumdescription.php +++ b/phpBB/phpbb/textreparser/forum_description.php @@ -13,7 +13,7 @@ namespace phpbb\textreparser; -class forumdescription extends base +class forum_description extends base { /** * {@inheritdoc} diff --git a/phpBB/phpbb/textreparser/forumrules.php b/phpBB/phpbb/textreparser/forum_rules.php similarity index 98% rename from phpBB/phpbb/textreparser/forumrules.php rename to phpBB/phpbb/textreparser/forum_rules.php index c0538f6cce..5a3cc7b405 100644 --- a/phpBB/phpbb/textreparser/forumrules.php +++ b/phpBB/phpbb/textreparser/forum_rules.php @@ -13,7 +13,7 @@ namespace phpbb\textreparser; -class forumrules extends base +class forum_rules extends base { /** * {@inheritdoc} diff --git a/phpBB/phpbb/textreparser/groupdescription.php b/phpBB/phpbb/textreparser/group_description.php similarity index 97% rename from phpBB/phpbb/textreparser/groupdescription.php rename to phpBB/phpbb/textreparser/group_description.php index 608cc806b6..61354c832b 100644 --- a/phpBB/phpbb/textreparser/groupdescription.php +++ b/phpBB/phpbb/textreparser/group_description.php @@ -13,7 +13,7 @@ namespace phpbb\textreparser; -class groupdescription extends base +class group_description extends base { /** * {@inheritdoc} diff --git a/phpBB/phpbb/textreparser/pmtext.php b/phpBB/phpbb/textreparser/pm_text.php similarity index 97% rename from phpBB/phpbb/textreparser/pmtext.php rename to phpBB/phpbb/textreparser/pm_text.php index e1b27e60fe..b02cb0083f 100644 --- a/phpBB/phpbb/textreparser/pmtext.php +++ b/phpBB/phpbb/textreparser/pm_text.php @@ -13,7 +13,7 @@ namespace phpbb\textreparser; -class pmtext extends base +class pm_text extends base { /** * {@inheritdoc} diff --git a/phpBB/phpbb/textreparser/posttext.php b/phpBB/phpbb/textreparser/post_text.php similarity index 97% rename from phpBB/phpbb/textreparser/posttext.php rename to phpBB/phpbb/textreparser/post_text.php index 916fc94bfa..288bb0966b 100644 --- a/phpBB/phpbb/textreparser/posttext.php +++ b/phpBB/phpbb/textreparser/post_text.php @@ -13,7 +13,7 @@ namespace phpbb\textreparser; -class posttext extends base +class post_text extends base { /** * {@inheritdoc} diff --git a/tests/text_reparser/posttext_test.php b/tests/text_reparser/post_text_test.php similarity index 91% rename from tests/text_reparser/posttext_test.php rename to tests/text_reparser/post_text_test.php index 4dec53dc63..dc13cebf44 100644 --- a/tests/text_reparser/posttext_test.php +++ b/tests/text_reparser/post_text_test.php @@ -14,7 +14,7 @@ require_once __DIR__ . '/../../phpBB/includes/functions.php'; require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; -class phpbb_textreparser_posttext_test extends phpbb_database_test_case +class phpbb_textreparser_post_text_test extends phpbb_database_test_case { public function setUp() { @@ -38,7 +38,7 @@ class phpbb_textreparser_posttext_test extends phpbb_database_test_case public function testReparse($min_id, $max_id, $expected) { $db = $this->new_dbal(); - $reparser = new \phpbb\textreparser\posttext($db); + $reparser = new \phpbb\textreparser\post_text($db); $reparser->reparse_range($min_id, $max_id); $sql = 'SELECT post_id, post_text FROM ' . POSTS_TABLE . " From 986af43f37342953bff548630aa33904c21234f4 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 1 May 2015 08:47:01 +0200 Subject: [PATCH 0357/1676] [ticket/13803] Added plugins PHPBB3-13803 --- .../container/services_text_reparser.yml | 20 +-- phpBB/phpbb/textreparser/base.php | 15 -- .../phpbb/textreparser/forum_description.php | 63 --------- phpBB/phpbb/textreparser/forum_rules.php | 63 --------- .../phpbb/textreparser/group_description.php | 63 --------- .../plugins/admin_contact_info.php | 69 ++++++++++ .../plugins/forum_description.php | 37 +++++ .../textreparser/plugins/forum_rules.php | 37 +++++ .../plugins/group_description.php | 37 +++++ phpBB/phpbb/textreparser/plugins/pm_text.php | 40 ++++++ .../textreparser/plugins/poll_option.php | 50 +++++++ .../phpbb/textreparser/plugins/poll_title.php | 50 +++++++ .../phpbb/textreparser/plugins/post_text.php | 40 ++++++ .../textreparser/plugins/user_signature.php | 37 +++++ phpBB/phpbb/textreparser/pm_text.php | 56 -------- phpBB/phpbb/textreparser/post_text.php | 56 -------- phpBB/phpbb/textreparser/row_based_plugin.php | 128 ++++++++++++++++++ tests/text_reparser/post_text_test.php | 2 +- 18 files changed, 536 insertions(+), 327 deletions(-) delete mode 100644 phpBB/phpbb/textreparser/forum_description.php delete mode 100644 phpBB/phpbb/textreparser/forum_rules.php delete mode 100644 phpBB/phpbb/textreparser/group_description.php create mode 100644 phpBB/phpbb/textreparser/plugins/admin_contact_info.php create mode 100644 phpBB/phpbb/textreparser/plugins/forum_description.php create mode 100644 phpBB/phpbb/textreparser/plugins/forum_rules.php create mode 100644 phpBB/phpbb/textreparser/plugins/group_description.php create mode 100644 phpBB/phpbb/textreparser/plugins/pm_text.php create mode 100644 phpBB/phpbb/textreparser/plugins/poll_option.php create mode 100644 phpBB/phpbb/textreparser/plugins/poll_title.php create mode 100644 phpBB/phpbb/textreparser/plugins/post_text.php create mode 100644 phpBB/phpbb/textreparser/plugins/user_signature.php delete mode 100644 phpBB/phpbb/textreparser/pm_text.php delete mode 100644 phpBB/phpbb/textreparser/post_text.php create mode 100644 phpBB/phpbb/textreparser/row_based_plugin.php diff --git a/phpBB/config/default/container/services_text_reparser.yml b/phpBB/config/default/container/services_text_reparser.yml index c458be12ac..c10a8c600a 100644 --- a/phpBB/config/default/container/services_text_reparser.yml +++ b/phpBB/config/default/container/services_text_reparser.yml @@ -1,62 +1,62 @@ services: text_reparser.admin_contact_info: - class: phpbb\textreparser\admin_contact_info + class: phpbb\textreparser\plugins\admin_contact_info arguments: - - @dbal.conn + - @config_text tags: - { name: text_reparser.plugin } text_reparser.forum_description: - class: phpbb\textreparser\forum_description + class: phpbb\textreparser\plugins\forum_description arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.forum_rules: - class: phpbb\textreparser\forum_rules + class: phpbb\textreparser\plugins\forum_rules arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.group_description: - class: phpbb\textreparser\group_description + class: phpbb\textreparser\plugins\group_description arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.pm_text: - class: phpbb\textreparser\pm_text + class: phpbb\textreparser\plugins\pm_text arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.poll_option: - class: phpbb\textreparser\poll_option + class: phpbb\textreparser\plugins\poll_option arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.poll_title: - class: phpbb\textreparser\poll_title + class: phpbb\textreparser\plugins\poll_title arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.post_text: - class: phpbb\textreparser\post_text + class: phpbb\textreparser\plugins\post_text arguments: - @dbal.conn tags: - { name: text_reparser.plugin } text_reparser.user_signature: - class: phpbb\textreparser\user_signature + class: phpbb\textreparser\plugins\user_signature arguments: - @dbal.conn tags: diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 6aa20d0015..7d1e12c52d 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -15,21 +15,6 @@ namespace phpbb\textreparser; abstract class base implements reparser_interface { - /** - * @var \phpbb\db\driver\driver_interface - */ - protected $db; - - /** - * Constructor - * - * @param \phpbb\db\driver\driver_interface $db Database connection - */ - public function __construct(\phpbb\db\driver\driver_interface $db) - { - $this->db = $db; - } - /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/textreparser/forum_description.php b/phpBB/phpbb/textreparser/forum_description.php deleted file mode 100644 index 493f8d6c94..0000000000 --- a/phpBB/phpbb/textreparser/forum_description.php +++ /dev/null @@ -1,63 +0,0 @@ - -* @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\textreparser; - -class forum_description extends base -{ - /** - * {@inheritdoc} - */ - public function get_max_id() - { - $sql = 'SELECT MAX(forum_id) AS max_id FROM ' . FORUMS_TABLE; - $result = $this->db->sql_query($sql); - $max_id = (int) $this->db->sql_fetchfield('max_id'); - $this->db->sql_freeresult($result); - - return $max_id; - } - - /** - * {@inheritdoc} - */ - protected function get_records($min_id, $max_id) - { - $sql = 'SELECT forum_id AS id, forum_desc AS text, forum_desc_uid AS bbcode_uid - FROM ' . FORUMS_TABLE . ' - WHERE forum_id BETWEEN ' . $min_id . ' AND ' . $max_id; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // Those fields are not saved to the database, we need to guess their original value - $row['enable_bbcode'] = !empty($row['bbcode_uid']); - $row['enable_smilies'] = (strpos($row['text'], '') !== false); - } - $records = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - - return $records; - } - - /** - * {@inheritdoc} - */ - protected function save_record(array $record) - { - $sql = 'UPDATE ' . FORUMS_TABLE . " - SET forum_desc = '" . $this->db->sql_escape($record['text']) . "' - WHERE forum_id = " . $record['id']; - $this->db->sql_query($sql); - } -} diff --git a/phpBB/phpbb/textreparser/forum_rules.php b/phpBB/phpbb/textreparser/forum_rules.php deleted file mode 100644 index 5a3cc7b405..0000000000 --- a/phpBB/phpbb/textreparser/forum_rules.php +++ /dev/null @@ -1,63 +0,0 @@ - -* @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\textreparser; - -class forum_rules extends base -{ - /** - * {@inheritdoc} - */ - public function get_max_id() - { - $sql = 'SELECT MAX(forum_id) AS max_id FROM ' . FORUMS_TABLE; - $result = $this->db->sql_query($sql); - $max_id = (int) $this->db->sql_fetchfield('max_id'); - $this->db->sql_freeresult($result); - - return $max_id; - } - - /** - * {@inheritdoc} - */ - protected function get_records($min_id, $max_id) - { - $sql = 'SELECT forum_id AS id, forum_rules AS text, forum_rules_uid AS bbcode_uid - FROM ' . FORUMS_TABLE . ' - WHERE forum_id BETWEEN ' . $min_id . ' AND ' . $max_id; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // Those fields are not saved to the database, we need to guess their original value - $row['enable_bbcode'] = !empty($row['bbcode_uid']); - $row['enable_smilies'] = (strpos($row['text'], '') !== false); - } - $records = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - - return $records; - } - - /** - * {@inheritdoc} - */ - protected function save_record(array $record) - { - $sql = 'UPDATE ' . FORUMS_TABLE . " - SET forum_rules = '" . $this->db->sql_escape($record['text']) . "' - WHERE forum_id = " . $record['id']; - $this->db->sql_query($sql); - } -} diff --git a/phpBB/phpbb/textreparser/group_description.php b/phpBB/phpbb/textreparser/group_description.php deleted file mode 100644 index 61354c832b..0000000000 --- a/phpBB/phpbb/textreparser/group_description.php +++ /dev/null @@ -1,63 +0,0 @@ - -* @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\textreparser; - -class group_description extends base -{ - /** - * {@inheritdoc} - */ - public function get_max_id() - { - $sql = 'SELECT MAX(group_id) AS max_id FROM ' . GROUPS_TABLE; - $result = $this->db->sql_query($sql); - $max_id = (int) $this->db->sql_fetchfield('max_id'); - $this->db->sql_freeresult($result); - - return $max_id; - } - - /** - * {@inheritdoc} - */ - protected function get_records($min_id, $max_id) - { - $sql = 'SELECT group_id AS id, group_desc AS text, group_desc_uid AS bbcode_uid - FROM ' . GROUPS_TABLE . ' - WHERE group_id BETWEEN ' . $min_id . ' AND ' . $max_id; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // Those fields are not saved to the database, we need to guess their original value - $row['enable_bbcode'] = !empty($row['bbcode_uid']); - $row['enable_smilies'] = (strpos($row['text'], '') !== false); - } - $records = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - - return $records; - } - - /** - * {@inheritdoc} - */ - protected function save_record(array $record) - { - $sql = 'UPDATE ' . GROUPS_TABLE . " - SET group_desc = '" . $this->db->sql_escape($record['text']) . "' - WHERE group_id = " . $record['id']; - $this->db->sql_query($sql); - } -} diff --git a/phpBB/phpbb/textreparser/plugins/admin_contact_info.php b/phpBB/phpbb/textreparser/plugins/admin_contact_info.php new file mode 100644 index 0000000000..e432ddea81 --- /dev/null +++ b/phpBB/phpbb/textreparser/plugins/admin_contact_info.php @@ -0,0 +1,69 @@ + +* @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\textreparser\plugins; + +class admin_contact_info extends \phpbb\textreparser\base +{ + /** + * @var \phpbb\config\db_text + */ + protected $config_text; + + /** + * Constructor + * + * @param \phpbb\config\db_text $config_text + */ + public function __construct(\phpbb\config\db_text $config_text) + { + $this->config_text = $config_text; + } + + /** + * {@inheritdoc} + */ + public function get_max_id() + { + return 1; + } + + /** + * {@inheritdoc} + */ + protected function get_records($min_id, $max_id) + { + $values = $this->config_text->get_array(array( + 'contact_admin_info', + 'contact_admin_info_uid', + 'contact_admin_info_flags', + )); + + return array(array( + 'id' => 1, + 'text' => $values['contact_admin_info'], + 'bbcode_uid' => $values['contact_admin_info_uid'], + 'enable_bbcode' => $values['contact_admin_info_flags'] & OPTION_FLAG_BBCODE, + 'enable_magic_url' => $values['contact_admin_info_flags'] & OPTION_FLAG_LINKS, + 'enable_smilies' => $values['contact_admin_info_flags'] & OPTION_FLAG_SMILIES, + )); + } + + /** + * {@inheritdoc} + */ + protected function save_record(array $record) + { + $this->config_text->set('admin_contact_info', $record['text']); + } +} diff --git a/phpBB/phpbb/textreparser/plugins/forum_description.php b/phpBB/phpbb/textreparser/plugins/forum_description.php new file mode 100644 index 0000000000..d6e95c9638 --- /dev/null +++ b/phpBB/phpbb/textreparser/plugins/forum_description.php @@ -0,0 +1,37 @@ + +* @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\textreparser\plugins; + +class forum_description extends \phpbb\textreparser\row_based_plugin +{ + /** + * {@inheritdoc} + */ + protected function get_columns() + { + return array( + 'id' => 'forum_id', + 'text' => 'forum_desc', + 'bbcode_uid' => 'forum_desc_uid', + ); + } + + /** + * {@inheritdoc} + */ + protected function get_table_name() + { + return FORUMS_TABLE; + } +} diff --git a/phpBB/phpbb/textreparser/plugins/forum_rules.php b/phpBB/phpbb/textreparser/plugins/forum_rules.php new file mode 100644 index 0000000000..36bb595cb9 --- /dev/null +++ b/phpBB/phpbb/textreparser/plugins/forum_rules.php @@ -0,0 +1,37 @@ + +* @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\textreparser\plugins; + +class forum_rules extends \phpbb\textreparser\row_based_plugin +{ + /** + * {@inheritdoc} + */ + protected function get_columns() + { + return array( + 'id' => 'forum_id', + 'text' => 'forum_rules', + 'bbcode_uid' => 'forum_rules_uid', + ); + } + + /** + * {@inheritdoc} + */ + protected function get_table_name() + { + return FORUMS_TABLE; + } +} diff --git a/phpBB/phpbb/textreparser/plugins/group_description.php b/phpBB/phpbb/textreparser/plugins/group_description.php new file mode 100644 index 0000000000..c83079827c --- /dev/null +++ b/phpBB/phpbb/textreparser/plugins/group_description.php @@ -0,0 +1,37 @@ + +* @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\textreparser\plugins; + +class group_description extends \phpbb\textreparser\row_based_plugin +{ + /** + * {@inheritdoc} + */ + protected function get_columns() + { + return array( + 'id' => 'group_id', + 'text' => 'group_desc', + 'bbcode_uid' => 'group_desc_uid', + ); + } + + /** + * {@inheritdoc} + */ + protected function get_table_name() + { + return GROUPS_TABLE; + } +} diff --git a/phpBB/phpbb/textreparser/plugins/pm_text.php b/phpBB/phpbb/textreparser/plugins/pm_text.php new file mode 100644 index 0000000000..f4d87525df --- /dev/null +++ b/phpBB/phpbb/textreparser/plugins/pm_text.php @@ -0,0 +1,40 @@ + +* @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\textreparser\plugins; + +class pm_text extends \phpbb\textreparser\row_based_plugin +{ + /** + * {@inheritdoc} + */ + protected function get_columns() + { + return array( + 'id' => 'msg_id', + 'enable_bbcode' => 'enable_bbcode', + 'enable_smilies' => 'enable_smilies', + 'enable_magic_url' => 'enable_magic_url', + 'text' => 'message_text', + 'bbcode_uid' => 'bbcode_uid', + ); + } + + /** + * {@inheritdoc} + */ + protected function get_table_name() + { + return PRIVMSGS_TABLE; + } +} diff --git a/phpBB/phpbb/textreparser/plugins/poll_option.php b/phpBB/phpbb/textreparser/plugins/poll_option.php new file mode 100644 index 0000000000..f074f1866d --- /dev/null +++ b/phpBB/phpbb/textreparser/plugins/poll_option.php @@ -0,0 +1,50 @@ + +* @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\textreparser\plugins; + +class poll_option extends \phpbb\textreparser\row_based_plugin +{ + /** + * {@inheritdoc} + */ + protected function get_columns() + { + return array( + 'id' => 'poll_option_id', + 'text' => 'poll_option_text', + ); + } + + /** + * {@inheritdoc} + */ + protected function get_records_query($min_id, $max_id) + { + $sql = 'SELECT o.poll_option_id AS id, o.poll_option_text AS text, p.bbcode_uid + FROM ' . POLL_OPTIONS_TABLE . ' o, ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p + WHERE o.poll_option_id BETWEEN ' . $min_id . ' AND ' . $max_id .' + AND t.topic_id = o.topic_id + AND p.post_id = t.topic_first_post_id'; + + return $sql; + } + + /** + * {@inheritdoc} + */ + protected function get_table_name() + { + return POLL_OPTIONS_TABLE; + } +} diff --git a/phpBB/phpbb/textreparser/plugins/poll_title.php b/phpBB/phpbb/textreparser/plugins/poll_title.php new file mode 100644 index 0000000000..e794780eba --- /dev/null +++ b/phpBB/phpbb/textreparser/plugins/poll_title.php @@ -0,0 +1,50 @@ + +* @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\textreparser\plugins; + +class poll_title extends \phpbb\textreparser\row_based_plugin +{ + /** + * {@inheritdoc} + */ + protected function get_columns() + { + return array( + 'id' => 'topic_id', + 'text' => 'poll_title', + ); + } + + /** + * {@inheritdoc} + */ + protected function get_records_query($min_id, $max_id) + { + $sql = 'SELECT t.topic_id AS id, t.poll_title AS text, p.bbcode_uid + FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p + WHERE t.topic_id BETWEEN ' . $min_id . ' AND ' . $max_id .' + AND t.poll_max_options > 0 + AND p.post_id = t.topic_first_post_id'; + + return $sql; + } + + /** + * {@inheritdoc} + */ + protected function get_table_name() + { + return TOPICS_TABLE; + } +} diff --git a/phpBB/phpbb/textreparser/plugins/post_text.php b/phpBB/phpbb/textreparser/plugins/post_text.php new file mode 100644 index 0000000000..2b16518b03 --- /dev/null +++ b/phpBB/phpbb/textreparser/plugins/post_text.php @@ -0,0 +1,40 @@ + +* @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\textreparser\plugins; + +class post_text extends \phpbb\textreparser\row_based_plugin +{ + /** + * {@inheritdoc} + */ + protected function get_columns() + { + return array( + 'id' => 'post_id', + 'enable_bbcode' => 'enable_bbcode', + 'enable_smilies' => 'enable_smilies', + 'enable_magic_url' => 'enable_magic_url', + 'text' => 'post_text', + 'bbcode_uid' => 'bbcode_uid', + ); + } + + /** + * {@inheritdoc} + */ + protected function get_table_name() + { + return POSTS_TABLE; + } +} diff --git a/phpBB/phpbb/textreparser/plugins/user_signature.php b/phpBB/phpbb/textreparser/plugins/user_signature.php new file mode 100644 index 0000000000..2beaaf98e5 --- /dev/null +++ b/phpBB/phpbb/textreparser/plugins/user_signature.php @@ -0,0 +1,37 @@ + +* @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\textreparser\plugins; + +class user_signature extends \phpbb\textreparser\row_based_plugin +{ + /** + * {@inheritdoc} + */ + protected function get_columns() + { + return array( + 'id' => 'user_id', + 'text' => 'user_sig', + 'bbcode_uid' => 'user_sig_bbcode_uid', + ); + } + + /** + * {@inheritdoc} + */ + protected function get_table_name() + { + return USERS_TABLE; + } +} diff --git a/phpBB/phpbb/textreparser/pm_text.php b/phpBB/phpbb/textreparser/pm_text.php deleted file mode 100644 index b02cb0083f..0000000000 --- a/phpBB/phpbb/textreparser/pm_text.php +++ /dev/null @@ -1,56 +0,0 @@ - -* @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\textreparser; - -class pm_text extends base -{ - /** - * {@inheritdoc} - */ - public function get_max_id() - { - $sql = 'SELECT MAX(msg_id) AS max_id FROM ' . PRIVMSGS_TABLE; - $result = $this->db->sql_query($sql); - $max_id = (int) $this->db->sql_fetchfield('max_id'); - $this->db->sql_freeresult($result); - - return $max_id; - } - - /** - * {@inheritdoc} - */ - protected function get_records($min_id, $max_id) - { - $sql = 'SELECT msg_id AS id, enable_bbcode, enable_smilies, enable_magic_url, message_text AS text, bbcode_uid - FROM ' . PRIVMSGS_TABLE . ' - WHERE msg_id BETWEEN ' . $min_id . ' AND ' . $max_id; - $result = $this->db->sql_query($sql); - $records = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - - return $records; - } - - /** - * {@inheritdoc} - */ - protected function save_record(array $record) - { - $sql = 'UPDATE ' . PRIVMSGS_TABLE . " - SET message_text = '" . $this->db->sql_escape($record['text']) . "' - WHERE msg_id = " . $record['id']; - $this->db->sql_query($sql); - } -} diff --git a/phpBB/phpbb/textreparser/post_text.php b/phpBB/phpbb/textreparser/post_text.php deleted file mode 100644 index 288bb0966b..0000000000 --- a/phpBB/phpbb/textreparser/post_text.php +++ /dev/null @@ -1,56 +0,0 @@ - -* @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\textreparser; - -class post_text extends base -{ - /** - * {@inheritdoc} - */ - public function get_max_id() - { - $sql = 'SELECT MAX(post_id) AS max_id FROM ' . POSTS_TABLE; - $result = $this->db->sql_query($sql); - $max_id = (int) $this->db->sql_fetchfield('max_id'); - $this->db->sql_freeresult($result); - - return $max_id; - } - - /** - * {@inheritdoc} - */ - protected function get_records($min_id, $max_id) - { - $sql = 'SELECT post_id AS id, enable_bbcode, enable_smilies, enable_magic_url, post_text AS text, bbcode_uid - FROM ' . POSTS_TABLE . ' - WHERE post_id BETWEEN ' . $min_id . ' AND ' . $max_id; - $result = $this->db->sql_query($sql); - $records = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - - return $records; - } - - /** - * {@inheritdoc} - */ - protected function save_record(array $record) - { - $sql = 'UPDATE ' . POSTS_TABLE . " - SET post_text = '" . $this->db->sql_escape($record['text']) . "' - WHERE post_id = " . $record['id']; - $this->db->sql_query($sql); - } -} diff --git a/phpBB/phpbb/textreparser/row_based_plugin.php b/phpBB/phpbb/textreparser/row_based_plugin.php new file mode 100644 index 0000000000..2317c79e4f --- /dev/null +++ b/phpBB/phpbb/textreparser/row_based_plugin.php @@ -0,0 +1,128 @@ + +* @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\textreparser; + +abstract class row_based_plugin extends base +{ + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * Constructor + * + * @param \phpbb\db\driver\driver_interface $db Database connection + */ + public function __construct(\phpbb\db\driver\driver_interface $db) + { + $this->db = $db; + } + + /** + * Return the name of the column that correspond to each field + * + * @return array + */ + abstract protected function get_columns(); + + /** + * Return the name of the table used by this plugin + * + * @return string + */ + abstract protected function get_table_name(); + + /** + * {@inheritdoc} + */ + public function get_max_id() + { + $columns = $this->get_columns(); + + $sql = 'SELECT MAX(' . $columns['id'] . ' AS max_id FROM ' . $this->get_table_name(); + $result = $this->db->sql_query($sql); + $max_id = (int) $this->db->sql_fetchfield('max_id'); + $this->db->sql_freeresult($result); + + return $max_id; + } + + /** + * {@inheritdoc} + */ + protected function get_records($min_id, $max_id) + { + $result = $this->db->sql_query($this->get_records_query($min_id, $max_id)); + while ($row = $this->db->sql_fetchrow($result)) + { + if (!isset($row['enable_bbcode'], $row['enable_smilies'], $row['enable_magic_url'])) + { + // Those fields are not saved to the database, we need to guess their original value + $row += array( + 'enable_bbcode' => !empty($row['bbcode_uid']), + 'enable_smilies' => (strpos($row['text'], '') !== false) + ); + } + $records[] = $row; + } + $this->db->sql_freeresult($result); + + return $records; + } + + /** + * Generate the query that retrieves all records for given range + * + * @param integer $min_id Lower bound + * @param integer $max_id Upper bound + * @return string SQL query + */ + protected function get_records_query($min_id, $max_id) + { + $columns = $this->get_columns(); + $fields = array(); + foreach ($columns as $field_name => $column_name) + { + if ($column_name === $field_name) + { + $fields[] = $column_name; + } + else + { + $fields[] = $column_name . ' AS ' . $field_name; + } + } + + $sql = 'SELECT ' . implode(', ', $fields) . ' + FROM ' . $this->get_table_name() . ' + WHERE ' . $columns['id'] . ' BETWEEN ' . $min_id . ' AND ' . $max_id; + + return $sql; + } + + /** + * {@inheritdoc} + */ + protected function save_record(array $record) + { + $columns = $this->get_columns(); + + $sql = 'UPDATE ' . $this->get_table_name() . ' + SET ' . $columns['text'] . " = '" . $this->db->sql_escape($record['text']) . "' + WHERE " . $columns['id'] . ' = ' . $record['id']; + $this->db->sql_query($sql); + } +} diff --git a/tests/text_reparser/post_text_test.php b/tests/text_reparser/post_text_test.php index dc13cebf44..9d9d689db9 100644 --- a/tests/text_reparser/post_text_test.php +++ b/tests/text_reparser/post_text_test.php @@ -38,7 +38,7 @@ class phpbb_textreparser_post_text_test extends phpbb_database_test_case public function testReparse($min_id, $max_id, $expected) { $db = $this->new_dbal(); - $reparser = new \phpbb\textreparser\post_text($db); + $reparser = new \phpbb\textreparser\plugins\post_text($db); $reparser->reparse_range($min_id, $max_id); $sql = 'SELECT post_id, post_text FROM ' . POSTS_TABLE . " From b5911281ae175340817345e63ddbfaf43abb3cec Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 1 May 2015 19:21:01 +0200 Subject: [PATCH 0358/1676] [ticket/13803] Added tests, fixed param order in generate_text_for_storage() PHPBB3-13803 --- phpBB/phpbb/textreparser/base.php | 4 +- .../textreparser/plugins/user_signature.php | 39 +++++++++++++++-- phpBB/phpbb/textreparser/row_based_plugin.php | 34 ++++++++++----- tests/text_reparser/fixtures/posts.xml | 42 ++++++++++++++++++- tests/text_reparser/post_text_test.php | 38 ++++++++++++++--- 5 files changed, 135 insertions(+), 22 deletions(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 7d1e12c52d..f65745f6ab 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -63,8 +63,8 @@ abstract class base implements reparser_interface $bitfield, $flags, $unparsed['enable_bbcode'], - $unparsed['enable_smilies'], - $unparsed['enable_magic_url'] + $unparsed['enable_magic_url'], + $unparsed['enable_smilies'] ); // Save the new text if it has changed diff --git a/phpBB/phpbb/textreparser/plugins/user_signature.php b/phpBB/phpbb/textreparser/plugins/user_signature.php index 2beaaf98e5..7a66f39ab6 100644 --- a/phpBB/phpbb/textreparser/plugins/user_signature.php +++ b/phpBB/phpbb/textreparser/plugins/user_signature.php @@ -15,15 +15,48 @@ namespace phpbb\textreparser\plugins; class user_signature extends \phpbb\textreparser\row_based_plugin { + /** + * @var array Bit numbers used for user options + * @see \phpbb\user + */ + protected $keyoptions; + + /** + * Constructor + * + * Retrieves and saves the bit numbers used for user options + */ + public function __construct() + { + $class_vars = get_class_vars('phpbb\\user'); + $this->keyoptions = $class_vars['keyoptions']; + } + + /** + * {@inheritdoc} + */ + protected function add_missing_fields(array $row) + { + $options = $row['user_options']; + $row += array( + 'enable_bbcode' => phpbb_optionget($this->keyoptions['sig_bbcode'], $options), + 'enable_smilies' => phpbb_optionget($this->keyoptions['sig_smilies'], $options), + 'enable_magic_url' => phpbb_optionget($this->keyoptions['sig_links'], $options), + ); + + return $row; + } + /** * {@inheritdoc} */ protected function get_columns() { return array( - 'id' => 'user_id', - 'text' => 'user_sig', - 'bbcode_uid' => 'user_sig_bbcode_uid', + 'id' => 'user_id', + 'text' => 'user_sig', + 'bbcode_uid' => 'user_sig_bbcode_uid', + 'user_options' => 'user_options', ); } diff --git a/phpBB/phpbb/textreparser/row_based_plugin.php b/phpBB/phpbb/textreparser/row_based_plugin.php index 2317c79e4f..b946d6532b 100644 --- a/phpBB/phpbb/textreparser/row_based_plugin.php +++ b/phpBB/phpbb/textreparser/row_based_plugin.php @@ -44,6 +44,29 @@ abstract class row_based_plugin extends base */ abstract protected function get_table_name(); + /** + * Add fields to given row, if applicable + * + * The enable_* fields are not always saved to the database. Sometimes we need to guess their + * original value based on the text content or possibly other fields + * + * @param array $row Original row + * @return array Complete row + */ + protected function add_missing_fields(array $row) + { + if (!isset($row['enable_bbcode'], $row['enable_smilies'], $row['enable_magic_url'])) + { + $row += array( + 'enable_bbcode' => !empty($row['bbcode_uid']), + 'enable_smilies' => (strpos($row['text'], '') !== false), + ); + } + + return $row; + } + /** * {@inheritdoc} */ @@ -67,16 +90,7 @@ abstract class row_based_plugin extends base $result = $this->db->sql_query($this->get_records_query($min_id, $max_id)); while ($row = $this->db->sql_fetchrow($result)) { - if (!isset($row['enable_bbcode'], $row['enable_smilies'], $row['enable_magic_url'])) - { - // Those fields are not saved to the database, we need to guess their original value - $row += array( - 'enable_bbcode' => !empty($row['bbcode_uid']), - 'enable_smilies' => (strpos($row['text'], '') !== false) - ); - } - $records[] = $row; + $records[] = $this->add_missing_fields($row); } $this->db->sql_freeresult($result); diff --git a/tests/text_reparser/fixtures/posts.xml b/tests/text_reparser/fixtures/posts.xml index 6485293361..3cfbfd2e95 100644 --- a/tests/text_reparser/fixtures/posts.xml +++ b/tests/text_reparser/fixtures/posts.xml @@ -12,7 +12,47 @@ 1 1 1 - Plain text + This post should be [b]ignored[/b] + abcd1234 + + + 2 + 0 + 0 + 0 + [b]Not bold[/b] :) http://example.org + abcd1234 + + + 3 + 1 + 0 + 0 + [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + abcd1234 + + + 4 + 0 + 1 + 0 + :) http://example.org]]> + abcd1234 + + + 5 + 0 + 0 + 1 + http://example.org]]> + abcd1234 + + + 1000 + 1 + 1 + 1 + This post should be [b]ignored[/b] abcd1234 diff --git a/tests/text_reparser/post_text_test.php b/tests/text_reparser/post_text_test.php index 9d9d689db9..19e9c37ecc 100644 --- a/tests/text_reparser/post_text_test.php +++ b/tests/text_reparser/post_text_test.php @@ -40,9 +40,15 @@ class phpbb_textreparser_post_text_test extends phpbb_database_test_case $db = $this->new_dbal(); $reparser = new \phpbb\textreparser\plugins\post_text($db); $reparser->reparse_range($min_id, $max_id); + + $post_ids = array(); + foreach ($expected as $row) + { + $post_ids[] = $row['post_id']; + } $sql = 'SELECT post_id, post_text - FROM ' . POSTS_TABLE . " - WHERE post_id BETWEEN $min_id AND $max_id"; + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_id', $post_ids); $result = $db->sql_query($sql); $rows = $db->sql_fetchrowset($result); $db->sql_freeresult($result); @@ -53,13 +59,33 @@ class phpbb_textreparser_post_text_test extends phpbb_database_test_case { return array( array( - 1, - 1, + 2, + 5, array( array( 'post_id' => 1, - 'post_text' => 'Plain text' - ) + 'post_text' => 'This post should be [b]ignored[/b]', + ), + array( + 'post_id' => 2, + 'post_text' => '[b]Not bold[/b] :) http://example.org', + ), + array( + 'post_id' => 3, + 'post_text' => '[b]Bold[/b] :) http://example.org', + ), + array( + 'post_id' => 4, + 'post_text' => '[b]Not bold[/b] :) http://example.org', + ), + array( + 'post_id' => 5, + 'post_text' => '[b]Not bold[/b] :) http://example.org', + ), + array( + 'post_id' => 1000, + 'post_text' => 'This post should be [b]ignored[/b]', + ), ) ), ); From 459f1d4c1f26658c70d29ac7c4e3f3389a973a59 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 1 May 2015 20:05:15 +0200 Subject: [PATCH 0359/1676] [ticket/13803] Refactored test PHPBB3-13803 --- .../plugins/forum_description.php | 4 +- .../textreparser/plugins/forum_rules.php | 4 +- .../plugins/group_description.php | 4 +- phpBB/phpbb/textreparser/plugins/pm_text.php | 4 +- .../textreparser/plugins/poll_option.php | 4 +- .../phpbb/textreparser/plugins/poll_title.php | 4 +- .../phpbb/textreparser/plugins/post_text.php | 4 +- .../textreparser/plugins/user_signature.php | 4 +- phpBB/phpbb/textreparser/row_based_plugin.php | 4 +- tests/text_reparser/fixtures/posts.xml | 4 +- tests/text_reparser/post_text_test.php | 75 +-------------- tests/text_reparser/test_row_based_plugin.php | 92 +++++++++++++++++++ 12 files changed, 116 insertions(+), 91 deletions(-) create mode 100644 tests/text_reparser/test_row_based_plugin.php diff --git a/phpBB/phpbb/textreparser/plugins/forum_description.php b/phpBB/phpbb/textreparser/plugins/forum_description.php index d6e95c9638..7798e4b20b 100644 --- a/phpBB/phpbb/textreparser/plugins/forum_description.php +++ b/phpBB/phpbb/textreparser/plugins/forum_description.php @@ -18,7 +18,7 @@ class forum_description extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_columns() + public function get_columns() { return array( 'id' => 'forum_id', @@ -30,7 +30,7 @@ class forum_description extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_table_name() + public function get_table_name() { return FORUMS_TABLE; } diff --git a/phpBB/phpbb/textreparser/plugins/forum_rules.php b/phpBB/phpbb/textreparser/plugins/forum_rules.php index 36bb595cb9..57c666a556 100644 --- a/phpBB/phpbb/textreparser/plugins/forum_rules.php +++ b/phpBB/phpbb/textreparser/plugins/forum_rules.php @@ -18,7 +18,7 @@ class forum_rules extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_columns() + public function get_columns() { return array( 'id' => 'forum_id', @@ -30,7 +30,7 @@ class forum_rules extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_table_name() + public function get_table_name() { return FORUMS_TABLE; } diff --git a/phpBB/phpbb/textreparser/plugins/group_description.php b/phpBB/phpbb/textreparser/plugins/group_description.php index c83079827c..ddd0e1d1c5 100644 --- a/phpBB/phpbb/textreparser/plugins/group_description.php +++ b/phpBB/phpbb/textreparser/plugins/group_description.php @@ -18,7 +18,7 @@ class group_description extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_columns() + public function get_columns() { return array( 'id' => 'group_id', @@ -30,7 +30,7 @@ class group_description extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_table_name() + public function get_table_name() { return GROUPS_TABLE; } diff --git a/phpBB/phpbb/textreparser/plugins/pm_text.php b/phpBB/phpbb/textreparser/plugins/pm_text.php index f4d87525df..4d06a2878b 100644 --- a/phpBB/phpbb/textreparser/plugins/pm_text.php +++ b/phpBB/phpbb/textreparser/plugins/pm_text.php @@ -18,7 +18,7 @@ class pm_text extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_columns() + public function get_columns() { return array( 'id' => 'msg_id', @@ -33,7 +33,7 @@ class pm_text extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_table_name() + public function get_table_name() { return PRIVMSGS_TABLE; } diff --git a/phpBB/phpbb/textreparser/plugins/poll_option.php b/phpBB/phpbb/textreparser/plugins/poll_option.php index f074f1866d..cc28599737 100644 --- a/phpBB/phpbb/textreparser/plugins/poll_option.php +++ b/phpBB/phpbb/textreparser/plugins/poll_option.php @@ -18,7 +18,7 @@ class poll_option extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_columns() + public function get_columns() { return array( 'id' => 'poll_option_id', @@ -43,7 +43,7 @@ class poll_option extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_table_name() + public function get_table_name() { return POLL_OPTIONS_TABLE; } diff --git a/phpBB/phpbb/textreparser/plugins/poll_title.php b/phpBB/phpbb/textreparser/plugins/poll_title.php index e794780eba..6665d68847 100644 --- a/phpBB/phpbb/textreparser/plugins/poll_title.php +++ b/phpBB/phpbb/textreparser/plugins/poll_title.php @@ -18,7 +18,7 @@ class poll_title extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_columns() + public function get_columns() { return array( 'id' => 'topic_id', @@ -43,7 +43,7 @@ class poll_title extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_table_name() + public function get_table_name() { return TOPICS_TABLE; } diff --git a/phpBB/phpbb/textreparser/plugins/post_text.php b/phpBB/phpbb/textreparser/plugins/post_text.php index 2b16518b03..4a07c98cea 100644 --- a/phpBB/phpbb/textreparser/plugins/post_text.php +++ b/phpBB/phpbb/textreparser/plugins/post_text.php @@ -18,7 +18,7 @@ class post_text extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_columns() + public function get_columns() { return array( 'id' => 'post_id', @@ -33,7 +33,7 @@ class post_text extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_table_name() + public function get_table_name() { return POSTS_TABLE; } diff --git a/phpBB/phpbb/textreparser/plugins/user_signature.php b/phpBB/phpbb/textreparser/plugins/user_signature.php index 7a66f39ab6..db82d4089b 100644 --- a/phpBB/phpbb/textreparser/plugins/user_signature.php +++ b/phpBB/phpbb/textreparser/plugins/user_signature.php @@ -50,7 +50,7 @@ class user_signature extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_columns() + public function get_columns() { return array( 'id' => 'user_id', @@ -63,7 +63,7 @@ class user_signature extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_table_name() + public function get_table_name() { return USERS_TABLE; } diff --git a/phpBB/phpbb/textreparser/row_based_plugin.php b/phpBB/phpbb/textreparser/row_based_plugin.php index b946d6532b..2be0b68411 100644 --- a/phpBB/phpbb/textreparser/row_based_plugin.php +++ b/phpBB/phpbb/textreparser/row_based_plugin.php @@ -35,14 +35,14 @@ abstract class row_based_plugin extends base * * @return array */ - abstract protected function get_columns(); + abstract public function get_columns(); /** * Return the name of the table used by this plugin * * @return string */ - abstract protected function get_table_name(); + abstract public function get_table_name(); /** * Add fields to given row, if applicable diff --git a/tests/text_reparser/fixtures/posts.xml b/tests/text_reparser/fixtures/posts.xml index 3cfbfd2e95..5e725825d8 100644 --- a/tests/text_reparser/fixtures/posts.xml +++ b/tests/text_reparser/fixtures/posts.xml @@ -12,7 +12,7 @@ 1 1 1 - This post should be [b]ignored[/b] + This row should be [b]ignored[/b] abcd1234 @@ -52,7 +52,7 @@ 1 1 1 - This post should be [b]ignored[/b] + This row should be [b]ignored[/b] abcd1234 diff --git a/tests/text_reparser/post_text_test.php b/tests/text_reparser/post_text_test.php index 19e9c37ecc..ac540f170c 100644 --- a/tests/text_reparser/post_text_test.php +++ b/tests/text_reparser/post_text_test.php @@ -10,84 +10,17 @@ * the docs/CREDITS.txt file. * */ -require_once __DIR__ . '/../../phpBB/includes/functions.php'; -require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; -require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; +include_once __DIR__ . '/test_row_based_plugin.php'; -class phpbb_textreparser_post_text_test extends phpbb_database_test_case +class phpbb_textreparser_post_text_test extends phpbb_textreparser_test_row_based_plugin { - public function setUp() - { - global $config; - if (!isset($config)) - { - $config = new \phpbb\config\config(array()); - } - $this->get_test_case_helpers()->set_s9e_services(); - parent::setUp(); - } - public function getDataSet() { return $this->createXMLDataSet(__DIR__ . '/fixtures/posts.xml'); } - /** - * @dataProvider getReparseTests - */ - public function testReparse($min_id, $max_id, $expected) + public function get_reparser() { - $db = $this->new_dbal(); - $reparser = new \phpbb\textreparser\plugins\post_text($db); - $reparser->reparse_range($min_id, $max_id); - - $post_ids = array(); - foreach ($expected as $row) - { - $post_ids[] = $row['post_id']; - } - $sql = 'SELECT post_id, post_text - FROM ' . POSTS_TABLE . ' - WHERE ' . $db->sql_in_set('post_id', $post_ids); - $result = $db->sql_query($sql); - $rows = $db->sql_fetchrowset($result); - $db->sql_freeresult($result); - $this->assertEquals($expected, $rows); - } - - public function getReparseTests() - { - return array( - array( - 2, - 5, - array( - array( - 'post_id' => 1, - 'post_text' => 'This post should be [b]ignored[/b]', - ), - array( - 'post_id' => 2, - 'post_text' => '[b]Not bold[/b] :) http://example.org', - ), - array( - 'post_id' => 3, - 'post_text' => '[b]Bold[/b] :) http://example.org', - ), - array( - 'post_id' => 4, - 'post_text' => '[b]Not bold[/b] :) http://example.org', - ), - array( - 'post_id' => 5, - 'post_text' => '[b]Not bold[/b] :) http://example.org', - ), - array( - 'post_id' => 1000, - 'post_text' => 'This post should be [b]ignored[/b]', - ), - ) - ), - ); + return new \phpbb\textreparser\plugins\post_text($this->db); } } diff --git a/tests/text_reparser/test_row_based_plugin.php b/tests/text_reparser/test_row_based_plugin.php new file mode 100644 index 0000000000..7dd90f21d0 --- /dev/null +++ b/tests/text_reparser/test_row_based_plugin.php @@ -0,0 +1,92 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +require_once __DIR__ . '/../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; +require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; + +abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_test_case +{ + protected $db; + + public function setUp() + { + global $config; + if (!isset($config)) + { + $config = new \phpbb\config\config(array()); + } + $this->get_test_case_helpers()->set_s9e_services(); + $this->db = $this->new_dbal(); + parent::setUp(); + } + + /** + * @dataProvider getReparseTests + */ + public function testReparse($min_id, $max_id, $expected) + { + $reparser = $this->get_reparser(); + $reparser->reparse_range($min_id, $max_id); + + $ids = array(); + foreach ($expected as $row) + { + $ids[] = $row['id']; + } + + $columns = $reparser->get_columns(); + $sql = 'SELECT ' . $columns['id'] . ' AS id, ' . $columns['text'] . ' AS text + FROM ' . $reparser->get_table_name() . ' + WHERE ' . $this->db->sql_in_set($columns['id'], $ids); + $result = $this->db->sql_query($sql); + $rows = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + $this->assertEquals($expected, $rows); + } + + public function getReparseTests() + { + return array( + array( + 2, + 5, + array( + array( + 'id' => 1, + 'text' => 'This row should be [b]ignored[/b]', + ), + array( + 'id' => 2, + 'text' => '[b]Not bold[/b] :) http://example.org', + ), + array( + 'id' => 3, + 'text' => '[b]Bold[/b] :) http://example.org', + ), + array( + 'id' => 4, + 'text' => '[b]Not bold[/b] :) http://example.org', + ), + array( + 'id' => 5, + 'text' => '[b]Not bold[/b] :) http://example.org', + ), + array( + 'id' => 1000, + 'text' => 'This row should be [b]ignored[/b]', + ), + ) + ), + ); + } +} From ea445ffa4776b7ce0b1d13485f113c7e1ec28af0 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 2 May 2015 01:08:32 +0200 Subject: [PATCH 0360/1676] [ticket/13803] Added methods to detect whether a given feature is in use They test whether a given BBCode was enabled and has been used in a text, or smilies, or magic URLs. PHPBB3-13803 --- phpBB/phpbb/textreparser/base.php | 56 +++++++++++++++++++ phpBB/phpbb/textreparser/row_based_plugin.php | 13 ++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index f65745f6ab..f3f31ca320 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -29,6 +29,62 @@ abstract class base implements reparser_interface */ abstract protected function get_records($min_id, $max_id); + /** + * Guess whether given BBCode is in use in given record + * + * @param array $record + * @param string $bbcode + * @return bool + */ + protected function guess_bbcode(array $record, $bbcode) + { + if (!empty($record['bbcode_uid'])) + { + // Look for the closing tag, e.g. [/url] + $match = '[/' . $bbcode . ':' . $record['bbcode_uid']; + if (stripos($record['text'], $match) !== false) + { + return true; + } + } + + if (substr($record['text'], 0, 2) == '[/url] + $match = '[/' . $bbcode . ']'; + if (stripos($record['text'], $match) !== false) + { + return true; + } + } + + return false; + } + + /** + * Guess whether magic URLs are in use in given record + * + * @param array $record + * @return bool + */ + protected function guess_magic_url(array $record) + { + // Look for or for a URL tag that's not immediately followed by + return (strpos($record['text'], '') !== false || preg_match('(]++>(?!))', strpos($row['text']))); + } + + /** + * Guess whether smilies are in use in given record + * + * @param array $record + * @return bool + */ + protected function guess_smilies(array $record) + { + return (strpos($row['text'], '') !== false), + 'enable_smilies' => $this->guess_smilies($row), + 'enable_magic_url' => $this->guess_magic_url($row), ); } + // Those BBCodes are disabled based on context and user permissions and that value is never + // stored in the database. Here we test whether they were used in the original text. + $bbcodes = array('flash', 'img', 'quote', 'url'); + foreach ($bbcodes as $bbcode) + { + $field_name = 'enable_' . $bbcode; + $row[$field_name] = $this->guess_bbcode($row, $bbcode); + } + return $row; } From 9bf0f794b5876b10491c91548f1a92bc0dff7400 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 2 May 2015 02:55:45 +0200 Subject: [PATCH 0361/1676] [ticket/13803] Added pm_text tests PHPBB3-13803 --- phpBB/phpbb/textreparser/base.php | 38 +++++++++- phpBB/phpbb/textreparser/row_based_plugin.php | 32 -------- tests/text_reparser/fixtures/privmsgs.xml | 73 +++++++++++++++++++ tests/text_reparser/pm_text_test.php | 26 +++++++ 4 files changed, 136 insertions(+), 33 deletions(-) create mode 100644 tests/text_reparser/fixtures/privmsgs.xml create mode 100644 tests/text_reparser/pm_text_test.php diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index f3f31ca320..2d4a4171af 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -29,6 +29,38 @@ abstract class base implements reparser_interface */ abstract protected function get_records($min_id, $max_id); + /** + * Add fields to given record, if applicable + * + * The enable_* fields are not always saved to the database. Sometimes we need to guess their + * original value based on the text content or possibly other fields + * + * @param array $record Original record + * @return array Complete record + */ + protected function add_missing_fields(array $record) + { + if (!isset($record['enable_bbcode'], $record['enable_smilies'], $record['enable_magic_url'])) + { + $record += array( + 'enable_bbcode' => !empty($record['bbcode_uid']), + 'enable_smilies' => $this->guess_smilies($record), + 'enable_magic_url' => $this->guess_magic_url($record), + ); + } + + // Those BBCodes are disabled based on context and user permissions and that value is never + // stored in the database. Here we test whether they were used in the original text. + $bbcodes = array('flash', 'img', 'quote', 'url'); + foreach ($bbcodes as $bbcode) + { + $field_name = 'enable_' . $bbcode . '_bbcode'; + $record[$field_name] = $this->guess_bbcode($record, $bbcode); + } + + return $record; + } + /** * Guess whether given BBCode is in use in given record * @@ -120,7 +152,11 @@ abstract class base implements reparser_interface $flags, $unparsed['enable_bbcode'], $unparsed['enable_magic_url'], - $unparsed['enable_smilies'] + $unparsed['enable_smilies'], + $unparsed['enable_img_bbcode'], + $unparsed['enable_flash_bbcode'], + $unparsed['enable_quote_bbcode'], + $unparsed['enable_url_bbcode'] ); // Save the new text if it has changed diff --git a/phpBB/phpbb/textreparser/row_based_plugin.php b/phpBB/phpbb/textreparser/row_based_plugin.php index 80525a404e..e39ec4d5d3 100644 --- a/phpBB/phpbb/textreparser/row_based_plugin.php +++ b/phpBB/phpbb/textreparser/row_based_plugin.php @@ -44,38 +44,6 @@ abstract class row_based_plugin extends base */ abstract public function get_table_name(); - /** - * Add fields to given row, if applicable - * - * The enable_* fields are not always saved to the database. Sometimes we need to guess their - * original value based on the text content or possibly other fields - * - * @param array $row Original row - * @return array Complete row - */ - protected function add_missing_fields(array $row) - { - if (!isset($row['enable_bbcode'], $row['enable_smilies'], $row['enable_magic_url'])) - { - $row += array( - 'enable_bbcode' => !empty($row['bbcode_uid']), - 'enable_smilies' => $this->guess_smilies($row), - 'enable_magic_url' => $this->guess_magic_url($row), - ); - } - - // Those BBCodes are disabled based on context and user permissions and that value is never - // stored in the database. Here we test whether they were used in the original text. - $bbcodes = array('flash', 'img', 'quote', 'url'); - foreach ($bbcodes as $bbcode) - { - $field_name = 'enable_' . $bbcode; - $row[$field_name] = $this->guess_bbcode($row, $bbcode); - } - - return $row; - } - /** * {@inheritdoc} */ diff --git a/tests/text_reparser/fixtures/privmsgs.xml b/tests/text_reparser/fixtures/privmsgs.xml new file mode 100644 index 0000000000..9ca49a2af8 --- /dev/null +++ b/tests/text_reparser/fixtures/privmsgs.xml @@ -0,0 +1,73 @@ + + + + msg_id + enable_bbcode + enable_smilies + enable_magic_url + message_text + bbcode_uid + to_address + bcc_address + + 1 + 1 + 1 + 1 + This row should be [b]ignored[/b] + abcd1234 + + + + + 2 + 0 + 0 + 0 + [b]Not bold[/b] :) http://example.org + abcd1234 + + + + + 3 + 1 + 0 + 0 + [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + abcd1234 + + + + + 4 + 0 + 1 + 0 + :) http://example.org]]> + abcd1234 + + + + + 5 + 0 + 0 + 1 + http://example.org]]> + abcd1234 + + + + + 1000 + 1 + 1 + 1 + This row should be [b]ignored[/b] + abcd1234 + + + +
          +
          diff --git a/tests/text_reparser/pm_text_test.php b/tests/text_reparser/pm_text_test.php new file mode 100644 index 0000000000..6b409d27e3 --- /dev/null +++ b/tests/text_reparser/pm_text_test.php @@ -0,0 +1,26 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_pm_text_test extends phpbb_textreparser_test_row_based_plugin +{ + public function getDataSet() + { + return $this->createXMLDataSet(__DIR__ . '/fixtures/privmsgs.xml'); + } + + public function get_reparser() + { + return new \phpbb\textreparser\plugins\pm_text($this->db); + } +} From 70cd911281056ecb4eefc23e678126e1747debc8 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 2 May 2015 08:51:56 +0200 Subject: [PATCH 0362/1676] [ticket/13803] Added tests PHPBB3-13803 --- phpBB/phpbb/textreparser/base.php | 50 ++++++++++++++++--- tests/text_reparser/fixtures/posts.xml | 32 ++++++++++++ tests/text_reparser/fixtures/privmsgs.xml | 40 +++++++++++++++ tests/text_reparser/test_row_based_plugin.php | 40 ++++++++++++--- 4 files changed, 149 insertions(+), 13 deletions(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 2d4a4171af..865b0662f9 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -43,7 +43,7 @@ abstract class base implements reparser_interface if (!isset($record['enable_bbcode'], $record['enable_smilies'], $record['enable_magic_url'])) { $record += array( - 'enable_bbcode' => !empty($record['bbcode_uid']), + 'enable_bbcode' => $this->guess_bbcodes($record), 'enable_smilies' => $this->guess_smilies($record), 'enable_magic_url' => $this->guess_magic_url($record), ); @@ -58,6 +58,13 @@ abstract class base implements reparser_interface $record[$field_name] = $this->guess_bbcode($record, $bbcode); } + // Magic URLs are tied to the URL BBCode, that's why if magic URLs are enabled we make sure + // that the URL BBCode is also enabled + if ($record['enable_magic_url']) + { + $record['enable_url_bbcode'] = true; + } + return $record; } @@ -74,7 +81,7 @@ abstract class base implements reparser_interface { // Look for the closing tag, e.g. [/url] $match = '[/' . $bbcode . ':' . $record['bbcode_uid']; - if (stripos($record['text'], $match) !== false) + if (strpos($record['text'], $match) !== false) { return true; } @@ -84,8 +91,8 @@ abstract class base implements reparser_interface { // Look for the closing tag inside of a e element, in an element of the same name, e.g. // [/url]
          - $match = '[/' . $bbcode . ']'; - if (stripos($record['text'], $match) !== false) + $match = '[/' . $bbcode . ']'; + if (strpos($record['text'], $match) !== false) { return true; } @@ -94,6 +101,33 @@ abstract class base implements reparser_interface return false; } + /** + * Guess whether any BBCode is in use in given record + * + * @param array $record + * @return bool + */ + protected function guess_bbcodes(array $record) + { + if (!empty($record['bbcode_uid'])) + { + // Test whether the bbcode_uid is in use + $match = ':' . $record['bbcode_uid']; + if (strpos($record['text'], $match) !== false) + { + return true; + } + } + + if (substr($record['text'], 0, 2) == '\\[/\\w+\\])', $match); + } + + return false; + } + /** * Guess whether magic URLs are in use in given record * @@ -103,7 +137,7 @@ abstract class base implements reparser_interface protected function guess_magic_url(array $record) { // Look for or for a URL tag that's not immediately followed by - return (strpos($record['text'], '') !== false || preg_match('(]++>(?!))', strpos($row['text']))); + return (strpos($record['text'], '') !== false || preg_match('(]++>(?!))', $record['text'])); } /** @@ -114,7 +148,7 @@ abstract class base implements reparser_interface */ protected function guess_smilies(array $record) { - return (strpos($row['text'], 'http://example.org]]> abcd1234 + + 6 + 1 + 1 + 0 + + abcd1234 + + + 7 + 1 + 1 + 0 + + abcd1234 + + + 8 + 1 + 1 + 0 + + abcd1234 + + + 9 + 1 + 1 + 0 + + abcd1234 + 1000 1 diff --git a/tests/text_reparser/fixtures/privmsgs.xml b/tests/text_reparser/fixtures/privmsgs.xml index 9ca49a2af8..4049b9890a 100644 --- a/tests/text_reparser/fixtures/privmsgs.xml +++ b/tests/text_reparser/fixtures/privmsgs.xml @@ -59,6 +59,46 @@ + + 6 + 1 + 1 + 0 + + abcd1234 + + + + + 7 + 1 + 1 + 0 + + abcd1234 + + + + + 8 + 1 + 1 + 0 + + abcd1234 + + + + + 9 + 1 + 1 + 0 + + abcd1234 + + + 1000 1 diff --git a/tests/text_reparser/test_row_based_plugin.php b/tests/text_reparser/test_row_based_plugin.php index 7dd90f21d0..405341e2fc 100644 --- a/tests/text_reparser/test_row_based_plugin.php +++ b/tests/text_reparser/test_row_based_plugin.php @@ -62,31 +62,59 @@ abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_t 5, array( array( - 'id' => 1, + 'id' => '1', 'text' => 'This row should be [b]ignored[/b]', ), array( - 'id' => 2, + 'id' => '2', 'text' => '[b]Not bold[/b] :) http://example.org', ), array( - 'id' => 3, + 'id' => '3', 'text' => '[b]Bold[/b] :) http://example.org', ), array( - 'id' => 4, + 'id' => '4', 'text' => '[b]Not bold[/b] :) http://example.org', ), array( - 'id' => 5, + 'id' => '5', 'text' => '[b]Not bold[/b] :) http://example.org', ), array( - 'id' => 1000, + 'id' => '1000', 'text' => 'This row should be [b]ignored[/b]', ), ) ), + array( + 6, + 7, + array( + array( + 'id' => '6', + 'text' => '[flash=123,345]http://example.org/flash.swf[/flash]', + ), + array( + 'id' => '7', + 'text' => '[flash=123,345]http://example.org/flash.swf[/flash]', + ), + ) + ), + array( + 8, + 9, + array( + array( + 'id' => '8', + 'text' => '[img]http://example.org/img.png[/img]', + ), + array( + 'id' => '9', + 'text' => '[img]http://example.org/img.png[/img]', + ), + ) + ), ); } } From 6ab524f8dcf8f918159ba584a659dd88dc9ca3b9 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 3 May 2015 01:39:56 +0200 Subject: [PATCH 0363/1676] [ticket/13803] Added tests PHPBB3-13803 --- tests/text_reparser/fixtures/forums.xml | 91 +++++++++++++++++++ .../text_reparser/forum_description_test.php | 26 ++++++ tests/text_reparser/forum_rules_test.php | 26 ++++++ 3 files changed, 143 insertions(+) create mode 100644 tests/text_reparser/fixtures/forums.xml create mode 100644 tests/text_reparser/forum_description_test.php create mode 100644 tests/text_reparser/forum_rules_test.php diff --git a/tests/text_reparser/fixtures/forums.xml b/tests/text_reparser/fixtures/forums.xml new file mode 100644 index 0000000000..39c172c969 --- /dev/null +++ b/tests/text_reparser/fixtures/forums.xml @@ -0,0 +1,91 @@ + + + + forum_id + forum_parents + forum_desc + forum_desc_uid + forum_rules + forum_rules_uid + + 1 + + This row should be [b]ignored[/b] + abcd1234 + This row should be [b]ignored[/b] + abcd1234 + + + 2 + + [b]Not bold[/b] :) http://example.org + abcd1234 + [b]Not bold[/b] :) http://example.org + abcd1234 + + + 3 + + [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + abcd1234 + [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + abcd1234 + + + 4 + + :) http://example.org]]> + abcd1234 + :) http://example.org]]> + abcd1234 + + + 5 + + http://example.org]]> + abcd1234 + http://example.org]]> + abcd1234 + + + 6 + + + abcd1234 + + abcd1234 + + + 7 + + + abcd1234 + + abcd1234 + + + 8 + + + abcd1234 + + abcd1234 + + + 9 + + + abcd1234 + + abcd1234 + + + 1000 + + This row should be [b]ignored[/b] + abcd1234 + This row should be [b]ignored[/b] + abcd1234 + +
          +
          diff --git a/tests/text_reparser/forum_description_test.php b/tests/text_reparser/forum_description_test.php new file mode 100644 index 0000000000..66ed261a6f --- /dev/null +++ b/tests/text_reparser/forum_description_test.php @@ -0,0 +1,26 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_forum_description_test extends phpbb_textreparser_test_row_based_plugin +{ + public function getDataSet() + { + return $this->createXMLDataSet(__DIR__ . '/fixtures/forums.xml'); + } + + public function get_reparser() + { + return new \phpbb\textreparser\plugins\forum_description($this->db); + } +} diff --git a/tests/text_reparser/forum_rules_test.php b/tests/text_reparser/forum_rules_test.php new file mode 100644 index 0000000000..c89f47cf8e --- /dev/null +++ b/tests/text_reparser/forum_rules_test.php @@ -0,0 +1,26 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_forum_rules_test extends phpbb_textreparser_test_row_based_plugin +{ + public function getDataSet() + { + return $this->createXMLDataSet(__DIR__ . '/fixtures/forums.xml'); + } + + public function get_reparser() + { + return new \phpbb\textreparser\plugins\forum_rules($this->db); + } +} From d42b2fe795de913894c0cc9f1df084f8ef0c58f9 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 3 May 2015 02:05:20 +0200 Subject: [PATCH 0364/1676] [ticket/13803] Sort test rows in SQL to match the expected result PHPBB3-13803 --- tests/text_reparser/test_row_based_plugin.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/text_reparser/test_row_based_plugin.php b/tests/text_reparser/test_row_based_plugin.php index 405341e2fc..0258745bf2 100644 --- a/tests/text_reparser/test_row_based_plugin.php +++ b/tests/text_reparser/test_row_based_plugin.php @@ -47,7 +47,8 @@ abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_t $columns = $reparser->get_columns(); $sql = 'SELECT ' . $columns['id'] . ' AS id, ' . $columns['text'] . ' AS text FROM ' . $reparser->get_table_name() . ' - WHERE ' . $this->db->sql_in_set($columns['id'], $ids); + WHERE ' . $this->db->sql_in_set($columns['id'], $ids) . ' + ORDER BY id'; $result = $this->db->sql_query($sql); $rows = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); From 212fc277b481440a99ff0483e5fbc40c790e8dda Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 6 May 2015 13:01:09 +0200 Subject: [PATCH 0365/1676] [ticket/13803] Reordered methods [ci skip] PHPBB3-13803 --- phpBB/phpbb/textreparser/base.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 865b0662f9..85327cdfce 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -29,6 +29,11 @@ abstract class base implements reparser_interface */ abstract protected function get_records($min_id, $max_id); + /** + * {@inheritdoc} + */ + abstract protected function save_record(array $record); + /** * Add fields to given record, if applicable * @@ -202,9 +207,4 @@ abstract class base implements reparser_interface $this->save_record($record); } } - - /** - * {@inheritdoc} - */ - abstract protected function save_record(array $record); } From a870f8f8603993a2d6a2443c8ad746212071f392 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 6 May 2015 21:32:39 +0200 Subject: [PATCH 0366/1676] [ticket/13803] Added user_signature tests PHPBB3-13803 --- .../textreparser/plugins/user_signature.php | 27 +++--- tests/text_reparser/fixtures/users.xml | 91 +++++++++++++++++++ .../text_reparser/forum_description_test.php | 2 +- tests/text_reparser/forum_rules_test.php | 2 +- tests/text_reparser/pm_text_test.php | 2 +- tests/text_reparser/post_text_test.php | 2 +- tests/text_reparser/test_row_based_plugin.php | 2 + tests/text_reparser/user_signature_test.php | 26 ++++++ 8 files changed, 138 insertions(+), 16 deletions(-) create mode 100644 tests/text_reparser/fixtures/users.xml create mode 100644 tests/text_reparser/user_signature_test.php diff --git a/phpBB/phpbb/textreparser/plugins/user_signature.php b/phpBB/phpbb/textreparser/plugins/user_signature.php index db82d4089b..f657a45d38 100644 --- a/phpBB/phpbb/textreparser/plugins/user_signature.php +++ b/phpBB/phpbb/textreparser/plugins/user_signature.php @@ -21,22 +21,16 @@ class user_signature extends \phpbb\textreparser\row_based_plugin */ protected $keyoptions; - /** - * Constructor - * - * Retrieves and saves the bit numbers used for user options - */ - public function __construct() - { - $class_vars = get_class_vars('phpbb\\user'); - $this->keyoptions = $class_vars['keyoptions']; - } - /** * {@inheritdoc} */ protected function add_missing_fields(array $row) { + if (!isset($this->keyoptions)) + { + $this->save_keyoptions(); + } + $options = $row['user_options']; $row += array( 'enable_bbcode' => phpbb_optionget($this->keyoptions['sig_bbcode'], $options), @@ -44,7 +38,7 @@ class user_signature extends \phpbb\textreparser\row_based_plugin 'enable_magic_url' => phpbb_optionget($this->keyoptions['sig_links'], $options), ); - return $row; + return parent::add_missing_fields($row); } /** @@ -67,4 +61,13 @@ class user_signature extends \phpbb\textreparser\row_based_plugin { return USERS_TABLE; } + + /** + * Save the keyoptions var from \phpbb\user + */ + protected function save_keyoptions() + { + $class_vars = get_class_vars('phpbb\\user'); + $this->keyoptions = $class_vars['keyoptions']; + } } diff --git a/tests/text_reparser/fixtures/users.xml b/tests/text_reparser/fixtures/users.xml new file mode 100644 index 0000000000..60c623b6b1 --- /dev/null +++ b/tests/text_reparser/fixtures/users.xml @@ -0,0 +1,91 @@ + + + + user_id + user_permissions + username_clean + user_options + user_sig + user_sig_bbcode_uid + + 1 + + user1 + 230271 + This row should be [b]ignored[/b] + abcd1234 + + + 2 + + user2 + 895 + [b]Not bold[/b] :) http://example.org + abcd1234 + + + 3 + + user3 + 33663 + [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + abcd1234 + + + 4 + + user4 + 66431 + :) http://example.org]]> + abcd1234 + + + 5 + + user5 + 131967 + http://example.org]]> + abcd1234 + + + 6 + + user6 + 99199 + + abcd1234 + + + 7 + + user7 + 99199 + + abcd1234 + + + 8 + + user8 + 99199 + + abcd1234 + + + 9 + + user9 + 99199 + + abcd1234 + + + 1000 + + user1000 + 230271 + This row should be [b]ignored[/b] + abcd1234 + +
          +
          diff --git a/tests/text_reparser/forum_description_test.php b/tests/text_reparser/forum_description_test.php index 66ed261a6f..3b739353cd 100644 --- a/tests/text_reparser/forum_description_test.php +++ b/tests/text_reparser/forum_description_test.php @@ -19,7 +19,7 @@ class phpbb_textreparser_forum_description_test extends phpbb_textreparser_test_ return $this->createXMLDataSet(__DIR__ . '/fixtures/forums.xml'); } - public function get_reparser() + protected function get_reparser() { return new \phpbb\textreparser\plugins\forum_description($this->db); } diff --git a/tests/text_reparser/forum_rules_test.php b/tests/text_reparser/forum_rules_test.php index c89f47cf8e..4c267c9014 100644 --- a/tests/text_reparser/forum_rules_test.php +++ b/tests/text_reparser/forum_rules_test.php @@ -19,7 +19,7 @@ class phpbb_textreparser_forum_rules_test extends phpbb_textreparser_test_row_ba return $this->createXMLDataSet(__DIR__ . '/fixtures/forums.xml'); } - public function get_reparser() + protected function get_reparser() { return new \phpbb\textreparser\plugins\forum_rules($this->db); } diff --git a/tests/text_reparser/pm_text_test.php b/tests/text_reparser/pm_text_test.php index 6b409d27e3..3896a57e98 100644 --- a/tests/text_reparser/pm_text_test.php +++ b/tests/text_reparser/pm_text_test.php @@ -19,7 +19,7 @@ class phpbb_textreparser_pm_text_test extends phpbb_textreparser_test_row_based_ return $this->createXMLDataSet(__DIR__ . '/fixtures/privmsgs.xml'); } - public function get_reparser() + protected function get_reparser() { return new \phpbb\textreparser\plugins\pm_text($this->db); } diff --git a/tests/text_reparser/post_text_test.php b/tests/text_reparser/post_text_test.php index ac540f170c..0f934a06ee 100644 --- a/tests/text_reparser/post_text_test.php +++ b/tests/text_reparser/post_text_test.php @@ -19,7 +19,7 @@ class phpbb_textreparser_post_text_test extends phpbb_textreparser_test_row_base return $this->createXMLDataSet(__DIR__ . '/fixtures/posts.xml'); } - public function get_reparser() + protected function get_reparser() { return new \phpbb\textreparser\plugins\post_text($this->db); } diff --git a/tests/text_reparser/test_row_based_plugin.php b/tests/text_reparser/test_row_based_plugin.php index 0258745bf2..4d4d64a56d 100644 --- a/tests/text_reparser/test_row_based_plugin.php +++ b/tests/text_reparser/test_row_based_plugin.php @@ -18,6 +18,8 @@ abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_t { protected $db; + abstract protected function get_reparser(); + public function setUp() { global $config; diff --git a/tests/text_reparser/user_signature_test.php b/tests/text_reparser/user_signature_test.php new file mode 100644 index 0000000000..ab830a303d --- /dev/null +++ b/tests/text_reparser/user_signature_test.php @@ -0,0 +1,26 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_user_signature_test extends phpbb_textreparser_test_row_based_plugin +{ + public function getDataSet() + { + return $this->createXMLDataSet(__DIR__ . '/fixtures/users.xml'); + } + + protected function get_reparser() + { + return new \phpbb\textreparser\plugins\user_signature($this->db); + } +} From b0eb63e5b9315e8a6f96ea308a835cb7fd712753 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 7 May 2015 11:40:54 +0200 Subject: [PATCH 0367/1676] [ticket/13803] Added group_description tests PHPBB3-13803 --- tests/text_reparser/fixtures/groups.xml | 69 +++++++++++++++++++ .../text_reparser/group_description_test.php | 26 +++++++ 2 files changed, 95 insertions(+) create mode 100644 tests/text_reparser/fixtures/groups.xml create mode 100644 tests/text_reparser/group_description_test.php diff --git a/tests/text_reparser/fixtures/groups.xml b/tests/text_reparser/fixtures/groups.xml new file mode 100644 index 0000000000..d3df0131a3 --- /dev/null +++ b/tests/text_reparser/fixtures/groups.xml @@ -0,0 +1,69 @@ + + + + group_id + group_desc + group_desc_options + group_desc_uid + + 1 + This row should be [b]ignored[/b] + 7 + abcd1234 + + + 2 + [b]Not bold[/b] :) http://example.org + 0 + abcd1234 + + + 3 + [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + 1 + abcd1234 + + + 4 + :) http://example.org]]> + 2 + abcd1234 + + + 5 + http://example.org]]> + 4 + abcd1234 + + + 6 + + 7 + abcd1234 + + + 7 + + 7 + abcd1234 + + + 8 + + 7 + abcd1234 + + + 9 + + 7 + abcd1234 + + + 1000 + This row should be [b]ignored[/b] + 7 + abcd1234 + +
          +
          diff --git a/tests/text_reparser/group_description_test.php b/tests/text_reparser/group_description_test.php new file mode 100644 index 0000000000..51035903e1 --- /dev/null +++ b/tests/text_reparser/group_description_test.php @@ -0,0 +1,26 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_group_description_test extends phpbb_textreparser_test_row_based_plugin +{ + public function getDataSet() + { + return $this->createXMLDataSet(__DIR__ . '/fixtures/groups.xml'); + } + + protected function get_reparser() + { + return new \phpbb\textreparser\plugins\group_description($this->db); + } +} From 8ef15d10e6295eb26fd292a411a8f1edd3853287 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 9 May 2015 18:07:19 +0200 Subject: [PATCH 0368/1676] [ticket/13803] Added poll_title tests PHPBB3-13803 --- tests/text_reparser/fixtures/polls.xml | 68 +++++++++++++++++++++++++ tests/text_reparser/poll_title_test.php | 26 ++++++++++ 2 files changed, 94 insertions(+) create mode 100644 tests/text_reparser/fixtures/polls.xml create mode 100644 tests/text_reparser/poll_title_test.php diff --git a/tests/text_reparser/fixtures/polls.xml b/tests/text_reparser/fixtures/polls.xml new file mode 100644 index 0000000000..9baf813c97 --- /dev/null +++ b/tests/text_reparser/fixtures/polls.xml @@ -0,0 +1,68 @@ + + + + post_id + post_text + bbcode_uid + + 1 + + abcd1234 + +
          + + topic_id + topic_first_post_id + poll_title + + 1 + 1 + This row should be [b]ignored[/b] + + + 2 + 1 + [b]Not bold[/b] :) http://example.org + + + 3 + 1 + [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + + + 4 + 1 + :) http://example.org]]> + + + 5 + 1 + http://example.org]]> + + + 6 + 1 + + + + 7 + 1 + + + + 8 + 1 + + + + 9 + 1 + + + + 1000 + 1 + This row should be [b]ignored[/b] + +
          +
          diff --git a/tests/text_reparser/poll_title_test.php b/tests/text_reparser/poll_title_test.php new file mode 100644 index 0000000000..76ca2ee228 --- /dev/null +++ b/tests/text_reparser/poll_title_test.php @@ -0,0 +1,26 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_poll_title_test extends phpbb_textreparser_test_row_based_plugin +{ + public function getDataSet() + { + return $this->createXMLDataSet(__DIR__ . '/fixtures/polls.xml'); + } + + protected function get_reparser() + { + return new \phpbb\textreparser\plugins\poll_title($this->db); + } +} From 2dc19cec9d3cb0c1e9ab8ef0afd7515f4bb7cee1 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 9 May 2015 18:14:03 +0200 Subject: [PATCH 0369/1676] [ticket/13803] Added poll_option tests PHPBB3-13803 --- tests/text_reparser/fixtures/poll_options.xml | 78 +++++++++++++++++++ tests/text_reparser/poll_option_test.php | 26 +++++++ 2 files changed, 104 insertions(+) create mode 100644 tests/text_reparser/fixtures/poll_options.xml create mode 100644 tests/text_reparser/poll_option_test.php diff --git a/tests/text_reparser/fixtures/poll_options.xml b/tests/text_reparser/fixtures/poll_options.xml new file mode 100644 index 0000000000..f0ed54aafb --- /dev/null +++ b/tests/text_reparser/fixtures/poll_options.xml @@ -0,0 +1,78 @@ + + + + poll_option_id + topic_id + poll_option_text + + 1 + 1 + This row should be [b]ignored[/b] + + + 2 + 1 + [b]Not bold[/b] :) http://example.org + + + 3 + 1 + [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + + + 4 + 1 + :) http://example.org]]> + + + 5 + 1 + http://example.org]]> + + + 6 + 1 + + + + 7 + 1 + + + + 8 + 1 + + + + 9 + 1 + + + + 1000 + 1 + This row should be [b]ignored[/b] + +
          + + post_id + post_text + bbcode_uid + + 1 + + abcd1234 + +
          + + topic_id + topic_first_post_id + poll_title + + 1 + 1 + This row should be [b]ignored[/b] + +
          +
          diff --git a/tests/text_reparser/poll_option_test.php b/tests/text_reparser/poll_option_test.php new file mode 100644 index 0000000000..0f08f720ff --- /dev/null +++ b/tests/text_reparser/poll_option_test.php @@ -0,0 +1,26 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_poll_option_test extends phpbb_textreparser_test_row_based_plugin +{ + public function getDataSet() + { + return $this->createXMLDataSet(__DIR__ . '/fixtures/poll_options.xml'); + } + + protected function get_reparser() + { + return new \phpbb\textreparser\plugins\poll_option($this->db); + } +} From ae6ad754a430309796e1963684b59c01739ba4dd Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 9 May 2015 18:54:57 +0200 Subject: [PATCH 0370/1676] [ticket/13803] Moved the add_missing_fields() call to the base class PHPBB3-13803 --- phpBB/phpbb/textreparser/base.php | 1 + phpBB/phpbb/textreparser/row_based_plugin.php | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 85327cdfce..47ac177e05 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -174,6 +174,7 @@ abstract class base implements reparser_interface */ protected function reparse_record(array $record) { + $record = $this->add_missing_fields($record); $unparsed = array_merge( $record, generate_text_for_edit( diff --git a/phpBB/phpbb/textreparser/row_based_plugin.php b/phpBB/phpbb/textreparser/row_based_plugin.php index e39ec4d5d3..6b63ffeeaf 100644 --- a/phpBB/phpbb/textreparser/row_based_plugin.php +++ b/phpBB/phpbb/textreparser/row_based_plugin.php @@ -65,10 +65,7 @@ abstract class row_based_plugin extends base protected function get_records($min_id, $max_id) { $result = $this->db->sql_query($this->get_records_query($min_id, $max_id)); - while ($row = $this->db->sql_fetchrow($result)) - { - $records[] = $this->add_missing_fields($row); - } + $records = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); return $records; From 7a8ac4bb714299d2544ec215c24018fe07caa0ec Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 9 May 2015 19:06:48 +0200 Subject: [PATCH 0371/1676] [ticket/13803] Added get_max_id() tests PHPBB3-13803 --- phpBB/phpbb/textreparser/row_based_plugin.php | 2 +- tests/text_reparser/test_row_based_plugin.php | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/textreparser/row_based_plugin.php b/phpBB/phpbb/textreparser/row_based_plugin.php index 6b63ffeeaf..05a6e19553 100644 --- a/phpBB/phpbb/textreparser/row_based_plugin.php +++ b/phpBB/phpbb/textreparser/row_based_plugin.php @@ -51,7 +51,7 @@ abstract class row_based_plugin extends base { $columns = $this->get_columns(); - $sql = 'SELECT MAX(' . $columns['id'] . ' AS max_id FROM ' . $this->get_table_name(); + $sql = 'SELECT MAX(' . $columns['id'] . ') AS max_id FROM ' . $this->get_table_name(); $result = $this->db->sql_query($sql); $max_id = (int) $this->db->sql_fetchfield('max_id'); $this->db->sql_freeresult($result); diff --git a/tests/text_reparser/test_row_based_plugin.php b/tests/text_reparser/test_row_based_plugin.php index 4d4d64a56d..489dff280b 100644 --- a/tests/text_reparser/test_row_based_plugin.php +++ b/tests/text_reparser/test_row_based_plugin.php @@ -32,6 +32,12 @@ abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_t parent::setUp(); } + public function test_get_max_id() + { + $reparser = $this->get_reparser(); + $this->assertEquals(1000, $reparser->get_max_id()); + } + /** * @dataProvider getReparseTests */ From 3827a131ae11dcd3adf852f80ff4d85e7a7d470b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 9 May 2015 20:12:30 +0200 Subject: [PATCH 0372/1676] [ticket/13803] Rewrote the poll_option plugin As it turns out, poll_option_id is not a primary key. PHPBB3-13803 --- .../textreparser/plugins/poll_option.php | 50 ++++++++---- tests/text_reparser/fixtures/poll_options.xml | 63 +++++++-------- tests/text_reparser/poll_option_test.php | 78 ++++++++++++++++++- 3 files changed, 142 insertions(+), 49 deletions(-) diff --git a/phpBB/phpbb/textreparser/plugins/poll_option.php b/phpBB/phpbb/textreparser/plugins/poll_option.php index cc28599737..3249e21694 100644 --- a/phpBB/phpbb/textreparser/plugins/poll_option.php +++ b/phpBB/phpbb/textreparser/plugins/poll_option.php @@ -13,38 +13,62 @@ namespace phpbb\textreparser\plugins; -class poll_option extends \phpbb\textreparser\row_based_plugin +class poll_option extends \phpbb\textreparser\base { /** - * {@inheritdoc} + * @var \phpbb\db\driver\driver_interface */ - public function get_columns() + protected $db; + + /** + * Constructor + * + * @param \phpbb\db\driver\driver_interface $db Database connection + */ + public function __construct(\phpbb\db\driver\driver_interface $db) { - return array( - 'id' => 'poll_option_id', - 'text' => 'poll_option_text', - ); + $this->db = $db; } /** * {@inheritdoc} */ - protected function get_records_query($min_id, $max_id) + public function get_max_id() { - $sql = 'SELECT o.poll_option_id AS id, o.poll_option_text AS text, p.bbcode_uid + $sql = 'SELECT MAX(topic_id) AS max_id FROM ' . POLL_OPTIONS_TABLE; + $result = $this->db->sql_query($sql); + $max_id = (int) $this->db->sql_fetchfield('max_id'); + $this->db->sql_freeresult($result); + + return $max_id; + } + + /** + * {@inheritdoc} + */ + protected function get_records($min_id, $max_id) + { + $sql = 'SELECT o.topic_id, o.poll_option_id, o.poll_option_text AS text, p.bbcode_uid FROM ' . POLL_OPTIONS_TABLE . ' o, ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p - WHERE o.poll_option_id BETWEEN ' . $min_id . ' AND ' . $max_id .' + WHERE o.topic_id BETWEEN ' . $min_id . ' AND ' . $max_id .' AND t.topic_id = o.topic_id AND p.post_id = t.topic_first_post_id'; + $result = $this->db->sql_query($sql); + $records = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); - return $sql; + return $records; } /** * {@inheritdoc} */ - public function get_table_name() + protected function save_record(array $record) { - return POLL_OPTIONS_TABLE; + $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . " + SET poll_option_text = '" . $this->db->sql_escape($record['text']) . "' + WHERE topic_id = " . $record['topic_id'] . ' + AND poll_option_id = ' . $record['poll_option_id']; + $this->db->sql_query($sql); } } diff --git a/tests/text_reparser/fixtures/poll_options.xml b/tests/text_reparser/fixtures/poll_options.xml index f0ed54aafb..c2fad9f764 100644 --- a/tests/text_reparser/fixtures/poll_options.xml +++ b/tests/text_reparser/fixtures/poll_options.xml @@ -12,48 +12,33 @@ 2 1 - [b]Not bold[/b] :) http://example.org + This row should be [b:abcd1234]ignored[/b:abcd1234] + + + 1 + 2 + [b:abcd1234]Bold[/b:abcd1234] + + + 2 + 2 + :)]]> 3 - 1 - [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + 2 + http://example.org]]> - 4 - 1 - :) http://example.org]]> - - - 5 - 1 - http://example.org]]> - - - 6 - 1 - - - - 7 - 1 - - - - 8 - 1 - - - - 9 - 1 - - - - 1000 1 + 123 This row should be [b]ignored[/b] + + 2 + 123 + This row should be [b:abcd1234]ignored[/b:abcd1234] + post_id @@ -74,5 +59,15 @@ 1This row should be [b]ignored[/b] + + 2 + 1 + This row should be [b]ignored[/b] + + + 123 + 1 + This row should be [b]ignored[/b] +
          diff --git a/tests/text_reparser/poll_option_test.php b/tests/text_reparser/poll_option_test.php index 0f08f720ff..669d859f9a 100644 --- a/tests/text_reparser/poll_option_test.php +++ b/tests/text_reparser/poll_option_test.php @@ -10,10 +10,14 @@ * the docs/CREDITS.txt file. * */ -include_once __DIR__ . '/test_row_based_plugin.php'; +require_once __DIR__ . '/../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; +require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; -class phpbb_textreparser_poll_option_test extends phpbb_textreparser_test_row_based_plugin +class phpbb_textreparser_poll_option_test extends phpbb_database_test_case { + protected $db; + public function getDataSet() { return $this->createXMLDataSet(__DIR__ . '/fixtures/poll_options.xml'); @@ -23,4 +27,74 @@ class phpbb_textreparser_poll_option_test extends phpbb_textreparser_test_row_ba { return new \phpbb\textreparser\plugins\poll_option($this->db); } + + public function setUp() + { + global $config; + if (!isset($config)) + { + $config = new \phpbb\config\config(array()); + } + $this->get_test_case_helpers()->set_s9e_services(); + $this->db = $this->new_dbal(); + parent::setUp(); + } + + public function test_get_max_id() + { + $reparser = $this->get_reparser(); + $this->assertEquals(123, $reparser->get_max_id()); + } + + public function testReparse() + { + $reparser = $this->get_reparser(); + $reparser->reparse_range(2, 3); + + $sql = 'SELECT topic_id, poll_option_id, poll_option_text + FROM ' . POLL_OPTIONS_TABLE . ' + ORDER BY topic_id, poll_option_id'; + $result = $this->db->sql_query($sql); + $rows = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + $expected = array( + array( + 'topic_id' => 1, + 'poll_option_id' => 1, + 'poll_option_text' => 'This row should be [b]ignored[/b]', + ), + array( + 'topic_id' => 1, + 'poll_option_id' => 2, + 'poll_option_text' => 'This row should be [b:abcd1234]ignored[/b:abcd1234]', + ), + array( + 'topic_id' => 2, + 'poll_option_id' => 1, + 'poll_option_text' => '[b]Bold[/b]', + ), + array( + 'topic_id' => 2, + 'poll_option_id' => 2, + 'poll_option_text' => ':)', + ), + array( + 'topic_id' => 2, + 'poll_option_id' => 3, + 'poll_option_text' => 'http://example.org', + ), + array( + 'topic_id' => 123, + 'poll_option_id' => 1, + 'poll_option_text' => 'This row should be [b]ignored[/b]', + ), + array( + 'topic_id' => 123, + 'poll_option_id' => 2, + 'poll_option_text' => 'This row should be [b:abcd1234]ignored[/b:abcd1234]', + ), + ); + $this->assertEquals($expected, $rows); + } } From 54b18df084b845c058426b38e7ccfeb534d04ce0 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 10 May 2015 01:54:54 +0200 Subject: [PATCH 0373/1676] [ticket/13803] Added contact_admin_info tests PHPBB3-13803 --- .../container/services_text_reparser.yml | 4 +- ...ontact_info.php => contact_admin_info.php} | 4 +- .../text_reparser/contact_admin_info_test.php | 81 +++++++++++++++++++ .../fixtures/contact_admin_info.xml | 23 ++++++ 4 files changed, 108 insertions(+), 4 deletions(-) rename phpBB/phpbb/textreparser/plugins/{admin_contact_info.php => contact_admin_info.php} (91%) create mode 100644 tests/text_reparser/contact_admin_info_test.php create mode 100644 tests/text_reparser/fixtures/contact_admin_info.xml diff --git a/phpBB/config/default/container/services_text_reparser.yml b/phpBB/config/default/container/services_text_reparser.yml index c10a8c600a..f25728d9c8 100644 --- a/phpBB/config/default/container/services_text_reparser.yml +++ b/phpBB/config/default/container/services_text_reparser.yml @@ -1,6 +1,6 @@ services: - text_reparser.admin_contact_info: - class: phpbb\textreparser\plugins\admin_contact_info + text_reparser.contact_admin_info: + class: phpbb\textreparser\plugins\contact_admin_info arguments: - @config_text tags: diff --git a/phpBB/phpbb/textreparser/plugins/admin_contact_info.php b/phpBB/phpbb/textreparser/plugins/contact_admin_info.php similarity index 91% rename from phpBB/phpbb/textreparser/plugins/admin_contact_info.php rename to phpBB/phpbb/textreparser/plugins/contact_admin_info.php index e432ddea81..d21ef89445 100644 --- a/phpBB/phpbb/textreparser/plugins/admin_contact_info.php +++ b/phpBB/phpbb/textreparser/plugins/contact_admin_info.php @@ -13,7 +13,7 @@ namespace phpbb\textreparser\plugins; -class admin_contact_info extends \phpbb\textreparser\base +class contact_admin_info extends \phpbb\textreparser\base { /** * @var \phpbb\config\db_text @@ -64,6 +64,6 @@ class admin_contact_info extends \phpbb\textreparser\base */ protected function save_record(array $record) { - $this->config_text->set('admin_contact_info', $record['text']); + $this->config_text->set('contact_admin_info', $record['text']); } } diff --git a/tests/text_reparser/contact_admin_info_test.php b/tests/text_reparser/contact_admin_info_test.php new file mode 100644 index 0000000000..5cccdfa4d5 --- /dev/null +++ b/tests/text_reparser/contact_admin_info_test.php @@ -0,0 +1,81 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +require_once __DIR__ . '/../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; +require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; + +class phpbb_textreparser_contact_admin_info_test extends phpbb_database_test_case +{ + protected $db; + + public function getDataSet() + { + return $this->createXMLDataSet(__DIR__ . '/fixtures/contact_admin_info.xml'); + } + + protected function get_reparser() + { + return new \phpbb\textreparser\plugins\contact_admin_info(new \phpbb\config\db_text($this->db, CONFIG_TEXT_TABLE)); + } + + public function setUp() + { + global $config; + if (!isset($config)) + { + $config = new \phpbb\config\config(array()); + } + $this->get_test_case_helpers()->set_s9e_services(); + $this->db = $this->new_dbal(); + parent::setUp(); + } + + public function test_get_max_id() + { + $reparser = $this->get_reparser(); + $this->assertEquals(1, $reparser->get_max_id()); + } + + public function testReparse() + { + $reparser = $this->get_reparser(); + $reparser->reparse_range(1, 1); + + $sql = 'SELECT config_name, config_value + FROM ' . CONFIG_TEXT_TABLE . ' + ORDER BY config_name'; + $result = $this->db->sql_query($sql); + $rows = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + $expected = array( + array( + 'config_name' => 'contact_admin_info', + 'config_value' => '[email]admin@example.org[/email]', + ), + array( + 'config_name' => 'contact_admin_info_bitfield', + 'config_value' => 'ACA=', + ), + array( + 'config_name' => 'contact_admin_info_flags', + 'config_value' => '7', + ), + array( + 'config_name' => 'contact_admin_info_uid', + 'config_value' => '1a2hbwf5', + ), + ); + $this->assertEquals($expected, $rows); + } +} diff --git a/tests/text_reparser/fixtures/contact_admin_info.xml b/tests/text_reparser/fixtures/contact_admin_info.xml new file mode 100644 index 0000000000..13cd82b1a4 --- /dev/null +++ b/tests/text_reparser/fixtures/contact_admin_info.xml @@ -0,0 +1,23 @@ + + + + config_name + config_value + + contact_admin_info + [email:1a2hbwf5]admin@example.org[/email:1a2hbwf5] + + + contact_admin_info_uid + 1a2hbwf5 + + + contact_admin_info_bitfield + ACA= + + + contact_admin_info_flags + 7 + +
          +
          From 75eb283f8d7a7afcd3945d0d28bd0f58aa4f0cd6 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 19 May 2015 09:48:29 +0200 Subject: [PATCH 0374/1676] [ticket/13803] Renamed methods PHPBB3-13803 --- phpBB/phpbb/textreparser/base.php | 6 +++--- phpBB/phpbb/textreparser/plugins/contact_admin_info.php | 2 +- phpBB/phpbb/textreparser/plugins/poll_option.php | 2 +- phpBB/phpbb/textreparser/reparser_interface.php | 4 ++-- phpBB/phpbb/textreparser/row_based_plugin.php | 7 ++++--- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 47ac177e05..2b8cacb092 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -25,9 +25,9 @@ abstract class base implements reparser_interface * * @param integer $min_id Lower bound * @param integer $max_id Upper bound - * @return array Array of record + * @return array Array of records */ - abstract protected function get_records($min_id, $max_id); + abstract protected function get_records_by_range($min_id, $max_id); /** * {@inheritdoc} @@ -161,7 +161,7 @@ abstract class base implements reparser_interface */ public function reparse_range($min_id, $max_id) { - foreach ($this->get_records($min_id, $max_id) as $record) + foreach ($this->get_records_by_range($min_id, $max_id) as $record) { $this->reparse_record($record); } diff --git a/phpBB/phpbb/textreparser/plugins/contact_admin_info.php b/phpBB/phpbb/textreparser/plugins/contact_admin_info.php index d21ef89445..8910f2256b 100644 --- a/phpBB/phpbb/textreparser/plugins/contact_admin_info.php +++ b/phpBB/phpbb/textreparser/plugins/contact_admin_info.php @@ -41,7 +41,7 @@ class contact_admin_info extends \phpbb\textreparser\base /** * {@inheritdoc} */ - protected function get_records($min_id, $max_id) + protected function get_records_by_range($min_id, $max_id) { $values = $this->config_text->get_array(array( 'contact_admin_info', diff --git a/phpBB/phpbb/textreparser/plugins/poll_option.php b/phpBB/phpbb/textreparser/plugins/poll_option.php index 3249e21694..7b803146c4 100644 --- a/phpBB/phpbb/textreparser/plugins/poll_option.php +++ b/phpBB/phpbb/textreparser/plugins/poll_option.php @@ -46,7 +46,7 @@ class poll_option extends \phpbb\textreparser\base /** * {@inheritdoc} */ - protected function get_records($min_id, $max_id) + protected function get_records_by_range($min_id, $max_id) { $sql = 'SELECT o.topic_id, o.poll_option_id, o.poll_option_text AS text, p.bbcode_uid FROM ' . POLL_OPTIONS_TABLE . ' o, ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p diff --git a/phpBB/phpbb/textreparser/reparser_interface.php b/phpBB/phpbb/textreparser/reparser_interface.php index 20f8d92b1a..9ea1732870 100644 --- a/phpBB/phpbb/textreparser/reparser_interface.php +++ b/phpBB/phpbb/textreparser/reparser_interface.php @@ -25,8 +25,8 @@ interface reparser_interface /** * Reparse all records in given range * - * @param integer $min_id Lower bound - * @param integer $max_id Upper bound + * @param integer $min_id Lower bound + * @param integer $max_id Upper bound */ public function reparse_range($min_id, $max_id); } diff --git a/phpBB/phpbb/textreparser/row_based_plugin.php b/phpBB/phpbb/textreparser/row_based_plugin.php index 05a6e19553..d3ca334591 100644 --- a/phpBB/phpbb/textreparser/row_based_plugin.php +++ b/phpBB/phpbb/textreparser/row_based_plugin.php @@ -62,9 +62,10 @@ abstract class row_based_plugin extends base /** * {@inheritdoc} */ - protected function get_records($min_id, $max_id) + protected function get_records_by_range($min_id, $max_id) { - $result = $this->db->sql_query($this->get_records_query($min_id, $max_id)); + $sql = $this->get_records_by_range_query($min_id, $max_id); + $result = $this->db->sql_query($sql); $records = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); @@ -78,7 +79,7 @@ abstract class row_based_plugin extends base * @param integer $max_id Upper bound * @return string SQL query */ - protected function get_records_query($min_id, $max_id) + protected function get_records_by_range_query($min_id, $max_id) { $columns = $this->get_columns(); $fields = array(); From 1bff7d1175cb92f10d9fc872c2bae05b1f955174 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 19 May 2015 11:29:52 +0200 Subject: [PATCH 0375/1676] [ticket/13803] Fixed method name PHPBB3-13803 --- phpBB/phpbb/textreparser/plugins/poll_title.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/textreparser/plugins/poll_title.php b/phpBB/phpbb/textreparser/plugins/poll_title.php index 6665d68847..b447004527 100644 --- a/phpBB/phpbb/textreparser/plugins/poll_title.php +++ b/phpBB/phpbb/textreparser/plugins/poll_title.php @@ -29,7 +29,7 @@ class poll_title extends \phpbb\textreparser\row_based_plugin /** * {@inheritdoc} */ - protected function get_records_query($min_id, $max_id) + protected function get_records_by_range_query($min_id, $max_id) { $sql = 'SELECT t.topic_id AS id, t.poll_title AS text, p.bbcode_uid FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p From f463b99ad0e6592567ed5a7fa5d2e765089b80ae Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 20 May 2015 04:03:40 +0200 Subject: [PATCH 0376/1676] [ticket/13803] Updated services.yml [ci skip] PHPBB3-13803 --- phpBB/config/default/container/services.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 6577a44195..a6b133853a 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -17,6 +17,7 @@ imports: - { resource: services_report.yml } - { resource: services_routing.yml } - { resource: services_text_formatter.yml } + - { resource: services_text_reparser.yml } - { resource: services_twig.yml } - { resource: services_user.yml } From 1275f77da5e1522d530bee55a5aa493817f58e71 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 20 May 2015 10:34:49 +0200 Subject: [PATCH 0377/1676] [ticket/13803] Renamed var PHPBB3-13803 --- phpBB/phpbb/textreparser/base.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 2b8cacb092..4afcecff6a 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -185,10 +185,10 @@ abstract class base implements reparser_interface ); // generate_text_for_edit() and decode_message() actually return the text as HTML. It has to // be decoded to plain text before it can be reparsed - $parsed_text = html_entity_decode($unparsed['text'], ENT_QUOTES, 'UTF-8'); + $text = html_entity_decode($unparsed['text'], ENT_QUOTES, 'UTF-8'); $bitfield = $flags = null; generate_text_for_storage( - $parsed_text, + $text, $unparsed['bbcode_uid'], $bitfield, $flags, @@ -202,9 +202,9 @@ abstract class base implements reparser_interface ); // Save the new text if it has changed - if ($parsed_text !== $record['text']) + if ($text !== $record['text']) { - $record['text'] = $parsed_text; + $record['text'] = $text; $this->save_record($record); } } From c8052ea8230cf7bb70c979dfc87b04527635f4b0 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 29 May 2015 17:35:26 +0200 Subject: [PATCH 0378/1676] [ticket/13803] Set up a global $user for tests PHPBB3-13803 --- tests/test_framework/phpbb_test_case_helpers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 210cda9a94..cf530cc5be 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -315,7 +315,7 @@ class phpbb_test_case_helpers public function set_s9e_services(ContainerInterface $container = null, $fixture = null, $styles_path = null) { static $first_run; - global $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx; + global $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx, $user; $cache_dir = __DIR__ . '/../tmp/'; From 132282634ff746c6c4627b87e307df3748f7bbd9 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 29 May 2015 17:36:06 +0200 Subject: [PATCH 0379/1676] [ticket/13803] Moved tests to a subdir PHPBB3-13803 --- .../text_reparser/{ => plugins}/contact_admin_info_test.php | 6 +++--- .../{ => plugins}/fixtures/contact_admin_info.xml | 0 tests/text_reparser/{ => plugins}/fixtures/forums.xml | 0 tests/text_reparser/{ => plugins}/fixtures/groups.xml | 0 tests/text_reparser/{ => plugins}/fixtures/poll_options.xml | 0 tests/text_reparser/{ => plugins}/fixtures/polls.xml | 0 tests/text_reparser/{ => plugins}/fixtures/posts.xml | 0 tests/text_reparser/{ => plugins}/fixtures/privmsgs.xml | 0 tests/text_reparser/{ => plugins}/fixtures/users.xml | 0 .../text_reparser/{ => plugins}/forum_description_test.php | 0 tests/text_reparser/{ => plugins}/forum_rules_test.php | 0 .../text_reparser/{ => plugins}/group_description_test.php | 0 tests/text_reparser/{ => plugins}/pm_text_test.php | 0 tests/text_reparser/{ => plugins}/poll_option_test.php | 6 +++--- tests/text_reparser/{ => plugins}/poll_title_test.php | 0 tests/text_reparser/{ => plugins}/post_text_test.php | 0 tests/text_reparser/{ => plugins}/test_row_based_plugin.php | 6 +++--- tests/text_reparser/{ => plugins}/user_signature_test.php | 0 18 files changed, 9 insertions(+), 9 deletions(-) rename tests/text_reparser/{ => plugins}/contact_admin_info_test.php (89%) rename tests/text_reparser/{ => plugins}/fixtures/contact_admin_info.xml (100%) rename tests/text_reparser/{ => plugins}/fixtures/forums.xml (100%) rename tests/text_reparser/{ => plugins}/fixtures/groups.xml (100%) rename tests/text_reparser/{ => plugins}/fixtures/poll_options.xml (100%) rename tests/text_reparser/{ => plugins}/fixtures/polls.xml (100%) rename tests/text_reparser/{ => plugins}/fixtures/posts.xml (100%) rename tests/text_reparser/{ => plugins}/fixtures/privmsgs.xml (100%) rename tests/text_reparser/{ => plugins}/fixtures/users.xml (100%) rename tests/text_reparser/{ => plugins}/forum_description_test.php (100%) rename tests/text_reparser/{ => plugins}/forum_rules_test.php (100%) rename tests/text_reparser/{ => plugins}/group_description_test.php (100%) rename tests/text_reparser/{ => plugins}/pm_text_test.php (100%) rename tests/text_reparser/{ => plugins}/poll_option_test.php (91%) rename tests/text_reparser/{ => plugins}/poll_title_test.php (100%) rename tests/text_reparser/{ => plugins}/post_text_test.php (100%) rename tests/text_reparser/{ => plugins}/test_row_based_plugin.php (93%) rename tests/text_reparser/{ => plugins}/user_signature_test.php (100%) diff --git a/tests/text_reparser/contact_admin_info_test.php b/tests/text_reparser/plugins/contact_admin_info_test.php similarity index 89% rename from tests/text_reparser/contact_admin_info_test.php rename to tests/text_reparser/plugins/contact_admin_info_test.php index 5cccdfa4d5..e577d2fd3d 100644 --- a/tests/text_reparser/contact_admin_info_test.php +++ b/tests/text_reparser/plugins/contact_admin_info_test.php @@ -10,9 +10,9 @@ * the docs/CREDITS.txt file. * */ -require_once __DIR__ . '/../../phpBB/includes/functions.php'; -require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; -require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; +require_once __DIR__ . '/../../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../../phpBB/includes/functions_content.php'; +require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php'; class phpbb_textreparser_contact_admin_info_test extends phpbb_database_test_case { diff --git a/tests/text_reparser/fixtures/contact_admin_info.xml b/tests/text_reparser/plugins/fixtures/contact_admin_info.xml similarity index 100% rename from tests/text_reparser/fixtures/contact_admin_info.xml rename to tests/text_reparser/plugins/fixtures/contact_admin_info.xml diff --git a/tests/text_reparser/fixtures/forums.xml b/tests/text_reparser/plugins/fixtures/forums.xml similarity index 100% rename from tests/text_reparser/fixtures/forums.xml rename to tests/text_reparser/plugins/fixtures/forums.xml diff --git a/tests/text_reparser/fixtures/groups.xml b/tests/text_reparser/plugins/fixtures/groups.xml similarity index 100% rename from tests/text_reparser/fixtures/groups.xml rename to tests/text_reparser/plugins/fixtures/groups.xml diff --git a/tests/text_reparser/fixtures/poll_options.xml b/tests/text_reparser/plugins/fixtures/poll_options.xml similarity index 100% rename from tests/text_reparser/fixtures/poll_options.xml rename to tests/text_reparser/plugins/fixtures/poll_options.xml diff --git a/tests/text_reparser/fixtures/polls.xml b/tests/text_reparser/plugins/fixtures/polls.xml similarity index 100% rename from tests/text_reparser/fixtures/polls.xml rename to tests/text_reparser/plugins/fixtures/polls.xml diff --git a/tests/text_reparser/fixtures/posts.xml b/tests/text_reparser/plugins/fixtures/posts.xml similarity index 100% rename from tests/text_reparser/fixtures/posts.xml rename to tests/text_reparser/plugins/fixtures/posts.xml diff --git a/tests/text_reparser/fixtures/privmsgs.xml b/tests/text_reparser/plugins/fixtures/privmsgs.xml similarity index 100% rename from tests/text_reparser/fixtures/privmsgs.xml rename to tests/text_reparser/plugins/fixtures/privmsgs.xml diff --git a/tests/text_reparser/fixtures/users.xml b/tests/text_reparser/plugins/fixtures/users.xml similarity index 100% rename from tests/text_reparser/fixtures/users.xml rename to tests/text_reparser/plugins/fixtures/users.xml diff --git a/tests/text_reparser/forum_description_test.php b/tests/text_reparser/plugins/forum_description_test.php similarity index 100% rename from tests/text_reparser/forum_description_test.php rename to tests/text_reparser/plugins/forum_description_test.php diff --git a/tests/text_reparser/forum_rules_test.php b/tests/text_reparser/plugins/forum_rules_test.php similarity index 100% rename from tests/text_reparser/forum_rules_test.php rename to tests/text_reparser/plugins/forum_rules_test.php diff --git a/tests/text_reparser/group_description_test.php b/tests/text_reparser/plugins/group_description_test.php similarity index 100% rename from tests/text_reparser/group_description_test.php rename to tests/text_reparser/plugins/group_description_test.php diff --git a/tests/text_reparser/pm_text_test.php b/tests/text_reparser/plugins/pm_text_test.php similarity index 100% rename from tests/text_reparser/pm_text_test.php rename to tests/text_reparser/plugins/pm_text_test.php diff --git a/tests/text_reparser/poll_option_test.php b/tests/text_reparser/plugins/poll_option_test.php similarity index 91% rename from tests/text_reparser/poll_option_test.php rename to tests/text_reparser/plugins/poll_option_test.php index 669d859f9a..e043858597 100644 --- a/tests/text_reparser/poll_option_test.php +++ b/tests/text_reparser/plugins/poll_option_test.php @@ -10,9 +10,9 @@ * the docs/CREDITS.txt file. * */ -require_once __DIR__ . '/../../phpBB/includes/functions.php'; -require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; -require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; +require_once __DIR__ . '/../../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../../phpBB/includes/functions_content.php'; +require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php'; class phpbb_textreparser_poll_option_test extends phpbb_database_test_case { diff --git a/tests/text_reparser/poll_title_test.php b/tests/text_reparser/plugins/poll_title_test.php similarity index 100% rename from tests/text_reparser/poll_title_test.php rename to tests/text_reparser/plugins/poll_title_test.php diff --git a/tests/text_reparser/post_text_test.php b/tests/text_reparser/plugins/post_text_test.php similarity index 100% rename from tests/text_reparser/post_text_test.php rename to tests/text_reparser/plugins/post_text_test.php diff --git a/tests/text_reparser/test_row_based_plugin.php b/tests/text_reparser/plugins/test_row_based_plugin.php similarity index 93% rename from tests/text_reparser/test_row_based_plugin.php rename to tests/text_reparser/plugins/test_row_based_plugin.php index 489dff280b..befcb48bda 100644 --- a/tests/text_reparser/test_row_based_plugin.php +++ b/tests/text_reparser/plugins/test_row_based_plugin.php @@ -10,9 +10,9 @@ * the docs/CREDITS.txt file. * */ -require_once __DIR__ . '/../../phpBB/includes/functions.php'; -require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; -require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; +require_once __DIR__ . '/../../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../../phpBB/includes/functions_content.php'; +require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php'; abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_test_case { diff --git a/tests/text_reparser/user_signature_test.php b/tests/text_reparser/plugins/user_signature_test.php similarity index 100% rename from tests/text_reparser/user_signature_test.php rename to tests/text_reparser/plugins/user_signature_test.php From 25ce302a605952e0a38605c6255c5ad212c2b4c6 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 29 May 2015 23:05:11 +0200 Subject: [PATCH 0380/1676] [ticket/13803] Added text_reparser_collection service PHPBB3-13803 --- phpBB/config/default/container/services_text_reparser.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/phpBB/config/default/container/services_text_reparser.yml b/phpBB/config/default/container/services_text_reparser.yml index f25728d9c8..5d54e8dc82 100644 --- a/phpBB/config/default/container/services_text_reparser.yml +++ b/phpBB/config/default/container/services_text_reparser.yml @@ -1,4 +1,11 @@ services: + text_reparser_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: text_reparser.plugin } + text_reparser.contact_admin_info: class: phpbb\textreparser\plugins\contact_admin_info arguments: From 2a7d26d3debdce7ca82f3044de45b651286c6034 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 29 May 2015 23:38:01 +0200 Subject: [PATCH 0381/1676] [ticket/13803] Use accurate flags for generate_text_for_edit() PHPBB3-13803 --- phpBB/phpbb/textreparser/base.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 4afcecff6a..87a4268d0d 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -175,14 +175,14 @@ abstract class base implements reparser_interface protected function reparse_record(array $record) { $record = $this->add_missing_fields($record); + $flags = ($record['enable_bbcode']) ? OPTION_FLAG_BBCODE : 0; + $flags |= ($record['enable_smilies']) ? OPTION_FLAG_SMILIES : 0; + $flags |= ($record['enable_magic_url']) ? OPTION_FLAG_LINKS : 0; $unparsed = array_merge( $record, - generate_text_for_edit( - $record['text'], - $record['bbcode_uid'], - OPTION_FLAG_BBCODE | OPTION_FLAG_SMILIES | OPTION_FLAG_LINKS - ) + generate_text_for_edit($record['text'], $record['bbcode_uid'], $flags) ); + // generate_text_for_edit() and decode_message() actually return the text as HTML. It has to // be decoded to plain text before it can be reparsed $text = html_entity_decode($unparsed['text'], ENT_QUOTES, 'UTF-8'); From 2f0d11ba3c28f27e535988de2a8d08f7b17aef92 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 30 May 2015 22:17:14 +0200 Subject: [PATCH 0382/1676] [ticket/13901] Add more whitespace to long quotes for readability PHPBB3-13901 --- phpBB/includes/ucp/ucp_pm_compose.php | 6 +++--- phpBB/phpbb/textformatter/s9e/utils.php | 5 ++++- phpBB/posting.php | 4 ++-- tests/text_formatter/s9e/default_formatting_test.php | 4 ++++ tests/text_formatter/s9e/utils_test.php | 10 ++++++++++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 4ff27e8cf1..ae0c0f6049 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -942,10 +942,10 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $message_link = ''; } $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( - censor_text(trim($message_parser->message)), + censor_text($message_parser->message), array('author' => $quote_username) ); - $message_parser->message = $message_link . $quote_text . "\n"; + $message_parser->message = $message_link . $quote_text . "\n\n"; } if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh) @@ -974,7 +974,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $forward_text[] = sprintf($user->lang['FWD_TO'], implode($user->lang['COMMA_SEPARATOR'], $fwd_to_field['to'])); $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( - censor_text(trim($message_parser->message)), + censor_text($message_parser->message), array('author' => $quote_username) ); $message_parser->message = implode("\n", $forward_text) . "\n\n" . $quote_text; diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index 04df589930..64fdb628ca 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -56,6 +56,7 @@ class utils implements \phpbb\textformatter\utils_interface */ public function generate_quote($text, array $attributes = array()) { + $text = trim($text); $quote = '[quote'; if (isset($attributes['author'])) { @@ -67,7 +68,9 @@ class utils implements \phpbb\textformatter\utils_interface { $quote .= ' ' . $name . '=' . $this->enquote($value); } - $quote .= ']' . $text . '[/quote]'; + $quote .= ']'; + $newline = (strlen($quote . $text . '[/quote]') > 80) ? "\n" : ''; + $quote .= $newline . $text . $newline . '[/quote]'; return $quote; } diff --git a/phpBB/posting.php b/phpBB/posting.php index 1c7b756fc2..4f4c6cd373 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1598,10 +1598,10 @@ if ($generate_quote) if ($config['allow_bbcode']) { $message_parser->message = $phpbb_container->get('text_formatter.utils')->generate_quote( - censor_text(trim($message_parser->message)), + censor_text($message_parser->message), array('author' => $post_data['quote_username']) ); - $message_parser->message .= "\n"; + $message_parser->message .= "\n\n"; } else { diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 2aa15146aa..67921d5b1e 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -221,6 +221,10 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case '[quote="http://example.org"]...[/quote]', '
          ' ), + array( + "[quote]\nThis is a long quote that is definitely going to exceed 80 characters\n[/quote]\n\nFollowed by a reply", + "
          \nThis is a long quote that is definitely going to exceed 80 characters\n
          \n\nFollowed by a reply" + ), ); } } diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index 555f29cb38..d40d450f5a 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -171,6 +171,16 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case ), '[quote="user" post_id="123" url="http://example.org"]...[/quote]', ), + array( + 'This is a long quote that is definitely going to exceed 80 characters', + array(), + "[quote]\nThis is a long quote that is definitely going to exceed 80 characters\n[/quote]", + ), + array( + ' This is a short quote on its own line ', + array(), + '[quote]This is a short quote on its own line[/quote]', + ), ); } From b69e33c2b0dfaaf9274e783cd189a8d1d49bce07 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 30 May 2015 22:20:52 +0200 Subject: [PATCH 0383/1676] [ticket/13901] Add whitespace to short, multiline quotes for readability PHPBB3-13901 --- phpBB/phpbb/textformatter/s9e/utils.php | 2 +- tests/text_formatter/s9e/utils_test.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index 64fdb628ca..803c71a5a2 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -69,7 +69,7 @@ class utils implements \phpbb\textformatter\utils_interface $quote .= ' ' . $name . '=' . $this->enquote($value); } $quote .= ']'; - $newline = (strlen($quote . $text . '[/quote]') > 80) ? "\n" : ''; + $newline = (strlen($quote . $text . '[/quote]') > 80 || strpos($text, "\n") !== false) ? "\n" : ''; $quote .= $newline . $text . $newline . '[/quote]'; return $quote; diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index d40d450f5a..152c316b2e 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -181,6 +181,11 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case array(), '[quote]This is a short quote on its own line[/quote]', ), + array( + "This is a short quote\non two lines", + array(), + "[quote]\nThis is a short quote\non two lines\n[/quote]", + ), ); } From 433021f429f22dfd6d5dfc16c11195b19a488161 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 30 May 2015 23:51:09 +0200 Subject: [PATCH 0384/1676] [ticket/13901] Fixed test's expected result PHPBB3-13901 --- tests/functional/private_messages_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/private_messages_test.php b/tests/functional/private_messages_test.php index 3f602d62fb..be584c20c1 100644 --- a/tests/functional/private_messages_test.php +++ b/tests/functional/private_messages_test.php @@ -84,7 +84,7 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case public function test_quote_forward() { $text = 'This is a test private message sent by the testing framework.'; - $expected = '[quote="admin"]' . $text . '[/quote]'; + $expected = "[quote=\"admin\"]\n" . $text . "\n[/quote]"; $this->login(); $message_id = $this->create_private_message('Test', $text, array(2)); From 6ac37145ec1bb41625c0c6a3875e4392ab6b703b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 31 May 2015 10:13:20 +0200 Subject: [PATCH 0385/1676] [ticket/8420] Added regression test PHPBB3-8420 --- tests/functional/posting_test.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 8677237772..49f0c1d749 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -166,4 +166,18 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $crawler = self::submit($form); $this->assertEquals(1, $crawler->filter('.successbox')->count()); } + + public function test_ticket_8420() + { + $text = '[b][url=http://example.org] :arrow: here[/url][/b]'; + + $this->login(); + $crawler = self::request('GET', 'posting.php?mode=post&f=2'); + $form = $crawler->selectButton('Preview')->form(array( + 'subject' => 'Test subject', + 'message' => $text + )); + $crawler = self::submit($form); + $this->assertEquals($text, $crawler->filter('#message')->text()); + } } From 71d03647f0433fca5a071e485d3f0cc3145c44d1 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Sun, 31 May 2015 13:19:50 +0200 Subject: [PATCH 0386/1676] [ticket/13777] Move module management into service PHPBB3-13777 --- phpBB/config/default/container/services.yml | 1 + .../default/container/services_module.yml | 10 + phpBB/includes/acp/acp_modules.php | 619 +++--------------- .../module_class_not_defined_exception.php | 19 + .../module/exception/module_exception.php | 19 + .../exception/module_not_found_exception.php | 19 + phpBB/phpbb/module/module_manager.php | 570 ++++++++++++++++ 7 files changed, 727 insertions(+), 530 deletions(-) create mode 100644 phpBB/config/default/container/services_module.yml create mode 100644 phpBB/phpbb/module/exception/module_class_not_defined_exception.php create mode 100644 phpBB/phpbb/module/exception/module_exception.php create mode 100644 phpBB/phpbb/module/exception/module_not_found_exception.php create mode 100644 phpBB/phpbb/module/module_manager.php diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 6577a44195..9b5fd538ee 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -11,6 +11,7 @@ imports: - { resource: services_help.yml } - { resource: services_language.yml } - { resource: services_mimetype_guesser.yml } + - { resource: services_module.yml } - { resource: services_notification.yml } - { resource: services_password.yml } - { resource: services_profilefield.yml } diff --git a/phpBB/config/default/container/services_module.yml b/phpBB/config/default/container/services_module.yml new file mode 100644 index 0000000000..513b71553a --- /dev/null +++ b/phpBB/config/default/container/services_module.yml @@ -0,0 +1,10 @@ +services: + module.manager: + class: phpbb\module\module_manager + arguments: + - @cache.driver + - @dbal.conn + - @ext.manager + - %tables.modules% + - %core.root_path% + - %core.php_ext% diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index 4fca366868..45eba48777 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -19,6 +19,8 @@ if (!defined('IN_PHPBB')) exit; } +use phpbb\module\exception\module_exception; + /** * - Able to check for new module versions (modes changed/adjusted/added/removed) * Icons for: @@ -37,8 +39,10 @@ class acp_modules function main($id, $mode) { - global $db, $user, $auth, $template, $module, $request, $phpbb_log; - global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; + global $db, $user, $template, $module, $request, $phpbb_log, $phpbb_container; + + /** @var \phpbb\module\module_manager $module_manager */ + $module_manager = $phpbb_container->get('module.manager'); // Set a global define for modules we might include (the author is able to prevent execution of code by checking this constant) define('MODULE_INCLUDE', true); @@ -91,13 +95,20 @@ class acp_modules $db->sql_freeresult($result); } - $errors = $this->delete_module($module_id); - - if (!sizeof($errors)) + try { - $this->remove_cache_file(); - trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + $row = $module_manager->get_module_row($module_id, $this->module_class); + $module_manager->delete_module($module_id, $this->module_class); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_REMOVED', false, array($user->lang($row['module_langname']))); } + catch (module_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $module_manager->remove_cache_file($this->module_class); + trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); } else { @@ -138,8 +149,8 @@ class acp_modules AND module_id = $module_id"; $db->sql_query($sql); - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($this->lang_name($row['module_langname']))); - $this->remove_cache_file(); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($user->lang($row['module_langname']))); + $module_manager->remove_cache_file($this->module_class); break; @@ -163,12 +174,16 @@ class acp_modules trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } - $move_module_name = $this->move_module_by($row, $action, 1); - - if ($move_module_name !== false) + try { - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($this->lang_name($row['module_langname']), $move_module_name)); - $this->remove_cache_file(); + $move_module_name = $module_manager->move_module_by($row, $this->module_class, $action, 1); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($user->lang($row['module_langname']), $move_module_name)); + $module_manager->remove_cache_file($this->module_class); + } + catch (module_exception $e) + { + // Do nothing } if ($request->is_ajax()) @@ -194,7 +209,7 @@ class acp_modules list($module_basename, $module_mode) = explode('::', $quick_install); // Check if module name and mode exist... - $fileinfo = $this->get_module_infos($module_basename); + $fileinfo = $module_manager->get_module_infos($module_basename, $this->module_class); $fileinfo = $fileinfo[$module_basename]; if (isset($fileinfo['modes'][$module_mode])) @@ -210,11 +225,20 @@ class acp_modules 'module_auth' => $fileinfo['modes'][$module_mode]['auth'], ); - $errors = $this->update_module_data($module_data); + try + { + $module_manager->update_module_data($module_data); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($user->lang($module_data['module_langname']))); + } + catch (\phpbb\module\exception\module_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } if (!sizeof($errors)) { - $this->remove_cache_file(); + $module_manager->remove_cache_file($this->module_class); trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); } @@ -240,7 +264,15 @@ class acp_modules trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } - $module_row = $this->get_module_row($module_id); + try + { + $module_row = $module_manager->get_module_row($module_id, $this->module_class); + } + catch (\phpbb\module\exception\module_not_found_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } // no break @@ -294,15 +326,29 @@ class acp_modules // Adjust auth row if ($module_data['module_basename'] && $module_data['module_mode']) { - $fileinfo = $this->get_module_infos($module_data['module_basename']); + $fileinfo = $module_manager->get_module_infos($module_data['module_basename'], $this->module_class); $module_data['module_auth'] = $fileinfo[$module_data['module_basename']]['modes'][$module_data['module_mode']]['auth']; } - $errors = $this->update_module_data($module_data); + try + { + $module_manager->update_module_data($module_data); + $phpbb_log->add('admin', + $user->data['user_id'], + $user->ip, + ($action === 'edit') ? 'LOG_MODULE_EDIT' : 'LOG_MODULE_ADD', + false, + array($user->lang($module_data['module_langname'])) + ); } + catch (\phpbb\module\exception\module_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } if (!sizeof($errors)) { - $this->remove_cache_file(); + $module_manager->remove_cache_file($this->module_class); trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); } @@ -312,7 +358,7 @@ class acp_modules $is_cat = (!$module_data['module_basename']) ? true : false; // Get module information - $module_infos = $this->get_module_infos(); + $module_infos = $module_manager->get_module_infos('', $this->module_class); // Build name options $s_name_options = $s_mode_options = ''; @@ -324,7 +370,7 @@ class acp_modules } // Name options - $s_name_options .= ''; + $s_name_options .= ''; $template->assign_block_vars('m_names', array('NAME' => $option, 'A_NAME' => addslashes($option))); @@ -333,14 +379,14 @@ class acp_modules { if ($option == $module_data['module_basename']) { - $s_mode_options .= ''; + $s_mode_options .= ''; } $template->assign_block_vars('m_names.modes', array( 'OPTION' => $m_mode, - 'VALUE' => $this->lang_name($m_values['title']), + 'VALUE' => $user->lang($m_values['title']), 'A_OPTION' => addslashes($m_mode), - 'A_VALUE' => addslashes($this->lang_name($m_values['title']))) + 'A_VALUE' => addslashes($user->lang($m_values['title']))) ); } } @@ -358,7 +404,7 @@ class acp_modules 'L_TITLE' => $user->lang[strtoupper($action) . '_MODULE'], - 'MODULENAME' => $this->lang_name($module_data['module_langname']), + 'MODULENAME' => $user->lang($module_data['module_langname']), 'ACTION' => $action, 'MODULE_ID' => $module_id, @@ -406,11 +452,11 @@ class acp_modules { $navigation = '' . strtoupper($this->module_class) . ''; - $modules_nav = $this->get_module_branch($this->parent_id, 'parents', 'descending'); + $modules_nav = $module_manager->get_module_branch($this->parent_id, $this->module_class, 'parents'); foreach ($modules_nav as $row) { - $langname = $this->lang_name($row['module_langname']); + $langname = $user->lang($row['module_langname']); if ($row['module_id'] == $this->parent_id) { @@ -437,7 +483,7 @@ class acp_modules { do { - $langname = $this->lang_name($row['module_langname']); + $langname = $user->lang($row['module_langname']); if (!$row['module_enabled']) { @@ -472,7 +518,15 @@ class acp_modules } else if ($this->parent_id) { - $row = $this->get_module_row($this->parent_id); + try + { + $row = $module_manager->get_module_row($this->parent_id, $this->module_class); + } + catch (\phpbb\module\exception\module_not_found_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } $url = $this->u_action . '&parent_id=' . $this->parent_id . '&m=' . $row['module_id']; @@ -491,19 +545,19 @@ class acp_modules $db->sql_freeresult($result); // Quick adding module - $module_infos = $this->get_module_infos(); + $module_infos = $module_manager->get_module_infos('', $this->module_class); // Build quick options $s_install_options = ''; foreach ($module_infos as $option => $values) { // Name options - $s_install_options .= ''; + $s_install_options .= ''; // Build module modes foreach ($values['modes'] as $m_mode => $m_values) { - $s_install_options .= ''; + $s_install_options .= ''; } $s_install_options .= ''; @@ -520,104 +574,6 @@ class acp_modules ); } - /** - * Get row for specified module - */ - function get_module_row($module_id) - { - global $db, $user; - - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND module_id = $module_id"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$row) - { - trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); - } - - return $row; - } - - /** - * Get available module information from module files - * - * @param string $module - * @param bool|string $module_class - * @param bool $use_all_available Use all available instead of just all - * enabled extensions - * @return array - */ - function get_module_infos($module = '', $module_class = false, $use_all_available = false) - { - global $phpbb_extension_manager, $phpbb_root_path, $phpEx; - - $module_class = ($module_class === false) ? $this->module_class : $module_class; - - $directory = $phpbb_root_path . 'includes/' . $module_class . '/info/'; - $fileinfo = array(); - - $finder = $phpbb_extension_manager->get_finder($use_all_available); - - $modules = $finder - ->extension_suffix('_module') - ->extension_directory("/$module_class") - ->core_path("includes/$module_class/info/") - ->core_prefix($module_class . '_') - ->get_classes(true); - - foreach ($modules as $cur_module) - { - // Skip entries we do not need if we know the module we are - // looking for - if ($module && strpos(str_replace('\\', '_', $cur_module), $module) === false && $module !== $cur_module) - { - continue; - } - - $info_class = preg_replace('/_module$/', '_info', $cur_module); - - // If the class does not exist it might be following the old - // format. phpbb_acp_info_acp_foo needs to be turned into - // acp_foo_info and the respective file has to be included - // manually because it does not support auto loading - $old_info_class_file = str_replace("phpbb_{$module_class}_info_", '', $cur_module); - $old_info_class = $old_info_class_file . '_info'; - - if (class_exists($old_info_class)) - { - $info_class = $old_info_class; - } - else if (!class_exists($info_class)) - { - $info_class = $old_info_class; - // need to check class exists again because previous checks triggered autoloading - if (!class_exists($info_class) && file_exists($directory . $old_info_class_file . '.' . $phpEx)) - { - include($directory . $old_info_class_file . '.' . $phpEx); - } - } - - if (class_exists($info_class)) - { - $info = new $info_class(); - $module_info = $info->module(); - - $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $cur_module; - - $fileinfo[$main_class] = $module_info; - } - } - - ksort($fileinfo); - - return $fileinfo; - } - /** * Simple version of jumpbox, just lists modules */ @@ -678,7 +634,7 @@ class acp_modules $selected = (is_array($select_id)) ? ((in_array($row['module_id'], $select_id)) ? ' selected="selected"' : '') : (($row['module_id'] == $select_id) ? ' selected="selected"' : ''); - $langname = $this->lang_name($row['module_langname']); + $langname = $user->lang($row['module_langname']); $module_list .= ''; $iteration++; @@ -689,401 +645,4 @@ class acp_modules return $module_list; } - - /** - * Get module branch - */ - function get_module_branch($module_id, $type = 'all', $order = 'descending', $include_module = true) - { - global $db; - - switch ($type) - { - case 'parents': - $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id'; - break; - - case 'children': - $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id'; - break; - - default: - $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id'; - break; - } - - $rows = array(); - - $sql = 'SELECT m2.* - FROM ' . MODULES_TABLE . ' m1 - LEFT JOIN ' . MODULES_TABLE . " m2 ON ($condition) - WHERE m1.module_class = '" . $db->sql_escape($this->module_class) . "' - AND m2.module_class = '" . $db->sql_escape($this->module_class) . "' - AND m1.module_id = $module_id - ORDER BY m2.left_id " . (($order == 'descending') ? 'ASC' : 'DESC'); - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - if (!$include_module && $row['module_id'] == $module_id) - { - continue; - } - - $rows[] = $row; - } - $db->sql_freeresult($result); - - return $rows; - } - - /** - * Remove modules cache file - */ - function remove_cache_file() - { - global $phpbb_container; - - // Sanitise for future path use, it's escaped as appropriate for queries - $p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class)); - - $phpbb_container->get('cache.driver')->destroy('_modules_' . $p_class); - - // Additionally remove sql cache - $phpbb_container->get('cache.driver')->destroy('sql', MODULES_TABLE); - } - - /** - * Return correct language name - */ - function lang_name($module_langname) - { - global $user; - - return (!empty($user->lang[$module_langname])) ? $user->lang[$module_langname] : $module_langname; - } - - /** - * Update/Add module - * - * @param array &$module_data The module data - * @param bool $run_inline if set to true errors will be returned and no logs being written - */ - function update_module_data(&$module_data, $run_inline = false) - { - global $db, $user, $phpbb_log; - - if (!isset($module_data['module_id'])) - { - // no module_id means we're creating a new category/module - if ($module_data['parent_id']) - { - $sql = 'SELECT left_id, right_id - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' - AND module_id = " . (int) $module_data['parent_id']; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$row) - { - if ($run_inline) - { - return 'PARENT_NO_EXIST'; - } - - trigger_error($user->lang['PARENT_NO_EXIST'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); - } - - // Workaround - $row['left_id'] = (int) $row['left_id']; - $row['right_id'] = (int) $row['right_id']; - - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id + 2, right_id = right_id + 2 - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' - AND left_id > {$row['right_id']}"; - $db->sql_query($sql); - - $sql = 'UPDATE ' . MODULES_TABLE . " - SET right_id = right_id + 2 - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' - AND {$row['left_id']} BETWEEN left_id AND right_id"; - $db->sql_query($sql); - - $module_data['left_id'] = (int) $row['right_id']; - $module_data['right_id'] = (int) $row['right_id'] + 1; - } - else - { - $sql = 'SELECT MAX(right_id) AS right_id - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $module_data['left_id'] = (int) $row['right_id'] + 1; - $module_data['right_id'] = (int) $row['right_id'] + 2; - } - - $sql = 'INSERT INTO ' . MODULES_TABLE . ' ' . $db->sql_build_array('INSERT', $module_data); - $db->sql_query($sql); - - $module_data['module_id'] = $db->sql_nextid(); - - if (!$run_inline) - { - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($this->lang_name($module_data['module_langname']))); - } - } - else - { - $row = $this->get_module_row($module_data['module_id']); - - if ($module_data['module_basename'] && !$row['module_basename']) - { - // we're turning a category into a module - $branch = $this->get_module_branch($module_data['module_id'], 'children', 'descending', false); - - if (sizeof($branch)) - { - return array($user->lang['NO_CATEGORY_TO_MODULE']); - } - } - - if ($row['parent_id'] != $module_data['parent_id']) - { - $this->move_module($module_data['module_id'], $module_data['parent_id']); - } - - $update_ary = $module_data; - unset($update_ary['module_id']); - - $sql = 'UPDATE ' . MODULES_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $update_ary) . " - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' - AND module_id = " . (int) $module_data['module_id']; - $db->sql_query($sql); - - if (!$run_inline) - { - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_EDIT', false, array($this->lang_name($module_data['module_langname']))); - } - } - - return array(); - } - - /** - * Move module around the tree - */ - function move_module($from_module_id, $to_parent_id) - { - global $db; - - $moved_modules = $this->get_module_branch($from_module_id, 'children', 'descending'); - $from_data = $moved_modules[0]; - $diff = sizeof($moved_modules) * 2; - - $moved_ids = array(); - for ($i = 0; $i < sizeof($moved_modules); ++$i) - { - $moved_ids[] = $moved_modules[$i]['module_id']; - } - - // Resync parents - $sql = 'UPDATE ' . MODULES_TABLE . " - SET right_id = right_id - $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id < " . (int) $from_data['right_id'] . ' - AND right_id > ' . (int) $from_data['right_id']; - $db->sql_query($sql); - - // Resync righthand side of tree - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id - $diff, right_id = right_id - $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id > " . (int) $from_data['right_id']; - $db->sql_query($sql); - - if ($to_parent_id > 0) - { - $to_data = $this->get_module_row($to_parent_id); - - // Resync new parents - $sql = 'UPDATE ' . MODULES_TABLE . " - SET right_id = right_id + $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id - AND ' . $db->sql_in_set('module_id', $moved_ids, true); - $db->sql_query($sql); - - // Resync the righthand side of the tree - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id + $diff, right_id = right_id + $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id > " . (int) $to_data['right_id'] . ' - AND ' . $db->sql_in_set('module_id', $moved_ids, true); - $db->sql_query($sql); - - // Resync moved branch - $to_data['right_id'] += $diff; - if ($to_data['right_id'] > $from_data['right_id']) - { - $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1); - } - else - { - $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1); - } - } - else - { - $sql = 'SELECT MAX(right_id) AS right_id - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND " . $db->sql_in_set('module_id', $moved_ids, true); - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1); - } - - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id $diff, right_id = right_id $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND " . $db->sql_in_set('module_id', $moved_ids); - $db->sql_query($sql); - } - - /** - * Remove module from tree - */ - function delete_module($module_id) - { - global $db, $user, $phpbb_log; - - $row = $this->get_module_row($module_id); - - $branch = $this->get_module_branch($module_id, 'children', 'descending', false); - - if (sizeof($branch)) - { - return array($user->lang['CANNOT_REMOVE_MODULE']); - } - - // If not move - $diff = 2; - $sql = 'DELETE FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND module_id = $module_id"; - $db->sql_query($sql); - - $row['right_id'] = (int) $row['right_id']; - $row['left_id'] = (int) $row['left_id']; - - // Resync tree - $sql = 'UPDATE ' . MODULES_TABLE . " - SET right_id = right_id - $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}"; - $db->sql_query($sql); - - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id - $diff, right_id = right_id - $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id > {$row['right_id']}"; - $db->sql_query($sql); - - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_REMOVED', false, array($this->lang_name($row['module_langname']))); - - return array(); - - } - - /** - * Move module position by $steps up/down - */ - function move_module_by($module_row, $action = 'move_up', $steps = 1) - { - global $db; - - /** - * Fetch all the siblings between the module's current spot - * and where we want to move it to. If there are less than $steps - * siblings between the current spot and the target then the - * module will move as far as possible - */ - $sql = 'SELECT module_id, left_id, right_id, module_langname - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND parent_id = " . (int) $module_row['parent_id'] . ' - AND ' . (($action == 'move_up') ? 'right_id < ' . (int) $module_row['right_id'] . ' ORDER BY right_id DESC' : 'left_id > ' . (int) $module_row['left_id'] . ' ORDER BY left_id ASC'); - $result = $db->sql_query_limit($sql, $steps); - - $target = array(); - while ($row = $db->sql_fetchrow($result)) - { - $target = $row; - } - $db->sql_freeresult($result); - - if (!sizeof($target)) - { - // The module is already on top or bottom - return false; - } - - /** - * $left_id and $right_id define the scope of the nodes that are affected by the move. - * $diff_up and $diff_down are the values to substract or add to each node's left_id - * and right_id in order to move them up or down. - * $move_up_left and $move_up_right define the scope of the nodes that are moving - * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down. - */ - if ($action == 'move_up') - { - $left_id = (int) $target['left_id']; - $right_id = (int) $module_row['right_id']; - - $diff_up = (int) ($module_row['left_id'] - $target['left_id']); - $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); - - $move_up_left = (int) $module_row['left_id']; - $move_up_right = (int) $module_row['right_id']; - } - else - { - $left_id = (int) $module_row['left_id']; - $right_id = (int) $target['right_id']; - - $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); - $diff_down = (int) ($target['right_id'] - $module_row['right_id']); - - $move_up_left = (int) ($module_row['right_id'] + 1); - $move_up_right = (int) $target['right_id']; - } - - // Now do the dirty job - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id + CASE - WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} - ELSE {$diff_down} - END, - right_id = right_id + CASE - WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} - ELSE {$diff_down} - END - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id BETWEEN {$left_id} AND {$right_id} - AND right_id BETWEEN {$left_id} AND {$right_id}"; - $db->sql_query($sql); - - $this->remove_cache_file(); - - return $this->lang_name($target['module_langname']); - } } diff --git a/phpBB/phpbb/module/exception/module_class_not_defined_exception.php b/phpBB/phpbb/module/exception/module_class_not_defined_exception.php new file mode 100644 index 0000000000..3551dc733d --- /dev/null +++ b/phpBB/phpbb/module/exception/module_class_not_defined_exception.php @@ -0,0 +1,19 @@ + + * @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\module\exception; + +class module_class_not_defined_exception extends module_exception +{ + +} diff --git a/phpBB/phpbb/module/exception/module_exception.php b/phpBB/phpbb/module/exception/module_exception.php new file mode 100644 index 0000000000..8ad75112bc --- /dev/null +++ b/phpBB/phpbb/module/exception/module_exception.php @@ -0,0 +1,19 @@ + + * @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\module\exception; + +class module_exception extends \phpbb\exception\runtime_exception +{ + +} diff --git a/phpBB/phpbb/module/exception/module_not_found_exception.php b/phpBB/phpbb/module/exception/module_not_found_exception.php new file mode 100644 index 0000000000..2d485e7b35 --- /dev/null +++ b/phpBB/phpbb/module/exception/module_not_found_exception.php @@ -0,0 +1,19 @@ + + * @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\module\exception; + +class module_not_found_exception extends module_exception +{ + +} diff --git a/phpBB/phpbb/module/module_manager.php b/phpBB/phpbb/module/module_manager.php new file mode 100644 index 0000000000..da3b037b5e --- /dev/null +++ b/phpBB/phpbb/module/module_manager.php @@ -0,0 +1,570 @@ + + * @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\module; + +use phpbb\module\exception\module_class_not_defined_exception; +use phpbb\module\exception\module_exception; +use phpbb\module\exception\module_not_found_exception; + +class module_manager +{ + /** + * @var \phpbb\cache\driver\driver_interface + */ + protected $cache; + + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \phpbb\extension\manager + */ + protected $extension_manager; + + /** + * @var string + */ + protected $modules_table; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param \phpbb\cache\driver\driver_interface $cache Cache driver + * @param \phpbb\db\driver\driver_interface $db Database driver + * @param \phpbb\extension\manager $ext_manager Extension manager + * @param string $modules_table Module database table's name + * @param string $phpbb_root_path Path to phpBB's root + * @param string $php_ext Extension of PHP files + */ + public function __construct(\phpbb\cache\driver\driver_interface $cache, \phpbb\db\driver\driver_interface $db, \phpbb\extension\manager $ext_manager, $modules_table, $phpbb_root_path, $php_ext) + { + $this->cache = $cache; + $this->db = $db; + $this->extension_manager = $ext_manager; + $this->modules_table = $modules_table; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + } + + /** + * Get row for specified module + * + * @param int $module_id ID of the module + * @param string $module_class Class of the module (acp, ucp, mcp etc...) + * + * @return array Array of data fetched from the database + * + * @throws \phpbb\module\exception\module_not_found_exception When there is no module with $module_id + */ + public function get_module_row($module_id, $module_class) + { + $module_id = (int) $module_id; + + $sql = 'SELECT * + FROM ' . $this->modules_table . " + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND module_id = $module_id"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if (!$row) + { + throw new module_not_found_exception('NO_MODULE'); + } + + return $row; + } + + /** + * Get available module information from module files + * + * @param string $module ID of module + * @param string $module_class Class of the module (acp, ucp, mcp etc...) + * @param bool $use_all_available Use all available instead of just all + * enabled extensions + * + * @return array Array with module information gathered from module info files. + */ + public function get_module_infos($module = '', $module_class = null, $use_all_available = false) + { + if ($module_class === null) + { + throw new module_class_not_defined_exception(); + } + + $directory = $this->phpbb_root_path . 'includes/' . $module_class . '/info/'; + $fileinfo = array(); + + $finder = $this->extension_manager->get_finder($use_all_available); + + $modules = $finder + ->extension_suffix('_module') + ->extension_directory("/$module_class") + ->core_path("includes/$module_class/info/") + ->core_prefix($module_class . '_') + ->get_classes(true); + + foreach ($modules as $cur_module) + { + // Skip entries we do not need if we know the module we are + // looking for + if ($module && strpos(str_replace('\\', '_', $cur_module), $module) === false && $module !== $cur_module) + { + continue; + } + + $info_class = preg_replace('/_module$/', '_info', $cur_module); + + // If the class does not exist it might be following the old + // format. phpbb_acp_info_acp_foo needs to be turned into + // acp_foo_info and the respective file has to be included + // manually because it does not support auto loading + $old_info_class_file = str_replace("phpbb_{$module_class}_info_", '', $cur_module); + $old_info_class = $old_info_class_file . '_info'; + + if (class_exists($old_info_class)) + { + $info_class = $old_info_class; + } + else if (!class_exists($info_class)) + { + $info_class = $old_info_class; + + // need to check class exists again because previous checks triggered autoloading + if (!class_exists($info_class) && file_exists($directory . $old_info_class_file . '.' . $this->php_ext)) + { + include($directory . $old_info_class_file . '.' . $this->php_ext); + } + } + + if (class_exists($info_class)) + { + $info = new $info_class(); + $module_info = $info->module(); + + $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $cur_module; + + $fileinfo[$main_class] = $module_info; + } + } + + ksort($fileinfo); + + return $fileinfo; + } + + /** + * Get module branch + * + * @param int $module_id ID of the module + * @param string $module_class Class of the module (acp, ucp, mcp etc...) + * @param string $type Type of branch (Expected values: all, parents or children) + * @param bool $include_module Whether or not to include the specified module with $module_id + * + * @return array Returns an array containing the modules in the specified branch type. + */ + public function get_module_branch($module_id, $module_class, $type = 'all', $include_module = true) + { + $module_id = (int) $module_id; + + switch ($type) + { + case 'parents': + $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id'; + break; + + case 'children': + $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id'; + break; + + default: + $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id'; + break; + } + + $rows = array(); + + $sql = 'SELECT m2.* + FROM ' . $this->modules_table . ' m1 + LEFT JOIN ' . $this->modules_table . " m2 ON ($condition) + WHERE m1.module_class = '" . $this->db->sql_escape($module_class) . "' + AND m2.module_class = '" . $this->db->sql_escape($module_class) . "' + AND m1.module_id = $module_id + ORDER BY m2.left_id DESC"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + if (!$include_module && $row['module_id'] == $module_id) + { + continue; + } + + $rows[] = $row; + } + $this->db->sql_freeresult($result); + + return $rows; + } + + /** + * Remove modules cache file + * + * @param string $module_class Class of the module (acp, ucp, mcp etc...) + */ + public function remove_cache_file($module_class) + { + // Sanitise for future path use, it's escaped as appropriate for queries + $cache_class = str_replace(array('.', '/', '\\'), '', basename($module_class)); + $this->cache->destroy('_modules_' . $cache_class); + $this->cache->destroy('sql', $this->modules_table); + } + + /** + * Update/Add module + * + * @param array &$module_data The module data + * + * @throws \phpbb\module\exception\module_not_found_exception When parent module or the category is not exist + */ + public function update_module_data(&$module_data) + { + if (!isset($module_data['module_id'])) + { + // no module_id means we're creating a new category/module + if ($module_data['parent_id']) + { + $sql = 'SELECT left_id, right_id + FROM ' . $this->modules_table . " + WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "' + AND module_id = " . (int) $module_data['parent_id']; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if (!$row) + { + throw new module_not_found_exception('PARENT_NOT_EXIST'); + } + + // Workaround + $row['left_id'] = (int) $row['left_id']; + $row['right_id'] = (int) $row['right_id']; + + $sql = 'UPDATE ' . $this->modules_table . " + SET left_id = left_id + 2, right_id = right_id + 2 + WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "' + AND left_id > {$row['right_id']}"; + $this->db->sql_query($sql); + + $sql = 'UPDATE ' . $this->modules_table . " + SET right_id = right_id + 2 + WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "' + AND {$row['left_id']} BETWEEN left_id AND right_id"; + $this->db->sql_query($sql); + + $module_data['left_id'] = (int) $row['right_id']; + $module_data['right_id'] = (int) $row['right_id'] + 1; + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . $this->modules_table . " + WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $module_data['left_id'] = (int) $row['right_id'] + 1; + $module_data['right_id'] = (int) $row['right_id'] + 2; + } + + $sql = 'INSERT INTO ' . $this->modules_table . ' ' . $this->db->sql_build_array('INSERT', $module_data); + $this->db->sql_query($sql); + + $module_data['module_id'] = $this->db->sql_nextid(); + } + else + { + $row = $this->get_module_row($module_data['module_id'], $module_data['module_class']); + + if ($module_data['module_basename'] && !$row['module_basename']) + { + // we're turning a category into a module + $branch = $this->get_module_branch($module_data['module_id'], $module_data['module_class'], 'children', false); + + if (sizeof($branch)) + { + throw new module_not_found_exception('NO_CATEGORY_TO_MODULE'); + } + } + + if ($row['parent_id'] != $module_data['parent_id']) + { + $this->move_module($module_data['module_id'], $module_data['parent_id'], $module_data['module_class']); + } + + $update_ary = $module_data; + unset($update_ary['module_id']); + + $sql = 'UPDATE ' . $this->modules_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $update_ary) . " + WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "' + AND module_id = " . (int) $module_data['module_id']; + $this->db->sql_query($sql); + } + } + + /** + * Move module around the tree + * + * @param int $from_module_id ID of the current parent module + * @param int $to_parent_id ID of the target parent module + * @param string $module_class Class of the module (acp, ucp, mcp etc...) + * + * @throws \phpbb\module\exception\module_not_found_exception If the module specified to move modules from does not + * have any children. + */ + public function move_module($from_module_id, $to_parent_id, $module_class) + { + $moved_modules = $this->get_module_branch($from_module_id, $module_class, 'children'); + + if (empty($moved_modules)) + { + throw new module_not_found_exception(); + } + + $from_data = $moved_modules[0]; + $diff = sizeof($moved_modules) * 2; + + $moved_ids = array(); + for ($i = 0; $i < sizeof($moved_modules); ++$i) + { + $moved_ids[] = $moved_modules[$i]['module_id']; + } + + // Resync parents + $sql = 'UPDATE ' . $this->modules_table . " + SET right_id = right_id - $diff + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND left_id < " . (int) $from_data['right_id'] . ' + AND right_id > ' . (int) $from_data['right_id']; + $this->db->sql_query($sql); + + // Resync righthand side of tree + $sql = 'UPDATE ' . $this->modules_table . " + SET left_id = left_id - $diff, right_id = right_id - $diff + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND left_id > " . (int) $from_data['right_id']; + $this->db->sql_query($sql); + + if ($to_parent_id > 0) + { + $to_data = $this->get_module_row($to_parent_id, $module_class); + + // Resync new parents + $sql = 'UPDATE ' . $this->modules_table . " + SET right_id = right_id + $diff + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id + AND ' . $this->db->sql_in_set('module_id', $moved_ids, true); + $this->db->sql_query($sql); + + // Resync the righthand side of the tree + $sql = 'UPDATE ' . $this->modules_table . " + SET left_id = left_id + $diff, right_id = right_id + $diff + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND left_id > " . (int) $to_data['right_id'] . ' + AND ' . $this->db->sql_in_set('module_id', $moved_ids, true); + $this->db->sql_query($sql); + + // Resync moved branch + $to_data['right_id'] += $diff; + if ($to_data['right_id'] > $from_data['right_id']) + { + $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1); + } + else + { + $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1); + } + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . $this->modules_table . " + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND " . $this->db->sql_in_set('module_id', $moved_ids, true); + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1); + } + + $sql = 'UPDATE ' . $this->modules_table . " + SET left_id = left_id $diff, right_id = right_id $diff + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND " . $this->db->sql_in_set('module_id', $moved_ids); + $this->db->sql_query($sql); + } + + /** + * Remove module from tree + * + * @param int $module_id ID of the module to delete + * @param string $module_class Class of the module (acp, ucp, mcp etc...) + * + * @throws \phpbb\module\exception\module_exception When the specified module cannot be removed + */ + public function delete_module($module_id, $module_class) + { + $module_id = (int) $module_id; + + $row = $this->get_module_row($module_id, $module_class); + + $branch = $this->get_module_branch($module_id, $module_class, 'children', false); + + if (sizeof($branch)) + { + throw new module_exception('CANNOT_REMOVE_MODULE'); + } + + // If not move + $diff = 2; + $sql = 'DELETE FROM ' . $this->modules_table . " + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND module_id = $module_id"; + $this->db->sql_query($sql); + + $row['right_id'] = (int) $row['right_id']; + $row['left_id'] = (int) $row['left_id']; + + // Resync tree + $sql = 'UPDATE ' . $this->modules_table . " + SET right_id = right_id - $diff + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}"; + $this->db->sql_query($sql); + + $sql = 'UPDATE ' . $this->modules_table . " + SET left_id = left_id - $diff, right_id = right_id - $diff + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND left_id > {$row['right_id']}"; + $this->db->sql_query($sql); + } + + /** + * Move module position by $steps up/down + * + * @param array $module_row Array of module data + * @param string $module_class Class of the module (acp, ucp, mcp etc...) + * @param string $action Direction of moving (valid values: move_up or move_down) + * @param int $steps Number of steps to move module + * + * @return string Returns the language name of the module + * + * @throws \phpbb\module\exception\module_not_found_exception When the specified module does not exists + */ + public function move_module_by($module_row, $module_class, $action = 'move_up', $steps = 1) + { + /** + * Fetch all the siblings between the module's current spot + * and where we want to move it to. If there are less than $steps + * siblings between the current spot and the target then the + * module will move as far as possible + */ + $sql = 'SELECT module_id, left_id, right_id, module_langname + FROM ' . $this->modules_table . " + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND parent_id = " . (int) $module_row['parent_id'] . ' + AND ' . (($action == 'move_up') ? 'right_id < ' . (int) $module_row['right_id'] . ' ORDER BY right_id DESC' : 'left_id > ' . (int) $module_row['left_id'] . ' ORDER BY left_id ASC'); + $result = $this->db->sql_query_limit($sql, $steps); + + $target = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $target = $row; + } + $this->db->sql_freeresult($result); + + if (!sizeof($target)) + { + // The module is already on top or bottom + throw new module_not_found_exception(); + } + + /** + * $left_id and $right_id define the scope of the nodes that are affected by the move. + * $diff_up and $diff_down are the values to substract or add to each node's left_id + * and right_id in order to move them up or down. + * $move_up_left and $move_up_right define the scope of the nodes that are moving + * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down. + */ + if ($action == 'move_up') + { + $left_id = (int) $target['left_id']; + $right_id = (int) $module_row['right_id']; + + $diff_up = (int) ($module_row['left_id'] - $target['left_id']); + $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); + + $move_up_left = (int) $module_row['left_id']; + $move_up_right = (int) $module_row['right_id']; + } + else + { + $left_id = (int) $module_row['left_id']; + $right_id = (int) $target['right_id']; + + $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); + $diff_down = (int) ($target['right_id'] - $module_row['right_id']); + + $move_up_left = (int) ($module_row['right_id'] + 1); + $move_up_right = (int) $target['right_id']; + } + + // Now do the dirty job + $sql = 'UPDATE ' . $this->modules_table . " + SET left_id = left_id + CASE + WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END, + right_id = right_id + CASE + WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END + WHERE module_class = '" . $this->db->sql_escape($module_class) . "' + AND left_id BETWEEN {$left_id} AND {$right_id} + AND right_id BETWEEN {$left_id} AND {$right_id}"; + $this->db->sql_query($sql); + + $this->remove_cache_file($module_class); + + return $target['module_langname']; + } +} From e877a752be55dfda5a72c7995708e4e132a1079d Mon Sep 17 00:00:00 2001 From: MateBartus Date: Sun, 31 May 2015 13:20:56 +0200 Subject: [PATCH 0387/1676] [ticket/13777] Deduplicate migration service definitions PHPBB3-13777 --- phpBB/config/default/container/services.yml | 1 + .../config/default/container/services_db.yml | 63 ------------------- .../default/container/services_migrator.yml | 4 ++ 3 files changed, 5 insertions(+), 63 deletions(-) diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 9b5fd538ee..cab82a5d9c 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -10,6 +10,7 @@ imports: - { resource: services_feed.yml } - { resource: services_help.yml } - { resource: services_language.yml } + - { resource: services_migrator.yml } - { resource: services_mimetype_guesser.yml } - { resource: services_module.yml } - { resource: services_notification.yml } diff --git a/phpBB/config/default/container/services_db.yml b/phpBB/config/default/container/services_db.yml index ae2707b9a5..ed3f88c704 100644 --- a/phpBB/config/default/container/services_db.yml +++ b/phpBB/config/default/container/services_db.yml @@ -79,66 +79,3 @@ services: - %core.root_path% - @request - @dbal.conn.driver - -# ----- Migrator ----- - migrator: - class: phpbb\db\migrator - arguments: - - @service_container - - @config - - @dbal.conn - - @dbal.tools - - %tables.migrations% - - %core.root_path% - - %core.php_ext% - - %core.table_prefix% - - @migrator.tool_collection - - @migrator.helper - - migrator.helper: - class: phpbb\db\migration\helper - -# ----- Migrator's tools ----- - migrator.tool_collection: - class: phpbb\di\service_collection - arguments: - - @service_container - tags: - - { name: service_collection, tag: migrator.tool } - - migrator.tool.config: - class: phpbb\db\migration\tool\config - arguments: - - @config - tags: - - { name: migrator.tool } - - migrator.tool.config_text: - class: phpbb\db\migration\tool\config_text - arguments: - - @config_text - tags: - - { name: migrator.tool } - - migrator.tool.module: - class: phpbb\db\migration\tool\module - arguments: - - @dbal.conn - - @cache - - @user - - %core.root_path% - - %core.php_ext% - - %tables.modules% - tags: - - { name: migrator.tool } - - migrator.tool.permission: - class: phpbb\db\migration\tool\permission - arguments: - - @dbal.conn - - @cache - - @auth - - %core.root_path% - - %core.php_ext% - tags: - - { name: migrator.tool } diff --git a/phpBB/config/default/container/services_migrator.yml b/phpBB/config/default/container/services_migrator.yml index cd04eea5c2..01bd7d3a11 100644 --- a/phpBB/config/default/container/services_migrator.yml +++ b/phpBB/config/default/container/services_migrator.yml @@ -1,7 +1,9 @@ services: +# ----- Migrator ----- migrator: class: phpbb\db\migrator arguments: + - @service_container - @config - @dbal.conn - @dbal.tools @@ -15,6 +17,7 @@ services: migrator.helper: class: phpbb\db\migration\helper +# ----- Migrator's tools ----- migrator.tool_collection: class: phpbb\di\service_collection arguments: @@ -42,6 +45,7 @@ services: - @dbal.conn - @cache - @user + - @module.manager - %core.root_path% - %core.php_ext% - %tables.modules% From 77ee0e62ca1685e4577947cc60163367dfa97de6 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Sun, 31 May 2015 13:21:45 +0200 Subject: [PATCH 0388/1676] [ticket/13777] Use module manager in phpBB core files PHPBB3-13777 --- phpBB/install/install_install.php | 41 ++++++++------ .../data/v310/acp_prune_users_module.php | 11 +--- phpBB/phpbb/db/migration/data/v310/dev.php | 11 +--- phpBB/phpbb/db/migration/tool/module.php | 55 ++++++------------- 4 files changed, 47 insertions(+), 71 deletions(-) diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index e8890a3d08..ce457aaef5 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -1552,9 +1552,14 @@ class install_install extends module $phpbb_extension_manager = $phpbb_container->get('ext.manager'); } - include_once($phpbb_root_path . 'includes/acp/acp_modules.' . $phpEx); - - $_module = new acp_modules(); + $_module = new \phpbb\module\module_manager( + new \phpbb\cache\driver\dummy(), + $db, + $phpbb_extension_manager, + MODULES_TABLE, + $phpbb_root_path, + $phpEx + ); $module_classes = array('acp', 'mcp', 'ucp'); // Add categories @@ -1585,7 +1590,7 @@ class install_install extends module ); // Add category - $_module->update_module_data($module_data, true); + $_module->update_module_data($module_data); // Check for last sql error happened if ($db->get_sql_error_triggered()) @@ -1619,7 +1624,7 @@ class install_install extends module 'module_auth' => '', ); - $_module->update_module_data($module_data, true); + $_module->update_module_data($module_data); // Check for last sql error happened if ($db->get_sql_error_triggered()) @@ -1659,7 +1664,7 @@ class install_install extends module 'module_auth' => $row['auth'], ); - $_module->update_module_data($module_data, true); + $_module->update_module_data($module_data); // Check for last sql error happened if ($db->get_sql_error_triggered()) @@ -1684,7 +1689,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_up', 4); + $_module->move_module_by($row, 'acp', 'move_up', 4); // Move permissions intro screen module 4 up... $sql = 'SELECT * @@ -1696,7 +1701,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_up', 4); + $_module->move_module_by($row, 'acp', 'move_up', 4); // Move manage users screen module 5 up... $sql = 'SELECT * @@ -1708,7 +1713,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_up', 5); + $_module->move_module_by($row, 'acp', 'move_up', 5); // Move extension management module 1 up... $sql = 'SELECT * @@ -1721,7 +1726,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_up', 1); + $_module->move_module_by($row, 'acp', 'move_up', 1); } if ($module_class == 'mcp') @@ -1736,7 +1741,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_down', 3); + $_module->move_module_by($row, 'mcp', 'move_down', 3); // Move closed pm reports module 3 down... $sql = 'SELECT * @@ -1748,7 +1753,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_down', 3); + $_module->move_module_by($row, 'mcp', 'move_down', 3); // Move open pm reports module 3 down... $sql = 'SELECT * @@ -1760,7 +1765,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_down', 3); + $_module->move_module_by($row, 'mcp', 'move_down', 3); } if ($module_class == 'ucp') @@ -1775,7 +1780,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_down', 4); + $_module->move_module_by($row, 'ucp', 'move_down', 4); // Move notification options module 4 down... $sql = 'SELECT * @@ -1787,7 +1792,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_down', 4); + $_module->move_module_by($row, 'ucp', 'move_down', 4); // Move OAuth module 5 down... $sql = 'SELECT * @@ -1799,7 +1804,7 @@ class install_install extends module $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $_module->move_module_by($row, 'move_down', 5); + $_module->move_module_by($row, 'ucp', 'move_down', 5); } // And now for the special ones @@ -1838,7 +1843,7 @@ class install_install extends module 'module_auth' => $row['module_auth'], ); - $_module->update_module_data($module_data, true); + $_module->update_module_data($module_data); // Check for last sql error happened if ($db->get_sql_error_triggered()) @@ -1850,7 +1855,7 @@ class install_install extends module } } - $_module->remove_cache_file(); + $_module->remove_cache_file($module_class); } } diff --git a/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php b/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php index 0ca4f2f19c..725c57ca86 100644 --- a/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php +++ b/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php @@ -13,7 +13,7 @@ namespace phpbb\db\migration\data\v310; -class acp_prune_users_module extends \phpbb\db\migration\migration +class acp_prune_users_module extends \phpbb\db\migration\container_aware_migration { public function effectively_installed() { @@ -70,12 +70,7 @@ class acp_prune_users_module extends \phpbb\db\migration\migration $acp_cat_users_id = (int) $this->db->sql_fetchfield('module_id'); $this->db->sql_freeresult($result); - if (!class_exists('\acp_modules')) - { - include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); - } - $module_manager = new \acp_modules(); - $module_manager->module_class = 'acp'; - $module_manager->move_module($acp_prune_users_id, $acp_cat_users_id); + $module_manager = $this->container->get('module.manager'); + $module_manager->move_module($acp_prune_users_id, $acp_cat_users_id, 'acp'); } } diff --git a/phpBB/phpbb/db/migration/data/v310/dev.php b/phpBB/phpbb/db/migration/data/v310/dev.php index f037191c2a..250258eea7 100644 --- a/phpBB/phpbb/db/migration/data/v310/dev.php +++ b/phpBB/phpbb/db/migration/data/v310/dev.php @@ -13,7 +13,7 @@ namespace phpbb\db\migration\data\v310; -class dev extends \phpbb\db\migration\migration +class dev extends \phpbb\db\migration\container_aware_migration { public function effectively_installed() { @@ -204,18 +204,13 @@ class dev extends \phpbb\db\migration\migration $language_management_module_id = $this->db->sql_fetchfield('module_id'); $this->db->sql_freeresult($result); - if (!class_exists('acp_modules')) - { - include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); - } // acp_modules calls adm_back_link, which is undefined at this point if (!function_exists('adm_back_link')) { include($this->phpbb_root_path . 'includes/functions_acp.' . $this->php_ext); } - $module_manager = new \acp_modules(); - $module_manager->module_class = 'acp'; - $module_manager->move_module($language_module_id, $language_management_module_id); + $module_manager = $this->container->get('module.manager'); + $module_manager->move_module($language_module_id, $language_management_module_id, 'acp'); } public function update_ucp_pm_basename() diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php index b6f0372181..3b181872db 100644 --- a/phpBB/phpbb/db/migration/tool/module.php +++ b/phpBB/phpbb/db/migration/tool/module.php @@ -13,6 +13,8 @@ namespace phpbb\db\migration\tool; +use phpbb\module\exception\module_exception; + /** * Migration module management tool */ @@ -27,6 +29,9 @@ class module implements \phpbb\db\migration\tool\tool_interface /** @var \phpbb\user */ protected $user; + /** @var \phpbb\module\module_manager */ + protected $module_manager; + /** @var string */ protected $phpbb_root_path; @@ -42,15 +47,17 @@ class module implements \phpbb\db\migration\tool\tool_interface * @param \phpbb\db\driver\driver_interface $db * @param \phpbb\cache\service $cache * @param \phpbb\user $user + * @param \phpbb\module\module_manager $module_manager * @param string $phpbb_root_path * @param string $php_ext * @param string $modules_table */ - public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\user $user, $phpbb_root_path, $php_ext, $modules_table) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\user $user, \phpbb\module\module_manager $module_manager, $phpbb_root_path, $php_ext, $modules_table) { $this->db = $db; $this->cache = $cache; $this->user = $user; + $this->module_manager = $module_manager; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; $this->modules_table = $modules_table; @@ -188,7 +195,6 @@ class module implements \phpbb\db\migration\tool\tool_interface $basename = (isset($data['module_basename'])) ? $data['module_basename'] : ''; $module = $this->get_module_info($class, $basename); - $result = ''; foreach ($module['modes'] as $mode => $module_info) { if (!isset($data['modes']) || in_array($mode, $data['modes'])) @@ -239,13 +245,6 @@ class module implements \phpbb\db\migration\tool\tool_interface return; } - if (!class_exists('acp_modules')) - { - include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); - $this->user->add_lang('acp/modules'); - } - $acp_modules = new \acp_modules(); - $module_data = array( 'module_enabled' => (isset($data['module_enabled'])) ? $data['module_enabled'] : 1, 'module_display' => (isset($data['module_display'])) ? $data['module_display'] : 1, @@ -256,16 +255,11 @@ class module implements \phpbb\db\migration\tool\tool_interface 'module_mode' => (isset($data['module_mode'])) ? $data['module_mode'] : '', 'module_auth' => (isset($data['module_auth'])) ? $data['module_auth'] : '', ); - $result = $acp_modules->update_module_data($module_data, true); - // update_module_data can either return a string or an empty array... - if (is_string($result)) - { - // Error - throw new \phpbb\db\migration\exception('MODULE_ERROR', $result); - } - else + try { + $this->module_manager->update_module_data($module_data); + // Success $module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($module_log_name)); @@ -318,6 +312,11 @@ class module implements \phpbb\db\migration\tool\tool_interface $this->db->sql_query($sql); } } + catch (module_exception $e) + { + // Error + throw new \phpbb\db\migration\exception('MODULE_ERROR', $e->getMessage()); + } // Clear the Modules Cache $this->cache->destroy("_modules_$class"); @@ -417,21 +416,9 @@ class module implements \phpbb\db\migration\tool\tool_interface $module_ids[] = (int) $module; } - if (!class_exists('acp_modules')) - { - include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); - $this->user->add_lang('acp/modules'); - } - $acp_modules = new \acp_modules(); - $acp_modules->module_class = $class; - foreach ($module_ids as $module_id) { - $result = $acp_modules->delete_module($module_id); - if (!empty($result)) - { - return; - } + $this->module_manager->delete_module($module_id, $class); } $this->cache->destroy("_modules_$class"); @@ -474,13 +461,7 @@ class module implements \phpbb\db\migration\tool\tool_interface */ protected function get_module_info($class, $basename) { - if (!class_exists('acp_modules')) - { - include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); - $this->user->add_lang('acp/modules'); - } - $acp_modules = new \acp_modules(); - $module = $acp_modules->get_module_infos($basename, $class, true); + $module = $this->module_manager->get_module_infos($basename, $class, true); if (empty($module)) { From fcff3ee4ad2a273081ed3061a550399dfaa9c11e Mon Sep 17 00:00:00 2001 From: MateBartus Date: Sun, 31 May 2015 13:22:03 +0200 Subject: [PATCH 0389/1676] [ticket/13777] Fix tests PHPBB3-13777 --- tests/dbal/migrator_tool_module_test.php | 5 ++- tests/extension/modules_test.php | 51 ++++++++-------------- tests/functional/extension_module_test.php | 11 ++--- 3 files changed, 29 insertions(+), 38 deletions(-) diff --git a/tests/dbal/migrator_tool_module_test.php b/tests/dbal/migrator_tool_module_test.php index 695a7e7a7f..a71334f23f 100644 --- a/tests/dbal/migrator_tool_module_test.php +++ b/tests/dbal/migrator_tool_module_test.php @@ -41,7 +41,10 @@ class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case $auth = $this->getMock('\phpbb\auth\auth'); $phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); - $this->tool = new \phpbb\db\migration\tool\module($this->db, $this->cache, $this->user, $phpbb_root_path, $phpEx, 'phpbb_modules'); + $phpbb_extension_manager = new phpbb_mock_extension_manager($phpbb_root_path); + $module_manager = new \phpbb\module\module_manager($cache, $this->db, $phpbb_extension_manager, MODULES_TABLE, $phpbb_root_path, $phpEx); + + $this->tool = new \phpbb\db\migration\tool\module($this->db, $this->cache, $this->user, $module_manager, $phpbb_root_path, $phpEx, 'phpbb_modules'); } public function exists_data() diff --git a/tests/extension/modules_test.php b/tests/extension/modules_test.php index cbcfdfb787..61ab82c3d0 100644 --- a/tests/extension/modules_test.php +++ b/tests/extension/modules_test.php @@ -22,6 +22,7 @@ class phpbb_extension_modules_test extends phpbb_test_case { protected $extension_manager; protected $finder; + protected $module_manager; public function setUp() { @@ -43,7 +44,14 @@ class phpbb_extension_modules_test extends phpbb_test_case )); $phpbb_extension_manager = $this->extension_manager; - $this->acp_modules = new acp_modules(); + $this->module_manager = new \phpbb\module\module_manager( + new \phpbb\cache\driver\dummy(), + $this->getMock('\phpbb\db\driver\driver_interface'), + $this->extension_manager, + MODULES_TABLE, + dirname(__FILE__) . '/', + 'php' + ); } public function test_get_module_infos() @@ -56,8 +64,7 @@ class phpbb_extension_modules_test extends phpbb_test_case $phpbb_root_path = dirname(__FILE__) . '/'; // Find acp module info files - $this->acp_modules->module_class = 'acp'; - $acp_modules = $this->acp_modules->get_module_infos(); + $acp_modules = $this->module_manager->get_module_infos('', 'acp'); $this->assertEquals(array( 'vendor2\\foo\\acp\\a_module' => array( 'filename' => 'vendor2\\foo\\acp\\a_module', @@ -76,8 +83,7 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // Find mcp module info files - $this->acp_modules->module_class = 'mcp'; - $acp_modules = $this->acp_modules->get_module_infos(); + $acp_modules = $this->module_manager->get_module_infos('', 'mcp'); $this->assertEquals(array( 'vendor2\\foo\\mcp\\a_module' => array( 'filename' => 'vendor2\\foo\\mcp\\a_module', @@ -89,21 +95,7 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // Find a specific module info file (mcp_a_module) - $this->acp_modules->module_class = 'mcp'; - $acp_modules = $this->acp_modules->get_module_infos('mcp_a_module'); - $this->assertEquals(array( - 'vendor2\\foo\\mcp\\a_module' => array( - 'filename' => 'vendor2\\foo\\mcp\\a_module', - 'title' => 'Foobar', - 'modes' => array( - 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('MCP_MAIN')), - ), - ), - ), $acp_modules); - - // Find a specific module info file (mcp_a_module) with passing the module_class - $this->acp_modules->module_class = ''; - $acp_modules = $this->acp_modules->get_module_infos('mcp_a_module', 'mcp'); + $acp_modules = $this->module_manager->get_module_infos('mcp_a_module', 'mcp'); $this->assertEquals(array( 'vendor2\\foo\\mcp\\a_module' => array( 'filename' => 'vendor2\\foo\\mcp\\a_module', @@ -115,18 +107,15 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // The mcp module info file we're looking for shouldn't exist - $this->acp_modules->module_class = 'mcp'; - $acp_modules = $this->acp_modules->get_module_infos('mcp_a_fail'); + $acp_modules = $this->module_manager->get_module_infos('mcp_a_fail', 'mcp'); $this->assertEquals(array(), $acp_modules); // As there are no ucp modules we shouldn't find any - $this->acp_modules->module_class = 'ucp'; - $acp_modules = $this->acp_modules->get_module_infos(); + $acp_modules = $this->module_manager->get_module_infos('', 'ucp'); $this->assertEquals(array(), $acp_modules); // Get module info of specified extension module - $this->acp_modules->module_class = 'acp'; - $acp_modules = $this->acp_modules->get_module_infos('foo_acp_a_module'); + $acp_modules = $this->module_manager->get_module_infos('foo_acp_a_module', 'acp'); $this->assertEquals(array( 'vendor2\\foo\\acp\\a_module' => array ( 'filename' => 'vendor2\\foo\\acp\\a_module', @@ -138,18 +127,16 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // No specific module and module class set to an incorrect name - $acp_modules = $this->acp_modules->get_module_infos('', 'wcp', true); + $acp_modules = $this->module_manager->get_module_infos('', 'wcp', true); $this->assertEquals(array(), $acp_modules); // No specific module, no module_class set in the function parameter, and an incorrect module class - $this->acp_modules->module_class = 'wcp'; - $acp_modules = $this->acp_modules->get_module_infos(); + $acp_modules = $this->module_manager->get_module_infos('', 'wcp'); $this->assertEquals(array(), $acp_modules); // No specific module, module class set to false (will default to the above acp) // Setting $use_all_available will cause get_module_infos() to also load not enabled extensions (vendor2/bar) - $this->acp_modules->module_class = 'acp'; - $acp_modules = $this->acp_modules->get_module_infos('', false, true); + $acp_modules = $this->module_manager->get_module_infos('', 'acp', true); $this->assertEquals(array( 'vendor2\\foo\\acp\\a_module' => array( 'filename' => 'vendor2\\foo\\acp\\a_module', @@ -175,7 +162,7 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // Specific module set to disabled extension - $acp_modules = $this->acp_modules->get_module_infos('vendor2_bar_acp_a_module', 'acp', true); + $acp_modules = $this->module_manager->get_module_infos('vendor2_bar_acp_a_module', 'acp', true); $this->assertEquals(array( 'vendor2\\bar\\acp\\a_module' => array( 'filename' => 'vendor2\\bar\\acp\\a_module', diff --git a/tests/functional/extension_module_test.php b/tests/functional/extension_module_test.php index ee084720e4..95107665cd 100644 --- a/tests/functional/extension_module_test.php +++ b/tests/functional/extension_module_test.php @@ -49,8 +49,9 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case $this->phpbb_extension_manager = $this->get_extension_manager(); $this->phpbb_extension_manager->enable('foo/bar'); - $modules = new acp_modules(); $db = $this->get_db(); + $cache = $this->get_cache_driver(); + $modules = new \phpbb\module\module_manager($cache, $db, $this->phpbb_extension_manager, MODULES_TABLE, dirname(__FILE__) . '/../../phpBB/', 'php'); $sql = 'SELECT module_id FROM ' . MODULES_TABLE . " @@ -70,7 +71,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case 'module_mode' => '', 'module_auth' => '', ); - $modules->update_module_data($parent_data, true); + $modules->update_module_data($parent_data); $module_data = array( 'module_basename' => 'foo\\bar\\acp\\main_module', @@ -82,7 +83,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case 'module_mode' => 'mode', 'module_auth' => '', ); - $modules->update_module_data($module_data, true); + $modules->update_module_data($module_data); $parent_data = array( 'module_basename' => '', @@ -94,7 +95,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case 'module_mode' => '', 'module_auth' => '', ); - $modules->update_module_data($parent_data, true); + $modules->update_module_data($parent_data); $module_data = array( 'module_basename' => 'foo\\bar\\ucp\\main_module', @@ -106,7 +107,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case 'module_mode' => 'mode', 'module_auth' => '', ); - $modules->update_module_data($module_data, true); + $modules->update_module_data($module_data); $this->purge_cache(); } From 4044b5df8997b720ef86955f9e660189962182ea Mon Sep 17 00:00:00 2001 From: MateBartus Date: Sun, 31 May 2015 16:03:11 +0200 Subject: [PATCH 0390/1676] [ticket/13777] Reorder get_module_infos() method's arguments PHPBB3-13777 --- phpBB/includes/acp/acp_modules.php | 8 ++++---- phpBB/install/install_install.php | 2 +- phpBB/phpbb/db/migration/tool/module.php | 2 +- phpBB/phpbb/module/module_manager.php | 9 ++------- tests/extension/modules_test.php | 20 ++++++++++---------- 5 files changed, 18 insertions(+), 23 deletions(-) diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index 45eba48777..c2407f15b4 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -209,7 +209,7 @@ class acp_modules list($module_basename, $module_mode) = explode('::', $quick_install); // Check if module name and mode exist... - $fileinfo = $module_manager->get_module_infos($module_basename, $this->module_class); + $fileinfo = $module_manager->get_module_infos($this->module_class, $module_basename); $fileinfo = $fileinfo[$module_basename]; if (isset($fileinfo['modes'][$module_mode])) @@ -326,7 +326,7 @@ class acp_modules // Adjust auth row if ($module_data['module_basename'] && $module_data['module_mode']) { - $fileinfo = $module_manager->get_module_infos($module_data['module_basename'], $this->module_class); + $fileinfo = $module_manager->get_module_infos($this->module_class, $module_data['module_basename']); $module_data['module_auth'] = $fileinfo[$module_data['module_basename']]['modes'][$module_data['module_mode']]['auth']; } @@ -358,7 +358,7 @@ class acp_modules $is_cat = (!$module_data['module_basename']) ? true : false; // Get module information - $module_infos = $module_manager->get_module_infos('', $this->module_class); + $module_infos = $module_manager->get_module_infos($this->module_class); // Build name options $s_name_options = $s_mode_options = ''; @@ -545,7 +545,7 @@ class acp_modules $db->sql_freeresult($result); // Quick adding module - $module_infos = $module_manager->get_module_infos('', $this->module_class); + $module_infos = $module_manager->get_module_infos($this->module_class); // Build quick options $s_install_options = ''; diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index ce457aaef5..b06ef0b51d 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -1640,7 +1640,7 @@ class install_install extends module } // Get the modules we want to add... returned sorted by name - $module_info = $_module->get_module_infos('', $module_class); + $module_info = $_module->get_module_infos($module_class); foreach ($module_info as $module_basename => $fileinfo) { diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php index 3b181872db..69ac71abb7 100644 --- a/phpBB/phpbb/db/migration/tool/module.php +++ b/phpBB/phpbb/db/migration/tool/module.php @@ -461,7 +461,7 @@ class module implements \phpbb\db\migration\tool\tool_interface */ protected function get_module_info($class, $basename) { - $module = $this->module_manager->get_module_infos($basename, $class, true); + $module = $this->module_manager->get_module_infos($class, $basename, true); if (empty($module)) { diff --git a/phpBB/phpbb/module/module_manager.php b/phpBB/phpbb/module/module_manager.php index da3b037b5e..707e297257 100644 --- a/phpBB/phpbb/module/module_manager.php +++ b/phpBB/phpbb/module/module_manager.php @@ -102,20 +102,15 @@ class module_manager /** * Get available module information from module files * - * @param string $module ID of module * @param string $module_class Class of the module (acp, ucp, mcp etc...) + * @param string $module ID of module * @param bool $use_all_available Use all available instead of just all * enabled extensions * * @return array Array with module information gathered from module info files. */ - public function get_module_infos($module = '', $module_class = null, $use_all_available = false) + public function get_module_infos($module_class, $module = '', $use_all_available = false) { - if ($module_class === null) - { - throw new module_class_not_defined_exception(); - } - $directory = $this->phpbb_root_path . 'includes/' . $module_class . '/info/'; $fileinfo = array(); diff --git a/tests/extension/modules_test.php b/tests/extension/modules_test.php index 61ab82c3d0..88634bc6ba 100644 --- a/tests/extension/modules_test.php +++ b/tests/extension/modules_test.php @@ -64,7 +64,7 @@ class phpbb_extension_modules_test extends phpbb_test_case $phpbb_root_path = dirname(__FILE__) . '/'; // Find acp module info files - $acp_modules = $this->module_manager->get_module_infos('', 'acp'); + $acp_modules = $this->module_manager->get_module_infos('acp'); $this->assertEquals(array( 'vendor2\\foo\\acp\\a_module' => array( 'filename' => 'vendor2\\foo\\acp\\a_module', @@ -83,7 +83,7 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // Find mcp module info files - $acp_modules = $this->module_manager->get_module_infos('', 'mcp'); + $acp_modules = $this->module_manager->get_module_infos('mcp'); $this->assertEquals(array( 'vendor2\\foo\\mcp\\a_module' => array( 'filename' => 'vendor2\\foo\\mcp\\a_module', @@ -95,7 +95,7 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // Find a specific module info file (mcp_a_module) - $acp_modules = $this->module_manager->get_module_infos('mcp_a_module', 'mcp'); + $acp_modules = $this->module_manager->get_module_infos('mcp', 'mcp_a_module'); $this->assertEquals(array( 'vendor2\\foo\\mcp\\a_module' => array( 'filename' => 'vendor2\\foo\\mcp\\a_module', @@ -107,15 +107,15 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // The mcp module info file we're looking for shouldn't exist - $acp_modules = $this->module_manager->get_module_infos('mcp_a_fail', 'mcp'); + $acp_modules = $this->module_manager->get_module_infos('mcp', 'mcp_a_fail'); $this->assertEquals(array(), $acp_modules); // As there are no ucp modules we shouldn't find any - $acp_modules = $this->module_manager->get_module_infos('', 'ucp'); + $acp_modules = $this->module_manager->get_module_infos('ucp'); $this->assertEquals(array(), $acp_modules); // Get module info of specified extension module - $acp_modules = $this->module_manager->get_module_infos('foo_acp_a_module', 'acp'); + $acp_modules = $this->module_manager->get_module_infos('acp', 'foo_acp_a_module'); $this->assertEquals(array( 'vendor2\\foo\\acp\\a_module' => array ( 'filename' => 'vendor2\\foo\\acp\\a_module', @@ -127,16 +127,16 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // No specific module and module class set to an incorrect name - $acp_modules = $this->module_manager->get_module_infos('', 'wcp', true); + $acp_modules = $this->module_manager->get_module_infos('wcp', '', true); $this->assertEquals(array(), $acp_modules); // No specific module, no module_class set in the function parameter, and an incorrect module class - $acp_modules = $this->module_manager->get_module_infos('', 'wcp'); + $acp_modules = $this->module_manager->get_module_infos('wcp'); $this->assertEquals(array(), $acp_modules); // No specific module, module class set to false (will default to the above acp) // Setting $use_all_available will cause get_module_infos() to also load not enabled extensions (vendor2/bar) - $acp_modules = $this->module_manager->get_module_infos('', 'acp', true); + $acp_modules = $this->module_manager->get_module_infos('acp', '', true); $this->assertEquals(array( 'vendor2\\foo\\acp\\a_module' => array( 'filename' => 'vendor2\\foo\\acp\\a_module', @@ -162,7 +162,7 @@ class phpbb_extension_modules_test extends phpbb_test_case ), $acp_modules); // Specific module set to disabled extension - $acp_modules = $this->module_manager->get_module_infos('vendor2_bar_acp_a_module', 'acp', true); + $acp_modules = $this->module_manager->get_module_infos('acp', 'vendor2_bar_acp_a_module', true); $this->assertEquals(array( 'vendor2\\bar\\acp\\a_module' => array( 'filename' => 'vendor2\\bar\\acp\\a_module', From 8d443c3de7c508068e4d6143cc41a1172df466a0 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Sun, 31 May 2015 16:27:16 +0200 Subject: [PATCH 0391/1676] [ticket/13777] Remove module_class_not_defined_exception PHPBB3-13777 --- .../module_class_not_defined_exception.php | 19 ------------------- phpBB/phpbb/module/module_manager.php | 1 - 2 files changed, 20 deletions(-) delete mode 100644 phpBB/phpbb/module/exception/module_class_not_defined_exception.php diff --git a/phpBB/phpbb/module/exception/module_class_not_defined_exception.php b/phpBB/phpbb/module/exception/module_class_not_defined_exception.php deleted file mode 100644 index 3551dc733d..0000000000 --- a/phpBB/phpbb/module/exception/module_class_not_defined_exception.php +++ /dev/null @@ -1,19 +0,0 @@ - - * @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\module\exception; - -class module_class_not_defined_exception extends module_exception -{ - -} diff --git a/phpBB/phpbb/module/module_manager.php b/phpBB/phpbb/module/module_manager.php index 707e297257..a812d06736 100644 --- a/phpBB/phpbb/module/module_manager.php +++ b/phpBB/phpbb/module/module_manager.php @@ -13,7 +13,6 @@ namespace phpbb\module; -use phpbb\module\exception\module_class_not_defined_exception; use phpbb\module\exception\module_exception; use phpbb\module\exception\module_not_found_exception; From eb227977d27839bb0e2f1826084e00b667659e25 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 1 Jun 2015 02:24:48 +0200 Subject: [PATCH 0392/1676] [ticket/13906] Fixed old signatures in post preview PHPBB3-13906 --- phpBB/posting.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/phpBB/posting.php b/phpBB/posting.php index 1c7b756fc2..5b0e3d1da6 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1487,14 +1487,11 @@ if (!sizeof($error) && $preview) // Signature if ($post_data['enable_sig'] && $config['allow_sig'] && $preview_signature && $auth->acl_get('f_sigs', $forum_id)) { - $parse_sig = new parse_message($preview_signature); - $parse_sig->bbcode_uid = $preview_signature_uid; - $parse_sig->bbcode_bitfield = $preview_signature_bitfield; + $flags = ($config['allow_sig_bbcode']) ? OPTION_FLAG_BBCODE : 0; + $flags |= ($config['allow_sig_links']) ? OPTION_FLAG_LINKS : 0; + $flags |= ($config['allow_sig_smilies']) ? OPTION_FLAG_SMILIES : 0; - // Not sure about parameters for bbcode/smilies/urls... in signatures - $parse_sig->format_display($config['allow_sig_bbcode'], $config['allow_sig_links'], $config['allow_sig_smilies']); - $preview_signature = $parse_sig->message; - unset($parse_sig); + $preview_signature = generate_text_for_display($preview_signature, $preview_signature_uid, $preview_signature_bitfield, $flags, false); } else { From d37c995f4be23ca058cec59c44c92ab54015b11d Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 2 Jun 2015 12:37:36 +0200 Subject: [PATCH 0393/1676] [ticket/13906] Added test PHPBB3-13906 --- tests/functional/posting_test.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 49f0c1d749..c107b78384 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -180,4 +180,26 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $crawler = self::submit($form); $this->assertEquals($text, $crawler->filter('#message')->text()); } + + public function test_ticket_13906() + { + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_sig = '[b:2u8sdcwb]My signature[/b:2u8sdcwb]', + user_sig_bbcode_uid = '2u8sdcwb', + user_sig_bbcode_bitfield = 'QA==' + WHERE user_id = 2"; + $this->get_db()->sql_query($sql); + + $this->login(); + $crawler = self::request('GET', 'posting.php?mode=post&f=2'); + $form = $crawler->selectButton('Preview')->form(array( + 'subject' => 'Test subject', + 'message' => 'My post', + )); + $crawler = self::submit($form); + $this->assertContains( + 'My signature', + $crawler->filter('#preview .signature')->html() + ); + } } From 78eeb210e78429d867347ecb7c0eedf707005632 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 2 Jun 2015 22:46:14 +0200 Subject: [PATCH 0394/1676] [ticket/13906] Renamed test PHPBB3-13906 --- tests/functional/posting_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index c107b78384..ccfeb10deb 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -181,7 +181,7 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $this->assertEquals($text, $crawler->filter('#message')->text()); } - public function test_ticket_13906() + public function test_old_signature_in_preview() { $sql = 'UPDATE ' . USERS_TABLE . " SET user_sig = '[b:2u8sdcwb]My signature[/b:2u8sdcwb]', From 49f2dd8c5e42265c9b1a21953922644f84752c16 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 4 Jun 2015 19:26:56 +0200 Subject: [PATCH 0395/1676] [ticket/13564] Fix user_delete_test on master PHPBB3-13564 --- tests/functions/user_delete_test.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/functions/user_delete_test.php b/tests/functions/user_delete_test.php index db52dcded7..21561492fd 100644 --- a/tests/functions/user_delete_test.php +++ b/tests/functions/user_delete_test.php @@ -28,10 +28,12 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case { parent::setUp(); - global $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user; + global $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx; $this->db = $db = $this->new_dbal(); - $user = new \phpbb\user('\phpbb\datetime'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $phpbb_container = new phpbb_mock_container_builder(); $config = new \phpbb\config\config(array( @@ -39,8 +41,7 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case 'auth_oauth_google_key' => 'foo', 'auth_oauth_google_secret' => 'bar', )); - set_config_count('foobar', 0, false, $config); - $cache = new \phpbb\cache\driver\null(); + $cache = new \phpbb\cache\driver\dummy(); $request = new phpbb_mock_request(); $notification_manager = new phpbb_mock_notification_manager(); $provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config); From 3c0cbda2893282856c4740a260582a3c3458ae09 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 7 Jun 2015 06:57:59 +0200 Subject: [PATCH 0396/1676] [ticket/13902] Increased CSS margin around quotes PHPBB3-13902 --- phpBB/styles/prosilver/theme/content.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 85c3cb9f4c..f8eefb1b8e 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -460,7 +460,7 @@ blockquote { background: transparent none 6px 8px no-repeat; border: 1px solid transparent; font-size: 0.95em; - margin: 0.5em 1px 0 25px; + margin: 1em 1px 1em 25px; overflow: hidden; padding: 5px; } @@ -468,7 +468,7 @@ blockquote { blockquote blockquote { /* Nested quotes */ font-size: 1em; - margin: 0.5em 1px 0 15px; + margin: 1em 1px 1em 15px; } blockquote cite { From 1fae4152efd10c3eeb0e5e21d30a109c3ca9a36d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 8 Jun 2015 15:55:03 +0200 Subject: [PATCH 0397/1676] [ticket/13930] Add missing space to mssql_extractor PHPBB3-13930 --- phpBB/phpbb/db/extractor/mssql_extractor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/extractor/mssql_extractor.php b/phpBB/phpbb/db/extractor/mssql_extractor.php index d0aa78f1f5..fc30f4789d 100644 --- a/phpBB/phpbb/db/extractor/mssql_extractor.php +++ b/phpBB/phpbb/db/extractor/mssql_extractor.php @@ -184,7 +184,7 @@ class mssql_extractor extends base_extractor { $this->write_data_mssql($table_name); } - else if($this->db->get_sql_layer() === 'mssqlnative') + else if ($this->db->get_sql_layer() === 'mssqlnative') { $this->write_data_mssqlnative($table_name); } From 4276962e788a0e4b111696a5d8bd69d0e2ad7df8 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 11 Jun 2015 20:57:26 +0200 Subject: [PATCH 0398/1676] [3.1.x] Increase dev version to 3.1.6-dev --- build/build.xml | 4 ++-- phpBB/includes/constants.php | 2 +- phpBB/install/schemas/schema_data.sql | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/build.xml b/build/build.xml index c3f23b4386..34d94af973 100644 --- a/build/build.xml +++ b/build/build.xml @@ -2,9 +2,9 @@ - + - + diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 3e44125204..62e5fe7a0a 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -28,7 +28,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -define('PHPBB_VERSION', '3.1.5-RC1'); +define('PHPBB_VERSION', '3.1.6-dev'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 972ee579db..bc5df123f7 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -273,7 +273,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0 INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.1.5-RC1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.1.6-dev'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); From eb11c80b2309cc84a7a33fb1b8fb45ca581dabdf Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 13 Jun 2015 14:27:12 +0200 Subject: [PATCH 0399/1676] [ticket/13921] Fix block BBCodes inside of inline BBCodes PHPBB3-13921 --- phpBB/composer.lock | 8 +++--- .../tickets_data/PHPBB3-13921.html | 1 + .../tickets_data/PHPBB3-13921.txt | 1 + .../tickets_data/PHPBB3-13921.xml | 28 +++++++++++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 tests/text_processing/tickets_data/PHPBB3-13921.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-13921.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-13921.xml diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 2d965ecbee..27dbc48321 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -220,12 +220,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "4c124782e8f74cc462c4f27e81f81192b2853408" + "reference": "85ac4557e7fc504e74ec0a672680af8481fe329c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/4c124782e8f74cc462c4f27e81f81192b2853408", - "reference": "4c124782e8f74cc462c4f27e81f81192b2853408", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/85ac4557e7fc504e74ec0a672680af8481fe329c", + "reference": "85ac4557e7fc504e74ec0a672680af8481fe329c", "shasum": "" }, "require": { @@ -270,7 +270,7 @@ "parser", "shortcodes" ], - "time": "2015-05-30 02:58:41" + "time": "2015-06-13 12:25:49" }, { "name": "symfony/config", diff --git a/tests/text_processing/tickets_data/PHPBB3-13921.html b/tests/text_processing/tickets_data/PHPBB3-13921.html new file mode 100644 index 0000000000..6a9dc7f504 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13921.html @@ -0,0 +1 @@ +
          xxx
          \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13921.txt b/tests/text_processing/tickets_data/PHPBB3-13921.txt new file mode 100644 index 0000000000..392da0c3c8 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13921.txt @@ -0,0 +1 @@ +[size=200][center]xxx[/center][/size] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13921.xml b/tests/text_processing/tickets_data/PHPBB3-13921.xml new file mode 100644 index 0000000000..8d39246bb4 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13921.xml @@ -0,0 +1,28 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + center + + 1 + [center]{TEXT}[/center] + {TEXT}]]> + !\[center\](.*?)\[/center\]!ies + '[center:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${1}')).'[/center:$uid]' + !\[center:$uid\](.*?)\[/center:$uid\]!s + ${1}]]> + +
          +
          From 08c7afedfa544d289da3880858df825144fa24e2 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 14 Jun 2015 19:06:36 +0200 Subject: [PATCH 0400/1676] [ticket/13946] Increase the CSS margin around [code] and [list] PHPBB3-13946 --- phpBB/styles/prosilver/theme/content.css | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index f8eefb1b8e..cfddf5df5b 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -383,8 +383,7 @@ dl.faq dt { } .content ul, .content ol { - margin-bottom: 1em; - margin-left: 3em; + margin: 1em 0 1.2em 3em; } .posthilit { @@ -430,8 +429,7 @@ dd .signature { } .signature ul, .signature ol { - margin-bottom: 1em; - margin-left: 3em; + margin: 1em 0 1.2em 3em; } /* Post noticies */ @@ -493,6 +491,7 @@ blockquote.uncited { padding: 3px; border: 1px solid transparent; font-size: 1em; + margin: 1em 0 1.2em 0; } .codebox p { From 4be0730898d44c2c1a5ac449eb6da27800b74484 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 16 Jun 2015 17:20:14 +0200 Subject: [PATCH 0401/1676] [ticket/13946] Changed [list] margin to match [code] PHPBB3-13946 --- phpBB/styles/prosilver/theme/content.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index cfddf5df5b..3d2e445c37 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -383,7 +383,7 @@ dl.faq dt { } .content ul, .content ol { - margin: 1em 0 1.2em 3em; + margin: 0.8em 0 0.9em 3em; } .posthilit { @@ -429,7 +429,7 @@ dd .signature { } .signature ul, .signature ol { - margin: 1em 0 1.2em 3em; + margin: 0.8em 0 0.9em 3em; } /* Post noticies */ From 98cb70f5d2e42dafa48413713cc60ddd881c54c6 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 23 Jun 2015 14:31:18 +0200 Subject: [PATCH 0402/1676] [ticket/13961] Move service_collection to di/service_collection namespace PHPBB3-13961 --- phpBB/config/default/container/services_auth.yml | 2 +- phpBB/config/default/container/services_avatar.yml | 2 +- phpBB/config/default/container/services_captcha.yml | 2 +- phpBB/config/default/container/services_console.yml | 2 +- phpBB/config/default/container/services_cron.yml | 2 +- phpBB/config/default/container/services_migrator.yml | 2 +- .../config/default/container/services_mimetype_guesser.yml | 2 +- phpBB/config/default/container/services_notification.yml | 6 +++--- phpBB/config/default/container/services_password.yml | 2 +- phpBB/config/default/container/services_profilefield.yml | 2 +- phpBB/config/default/container/services_twig.yml | 2 +- phpBB/includes/acp/acp_profile.php | 2 +- phpBB/phpbb/auth/provider/oauth/oauth.php | 6 +++--- phpBB/phpbb/auth/provider_collection.php | 2 +- phpBB/phpbb/captcha/factory.php | 6 +++--- phpBB/phpbb/console/application.php | 4 ++-- .../di/{ => service_collection}/service_collection.php | 2 +- .../service_collection_iterator.php | 6 +++--- phpBB/phpbb/passwords/manager.php | 2 +- phpBB/phpbb/profilefields/manager.php | 6 +++--- tests/functions/user_delete_test.php | 2 +- tests/session/garbage_collection_test.php | 2 +- 22 files changed, 33 insertions(+), 33 deletions(-) rename phpBB/phpbb/di/{ => service_collection}/service_collection.php (97%) rename phpBB/phpbb/di/{ => service_collection}/service_collection_iterator.php (81%) diff --git a/phpBB/config/default/container/services_auth.yml b/phpBB/config/default/container/services_auth.yml index 88a90ca2d6..28b98a98b7 100644 --- a/phpBB/config/default/container/services_auth.yml +++ b/phpBB/config/default/container/services_auth.yml @@ -69,7 +69,7 @@ services: # ----- OAuth services providers ----- auth.provider.oauth.service_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_avatar.yml b/phpBB/config/default/container/services_avatar.yml index c74bef3d66..cd5b0756c6 100644 --- a/phpBB/config/default/container/services_avatar.yml +++ b/phpBB/config/default/container/services_avatar.yml @@ -7,7 +7,7 @@ services: # ----- Avatar drivers ----- avatar.driver_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_captcha.yml b/phpBB/config/default/container/services_captcha.yml index e3f617e909..9e4150b094 100644 --- a/phpBB/config/default/container/services_captcha.yml +++ b/phpBB/config/default/container/services_captcha.yml @@ -8,7 +8,7 @@ services: # ----- Captcha plugins ----- # Scope MUST be prototype for all the plugins to work. captcha.plugins.service_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index f0ae6c8ab4..36e2bd5729 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -1,6 +1,6 @@ services: console.command_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_cron.yml b/phpBB/config/default/container/services_cron.yml index c5b88df181..cc3c70c542 100644 --- a/phpBB/config/default/container/services_cron.yml +++ b/phpBB/config/default/container/services_cron.yml @@ -15,7 +15,7 @@ services: # ----- Cron tasks ----- cron.task_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_migrator.yml b/phpBB/config/default/container/services_migrator.yml index 01bd7d3a11..8c81aec8b3 100644 --- a/phpBB/config/default/container/services_migrator.yml +++ b/phpBB/config/default/container/services_migrator.yml @@ -19,7 +19,7 @@ services: # ----- Migrator's tools ----- migrator.tool_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_mimetype_guesser.yml b/phpBB/config/default/container/services_mimetype_guesser.yml index 2e89ed3c1f..f22a41613a 100644 --- a/phpBB/config/default/container/services_mimetype_guesser.yml +++ b/phpBB/config/default/container/services_mimetype_guesser.yml @@ -1,6 +1,6 @@ services: mimetype.guesser_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index c3bbcddfa6..896b93f75b 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -20,7 +20,7 @@ services: # ----- Notification's types ----- # Scope MUST be prototype for all the plugins to work. notification.type_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: @@ -351,11 +351,11 @@ services: - %tables.user_notifications% tags: - { name: notification.type } - + # ----- Notification's methods ----- # Scope MUST be prototype for all the plugins to work. notification.method_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_password.yml b/phpBB/config/default/container/services_password.yml index cb45ec3d42..22530f33d6 100644 --- a/phpBB/config/default/container/services_password.yml +++ b/phpBB/config/default/container/services_password.yml @@ -18,7 +18,7 @@ services: # ----- Password's drivers ----- passwords.driver_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_profilefield.yml b/phpBB/config/default/container/services_profilefield.yml index 5ccfef9148..9bbc0be4c9 100644 --- a/phpBB/config/default/container/services_profilefield.yml +++ b/phpBB/config/default/container/services_profilefield.yml @@ -21,7 +21,7 @@ services: # ----- Profile fields types ----- profilefields.type_collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index 2799892376..2c5b5a8398 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -25,7 +25,7 @@ services: - @filesystem template.twig.extensions.collection: - class: phpbb\di\service_collection + class: phpbb\di\service_collection\service_collection arguments: - @service_container tags: diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 146e116cfd..79feda88f1 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -27,7 +27,7 @@ class acp_profile var $lang_defs; /** - * @var \phpbb\di\service_collection + * @var \phpbb\di\service_collection\service_collection */ protected $type_collection; diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php index be0fbf5831..612446a2a8 100644 --- a/phpBB/phpbb/auth/provider/oauth/oauth.php +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -72,7 +72,7 @@ class oauth extends \phpbb\auth\provider\base /** * All OAuth service providers * - * @var \phpbb\di\service_collection Contains \phpbb\auth\provider\oauth\service_interface + * @var \phpbb\di\service_collection\service_collection Contains \phpbb\auth\provider\oauth\service_interface */ protected $service_providers; @@ -121,13 +121,13 @@ class oauth extends \phpbb\auth\provider\base * @param \phpbb\user $user * @param string $auth_provider_oauth_token_storage_table * @param string $auth_provider_oauth_token_account_assoc - * @param \phpbb\di\service_collection $service_providers Contains \phpbb\auth\provider\oauth\service_interface + * @param \phpbb\di\service_collection\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 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_collection $service_providers, $users_table, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, $phpbb_root_path, $php_ext) { $this->db = $db; $this->config = $config; diff --git a/phpBB/phpbb/auth/provider_collection.php b/phpBB/phpbb/auth/provider_collection.php index 8e7e9e2cc1..71da30e4c4 100644 --- a/phpBB/phpbb/auth/provider_collection.php +++ b/phpBB/phpbb/auth/provider_collection.php @@ -18,7 +18,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** * Collection of auth providers to be configured at container compile time. */ -class provider_collection extends \phpbb\di\service_collection +class provider_collection extends \phpbb\di\service_collection\service_collection { /** @var \phpbb\config\config phpBB Config */ protected $config; diff --git a/phpBB/phpbb/captcha/factory.php b/phpBB/phpbb/captcha/factory.php index dd44aca8bb..1357e919bb 100644 --- a/phpBB/phpbb/captcha/factory.php +++ b/phpBB/phpbb/captcha/factory.php @@ -21,7 +21,7 @@ class factory private $container; /** - * @var \phpbb\di\service_collection + * @var \phpbb\di\service_collection\service_collection */ private $plugins; @@ -29,9 +29,9 @@ class factory * Constructor * * @param \Symfony\Component\DependencyInjection\ContainerInterface $container - * @param \phpbb\di\service_collection $plugins + * @param \phpbb\di\service_collection\service_collection $plugins */ - public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, \phpbb\di\service_collection $plugins) + public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, \phpbb\di\service_collection\service_collection $plugins) { $this->container = $container; $this->plugins = $plugins; diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php index bc4897af18..fa847cd64d 100644 --- a/phpBB/phpbb/console/application.php +++ b/phpBB/phpbb/console/application.php @@ -89,9 +89,9 @@ class application extends \Symfony\Component\Console\Application /** * Register a set of commands from the container * - * @param \phpbb\di\service_collection $command_collection The console service collection + * @param \phpbb\di\service_collection\service_collection $command_collection The console service collection */ - public function register_container_commands(\phpbb\di\service_collection $command_collection) + public function register_container_commands(\phpbb\di\service_collection\service_collection $command_collection) { foreach ($command_collection as $service_command) { diff --git a/phpBB/phpbb/di/service_collection.php b/phpBB/phpbb/di/service_collection/service_collection.php similarity index 97% rename from phpBB/phpbb/di/service_collection.php rename to phpBB/phpbb/di/service_collection/service_collection.php index 82ca9bf679..8085128fed 100644 --- a/phpBB/phpbb/di/service_collection.php +++ b/phpBB/phpbb/di/service_collection/service_collection.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\di; +namespace phpbb\di\service_collection; use Symfony\Component\DependencyInjection\ContainerInterface; diff --git a/phpBB/phpbb/di/service_collection_iterator.php b/phpBB/phpbb/di/service_collection/service_collection_iterator.php similarity index 81% rename from phpBB/phpbb/di/service_collection_iterator.php rename to phpBB/phpbb/di/service_collection/service_collection_iterator.php index 0d031ab52d..76e22b048e 100644 --- a/phpBB/phpbb/di/service_collection_iterator.php +++ b/phpBB/phpbb/di/service_collection/service_collection_iterator.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\di; +namespace phpbb\di\service_collection; /** * Iterator which loads the services when they are requested @@ -19,14 +19,14 @@ namespace phpbb\di; class service_collection_iterator extends \ArrayIterator { /** - * @var \phpbb\di\service_collection + * @var \phpbb\di\service_collection\service_collection */ protected $collection; /** * Construct an ArrayIterator for service_collection * - * @param \phpbb\di\service_collection $collection The collection to iterate over + * @param \phpbb\di\service_collection\service_collection $collection The collection to iterate over * @param int $flags Flags to control the behaviour of the ArrayObject object. * @see ArrayObject::setFlags() */ diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index aa9147ecf4..8974dc36d1 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -89,7 +89,7 @@ class manager /** * Fill algorithm type map * - * @param \phpbb\di\service_collection $hashing_algorithms + * @param \phpbb\di\service_collection\service_collection $hashing_algorithms */ protected function fill_type_map($hashing_algorithms) { diff --git a/phpBB/phpbb/profilefields/manager.php b/phpBB/phpbb/profilefields/manager.php index 4ad3214ae4..802629a10e 100644 --- a/phpBB/phpbb/profilefields/manager.php +++ b/phpBB/phpbb/profilefields/manager.php @@ -50,7 +50,7 @@ class manager /** * Service Collection object - * @var \phpbb\di\service_collection + * @var \phpbb\di\service_collection\service_collection */ protected $type_collection; @@ -76,13 +76,13 @@ class manager * @param \phpbb\event\dispatcher_interface $dispatcher Event dispatcher object * @param \phpbb\request\request $request Request object * @param \phpbb\template\template $template Template object - * @param \phpbb\di\service_collection $type_collection + * @param \phpbb\di\service_collection\service_collection $type_collection * @param \phpbb\user $user User object * @param string $fields_table * @param string $fields_language_table * @param string $fields_data_table */ - public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\di\service_collection $type_collection, \phpbb\user $user, $fields_table, $fields_language_table, $fields_data_table) + public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\di\service_collection\service_collection $type_collection, \phpbb\user $user, $fields_table, $fields_language_table, $fields_data_table) { $this->auth = $auth; $this->db = $db; diff --git a/tests/functions/user_delete_test.php b/tests/functions/user_delete_test.php index 21561492fd..011d251167 100644 --- a/tests/functions/user_delete_test.php +++ b/tests/functions/user_delete_test.php @@ -46,7 +46,7 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case $notification_manager = new phpbb_mock_notification_manager(); $provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config); $oauth_provider_google = new \phpbb\auth\provider\oauth\service\google($config, $request); - $oauth_provider_collection = new \phpbb\di\service_collection($phpbb_container); + $oauth_provider_collection = new \phpbb\di\service_collection\service_collection($phpbb_container); $oauth_provider_collection->offsetSet('auth.provider.oauth.service.google', $oauth_provider_google); $driver_helper = new \phpbb\passwords\driver\helper($config); diff --git a/tests/session/garbage_collection_test.php b/tests/session/garbage_collection_test.php index 3fad81c68b..5b337be44e 100644 --- a/tests/session/garbage_collection_test.php +++ b/tests/session/garbage_collection_test.php @@ -30,7 +30,7 @@ class phpbb_session_garbage_collection_test extends phpbb_session_test_case global $phpbb_container; - $plugins = new \phpbb\di\service_collection($phpbb_container); + $plugins = new \phpbb\di\service_collection\service_collection($phpbb_container); $plugins->add('core.captcha.plugins.nogd'); $phpbb_container->set( 'captcha.factory', From 9dbd8f4f9b1c8a9edd0d1734c2c61b7360d54836 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 23 Jun 2015 14:35:45 +0200 Subject: [PATCH 0403/1676] [ticket/13961] Add test to service_collection PHPBB3-13961 --- tests/di/service_collection_test.php | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/di/service_collection_test.php diff --git a/tests/di/service_collection_test.php b/tests/di/service_collection_test.php new file mode 100644 index 0000000000..5b51254a4a --- /dev/null +++ b/tests/di/service_collection_test.php @@ -0,0 +1,47 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_service_collection_test extends \phpbb_test_case +{ + /** + * @var \phpbb\di\service_collection + */ + protected $service_collection; + + public function setUp() + { + $container = new phpbb_mock_container_builder(); + $container->set('foo', new StdClass); + $container->set('bar', new StdClass); + + $this->service_collection = new \phpbb\di\service_collection($container); + $this->service_collection->add('foo'); + $this->service_collection->add('bar'); + + parent::setUp(); + } + + public function test_service_collection() + { + $service_names = array(); + + // Test the iterator + foreach ($this->service_collection as $name => $service) + { + $service_names[] = $name; + $this->assertInstanceOf('StdClass', $service); + } + + $this->assertSame(array('foo', 'bar'), $service_names); + } +} From a91c4e4f96309401f2e1a7a05ccadc876781298e Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 24 Jun 2015 13:08:19 +0200 Subject: [PATCH 0404/1676] [ticket/13961] Add ordered service collection PHPBB3-13961 --- phpBB/phpbb/di/pass/collection_pass.php | 11 +- .../ordered_service_collection.php | 108 ++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 phpBB/phpbb/di/service_collection/ordered_service_collection.php diff --git a/phpBB/phpbb/di/pass/collection_pass.php b/phpBB/phpbb/di/pass/collection_pass.php index a5c054674e..ccc1250c20 100644 --- a/phpBB/phpbb/di/pass/collection_pass.php +++ b/phpBB/phpbb/di/pass/collection_pass.php @@ -37,7 +37,16 @@ class collection_pass implements CompilerPassInterface foreach ($container->findTaggedServiceIds($data[0]['tag']) as $service_id => $service_data) { - $definition->addMethodCall('add', array($service_id)); + if (substr($definition->getClass(), -strlen('ordered_service_collection')) === 'ordered_service_collection') + { + $arguments = array($service_id, $service_data[0]['order']); + } + else + { + $arguments = array($service_id); + } + + $definition->addMethodCall('add', $arguments); } } } diff --git a/phpBB/phpbb/di/service_collection/ordered_service_collection.php b/phpBB/phpbb/di/service_collection/ordered_service_collection.php new file mode 100644 index 0000000000..01d0914ad4 --- /dev/null +++ b/phpBB/phpbb/di/service_collection/ordered_service_collection.php @@ -0,0 +1,108 @@ + + * @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\di\service_collection; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Collection of services in a specified order + */ +class ordered_service_collection extends service_collection +{ + /** + * @var bool + */ + protected $is_ordered; + + /** + * @var array + */ + protected $service_ids; + + /** + * Constructor + * + * @param ContainerInterface $container Container object + */ + public function __construct(ContainerInterface $container) + { + $this->is_ordered = false; + $this->service_ids = array(); + + parent::__construct($container); + } + + /** + * {@inheritdoc} + */ + public function offsetExists($index) + { + if (!$this->is_ordered) + { + $this->sort_services(); + } + + return parent::offsetExists($index); + } + + /** + * {@inheritdoc} + */ + public function offsetGet($index) + { + if (!$this->is_ordered) + { + $this->sort_services(); + } + + return parent::offsetGet($index); + } + + /** + * Adds a service ID to the collection + * + * @param string $service_id + * @param int $order + */ + public function add($service_id, $order) + { + if ($this->is_ordered) + { + return; + } + + $order = (int) $order; + + $this->service_ids[$order][] = $service_id; + } + + protected function sort_services() + { + if ($this->is_ordered) + { + return; + } + + ksort($this->service_ids); + foreach ($this->service_ids as $service_order_group) + { + foreach ($service_order_group as $service_id) + { + $this->offsetSet($service_id, null); + } + } + + $this->is_ordered = true; + } +} From f5b476b221d2fec5cb5886ca6174b3e7c27b1cba Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 24 Jun 2015 13:13:13 +0200 Subject: [PATCH 0405/1676] [ticket/13961] Add tests for ordered collections PHPBB3-13961 --- tests/di/ordered_service_collection_test.php | 51 ++++++++++++++++++++ tests/di/service_collection_test.php | 4 +- 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 tests/di/ordered_service_collection_test.php diff --git a/tests/di/ordered_service_collection_test.php b/tests/di/ordered_service_collection_test.php new file mode 100644 index 0000000000..046cd8ccef --- /dev/null +++ b/tests/di/ordered_service_collection_test.php @@ -0,0 +1,51 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_ordered_service_collection_test extends \phpbb_test_case +{ + /** + * @var \phpbb\di\service_collection\ordered_service_collection + */ + protected $service_collection; + + public function setUp() + { + $container = new phpbb_mock_container_builder(); + $container->set('foo', new StdClass); + $container->set('bar', new StdClass); + $container->set('foobar', new StdClass); + $container->set('barfoo', new StdClass); + + $this->service_collection = new \phpbb\di\service_collection\ordered_service_collection($container); + $this->service_collection->add('foo', 7); + $this->service_collection->add('bar', 3); + $this->service_collection->add('barfoo', 5); + $this->service_collection->add('foobar', 2); + + parent::setUp(); + } + + public function test_service_collection() + { + $service_names = array(); + + // Test the iterator + foreach ($this->service_collection as $name => $service) + { + $service_names[] = $name; + $this->assertInstanceOf('StdClass', $service); + } + + $this->assertSame(array('foobar', 'bar', 'barfoo', 'foo'), $service_names); + } +} diff --git a/tests/di/service_collection_test.php b/tests/di/service_collection_test.php index 5b51254a4a..e78a5180b6 100644 --- a/tests/di/service_collection_test.php +++ b/tests/di/service_collection_test.php @@ -14,7 +14,7 @@ class phpbb_service_collection_test extends \phpbb_test_case { /** - * @var \phpbb\di\service_collection + * @var \phpbb\di\service_collection\service_collection */ protected $service_collection; @@ -24,7 +24,7 @@ class phpbb_service_collection_test extends \phpbb_test_case $container->set('foo', new StdClass); $container->set('bar', new StdClass); - $this->service_collection = new \phpbb\di\service_collection($container); + $this->service_collection = new \phpbb\di\service_collection\service_collection($container); $this->service_collection->add('foo'); $this->service_collection->add('bar'); From a34a65afdce363aed65d037576278aef4484b753 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 24 Jun 2015 15:15:38 +0200 Subject: [PATCH 0406/1676] [ticket/13691] Add services when the iterator requested PHPBB3-13691 --- .../ordered_service_collection.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/phpBB/phpbb/di/service_collection/ordered_service_collection.php b/phpBB/phpbb/di/service_collection/ordered_service_collection.php index 01d0914ad4..f012abcd09 100644 --- a/phpBB/phpbb/di/service_collection/ordered_service_collection.php +++ b/phpBB/phpbb/di/service_collection/ordered_service_collection.php @@ -43,6 +43,19 @@ class ordered_service_collection extends service_collection parent::__construct($container); } + /** + * {@inheritdoc} + */ + public function getIterator() + { + if (!$this->is_ordered) + { + $this->sort_services(); + } + + return new service_collection_iterator($this); + } + /** * {@inheritdoc} */ From 050de400d741d48403fb32485933d1fe161e89b0 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 24 Jun 2015 15:35:47 +0200 Subject: [PATCH 0407/1676] [ticket/13961] Fix compatibility issue with parent class PHPBB3-13961 --- .../phpbb/di/service_collection/ordered_service_collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/di/service_collection/ordered_service_collection.php b/phpBB/phpbb/di/service_collection/ordered_service_collection.php index f012abcd09..8d56434504 100644 --- a/phpBB/phpbb/di/service_collection/ordered_service_collection.php +++ b/phpBB/phpbb/di/service_collection/ordered_service_collection.php @@ -88,7 +88,7 @@ class ordered_service_collection extends service_collection * @param string $service_id * @param int $order */ - public function add($service_id, $order) + public function add($service_id, $order = 0) { if ($this->is_ordered) { From f02cc27014c27acaf44b27066959426db27b3493 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 16 Jun 2015 08:16:56 +0200 Subject: [PATCH 0408/1676] [ticket/10620] Implemented quote improvements PHPBB3-10620 --- .../container/services_text_formatter.yml | 8 ++ phpBB/includes/ucp/ucp_pm_compose.php | 11 ++- phpBB/phpbb/textformatter/s9e/factory.php | 28 +++---- .../phpbb/textformatter/s9e/quote_helper.php | 81 +++++++++++++++++++ phpBB/phpbb/textformatter/s9e/renderer.php | 19 +++++ phpBB/phpbb/textformatter/s9e/utils.php | 1 + phpBB/posting.php | 7 +- phpBB/styles/prosilver/template/bbcode.html | 33 ++++++++ tests/functional/posting_test.php | 17 ++-- tests/functional/private_messages_test.php | 20 ++++- .../phpbb_test_case_helpers.php | 32 +++++++- .../s9e/default_formatting_test.php | 22 +++++ 12 files changed, 248 insertions(+), 31 deletions(-) create mode 100644 phpBB/phpbb/textformatter/s9e/quote_helper.php diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index 20436f0f64..ae698af9e4 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -44,6 +44,13 @@ services: - @text_formatter.s9e.factory - @dispatcher + text_formatter.s9e.quote_helper: + class: phpbb\textformatter\s9e\quote_helper + arguments: + - @user + - %core.root_path% + - %core.php_ext% + text_formatter.s9e.renderer: class: phpbb\textformatter\s9e\renderer arguments: @@ -53,6 +60,7 @@ services: - @text_formatter.s9e.factory - @dispatcher calls: + - [configure_quote_helper, [@text_formatter.s9e.quote_helper]] - [configure_smilies_path, [@config, @path_helper]] - [configure_user, [@user, @config, @auth]] diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 0989539a0f..c00363bee9 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -941,9 +941,18 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { $message_link = ''; } + $quote_attributes = array( + 'author' => $quote_username, + 'time' => $post['message_time'], + 'user_id' => $post['author_id'], + ); + if ($action === 'quotepost') + { + $quote_attributes['post_id'] = $post['msg_id']; + } $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( censor_text($message_parser->message), - array('author' => $quote_username) + $quote_attributes ); $message_parser->message = $message_link . $quote_text . "\n\n"; } diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index e07a1b52ca..cd4e593fb1 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -77,7 +77,12 @@ class factory implements \phpbb\textformatter\cache_interface 'quote' => "[QUOTE author={TEXT1;optional} + post_id={UINT;optional} + post_url={URL;optional;postFilter=#false} + profile_url={URL;optional;postFilter=#false} + time={UINT;optional} url={URL;optional} + user_id={UINT;optional} author={PARSE=/^\\[url=(?'url'.*?)](?'author'.*)\\[\\/url]$/i} author={PARSE=/^\\[url](?'author'(?'url'.*?))\\[\\/url]$/i} author={PARSE=/(?'url'https?:\\/\\/[^[\\]]+)/i} @@ -471,24 +476,11 @@ class factory implements \phpbb\textformatter\cache_interface $templates['li'] = $fragments['listitem'] . '' . $fragments['listitem_close']; - $fragments['quote_username_open'] = str_replace( - '{USERNAME}', - ' - ' . str_replace('{DESCRIPTION}', '{USERNAME}', $fragments['url']) . ' - {USERNAME} - ', - $fragments['quote_username_open'] - ); - - $templates['quote'] = - ' - - ' . $fragments['quote_username_open'] . '' . $fragments['quote_close'] . ' - - - ' . $fragments['quote_open'] . '' . $fragments['quote_close'] . ' - - '; + // Replace the regular quote template with the extended quote template if available + if (isset($fragments['quote_extended'])) + { + $templates['quote'] = $fragments['quote_extended']; + } // The [attachment] BBCode uses the inline_attachment template to output a comment that // is post-processed by parse_attachments() diff --git a/phpBB/phpbb/textformatter/s9e/quote_helper.php b/phpBB/phpbb/textformatter/s9e/quote_helper.php new file mode 100644 index 0000000000..24109ac8cc --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/quote_helper.php @@ -0,0 +1,81 @@ + +* @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\textformatter\s9e; + +class quote_helper +{ + /** + * @var string Base URL for a post link, uses {POST_ID} as placeholder + */ + protected $post_url; + + /** + * @var string Base URL for a profile link, uses {USER_ID} as placeholder + */ + protected $profile_url; + + /** + * @var \phpbb\user + */ + protected $user; + + /** + * Constructor + * + * @param \phpbb\user $user + * @param string $root_path + * @param string $php_ext + */ + public function __construct(\phpbb\user $user, $root_path, $php_ext) + { + $this->post_url = append_sid($root_path . 'viewtopic.' . $php_ext, 'p={POST_ID}#p{POST_ID}'); + $this->profile_url = append_sid($root_path . 'memberlist.' . $php_ext, 'mode=viewprofile&u={USER_ID}'); + $this->user = $user; + } + + /** + * Inject dynamic metadata into QUOTE tags in given XML + * + * @param string $xml Original XML + * @return string Modified XML + */ + public function inject_metadata($xml) + { + $post_url = $this->post_url; + $profile_url = $this->profile_url; + $user = $this->user; + + return \s9e\TextFormatter\Utils::replaceAttributes( + $xml, + 'QUOTE', + function ($attributes) use ($post_url, $profile_url, $user) + { + if (isset($attributes['post_id'])) + { + $attributes['post_url'] = str_replace('{POST_ID}', $attributes['post_id'], $post_url); + } + if (isset($attributes['time'])) + { + $attributes['date'] = $user->format_date($attributes['time']); + } + if (isset($attributes['user_id'])) + { + $attributes['profile_url'] = str_replace('{USER_ID}', $attributes['user_id'], $profile_url); + } + + return $attributes; + } + ); + } +} diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 51bc44f339..2206605ba2 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -28,6 +28,11 @@ class renderer implements \phpbb\textformatter\renderer_interface */ protected $dispatcher; + /** + * @var quote_helper + */ + protected $quote_helper; + /** * @var \s9e\TextFormatter\Renderer */ @@ -112,6 +117,16 @@ class renderer implements \phpbb\textformatter\renderer_interface extract($dispatcher->trigger_event('core.text_formatter_s9e_renderer_setup', compact($vars))); } + /** + * Configure the quote_helper object used to display extended information in quotes + * + * @param quote_helper $quote_helper + */ + public function configure_quote_helper(quote_helper $quote_helper) + { + $this->quote_helper = $quote_helper; + } + /** * Automatically set the smilies path based on config * @@ -214,6 +229,10 @@ class renderer implements \phpbb\textformatter\renderer_interface */ public function render($xml) { + if (isset($this->quote_helper)) + { + $xml = $this->quote_helper->inject_metadata($xml); + } $renderer = $this; /** diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index 803c71a5a2..df1966fa32 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -64,6 +64,7 @@ class utils implements \phpbb\textformatter\utils_interface $quote .= '=' . $this->enquote($attributes['author']); unset($attributes['author']); } + ksort($attributes); foreach ($attributes as $name => $value) { $quote .= ' ' . $name . '=' . $this->enquote($value); diff --git a/phpBB/posting.php b/phpBB/posting.php index 2f9beefcf9..327004b1bf 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1605,7 +1605,12 @@ if ($generate_quote) { $message_parser->message = $phpbb_container->get('text_formatter.utils')->generate_quote( censor_text($message_parser->message), - array('author' => $post_data['quote_username']) + array( + 'author' => $post_data['quote_username'], + 'post_id' => $post_data['post_id'], + 'time' => $post_data['post_time'], + 'user_id' => $post_data['poster_id'], + ) ); $message_parser->message .= "\n\n"; } diff --git a/phpBB/styles/prosilver/template/bbcode.html b/phpBB/styles/prosilver/template/bbcode.html index af8e6ae4b0..6adbdb6aba 100644 --- a/phpBB/styles/prosilver/template/bbcode.html +++ b/phpBB/styles/prosilver/template/bbcode.html @@ -11,6 +11,39 @@
          {USERNAME} {L_WROTE}{L_COLON}
          + +
          + + uncited + +
          + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          +

          {L_CODE}{L_COLON} {L_SELECT_ALL_CODE}

          
           
          diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index ccfeb10deb..d9e6cc5ab3 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -75,7 +75,7 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case public function test_quote() { $text = 'Test post "\' &&amp;'; - $expected = '[quote="admin"]' . $text . '[/quote]'; + $expected = '([quote="admin"[^]]*\\]' . preg_quote($text) . '\\[/quote\\])'; $this->login(); $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); @@ -83,7 +83,7 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $crawler = self::request('GET', "posting.php?mode=quote&f=2&t={$post['topic_id']}&p={$post['post_id']}&sid={$this->sid}"); - $this->assertContains($expected, $crawler->filter('textarea#message')->text()); + $this->assertRegexp($expected, $crawler->filter('textarea#message')->text()); } /** @@ -93,10 +93,10 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case { $text = '0[quote]1[quote]2[/quote]1[/quote]0'; $expected = array( - 0 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]', - 1 => '[quote="admin"]00[/quote]', - 2 => '[quote="admin"]0[quote]11[/quote]0[/quote]', - 3 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]', + 0 => '0[quote]1[quote]2[/quote]1[/quote]0', + 1 => '00', + 2 => '0[quote]11[/quote]0', + 3 => '0[quote]1[quote]2[/quote]1[/quote]0', ); $this->login(); @@ -109,7 +109,10 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case { $this->set_quote_depth($quote_depth); $crawler = self::request('GET', $quote_url); - $this->assertContains($expected_text, $crawler->filter('textarea#message')->text()); + $this->assertRegexp( + '(\\[quote="admin"[^]]*\\]' . preg_quote($expected_text) . '\\[/quote\\])', + $crawler->filter('textarea#message')->text() + ); } } diff --git a/tests/functional/private_messages_test.php b/tests/functional/private_messages_test.php index be584c20c1..9bfb5bc7ad 100644 --- a/tests/functional/private_messages_test.php +++ b/tests/functional/private_messages_test.php @@ -69,16 +69,30 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case public function test_quote_post() { - $text = 'Test post'; - $expected = '[quote="admin"]' . $text . '[/quote]'; + $text = 'Test post'; $this->login(); $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); + $expected = '(\\[quote="admin" post_id="' . $post['post_id'] . '" time="\\d+" user_id="2"\\]' . $text . '\\[/quote\\])'; + $crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=quotepost&p=' . $post['post_id'] . '&sid=' . $this->sid); - $this->assertContains($expected, $crawler->filter('textarea#message')->text()); + $this->assertRegexp($expected, $crawler->filter('textarea#message')->text()); + } + + public function test_quote_pm() + { + $text = 'This is a test private message sent by the testing framework.'; + $expected = '(\\[quote="admin" time="\\d+" user_id="2"\\]' . $text . '\\[/quote\\])'; + + $this->login(); + $message_id = $this->create_private_message('Test', $text, array(2)); + + $crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=quote&p=' . $message_id . '&sid=' . $this->sid); + + $this->assertRegexp($expected, $crawler->filter('textarea#message')->text()); } public function test_quote_forward() diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index cf530cc5be..62a56ed693 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -476,11 +476,21 @@ class phpbb_test_case_helpers { $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); $lang = new \phpbb\language\language($lang_loader); - $user = new \phpbb\user($lang, '\phpbb\datetime'); + + $user = $this->test_case->getMockBuilder('\phpbb\user') + ->setConstructorArgs(array($lang, '\phpbb\datetime')) + ->setMethods(array('format_date')) + ->getMock(); + $user->expects($this->test_case->any()) + ->method('format_date') + ->will($this->test_case->returnCallback(__CLASS__ . '::format_date')); + + $user->date_format = 'Y-m-d H:i:s'; $user->optionset('viewcensors', true); $user->optionset('viewflash', true); $user->optionset('viewimg', true); $user->optionset('viewsmilies', true); + $user->timezone = new \DateTimeZone('UTC'); $container->set('user', $user); } $user->add_lang('common'); @@ -490,6 +500,14 @@ class phpbb_test_case_helpers $user->style = array('style_id' => 1); } + // Create and register a quote_helper + $quote_helper = new \phpbb\textformatter\s9e\quote_helper( + $container->get('user'), + $phpbb_root_path, + $phpEx + ); + $container->set('text_formatter.s9e.quote_helper', $quote_helper); + // Create and register the text_formatter.s9e.parser service and its alias $parser = new \phpbb\textformatter\s9e\parser( $cache, @@ -515,6 +533,7 @@ class phpbb_test_case_helpers $auth = ($container->has('auth')) ? $container->get('auth') : new \phpbb\auth\auth; // Calls configured in services.yml + $renderer->configure_quote_helper($quote_helper); $renderer->configure_smilies_path($config, $container->get('path_helper')); $renderer->configure_user($user, $config, $auth); @@ -528,4 +547,15 @@ class phpbb_test_case_helpers return $container; } + + /** + * Mocked replacement for \phpbb\user::format_date() + * + * @param integer $gmepoch unix timestamp + * @return string + */ + static public function format_date($gmepoch) + { + return gmdate('Y-m-d H:i:s', $gmepoch); + } } diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 67921d5b1e..3f8e375ad1 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -225,6 +225,28 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case "[quote]\nThis is a long quote that is definitely going to exceed 80 characters\n[/quote]\n\nFollowed by a reply", "
          \nThis is a long quote that is definitely going to exceed 80 characters\n
          \n\nFollowed by a reply" ), + array( + '[quote="Username" post_id="123"]...[/quote]', + '
          Username wrote: ↑...
          ' + ), + array( + // Users are not allowed to submit their own URL for the post + '[quote="Username" post_url="http://fake.example.org"]...[/quote]', + '
          Username wrote:...
          ' + ), + array( + '[quote="Username" time="58705871"]...[/quote]', + '
          1971-11-11 11:11:11 Username wrote:...
          ' + ), + array( + '[quote="Username" user_id="123"]...[/quote]', + '
          Username wrote:...
          ' + ), + array( + // Users are not allowed to submit their own URL for the profile + '[quote="Username" profile_url="http://fake.example.org"]...[/quote]', + '
          Username wrote:...
          ' + ), ); } } From c934b8f150c81115062687e59988ca0f78b35c37 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 20 Jun 2015 17:18:46 +0200 Subject: [PATCH 0409/1676] [ticket/10620] Updated docblock PHPBB3-10620 --- phpBB/phpbb/textformatter/utils_interface.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/utils_interface.php b/phpBB/phpbb/textformatter/utils_interface.php index 41a6ba2345..4810453cd1 100644 --- a/phpBB/phpbb/textformatter/utils_interface.php +++ b/phpBB/phpbb/textformatter/utils_interface.php @@ -32,7 +32,10 @@ interface utils_interface * Create a quote block for given text * * Possible attributes: - * - author + * - author: author's name (usually a username) + * - post_id: post_id of the post being quoted + * - user_id: user_id of the user being quoted + * - time: timestamp of the original message * * @param string $text Quote's text * @param array $attributes Quote's attributes From 06936bda05a48e5b6e20d7c0b0979cf7fc1a29ae Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 22 Jun 2015 04:00:55 +0200 Subject: [PATCH 0410/1676] [ticket/10620] Added enhanced quotes in topic review Added support for enhanced quotes in topic_review's quote button. NOTE: the UI doesn't appear to be testable via PhantomJS. PHPBB3-10620 --- phpBB/assets/javascript/editor.js | 58 ++++++++++++++++++- phpBB/includes/functions_posting.php | 2 + .../template/posting_topic_review.html | 2 +- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/phpBB/assets/javascript/editor.js b/phpBB/assets/javascript/editor.js index 298526ab1f..d0d849330a 100644 --- a/phpBB/assets/javascript/editor.js +++ b/phpBB/assets/javascript/editor.js @@ -167,7 +167,7 @@ function attachInline(index, filename) { /** * Add quote text to message */ -function addquote(post_id, username, l_wrote) { +function addquote(post_id, username, l_wrote, attributes) { var message_name = 'message_' + post_id; var theSelection = ''; var divarea = false; @@ -213,7 +213,12 @@ function addquote(post_id, username, l_wrote) { if (theSelection) { if (bbcodeEnabled) { - insert_text('[quote="' + username + '"]' + theSelection + '[/quote]'); + if (typeof attributes === 'undefined') + { + attributes = {}; + } + attributes.author = username; + insert_text(generate_quote(theSelection, attributes)); } else { insert_text(username + ' ' + l_wrote + ':' + '\n'); var lines = split_lines(theSelection); @@ -226,6 +231,55 @@ function addquote(post_id, username, l_wrote) { return; } +/** +* Create a quote block for given text +* +* Possible attributes: +* - author: author's name (usually a username) +* - post_id: post_id of the post being quoted +* - user_id: user_id of the user being quoted +* - time: timestamp of the original message +* +* @param {!string} text Quote's text +* @param {!Object} attributes Quote's attributes +* @return {!string} Quote block to be used in a new post/text +*/ +function generate_quote(text, attributes) +{ + var quote = '[quote'; + if ('author' in attributes) + { + // Add the author as the BBCode's default attribute + quote += '=' + enquote(attributes.author); + delete attributes.author; + } + for (var name in attributes) + { + var value = attributes[name]; + quote += ' ' + name + '=' + enquote(String(value)); + } + quote += ']' + text + '[/quote]'; + + return quote; +} + +/** +* Return given string between quotes +* +* Will use either single- or double- quotes depending on whichever requires less escaping. +* Quotes and backslashes are escaped with backslashes where necessary +* +* @param {!string} str Original string +* @return {!string} Escaped string within quotes +*/ +function enquote(str) +{ + var singleQuoted = "'" + str.replace(/[\\']/g, '\\$&') + "'", + doubleQuoted = '"' + str.replace(/[\\"]/g, '\\$&') + '"'; + + return (singleQuoted.length < doubleQuoted.length) ? singleQuoted : doubleQuoted; +} + function split_lines(text) { var lines = text.split('\n'); var splitLines = new Array(); diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index a1ace42c32..9109c48ab6 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1193,6 +1193,8 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id 'MESSAGE' => $message, 'DECODED_MESSAGE' => $decoded_message, 'POST_ID' => $row['post_id'], + 'POST_TIME' => $row['post_time'], + 'USER_ID' => $row['user_id'], 'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'], 'U_MCP_DETAILS' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=post_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', 'POSTER_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '', diff --git a/phpBB/styles/prosilver/template/posting_topic_review.html b/phpBB/styles/prosilver/template/posting_topic_review.html index 6909877196..fc7d0a2c63 100644 --- a/phpBB/styles/prosilver/template/posting_topic_review.html +++ b/phpBB/styles/prosilver/template/posting_topic_review.html @@ -35,7 +35,7 @@
        • - + {L_QUOTE} {topic_review_row.POST_AUTHOR}
        • From 129b3375ae873b3e6e947e3c5f47897bc4f9c572 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 22 Jun 2015 18:25:20 +0200 Subject: [PATCH 0411/1676] [ticket/10620] Added enhanced quotes in pm history PHPBB3-10620 --- phpBB/includes/functions_privmsgs.php | 2 ++ phpBB/styles/prosilver/template/ucp_pm_history.html | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 245b1c0d1a..26df5b9954 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -2100,6 +2100,8 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode 'S_IN_POST_MODE' => $in_post_mode, 'MSG_ID' => $row['msg_id'], + 'MESSAGE_TIME' => $row['message_time'], + 'USER_ID' => $row['user_id'], 'U_VIEW_MESSAGE' => "$url&f=$folder_id&p=" . $row['msg_id'], 'U_QUOTE' => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '', 'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '') diff --git a/phpBB/styles/prosilver/template/ucp_pm_history.html b/phpBB/styles/prosilver/template/ucp_pm_history.html index 0e9c3844cc..8f7b4fdb3e 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_history.html +++ b/phpBB/styles/prosilver/template/ucp_pm_history.html @@ -20,7 +20,7 @@
          • - href="{history_row.U_QUOTE}"href="#postingbox" onclick="addquote({history_row.MSG_ID}, '{history_row.MESSAGE_AUTHOR_QUOTE}', '{LA_WROTE}');" title="{L_QUOTE} {history_row.MESSAGE_AUTHOR}" class="button icon-button quote-icon"> + href="{history_row.U_QUOTE}"href="#postingbox" onclick="addquote({history_row.MSG_ID}, '{history_row.MESSAGE_AUTHOR_QUOTE}', '{LA_WROTE}', {time:{history_row.MESSAGE_TIME},user_id:{history_row.USER_ID}});" title="{L_QUOTE} {history_row.MESSAGE_AUTHOR}" class="button icon-button quote-icon"> {L_QUOTE} {history_row.MESSAGE_AUTHOR}
          • From 4f1b25706f6a1ae6eb1c6c60ef27b42bb7ac4b40 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 24 Jun 2015 22:20:39 +0200 Subject: [PATCH 0412/1676] [ticket/10620] Removed extraneous quotes from attribute values PHPBB3-10620 --- phpBB/assets/javascript/editor.js | 18 ++++++++++++------ phpBB/phpbb/textformatter/s9e/utils.php | 18 ++++++++++++------ tests/functional/posting_test.php | 4 ++-- tests/functional/private_messages_test.php | 6 +++--- .../s9e/default_formatting_test.php | 10 +++++----- tests/text_formatter/s9e/utils_test.php | 10 +++++++--- 6 files changed, 41 insertions(+), 25 deletions(-) diff --git a/phpBB/assets/javascript/editor.js b/phpBB/assets/javascript/editor.js index d0d849330a..878a5cab86 100644 --- a/phpBB/assets/javascript/editor.js +++ b/phpBB/assets/javascript/editor.js @@ -250,13 +250,13 @@ function generate_quote(text, attributes) if ('author' in attributes) { // Add the author as the BBCode's default attribute - quote += '=' + enquote(attributes.author); + quote += '=' + format_attribute_value(attributes.author); delete attributes.author; } for (var name in attributes) { var value = attributes[name]; - quote += ' ' + name + '=' + enquote(String(value)); + quote += ' ' + name + '=' + format_attribute_value(String(value)); } quote += ']' + text + '[/quote]'; @@ -264,16 +264,22 @@ function generate_quote(text, attributes) } /** -* Return given string between quotes +* Format given string to be used as an attribute value * -* Will use either single- or double- quotes depending on whichever requires less escaping. +* Will return the string as-is if it can be used in a BBCode without quotes. Otherwise, +* it will use either single- or double- quotes depending on whichever requires less escaping. * Quotes and backslashes are escaped with backslashes where necessary * * @param {!string} str Original string -* @return {!string} Escaped string within quotes +* @return {!string} Same string if possible, escaped string within quotes otherwise */ -function enquote(str) +function format_attribute_value(str) { + if (!/[ "'\\\]]/.test(str)) + { + // Return as-is if it contains none of: space, ' " \ or ] + return str; + } var singleQuoted = "'" + str.replace(/[\\']/g, '\\$&') + "'", doubleQuoted = '"' + str.replace(/[\\"]/g, '\\$&') + '"'; diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index df1966fa32..40479b3423 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -35,16 +35,22 @@ class utils implements \phpbb\textformatter\utils_interface } /** - * Return given string between quotes + * Format given string to be used as an attribute value * - * Will use either single- or double- quotes depending on whichever requires less escaping. + * Will return the string as-is if it can be used in a BBCode without quotes. Otherwise, + * it will use either single- or double- quotes depending on whichever requires less escaping. * Quotes and backslashes are escaped with backslashes where necessary * * @param string $str Original string - * @return string Escaped string within quotes + * @return string Same string if possible, escaped string within quotes otherwise */ - protected function enquote($str) + protected function format_attribute_value($str) { + if (!preg_match('/[ "\'\\\\\\]]/', $str)) + { + // Return as-is if it contains none of: space, ' " \ or ] + return $str; + } $singleQuoted = "'" . addcslashes($str, "\\'") . "'"; $doubleQuoted = '"' . addcslashes($str, '\\"') . '"'; @@ -61,13 +67,13 @@ class utils implements \phpbb\textformatter\utils_interface if (isset($attributes['author'])) { // Add the author as the BBCode's default attribute - $quote .= '=' . $this->enquote($attributes['author']); + $quote .= '=' . $this->format_attribute_value($attributes['author']); unset($attributes['author']); } ksort($attributes); foreach ($attributes as $name => $value) { - $quote .= ' ' . $name . '=' . $this->enquote($value); + $quote .= ' ' . $name . '=' . $this->format_attribute_value($value); } $quote .= ']'; $newline = (strlen($quote . $text . '[/quote]') > 80 || strpos($text, "\n") !== false) ? "\n" : ''; diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index d9e6cc5ab3..4f4ecfef45 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -75,7 +75,7 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case public function test_quote() { $text = 'Test post "\' &&amp;'; - $expected = '([quote="admin"[^]]*\\]' . preg_quote($text) . '\\[/quote\\])'; + $expected = '([quote=admin[^]]*\\]' . preg_quote($text) . '\\[/quote\\])'; $this->login(); $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); @@ -110,7 +110,7 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $this->set_quote_depth($quote_depth); $crawler = self::request('GET', $quote_url); $this->assertRegexp( - '(\\[quote="admin"[^]]*\\]' . preg_quote($expected_text) . '\\[/quote\\])', + '(\\[quote=admin[^]]*\\]' . preg_quote($expected_text) . '\\[/quote\\])', $crawler->filter('textarea#message')->text() ); } diff --git a/tests/functional/private_messages_test.php b/tests/functional/private_messages_test.php index 9bfb5bc7ad..a7d1a29e80 100644 --- a/tests/functional/private_messages_test.php +++ b/tests/functional/private_messages_test.php @@ -75,7 +75,7 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); - $expected = '(\\[quote="admin" post_id="' . $post['post_id'] . '" time="\\d+" user_id="2"\\]' . $text . '\\[/quote\\])'; + $expected = '(\\[quote=admin post_id=' . $post['post_id'] . ' time=\\d+ user_id=2\\]' . $text . '\\[/quote\\])'; $crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=quotepost&p=' . $post['post_id'] . '&sid=' . $this->sid); @@ -85,7 +85,7 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case public function test_quote_pm() { $text = 'This is a test private message sent by the testing framework.'; - $expected = '(\\[quote="admin" time="\\d+" user_id="2"\\]' . $text . '\\[/quote\\])'; + $expected = '(\\[quote=admin time=\\d+ user_id=2\\]' . $text . '\\[/quote\\])'; $this->login(); $message_id = $this->create_private_message('Test', $text, array(2)); @@ -98,7 +98,7 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case public function test_quote_forward() { $text = 'This is a test private message sent by the testing framework.'; - $expected = "[quote=\"admin\"]\n" . $text . "\n[/quote]"; + $expected = '[quote=admin]' . $text . '[/quote]'; $this->login(); $message_id = $this->create_private_message('Test', $text, array(2)); diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 3f8e375ad1..38604b49a0 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -218,7 +218,7 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case '
            ' ), array( - '[quote="http://example.org"]...[/quote]', + '[quote=http://example.org]...[/quote]', '
            ' ), array( @@ -226,7 +226,7 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case "
            \nThis is a long quote that is definitely going to exceed 80 characters\n
            \n\nFollowed by a reply" ), array( - '[quote="Username" post_id="123"]...[/quote]', + '[quote=Username post_id=123]...[/quote]', '
            Username wrote: ↑...
            ' ), array( @@ -235,16 +235,16 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case '
            Username wrote:...
            ' ), array( - '[quote="Username" time="58705871"]...[/quote]', + '[quote=Username time=58705871]...[/quote]', '
            1971-11-11 11:11:11 Username wrote:...
            ' ), array( - '[quote="Username" user_id="123"]...[/quote]', + '[quote=Username user_id=123]...[/quote]', '
            Username wrote:...
            ' ), array( // Users are not allowed to submit their own URL for the profile - '[quote="Username" profile_url="http://fake.example.org"]...[/quote]', + '[quote=Username profile_url=http://fake.example.org]...[/quote]', '
            Username wrote:...
            ' ), ); diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index 152c316b2e..f2b480facb 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -98,11 +98,15 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case array('foo') ), array( - '[quote="foo"]..[/quote] [quote="bar"]..[/quote]', + '[quote=foo]..[/quote] [quote]..[/quote]', + array('foo') + ), + array( + '[quote=foo]..[/quote] [quote=bar]..[/quote]', array('foo', 'bar') ), array( - '[quote="foo"].[quote="baz"]..[/quote].[/quote] [quote="bar"]..[/quote]', + '[quote=foo].[quote=baz]..[/quote].[/quote] [quote=bar]..[/quote]', array('foo', 'bar') ), ); @@ -169,7 +173,7 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case 'post_id' => 123, 'url' => 'http://example.org' ), - '[quote="user" post_id="123" url="http://example.org"]...[/quote]', + '[quote=user post_id=123 url=http://example.org]...[/quote]', ), array( 'This is a long quote that is definitely going to exceed 80 characters', From 7ce2d996a82b5a2f68560a4136c1f3938a1955d4 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 24 Jun 2015 22:36:38 +0200 Subject: [PATCH 0413/1676] [ticket/10620] Added tests PHPBB3-10620 --- .../s9e/default_formatting_test.php | 5 ++++ tests/text_formatter/s9e/utils_test.php | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 38604b49a0..ed75555b42 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -247,6 +247,11 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case '[quote=Username profile_url=http://fake.example.org]...[/quote]', '
            Username wrote:...
            ' ), + array( + // From phpbb_textformatter_s9e_utils_test::test_generate_quote() + '[quote=\'[quote="foo"]\']...[/quote]', + '
            [quote="foo"] wrote:...
            ' + ), ); } } diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index f2b480facb..1c03783792 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -175,6 +175,36 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case ), '[quote=user post_id=123 url=http://example.org]...[/quote]', ), + array( + '...', + array('author' => ' '), + '[quote=" "]...[/quote]', + ), + array( + '...', + array('author' => 'foo bar'), + '[quote="foo bar"]...[/quote]', + ), + array( + '...', + array('author' => '\\'), + '[quote="\\\\"]...[/quote]', + ), + array( + '...', + array('author' => '[quote="foo"]'), + '[quote=\'[quote="foo"]\']...[/quote]', + ), + array( + '...', + array('author' => '""'), + '[quote=\'""\']...[/quote]', + ), + array( + '...', + array('author' => "''"), + '[quote="\'\'"]...[/quote]', + ), array( 'This is a long quote that is definitely going to exceed 80 characters', array(), From 4c9507e20ad4e3de291143c8a40d5c977388f5a5 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 24 Jun 2015 22:36:44 +0200 Subject: [PATCH 0414/1676] [ticket/10620] Fixed some stylistic issues in JS PHPBB3-10620 --- phpBB/assets/javascript/editor.js | 35 +++++++++++++------------------ 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/phpBB/assets/javascript/editor.js b/phpBB/assets/javascript/editor.js index 878a5cab86..f0fa064ec5 100644 --- a/phpBB/assets/javascript/editor.js +++ b/phpBB/assets/javascript/editor.js @@ -111,7 +111,6 @@ function bbfontstyle(bbopen, bbclose) { } textarea.focus(); - return; } /** @@ -177,6 +176,9 @@ function addquote(post_id, username, l_wrote, attributes) { // Backwards compatibility l_wrote = 'wrote'; } + if (typeof attributes !== 'object') { + attributes = {}; + } if (document.all) { divarea = document.all[message_name]; @@ -213,12 +215,8 @@ function addquote(post_id, username, l_wrote, attributes) { if (theSelection) { if (bbcodeEnabled) { - if (typeof attributes === 'undefined') - { - attributes = {}; - } attributes.author = username; - insert_text(generate_quote(theSelection, attributes)); + insert_text(generateQuote(theSelection, attributes)); } else { insert_text(username + ' ' + l_wrote + ':' + '\n'); var lines = split_lines(theSelection); @@ -227,8 +225,6 @@ function addquote(post_id, username, l_wrote, attributes) { } } } - - return; } /** @@ -244,19 +240,18 @@ function addquote(post_id, username, l_wrote, attributes) { * @param {!Object} attributes Quote's attributes * @return {!string} Quote block to be used in a new post/text */ -function generate_quote(text, attributes) -{ +function generateQuote(text, attributes) { var quote = '[quote'; - if ('author' in attributes) - { + if (attributes.author) { // Add the author as the BBCode's default attribute - quote += '=' + format_attribute_value(attributes.author); + quote += '=' + formatAttributeValue(attributes.author); delete attributes.author; } - for (var name in attributes) - { - var value = attributes[name]; - quote += ' ' + name + '=' + format_attribute_value(String(value)); + for (var name in attributes) { + if (attributes.hasOwnProperty(name)) { + var value = attributes[name]; + quote += ' ' + name + '=' + formatAttributeValue(value.toString()); + } } quote += ']' + text + '[/quote]'; @@ -273,10 +268,8 @@ function generate_quote(text, attributes) * @param {!string} str Original string * @return {!string} Same string if possible, escaped string within quotes otherwise */ -function format_attribute_value(str) -{ - if (!/[ "'\\\]]/.test(str)) - { +function formatAttributeValue(str) { + if (!/[ "'\\\]]/.test(str)) { // Return as-is if it contains none of: space, ' " \ or ] return str; } From 5a55ce3f6832677e2c0a244d3a5c0b4c2587b8c5 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 24 Jun 2015 22:41:58 +0200 Subject: [PATCH 0415/1676] [ticket/10620] Add more whitespace to long quotes in JS PHPBB3-10620 --- phpBB/assets/javascript/editor.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpBB/assets/javascript/editor.js b/phpBB/assets/javascript/editor.js index f0fa064ec5..df353bc29d 100644 --- a/phpBB/assets/javascript/editor.js +++ b/phpBB/assets/javascript/editor.js @@ -241,6 +241,7 @@ function addquote(post_id, username, l_wrote, attributes) { * @return {!string} Quote block to be used in a new post/text */ function generateQuote(text, attributes) { + text = text.replace(/^\s+/, '').replace(/\s+$/, ''); var quote = '[quote'; if (attributes.author) { // Add the author as the BBCode's default attribute @@ -253,7 +254,9 @@ function generateQuote(text, attributes) { quote += ' ' + name + '=' + formatAttributeValue(value.toString()); } } - quote += ']' + text + '[/quote]'; + quote += ']'; + var newline = ((quote + text + '[/quote]').length > 80 || text.indexOf('\n') > -1) ? '\n' : ''; + quote += newline + text + newline + '[/quote]'; return quote; } From 1f6b9bc0487ba43a614b05528dcd9ae830cc3b0f Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 24 Jun 2015 23:42:36 +0200 Subject: [PATCH 0416/1676] [ticket/10620] Fixed functional tests to account for newlines PHPBB3-10620 --- tests/functional/posting_test.php | 4 ++-- tests/functional/private_messages_test.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 4f4ecfef45..e9b62c0b6c 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -75,7 +75,7 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case public function test_quote() { $text = 'Test post "\' &&amp;'; - $expected = '([quote=admin[^]]*\\]' . preg_quote($text) . '\\[/quote\\])'; + $expected = "(\\[quote=admin[^\\]]*\\]\n" . preg_quote($text) . "\n\\[/quote\\])"; $this->login(); $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); @@ -110,7 +110,7 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $this->set_quote_depth($quote_depth); $crawler = self::request('GET', $quote_url); $this->assertRegexp( - '(\\[quote=admin[^]]*\\]' . preg_quote($expected_text) . '\\[/quote\\])', + "(\\[quote=admin[^\\]]*\\]\n?" . preg_quote($expected_text) . "\n?\\[/quote\\])", $crawler->filter('textarea#message')->text() ); } diff --git a/tests/functional/private_messages_test.php b/tests/functional/private_messages_test.php index a7d1a29e80..7fda26fb49 100644 --- a/tests/functional/private_messages_test.php +++ b/tests/functional/private_messages_test.php @@ -85,7 +85,7 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case public function test_quote_pm() { $text = 'This is a test private message sent by the testing framework.'; - $expected = '(\\[quote=admin time=\\d+ user_id=2\\]' . $text . '\\[/quote\\])'; + $expected = "(\\[quote=admin time=\\d+ user_id=2\\]\n" . $text . "\n\\[/quote\\])"; $this->login(); $message_id = $this->create_private_message('Test', $text, array(2)); @@ -98,7 +98,7 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case public function test_quote_forward() { $text = 'This is a test private message sent by the testing framework.'; - $expected = '[quote=admin]' . $text . '[/quote]'; + $expected = "[quote=admin]\n" . $text . "\n[/quote]"; $this->login(); $message_id = $this->create_private_message('Test', $text, array(2)); From 9d364aee4a739d0a8c8b745449940a37d81c9abf Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 25 Jun 2015 02:23:00 +0200 Subject: [PATCH 0417/1676] [ticket/10620] Moved quote's date to the upper corner PHPBB3-10620 --- phpBB/styles/prosilver/template/bbcode.html | 4 +++- phpBB/styles/prosilver/theme/content.css | 5 +++++ tests/text_formatter/s9e/default_formatting_test.php | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/phpBB/styles/prosilver/template/bbcode.html b/phpBB/styles/prosilver/template/bbcode.html index 6adbdb6aba..8c4e941092 100644 --- a/phpBB/styles/prosilver/template/bbcode.html +++ b/phpBB/styles/prosilver/template/bbcode.html @@ -19,7 +19,6 @@
            - @@ -38,6 +37,9 @@ + +
            +
            diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 3d2e445c37..e20aaef7d4 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -486,6 +486,11 @@ blockquote.uncited { padding-top: 25px; } +blockquote cite > div { + float: right; + font-weight: normal; +} + /* Code block */ .codebox { padding: 3px; diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index ed75555b42..40bec9ceee 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -236,7 +236,7 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case ), array( '[quote=Username time=58705871]...[/quote]', - '
            1971-11-11 11:11:11 Username wrote:...
            ' + '
            Username wrote:
            1971-11-11 11:11:11
            ...
            ' ), array( '[quote=Username user_id=123]...[/quote]', From b09293d5ff38633d506083cffc0a9dd2c98c15c4 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 26 Jun 2015 01:02:04 +0200 Subject: [PATCH 0418/1676] [ticket/13961] Move back service_collections under original namespace PHPBB3-13961 --- phpBB/config/default/container/services_auth.yml | 2 +- phpBB/config/default/container/services_avatar.yml | 2 +- phpBB/config/default/container/services_captcha.yml | 2 +- phpBB/config/default/container/services_console.yml | 2 +- phpBB/config/default/container/services_cron.yml | 2 +- phpBB/config/default/container/services_migrator.yml | 2 +- .../config/default/container/services_mimetype_guesser.yml | 2 +- phpBB/config/default/container/services_notification.yml | 6 +++--- phpBB/config/default/container/services_password.yml | 2 +- phpBB/config/default/container/services_profilefield.yml | 2 +- phpBB/config/default/container/services_twig.yml | 2 +- phpBB/includes/acp/acp_profile.php | 2 +- phpBB/phpbb/auth/provider/oauth/oauth.php | 6 +++--- phpBB/phpbb/auth/provider_collection.php | 2 +- phpBB/phpbb/captcha/factory.php | 6 +++--- phpBB/phpbb/console/application.php | 4 ++-- .../{service_collection => }/ordered_service_collection.php | 2 +- .../di/{service_collection => }/service_collection.php | 2 +- .../service_collection_iterator.php | 6 +++--- phpBB/phpbb/passwords/manager.php | 2 +- phpBB/phpbb/profilefields/manager.php | 6 +++--- tests/di/ordered_service_collection_test.php | 4 ++-- tests/di/service_collection_test.php | 4 ++-- tests/functions/user_delete_test.php | 2 +- tests/session/garbage_collection_test.php | 2 +- 25 files changed, 38 insertions(+), 38 deletions(-) rename phpBB/phpbb/di/{service_collection => }/ordered_service_collection.php (98%) rename phpBB/phpbb/di/{service_collection => }/service_collection.php (97%) rename phpBB/phpbb/di/{service_collection => }/service_collection_iterator.php (81%) diff --git a/phpBB/config/default/container/services_auth.yml b/phpBB/config/default/container/services_auth.yml index 28b98a98b7..88a90ca2d6 100644 --- a/phpBB/config/default/container/services_auth.yml +++ b/phpBB/config/default/container/services_auth.yml @@ -69,7 +69,7 @@ services: # ----- OAuth services providers ----- auth.provider.oauth.service_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_avatar.yml b/phpBB/config/default/container/services_avatar.yml index cd5b0756c6..c74bef3d66 100644 --- a/phpBB/config/default/container/services_avatar.yml +++ b/phpBB/config/default/container/services_avatar.yml @@ -7,7 +7,7 @@ services: # ----- Avatar drivers ----- avatar.driver_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_captcha.yml b/phpBB/config/default/container/services_captcha.yml index 9e4150b094..e3f617e909 100644 --- a/phpBB/config/default/container/services_captcha.yml +++ b/phpBB/config/default/container/services_captcha.yml @@ -8,7 +8,7 @@ services: # ----- Captcha plugins ----- # Scope MUST be prototype for all the plugins to work. captcha.plugins.service_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 36e2bd5729..f0ae6c8ab4 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -1,6 +1,6 @@ services: console.command_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_cron.yml b/phpBB/config/default/container/services_cron.yml index cc3c70c542..c5b88df181 100644 --- a/phpBB/config/default/container/services_cron.yml +++ b/phpBB/config/default/container/services_cron.yml @@ -15,7 +15,7 @@ services: # ----- Cron tasks ----- cron.task_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_migrator.yml b/phpBB/config/default/container/services_migrator.yml index 8c81aec8b3..01bd7d3a11 100644 --- a/phpBB/config/default/container/services_migrator.yml +++ b/phpBB/config/default/container/services_migrator.yml @@ -19,7 +19,7 @@ services: # ----- Migrator's tools ----- migrator.tool_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_mimetype_guesser.yml b/phpBB/config/default/container/services_mimetype_guesser.yml index f22a41613a..2e89ed3c1f 100644 --- a/phpBB/config/default/container/services_mimetype_guesser.yml +++ b/phpBB/config/default/container/services_mimetype_guesser.yml @@ -1,6 +1,6 @@ services: mimetype.guesser_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index 896b93f75b..c3bbcddfa6 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -20,7 +20,7 @@ services: # ----- Notification's types ----- # Scope MUST be prototype for all the plugins to work. notification.type_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: @@ -351,11 +351,11 @@ services: - %tables.user_notifications% tags: - { name: notification.type } - + # ----- Notification's methods ----- # Scope MUST be prototype for all the plugins to work. notification.method_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_password.yml b/phpBB/config/default/container/services_password.yml index 22530f33d6..cb45ec3d42 100644 --- a/phpBB/config/default/container/services_password.yml +++ b/phpBB/config/default/container/services_password.yml @@ -18,7 +18,7 @@ services: # ----- Password's drivers ----- passwords.driver_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_profilefield.yml b/phpBB/config/default/container/services_profilefield.yml index 9bbc0be4c9..5ccfef9148 100644 --- a/phpBB/config/default/container/services_profilefield.yml +++ b/phpBB/config/default/container/services_profilefield.yml @@ -21,7 +21,7 @@ services: # ----- Profile fields types ----- profilefields.type_collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index 2c5b5a8398..2799892376 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -25,7 +25,7 @@ services: - @filesystem template.twig.extensions.collection: - class: phpbb\di\service_collection\service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 79feda88f1..146e116cfd 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -27,7 +27,7 @@ class acp_profile var $lang_defs; /** - * @var \phpbb\di\service_collection\service_collection + * @var \phpbb\di\service_collection */ protected $type_collection; diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php index 612446a2a8..be0fbf5831 100644 --- a/phpBB/phpbb/auth/provider/oauth/oauth.php +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -72,7 +72,7 @@ class oauth extends \phpbb\auth\provider\base /** * All OAuth service providers * - * @var \phpbb\di\service_collection\service_collection Contains \phpbb\auth\provider\oauth\service_interface + * @var \phpbb\di\service_collection Contains \phpbb\auth\provider\oauth\service_interface */ protected $service_providers; @@ -121,13 +121,13 @@ class oauth extends \phpbb\auth\provider\base * @param \phpbb\user $user * @param string $auth_provider_oauth_token_storage_table * @param string $auth_provider_oauth_token_account_assoc - * @param \phpbb\di\service_collection\service_collection $service_providers Contains \phpbb\auth\provider\oauth\service_interface + * @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 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_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_root_path, $php_ext) { $this->db = $db; $this->config = $config; diff --git a/phpBB/phpbb/auth/provider_collection.php b/phpBB/phpbb/auth/provider_collection.php index 71da30e4c4..8e7e9e2cc1 100644 --- a/phpBB/phpbb/auth/provider_collection.php +++ b/phpBB/phpbb/auth/provider_collection.php @@ -18,7 +18,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** * Collection of auth providers to be configured at container compile time. */ -class provider_collection extends \phpbb\di\service_collection\service_collection +class provider_collection extends \phpbb\di\service_collection { /** @var \phpbb\config\config phpBB Config */ protected $config; diff --git a/phpBB/phpbb/captcha/factory.php b/phpBB/phpbb/captcha/factory.php index 1357e919bb..dd44aca8bb 100644 --- a/phpBB/phpbb/captcha/factory.php +++ b/phpBB/phpbb/captcha/factory.php @@ -21,7 +21,7 @@ class factory private $container; /** - * @var \phpbb\di\service_collection\service_collection + * @var \phpbb\di\service_collection */ private $plugins; @@ -29,9 +29,9 @@ class factory * Constructor * * @param \Symfony\Component\DependencyInjection\ContainerInterface $container - * @param \phpbb\di\service_collection\service_collection $plugins + * @param \phpbb\di\service_collection $plugins */ - public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, \phpbb\di\service_collection\service_collection $plugins) + public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, \phpbb\di\service_collection $plugins) { $this->container = $container; $this->plugins = $plugins; diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php index fa847cd64d..bc4897af18 100644 --- a/phpBB/phpbb/console/application.php +++ b/phpBB/phpbb/console/application.php @@ -89,9 +89,9 @@ class application extends \Symfony\Component\Console\Application /** * Register a set of commands from the container * - * @param \phpbb\di\service_collection\service_collection $command_collection The console service collection + * @param \phpbb\di\service_collection $command_collection The console service collection */ - public function register_container_commands(\phpbb\di\service_collection\service_collection $command_collection) + public function register_container_commands(\phpbb\di\service_collection $command_collection) { foreach ($command_collection as $service_command) { diff --git a/phpBB/phpbb/di/service_collection/ordered_service_collection.php b/phpBB/phpbb/di/ordered_service_collection.php similarity index 98% rename from phpBB/phpbb/di/service_collection/ordered_service_collection.php rename to phpBB/phpbb/di/ordered_service_collection.php index 8d56434504..46f397a004 100644 --- a/phpBB/phpbb/di/service_collection/ordered_service_collection.php +++ b/phpBB/phpbb/di/ordered_service_collection.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\di\service_collection; +namespace phpbb\di; use Symfony\Component\DependencyInjection\ContainerInterface; diff --git a/phpBB/phpbb/di/service_collection/service_collection.php b/phpBB/phpbb/di/service_collection.php similarity index 97% rename from phpBB/phpbb/di/service_collection/service_collection.php rename to phpBB/phpbb/di/service_collection.php index 8085128fed..82ca9bf679 100644 --- a/phpBB/phpbb/di/service_collection/service_collection.php +++ b/phpBB/phpbb/di/service_collection.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\di\service_collection; +namespace phpbb\di; use Symfony\Component\DependencyInjection\ContainerInterface; diff --git a/phpBB/phpbb/di/service_collection/service_collection_iterator.php b/phpBB/phpbb/di/service_collection_iterator.php similarity index 81% rename from phpBB/phpbb/di/service_collection/service_collection_iterator.php rename to phpBB/phpbb/di/service_collection_iterator.php index 76e22b048e..0d031ab52d 100644 --- a/phpBB/phpbb/di/service_collection/service_collection_iterator.php +++ b/phpBB/phpbb/di/service_collection_iterator.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\di\service_collection; +namespace phpbb\di; /** * Iterator which loads the services when they are requested @@ -19,14 +19,14 @@ namespace phpbb\di\service_collection; class service_collection_iterator extends \ArrayIterator { /** - * @var \phpbb\di\service_collection\service_collection + * @var \phpbb\di\service_collection */ protected $collection; /** * Construct an ArrayIterator for service_collection * - * @param \phpbb\di\service_collection\service_collection $collection The collection to iterate over + * @param \phpbb\di\service_collection $collection The collection to iterate over * @param int $flags Flags to control the behaviour of the ArrayObject object. * @see ArrayObject::setFlags() */ diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 8974dc36d1..aa9147ecf4 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -89,7 +89,7 @@ class manager /** * Fill algorithm type map * - * @param \phpbb\di\service_collection\service_collection $hashing_algorithms + * @param \phpbb\di\service_collection $hashing_algorithms */ protected function fill_type_map($hashing_algorithms) { diff --git a/phpBB/phpbb/profilefields/manager.php b/phpBB/phpbb/profilefields/manager.php index 802629a10e..4ad3214ae4 100644 --- a/phpBB/phpbb/profilefields/manager.php +++ b/phpBB/phpbb/profilefields/manager.php @@ -50,7 +50,7 @@ class manager /** * Service Collection object - * @var \phpbb\di\service_collection\service_collection + * @var \phpbb\di\service_collection */ protected $type_collection; @@ -76,13 +76,13 @@ class manager * @param \phpbb\event\dispatcher_interface $dispatcher Event dispatcher object * @param \phpbb\request\request $request Request object * @param \phpbb\template\template $template Template object - * @param \phpbb\di\service_collection\service_collection $type_collection + * @param \phpbb\di\service_collection $type_collection * @param \phpbb\user $user User object * @param string $fields_table * @param string $fields_language_table * @param string $fields_data_table */ - public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\di\service_collection\service_collection $type_collection, \phpbb\user $user, $fields_table, $fields_language_table, $fields_data_table) + public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\di\service_collection $type_collection, \phpbb\user $user, $fields_table, $fields_language_table, $fields_data_table) { $this->auth = $auth; $this->db = $db; diff --git a/tests/di/ordered_service_collection_test.php b/tests/di/ordered_service_collection_test.php index 046cd8ccef..47e6d23744 100644 --- a/tests/di/ordered_service_collection_test.php +++ b/tests/di/ordered_service_collection_test.php @@ -14,7 +14,7 @@ class phpbb_ordered_service_collection_test extends \phpbb_test_case { /** - * @var \phpbb\di\service_collection\ordered_service_collection + * @var \phpbb\di\ordered_service_collection */ protected $service_collection; @@ -26,7 +26,7 @@ class phpbb_ordered_service_collection_test extends \phpbb_test_case $container->set('foobar', new StdClass); $container->set('barfoo', new StdClass); - $this->service_collection = new \phpbb\di\service_collection\ordered_service_collection($container); + $this->service_collection = new \phpbb\di\ordered_service_collection($container); $this->service_collection->add('foo', 7); $this->service_collection->add('bar', 3); $this->service_collection->add('barfoo', 5); diff --git a/tests/di/service_collection_test.php b/tests/di/service_collection_test.php index e78a5180b6..5b51254a4a 100644 --- a/tests/di/service_collection_test.php +++ b/tests/di/service_collection_test.php @@ -14,7 +14,7 @@ class phpbb_service_collection_test extends \phpbb_test_case { /** - * @var \phpbb\di\service_collection\service_collection + * @var \phpbb\di\service_collection */ protected $service_collection; @@ -24,7 +24,7 @@ class phpbb_service_collection_test extends \phpbb_test_case $container->set('foo', new StdClass); $container->set('bar', new StdClass); - $this->service_collection = new \phpbb\di\service_collection\service_collection($container); + $this->service_collection = new \phpbb\di\service_collection($container); $this->service_collection->add('foo'); $this->service_collection->add('bar'); diff --git a/tests/functions/user_delete_test.php b/tests/functions/user_delete_test.php index 011d251167..21561492fd 100644 --- a/tests/functions/user_delete_test.php +++ b/tests/functions/user_delete_test.php @@ -46,7 +46,7 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case $notification_manager = new phpbb_mock_notification_manager(); $provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config); $oauth_provider_google = new \phpbb\auth\provider\oauth\service\google($config, $request); - $oauth_provider_collection = new \phpbb\di\service_collection\service_collection($phpbb_container); + $oauth_provider_collection = new \phpbb\di\service_collection($phpbb_container); $oauth_provider_collection->offsetSet('auth.provider.oauth.service.google', $oauth_provider_google); $driver_helper = new \phpbb\passwords\driver\helper($config); diff --git a/tests/session/garbage_collection_test.php b/tests/session/garbage_collection_test.php index 5b337be44e..3fad81c68b 100644 --- a/tests/session/garbage_collection_test.php +++ b/tests/session/garbage_collection_test.php @@ -30,7 +30,7 @@ class phpbb_session_garbage_collection_test extends phpbb_session_test_case global $phpbb_container; - $plugins = new \phpbb\di\service_collection\service_collection($phpbb_container); + $plugins = new \phpbb\di\service_collection($phpbb_container); $plugins->add('core.captcha.plugins.nogd'); $phpbb_container->set( 'captcha.factory', From 353b3b4cfd7133ea0cef4a7fdb34d0451b16a0dd Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 27 Jun 2015 12:33:44 +0200 Subject: [PATCH 0419/1676] [ticket/13970] Save the value of the optional [code] parameter PHPBB3-13970 --- phpBB/phpbb/textformatter/s9e/factory.php | 2 +- tests/text_formatter/s9e/default_formatting_test.php | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index e07a1b52ca..7ad728e6cc 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -66,7 +66,7 @@ class factory implements \phpbb\textformatter\cache_interface protected $default_definitions = array( 'attachment' => '[ATTACHMENT index={NUMBER} filename={TEXT;useContent}]', 'b' => '[B]{TEXT}[/B]', - 'code' => '[CODE]{TEXT}[/CODE]', + 'code' => '[CODE lang={IDENTIFIER;optional}]{TEXT}[/CODE]', 'color' => '[COLOR={COLOR}]{TEXT}[/COLOR]', 'email' => '[EMAIL={EMAIL;useContent} subject={TEXT;optional;postFilter=rawurlencode} body={TEXT;optional;postFilter=rawurlencode}]{TEXT}[/EMAIL]', 'flash' => '[FLASH={NUMBER1},{NUMBER2} width={NUMBER1;postFilter=#flashwidth} height={NUMBER2;postFilter=#flashheight} url={URL;useContent} /]', diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 67921d5b1e..4829e9bbc8 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -15,6 +15,17 @@ require_once __DIR__ . '/../../../phpBB/includes/functions_content.php'; class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case { + public function test_bbcode_code_lang_is_saved() + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $parser = $container->get('text_formatter.parser'); + + $original = '[code]...[/code][code=php]...[/code]'; + $expected = '[code]...[/code][code=php]...[/code]'; + + $this->assertXmlStringEqualsXmlString($expected, $parser->parse($original)); + } + /** * @dataProvider get_default_formatting_tests */ From c80cf87b90eefab664ecf69f29796f9390a3ff17 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Sat, 27 Jun 2015 12:49:10 +0200 Subject: [PATCH 0420/1676] [ticket/13961] Allow the collection to be modified runtime PHPBB3-13961 --- phpBB/phpbb/di/ordered_service_collection.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/phpBB/phpbb/di/ordered_service_collection.php b/phpBB/phpbb/di/ordered_service_collection.php index 46f397a004..046012ae5b 100644 --- a/phpBB/phpbb/di/ordered_service_collection.php +++ b/phpBB/phpbb/di/ordered_service_collection.php @@ -90,14 +90,9 @@ class ordered_service_collection extends service_collection */ public function add($service_id, $order = 0) { - if ($this->is_ordered) - { - return; - } - $order = (int) $order; - $this->service_ids[$order][] = $service_id; + $this->is_ordered = false; } protected function sort_services() @@ -107,6 +102,7 @@ class ordered_service_collection extends service_collection return; } + $this->exchangeArray(array()); ksort($this->service_ids); foreach ($this->service_ids as $service_order_group) { From 615ab099e228f2d7a35a76557095a65321425963 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 29 May 2015 19:33:17 +0200 Subject: [PATCH 0421/1676] [ticket/13891] Added reparser:list and reparser:reparse to CLI PHPBB3-13891 --- .../default/container/services_console.yml | 16 +++ phpBB/language/en/cli.php | 5 + .../console/command/reparser/list_all.php | 70 ++++++++++++ .../console/command/reparser/reparse.php | 106 ++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 phpBB/phpbb/console/command/reparser/list_all.php create mode 100644 phpBB/phpbb/console/command/reparser/reparse.php diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index f0ae6c8ab4..98a26b10e8 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -140,3 +140,19 @@ services: - @dbal.conn tags: - { name: console.command } + + console.command.reparser.list: + class: phpbb\console\command\reparser\list_all + arguments: + - @user + - @service_container + tags: + - { name: console.command } + + console.command.reparser.reparse: + class: phpbb\console\command\reparser\reparse + arguments: + - @user + - @text_reparser_collection + tags: + - { name: console.command } diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 0e7dc39b95..bbcc736143 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -61,6 +61,9 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_OPTION_SAFE_MODE' => 'Run in Safe Mode (without extensions).', 'CLI_DESCRIPTION_OPTION_SHELL' => 'Launch the shell.', 'CLI_DESCRIPTION_PURGE_EXTENSION' => 'Purges the specified extension.', + 'CLI_DESCRIPTION_REPARSER_LIST' => 'Lists the types of text that can be reparsed.', + 'CLI_DESCRIPTION_REPARSER_REPARSE' => 'Reparses stored text with the current text_formatter services.', + 'CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1' => 'Type of text to reparse. Leave blank to reparse everything.', 'CLI_DESCRIPTION_RECALCULATE_EMAIL_HASH' => 'Recalculates the user_email_hash column of the users table.', 'CLI_DESCRIPTION_SET_ATOMIC_CONFIG' => 'Sets a configuration option’s value only if the old matches the current value', 'CLI_DESCRIPTION_SET_CONFIG' => 'Sets a configuration option’s value', @@ -78,4 +81,6 @@ $lang = array_merge($lang, array( 'CLI_EXTENSIONS_ENABLED' => 'Enabled', 'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.', + + 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s with range %2$d..%3$d', )); diff --git a/phpBB/phpbb/console/command/reparser/list_all.php b/phpBB/phpbb/console/command/reparser/list_all.php new file mode 100644 index 0000000000..10db568386 --- /dev/null +++ b/phpBB/phpbb/console/command/reparser/list_all.php @@ -0,0 +1,70 @@ + +* @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\console\command\reparser; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class list_all extends \phpbb\console\command\command +{ + /** + * @var string[] Names of the reparser services + */ + protected $reparser_names; + + /** + * Constructor + * + * @param \phpbb\user $user + * @param ContainerBuilder $container Container used to locate the reparsers + */ + public function __construct(\phpbb\user $user, ContainerBuilder $container) + { + parent::__construct($user); + $this->reparser_names = array(); + foreach (array_keys($container->findTaggedServiceIds('text_reparser.plugin')) as $name) + { + // Store the names without the "text_reparser." prefix + $this->reparser_names[] = str_replace('text_reparser.', '', $name); + } + } + + /** + * Sets the command name and description + * + * @return null + */ + protected function configure() + { + $this + ->setName('reparser:list') + ->setDescription($this->user->lang('CLI_DESCRIPTION_REPARSER_LIST')) + ; + } + + /** + * Executes the command reparser:reparse + * + * @param InputInterface $input + * @param OutputInterface $output + * @return integer + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln('' . implode(', ', $this->reparser_names) . ''); + + return 0; + } +} diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php new file mode 100644 index 0000000000..f2bbe9c7d1 --- /dev/null +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -0,0 +1,106 @@ + +* @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\console\command\reparser; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Output\OutputInterface; + +class reparse extends \phpbb\console\command\command +{ + /** + * @var \phpbb\textreparser\reparser_collection + */ + protected $reparser_collection; + + /** + * Constructor + * + * @param \phpbb\user $user + * @param \phpbb\textreparser\reparser_collection $reparser_collection + */ + public function __construct(\phpbb\user $user, \phpbb\textreparser\reparser_collection $reparser_collection) + { + require_once __DIR__ . '/../../../../includes/functions_content.php'; + + $this->reparser_collection = $reparser_collection; + parent::__construct($user); + } + + /** + * Sets the command name and description + * + * @return null + */ + protected function configure() + { + $this + ->setName('reparser:reparse') + ->setDescription($this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE')) + ->addArgument('reparser-name', InputArgument::OPTIONAL, $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1')) + ; + } + + /** + * Executes the command reparser:reparse + * + * @param InputInterface $input + * @param OutputInterface $output + * @return integer + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $name = $input->getArgument('reparser-name'); + if (isset($name)) + { + // Allow "post_text" to be an alias for "text_reparser.post_text" + if (!isset($this->reparser_collection[$name])) + { + $name = 'text_reparser.' . $name; + } + $this->reparse($output, $name); + } + else + { + foreach ($this->reparser_collection as $name => $service) + { + $this->reparse($output, $name); + } + } + + return 0; + } + + /** + * Reparse all text handled by given reparser + * + * @param OutputInterface $output + * @param string $name Reparser name + * @return null + */ + protected function reparse(OutputInterface $output, $name) + { + $reparser = $this->reparser_collection[$name]; + $id = $reparser->get_max_id(); + $n = 100; + while ($id > 0) + { + $start = max(0, $id + 1 - $n); + $end = $id; + $output->writeln('' . $this->user->lang('CLI_REPARSER_REPARSE_REPARSING', $name, $start, $end) . ''); + $reparser->reparse_range($start, $end); + $id -= $n; + } + } +} From 119f90e36301463ffd01005a9390d3346be7774f Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 29 Jun 2015 22:15:08 +0200 Subject: [PATCH 0422/1676] [ticket/13891] Replaced ContainerBuilder with service_collection PHPBB3-13891 --- .../default/container/services_console.yml | 2 +- .../phpbb/console/command/reparser/list_all.php | 7 +++---- phpBB/phpbb/console/command/reparser/reparse.php | 16 ++++++++-------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 98a26b10e8..f39218ed9c 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -145,7 +145,7 @@ services: class: phpbb\console\command\reparser\list_all arguments: - @user - - @service_container + - @text_reparser_collection tags: - { name: console.command } diff --git a/phpBB/phpbb/console/command/reparser/list_all.php b/phpBB/phpbb/console/command/reparser/list_all.php index 10db568386..1589836ddd 100644 --- a/phpBB/phpbb/console/command/reparser/list_all.php +++ b/phpBB/phpbb/console/command/reparser/list_all.php @@ -15,7 +15,6 @@ namespace phpbb\console\command\reparser; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; class list_all extends \phpbb\console\command\command { @@ -28,13 +27,13 @@ class list_all extends \phpbb\console\command\command * Constructor * * @param \phpbb\user $user - * @param ContainerBuilder $container Container used to locate the reparsers + * @param \phpbb\di\service_collection $reparsers */ - public function __construct(\phpbb\user $user, ContainerBuilder $container) + public function __construct(\phpbb\user $user, \phpbb\di\service_collection $reparsers) { parent::__construct($user); $this->reparser_names = array(); - foreach (array_keys($container->findTaggedServiceIds('text_reparser.plugin')) as $name) + foreach ($reparsers as $name => $reparser) { // Store the names without the "text_reparser." prefix $this->reparser_names[] = str_replace('text_reparser.', '', $name); diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index f2bbe9c7d1..8cefee837f 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -20,21 +20,21 @@ use Symfony\Component\Console\Output\OutputInterface; class reparse extends \phpbb\console\command\command { /** - * @var \phpbb\textreparser\reparser_collection + * @var \phpbb\di\service_collection */ - protected $reparser_collection; + protected $reparsers; /** * Constructor * * @param \phpbb\user $user - * @param \phpbb\textreparser\reparser_collection $reparser_collection + * @param \phpbb\di\service_collection $reparser_collection */ - public function __construct(\phpbb\user $user, \phpbb\textreparser\reparser_collection $reparser_collection) + public function __construct(\phpbb\user $user, \phpbb\di\service_collection $reparsers) { require_once __DIR__ . '/../../../../includes/functions_content.php'; - $this->reparser_collection = $reparser_collection; + $this->reparsers = $reparsers; parent::__construct($user); } @@ -65,7 +65,7 @@ class reparse extends \phpbb\console\command\command if (isset($name)) { // Allow "post_text" to be an alias for "text_reparser.post_text" - if (!isset($this->reparser_collection[$name])) + if (!isset($this->reparsers[$name])) { $name = 'text_reparser.' . $name; } @@ -73,7 +73,7 @@ class reparse extends \phpbb\console\command\command } else { - foreach ($this->reparser_collection as $name => $service) + foreach ($this->reparsers as $name => $service) { $this->reparse($output, $name); } @@ -91,7 +91,7 @@ class reparse extends \phpbb\console\command\command */ protected function reparse(OutputInterface $output, $name) { - $reparser = $this->reparser_collection[$name]; + $reparser = $this->reparsers[$name]; $id = $reparser->get_max_id(); $n = 100; while ($id > 0) From fadb192c570db25fe4b36b1b3803fb923e6f9d4e Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 29 Jun 2015 23:05:52 +0200 Subject: [PATCH 0423/1676] [ticket/13891] Added command-line options PHPBB3-13891 --- phpBB/language/en/cli.php | 3 ++ .../console/command/reparser/reparse.php | 43 +++++++++++++++---- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index bbcc736143..c301f98261 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -64,6 +64,9 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_REPARSER_LIST' => 'Lists the types of text that can be reparsed.', 'CLI_DESCRIPTION_REPARSER_REPARSE' => 'Reparses stored text with the current text_formatter services.', 'CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1' => 'Type of text to reparse. Leave blank to reparse everything.', + 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MIN' => 'Lowest record ID to process', + 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MAX' => 'Highest record ID to process', + 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_SIZE' => 'Approximate number of records to process at a time', 'CLI_DESCRIPTION_RECALCULATE_EMAIL_HASH' => 'Recalculates the user_email_hash column of the users table.', 'CLI_DESCRIPTION_SET_ATOMIC_CONFIG' => 'Sets a configuration option’s value only if the old matches the current value', 'CLI_DESCRIPTION_SET_CONFIG' => 'Sets a configuration option’s value', diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 8cefee837f..5e1993d44c 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -15,6 +15,7 @@ namespace phpbb\console\command\reparser; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class reparse extends \phpbb\console\command\command @@ -49,6 +50,26 @@ class reparse extends \phpbb\console\command\command ->setName('reparser:reparse') ->setDescription($this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE')) ->addArgument('reparser-name', InputArgument::OPTIONAL, $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1')) + ->addOption( + 'range-min', + null, + InputOption::VALUE_REQUIRED, + $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MIN'), + 0 + ) + ->addOption( + 'range-max', + null, + InputOption::VALUE_REQUIRED, + $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MAX') + ) + ->addOption( + 'range-size', + null, + InputOption::VALUE_REQUIRED, + $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_SIZE'), + 100 + ); ; } @@ -69,13 +90,13 @@ class reparse extends \phpbb\console\command\command { $name = 'text_reparser.' . $name; } - $this->reparse($output, $name); + $this->reparse($input, $output, $name); } else { foreach ($this->reparsers as $name => $service) { - $this->reparse($output, $name); + $this->reparse($input, $output, $name); } } @@ -83,24 +104,28 @@ class reparse extends \phpbb\console\command\command } /** - * Reparse all text handled by given reparser + * Reparse all text handled by given reparser within given range * + * @param InputInterface $input * @param OutputInterface $output * @param string $name Reparser name * @return null */ - protected function reparse(OutputInterface $output, $name) + protected function reparse(InputInterface $input, OutputInterface $output, $name) { $reparser = $this->reparsers[$name]; - $id = $reparser->get_max_id(); - $n = 100; - while ($id > 0) + + // Start at range-max if specified or at the highest ID otherwise + $id = (is_null($input->getOption('range-max'))) ? $reparser->get_max_id() : $input->getOption('range-max'); + $min = $input->getOption('range-min'); + $size = $input->getOption('range-size'); + while ($id > $min) { - $start = max(0, $id + 1 - $n); + $start = max($min, $id + 1 - $size); $end = $id; $output->writeln('' . $this->user->lang('CLI_REPARSER_REPARSE_REPARSING', $name, $start, $end) . ''); $reparser->reparse_range($start, $end); - $id -= $n; + $id -= $size; } } } From 6de5e5cc36d4b934cfa4043faf12adb279f8a2c6 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 30 Jun 2015 00:28:02 +0200 Subject: [PATCH 0424/1676] [ticket/13891] Added a progress bar PHPBB3-13891 --- phpBB/language/en/cli.php | 2 +- .../console/command/reparser/reparse.php | 26 ++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index c301f98261..d1f229272c 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -85,5 +85,5 @@ $lang = array_merge($lang, array( 'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.', - 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s with range %2$d..%3$d', + 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s from %2$d to %3$d', )); diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 5e1993d44c..a2b8b71818 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -13,6 +13,7 @@ namespace phpbb\console\command\reparser; +use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; @@ -116,16 +117,29 @@ class reparse extends \phpbb\console\command\command $reparser = $this->reparsers[$name]; // Start at range-max if specified or at the highest ID otherwise - $id = (is_null($input->getOption('range-max'))) ? $reparser->get_max_id() : $input->getOption('range-max'); + $max = (is_null($input->getOption('range-max'))) ? $reparser->get_max_id() : $input->getOption('range-max'); $min = $input->getOption('range-min'); $size = $input->getOption('range-size'); - while ($id > $min) + + $output->writeLn($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $min, $max) . ''); + + $progress = new ProgressBar($output, $max - $min); + $progress->start(); + + // Start from $max and decrement $current by $size until we reach $min + $current = $max; + while ($current > $min) { - $start = max($min, $id + 1 - $size); - $end = $id; - $output->writeln('' . $this->user->lang('CLI_REPARSER_REPARSE_REPARSING', $name, $start, $end) . ''); + $start = max($min, $current + 1 - $size); + $end = $current; $reparser->reparse_range($start, $end); - $id -= $size; + + $current = max($min, $start - 1); + $progress->setProgress($max - $current); } + $progress->finish(); + + // The progress bar does not seem to end with a newline so we add one manually + $output->writeLn(''); } } From c7f10ec4d455877b8df96c00f28ada0bcb84f17b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 30 Jun 2015 09:55:23 +0200 Subject: [PATCH 0425/1676] [ticket/13891] Updated range description Does not count #0 as a potential record PHPBB3-13891 --- phpBB/language/en/cli.php | 2 +- phpBB/phpbb/console/command/reparser/reparse.php | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index d1f229272c..b8e7d25f60 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -85,5 +85,5 @@ $lang = array_merge($lang, array( 'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.', - 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s from %2$d to %3$d', + 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s (range %2$d..%3$d)', )); diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index a2b8b71818..e922ea90e3 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -56,7 +56,7 @@ class reparse extends \phpbb\console\command\command null, InputOption::VALUE_REQUIRED, $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MIN'), - 0 + 1 ) ->addOption( 'range-max', @@ -123,19 +123,19 @@ class reparse extends \phpbb\console\command\command $output->writeLn($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $min, $max) . ''); - $progress = new ProgressBar($output, $max - $min); + $progress = new ProgressBar($output, $max + 1 - $min); $progress->start(); // Start from $max and decrement $current by $size until we reach $min $current = $max; - while ($current > $min) + while ($current >= $min) { $start = max($min, $current + 1 - $size); - $end = $current; + $end = max($min, $current); $reparser->reparse_range($start, $end); - $current = max($min, $start - 1); - $progress->setProgress($max - $current); + $current = $start - 1; + $progress->setProgress($max + 1 - $start); } $progress->finish(); From 6b68544483fb8674949e1d3a69eae997cef6afbe Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 1 Jul 2015 15:49:32 +0200 Subject: [PATCH 0426/1676] [ticket/13891] Use the SymfonyStyle in the reparse command PHPBB3-13891 --- phpBB/language/en/cli.php | 1 + .../console/command/reparser/reparse.php | 39 ++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index b8e7d25f60..8c0d6bf6c3 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -86,4 +86,5 @@ $lang = array_merge($lang, array( 'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.', 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s (range %2$d..%3$d)', + 'CLI_REPARSER_REPARSE_SUCCESS' => 'Reparsing ended with success', )); diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index e922ea90e3..2220e53193 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -13,11 +13,11 @@ namespace phpbb\console\command\reparser; -use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class reparse extends \phpbb\console\command\command { @@ -26,6 +26,11 @@ class reparse extends \phpbb\console\command\command */ protected $reparsers; + /** + * @var SymfonyStyle + */ + protected $io; + /** * Constructor * @@ -83,6 +88,8 @@ class reparse extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { + $this->io = new SymfonyStyle($input, $output); + $name = $input->getArgument('reparser-name'); if (isset($name)) { @@ -101,6 +108,8 @@ class reparse extends \phpbb\console\command\command } } + $this->io->success($this->user->lang('CLI_REPARSER_REPARSE_SUCCESS')); + return 0; } @@ -121,9 +130,28 @@ class reparse extends \phpbb\console\command\command $min = $input->getOption('range-min'); $size = $input->getOption('range-size'); - $output->writeLn($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $min, $max) . ''); + if ($max === 0) + { + return; + } + + $this->io->section($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $min, $max)); + $this->io->newLine(2); + + $progress = $this->io->createProgressBar($max); + $progress->setFormat( + " %current:s%/%max:s% %bar% %percent:3s%%\n" . + " %message%\n"); + $progress->setBarWidth(60); + $progress->setMessage(''); + + if (!defined('PHP_WINDOWS_VERSION_BUILD')) + { + $progress->setEmptyBarCharacter('░'); // light shade character \u2591 + $progress->setProgressCharacter(''); + $progress->setBarCharacter('▓'); // dark shade character \u2593 + } - $progress = new ProgressBar($output, $max + 1 - $min); $progress->start(); // Start from $max and decrement $current by $size until we reach $min @@ -132,6 +160,8 @@ class reparse extends \phpbb\console\command\command { $start = max($min, $current + 1 - $size); $end = max($min, $current); + + $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $start, $end)); $reparser->reparse_range($start, $end); $current = $start - 1; @@ -139,7 +169,6 @@ class reparse extends \phpbb\console\command\command } $progress->finish(); - // The progress bar does not seem to end with a newline so we add one manually - $output->writeLn(''); + $this->io->newLine(2); } } From dd131d74390a8c8766c28734efebede681e3b794 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 2 Jul 2015 12:22:51 +0200 Subject: [PATCH 0427/1676] [ticket/13891] Added elapsed/estimated time and memory to the progress bar Also fixed some extra whitespace. PHPBB3-13891 --- phpBB/phpbb/console/command/reparser/reparse.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 2220e53193..3aac0e3e93 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -27,8 +27,8 @@ class reparse extends \phpbb\console\command\command protected $reparsers; /** - * @var SymfonyStyle - */ + * @var SymfonyStyle + */ protected $io; /** @@ -141,7 +141,7 @@ class reparse extends \phpbb\console\command\command $progress = $this->io->createProgressBar($max); $progress->setFormat( " %current:s%/%max:s% %bar% %percent:3s%%\n" . - " %message%\n"); + " %message% %elapsed:6s%/%estimated:-6s% %memory:6s%\n"); $progress->setBarWidth(60); $progress->setMessage(''); From 5970d0360c5b60a5af7bbaef37ffb8bb9932f8a8 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 2 Jul 2015 13:40:02 +0200 Subject: [PATCH 0428/1676] [ticket/13891] Handle verbosity PHPBB3-13891 --- phpBB/language/en/cli.php | 5 ++-- .../console/command/reparser/reparse.php | 26 ++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 8c0d6bf6c3..9eca60fb68 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -85,6 +85,7 @@ $lang = array_merge($lang, array( 'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.', - 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s (range %2$d..%3$d)', - 'CLI_REPARSER_REPARSE_SUCCESS' => 'Reparsing ended with success', + 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s (range %2$d..%3$d)', + 'CLI_REPARSER_REPARSE_REPARSING_START' => 'Reparsing %s...', + 'CLI_REPARSER_REPARSE_SUCCESS' => 'Reparsing ended with success', )); diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 3aac0e3e93..c261507a57 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -136,14 +136,28 @@ class reparse extends \phpbb\console\command\command } $this->io->section($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $min, $max)); - $this->io->newLine(2); $progress = $this->io->createProgressBar($max); - $progress->setFormat( - " %current:s%/%max:s% %bar% %percent:3s%%\n" . - " %message% %elapsed:6s%/%estimated:-6s% %memory:6s%\n"); - $progress->setBarWidth(60); - $progress->setMessage(''); + if ($output->getVerbosity() === OutputInterface::VERBOSITY_VERBOSE) + { + $progress->setFormat('[%percent:3s%%] %message%'); + $progress->setOverwrite(false); + } + elseif ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) + { + $progress->setFormat('[%current:s%/%max:s%][%elapsed%/%estimated%][%memory%] %message%'); + $progress->setOverwrite(false); + } + else + { + $this->io->newLine(2); + $progress->setFormat( + " %current:s%/%max:s% %bar% %percent:3s%%\n" . + " %message% %elapsed:6s%/%estimated:-6s% %memory:6s%\n"); + $progress->setBarWidth(60); + } + + $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING_START', str_replace('text_reparser.', '', $name))); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { From b251d9831476754d6db4f0314cbc7607c57d7128 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 2 Jul 2015 15:26:49 +0200 Subject: [PATCH 0429/1676] [ticket/13891] Fix CS PHPBB3-13891 --- phpBB/phpbb/console/command/reparser/reparse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index c261507a57..52075dd0ac 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -143,7 +143,7 @@ class reparse extends \phpbb\console\command\command $progress->setFormat('[%percent:3s%%] %message%'); $progress->setOverwrite(false); } - elseif ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) + else if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) { $progress->setFormat('[%current:s%/%max:s%][%elapsed%/%estimated%][%memory%] %message%'); $progress->setOverwrite(false); From 108b9833a10ff657d5d55ba1f976ad7314ecbfa3 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 2 Jul 2015 16:10:55 +0200 Subject: [PATCH 0430/1676] [ticket/13961] Define behaviour when the array is modified in a loop PHPBB3-13961 --- phpBB/phpbb/di/service_collection_iterator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/di/service_collection_iterator.php b/phpBB/phpbb/di/service_collection_iterator.php index 0d031ab52d..31bc156e99 100644 --- a/phpBB/phpbb/di/service_collection_iterator.php +++ b/phpBB/phpbb/di/service_collection_iterator.php @@ -32,7 +32,7 @@ class service_collection_iterator extends \ArrayIterator */ public function __construct(service_collection $collection, $flags = 0) { - parent::__construct($collection, $flags); + parent::__construct($collection->getArrayCopy(), $flags); $this->collection = $collection; } From 57a07f4ff71d1513d1891ad8cca6c29c40dfa6b7 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 6 Jul 2015 01:15:18 +0200 Subject: [PATCH 0431/1676] [ticket/13985] Updated s9e\TextFormatter PHPBB3-13985 --- phpBB/composer.lock | 8 ++++---- tests/text_processing/tickets_data/PHPBB3-10989.html | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 27dbc48321..cff4bd6289 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -220,12 +220,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "85ac4557e7fc504e74ec0a672680af8481fe329c" + "reference": "326a5a0bbaee59a3d5542fc8e38fe41971931cce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/85ac4557e7fc504e74ec0a672680af8481fe329c", - "reference": "85ac4557e7fc504e74ec0a672680af8481fe329c", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/326a5a0bbaee59a3d5542fc8e38fe41971931cce", + "reference": "326a5a0bbaee59a3d5542fc8e38fe41971931cce", "shasum": "" }, "require": { @@ -270,7 +270,7 @@ "parser", "shortcodes" ], - "time": "2015-06-13 12:25:49" + "time": "2015-07-05 23:13:46" }, { "name": "symfony/config", diff --git a/tests/text_processing/tickets_data/PHPBB3-10989.html b/tests/text_processing/tickets_data/PHPBB3-10989.html index f003ad3dfa..cd24df60e5 100644 --- a/tests/text_processing/tickets_data/PHPBB3-10989.html +++ b/tests/text_processing/tickets_data/PHPBB3-10989.html @@ -1,6 +1,6 @@
            Lorem wrote:[quote="Lorem"
            Suspendisse iaculis porta tempor. Nulla.
            Nullam a tortor sit amet.
            - Proin ac mi eget magna. + Proin ac mi eget magna.
            Lorem wrote:Quisque fermentum tortor quis odio scelerisque consequat fermentum urna gravida. In semper vehicula condimentum. Donec suscipit ante imperdiet augue rhoncus.
            From a44711e57478c6f9d1fa38582deae72cad240560 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 6 Jul 2015 19:17:40 +0200 Subject: [PATCH 0432/1676] [ticket/13990] Reparse markup inside of forum rules/description PHPBB3-13990 --- phpBB/phpbb/textreparser/base.php | 25 +++++--- .../plugins/forum_description.php | 1 + .../textreparser/plugins/forum_rules.php | 1 + .../plugins/group_description.php | 1 + .../textreparser/plugins/poll_option.php | 2 +- .../phpbb/textreparser/plugins/poll_title.php | 2 +- .../text_reparser/plugins/fixtures/forums.xml | 22 +++++++ .../text_reparser/plugins/fixtures/groups.xml | 8 +-- .../plugins/fixtures/poll_options.xml | 60 +++++++++++++++++++ .../text_reparser/plugins/fixtures/polls.xml | 40 +++++++++++-- .../plugins/poll_option_test.php | 17 +++++- 11 files changed, 160 insertions(+), 19 deletions(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 87a4268d0d..ed6c2376c7 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -47,11 +47,22 @@ abstract class base implements reparser_interface { if (!isset($record['enable_bbcode'], $record['enable_smilies'], $record['enable_magic_url'])) { - $record += array( - 'enable_bbcode' => $this->guess_bbcodes($record), - 'enable_smilies' => $this->guess_smilies($record), - 'enable_magic_url' => $this->guess_magic_url($record), - ); + if (isset($record['options'])) + { + $record += array( + 'enable_bbcode' => (bool) ($record['options'] & OPTION_FLAG_BBCODE), + 'enable_smilies' => (bool) ($record['options'] & OPTION_FLAG_SMILIES), + 'enable_magic_url' => (bool) ($record['options'] & OPTION_FLAG_LINKS), + ); + } + else + { + $record += array( + 'enable_bbcode' => $this->guess_bbcodes($record), + 'enable_smilies' => $this->guess_smilies($record), + 'enable_magic_url' => $this->guess_magic_url($record), + ); + } } // Those BBCodes are disabled based on context and user permissions and that value is never @@ -92,7 +103,7 @@ abstract class base implements reparser_interface } } - if (substr($record['text'], 0, 2) == '[/url] @@ -124,7 +135,7 @@ abstract class base implements reparser_interface } } - if (substr($record['text'], 0, 2) == '\\[/\\w+\\])', $match); diff --git a/phpBB/phpbb/textreparser/plugins/forum_description.php b/phpBB/phpbb/textreparser/plugins/forum_description.php index 7798e4b20b..0302dc3082 100644 --- a/phpBB/phpbb/textreparser/plugins/forum_description.php +++ b/phpBB/phpbb/textreparser/plugins/forum_description.php @@ -24,6 +24,7 @@ class forum_description extends \phpbb\textreparser\row_based_plugin 'id' => 'forum_id', 'text' => 'forum_desc', 'bbcode_uid' => 'forum_desc_uid', + 'options' => 'forum_desc_options', ); } diff --git a/phpBB/phpbb/textreparser/plugins/forum_rules.php b/phpBB/phpbb/textreparser/plugins/forum_rules.php index 57c666a556..ce550225f2 100644 --- a/phpBB/phpbb/textreparser/plugins/forum_rules.php +++ b/phpBB/phpbb/textreparser/plugins/forum_rules.php @@ -24,6 +24,7 @@ class forum_rules extends \phpbb\textreparser\row_based_plugin 'id' => 'forum_id', 'text' => 'forum_rules', 'bbcode_uid' => 'forum_rules_uid', + 'options' => 'forum_rules_options', ); } diff --git a/phpBB/phpbb/textreparser/plugins/group_description.php b/phpBB/phpbb/textreparser/plugins/group_description.php index ddd0e1d1c5..3346ccf25e 100644 --- a/phpBB/phpbb/textreparser/plugins/group_description.php +++ b/phpBB/phpbb/textreparser/plugins/group_description.php @@ -24,6 +24,7 @@ class group_description extends \phpbb\textreparser\row_based_plugin 'id' => 'group_id', 'text' => 'group_desc', 'bbcode_uid' => 'group_desc_uid', + 'options' => 'group_desc_options', ); } diff --git a/phpBB/phpbb/textreparser/plugins/poll_option.php b/phpBB/phpbb/textreparser/plugins/poll_option.php index 7b803146c4..44cacfae62 100644 --- a/phpBB/phpbb/textreparser/plugins/poll_option.php +++ b/phpBB/phpbb/textreparser/plugins/poll_option.php @@ -48,7 +48,7 @@ class poll_option extends \phpbb\textreparser\base */ protected function get_records_by_range($min_id, $max_id) { - $sql = 'SELECT o.topic_id, o.poll_option_id, o.poll_option_text AS text, p.bbcode_uid + $sql = 'SELECT o.topic_id, o.poll_option_id, o.poll_option_text AS text, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.bbcode_uid FROM ' . POLL_OPTIONS_TABLE . ' o, ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p WHERE o.topic_id BETWEEN ' . $min_id . ' AND ' . $max_id .' AND t.topic_id = o.topic_id diff --git a/phpBB/phpbb/textreparser/plugins/poll_title.php b/phpBB/phpbb/textreparser/plugins/poll_title.php index b447004527..038ae0c366 100644 --- a/phpBB/phpbb/textreparser/plugins/poll_title.php +++ b/phpBB/phpbb/textreparser/plugins/poll_title.php @@ -31,7 +31,7 @@ class poll_title extends \phpbb\textreparser\row_based_plugin */ protected function get_records_by_range_query($min_id, $max_id) { - $sql = 'SELECT t.topic_id AS id, t.poll_title AS text, p.bbcode_uid + $sql = 'SELECT t.topic_id AS id, t.poll_title AS text, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.bbcode_uid FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p WHERE t.topic_id BETWEEN ' . $min_id . ' AND ' . $max_id .' AND t.poll_max_options > 0 diff --git a/tests/text_reparser/plugins/fixtures/forums.xml b/tests/text_reparser/plugins/fixtures/forums.xml index 39c172c969..c12c8d6d48 100644 --- a/tests/text_reparser/plugins/fixtures/forums.xml +++ b/tests/text_reparser/plugins/fixtures/forums.xml @@ -5,87 +5,109 @@ forum_parents forum_desc forum_desc_uid + forum_desc_options forum_rules forum_rules_uid + forum_rules_options 1 This row should be [b]ignored[/b] abcd1234 + 0 This row should be [b]ignored[/b] abcd1234 + 0 2 [b]Not bold[/b] :) http://example.org abcd1234 + 0 [b]Not bold[/b] :) http://example.org abcd1234 + 0 3 [b:abcd1234]Bold[/b:abcd1234] :) http://example.org abcd1234 + 1 [b:abcd1234]Bold[/b:abcd1234] :) http://example.org abcd1234 + 1 4 :) http://example.org]]> abcd1234 + 2 :) http://example.org]]> abcd1234 + 2 5 http://example.org]]> abcd1234 + 4 http://example.org]]> abcd1234 + 4 6 abcd1234 + 1 abcd1234 + 1 7 abcd1234 + 0 abcd1234 + 0 8 abcd1234 + 1 abcd1234 + 1 9 abcd1234 + 0 abcd1234 + 0 1000 This row should be [b]ignored[/b] abcd1234 + 0 This row should be [b]ignored[/b] abcd1234 + 0 diff --git a/tests/text_reparser/plugins/fixtures/groups.xml b/tests/text_reparser/plugins/fixtures/groups.xml index d3df0131a3..15151426bc 100644 --- a/tests/text_reparser/plugins/fixtures/groups.xml +++ b/tests/text_reparser/plugins/fixtures/groups.xml @@ -38,25 +38,25 @@ 6 - 7 + 1 abcd1234 7 - 7 + 1 abcd1234 8 - 7 + 1 abcd1234 9 - 7 + 1 abcd1234 diff --git a/tests/text_reparser/plugins/fixtures/poll_options.xml b/tests/text_reparser/plugins/fixtures/poll_options.xml index c2fad9f764..48ba024315 100644 --- a/tests/text_reparser/plugins/fixtures/poll_options.xml +++ b/tests/text_reparser/plugins/fixtures/poll_options.xml @@ -29,6 +29,21 @@ 2 http://example.org]]> + + 1 + 11 + [b:abcd1234]Bold[/b:abcd1234] :) http://example.org + + + 1 + 12 + :) http://example.org]]> + + + 1 + 13 + http://example.org]]> + 1 123 @@ -42,9 +57,39 @@ post_id + enable_bbcode + enable_smilies + enable_magic_urlpost_textbbcode_uid + 1 + 1 + 1 + 1 + + abcd1234 + + + 11 + 1 + 0 + 0 + + abcd1234 + + + 12 + 0 + 1 + 0 + + abcd1234 + + + 13 + 0 + 0 1 abcd1234 @@ -64,6 +109,21 @@ 1 This row should be [b]ignored[/b] + + 11 + 11 + BBCode + + + 12 + 12 + Smilies + + + 13 + 13 + Magic URLs + 123 1 diff --git a/tests/text_reparser/plugins/fixtures/polls.xml b/tests/text_reparser/plugins/fixtures/polls.xml index 9baf813c97..2960d640a9 100644 --- a/tests/text_reparser/plugins/fixtures/polls.xml +++ b/tests/text_reparser/plugins/fixtures/polls.xml @@ -2,9 +2,39 @@
            post_id + enable_bbcode + enable_smilies + enable_magic_urlpost_textbbcode_uid + 1 + 0 + 0 + 0 + + abcd1234 + + + 2 + 1 + 0 + 0 + + abcd1234 + + + 3 + 0 + 1 + 0 + + abcd1234 + + + 4 + 0 + 0 1 abcd1234 @@ -26,22 +56,22 @@ 3 - 1 + 2 [b:abcd1234]Bold[/b:abcd1234] :) http://example.org 4 - 1 + 3 :) http://example.org]]> 5 - 1 + 4 http://example.org]]> 6 - 1 + 2 @@ -51,7 +81,7 @@ 8 - 1 + 2 diff --git a/tests/text_reparser/plugins/poll_option_test.php b/tests/text_reparser/plugins/poll_option_test.php index e043858597..acabda2146 100644 --- a/tests/text_reparser/plugins/poll_option_test.php +++ b/tests/text_reparser/plugins/poll_option_test.php @@ -49,7 +49,7 @@ class phpbb_textreparser_poll_option_test extends phpbb_database_test_case public function testReparse() { $reparser = $this->get_reparser(); - $reparser->reparse_range(2, 3); + $reparser->reparse_range(2, 13); $sql = 'SELECT topic_id, poll_option_id, poll_option_text FROM ' . POLL_OPTIONS_TABLE . ' @@ -84,6 +84,21 @@ class phpbb_textreparser_poll_option_test extends phpbb_database_test_case 'poll_option_id' => 3, 'poll_option_text' => 'http://example.org', ), + array( + 'topic_id' => 11, + 'poll_option_id' => 1, + 'poll_option_text' => '[b]Bold[/b] :) http://example.org', + ), + array( + 'topic_id' => 12, + 'poll_option_id' => 1, + 'poll_option_text' => '[b]Not bold[/b] :) http://example.org', + ), + array( + 'topic_id' => 13, + 'poll_option_id' => 1, + 'poll_option_text' => '[b]Not bold[/b] :) http://example.org', + ), array( 'topic_id' => 123, 'poll_option_id' => 1, From 7ccb6389124c5e990abaa917a6684fc3f4d072db Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 6 Jul 2015 01:43:43 +0200 Subject: [PATCH 0433/1676] [ticket/13987] Add --dry-run option to reparser CLI PHPBB3-13987 --- phpBB/language/en/cli.php | 1 + .../console/command/reparser/reparse.php | 15 +++++-- phpBB/phpbb/textreparser/base.php | 13 +++--- .../phpbb/textreparser/reparser_interface.php | 7 ++-- .../plugins/contact_admin_info_test.php | 33 ++++++++++----- .../plugins/poll_option_test.php | 31 +++++++++----- .../plugins/test_row_based_plugin.php | 40 +++++++++++++------ 7 files changed, 96 insertions(+), 44 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 9eca60fb68..d45c52ac5d 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -64,6 +64,7 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_REPARSER_LIST' => 'Lists the types of text that can be reparsed.', 'CLI_DESCRIPTION_REPARSER_REPARSE' => 'Reparses stored text with the current text_formatter services.', 'CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1' => 'Type of text to reparse. Leave blank to reparse everything.', + 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_DRY_RUN' => 'Do not save any changes; just print what would happen', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MIN' => 'Lowest record ID to process', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MAX' => 'Highest record ID to process', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_SIZE' => 'Approximate number of records to process at a time', diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 52075dd0ac..8352c523de 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -56,6 +56,12 @@ class reparse extends \phpbb\console\command\command ->setName('reparser:reparse') ->setDescription($this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE')) ->addArgument('reparser-name', InputArgument::OPTIONAL, $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1')) + ->addOption( + 'dry-run', + null, + InputOption::VALUE_NONE, + $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_DRY_RUN') + ) ->addOption( 'range-min', null, @@ -126,9 +132,10 @@ class reparse extends \phpbb\console\command\command $reparser = $this->reparsers[$name]; // Start at range-max if specified or at the highest ID otherwise - $max = (is_null($input->getOption('range-max'))) ? $reparser->get_max_id() : $input->getOption('range-max'); - $min = $input->getOption('range-min'); - $size = $input->getOption('range-size'); + $max = (is_null($input->getOption('range-max'))) ? $reparser->get_max_id() : $input->getOption('range-max'); + $min = $input->getOption('range-min'); + $size = $input->getOption('range-size'); + $dry_run = $input->getOption('dry-run'); if ($max === 0) { @@ -176,7 +183,7 @@ class reparse extends \phpbb\console\command\command $end = max($min, $current); $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $start, $end)); - $reparser->reparse_range($start, $end); + $reparser->reparse_range($start, $end, $dry_run); $current = $start - 1; $progress->setProgress($max + 1 - $start); diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index ed6c2376c7..6a366d659b 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -170,20 +170,21 @@ abstract class base implements reparser_interface /** * {@inheritdoc} */ - public function reparse_range($min_id, $max_id) + public function reparse_range($min_id, $max_id, $dry_run = false) { foreach ($this->get_records_by_range($min_id, $max_id) as $record) { - $this->reparse_record($record); + $this->reparse_record($record, $dry_run); } } /** * Reparse given record * - * @param array $record Associative array containing the record's data + * @param array $record Associative array containing the record's data + * @param integer $dry_run If TRUE, do not save the changes */ - protected function reparse_record(array $record) + protected function reparse_record(array $record, $dry_run) { $record = $this->add_missing_fields($record); $flags = ($record['enable_bbcode']) ? OPTION_FLAG_BBCODE : 0; @@ -212,8 +213,8 @@ abstract class base implements reparser_interface $unparsed['enable_url_bbcode'] ); - // Save the new text if it has changed - if ($text !== $record['text']) + // Save the new text if it has changed and it's not a dry run + if ($text !== $record['text'] && !$dry_run) { $record['text'] = $text; $this->save_record($record); diff --git a/phpBB/phpbb/textreparser/reparser_interface.php b/phpBB/phpbb/textreparser/reparser_interface.php index 9ea1732870..e201a77882 100644 --- a/phpBB/phpbb/textreparser/reparser_interface.php +++ b/phpBB/phpbb/textreparser/reparser_interface.php @@ -25,8 +25,9 @@ interface reparser_interface /** * Reparse all records in given range * - * @param integer $min_id Lower bound - * @param integer $max_id Upper bound + * @param integer $min_id Lower bound + * @param integer $max_id Upper bound + * @param integer $dry_run If TRUE, do not save the changes */ - public function reparse_range($min_id, $max_id); + public function reparse_range($min_id, $max_id, $dry_run = false); } diff --git a/tests/text_reparser/plugins/contact_admin_info_test.php b/tests/text_reparser/plugins/contact_admin_info_test.php index e577d2fd3d..e3df1ee2b8 100644 --- a/tests/text_reparser/plugins/contact_admin_info_test.php +++ b/tests/text_reparser/plugins/contact_admin_info_test.php @@ -28,6 +28,18 @@ class phpbb_textreparser_contact_admin_info_test extends phpbb_database_test_cas return new \phpbb\textreparser\plugins\contact_admin_info(new \phpbb\config\db_text($this->db, CONFIG_TEXT_TABLE)); } + protected function get_rows() + { + $sql = 'SELECT config_name, config_value + FROM ' . CONFIG_TEXT_TABLE . ' + ORDER BY config_name'; + $result = $this->db->sql_query($sql); + $rows = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + return $rows; + } + public function setUp() { global $config; @@ -46,18 +58,19 @@ class phpbb_textreparser_contact_admin_info_test extends phpbb_database_test_cas $this->assertEquals(1, $reparser->get_max_id()); } - public function testReparse() + public function test_dry_run() + { + $old_rows = $this->get_rows(); + $reparser = $this->get_reparser(); + $reparser->reparse_range(1, 1, true); + $new_rows = $this->get_rows(); + $this->assertEquals($old_rows, $new_rows); + } + + public function test_reparse() { $reparser = $this->get_reparser(); $reparser->reparse_range(1, 1); - - $sql = 'SELECT config_name, config_value - FROM ' . CONFIG_TEXT_TABLE . ' - ORDER BY config_name'; - $result = $this->db->sql_query($sql); - $rows = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - $expected = array( array( 'config_name' => 'contact_admin_info', @@ -76,6 +89,6 @@ class phpbb_textreparser_contact_admin_info_test extends phpbb_database_test_cas 'config_value' => '1a2hbwf5', ), ); - $this->assertEquals($expected, $rows); + $this->assertEquals($expected, $this->get_rows()); } } diff --git a/tests/text_reparser/plugins/poll_option_test.php b/tests/text_reparser/plugins/poll_option_test.php index acabda2146..cc6163a81b 100644 --- a/tests/text_reparser/plugins/poll_option_test.php +++ b/tests/text_reparser/plugins/poll_option_test.php @@ -28,6 +28,18 @@ class phpbb_textreparser_poll_option_test extends phpbb_database_test_case return new \phpbb\textreparser\plugins\poll_option($this->db); } + protected function get_rows() + { + $sql = 'SELECT topic_id, poll_option_id, poll_option_text + FROM ' . POLL_OPTIONS_TABLE . ' + ORDER BY topic_id, poll_option_id'; + $result = $this->db->sql_query($sql); + $rows = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + return $rows; + } + public function setUp() { global $config; @@ -46,18 +58,19 @@ class phpbb_textreparser_poll_option_test extends phpbb_database_test_case $this->assertEquals(123, $reparser->get_max_id()); } + public function test_dry_run() + { + $old_rows = $this->get_rows(); + $reparser = $this->get_reparser(); + $reparser->reparse_range(1, 1, true); + $new_rows = $this->get_rows(); + $this->assertEquals($old_rows, $new_rows); + } + public function testReparse() { $reparser = $this->get_reparser(); $reparser->reparse_range(2, 13); - - $sql = 'SELECT topic_id, poll_option_id, poll_option_text - FROM ' . POLL_OPTIONS_TABLE . ' - ORDER BY topic_id, poll_option_id'; - $result = $this->db->sql_query($sql); - $rows = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - $expected = array( array( 'topic_id' => 1, @@ -110,6 +123,6 @@ class phpbb_textreparser_poll_option_test extends phpbb_database_test_case 'poll_option_text' => 'This row should be [b:abcd1234]ignored[/b:abcd1234]', ), ); - $this->assertEquals($expected, $rows); + $this->assertEquals($expected, $this->get_rows()); } } diff --git a/tests/text_reparser/plugins/test_row_based_plugin.php b/tests/text_reparser/plugins/test_row_based_plugin.php index befcb48bda..9f9ecc609a 100644 --- a/tests/text_reparser/plugins/test_row_based_plugin.php +++ b/tests/text_reparser/plugins/test_row_based_plugin.php @@ -20,6 +20,21 @@ abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_t abstract protected function get_reparser(); + protected function get_rows(array $ids) + { + $reparser = $this->get_reparser(); + $columns = $reparser->get_columns(); + $sql = 'SELECT ' . $columns['id'] . ' AS id, ' . $columns['text'] . ' AS text + FROM ' . $reparser->get_table_name() . ' + WHERE ' . $this->db->sql_in_set($columns['id'], $ids) . ' + ORDER BY id'; + $result = $this->db->sql_query($sql); + $rows = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + return $rows; + } + public function setUp() { global $config; @@ -38,10 +53,19 @@ abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_t $this->assertEquals(1000, $reparser->get_max_id()); } + public function test_dry_run() + { + $old_rows = $this->get_rows(array(1)); + $reparser = $this->get_reparser(); + $reparser->reparse_range(1, 1, true); + $new_rows = $this->get_rows(array(1)); + $this->assertEquals($old_rows, $new_rows); + } + /** - * @dataProvider getReparseTests + * @dataProvider get_reparse_tests */ - public function testReparse($min_id, $max_id, $expected) + public function test_reparse($min_id, $max_id, $expected) { $reparser = $this->get_reparser(); $reparser->reparse_range($min_id, $max_id); @@ -52,18 +76,10 @@ abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_t $ids[] = $row['id']; } - $columns = $reparser->get_columns(); - $sql = 'SELECT ' . $columns['id'] . ' AS id, ' . $columns['text'] . ' AS text - FROM ' . $reparser->get_table_name() . ' - WHERE ' . $this->db->sql_in_set($columns['id'], $ids) . ' - ORDER BY id'; - $result = $this->db->sql_query($sql); - $rows = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - $this->assertEquals($expected, $rows); + $this->assertEquals($expected, $this->get_rows($ids)); } - public function getReparseTests() + public function get_reparse_tests() { return array( array( From cf4cdcda586a2371aa92ae452951f9660737ae09 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 6 Jul 2015 01:57:54 +0200 Subject: [PATCH 0434/1676] [ticket/13987] Replaced optional parameter with explicit API Added disable_save() and enable_save() to toggle a dry run PHPBB3-13987 --- .../console/command/reparser/reparse.php | 17 +++++++--- phpBB/phpbb/textreparser/base.php | 32 +++++++++++++++---- .../phpbb/textreparser/reparser_interface.php | 7 ++-- .../plugins/contact_admin_info_test.php | 4 ++- .../plugins/poll_option_test.php | 4 ++- .../plugins/test_row_based_plugin.php | 3 +- 6 files changed, 49 insertions(+), 18 deletions(-) diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 8352c523de..151e196358 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -130,12 +130,19 @@ class reparse extends \phpbb\console\command\command protected function reparse(InputInterface $input, OutputInterface $output, $name) { $reparser = $this->reparsers[$name]; + if ($input->getOption('dry-run')) + { + $reparser->disable_save(); + } + else + { + $reparser->enable_save(); + } // Start at range-max if specified or at the highest ID otherwise - $max = (is_null($input->getOption('range-max'))) ? $reparser->get_max_id() : $input->getOption('range-max'); - $min = $input->getOption('range-min'); - $size = $input->getOption('range-size'); - $dry_run = $input->getOption('dry-run'); + $max = (is_null($input->getOption('range-max'))) ? $reparser->get_max_id() : $input->getOption('range-max'); + $min = $input->getOption('range-min'); + $size = $input->getOption('range-size'); if ($max === 0) { @@ -183,7 +190,7 @@ class reparse extends \phpbb\console\command\command $end = max($min, $current); $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $start, $end)); - $reparser->reparse_range($start, $end, $dry_run); + $reparser->reparse_range($start, $end); $current = $start - 1; $progress->setProgress($max + 1 - $start); diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 6a366d659b..3e5ee248a1 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -15,6 +15,11 @@ namespace phpbb\textreparser; abstract class base implements reparser_interface { + /** + * @var bool Whether to save changes to the database + */ + protected $save_changes = true; + /** * {@inheritdoc} */ @@ -84,6 +89,22 @@ abstract class base implements reparser_interface return $record; } + /** + * Disable saving changes to the database + */ + public function disable_save() + { + $this->save_changes = false; + } + + /** + * Enable saving changes to the database + */ + public function enable_save() + { + $this->save_changes = true; + } + /** * Guess whether given BBCode is in use in given record * @@ -170,21 +191,20 @@ abstract class base implements reparser_interface /** * {@inheritdoc} */ - public function reparse_range($min_id, $max_id, $dry_run = false) + public function reparse_range($min_id, $max_id) { foreach ($this->get_records_by_range($min_id, $max_id) as $record) { - $this->reparse_record($record, $dry_run); + $this->reparse_record($record); } } /** * Reparse given record * - * @param array $record Associative array containing the record's data - * @param integer $dry_run If TRUE, do not save the changes + * @param array $record Associative array containing the record's data */ - protected function reparse_record(array $record, $dry_run) + protected function reparse_record(array $record) { $record = $this->add_missing_fields($record); $flags = ($record['enable_bbcode']) ? OPTION_FLAG_BBCODE : 0; @@ -214,7 +234,7 @@ abstract class base implements reparser_interface ); // Save the new text if it has changed and it's not a dry run - if ($text !== $record['text'] && !$dry_run) + if ($text !== $record['text'] && $this->save_changes) { $record['text'] = $text; $this->save_record($record); diff --git a/phpBB/phpbb/textreparser/reparser_interface.php b/phpBB/phpbb/textreparser/reparser_interface.php index e201a77882..9ea1732870 100644 --- a/phpBB/phpbb/textreparser/reparser_interface.php +++ b/phpBB/phpbb/textreparser/reparser_interface.php @@ -25,9 +25,8 @@ interface reparser_interface /** * Reparse all records in given range * - * @param integer $min_id Lower bound - * @param integer $max_id Upper bound - * @param integer $dry_run If TRUE, do not save the changes + * @param integer $min_id Lower bound + * @param integer $max_id Upper bound */ - public function reparse_range($min_id, $max_id, $dry_run = false); + public function reparse_range($min_id, $max_id); } diff --git a/tests/text_reparser/plugins/contact_admin_info_test.php b/tests/text_reparser/plugins/contact_admin_info_test.php index e3df1ee2b8..1dc03834b6 100644 --- a/tests/text_reparser/plugins/contact_admin_info_test.php +++ b/tests/text_reparser/plugins/contact_admin_info_test.php @@ -62,7 +62,8 @@ class phpbb_textreparser_contact_admin_info_test extends phpbb_database_test_cas { $old_rows = $this->get_rows(); $reparser = $this->get_reparser(); - $reparser->reparse_range(1, 1, true); + $reparser->disable_save(); + $reparser->reparse_range(1, 1); $new_rows = $this->get_rows(); $this->assertEquals($old_rows, $new_rows); } @@ -70,6 +71,7 @@ class phpbb_textreparser_contact_admin_info_test extends phpbb_database_test_cas public function test_reparse() { $reparser = $this->get_reparser(); + $reparser->enable_save(); $reparser->reparse_range(1, 1); $expected = array( array( diff --git a/tests/text_reparser/plugins/poll_option_test.php b/tests/text_reparser/plugins/poll_option_test.php index cc6163a81b..dfa3a030ed 100644 --- a/tests/text_reparser/plugins/poll_option_test.php +++ b/tests/text_reparser/plugins/poll_option_test.php @@ -62,7 +62,8 @@ class phpbb_textreparser_poll_option_test extends phpbb_database_test_case { $old_rows = $this->get_rows(); $reparser = $this->get_reparser(); - $reparser->reparse_range(1, 1, true); + $reparser->disable_save(); + $reparser->reparse_range(1, 1); $new_rows = $this->get_rows(); $this->assertEquals($old_rows, $new_rows); } @@ -70,6 +71,7 @@ class phpbb_textreparser_poll_option_test extends phpbb_database_test_case public function testReparse() { $reparser = $this->get_reparser(); + $reparser->enable_save(); $reparser->reparse_range(2, 13); $expected = array( array( diff --git a/tests/text_reparser/plugins/test_row_based_plugin.php b/tests/text_reparser/plugins/test_row_based_plugin.php index 9f9ecc609a..bbae44c8e0 100644 --- a/tests/text_reparser/plugins/test_row_based_plugin.php +++ b/tests/text_reparser/plugins/test_row_based_plugin.php @@ -57,7 +57,8 @@ abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_t { $old_rows = $this->get_rows(array(1)); $reparser = $this->get_reparser(); - $reparser->reparse_range(1, 1, true); + $reparser->disable_save(); + $reparser->reparse_range(1, 1); $new_rows = $this->get_rows(array(1)); $this->assertEquals($old_rows, $new_rows); } From 1365519283d5574ea0668f25052f4fee960d27f4 Mon Sep 17 00:00:00 2001 From: rxu Date: Tue, 25 Nov 2014 22:20:14 +0700 Subject: [PATCH 0435/1676] [ticket/13377] Fix decoding for www type URLs in function decode_message() PHPBB3-13377 --- phpBB/includes/functions.php | 2 +- phpBB/includes/functions_content.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index bb4fc5dbae..d6ed40bdf8 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2749,7 +2749,7 @@ function get_preg_expression($mode) return array( '#.*?#', '#.*?#', - '#.*?#', + '#(.*?)#', '#:)', ':)' ), + array( + 'www.phpbb.com', + 'www.phpbb.com' + ), + array( + 'http://www.phpbb.com', + 'http://www.phpbb.com' + ), /** * Fails as per PHPBB3-8420 * @link http://tracker.phpbb.com/browse/PHPBB3-8420 From 14e8f712ae0278afff2a750b707dfd66f6e13182 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Fri, 17 Apr 2015 18:38:21 +0200 Subject: [PATCH 0437/1676] [ticket/13740] Moving old installer to install_old PHPBB3-13740 --- phpBB/install/install_install.php | 2368 ----------------- phpBB/install/install_main.php | 78 - .../convertors/convert_phpbb20.php | 0 .../convertors/functions_phpbb20.php | 0 .../data/confusables.php | 0 .../database_update.php | 0 phpBB/{install => install_old}/index.php | 0 .../install_convert.php | 0 .../install_update.php | 0 phpBB/{install => install_old}/phpinfo.php | 0 10 files changed, 2446 deletions(-) delete mode 100644 phpBB/install/install_install.php delete mode 100644 phpBB/install/install_main.php rename phpBB/{install => install_old}/convertors/convert_phpbb20.php (100%) rename phpBB/{install => install_old}/convertors/functions_phpbb20.php (100%) rename phpBB/{install => install_old}/data/confusables.php (100%) rename phpBB/{install => install_old}/database_update.php (100%) rename phpBB/{install => install_old}/index.php (100%) rename phpBB/{install => install_old}/install_convert.php (100%) rename phpBB/{install => install_old}/install_update.php (100%) rename phpBB/{install => install_old}/phpinfo.php (100%) diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php deleted file mode 100644 index 0e223866b1..0000000000 --- a/phpBB/install/install_install.php +++ /dev/null @@ -1,2368 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -/** -*/ -if (!defined('IN_INSTALL')) -{ - // Someone has tried to access the file direct. This is not a good idea, so exit - exit; -} - -if (!empty($setmodules)) -{ - // If phpBB is already installed we do not include this module - if (phpbb_check_installation_exists($phpbb_root_path, $phpEx) && !file_exists($phpbb_root_path . 'cache/install_lock')) - { - return; - } - - $module[] = array( - 'module_type' => 'install', - 'module_title' => 'INSTALL', - 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1), - 'module_order' => 10, - 'module_subs' => '', - 'module_stages' => array('INTRO', 'REQUIREMENTS', 'DATABASE', 'ADMINISTRATOR', 'CONFIG_FILE', 'ADVANCED', 'CREATE_TABLE', 'FINAL'), - 'module_reqs' => '' - ); -} - -/** -* Installation -*/ -class install_install extends module -{ - /** - * @var \phpbb\filesystem\filesystem_interface - */ - protected $filesystem; - - function install_install(&$p_master) - { - $this->p_master = &$p_master; - $this->filesystem = new \phpbb\filesystem\filesystem(); - } - - function main($mode, $sub) - { - global $lang, $template, $language, $phpbb_root_path, $phpEx; - global $phpbb_container, $cache, $phpbb_log, $request, $phpbb_config_php_file; - - switch ($sub) - { - case 'intro': - $phpbb_container->get('cache.driver')->purge(); - - $this->page_title = $lang['SUB_INTRO']; - - $template->assign_vars(array( - 'TITLE' => $lang['INSTALL_INTRO'], - 'BODY' => $lang['INSTALL_INTRO_BODY'], - 'L_SUBMIT' => $lang['NEXT_STEP'], - 'S_LANG_SELECT' => '', - 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&sub=requirements&language=$language", - )); - - break; - - case 'requirements': - $this->check_server_requirements($mode, $sub); - - break; - - case 'database': - $this->obtain_database_settings($mode, $sub); - - break; - - case 'administrator': - $this->obtain_admin_settings($mode, $sub); - - break; - - case 'config_file': - $this->create_config_file($mode, $sub); - - break; - - case 'advanced': - $this->obtain_advanced_settings($mode, $sub); - - break; - - case 'create_table': - $this->load_schema($mode, $sub); - break; - - case 'final': - // Enable super globals to prevent issues with the new \phpbb\request\request object - $request->enable_super_globals(); - - // Create a normal container now - $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); - $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container(); - - // Sets the global variables - /* @var $cache \phpbb\cache\service */ - $cache = $phpbb_container->get('cache'); - - /* @var $phpbb_log \phpbb\log\log_interface */ - $phpbb_log = $phpbb_container->get('log'); - - $this->build_search_index($mode, $sub); - $this->add_modules($mode, $sub); - $this->add_language($mode, $sub); - $this->add_bots($mode, $sub); - $this->email_admin($mode, $sub); - $this->disable_avatars_if_unwritable(); - $this->populate_migrations($phpbb_container->get('ext.manager'), $phpbb_container->get('migrator')); - - // Remove the lock file - @unlink($phpbb_root_path . 'cache/install_lock'); - - break; - } - - $this->tpl_name = 'install_install'; - } - - /** - * Checks that the server we are installing on meets the requirements for running phpBB - */ - function check_server_requirements($mode, $sub) - { - global $lang, $template, $phpbb_root_path, $phpEx, $language; - - $this->page_title = $lang['STAGE_REQUIREMENTS']; - - $template->assign_vars(array( - 'TITLE' => $lang['REQUIREMENTS_TITLE'], - 'BODY' => $lang['REQUIREMENTS_EXPLAIN'], - )); - - $passed = array('php' => false, 'db' => false, 'files' => false, 'pcre' => false, 'imagesize' => false, 'json' => false,); - - // Test for basic PHP settings - $template->assign_block_vars('checks', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang['PHP_SETTINGS'], - 'LEGEND_EXPLAIN' => $lang['PHP_SETTINGS_EXPLAIN'], - )); - - // Test the minimum PHP version - $php_version = PHP_VERSION; - - if (version_compare($php_version, '5.3.9') < 0) - { - $result = '' . $lang['NO'] . ''; - } - else - { - $passed['php'] = true; - - // We also give feedback on whether we're running in safe mode - $result = '' . $lang['YES']; - if (@ini_get('safe_mode') == '1' || strtolower(@ini_get('safe_mode')) == 'on') - { - $result .= ', ' . $lang['PHP_SAFE_MODE']; - } - $result .= ''; - } - - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['PHP_VERSION_REQD'], - 'RESULT' => $result, - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - - // Don't check for register_globals on 5.4+ - if (version_compare($php_version, '5.4.0-dev') < 0) - { - // Check for register_globals being enabled - if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on') - { - $result = '' . $lang['NO'] . ''; - } - else - { - $result = '' . $lang['YES'] . ''; - } - - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['PHP_REGISTER_GLOBALS'], - 'TITLE_EXPLAIN' => $lang['PHP_REGISTER_GLOBALS_EXPLAIN'], - 'RESULT' => $result, - - 'S_EXPLAIN' => true, - 'S_LEGEND' => false, - )); - } - - // Check for url_fopen - if (@ini_get('allow_url_fopen') == '1' || strtolower(@ini_get('allow_url_fopen')) == 'on') - { - $result = '' . $lang['YES'] . ''; - } - else - { - $result = '' . $lang['NO'] . ''; - } - - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['PHP_URL_FOPEN_SUPPORT'], - 'TITLE_EXPLAIN' => $lang['PHP_URL_FOPEN_SUPPORT_EXPLAIN'], - 'RESULT' => $result, - - 'S_EXPLAIN' => true, - 'S_LEGEND' => false, - )); - - // Check for getimagesize - if (@function_exists('getimagesize')) - { - $passed['imagesize'] = true; - $result = '' . $lang['YES'] . ''; - } - else - { - $result = '' . $lang['NO'] . ''; - } - - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['PHP_GETIMAGESIZE_SUPPORT'], - 'TITLE_EXPLAIN' => $lang['PHP_GETIMAGESIZE_SUPPORT_EXPLAIN'], - 'RESULT' => $result, - - 'S_EXPLAIN' => true, - 'S_LEGEND' => false, - )); - - // Check for PCRE UTF-8 support - if (@preg_match('//u', '')) - { - $passed['pcre'] = true; - $result = '' . $lang['YES'] . ''; - } - else - { - $result = '' . $lang['NO'] . ''; - } - - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['PCRE_UTF_SUPPORT'], - 'TITLE_EXPLAIN' => $lang['PCRE_UTF_SUPPORT_EXPLAIN'], - 'RESULT' => $result, - - 'S_EXPLAIN' => true, - 'S_LEGEND' => false, - )); - - // Check for php json support - if (@extension_loaded('json')) - { - $passed['json'] = true; - $result = '' . $lang['YES'] . ''; - } - else - { - $result = '' . $lang['NO'] . ''; - } - - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['PHP_JSON_SUPPORT'], - 'TITLE_EXPLAIN' => $lang['PHP_JSON_SUPPORT_EXPLAIN'], - 'RESULT' => $result, - - 'S_EXPLAIN' => true, - 'S_LEGEND' => false, - )); - - $passed['mbstring'] = true; - if (@extension_loaded('mbstring')) - { - // Test for available database modules - $template->assign_block_vars('checks', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang['MBSTRING_CHECK'], - 'LEGEND_EXPLAIN' => $lang['MBSTRING_CHECK_EXPLAIN'], - )); - - $checks = array( - array('func_overload', '&', MB_OVERLOAD_MAIL|MB_OVERLOAD_STRING), - array('encoding_translation', '!=', 0), - array('http_input', '!=', array('pass', '')), - array('http_output', '!=', array('pass', '')) - ); - - foreach ($checks as $mb_checks) - { - $ini_val = @ini_get('mbstring.' . $mb_checks[0]); - switch ($mb_checks[1]) - { - case '&': - if (intval($ini_val) & $mb_checks[2]) - { - $result = '' . $lang['NO'] . ''; - $passed['mbstring'] = false; - } - else - { - $result = '' . $lang['YES'] . ''; - } - break; - - case '!=': - if (!is_array($mb_checks[2]) && $ini_val != $mb_checks[2] || - is_array($mb_checks[2]) && !in_array($ini_val, $mb_checks[2])) - { - $result = '' . $lang['NO'] . ''; - $passed['mbstring'] = false; - } - else - { - $result = '' . $lang['YES'] . ''; - } - break; - } - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['MBSTRING_' . strtoupper($mb_checks[0])], - 'TITLE_EXPLAIN' => $lang['MBSTRING_' . strtoupper($mb_checks[0]) . '_EXPLAIN'], - 'RESULT' => $result, - - 'S_EXPLAIN' => true, - 'S_LEGEND' => false, - )); - } - } - - // Test for available database modules - $template->assign_block_vars('checks', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang['PHP_SUPPORTED_DB'], - 'LEGEND_EXPLAIN' => $lang['PHP_SUPPORTED_DB_EXPLAIN'], - )); - - $available_dbms = get_available_dbms(false, true); - $passed['db'] = $available_dbms['ANY_DB_SUPPORT']; - unset($available_dbms['ANY_DB_SUPPORT']); - - foreach ($available_dbms as $db_name => $db_ary) - { - if (!$db_ary['AVAILABLE']) - { - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['DLL_' . strtoupper($db_name)], - 'RESULT' => '' . $lang['UNAVAILABLE'] . '', - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - } - else - { - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['DLL_' . strtoupper($db_name)], - 'RESULT' => '' . $lang['AVAILABLE'] . '', - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - } - } - - // Test for other modules - $template->assign_block_vars('checks', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang['PHP_OPTIONAL_MODULE'], - 'LEGEND_EXPLAIN' => $lang['PHP_OPTIONAL_MODULE_EXPLAIN'], - )); - - foreach ($this->php_dlls_other as $dll) - { - if (!@extension_loaded($dll)) - { - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['DLL_' . strtoupper($dll)], - 'RESULT' => '' . $lang['UNAVAILABLE'] . '', - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - continue; - } - - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['DLL_' . strtoupper($dll)], - 'RESULT' => '' . $lang['AVAILABLE'] . '', - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - } - - // Can we find Imagemagick anywhere on the system? - $exe = (DIRECTORY_SEPARATOR == '\\') ? '.exe' : ''; - - $magic_home = getenv('MAGICK_HOME'); - $img_imagick = ''; - if (empty($magic_home)) - { - $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/'); - $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH')))); - - $locations = array_merge($path_locations, $locations); - foreach ($locations as $location) - { - // The path might not end properly, fudge it - if (substr($location, -1, 1) !== '/') - { - $location .= '/'; - } - - if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) - { - $img_imagick = str_replace('\\', '/', $location); - continue; - } - } - } - else - { - $img_imagick = str_replace('\\', '/', $magic_home); - } - - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['APP_MAGICK'], - 'RESULT' => ($img_imagick) ? '' . $lang['AVAILABLE'] . ', ' . $img_imagick . '' : '' . $lang['NO_LOCATION'] . '', - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - - // Check permissions on files/directories we need access to - $template->assign_block_vars('checks', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang['FILES_REQUIRED'], - 'LEGEND_EXPLAIN' => $lang['FILES_REQUIRED_EXPLAIN'], - )); - - $directories = array('cache/', 'files/', 'store/'); - - umask(0); - - $passed['files'] = true; - foreach ($directories as $dir) - { - $exists = $write = false; - - // Try to create the directory if it does not exist - if (!file_exists($phpbb_root_path . $dir)) - { - @mkdir($phpbb_root_path . $dir, 0777); - - try - { - $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE); - } - catch (\phpbb\filesystem\exception\filesystem_exception $e) - { - // Do nothing - } - } - - // Now really check - if (file_exists($phpbb_root_path . $dir) && is_dir($phpbb_root_path . $dir)) - { - try - { - $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE); - } - catch (\phpbb\filesystem\exception\filesystem_exception $e) - { - // Do nothing - } - - $exists = true; - } - - // Now check if it is writable by storing a simple file - $fp = @fopen($phpbb_root_path . $dir . 'test_lock', 'wb'); - if ($fp !== false) - { - $write = true; - } - @fclose($fp); - - @unlink($phpbb_root_path . $dir . 'test_lock'); - - $passed['files'] = ($exists && $write && $passed['files']) ? true : false; - - $exists = ($exists) ? '' . $lang['FOUND'] . '' : '' . $lang['NOT_FOUND'] . ''; - $write = ($write) ? ', ' . $lang['WRITABLE'] . '' : (($exists) ? ', ' . $lang['UNWRITABLE'] . '' : ''); - - $template->assign_block_vars('checks', array( - 'TITLE' => $dir, - 'RESULT' => $exists . $write, - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - } - - // Check permissions on files/directories it would be useful access to - $template->assign_block_vars('checks', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang['FILES_OPTIONAL'], - 'LEGEND_EXPLAIN' => $lang['FILES_OPTIONAL_EXPLAIN'], - )); - - $directories = array('config.' . $phpEx, 'images/avatars/upload/'); - - foreach ($directories as $dir) - { - $write = $exists = true; - if (file_exists($phpbb_root_path . $dir)) - { - if (!$this->filesystem->is_writable($phpbb_root_path . $dir)) - { - $write = false; - } - } - else - { - $write = $exists = false; - } - - $exists_str = ($exists) ? '' . $lang['FOUND'] . '' : '' . $lang['NOT_FOUND'] . ''; - $write_str = ($write) ? ', ' . $lang['WRITABLE'] . '' : (($exists) ? ', ' . $lang['UNWRITABLE'] . '' : ''); - - $template->assign_block_vars('checks', array( - 'TITLE' => $dir, - 'RESULT' => $exists_str . $write_str, - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - } - - // And finally where do we want to go next (well today is taken isn't it :P) - $s_hidden_fields = ($img_imagick) ? '' : ''; - - $url = (!in_array(false, $passed)) ? $this->p_master->module_url . "?mode=$mode&sub=database&language=$language" : $this->p_master->module_url . "?mode=$mode&sub=requirements&language=$language "; - $submit = (!in_array(false, $passed)) ? $lang['INSTALL_START'] : $lang['INSTALL_TEST']; - - $template->assign_vars(array( - 'L_SUBMIT' => $submit, - 'S_HIDDEN' => $s_hidden_fields, - 'U_ACTION' => $url, - )); - } - - /** - * Obtain the information required to connect to the database - */ - function obtain_database_settings($mode, $sub) - { - global $lang, $template, $phpEx; - - $this->page_title = $lang['STAGE_DATABASE']; - - // Obtain any submitted data - $data = $this->get_submitted_data(); - - $connect_test = false; - $error = array(); - $available_dbms = get_available_dbms(false, true); - - // Has the user opted to test the connection? - if (isset($_POST['testdb'])) - { - if (!isset($available_dbms[$data['dbms']]) || !$available_dbms[$data['dbms']]['AVAILABLE']) - { - $error[] = $lang['INST_ERR_NO_DB']; - $connect_test = false; - } - else if (!preg_match(get_preg_expression('table_prefix'), $data['table_prefix'])) - { - $error[] = $lang['INST_ERR_DB_INVALID_PREFIX']; - $connect_test = false; - } - else - { - $connect_test = connect_check_db(true, $error, $available_dbms[$data['dbms']], $data['table_prefix'], $data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport']); - } - - $template->assign_block_vars('checks', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang['DB_CONNECTION'], - 'LEGEND_EXPLAIN' => false, - )); - - if ($connect_test) - { - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['DB_TEST'], - 'RESULT' => '' . $lang['SUCCESSFUL_CONNECT'] . '', - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - } - else - { - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['DB_TEST'], - 'RESULT' => '' . implode('
            ', $error) . '
            ', - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - } - } - - if (!$connect_test) - { - // Update the list of available DBMS modules to only contain those which can be used - $available_dbms_temp = array(); - foreach ($available_dbms as $type => $dbms_ary) - { - if (!$dbms_ary['AVAILABLE']) - { - continue; - } - - $available_dbms_temp[$type] = $dbms_ary; - } - - $available_dbms = &$available_dbms_temp; - - // And now for the main part of this page - $data['table_prefix'] = (!empty($data['table_prefix']) ? $data['table_prefix'] : 'phpbb_'); - - foreach ($this->db_config_options as $config_key => $vars) - { - if (!is_array($vars) && strpos($config_key, 'legend') === false) - { - continue; - } - - if (strpos($config_key, 'legend') !== false) - { - $template->assign_block_vars('options', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang[$vars]) - ); - - continue; - } - - $options = isset($vars['options']) ? $vars['options'] : ''; - - $template->assign_block_vars('options', array( - 'KEY' => $config_key, - 'TITLE' => $lang[$vars['lang']], - 'S_EXPLAIN' => $vars['explain'], - 'S_LEGEND' => false, - 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '', - 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options), - ) - ); - } - } - - // And finally where do we want to go next (well today is taken isn't it :P) - $s_hidden_fields = ($data['img_imagick']) ? '' : ''; - $s_hidden_fields .= ''; - if ($connect_test) - { - foreach ($this->db_config_options as $config_key => $vars) - { - if (!is_array($vars)) - { - continue; - } - $s_hidden_fields .= ''; - } - } - - $url = ($connect_test) ? $this->p_master->module_url . "?mode=$mode&sub=administrator" : $this->p_master->module_url . "?mode=$mode&sub=database"; - $s_hidden_fields .= ($connect_test) ? '' : ''; - - $submit = $lang['NEXT_STEP']; - - $template->assign_vars(array( - 'L_SUBMIT' => $submit, - 'S_HIDDEN' => $s_hidden_fields, - 'U_ACTION' => $url, - )); - } - - /** - * Obtain the administrator's name, password and email address - */ - function obtain_admin_settings($mode, $sub) - { - global $lang, $template, $phpEx; - - $this->page_title = $lang['STAGE_ADMINISTRATOR']; - - // Obtain any submitted data - $data = $this->get_submitted_data(); - - if ($data['dbms'] == '') - { - // Someone's been silly and tried calling this page direct - // So we send them back to the start to do it again properly - $this->p_master->redirect("index.$phpEx?mode=install"); - } - - $s_hidden_fields = ($data['img_imagick']) ? '' : ''; - $passed = false; - - $data['default_lang'] = ($data['default_lang'] !== '') ? $data['default_lang'] : $data['language']; - - if (isset($_POST['check'])) - { - $error = array(); - - // Check the entered email address and password - if ($data['admin_name'] == '' || $data['admin_pass1'] == '' || $data['admin_pass2'] == '' || $data['board_email'] == '') - { - $error[] = $lang['INST_ERR_MISSING_DATA']; - } - - if ($data['admin_pass1'] != $data['admin_pass2'] && $data['admin_pass1'] != '') - { - $error[] = $lang['INST_ERR_PASSWORD_MISMATCH']; - } - - // Test against the default username rules - if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) < 3) - { - $error[] = $lang['INST_ERR_USER_TOO_SHORT']; - } - - if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) > 20) - { - $error[] = $lang['INST_ERR_USER_TOO_LONG']; - } - - // Test against the default password rules - if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) < 6) - { - $error[] = $lang['INST_ERR_PASSWORD_TOO_SHORT']; - } - - if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) > 30) - { - $error[] = $lang['INST_ERR_PASSWORD_TOO_LONG']; - } - - if ($data['board_email'] != '' && !preg_match('/^' . get_preg_expression('email') . '$/i', $data['board_email'])) - { - $error[] = $lang['INST_ERR_EMAIL_INVALID']; - } - - $template->assign_block_vars('checks', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang['STAGE_ADMINISTRATOR'], - 'LEGEND_EXPLAIN' => false, - )); - - if (!sizeof($error)) - { - $passed = true; - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['ADMIN_TEST'], - 'RESULT' => '' . $lang['TESTS_PASSED'] . '', - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - } - else - { - $template->assign_block_vars('checks', array( - 'TITLE' => $lang['ADMIN_TEST'], - 'RESULT' => '' . implode('
            ', $error) . '
            ', - - 'S_EXPLAIN' => false, - 'S_LEGEND' => false, - )); - } - } - - if (!$passed) - { - foreach ($this->admin_config_options as $config_key => $vars) - { - if (!is_array($vars) && strpos($config_key, 'legend') === false) - { - continue; - } - - if (strpos($config_key, 'legend') !== false) - { - $template->assign_block_vars('options', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang[$vars]) - ); - - continue; - } - - $options = isset($vars['options']) ? $vars['options'] : ''; - - $template->assign_block_vars('options', array( - 'KEY' => $config_key, - 'TITLE' => $lang[$vars['lang']], - 'S_EXPLAIN' => $vars['explain'], - 'S_LEGEND' => false, - 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '', - 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options), - ) - ); - } - } - else - { - foreach ($this->admin_config_options as $config_key => $vars) - { - if (!is_array($vars)) - { - continue; - } - $s_hidden_fields .= ''; - } - } - - $s_hidden_fields .= ($data['img_imagick']) ? '' : ''; - $s_hidden_fields .= ''; - - foreach ($this->db_config_options as $config_key => $vars) - { - if (!is_array($vars)) - { - continue; - } - $s_hidden_fields .= ''; - } - - $submit = $lang['NEXT_STEP']; - - $url = ($passed) ? $this->p_master->module_url . "?mode=$mode&sub=config_file" : $this->p_master->module_url . "?mode=$mode&sub=administrator"; - $s_hidden_fields .= ($passed) ? '' : ''; - - $template->assign_vars(array( - 'L_SUBMIT' => $submit, - 'S_HIDDEN' => $s_hidden_fields, - 'U_ACTION' => $url, - )); - } - - /** - * Writes the config file to disk, or if unable to do so offers alternative methods - */ - function create_config_file($mode, $sub) - { - global $lang, $template, $phpbb_root_path, $phpEx; - - $this->page_title = $lang['STAGE_CONFIG_FILE']; - - // Obtain any submitted data - $data = $this->get_submitted_data(); - - if ($data['dbms'] == '') - { - // Someone's been silly and tried calling this page direct - // So we send them back to the start to do it again properly - $this->p_master->redirect("index.$phpEx?mode=install"); - } - - $s_hidden_fields = ($data['img_imagick']) ? '' : ''; - $s_hidden_fields .= ''; - $written = false; - - // Create a list of any PHP modules we wish to have loaded - $available_dbms = get_available_dbms($data['dbms']); - - // Create a lock file to indicate that there is an install in progress - $fp = @fopen($phpbb_root_path . 'cache/install_lock', 'wb'); - if ($fp === false) - { - // We were unable to create the lock file - abort - $this->p_master->error($lang['UNABLE_WRITE_LOCK'], __LINE__, __FILE__); - } - @fclose($fp); - - @chmod($phpbb_root_path . 'cache/install_lock', 0777); - - // Time to convert the data provided into a config file - $config_data = phpbb_create_config_file_data($data, $available_dbms[$data['dbms']]['DRIVER']); - - // Attempt to write out the config file directly. If it works, this is the easiest way to do it ... - if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && $this->filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx)) || $this->filesystem->is_writable($phpbb_root_path)) - { - // Assume it will work ... if nothing goes wrong below - $written = true; - - if (!($fp = @fopen($phpbb_root_path . 'config.' . $phpEx, 'w'))) - { - // Something went wrong ... so let's try another method - $written = false; - } - - if (!(@fwrite($fp, $config_data))) - { - // Something went wrong ... so let's try another method - $written = false; - } - - @fclose($fp); - - if ($written) - { - // We may revert back to chmod() if we see problems with users not able to change their config.php file directly - try - { - $this->filesystem->phpbb_chmod($phpbb_root_path . 'config.' . $phpEx, CHMOD_READ); - } - catch (\phpbb\filesystem\exception\filesystem_exception $e) - { - // Do nothing - } - } - } - - if (isset($_POST['dldone'])) - { - // Do a basic check to make sure that the file has been uploaded - // Note that all we check is that the file has _something_ in it - // We don't compare the contents exactly - if they can't upload - // a single file correctly, it's likely they will have other problems.... - if (filesize($phpbb_root_path . 'config.' . $phpEx) > 10) - { - $written = true; - } - } - - $config_options = array_merge($this->db_config_options, $this->admin_config_options); - - foreach ($config_options as $config_key => $vars) - { - if (!is_array($vars)) - { - continue; - } - $s_hidden_fields .= ''; - } - - if (!$written) - { - // OK, so it didn't work let's try the alternatives - - if (isset($_POST['dlconfig'])) - { - // They want a copy of the file to download, so send the relevant headers and dump out the data - header("Content-Type: text/x-delimtext; name=\"config.$phpEx\""); - header("Content-disposition: attachment; filename=config.$phpEx"); - echo $config_data; - exit; - } - - // The option to download the config file is always available, so output it here - $template->assign_vars(array( - 'BODY' => $lang['CONFIG_FILE_UNABLE_WRITE'], - 'L_DL_CONFIG' => $lang['DL_CONFIG'], - 'L_DL_CONFIG_EXPLAIN' => $lang['DL_CONFIG_EXPLAIN'], - 'L_DL_DONE' => $lang['DONE'], - 'L_DL_DOWNLOAD' => $lang['DL_DOWNLOAD'], - 'S_HIDDEN' => $s_hidden_fields, - 'S_SHOW_DOWNLOAD' => true, - 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&sub=config_file", - )); - return; - } - else - { - $template->assign_vars(array( - 'BODY' => $lang['CONFIG_FILE_WRITTEN'], - 'L_SUBMIT' => $lang['NEXT_STEP'], - 'S_HIDDEN' => $s_hidden_fields, - 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&sub=advanced", - )); - return; - } - } - - /** - * Provide an opportunity to customise some advanced settings during the install - * in case it is necessary for them to be set to access later - */ - function obtain_advanced_settings($mode, $sub) - { - global $lang, $template, $phpEx, $request; - - $this->page_title = $lang['STAGE_ADVANCED']; - - // Obtain any submitted data - $data = $this->get_submitted_data(); - - if ($data['dbms'] == '') - { - // Someone's been silly and tried calling this page direct - // So we send them back to the start to do it again properly - $this->p_master->redirect("index.$phpEx?mode=install"); - } - - $s_hidden_fields = ($data['img_imagick']) ? '' : ''; - $s_hidden_fields .= ''; - - // HTTP_HOST is having the correct browser url in most cases... - $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME')))); - - // HTTP HOST can carry a port number... - if (strpos($server_name, ':') !== false) - { - $server_name = substr($server_name, 0, strpos($server_name, ':')); - } - - $data['email_enable'] = ($data['email_enable'] !== '') ? $data['email_enable'] : true; - $data['server_name'] = ($data['server_name'] !== '') ? $data['server_name'] : $server_name; - $data['server_port'] = ($data['server_port'] !== '') ? $data['server_port'] : $request->server('SERVER_PORT', 0); - $data['server_protocol'] = ($data['server_protocol'] !== '') ? $data['server_protocol'] : ($request->is_secure() ? 'https://' : 'http://'); - $data['cookie_secure'] = ($data['cookie_secure'] !== '') ? $data['cookie_secure'] : $request->is_secure(); - - if ($data['script_path'] === '') - { - $name = htmlspecialchars_decode($request->server('PHP_SELF')); - if (!$name) - { - $name = htmlspecialchars_decode($request->server('REQUEST_URI')); - } - - // Replace backslashes and doubled slashes (could happen on some proxy setups) - $name = str_replace(array('\\', '//'), '/', $name); - $data['script_path'] = trim(dirname(dirname($name))); - } - - foreach ($this->advanced_config_options as $config_key => $vars) - { - if (!is_array($vars) && strpos($config_key, 'legend') === false) - { - continue; - } - - if (strpos($config_key, 'legend') !== false) - { - $template->assign_block_vars('options', array( - 'S_LEGEND' => true, - 'LEGEND' => $lang[$vars]) - ); - - continue; - } - - $options = isset($vars['options']) ? $vars['options'] : ''; - - $template->assign_block_vars('options', array( - 'KEY' => $config_key, - 'TITLE' => $lang[$vars['lang']], - 'S_EXPLAIN' => $vars['explain'], - 'S_LEGEND' => false, - 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '', - 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options), - ) - ); - } - - $config_options = array_merge($this->db_config_options, $this->admin_config_options); - foreach ($config_options as $config_key => $vars) - { - if (!is_array($vars)) - { - continue; - } - $s_hidden_fields .= ''; - } - - $submit = $lang['NEXT_STEP']; - - $url = $this->p_master->module_url . "?mode=$mode&sub=create_table"; - - $template->assign_vars(array( - 'BODY' => $lang['STAGE_ADVANCED_EXPLAIN'], - 'L_SUBMIT' => $submit, - 'S_HIDDEN' => $s_hidden_fields, - 'U_ACTION' => $url, - )); - } - - /** - * Load the contents of the schema into the database and then alter it based on what has been input during the installation - */ - function load_schema($mode, $sub) - { - global $db, $lang, $template, $phpbb_root_path, $phpEx, $request; - - $this->page_title = $lang['STAGE_CREATE_TABLE']; - $s_hidden_fields = ''; - - // Obtain any submitted data - $data = $this->get_submitted_data(); - - if ($data['dbms'] == '') - { - // Someone's been silly and tried calling this page direct - // So we send them back to the start to do it again properly - $this->p_master->redirect("index.$phpEx?mode=install"); - } - - // HTTP_HOST is having the correct browser url in most cases... - $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME')))); - $referer = strtolower($request->header('Referer')); - - // HTTP HOST can carry a port number... - if (strpos($server_name, ':') !== false) - { - $server_name = substr($server_name, 0, strpos($server_name, ':')); - } - - $cookie_domain = ($data['server_name'] != '') ? $data['server_name'] : $server_name; - - // Try to come up with the best solution for cookie domain... - if (strpos($cookie_domain, 'www.') === 0) - { - $cookie_domain = str_replace('www.', '.', $cookie_domain); - } - - // If we get here and the extension isn't loaded it should be safe to just go ahead and load it - $available_dbms = get_available_dbms($data['dbms']); - - if (!isset($available_dbms[$data['dbms']])) - { - // Someone's been silly and tried providing a non-existant dbms - $this->p_master->redirect("index.$phpEx?mode=install"); - } - - $dbms = $available_dbms[$data['dbms']]['DRIVER']; - - // Instantiate the database - $db = new $dbms(); - $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false); - - // NOTE: trigger_error does not work here. - $db->sql_return_on_error(true); - - // If mysql is chosen, we need to adjust the schema filename slightly to reflect the correct version. ;) - if ($data['dbms'] == 'mysql') - { - if (version_compare($db->sql_server_info(true), '4.1.3', '>=')) - { - $available_dbms[$data['dbms']]['SCHEMA'] .= '_41'; - } - else - { - $available_dbms[$data['dbms']]['SCHEMA'] .= '_40'; - } - } - - // Ok we have the db info go ahead and read in the relevant schema - // and work on building the table - $dbms_schema = 'schemas/' . $available_dbms[$data['dbms']]['SCHEMA'] . '_schema.sql'; - - // How should we treat this schema? - $delimiter = $available_dbms[$data['dbms']]['DELIM']; - - if (file_exists($dbms_schema)) - { - $sql_query = @file_get_contents($dbms_schema); - $sql_query = preg_replace('#phpbb_#i', $data['table_prefix'], $sql_query); - $sql_query = phpbb_remove_comments($sql_query); - $sql_query = split_sql_file($sql_query, $delimiter); - - foreach ($sql_query as $sql) - { - // Ignore errors when the functions or types already exist - // to allow installing phpBB twice in the same database with - // a different prefix - $db->sql_query($sql); - } - unset($sql_query); - } - - // Ok we have the db info go ahead and work on building the table - if (file_exists('schemas/schema.json')) - { - $db_table_schema = @file_get_contents('schemas/schema.json'); - $db_table_schema = json_decode($db_table_schema, true); - } - else - { - global $phpbb_root_path, $phpEx, $table_prefix; - $table_prefix = 'phpbb_'; - - if (!defined('CONFIG_TABLE')) - { - // We need to include the constants file for the table constants - // when we generate the schema from the migration files. - include($phpbb_root_path . 'includes/constants.' . $phpEx); - } - - $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx); - $classes = $finder->core_path('phpbb/db/migration/data/') - ->get_classes(); - - $sqlite_db = new \phpbb\db\driver\sqlite(); - $factory = new \phpbb\db\tools\factory(); - $db_tools = $factory->get($sqlite_db, true); - $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $sqlite_db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix); - $db_table_schema = $schema_generator->get_schema(); - } - - if (!defined('CONFIG_TABLE')) - { - // CONFIG_TABLE is required by sql_create_index() to check the - // length of index names. However table_prefix is not defined - // here yet, so we need to create the constant ourselves. - define('CONFIG_TABLE', $data['table_prefix'] . 'config'); - } - - $factory = new \phpbb\db\tools\factory(); - $db_tools = $factory->get($db); - foreach ($db_table_schema as $table_name => $table_data) - { - $db_tools->sql_create_table( - $data['table_prefix'] . substr($table_name, 6), - $table_data - ); - } - - // Ok tables have been built, let's fill in the basic information - $sql_query = file_get_contents('schemas/schema_data.sql'); - - // Deal with any special comments and characters - switch ($data['dbms']) - { - case 'mssql': - case 'mssql_odbc': - case 'mssqlnative': - $sql_query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $sql_query); - break; - - case 'postgres': - $sql_query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $sql_query); - break; - - case 'mysql': - case 'mysqli': - $sql_query = str_replace('\\', '\\\\', $sql_query); - break; - } - - // Change prefix - $sql_query = preg_replace('# phpbb_([^\s]*) #i', ' ' . $data['table_prefix'] . '\1 ', $sql_query); - - // Change language strings... - $sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', 'adjust_language_keys_callback', $sql_query); - - $sql_query = phpbb_remove_comments($sql_query); - $sql_query = split_sql_file($sql_query, ';'); - - foreach ($sql_query as $sql) - { - //$sql = trim(str_replace('|', ';', $sql)); - if (!$db->sql_query($sql)) - { - $error = $db->sql_error(); - $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__); - } - } - unset($sql_query); - - $current_time = time(); - - $user_ip = $request->server('REMOTE_ADDR') ? phpbb_ip_normalise($request->server('REMOTE_ADDR')) : ''; - - if ($data['script_path'] !== '/') - { - // Adjust destination path (no trailing slash) - if (substr($data['script_path'], -1) == '/') - { - $data['script_path'] = substr($data['script_path'], 0, -1); - } - - $data['script_path'] = str_replace(array('../', './'), '', $data['script_path']); - - if ($data['script_path'][0] != '/') - { - $data['script_path'] = '/' . $data['script_path']; - } - } - - // Set default config and post data, this applies to all DB's - $sql_ary = array( - 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value) - VALUES ('board_startdate', '$current_time')", - - 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value) - VALUES ('default_lang', '" . $db->sql_escape($data['default_lang']) . "')", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['img_imagick']) . "' - WHERE config_name = 'img_imagick'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['server_name']) . "' - WHERE config_name = 'server_name'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['server_port']) . "' - WHERE config_name = 'server_port'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['board_email']) . "' - WHERE config_name = 'board_email'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['board_email']) . "' - WHERE config_name = 'board_contact'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($cookie_domain) . "' - WHERE config_name = 'cookie_domain'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($lang['default_dateformat']) . "' - WHERE config_name = 'default_dateformat'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['email_enable']) . "' - WHERE config_name = 'email_enable'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['smtp_delivery']) . "' - WHERE config_name = 'smtp_delivery'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['smtp_host']) . "' - WHERE config_name = 'smtp_host'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['smtp_auth']) . "' - WHERE config_name = 'smtp_auth_method'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['smtp_user']) . "' - WHERE config_name = 'smtp_username'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['smtp_pass']) . "' - WHERE config_name = 'smtp_password'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['cookie_secure']) . "' - WHERE config_name = 'cookie_secure'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['force_server_vars']) . "' - WHERE config_name = 'force_server_vars'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['script_path']) . "' - WHERE config_name = 'script_path'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['server_protocol']) . "' - WHERE config_name = 'server_protocol'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($data['admin_name']) . "' - WHERE config_name = 'newest_username'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . md5(mt_rand()) . "' - WHERE config_name = 'avatar_salt'", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . md5(mt_rand()) . "' - WHERE config_name = 'plupload_salt'", - - 'UPDATE ' . $data['table_prefix'] . "users - SET username = '" . $db->sql_escape($data['admin_name']) . "', user_password='" . $db->sql_escape(md5($data['admin_pass1'])) . "', user_ip = '" . $db->sql_escape($user_ip) . "', user_lang = '" . $db->sql_escape($data['default_lang']) . "', user_email='" . $db->sql_escape($data['board_email']) . "', user_dateformat='" . $db->sql_escape($lang['default_dateformat']) . "', user_email_hash = " . $db->sql_escape(phpbb_email_hash($data['board_email'])) . ", username_clean = '" . $db->sql_escape(utf8_clean_string($data['admin_name'])) . "' - WHERE username = 'Admin'", - - 'UPDATE ' . $data['table_prefix'] . "moderator_cache - SET username = '" . $db->sql_escape($data['admin_name']) . "' - WHERE username = 'Admin'", - - 'UPDATE ' . $data['table_prefix'] . "forums - SET forum_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "' - WHERE forum_last_poster_name = 'Admin'", - - 'UPDATE ' . $data['table_prefix'] . "topics - SET topic_first_poster_name = '" . $db->sql_escape($data['admin_name']) . "', topic_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "' - WHERE topic_first_poster_name = 'Admin' - OR topic_last_poster_name = 'Admin'", - - 'UPDATE ' . $data['table_prefix'] . "users - SET user_regdate = $current_time", - - 'UPDATE ' . $data['table_prefix'] . "posts - SET post_time = $current_time, poster_ip = '" . $db->sql_escape($user_ip) . "'", - - 'UPDATE ' . $data['table_prefix'] . "topics - SET topic_time = $current_time, topic_last_post_time = $current_time", - - 'UPDATE ' . $data['table_prefix'] . "forums - SET forum_last_post_time = $current_time", - - 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($db->sql_server_info(true)) . "' - WHERE config_name = 'dbms_version'", - ); - - if (@extension_loaded('gd')) - { - $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = 'core.captcha.plugins.gd' - WHERE config_name = 'captcha_plugin'"; - - $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '1' - WHERE config_name = 'captcha_gd'"; - } - - $ref = substr($referer, strpos($referer, '://') + 3); - - if (!(stripos($ref, $server_name) === 0)) - { - $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '0' - WHERE config_name = 'referer_validation'"; - } - - // We set a (semi-)unique cookie name to bypass login issues related to the cookie name. - $cookie_name = 'phpbb3_'; - $rand_str = md5(mt_rand()); - $rand_str = str_replace('0', 'z', base_convert($rand_str, 16, 35)); - $rand_str = substr($rand_str, 0, 5); - $cookie_name .= strtolower($rand_str); - - $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '" . $db->sql_escape($cookie_name) . "' - WHERE config_name = 'cookie_name'"; - - foreach ($sql_ary as $sql) - { - //$sql = trim(str_replace('|', ';', $sql)); - - if (!$db->sql_query($sql)) - { - $error = $db->sql_error(); - $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__); - } - } - - $submit = $lang['NEXT_STEP']; - - $url = $this->p_master->module_url . "?mode=$mode&sub=final"; - - $template->assign_vars(array( - 'BODY' => $lang['STAGE_CREATE_TABLE_EXPLAIN'], - 'L_SUBMIT' => $submit, - 'S_HIDDEN' => build_hidden_fields($data), - 'U_ACTION' => $url, - )); - } - - /** - * Build the search index... - */ - function build_search_index($mode, $sub) - { - global $db, $lang, $phpbb_root_path, $phpbb_dispatcher, $phpEx, $config, $auth, $user; - - // Obtain any submitted data - $data = $this->get_submitted_data(); - $table_prefix = $data['table_prefix']; - - // If we get here and the extension isn't loaded it should be safe to just go ahead and load it - $available_dbms = get_available_dbms($data['dbms']); - - if (!isset($available_dbms[$data['dbms']])) - { - // Someone's been silly and tried providing a non-existant dbms - $this->p_master->redirect("index.$phpEx?mode=install"); - } - - $dbms = $available_dbms[$data['dbms']]['DRIVER']; - - // Instantiate the database - $db = new $dbms(); - $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false); - - // NOTE: trigger_error does not work here. - $db->sql_return_on_error(true); - - include_once($phpbb_root_path . 'includes/constants.' . $phpEx); - include_once($phpbb_root_path . 'phpbb/search/fulltext_native.' . $phpEx); - - // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); - - $error = false; - $search = new \phpbb\search\fulltext_native($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); - - $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id - FROM ' . POSTS_TABLE; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); - } - $db->sql_freeresult($result); - } - - /** - * Populate the module tables - */ - function add_modules($mode, $sub) - { - global $db, $lang, $phpbb_root_path, $phpEx, $phpbb_extension_manager, $config, $phpbb_container; - - // modules require an extension manager - if (empty($phpbb_extension_manager)) - { - /* @var $phpbb_extension_manager \phpbb\extension\manager */ - $phpbb_extension_manager = $phpbb_container->get('ext.manager'); - } - - $_module = new \phpbb\module\module_manager( - new \phpbb\cache\driver\dummy(), - $db, - $phpbb_extension_manager, - MODULES_TABLE, - $phpbb_root_path, - $phpEx - ); - $module_classes = array('acp', 'mcp', 'ucp'); - - // Add categories - foreach ($module_classes as $module_class) - { - $categories = array(); - - // Set the module class - $_module->module_class = $module_class; - - foreach ($this->module_categories[$module_class] as $cat_name => $subs) - { - $basename = ''; - // Check if this sub-category has a basename. If it has, use it. - if (isset($this->module_categories_basenames[$cat_name])) - { - $basename = $this->module_categories_basenames[$cat_name]; - } - $module_data = array( - 'module_basename' => $basename, - 'module_enabled' => 1, - 'module_display' => 1, - 'parent_id' => 0, - 'module_class' => $module_class, - 'module_langname' => $cat_name, - 'module_mode' => '', - 'module_auth' => '', - ); - - // Add category - $_module->update_module_data($module_data); - - // Check for last sql error happened - if ($db->get_sql_error_triggered()) - { - $error = $db->sql_error($db->get_sql_error_sql()); - $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); - } - - $categories[$cat_name]['id'] = (int) $module_data['module_id']; - $categories[$cat_name]['parent_id'] = 0; - - // Create sub-categories... - if (is_array($subs)) - { - foreach ($subs as $level2_name) - { - $basename = ''; - // Check if this sub-category has a basename. If it has, use it. - if (isset($this->module_categories_basenames[$level2_name])) - { - $basename = $this->module_categories_basenames[$level2_name]; - } - $module_data = array( - 'module_basename' => $basename, - 'module_enabled' => 1, - 'module_display' => 1, - 'parent_id' => (int) $categories[$cat_name]['id'], - 'module_class' => $module_class, - 'module_langname' => $level2_name, - 'module_mode' => '', - 'module_auth' => '', - ); - - $_module->update_module_data($module_data); - - // Check for last sql error happened - if ($db->get_sql_error_triggered()) - { - $error = $db->sql_error($db->get_sql_error_sql()); - $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); - } - - $categories[$level2_name]['id'] = (int) $module_data['module_id']; - $categories[$level2_name]['parent_id'] = (int) $categories[$cat_name]['id']; - } - } - } - - // Get the modules we want to add... returned sorted by name - $module_info = $_module->get_module_infos($module_class); - - foreach ($module_info as $module_basename => $fileinfo) - { - foreach ($fileinfo['modes'] as $module_mode => $row) - { - foreach ($row['cat'] as $cat_name) - { - if (!isset($categories[$cat_name])) - { - continue; - } - - $module_data = array( - 'module_basename' => $module_basename, - 'module_enabled' => 1, - 'module_display' => (isset($row['display'])) ? (int) $row['display'] : 1, - 'parent_id' => (int) $categories[$cat_name]['id'], - 'module_class' => $module_class, - 'module_langname' => $row['title'], - 'module_mode' => $module_mode, - 'module_auth' => $row['auth'], - ); - - $_module->update_module_data($module_data); - - // Check for last sql error happened - if ($db->get_sql_error_triggered()) - { - $error = $db->sql_error($db->get_sql_error_sql()); - $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); - } - } - } - } - - // Move some of the modules around since the code above will put them in the wrong place - if ($module_class == 'acp') - { - // Move main module 4 up... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_basename = 'acp_main' - AND module_class = 'acp' - AND module_mode = 'main'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'acp', 'move_up', 4); - - // Move permissions intro screen module 4 up... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_basename = 'acp_permissions' - AND module_class = 'acp' - AND module_mode = 'intro'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'acp', 'move_up', 4); - - // Move manage users screen module 5 up... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_basename = 'acp_users' - AND module_class = 'acp' - AND module_mode = 'overview'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'acp', 'move_up', 5); - - // Move extension management module 1 up... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_langname = 'ACP_EXTENSION_MANAGEMENT' - AND module_class = 'acp' - AND module_mode = '' - AND module_basename = ''"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'acp', 'move_up', 1); - } - - if ($module_class == 'mcp') - { - // Move pm report details module 3 down... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_basename = 'mcp_pm_reports' - AND module_class = 'mcp' - AND module_mode = 'pm_report_details'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'mcp', 'move_down', 3); - - // Move closed pm reports module 3 down... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_basename = 'mcp_pm_reports' - AND module_class = 'mcp' - AND module_mode = 'pm_reports_closed'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'mcp', 'move_down', 3); - - // Move open pm reports module 3 down... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_basename = 'mcp_pm_reports' - AND module_class = 'mcp' - AND module_mode = 'pm_reports'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'mcp', 'move_down', 3); - } - - if ($module_class == 'ucp') - { - // Move attachment module 4 down... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_basename = 'ucp_attachments' - AND module_class = 'ucp' - AND module_mode = 'attachments'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'ucp', 'move_down', 4); - - // Move notification options module 4 down... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_basename = 'ucp_notifications' - AND module_class = 'ucp' - AND module_mode = 'notification_options'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'ucp', 'move_down', 4); - - // Move OAuth module 5 down... - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_basename = 'ucp_auth_link' - AND module_class = 'ucp' - AND module_mode = 'auth_link'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $_module->move_module_by($row, 'ucp', 'move_down', 5); - } - - // And now for the special ones - // (these are modules which appear in multiple categories and thus get added manually to some for more control) - if (isset($this->module_extras[$module_class])) - { - foreach ($this->module_extras[$module_class] as $cat_name => $mods) - { - $sql = 'SELECT module_id, left_id, right_id - FROM ' . MODULES_TABLE . " - WHERE module_langname = '" . $db->sql_escape($cat_name) . "' - AND module_class = '" . $db->sql_escape($module_class) . "'"; - $result = $db->sql_query_limit($sql, 1); - $row2 = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - foreach ($mods as $mod_name) - { - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_langname = '" . $db->sql_escape($mod_name) . "' - AND module_class = '" . $db->sql_escape($module_class) . "' - AND module_basename <> ''"; - $result = $db->sql_query_limit($sql, 1); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $module_data = array( - 'module_basename' => $row['module_basename'], - 'module_enabled' => (int) $row['module_enabled'], - 'module_display' => (int) $row['module_display'], - 'parent_id' => (int) $row2['module_id'], - 'module_class' => $row['module_class'], - 'module_langname' => $row['module_langname'], - 'module_mode' => $row['module_mode'], - 'module_auth' => $row['module_auth'], - ); - - $_module->update_module_data($module_data); - - // Check for last sql error happened - if ($db->get_sql_error_triggered()) - { - $error = $db->sql_error($db->get_sql_error_sql()); - $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); - } - } - } - } - - $_module->remove_cache_file($module_class); - } - } - - /** - * Populate the language tables - */ - function add_language($mode, $sub) - { - global $db, $lang, $phpbb_root_path, $phpEx; - - $dir = @opendir($phpbb_root_path . 'language'); - - if (!$dir) - { - $this->error('Unable to access the language directory', __LINE__, __FILE__); - } - - $installed_languages = array(); - while (($file = readdir($dir)) !== false) - { - $path = $phpbb_root_path . 'language/' . $file; - - if ($file == '.' || $file == '..' || is_link($path) || is_file($path) || $file == 'CVS') - { - continue; - } - - if (is_dir($path) && file_exists($path . '/iso.txt')) - { - $lang_file = file("$path/iso.txt"); - - $lang_pack = array( - 'lang_iso' => basename($path), - 'lang_dir' => basename($path), - 'lang_english_name' => trim(htmlspecialchars($lang_file[0])), - 'lang_local_name' => trim(htmlspecialchars($lang_file[1], ENT_COMPAT, 'UTF-8')), - 'lang_author' => trim(htmlspecialchars($lang_file[2], ENT_COMPAT, 'UTF-8')), - ); - - $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $lang_pack)); - - $installed_languages[] = (int) $db->sql_nextid(); - if ($db->get_sql_error_triggered()) - { - $error = $db->sql_error($db->get_sql_error_sql()); - $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); - } - } - } - closedir($dir); - - $sql = 'SELECT * - FROM ' . PROFILE_FIELDS_TABLE; - $result = $db->sql_query($sql); - - $profile_fields = array(); - $insert_buffer = new \phpbb\db\sql_insert_buffer($db, PROFILE_LANG_TABLE); - while ($row = $db->sql_fetchrow($result)) - { - foreach ($installed_languages as $lang_id) - { - $insert_buffer->insert(array( - 'field_id' => $row['field_id'], - 'lang_id' => $lang_id, - 'lang_name' => strtoupper(substr($row['field_name'], 6)),// Remove phpbb_ from field name - 'lang_explain' => '', - 'lang_default_value' => '', - )); - } - } - $db->sql_freeresult($result); - - $insert_buffer->flush(); - } - - /** - * Add search robots to the database - */ - function add_bots($mode, $sub) - { - global $db, $lang, $phpbb_root_path, $phpEx, $config; - - // Obtain any submitted data - $data = $this->get_submitted_data(); - - // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); - - $sql = 'SELECT group_id - FROM ' . GROUPS_TABLE . " - WHERE group_name = 'BOTS'"; - $result = $db->sql_query($sql); - $group_id = (int) $db->sql_fetchfield('group_id'); - $db->sql_freeresult($result); - - if (!$group_id) - { - // If we reach this point then something has gone very wrong - $this->p_master->error($lang['NO_GROUP'], __LINE__, __FILE__); - } - - if (!function_exists('user_add')) - { - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); - } - - foreach ($this->bot_list as $bot_name => $bot_ary) - { - $user_row = array( - 'user_type' => USER_IGNORE, - 'group_id' => $group_id, - 'username' => $bot_name, - 'user_regdate' => time(), - 'user_password' => '', - 'user_colour' => '9E8DA7', - 'user_email' => '', - 'user_lang' => $data['default_lang'], - 'user_style' => 1, - 'user_timezone' => 'UTC', - 'user_dateformat' => $lang['default_dateformat'], - 'user_allow_massemail' => 0, - 'user_allow_pm' => 0, - ); - - $user_id = user_add($user_row); - - if (!$user_id) - { - // If we can't insert this user then continue to the next one to avoid inconsistent data - $this->p_master->db_error('Unable to insert bot into users table', $db->get_sql_error_sql(), __LINE__, __FILE__, true); - continue; - } - - $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'bot_active' => 1, - 'bot_name' => (string) $bot_name, - 'user_id' => (int) $user_id, - 'bot_agent' => (string) $bot_ary[0], - 'bot_ip' => (string) $bot_ary[1], - )); - - $db->sql_query($sql); - } - } - - /** - * Sends an email to the board administrator with their password and some useful links - */ - function email_admin($mode, $sub) - { - global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; - - $this->page_title = $lang['STAGE_FINAL']; - - // Obtain any submitted data - $data = $this->get_submitted_data(); - - // We need to fill the config to let internal functions correctly work - $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); - - $user->session_begin(); - $auth->login($data['admin_name'], $data['admin_pass1'], false, true, true); - - // OK, Now that we've reached this point we can be confident that everything - // is installed and working......I hope :) - // So it's time to send an email to the administrator confirming the details - // they entered - - if ($config['email_enable']) - { - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - - $messenger = new messenger(false); - - $messenger->template('installed', $data['language']); - - $messenger->to($data['board_email'], $data['admin_name']); - - $messenger->anti_abuse_headers($config, $user); - - $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($data['admin_name']), - 'PASSWORD' => htmlspecialchars_decode($data['admin_pass1'])) - ); - - $messenger->send(NOTIFY_EMAIL); - } - - // And finally, add a note to the log - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_INSTALLED', false, array($config['version'])); - - $template->assign_vars(array( - 'TITLE' => $lang['INSTALL_CONGRATS'], - 'BODY' => sprintf($lang['INSTALL_CONGRATS_EXPLAIN'], $config['version'], append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=convert&language=' . $data['language']), '../docs/README.html'), - 'L_SUBMIT' => $lang['INSTALL_LOGIN'], - 'U_ACTION' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'i=send_statistics&mode=send_statistics'), - )); - } - - /** - * Check if the avatar directory is writable and disable avatars - * if it isn't writable. - */ - function disable_avatars_if_unwritable() - { - global $config, $phpbb_root_path; - - if (!$this->filesystem->is_writable($phpbb_root_path . 'images/avatars/upload/')) - { - $config->set('allow_avatar', 0); - $config->set('allow_avatar_upload', 0); - } - } - - /** - * Populate migrations for the installation - * - * This "installs" all migrations from (root path)/phpbb/db/migrations/data. - * "installs" means it adds all migrations to the migrations table, but does not - * perform any of the actions in the migrations. - * - * @param \phpbb\extension\manager $extension_manager - * @param \phpbb\db\migrator $migrator - */ - function populate_migrations($extension_manager, $migrator) - { - $finder = $extension_manager->get_finder(); - - $migrations = $finder - ->core_path('phpbb/db/migration/data/') - ->get_classes(); - $migrator->populate_migrations($migrations); - } - - /** - * Generate a list of available mail server authentication methods - */ - function mail_auth_select($selected_method) - { - global $lang; - - $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP'); - $s_smtp_auth_options = ''; - - foreach ($auth_methods as $method) - { - $s_smtp_auth_options .= ''; - } - - return $s_smtp_auth_options; - } - - /** - * Get submitted data - */ - function get_submitted_data() - { - global $request; - - return array( - 'language' => basename($request->variable('language', '')), - 'dbms' => $request->variable('dbms', ''), - 'dbhost' => $request->variable('dbhost', ''), - 'dbport' => $request->variable('dbport', ''), - 'dbuser' => $request->variable('dbuser', ''), - 'dbpasswd' => $request->variable('dbpasswd', '', true), - 'dbname' => $request->variable('dbname', ''), - 'table_prefix' => $request->variable('table_prefix', ''), - 'default_lang' => basename($request->variable('default_lang', '')), - 'admin_name' => $request->variable('admin_name', '', true), - 'admin_pass1' => $request->variable('admin_pass1', '', true), - 'admin_pass2' => $request->variable('admin_pass2', '', true), - 'board_email' => strtolower($request->variable('board_email', '')), - 'img_imagick' => $request->variable('img_imagick', ''), - 'ftp_path' => $request->variable('ftp_path', ''), - 'ftp_user' => $request->variable('ftp_user', ''), - 'ftp_pass' => $request->variable('ftp_pass', ''), - 'email_enable' => $request->variable('email_enable', ''), - 'smtp_delivery' => $request->variable('smtp_delivery', ''), - 'smtp_host' => $request->variable('smtp_host', ''), - 'smtp_auth' => $request->variable('smtp_auth', ''), - 'smtp_user' => $request->variable('smtp_user', ''), - 'smtp_pass' => $request->variable('smtp_pass', ''), - 'cookie_secure' => $request->variable('cookie_secure', ''), - 'force_server_vars' => $request->variable('force_server_vars', ''), - 'server_protocol' => $request->variable('server_protocol', ''), - 'server_name' => $request->variable('server_name', ''), - 'server_port' => $request->variable('server_port', ''), - 'script_path' => $request->variable('script_path', ''), - ); - } - - /** - * The information below will be used to build the input fields presented to the user - */ - var $db_config_options = array( - 'legend1' => 'DB_CONFIG', - 'dbms' => array('lang' => 'DBMS', 'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\')', 'explain' => false), - 'dbhost' => array('lang' => 'DB_HOST', 'type' => 'text:25:100', 'explain' => true), - 'dbport' => array('lang' => 'DB_PORT', 'type' => 'text:25:100', 'explain' => true), - 'dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false), - 'dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false), - 'dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false), - 'table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => true), - ); - var $admin_config_options = array( - 'legend1' => 'ADMIN_CONFIG', - 'default_lang' => array('lang' => 'DEFAULT_LANG', 'type' => 'select', 'options' => '$this->module->inst_language_select(\'{VALUE}\')', 'explain' => false), - 'admin_name' => array('lang' => 'ADMIN_USERNAME', 'type' => 'text:25:100', 'explain' => true), - 'admin_pass1' => array('lang' => 'ADMIN_PASSWORD', 'type' => 'password:25:100', 'explain' => true), - 'admin_pass2' => array('lang' => 'ADMIN_PASSWORD_CONFIRM', 'type' => 'password:25:100', 'explain' => false), - 'board_email' => array('lang' => 'CONTACT_EMAIL', 'type' => 'email:25:100', 'explain' => false), - ); - var $advanced_config_options = array( - 'legend1' => 'ACP_EMAIL_SETTINGS', - 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'type' => 'radio:enabled_disabled', 'explain' => true), - 'smtp_delivery' => array('lang' => 'USE_SMTP', 'type' => 'radio:yes_no', 'explain' => true), - 'smtp_host' => array('lang' => 'SMTP_SERVER', 'type' => 'text:25:50', 'explain' => false), - 'smtp_auth' => array('lang' => 'SMTP_AUTH_METHOD', 'type' => 'select', 'options' => '$this->module->mail_auth_select(\'{VALUE}\')', 'explain' => true), - 'smtp_user' => array('lang' => 'SMTP_USERNAME', 'type' => 'text:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')), - 'smtp_pass' => array('lang' => 'SMTP_PASSWORD', 'type' => 'password:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')), - - 'legend2' => 'SERVER_URL_SETTINGS', - 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'type' => 'radio:enabled_disabled', 'explain' => true), - 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'type' => 'radio:yes_no', 'explain' => true), - 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'type' => 'text:10:10', 'explain' => true), - 'server_name' => array('lang' => 'SERVER_NAME', 'type' => 'text:40:255', 'explain' => true), - 'server_port' => array('lang' => 'SERVER_PORT', 'type' => 'text:5:5', 'explain' => true), - 'script_path' => array('lang' => 'SCRIPT_PATH', 'type' => 'text::255', 'explain' => true), - ); - - /** - * Specific PHP modules we may require for certain optional or extended features - */ - var $php_dlls_other = array('zlib', 'ftp', 'gd', 'xml'); - - /** - * A list of the web-crawlers/bots we recognise by default - * - * Candidates but not included: - * 'Accoona [Bot]' 'Accoona-AI-Agent/' - * 'ASPseek [Crawler]' 'ASPseek/' - * 'Boitho [Crawler]' 'boitho.com-dc/' - * 'Bunnybot [Bot]' 'powered by www.buncat.de' - * 'Cosmix [Bot]' 'cfetch/' - * 'Crawler Search [Crawler]' '.Crawler-Search.de' - * 'Findexa [Crawler]' 'Findexa Crawler (' - * 'GBSpider [Spider]' 'GBSpider v' - * 'genie [Bot]' 'genieBot (' - * 'Hogsearch [Bot]' 'oegp v. 1.3.0' - * 'Insuranco [Bot]' 'InsurancoBot' - * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler' - * 'ISC Systems [Bot]' 'ISC Systems iRc Search' - * 'Jyxobot [Bot]' 'Jyxobot/' - * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/' - * 'LinkWalker' 'LinkWalker' - * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html' - * 'Naver [Bot]' 'nhnbot@naver.com)' - * 'NetResearchServer' 'NetResearchServer/' - * 'Nimble [Crawler]' 'NimbleCrawler' - * 'Ocelli [Bot]' 'Ocelli/' - * 'Onsearch [Bot]' 'onCHECK-Robot' - * 'Orange [Spider]' 'OrangeSpider' - * 'Sproose [Bot]' 'http://www.sproose.com/bot' - * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)' - * 'Tbot [Bot]' 'Tbot/' - * 'Thumbshots [Capture]' 'thumbshots-de-Bot' - * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/' - * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)' - * 'WissenOnline [Bot]' 'WissenOnline-Bot' - * 'WWWeasel [Bot]' 'WWWeasel Robot v' - * 'Xaldon [Spider]' 'Xaldon WebSpider' - */ - var $bot_list = array( - 'AdsBot [Google]' => array('AdsBot-Google', ''), - 'Alexa [Bot]' => array('ia_archiver', ''), - 'Alta Vista [Bot]' => array('Scooter/', ''), - 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''), - 'Baidu [Spider]' => array('Baiduspider', ''), - 'Bing [Bot]' => array('bingbot/', ''), - 'Exabot [Bot]' => array('Exabot', ''), - 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''), - 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''), - 'Francis [Bot]' => array('http://www.neomo.de/', ''), - 'Gigabot [Bot]' => array('Gigabot/', ''), - 'Google Adsense [Bot]' => array('Mediapartners-Google', ''), - 'Google Desktop' => array('Google Desktop', ''), - 'Google Feedfetcher' => array('Feedfetcher-Google', ''), - 'Google [Bot]' => array('Googlebot', ''), - 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''), - 'Heritrix [Crawler]' => array('heritrix/1.', ''), - 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''), - 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''), - 'ichiro [Crawler]' => array('ichiro/', ''), - 'Majestic-12 [Bot]' => array('MJ12bot/', ''), - 'Metager [Bot]' => array('MetagerBot/', ''), - 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''), - 'MSN [Bot]' => array('msnbot/', ''), - 'MSNbot Media' => array('msnbot-media/', ''), - 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''), - 'Online link [Validator]' => array('online link validator', ''), - 'psbot [Picsearch]' => array('psbot/0', ''), - 'Sensis [Crawler]' => array('Sensis Web Crawler', ''), - 'SEO Crawler' => array('SEO search Crawler/', ''), - 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''), - 'SEOSearch [Crawler]' => array('SEOsearch/', ''), - 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''), - 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''), - 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''), - 'TurnitinBot [Bot]' => array('TurnitinBot/', ''), - 'Voyager [Bot]' => array('voyager/', ''), - 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''), - 'W3C [Linkcheck]' => array('W3C-checklink/', ''), - 'W3C [Validator]' => array('W3C_Validator', ''), - 'YaCy [Bot]' => array('yacybot', ''), - 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''), - 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''), - 'Yahoo [Bot]' => array('Yahoo! Slurp', ''), - 'YahooSeeker [Bot]' => array('YahooSeeker/', ''), - ); - - /** - * Define the module structure so that we can populate the database without - * needing to hard-code module_id values - */ - var $module_categories = array( - 'acp' => array( - 'ACP_CAT_GENERAL' => array( - 'ACP_QUICK_ACCESS', - 'ACP_BOARD_CONFIGURATION', - 'ACP_CLIENT_COMMUNICATION', - 'ACP_SERVER_CONFIGURATION', - ), - 'ACP_CAT_FORUMS' => array( - 'ACP_MANAGE_FORUMS', - 'ACP_FORUM_BASED_PERMISSIONS', - ), - 'ACP_CAT_POSTING' => array( - 'ACP_MESSAGES', - 'ACP_ATTACHMENTS', - ), - 'ACP_CAT_USERGROUP' => array( - 'ACP_CAT_USERS', - 'ACP_GROUPS', - 'ACP_USER_SECURITY', - ), - 'ACP_CAT_PERMISSIONS' => array( - 'ACP_GLOBAL_PERMISSIONS', - 'ACP_FORUM_BASED_PERMISSIONS', - 'ACP_PERMISSION_ROLES', - 'ACP_PERMISSION_MASKS', - ), - 'ACP_CAT_CUSTOMISE' => array( - 'ACP_STYLE_MANAGEMENT', - 'ACP_EXTENSION_MANAGEMENT', - 'ACP_LANGUAGE', - ), - 'ACP_CAT_MAINTENANCE' => array( - 'ACP_FORUM_LOGS', - 'ACP_CAT_DATABASE', - ), - 'ACP_CAT_SYSTEM' => array( - 'ACP_AUTOMATION', - 'ACP_GENERAL_TASKS', - 'ACP_MODULE_MANAGEMENT', - ), - 'ACP_CAT_DOT_MODS' => null, - ), - 'mcp' => array( - 'MCP_MAIN' => null, - 'MCP_QUEUE' => null, - 'MCP_REPORTS' => null, - 'MCP_NOTES' => null, - 'MCP_WARN' => null, - 'MCP_LOGS' => null, - 'MCP_BAN' => null, - ), - 'ucp' => array( - 'UCP_MAIN' => null, - 'UCP_PROFILE' => null, - 'UCP_PREFS' => null, - 'UCP_PM' => null, - 'UCP_USERGROUPS' => null, - 'UCP_ZEBRA' => null, - ), - ); - var $module_categories_basenames = array( - 'UCP_PM' => 'ucp_pm', - ); - - var $module_extras = array( - 'acp' => array( - 'ACP_QUICK_ACCESS' => array( - 'ACP_MANAGE_USERS', - 'ACP_GROUPS_MANAGE', - 'ACP_MANAGE_FORUMS', - 'ACP_MOD_LOGS', - 'ACP_BOTS', - 'ACP_PHP_INFO', - ), - 'ACP_FORUM_BASED_PERMISSIONS' => array( - 'ACP_FORUM_PERMISSIONS', - 'ACP_FORUM_PERMISSIONS_COPY', - 'ACP_FORUM_MODERATORS', - 'ACP_USERS_FORUM_PERMISSIONS', - 'ACP_GROUPS_FORUM_PERMISSIONS', - ), - ), - ); -} diff --git a/phpBB/install/install_main.php b/phpBB/install/install_main.php deleted file mode 100644 index d5874dac83..0000000000 --- a/phpBB/install/install_main.php +++ /dev/null @@ -1,78 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -/** -*/ - -if ( !defined('IN_INSTALL') ) -{ - // Someone has tried to access the file direct. This is not a good idea, so exit - exit; -} - -if (!empty($setmodules)) -{ - $module[] = array( - 'module_type' => 'install', - 'module_title' => 'OVERVIEW', - 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1), - 'module_order' => 0, - 'module_subs' => array('INTRO', 'LICENSE', 'SUPPORT'), - 'module_stages' => '', - 'module_reqs' => '' - ); -} - -/** -* Main Tab - Installation -*/ -class install_main extends module -{ - function install_main(&$p_master) - { - $this->p_master = &$p_master; - } - - function main($mode, $sub) - { - global $lang, $template, $language; - - switch ($sub) - { - case 'intro' : - $title = $lang['SUB_INTRO']; - $body = $lang['OVERVIEW_BODY']; - break; - - case 'license' : - $title = $lang['GPL']; - $body = implode("
            \n", file(__DIR__ . '/../docs/LICENSE.txt')); - break; - - case 'support' : - $title = $lang['SUB_SUPPORT']; - $body = $lang['SUPPORT_BODY']; - break; - } - - $this->tpl_name = 'install_main'; - $this->page_title = $title; - - $template->assign_vars(array( - 'TITLE' => $title, - 'BODY' => $body, - - 'S_LANG_SELECT' => '', - )); - } -} diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install_old/convertors/convert_phpbb20.php similarity index 100% rename from phpBB/install/convertors/convert_phpbb20.php rename to phpBB/install_old/convertors/convert_phpbb20.php diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install_old/convertors/functions_phpbb20.php similarity index 100% rename from phpBB/install/convertors/functions_phpbb20.php rename to phpBB/install_old/convertors/functions_phpbb20.php diff --git a/phpBB/install/data/confusables.php b/phpBB/install_old/data/confusables.php similarity index 100% rename from phpBB/install/data/confusables.php rename to phpBB/install_old/data/confusables.php diff --git a/phpBB/install/database_update.php b/phpBB/install_old/database_update.php similarity index 100% rename from phpBB/install/database_update.php rename to phpBB/install_old/database_update.php diff --git a/phpBB/install/index.php b/phpBB/install_old/index.php similarity index 100% rename from phpBB/install/index.php rename to phpBB/install_old/index.php diff --git a/phpBB/install/install_convert.php b/phpBB/install_old/install_convert.php similarity index 100% rename from phpBB/install/install_convert.php rename to phpBB/install_old/install_convert.php diff --git a/phpBB/install/install_update.php b/phpBB/install_old/install_update.php similarity index 100% rename from phpBB/install/install_update.php rename to phpBB/install_old/install_update.php diff --git a/phpBB/install/phpinfo.php b/phpBB/install_old/phpinfo.php similarity index 100% rename from phpBB/install/phpinfo.php rename to phpBB/install_old/phpinfo.php From 5afc632bcaee256811942b442d244ef284d1eff6 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Tue, 28 Apr 2015 15:49:07 +0200 Subject: [PATCH 0438/1676] [ticket/13740] Core file workarounds [ci skip] PHPBB3-13740 --- phpBB/common.php | 2 +- phpBB/config/default/container/services.yml | 32 +----- .../default/container/services_files.yml | 3 + .../default/container/services_http.yml | 23 +++++ .../config/default/container/services_php.yml | 3 + phpBB/config/default/container/tables.yml | 1 + phpBB/includes/compatibility_globals.php | 99 +++++++++++-------- 7 files changed, 92 insertions(+), 71 deletions(-) create mode 100644 phpBB/config/default/container/services_files.yml create mode 100644 phpBB/config/default/container/services_http.yml create mode 100644 phpBB/config/default/container/services_php.yml diff --git a/phpBB/common.php b/phpBB/common.php index 0b898d9553..38761cfadc 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -52,7 +52,7 @@ if (!defined('PHPBB_INSTALLED')) } // $phpbb_root_path accounts for redirects from e.g. /adm - $script_path = trim(dirname($script_name)) . '/' . $phpbb_root_path . 'install/index.' . $phpEx; + $script_path = trim(dirname($script_name)) . '/' . $phpbb_root_path . 'install/app.' . $phpEx; // Replace any number of consecutive backslashes and/or slashes with a single slash // (could happen on some proxy setups and/or Windows servers) $script_path = preg_replace('#[\\\\/]{2,}#', '/', $script_path); diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index aec61e0272..841b50c38b 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -8,13 +8,16 @@ imports: - { resource: services_db.yml } - { resource: services_event.yml } - { resource: services_feed.yml } + - { resource: services_files.yml } - { resource: services_help.yml } + - { resource: services_http.yml } - { resource: services_language.yml } - { resource: services_migrator.yml } - { resource: services_mimetype_guesser.yml } - { resource: services_module.yml } - { resource: services_notification.yml } - { resource: services_password.yml } + - { resource: services_php.yml } - { resource: services_profilefield.yml } - { resource: services_report.yml } - { resource: services_routing.yml } @@ -107,19 +110,9 @@ services: - %core.php_ext% - @cache.driver - filesystem: - class: phpbb\filesystem\filesystem - file_downloader: class: phpbb\file_downloader - http_kernel: - class: Symfony\Component\HttpKernel\HttpKernel - arguments: - - @dispatcher - - @controller.resolver - - @request_stack - log: class: phpbb\log\log arguments: @@ -142,9 +135,6 @@ services: - %core.php_ext% - %core.adm_relative_path% - php_ini: - class: phpbb\php\ini - plupload: class: phpbb\plupload\plupload arguments: @@ -155,22 +145,6 @@ services: - @php_ini - @mimetype.guesser - request: - class: phpbb\request\request - arguments: - - null - - %core.disable_super_globals% - - # WARNING: The Symfony request does not escape the input and should be used very carefully - # prefer the phpbb request (service @request) as possible - symfony_request: - class: phpbb\symfony_request - arguments: - - @request - - request_stack: - class: Symfony\Component\HttpFoundation\RequestStack - upload_imagesize: class: fastImageSize\fastImageSize diff --git a/phpBB/config/default/container/services_files.yml b/phpBB/config/default/container/services_files.yml new file mode 100644 index 0000000000..828f9076dd --- /dev/null +++ b/phpBB/config/default/container/services_files.yml @@ -0,0 +1,3 @@ +services: + filesystem: + class: phpbb\filesystem\filesystem diff --git a/phpBB/config/default/container/services_http.yml b/phpBB/config/default/container/services_http.yml new file mode 100644 index 0000000000..9c2bdd2337 --- /dev/null +++ b/phpBB/config/default/container/services_http.yml @@ -0,0 +1,23 @@ +services: + # WARNING: The Symfony request does not escape the input and should be used very carefully + # prefer the phpbb request (service @request) as possible + symfony_request: + class: phpbb\symfony_request + arguments: + - @request + + request_stack: + class: Symfony\Component\HttpFoundation\RequestStack + + request: + class: phpbb\request\request + arguments: + - null + - %core.disable_super_globals% + + http_kernel: + class: Symfony\Component\HttpKernel\HttpKernel + arguments: + - @dispatcher + - @controller.resolver + - @request_stack diff --git a/phpBB/config/default/container/services_php.yml b/phpBB/config/default/container/services_php.yml new file mode 100644 index 0000000000..8aabc7341f --- /dev/null +++ b/phpBB/config/default/container/services_php.yml @@ -0,0 +1,3 @@ +services: + php_ini: + class: phpbb\php\ini diff --git a/phpBB/config/default/container/tables.yml b/phpBB/config/default/container/tables.yml index 00067d5abe..c4b5ac2375 100644 --- a/phpBB/config/default/container/tables.yml +++ b/phpBB/config/default/container/tables.yml @@ -11,6 +11,7 @@ parameters: tables.forums: %core.table_prefix%forums tables.log: %core.table_prefix%log tables.migrations: %core.table_prefix%migrations + tables.moderator_cache: %core.table_prefix%moderator_cache tables.modules: %core.table_prefix%modules tables.notification_types: %core.table_prefix%notification_types tables.notifications: %core.table_prefix%notifications diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php index 5c18793655..cb4087d09b 100644 --- a/phpBB/includes/compatibility_globals.php +++ b/phpBB/includes/compatibility_globals.php @@ -1,62 +1,79 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ /** -*/ + */ if (!defined('IN_PHPBB')) { exit; } -// set up caching -/* @var $cache \phpbb\cache\service */ -$cache = $phpbb_container->get('cache'); +/** + * Sets compatibility globals in the global scope + * + * This function registers compatibility variables to the global + * variable scope. This is required to make it possible to include this file + * in a service. + */ +function register_compatibility_globals() +{ + global $phpbb_container; -// Instantiate some basic classes -/* @var $phpbb_dispatcher \phpbb\event\dispatcher */ -$phpbb_dispatcher = $phpbb_container->get('dispatcher'); + global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log; + global $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template; -/* @var $request \phpbb\request\request_interface */ -$request = $phpbb_container->get('request'); + // set up caching + /* @var $cache \phpbb\cache\service */ + $cache = $phpbb_container->get('cache'); -/* @var $user \phpbb\user */ -$user = $phpbb_container->get('user'); + // Instantiate some basic classes + /* @var $phpbb_dispatcher \phpbb\event\dispatcher */ + $phpbb_dispatcher = $phpbb_container->get('dispatcher'); -/* @var $auth \phpbb\auth\auth */ -$auth = $phpbb_container->get('auth'); + /* @var $request \phpbb\request\request_interface */ + $request = $phpbb_container->get('request'); -/* @var $db \phpbb\db\driver\driver_interface */ -$db = $phpbb_container->get('dbal.conn'); + /* @var $user \phpbb\user */ + $user = $phpbb_container->get('user'); -// Grab global variables, re-cache if necessary -/* @var $config phpbb\config\db */ -$config = $phpbb_container->get('config'); + /* @var $auth \phpbb\auth\auth */ + $auth = $phpbb_container->get('auth'); -/* @var $phpbb_log \phpbb\log\log_interface */ -$phpbb_log = $phpbb_container->get('log'); + /* @var $db \phpbb\db\driver\driver_interface */ + $db = $phpbb_container->get('dbal.conn'); -/* @var $symfony_request \phpbb\symfony_request */ -$symfony_request = $phpbb_container->get('symfony_request'); + // Grab global variables, re-cache if necessary + /* @var $config phpbb\config\db */ + $config = $phpbb_container->get('config'); -/* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */ -$phpbb_filesystem = $phpbb_container->get('filesystem'); + /* @var $phpbb_log \phpbb\log\log_interface */ + $phpbb_log = $phpbb_container->get('log'); -/* @var $phpbb_path_helper \phpbb\path_helper */ -$phpbb_path_helper = $phpbb_container->get('path_helper'); + /* @var $symfony_request \phpbb\symfony_request */ + $symfony_request = $phpbb_container->get('symfony_request'); -// load extensions -/* @var $phpbb_extension_manager \phpbb\extension\manager */ -$phpbb_extension_manager = $phpbb_container->get('ext.manager'); + /* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */ + $phpbb_filesystem = $phpbb_container->get('filesystem'); -/* @var $template \phpbb\template\template */ -$template = $phpbb_container->get('template'); + /* @var $phpbb_path_helper \phpbb\path_helper */ + $phpbb_path_helper = $phpbb_container->get('path_helper'); + + // load extensions + /* @var $phpbb_extension_manager \phpbb\extension\manager */ + $phpbb_extension_manager = $phpbb_container->get('ext.manager'); + + /* @var $template \phpbb\template\template */ + $template = $phpbb_container->get('template'); +} + +register_compatibility_globals(); From 53c5610080d45660fc8d5528135408cb9ac293cf Mon Sep 17 00:00:00 2001 From: MateBartus Date: Thu, 23 Apr 2015 14:22:05 +0200 Subject: [PATCH 0439/1676] [ticket/13740] Add new language file for install [ci skip] PHPBB3-13740 --- phpBB/language/en/install.php | 650 ++++++------------------------ phpBB/language/en/old_install.php | 629 +++++++++++++++++++++++++++++ 2 files changed, 752 insertions(+), 527 deletions(-) create mode 100644 phpBB/language/en/old_install.php diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 75e5d50225..59ad1b0d41 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -36,553 +36,141 @@ if (empty($lang) || !is_array($lang)) // equally where a string contains only two placeholders which are used to wrap text // in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine +// Common installer pages $lang = array_merge($lang, array( + 'INSTALL_PANEL' => 'Installation Panel', + + // Introduction page + 'INTRODUCTION_TITLE' => 'Introduction', + 'INTRODUCTION_BODY' => 'Welcome to phpBB3!

            phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.

            This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read the installation guide.

            To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.', + + // Support page + 'SUPPORT_TITLE' => 'Support', + 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:

            • installation
            • configuration
            • technical questions
            • problems relating to potential bugs in the software
            • updating from Release Candidate (RC) versions to the latest stable version
            • converting from phpBB 2.0.x to phpBB3
            • converting from other discussion board software to phpBB3 (please see the Convertors Forum)

            We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.

            Extensions / Styles

            For issues relating to Extensions, please post in the appropriate Extensions Forum.
            For issues relating to styles, templates and themes, please post in the appropriate Styles Forum.

            If your question relates to a specific package, please post directly in the topic dedicated to the package.

            Obtaining Support

            The phpBB Welcome Package
            Support Section
            Quick Start Guide

            To ensure you stay up to date with the latest news and releases, why not subscribe to our mailing list?

            ', + + // License + 'LICENSE_TITLE' => 'General Public License', +)); + +// Requirements translation +$lang = array_merge($lang, array( + // Filesystem requirements + 'FILE_NOT_EXISTS' => 'File not exists', + 'FILE_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s file need to exist.', + 'FILE_NOT_WRITABLE' => 'File not writable', + 'FILE_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s file need to be writable.', + + 'DIRECTORY_NOT_EXISTS' => 'Directory not exists', + 'DIRECTORY_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s directory need to exist.', + 'DIRECTORY_NOT_WRITABLE' => 'Directory not writable', + 'DIRECTORY_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s directory need to be writable.', + + // Server requirements + 'PHP_VERSION_REQD' => 'PHP version', + 'PHP_VERSION_REQD_EXPLAIN' => 'phpBB requires PHP version 5.3.9 or higher.', + 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP getimagesize() function is required', + 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the getimagesize function needs to be available.', + 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support', + 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.', + 'PHP_JSON_SUPPORT' => 'PHP JSON support', + 'PHP_JSON_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the PHP JSON extension needs to be available.', + 'PHP_SUPPORTED_DB' => 'Supported databases', + 'PHP_SUPPORTED_DB_EXPLAIN' => 'You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.', +)); + +// General error messages +$lang = array_merge($lang, array( + 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.', +)); + +// Data obtaining translations +$lang = array_merge($lang, array( + // + // Admin data + // + 'STAGE_ADMINISTRATOR' => 'Administrator details', + + // Form labels 'ADMIN_CONFIG' => 'Administrator configuration', 'ADMIN_PASSWORD' => 'Administrator password', 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password', 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.', - 'ADMIN_TEST' => 'Check administrator settings', 'ADMIN_USERNAME' => 'Administrator username', 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.', - 'APP_MAGICK' => 'Imagemagick support [ Attachments ]', - 'AUTHOR_NOTES' => 'Author notes
            » %s', - 'AVAILABLE' => 'Available', - 'AVAILABLE_CONVERTORS' => 'Available convertors', - 'BEGIN_CONVERT' => 'Begin conversion', - 'BLANK_PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using no table prefix.', - 'BOARD_NOT_INSTALLED' => 'No installation found', - 'BOARD_NOT_INSTALLED_EXPLAIN' => 'The phpBB Unified Convertor Framework requires a default installation of phpBB3 to function, please proceed by first installing phpBB3.', - 'BACKUP_NOTICE' => 'Please backup your board before updating in case any problems arise during the update process.', - - 'CATEGORY' => 'Category', - 'CACHE_STORE' => 'Cache type', - 'CACHE_STORE_EXPLAIN' => 'The physical location where data is cached, filesystem is preferred.', - 'CAT_CONVERT' => 'Convert', - 'CAT_INSTALL' => 'Install', - 'CAT_OVERVIEW' => 'Overview', - 'CAT_UPDATE' => 'Update', - 'CHANGE' => 'Change', - 'CHECK_TABLE_PREFIX' => 'Please check your table prefix and try again.', - 'CLEAN_VERIFY' => 'Cleaning up and verifying the final structure', - 'CLEANING_USERNAMES' => 'Cleaning usernames', - 'COLLIDING_CLEAN_USERNAME' => '%s is the clean username for:', - 'COLLIDING_USERNAMES_FOUND' => 'Colliding usernames were found on your old board. In order to complete the conversion please delete or rename these users so that there is only one user on your old board for each clean username.', - 'COLLIDING_USER' => '» user id: %d username: %s (%d posts)', - 'CONFIG_CONVERT' => 'Converting the configuration', - 'CONFIG_FILE_UNABLE_WRITE' => 'It was not possible to write the configuration file. Alternative methods for this file to be created are presented below.', - 'CONFIG_FILE_WRITTEN' => 'The configuration file has been written. You may now proceed to the next step of the installation.', - 'CONFIG_PHPBB_EMPTY' => 'The phpBB3 config variable for “%s†is empty.', - 'CONFIG_RETRY' => 'Retry', - 'CONTINUE_CONVERT' => 'Continue conversion', - 'CONTINUE_CONVERT_BODY' => 'A previous conversion attempt has been determined. You are now able to choose between starting a new conversion or continuing the conversion.', - 'CONTINUE_LAST' => 'Continue last statements', - 'CONTINUE_OLD_CONVERSION' => 'Continue previously started conversion', - 'CONVERT' => 'Convert', - 'CONVERT_COMPLETE' => 'Conversion completed', - 'CONVERT_COMPLETE_EXPLAIN' => 'You have now successfully converted your board to phpBB 3.1. You can now login and access your board. Please ensure that the settings were transferred correctly before enabling your board by deleting the install directory. Remember that help on using phpBB is available online via the Documentation and the support forums.', - 'CONVERT_INTRO' => 'Welcome to the phpBB Unified Convertor Framework', - 'CONVERT_INTRO_BODY' => 'From here, you are able to import data from other (installed) board systems. The list below shows all the conversion modules currently available. If there is no convertor shown in this list for the board software you wish to convert from, please check our website where further conversion modules may be available for download.', - 'CONVERT_NEW_CONVERSION' => 'New conversion', - 'CONVERT_NOT_EXIST' => 'The specified convertor does not exist.', - 'CONVERT_OPTIONS' => 'Options', - 'CONVERT_SETTINGS_VERIFIED' => 'The information you entered has been verified. To start the conversion process, please push the button below.', - 'CONV_ERR_FATAL' => 'Fatal conversion error', - - 'CONV_ERROR_ATTACH_FTP_DIR' => 'FTP upload for attachments is enabled at the old board. Please disable the FTP upload option and make sure a valid upload directory is specified, then copy all attachment files to this new web accessible directory. Once you have done this, restart the convertor.', - 'CONV_ERROR_CONFIG_EMPTY' => 'There is no configuration information available for the conversion.', - 'CONV_ERROR_FORUM_ACCESS' => 'Unable to get forum access information.', - 'CONV_ERROR_GET_CATEGORIES' => 'Unable to get categories.', - 'CONV_ERROR_GET_CONFIG' => 'Could not retrieve your board configuration.', - 'CONV_ERROR_COULD_NOT_READ' => 'Unable to access/read “%sâ€.', - 'CONV_ERROR_GROUP_ACCESS' => 'Unable to get group authentication information.', - 'CONV_ERROR_INCONSISTENT_GROUPS' => 'Inconsistency in groups table detected in add_bots() - you need to add all special groups if you do it manually.', - 'CONV_ERROR_INSERT_BOT' => 'Unable to insert bot into users table.', - 'CONV_ERROR_INSERT_BOTGROUP' => 'Unable to insert bot into bots table.', - 'CONV_ERROR_INSERT_USER_GROUP' => 'Unable to insert user into user_group table.', - 'CONV_ERROR_MESSAGE_PARSER' => 'Message parser error', - 'CONV_ERROR_NO_AVATAR_PATH' => 'Note to developer: you must specify $convertor[\'avatar_path\'] to use %s.', - 'CONV_ERROR_NO_FORUM_PATH' => 'The relative path to the source board has not been specified.', - 'CONV_ERROR_NO_GALLERY_PATH' => 'Note to developer: you must specify $convertor[\'avatar_gallery_path\'] to use %s.', - 'CONV_ERROR_NO_GROUP' => 'Group “%1$s†could not be found in %2$s.', - 'CONV_ERROR_NO_RANKS_PATH' => 'Note to developer: you must specify $convertor[\'ranks_path\'] to use %s.', - 'CONV_ERROR_NO_SMILIES_PATH' => 'Note to developer: you must specify $convertor[\'smilies_path\'] to use %s.', - 'CONV_ERROR_NO_UPLOAD_DIR' => 'Note to developer: you must specify $convertor[\'upload_path\'] to use %s.', - 'CONV_ERROR_PERM_SETTING' => 'Unable to insert/update permission setting.', - 'CONV_ERROR_PM_COUNT' => 'Unable to select folder pm count.', - 'CONV_ERROR_REPLACE_CATEGORY' => 'Unable to insert new forum replacing old category.', - 'CONV_ERROR_REPLACE_FORUM' => 'Unable to insert new forum replacing old forum.', - 'CONV_ERROR_USER_ACCESS' => 'Unable to get user authentication information.', - 'CONV_ERROR_WRONG_GROUP' => 'Wrong group “%1$s†defined in %2$s.', - 'CONV_OPTIONS_BODY' => 'This page collects the data required to access the source board. Enter the database details of your former board; the converter will not change anything in the database given below. The source board should be disabled to allow a consistent conversion.', - 'CONV_SAVED_MESSAGES' => 'Saved messages', - - 'COULD_NOT_COPY' => 'Could not copy file %1$s to %2$s

            Please check that the target directory exists and is writable by the webserver.', - 'COULD_NOT_FIND_PATH' => 'Could not find path to your former board. Please check your settings and try again.
            » %s was specified as the source path.', - - 'DBMS' => 'Database type', - 'DB_CONFIG' => 'Database configuration', - 'DB_CONNECTION' => 'Database connection', - 'DB_ERR_INSERT' => 'Error while processing INSERT query.', - 'DB_ERR_LAST' => 'Error while processing query_last.', - 'DB_ERR_QUERY_FIRST' => 'Error while executing query_first.', - 'DB_ERR_QUERY_FIRST_TABLE' => 'Error while executing query_first, %s (“%sâ€).', - 'DB_ERR_SELECT' => 'Error while running SELECT query.', - 'DB_HOST' => 'Database server hostname or DSN', - 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.', - 'DB_NAME' => 'Database name', - 'DB_PASSWORD' => 'Database password', - 'DB_PORT' => 'Database server port', - 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.', - 'DB_UPDATE_NOT_SUPPORTED' => 'We are sorry, but this script does not support updating from versions of phpBB prior to “%1$sâ€. The version you currently have installed is “%2$sâ€. Please update to a previous version before running this script. Assistance with this is available in the Support Forum on phpBB.com.', - 'DB_USERNAME' => 'Database username', - 'DB_TEST' => 'Test connection', - 'DEFAULT_LANG' => 'Default board language', - 'DEFAULT_PREFIX_IS' => 'The convertor was not able to find tables with the specified prefix. Please make sure you have entered the correct details for the board you are converting from. The default table prefix for %1$s is %2$s.', - 'DEV_NO_TEST_FILE' => 'No value has been specified for the test_file variable in the convertor. If you are a user of this convertor, you should not be seeing this error, please report this message to the convertor author. If you are a convertor author, you must specify the name of a file which exists in the source board to allow the path to it to be verified.', - 'DIRECTORIES_AND_FILES' => 'Directory and file setup', - 'DISABLE_KEYS' => 'Disabling keys', - 'DLL_FTP' => 'Remote FTP support [ Installation ]', - 'DLL_GD' => 'GD graphics support [ Visual Confirmation ]', - 'DLL_MBSTRING' => 'Multi-byte character support', - 'DLL_MSSQL' => 'MSSQL Server 2000+', - 'DLL_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC', - 'DLL_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]', - 'DLL_MYSQL' => 'MySQL', - 'DLL_MYSQLI' => 'MySQL with MySQLi Extension', - 'DLL_ORACLE' => 'Oracle', - 'DLL_POSTGRES' => 'PostgreSQL', - 'DLL_SQLITE' => 'SQLite 2', - 'DLL_SQLITE3' => 'SQLite 3', - 'DLL_XML' => 'XML support [ Jabber ]', - 'DLL_ZLIB' => 'zlib compression support [ gz, .tar.gz, .zip ]', - 'DL_CONFIG' => 'Download config', - 'DL_CONFIG_EXPLAIN' => 'You may download the complete config.php to your own PC. You will then need to upload the file manually, replacing any existing config.php in your phpBB 3.1 root directory. Please remember to upload the file in ASCII format (see your FTP application documentation if you are unsure how to achieve this). When you have uploaded the config.php please click “Done†to move to the next stage.', - 'DL_DOWNLOAD' => 'Download', - 'DONE' => 'Done', - - 'ENABLE_KEYS' => 'Re-enabling keys. This can take a while.', - - 'FILES_OPTIONAL' => 'Optional files and directories', - 'FILES_OPTIONAL_EXPLAIN' => 'Optional - These files, directories or permission settings are not required. The installation system will attempt to use various techniques to create them if they do not exist or cannot be written to. However, the presence of these will speed installation.', - 'FILES_REQUIRED' => 'Files and Directories', - 'FILES_REQUIRED_EXPLAIN' => 'Required - In order to function correctly phpBB needs to be able to access or write to certain files or directories. If you see “Not Found†you need to create the relevant file or directory. If you see “Unwritable†you need to change the permissions on the file or directory to allow phpBB to write to it.', - 'FILLING_TABLE' => 'Filling table %s', - 'FILLING_TABLES' => 'Filling tables', - - 'FINAL_STEP' => 'Process final step', - 'FORUM_ADDRESS' => 'Board address', - 'FORUM_ADDRESS_EXPLAIN' => 'This is the URL of your former board, for example http://www.example.com/phpBB2/. If an address is entered here and not left empty every instance of this address will be replaced by your new board address within messages, private messages and signatures.', - 'FORUM_PATH' => 'Board path', - 'FORUM_PATH_EXPLAIN' => 'This is the relative path on disk to your former board from the root of this phpBB3 installation.', - 'FOUND' => 'Found', - 'FTP_CONFIG' => 'Transfer config by FTP', - 'FTP_CONFIG_EXPLAIN' => 'phpBB has detected the presence of the FTP module on this server. You may attempt to install your config.php via this if you wish. You will need to supply the information listed below. Remember your username and password are those to your server! (ask your hosting provider for details if you are unsure what these are).', - 'FTP_PATH' => 'FTP path', - 'FTP_PATH_EXPLAIN' => 'This is the path from your root directory to that of phpBB, e.g. htdocs/phpBB3/.', - 'FTP_UPLOAD' => 'Upload', - - 'GPL' => 'General Public License', - - 'INITIAL_CONFIG' => 'Basic configuration', - 'INITIAL_CONFIG_EXPLAIN' => 'Now that install has determined your server can run phpBB you need to supply some specific information. If you do not know how to connect to your database please contact your hosting provider (in the first instance) or use the phpBB support forums. When entering data please ensure you check it thoroughly before continuing.', - 'INSTALL_CONGRATS' => 'Congratulations!', - 'INSTALL_CONGRATS_EXPLAIN' => ' - You have successfully installed phpBB %1$s. Please proceed by choosing one of the following options:

            -

            Convert an existing board to phpBB3

            -

            The phpBB Unified Convertor Framework supports the conversion of phpBB 2.0.x and other board systems to phpBB3. If you have an existing board that you wish to convert, please proceed to the convertor.

            -

            Go live with your phpBB3!

            -

            Clicking the button below will take you to a form for submitting statistical data to phpBB in your Administration Control Panel (ACP). We would appreciate it if you could help us by sending that information. Afterwards you should take some time to examine the options available to you. Remember that help is available online via the Documentation, README and the Support Forums.

            Please delete, move or rename the install directory before using your board. While this directory exists, only the Administration Control Panel (ACP) will be accessible.', - 'INSTALL_INTRO' => 'Welcome to Installation', - - 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.

            In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:

            - -
              -
            • The Database Type - the database you will be using.
            • -
            • The Database server hostname or DSN - the address of the database server.
            • -
            • The Database server port - the port of the database server (most of the time this is not needed).
            • -
            • The Database name - the name of the database on the server.
            • -
            • The Database username and Database password - the login data to access the database.
            • -
            - -

            Note: if you are installing using SQLite, you should enter the full path to your database file in the DSN field and leave the username and password fields blank. For security reasons, you should make sure that the database file is not stored in a location accessible from the web.

            - -

            phpBB3 supports the following databases:

            -
              -
            • MySQL 3.23 or above (MySQLi supported)
            • -
            • PostgreSQL 8.3+
            • -
            • SQLite 2.8.2+
            • -
            • SQLite 3.6.15+
            • -
            • MS SQL Server 2000 or above (directly or via ODBC)
            • -
            • MS SQL Server 2005 or above (native)
            • -
            • Oracle
            • -
            - -

            Only those databases supported on your server will be displayed.', - 'INSTALL_INTRO_NEXT' => 'To commence the installation, please press the button below.', - 'INSTALL_LOGIN' => 'Login', - 'INSTALL_NEXT' => 'Next stage', - 'INSTALL_NEXT_FAIL' => 'Some tests failed and you should correct these problems before proceeding to the next stage. Failure to do so may result in an incomplete installation.', - 'INSTALL_NEXT_PASS' => 'All the basic tests have been passed and you may proceed to the next stage of installation. If you have changed any permissions, modules, etc. and wish to re-test you can do so if you wish.', - 'INSTALL_PANEL' => 'Installation Panel', - 'INSTALL_SEND_CONFIG' => 'Unfortunately phpBB could not write the configuration information directly to your config.php. This may be because the file does not exist or is not writable. A number of options will be listed below enabling you to complete installation of config.php.', - 'INSTALL_START' => 'Start install', - 'INSTALL_TEST' => 'Test again', - 'INST_ERR' => 'Installation error', - 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.', - 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.', - 'INST_ERR_DB_INVALID_PREFIX'=> 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.', - 'INST_ERR_DB_NO_ERROR' => 'No error message given.', - 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension†option you have selected. Please try the “MySQL†option instead.', - 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.', - 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.', - 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the NLS_CHARACTERSET parameter to UTF8. Either upgrade your installation to 9.2+ or change the parameter.', - 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in UNICODE or UTF8 encoding. Try installing with a database in UNICODE or UTF8 encoding.', - 'INST_ERR_DB_NO_NAME' => 'No database name specified.', - 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.', - 'INST_ERR_EMAIL_MISMATCH' => 'The emails you entered did not match.', - 'INST_ERR_FATAL' => 'Fatal installation error', - 'INST_ERR_FATAL_DB' => 'A fatal and unrecoverable database error has occurred. This may be because the specified user does not have appropriate permissions to CREATE TABLES or INSERT data, etc. Further information may be given below. Please contact your hosting provider in the first instance or the support forums of phpBB for further assistance.', - 'INST_ERR_FTP_PATH' => 'Could not change to the given directory, please check the path.', - 'INST_ERR_FTP_LOGIN' => 'Could not login to FTP server, check your username and password.', - 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.', - 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.', + // Errors + 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.', 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.', 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.', 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.', - 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.', - 'INST_ERR_PREFIX_INVALID' => 'The table prefix you have specified is invalid for your database. Please try another, removing characters such as the hyphen.', - 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.', - 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.', - 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.', - 'INVALID_PRIMARY_KEY' => 'Invalid primary key : %s', + 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.', + 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.', - 'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.', + // + // Board data + // + // Form labels + 'BOARD_CONFIG' => 'Bulletin board configuration', + 'DEFAULT_LANGUAGE' => 'Default language', + 'BOARD_NAME' => 'Title of the board', + 'BOARD_DESCRIPTION' => 'Short description of the board', - // mbstring - 'MBSTRING_CHECK' => 'mbstring extension check', - 'MBSTRING_CHECK_EXPLAIN' => 'Required - mbstring is a PHP extension that provides multibyte string functions. Certain features of mbstring are not compatible with phpBB and must be disabled.', - 'MBSTRING_FUNC_OVERLOAD' => 'Function overloading', - 'MBSTRING_FUNC_OVERLOAD_EXPLAIN' => 'mbstring.func_overload must be set to either 0 or 4.', - 'MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding', - 'MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => 'mbstring.encoding_translation must be set to 0.', - 'MBSTRING_HTTP_INPUT' => 'HTTP input character conversion', - 'MBSTRING_HTTP_INPUT_EXPLAIN' => 'mbstring.http_input must be set to pass.', - 'MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion', - 'MBSTRING_HTTP_OUTPUT_EXPLAIN' => 'mbstring.http_output must be set to pass.', + // + // Database data + // + 'STAGE_DATABASE' => 'Database settings', - 'MAKE_FOLDER_WRITABLE' => 'Please make sure that this folder exists and is writable by the webserver then try again:
            »%s.', - 'MAKE_FOLDERS_WRITABLE' => 'Please make sure that these folders exist and are writable by the webserver then try again:
            »%s.', + // Form labels + 'DB_CONFIG' => 'Database configuration', + 'DBMS' => 'Database type', + 'DB_HOST' => 'Database server hostname or DSN', + 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.', + 'DB_PORT' => 'Database server port', + 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.', + 'DB_PASSWORD' => 'Database password', + 'DB_NAME' => 'Database name', + 'DB_USERNAME' => 'Database username', + 'TABLE_PREFIX' => 'Prefix for tables in database', + 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.', - 'MYSQL_SCHEMA_UPDATE_REQUIRED' => 'Your MySQL database schema for phpBB is outdated. phpBB detected a schema for MySQL 3.x/4.x, but the server runs on MySQL %2$s.
            Before you proceed the update, you need to upgrade the schema.

            Please refer to the Knowledge Base article about upgrading the MySQL schema. If you encounter problems, please use our support forums.', + // Database options + 'DB_OPTION_MSSQL' => 'MSSQL Server 2000+', + 'DB_OPTION_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC', + 'DB_OPTION_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]', + 'DB_OPTION_MYSQL' => 'MySQL', + 'DB_OPTION_MYSQLI' => 'MySQL with MySQLi Extension', + 'DB_OPTION_ORACLE' => 'Oracle', + 'DB_OPTION_POSTGRES' => 'PostgreSQL', + 'DB_OPTION_SQLITE' => 'SQLite 2', + 'DB_OPTION_SQLITE3' => 'SQLite 3', - 'NAMING_CONFLICT' => 'Naming conflict: %s and %s are both aliases

            %s', - 'NEXT_STEP' => 'Proceed to next step', - 'NOT_FOUND' => 'Cannot find', - 'NOT_UNDERSTAND' => 'Could not understand %s #%d, table %s (“%sâ€)', - 'NO_CONVERTORS' => 'No convertors are available for use.', - 'NO_CONVERT_SPECIFIED' => 'No convertor specified.', - 'NO_LOCATION' => 'Cannot determine location. If you know Imagemagick is installed, you may specify the location later within your administration control panel', - 'NO_TABLES_FOUND' => 'No tables found.', + // Errors + 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.', + 'INST_ERR_DB_INVALID_PREFIX' => 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.', + 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.', + 'INST_ERR_DB_NO_NAME' => 'No database name specified.', + 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.', + 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.', + 'INST_ERR_DB_NO_ERROR' => 'No error message given.', + 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.', + 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension†option you have selected. Please try the “MySQL†option instead.', + 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.', + 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.', + 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the NLS_CHARACTERSET parameter to UTF8. Either upgrade your installation to 9.2+ or change the parameter.', + 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in UNICODE or UTF8 encoding. Try installing with a database in UNICODE or UTF8 encoding.', - 'OVERVIEW_BODY' => 'Welcome to phpBB3!

            phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.

            This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read the installation guide.

            To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.', - - 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support', - 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.', - 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP function getimagesize() is available', - 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'Required - In order for phpBB to function correctly, the getimagesize function needs to be available.', - 'PHP_JSON_SUPPORT' => 'PHP JSON support', - 'PHP_JSON_SUPPORT_EXPLAIN' => 'Required - In order for phpBB to function correctly, the PHP JSON extension needs to be available.', - 'PHP_OPTIONAL_MODULE' => 'Optional modules', - 'PHP_OPTIONAL_MODULE_EXPLAIN' => 'Optional - These modules or applications are optional. However, if they are available they will enable extra features.', - 'PHP_SUPPORTED_DB' => 'Supported databases', - 'PHP_SUPPORTED_DB_EXPLAIN' => 'Required - You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.', - 'PHP_REGISTER_GLOBALS' => 'PHP setting register_globals is disabled', - 'PHP_REGISTER_GLOBALS_EXPLAIN' => 'phpBB will still run if this setting is enabled, but if possible, it is recommended that register_globals is disabled on your PHP install for security reasons.', - 'PHP_SAFE_MODE' => 'Safe mode', - 'PHP_SETTINGS' => 'PHP version and settings', - 'PHP_SETTINGS_EXPLAIN' => 'Required - You must be running at least version 5.3.9 of PHP in order to install phpBB. If safe mode is displayed below your PHP installation is running in that mode. This will impose limitations on remote administration and similar features.', - 'PHP_URL_FOPEN_SUPPORT' => 'PHP setting allow_url_fopen is enabled', - 'PHP_URL_FOPEN_SUPPORT_EXPLAIN' => 'Optional - This setting is optional, however certain phpBB functions like off-site avatars will not work properly without it.', - 'PHP_VERSION_REQD' => 'PHP version >= 5.3.9', - 'POST_ID' => 'Post ID', - 'PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using %s as table prefix.', - 'PREPROCESS_STEP' => 'Executing pre-processing functions/queries', - 'PRE_CONVERT_COMPLETE' => 'All pre-conversion steps have successfully been completed. You may now begin the actual conversion process. Please note that you may have to manually do and adjust several things. After conversion, especially check the permissions assigned, rebuild your search index which is not converted and also make sure files got copied correctly, for example avatars and smilies.', - 'PROCESS_LAST' => 'Processing last statements', - - 'REFRESH_PAGE' => 'Refresh page to continue conversion', - 'REFRESH_PAGE_EXPLAIN' => 'If set to yes, the convertor will refresh the page to continue the conversion after having finished a step. If this is your first conversion for testing purposes and to determine any errors in advance, we suggest to set this to No.', - 'REQUIREMENTS_TITLE' => 'Installation compatibility', - 'REQUIREMENTS_EXPLAIN' => 'Before proceeding with the full installation phpBB will carry out some tests on your server configuration and files to ensure that you are able to install and run phpBB. Please ensure you read through the results thoroughly and do not proceed until all the required tests are passed. If you wish to use any of the features depending on the optional tests, you should ensure that these tests are passed also.', - 'RETRY_WRITE' => 'Retry writing config', - 'RETRY_WRITE_EXPLAIN' => 'If you wish you can change the permissions on config.php to allow phpBB to write to it. Should you wish to do that you can click Retry below to try again. Remember to return the permissions on config.php after phpBB has finished installation.', + // + // Email data + // + 'EMAIL_CONFIG' => 'E-mail configuration', + // + // Server data + // + // Form labels + 'SERVER_CONFIG' => 'Server configuration', 'SCRIPT_PATH' => 'Script path', 'SCRIPT_PATH_EXPLAIN' => 'The path where phpBB is located relative to the domain name, e.g. /phpBB3.', - 'SELECT_LANG' => 'Select language', - 'SERVER_CONFIG' => 'Server configuration', - 'SEARCH_INDEX_UNCONVERTED' => 'Search index was not converted', - 'SEARCH_INDEX_UNCONVERTED_EXPLAIN' => 'Your old search index was not converted. Searching will always yield an empty result. To create a new search index go to the Administration Control Panel, select Maintenance and then choose Search index from the submenu.', - 'SELECT_FORUM_GA' => 'In phpBB 3.1 the global announcements are linked to forums. Select a forum for your current global announcements (can be moved later):', - 'SOFTWARE' => 'Board software', - 'SPECIFY_OPTIONS' => 'Specify conversion options', - 'STAGE_ADMINISTRATOR' => 'Administrator details', - 'STAGE_ADVANCED' => 'Advanced settings', - 'STAGE_ADVANCED_EXPLAIN' => 'The settings on this page are only necessary to set if you know that you require something different from the default. If you are unsure, just proceed to the next page, as these settings can be altered from the Administration Control Panel later.', - 'STAGE_CONFIG_FILE' => 'Configuration file', - 'STAGE_CREATE_TABLE' => 'Create database tables', - 'STAGE_CREATE_TABLE_EXPLAIN' => 'The database tables used by phpBB 3.1 have been created and populated with some initial data. Proceed to the next screen to finish installing phpBB.', - 'STAGE_DATABASE' => 'Database settings', - 'STAGE_FINAL' => 'Final stage', - 'STAGE_INTRO' => 'Introduction', - 'STAGE_IN_PROGRESS' => 'Conversion in progress', - 'STAGE_REQUIREMENTS' => 'Requirements', - 'STAGE_SETTINGS' => 'Settings', - 'STARTING_CONVERT' => 'Starting conversion process', - 'STEP_PERCENT_COMPLETED' => 'Step %d of %d', - 'SUB_INTRO' => 'Introduction', - 'SUB_LICENSE' => 'License', - 'SUB_SUPPORT' => 'Support', - 'SUCCESSFUL_CONNECT' => 'Successful connection', - 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:

            • installation
            • configuration
            • technical questions
            • problems relating to potential bugs in the software
            • updating from Release Candidate (RC) versions to the latest stable version
            • converting from phpBB 2.0.x to phpBB3
            • converting from other discussion board software to phpBB3 (please see the Convertors Forum)

            We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.

            Extensions / Styles

            For issues relating to Extensions, please post in the appropriate Extensions Forum.
            For issues relating to styles, templates and themes, please post in the appropriate Styles Forum.

            If your question relates to a specific package, please post directly in the topic dedicated to the package.

            Obtaining Support

            The phpBB Welcome Package
            Support Section
            Quick Start Guide

            To ensure you stay up to date with the latest news and releases, why not subscribe to our mailing list?

            ', - 'SYNC_FORUMS' => 'Starting to synchronise forums', - 'SYNC_POST_COUNT' => 'Synchronising post_counts', - 'SYNC_POST_COUNT_ID' => 'Synchronising post_counts from entry %1$s to %2$s.', - 'SYNC_TOPICS' => 'Starting to synchronise topics', - 'SYNC_TOPIC_ID' => 'Synchronising topics from topic_id %1$s to %2$s.', - - 'TABLES_MISSING' => 'Could not find these tables
            » %s.', - 'TABLE_PREFIX' => 'Prefix for tables in database', - 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.', - 'TABLE_PREFIX_SAME' => 'The table prefix needs to be the one used by the software you are converting from.
            » Specified table prefix was %s.', - 'TESTS_PASSED' => 'Tests passed', - 'TESTS_FAILED' => 'Tests failed', - - 'UNABLE_WRITE_LOCK' => 'Unable to write lock file.', - 'UNAVAILABLE' => 'Unavailable', - 'UNWRITABLE' => 'Unwritable', - 'UPDATE_TOPICS_POSTED' => 'Generating topics posted information', - 'UPDATE_TOPICS_POSTED_ERR' => 'An error occurred while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.', - 'VERIFY_OPTIONS' => 'Verifying conversion options', - 'VERSION' => 'Version', - - 'WELCOME_INSTALL' => 'Welcome to phpBB3 Installation', - 'WRITABLE' => 'Writable', -)); - -// Updater -$lang = array_merge($lang, array( - 'ALL_FILES_UP_TO_DATE' => 'All files are up to date with the latest phpBB version.', - 'ARCHIVE_FILE' => 'Source file within archive', - - 'BACK' => 'Back', - 'BINARY_FILE' => 'Binary file', - 'BOT' => 'Spider/Robot', - - 'CHANGE_CLEAN_NAMES' => 'The method used to make sure a username is not used by multiple users has been changed. There are some users which have the same name when compared with the new method. You have to delete or rename these users to make sure that each name is only used by one user before you can proceed.', - 'CHECK_FILES' => 'Check files', - 'CHECK_FILES_AGAIN' => 'Check files again', - 'CHECK_FILES_EXPLAIN' => 'Within the next step all files will be checked against the update files - this can take a while if this is the first file check.', - 'CHECK_FILES_UP_TO_DATE' => 'According to your database your version is up to date. You may want to proceed with the file check to make sure all files are really up to date with the latest phpBB version.', - 'CHECK_UPDATE_DATABASE' => 'Continue update process', - 'COLLECTED_INFORMATION' => 'File information', - 'COLLECTED_INFORMATION_EXPLAIN' => 'The list below shows information about the files needing an update. Please read the information in front of every status block to see what they mean and what you may need to do to perform a successful update.', - 'COLLECTING_FILE_DIFFS' => 'Collecting file differences', - 'COMPLETE_LOGIN_TO_BOARD' => 'You should now login to your board and check if everything is working fine. Do not forget to delete, rename or move your install directory!', - 'CONTINUE_UPDATE_NOW' => 'Continue the update process now', // Shown within the database update script at the end if called from the updater - 'CONTINUE_UPDATE' => 'Continue update now', // Shown after file upload to indicate the update process is not yet finished - 'CURRENT_FILE' => 'Begin of Conflict - Original File code before update', - 'CURRENT_VERSION' => 'Current version', - - 'DATABASE_TYPE' => 'Database type', - 'DATABASE_UPDATE_COMPLETE' => 'Database updater has completed!', - 'DATABASE_UPDATE_CONTINUE' => 'Continue database update', - 'DATABASE_UPDATE_INFO_OLD' => 'The database update file within the install directory is outdated. Please make sure you uploaded the correct version of the file.', - 'DATABASE_UPDATE_NOT_COMPLETED' => 'The database update has not yet completed.', - 'DELETE_USER_REMOVE' => 'Delete user and remove posts', - 'DELETE_USER_RETAIN' => 'Delete user but keep posts', - 'DESTINATION' => 'Destination file', - 'DIFF_INLINE' => 'Inline', - 'DIFF_RAW' => 'Raw unified diff', - 'DIFF_SEP_EXPLAIN' => 'Code block used within the updated/new file', - 'DIFF_SIDE_BY_SIDE' => 'Side by Side', - 'DIFF_UNIFIED' => 'Unified diff', - 'DO_NOT_UPDATE' => 'Do not update this file', - 'DONE' => 'Done', - 'DOWNLOAD' => 'Download', - 'DOWNLOAD_AS' => 'Download as', - 'DOWNLOAD_UPDATE_METHOD_BUTTON' => 'Download modified files archive (recommended)', - 'DOWNLOAD_CONFLICTS' => 'Download conflicts for this file', - 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for <<< to spot conflicts', - 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive', - 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, please check the files again with the other button below.', - - 'EDIT_USERNAME' => 'Edit username', - 'ERROR' => 'Error', - 'EVERYTHING_UP_TO_DATE' => 'Everything is up to date with the latest phpBB version. You should now login to your board and check if everything is working fine. Do not forget to delete, rename or move your install directory! Please send us updated information about your server and board configurations from the Send statistics module in your ACP.', - - 'FILE_ALREADY_UP_TO_DATE' => 'File is already up to date.', - 'FILE_DIFF_NOT_ALLOWED' => 'File not allowed to be diffed.', - 'FILE_USED' => 'Information used from', // Single file - 'FILES_CONFLICT' => 'Conflict files', - 'FILES_CONFLICT_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. phpBB determined that these files create conflicts if they are tried to be merged. Please investigate the conflicts and try to manually resolve them or continue the update choosing the preferred merging method. If you resolve the conflicts manually check the files again after you modified them. You are also able to choose between the preferred merge method for every file. The first one will result in a file where the conflicting lines from your old file will be lost, the other one will result in losing the changes from the newer file.', - 'FILES_DELETED' => 'Deleted files', - 'FILES_DELETED_EXPLAIN' => 'The following files do not exist in the new version. These files have to be deleted from your installation.', - 'FILES_MODIFIED' => 'Modified files', - 'FILES_MODIFIED_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. The updated file will be a merge between your modifications and the new file.', - 'FILES_NEW' => 'New files', - 'FILES_NEW_EXPLAIN' => 'The following files currently do not exist within your installation. These files will be added to your installation.', - 'FILES_NEW_CONFLICT' => 'New conflicting files', - 'FILES_NEW_CONFLICT_EXPLAIN' => 'The following files are new within the latest version but it has been determined that there is already a file with the same name within the same position. This file will be overwritten by the new file.', - 'FILES_NOT_MODIFIED' => 'Not modified files', - 'FILES_NOT_MODIFIED_EXPLAIN' => 'The following files are not modified and represent the original phpBB files from the version you want to update from.', - 'FILES_UP_TO_DATE' => 'Already updated files', - 'FILES_UP_TO_DATE_EXPLAIN' => 'The following files are already up to date and do not need to be updated.', - 'FTP_SETTINGS' => 'FTP settings', - 'FTP_UPDATE_METHOD' => 'FTP upload', - - 'INCOMPATIBLE_UPDATE_FILES' => 'The update files found are incompatible with your installed version. Your installed version is %1$s and the update file is for updating phpBB %2$s to %3$s.', - 'INCOMPLETE_UPDATE_FILES' => 'The update files are incomplete.', - 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful. Now you need to continue the update process.', - - 'KEEP_OLD_NAME' => 'Keep username', - - 'LATEST_VERSION' => 'Latest version', - 'LINE' => 'Line', - 'LINE_ADDED' => 'Added', - 'LINE_MODIFIED' => 'Modified', - 'LINE_REMOVED' => 'Removed', - 'LINE_UNMODIFIED' => 'Unmodified', - 'LOGIN_UPDATE_EXPLAIN' => 'In order to update your installation you need to login first.', - - 'MAPPING_FILE_STRUCTURE' => 'To ease the upload here are the file locations which map your phpBB installation.', - - 'MERGE_MODIFICATIONS_OPTION' => 'Merge modifications', - - 'MERGE_NO_MERGE_NEW_OPTION' => 'Do not merge - use new file', - 'MERGE_NO_MERGE_MOD_OPTION' => 'Do not merge - use currently installed file', - 'MERGE_MOD_FILE_OPTION' => 'Merge modifications (removes new phpBB code within conflicting block)', - 'MERGE_NEW_FILE_OPTION' => 'Merge modifications (removes modified code within conflicting block)', - 'MERGE_SELECT_ERROR' => 'Conflicting file merge modes are not correctly selected.', - 'MERGING_FILES' => 'Merging differences', - 'MERGING_FILES_EXPLAIN' => 'Currently collecting final file changes.

            Please wait until phpBB has completed all operations on changed files.', - - 'NEW_FILE' => 'End of Conflict', - 'NEW_USERNAME' => 'New username', - 'NO_AUTH_UPDATE' => 'Not authorised to update', - 'NO_ERRORS' => 'No errors', - 'NO_UPDATE_FILES' => 'Not updating the following files', - 'NO_UPDATE_FILES_EXPLAIN' => 'The following files are new or modified but the directory they normally reside in could not be found on your installation. If this list contains files to other directories than language/ or styles/ than you may have modified your directory structure and the update may be incomplete.', - 'NO_UPDATE_FILES_OUTDATED' => 'No valid update directory was found, please make sure you uploaded the relevant files.

            Your installation does not seem to be up to date. Updates are available for your version of phpBB %1$s, please visit https://www.phpbb.com/downloads/ to obtain the correct package to update from Version %2$s to Version %3$s.', - 'NO_UPDATE_FILES_UP_TO_DATE' => 'Your version is up to date. There is no need to run the update tool. If you want to make an integrity check on your files make sure you uploaded the correct update files.', - 'NO_UPDATE_INFO' => 'Update file information could not be found.', - 'NO_UPDATES_REQUIRED' => 'No updates required', - 'NO_VISIBLE_CHANGES' => 'No visible changes', - 'NOTICE' => 'Notice', - 'NUM_CONFLICTS' => 'Number of conflicts', - 'NUMBER_OF_FILES_COLLECTED' => 'Currently differences from %1$d of %2$d files have been checked.
            Please wait until all files are checked.', - - 'OLD_UPDATE_FILES' => 'Update files are out of date. The update files found are for updating from phpBB %1$s to phpBB %2$s but the latest version of phpBB is %3$s.', - - 'PACKAGE_UPDATES_TO' => 'Current package updates to version', - 'PERFORM_DATABASE_UPDATE' => 'Perform database update', - 'PERFORM_DATABASE_UPDATE_EXPLAIN' => 'Below you will find a button to the database update script. The database update can take a while, so please do not stop the execution if it seems to hang. After the database update has been performed just follow the instructions to continue the update process.', - 'PREVIOUS_VERSION' => 'Previous version', - 'PROGRESS' => 'Progress', - - 'RELEASE_ANNOUNCEMENT' => 'Announcement', - 'RESULT' => 'Result', - 'RUN_DATABASE_SCRIPT' => 'Update my database now', - - 'SELECT_DIFF_MODE' => 'Select diff mode', - 'SELECT_DOWNLOAD_FORMAT' => 'Select download archive format', - 'SELECT_FTP_SETTINGS' => 'Select FTP settings', - 'SHOW_DIFF_CONFLICT' => 'Show differences/conflicts', - 'SHOW_DIFF_DELETED' => 'Show file contents', - 'SHOW_DIFF_FINAL' => 'Show resulting file', - 'SHOW_DIFF_MODIFIED' => 'Show merged differences', - 'SHOW_DIFF_NEW' => 'Show file contents', - 'SHOW_DIFF_NEW_CONFLICT' => 'Show differences', - 'SHOW_DIFF_NOT_MODIFIED' => 'Show differences', - 'SOME_QUERIES_FAILED' => 'Some queries failed, the statements and errors are listed below.', - 'SQL' => 'SQL', - 'SQL_FAILURE_EXPLAIN' => 'This is probably nothing to worry about, update will continue. Should this fail to complete you may need to seek help at our support forums. See README for details on how to obtain advice.', - 'STAGE_FILE_CHECK' => 'Check files', - 'STAGE_UPDATE_DB' => 'Update database', - 'STAGE_UPDATE_FILES' => 'Update files', - 'STAGE_VERSION_CHECK' => 'Version check', - 'STATUS_CONFLICT' => 'Modified file producing conflicts', - 'STATUS_DELETED' => 'Deleted file', - 'STATUS_MODIFIED' => 'Modified file', - 'STATUS_NEW' => 'New file', - 'STATUS_NEW_CONFLICT' => 'Conflicting new file', - 'STATUS_NOT_MODIFIED' => 'Not modified file', - 'STATUS_UP_TO_DATE' => 'Already updated file', - - 'TOGGLE_DISPLAY' => 'View/Hide file list', - 'TRY_DOWNLOAD_METHOD' => 'You may want to try the download modified files method.
            This method always works and is also the recommended update path.', - 'TRY_DOWNLOAD_METHOD_BUTTON'=> 'Try this method now', - - 'UPDATE_COMPLETED' => 'Update completed', - 'UPDATE_DATABASE' => 'Update database', - 'UPDATE_DATABASE_EXPLAIN' => 'Within the next step the database will be updated.', - 'UPDATE_DATABASE_SCHEMA' => 'Updating database schema', - 'UPDATE_FILES' => 'Update files', - 'UPDATE_FILES_NOTICE' => 'Please make sure you have updated your board files too, this file is only updating your database.', - 'UPDATE_INSTALLATION' => 'Update phpBB installation', - 'UPDATE_INSTALLATION_EXPLAIN' => 'With this option, it is possible to update your phpBB installation to the latest version.
            During the process all of your files will be checked for their integrity. You are able to review all differences and files before the update.

            The file update itself can be done in two different ways.

            Manual Update

            With this update you only download your personal set of changed files to make sure you do not lose your file modifications you may have done. After you downloaded this package you need to manually upload the files to their correct position under your phpBB root directory. Once done, you are able to do the file check stage again to see if you moved the files to their correct location.

            Automatic Update with FTP

            This method is similar to the first one but without the need to download the changed files and uploading them on your own. This will be done for you. In order to use this method you need to know your FTP login details since you will be asked for them. Once finished you will be redirected to the file check again to make sure everything got updated correctly.

            ', - 'UPDATE_INSTRUCTIONS' => ' - -

            Release announcement

            - -

            Please read the release announcement for the latest version before you continue your update process, it may contain useful information. It also contains full download links as well as the change log.

            - -
            - -

            How to update your installation with the Automatic Update Package

            - -

            The recommended way of updating your installation listed here is only valid for the automatic update package. You are also able to update your installation using the methods listed within the INSTALL.html document. The steps for updating phpBB3 automatically are:

            - -
              -
            • Go to the phpBB.com downloads page and download the "Automatic Update Package" archive.

            • -
            • Unpack the archive.

            • -
            • Upload the complete uncompressed "install" and "vendor" folders to your phpBB root directory (where your config.php file is).

            • -
            - -

            Once uploaded your board will be offline for normal users due to the install directory you uploaded now present.

            - Now start the update process by pointing your browser to the install folder.
            -
            - You will then be guided through the update process. You will be notified once the update is complete. -

            - ', - 'UPDATE_METHOD' => 'Update method', - 'UPDATE_METHOD_EXPLAIN' => 'You are now able to choose your preferred update method. Using the FTP upload will present you with a form you need to enter your FTP account details into. With this method the files will be automatically moved to the new location and backups of the old files being created by appending .bak to the filename. If you choose to download the modified files you are able to unpack and upload them to their correct location manually later.', - 'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s', - 'UPDATE_SUCCESS' => 'Update was successful', - 'UPDATE_SUCCESS_EXPLAIN' => 'Successfully updated all files. The next step involves checking all files again to make sure the files got updated correctly.', - 'UPDATE_VERSION_OPTIMIZE' => 'Updating version and optimising tables', - 'UPDATING_DATA' => 'Updating data', - 'UPDATING_TO_LATEST_STABLE' => 'Updating database to latest stable release', - 'UPDATED_VERSION' => 'Updated version', - 'UPLOAD_METHOD' => 'Upload method', - - 'UPDATE_DB_SUCCESS' => 'Database update was successful.', - 'UPDATE_FILE_SUCCESS' => 'File update was successful.', - 'USER_ACTIVE' => 'Active user', - 'USER_INACTIVE' => 'Inactive user', - - 'VERSION_CHECK' => 'Version check', - 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.', - 'VERSION_NOT_UP_TO_DATE' => 'Your phpBB installation is not up to date. Please continue the update process.', - 'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.
            Below is a link to the release announcement, which contains more information as well as instructions on updating.', - 'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.', - 'VERSION_UP_TO_DATE' => 'Your phpBB installation is up to date. Although there are no updates available at this time, you may continue in order to perform a file validity check.', - 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.', - 'VIEWING_FILE_CONTENTS' => 'Viewing file contents', - 'VIEWING_FILE_DIFF' => 'Viewing file differences', - - 'WRONG_INFO_FILE_FORMAT' => 'Wrong info file format', )); // Default database schema entries... @@ -630,3 +218,11 @@ $lang = array_merge($lang, array( 'TOPICS_TOPIC_TITLE' => 'Welcome to phpBB3', )); + +// Common navigation items' translation +$lang = array_merge($lang, array( + 'MENU_OVERVIEW' => 'Overview', + 'MENU_INTRO' => 'Introduction', + 'MENU_LICENSE' => 'License', + 'MENU_SUPPORT' => 'Support', +)); diff --git a/phpBB/language/en/old_install.php b/phpBB/language/en/old_install.php new file mode 100644 index 0000000000..a776a539ed --- /dev/null +++ b/phpBB/language/en/old_install.php @@ -0,0 +1,629 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* DO NOT CHANGE +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +if (empty($lang) || !is_array($lang)) +{ + $lang = array(); +} + +// DEVELOPERS PLEASE NOTE +// +// All language files should use UTF-8 as their encoding and the files must not contain a BOM. +// +// Placeholders can now contain order information, e.g. instead of +// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows +// translators to re-order the output of data while ensuring it remains correct +// +// You do not need this where single placeholders are used, e.g. 'Message %d' is fine +// equally where a string contains only two placeholders which are used to wrap text +// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine + +$lang = array_merge($lang, array( + 'ADMIN_CONFIG' => 'Administrator configuration', + 'ADMIN_PASSWORD' => 'Administrator password', + 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password', + 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.', + 'ADMIN_TEST' => 'Check administrator settings', + 'ADMIN_USERNAME' => 'Administrator username', + 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.', + 'APP_MAGICK' => 'Imagemagick support [ Attachments ]', + 'AUTHOR_NOTES' => 'Author notes
            » %s', + 'AVAILABLE' => 'Available', + 'AVAILABLE_CONVERTORS' => 'Available convertors', + + 'BEGIN_CONVERT' => 'Begin conversion', + 'BLANK_PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using no table prefix.', + 'BOARD_NOT_INSTALLED' => 'No installation found', + 'BOARD_NOT_INSTALLED_EXPLAIN' => 'The phpBB Unified Convertor Framework requires a default installation of phpBB3 to function, please proceed by first installing phpBB3.', + 'BACKUP_NOTICE' => 'Please backup your board before updating in case any problems arise during the update process.', + + 'CATEGORY' => 'Category', + 'CACHE_STORE' => 'Cache type', + 'CACHE_STORE_EXPLAIN' => 'The physical location where data is cached, filesystem is preferred.', + 'CAT_CONVERT' => 'Convert', + 'CAT_INSTALL' => 'Install', + 'CAT_OVERVIEW' => 'Overview', + 'CAT_UPDATE' => 'Update', + 'CHANGE' => 'Change', + 'CHECK_TABLE_PREFIX' => 'Please check your table prefix and try again.', + 'CLEAN_VERIFY' => 'Cleaning up and verifying the final structure', + 'CLEANING_USERNAMES' => 'Cleaning usernames', + 'COLLIDING_CLEAN_USERNAME' => '%s is the clean username for:', + 'COLLIDING_USERNAMES_FOUND' => 'Colliding usernames were found on your old board. In order to complete the conversion please delete or rename these users so that there is only one user on your old board for each clean username.', + 'COLLIDING_USER' => '» user id: %d username: %s (%d posts)', + 'CONFIG_CONVERT' => 'Converting the configuration', + 'CONFIG_FILE_UNABLE_WRITE' => 'It was not possible to write the configuration file. Alternative methods for this file to be created are presented below.', + 'CONFIG_FILE_WRITTEN' => 'The configuration file has been written. You may now proceed to the next step of the installation.', + 'CONFIG_PHPBB_EMPTY' => 'The phpBB3 config variable for “%s†is empty.', + 'CONFIG_RETRY' => 'Retry', + 'CONTINUE_CONVERT' => 'Continue conversion', + 'CONTINUE_CONVERT_BODY' => 'A previous conversion attempt has been determined. You are now able to choose between starting a new conversion or continuing the conversion.', + 'CONTINUE_LAST' => 'Continue last statements', + 'CONTINUE_OLD_CONVERSION' => 'Continue previously started conversion', + 'CONVERT' => 'Convert', + 'CONVERT_COMPLETE' => 'Conversion completed', + 'CONVERT_COMPLETE_EXPLAIN' => 'You have now successfully converted your board to phpBB 3.1. You can now login and access your board. Please ensure that the settings were transferred correctly before enabling your board by deleting the install directory. Remember that help on using phpBB is available online via the Documentation and the support forums.', + 'CONVERT_INTRO' => 'Welcome to the phpBB Unified Convertor Framework', + 'CONVERT_INTRO_BODY' => 'From here, you are able to import data from other (installed) board systems. The list below shows all the conversion modules currently available. If there is no convertor shown in this list for the board software you wish to convert from, please check our website where further conversion modules may be available for download.', + 'CONVERT_NEW_CONVERSION' => 'New conversion', + 'CONVERT_NOT_EXIST' => 'The specified convertor does not exist.', + 'CONVERT_OPTIONS' => 'Options', + 'CONVERT_SETTINGS_VERIFIED' => 'The information you entered has been verified. To start the conversion process, please push the button below.', + 'CONV_ERR_FATAL' => 'Fatal conversion error', + + 'CONV_ERROR_ATTACH_FTP_DIR' => 'FTP upload for attachments is enabled at the old board. Please disable the FTP upload option and make sure a valid upload directory is specified, then copy all attachment files to this new web accessible directory. Once you have done this, restart the convertor.', + 'CONV_ERROR_CONFIG_EMPTY' => 'There is no configuration information available for the conversion.', + 'CONV_ERROR_FORUM_ACCESS' => 'Unable to get forum access information.', + 'CONV_ERROR_GET_CATEGORIES' => 'Unable to get categories.', + 'CONV_ERROR_GET_CONFIG' => 'Could not retrieve your board configuration.', + 'CONV_ERROR_COULD_NOT_READ' => 'Unable to access/read “%sâ€.', + 'CONV_ERROR_GROUP_ACCESS' => 'Unable to get group authentication information.', + 'CONV_ERROR_INCONSISTENT_GROUPS' => 'Inconsistency in groups table detected in add_bots() - you need to add all special groups if you do it manually.', + 'CONV_ERROR_INSERT_BOT' => 'Unable to insert bot into users table.', + 'CONV_ERROR_INSERT_BOTGROUP' => 'Unable to insert bot into bots table.', + 'CONV_ERROR_INSERT_USER_GROUP' => 'Unable to insert user into user_group table.', + 'CONV_ERROR_MESSAGE_PARSER' => 'Message parser error', + 'CONV_ERROR_NO_AVATAR_PATH' => 'Note to developer: you must specify $convertor[\'avatar_path\'] to use %s.', + 'CONV_ERROR_NO_FORUM_PATH' => 'The relative path to the source board has not been specified.', + 'CONV_ERROR_NO_GALLERY_PATH' => 'Note to developer: you must specify $convertor[\'avatar_gallery_path\'] to use %s.', + 'CONV_ERROR_NO_GROUP' => 'Group “%1$s†could not be found in %2$s.', + 'CONV_ERROR_NO_RANKS_PATH' => 'Note to developer: you must specify $convertor[\'ranks_path\'] to use %s.', + 'CONV_ERROR_NO_SMILIES_PATH' => 'Note to developer: you must specify $convertor[\'smilies_path\'] to use %s.', + 'CONV_ERROR_NO_UPLOAD_DIR' => 'Note to developer: you must specify $convertor[\'upload_path\'] to use %s.', + 'CONV_ERROR_PERM_SETTING' => 'Unable to insert/update permission setting.', + 'CONV_ERROR_PM_COUNT' => 'Unable to select folder pm count.', + 'CONV_ERROR_REPLACE_CATEGORY' => 'Unable to insert new forum replacing old category.', + 'CONV_ERROR_REPLACE_FORUM' => 'Unable to insert new forum replacing old forum.', + 'CONV_ERROR_USER_ACCESS' => 'Unable to get user authentication information.', + 'CONV_ERROR_WRONG_GROUP' => 'Wrong group “%1$s†defined in %2$s.', + 'CONV_OPTIONS_BODY' => 'This page collects the data required to access the source board. Enter the database details of your former board; the converter will not change anything in the database given below. The source board should be disabled to allow a consistent conversion.', + 'CONV_SAVED_MESSAGES' => 'Saved messages', + + 'COULD_NOT_COPY' => 'Could not copy file %1$s to %2$s

            Please check that the target directory exists and is writable by the webserver.', + 'COULD_NOT_FIND_PATH' => 'Could not find path to your former board. Please check your settings and try again.
            » %s was specified as the source path.', + + 'DBMS' => 'Database type', + 'DB_CONFIG' => 'Database configuration', + 'DB_CONNECTION' => 'Database connection', + 'DB_ERR_INSERT' => 'Error while processing INSERT query.', + 'DB_ERR_LAST' => 'Error while processing query_last.', + 'DB_ERR_QUERY_FIRST' => 'Error while executing query_first.', + 'DB_ERR_QUERY_FIRST_TABLE' => 'Error while executing query_first, %s (“%sâ€).', + 'DB_ERR_SELECT' => 'Error while running SELECT query.', + 'DB_HOST' => 'Database server hostname or DSN', + 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.', + 'DB_NAME' => 'Database name', + 'DB_PASSWORD' => 'Database password', + 'DB_PORT' => 'Database server port', + 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.', + 'DB_UPDATE_NOT_SUPPORTED' => 'We are sorry, but this script does not support updating from versions of phpBB prior to “%1$sâ€. The version you currently have installed is “%2$sâ€. Please update to a previous version before running this script. Assistance with this is available in the Support Forum on phpBB.com.', + 'DB_USERNAME' => 'Database username', + 'DB_TEST' => 'Test connection', + 'DEFAULT_LANG' => 'Default board language', + 'DEFAULT_PREFIX_IS' => 'The convertor was not able to find tables with the specified prefix. Please make sure you have entered the correct details for the board you are converting from. The default table prefix for %1$s is %2$s.', + 'DEV_NO_TEST_FILE' => 'No value has been specified for the test_file variable in the convertor. If you are a user of this convertor, you should not be seeing this error, please report this message to the convertor author. If you are a convertor author, you must specify the name of a file which exists in the source board to allow the path to it to be verified.', + 'DIRECTORIES_AND_FILES' => 'Directory and file setup', + 'DISABLE_KEYS' => 'Disabling keys', + 'DLL_FTP' => 'Remote FTP support [ Installation ]', + 'DLL_GD' => 'GD graphics support [ Visual Confirmation ]', + 'DLL_MBSTRING' => 'Multi-byte character support', + 'DLL_MSSQL' => 'MSSQL Server 2000+', + 'DLL_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC', + 'DLL_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]', + 'DLL_MYSQL' => 'MySQL', + 'DLL_MYSQLI' => 'MySQL with MySQLi Extension', + 'DLL_ORACLE' => 'Oracle', + 'DLL_POSTGRES' => 'PostgreSQL', + 'DLL_SQLITE' => 'SQLite 2', + 'DLL_SQLITE3' => 'SQLite 3', + 'DLL_XML' => 'XML support [ Jabber ]', + 'DLL_ZLIB' => 'zlib compression support [ gz, .tar.gz, .zip ]', + 'DL_CONFIG' => 'Download config', + 'DL_CONFIG_EXPLAIN' => 'You may download the complete config.php to your own PC. You will then need to upload the file manually, replacing any existing config.php in your phpBB 3.1 root directory. Please remember to upload the file in ASCII format (see your FTP application documentation if you are unsure how to achieve this). When you have uploaded the config.php please click “Done†to move to the next stage.', + 'DL_DOWNLOAD' => 'Download', + 'DONE' => 'Done', + + 'ENABLE_KEYS' => 'Re-enabling keys. This can take a while.', + + 'FILES_OPTIONAL' => 'Optional files and directories', + 'FILES_OPTIONAL_EXPLAIN' => 'Optional - These files, directories or permission settings are not required. The installation system will attempt to use various techniques to create them if they do not exist or cannot be written to. However, the presence of these will speed installation.', + 'FILES_REQUIRED' => 'Files and Directories', + 'FILES_REQUIRED_EXPLAIN' => 'Required - In order to function correctly phpBB needs to be able to access or write to certain files or directories. If you see “Not Found†you need to create the relevant file or directory. If you see “Unwritable†you need to change the permissions on the file or directory to allow phpBB to write to it.', + 'FILLING_TABLE' => 'Filling table %s', + 'FILLING_TABLES' => 'Filling tables', + + 'FINAL_STEP' => 'Process final step', + 'FORUM_ADDRESS' => 'Board address', + 'FORUM_ADDRESS_EXPLAIN' => 'This is the URL of your former board, for example http://www.example.com/phpBB2/. If an address is entered here and not left empty every instance of this address will be replaced by your new board address within messages, private messages and signatures.', + 'FORUM_PATH' => 'Board path', + 'FORUM_PATH_EXPLAIN' => 'This is the relative path on disk to your former board from the root of this phpBB3 installation.', + 'FOUND' => 'Found', + 'FTP_CONFIG' => 'Transfer config by FTP', + 'FTP_CONFIG_EXPLAIN' => 'phpBB has detected the presence of the FTP module on this server. You may attempt to install your config.php via this if you wish. You will need to supply the information listed below. Remember your username and password are those to your server! (ask your hosting provider for details if you are unsure what these are).', + 'FTP_PATH' => 'FTP path', + 'FTP_PATH_EXPLAIN' => 'This is the path from your root directory to that of phpBB, e.g. htdocs/phpBB3/.', + 'FTP_UPLOAD' => 'Upload', + + 'GPL' => 'General Public License', + + 'INITIAL_CONFIG' => 'Basic configuration', + 'INITIAL_CONFIG_EXPLAIN' => 'Now that install has determined your server can run phpBB you need to supply some specific information. If you do not know how to connect to your database please contact your hosting provider (in the first instance) or use the phpBB support forums. When entering data please ensure you check it thoroughly before continuing.', + 'INSTALL_CONGRATS' => 'Congratulations!', + 'INSTALL_CONGRATS_EXPLAIN' => ' + You have successfully installed phpBB %1$s. Please proceed by choosing one of the following options:

            +

            Convert an existing board to phpBB3

            +

            The phpBB Unified Convertor Framework supports the conversion of phpBB 2.0.x and other board systems to phpBB3. If you have an existing board that you wish to convert, please proceed to the convertor.

            +

            Go live with your phpBB3!

            +

            Clicking the button below will take you to a form for submitting statistical data to phpBB in your Administration Control Panel (ACP). We would appreciate it if you could help us by sending that information. Afterwards you should take some time to examine the options available to you. Remember that help is available online via the Documentation, README and the Support Forums.

            Please delete, move or rename the install directory before using your board. While this directory exists, only the Administration Control Panel (ACP) will be accessible.', + 'INSTALL_INTRO' => 'Welcome to Installation', + + 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.

            In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:

            + +
              +
            • The Database Type - the database you will be using.
            • +
            • The Database server hostname or DSN - the address of the database server.
            • +
            • The Database server port - the port of the database server (most of the time this is not needed).
            • +
            • The Database name - the name of the database on the server.
            • +
            • The Database username and Database password - the login data to access the database.
            • +
            + +

            Note: if you are installing using SQLite, you should enter the full path to your database file in the DSN field and leave the username and password fields blank. For security reasons, you should make sure that the database file is not stored in a location accessible from the web.

            + +

            phpBB3 supports the following databases:

            +
              +
            • MySQL 3.23 or above (MySQLi supported)
            • +
            • PostgreSQL 8.3+
            • +
            • SQLite 2.8.2+
            • +
            • SQLite 3.6.15+
            • +
            • MS SQL Server 2000 or above (directly or via ODBC)
            • +
            • MS SQL Server 2005 or above (native)
            • +
            • Oracle
            • +
            + +

            Only those databases supported on your server will be displayed.', + 'INSTALL_INTRO_NEXT' => 'To commence the installation, please press the button below.', + 'INSTALL_LOGIN' => 'Login', + 'INSTALL_NEXT' => 'Next stage', + 'INSTALL_NEXT_FAIL' => 'Some tests failed and you should correct these problems before proceeding to the next stage. Failure to do so may result in an incomplete installation.', + 'INSTALL_NEXT_PASS' => 'All the basic tests have been passed and you may proceed to the next stage of installation. If you have changed any permissions, modules, etc. and wish to re-test you can do so if you wish.', + 'INSTALL_PANEL' => 'Installation Panel', + 'INSTALL_SEND_CONFIG' => 'Unfortunately phpBB could not write the configuration information directly to your config.php. This may be because the file does not exist or is not writable. A number of options will be listed below enabling you to complete installation of config.php.', + 'INSTALL_START' => 'Start install', + 'INSTALL_TEST' => 'Test again', + 'INST_ERR' => 'Installation error', + 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.', + 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.', + 'INST_ERR_DB_INVALID_PREFIX'=> 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.', + 'INST_ERR_DB_NO_ERROR' => 'No error message given.', + 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension†option you have selected. Please try the “MySQL†option instead.', + 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.', + 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.', + 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the NLS_CHARACTERSET parameter to UTF8. Either upgrade your installation to 9.2+ or change the parameter.', + 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in UNICODE or UTF8 encoding. Try installing with a database in UNICODE or UTF8 encoding.', + 'INST_ERR_DB_NO_NAME' => 'No database name specified.', + 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.', + 'INST_ERR_EMAIL_MISMATCH' => 'The emails you entered did not match.', + 'INST_ERR_FATAL' => 'Fatal installation error', + 'INST_ERR_FATAL_DB' => 'A fatal and unrecoverable database error has occurred. This may be because the specified user does not have appropriate permissions to CREATE TABLES or INSERT data, etc. Further information may be given below. Please contact your hosting provider in the first instance or the support forums of phpBB for further assistance.', + 'INST_ERR_FTP_PATH' => 'Could not change to the given directory, please check the path.', + 'INST_ERR_FTP_LOGIN' => 'Could not login to FTP server, check your username and password.', + 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.', + 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.', + 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.', + 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.', + 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.', + 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.', + 'INST_ERR_PREFIX_INVALID' => 'The table prefix you have specified is invalid for your database. Please try another, removing characters such as the hyphen.', + 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.', + 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.', + 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.', + 'INVALID_PRIMARY_KEY' => 'Invalid primary key : %s', + + 'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.', + + // mbstring + 'MBSTRING_CHECK' => 'mbstring extension check', + 'MBSTRING_CHECK_EXPLAIN' => 'Required - mbstring is a PHP extension that provides multibyte string functions. Certain features of mbstring are not compatible with phpBB and must be disabled.', + 'MBSTRING_FUNC_OVERLOAD' => 'Function overloading', + 'MBSTRING_FUNC_OVERLOAD_EXPLAIN' => 'mbstring.func_overload must be set to either 0 or 4.', + 'MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding', + 'MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => 'mbstring.encoding_translation must be set to 0.', + 'MBSTRING_HTTP_INPUT' => 'HTTP input character conversion', + 'MBSTRING_HTTP_INPUT_EXPLAIN' => 'mbstring.http_input must be set to pass.', + 'MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion', + 'MBSTRING_HTTP_OUTPUT_EXPLAIN' => 'mbstring.http_output must be set to pass.', + + 'MAKE_FOLDER_WRITABLE' => 'Please make sure that this folder exists and is writable by the webserver then try again:
            »%s.', + 'MAKE_FOLDERS_WRITABLE' => 'Please make sure that these folders exist and are writable by the webserver then try again:
            »%s.', + + 'MYSQL_SCHEMA_UPDATE_REQUIRED' => 'Your MySQL database schema for phpBB is outdated. phpBB detected a schema for MySQL 3.x/4.x, but the server runs on MySQL %2$s.
            Before you proceed the update, you need to upgrade the schema.

            Please refer to the Knowledge Base article about upgrading the MySQL schema. If you encounter problems, please use our support forums.', + + 'NAMING_CONFLICT' => 'Naming conflict: %s and %s are both aliases

            %s', + 'NEXT_STEP' => 'Proceed to next step', + 'NOT_FOUND' => 'Cannot find', + 'NOT_UNDERSTAND' => 'Could not understand %s #%d, table %s (“%sâ€)', + 'NO_CONVERTORS' => 'No convertors are available for use.', + 'NO_CONVERT_SPECIFIED' => 'No convertor specified.', + 'NO_LOCATION' => 'Cannot determine location. If you know Imagemagick is installed, you may specify the location later within your administration control panel', + 'NO_TABLES_FOUND' => 'No tables found.', + + 'OVERVIEW_BODY' => 'Welcome to phpBB3!

            phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.

            This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read the installation guide.

            To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.', + + 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support', + 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.', + 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP function getimagesize() is available', + 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'Required - In order for phpBB to function correctly, the getimagesize function needs to be available.', + 'PHP_JSON_SUPPORT' => 'PHP JSON support', + 'PHP_JSON_SUPPORT_EXPLAIN' => 'Required - In order for phpBB to function correctly, the PHP JSON extension needs to be available.', + 'PHP_OPTIONAL_MODULE' => 'Optional modules', + 'PHP_OPTIONAL_MODULE_EXPLAIN' => 'Optional - These modules or applications are optional. However, if they are available they will enable extra features.', + 'PHP_SUPPORTED_DB' => 'Supported databases', + 'PHP_SUPPORTED_DB_EXPLAIN' => 'Required - You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.', + 'PHP_REGISTER_GLOBALS' => 'PHP setting register_globals is disabled', + 'PHP_REGISTER_GLOBALS_EXPLAIN' => 'phpBB will still run if this setting is enabled, but if possible, it is recommended that register_globals is disabled on your PHP install for security reasons.', + 'PHP_SAFE_MODE' => 'Safe mode', + 'PHP_SETTINGS' => 'PHP version and settings', + 'PHP_SETTINGS_EXPLAIN' => 'Required - You must be running at least version 5.3.9 of PHP in order to install phpBB. If safe mode is displayed below your PHP installation is running in that mode. This will impose limitations on remote administration and similar features.', + 'PHP_URL_FOPEN_SUPPORT' => 'PHP setting allow_url_fopen is enabled', + 'PHP_URL_FOPEN_SUPPORT_EXPLAIN' => 'Optional - This setting is optional, however certain phpBB functions like off-site avatars will not work properly without it.', + 'PHP_VERSION_REQD' => 'PHP version >= 5.3.9', + 'POST_ID' => 'Post ID', + 'PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using %s as table prefix.', + 'PREPROCESS_STEP' => 'Executing pre-processing functions/queries', + 'PRE_CONVERT_COMPLETE' => 'All pre-conversion steps have successfully been completed. You may now begin the actual conversion process. Please note that you may have to manually do and adjust several things. After conversion, especially check the permissions assigned, rebuild your search index which is not converted and also make sure files got copied correctly, for example avatars and smilies.', + 'PROCESS_LAST' => 'Processing last statements', + + 'REFRESH_PAGE' => 'Refresh page to continue conversion', + 'REFRESH_PAGE_EXPLAIN' => 'If set to yes, the convertor will refresh the page to continue the conversion after having finished a step. If this is your first conversion for testing purposes and to determine any errors in advance, we suggest to set this to No.', + 'REQUIREMENTS_TITLE' => 'Installation compatibility', + 'REQUIREMENTS_EXPLAIN' => 'Before proceeding with the full installation phpBB will carry out some tests on your server configuration and files to ensure that you are able to install and run phpBB. Please ensure you read through the results thoroughly and do not proceed until all the required tests are passed. If you wish to use any of the features depending on the optional tests, you should ensure that these tests are passed also.', + 'RETRY_WRITE' => 'Retry writing config', + 'RETRY_WRITE_EXPLAIN' => 'If you wish you can change the permissions on config.php to allow phpBB to write to it. Should you wish to do that you can click Retry below to try again. Remember to return the permissions on config.php after phpBB has finished installation.', + + 'SELECT_LANG' => 'Select language', + 'SEARCH_INDEX_UNCONVERTED' => 'Search index was not converted', + 'SEARCH_INDEX_UNCONVERTED_EXPLAIN' => 'Your old search index was not converted. Searching will always yield an empty result. To create a new search index go to the Administration Control Panel, select Maintenance and then choose Search index from the submenu.', + 'SELECT_FORUM_GA' => 'In phpBB 3.1 the global announcements are linked to forums. Select a forum for your current global announcements (can be moved later):', + 'SOFTWARE' => 'Board software', + 'SPECIFY_OPTIONS' => 'Specify conversion options', + 'STAGE_ADMINISTRATOR' => 'Administrator details', + 'STAGE_ADVANCED' => 'Advanced settings', + 'STAGE_ADVANCED_EXPLAIN' => 'The settings on this page are only necessary to set if you know that you require something different from the default. If you are unsure, just proceed to the next page, as these settings can be altered from the Administration Control Panel later.', + 'STAGE_CONFIG_FILE' => 'Configuration file', + 'STAGE_CREATE_TABLE' => 'Create database tables', + 'STAGE_CREATE_TABLE_EXPLAIN' => 'The database tables used by phpBB 3.1 have been created and populated with some initial data. Proceed to the next screen to finish installing phpBB.', + 'STAGE_DATABASE' => 'Database settings', + 'STAGE_FINAL' => 'Final stage', + 'STAGE_INTRO' => 'Introduction', + 'STAGE_IN_PROGRESS' => 'Conversion in progress', + 'STAGE_REQUIREMENTS' => 'Requirements', + 'STAGE_SETTINGS' => 'Settings', + 'STARTING_CONVERT' => 'Starting conversion process', + 'STEP_PERCENT_COMPLETED' => 'Step %d of %d', + 'SUB_INTRO' => 'Introduction', + 'SUB_LICENSE' => 'License', + 'SUB_SUPPORT' => 'Support', + 'SUCCESSFUL_CONNECT' => 'Successful connection', + 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:

            • installation
            • configuration
            • technical questions
            • problems relating to potential bugs in the software
            • updating from Release Candidate (RC) versions to the latest stable version
            • converting from phpBB 2.0.x to phpBB3
            • converting from other discussion board software to phpBB3 (please see the Convertors Forum)

            We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.

            Extensions / Styles

            For issues relating to Extensions, please post in the appropriate Extensions Forum.
            For issues relating to styles, templates and themes, please post in the appropriate Styles Forum.

            If your question relates to a specific package, please post directly in the topic dedicated to the package.

            Obtaining Support

            The phpBB Welcome Package
            Support Section
            Quick Start Guide

            To ensure you stay up to date with the latest news and releases, why not subscribe to our mailing list?

            ', + 'SYNC_FORUMS' => 'Starting to synchronise forums', + 'SYNC_POST_COUNT' => 'Synchronising post_counts', + 'SYNC_POST_COUNT_ID' => 'Synchronising post_counts from entry %1$s to %2$s.', + 'SYNC_TOPICS' => 'Starting to synchronise topics', + 'SYNC_TOPIC_ID' => 'Synchronising topics from topic_id %1$s to %2$s.', + + 'TABLES_MISSING' => 'Could not find these tables
            » %s.', + 'TABLE_PREFIX' => 'Prefix for tables in database', + 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.', + 'TABLE_PREFIX_SAME' => 'The table prefix needs to be the one used by the software you are converting from.
            » Specified table prefix was %s.', + 'TESTS_PASSED' => 'Tests passed', + 'TESTS_FAILED' => 'Tests failed', + + 'UNABLE_WRITE_LOCK' => 'Unable to write lock file.', + 'UNAVAILABLE' => 'Unavailable', + 'UNWRITABLE' => 'Unwritable', + 'UPDATE_TOPICS_POSTED' => 'Generating topics posted information', + 'UPDATE_TOPICS_POSTED_ERR' => 'An error occurred while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.', + 'VERIFY_OPTIONS' => 'Verifying conversion options', + 'VERSION' => 'Version', + + 'WELCOME_INSTALL' => 'Welcome to phpBB3 Installation', + 'WRITABLE' => 'Writable', +)); + +// Updater +$lang = array_merge($lang, array( + 'ALL_FILES_UP_TO_DATE' => 'All files are up to date with the latest phpBB version.', + 'ARCHIVE_FILE' => 'Source file within archive', + + 'BACK' => 'Back', + 'BINARY_FILE' => 'Binary file', + 'BOT' => 'Spider/Robot', + + 'CHANGE_CLEAN_NAMES' => 'The method used to make sure a username is not used by multiple users has been changed. There are some users which have the same name when compared with the new method. You have to delete or rename these users to make sure that each name is only used by one user before you can proceed.', + 'CHECK_FILES' => 'Check files', + 'CHECK_FILES_AGAIN' => 'Check files again', + 'CHECK_FILES_EXPLAIN' => 'Within the next step all files will be checked against the update files - this can take a while if this is the first file check.', + 'CHECK_FILES_UP_TO_DATE' => 'According to your database your version is up to date. You may want to proceed with the file check to make sure all files are really up to date with the latest phpBB version.', + 'CHECK_UPDATE_DATABASE' => 'Continue update process', + 'COLLECTED_INFORMATION' => 'File information', + 'COLLECTED_INFORMATION_EXPLAIN' => 'The list below shows information about the files needing an update. Please read the information in front of every status block to see what they mean and what you may need to do to perform a successful update.', + 'COLLECTING_FILE_DIFFS' => 'Collecting file differences', + 'COMPLETE_LOGIN_TO_BOARD' => 'You should now login to your board and check if everything is working fine. Do not forget to delete, rename or move your install directory!', + 'CONTINUE_UPDATE_NOW' => 'Continue the update process now', // Shown within the database update script at the end if called from the updater + 'CONTINUE_UPDATE' => 'Continue update now', // Shown after file upload to indicate the update process is not yet finished + 'CURRENT_FILE' => 'Begin of Conflict - Original File code before update', + 'CURRENT_VERSION' => 'Current version', + + 'DATABASE_TYPE' => 'Database type', + 'DATABASE_UPDATE_COMPLETE' => 'Database updater has completed!', + 'DATABASE_UPDATE_CONTINUE' => 'Continue database update', + 'DATABASE_UPDATE_INFO_OLD' => 'The database update file within the install directory is outdated. Please make sure you uploaded the correct version of the file.', + 'DATABASE_UPDATE_NOT_COMPLETED' => 'The database update has not yet completed.', + 'DELETE_USER_REMOVE' => 'Delete user and remove posts', + 'DELETE_USER_RETAIN' => 'Delete user but keep posts', + 'DESTINATION' => 'Destination file', + 'DIFF_INLINE' => 'Inline', + 'DIFF_RAW' => 'Raw unified diff', + 'DIFF_SEP_EXPLAIN' => 'Code block used within the updated/new file', + 'DIFF_SIDE_BY_SIDE' => 'Side by Side', + 'DIFF_UNIFIED' => 'Unified diff', + 'DO_NOT_UPDATE' => 'Do not update this file', + 'DONE' => 'Done', + 'DOWNLOAD' => 'Download', + 'DOWNLOAD_AS' => 'Download as', + 'DOWNLOAD_UPDATE_METHOD_BUTTON' => 'Download modified files archive (recommended)', + 'DOWNLOAD_CONFLICTS' => 'Download conflicts for this file', + 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for <<< to spot conflicts', + 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive', + 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, please check the files again with the other button below.', + + 'EDIT_USERNAME' => 'Edit username', + 'ERROR' => 'Error', + 'EVERYTHING_UP_TO_DATE' => 'Everything is up to date with the latest phpBB version. You should now login to your board and check if everything is working fine. Do not forget to delete, rename or move your install directory! Please send us updated information about your server and board configurations from the Send statistics module in your ACP.', + + 'FILE_ALREADY_UP_TO_DATE' => 'File is already up to date.', + 'FILE_DIFF_NOT_ALLOWED' => 'File not allowed to be diffed.', + 'FILE_USED' => 'Information used from', // Single file + 'FILES_CONFLICT' => 'Conflict files', + 'FILES_CONFLICT_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. phpBB determined that these files create conflicts if they are tried to be merged. Please investigate the conflicts and try to manually resolve them or continue the update choosing the preferred merging method. If you resolve the conflicts manually check the files again after you modified them. You are also able to choose between the preferred merge method for every file. The first one will result in a file where the conflicting lines from your old file will be lost, the other one will result in losing the changes from the newer file.', + 'FILES_DELETED' => 'Deleted files', + 'FILES_DELETED_EXPLAIN' => 'The following files do not exist in the new version. These files have to be deleted from your installation.', + 'FILES_MODIFIED' => 'Modified files', + 'FILES_MODIFIED_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. The updated file will be a merge between your modifications and the new file.', + 'FILES_NEW' => 'New files', + 'FILES_NEW_EXPLAIN' => 'The following files currently do not exist within your installation. These files will be added to your installation.', + 'FILES_NEW_CONFLICT' => 'New conflicting files', + 'FILES_NEW_CONFLICT_EXPLAIN' => 'The following files are new within the latest version but it has been determined that there is already a file with the same name within the same position. This file will be overwritten by the new file.', + 'FILES_NOT_MODIFIED' => 'Not modified files', + 'FILES_NOT_MODIFIED_EXPLAIN' => 'The following files are not modified and represent the original phpBB files from the version you want to update from.', + 'FILES_UP_TO_DATE' => 'Already updated files', + 'FILES_UP_TO_DATE_EXPLAIN' => 'The following files are already up to date and do not need to be updated.', + 'FTP_SETTINGS' => 'FTP settings', + 'FTP_UPDATE_METHOD' => 'FTP upload', + + 'INCOMPATIBLE_UPDATE_FILES' => 'The update files found are incompatible with your installed version. Your installed version is %1$s and the update file is for updating phpBB %2$s to %3$s.', + 'INCOMPLETE_UPDATE_FILES' => 'The update files are incomplete.', + 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful. Now you need to continue the update process.', + + 'KEEP_OLD_NAME' => 'Keep username', + + 'LATEST_VERSION' => 'Latest version', + 'LINE' => 'Line', + 'LINE_ADDED' => 'Added', + 'LINE_MODIFIED' => 'Modified', + 'LINE_REMOVED' => 'Removed', + 'LINE_UNMODIFIED' => 'Unmodified', + 'LOGIN_UPDATE_EXPLAIN' => 'In order to update your installation you need to login first.', + + 'MAPPING_FILE_STRUCTURE' => 'To ease the upload here are the file locations which map your phpBB installation.', + + 'MERGE_MODIFICATIONS_OPTION' => 'Merge modifications', + + 'MERGE_NO_MERGE_NEW_OPTION' => 'Do not merge - use new file', + 'MERGE_NO_MERGE_MOD_OPTION' => 'Do not merge - use currently installed file', + 'MERGE_MOD_FILE_OPTION' => 'Merge modifications (removes new phpBB code within conflicting block)', + 'MERGE_NEW_FILE_OPTION' => 'Merge modifications (removes modified code within conflicting block)', + 'MERGE_SELECT_ERROR' => 'Conflicting file merge modes are not correctly selected.', + 'MERGING_FILES' => 'Merging differences', + 'MERGING_FILES_EXPLAIN' => 'Currently collecting final file changes.

            Please wait until phpBB has completed all operations on changed files.', + + 'NEW_FILE' => 'End of Conflict', + 'NEW_USERNAME' => 'New username', + 'NO_AUTH_UPDATE' => 'Not authorised to update', + 'NO_ERRORS' => 'No errors', + 'NO_UPDATE_FILES' => 'Not updating the following files', + 'NO_UPDATE_FILES_EXPLAIN' => 'The following files are new or modified but the directory they normally reside in could not be found on your installation. If this list contains files to other directories than language/ or styles/ than you may have modified your directory structure and the update may be incomplete.', + 'NO_UPDATE_FILES_OUTDATED' => 'No valid update directory was found, please make sure you uploaded the relevant files.

            Your installation does not seem to be up to date. Updates are available for your version of phpBB %1$s, please visit https://www.phpbb.com/downloads/ to obtain the correct package to update from Version %2$s to Version %3$s.', + 'NO_UPDATE_FILES_UP_TO_DATE' => 'Your version is up to date. There is no need to run the update tool. If you want to make an integrity check on your files make sure you uploaded the correct update files.', + 'NO_UPDATE_INFO' => 'Update file information could not be found.', + 'NO_UPDATES_REQUIRED' => 'No updates required', + 'NO_VISIBLE_CHANGES' => 'No visible changes', + 'NOTICE' => 'Notice', + 'NUM_CONFLICTS' => 'Number of conflicts', + 'NUMBER_OF_FILES_COLLECTED' => 'Currently differences from %1$d of %2$d files have been checked.
            Please wait until all files are checked.', + + 'OLD_UPDATE_FILES' => 'Update files are out of date. The update files found are for updating from phpBB %1$s to phpBB %2$s but the latest version of phpBB is %3$s.', + + 'PACKAGE_UPDATES_TO' => 'Current package updates to version', + 'PERFORM_DATABASE_UPDATE' => 'Perform database update', + 'PERFORM_DATABASE_UPDATE_EXPLAIN' => 'Below you will find a button to the database update script. The database update can take a while, so please do not stop the execution if it seems to hang. After the database update has been performed just follow the instructions to continue the update process.', + 'PREVIOUS_VERSION' => 'Previous version', + 'PROGRESS' => 'Progress', + + 'RELEASE_ANNOUNCEMENT' => 'Announcement', + 'RESULT' => 'Result', + 'RUN_DATABASE_SCRIPT' => 'Update my database now', + + 'SELECT_DIFF_MODE' => 'Select diff mode', + 'SELECT_DOWNLOAD_FORMAT' => 'Select download archive format', + 'SELECT_FTP_SETTINGS' => 'Select FTP settings', + 'SHOW_DIFF_CONFLICT' => 'Show differences/conflicts', + 'SHOW_DIFF_DELETED' => 'Show file contents', + 'SHOW_DIFF_FINAL' => 'Show resulting file', + 'SHOW_DIFF_MODIFIED' => 'Show merged differences', + 'SHOW_DIFF_NEW' => 'Show file contents', + 'SHOW_DIFF_NEW_CONFLICT' => 'Show differences', + 'SHOW_DIFF_NOT_MODIFIED' => 'Show differences', + 'SOME_QUERIES_FAILED' => 'Some queries failed, the statements and errors are listed below.', + 'SQL' => 'SQL', + 'SQL_FAILURE_EXPLAIN' => 'This is probably nothing to worry about, update will continue. Should this fail to complete you may need to seek help at our support forums. See README for details on how to obtain advice.', + 'STAGE_FILE_CHECK' => 'Check files', + 'STAGE_UPDATE_DB' => 'Update database', + 'STAGE_UPDATE_FILES' => 'Update files', + 'STAGE_VERSION_CHECK' => 'Version check', + 'STATUS_CONFLICT' => 'Modified file producing conflicts', + 'STATUS_DELETED' => 'Deleted file', + 'STATUS_MODIFIED' => 'Modified file', + 'STATUS_NEW' => 'New file', + 'STATUS_NEW_CONFLICT' => 'Conflicting new file', + 'STATUS_NOT_MODIFIED' => 'Not modified file', + 'STATUS_UP_TO_DATE' => 'Already updated file', + + 'TOGGLE_DISPLAY' => 'View/Hide file list', + 'TRY_DOWNLOAD_METHOD' => 'You may want to try the download modified files method.
            This method always works and is also the recommended update path.', + 'TRY_DOWNLOAD_METHOD_BUTTON'=> 'Try this method now', + + 'UPDATE_COMPLETED' => 'Update completed', + 'UPDATE_DATABASE' => 'Update database', + 'UPDATE_DATABASE_EXPLAIN' => 'Within the next step the database will be updated.', + 'UPDATE_DATABASE_SCHEMA' => 'Updating database schema', + 'UPDATE_FILES' => 'Update files', + 'UPDATE_FILES_NOTICE' => 'Please make sure you have updated your board files too, this file is only updating your database.', + 'UPDATE_INSTALLATION' => 'Update phpBB installation', + 'UPDATE_INSTALLATION_EXPLAIN' => 'With this option, it is possible to update your phpBB installation to the latest version.
            During the process all of your files will be checked for their integrity. You are able to review all differences and files before the update.

            The file update itself can be done in two different ways.

            Manual Update

            With this update you only download your personal set of changed files to make sure you do not lose your file modifications you may have done. After you downloaded this package you need to manually upload the files to their correct position under your phpBB root directory. Once done, you are able to do the file check stage again to see if you moved the files to their correct location.

            Automatic Update with FTP

            This method is similar to the first one but without the need to download the changed files and uploading them on your own. This will be done for you. In order to use this method you need to know your FTP login details since you will be asked for them. Once finished you will be redirected to the file check again to make sure everything got updated correctly.

            ', + 'UPDATE_INSTRUCTIONS' => ' + +

            Release announcement

            + +

            Please read the release announcement for the latest version before you continue your update process, it may contain useful information. It also contains full download links as well as the change log.

            + +
            + +

            How to update your installation with the Automatic Update Package

            + +

            The recommended way of updating your installation listed here is only valid for the automatic update package. You are also able to update your installation using the methods listed within the INSTALL.html document. The steps for updating phpBB3 automatically are:

            + +
              +
            • Go to the phpBB.com downloads page and download the "Automatic Update Package" archive.

            • +
            • Unpack the archive.

            • +
            • Upload the complete uncompressed "install" and "vendor" folders to your phpBB root directory (where your config.php file is).

            • +
            + +

            Once uploaded your board will be offline for normal users due to the install directory you uploaded now present.

            + Now start the update process by pointing your browser to the install folder.
            +
            + You will then be guided through the update process. You will be notified once the update is complete. +

            + ', + 'UPDATE_METHOD' => 'Update method', + 'UPDATE_METHOD_EXPLAIN' => 'You are now able to choose your preferred update method. Using the FTP upload will present you with a form you need to enter your FTP account details into. With this method the files will be automatically moved to the new location and backups of the old files being created by appending .bak to the filename. If you choose to download the modified files you are able to unpack and upload them to their correct location manually later.', + 'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s', + 'UPDATE_SUCCESS' => 'Update was successful', + 'UPDATE_SUCCESS_EXPLAIN' => 'Successfully updated all files. The next step involves checking all files again to make sure the files got updated correctly.', + 'UPDATE_VERSION_OPTIMIZE' => 'Updating version and optimising tables', + 'UPDATING_DATA' => 'Updating data', + 'UPDATING_TO_LATEST_STABLE' => 'Updating database to latest stable release', + 'UPDATED_VERSION' => 'Updated version', + 'UPLOAD_METHOD' => 'Upload method', + + 'UPDATE_DB_SUCCESS' => 'Database update was successful.', + 'UPDATE_FILE_SUCCESS' => 'File update was successful.', + 'USER_ACTIVE' => 'Active user', + 'USER_INACTIVE' => 'Inactive user', + + 'VERSION_CHECK' => 'Version check', + 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.', + 'VERSION_NOT_UP_TO_DATE' => 'Your phpBB installation is not up to date. Please continue the update process.', + 'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.
            Below is a link to the release announcement, which contains more information as well as instructions on updating.', + 'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.', + 'VERSION_UP_TO_DATE' => 'Your phpBB installation is up to date. Although there are no updates available at this time, you may continue in order to perform a file validity check.', + 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.', + 'VIEWING_FILE_CONTENTS' => 'Viewing file contents', + 'VIEWING_FILE_DIFF' => 'Viewing file differences', + + 'WRONG_INFO_FILE_FORMAT' => 'Wrong info file format', +)); + +// Default database schema entries... +$lang = array_merge($lang, array( + 'CONFIG_BOARD_EMAIL_SIG' => 'Thanks, The Management', + 'CONFIG_SITE_DESC' => 'A short text to describe your forum', + 'CONFIG_SITENAME' => 'yourdomain.com', + + 'DEFAULT_INSTALL_POST' => 'This is an example post in your phpBB3 installation. Everything seems to be working. You may delete this post if you like and continue to set up your board. During the installation process your first category and your first forum are assigned an appropriate set of permissions for the predefined usergroups administrators, bots, global moderators, guests, registered users and registered COPPA users. If you also choose to delete your first category and your first forum, do not forget to assign permissions for all these usergroups for all new categories and forums you create. It is recommended to rename your first category and your first forum and copy permissions from these while creating new categories and forums. Have fun!', + + 'FORUMS_FIRST_CATEGORY' => 'Your first category', + 'FORUMS_TEST_FORUM_DESC' => 'Description of your first forum.', + 'FORUMS_TEST_FORUM_TITLE' => 'Your first forum', + + 'RANKS_SITE_ADMIN_TITLE' => 'Site Admin', + 'REPORT_WAREZ' => 'The post contains links to illegal or pirated software.', + 'REPORT_SPAM' => 'The reported post has the only purpose to advertise for a website or another product.', + 'REPORT_OFF_TOPIC' => 'The reported post is off topic.', + 'REPORT_OTHER' => 'The reported post does not fit into any other category, please use the further information field.', + + 'SMILIES_ARROW' => 'Arrow', + 'SMILIES_CONFUSED' => 'Confused', + 'SMILIES_COOL' => 'Cool', + 'SMILIES_CRYING' => 'Crying or Very Sad', + 'SMILIES_EMARRASSED' => 'Embarrassed', + 'SMILIES_EVIL' => 'Evil or Very Mad', + 'SMILIES_EXCLAMATION' => 'Exclamation', + 'SMILIES_GEEK' => 'Geek', + 'SMILIES_IDEA' => 'Idea', + 'SMILIES_LAUGHING' => 'Laughing', + 'SMILIES_MAD' => 'Mad', + 'SMILIES_MR_GREEN' => 'Mr. Green', + 'SMILIES_NEUTRAL' => 'Neutral', + 'SMILIES_QUESTION' => 'Question', + 'SMILIES_RAZZ' => 'Razz', + 'SMILIES_ROLLING_EYES' => 'Rolling Eyes', + 'SMILIES_SAD' => 'Sad', + 'SMILIES_SHOCKED' => 'Shocked', + 'SMILIES_SMILE' => 'Smile', + 'SMILIES_SURPRISED' => 'Surprised', + 'SMILIES_TWISTED_EVIL' => 'Twisted Evil', + 'SMILIES_UBER_GEEK' => 'Uber Geek', + 'SMILIES_VERY_HAPPY' => 'Very Happy', + 'SMILIES_WINK' => 'Wink', + + 'TOPICS_TOPIC_TITLE' => 'Welcome to phpBB3', +)); From 8155205ae7a5ec27ff3058137513fc480d7ee6c5 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Fri, 17 Apr 2015 23:17:23 +0200 Subject: [PATCH 0440/1676] [ticket/13740] Implementation of the new installer framework [ci skip] PHPBB3-13740 --- .../cannot_build_container_exception.php | 22 + .../exception/invalid_dbms_exception.php | 22 + .../user_interaction_required_exception.php | 22 + phpBB/install/helper/config.php | 259 ++++++++++ phpBB/install/helper/container_factory.php | 149 ++++++ phpBB/install/helper/database.php | 459 ++++++++++++++++++ .../helper/iohandler/ajax_iohandler.php | 202 ++++++++ .../iohandler_not_implemented_exception.php | 19 + phpBB/install/helper/iohandler/factory.php | 72 +++ .../helper/iohandler/iohandler_base.php | 121 +++++ .../helper/iohandler/iohandler_interface.php | 119 +++++ .../helper/navigation/install_navigation.php | 28 ++ .../navigation/navigation_interface.php | 43 ++ .../helper/navigation/navigation_provider.php | 92 ++++ phpBB/install/installer.php | 146 ++++++ phpBB/install/module_base.php | 175 +++++++ phpBB/install/module_interface.php | 56 +++ phpBB/install/task_base.php | 53 ++ phpBB/install/task_interface.php | 47 ++ 19 files changed, 2106 insertions(+) create mode 100644 phpBB/install/exception/cannot_build_container_exception.php create mode 100644 phpBB/install/exception/invalid_dbms_exception.php create mode 100644 phpBB/install/exception/user_interaction_required_exception.php create mode 100644 phpBB/install/helper/config.php create mode 100644 phpBB/install/helper/container_factory.php create mode 100644 phpBB/install/helper/database.php create mode 100644 phpBB/install/helper/iohandler/ajax_iohandler.php create mode 100644 phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php create mode 100644 phpBB/install/helper/iohandler/factory.php create mode 100644 phpBB/install/helper/iohandler/iohandler_base.php create mode 100644 phpBB/install/helper/iohandler/iohandler_interface.php create mode 100644 phpBB/install/helper/navigation/install_navigation.php create mode 100644 phpBB/install/helper/navigation/navigation_interface.php create mode 100644 phpBB/install/helper/navigation/navigation_provider.php create mode 100644 phpBB/install/installer.php create mode 100644 phpBB/install/module_base.php create mode 100644 phpBB/install/module_interface.php create mode 100644 phpBB/install/task_base.php create mode 100644 phpBB/install/task_interface.php diff --git a/phpBB/install/exception/cannot_build_container_exception.php b/phpBB/install/exception/cannot_build_container_exception.php new file mode 100644 index 0000000000..11be507bc9 --- /dev/null +++ b/phpBB/install/exception/cannot_build_container_exception.php @@ -0,0 +1,22 @@ + + * @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\install\exception; + +/** + * This exception should be thrown when + */ +class cannot_build_container_exception extends installer_exception +{ + +} diff --git a/phpBB/install/exception/invalid_dbms_exception.php b/phpBB/install/exception/invalid_dbms_exception.php new file mode 100644 index 0000000000..ccb35bc237 --- /dev/null +++ b/phpBB/install/exception/invalid_dbms_exception.php @@ -0,0 +1,22 @@ + + * @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\install\exception; + +/** + * This exception should be thrown when + */ +class invalid_dbms_exception extends installer_exception +{ + +} diff --git a/phpBB/install/exception/user_interaction_required_exception.php b/phpBB/install/exception/user_interaction_required_exception.php new file mode 100644 index 0000000000..0aaae648cf --- /dev/null +++ b/phpBB/install/exception/user_interaction_required_exception.php @@ -0,0 +1,22 @@ + + * @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\install\exception; + +/** + * This exception should be thrown when user interaction is inevitable + */ +class user_interaction_required_exception extends installer_exception +{ + +} diff --git a/phpBB/install/helper/config.php b/phpBB/install/helper/config.php new file mode 100644 index 0000000000..b759df737e --- /dev/null +++ b/phpBB/install/helper/config.php @@ -0,0 +1,259 @@ + + * @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\install\helper; + +/** + * Stores common settings and installation status + */ +class config +{ + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** + * Array which contains config settings for the installer + * + * The array will also store all the user input, as well as any + * data that is passed to other tasks by a task. + * + * @var array + */ + protected $installer_config; + + /** + * @var string + */ + protected $install_config_file; + + /** + * @var \phpbb\php\ini + */ + protected $php_ini; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * Array containing progress information + * + * @var array + */ + protected $progress_data; + + /** + * Array containing system information + * + * The array contains run time and memory limitations. + * + * @var array + */ + protected $system_data; + + /** + * Constructor + */ + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, \phpbb\php\ini $php_ini, $phpbb_root_path) + { + $this->filesystem = $filesystem; + $this->php_ini = $php_ini; + $this->phpbb_root_path = $phpbb_root_path; + + // Set up data arrays + $this->installer_config = array(); + $this->system_data = array(); + $this->progress_data = array( + 'last_task_module_index' => 0, + 'last_task_module_name' => '', // Stores the service name of the latest finished module + 'last_task_index' => 0, + 'last_task_name' => '', // Stores the service name of the latest finished task + ); + + $this->install_config_file = $this->phpbb_root_path . 'store/install_config.php'; + + $this->setup_system_data(); + } + + /** + * Returns data for a specified parameter + * + * @param string $param_name Name of the parameter to return + * @param mixed $default Default value to return when the specified data + * does not exist. + * + * @return mixed value of the specified parameter or the default value if the data + * cannot be recovered. + */ + public function get($param_name, $default = false) + { + return (isset($this->installer_config[$param_name])) ? $this->installer_config[$param_name] : $default; + } + + /** + * Sets a parameter in installer_config + * + * @param string $param_name Name of the parameter + * @param mixed $value Values to set the parameter + * + * @return null + */ + public function set($param_name, $value) + { + $this->installer_config = array_merge($this->installer_config, array( + $param_name => $value, + )); + } + + /** + * Returns system parameter + * + * @param string $param_name Name of the parameter + * + * @return mixed Returns system parameter if it is defined, false otherwise + */ + public function system_get($param_name) + { + return (isset($this->system_data[$param_name])) ? $this->system_data[$param_name] : false; + } + + /** + * Returns remaining time until the run time limit + * + * @return int Remaining time until the run time limit in seconds + */ + public function get_time_remaining() + { + return ($this->system_data['start_time'] + $this->system_data['max_execution_time']) - time(); + } + + /** + * Returns remaining memory available for PHP + * + * @return int Remaining memory until reaching the limit + */ + public function get_memory_remaining() + { + if (function_exists('memory_get_usage')) + { + return ($this->system_data['memory_limit'] - memory_get_usage()); + } + + // If we cannot get the information then just return a positive number (and cross fingers) + return 1; + } + + /** + * Saves the latest executed task + * + * @param string $task_service_name Name of the installer task service + * @param int $task_index Index of the task in the task list array + * + * @return null + */ + public function set_finished_task($task_service_name, $task_index) + { + $this->progress_data['last_task_name'] = $task_service_name; + $this->progress_data['last_task_index'] = $task_index; + } + + /** + * Set active module + * + * @param string $module_service_name Name of the installer module service + * @param int $module_index Index of the module in the module list array + * + * @return null + */ + public function set_active_module($module_service_name, $module_index) + { + $this->progress_data['last_task_module_name'] = $module_service_name; + $this->progress_data['last_task_module_index'] = $module_index; + } + + /** + * Getter for progress data + * + * @return array + */ + public function get_progress_data() + { + return $this->progress_data; + } + + /** + * Recovers install configuration from file + * + * @return null + */ + public function load_config() + { + if (!$this->filesystem->exists($this->install_config_file)) + { + return; + } + + $file_content = @file_get_contents($this->install_config_file); + $serialized_data = trim(substr($file_content, 8)); + $unserialized_data = unserialize($serialized_data); + + $this->installer_config = $unserialized_data['installer_config']; + $this->progress_data = $unserialized_data['progress_data']; + } + + /** + * Dumps install configuration to disk + * + * @return null + */ + public function save_config() + { + // Create array to save + $save_array = array( + 'installer_config' => $this->installer_config, + 'progress_data' => $this->progress_data, + ); + + // Create file content + $file_content = 'install_config_file, 'w'); + fwrite($fp, $file_content); + fclose($fp); + } + + /** + * Filling up system_data array + * + * @return null + */ + protected function setup_system_data() + { + // Query maximum runtime from php.ini + $execution_time = $this->php_ini->get_int('max_execution_time'); + $execution_time = min(15, $execution_time / 2); + $this->system_data['max_execution_time'] = $execution_time; + + // Set start time + $this->system_data['start_time'] = time(); + + // Get memory limit + $this->system_data['memory_limit'] = $this->php_ini->get_bytes('memory_limit'); + } +} diff --git a/phpBB/install/helper/container_factory.php b/phpBB/install/helper/container_factory.php new file mode 100644 index 0000000000..255f8f428e --- /dev/null +++ b/phpBB/install/helper/container_factory.php @@ -0,0 +1,149 @@ + + * @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\install\helper; + +use phpbb\install\exception\cannot_build_container_exception; + +class container_factory +{ + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var string + */ + protected $php_ext; + + /** + * @var \phpbb\request\request + */ + protected $request; + + /** + * The full phpBB container + * + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + /** + * Constructor + * + * @param \phpbb\request\request $request Request interface + * @param string $phpbb_root_path Path to phpBB's root + * @param string $php_ext Extension of PHP files + */ + public function __construct(\phpbb\request\request $request, $phpbb_root_path, $php_ext) + { + $this->request = $request; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + $this->container = null; + } + + /** + * Container getter + * + * @param null|string $service_name Name of the service to return + * + * @return \Symfony\Component\DependencyInjection\ContainerInterface|Object phpBB's dependency injection container + * or the service specified in $service_name + * + * @throws \phpbb\install\exception\cannot_build_container_exception When container cannot be built + * @throws \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException If the service is not defined + * @throws \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException When a circular reference is detected + * @throws \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException When the service is not defined + */ + public function get($service_name = null) + { + // Check if container was built, if not try to build it + if ($this->container === null) + { + // Check whether container can be built + // We need config.php for that so let's check if it has been set up yet + if (filesize($this->phpbb_root_path . 'config.' . $this->php_ext)) + { + $this->build_container(); + } + else + { + throw new cannot_build_container_exception(); + } + } + + return ($service_name === null) ? $this->container : $this->container->get($service_name); + } + + /** + * Returns the specified parameter from the container + * + * @param string $param_name + * + * @return mixed + */ + public function get_parameter($param_name) + { + return $this->container->getParameter($param_name); + } + + /** + * Build dependency injection container + */ + protected function build_container() + { + // If the container has been already built just return. + // Although this should never happen + if ($this->container instanceof \Symfony\Component\DependencyInjection\ContainerInterface) + { + return; + } + + $phpbb_config_php_file = new \phpbb\config_php_file($this->phpbb_root_path, $this->php_ext); + $phpbb_container_builder = new \phpbb\di\container_builder($this->phpbb_root_path, $this->php_ext); + + // For BC with functions that we need during install + global $phpbb_container; + + $disable_super_globals = $this->request->super_globals_disabled(); + + // This is needed because container_builder::get_env_parameters() uses $_SERVER + if ($disable_super_globals) + { + $this->request->enable_super_globals(); + } + + $this->container = $phpbb_container = $phpbb_container_builder + ->with_config($phpbb_config_php_file) + ->without_cache() + ->without_compiled_container() + ->get_container(); + + // Setting request is required for the compatibility globals as those are generated from + // this container + $this->container->register('request')->setSynthetic(true); + $this->container->set('request', $this->request); + $this->container->compile(); + + // Restore super globals to previous state + if ($disable_super_globals) + { + $this->request->disable_super_globals(); + } + + // Get compatibilty globals + require ($this->phpbb_root_path . 'includes/compatibility_globals.' . $this->php_ext); + } +} diff --git a/phpBB/install/helper/database.php b/phpBB/install/helper/database.php new file mode 100644 index 0000000000..d728c8b93b --- /dev/null +++ b/phpBB/install/helper/database.php @@ -0,0 +1,459 @@ + + * @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\install\helper; + +use phpbb\install\exception\invalid_dbms_exception; + +/** + * Database related general functionality for installer + */ +class database +{ + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var array + */ + protected $supported_dbms; + + /** + * Constructor + * + * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem interface + * @param string $phpbb_root_path Path to phpBB's root + */ + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path) + { + $this->filesystem = $filesystem; + + // DBMS supported by phpBB + $this->supported_dbms = array( + // Note: php 5.5 alpha 2 deprecated mysql. + // Keep mysqli before mysql in this list. + 'mysqli' => array( + 'LABEL' => 'MySQL with MySQLi Extension', + 'SCHEMA' => 'mysql_41', + 'MODULE' => 'mysqli', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\mysqli', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mysql' => array( + 'LABEL' => 'MySQL', + 'SCHEMA' => 'mysql', + 'MODULE' => 'mysql', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\mysql', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mssql' => array( + 'LABEL' => 'MS SQL Server 2000+', + 'SCHEMA' => 'mssql', + 'MODULE' => 'mssql', + 'DELIM' => 'GO', + 'DRIVER' => 'phpbb\db\driver\mssql', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mssql_odbc'=> array( + 'LABEL' => 'MS SQL Server [ ODBC ]', + 'SCHEMA' => 'mssql', + 'MODULE' => 'odbc', + 'DELIM' => 'GO', + 'DRIVER' => 'phpbb\db\driver\mssql_odbc', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mssqlnative' => array( + 'LABEL' => 'MS SQL Server 2005+ [ Native ]', + 'SCHEMA' => 'mssql', + 'MODULE' => 'sqlsrv', + 'DELIM' => 'GO', + 'DRIVER' => 'phpbb\db\driver\mssqlnative', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + 'oracle' => array( + 'LABEL' => 'Oracle', + 'SCHEMA' => 'oracle', + 'MODULE' => 'oci8', + 'DELIM' => '/', + 'DRIVER' => 'phpbb\db\driver\oracle', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + 'postgres' => array( + 'LABEL' => 'PostgreSQL 8.3+', + 'SCHEMA' => 'postgres', + 'MODULE' => 'pgsql', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\postgres', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'sqlite' => array( + 'LABEL' => 'SQLite', + 'SCHEMA' => 'sqlite', + 'MODULE' => 'sqlite', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\sqlite', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + 'sqlite3' => array( + 'LABEL' => 'SQLite3', + 'SCHEMA' => 'sqlite', + 'MODULE' => 'sqlite3', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\sqlite3', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + ); + } + + /** + * Returns an array of available DBMS supported by phpBB + * + * If a DBMS is specified it will only return data for that DBMS + * and will load its extension if necessary. + * + * @param mixed $dbms name of the DBMS that's info is required or false for all DBMS info + * @param bool $return_unavailable set it to true if you expect unavailable but supported DBMS + * returned as well + * @param bool $only_20x_options set it to true if you only want to recover 2.0.x options + * + * @return array Array of available and supported DBMS + */ + public function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false) + { + $available_dbms = $this->supported_dbms; + + if ($dbms) + { + if (isset($this->supported_dbms[$dbms])) + { + $available_dbms = array($dbms => $this->supported_dbms[$dbms]); + } + else + { + return array(); + } + } + + $any_dbms_available = false; + foreach ($available_dbms as $db_name => $db_array) + { + if ($only_20x_options && !$db_array['2.0.x']) + { + if ($return_unavailable) + { + $available_dbms[$db_name]['AVAILABLE'] = false; + } + else + { + unset($available_dbms[$db_name]); + } + + continue; + } + + $dll = $db_array['MODULE']; + if (!@extension_loaded($dll)) + { + if ($return_unavailable) + { + $available_dbms[$db_name]['AVAILABLE'] = false; + } + else + { + unset($available_dbms[$db_name]); + } + + continue; + } + + $any_dbms_available = true; + } + + if ($return_unavailable) + { + $available_dbms['ANY_DB_SUPPORT'] = $any_dbms_available; + } + + return $available_dbms; + } + + /** + * Removes "/* style" as well as "# style" comments from $input. + * + * @param string $sql_query Input string + * + * @return string Input string with comments removed + */ + public function remove_comments($sql_query) + { + // Remove /* */ comments (http://ostermiller.org/findcomment.html) + $sql_query = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql_query); + + // Remove # style comments + $sql_query = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql_query)); + + return $sql_query; + } + + /** + * split_sql_file() will split an uploaded sql file into single sql statements. + * + * Note: expects trim() to have already been run on $sql. + * + * @param string $sql SQL statements + * @param string $delimiter Delimiter between sql statements + * + * @return array Array of sql statements + */ + public function split_sql_file($sql, $delimiter) + { + $sql = str_replace("\r" , '', $sql); + $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql); + + $data = array_map('trim', $data); + + // The empty case + $end_data = end($data); + + if (empty($end_data)) + { + unset($data[key($data)]); + } + + return $data; + } + + /** + * Validates table prefix + * + * @param string $dbms The selected dbms + * @param string $table_prefix The table prefix to validate + * + * @return bool|array true if table prefix is valid, array of errors otherwise + * + * @throws \phpbb\install\exception\invalid_dbms_exception When $dbms is not a valid + */ + public function validate_table_prefix($dbms, $table_prefix) + { + $errors = array(); + + if (!preg_match('#^[a-zA-Z][a-zA-Z0-9_]*$#', $table_prefix)) + { + $errors[] = array( + 'title' => 'INST_ERR_DB_INVALID_PREFIX', + ); + } + + // Do dbms specific checks + $dbms_info = $this->get_available_dbms($dbms); + switch ($dbms_info[$dbms]['SCHEMA']) + { + case 'mysql': + case 'mysql_41': + $prefix_length = 36; + break; + case 'mssql': + $prefix_length = 90; + break; + case 'oracle': + $prefix_length = 6; + break; + case 'postgres': + $prefix_length = 36; + break; + case 'sqlite': + $prefix_length = 200; + break; + default: + throw new invalid_dbms_exception(); + break; + } + + // Check the prefix length to ensure that index names are not too long + if (strlen($table_prefix) > $prefix_length) + { + $errors[] = array( + 'title' => array('INST_ERR_PREFIX_TOO_LONG', $prefix_length), + ); + } + + return (empty($errors)) ? true : $errors; + } + + /** + * Check if the user provided database parameters are correct + * + * This function checks the database connection data and also checks for + * any other problems that could cause an error during the installation + * such as if there is any database table names conflicting. + * + * Note: The function assumes that $table_prefix has been already validated + * with validate_table_prefix(). + * + * @param string $dbms Selected database type + * @param string $dbhost Database host address + * @param int $dbport Database port number + * @param string $dbuser Database username + * @param string $dbpass Database password + * @param string $dbname Database name + * @param string $table_prefix Database table prefix + * + * @return array|bool Returns true if test is successful, array of errors otherwise + */ + public function check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix) + { + $dbms_info = $this->get_available_dbms($dbms); + $dbms_info = $dbms_info[$dbms]; + $errors = array(); + + // Instantiate it and set return on error true + /** @var \phpbb\db\driver\driver_interface $db */ + $db = new $dbms_info['DRIVER']; + $db->sql_return_on_error(true); + + // Check that we actually have a database name before going any further + if (!in_array($dbms_info['SCHEMA'], array('sqlite', 'oracle')) && $dbname === '') + { + $errors[] = array( + 'title' => 'INST_ERR_DB_NO_NAME', + ); + } + + // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea + if ($dbms_info['SCHEMA'] === 'sqlite' + && stripos($this->filesystem->realpath($dbhost), $this->filesystem->realpath($this->phpbb_root_path) === 0)) + { + $errors[] = array( + 'title' =>'INST_ERR_DB_FORUM_PATH', + ); + } + + // Try to connect to db + if (is_array($db->sql_connect($dbhost, $dbuser, $dbpass, $dbname, $dbport, false, true))) + { + $db_error = $db->sql_error(); + $errors[] = array( + 'title' => 'INST_ERR_DB_CONNECT', + 'description' => ($db_error['message']) ? utf8_convert_message($db_error['message']) : 'INST_ERR_DB_NO_ERROR', + ); + } + else + { + // Check if there is any table name collisions + $temp_prefix = strtolower($table_prefix); + $table_ary = array( + $temp_prefix . 'attachments', + $temp_prefix . 'config', + $temp_prefix . 'sessions', + $temp_prefix . 'topics', + $temp_prefix . 'users', + ); + + $db_tools_factory = new \phpbb\db\tools\factory(); + $db_tools = $db_tools_factory->get($db); + $tables = $db_tools->sql_list_tables(); + $tables = array_map('strtolower', $tables); + $table_intersect = array_intersect($tables, $table_ary); + + if (sizeof($table_intersect)) + { + $errors[] = array( + 'title' => 'INST_ERR_PREFIX', + ); + } + + // Check if database version is supported + switch ($dbms) + { + case 'mysqli': + if (version_compare(mysqli_get_server_info($db->get_db_connect_id()), '4.1.3', '<')) + { + $errors[] = array( + 'title' => 'INST_ERR_DB_NO_MYSQLI', + ); + } + break; + case 'sqlite': + if (version_compare(sqlite_libversion(), '2.8.2', '<')) + { + $errors[] = array( + 'title' => 'INST_ERR_DB_NO_SQLITE', + ); + } + break; + case 'sqlite3': + $version = \SQLite3::version(); + if (version_compare($version['versionString'], '3.6.15', '<')) + { + $errors[] = array( + 'title' => 'INST_ERR_DB_NO_SQLITE3', + ); + } + break; + case 'oracle': + $sql = "SELECT * + FROM NLS_DATABASE_PARAMETERS + WHERE PARAMETER = 'NLS_RDBMS_VERSION' + OR PARAMETER = 'NLS_CHARACTERSET'"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $stats[$row['parameter']] = $row['value']; + } + $db->sql_freeresult($result); + + if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8') + { + $errors[] = array( + 'title' => 'INST_ERR_DB_NO_ORACLE', + ); + } + break; + case 'postgres': + $sql = "SHOW server_encoding;"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8') + { + $errors[] = array( + 'title' => 'INST_ERR_DB_NO_POSTGRES', + ); + } + break; + } + } + + return (empty($errors)) ? true : $errors; + } +} diff --git a/phpBB/install/helper/iohandler/ajax_iohandler.php b/phpBB/install/helper/iohandler/ajax_iohandler.php new file mode 100644 index 0000000000..44a185139e --- /dev/null +++ b/phpBB/install/helper/iohandler/ajax_iohandler.php @@ -0,0 +1,202 @@ + + * @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\install\helper\iohandler; + +/** + * Input-Output handler for the AJAX frontend + */ +class ajax_iohandler extends iohandler_base +{ + /** + * @var \phpbb\request\request_interface + */ + protected $request; + + /** + * @var \phpbb\template\template + */ + protected $template; + + /** + * @var string + */ + protected $form; + + /** + * Constructor + * + * @param \phpbb\request\request_interface $request HTTP request interface + * @param \phpbb\template\template $template Template engine + */ + public function __construct(\phpbb\request\request_interface $request, \phpbb\template\template $template) + { + $this->request = $request; + $this->template = $template; + $this->form = ''; + + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + public function get_input($name, $default, $multibyte = false) + { + return $this->request->variable($name, $default, $multibyte); + } + + /** + * {@inheritdoc} + */ + public function get_server_variable($name, $default = '') + { + return $this->request->server($name, $default); + } + + /** + * {@inheritdoc} + */ + public function get_header_variable($name, $default = '') + { + return $this->request->header($name, $default); + } + + /** + * {@inheritdoc} + */ + public function is_secure() + { + return $this->request->is_secure(); + } + + /** + * {@inheritdoc} + */ + public function add_user_form_group($title, $form) + { + // + // This code is pretty ugly... but works + // + + $this->template->assign_block_vars('options', array( + 'LEGEND' => $this->language->lang($title), + 'S_LEGEND' => true, + )); + + foreach ($form as $input_name => $input_options) + { + if (!isset($input_options['type'])) + { + continue; + } + + $tpl_ary = array(); + + $tpl_ary['TYPE'] = $input_options['type']; + $tpl_ary['TITLE'] = $this->language->lang($input_options['label']); + $tpl_ary['KEY'] = $input_name; + $tpl_ary['S_EXPLAIN'] = false; + + if (isset($input_options['default'])) + { + $default = $input_options['default']; + $default = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', array($this, 'lang_replace_callback'), $default); + $tpl_ary['DEFAULT'] = $default; + } + + if (isset($input_options['description'])) + { + $tpl_ary['TITLE_EXPLAIN'] = $this->language->lang($input_options['description']); + $tpl_ary['S_EXPLAIN'] = true; + } + + if (in_array($input_options['type'], array('select', 'radio'))) + { + for ($i = 0, $total = sizeof($input_options['options']); $i < $total; $i++) + { + if (isset($input_options['options'][$i]['label'])) + { + $input_options['options'][$i]['label'] = $this->language->lang($input_options['options'][$i]['label']); + } + } + + $tpl_ary['OPTIONS'] = $input_options['options']; + } + + $this->template->assign_block_vars('options', $tpl_ary); + } + + $this->template->set_filenames(array( + 'form_install' => 'installer_form.html', + )); + + $this->form = $this->template->assign_display('form_install'); + } + + /** + * {@inheritdoc} + */ + public function send_response() + { + $json_data_array = $this->prepare_json_array(); + $json_data = json_encode($json_data_array); + + // Try to push content to the browser + print (str_pad(' ', 4096) . "\n"); + print ($json_data . "\n\n"); + flush(); + } + + /** + * Prepares iohandler's data to be sent out to the client. + * + * @return array + */ + protected function prepare_json_array() + { + $json_array = array( + 'errors' => $this->errors, + 'warnings' => $this->warnings, + 'logs' => $this->logs, + ); + + if (!empty($this->form)) + { + $json_array['form'] = $this->form; + $this->form = ''; + } + + $this->errors = array(); + $this->warnings = array(); + $this->logs = array(); + + return $json_array; + } + + /** + * Callback function for language replacing + * + * @param array $matches + * @return string + */ + public function lang_replace_callback($matches) + { + if (!empty($matches[1])) + { + return $this->language->lang($matches[1]); + } + + return ''; + } +} diff --git a/phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php b/phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php new file mode 100644 index 0000000000..f2ddeda6f7 --- /dev/null +++ b/phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php @@ -0,0 +1,19 @@ + + * @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\install\helper\iohandler\exception; + +class iohandler_not_implemented_exception extends \Exception +{ + +} diff --git a/phpBB/install/helper/iohandler/factory.php b/phpBB/install/helper/iohandler/factory.php new file mode 100644 index 0000000000..0b59e5ec63 --- /dev/null +++ b/phpBB/install/helper/iohandler/factory.php @@ -0,0 +1,72 @@ + + * @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\install\helper\iohandler; + +use phpbb\install\helper\iohandler\exception\iohandler_not_implemented_exception; + +/** + * Input-output handler factory + */ +class factory +{ + /** + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + /** + * @var string + */ + protected $environment; + + /** + * Constructor + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container Dependency injection container + */ + public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container) + { + $this->container = $container; + $this->environment = null; + } + + /** + * @param string $environment The name of the input-output handler to use + */ + public function set_environment($environment) + { + $this->environment = $environment; + } + + /** + * Factory getter for iohandler + * + * @return \phpbb\install\helper\iohandler\iohandler_interface + * + * @throws \phpbb\install\helper\iohandler\exception\iohandler_not_implemented_exception + * When the specified iohandler_interface does not exists + */ + public function get() + { + switch ($this->environment) + { + case 'ajax': + return $this->container->get('installer.helper.iohandler_ajax'); + break; + default: + throw new iohandler_not_implemented_exception(); + break; + } + } +} diff --git a/phpBB/install/helper/iohandler/iohandler_base.php b/phpBB/install/helper/iohandler/iohandler_base.php new file mode 100644 index 0000000000..0d5467d202 --- /dev/null +++ b/phpBB/install/helper/iohandler/iohandler_base.php @@ -0,0 +1,121 @@ + + * @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\install\helper\iohandler; + +/** + * Base class for installer input-output handlers + */ +abstract class iohandler_base implements iohandler_interface +{ + /** + * Array of errors + * + * Errors should be added, when the installation cannot continue without + * user interaction. If the aim is to notify the user about something, please + * use a warning instead. + * + * @var array + */ + protected $errors; + + /** + * Array of warnings + * + * @var array + */ + protected $warnings; + + /** + * Array of logs + * + * @var array + */ + protected $logs; + + /** + * @var \phpbb\language\language + */ + protected $language; + + /** + * Constructor + */ + public function __construct() + { + $this->errors = array(); + $this->warnings = array(); + $this->logs = array(); + } + + /** + * Set language service + * + * @param \phpbb\language\language $language + * + * @return null + */ + public function set_language(\phpbb\language\language $language) + { + $this->language = $language; + } + + /** + * {@inheritdoc} + */ + public function add_error_message($error_title, $error_description = false) + { + $this->errors[] = $this->translate_message($error_title, $error_description); + } + + /** + * {@inheritdoc} + */ + public function add_warning_message($warning_title, $warning_description = false) + { + $this->warnings[] = $this->translate_message($warning_title, $warning_description); + } + + /** + * {@inheritdoc} + */ + public function add_log_message($log_title, $log_description = false) + { + $this->logs[] = $this->translate_message($log_title, $log_description); + } + + /** + * Localize message. + * + * Note: When an array is passed into the parameters below, it will be + * resolved as printf($param[0], $param[1], ...). + * + * @param array|string $title Title of the message + * @param array|string|bool $description Description of the message + * + * @return array Localized message in an array + */ + protected function translate_message($title, $description) + { + $message_array = array(); + + $message_array['title'] = call_user_func_array(array($this->language, 'lang'), (array) $title); + + if ($description !== false) + { + $message_array['description'] = call_user_func_array(array($this->language, 'lang'), (array) $description); + } + + return $message_array; + } +} diff --git a/phpBB/install/helper/iohandler/iohandler_interface.php b/phpBB/install/helper/iohandler/iohandler_interface.php new file mode 100644 index 0000000000..cea5610586 --- /dev/null +++ b/phpBB/install/helper/iohandler/iohandler_interface.php @@ -0,0 +1,119 @@ + + * @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\install\helper\iohandler; + +/** + * Input-Output handler interface for the installer + */ +interface iohandler_interface +{ + /** + * Renders or returns response message + */ + public function send_response(); + + /** + * Returns input variable + * + * @param string $name Name of the input variable to obtain + * @param mixed $default A default value that is returned if the variable was not set. + * This function will always return a value of the same type as the default. + * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters + * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks + * + * @return mixed Value of the input variable + */ + public function get_input($name, $default, $multibyte = false); + + /** + * Returns server variable + * + * This function should work the same as request_interterface::server(). + * + * @param string $name Name of the server variable + * @param mixed $default Default value to return when the requested variable does not exist + * + * @return mixed Value of the server variable + */ + public function get_server_variable($name, $default = ''); + + /** + * Wrapper function for request_interterface::header() + * + * @param string $name Name of the request header variable + * @param mixed $default Default value to return when the requested variable does not exist + * + * @return mixed + */ + public function get_header_variable($name, $default = ''); + + /** + * Returns true if the connection is encrypted + * + * @return bool + */ + public function is_secure(); + + /** + * Adds an error message to the rendering queue + * + * Note: When an array is passed into the parameters below, it will be + * resolved as printf($param[0], $param[1], ...). + * + * @param string|array $error_title Title of the error message. + * @param string|bool|array $error_description Description of the error (and possibly guidelines to resolve it), + * or false if the error description is not available. + * + * @return null + */ + public function add_error_message($error_title, $error_description = false); + + /** + * Adds a warning message to the rendering queue + * + * Note: When an array is passed into the parameters below, it will be + * resolved as printf($param[0], $param[1], ...). + * + * @param string|array $warning_title Title of the error message + * @param string|bool|array $warning_description Description of the error (and possibly guidelines to resolve it), + * or false if the error description is not available + * + * @return null + */ + public function add_warning_message($warning_title, $warning_description = false); + + /** + * Adds a log message to the rendering queue + * + * Note: When an array is passed into the parameters below, it will be + * resolved as printf($param[0], $param[1], ...). + * + * @param string|array $log_title Title of the error message + * @param string|bool|array $log_description Description of the error (and possibly guidelines to resolve it), + * or false if the error description is not available + * + * @return null + */ + public function add_log_message($log_title, $log_description = false); + + /** + * Adds a requested data group to the rendering queue + * + * @param string $title Language variable with the title of the form + * @param array $form An array describing the required data (options etc) + * + * @return null + */ + public function add_user_form_group($title, $form); +} diff --git a/phpBB/install/helper/navigation/install_navigation.php b/phpBB/install/helper/navigation/install_navigation.php new file mode 100644 index 0000000000..3e29e55038 --- /dev/null +++ b/phpBB/install/helper/navigation/install_navigation.php @@ -0,0 +1,28 @@ + + * @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\install\helper\navigation; + +class install_navigation implements navigation_interface +{ + public function get() + { + return array( + 'install' => array( + 'label' => 'INSTALL', + 'route' => 'phpbb_installer_install', + 'order' => 0, + ), + ); + } +} diff --git a/phpBB/install/helper/navigation/navigation_interface.php b/phpBB/install/helper/navigation/navigation_interface.php new file mode 100644 index 0000000000..eebdbe923f --- /dev/null +++ b/phpBB/install/helper/navigation/navigation_interface.php @@ -0,0 +1,43 @@ + + * @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\install\helper\navigation; + +/** + * Interface for installer's navigation defining services + */ +interface navigation_interface +{ + /** + * Returns an array with the navigation items + * + * The returned array should have the following format: + * + * array( + * 'parent_nav_name' => array( + * 'nav_name' => array( + * 'label' => 'MY_MENU', + * 'route' => 'phpbb_route_name', + * ) + * ) + * ) + * + * + * Navigation item setting options: + * - label: The language variable name + * - route: Name of the route which it is belongs to + * + * @return array + */ + public function get(); +} diff --git a/phpBB/install/helper/navigation/navigation_provider.php b/phpBB/install/helper/navigation/navigation_provider.php new file mode 100644 index 0000000000..ddb2509348 --- /dev/null +++ b/phpBB/install/helper/navigation/navigation_provider.php @@ -0,0 +1,92 @@ + + * @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\install\helper\navigation; + +/** + * Installers navigation provider + */ +class navigation_provider +{ + /** + * @var array + */ + private $menu_collection; + + /** + * Constructor + * + * @param \phpbb\di\service_collection $plugins + */ + public function __construct(\phpbb\di\service_collection $plugins) + { + $this->menu_collection = array(); + + foreach ($plugins as $plugin => $plugin_instance) + { + $this->register($plugin_instance); + } + } + + /** + * Returns navigation array + * + * @return array + */ + public function get() + { + return $this->menu_collection; + } + + /** + * Registers a navigation provider's navigation items + * + * @param navigation_interface $navigation + */ + public function register(navigation_interface $navigation) + { + $nav_arry = $navigation->get(); + $this->merge($nav_arry, $this->menu_collection); + } + + /** + * Recursive array merge + * + * This function is necessary to be able to replace the options of + * already set navigation items. + * + * @param array $array_to_merge + * @param array $array_to_merge_into + */ + private function merge(&$array_to_merge, &$array_to_merge_into) + { + foreach ($array_to_merge as $key => $value) + { + if (isset($array_to_merge_into[$key])) + { + if (is_array($array_to_merge_into[$key]) && is_array($value)) + { + $this->merge($value, $array_to_merge_into[$key]); + } + else + { + $array_to_merge_into[$key] = $value; + } + } + else + { + $array_to_merge_into[$key] = $value; + } + } + } +} diff --git a/phpBB/install/installer.php b/phpBB/install/installer.php new file mode 100644 index 0000000000..5a2fcc4d85 --- /dev/null +++ b/phpBB/install/installer.php @@ -0,0 +1,146 @@ + + * @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\install; + +class installer +{ + /** + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var array + */ + protected $installer_modules; + + /** + * Constructor + * + * @param \phpbb\install\helper\config $config Installer config handler + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container Dependency injection container + */ + public function __construct(\phpbb\install\helper\config $config, \Symfony\Component\DependencyInjection\ContainerInterface $container) + { + $this->install_config = $config; + $this->container = $container; + $this->installer_modules = array(); + } + + /** + * Sets modules to execute + * + * Note: The installer will run modules in the order they are set in + * the array. + * + * @param array $modules Array of module service names + */ + public function set_modules($modules) + { + $modules = (array) $modules; + + $this->installer_modules = $modules; + } + + /** + * Run phpBB installer + * + * @return null + */ + public function run() + { + // Load install progress + $this->install_config->load_config(); + + // Recover install progress + $module_index = $this->recover_progress(); + + $install_finished = false; + + try + { + // Run until there are available resources + while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0) + { + // Check if module exists, if not the install is completed + if (!isset($this->installer_modules[$module_index])) + { + $install_finished = true; + break; + } + + // Log progress + $module_service_name = $this->installer_modules[$module_index]; + $this->install_config->set_active_module($module_service_name, $module_index); + + // Get module from container + /** @var \phpbb\install\module_interface $module */ + $module = $this->container->get($module_service_name); + + $module_index++; + + // Check if module should be executed + if (!$module->is_essential() && !$module->check_requirements()) + { + continue; + } + + $module->run(); + + // Clear task progress + $this->install_config->set_finished_task('', 0); + } + + if ($install_finished) + { + die ("install finished"); + } + else + { + die ("install memory or time limit reached"); + } + } + catch (\phpbb\install\exception\user_interaction_required_exception $e) + { + // @todo handle exception + } + + // Save install progress + $this->install_config->save_config(); + } + + /** + * Recover install progress + * + * @return int Index of the next installer module to execute + */ + protected function recover_progress() + { + $progress_array = $this->install_config->get_progress_data(); + $module_service = $progress_array['last_task_module_name']; + $module_index = $progress_array['last_task_module_index']; + + if ($this->installer_modules[$module_index] === $module_service) + { + return $module_index; + } + + return 0; + } +} diff --git a/phpBB/install/module_base.php b/phpBB/install/module_base.php new file mode 100644 index 0000000000..defccaefef --- /dev/null +++ b/phpBB/install/module_base.php @@ -0,0 +1,175 @@ + + * @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\install; + +/** + * Base class for installer module + */ +abstract class module_base implements module_interface +{ + /** + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $iohandler; + + /** + * @var bool + */ + protected $is_essential; + + /** + * Array of tasks for installer module + * + * @var array + */ + protected $task_collection; + + /** + * Installer module constructor + * + * @param array $tasks array of installer tasks for installer module + * @param bool $essential flag that indicates if module is essential or not + */ + public function __construct(array $tasks, $essential = true) + { + $this->task_collection = $tasks; + $this->is_essential = $essential; + } + + /** + * Dependency getter + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * @param \phpbb\install\helper\config $config + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler + * + * @return null + */ + public function setup(\Symfony\Component\DependencyInjection\ContainerInterface $container, \phpbb\install\helper\config $config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler) + { + $this->container = $container; + $this->install_config = $config; + $this->iohandler = $iohandler; + } + + /** + * {@inheritdoc} + */ + public function is_essential() + { + return $this->is_essential; + } + + /** + * {@inheritdoc} + * + * Overwrite this method if your task is non-essential! + */ + public function check_requirements() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function run() + { + // Recover install progress + $task_index = $this->recover_progress(); + + // Run until there are available resources + while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0) + { + // Check if task exists + if (!isset($this->task_collection[$task_index])) + { + break; + } + + // Recover task to be executed + /** @var \phpbb\install\task_interface $task */ + $task = $this->container->get($this->task_collection[$task_index]); + + // Iterate to the next task + $task_index++; + + // Check if we can run the task + if (!$task->is_essential() && !$task->check_requirements()) + { + continue; + } + + $task->run(); + + // Increment progress + if ($this->get_task_count() !== 0) + { + //$this->iohandler->increment_progress(); + } + + $this->iohandler->send_response(); + + // Log install progress + $current_task_index = $task_index - 1; + $this->install_config->set_finished_task($this->task_collection[$current_task_index], $current_task_index); + } + } + + /** + * Returns the next task's index + * + * @return int index of the array element of the next task + */ + protected function recover_progress() + { + $progress_array = $this->install_config->get_progress_data(); + $last_finished_task_name = $progress_array['last_task_name']; + $last_finished_task_index = $progress_array['last_task_index']; + + // Check if the data is relevant to this module + if (isset($this->task_collection[$last_finished_task_index])) + { + if ($this->task_collection[$last_finished_task_index] === $last_finished_task_name) + { + // Return the task index of the next task + return $last_finished_task_index + 1; + } + } + + // As of now if the progress has not been resolved we assume that it is because + // the task progress belongs to the previous module, + // so just default to the first task + // @todo make module aware of it's service name that way this can be improved + return 0; + } + + /** + * {@inheritdoc} + */ + public function get_task_count() + { + return sizeof($this->task_collection); + } +} diff --git a/phpBB/install/module_interface.php b/phpBB/install/module_interface.php new file mode 100644 index 0000000000..e0ec4e4347 --- /dev/null +++ b/phpBB/install/module_interface.php @@ -0,0 +1,56 @@ + + * @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\install; + +/** + * Interface for installer modules + * + * An installer module is a task collection which executes installer tasks. + */ +interface module_interface +{ + /** + * Checks if the execution of the module is essential to install phpBB or it can be skipped + * + * Note: Please note that all the non-essential modules have to implement check_requirements() + * method. + * + * @return bool true if the module is essential, false otherwise + */ + public function is_essential(); + + /** + * Checks requirements for the tasks + * + * Note: Only need to be implemented for non-essential tasks, as essential tasks + * requirements should be checked in the requirements install module. + * + * @return bool true if the task's requirements are met + */ + public function check_requirements(); + + /** + * Executes the task + * + * @return null + */ + public function run(); + + /** + * Returns the number of tasks in the module + * + * @return int + */ + public function get_task_count(); +} diff --git a/phpBB/install/task_base.php b/phpBB/install/task_base.php new file mode 100644 index 0000000000..5946be8c52 --- /dev/null +++ b/phpBB/install/task_base.php @@ -0,0 +1,53 @@ + + * @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\install; + +/** + * Base class for installer task + */ +abstract class task_base implements task_interface +{ + /** + * @var bool + */ + protected $is_essential; + + /** + * Constructor + * + * @param bool $essential + */ + public function __construct($essential = true) + { + $this->is_essential = $essential; + } + + /** + * {@inheritdoc} + */ + public function is_essential() + { + return $this->is_essential; + } + + /** + * {@inheritdoc} + * + * Overwrite this method if your task is non-essential! + */ + public function check_requirements() + { + return true; + } +} diff --git a/phpBB/install/task_interface.php b/phpBB/install/task_interface.php new file mode 100644 index 0000000000..9cfc4d19c2 --- /dev/null +++ b/phpBB/install/task_interface.php @@ -0,0 +1,47 @@ + + * @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\install; + +/** + * Interface for installer tasks + */ +interface task_interface +{ + /** + * Checks if the task is essential to install phpBB or it can be skipped + * + * Note: Please note that all the non-essential modules have to implement check_requirements() + * method. + * + * @return bool true if the task is essential, false otherwise + */ + public function is_essential(); + + /** + * Checks requirements for the tasks + * + * Note: Only need to be implemented for non-essential tasks, as essential tasks + * requirements should be checked in the requirements install module. + * + * @return bool true if the task's requirements are met + */ + public function check_requirements(); + + /** + * Executes the task + * + * @return null + */ + public function run(); +} From 11623dd6718ec12504286db3dfcd042ccb4e3688 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Tue, 28 Apr 2015 22:33:04 +0200 Subject: [PATCH 0441/1676] [ticket/13740] Front facing files and controllers [ci skip] PHPBB3-13740 --- phpBB/adm/style/admin.css | 6 +- phpBB/adm/style/installer_form.html | 52 ++++ phpBB/adm/style/installer_install.html | 13 + phpBB/assets/javascript/installer.js | 205 ++++++++++++++++ .../config/installer/routing/environment.yml | 2 + phpBB/config/installer/routing/installer.yml | 22 ++ phpBB/install/app.php | 83 +++++++ phpBB/install/controller/helper.php | 228 ++++++++++++++++++ phpBB/install/controller/install.php | 109 +++++++++ phpBB/install/controller/install_index.php | 79 ++++++ 10 files changed, 798 insertions(+), 1 deletion(-) create mode 100644 phpBB/adm/style/installer_form.html create mode 100644 phpBB/adm/style/installer_install.html create mode 100644 phpBB/assets/javascript/installer.js create mode 100644 phpBB/config/installer/routing/environment.yml create mode 100644 phpBB/config/installer/routing/installer.yml create mode 100644 phpBB/install/app.php create mode 100644 phpBB/install/controller/helper.php create mode 100644 phpBB/install/controller/install.php create mode 100644 phpBB/install/controller/install_index.php diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index 145bcfaec1..dd5878a976 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -1776,7 +1776,7 @@ li.pagination ul { /* Action Highlighting ---------------------------------------- */ -.successbox, .errorbox { +.successbox, .errorbox, .warningbox { padding: 8px; margin: 10px 0; color: #FFFFFF; @@ -1800,6 +1800,10 @@ li.pagination ul { background-color: #BC2A4D; } +.warningbox { + background-color: #fca600; +} + .successbox h3, .errorbox h3 { color: #FFFFFF; margin: 0 0 0.5em; diff --git a/phpBB/adm/style/installer_form.html b/phpBB/adm/style/installer_form.html new file mode 100644 index 0000000000..dbcf3c19f8 --- /dev/null +++ b/phpBB/adm/style/installer_form.html @@ -0,0 +1,52 @@ + + +
            + + + + +
            + +
            + + {options.LEGEND} + + + +
            +

            {options.TITLE_EXPLAIN}
            +
            + + + + + + + + + + + + + + + checked /> {options.OPTIONS.label} + + +
            +
            + +
            +
            + {L_SUBMIT} + +
            + + + + + diff --git a/phpBB/adm/style/installer_install.html b/phpBB/adm/style/installer_install.html new file mode 100644 index 0000000000..7d62075c62 --- /dev/null +++ b/phpBB/adm/style/installer_install.html @@ -0,0 +1,13 @@ + +

            {L_INSTALL}

            +{CONTENT} + +
            +
            + {L_SUBMIT} + +
            + + + + diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js new file mode 100644 index 0000000000..302d95e7c6 --- /dev/null +++ b/phpBB/assets/javascript/installer.js @@ -0,0 +1,205 @@ +/** + * Installer's AJAX frontend handler + */ + +(function($) { // Avoid conflicts with other libraries + // Global variables + var pollTimer = null; + var nextReadPosition = 0; + + // Template related variables + var $contentWrapper = $('.install-body').find('.main'); + + // Intercept form submits + intercept_form_submit($('#install_install')); + + function poll_content(xhReq) { + var messages = xhReq.responseText; + + do { + var unprocessed = messages.substring(nextReadPosition); + var messageEndIndex = unprocessed.indexOf('}\n\n'); + + if (messageEndIndex !== -1) { + var endOfMessageIndex = messageEndIndex + 3; // 3 is the length of "}\n\n" + var message = unprocessed.substring(0, endOfMessageIndex); + parse_message(message); + nextReadPosition += endOfMessageIndex; + } + } while (messageEndIndex !== -1); + + if (xhReq.readyState === 4) { + $('#loading_indicator').css('display', 'none'); + reset_polling(); + } + } + + function parse_message(messageJSON) { + $('#loading_indicator').css('display', 'none'); + + messageJSON = messageJSON.trim(); + var responseObject = JSON.parse(messageJSON); + + // Parse object + if (responseObject.hasOwnProperty('errors')) { + add_message('error', responseObject.errors) + } + + if (responseObject.hasOwnProperty('warnings')) { + add_message('warning', responseObject.warnings) + } + + if (responseObject.hasOwnProperty('logs')) { + add_message('log', responseObject.logs); + } + + if (responseObject.hasOwnProperty('form')) { + add_form(responseObject.form); + } + } + + function add_message(type, messages) { + // Get message containers + var errorContainer = $('#error-container'); + var warningContainer = $('#warning-container'); + var logContainer = $('#log-container'); + + var title, description, msgElement, arraySize = messages.length; + for (var i = 0; i < arraySize; i++) { + msgElement = $('
            '); + title = $(document.createElement('strong')); + title.text(messages[i].title); + msgElement.append(title); + + if (messages[i].hasOwnProperty('description')) { + description = $(document.createElement('p')); + description.text(messages[i].description); + msgElement.append(description); + } + + switch (type) { + case 'error': + msgElement.addClass('errorbox'); + errorContainer.append(msgElement); + break; + case 'warning': + msgElement.addClass('warningbox'); + warningContainer.append(msgElement); + break; + case 'log': + msgElement.addClass('log'); + logContainer.append(msgElement); + break; + } + } + } + + function add_form(formHtml) { + var formContainer = $('#content-container'); + formContainer.html(formHtml); + var form = $('#install_install'); + intercept_form_submit(form); + } + + function start_polling(xhReq) { + reset_polling(); + pollTimer = setInterval(function () { + poll_content(xhReq); + }, 500); + } + + function reset_polling() { + clearInterval(pollTimer); + nextReadPosition = 0; + } + + function submit_form(form, submitBtn) { + form.css('display', 'none'); + + var xhReq = create_xhr_object(); + xhReq.open('POST', form.attr('action'), true); + xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xhReq.send(get_form_fields(form, submitBtn)); + + // Clear content + setup_ajax_layout(); + $('#loading_indicator').css('display', 'block'); + + start_polling(xhReq); + } + + // Workaround for submit buttons + function get_form_fields(form, submitBtn) { + var formData = form.serialize(); + //var submitBtn = form.find(':submit'); + formData += ((formData.length) ? '&' : '') + encodeURIComponent(submitBtn.attr('name')) + '='; + formData += encodeURIComponent(submitBtn.attr('value')); + + return formData; + } + + function intercept_form_submit(form) { + if (!form.length) { + return; + } + + form.find(':submit').bind('click', function (event) { + event.preventDefault(); + submit_form(form, $(this)); + }); + + } + + /** + * jQuery cannot be used as the response is streamed, and + * as of now, jQuery does not provide access to the response until + * the connection is not closed. + */ + function create_xhr_object() { + var xhReq; + + if (window.XMLHttpRequest) { + xhReq = new XMLHttpRequest(); + } + else if (window.ActiveXObject) { + xhReq = new ActiveXObject("Msxml2.XMLHTTP"); + } + + return xhReq; + } + + function setup_ajax_layout() { + // Clear content + $contentWrapper.html(''); + + var $header = $('
            '); + $header.attr('id', 'header-container'); + $contentWrapper.append($header); + + var $description = $('
            '); + $description.attr('id', 'description-container'); + $contentWrapper.append($description); + + var $errorContainer = $('
            '); + $errorContainer.attr('id', 'error-container'); + $contentWrapper.append($errorContainer); + + var $warningContainer = $('
            '); + $warningContainer.attr('id', 'warning-container'); + $contentWrapper.append($warningContainer); + + var $installerContentWrapper = $('
            '); + $installerContentWrapper.attr('id', 'content-container'); + $contentWrapper.append($installerContentWrapper); + + var $logContainer = $('
            '); + $logContainer.attr('id', 'log-container'); + $contentWrapper.append($logContainer); + + var $spinner = $('
            '); + $spinner.attr('id', 'loading_indicator'); + $spinner.html(' '); + $contentWrapper.append($spinner); + } +})(jQuery); // Avoid conflicts with other libraries diff --git a/phpBB/config/installer/routing/environment.yml b/phpBB/config/installer/routing/environment.yml new file mode 100644 index 0000000000..60324c975b --- /dev/null +++ b/phpBB/config/installer/routing/environment.yml @@ -0,0 +1,2 @@ +core.default: + resource: "installer.yml" diff --git a/phpBB/config/installer/routing/installer.yml b/phpBB/config/installer/routing/installer.yml new file mode 100644 index 0000000000..80a995ab6e --- /dev/null +++ b/phpBB/config/installer/routing/installer.yml @@ -0,0 +1,22 @@ +phpbb_installer_index: + path: / + defaults: + _controller: phpbb.installer.controller.welcome:handle + mode: "intro" + +phpbb_installer_license: + path: /license + defaults: + _controller: phpbb.installer.controller.welcome:handle + mode: "license" + +phpbb_installer_support: + path: /support + defaults: + _controller: phpbb.installer.controller.welcome:handle + mode: "support" + +phpbb_installer_install: + path: /install + defaults: + _controller: phpbb.installer.controller.install:handle diff --git a/phpBB/install/app.php b/phpBB/install/app.php new file mode 100644 index 0000000000..58ca141af7 --- /dev/null +++ b/phpBB/install/app.php @@ -0,0 +1,83 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +/** + * @ignore + */ +define('IN_PHPBB', true); +define('IN_INSTALL', true); +define('PHPBB_ENVIRONMENT', 'production'); +$phpbb_root_path = '../'; +$phpEx = substr(strrchr(__FILE__, '.'), 1); + +// +// Let's do the common.php logic +// +require($phpbb_root_path . 'includes/startup.' . $phpEx); +require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx); + +$phpbb_class_loader = new \phpbb\class_loader('phpbb\\install\\', "{$phpbb_root_path}install/", $phpEx); +$phpbb_class_loader->register(); + +$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx); +$phpbb_class_loader->register(); + +// In case $phpbb_adm_relative_path is not set (in case of an update), use the default. +$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/'; +$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path; + +// Include files +require($phpbb_root_path . 'includes/functions.' . $phpEx); +require($phpbb_root_path . 'includes/functions_content.' . $phpEx); +include($phpbb_root_path . 'includes/functions_compatibility.' . $phpEx); +require($phpbb_root_path . 'includes/functions_user.' . $phpEx); +require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); + +// Set PHP error handler to ours +set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler'); + +$phpbb_installer_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); +$phpbb_installer_container = $phpbb_installer_container_builder + ->with_environment('installer') + ->without_extensions() + ->without_cache() + ->get_container(); + +// Path to templates +$paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style'); +$paths = array_filter($paths, 'is_dir'); + +/** @var \phpbb\filesystem\filesystem $phpbb_filesystem */ +$phpbb_filesystem = $phpbb_installer_container->get('filesystem'); + +/** @var \phpbb\template\template $template */ +$template = $phpbb_installer_container->get('template'); +$template->set_custom_style(array( + array( + 'name' => 'adm', + 'ext_path' => 'adm/style/', + ), +), $paths); + +/** @var \phpbb\language\language $language */ +$language = $phpbb_installer_container->get('language'); +$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting')); + +/* @var $http_kernel \Symfony\Component\HttpKernel\HttpKernel */ +$http_kernel = $phpbb_installer_container->get('http_kernel'); + +/* @var $symfony_request \phpbb\symfony_request */ +$symfony_request = $phpbb_installer_container->get('symfony_request'); +$response = $http_kernel->handle($symfony_request); +$response->send(); +$http_kernel->terminate($symfony_request, $response); diff --git a/phpBB/install/controller/helper.php b/phpBB/install/controller/helper.php new file mode 100644 index 0000000000..7a5e20406d --- /dev/null +++ b/phpBB/install/controller/helper.php @@ -0,0 +1,228 @@ + + * @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\install\controller; + +use Symfony\Component\HttpFoundation\Response; + +/** + * A duplicate of \phpbb\controller\helper + * + * This class is necessary because of controller\helper's legacy function calls + * to page_header() page_footer() functions which has unavailable dependencies. + */ +class helper +{ + /** + * @var \phpbb\language\language + */ + protected $language; + + /** + * @var \phpbb\language\language_file_helper + */ + protected $lang_helper; + + /** + * @var \phpbb\install\helper\navigation\navigation_provider + */ + protected $navigation_provider; + + /** + * @var \phpbb\template\template + */ + protected $template; + + /** + * @var \phpbb\path_helper + */ + protected $path_helper; + + /** + * @var \phpbb\symfony_request + */ + protected $request; + + /** + * @var \phpbb\routing\router + */ + protected $router; + + /** + * @var string + */ + protected $phpbb_admin_path; + + /** + * @var string + */ + protected $phpbb_root_path; + + public function __construct(\phpbb\language\language $language, \phpbb\language\language_file_helper $lang_helper, \phpbb\install\helper\navigation\navigation_provider $nav, \phpbb\template\template $template, \phpbb\path_helper $path_helper, \phpbb\symfony_request $request, \phpbb\routing\router $router, $phpbb_root_path) + { + $this->language = $language; + $this->lang_helper = $lang_helper; + $this->navigation_provider = $nav; + $this->template = $template; + $this->path_helper = $path_helper; + $this->request = $request; + $this->router = $router; + $this->phpbb_root_path = $phpbb_root_path; + $this->phpbb_admin_path = $phpbb_root_path . 'adm/'; + } + + /** + * Automate setting up the page and creating the response object. + * + * @param string $template_file The template handle to render + * @param string $page_title The title of the page to output + * @param int $status_code The status code to be sent to the page header + * + * @return Response object containing rendered page + */ + public function render($template_file, $page_title = '', $status_code = 200) + { + $this->page_header($page_title); + + $this->template->set_filenames(array( + 'body' => $template_file, + )); + + return new Response($this->template->assign_display('body'), $status_code); + } + + /** + * Set default template variables + * + * @param string $page_title + */ + protected function page_header($page_title) + { + $this->template->assign_vars(array( + 'L_CHANGE' => $this->language->lang('CHANGE'), + 'L_COLON' => $this->language->lang('COLON'), + 'L_INSTALL_PANEL' => $this->language->lang('INSTALL_PANEL'), + 'L_SELECT_LANG' => $this->language->lang('SELECT_LANG'), + 'L_SKIP' => $this->language->lang('SKIP'), + 'PAGE_TITLE' => $this->language->lang($page_title), + 'T_IMAGE_PATH' => htmlspecialchars($this->phpbb_admin_path) . 'images/', + 'T_JQUERY_LINK' => $this->path_helper->get_web_root_path() . 'assets/javascript/jquery.min.js', + 'T_TEMPLATE_PATH' => $this->path_helper->get_web_root_path() . 'adm/style', + 'T_ASSETS_PATH' => $this->path_helper->get_web_root_path() . 'assets/', + + 'S_CONTENT_DIRECTION' => $this->language->lang('DIRECTION'), + 'S_CONTENT_FLOW_BEGIN' => ($this->language->lang('DIRECTION') === 'ltr') ? 'left' : 'right', + 'S_CONTENT_FLOW_END' => ($this->language->lang('DIRECTION') === 'ltr') ? 'right' : 'left', + 'S_CONTENT_ENCODING' => 'UTF-8', + + 'S_USER_LANG' => $this->language->lang('USER_LANG'), + ) + ); + + $this->render_navigation(); + } + + /** + * Render navigation + */ + protected function render_navigation() + { + // Get navigation items + $nav_array = $this->navigation_provider->get(); + + // @todo Sort navs by order + + $active_main_menu = $this->get_active_main_menu($nav_array); + + // Pass navigation to template + foreach ($nav_array as $key => $entry) + { + $this->template->assign_block_vars('t_block1', array( + 'L_TITLE' => $this->language->lang($entry['label']), + 'S_SELECTED' => ($active_main_menu === $key), + 'U_TITLE' => $this->route($entry['route']), + )); + + if (is_array($entry[0]) && $active_main_menu === $key) + { + // @todo Sort navs by order + + foreach ($entry[0] as $sub_entry) + { + $this->template->assign_block_vars('l_block1', array( + 'L_TITLE' => $this->language->lang($sub_entry['label']), + 'S_SELECTED' => (isset($sub_entry['route']) && $sub_entry['route'] === $this->request->get('_route')), + 'U_TITLE' => $this->route($sub_entry['route']), + )); + } + } + } + } + + /** + * Returns path from route name + * + * @param string $route_name + * + * @return string + */ + public function route($route_name) + { + $url = $this->router->generate($route_name); + + return $url; + } + + /** + * Render language select form + */ + protected function render_language_select() + { + $langs = $this->lang_helper->get_available_languages(); + } + + /** + * Returns the name of the active main menu item + * + * @param array $nav_array + * + * @return string|bool Returns the name of the active main menu element, if the element not found, returns false + */ + protected function get_active_main_menu($nav_array) + { + $active_route = $this->request->get('_route'); + + foreach ($nav_array as $nav_name => $nav_options) + { + $current_menu = $nav_name; + + if (isset($nav_options['route']) && $nav_options['route'] === $active_route) + { + return $nav_name; + } + + if (is_array($nav_options[0])) + { + foreach ($nav_options[0] as $sub_menus) + { + if (isset($sub_menus['route']) &&$sub_menus['route'] === $active_route) + { + return $current_menu; + } + } + } + } + + return false; + } +} diff --git a/phpBB/install/controller/install.php b/phpBB/install/controller/install.php new file mode 100644 index 0000000000..1217107484 --- /dev/null +++ b/phpBB/install/controller/install.php @@ -0,0 +1,109 @@ + + * @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\install\controller; + +use Symfony\Component\HttpFoundation\StreamedResponse; + +/** + * Controller for installing phpBB + */ +class install +{ + /** + * @var \phpbb\install\controller\helper + */ + protected $controller_helper; + + /** + * @var \phpbb\install\helper\iohandler\factory + */ + protected $iohandler_factory; + + /** + * @var \phpbb\template\template + */ + protected $template; + + /** + * @var \phpbb\request\request_interface + */ + protected $request; + + /** + * @var \phpbb\install\installer + */ + protected $installer; + + /** + * Constructor + * + * @param helper $helper + * @param \phpbb\install\helper\iohandler\factory $factory + * @param \phpbb\request\request_interface $request + * @param \phpbb\install\installer $installer + */ + public function __construct(helper $helper, \phpbb\install\helper\iohandler\factory $factory, \phpbb\template\template $template, \phpbb\request\request_interface $request, \phpbb\install\installer $installer) + { + $this->controller_helper = $helper; + $this->iohandler_factory = $factory; + $this->template = $template; + $this->request = $request; + $this->installer = $installer; + } + + public function handle() + { + // @todo check that phpBB is not already installed + + $this->template->assign_vars(array( + 'U_ACTION' => $this->controller_helper->route('phpbb_installer_install'), + )); + + // Set up input-output handler + if ($this->request->is_ajax()) + { + $this->iohandler_factory->set_environment('ajax'); + } + else + { + $this->iohandler_factory->set_environment('nojs'); + } + + if ($this->request->is_ajax()) + { + $installer = &$this->installer; + + $response = new StreamedResponse(); + $response->setCallback(function() use ($installer) { + $installer->run(); + }); + + return $response; + } + else + { + // Determine whether the installation was started or not + if (true) + { + // If not, let's render the welcome page + $this->template->assign_vars(array( + 'SHOW_INSTALL_START_FORM' => true, + )); + return $this->controller_helper->render('installer_install.html', 'INSTALL'); + } + + // @todo: implement no js controller logic + } + } +} diff --git a/phpBB/install/controller/install_index.php b/phpBB/install/controller/install_index.php new file mode 100644 index 0000000000..c61d68f7fb --- /dev/null +++ b/phpBB/install/controller/install_index.php @@ -0,0 +1,79 @@ + + * @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\install\controller; + +class install_index +{ + /** + * @var helper + */ + protected $helper; + + /** + * @var \phpbb\language\language + */ + protected $language; + + /** + * @var \phpbb\template\template + */ + protected $template; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * Constructor + * + * @param helper $helper + * @param \phpbb\language\language $language + * @param \phpbb\template\template $template + * @param string $phpbb_root_path + */ + public function __construct(helper $helper, \phpbb\language\language $language, \phpbb\template\template $template, $phpbb_root_path) + { + $this->helper = $helper; + $this->language = $language; + $this->template = $template; + $this->phpbb_root_path = $phpbb_root_path; + } + + public function handle($mode) + { + switch ($mode) + { + case "intro": + $title = $this->language->lang('INTRODUCTION_TITLE'); + $body = $this->language->lang('INTRODUCTION_BODY'); + break; + case "support": + $title = $this->language->lang('SUPPORT_TITLE'); + $body = $this->language->lang('SUPPORT_BODY'); + break; + case "license": + $title = $this->language->lang('LICENSE_TITLE'); + $body = implode("
            \n", file($this->phpbb_root_path . 'docs/LICENSE.txt')); + break; + } + + $this->template->assign_vars(array( + 'TITLE' => $title, + 'BODY' => $body, + )); + + return $this->helper->render('install_main.html', $title); + } +} From 0b74e3b0dea723cf0e5a83dcd910bc29941d1456 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Sun, 19 Apr 2015 00:43:51 +0200 Subject: [PATCH 0442/1676] [ticket/13740] Installer's install tasks and modules [ci skip] PHPBB3-13740 --- phpBB/config/installer/config.yml | 2 + .../installer/container/environment.yml | 3 + .../config/installer/container/parameters.yml | 2 + phpBB/config/installer/container/services.yml | 70 +++ .../container/services_install_controller.yml | 29 ++ .../container/services_install_data.yml | 29 ++ .../container/services_install_database.yml | 36 ++ .../container/services_install_filesystem.yml | 16 + .../container/services_install_finish.yml | 20 + .../container/services_install_navigation.yml | 25 + .../services_install_obtain_data.yml | 43 ++ .../services_install_requirements.yml | 20 + .../container/services_installer.yml | 70 +++ .../install/exception/installer_exception.php | 22 + .../helper/navigation/main_navigation.php | 45 ++ phpBB/install/module/install_data/module.php | 22 + .../module/install_data/task/add_bots.php | 224 +++++++++ .../install_data/task/add_languages.php | 105 ++++ .../module/install_data/task/add_modules.php | 452 ++++++++++++++++++ .../module/install_database/module.php | 22 + .../task/add_config_settings.php | 325 +++++++++++++ .../task/add_default_data.php | 145 ++++++ .../install_database/task/create_schema.php | 198 ++++++++ .../module/install_filesystem/module.php | 22 + .../task/create_config_file.php | 219 +++++++++ .../install/module/install_finish/module.php | 22 + .../install_finish/task/notify_user.php | 113 +++++ .../task/populate_migrations.php | 54 +++ phpBB/install/module/obtain_data/module.php | 63 +++ .../obtain_data/task/obtain_admin_data.php | 207 ++++++++ .../obtain_data/task/obtain_board_data.php | 172 +++++++ .../obtain_data/task/obtain_database_data.php | 259 ++++++++++ .../obtain_data/task/obtain_email_data.php | 151 ++++++ .../obtain_data/task/obtain_imagick_path.php | 73 +++ .../obtain_data/task/obtain_server_data.php | 187 ++++++++ phpBB/install/module/requirements/module.php | 73 +++ .../requirements/task/check_filesystem.php | 258 ++++++++++ .../task/check_server_environment.php | 185 +++++++ 38 files changed, 3983 insertions(+) create mode 100644 phpBB/config/installer/config.yml create mode 100644 phpBB/config/installer/container/environment.yml create mode 100644 phpBB/config/installer/container/parameters.yml create mode 100644 phpBB/config/installer/container/services.yml create mode 100644 phpBB/config/installer/container/services_install_controller.yml create mode 100644 phpBB/config/installer/container/services_install_data.yml create mode 100644 phpBB/config/installer/container/services_install_database.yml create mode 100644 phpBB/config/installer/container/services_install_filesystem.yml create mode 100644 phpBB/config/installer/container/services_install_finish.yml create mode 100644 phpBB/config/installer/container/services_install_navigation.yml create mode 100644 phpBB/config/installer/container/services_install_obtain_data.yml create mode 100644 phpBB/config/installer/container/services_install_requirements.yml create mode 100644 phpBB/config/installer/container/services_installer.yml create mode 100644 phpBB/install/exception/installer_exception.php create mode 100644 phpBB/install/helper/navigation/main_navigation.php create mode 100644 phpBB/install/module/install_data/module.php create mode 100644 phpBB/install/module/install_data/task/add_bots.php create mode 100644 phpBB/install/module/install_data/task/add_languages.php create mode 100644 phpBB/install/module/install_data/task/add_modules.php create mode 100644 phpBB/install/module/install_database/module.php create mode 100644 phpBB/install/module/install_database/task/add_config_settings.php create mode 100644 phpBB/install/module/install_database/task/add_default_data.php create mode 100644 phpBB/install/module/install_database/task/create_schema.php create mode 100644 phpBB/install/module/install_filesystem/module.php create mode 100644 phpBB/install/module/install_filesystem/task/create_config_file.php create mode 100644 phpBB/install/module/install_finish/module.php create mode 100644 phpBB/install/module/install_finish/task/notify_user.php create mode 100644 phpBB/install/module/install_finish/task/populate_migrations.php create mode 100644 phpBB/install/module/obtain_data/module.php create mode 100644 phpBB/install/module/obtain_data/task/obtain_admin_data.php create mode 100644 phpBB/install/module/obtain_data/task/obtain_board_data.php create mode 100644 phpBB/install/module/obtain_data/task/obtain_database_data.php create mode 100644 phpBB/install/module/obtain_data/task/obtain_email_data.php create mode 100644 phpBB/install/module/obtain_data/task/obtain_imagick_path.php create mode 100644 phpBB/install/module/obtain_data/task/obtain_server_data.php create mode 100644 phpBB/install/module/requirements/module.php create mode 100644 phpBB/install/module/requirements/task/check_filesystem.php create mode 100644 phpBB/install/module/requirements/task/check_server_environment.php diff --git a/phpBB/config/installer/config.yml b/phpBB/config/installer/config.yml new file mode 100644 index 0000000000..979dbbcdd9 --- /dev/null +++ b/phpBB/config/installer/config.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../default/config.yml } diff --git a/phpBB/config/installer/container/environment.yml b/phpBB/config/installer/container/environment.yml new file mode 100644 index 0000000000..40a3c7a683 --- /dev/null +++ b/phpBB/config/installer/container/environment.yml @@ -0,0 +1,3 @@ +imports: + - { resource: services.yml } + - { resource: parameters.yml } diff --git a/phpBB/config/installer/container/parameters.yml b/phpBB/config/installer/container/parameters.yml new file mode 100644 index 0000000000..0447646806 --- /dev/null +++ b/phpBB/config/installer/container/parameters.yml @@ -0,0 +1,2 @@ +imports: + - { resource: ../../default/container/parameters.yml } diff --git a/phpBB/config/installer/container/services.yml b/phpBB/config/installer/container/services.yml new file mode 100644 index 0000000000..8296bcc079 --- /dev/null +++ b/phpBB/config/installer/container/services.yml @@ -0,0 +1,70 @@ +imports: + - { resource: services_installer.yml } + - { resource: ../../default/container/services_files.yml } + - { resource: ../../default/container/services_http.yml } + - { resource: ../../default/container/services_language.yml } + - { resource: ../../default/container/services_php.yml } + - { resource: ../../default/container/services_routing.yml } + - { resource: ../../default/container/services_twig.yml } + +services: + config: + class: phpbb\config\config + arguments: + - [] + + controller.resolver: + class: phpbb\controller\resolver + arguments: + - @service_container + - %core.root_path% + - @template + + dispatcher: + class: phpbb\event\dispatcher + arguments: + - @service_container + + language.loader: + parent: language.loader_abstract + + path_helper: + class: phpbb\path_helper + arguments: + - @symfony_request + - @filesystem + - @request + - %core.root_path% + - %core.php_ext% + + router: + class: phpbb\routing\router + arguments: + - @service_container + - @filesystem + - %core.root_path% + - %core.php_ext% + - %core.environment% + + template: + class: phpbb\template\twig\twig + arguments: + - @path_helper + - @config + - @template_context + - @template.twig.environment + - %core.template.cache_path% + - null + - @template.twig.extensions.collection + + template.twig.environment: + class: phpbb\template\twig\environment + arguments: + - @config + - @filesystem + - @path_helper + - @service_container + - %core.template.cache_path% + - null + - @template.twig.loader + - [] diff --git a/phpBB/config/installer/container/services_install_controller.yml b/phpBB/config/installer/container/services_install_controller.yml new file mode 100644 index 0000000000..5eea133590 --- /dev/null +++ b/phpBB/config/installer/container/services_install_controller.yml @@ -0,0 +1,29 @@ +services: + phpbb.installer.controller.welcome: + class: phpbb\install\controller\install_index + arguments: + - @phpbb.installer.controller.helper + - @language + - @template + - %core.root_path% + + phpbb.installer.controller.helper: + class: phpbb\install\controller\helper + arguments: + - @language + - @language.helper.language_file + - @installer.navigation.provider + - @template + - @path_helper + - @symfony_request + - @router + - %core.root_path% + + phpbb.installer.controller.install: + class: phpbb\install\controller\install + arguments: + - @phpbb.installer.controller.helper + - @installer.helper.iohandler_factory + - @template + - @request + - @installer.installer.install diff --git a/phpBB/config/installer/container/services_install_data.yml b/phpBB/config/installer/container/services_install_data.yml new file mode 100644 index 0000000000..5e01be2bce --- /dev/null +++ b/phpBB/config/installer/container/services_install_data.yml @@ -0,0 +1,29 @@ +services: + installer.install_data.add_bots: + class: phpbb\install\module\install_data\task\add_bots + arguments: + - @installer.helper.config + - @installer.helper.iohandler + - @installer.helper.container_factory + - @language + - %core.root_path% + - %core.php_ext% + + installer.install_data.add_languages: + class: phpbb\install\module\install_data\task\add_languages + arguments: + - @installer.helper.iohandler + - @installer.helper.container_factory + - @language.helper.language_file + + installer.install_data.add_modules: + class: phpbb\install\module\install_data\task\add_modules + arguments: + - @installer.helper.iohandler + - @installer.helper.container_factory + + installer.module.data_install: + class: phpbb\install\module\install_data\module + parent: installer.module_base + arguments: + - ["installer.install_data.add_languages", "installer.install_data.add_bots", "installer.install_data.add_modules"] diff --git a/phpBB/config/installer/container/services_install_database.yml b/phpBB/config/installer/container/services_install_database.yml new file mode 100644 index 0000000000..865f2d8ab6 --- /dev/null +++ b/phpBB/config/installer/container/services_install_database.yml @@ -0,0 +1,36 @@ +services: + installer.install_database.create_schema: + class: phpbb\install\module\install_database\task\create_schema + arguments: + - @installer.helper.config + - @installer.helper.database + - @filesystem + - @installer.helper.iohandler + # - @installer.helper.container_factory + - %core.root_path% + - %core.php_ext% + + installer.install_database.add_default_data: + class: phpbb\install\module\install_database\task\add_default_data + arguments: + - @installer.helper.database + - @installer.helper.config + - @installer.helper.iohandler + - @installer.helper.container_factory + - @language + + installer.install_database.add_config_settings: + class: phpbb\install\module\install_database\task\add_config_settings + arguments: + - @filesystem + - @installer.helper.config + - @installer.helper.iohandler + - @installer.helper.container_factory + - @language + - %core.root_path% + + installer.module.database_install: + class: phpbb\install\module\install_database\module + parent: installer.module_base + arguments: + - ["installer.install_database.create_schema", "installer.install_database.add_default_data", "installer.install_database.add_config_settings"] diff --git a/phpBB/config/installer/container/services_install_filesystem.yml b/phpBB/config/installer/container/services_install_filesystem.yml new file mode 100644 index 0000000000..24497d330a --- /dev/null +++ b/phpBB/config/installer/container/services_install_filesystem.yml @@ -0,0 +1,16 @@ +services: + installer.filesystem.create_config: + class: phpbb\install\module\install_filesystem\task\create_config_file + arguments: + - @filesystem + - @installer.helper.config + - @installer.helper.database + - @installer.helper.iohandler + - %core.root_path% + - %core.php_ext% + + installer.module.filesystem_install: + class: phpbb\install\module\install_filesystem\module + parent: installer.module_base + arguments: + - ["installer.filesystem.create_config"] diff --git a/phpBB/config/installer/container/services_install_finish.yml b/phpBB/config/installer/container/services_install_finish.yml new file mode 100644 index 0000000000..20cd60983b --- /dev/null +++ b/phpBB/config/installer/container/services_install_finish.yml @@ -0,0 +1,20 @@ +services: + installer.finish.populate_migrations: + class: phpbb\install\module\install_finish\task\populate_migrations + arguments: + - @installer.helper.container_factory + + installer.finish.notify_user: + class: phpbb\install\module\install_finish\task\notify_user + arguments: + - @installer.helper.container_factory + - @installer.helper.config + - @installer.helper.iohandler + - %core.root_path% + - %core.php_ext% + + installer.module.finish_install: + class: phpbb\install\module\install_filesystem\module + parent: installer.module_base + arguments: + - ["installer.finish.populate_migrations", "installer.finish.notify_user"] diff --git a/phpBB/config/installer/container/services_install_navigation.yml b/phpBB/config/installer/container/services_install_navigation.yml new file mode 100644 index 0000000000..88c495825b --- /dev/null +++ b/phpBB/config/installer/container/services_install_navigation.yml @@ -0,0 +1,25 @@ +services: + installer.navigation.provider: + class: phpbb\install\helper\navigation\navigation_provider + arguments: + - @installer.navigation.service_collection + + installer.navigation.service_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: installer.navigation } + + installer.navigation.main_navigation: + class: phpbb\install\helper\navigation\main_navigation + scope: prototype + tags: + - { name: installer.navigation } + + installer.navigation.install_navigation: + class: phpbb\install\helper\navigation\install_navigation + scope: prototype + tags: + - { name: installer.navigation } + diff --git a/phpBB/config/installer/container/services_install_obtain_data.yml b/phpBB/config/installer/container/services_install_obtain_data.yml new file mode 100644 index 0000000000..2800392c58 --- /dev/null +++ b/phpBB/config/installer/container/services_install_obtain_data.yml @@ -0,0 +1,43 @@ +services: + installer.obtain_data.admin: + class: phpbb\install\module\obtain_data\task\obtain_admin_data + arguments: + - @installer.helper.config + - @installer.helper.iohandler + + installer.obtain_data.board: + class: phpbb\install\module\obtain_data\task\obtain_board_data + arguments: + - @installer.helper.config + - @installer.helper.iohandler + - @language.helper.language_file + + installer.obtain_data.database: + class: phpbb\install\module\obtain_data\task\obtain_database_data + arguments: + - @installer.helper.database + - @installer.helper.config + - @installer.helper.iohandler + + installer.obtain_data.email: + class: phpbb\install\module\obtain_data\task\obtain_email_data + arguments: + - @installer.helper.config + - @installer.helper.iohandler + + installer.obtain_data.imagick: + class: phpbb\install\module\obtain_data\task\obtain_imagick_path + arguments: + - @installer.helper.config + + installer.obtain_data.server: + class: phpbb\install\module\obtain_data\task\obtain_server_data + arguments: + - @installer.helper.config + - @installer.helper.iohandler + + installer.module.obtain_data_install: + class: phpbb\install\module\obtain_data\module + parent: installer.module_base + arguments: + - ["installer.obtain_data.admin", "installer.obtain_data.database", "installer.obtain_data.server", "installer.obtain_data.email", "installer.obtain_data.board", "installer.obtain_data.imagick"] diff --git a/phpBB/config/installer/container/services_install_requirements.yml b/phpBB/config/installer/container/services_install_requirements.yml new file mode 100644 index 0000000000..afbe341c06 --- /dev/null +++ b/phpBB/config/installer/container/services_install_requirements.yml @@ -0,0 +1,20 @@ +services: + installer.requirements.task.filesystem: + class: phpbb\install\module\requirements\task\check_filesystem + arguments: + - @filesystem + - @installer.helper.iohandler + - %core.root_path% + - %core.php_ext% + + installer.requirements.task.server: + class: phpbb\install\module\requirements\task\check_server_environment + arguments: + - @installer.helper.database + - @installer.helper.iohandler + + installer.module.requirements_install: + class: phpbb\install\module\requirements\module + parent: installer.module_base + arguments: + - ["installer.requirements.task.filesystem", "installer.requirements.task.server"] diff --git a/phpBB/config/installer/container/services_installer.yml b/phpBB/config/installer/container/services_installer.yml new file mode 100644 index 0000000000..ce27ae8abd --- /dev/null +++ b/phpBB/config/installer/container/services_installer.yml @@ -0,0 +1,70 @@ +imports: + - { resource: services_install_controller.yml } + - { resource: services_install_data.yml } + - { resource: services_install_database.yml } + - { resource: services_install_filesystem.yml } + - { resource: services_install_finish.yml } + - { resource: services_install_navigation.yml } + - { resource: services_install_obtain_data.yml } + - { resource: services_install_requirements.yml } + +services: +# -------- Installer helpers ------------------------ + installer.helper.config: + class: phpbb\install\helper\config + arguments: + - @filesystem + - @php_ini + - %core.root_path% + + installer.helper.database: + class: phpbb\install\helper\database + arguments: + - @filesystem + - %core.root_path% + + installer.helper.iohandler_factory: + class: phpbb\install\helper\iohandler\factory + arguments: + - @service_container + + installer.helper.iohandler_abstract: + abstract: true + calls: + - [set_language, ["@language"]] + + installer.helper.iohandler_ajax: + class: phpbb\install\helper\iohandler\ajax_iohandler + parent: installer.helper.iohandler_abstract + arguments: + - @request + - @template + + installer.helper.iohandler: + class: phpbb\install\helper\iohandler\iohandler_interface + factory: ["@installer.helper.iohandler_factory", get] + + installer.helper.container_factory: + class: phpbb\install\helper\container_factory + arguments: + - @request + - %core.root_path% + - %core.php_ext% + +# -------- Installer -------------------------------- + installer.module_base: + abstract: true + calls: + - [setup, [@service_container, @installer.helper.config, @installer.helper.iohandler]] + + installer.installer.abstract: + class: phpbb\install\installer + abstract: true + arguments: + - @installer.helper.config + - @service_container + + installer.installer.install: + parent: installer.installer.abstract + calls: + - [set_modules, [["installer.module.requirements_install", "installer.module.obtain_data_install", "installer.module.filesystem_install", "installer.module.database_install", "installer.module.data_install", "installer.module.finish_install"]]] diff --git a/phpBB/install/exception/installer_exception.php b/phpBB/install/exception/installer_exception.php new file mode 100644 index 0000000000..c37950d05c --- /dev/null +++ b/phpBB/install/exception/installer_exception.php @@ -0,0 +1,22 @@ + + * @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\install\exception; + +/** + * Installer's base exception + */ +class installer_exception extends \Exception +{ + +} diff --git a/phpBB/install/helper/navigation/main_navigation.php b/phpBB/install/helper/navigation/main_navigation.php new file mode 100644 index 0000000000..ad67840424 --- /dev/null +++ b/phpBB/install/helper/navigation/main_navigation.php @@ -0,0 +1,45 @@ + + * @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\install\helper\navigation; + +class main_navigation implements navigation_interface +{ + public function get() + { + return array( + 'overview' => array( + 'label' => 'MENU_OVERVIEW', + 'route' => 'phpbb_installer_index', + 'order' => 0, + array( + 'introduction' => array( + 'label' => 'MENU_INTRO', + 'route' => 'phpbb_installer_index', + 'order' => 0, + ), + 'support' => array( + 'label' => 'MENU_SUPPORT', + 'route' => 'phpbb_installer_support', + 'order' => 1, + ), + 'license' => array( + 'label' => 'MENU_LICENSE', + 'route' => 'phpbb_installer_license', + 'order' => 2, + ), + ), + ), + ); + } +} diff --git a/phpBB/install/module/install_data/module.php b/phpBB/install/module/install_data/module.php new file mode 100644 index 0000000000..231bcb0866 --- /dev/null +++ b/phpBB/install/module/install_data/module.php @@ -0,0 +1,22 @@ + + * @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\install\module\install_data; + +/** + * Installer module for recovering and installing default data installation + */ +class module extends \phpbb\install\module_base +{ + +} diff --git a/phpBB/install/module/install_data/task/add_bots.php b/phpBB/install/module/install_data/task/add_bots.php new file mode 100644 index 0000000000..8ce4ae765d --- /dev/null +++ b/phpBB/install/module/install_data/task/add_bots.php @@ -0,0 +1,224 @@ + + * @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\install\module\install_data\task; + +class add_bots extends \phpbb\install\task_base +{ + /** + * @var array + */ + protected $bot_list; + + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $io_handler; + + /** + * @var \phpbb\language\language + */ + protected $language; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param \phpbb\install\helper\config $install_config Installer's config + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Input-output handler for the installer + * @param \phpbb\install\helper\container_factory $container Installer's DI container + * @param \phpbb\language\language $language Language provider + * @param string $phpbb_root_path Relative path to phpBB root + * @param string $php_ext PHP extension + */ + public function __construct(\phpbb\install\helper\config $install_config, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler, + \phpbb\install\helper\container_factory $container, + \phpbb\language\language $language, + $phpbb_root_path, + $php_ext) + { + parent::__construct(true); + + $this->db = $container->get('dbal.conn'); + $this->install_config = $install_config; + $this->io_handler = $iohandler; + $this->language = $language; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + + /** + * A list of the web-crawlers/bots we recognise by default + * + * Candidates but not included: + * 'Accoona [Bot]' 'Accoona-AI-Agent/' + * 'ASPseek [Crawler]' 'ASPseek/' + * 'Boitho [Crawler]' 'boitho.com-dc/' + * 'Bunnybot [Bot]' 'powered by www.buncat.de' + * 'Cosmix [Bot]' 'cfetch/' + * 'Crawler Search [Crawler]' '.Crawler-Search.de' + * 'Findexa [Crawler]' 'Findexa Crawler (' + * 'GBSpider [Spider]' 'GBSpider v' + * 'genie [Bot]' 'genieBot (' + * 'Hogsearch [Bot]' 'oegp v. 1.3.0' + * 'Insuranco [Bot]' 'InsurancoBot' + * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler' + * 'ISC Systems [Bot]' 'ISC Systems iRc Search' + * 'Jyxobot [Bot]' 'Jyxobot/' + * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/' + * 'LinkWalker' 'LinkWalker' + * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html' + * 'Naver [Bot]' 'nhnbot@naver.com)' + * 'NetResearchServer' 'NetResearchServer/' + * 'Nimble [Crawler]' 'NimbleCrawler' + * 'Ocelli [Bot]' 'Ocelli/' + * 'Onsearch [Bot]' 'onCHECK-Robot' + * 'Orange [Spider]' 'OrangeSpider' + * 'Sproose [Bot]' 'http://www.sproose.com/bot' + * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)' + * 'Tbot [Bot]' 'Tbot/' + * 'Thumbshots [Capture]' 'thumbshots-de-Bot' + * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/' + * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)' + * 'WissenOnline [Bot]' 'WissenOnline-Bot' + * 'WWWeasel [Bot]' 'WWWeasel Robot v' + * 'Xaldon [Spider]' 'Xaldon WebSpider' + */ + $this->bot_list = array( + 'AdsBot [Google]' => array('AdsBot-Google', ''), + 'Alexa [Bot]' => array('ia_archiver', ''), + 'Alta Vista [Bot]' => array('Scooter/', ''), + 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''), + 'Baidu [Spider]' => array('Baiduspider', ''), + 'Bing [Bot]' => array('bingbot/', ''), + 'Exabot [Bot]' => array('Exabot', ''), + 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''), + 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''), + 'Francis [Bot]' => array('http://www.neomo.de/', ''), + 'Gigabot [Bot]' => array('Gigabot/', ''), + 'Google Adsense [Bot]' => array('Mediapartners-Google', ''), + 'Google Desktop' => array('Google Desktop', ''), + 'Google Feedfetcher' => array('Feedfetcher-Google', ''), + 'Google [Bot]' => array('Googlebot', ''), + 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''), + 'Heritrix [Crawler]' => array('heritrix/1.', ''), + 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''), + 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''), + 'ichiro [Crawler]' => array('ichiro/', ''), + 'Majestic-12 [Bot]' => array('MJ12bot/', ''), + 'Metager [Bot]' => array('MetagerBot/', ''), + 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''), + 'MSN [Bot]' => array('msnbot/', ''), + 'MSNbot Media' => array('msnbot-media/', ''), + 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''), + 'Online link [Validator]' => array('online link validator', ''), + 'psbot [Picsearch]' => array('psbot/0', ''), + 'Sensis [Crawler]' => array('Sensis Web Crawler', ''), + 'SEO Crawler' => array('SEO search Crawler/', ''), + 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''), + 'SEOSearch [Crawler]' => array('SEOsearch/', ''), + 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''), + 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''), + 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''), + 'TurnitinBot [Bot]' => array('TurnitinBot/', ''), + 'Voyager [Bot]' => array('voyager/', ''), + 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''), + 'W3C [Linkcheck]' => array('W3C-checklink/', ''), + 'W3C [Validator]' => array('W3C_Validator', ''), + 'YaCy [Bot]' => array('yacybot', ''), + 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''), + 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''), + 'Yahoo [Bot]' => array('Yahoo! Slurp', ''), + 'YahooSeeker [Bot]' => array('YahooSeeker/', ''), + ); + } + + /** + * {@inheritdoc} + */ + public function run() + { + $this->db->sql_return_on_error(true); + + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . " + WHERE group_name = 'BOTS'"; + $result = $this->db->sql_query($sql); + $group_id = (int) $this->db->sql_fetchfield('group_id'); + $this->db->sql_freeresult($result); + + if (!$group_id) + { + // If we reach this point then something has gone very wrong + $this->io_handler->add_error_message('NO_GROUP'); + } + + foreach ($this->bot_list as $bot_name => $bot_ary) + { + $user_row = array( + 'user_type' => USER_IGNORE, + 'group_id' => $group_id, + 'username' => $bot_name, + 'user_regdate' => time(), + 'user_password' => '', + 'user_colour' => '9E8DA7', + 'user_email' => '', + 'user_lang' => $this->install_config->get('default_lang'), + 'user_style' => 1, + 'user_timezone' => 'UTC', + 'user_dateformat' => $this->language->lang('default_dateformat'), + 'user_allow_massemail' => 0, + 'user_allow_pm' => 0, + ); + + $user_id = user_add($user_row); + + if (!$user_id) + { + // If we can't insert this user then continue to the next one to avoid inconsistent data + $this->io_handler->add_error_message('CONV_ERROR_INSERT_BOT'); + + continue; + } + + $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', array( + 'bot_active' => 1, + 'bot_name' => (string) $bot_name, + 'user_id' => (int) $user_id, + 'bot_agent' => (string) $bot_ary[0], + 'bot_ip' => (string) $bot_ary[1], + )); + + $this->db->sql_query($sql); + } + } +} diff --git a/phpBB/install/module/install_data/task/add_languages.php b/phpBB/install/module/install_data/task/add_languages.php new file mode 100644 index 0000000000..9502a736f3 --- /dev/null +++ b/phpBB/install/module/install_data/task/add_languages.php @@ -0,0 +1,105 @@ + + * @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\install\module\install_data\task; + +class add_languages extends \phpbb\install\task_base +{ + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $iohandler; + + /** + * @var \phpbb\language\language_file_helper + */ + protected $language_helper; + + /** + * Constructor + * + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + * @param \phpbb\install\helper\container_factory $container Installer's DI container + * @param \phpbb\language\language_file_helper $language_helper Language file helper service + */ + public function __construct(\phpbb\install\helper\iohandler\iohandler_interface $iohandler, + \phpbb\install\helper\container_factory $container, + \phpbb\language\language_file_helper $language_helper) + { + $this->db = $container->get('dbal.conn'); + $this->iohandler = $iohandler; + $this->language_helper = $language_helper; + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + $this->db->sql_return_on_error(true); + + $languages = $this->language_helper->get_available_languages(); + $installed_languages = array(); + + foreach ($languages as $lang_info) + { + $lang_pack = array( + 'lang_iso' => $lang_info['iso'], + 'lang_dir' => $lang_info['iso'], + 'lang_english_name' => htmlspecialchars($lang_info['name']), + 'lang_local_name' => htmlspecialchars($lang_info['local_name'], ENT_COMPAT, 'UTF-8'), + 'lang_author' => htmlspecialchars($lang_info['author'], ENT_COMPAT, 'UTF-8'), + ); + + $this->db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $this->db->sql_build_array('INSERT', $lang_pack)); + + $installed_languages[] = (int) $this->db->sql_nextid(); + if ($this->db->get_sql_error_triggered()) + { + $error = $this->db->sql_error($this->db->get_sql_error_sql()); + $this->iohandler->add_error_message($error['message']); + } + } + + $sql = 'SELECT * FROM ' . PROFILE_FIELDS_TABLE; + $result = $this->db->sql_query($sql); + + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, PROFILE_LANG_TABLE); + while ($row = $this->db->sql_fetchrow($result)) + { + foreach ($installed_languages as $lang_id) + { + $insert_buffer->insert(array( + 'field_id' => $row['field_id'], + 'lang_id' => $lang_id, + + // Remove phpbb_ from field name + 'lang_name' => strtoupper(substr($row['field_name'], 6)), + 'lang_explain' => '', + 'lang_default_value' => '', + )); + } + } + + $this->db->sql_freeresult($result); + + $insert_buffer->flush(); + } +} diff --git a/phpBB/install/module/install_data/task/add_modules.php b/phpBB/install/module/install_data/task/add_modules.php new file mode 100644 index 0000000000..98b52d7494 --- /dev/null +++ b/phpBB/install/module/install_data/task/add_modules.php @@ -0,0 +1,452 @@ + + * @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\install\module\install_data\task; + +class add_modules extends \phpbb\install\task_base +{ + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \phpbb\extension\manager + */ + protected $extension_manager; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $iohandler; + + /** + * @var \phpbb\module\module_manager + */ + protected $module_manager; + + /** + * Define the module structure so that we can populate the database without + * needing to hard-code module_id values + * + * @var array + */ + protected $module_categories; + + /** + * @var array + */ + protected $module_categories_basenames; + + /** + * @var array + */ + protected $module_extras; + + /** + * Constructor + * + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + * @param \phpbb\install\helper\container_factory $container Installer's DI container + */ + public function __construct(\phpbb\install\helper\iohandler\iohandler_interface $iohandler, + \phpbb\install\helper\container_factory $container) + { + $this->db = $container->get('dbal.conn'); + $this->extension_manager = $container->get('ext.manager'); + $this->iohandler = $iohandler; + $this->module_manager = $container->get('module.manager'); + + parent::__construct(true); + + $this->module_categories = array( + 'acp' => array( + 'ACP_CAT_GENERAL' => array( + 'ACP_QUICK_ACCESS', + 'ACP_BOARD_CONFIGURATION', + 'ACP_CLIENT_COMMUNICATION', + 'ACP_SERVER_CONFIGURATION', + ), + 'ACP_CAT_FORUMS' => array( + 'ACP_MANAGE_FORUMS', + 'ACP_FORUM_BASED_PERMISSIONS', + ), + 'ACP_CAT_POSTING' => array( + 'ACP_MESSAGES', + 'ACP_ATTACHMENTS', + ), + 'ACP_CAT_USERGROUP' => array( + 'ACP_CAT_USERS', + 'ACP_GROUPS', + 'ACP_USER_SECURITY', + ), + 'ACP_CAT_PERMISSIONS' => array( + 'ACP_GLOBAL_PERMISSIONS', + 'ACP_FORUM_BASED_PERMISSIONS', + 'ACP_PERMISSION_ROLES', + 'ACP_PERMISSION_MASKS', + ), + 'ACP_CAT_CUSTOMISE' => array( + 'ACP_STYLE_MANAGEMENT', + 'ACP_EXTENSION_MANAGEMENT', + 'ACP_LANGUAGE', + ), + 'ACP_CAT_MAINTENANCE' => array( + 'ACP_FORUM_LOGS', + 'ACP_CAT_DATABASE', + ), + 'ACP_CAT_SYSTEM' => array( + 'ACP_AUTOMATION', + 'ACP_GENERAL_TASKS', + 'ACP_MODULE_MANAGEMENT', + ), + 'ACP_CAT_DOT_MODS' => null, + ), + 'mcp' => array( + 'MCP_MAIN' => null, + 'MCP_QUEUE' => null, + 'MCP_REPORTS' => null, + 'MCP_NOTES' => null, + 'MCP_WARN' => null, + 'MCP_LOGS' => null, + 'MCP_BAN' => null, + ), + 'ucp' => array( + 'UCP_MAIN' => null, + 'UCP_PROFILE' => null, + 'UCP_PREFS' => null, + 'UCP_PM' => null, + 'UCP_USERGROUPS' => null, + 'UCP_ZEBRA' => null, + ), + ); + + $this->module_categories_basenames = array( + 'UCP_PM' => 'ucp_pm', + ); + + $this->module_extras = array( + 'acp' => array( + 'ACP_QUICK_ACCESS' => array( + 'ACP_MANAGE_USERS', + 'ACP_GROUPS_MANAGE', + 'ACP_MANAGE_FORUMS', + 'ACP_MOD_LOGS', + 'ACP_BOTS', + 'ACP_PHP_INFO', + ), + 'ACP_FORUM_BASED_PERMISSIONS' => array( + 'ACP_FORUM_PERMISSIONS', + 'ACP_FORUM_PERMISSIONS_COPY', + 'ACP_FORUM_MODERATORS', + 'ACP_USERS_FORUM_PERMISSIONS', + 'ACP_GROUPS_FORUM_PERMISSIONS', + ), + ), + ); + } + + /** + * {@inheritdoc} + */ + public function run() + { + $this->db->sql_return_on_error(true); + + $module_classes = array('acp', 'mcp', 'ucp'); + foreach ($module_classes as $module_class) + { + $categories = array(); + + foreach ($this->module_categories[$module_class] as $cat_name => $subs) + { + // Check if this sub-category has a basename. If it has, use it. + $basename = (isset($this->module_categories_basenames[$cat_name])) ? $this->module_categories_basenames[$cat_name] : ''; + + $module_data = array( + 'module_basename' => $basename, + 'module_enabled' => 1, + 'module_display' => 1, + 'parent_id' => 0, + 'module_class' => $module_class, + 'module_langname' => $cat_name, + 'module_mode' => '', + 'module_auth' => '', + ); + + $this->module_manager->update_module_data($module_data); + + // Check for last sql error happened + if ($this->db->get_sql_error_triggered()) + { + $error = $this->db->sql_error($this->db->get_sql_error_sql()); + $this->iohandler->add_error_message('INST_ERR_DB', $error['message']); + } + + $categories[$cat_name]['id'] = (int)$module_data['module_id']; + $categories[$cat_name]['parent_id'] = 0; + + if (is_array($subs)) + { + foreach ($subs as $level2_name) + { + // Check if this sub-category has a basename. If it has, use it. + $basename = (isset($this->module_categories_basenames[$level2_name])) ? $this->module_categories_basenames[$level2_name] : ''; + + $module_data = array( + 'module_basename' => $basename, + 'module_enabled' => 1, + 'module_display' => 1, + 'parent_id' => (int)$categories[$cat_name]['id'], + 'module_class' => $module_class, + 'module_langname' => $level2_name, + 'module_mode' => '', + 'module_auth' => '', + ); + + $this->module_manager->update_module_data($module_data); + + // Check for last sql error happened + if ($this->db->get_sql_error_triggered()) + { + $error = $this->db->sql_error($this->db->get_sql_error_sql()); + $this->iohandler->add_error_message('INST_ERR_DB', $error['message']); + } + + $categories[$level2_name]['id'] = (int)$module_data['module_id']; + $categories[$level2_name]['parent_id'] = (int)$categories[$cat_name]['id']; + } + } + } + + // Get the modules we want to add... returned sorted by name + $module_info = $this->module_manager->get_module_infos($module_class); + + foreach ($module_info as $module_basename => $fileinfo) + { + foreach ($fileinfo['modes'] as $module_mode => $row) + { + foreach ($row['cat'] as $cat_name) + { + if (!isset($categories[$cat_name])) + { + continue; + } + + $module_data = array( + 'module_basename' => $module_basename, + 'module_enabled' => 1, + 'module_display' => (isset($row['display'])) ? (int) $row['display'] : 1, + 'parent_id' => (int) $categories[$cat_name]['id'], + 'module_class' => $module_class, + 'module_langname' => $row['title'], + 'module_mode' => $module_mode, + 'module_auth' => $row['auth'], + ); + + $this->module_manager->update_module_data($module_data); + + // Check for last sql error happened + if ($this->db->get_sql_error_triggered()) + { + $error = $this->db->sql_error($this->db->get_sql_error_sql()); + $this->iohandler->add_error_message('INST_ERR_DB', $error['message']); + } + } + } + } + + // Move some of the modules around since the code above will put them in the wrong place + if ($module_class === 'acp') + { + // Move main module 4 up... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'acp_main' + AND module_class = 'acp' + AND module_mode = 'main'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'acp', 'move_up', 4); + + // Move permissions intro screen module 4 up... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'acp_permissions' + AND module_class = 'acp' + AND module_mode = 'intro'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'acp', 'move_up', 4); + + // Move manage users screen module 5 up... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'acp_users' + AND module_class = 'acp' + AND module_mode = 'overview'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'acp', 'move_up', 5); + + // Move extension management module 1 up... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_langname = 'ACP_EXTENSION_MANAGEMENT' + AND module_class = 'acp' + AND module_mode = '' + AND module_basename = ''"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'acp', 'move_up', 1); + } + + if ($module_class == 'mcp') + { + // Move pm report details module 3 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'mcp_pm_reports' + AND module_class = 'mcp' + AND module_mode = 'pm_report_details'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'mcp', 'move_down', 3); + + // Move closed pm reports module 3 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'mcp_pm_reports' + AND module_class = 'mcp' + AND module_mode = 'pm_reports_closed'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'mcp', 'move_down', 3); + + // Move open pm reports module 3 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'mcp_pm_reports' + AND module_class = 'mcp' + AND module_mode = 'pm_reports'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'mcp', 'move_down', 3); + } + + if ($module_class == 'ucp') + { + // Move attachment module 4 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'ucp_attachments' + AND module_class = 'ucp' + AND module_mode = 'attachments'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'ucp', 'move_down', 4); + + // Move notification options module 4 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'ucp_notifications' + AND module_class = 'ucp' + AND module_mode = 'notification_options'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'ucp', 'move_down', 4); + + // Move OAuth module 5 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'ucp_auth_link' + AND module_class = 'ucp' + AND module_mode = 'auth_link'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $this->module_manager->move_module_by($row, 'ucp', 'move_down', 5); + } + + // And now for the special ones + // (these are modules which appear in multiple categories and thus get added manually + // to some for more control) + if (isset($this->module_extras[$module_class])) + { + foreach ($this->module_extras[$module_class] as $cat_name => $mods) + { + $sql = 'SELECT module_id, left_id, right_id + FROM ' . MODULES_TABLE . " + WHERE module_langname = '" . $this->db->sql_escape($cat_name) . "' + AND module_class = '" . $this->db->sql_escape($module_class) . "'"; + $result = $this->db->sql_query_limit($sql, 1); + $row2 = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + foreach ($mods as $mod_name) + { + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_langname = '" . $this->db->sql_escape($mod_name) . "' + AND module_class = '" . $this->db->sql_escape($module_class) . "' + AND module_basename <> ''"; + $result = $this->db->sql_query_limit($sql, 1); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $module_data = array( + 'module_basename' => $row['module_basename'], + 'module_enabled' => (int) $row['module_enabled'], + 'module_display' => (int) $row['module_display'], + 'parent_id' => (int) $row2['module_id'], + 'module_class' => $row['module_class'], + 'module_langname' => $row['module_langname'], + 'module_mode' => $row['module_mode'], + 'module_auth' => $row['module_auth'], + ); + + $this->module_manager->update_module_data($module_data); + + // Check for last sql error happened + if ($this->db->get_sql_error_triggered()) + { + $error = $this->db->sql_error($this->db->get_sql_error_sql()); + $this->iohandler->add_error_message('INST_ERR_DB', $error['message']); + } + } + } + } + + $this->module_manager->remove_cache_file($module_class); + } + } +} diff --git a/phpBB/install/module/install_database/module.php b/phpBB/install/module/install_database/module.php new file mode 100644 index 0000000000..d31c5573ec --- /dev/null +++ b/phpBB/install/module/install_database/module.php @@ -0,0 +1,22 @@ + + * @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\install\module\install_database; + +/** + * Installer module for database installation + */ +class module extends \phpbb\install\module_base +{ + +} diff --git a/phpBB/install/module/install_database/task/add_config_settings.php b/phpBB/install/module/install_database/task/add_config_settings.php new file mode 100644 index 0000000000..38dcef1d7a --- /dev/null +++ b/phpBB/install/module/install_database/task/add_config_settings.php @@ -0,0 +1,325 @@ + + * @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\install\module\install_database\task; + +/** + * Create database schema + */ +class add_config_settings extends \phpbb\install\task_base +{ + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $iohandler; + + /** + * @var \phpbb\language\language + */ + protected $language; + + /** + * @var \phpbb\passwords\manager + */ + protected $password_manager; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var string + */ + protected $config_table; + + /** + * @var string + */ + protected $user_table; + + /** + * @var string + */ + protected $topics_table; + + /** + * @var string + */ + protected $forums_table; + + /** + * @var string + */ + protected $posts_table; + + /** + * @var string + */ + protected $moderator_cache_table; + + /** + * Constructor + * + * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem service + * @param \phpbb\install\helper\config $install_config Installer's config helper + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + * @param \phpbb\install\helper\container_factory $container Installer's DI container + * @param \phpbb\language\language $language Language service + * @param string $phpbb_root_path Path to phpBB's root + */ + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, + \phpbb\install\helper\config $install_config, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler, + \phpbb\install\helper\container_factory $container, + \phpbb\language\language $language, + $phpbb_root_path) + { + $this->db = $container->get('dbal.conn'); + $this->filesystem = $filesystem; + $this->install_config = $install_config; + $this->iohandler = $iohandler; + $this->language = $language; + $this->password_manager = $container->get('passwords.manager'); + $this->phpbb_root_path = $phpbb_root_path; + + // Table names + $this->config_table = $container->get_parameter('tables.config'); + $this->forums_table = $container->get_parameter('tables.forums'); + $this->topics_table = $container->get_parameter('tables.topics'); + $this->user_table = $container->get_parameter('tables.users'); + $this->moderator_cache_table = $container->get_parameter('tables.moderator_cache'); + $this->posts_table = $container->get_parameter('tables.posts'); + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + $this->db->sql_return_on_error(true); + + $server_name = $this->install_config->get('server_name'); + $cookie_domain = $this->install_config->get('cookie_domain'); + $current_time = time(); + $user_ip = phpbb_ip_normalise($this->iohandler->get_server_variable('REMOTE_ADDR')); + $user_ip = ($user_ip === false) ? '' : $user_ip; + $referer = $this->iohandler->get_server_variable('REFERER'); + + // Set default config and post data, this applies to all DB's + $sql_ary = array( + 'INSERT INTO ' . $this->config_table . " (config_name, config_value) + VALUES ('board_startdate', '$current_time')", + + 'INSERT INTO ' . $this->config_table . " (config_name, config_value) + VALUES ('default_lang', '" . $this->db->sql_escape($this->install_config->get('default_lang')) . "')", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('img_imagick')) . "' + WHERE config_name = 'img_imagick'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('server_name')) . "' + WHERE config_name = 'server_name'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('server_port')) . "' + WHERE config_name = 'server_port'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_email')) . "' + WHERE config_name = 'board_email'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_email')) . "' + WHERE config_name = 'board_contact'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($cookie_domain) . "' + WHERE config_name = 'cookie_domain'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->language->lang('default_dateformat')) . "' + WHERE config_name = 'default_dateformat'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('email_enable')) . "' + WHERE config_name = 'email_enable'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_delivery')) . "' + WHERE config_name = 'smtp_delivery'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_host')) . "' + WHERE config_name = 'smtp_host'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_auth')) . "' + WHERE config_name = 'smtp_auth_method'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_user')) . "' + WHERE config_name = 'smtp_username'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_pass')) . "' + WHERE config_name = 'smtp_password'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('cookie_secure')) . "' + WHERE config_name = 'cookie_secure'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('force_server_vars')) . "' + WHERE config_name = 'force_server_vars'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('script_path')) . "' + WHERE config_name = 'script_path'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('server_protocol')) . "' + WHERE config_name = 'server_protocol'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "' + WHERE config_name = 'newest_username'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . md5(mt_rand()) . "' + WHERE config_name = 'avatar_salt'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . md5(mt_rand()) . "' + WHERE config_name = 'plupload_salt'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_name')) . "' + WHERE config_name = 'sitename'", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_description')) . "' + WHERE config_name = 'site_desc'", + + 'UPDATE ' . $this->user_table . " + SET username = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "', + user_password='" . $this->password_manager->hash($this->install_config->get('admin_passwd')) . "', + user_ip = '" . $this->db->sql_escape($user_ip) . "', + user_lang = '" . $this->db->sql_escape($this->install_config->get('language')) . "', + user_email='" . $this->db->sql_escape($this->install_config->get('board_email')) . "', + user_dateformat='" . $this->db->sql_escape($this->language->lang('default_dateformat')) . "', + user_email_hash = " . $this->db->sql_escape(phpbb_email_hash($this->install_config->get('board_email'))) . ", + username_clean = '" . $this->db->sql_escape(utf8_clean_string($this->install_config->get('admin_name'))) . "' + WHERE username = 'Admin'", + + 'UPDATE ' . $this->moderator_cache_table . " + SET username = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "' + WHERE username = 'Admin'", + + 'UPDATE ' . $this->forums_table . " + SET forum_last_poster_name = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "' + WHERE forum_last_poster_name = 'Admin'", + + 'UPDATE ' . $this->topics_table . " + SET topic_first_poster_name = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "', + topic_last_poster_name = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "' + WHERE topic_first_poster_name = 'Admin' + OR topic_last_poster_name = 'Admin'", + + 'UPDATE ' . $this->user_table . " + SET user_regdate = $current_time", + + 'UPDATE ' . $this->posts_table . " + SET post_time = $current_time, poster_ip = '" . $this->db->sql_escape($user_ip) . "'", + + 'UPDATE ' . $this->topics_table . " + SET topic_time = $current_time, topic_last_post_time = $current_time", + + 'UPDATE ' . $this->forums_table . " + SET forum_last_post_time = $current_time", + + 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($this->db->sql_server_info(true)) . "' + WHERE config_name = 'dbms_version'", + ); + + if (@extension_loaded('gd')) + { + $sql_ary[] = 'UPDATE ' . $this->config_table . " + SET config_value = 'core.captcha.plugins.gd' + WHERE config_name = 'captcha_plugin'"; + + $sql_ary[] = 'UPDATE ' . $this->config_table . " + SET config_value = '1' + WHERE config_name = 'captcha_gd'"; + } + + $ref = substr($referer, strpos($referer, '://') + 3); + if (!(stripos($ref, $server_name) === 0)) + { + $sql_ary[] = 'UPDATE ' . $this->config_table . " + SET config_value = '0' + WHERE config_name = 'referer_validation'"; + } + + // We set a (semi-)unique cookie name to bypass login issues related to the cookie name. + $cookie_name = 'phpbb3_'; + $rand_str = md5(mt_rand()); + $rand_str = str_replace('0', 'z', base_convert($rand_str, 16, 35)); + $rand_str = substr($rand_str, 0, 5); + $cookie_name .= strtolower($rand_str); + + $sql_ary[] = 'UPDATE ' . $this->config_table . " + SET config_value = '" . $this->db->sql_escape($cookie_name) . "' + WHERE config_name = 'cookie_name'"; + + // Disable avatars if upload directory is not writable + if (!$this->filesystem->is_writable($this->phpbb_root_path . 'images/avatars/upload/')) + { + $sql_ary[] = 'UPDATE ' . $this->config_table . " + SET config_value = '0' + WHERE config_name = 'allow_avatar'"; + + $sql_ary[] = 'UPDATE ' . $this->config_table . " + SET config_value = '0' + WHERE config_name = 'allow_avatar_upload'"; + } + + foreach ($sql_ary as $sql) + { + if (!$this->db->sql_query($sql)) + { + $error = $this->db->sql_error($this->db->get_sql_error_sql()); + $this->iohandler->add_error_message('INST_ERR_DB', $error['message']); + } + } + } +} diff --git a/phpBB/install/module/install_database/task/add_default_data.php b/phpBB/install/module/install_database/task/add_default_data.php new file mode 100644 index 0000000000..a5c2ffecd1 --- /dev/null +++ b/phpBB/install/module/install_database/task/add_default_data.php @@ -0,0 +1,145 @@ + + * @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\install\module\install_database\task; + +/** + * Create database schema + */ +class add_default_data extends \phpbb\install\task_base +{ + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \phpbb\install\helper\database + */ + protected $database_helper; + + /** + * @var \phpbb\install\helper\config + */ + protected $config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $iohandler; + + /** + * @var \phpbb\language\language + */ + protected $language; + + /** + * Constructor + * + * @param \phpbb\install\helper\database $db_helper Installer's database helper + * @param \phpbb\install\helper\config $config Installer config + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + * @param \phpbb\install\helper\container_factory $container Installer's DI container + * @param \phpbb\language\language $language Language service + */ + public function __construct(\phpbb\install\helper\database $db_helper, + \phpbb\install\helper\config $config, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler, + \phpbb\install\helper\container_factory $container, + \phpbb\language\language $language) + { + $dbms = $db_helper->get_available_dbms($config->get('dbms')); + $dbms = $dbms[$config->get('dbms')]['DRIVER']; + + $this->db = $container->get('dbal.conn'); //new $dbms(); + $this->database_helper = $db_helper; + $this->config = $config; + $this->iohandler = $iohandler; + $this->language = $language; + + parent::__construct(true); + + // Connect to DB + //$this->db->sql_connect($config->get('dbhost'), $config->get('dbuser'), $config->get('dbpasswd'), $config->get('dbname'), $config->get('dbport'), false, false); + } + + /** + * {@inheritdoc} + */ + public function run() + { + $this->db->sql_return_on_error(true); + + $table_prefix = $this->config->get('table_prefix'); + $dbms = $this->config->get('dbms'); + $dbms_info = $this->database_helper->get_available_dbms($dbms); + + // Get schema data from file + $sql_query = @file_get_contents('schemas/schema_data.sql'); + + // Clean up SQL + $sql_query = $this->replace_dbms_specific_sql($sql_query); + $sql_query = preg_replace('# phpbb_([^\s]*) #i', ' ' . $table_prefix . '\1 ', $sql_query); + $sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', array($this, 'lang_replace_callback'), $sql_query); + $sql_query = $this->database_helper->remove_comments($sql_query); + $sql_query = $this->database_helper->split_sql_file($sql_query, $dbms_info[$dbms]['DELIM']); + + foreach ($sql_query as $sql) + { + if (!$this->db->sql_query($sql)) + { + $error = $this->db->sql_error($this->db->get_sql_error_sql()); + $this->iohandler->add_error_message('INST_ERR_DB', $error['message']); + } + } + } + + /** + * Process DB specific SQL + * + * @return string + */ + protected function replace_dbms_specific_sql($query) + { + if ($this->db instanceof \phpbb\db\driver\mssql_base || $this->db instanceof \phpbb\db\driver\mssql) + { + $query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $query); + } + else if ($this->db instanceof \phpbb\db\driver\postgres) + { + $query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $query); + } + else if ($this->db instanceof \phpbb\db\driver\mysql_base) + { + $query = str_replace('\\', '\\\\', $query); + } + + return $query; + } + + /** + * Callback function for language replacing + * + * @param array $matches + * @return string + */ + public function lang_replace_callback($matches) + { + if (!empty($matches[1])) + { + return $this->db->sql_escape($this->language->lang($matches[1])); + } + + return ''; + } +} diff --git a/phpBB/install/module/install_database/task/create_schema.php b/phpBB/install/module/install_database/task/create_schema.php new file mode 100644 index 0000000000..aac710d337 --- /dev/null +++ b/phpBB/install/module/install_database/task/create_schema.php @@ -0,0 +1,198 @@ + + * @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\install\module\install_database\task; + +/** + * Create database schema + */ +class create_schema extends \phpbb\install\task_base +{ + /** + * @var \phpbb\install\helper\config + */ + protected $config; + + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var \phpbb\db\tools\tools_interface + */ + protected $db_tools; + + /** + * @var \phpbb\install\helper\database + */ + protected $database_helper; + + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $iohandler; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param \phpbb\install\helper\config $config Installer's config provider + * @param \phpbb\install\helper\database $db_helper Installer's database helper + * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem service + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + * @param string $phpbb_root_path Path phpBB's root + * @param string $php_ext Extension of PHP files + */ + public function __construct(\phpbb\install\helper\config $config, + \phpbb\install\helper\database $db_helper, + \phpbb\filesystem\filesystem_interface $filesystem, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler, + $phpbb_root_path, + $php_ext) + { + $dbms = $db_helper->get_available_dbms($config->get('dbms')); + $dbms = $dbms[$config->get('dbms')]['DRIVER']; + $factory = new \phpbb\db\tools\factory(); + + $this->db = new $dbms(); + $this->config = $config; + $this->db_tools = $factory->get($this->db); + $this->database_helper = $db_helper; + $this->filesystem = $filesystem; + $this->iohandler = $iohandler; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + + parent::__construct(true); + + // Connect to DB + $this->db->sql_connect($config->get('dbhost'), $config->get('dbuser'), $config->get('dbpasswd'), $config->get('dbname'), $config->get('dbport'), false, false); + } + + /** + * {@inheritdoc} + */ + public function run() + { + $this->db->sql_return_on_error(true); + + $dbms = $this->config->get('dbms'); + $dbms_info = $this->database_helper->get_available_dbms($dbms); + $schema_name = $dbms_info[$dbms]['SCHEMA']; + $delimiter = $dbms_info[$dbms]['DELIM']; + $table_prefix = $this->config->get('table_prefix'); + + if ($dbms === 'mysql') + { + if (version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) + { + $schema_name .= '_41'; + } + else + { + $schema_name .= '_40'; + } + } + + $db_schema_path = $this->phpbb_root_path . 'install/schemas/' . $schema_name . '_schema.sql'; + + // Load database vendor specific code if there is any + if ($this->filesystem->exists($db_schema_path)) + { + $sql_query = @file_get_contents($db_schema_path); + $sql_query = preg_replace('#phpbb_#i', $table_prefix, $sql_query); + $sql_query = $this->database_helper->remove_comments($sql_query); + $sql_query = $this->database_helper->split_sql_file($sql_query, $delimiter); + + foreach ($sql_query as $sql) + { + if (!$this->db->sql_query($sql)) + { + $error = $this->db->sql_error($this->db->get_sql_error_sql()); + $this->iohandler->add_error_message('INST_ERR_DB', $error['message']); + } + } + + unset($sql_query); + } + + $change_prefix = false; + + // Generate database schema + if ($this->filesystem->exists($this->phpbb_root_path . 'install/schemas/schema.json')) + { + $db_table_schema = @file_get_contents($this->phpbb_root_path . 'install/schemas/schema.json'); + $db_table_schema = json_decode($db_table_schema, true); + $change_prefix = true; + } + else + { + global $table_prefix; + + $table_prefix = $this->config->get('table_prefix'); + + if (!defined('CONFIG_TABLE')) + { + // We need to include the constants file for the table constants + // when we generate the schema from the migration files. + include ($this->phpbb_root_path . 'includes/constants.' . $this->php_ext); + } + + $finder = new \phpbb\finder($this->filesystem, $this->phpbb_root_path, null, $this->php_ext); + $migrator_classes = $finder->core_path('phpbb/db/migration/data/')->get_classes(); + $factory = new \phpbb\db\tools\factory(); + $db_tools = $factory->get($this->db, true); + $schema_generator = new \phpbb\db\migration\schema_generator( + $migrator_classes, + new \phpbb\config\config(array()), + $this->db, + $db_tools, + $this->phpbb_root_path, + $this->php_ext, + $table_prefix + ); + $db_table_schema = $schema_generator->get_schema(); + } + + if (!defined('CONFIG_TABLE')) + { + // CONFIG_TABLE is required by sql_create_index() to check the + // length of index names. However table_prefix is not defined + // here yet, so we need to create the constant ourselves. + define('CONFIG_TABLE', $table_prefix . 'config'); + } + + foreach ($db_table_schema as $table_name => $table_data) + { + $this->db_tools->sql_create_table( + ( ($change_prefix) ? ($table_prefix . substr($table_name, 6)) : $table_name ), + $table_data + ); + } + } +} diff --git a/phpBB/install/module/install_filesystem/module.php b/phpBB/install/module/install_filesystem/module.php new file mode 100644 index 0000000000..9562c957fd --- /dev/null +++ b/phpBB/install/module/install_filesystem/module.php @@ -0,0 +1,22 @@ + + * @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\install\module\install_filesystem; + +/** + * Installer module for filesystem installation + */ +class module extends \phpbb\install\module_base +{ + +} diff --git a/phpBB/install/module/install_filesystem/task/create_config_file.php b/phpBB/install/module/install_filesystem/task/create_config_file.php new file mode 100644 index 0000000000..f1191f53d0 --- /dev/null +++ b/phpBB/install/module/install_filesystem/task/create_config_file.php @@ -0,0 +1,219 @@ + + * @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\install\module\install_filesystem\task; + +use phpbb\install\exception\user_interaction_required_exception; + +/** + * Dumps config file + */ +class create_config_file extends \phpbb\install\task_base +{ + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** + * @var \phpbb\install\helper\database + */ + protected $db_helper; + + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $iohandler; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param \phpbb\filesystem\filesystem_interface $filesystem + * @param \phpbb\install\helper\config $install_config + * @param \phpbb\install\helper\database $db_helper + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler + * @param string $phpbb_root_path + * @param string $php_ext + */ + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, + \phpbb\install\helper\config $install_config, + \phpbb\install\helper\database $db_helper, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler, + $phpbb_root_path, + $php_ext) + { + $this->install_config = $install_config; + $this->db_helper = $db_helper; + $this->filesystem = $filesystem; + $this->iohandler = $iohandler; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + $config_written = true; + + // Create config.php + $path_to_config = $this->phpbb_root_path . 'config.' . $this->php_ext; + + $fp = @fopen($path_to_config, 'w'); + if (!$fp) + { + $config_written = false; + } + + $config_content = $this->get_config_data(); + + if (!@fwrite($fp, $config_content)) + { + $config_written = false; + } + + @fclose($fp); + + // chmod config.php to be only readable + if ($config_written) + { + try + { + $this->filesystem->phpbb_chmod($path_to_config, \phpbb\filesystem\filesystem_interface::CHMOD_READ); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing, the user will get a notice later + } + } + else + { + $this->iohandler->add_error_message('UNABLE_TO_WRITE_CONFIG_FILE'); + $this->iohandler->send_response(); + throw new user_interaction_required_exception(); + } + + // Create a lock file to indicate that there is an install in progress + $fp = @fopen($this->phpbb_root_path . 'cache/install_lock', 'wb'); + if ($fp === false) + { + // We were unable to create the lock file - abort + $this->iohandler->add_error_message('UNABLE_TO_WRITE_LOCK'); + $this->iohandler->send_response(); + throw new user_interaction_required_exception(); + } + @fclose($fp); + + try + { + $this->filesystem->phpbb_chmod($this->phpbb_root_path . 'cache/install_lock', 0777); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing, the user will get a notice later + } + } + + /** + * Returns the content which should be dumped to config.php + * + * @param bool $debug If the debug constants should be enabled by default or not + * @param bool $debug_container If the container should be compiled on + * every page load or not + * @param bool $debug_test If the DEBUG_TEST constant should be added + * NOTE: Only for use within the testing framework + * + * @return string content to be written to the config file + */ + protected function get_config_data($debug = false, $debug_container = false, $debug_test = false) + { + $config_content = "install_config->get('dbms'); + $db_driver = $this->db_helper->get_available_dbms($dbms); + $db_driver = $db_driver[$dbms]['DRIVER']; + + $config_data_array = array( + 'dbms' => $db_driver, + 'dbhost' => $this->install_config->get('dbhost'), + 'dbport' => $this->install_config->get('dbport'), + 'dbname' => $this->install_config->get('dbname'), + 'dbuser' => $this->install_config->get('dbuser'), + 'dbpasswd' => $this->install_config->get('dbpasswd'), + 'table_prefix' => $this->install_config->get('table_prefix'), + + 'phpbb_adm_relative_path' => 'adm/', + + 'acm_type' => 'phpbb\cache\driver\file', + ); + + foreach ($config_data_array as $key => $value) + { + $config_content .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n"; + } + + $config_content .= "\n@define('PHPBB_INSTALLED', true);\n"; + $config_content .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n"; + + if ($debug_test) + { + $config_content .= "@define('PHPBB_ENVIRONMENT', 'test');\n"; + } + else if ($debug) + { + $config_content .= "@define('PHPBB_ENVIRONMENT', 'development');\n"; + } + else + { + $config_content .= "@define('PHPBB_ENVIRONMENT', 'production');\n"; + } + + if ($debug_container) + { + $config_content .= "@define('DEBUG_CONTAINER', true);\n"; + } + else + { + $config_content .= "// @define('DEBUG_CONTAINER', true);\n"; + } + + if ($debug_test) + { + $config_content .= "@define('DEBUG_TEST', true);\n"; + + // Mandatory for the functional tests, will be removed by PHPBB3-12623 + $config_content .= "@define('DEBUG', true);\n"; + } + + return $config_content; + } +} diff --git a/phpBB/install/module/install_finish/module.php b/phpBB/install/module/install_finish/module.php new file mode 100644 index 0000000000..98c99d7cff --- /dev/null +++ b/phpBB/install/module/install_finish/module.php @@ -0,0 +1,22 @@ + + * @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\install\module\install_finish; + +/** + * Installer module for filesystem installation + */ +class module extends \phpbb\install\module_base +{ + +} diff --git a/phpBB/install/module/install_finish/task/notify_user.php b/phpBB/install/module/install_finish/task/notify_user.php new file mode 100644 index 0000000000..d95303fcb5 --- /dev/null +++ b/phpBB/install/module/install_finish/task/notify_user.php @@ -0,0 +1,113 @@ + + * @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\install\module\install_finish\task; + +/** + * Logs installation and sends an email to the admin + */ +class notify_user extends \phpbb\install\task_base +{ + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $iohandler; + + /** + * @var \phpbb\auth\auth + */ + protected $auth; + + /** + * @var \phpbb\config\db + */ + protected $config; + + /** + * @var \phpbb\log\log_interface + */ + protected $log; + + /** + * @var \phpbb\user + */ + protected $user; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param \phpbb\install\helper\container_factory $container + * @param \phpbb\install\helper\config $install_config + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler + * @param string $phpbb_root_path + * @param string $php_ext + */ + public function __construct(\phpbb\install\helper\container_factory $container, \phpbb\install\helper\config $install_config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler, $phpbb_root_path, $php_ext) + { + $this->install_config = $install_config; + $this->iohandler = $iohandler; + + $this->auth = $container->get('auth'); + $this->config = $container->get('config'); + $this->log = $container->get('log'); + $this->user = $container->get('user'); + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + } + + /** + * {@inheritdoc} + */ + public function run() + { + // @todo + //$this->user->setup('common'); + + //$this->user->session_begin(); + //$this->auth->login($this->install_config->get('admin_name'), $this->install_config->get('admin_pass1'), false, true, true); + + if ($this->config['email_enable']) + { + include ($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); + + $messenger = new \messenger(false); + $messenger->template('installed', $this->install_config->get('language')); + $messenger->to($this->config['board_email'], $this->install_config->get('admin_name')); + $messenger->anti_abuse_headers($this->config, $this->user); + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($this->install_config->get('admin_name')), + 'PASSWORD' => htmlspecialchars_decode($this->install_config->get('admin_pass1'))) + ); + $messenger->send(NOTIFY_EMAIL); + } + + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_INSTALL_INSTALLED', false, array($this->config['version'])); + + @unlink($this->phpbb_root_path . 'cache/install_lock'); + } +} diff --git a/phpBB/install/module/install_finish/task/populate_migrations.php b/phpBB/install/module/install_finish/task/populate_migrations.php new file mode 100644 index 0000000000..4f701b84ca --- /dev/null +++ b/phpBB/install/module/install_finish/task/populate_migrations.php @@ -0,0 +1,54 @@ + + * @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\install\module\install_finish\task; + +/** + * Populates migrations + */ +class populate_migrations extends \phpbb\install\task_base +{ + /** + * @var \phpbb\extension\manager + */ + protected $extension_manager; + + /** + * @var \phpbb\db\migrator + */ + protected $migrator; + + /** + * Constructor + * + * @param \phpbb\install\helper\container_factory $container phpBB's DI contianer + */ + public function __construct(\phpbb\install\helper\container_factory $container) + { + $this->extension_manager = $container->get('ext.manager'); + $this->migrator = $container->get('migrator'); + } + + /** + * {@inheritdoc} + */ + public function run() + { + $finder = $this->extension_manager->get_finder(); + + $migrations = $finder + ->core_path('phpbb/db/migration/data/') + ->get_classes(); + $this->migrator->populate_migrations($migrations); + } +} diff --git a/phpBB/install/module/obtain_data/module.php b/phpBB/install/module/obtain_data/module.php new file mode 100644 index 0000000000..9a3307cd6f --- /dev/null +++ b/phpBB/install/module/obtain_data/module.php @@ -0,0 +1,63 @@ + + * @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\install\module\obtain_data; + +class module extends \phpbb\install\module_base +{ + /** + * {@inheritdoc} + */ + public function run() + { + // Recover install progress + $task_index = $this->recover_progress(); + + // Run until there are available resources + while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0) + { + // Check if task exists + if (!isset($this->task_collection[$task_index])) + { + break; + } + + // Recover task to be executed + /** @var \phpbb\install\task_interface $task */ + $task = $this->container->get($this->task_collection[$task_index]); + + // Iterate to the next task + $task_index++; + + // Check if we can run the task + if (!$task->is_essential() && !$task->check_requirements()) + { + continue; + } + + $task->run(); + + // Log install progress + $current_task_index = $task_index - 1; + $this->install_config->set_finished_task($this->task_collection[$current_task_index], $current_task_index); + } + } + + /** + * {@inheritdoc} + */ + public function get_task_count() + { + return 0; + } +} diff --git a/phpBB/install/module/obtain_data/task/obtain_admin_data.php b/phpBB/install/module/obtain_data/task/obtain_admin_data.php new file mode 100644 index 0000000000..d820353880 --- /dev/null +++ b/phpBB/install/module/obtain_data/task/obtain_admin_data.php @@ -0,0 +1,207 @@ + + * @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\install\module\obtain_data\task; + +use phpbb\install\exception\user_interaction_required_exception; + +/** + * This class requests and validates admin account data from the user + */ +class obtain_admin_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $io_handler; + + /** + * Constructor + * + * @param \phpbb\install\helper\config $install_config Installer's config helper + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + */ + public function __construct(\phpbb\install\helper\config $install_config, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler) + { + $this->install_config = $install_config; + $this->io_handler = $iohandler; + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + // Check if data is sent + if ($this->io_handler->get_input('submit_admin', false)) + { + $this->process_form(); + } + else + { + $this->request_form_data(); + } + } + + /** + * Process form data + * + * @return null + */ + protected function process_form() + { + // Admin data + $admin_name = $this->io_handler->get_input('admin_name', '', true); + $admin_pass1 = $this->io_handler->get_input('admin_pass1', '', true); + $admin_pass2 = $this->io_handler->get_input('admin_pass2', '', true); + $board_email = $this->io_handler->get_input('board_email', ''); + + $admin_data_valid = $this->check_admin_data($admin_name, $admin_pass1, $admin_pass2, $board_email); + + if ($admin_data_valid) + { + $this->install_config->set('admin_name', $admin_name); + $this->install_config->set('admin_passwd', $admin_pass1); + $this->install_config->set('board_email', $board_email); + } + else + { + $this->request_form_data(true); + } + } + + /** + * Request data from the user + * + * @param bool $use_request_data Whether to use submited data + * + * @return null + * + * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data + */ + protected function request_form_data($use_request_data = false) + { + if ($use_request_data) + { + $admin_username = $this->io_handler->get_input('admin_name', '', true); + $admin_email = $this->io_handler->get_input('board_email', '', true); + } + else + { + $admin_username = ''; + $admin_email = ''; + } + + $admin_form = array( + 'admin_name' => array( + 'label' => 'ADMIN_USERNAME', + 'description' => 'ADMIN_USERNAME_EXPLAIN', + 'type' => 'text', + 'default' => $admin_username, + ), + 'board_email' => array( + 'label' => 'CONTACT_EMAIL', + 'type' => 'email', + 'default' => $admin_email, + ), + 'admin_pass1' => array( + 'label' => 'ADMIN_PASSWORD', + 'description' => 'ADMIN_PASSWORD_EXPLAIN', + 'type' => 'password', + ), + 'admin_pass2' => array( + 'label' => 'ADMIN_PASSWORD_CONFIRM', + 'type' => 'password', + ), + 'submit_admin' => array( + 'label' => 'SUBMIT', + 'type' => 'submit', + ), + ); + + $this->io_handler->add_user_form_group('ADMIN_CONFIG', $admin_form); + + // Require user interaction + $this->io_handler->send_response(); + throw new user_interaction_required_exception(); + } + + /** + * Check admin data + * + * @param string $username Admin username + * @param string $pass1 Admin password + * @param string $pass2 Admin password confirmation + * @param string $email Admin e-mail address + * + * @return bool True if data is valid, false otherwise + */ + protected function check_admin_data($username, $pass1, $pass2, $email) + { + $data_valid = true; + + // Check if none of admin data is empty + if (in_array('', array($username, $pass1, $pass2, $email))) + { + $this->io_handler->add_error_message('INST_ERR_MISSING_DATA'); + $data_valid = false; + } + + if (utf8_strlen($username) < 3) + { + $this->io_handler->add_error_message('INST_ERR_USER_TOO_SHORT'); + $data_valid = false; + } + + if (utf8_strlen($username) > 20) + { + $this->io_handler->add_error_message('INST_ERR_USER_TOO_LONG'); + $data_valid = false; + } + + if ($pass1 !== $pass2 && $pass1 !== '') + { + $this->io_handler->add_error_message('INST_ERR_PASSWORD_MISMATCH'); + $data_valid = false; + } + + // Test against the default password rules + if (utf8_strlen($pass1) < 6) + { + $this->io_handler->add_error_message('INST_ERR_PASSWORD_TOO_SHORT'); + $data_valid = false; + } + + if (utf8_strlen($pass1) > 30) + { + $this->io_handler->add_error_message('INST_ERR_PASSWORD_TOO_LONG'); + $data_valid = false; + } + + if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email)) + { + $this->io_handler->add_error_message('INST_ERR_EMAIL_INVALID'); + $data_valid = false; + } + + return $data_valid; + } +} diff --git a/phpBB/install/module/obtain_data/task/obtain_board_data.php b/phpBB/install/module/obtain_data/task/obtain_board_data.php new file mode 100644 index 0000000000..e17ecd01c5 --- /dev/null +++ b/phpBB/install/module/obtain_data/task/obtain_board_data.php @@ -0,0 +1,172 @@ + + * @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\install\module\obtain_data\task; + +use phpbb\install\exception\user_interaction_required_exception; + +/** + * This class obtains default data from the user related to board (Board name, Board descritpion, etc...) + */ +class obtain_board_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $io_handler; + + /** + * @var \phpbb\language\language_file_helper + */ + protected $language_helper; + + /** + * Constructor + * + * @param \phpbb\install\helper\config $config Installer's config + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + * @param \phpbb\language\language_file_helper $lang_helper Language file helper + */ + public function __construct(\phpbb\install\helper\config $config, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler, + \phpbb\language\language_file_helper $lang_helper) + { + $this->install_config = $config; + $this->io_handler = $iohandler; + $this->language_helper = $lang_helper; + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + // Check if data is sent + if ($this->io_handler->get_input('submit_board', false)) + { + $this->process_form(); + } + else + { + $this->request_form_data(); + } + } + + /** + * Process form data + * + * @return null + */ + protected function process_form() + { + // Board data + $default_lang = $this->io_handler->get_input('default_lang', ''); + $board_name = $this->io_handler->get_input('board_name', ''); + $board_desc = $this->io_handler->get_input('board_description', ''); + + // Check default lang + $langs = $this->language_helper->get_available_languages(); + $lang_valid = false; + + foreach ($langs as $lang) + { + if ($lang['iso'] === $default_lang) + { + $lang_valid = true; + break; + } + } + + $this->install_config->set('board_name', $board_name); + $this->install_config->set('board_description', $board_desc); + + if ($lang_valid) + { + $this->install_config->set('default_lang', $default_lang); + } + else + { + $this->request_form_data(true); + } + } + + /** + * Request data from the user + * + * @param bool $use_request_data Whether to use submited data + * + * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data + */ + protected function request_form_data($use_request_data = false) + { + if ($use_request_data) + { + $board_name = $this->io_handler->get_input('board_name', ''); + $board_desc = $this->io_handler->get_input('board_description', ''); + } + else + { + $board_name = '{L_CONFIG_SITENAME}'; + $board_desc = '{L_CONFIG_SITE_DESC}'; + } + + // Use language because we only check this to be valid + $default_lang = $this->install_config->get('language', ''); + + $langs = $this->language_helper->get_available_languages(); + $lang_options = array(); + + foreach ($langs as $lang) + { + $lang_options[] = array( + 'value' => $lang['iso'], + 'label' => $lang['local_name'], + 'selected' => ($default_lang === $lang['iso']), + ); + } + + $board_form = array( + 'default_lang' => array( + 'label' => 'DEFAULT_LANGUAGE', + 'type' => 'select', + 'options' => $lang_options, + ), + 'board_name' => array( + 'label' => 'BOARD_NAME', + 'type' => 'text', + 'default' => $board_name, + ), + 'board_description' => array( + 'label' => 'BOARD_DESCRIPTION', + 'type' => 'text', + 'default' => $board_desc, + ), + 'submit_board' => array( + 'label' => 'SUBMIT', + 'type' => 'submit', + ), + ); + + $this->io_handler->add_user_form_group('BOARD_CONFIG', $board_form); + + $this->io_handler->send_response(); + throw new user_interaction_required_exception; + } +} diff --git a/phpBB/install/module/obtain_data/task/obtain_database_data.php b/phpBB/install/module/obtain_data/task/obtain_database_data.php new file mode 100644 index 0000000000..4c71c4adea --- /dev/null +++ b/phpBB/install/module/obtain_data/task/obtain_database_data.php @@ -0,0 +1,259 @@ + + * @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\install\module\obtain_data\task; + +use phpbb\install\exception\user_interaction_required_exception; + +/** + * This class requests and validates database information from the user + */ +class obtain_database_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ + /** + * @var \phpbb\install\helper\database + */ + protected $database_helper; + + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $io_handler; + + /** + * Constructor + * + * @param \phpbb\install\helper\database $database_helper Installer's database helper + * @param \phpbb\install\helper\config $install_config Installer's config helper + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + */ + public function __construct(\phpbb\install\helper\database $database_helper, + \phpbb\install\helper\config $install_config, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler) + { + $this->database_helper = $database_helper; + $this->install_config = $install_config; + $this->io_handler = $iohandler; + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + // Check if data is sent + if ($this->io_handler->get_input('submit_database', false)) + { + $this->process_form(); + } + else + { + $this->request_form_data(); + } + } + + /** + * Process form data + * + * @return null + */ + protected function process_form() + { + // Collect database data + $dbms = $this->io_handler->get_input('dbms', ''); + $dbhost = $this->io_handler->get_input('dbhost', ''); + $dbport = $this->io_handler->get_input('dbport', ''); + $dbuser = $this->io_handler->get_input('dbuser', ''); + $dbpasswd = $this->io_handler->get_input('dbpasswd', '', true); + $dbname = $this->io_handler->get_input('dbname', ''); + $table_prefix = $this->io_handler->get_input('table_prefix', ''); + + // Check database data + $user_data_vaild = $this->check_database_data($dbms, $dbhost, $dbport, $dbuser, $dbpasswd, $dbname, $table_prefix); + + // Save database data if it is correct + if ($user_data_vaild) + { + $this->install_config->set('dbms', $dbms); + $this->install_config->set('dbhost', $dbhost); + $this->install_config->set('dbport', $dbport); + $this->install_config->set('dbuser', $dbuser); + $this->install_config->set('dbpasswd', $dbpasswd); + $this->install_config->set('dbname', $dbname); + $this->install_config->set('table_prefix', $table_prefix); + } + else + { + $this->request_form_data(true); + } + } + + /** + * Request data from the user + * + * @param bool $use_request_data Whether to use submited data + * + * @return null + * + * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data + */ + protected function request_form_data($use_request_data = false) + { + if ($use_request_data) + { + $dbms = $this->io_handler->get_input('dbms', ''); + $dbhost = $this->io_handler->get_input('dbhost', ''); + $dbport = $this->io_handler->get_input('dbport', ''); + $dbuser = $this->io_handler->get_input('dbuser', ''); + $dbname = $this->io_handler->get_input('dbname', ''); + $table_prefix = $this->io_handler->get_input('table_prefix', 'phpbb_'); + } + else + { + $dbms = ''; + $dbhost = ''; + $dbport = ''; + $dbuser = ''; + $dbname = ''; + $table_prefix = 'phpbb_'; + } + + $dbms_select = array(); + foreach ($this->database_helper->get_available_dbms() as $dbms_key => $dbms_array) + { + $dbms_select[] = array( + 'value' => $dbms_key, + 'label' => 'DB_OPTION_' . strtoupper($dbms_key), + 'selected' => ($dbms_key === $dbms), + ); + } + + $database_form = array( + 'dbms' => array( + 'label' => 'DBMS', + 'type' => 'select', + 'options' => $dbms_select, + ), + 'dbhost' => array( + 'label' => 'DB_HOST', + 'description' => 'DB_HOST_EXPLAIN', + 'type' => 'text', + 'default' => $dbhost, + ), + 'dbport' => array( + 'label' => 'DB_PORT', + 'description' => 'DB_PORT_EXPLAIN', + 'type' => 'text', + 'default' => $dbport, + ), + 'dbuser' => array( + 'label' => 'DB_USERNAME', + 'type' => 'text', + 'default' => $dbuser, + ), + 'dbpasswd' => array( + 'label' => 'DB_PASSWORD', + 'type' => 'password', + ), + 'dbname' => array( + 'label' => 'DB_NAME', + 'type' => 'text', + 'default' => $dbname, + ), + 'table_prefix' => array( + 'label' => 'TABLE_PREFIX', + 'description' => 'TABLE_PREFIX_EXPLAIN', + 'type' => 'text', + 'default' => $table_prefix, + ), + 'submit_database' => array( + 'label' => 'SUBMIT', + 'type' => 'submit', + ), + ); + + $this->io_handler->add_user_form_group('DB_CONFIG', $database_form); + + // Require user interaction + $this->io_handler->send_response(); + throw new user_interaction_required_exception(); + } + + /** + * Check database data + * + * @param string $dbms Selected database type + * @param string $dbhost Database host address + * @param int $dbport Database port number + * @param string $dbuser Database username + * @param string $dbpass Database password + * @param string $dbname Database name + * @param string $table_prefix Database table prefix + * + * @return bool True if database data is correct, false otherwise + */ + protected function check_database_data($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix) + { + $available_dbms = $this->database_helper->get_available_dbms(); + $data_valid = true; + + // Check if PHP has the database extensions for the specified DBMS + if (!isset($available_dbms[$dbms])) + { + $this->io_handler->add_error_message('INST_ERR_NO_DB'); + $data_valid = false; + } + + // Validate table prefix + $prefix_valid = $this->database_helper->validate_table_prefix($dbms, $table_prefix); + if (is_array($prefix_valid)) + { + foreach ($prefix_valid as $error) + { + $this->io_handler->add_error_message( + $error['title'], + (isset($error['description'])) ? $error['description'] : false + ); + } + + $data_valid = false; + } + + // Try to connect to database if all provided data is valid + if ($data_valid) + { + $connect_test = $this->database_helper->check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix); + if (is_array($connect_test)) + { + foreach ($prefix_valid as $error) + { + $this->io_handler->add_error_message( + $error['title'], + (isset($error['description'])) ? $error['description'] : false + ); + } + + $data_valid = false; + } + } + + return $data_valid; + } +} diff --git a/phpBB/install/module/obtain_data/task/obtain_email_data.php b/phpBB/install/module/obtain_data/task/obtain_email_data.php new file mode 100644 index 0000000000..fbcef0a5c6 --- /dev/null +++ b/phpBB/install/module/obtain_data/task/obtain_email_data.php @@ -0,0 +1,151 @@ + + * @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\install\module\obtain_data\task; + +use phpbb\install\exception\user_interaction_required_exception; + +class obtain_email_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $io_handler; + + /** + * Constructor + * + * @param \phpbb\install\helper\config $config Installer's config + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + */ + public function __construct(\phpbb\install\helper\config $config, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler) + { + $this->install_config = $config; + $this->io_handler = $iohandler; + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + // E-mail data + $email_enable = $this->io_handler->get_input('email_enable', true); + $smtp_delivery = $this->io_handler->get_input('smtp_delivery', ''); + $smtp_host = $this->io_handler->get_input('smtp_host', ''); + $smtp_auth = $this->io_handler->get_input('smtp_auth', ''); + $smtp_user = $this->io_handler->get_input('smtp_user', ''); + $smtp_passwd = $this->io_handler->get_input('smtp_pass', ''); + + $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP'); + + // Check if data is sent + if ($this->io_handler->get_input('submit_email', false)) + { + $this->install_config->set('email_enable', $email_enable); + $this->install_config->set('smtp_delivery', $smtp_delivery); + $this->install_config->set('smtp_host', $smtp_host); + $this->install_config->set('smtp_auth', $smtp_auth); + $this->install_config->set('smtp_user', $smtp_user); + $this->install_config->set('smtp_pass', $smtp_passwd); + } + else + { + $auth_options = array(); + foreach ($auth_methods as $method) + { + $auth_options[] = array( + 'value' => $method, + 'label' => 'SMTP_' . str_replace('-', '_', $method), + 'selected' => false, + ); + } + + $email_form = array( + 'email_enable' => array( + 'label' => 'ENABLE_EMAIL', + 'description' => 'COOKIE_SECURE_EXPLAIN', + 'type' => 'radio', + 'options' => array( + array( + 'value' => 1, + 'label' => 'ENABLE', + 'selected' => true, + ), + array( + 'value' => 0, + 'label' => 'DISABLE', + 'selected' => false, + ), + ), + ), + 'smtp_delivery' => array( + 'label' => 'USE_SMTP', + 'description' => 'USE_SMTP_EXPLAIN', + 'type' => 'radio', + 'options' => array( + array( + 'value' => 0, + 'label' => 'NO', + 'selected' => true, + ), + array( + 'value' => 1, + 'label' => 'YES', + 'selected' => false, + ), + ), + ), + 'smtp_host' => array( + 'label' => 'SMTP_SERVER', + 'description' => 'SMTP_SERVER_EXPLAIN', + 'type' => 'text', + 'default' => $smtp_host, + ), + 'smtp_auth' => array( + 'label' => 'SMTP_AUTH_METHOD', + 'type' => 'select', + 'options' => $auth_options, + ), + 'smtp_user' => array( + 'label' => 'SMTP_USERNAME', + 'description' => 'SMTP_USERNAME_EXPLAIN', + 'type' => 'text', + 'default' => $smtp_user, + ), + 'smtp_pass' => array( + 'label' => 'SMTP_PASSWORD', + 'description' => 'SMTP_PASSWORD_EXPLAIN', + 'type' => 'password', + ), + 'submit_email' => array( + 'label' => 'SUBMIT', + 'type' => 'submit', + ), + ); + + $this->io_handler->add_user_form_group('EMAIL_CONFIG', $email_form); + + $this->io_handler->send_response(); + throw new user_interaction_required_exception(); + } + } +} diff --git a/phpBB/install/module/obtain_data/task/obtain_imagick_path.php b/phpBB/install/module/obtain_data/task/obtain_imagick_path.php new file mode 100644 index 0000000000..86af586e37 --- /dev/null +++ b/phpBB/install/module/obtain_data/task/obtain_imagick_path.php @@ -0,0 +1,73 @@ + + * @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\install\module\obtain_data\task; + +class obtain_imagick_path extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ + /** + * @var \phpbb\install\helper\config + */ + protected $config; + + /** + * Constructor + * + * @param \phpbb\install\helper\config $config Installer's config + */ + public function __construct(\phpbb\install\helper\config $config) + { + $this->config = $config; + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + // Can we find Imagemagick anywhere on the system? + $exe = (DIRECTORY_SEPARATOR == '\\') ? '.exe' : ''; + + $magic_home = getenv('MAGICK_HOME'); + $img_imagick = ''; + if (empty($magic_home)) + { + $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/'); + $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH')))); + + $locations = array_merge($path_locations, $locations); + foreach ($locations as $location) + { + // The path might not end properly, fudge it + if (substr($location, -1, 1) !== '/') + { + $location .= '/'; + } + + if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) + { + $img_imagick = str_replace('\\', '/', $location); + continue; + } + } + } + else + { + $img_imagick = str_replace('\\', '/', $magic_home); + } + + $this->config->set('img_imagick', $img_imagick); + } +} diff --git a/phpBB/install/module/obtain_data/task/obtain_server_data.php b/phpBB/install/module/obtain_data/task/obtain_server_data.php new file mode 100644 index 0000000000..39606f6281 --- /dev/null +++ b/phpBB/install/module/obtain_data/task/obtain_server_data.php @@ -0,0 +1,187 @@ + + * @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\install\module\obtain_data\task; + +use phpbb\install\exception\user_interaction_required_exception; + +/** + * This class requests and saves some information about the server + */ +class obtain_server_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ + /** + * @var \phpbb\install\helper\config + */ + protected $install_config; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $io_handler; + + /** + * Constructor + * + * @param \phpbb\install\helper\config $config Installer's config + * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler + */ + public function __construct(\phpbb\install\helper\config $config, + \phpbb\install\helper\iohandler\iohandler_interface $iohandler) + { + $this->install_config = $config; + $this->io_handler = $iohandler; + + parent::__construct(true); + } + /** + * {@inheritdoc} + */ + public function run() + { + $cookie_secure = $this->io_handler->is_secure(); + $server_protocol = ($this->io_handler->is_secure()) ? 'https://' : 'http://'; + $server_port = $this->io_handler->get_server_variable('SERVER_PORT', 0); + + // HTTP_HOST is having the correct browser url in most cases... + $server_name = strtolower(htmlspecialchars_decode($this->io_handler->get_header_variable( + 'Host', + $this->io_handler->get_server_variable('SERVER_NAME') + ))); + + // HTTP HOST can carry a port number... + if (strpos($server_name, ':') !== false) + { + $server_name = substr($server_name, 0, strpos($server_name, ':')); + } + + $script_path = htmlspecialchars_decode($this->io_handler->get_server_variable('PHP_SELF')); + + if (!$script_path) + { + $script_path = htmlspecialchars_decode($this->io_handler->get_server_variable('REQUEST_URI')); + } + + $script_path = str_replace(array('\\', '//'), '/', $script_path); + $script_path = trim(dirname(dirname($script_path))); + + // Server data + $cookie_secure = $this->io_handler->get_input('cookie_secure', $cookie_secure); + $server_protocol = $this->io_handler->get_input('server_protocol', $server_protocol); + $force_server_vars = $this->io_handler->get_input('force_server_vars', 0); + $server_name = $this->io_handler->get_input('server_name', $server_name); + $server_port = $this->io_handler->get_input('server_port', $server_port); + $script_path = $this->io_handler->get_input('script_path', $script_path); + + // Clean up script path + if ($script_path !== '/') + { + // Adjust destination path (no trailing slash) + if (substr($script_path, -1) === '/') + { + $script_path = substr($script_path, 0, -1); + } + + $script_path = str_replace(array('../', './'), '', $script_path); + + if ($script_path[0] !== '/') + { + $script_path = '/' . $script_path; + } + } + + // Check if data is sent + if ($this->io_handler->get_input('submit_server', false)) + { + $this->install_config->set('cookie_secure', $cookie_secure); + $this->install_config->set('server_protocol', $server_protocol); + $this->install_config->set('force_server_vars', $force_server_vars); + $this->install_config->set('server_name', $server_name); + $this->install_config->set('server_port', $server_port); + $this->install_config->set('script_path', $script_path); + } + else + { + // Render form + $server_form = array( + 'cookie_secure' => array( + 'label' => 'COOKIE_SECURE', + 'description' => 'COOKIE_SECURE_EXPLAIN', + 'type' => 'radio', + 'options' => array( + array( + 'value' => 0, + 'label' => 'NO', + 'selected' => (!$cookie_secure), + ), + array( + 'value' => 1, + 'label' => 'YES', + 'selected' => ($cookie_secure), + ), + ), + ), + 'force_server_vars' => array( + 'label' => 'FORCE_SERVER_VARS', + 'description' => 'FORCE_SERVER_VARS_EXPLAIN', + 'type' => 'radio', + 'options' => array( + array( + 'value' => 0, + 'label' => 'NO', + 'selected' => true, + ), + array( + 'value' => 1, + 'label' => 'YES', + 'selected' => false, + ), + ), + ), + 'server_protocol' => array( + 'label' => 'SERVER_PROTOCOL', + 'description' => 'SERVER_PROTOCOL_EXPLAIN', + 'type' => 'text', + 'default' => $server_protocol, + ), + 'server_name' => array( + 'label' => 'SERVER_NAME', + 'description' => 'SERVER_NAME_EXPLAIN', + 'type' => 'text', + 'default' => $server_name, + ), + 'server_port' => array( + 'label' => 'SERVER_PORT', + 'description' => 'SERVER_PORT_EXPLAIN', + 'type' => 'text', + 'default' => $server_port, + ), + 'script_path' => array( + 'label' => 'SCRIPT_PATH', + 'description' => 'SCRIPT_PATH_EXPLAIN', + 'type' => 'text', + 'default' => $script_path, + ), + 'submit_server' => array( + 'label' => 'SUBMIT', + 'type' => 'submit', + ) + ); + + $this->io_handler->add_user_form_group('SERVER_CONFIG', $server_form); + + $this->io_handler->send_response(); + throw new user_interaction_required_exception(); + } + } +} diff --git a/phpBB/install/module/requirements/module.php b/phpBB/install/module/requirements/module.php new file mode 100644 index 0000000000..aae8c75cbe --- /dev/null +++ b/phpBB/install/module/requirements/module.php @@ -0,0 +1,73 @@ + + * @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\install\module\requirements; + +use phpbb\install\exception\user_interaction_required_exception; + +class module extends \phpbb\install\module_base +{ + public function run() + { + $tests_passed = true; + + // Recover install progress + $task_index = 0; + + // Run until there are available resources + while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0) + { + // Check if task exists + if (!isset($this->task_collection[$task_index])) + { + break; + } + + // Recover task to be executed + /** @var \phpbb\install\task_interface $task */ + $task = $this->container->get($this->task_collection[$task_index]); + + // Iterate to the next task + $task_index++; + + // Check if we can run the task + if (!$task->is_essential() && !$task->check_requirements()) + { + continue; + } + + $test_result = $task->run(); + $tests_passed = ($tests_passed) ? $test_result : false; + } + + // Check if tests have failed + if (!$tests_passed) + { + // If requirements are not met, exit form installer + $this->iohandler->send_response(); + throw new user_interaction_required_exception(); + } + + // Log install progress + $current_task_index = $task_index - 1; + $this->install_config->set_finished_task($this->task_collection[$current_task_index], $current_task_index); + } + + /** + * {@inheritdoc} + */ + public function get_task_count() + { + return 0; + } +} diff --git a/phpBB/install/module/requirements/task/check_filesystem.php b/phpBB/install/module/requirements/task/check_filesystem.php new file mode 100644 index 0000000000..0314a988f1 --- /dev/null +++ b/phpBB/install/module/requirements/task/check_filesystem.php @@ -0,0 +1,258 @@ + + * @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\install\module\requirements\task; + +/** + * Checks filesystem requirements + */ +class check_filesystem extends \phpbb\install\task_base +{ + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** + * @var array + */ + protected $files_to_check; + + /** + * @var bool + */ + protected $tests_passed; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $response; + + /** + * Constructor + * + * @param \phpbb\filesystem\filesystem_interface $filesystem filesystem handler + * @parma \phpbb\install\helper\iohandler\iohandler_interface $response response helper + * @param string $phpbb_root_path relative path to phpBB's root + * @param string $php_ext extension of php files + */ + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, + \phpbb\install\helper\iohandler\iohandler_interface $response, + $phpbb_root_path, + $php_ext) + { + parent::__construct(true); + + $this->filesystem = $filesystem; + $this->response = $response; + $this->phpbb_root_path = $phpbb_root_path; + + $this->tests_passed = false; + + // Files/Directories to check + // All file/directory names must be relative to phpBB's root path + $this->files_to_check = array( + array( + 'path' => 'cache/', + 'failable' => false, + 'is_file' => false, + ), + array( + 'path' => 'store/', + 'failable' => false, + 'is_file' => false, + ), + array( + 'path' => 'files/', + 'failable' => false, + 'is_file' => false, + ), + array( + 'path' => 'images/avatars/upload/', + 'failable' => true, + 'is_file' => false, + ), + array( + 'path' => "config.$php_ext", + 'failable' => false, + 'is_file' => true, + ), + ); + } + + /** + * {@inheritdoc} + */ + public function run() + { + $this->tests_passed = true; + + // Check files/directories to be writable + foreach ($this->files_to_check as $file) + { + if ($file['is_file']) + { + $this->check_file($file['path'], $file['failable']); + } + else + { + $this->check_dir($file['path'], $file['failable']); + } + } + + return $this->tests_passed; + } + + /** + * Sets $this->tests_passed + * + * @param bool $is_passed + * @return null + */ + protected function set_test_passed($is_passed) + { + // If one test failed, tests_passed should be false + $this->tests_passed = (!$this->tests_passed) ? false : $is_passed; + } + + /** + * Check if a file is readable and writable + * + * @param string $file Filename + * @param bool $failable Whether failing test should interrupt installation process + */ + protected function check_file($file, $failable = false) + { + $path = $this->phpbb_root_path . $file; + $exists = $writable = true; + + // Try to create file if it does not exists + if (!file_exists($path)) + { + $fp = @fopen($path, 'w'); + @fclose($fp); + try + { + $this->filesystem->phpbb_chmod($path, + \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE + ); + $exists = true; + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + } + + if (file_exists($path)) + { + if (!$this->filesystem->is_writable($path)) + { + $writable = false; + } + } + else + { + $exists = $writable = false; + } + + $this->set_test_passed(($exists && $writable) || $failable); + + if (!($exists && $writable)) + { + $title = ($exists) ? 'FILE_NOT_WRITABLE' : 'FILE_NOT_EXISTS'; + $description = array($title . '_EXPLAIN', $file); + + if ($failable) + { + $this->response->add_warning_message($title, $description); + } + else + { + $this->response->add_error_message($title, $description); + } + } + } + + /** + * Check if a directory is readable and writable + * + * @param string $dir Filename + * @param bool $failable Whether failing test should abort the installation process + */ + protected function check_dir($dir, $failable = false) + { + $path = $this->phpbb_root_path . $dir; + $exists = $writable = false; + + // Try to create the directory if it does not exist + if (!file_exists($path)) + { + try + { + $this->filesystem->mkdir($path, 0777); + $this->filesystem->phpbb_chmod($path, + \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE + ); + $exists = true; + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + } + + // Now really check + if (file_exists($path) && is_dir($path)) + { + try + { + $exists = true; + $this->filesystem->phpbb_chmod($path, + \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE + ); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + } + + if ($this->filesystem->is_writable($path)) + { + $writable = true; + } + + $this->set_test_passed(($exists && $writable) || $failable); + + if (!($exists && $writable)) + { + $title = ($exists) ? 'DIRECTORY_NOT_WRITABLE' : 'DIRECTORY_NOT_EXISTS'; + $description = array($title . '_EXPLAIN', $dir); + + if ($failable) + { + $this->response->add_warning_message($title, $description); + } + else + { + $this->response->add_error_message($title, $description); + } + } + } +} diff --git a/phpBB/install/module/requirements/task/check_server_environment.php b/phpBB/install/module/requirements/task/check_server_environment.php new file mode 100644 index 0000000000..797083d429 --- /dev/null +++ b/phpBB/install/module/requirements/task/check_server_environment.php @@ -0,0 +1,185 @@ + + * @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\install\module\requirements\task; + +/** + * Installer task that checks if the server meats phpBB requirements + */ +class check_server_environment extends \phpbb\install\task_base +{ + /** + * @var \phpbb\install\helper\database + */ + protected $database_helper; + + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $response_helper; + + /** + * @var bool + */ + protected $tests_passed; + + /** + * Constructor + * + * @param \phpbb\install\helper\database $database_helper + * @param \phpbb\install\helper\iohandler\iohandler_interface $response + */ + public function __construct(\phpbb\install\helper\database $database_helper, + \phpbb\install\helper\iohandler\iohandler_interface $response) + { + $this->database_helper = $database_helper; + $this->response_helper = $response; + $this->tests_passed = true; + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + // + // Check requirements + // The error messages should be set in the check_ functions + // + + // Check PHP version + $this->check_php_version(); + + // Check for getimagesize() + $this->check_image_size(); + + // Check for PCRE support + $this->check_pcre(); + + // Check for JSON support + $this->check_json(); + + // Check for dbms support + $this->check_available_dbms(); + + return $this->tests_passed; + } + + /** + * Sets $this->tests_passed + * + * @param bool $is_passed + * @return null + */ + protected function set_test_passed($is_passed) + { + // If one test failed, tests_passed should be false + $this->tests_passed = (!$this->tests_passed) ? false : $is_passed; + } + + /** + * Check if the requirements for PHP version is met + * + * @return null + */ + protected function check_php_version() + { + $php_version = PHP_VERSION; + + if (version_compare($php_version, '5.3.9') < 0) + { + $this->response_helper->add_error_message('PHP_VERSION_REQD', 'PHP_VERSION_REQD_EXPLAIN'); + + $this->set_test_passed(false); + return; + } + + $this->set_test_passed(true); + } + + /** + * Checks if the installed PHP has getimagesize() available + * + * @return null + */ + protected function check_image_size() + { + if (!@function_exists('getimagesize')) + { + $this->response_helper->add_error_message('PHP_GETIMAGESIZE_SUPPORT', 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN'); + + $this->set_test_passed(false); + return; + } + + $this->set_test_passed(true); + } + + /** + * Checks if the installed PHP supports PCRE + * + * @return null + */ + protected function check_pcre() + { + if (@preg_match('//u', '')) + { + $this->set_test_passed(true); + return; + } + + $this->response_helper->add_error_message('PCRE_UTF_SUPPORT', 'PCRE_UTF_SUPPORT_EXPLAIN'); + + $this->set_test_passed(false); + } + + /** + * Checks whether PHP's JSON extension is available or not + * + * @return null + */ + protected function check_json() + { + if (@extension_loaded('json')) + { + $this->set_test_passed(true); + return; + } + + $this->response_helper->add_error_message('PHP_JSON_SUPPORT', 'PHP_JSON_SUPPORT_EXPLAIN'); + + $this->set_test_passed(false); + } + + /** + * Check if any supported DBMS is available + * + * @return null + */ + protected function check_available_dbms() + { + $available_dbms = $this->database_helper->get_available_dbms(false, true); + + if ($available_dbms['ANY_DB_SUPPORT']) + { + $this->set_test_passed(true); + return; + } + + $this->response_helper->add_error_message('PHP_SUPPORTED_DB', 'PHP_SUPPORTED_DB_EXPLAIN'); + + $this->set_test_passed(false); + } +} From 4df89d88486faa0c70473271c6ba757d5faab851 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Tue, 2 Jun 2015 20:41:26 +0200 Subject: [PATCH 0443/1676] [ticket/13740] Clean up docblocks PHPBB3-13740 --- phpBB/install/controller/install.php | 8 +++-- .../helper/iohandler/iohandler_base.php | 2 -- .../helper/iohandler/iohandler_interface.php | 31 ++++++++++++------- phpBB/install/installer.php | 2 -- .../obtain_data/task/obtain_admin_data.php | 4 --- .../obtain_data/task/obtain_board_data.php | 2 -- .../obtain_data/task/obtain_database_data.php | 4 --- .../requirements/task/check_filesystem.php | 1 - .../task/check_server_environment.php | 11 ------- phpBB/install/module_base.php | 2 -- 10 files changed, 25 insertions(+), 42 deletions(-) diff --git a/phpBB/install/controller/install.php b/phpBB/install/controller/install.php index 1217107484..12bc575b83 100644 --- a/phpBB/install/controller/install.php +++ b/phpBB/install/controller/install.php @@ -62,6 +62,11 @@ class install $this->installer = $installer; } + /** + * Controller logic + * + * @return \Symfony\Component\HttpFoundation\Response|StreamedResponse + */ public function handle() { // @todo check that phpBB is not already installed @@ -82,8 +87,7 @@ class install if ($this->request->is_ajax()) { - $installer = &$this->installer; - + $installer = $this->installer; $response = new StreamedResponse(); $response->setCallback(function() use ($installer) { $installer->run(); diff --git a/phpBB/install/helper/iohandler/iohandler_base.php b/phpBB/install/helper/iohandler/iohandler_base.php index 0d5467d202..c0e6921fb2 100644 --- a/phpBB/install/helper/iohandler/iohandler_base.php +++ b/phpBB/install/helper/iohandler/iohandler_base.php @@ -62,8 +62,6 @@ abstract class iohandler_base implements iohandler_interface * Set language service * * @param \phpbb\language\language $language - * - * @return null */ public function set_language(\phpbb\language\language $language) { diff --git a/phpBB/install/helper/iohandler/iohandler_interface.php b/phpBB/install/helper/iohandler/iohandler_interface.php index cea5610586..387a8617b9 100644 --- a/phpBB/install/helper/iohandler/iohandler_interface.php +++ b/phpBB/install/helper/iohandler/iohandler_interface.php @@ -74,8 +74,6 @@ interface iohandler_interface * @param string|array $error_title Title of the error message. * @param string|bool|array $error_description Description of the error (and possibly guidelines to resolve it), * or false if the error description is not available. - * - * @return null */ public function add_error_message($error_title, $error_description = false); @@ -85,11 +83,9 @@ interface iohandler_interface * Note: When an array is passed into the parameters below, it will be * resolved as printf($param[0], $param[1], ...). * - * @param string|array $warning_title Title of the error message - * @param string|bool|array $warning_description Description of the error (and possibly guidelines to resolve it), + * @param string|array $warning_title Title of the warning message + * @param string|bool|array $warning_description Description of the warning (and possibly guidelines to resolve it), * or false if the error description is not available - * - * @return null */ public function add_warning_message($warning_title, $warning_description = false); @@ -99,11 +95,9 @@ interface iohandler_interface * Note: When an array is passed into the parameters below, it will be * resolved as printf($param[0], $param[1], ...). * - * @param string|array $log_title Title of the error message - * @param string|bool|array $log_description Description of the error (and possibly guidelines to resolve it), + * @param string|array $log_title Title of the log message + * @param string|bool|array $log_description Description of the log (and possibly guidelines to resolve it), * or false if the error description is not available - * - * @return null */ public function add_log_message($log_title, $log_description = false); @@ -112,8 +106,21 @@ interface iohandler_interface * * @param string $title Language variable with the title of the form * @param array $form An array describing the required data (options etc) - * - * @return null */ public function add_user_form_group($title, $form); + + /** + * Sets the number of tasks belonging to the installer in the current mode. + * + * @param int $task_count Number of tasks + */ + public function set_task_count($task_count); + + /** + * Sets the progress information + * + * @param string $task_lang_key Language key for the name of the task + * @param int $task_number Position of the current task in the task queue + */ + public function set_progress($task_lang_key, $task_number); } diff --git a/phpBB/install/installer.php b/phpBB/install/installer.php index 5a2fcc4d85..34bc4b23f7 100644 --- a/phpBB/install/installer.php +++ b/phpBB/install/installer.php @@ -60,8 +60,6 @@ class installer /** * Run phpBB installer - * - * @return null */ public function run() { diff --git a/phpBB/install/module/obtain_data/task/obtain_admin_data.php b/phpBB/install/module/obtain_data/task/obtain_admin_data.php index d820353880..6745419eb2 100644 --- a/phpBB/install/module/obtain_data/task/obtain_admin_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_admin_data.php @@ -63,8 +63,6 @@ class obtain_admin_data extends \phpbb\install\task_base implements \phpbb\insta /** * Process form data - * - * @return null */ protected function process_form() { @@ -93,8 +91,6 @@ class obtain_admin_data extends \phpbb\install\task_base implements \phpbb\insta * * @param bool $use_request_data Whether to use submited data * - * @return null - * * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data */ protected function request_form_data($use_request_data = false) diff --git a/phpBB/install/module/obtain_data/task/obtain_board_data.php b/phpBB/install/module/obtain_data/task/obtain_board_data.php index e17ecd01c5..5415d152a7 100644 --- a/phpBB/install/module/obtain_data/task/obtain_board_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_board_data.php @@ -71,8 +71,6 @@ class obtain_board_data extends \phpbb\install\task_base implements \phpbb\insta /** * Process form data - * - * @return null */ protected function process_form() { diff --git a/phpBB/install/module/obtain_data/task/obtain_database_data.php b/phpBB/install/module/obtain_data/task/obtain_database_data.php index 4c71c4adea..c8bdff4bf8 100644 --- a/phpBB/install/module/obtain_data/task/obtain_database_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_database_data.php @@ -71,8 +71,6 @@ class obtain_database_data extends \phpbb\install\task_base implements \phpbb\in /** * Process form data - * - * @return null */ protected function process_form() { @@ -110,8 +108,6 @@ class obtain_database_data extends \phpbb\install\task_base implements \phpbb\in * * @param bool $use_request_data Whether to use submited data * - * @return null - * * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data */ protected function request_form_data($use_request_data = false) diff --git a/phpBB/install/module/requirements/task/check_filesystem.php b/phpBB/install/module/requirements/task/check_filesystem.php index 0314a988f1..1c76ed146e 100644 --- a/phpBB/install/module/requirements/task/check_filesystem.php +++ b/phpBB/install/module/requirements/task/check_filesystem.php @@ -122,7 +122,6 @@ class check_filesystem extends \phpbb\install\task_base * Sets $this->tests_passed * * @param bool $is_passed - * @return null */ protected function set_test_passed($is_passed) { diff --git a/phpBB/install/module/requirements/task/check_server_environment.php b/phpBB/install/module/requirements/task/check_server_environment.php index 797083d429..4bfea57b0e 100644 --- a/phpBB/install/module/requirements/task/check_server_environment.php +++ b/phpBB/install/module/requirements/task/check_server_environment.php @@ -81,7 +81,6 @@ class check_server_environment extends \phpbb\install\task_base * Sets $this->tests_passed * * @param bool $is_passed - * @return null */ protected function set_test_passed($is_passed) { @@ -91,8 +90,6 @@ class check_server_environment extends \phpbb\install\task_base /** * Check if the requirements for PHP version is met - * - * @return null */ protected function check_php_version() { @@ -111,8 +108,6 @@ class check_server_environment extends \phpbb\install\task_base /** * Checks if the installed PHP has getimagesize() available - * - * @return null */ protected function check_image_size() { @@ -129,8 +124,6 @@ class check_server_environment extends \phpbb\install\task_base /** * Checks if the installed PHP supports PCRE - * - * @return null */ protected function check_pcre() { @@ -147,8 +140,6 @@ class check_server_environment extends \phpbb\install\task_base /** * Checks whether PHP's JSON extension is available or not - * - * @return null */ protected function check_json() { @@ -165,8 +156,6 @@ class check_server_environment extends \phpbb\install\task_base /** * Check if any supported DBMS is available - * - * @return null */ protected function check_available_dbms() { diff --git a/phpBB/install/module_base.php b/phpBB/install/module_base.php index defccaefef..a34a103aca 100644 --- a/phpBB/install/module_base.php +++ b/phpBB/install/module_base.php @@ -63,8 +63,6 @@ abstract class module_base implements module_interface * @param \Symfony\Component\DependencyInjection\ContainerInterface $container * @param \phpbb\install\helper\config $config * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler - * - * @return null */ public function setup(\Symfony\Component\DependencyInjection\ContainerInterface $container, \phpbb\install\helper\config $config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler) { From 37b0134aa437e3e874464d3cf0d29c34a8da184a Mon Sep 17 00:00:00 2001 From: MateBartus Date: Tue, 2 Jun 2015 21:56:27 +0200 Subject: [PATCH 0444/1676] [ticket/13740] Add backend support for install progress tracking PHPBB3-13740 --- phpBB/install/controller/install.php | 6 ++ phpBB/install/helper/config.php | 62 +++++++++++++++---- .../helper/iohandler/iohandler_base.php | 39 ++++++++++++ phpBB/install/installer.php | 34 +++++++++- .../module/install_data/task/add_bots.php | 8 +++ .../install_data/task/add_languages.php | 8 +++ .../module/install_data/task/add_modules.php | 8 +++ .../task/add_config_settings.php | 8 +++ .../task/add_default_data.php | 8 +++ .../install_database/task/create_schema.php | 8 +++ .../task/create_config_file.php | 8 +++ .../install_finish/task/notify_user.php | 10 ++- .../task/populate_migrations.php | 8 +++ .../obtain_data/task/obtain_admin_data.php | 8 +++ .../obtain_data/task/obtain_board_data.php | 8 +++ .../obtain_data/task/obtain_database_data.php | 8 +++ .../obtain_data/task/obtain_email_data.php | 8 +++ .../obtain_data/task/obtain_imagick_path.php | 8 +++ .../obtain_data/task/obtain_server_data.php | 8 +++ .../requirements/task/check_filesystem.php | 8 +++ .../task/check_server_environment.php | 8 +++ phpBB/install/module_base.php | 17 +++-- phpBB/install/task_interface.php | 9 ++- phpBB/language/en/install.php | 23 +++++++ 24 files changed, 306 insertions(+), 22 deletions(-) diff --git a/phpBB/install/controller/install.php b/phpBB/install/controller/install.php index 12bc575b83..4021c5625b 100644 --- a/phpBB/install/controller/install.php +++ b/phpBB/install/controller/install.php @@ -85,8 +85,14 @@ class install $this->iohandler_factory->set_environment('nojs'); } + // Set the appropriate input-output handler + //$this->installer->set_iohandler($this->iohandler_factory->get()); + if ($this->request->is_ajax()) { + // @todo: remove this line, and use the above + $this->installer->set_iohandler($this->iohandler_factory->get()); + $installer = $this->installer; $response = new StreamedResponse(); $response->setCallback(function() use ($installer) { diff --git a/phpBB/install/helper/config.php b/phpBB/install/helper/config.php index b759df737e..f39e92b622 100644 --- a/phpBB/install/helper/config.php +++ b/phpBB/install/helper/config.php @@ -81,6 +81,8 @@ class config 'last_task_module_name' => '', // Stores the service name of the latest finished module 'last_task_index' => 0, 'last_task_name' => '', // Stores the service name of the latest finished task + 'max_task_progress' => 0, + 'current_task_progress' => 0, ); $this->install_config_file = $this->phpbb_root_path . 'store/install_config.php'; @@ -108,8 +110,6 @@ class config * * @param string $param_name Name of the parameter * @param mixed $value Values to set the parameter - * - * @return null */ public function set($param_name, $value) { @@ -161,8 +161,6 @@ class config * * @param string $task_service_name Name of the installer task service * @param int $task_index Index of the task in the task list array - * - * @return null */ public function set_finished_task($task_service_name, $task_index) { @@ -175,8 +173,6 @@ class config * * @param string $module_service_name Name of the installer module service * @param int $module_index Index of the module in the module list array - * - * @return null */ public function set_active_module($module_service_name, $module_index) { @@ -196,8 +192,6 @@ class config /** * Recovers install configuration from file - * - * @return null */ public function load_config() { @@ -216,8 +210,6 @@ class config /** * Dumps install configuration to disk - * - * @return null */ public function save_config() { @@ -239,9 +231,55 @@ class config } /** - * Filling up system_data array + * Increments the task progress + */ + public function increment_current_task_progress() + { + $this->progress_data['current_task_progress']++; + } + + /** + * Sets the task progress to a specific number * - * @return null + * @param int $task_progress The task progress number to be set + */ + public function set_current_task_progress($task_progress) + { + $this->progress_data['current_task_progress'] = $task_progress; + } + + /** + * Sets the number of tasks belonging to the installer in the current mode. + * + * @param int $task_progress_count Number of tasks + */ + public function set_task_progress_count($task_progress_count) + { + $this->progress_data['max_task_progress'] = $task_progress_count; + } + + /** + * Returns the number of the current task being executed + * + * @return int + */ + public function get_current_task_progress() + { + return $this->progress_data['current_task_progress']; + } + + /** + * Returns the number of tasks belonging to the installer in the current mode. + * + * @return int + */ + public function get_task_progress_count() + { + return $this->progress_data['max_task_progress']; + } + + /** + * Filling up system_data array */ protected function setup_system_data() { diff --git a/phpBB/install/helper/iohandler/iohandler_base.php b/phpBB/install/helper/iohandler/iohandler_base.php index c0e6921fb2..f767ecf4e9 100644 --- a/phpBB/install/helper/iohandler/iohandler_base.php +++ b/phpBB/install/helper/iohandler/iohandler_base.php @@ -48,6 +48,21 @@ abstract class iohandler_base implements iohandler_interface */ protected $language; + /** + * @var int + */ + protected $task_progress_count; + + /** + * @var int + */ + protected $current_task_progress; + + /** + * @var string + */ + protected $current_task_name; + /** * Constructor */ @@ -56,6 +71,10 @@ abstract class iohandler_base implements iohandler_interface $this->errors = array(); $this->warnings = array(); $this->logs = array(); + + $this->task_progress_count = 0; + $this->current_task_progress = 0; + $this->current_task_name = ''; } /** @@ -92,6 +111,26 @@ abstract class iohandler_base implements iohandler_interface $this->logs[] = $this->translate_message($log_title, $log_description); } + /** + * {@inheritdoc} + */ + public function set_task_count($task_count) + { + $this->task_progress_count = $task_count; + } + + /** + * {@inheritdoc} + */ + public function set_progress($task_lang_key, $task_number) + { + if (!empty($task_lang_key)) + { + $this->current_task_name = $this->language->lang($task_lang_key); + $this->current_task_progress = $task_number; + } + } + /** * Localize message. * diff --git a/phpBB/install/installer.php b/phpBB/install/installer.php index 34bc4b23f7..4779bc43c4 100644 --- a/phpBB/install/installer.php +++ b/phpBB/install/installer.php @@ -30,6 +30,11 @@ class installer */ protected $installer_modules; + /** + * @var \phpbb\install\helper\iohandler\iohandler_interface + */ + protected $iohandler; + /** * Constructor * @@ -58,6 +63,16 @@ class installer $this->installer_modules = $modules; } + /** + * Sets input-output handler objects + * + * @param helper\iohandler\iohandler_interface $iohandler + */ + public function set_iohandler(\phpbb\install\helper\iohandler\iohandler_interface $iohandler) + { + $this->iohandler = $iohandler; + } + /** * Run phpBB installer */ @@ -69,6 +84,20 @@ class installer // Recover install progress $module_index = $this->recover_progress(); + // Count all tasks in the current installer modules + $task_count = 0; + foreach ($this->installer_modules as $name) + { + /** @var \phpbb\install\module_interface $module */ + $module = $this->container->get($name); + + $task_count += $module->get_task_count(); + } + + // Set task count + $this->install_config->set_task_progress_count($task_count); + $this->iohandler->set_task_count($task_count); + $install_finished = false; try @@ -107,11 +136,12 @@ class installer if ($install_finished) { - die ("install finished"); + // Send install finished message + $this->iohandler->set_progress('INSTALLER_FINISHED', $this->install_config->get_task_progress_count()); } else { - die ("install memory or time limit reached"); + // @todo: Send refresh request } } catch (\phpbb\install\exception\user_interaction_required_exception $e) diff --git a/phpBB/install/module/install_data/task/add_bots.php b/phpBB/install/module/install_data/task/add_bots.php index 8ce4ae765d..cba228bdba 100644 --- a/phpBB/install/module/install_data/task/add_bots.php +++ b/phpBB/install/module/install_data/task/add_bots.php @@ -221,4 +221,12 @@ class add_bots extends \phpbb\install\task_base $this->db->sql_query($sql); } } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_ADD_BOTS'; + } } diff --git a/phpBB/install/module/install_data/task/add_languages.php b/phpBB/install/module/install_data/task/add_languages.php index 9502a736f3..8418829ca6 100644 --- a/phpBB/install/module/install_data/task/add_languages.php +++ b/phpBB/install/module/install_data/task/add_languages.php @@ -102,4 +102,12 @@ class add_languages extends \phpbb\install\task_base $insert_buffer->flush(); } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_ADD_LANGUAGES'; + } } diff --git a/phpBB/install/module/install_data/task/add_modules.php b/phpBB/install/module/install_data/task/add_modules.php index 98b52d7494..d47c2cd106 100644 --- a/phpBB/install/module/install_data/task/add_modules.php +++ b/phpBB/install/module/install_data/task/add_modules.php @@ -449,4 +449,12 @@ class add_modules extends \phpbb\install\task_base $this->module_manager->remove_cache_file($module_class); } } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_ADD_MODULES'; + } } diff --git a/phpBB/install/module/install_database/task/add_config_settings.php b/phpBB/install/module/install_database/task/add_config_settings.php index 38dcef1d7a..be008da1d2 100644 --- a/phpBB/install/module/install_database/task/add_config_settings.php +++ b/phpBB/install/module/install_database/task/add_config_settings.php @@ -322,4 +322,12 @@ class add_config_settings extends \phpbb\install\task_base } } } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_ADD_CONFIG_SETTINGS'; + } } diff --git a/phpBB/install/module/install_database/task/add_default_data.php b/phpBB/install/module/install_database/task/add_default_data.php index a5c2ffecd1..c6ca3b5c87 100644 --- a/phpBB/install/module/install_database/task/add_default_data.php +++ b/phpBB/install/module/install_database/task/add_default_data.php @@ -142,4 +142,12 @@ class add_default_data extends \phpbb\install\task_base return ''; } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_ADD_DEFAULT_DATA'; + } } diff --git a/phpBB/install/module/install_database/task/create_schema.php b/phpBB/install/module/install_database/task/create_schema.php index aac710d337..e17f0d08d9 100644 --- a/phpBB/install/module/install_database/task/create_schema.php +++ b/phpBB/install/module/install_database/task/create_schema.php @@ -195,4 +195,12 @@ class create_schema extends \phpbb\install\task_base ); } } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_CREATE_DATABASE_SCHEMA'; + } } diff --git a/phpBB/install/module/install_filesystem/task/create_config_file.php b/phpBB/install/module/install_filesystem/task/create_config_file.php index f1191f53d0..b0afa9a7fc 100644 --- a/phpBB/install/module/install_filesystem/task/create_config_file.php +++ b/phpBB/install/module/install_filesystem/task/create_config_file.php @@ -216,4 +216,12 @@ class create_config_file extends \phpbb\install\task_base return $config_content; } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_CREATE_CONFIG_FILE'; + } } diff --git a/phpBB/install/module/install_finish/task/notify_user.php b/phpBB/install/module/install_finish/task/notify_user.php index d95303fcb5..c39e561c56 100644 --- a/phpBB/install/module/install_finish/task/notify_user.php +++ b/phpBB/install/module/install_finish/task/notify_user.php @@ -101,7 +101,7 @@ class notify_user extends \phpbb\install\task_base $messenger->anti_abuse_headers($this->config, $this->user); $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($this->install_config->get('admin_name')), - 'PASSWORD' => htmlspecialchars_decode($this->install_config->get('admin_pass1'))) + 'PASSWORD' => htmlspecialchars_decode($this->install_config->get('admin_passwd'))) ); $messenger->send(NOTIFY_EMAIL); } @@ -110,4 +110,12 @@ class notify_user extends \phpbb\install\task_base @unlink($this->phpbb_root_path . 'cache/install_lock'); } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_NOTIFY_USER'; + } } diff --git a/phpBB/install/module/install_finish/task/populate_migrations.php b/phpBB/install/module/install_finish/task/populate_migrations.php index 4f701b84ca..1441351bf8 100644 --- a/phpBB/install/module/install_finish/task/populate_migrations.php +++ b/phpBB/install/module/install_finish/task/populate_migrations.php @@ -51,4 +51,12 @@ class populate_migrations extends \phpbb\install\task_base ->get_classes(); $this->migrator->populate_migrations($migrations); } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_POPULATE_MIGRATIONS'; + } } diff --git a/phpBB/install/module/obtain_data/task/obtain_admin_data.php b/phpBB/install/module/obtain_data/task/obtain_admin_data.php index 6745419eb2..4b070aa19b 100644 --- a/phpBB/install/module/obtain_data/task/obtain_admin_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_admin_data.php @@ -200,4 +200,12 @@ class obtain_admin_data extends \phpbb\install\task_base implements \phpbb\insta return $data_valid; } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return ''; + } } diff --git a/phpBB/install/module/obtain_data/task/obtain_board_data.php b/phpBB/install/module/obtain_data/task/obtain_board_data.php index 5415d152a7..8a2507f073 100644 --- a/phpBB/install/module/obtain_data/task/obtain_board_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_board_data.php @@ -167,4 +167,12 @@ class obtain_board_data extends \phpbb\install\task_base implements \phpbb\insta $this->io_handler->send_response(); throw new user_interaction_required_exception; } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return ''; + } } diff --git a/phpBB/install/module/obtain_data/task/obtain_database_data.php b/phpBB/install/module/obtain_data/task/obtain_database_data.php index c8bdff4bf8..38a6dac0c2 100644 --- a/phpBB/install/module/obtain_data/task/obtain_database_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_database_data.php @@ -252,4 +252,12 @@ class obtain_database_data extends \phpbb\install\task_base implements \phpbb\in return $data_valid; } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return ''; + } } diff --git a/phpBB/install/module/obtain_data/task/obtain_email_data.php b/phpBB/install/module/obtain_data/task/obtain_email_data.php index fbcef0a5c6..9a3edefd54 100644 --- a/phpBB/install/module/obtain_data/task/obtain_email_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_email_data.php @@ -148,4 +148,12 @@ class obtain_email_data extends \phpbb\install\task_base implements \phpbb\insta throw new user_interaction_required_exception(); } } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return ''; + } } diff --git a/phpBB/install/module/obtain_data/task/obtain_imagick_path.php b/phpBB/install/module/obtain_data/task/obtain_imagick_path.php index 86af586e37..15570eac43 100644 --- a/phpBB/install/module/obtain_data/task/obtain_imagick_path.php +++ b/phpBB/install/module/obtain_data/task/obtain_imagick_path.php @@ -70,4 +70,12 @@ class obtain_imagick_path extends \phpbb\install\task_base implements \phpbb\ins $this->config->set('img_imagick', $img_imagick); } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return ''; + } } diff --git a/phpBB/install/module/obtain_data/task/obtain_server_data.php b/phpBB/install/module/obtain_data/task/obtain_server_data.php index 39606f6281..3f5a1c769f 100644 --- a/phpBB/install/module/obtain_data/task/obtain_server_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_server_data.php @@ -184,4 +184,12 @@ class obtain_server_data extends \phpbb\install\task_base implements \phpbb\inst throw new user_interaction_required_exception(); } } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return ''; + } } diff --git a/phpBB/install/module/requirements/task/check_filesystem.php b/phpBB/install/module/requirements/task/check_filesystem.php index 1c76ed146e..dea59d618e 100644 --- a/phpBB/install/module/requirements/task/check_filesystem.php +++ b/phpBB/install/module/requirements/task/check_filesystem.php @@ -254,4 +254,12 @@ class check_filesystem extends \phpbb\install\task_base } } } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return ''; + } } diff --git a/phpBB/install/module/requirements/task/check_server_environment.php b/phpBB/install/module/requirements/task/check_server_environment.php index 4bfea57b0e..f8dde51883 100644 --- a/phpBB/install/module/requirements/task/check_server_environment.php +++ b/phpBB/install/module/requirements/task/check_server_environment.php @@ -171,4 +171,12 @@ class check_server_environment extends \phpbb\install\task_base $this->set_test_passed(false); } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return ''; + } } diff --git a/phpBB/install/module_base.php b/phpBB/install/module_base.php index a34a103aca..3629903747 100644 --- a/phpBB/install/module_base.php +++ b/phpBB/install/module_base.php @@ -110,8 +110,15 @@ abstract class module_base implements module_interface /** @var \phpbb\install\task_interface $task */ $task = $this->container->get($this->task_collection[$task_index]); + // Send progress information + $this->iohandler->set_progress( + $task->get_task_lang_name(), + $this->install_config->get_current_task_progress() + ); + // Iterate to the next task $task_index++; + $this->install_config->increment_current_task_progress(); // Check if we can run the task if (!$task->is_essential() && !$task->check_requirements()) @@ -121,11 +128,11 @@ abstract class module_base implements module_interface $task->run(); - // Increment progress - if ($this->get_task_count() !== 0) - { - //$this->iohandler->increment_progress(); - } + // Send progress info + $this->iohandler->set_progress( + $task->get_task_lang_name(), + $this->install_config->get_current_task_progress() + ); $this->iohandler->send_response(); diff --git a/phpBB/install/task_interface.php b/phpBB/install/task_interface.php index 9cfc4d19c2..6f0a01258f 100644 --- a/phpBB/install/task_interface.php +++ b/phpBB/install/task_interface.php @@ -40,8 +40,13 @@ interface task_interface /** * Executes the task - * - * @return null */ public function run(); + + /** + * Returns the language key of the name of the task + * + * @return string + */ + public function get_task_lang_name(); } diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 59ad1b0d41..e3c4b859f0 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -226,3 +226,26 @@ $lang = array_merge($lang, array( 'MENU_LICENSE' => 'License', 'MENU_SUPPORT' => 'Support', )); + +// Task names +$lang = array_merge($lang, array( + // Install filesystem + 'TASK_CREATE_CONFIG_FILE' => 'Creating configuration file', + + // Install database + 'TASK_ADD_CONFIG_SETTINGS' => 'Adding configuration settings', + 'TASK_ADD_DEFAULT_DATA' => 'Adding default settings to the database', + 'TASK_CREATE_DATABASE_SCHEMA' => 'Creating database schema', + + // Install data + 'TASK_ADD_BOTS' => 'Registering bots', + 'TASK_ADD_LANGUAGES' => 'Installing available languages', + 'TASK_ADD_MODULES' => 'Installing modules', + + // Install finish tasks + 'TASK_NOTIFY_USER' => 'Sending notification e-mail', + 'TASK_POPULATE_MIGRATIONS' => 'Populating migrations', + + // Installer general progress messages + 'INSTALLER_FINISHED' => 'The installer has finished successfully', +)); From b7ef709549597f2fa4f9c8525bfd602f81644530 Mon Sep 17 00:00:00 2001 From: MateBartus Date: Wed, 3 Jun 2015 01:31:48 +0200 Subject: [PATCH 0445/1676] [ticket/13740] Implement progress bar for AJAX UI PHPBB3-13740 --- phpBB/adm/style/admin.css | 27 ++++ phpBB/assets/javascript/installer.js | 135 +++++++++++++----- .../helper/iohandler/ajax_iohandler.php | 19 +++ 3 files changed, 146 insertions(+), 35 deletions(-) diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index dd5878a976..ca5daf5bc5 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -2521,3 +2521,30 @@ fieldset.permissions .padding { clear: both; display: block; } + +#progress-bar { + position: relative; + width: 90%; + height: 25px; + margin: 20px auto; + border: 1px solid #cecece; +} + +#progress-bar #progress-bar-text { + position: absolute; + top: 0; + width: 100%; + text-align: center; + line-height: 25px; + font-weight: bold; +} + +#progress-bar #progress-bar-filler { + display: block; + position: relative; + top: 0; + left: 0; + background-color: #3c84ad; + width: 0; + height: 25px; +} diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index 302d95e7c6..ea5ca638b8 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -3,9 +3,12 @@ */ (function($) { // Avoid conflicts with other libraries - // Global variables + // Installer variables var pollTimer = null; var nextReadPosition = 0; + var progressBarTriggered = false; + var progressTimer = null; + var currentProgress = 0; // Template related variables var $contentWrapper = $('.install-body').find('.main'); @@ -56,49 +59,112 @@ if (responseObject.hasOwnProperty('form')) { add_form(responseObject.form); } + + if (responseObject.hasOwnProperty('progress')) { + set_progress(responseObject.progress); + } } function add_message(type, messages) { // Get message containers - var errorContainer = $('#error-container'); - var warningContainer = $('#warning-container'); - var logContainer = $('#log-container'); + var $errorContainer = $('#error-container'); + var $warningContainer = $('#warning-container'); + var $logContainer = $('#log-container'); - var title, description, msgElement, arraySize = messages.length; + var $title, $description, $msgElement, arraySize = messages.length; for (var i = 0; i < arraySize; i++) { - msgElement = $('
            '); - title = $(document.createElement('strong')); - title.text(messages[i].title); - msgElement.append(title); + $msgElement = $('
            '); + $title = $(document.createElement('strong')); + $title.text(messages[i].title); + $msgElement.append($title); if (messages[i].hasOwnProperty('description')) { - description = $(document.createElement('p')); - description.text(messages[i].description); - msgElement.append(description); + $description = $(document.createElement('p')); + $description.text(messages[i].description); + $msgElement.append($description); } switch (type) { case 'error': - msgElement.addClass('errorbox'); - errorContainer.append(msgElement); + $msgElement.addClass('errorbox'); + $errorContainer.append($msgElement); break; case 'warning': - msgElement.addClass('warningbox'); - warningContainer.append(msgElement); + $msgElement.addClass('warningbox'); + $warningContainer.append($msgElement); break; case 'log': - msgElement.addClass('log'); - logContainer.append(msgElement); + $msgElement.addClass('log'); + $logContainer.append($msgElement); break; } } } function add_form(formHtml) { - var formContainer = $('#content-container'); - formContainer.html(formHtml); - var form = $('#install_install'); - intercept_form_submit(form); + var $formContainer = $('#content-container'); + $formContainer.html(formHtml); + var $form = $('#install_install'); + intercept_form_submit($form); + } + + function set_progress(progressObject) { + var $statusText, $progressBar, $progressText, $progressFiller; + + if (progressObject.task_name.length) { + if (!progressBarTriggered) { + // Create progress bar + var $contentContainer = $('#content-container'); + + // Create progress bar elements + $progressBar = $('
            '); + $progressBar.attr('id', 'progress-bar'); + $progressText = $('

            '); + $progressText.attr('id', 'progress-bar-text'); + $progressFiller = $(''); + $progressFiller.attr('id', 'progress-bar-filler'); + + $statusText = $('

            '); + $statusText.attr('id', 'progress-status-text'); + + $progressBar.append($progressFiller); + $progressBar.append($progressText); + + $contentContainer.append($statusText); + $contentContainer.append($progressBar); + + progressBarTriggered = true; + } else { + $statusText = $('#progress-status-text'); + } + + // Update progress bar + $statusText.text(progressObject.task_name + '…'); + increment_progress_bar(Math.round(progressObject.task_num / progressObject.task_count * 100)); + } + } + + function increment_progress_bar(progressLimit) { + var $progressFiller = $('#progress-bar-filler'); + var $progressText = $('#progress-bar-text'); + var progressStart = $progressFiller.width() / $progressFiller.offsetParent().width() * 100; + currentProgress = Math.floor(progressStart); + + clearInterval(progressTimer); + progressTimer = setInterval(function() { + incrementFiller($progressText, $progressFiller, progressLimit); + }, 10); + } + + function incrementFiller($progressText, $progressFiller, progressLimit) { + currentProgress++; + $progressText.text(currentProgress + '%'); + $progressFiller.css('width', currentProgress + '%'); + + if (currentProgress >= progressLimit || currentProgress >= 100) { + console.log("In if; " + progressLimit + "; " + currentProgress); + clearInterval(progressTimer); + } } function start_polling(xhReq) { @@ -113,14 +179,14 @@ nextReadPosition = 0; } - function submit_form(form, submitBtn) { - form.css('display', 'none'); + function submit_form($form, $submitBtn) { + $form.css('display', 'none'); var xhReq = create_xhr_object(); - xhReq.open('POST', form.attr('action'), true); + xhReq.open('POST', $form.attr('action'), true); xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - xhReq.send(get_form_fields(form, submitBtn)); + xhReq.send(get_form_fields($form, $submitBtn)); // Clear content setup_ajax_layout(); @@ -130,23 +196,22 @@ } // Workaround for submit buttons - function get_form_fields(form, submitBtn) { - var formData = form.serialize(); - //var submitBtn = form.find(':submit'); - formData += ((formData.length) ? '&' : '') + encodeURIComponent(submitBtn.attr('name')) + '='; - formData += encodeURIComponent(submitBtn.attr('value')); + function get_form_fields($form, $submitBtn) { + var formData = $form.serialize(); + formData += ((formData.length) ? '&' : '') + encodeURIComponent($submitBtn.attr('name')) + '='; + formData += encodeURIComponent($submitBtn.attr('value')); return formData; } - function intercept_form_submit(form) { - if (!form.length) { + function intercept_form_submit($form) { + if (!$form.length) { return; } - form.find(':submit').bind('click', function (event) { + $form.find(':submit').bind('click', function (event) { event.preventDefault(); - submit_form(form, $(this)); + submit_form($form, $(this)); }); } diff --git a/phpBB/install/helper/iohandler/ajax_iohandler.php b/phpBB/install/helper/iohandler/ajax_iohandler.php index 44a185139e..960dd615b5 100644 --- a/phpBB/install/helper/iohandler/ajax_iohandler.php +++ b/phpBB/install/helper/iohandler/ajax_iohandler.php @@ -177,6 +177,16 @@ class ajax_iohandler extends iohandler_base $this->form = ''; } + // If current task name is set, we push progress message to the client side + if (!empty($this->current_task_name)) + { + $json_array['progress'] = array( + 'task_name' => $this->current_task_name, + 'task_num' => $this->current_task_progress, + 'task_count' => $this->task_progress_count, + ); + } + $this->errors = array(); $this->warnings = array(); $this->logs = array(); @@ -184,6 +194,15 @@ class ajax_iohandler extends iohandler_base return $json_array; } + /** + * {@inheritdoc} + */ + public function set_progress($task_lang_key, $task_number) + { + parent::set_progress($task_lang_key, $task_number); + $this->send_response(); + } + /** * Callback function for language replacing * From 63c3500dacc8d272e85273a67f56faa51a9d5fba Mon Sep 17 00:00:00 2001 From: MateBartus Date: Wed, 3 Jun 2015 16:35:23 +0200 Subject: [PATCH 0446/1676] [ticket/13740] Clean up JS code some more PHPBB3-13740 --- phpBB/assets/javascript/installer.js | 309 ++++++++++++++++----------- 1 file changed, 188 insertions(+), 121 deletions(-) diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index ea5ca638b8..8afac0da78 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -3,6 +3,9 @@ */ (function($) { // Avoid conflicts with other libraries + + 'use strict'; + // Installer variables var pollTimer = null; var nextReadPosition = 0; @@ -14,58 +17,37 @@ var $contentWrapper = $('.install-body').find('.main'); // Intercept form submits - intercept_form_submit($('#install_install')); + interceptFormSubmit($('#install_install')); - function poll_content(xhReq) { - var messages = xhReq.responseText; + /** + * Creates an XHR object + * + * jQuery cannot be used as the response is streamed, and + * as of now, jQuery does not provide access to the response until + * the connection is not closed. + * + * @return XMLHttpRequest|ActiveXObject + */ + function createXhrObject() { + var xhReq; - do { - var unprocessed = messages.substring(nextReadPosition); - var messageEndIndex = unprocessed.indexOf('}\n\n'); - - if (messageEndIndex !== -1) { - var endOfMessageIndex = messageEndIndex + 3; // 3 is the length of "}\n\n" - var message = unprocessed.substring(0, endOfMessageIndex); - parse_message(message); - nextReadPosition += endOfMessageIndex; - } - } while (messageEndIndex !== -1); - - if (xhReq.readyState === 4) { - $('#loading_indicator').css('display', 'none'); - reset_polling(); + if (window.XMLHttpRequest) { + xhReq = new XMLHttpRequest(); } + else if (window.ActiveXObject) { + xhReq = new ActiveXObject("Msxml2.XMLHTTP"); + } + + return xhReq; } - function parse_message(messageJSON) { - $('#loading_indicator').css('display', 'none'); - - messageJSON = messageJSON.trim(); - var responseObject = JSON.parse(messageJSON); - - // Parse object - if (responseObject.hasOwnProperty('errors')) { - add_message('error', responseObject.errors) - } - - if (responseObject.hasOwnProperty('warnings')) { - add_message('warning', responseObject.warnings) - } - - if (responseObject.hasOwnProperty('logs')) { - add_message('log', responseObject.logs); - } - - if (responseObject.hasOwnProperty('form')) { - add_form(responseObject.form); - } - - if (responseObject.hasOwnProperty('progress')) { - set_progress(responseObject.progress); - } - } - - function add_message(type, messages) { + /** + * Displays error, warning and log messages + * + * @param type + * @param messages + */ + function addMessage(type, messages) { // Get message containers var $errorContainer = $('#error-container'); var $warningContainer = $('#warning-container'); @@ -101,14 +83,24 @@ } } - function add_form(formHtml) { + /** + * Displays a form from the response + * + * @param formHtml + */ + function addForm(formHtml) { var $formContainer = $('#content-container'); $formContainer.html(formHtml); var $form = $('#install_install'); - intercept_form_submit($form); + interceptFormSubmit($form); } - function set_progress(progressObject) { + /** + * Renders progress bar + * + * @param progressObject + */ + function setProgress(progressObject) { var $statusText, $progressBar, $progressText, $progressFiller; if (progressObject.task_name.length) { @@ -140,11 +132,93 @@ // Update progress bar $statusText.text(progressObject.task_name + '…'); - increment_progress_bar(Math.round(progressObject.task_num / progressObject.task_count * 100)); + incrementProgressBar(Math.round(progressObject.task_num / progressObject.task_count * 100)); } } - function increment_progress_bar(progressLimit) { + /** + * Parse messages from the response object + * + * @param messageJSON + */ + function parseMessage(messageJSON) { + $('#loading_indicator').css('display', 'none'); + + var responseObject = JSON.parse(messageJSON); + + // Parse object + if (responseObject.hasOwnProperty('errors')) { + addMessage('error', responseObject.errors); + } + + if (responseObject.hasOwnProperty('warnings')) { + addMessage('warning', responseObject.warnings); + } + + if (responseObject.hasOwnProperty('logs')) { + addMessage('log', responseObject.logs); + } + + if (responseObject.hasOwnProperty('form')) { + addForm(responseObject.form); + } + + if (responseObject.hasOwnProperty('progress')) { + setProgress(responseObject.progress); + } + } + + /** + * Process updates in streamed response + * + * @param xhReq XHR object + */ + function pollContent(xhReq) { + var messages = xhReq.responseText; + var msgSeparator = '}\n\n'; + var unprocessed, messageEndIndex, endOfMessageIndex, message; + + do { + unprocessed = messages.substring(nextReadPosition); + messageEndIndex = unprocessed.indexOf(msgSeparator); + + if (messageEndIndex !== -1) { + endOfMessageIndex = messageEndIndex + msgSeparator.length; + message = unprocessed.substring(0, endOfMessageIndex); + parseMessage(message); + nextReadPosition += endOfMessageIndex; + } + } while (messageEndIndex !== -1); + + if (xhReq.readyState === 4) { + $('#loading_indicator').css('display', 'none'); + resetPolling(); + } + } + + /** + * Animates the progress bar + * + * @param $progressText + * @param $progressFiller + * @param progressLimit + */ + function incrementFiller($progressText, $progressFiller, progressLimit) { + currentProgress++; + $progressText.text(currentProgress + '%'); + $progressFiller.css('width', currentProgress + '%'); + + if (currentProgress >= progressLimit || currentProgress >= 100) { + clearInterval(progressTimer); + } + } + + /** + * Wrapper function for progress bar rendering and animating + * + * @param progressLimit + */ + function incrementProgressBar(progressLimit) { var $progressFiller = $('#progress-bar-filler'); var $progressText = $('#progress-bar-text'); var progressStart = $progressFiller.width() / $progressFiller.offsetParent().width() * 100; @@ -156,85 +230,30 @@ }, 10); } - function incrementFiller($progressText, $progressFiller, progressLimit) { - currentProgress++; - $progressText.text(currentProgress + '%'); - $progressFiller.css('width', currentProgress + '%'); - - if (currentProgress >= progressLimit || currentProgress >= 100) { - console.log("In if; " + progressLimit + "; " + currentProgress); - clearInterval(progressTimer); - } - } - - function start_polling(xhReq) { - reset_polling(); + /** + * Sets up timer for processing the streamed HTTP response + * + * @param xhReq + */ + function startPolling(xhReq) { + resetPolling(); pollTimer = setInterval(function () { - poll_content(xhReq); + pollContent(xhReq); }, 500); } - function reset_polling() { + /** + * Resets the polling timer + */ + function resetPolling() { clearInterval(pollTimer); nextReadPosition = 0; } - function submit_form($form, $submitBtn) { - $form.css('display', 'none'); - - var xhReq = create_xhr_object(); - xhReq.open('POST', $form.attr('action'), true); - xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - xhReq.send(get_form_fields($form, $submitBtn)); - - // Clear content - setup_ajax_layout(); - $('#loading_indicator').css('display', 'block'); - - start_polling(xhReq); - } - - // Workaround for submit buttons - function get_form_fields($form, $submitBtn) { - var formData = $form.serialize(); - formData += ((formData.length) ? '&' : '') + encodeURIComponent($submitBtn.attr('name')) + '='; - formData += encodeURIComponent($submitBtn.attr('value')); - - return formData; - } - - function intercept_form_submit($form) { - if (!$form.length) { - return; - } - - $form.find(':submit').bind('click', function (event) { - event.preventDefault(); - submit_form($form, $(this)); - }); - - } - /** - * jQuery cannot be used as the response is streamed, and - * as of now, jQuery does not provide access to the response until - * the connection is not closed. + * Renders the AJAX UI layout */ - function create_xhr_object() { - var xhReq; - - if (window.XMLHttpRequest) { - xhReq = new XMLHttpRequest(); - } - else if (window.ActiveXObject) { - xhReq = new ActiveXObject("Msxml2.XMLHTTP"); - } - - return xhReq; - } - - function setup_ajax_layout() { + function setupAjaxLayout() { // Clear content $contentWrapper.html(''); @@ -267,4 +286,52 @@ $spinner.html(' '); $contentWrapper.append($spinner); } + + function submitForm($form, $submitBtn) { + $form.css('display', 'none'); + + var xhReq = createXhrObject(); + xhReq.open('POST', $form.attr('action'), true); + xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xhReq.send(getFormFields($form, $submitBtn)); + + // Clear content + setupAjaxLayout(); + $('#loading_indicator').css('display', 'block'); + + startPolling(xhReq); + } + + /** + * Add submit button to the POST information + * + * @param $form + * @param $submitBtn + * + * @returns {*} + */ + function getFormFields($form, $submitBtn) { + var formData = $form.serialize(); + formData += ((formData.length) ? '&' : '') + encodeURIComponent($submitBtn.attr('name')) + '='; + formData += encodeURIComponent($submitBtn.attr('value')); + + return formData; + } + + /** + * Intercept form submit events and determine the submit button used + * + * @param $form + */ + function interceptFormSubmit($form) { + if (!$form.length) { + return; + } + + $form.find(':submit').bind('click', function (event) { + event.preventDefault(); + submitForm($form, $(this)); + }); + } })(jQuery); // Avoid conflicts with other libraries From 0dc6029bfed10fac1a09a4fd8de7d1b31407693a Mon Sep 17 00:00:00 2001 From: CHItA Date: Thu, 4 Jun 2015 00:43:08 +0200 Subject: [PATCH 0447/1676] [ticket/13740] Tasks can appear as multiple steps for the progress bar PHPBB3-13740 --- .../container/services_install_filesystem.yml | 4 ++-- .../container/services_install_finish.yml | 6 ++--- .../services_install_obtain_data.yml | 14 +++++------ .../services_install_requirements.yml | 6 ++--- phpBB/install/installer.php | 2 +- .../module/install_data/task/add_bots.php | 8 +++++++ .../install_data/task/add_languages.php | 8 +++++++ .../module/install_data/task/add_modules.php | 8 +++++++ .../task/add_config_settings.php | 8 +++++++ .../task/add_default_data.php | 8 +++++++ .../install_database/task/create_schema.php | 8 +++++++ .../task/create_config_file.php | 8 +++++++ .../install_finish/task/notify_user.php | 8 +++++++ .../task/populate_migrations.php | 8 +++++++ phpBB/install/module/obtain_data/module.php | 2 +- .../obtain_data/task/obtain_admin_data.php | 8 +++++++ .../obtain_data/task/obtain_board_data.php | 8 +++++++ .../obtain_data/task/obtain_database_data.php | 8 +++++++ .../obtain_data/task/obtain_email_data.php | 8 +++++++ .../obtain_data/task/obtain_imagick_path.php | 8 +++++++ .../obtain_data/task/obtain_server_data.php | 8 +++++++ phpBB/install/module/requirements/module.php | 2 +- .../requirements/task/check_filesystem.php | 8 +++++++ .../task/check_server_environment.php | 8 +++++++ phpBB/install/module_base.php | 24 +++++++++++++++++-- phpBB/install/module_interface.php | 2 +- phpBB/install/task_interface.php | 13 ++++++++++ 27 files changed, 190 insertions(+), 21 deletions(-) diff --git a/phpBB/config/installer/container/services_install_filesystem.yml b/phpBB/config/installer/container/services_install_filesystem.yml index 24497d330a..077b1ccb98 100644 --- a/phpBB/config/installer/container/services_install_filesystem.yml +++ b/phpBB/config/installer/container/services_install_filesystem.yml @@ -1,5 +1,5 @@ services: - installer.filesystem.create_config: + installer.install_filesystem.create_config_file: class: phpbb\install\module\install_filesystem\task\create_config_file arguments: - @filesystem @@ -13,4 +13,4 @@ services: class: phpbb\install\module\install_filesystem\module parent: installer.module_base arguments: - - ["installer.filesystem.create_config"] + - ["installer.install_filesystem.create_config_file"] diff --git a/phpBB/config/installer/container/services_install_finish.yml b/phpBB/config/installer/container/services_install_finish.yml index 20cd60983b..d2002f9fd7 100644 --- a/phpBB/config/installer/container/services_install_finish.yml +++ b/phpBB/config/installer/container/services_install_finish.yml @@ -1,10 +1,10 @@ services: - installer.finish.populate_migrations: + installer.install_finish.populate_migrations: class: phpbb\install\module\install_finish\task\populate_migrations arguments: - @installer.helper.container_factory - installer.finish.notify_user: + installer.install_finish.notify_user: class: phpbb\install\module\install_finish\task\notify_user arguments: - @installer.helper.container_factory @@ -17,4 +17,4 @@ services: class: phpbb\install\module\install_filesystem\module parent: installer.module_base arguments: - - ["installer.finish.populate_migrations", "installer.finish.notify_user"] + - ["installer.install_finish.populate_migrations", "installer.install_finish.notify_user"] diff --git a/phpBB/config/installer/container/services_install_obtain_data.yml b/phpBB/config/installer/container/services_install_obtain_data.yml index 2800392c58..2cfe210309 100644 --- a/phpBB/config/installer/container/services_install_obtain_data.yml +++ b/phpBB/config/installer/container/services_install_obtain_data.yml @@ -1,36 +1,36 @@ services: - installer.obtain_data.admin: + installer.obtain_data.obtain_admin_data: class: phpbb\install\module\obtain_data\task\obtain_admin_data arguments: - @installer.helper.config - @installer.helper.iohandler - installer.obtain_data.board: + installer.obtain_data.obtain_board_data: class: phpbb\install\module\obtain_data\task\obtain_board_data arguments: - @installer.helper.config - @installer.helper.iohandler - @language.helper.language_file - installer.obtain_data.database: + installer.obtain_data.obtain_database_data: class: phpbb\install\module\obtain_data\task\obtain_database_data arguments: - @installer.helper.database - @installer.helper.config - @installer.helper.iohandler - installer.obtain_data.email: + installer.obtain_data.obtain_email_data: class: phpbb\install\module\obtain_data\task\obtain_email_data arguments: - @installer.helper.config - @installer.helper.iohandler - installer.obtain_data.imagick: + installer.obtain_data.obtain_imagick_path: class: phpbb\install\module\obtain_data\task\obtain_imagick_path arguments: - @installer.helper.config - installer.obtain_data.server: + installer.obtain_data.obtain_server_data: class: phpbb\install\module\obtain_data\task\obtain_server_data arguments: - @installer.helper.config @@ -40,4 +40,4 @@ services: class: phpbb\install\module\obtain_data\module parent: installer.module_base arguments: - - ["installer.obtain_data.admin", "installer.obtain_data.database", "installer.obtain_data.server", "installer.obtain_data.email", "installer.obtain_data.board", "installer.obtain_data.imagick"] + - ["installer.obtain_data.obtain_admin_data", "installer.obtain_data.obtain_database_data", "installer.obtain_data.obtain_server_data", "installer.obtain_data.obtain_email_data", "installer.obtain_data.obtain_board_data", "installer.obtain_data.obtain_imagick_path"] diff --git a/phpBB/config/installer/container/services_install_requirements.yml b/phpBB/config/installer/container/services_install_requirements.yml index afbe341c06..89c517c0cd 100644 --- a/phpBB/config/installer/container/services_install_requirements.yml +++ b/phpBB/config/installer/container/services_install_requirements.yml @@ -1,5 +1,5 @@ services: - installer.requirements.task.filesystem: + installer.requirements.check_filesystem: class: phpbb\install\module\requirements\task\check_filesystem arguments: - @filesystem @@ -7,7 +7,7 @@ services: - %core.root_path% - %core.php_ext% - installer.requirements.task.server: + installer.requirements.check_server_environment: class: phpbb\install\module\requirements\task\check_server_environment arguments: - @installer.helper.database @@ -17,4 +17,4 @@ services: class: phpbb\install\module\requirements\module parent: installer.module_base arguments: - - ["installer.requirements.task.filesystem", "installer.requirements.task.server"] + - ["installer.requirements.check_filesystem", "installer.requirements.check_server_environment"] diff --git a/phpBB/install/installer.php b/phpBB/install/installer.php index 4779bc43c4..cb3dacfbe0 100644 --- a/phpBB/install/installer.php +++ b/phpBB/install/installer.php @@ -91,7 +91,7 @@ class installer /** @var \phpbb\install\module_interface $module */ $module = $this->container->get($name); - $task_count += $module->get_task_count(); + $task_count += $module->get_step_count(); } // Set task count diff --git a/phpBB/install/module/install_data/task/add_bots.php b/phpBB/install/module/install_data/task/add_bots.php index cba228bdba..c31700e97f 100644 --- a/phpBB/install/module/install_data/task/add_bots.php +++ b/phpBB/install/module/install_data/task/add_bots.php @@ -222,6 +222,14 @@ class add_bots extends \phpbb\install\task_base } } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/install_data/task/add_languages.php b/phpBB/install/module/install_data/task/add_languages.php index 8418829ca6..7ffdf4f276 100644 --- a/phpBB/install/module/install_data/task/add_languages.php +++ b/phpBB/install/module/install_data/task/add_languages.php @@ -103,6 +103,14 @@ class add_languages extends \phpbb\install\task_base $insert_buffer->flush(); } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/install_data/task/add_modules.php b/phpBB/install/module/install_data/task/add_modules.php index d47c2cd106..6a77f8973b 100644 --- a/phpBB/install/module/install_data/task/add_modules.php +++ b/phpBB/install/module/install_data/task/add_modules.php @@ -450,6 +450,14 @@ class add_modules extends \phpbb\install\task_base } } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/install_database/task/add_config_settings.php b/phpBB/install/module/install_database/task/add_config_settings.php index be008da1d2..25da36e01d 100644 --- a/phpBB/install/module/install_database/task/add_config_settings.php +++ b/phpBB/install/module/install_database/task/add_config_settings.php @@ -323,6 +323,14 @@ class add_config_settings extends \phpbb\install\task_base } } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/install_database/task/add_default_data.php b/phpBB/install/module/install_database/task/add_default_data.php index c6ca3b5c87..5dbfbb4478 100644 --- a/phpBB/install/module/install_database/task/add_default_data.php +++ b/phpBB/install/module/install_database/task/add_default_data.php @@ -143,6 +143,14 @@ class add_default_data extends \phpbb\install\task_base return ''; } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/install_database/task/create_schema.php b/phpBB/install/module/install_database/task/create_schema.php index e17f0d08d9..7cc521eee8 100644 --- a/phpBB/install/module/install_database/task/create_schema.php +++ b/phpBB/install/module/install_database/task/create_schema.php @@ -196,6 +196,14 @@ class create_schema extends \phpbb\install\task_base } } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/install_filesystem/task/create_config_file.php b/phpBB/install/module/install_filesystem/task/create_config_file.php index b0afa9a7fc..337d401216 100644 --- a/phpBB/install/module/install_filesystem/task/create_config_file.php +++ b/phpBB/install/module/install_filesystem/task/create_config_file.php @@ -217,6 +217,14 @@ class create_config_file extends \phpbb\install\task_base return $config_content; } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/install_finish/task/notify_user.php b/phpBB/install/module/install_finish/task/notify_user.php index c39e561c56..4ab6ec56c6 100644 --- a/phpBB/install/module/install_finish/task/notify_user.php +++ b/phpBB/install/module/install_finish/task/notify_user.php @@ -111,6 +111,14 @@ class notify_user extends \phpbb\install\task_base @unlink($this->phpbb_root_path . 'cache/install_lock'); } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/install_finish/task/populate_migrations.php b/phpBB/install/module/install_finish/task/populate_migrations.php index 1441351bf8..b2a4800f86 100644 --- a/phpBB/install/module/install_finish/task/populate_migrations.php +++ b/phpBB/install/module/install_finish/task/populate_migrations.php @@ -52,6 +52,14 @@ class populate_migrations extends \phpbb\install\task_base $this->migrator->populate_migrations($migrations); } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/obtain_data/module.php b/phpBB/install/module/obtain_data/module.php index 9a3307cd6f..d846593315 100644 --- a/phpBB/install/module/obtain_data/module.php +++ b/phpBB/install/module/obtain_data/module.php @@ -56,7 +56,7 @@ class module extends \phpbb\install\module_base /** * {@inheritdoc} */ - public function get_task_count() + public function get_step_count() { return 0; } diff --git a/phpBB/install/module/obtain_data/task/obtain_admin_data.php b/phpBB/install/module/obtain_data/task/obtain_admin_data.php index 4b070aa19b..b2250e524b 100644 --- a/phpBB/install/module/obtain_data/task/obtain_admin_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_admin_data.php @@ -201,6 +201,14 @@ class obtain_admin_data extends \phpbb\install\task_base implements \phpbb\insta return $data_valid; } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 0; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/obtain_data/task/obtain_board_data.php b/phpBB/install/module/obtain_data/task/obtain_board_data.php index 8a2507f073..821c221123 100644 --- a/phpBB/install/module/obtain_data/task/obtain_board_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_board_data.php @@ -168,6 +168,14 @@ class obtain_board_data extends \phpbb\install\task_base implements \phpbb\insta throw new user_interaction_required_exception; } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 0; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/obtain_data/task/obtain_database_data.php b/phpBB/install/module/obtain_data/task/obtain_database_data.php index 38a6dac0c2..0c1146d9f5 100644 --- a/phpBB/install/module/obtain_data/task/obtain_database_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_database_data.php @@ -253,6 +253,14 @@ class obtain_database_data extends \phpbb\install\task_base implements \phpbb\in return $data_valid; } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 0; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/obtain_data/task/obtain_email_data.php b/phpBB/install/module/obtain_data/task/obtain_email_data.php index 9a3edefd54..ae7526a9e3 100644 --- a/phpBB/install/module/obtain_data/task/obtain_email_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_email_data.php @@ -149,6 +149,14 @@ class obtain_email_data extends \phpbb\install\task_base implements \phpbb\insta } } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 0; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/obtain_data/task/obtain_imagick_path.php b/phpBB/install/module/obtain_data/task/obtain_imagick_path.php index 15570eac43..9f74b61770 100644 --- a/phpBB/install/module/obtain_data/task/obtain_imagick_path.php +++ b/phpBB/install/module/obtain_data/task/obtain_imagick_path.php @@ -71,6 +71,14 @@ class obtain_imagick_path extends \phpbb\install\task_base implements \phpbb\ins $this->config->set('img_imagick', $img_imagick); } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 0; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/obtain_data/task/obtain_server_data.php b/phpBB/install/module/obtain_data/task/obtain_server_data.php index 3f5a1c769f..2d1e37b10e 100644 --- a/phpBB/install/module/obtain_data/task/obtain_server_data.php +++ b/phpBB/install/module/obtain_data/task/obtain_server_data.php @@ -185,6 +185,14 @@ class obtain_server_data extends \phpbb\install\task_base implements \phpbb\inst } } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 0; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/requirements/module.php b/phpBB/install/module/requirements/module.php index aae8c75cbe..f3d1cc71ec 100644 --- a/phpBB/install/module/requirements/module.php +++ b/phpBB/install/module/requirements/module.php @@ -66,7 +66,7 @@ class module extends \phpbb\install\module_base /** * {@inheritdoc} */ - public function get_task_count() + public function get_step_count() { return 0; } diff --git a/phpBB/install/module/requirements/task/check_filesystem.php b/phpBB/install/module/requirements/task/check_filesystem.php index dea59d618e..5b944b8415 100644 --- a/phpBB/install/module/requirements/task/check_filesystem.php +++ b/phpBB/install/module/requirements/task/check_filesystem.php @@ -255,6 +255,14 @@ class check_filesystem extends \phpbb\install\task_base } } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 0; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/requirements/task/check_server_environment.php b/phpBB/install/module/requirements/task/check_server_environment.php index f8dde51883..50efdc55a2 100644 --- a/phpBB/install/module/requirements/task/check_server_environment.php +++ b/phpBB/install/module/requirements/task/check_server_environment.php @@ -172,6 +172,14 @@ class check_server_environment extends \phpbb\install\task_base $this->set_test_passed(false); } + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 0; + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module_base.php b/phpBB/install/module_base.php index 3629903747..179884c039 100644 --- a/phpBB/install/module_base.php +++ b/phpBB/install/module_base.php @@ -173,8 +173,28 @@ abstract class module_base implements module_interface /** * {@inheritdoc} */ - public function get_task_count() + public function get_step_count() { - return sizeof($this->task_collection); + $step_count = 0; + + foreach ($this->task_collection as $task_service_name) + { + $task_service_name_parts = explode('.', $task_service_name); + + if ($task_service_name_parts[0] !== 'installer') + { + // @todo throw an exception + } + + $class_name = '\\phpbb\\install\\module\\' . $task_service_name_parts[1] . '\\task\\' . $task_service_name_parts[2]; + if (!class_exists($class_name)) + { + // @todo throw an exception + } + + $step_count += $class_name::get_step_count(); + } + + return $step_count; } } diff --git a/phpBB/install/module_interface.php b/phpBB/install/module_interface.php index e0ec4e4347..29918f0c34 100644 --- a/phpBB/install/module_interface.php +++ b/phpBB/install/module_interface.php @@ -52,5 +52,5 @@ interface module_interface * * @return int */ - public function get_task_count(); + public function get_step_count(); } diff --git a/phpBB/install/task_interface.php b/phpBB/install/task_interface.php index 6f0a01258f..14cde23a56 100644 --- a/phpBB/install/task_interface.php +++ b/phpBB/install/task_interface.php @@ -15,9 +15,22 @@ namespace phpbb\install; /** * Interface for installer tasks + * + * Note: The task service ID must match up with the namespace and class name. + * For example: if your task is located at \phpbb\install\module\module_name\task\task_name + * then the service ID must be installer.module_name.task_name. */ interface task_interface { + /** + * Returns the number of steps the task contains + * + * This is a helper method to provide a better progress bar for the front-end. + * + * @return int The number of steps that the task contains + */ + static public function get_step_count(); + /** * Checks if the task is essential to install phpBB or it can be skipped * From 1b81bf5b2370c045a6369705d2a11a2b35fe2281 Mon Sep 17 00:00:00 2001 From: CHItA Date: Fri, 5 Jun 2015 17:43:30 +0200 Subject: [PATCH 0448/1676] [ticket/13740] Add better progress handling, also add log messages PHPBB3-13740 --- phpBB/assets/javascript/installer.js | 9 +- .../services_install_obtain_data.yml | 2 + .../services_install_requirements.yml | 2 + .../invalid_service_name_exception.php | 69 +++++++++ .../exception/module_not_found_exception.php | 42 ++++++ .../exception/task_not_found_exception.php | 42 ++++++ phpBB/install/helper/config.php | 11 +- phpBB/install/installer.php | 134 ++++++++++++++---- phpBB/install/module/obtain_data/module.php | 38 ----- phpBB/install/module/requirements/module.php | 11 +- phpBB/install/module_base.php | 126 +++++++++++----- phpBB/language/en/install.php | 15 ++ 12 files changed, 393 insertions(+), 108 deletions(-) create mode 100644 phpBB/install/exception/invalid_service_name_exception.php create mode 100644 phpBB/install/exception/module_not_found_exception.php create mode 100644 phpBB/install/exception/task_not_found_exception.php diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index 8afac0da78..a9a315c0d5 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -204,13 +204,14 @@ * @param progressLimit */ function incrementFiller($progressText, $progressFiller, progressLimit) { + if (currentProgress >= progressLimit || currentProgress >= 100) { + clearInterval(progressTimer); + return; + } + currentProgress++; $progressText.text(currentProgress + '%'); $progressFiller.css('width', currentProgress + '%'); - - if (currentProgress >= progressLimit || currentProgress >= 100) { - clearInterval(progressTimer); - } } /** diff --git a/phpBB/config/installer/container/services_install_obtain_data.yml b/phpBB/config/installer/container/services_install_obtain_data.yml index 2cfe210309..ecbd3d6d37 100644 --- a/phpBB/config/installer/container/services_install_obtain_data.yml +++ b/phpBB/config/installer/container/services_install_obtain_data.yml @@ -41,3 +41,5 @@ services: parent: installer.module_base arguments: - ["installer.obtain_data.obtain_admin_data", "installer.obtain_data.obtain_database_data", "installer.obtain_data.obtain_server_data", "installer.obtain_data.obtain_email_data", "installer.obtain_data.obtain_board_data", "installer.obtain_data.obtain_imagick_path"] + - true + - false diff --git a/phpBB/config/installer/container/services_install_requirements.yml b/phpBB/config/installer/container/services_install_requirements.yml index 89c517c0cd..b1f38713e4 100644 --- a/phpBB/config/installer/container/services_install_requirements.yml +++ b/phpBB/config/installer/container/services_install_requirements.yml @@ -18,3 +18,5 @@ services: parent: installer.module_base arguments: - ["installer.requirements.check_filesystem", "installer.requirements.check_server_environment"] + - true + - false diff --git a/phpBB/install/exception/invalid_service_name_exception.php b/phpBB/install/exception/invalid_service_name_exception.php new file mode 100644 index 0000000000..e64cd2026f --- /dev/null +++ b/phpBB/install/exception/invalid_service_name_exception.php @@ -0,0 +1,69 @@ + + * @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\install\exception; + +class invalid_service_name_exception extends installer_exception +{ + /** + * @var string + */ + private $params; + + /** + * @var string + */ + private $error; + + /** + * Constructor + * + * @param string $error The name of the missing installer module + * @param array $params Additional values for message translation + */ + public function __construct($error, $params = array()) + { + $this->error = $error; + $this->params = $params; + } + + /** + * Returns the language entry's name for the error + * + * @return string + */ + public function get_error() + { + return $this->error; + } + + /** + * Returns parameters for the language entry, if there is any + * + * @return array + */ + public function get_params() + { + return $this->params; + } + + /** + * Returns true, if there are any parameters set + * + * @return bool + */ + public function has_params() + { + return (sizeof($this->params) !== 0); + } +} diff --git a/phpBB/install/exception/module_not_found_exception.php b/phpBB/install/exception/module_not_found_exception.php new file mode 100644 index 0000000000..9fa03fad6e --- /dev/null +++ b/phpBB/install/exception/module_not_found_exception.php @@ -0,0 +1,42 @@ + + * @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\install\exception; + +class module_not_found_exception extends installer_exception +{ + /** + * @var string + */ + private $module_service_name; + + /** + * Constructor + * + * @param string $module_service_name The name of the missing installer module + */ + public function __construct($module_service_name) + { + $this->module_service_name = $module_service_name; + } + + /** + * Returns the missing installer module's service name + * + * @return string + */ + public function get_module_service_name() + { + return $this->module_service_name; + } +} diff --git a/phpBB/install/exception/task_not_found_exception.php b/phpBB/install/exception/task_not_found_exception.php new file mode 100644 index 0000000000..11486cc6b0 --- /dev/null +++ b/phpBB/install/exception/task_not_found_exception.php @@ -0,0 +1,42 @@ + + * @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\install\exception; + +class task_not_found_exception extends installer_exception +{ + /** + * @var string + */ + private $task_service_name; + + /** + * Constructor + * + * @param string $task_service_name The name of the missing installer module + */ + public function __construct($task_service_name) + { + $this->task_service_name = $task_service_name; + } + + /** + * Returns the missing installer task's service name + * + * @return string + */ + public function get_task_service_name() + { + return $this->task_service_name; + } +} diff --git a/phpBB/install/helper/config.php b/phpBB/install/helper/config.php index f39e92b622..0c04b5e950 100644 --- a/phpBB/install/helper/config.php +++ b/phpBB/install/helper/config.php @@ -232,10 +232,17 @@ class config /** * Increments the task progress + * + * @param int $increment_by The amount to increment by */ - public function increment_current_task_progress() + public function increment_current_task_progress($increment_by = 1) { - $this->progress_data['current_task_progress']++; + $this->progress_data['current_task_progress'] += $increment_by; + + if ($this->progress_data['current_task_progress'] > $this->progress_data['max_task_progress']) + { + $this->progress_data['current_task_progress'] = $this->progress_data['max_task_progress']; + } } /** diff --git a/phpBB/install/installer.php b/phpBB/install/installer.php index cb3dacfbe0..1c7c9c8a92 100644 --- a/phpBB/install/installer.php +++ b/phpBB/install/installer.php @@ -13,15 +13,24 @@ namespace phpbb\install; +use phpbb\install\exception\invalid_service_name_exception; +use phpbb\install\exception\module_not_found_exception; +use phpbb\install\exception\task_not_found_exception; +use phpbb\install\exception\user_interaction_required_exception; +use phpbb\install\helper\config; +use phpbb\install\helper\iohandler\iohandler_interface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + class installer { /** - * @var \Symfony\Component\DependencyInjection\ContainerInterface + * @var ContainerInterface */ protected $container; /** - * @var \phpbb\install\helper\config + * @var config */ protected $install_config; @@ -31,17 +40,24 @@ class installer protected $installer_modules; /** - * @var \phpbb\install\helper\iohandler\iohandler_interface + * @var iohandler_interface */ protected $iohandler; + /** + * Stores the number of steps that a given module has + * + * @var array + */ + protected $module_step_count; + /** * Constructor * - * @param \phpbb\install\helper\config $config Installer config handler - * @param \Symfony\Component\DependencyInjection\ContainerInterface $container Dependency injection container + * @param config $config Installer config handler + * @param ContainerInterface $container Dependency injection container */ - public function __construct(\phpbb\install\helper\config $config, \Symfony\Component\DependencyInjection\ContainerInterface $container) + public function __construct(config $config, ContainerInterface $container) { $this->install_config = $config; $this->container = $container; @@ -66,9 +82,9 @@ class installer /** * Sets input-output handler objects * - * @param helper\iohandler\iohandler_interface $iohandler + * @param iohandler_interface $iohandler */ - public function set_iohandler(\phpbb\install\helper\iohandler\iohandler_interface $iohandler) + public function set_iohandler(iohandler_interface $iohandler) { $this->iohandler = $iohandler; } @@ -84,24 +100,44 @@ class installer // Recover install progress $module_index = $this->recover_progress(); - // Count all tasks in the current installer modules - $task_count = 0; - foreach ($this->installer_modules as $name) - { - /** @var \phpbb\install\module_interface $module */ - $module = $this->container->get($name); - - $task_count += $module->get_step_count(); - } - - // Set task count - $this->install_config->set_task_progress_count($task_count); - $this->iohandler->set_task_count($task_count); - + // Variable used to check if the install process have been finished $install_finished = false; + // Flag used by exception handling, whether or not we need to flush output buffer once again + $flush_messages = false; + try { + if ($this->install_config->get_task_progress_count() === 0) + { + // Count all tasks in the current installer modules + $step_count = 0; + foreach ($this->installer_modules as $index => $name) + { + try + { + /** @var \phpbb\install\module_interface $module */ + $module = $this->container->get($name); + } + catch (InvalidArgumentException $e) + { + throw new module_not_found_exception($name); + } + + $module_step_count = $module->get_step_count(); + $step_count += $module_step_count; + $this->module_step_count[$index] = $module_step_count; + } + + // Set task count + $this->install_config->set_task_progress_count($step_count); + } + + // Set up progress information + $this->iohandler->set_task_count( + $this->install_config->get_task_progress_count() + ); + // Run until there are available resources while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0) { @@ -117,14 +153,26 @@ class installer $this->install_config->set_active_module($module_service_name, $module_index); // Get module from container - /** @var \phpbb\install\module_interface $module */ - $module = $this->container->get($module_service_name); + try + { + /** @var \phpbb\install\module_interface $module */ + $module = $this->container->get($module_service_name); + } + catch (InvalidArgumentException $e) + { + throw new module_not_found_exception($module_service_name); + } $module_index++; // Check if module should be executed if (!$module->is_essential() && !$module->check_requirements()) { + $this->iohandler->add_log_message(array( + 'SKIP_MODULE', + $module_service_name, + )); + $this->install_config->increment_current_task_progress($this->module_step_count[$module_index - 1]); continue; } @@ -144,10 +192,46 @@ class installer // @todo: Send refresh request } } - catch (\phpbb\install\exception\user_interaction_required_exception $e) + catch (user_interaction_required_exception $e) { // @todo handle exception } + catch (module_not_found_exception $e) + { + $this->iohandler->add_error_message('MODULE_NOT_FOUND', array( + 'MODULE_NOT_FOUND_DESCRIPTION', + $e->get_module_service_name(), + )); + $flush_messages = true; + } + catch (task_not_found_exception $e) + { + $this->iohandler->add_error_message('TASK_NOT_FOUND', array( + 'TASK_NOT_FOUND_DESCRIPTION', + $e->get_task_service_name(), + )); + $flush_messages = true; + } + catch (invalid_service_name_exception $e) + { + if ($e->has_params()) + { + $msg = $e->get_params(); + array_unshift($msg, $e->get_error()); + } + else + { + $msg = $e->get_error(); + } + + $this->iohandler->add_error_message($msg); + $flush_messages = true; + } + + if ($flush_messages) + { + $this->iohandler->send_response(); + } // Save install progress $this->install_config->save_config(); diff --git a/phpBB/install/module/obtain_data/module.php b/phpBB/install/module/obtain_data/module.php index d846593315..a181c5231a 100644 --- a/phpBB/install/module/obtain_data/module.php +++ b/phpBB/install/module/obtain_data/module.php @@ -15,44 +15,6 @@ namespace phpbb\install\module\obtain_data; class module extends \phpbb\install\module_base { - /** - * {@inheritdoc} - */ - public function run() - { - // Recover install progress - $task_index = $this->recover_progress(); - - // Run until there are available resources - while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0) - { - // Check if task exists - if (!isset($this->task_collection[$task_index])) - { - break; - } - - // Recover task to be executed - /** @var \phpbb\install\task_interface $task */ - $task = $this->container->get($this->task_collection[$task_index]); - - // Iterate to the next task - $task_index++; - - // Check if we can run the task - if (!$task->is_essential() && !$task->check_requirements()) - { - continue; - } - - $task->run(); - - // Log install progress - $current_task_index = $task_index - 1; - $this->install_config->set_finished_task($this->task_collection[$current_task_index], $current_task_index); - } - } - /** * {@inheritdoc} */ diff --git a/phpBB/install/module/requirements/module.php b/phpBB/install/module/requirements/module.php index f3d1cc71ec..5de6bd70b9 100644 --- a/phpBB/install/module/requirements/module.php +++ b/phpBB/install/module/requirements/module.php @@ -34,8 +34,15 @@ class module extends \phpbb\install\module_base } // Recover task to be executed - /** @var \phpbb\install\task_interface $task */ - $task = $this->container->get($this->task_collection[$task_index]); + try + { + /** @var \phpbb\install\task_interface $task */ + $task = $this->container->get($this->task_collection[$task_index]); + } + catch (InvalidArgumentException $e) + { + throw new task_not_found_exception($this->task_collection[$task_index]); + } // Iterate to the next task $task_index++; diff --git a/phpBB/install/module_base.php b/phpBB/install/module_base.php index 179884c039..ac7ce7583a 100644 --- a/phpBB/install/module_base.php +++ b/phpBB/install/module_base.php @@ -13,23 +13,30 @@ namespace phpbb\install; +use phpbb\install\exception\invalid_service_name_exception; +use phpbb\install\exception\task_not_found_exception; +use phpbb\install\helper\iohandler\iohandler_interface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use phpbb\install\helper\config; + /** * Base class for installer module */ abstract class module_base implements module_interface { /** - * @var \Symfony\Component\DependencyInjection\ContainerInterface + * @var ContainerInterface */ protected $container; /** - * @var \phpbb\install\helper\config + * @var config */ protected $install_config; /** - * @var \phpbb\install\helper\iohandler\iohandler_interface + * @var iohandler_interface */ protected $iohandler; @@ -45,26 +52,33 @@ abstract class module_base implements module_interface */ protected $task_collection; + /** + * @var bool + */ + protected $allow_progress_bar; + /** * Installer module constructor * - * @param array $tasks array of installer tasks for installer module - * @param bool $essential flag that indicates if module is essential or not + * @param array $tasks array of installer tasks for installer module + * @param bool $essential flag indicating whether the module is essential or not + * @param bool $allow_progress_bar flag indicating whether or not to send progress information from within the module */ - public function __construct(array $tasks, $essential = true) + public function __construct(array $tasks, $essential = true, $allow_progress_bar = true) { - $this->task_collection = $tasks; - $this->is_essential = $essential; + $this->task_collection = $tasks; + $this->is_essential = $essential; + $this->allow_progress_bar = $allow_progress_bar; } /** * Dependency getter * - * @param \Symfony\Component\DependencyInjection\ContainerInterface $container - * @param \phpbb\install\helper\config $config - * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler + * @param ContainerInterface $container + * @param config $config + * @param iohandler_interface $iohandler */ - public function setup(\Symfony\Component\DependencyInjection\ContainerInterface $container, \phpbb\install\helper\config $config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler) + public function setup(ContainerInterface $container, config $config, iohandler_interface $iohandler) { $this->container = $container; $this->install_config = $config; @@ -107,32 +121,55 @@ abstract class module_base implements module_interface } // Recover task to be executed - /** @var \phpbb\install\task_interface $task */ - $task = $this->container->get($this->task_collection[$task_index]); + try + { + /** @var \phpbb\install\task_interface $task */ + $task = $this->container->get($this->task_collection[$task_index]); + } + catch (InvalidArgumentException $e) + { + throw new task_not_found_exception($this->task_collection[$task_index]); + } // Send progress information - $this->iohandler->set_progress( - $task->get_task_lang_name(), - $this->install_config->get_current_task_progress() - ); + if ($this->allow_progress_bar) + { + $this->iohandler->set_progress( + $task->get_task_lang_name(), + $this->install_config->get_current_task_progress() + ); + } // Iterate to the next task $task_index++; - $this->install_config->increment_current_task_progress(); // Check if we can run the task if (!$task->is_essential() && !$task->check_requirements()) { + $this->iohandler->add_log_message(array( + 'SKIP_TASK', + $this->task_collection[$task_index], + )); + $class_name = $this->get_class_from_service_name($this->task_collection[$task_index - 1]); + $this->install_config->increment_current_task_progress($class_name::get_step_count()); continue; } + if ($this->allow_progress_bar) + { + $this->install_config->increment_current_task_progress(); + } + $task->run(); - // Send progress info - $this->iohandler->set_progress( - $task->get_task_lang_name(), - $this->install_config->get_current_task_progress() - ); + // Send progress information + if ($this->allow_progress_bar) + { + $this->iohandler->set_progress( + $task->get_task_lang_name(), + $this->install_config->get_current_task_progress() + ); + } $this->iohandler->send_response(); @@ -179,22 +216,37 @@ abstract class module_base implements module_interface foreach ($this->task_collection as $task_service_name) { - $task_service_name_parts = explode('.', $task_service_name); - - if ($task_service_name_parts[0] !== 'installer') - { - // @todo throw an exception - } - - $class_name = '\\phpbb\\install\\module\\' . $task_service_name_parts[1] . '\\task\\' . $task_service_name_parts[2]; - if (!class_exists($class_name)) - { - // @todo throw an exception - } - + $class_name = $this->get_class_from_service_name($task_service_name); $step_count += $class_name::get_step_count(); } return $step_count; } + + /** + * Returns the name of the class form the service name + * + * @param string $task_service_name Name of the service + * + * @return string Name of the class + * + * @throws invalid_service_name_exception When the service name does not meet the requirements described in task_interface + */ + protected function get_class_from_service_name($task_service_name) + { + $task_service_name_parts = explode('.', $task_service_name); + + if ($task_service_name_parts[0] !== 'installer') + { + throw new invalid_service_name_exception('TASK_SERVICE_INSTALLER_MISSING'); + } + + $class_name = '\\phpbb\\install\\module\\' . $task_service_name_parts[1] . '\\task\\' . $task_service_name_parts[2]; + if (!class_exists($class_name)) + { + throw new invalid_service_name_exception('TASK_CLASS_NOT_FOUND', array($task_service_name, $class_name)); + } + + return $class_name; + } } diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index e3c4b859f0..92251a4992 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -249,3 +249,18 @@ $lang = array_merge($lang, array( // Installer general progress messages 'INSTALLER_FINISHED' => 'The installer has finished successfully', )); + +// Installer's general messages +$lang = array_merge($lang, array( + 'MODULE_NOT_FOUND' => 'Module not found', + 'MODULE_NOT_FOUND_DESCRIPTION' => 'No module is found under the service definition “%s†is not defined.', + + 'TASK_NOT_FOUND' => 'Task not found', + 'TASK_NOT_FOUND_DESCRIPTION' => 'No task is found under the service definition “%s†is not defined.', + + 'SKIP_MODULE' => 'Skip “%s†module', + 'SKIP_TASK' => 'Skip “%s†task', + + 'TASK_SERVICE_INSTALLER_MISSING' => 'All installer task services should start with “installerâ€', + 'TASK_CLASS_NOT_FOUND' => 'Installer task service definition is invalid. Service name “%1$s†given, the expected class namespace is “%2$s†for that. For more information please see the documentation of task_interface.', +)); From db4cfa7df62d5911bc5a0edcdc59236c39aede08 Mon Sep 17 00:00:00 2001 From: CHItA Date: Thu, 11 Jun 2015 19:32:11 +0200 Subject: [PATCH 0449/1676] [ticket/13740] Add navigation bar support for the installer Also added various UI elements and texts. [ci skip] PHPBB3-13740 --- phpBB/adm/style/install_header.html | 2 +- phpBB/adm/style/installer_form.html | 4 + phpBB/adm/style/installer_install.html | 6 +- phpBB/assets/javascript/installer.js | 61 ++++++++-- .../container/services_install_controller.yml | 3 + .../services_install_requirements.yml | 1 + phpBB/install/controller/helper.php | 24 +++- phpBB/install/controller/install.php | 108 ++++++++++++++---- ...{install_index.php => installer_index.php} | 2 +- ...nstaller_config_not_writable_exception.php | 22 ++++ .../user_interaction_required_exception.php | 3 + phpBB/install/helper/config.php | 49 +++++++- .../helper/iohandler/ajax_iohandler.php | 51 +++++++++ phpBB/install/helper/iohandler/factory.php | 4 + .../helper/iohandler/iohandler_interface.php | 19 +++ .../helper/navigation/install_navigation.php | 24 +++- .../helper/navigation/navigation_provider.php | 27 ++++- phpBB/install/installer.php | 34 +++++- phpBB/install/module/install_data/module.php | 8 +- .../module/install_database/module.php | 8 +- .../module/install_filesystem/module.php | 8 +- .../install/module/install_finish/module.php | 8 +- phpBB/install/module/obtain_data/module.php | 8 ++ phpBB/install/module/requirements/module.php | 17 +++ phpBB/install/module_base.php | 4 +- phpBB/install/module_interface.php | 7 ++ phpBB/language/en/install.php | 37 ++++++ 27 files changed, 495 insertions(+), 54 deletions(-) rename phpBB/install/controller/{install_index.php => installer_index.php} (98%) create mode 100644 phpBB/install/exception/installer_config_not_writable_exception.php diff --git a/phpBB/adm/style/install_header.html b/phpBB/adm/style/install_header.html index 6f7f129d39..b162fa3e89 100644 --- a/phpBB/adm/style/install_header.html +++ b/phpBB/adm/style/install_header.html @@ -43,7 +43,7 @@ id="activemenu">{l_block1.L_TITLE} - id="activemenu"> class="completed">{l_block2.L_TITLE} + id="activemenu"> class="completed" id="installer-stage-{l_block2.STAGE_NAME}">{l_block2.L_TITLE}

            diff --git a/phpBB/adm/style/installer_form.html b/phpBB/adm/style/installer_form.html index dbcf3c19f8..3cb4185bc6 100644 --- a/phpBB/adm/style/installer_form.html +++ b/phpBB/adm/style/installer_form.html @@ -1,6 +1,8 @@
            +
            + @@ -40,7 +42,9 @@ +
            +
            {L_SUBMIT} diff --git a/phpBB/adm/style/installer_install.html b/phpBB/adm/style/installer_install.html index 7d62075c62..7700c79036 100644 --- a/phpBB/adm/style/installer_install.html +++ b/phpBB/adm/style/installer_install.html @@ -1,11 +1,11 @@ -

            {L_INSTALL}

            -{CONTENT} +

            {TITLE}

            +

            {CONTENT}

            {L_SUBMIT} - +
            diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index a9a315c0d5..eafcd78f47 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -95,6 +95,45 @@ interceptFormSubmit($form); } + /** + * Handles navigation status updates + * + * @param navObj + */ + function updateNavbarStatus(navObj) { + var navID, $stage, $stageListItem, $active; + $active = $('#activemenu'); + + if (navObj.hasOwnProperty('finished')) { + // This should be an Array + var navItems = navObj.finished; + + for (var i = 0; i < navItems.length; i++) { + navID = 'installer-stage-' + navItems[i]; + $stage = $('#' + navID); + $stageListItem = $stage.parent(); + + if ($active.length && $active.is($stageListItem)) { + $active.removeAttr('id'); + } + + $stage.addClass('completed'); + } + } + + if (navObj.hasOwnProperty('active')) { + navID = 'installer-stage-' + navObj.active; + $stage = $('#' + navID); + $stageListItem = $stage.parent(); + + if ($active.length && !$active.is($stageListItem)) { + $active.removeAttr('id'); + } + + $stageListItem.attr('id', 'activemenu'); + } + } + /** * Renders progress bar * @@ -166,6 +205,10 @@ if (responseObject.hasOwnProperty('progress')) { setProgress(responseObject.progress); } + + if (responseObject.hasOwnProperty('nav')) { + updateNavbarStatus(responseObject.nav); + } } /** @@ -231,6 +274,14 @@ }, 10); } + /** + * Resets the polling timer + */ + function resetPolling() { + clearInterval(pollTimer); + nextReadPosition = 0; + } + /** * Sets up timer for processing the streamed HTTP response * @@ -240,15 +291,7 @@ resetPolling(); pollTimer = setInterval(function () { pollContent(xhReq); - }, 500); - } - - /** - * Resets the polling timer - */ - function resetPolling() { - clearInterval(pollTimer); - nextReadPosition = 0; + }, 250); } /** diff --git a/phpBB/config/installer/container/services_install_controller.yml b/phpBB/config/installer/container/services_install_controller.yml index 5eea133590..6e6ef4acea 100644 --- a/phpBB/config/installer/container/services_install_controller.yml +++ b/phpBB/config/installer/container/services_install_controller.yml @@ -23,7 +23,10 @@ services: class: phpbb\install\controller\install arguments: - @phpbb.installer.controller.helper + - @installer.helper.config - @installer.helper.iohandler_factory + - @installer.navigation.provider + - @language - @template - @request - @installer.installer.install diff --git a/phpBB/config/installer/container/services_install_requirements.yml b/phpBB/config/installer/container/services_install_requirements.yml index b1f38713e4..c93856837d 100644 --- a/phpBB/config/installer/container/services_install_requirements.yml +++ b/phpBB/config/installer/container/services_install_requirements.yml @@ -13,6 +13,7 @@ services: - @installer.helper.database - @installer.helper.iohandler +# Please note, that the name of this module is hard coded in the installer service installer.module.requirements_install: class: phpbb\install\module\requirements\module parent: installer.module_base diff --git a/phpBB/install/controller/helper.php b/phpBB/install/controller/helper.php index 7a5e20406d..0df1ae71a4 100644 --- a/phpBB/install/controller/helper.php +++ b/phpBB/install/controller/helper.php @@ -157,13 +157,25 @@ class helper { // @todo Sort navs by order - foreach ($entry[0] as $sub_entry) + foreach ($entry[0] as $name => $sub_entry) { - $this->template->assign_block_vars('l_block1', array( - 'L_TITLE' => $this->language->lang($sub_entry['label']), - 'S_SELECTED' => (isset($sub_entry['route']) && $sub_entry['route'] === $this->request->get('_route')), - 'U_TITLE' => $this->route($sub_entry['route']), - )); + if (isset($sub_entry['stage']) && $sub_entry['stage'] === true) + { + $this->template->assign_block_vars('l_block2', array( + 'L_TITLE' => $this->language->lang($sub_entry['label']), + 'S_SELECTED' => (isset($sub_entry['selected']) && $sub_entry['selected'] === true), + 'S_COMPLETE' => (isset($sub_entry['completed']) && $sub_entry['completed'] === true), + 'STAGE_NAME' => $name, + )); + } + else + { + $this->template->assign_block_vars('l_block1', array( + 'L_TITLE' => $this->language->lang($sub_entry['label']), + 'S_SELECTED' => (isset($sub_entry['route']) && $sub_entry['route'] === $this->request->get('_route')), + 'U_TITLE' => $this->route($sub_entry['route']), + )); + } } } } diff --git a/phpBB/install/controller/install.php b/phpBB/install/controller/install.php index 4021c5625b..c1329b6456 100644 --- a/phpBB/install/controller/install.php +++ b/phpBB/install/controller/install.php @@ -13,7 +13,16 @@ namespace phpbb\install\controller; +use phpbb\install\helper\config; +use phpbb\install\helper\navigation\navigation_provider; use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpFoundation\Response; +use phpbb\install\helper\iohandler\factory; +use phpbb\install\controller\helper; +use phpbb\template\template; +use phpbb\request\request_interface; +use phpbb\install\installer; +use phpbb\language\language; /** * Controller for installing phpBB @@ -21,51 +30,72 @@ use Symfony\Component\HttpFoundation\StreamedResponse; class install { /** - * @var \phpbb\install\controller\helper + * @var helper */ protected $controller_helper; /** - * @var \phpbb\install\helper\iohandler\factory + * @var config + */ + protected $installer_config; + + /** + * @var factory */ protected $iohandler_factory; /** - * @var \phpbb\template\template + * @var navigation_provider + */ + protected $menu_provider; + + /** + * @var language + */ + protected $language; + + /** + * @var template */ protected $template; /** - * @var \phpbb\request\request_interface + * @var request_interface */ protected $request; /** - * @var \phpbb\install\installer + * @var installer */ protected $installer; /** * Constructor * - * @param helper $helper - * @param \phpbb\install\helper\iohandler\factory $factory - * @param \phpbb\request\request_interface $request - * @param \phpbb\install\installer $installer + * @param helper $helper + * @param config $install_config + * @param factory $factory + * @param navigation_provider $nav_provider + * @param language $language + * @param request_interface $request + * @param installer $installer */ - public function __construct(helper $helper, \phpbb\install\helper\iohandler\factory $factory, \phpbb\template\template $template, \phpbb\request\request_interface $request, \phpbb\install\installer $installer) + public function __construct(helper $helper, config $install_config, factory $factory, navigation_provider $nav_provider, language $language, template $template, request_interface $request, installer $installer) { - $this->controller_helper = $helper; - $this->iohandler_factory = $factory; - $this->template = $template; - $this->request = $request; - $this->installer = $installer; + $this->controller_helper = $helper; + $this->installer_config = $install_config; + $this->iohandler_factory = $factory; + $this->menu_provider = $nav_provider; + $this->language = $language; + $this->template = $template; + $this->request = $request; + $this->installer = $installer; } /** * Controller logic * - * @return \Symfony\Component\HttpFoundation\Response|StreamedResponse + * @return Response|StreamedResponse */ public function handle() { @@ -86,13 +116,38 @@ class install } // Set the appropriate input-output handler - //$this->installer->set_iohandler($this->iohandler_factory->get()); + $this->installer->set_iohandler($this->iohandler_factory->get()); + + // Set up navigation + $nav_data = $this->installer_config->get_navigation_data(); + /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */ + $iohandler = $this->iohandler_factory->get(); + + // Set active navigation stage + if (isset($nav_data['active']) && is_array($nav_data['active'])) + { + $iohandler->set_active_stage_menu($nav_data['active']); + $this->menu_provider->set_nav_property($nav_data['active'], array( + 'selected' => true, + 'completed' => false, + )); + } + + // Set finished navigation stages + if (isset($nav_data['finished']) && is_array($nav_data['finished'])) + { + foreach ($nav_data['finished'] as $finished_stage) + { + $iohandler->set_finished_stage_menu($finished_stage); + $this->menu_provider->set_nav_property($finished_stage, array( + 'selected' => false, + 'completed' => true, + )); + } + } if ($this->request->is_ajax()) { - // @todo: remove this line, and use the above - $this->installer->set_iohandler($this->iohandler_factory->get()); - $installer = $this->installer; $response = new StreamedResponse(); $response->setCallback(function() use ($installer) { @@ -106,9 +161,20 @@ class install // Determine whether the installation was started or not if (true) { + // Set active stage + $this->menu_provider->set_nav_property( + array('install', 0, 'introduction'), + array( + 'selected' => true, + 'completed' => false, + ) + ); + // If not, let's render the welcome page $this->template->assign_vars(array( - 'SHOW_INSTALL_START_FORM' => true, + 'SHOW_INSTALL_START_FORM' => true, + 'TITLE' => $this->language->lang('INSTALL_INTRO'), + 'CONTENT' => $this->language->lang('INSTALL_INTRO_BODY'), )); return $this->controller_helper->render('installer_install.html', 'INSTALL'); } diff --git a/phpBB/install/controller/install_index.php b/phpBB/install/controller/installer_index.php similarity index 98% rename from phpBB/install/controller/install_index.php rename to phpBB/install/controller/installer_index.php index c61d68f7fb..3d5224f1be 100644 --- a/phpBB/install/controller/install_index.php +++ b/phpBB/install/controller/installer_index.php @@ -13,7 +13,7 @@ namespace phpbb\install\controller; -class install_index +class installer_index { /** * @var helper diff --git a/phpBB/install/exception/installer_config_not_writable_exception.php b/phpBB/install/exception/installer_config_not_writable_exception.php new file mode 100644 index 0000000000..3f3b03f178 --- /dev/null +++ b/phpBB/install/exception/installer_config_not_writable_exception.php @@ -0,0 +1,22 @@ + + * @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\install\exception; + +/** + * Exception for the event when installer config is not writable to disk + */ +class installer_config_not_writable_exception extends installer_exception +{ + +} diff --git a/phpBB/install/exception/user_interaction_required_exception.php b/phpBB/install/exception/user_interaction_required_exception.php index 0aaae648cf..d65a448841 100644 --- a/phpBB/install/exception/user_interaction_required_exception.php +++ b/phpBB/install/exception/user_interaction_required_exception.php @@ -15,6 +15,9 @@ namespace phpbb\install\exception; /** * This exception should be thrown when user interaction is inevitable + * + * Note: Please note that the output should already be setup for the user + * when you use throw this exception */ class user_interaction_required_exception extends installer_exception { diff --git a/phpBB/install/helper/config.php b/phpBB/install/helper/config.php index 0c04b5e950..5c1348c06d 100644 --- a/phpBB/install/helper/config.php +++ b/phpBB/install/helper/config.php @@ -13,6 +13,8 @@ namespace phpbb\install\helper; +use phpbb\install\exception\installer_config_not_writable_exception; + /** * Stores common settings and installation status */ @@ -64,6 +66,13 @@ class config */ protected $system_data; + /** + * Array containing navigation bar information + * + * @var array + */ + protected $navigation_data; + /** * Constructor */ @@ -74,6 +83,7 @@ class config $this->phpbb_root_path = $phpbb_root_path; // Set up data arrays + $this->navigation_data = array(); $this->installer_config = array(); $this->system_data = array(); $this->progress_data = array( @@ -206,6 +216,7 @@ class config $this->installer_config = $unserialized_data['installer_config']; $this->progress_data = $unserialized_data['progress_data']; + $this->navigation_data = $unserialized_data['navigation_data']; } /** @@ -217,6 +228,7 @@ class config $save_array = array( 'installer_config' => $this->installer_config, 'progress_data' => $this->progress_data, + 'navigation_data' => $this->navigation_data, ); // Create file content @@ -225,7 +237,12 @@ class config $file_content .= "\n"; // Dump file_content to disk - $fp = fopen($this->install_config_file, 'w'); + $fp = @fopen($this->install_config_file, 'w'); + if (!$fp) + { + throw new installer_config_not_writable_exception(); + } + fwrite($fp, $file_content); fclose($fp); } @@ -285,6 +302,36 @@ class config return $this->progress_data['max_task_progress']; } + /** + * Marks stage as completed in the navigation bar + * + * @param array $nav_path Array to the navigation elem + */ + public function set_finished_navigation_stage($nav_path) + { + $this->navigation_data['finished'][] = $nav_path; + } + + /** + * Marks stage as active in the navigation bar + * + * @param array $nav_path Array to the navigation elem + */ + public function set_active_navigation_stage($nav_path) + { + $this->navigation_data['active'] = $nav_path; + } + + /** + * Returns navigation data + * + * @return array + */ + public function get_navigation_data() + { + return $this->navigation_data; + } + /** * Filling up system_data array */ diff --git a/phpBB/install/helper/iohandler/ajax_iohandler.php b/phpBB/install/helper/iohandler/ajax_iohandler.php index 960dd615b5..71571fecba 100644 --- a/phpBB/install/helper/iohandler/ajax_iohandler.php +++ b/phpBB/install/helper/iohandler/ajax_iohandler.php @@ -33,6 +33,16 @@ class ajax_iohandler extends iohandler_base */ protected $form; + /** + * @var bool + */ + protected $request_client_refresh; + + /** + * @var array + */ + protected $nav_data; + /** * Constructor * @@ -44,6 +54,7 @@ class ajax_iohandler extends iohandler_base $this->request = $request; $this->template = $template; $this->form = ''; + $this->nav_data = array(); parent::__construct(); } @@ -89,6 +100,8 @@ class ajax_iohandler extends iohandler_base // This code is pretty ugly... but works // + $this->template->assign_var('S_FORM_ELEM_COUNT', sizeof($form)); + $this->template->assign_block_vars('options', array( 'LEGEND' => $this->language->lang($title), 'S_LEGEND' => true, @@ -187,9 +200,21 @@ class ajax_iohandler extends iohandler_base ); } + if (!empty($this->nav_data)) + { + $json_array['nav'] = $this->nav_data; + } + $this->errors = array(); $this->warnings = array(); $this->logs = array(); + $this->nav_data = array(); + + if ($this->request_client_refresh) + { + $json_array['refresh'] = true; + $this->request_client_refresh = false; + } return $json_array; } @@ -203,6 +228,32 @@ class ajax_iohandler extends iohandler_base $this->send_response(); } + /** + * {@inheritdoc} + */ + public function request_refresh() + { + $this->request_client_refresh = true; + } + + /** + * {@inheritdoc} + */ + public function set_active_stage_menu($menu_path) + { + $this->nav_data['active'] = $menu_path[sizeof($menu_path) - 1]; + $this->send_response(); + } + + /** + * {@inheritdoc} + */ + public function set_finished_stage_menu($menu_path) + { + $this->nav_data['finished'][] = $menu_path[sizeof($menu_path) - 1]; + $this->send_response(); + } + /** * Callback function for language replacing * diff --git a/phpBB/install/helper/iohandler/factory.php b/phpBB/install/helper/iohandler/factory.php index 0b59e5ec63..0af75b78ae 100644 --- a/phpBB/install/helper/iohandler/factory.php +++ b/phpBB/install/helper/iohandler/factory.php @@ -64,6 +64,10 @@ class factory case 'ajax': return $this->container->get('installer.helper.iohandler_ajax'); break; + case 'nojs': + // @todo replace this + return $this->container->get('installer.helper.iohandler_ajax'); + break; default: throw new iohandler_not_implemented_exception(); break; diff --git a/phpBB/install/helper/iohandler/iohandler_interface.php b/phpBB/install/helper/iohandler/iohandler_interface.php index 387a8617b9..c40fea24ce 100644 --- a/phpBB/install/helper/iohandler/iohandler_interface.php +++ b/phpBB/install/helper/iohandler/iohandler_interface.php @@ -123,4 +123,23 @@ interface iohandler_interface * @param int $task_number Position of the current task in the task queue */ public function set_progress($task_lang_key, $task_number); + + /** + * Sends refresh request to the client + */ + public function request_refresh(); + + /** + * Marks stage as active in the navigation bar + * + * @param array $menu_path Array to the navigation elem + */ + public function set_active_stage_menu($menu_path); + + /** + * Marks stage as completed in the navigation bar + * + * @param array $menu_path Array to the navigation elem + */ + public function set_finished_stage_menu($menu_path); } diff --git a/phpBB/install/helper/navigation/install_navigation.php b/phpBB/install/helper/navigation/install_navigation.php index 3e29e55038..1389f11fa0 100644 --- a/phpBB/install/helper/navigation/install_navigation.php +++ b/phpBB/install/helper/navigation/install_navigation.php @@ -21,7 +21,29 @@ class install_navigation implements navigation_interface 'install' => array( 'label' => 'INSTALL', 'route' => 'phpbb_installer_install', - 'order' => 0, + 'order' => 1, + array( + 'introduction' => array( + 'label' => 'INTRODUCTION_TITLE', + 'stage' => true, + 'order' => 0, + ), + 'requirements' => array( + 'label' => 'STAGE_REQUIREMENTS', + 'stage' => true, + 'order' => 1, + ), + 'obtain_data' => array( + 'label' => 'STAGE_OBTAIN_DATA', + 'stage' => true, + 'order' => 2, + ), + 'install' => array( + 'label' => 'STAGE_INSTALL', + 'stage' => true, + 'order' => 3, + ), + ), ), ); } diff --git a/phpBB/install/helper/navigation/navigation_provider.php b/phpBB/install/helper/navigation/navigation_provider.php index ddb2509348..1f58cbea83 100644 --- a/phpBB/install/helper/navigation/navigation_provider.php +++ b/phpBB/install/helper/navigation/navigation_provider.php @@ -13,6 +13,8 @@ namespace phpbb\install\helper\navigation; +use phpbb\di\service_collection; + /** * Installers navigation provider */ @@ -26,9 +28,9 @@ class navigation_provider /** * Constructor * - * @param \phpbb\di\service_collection $plugins + * @param service_collection $plugins */ - public function __construct(\phpbb\di\service_collection $plugins) + public function __construct(service_collection $plugins) { $this->menu_collection = array(); @@ -59,6 +61,27 @@ class navigation_provider $this->merge($nav_arry, $this->menu_collection); } + /** + * Set a property in the navigation array + * + * @param array $nav_element Array to the navigation elem + * @param array $property_array Array with the properties to set + */ + public function set_nav_property($nav_element, $property_array) + { + $array_pointer = array(); + $array_root_pointer = &$array_pointer; + foreach ($nav_element as $array_path) + { + $array_pointer[$array_path] = array(); + $array_pointer = &$array_pointer[$array_path]; + } + + $array_pointer = $property_array; + + $this->merge($array_root_pointer, $this->menu_collection); + } + /** * Recursive array merge * diff --git a/phpBB/install/installer.php b/phpBB/install/installer.php index 1c7c9c8a92..f5da898a00 100644 --- a/phpBB/install/installer.php +++ b/phpBB/install/installer.php @@ -13,6 +13,7 @@ namespace phpbb\install; +use phpbb\install\exception\installer_config_not_writable_exception; use phpbb\install\exception\invalid_service_name_exception; use phpbb\install\exception\module_not_found_exception; use phpbb\install\exception\task_not_found_exception; @@ -106,6 +107,10 @@ class installer // Flag used by exception handling, whether or not we need to flush output buffer once again $flush_messages = false; + // We are installing something, so the introduction stage can go now... + $this->install_config->set_finished_navigation_stage(array('install', 0, 'introduction')); + $this->iohandler->set_finished_stage_menu(array('install', 0, 'introduction')); + try { if ($this->install_config->get_task_progress_count() === 0) @@ -168,6 +173,9 @@ class installer // Check if module should be executed if (!$module->is_essential() && !$module->check_requirements()) { + $this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path()); + $this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path()); + $this->iohandler->add_log_message(array( 'SKIP_MODULE', $module_service_name, @@ -176,8 +184,15 @@ class installer continue; } + // Set the correct stage in the navigation bar + $this->install_config->set_active_navigation_stage($module->get_navigation_stage_path()); + $this->iohandler->set_active_stage_menu($module->get_navigation_stage_path()); + $module->run(); + $this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path()); + $this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path()); + // Clear task progress $this->install_config->set_finished_task('', 0); } @@ -189,12 +204,12 @@ class installer } else { - // @todo: Send refresh request + $this->iohandler->request_refresh(); } } catch (user_interaction_required_exception $e) { - // @todo handle exception + // Do nothing } catch (module_not_found_exception $e) { @@ -234,7 +249,20 @@ class installer } // Save install progress - $this->install_config->save_config(); + try + { + $this->install_config->save_config(); + } + catch (installer_config_not_writable_exception $e) + { + // It is allowed to fail this test during requirements testing + $progress_data = $this->install_config->get_progress_data(); + + if ($progress_data['last_task_module_name'] !== 'installer.module.requirements_install') + { + $this->iohandler->add_error_message('INSTALLER_CONFIG_NOT_WRITABLE'); + } + } } /** diff --git a/phpBB/install/module/install_data/module.php b/phpBB/install/module/install_data/module.php index 231bcb0866..77f1f73f1f 100644 --- a/phpBB/install/module/install_data/module.php +++ b/phpBB/install/module/install_data/module.php @@ -18,5 +18,11 @@ namespace phpbb\install\module\install_data; */ class module extends \phpbb\install\module_base { - + /** + * {@inheritdoc} + */ + public function get_navigation_stage_path() + { + return array('install', 0, 'install'); + } } diff --git a/phpBB/install/module/install_database/module.php b/phpBB/install/module/install_database/module.php index d31c5573ec..0d8b33087f 100644 --- a/phpBB/install/module/install_database/module.php +++ b/phpBB/install/module/install_database/module.php @@ -18,5 +18,11 @@ namespace phpbb\install\module\install_database; */ class module extends \phpbb\install\module_base { - + /** + * {@inheritdoc} + */ + public function get_navigation_stage_path() + { + return array('install', 0, 'install'); + } } diff --git a/phpBB/install/module/install_filesystem/module.php b/phpBB/install/module/install_filesystem/module.php index 9562c957fd..7215449664 100644 --- a/phpBB/install/module/install_filesystem/module.php +++ b/phpBB/install/module/install_filesystem/module.php @@ -18,5 +18,11 @@ namespace phpbb\install\module\install_filesystem; */ class module extends \phpbb\install\module_base { - + /** + * {@inheritdoc} + */ + public function get_navigation_stage_path() + { + return array('install', 0, 'install'); + } } diff --git a/phpBB/install/module/install_finish/module.php b/phpBB/install/module/install_finish/module.php index 98c99d7cff..3a7544b84f 100644 --- a/phpBB/install/module/install_finish/module.php +++ b/phpBB/install/module/install_finish/module.php @@ -18,5 +18,11 @@ namespace phpbb\install\module\install_finish; */ class module extends \phpbb\install\module_base { - + /** + * {@inheritdoc} + */ + public function get_navigation_stage_path() + { + return array('install', 0, 'install'); + } } diff --git a/phpBB/install/module/obtain_data/module.php b/phpBB/install/module/obtain_data/module.php index a181c5231a..0e008796c5 100644 --- a/phpBB/install/module/obtain_data/module.php +++ b/phpBB/install/module/obtain_data/module.php @@ -15,6 +15,14 @@ namespace phpbb\install\module\obtain_data; class module extends \phpbb\install\module_base { + /** + * {@inheritdoc} + */ + public function get_navigation_stage_path() + { + return array('install', 0, 'obtain_data'); + } + /** * {@inheritdoc} */ diff --git a/phpBB/install/module/requirements/module.php b/phpBB/install/module/requirements/module.php index 5de6bd70b9..d87ca15128 100644 --- a/phpBB/install/module/requirements/module.php +++ b/phpBB/install/module/requirements/module.php @@ -61,6 +61,15 @@ class module extends \phpbb\install\module_base if (!$tests_passed) { // If requirements are not met, exit form installer + // Set up UI for retesting + $this->iohandler->add_user_form_group('', array( + 'install' => array( + 'label' => 'RETEST_REQUIREMENTS', + 'type' => 'submit', + ), + )); + + // Send the response and quit $this->iohandler->send_response(); throw new user_interaction_required_exception(); } @@ -77,4 +86,12 @@ class module extends \phpbb\install\module_base { return 0; } + + /** + * {@inheritdoc} + */ + public function get_navigation_stage_path() + { + return array('install', 0, 'requirements'); + } } diff --git a/phpBB/install/module_base.php b/phpBB/install/module_base.php index ac7ce7583a..6c0c0e0c30 100644 --- a/phpBB/install/module_base.php +++ b/phpBB/install/module_base.php @@ -75,8 +75,8 @@ abstract class module_base implements module_interface * Dependency getter * * @param ContainerInterface $container - * @param config $config - * @param iohandler_interface $iohandler + * @param config $config + * @param iohandler_interface $iohandler */ public function setup(ContainerInterface $container, config $config, iohandler_interface $iohandler) { diff --git a/phpBB/install/module_interface.php b/phpBB/install/module_interface.php index 29918f0c34..a2d61e3958 100644 --- a/phpBB/install/module_interface.php +++ b/phpBB/install/module_interface.php @@ -53,4 +53,11 @@ interface module_interface * @return int */ public function get_step_count(); + + /** + * Returns an array to the correct navigation stage + * + * @return array + */ + public function get_navigation_stage_path(); } diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 92251a4992..f050d49ebd 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -40,6 +40,8 @@ if (empty($lang) || !is_array($lang)) $lang = array_merge($lang, array( 'INSTALL_PANEL' => 'Installation Panel', + 'STAGE_INSTALL' => 'Installing phpBB', + // Introduction page 'INTRODUCTION_TITLE' => 'Introduction', 'INTRODUCTION_BODY' => 'Welcome to phpBB3!

            phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.

            This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read the installation guide.

            To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.', @@ -50,6 +52,33 @@ $lang = array_merge($lang, array( // License 'LICENSE_TITLE' => 'General Public License', + + // Install page + 'INSTALL_INTRO' => 'Welcome to Installation', + 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.

            In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:

            + +
              +
            • The Database Type - the database you will be using.
            • +
            • The Database server hostname or DSN - the address of the database server.
            • +
            • The Database server port - the port of the database server (most of the time this is not needed).
            • +
            • The Database name - the name of the database on the server.
            • +
            • The Database username and Database password - the login data to access the database.
            • +
            + +

            Note: if you are installing using SQLite, you should enter the full path to your database file in the DSN field and leave the username and password fields blank. For security reasons, you should make sure that the database file is not stored in a location accessible from the web.

            + +

            phpBB3 supports the following databases:

            +
              +
            • MySQL 3.23 or above (MySQLi supported)
            • +
            • PostgreSQL 8.3+
            • +
            • SQLite 2.8.2+
            • +
            • SQLite 3.6.15+
            • +
            • MS SQL Server 2000 or above (directly or via ODBC)
            • +
            • MS SQL Server 2005 or above (native)
            • +
            • Oracle
            • +
            + +

            Only those databases supported on your server will be displayed.', )); // Requirements translation @@ -76,6 +105,10 @@ $lang = array_merge($lang, array( 'PHP_JSON_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the PHP JSON extension needs to be available.', 'PHP_SUPPORTED_DB' => 'Supported databases', 'PHP_SUPPORTED_DB_EXPLAIN' => 'You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.', + + 'RETEST_REQUIREMENTS' => 'Retest requirements', + + 'STAGE_REQUIREMENTS' => 'Check requirements' )); // General error messages @@ -85,6 +118,8 @@ $lang = array_merge($lang, array( // Data obtaining translations $lang = array_merge($lang, array( + 'STAGE_OBTAIN_DATA' => 'Set installation data', + // // Admin data // @@ -263,4 +298,6 @@ $lang = array_merge($lang, array( 'TASK_SERVICE_INSTALLER_MISSING' => 'All installer task services should start with “installerâ€', 'TASK_CLASS_NOT_FOUND' => 'Installer task service definition is invalid. Service name “%1$s†given, the expected class namespace is “%2$s†for that. For more information please see the documentation of task_interface.', + + 'INSTALLER_CONFIG_NOT_WRITABLE' => 'The installer config file is not writable.', )); From 3dcaa48850bf823b238391fbf9c3f085092010bc Mon Sep 17 00:00:00 2001 From: CHItA Date: Sat, 13 Jun 2015 15:35:19 +0200 Subject: [PATCH 0450/1676] [ticket/13740] Move installer files to phpbb/install directory PHPBB3-13740 --- phpBB/install/app.php | 3 --- phpBB/{ => phpbb}/install/controller/helper.php | 0 phpBB/{ => phpbb}/install/controller/install.php | 0 phpBB/{ => phpbb}/install/controller/installer_index.php | 0 .../install/exception/cannot_build_container_exception.php | 0 .../exception/installer_config_not_writable_exception.php | 0 phpBB/{ => phpbb}/install/exception/installer_exception.php | 0 phpBB/{ => phpbb}/install/exception/invalid_dbms_exception.php | 0 .../install/exception/invalid_service_name_exception.php | 0 .../install/exception/module_not_found_exception.php | 0 .../{ => phpbb}/install/exception/task_not_found_exception.php | 0 .../install/exception/user_interaction_required_exception.php | 0 phpBB/{ => phpbb}/install/helper/config.php | 0 phpBB/{ => phpbb}/install/helper/container_factory.php | 0 phpBB/{ => phpbb}/install/helper/database.php | 0 phpBB/{ => phpbb}/install/helper/iohandler/ajax_iohandler.php | 0 .../exception/iohandler_not_implemented_exception.php | 0 phpBB/{ => phpbb}/install/helper/iohandler/factory.php | 0 phpBB/{ => phpbb}/install/helper/iohandler/iohandler_base.php | 0 .../install/helper/iohandler/iohandler_interface.php | 0 .../install/helper/navigation/install_navigation.php | 0 .../{ => phpbb}/install/helper/navigation/main_navigation.php | 0 .../install/helper/navigation/navigation_interface.php | 0 .../install/helper/navigation/navigation_provider.php | 0 phpBB/{ => phpbb}/install/installer.php | 0 phpBB/{ => phpbb}/install/module/install_data/module.php | 0 .../{ => phpbb}/install/module/install_data/task/add_bots.php | 0 .../install/module/install_data/task/add_languages.php | 0 .../install/module/install_data/task/add_modules.php | 0 phpBB/{ => phpbb}/install/module/install_database/module.php | 0 .../module/install_database/task/add_config_settings.php | 0 .../install/module/install_database/task/add_default_data.php | 0 .../install/module/install_database/task/create_schema.php | 0 phpBB/{ => phpbb}/install/module/install_filesystem/module.php | 0 .../module/install_filesystem/task/create_config_file.php | 0 phpBB/{ => phpbb}/install/module/install_finish/module.php | 0 .../install/module/install_finish/task/notify_user.php | 0 .../install/module/install_finish/task/populate_migrations.php | 0 phpBB/{ => phpbb}/install/module/obtain_data/module.php | 0 .../install/module/obtain_data/task/obtain_admin_data.php | 0 .../install/module/obtain_data/task/obtain_board_data.php | 0 .../install/module/obtain_data/task/obtain_database_data.php | 0 .../install/module/obtain_data/task/obtain_email_data.php | 0 .../install/module/obtain_data/task/obtain_imagick_path.php | 0 .../install/module/obtain_data/task/obtain_server_data.php | 0 phpBB/{ => phpbb}/install/module/requirements/module.php | 0 .../install/module/requirements/task/check_filesystem.php | 0 .../module/requirements/task/check_server_environment.php | 0 phpBB/{ => phpbb}/install/module_base.php | 0 phpBB/{ => phpbb}/install/module_interface.php | 0 phpBB/{ => phpbb}/install/schemas/index.htm | 0 phpBB/{ => phpbb}/install/schemas/oracle_schema.sql | 0 phpBB/{ => phpbb}/install/schemas/postgres_schema.sql | 0 phpBB/{ => phpbb}/install/schemas/schema_data.sql | 0 phpBB/{ => phpbb}/install/task_base.php | 0 phpBB/{ => phpbb}/install/task_interface.php | 0 56 files changed, 3 deletions(-) rename phpBB/{ => phpbb}/install/controller/helper.php (100%) rename phpBB/{ => phpbb}/install/controller/install.php (100%) rename phpBB/{ => phpbb}/install/controller/installer_index.php (100%) rename phpBB/{ => phpbb}/install/exception/cannot_build_container_exception.php (100%) rename phpBB/{ => phpbb}/install/exception/installer_config_not_writable_exception.php (100%) rename phpBB/{ => phpbb}/install/exception/installer_exception.php (100%) rename phpBB/{ => phpbb}/install/exception/invalid_dbms_exception.php (100%) rename phpBB/{ => phpbb}/install/exception/invalid_service_name_exception.php (100%) rename phpBB/{ => phpbb}/install/exception/module_not_found_exception.php (100%) rename phpBB/{ => phpbb}/install/exception/task_not_found_exception.php (100%) rename phpBB/{ => phpbb}/install/exception/user_interaction_required_exception.php (100%) rename phpBB/{ => phpbb}/install/helper/config.php (100%) rename phpBB/{ => phpbb}/install/helper/container_factory.php (100%) rename phpBB/{ => phpbb}/install/helper/database.php (100%) rename phpBB/{ => phpbb}/install/helper/iohandler/ajax_iohandler.php (100%) rename phpBB/{ => phpbb}/install/helper/iohandler/exception/iohandler_not_implemented_exception.php (100%) rename phpBB/{ => phpbb}/install/helper/iohandler/factory.php (100%) rename phpBB/{ => phpbb}/install/helper/iohandler/iohandler_base.php (100%) rename phpBB/{ => phpbb}/install/helper/iohandler/iohandler_interface.php (100%) rename phpBB/{ => phpbb}/install/helper/navigation/install_navigation.php (100%) rename phpBB/{ => phpbb}/install/helper/navigation/main_navigation.php (100%) rename phpBB/{ => phpbb}/install/helper/navigation/navigation_interface.php (100%) rename phpBB/{ => phpbb}/install/helper/navigation/navigation_provider.php (100%) rename phpBB/{ => phpbb}/install/installer.php (100%) rename phpBB/{ => phpbb}/install/module/install_data/module.php (100%) rename phpBB/{ => phpbb}/install/module/install_data/task/add_bots.php (100%) rename phpBB/{ => phpbb}/install/module/install_data/task/add_languages.php (100%) rename phpBB/{ => phpbb}/install/module/install_data/task/add_modules.php (100%) rename phpBB/{ => phpbb}/install/module/install_database/module.php (100%) rename phpBB/{ => phpbb}/install/module/install_database/task/add_config_settings.php (100%) rename phpBB/{ => phpbb}/install/module/install_database/task/add_default_data.php (100%) rename phpBB/{ => phpbb}/install/module/install_database/task/create_schema.php (100%) rename phpBB/{ => phpbb}/install/module/install_filesystem/module.php (100%) rename phpBB/{ => phpbb}/install/module/install_filesystem/task/create_config_file.php (100%) rename phpBB/{ => phpbb}/install/module/install_finish/module.php (100%) rename phpBB/{ => phpbb}/install/module/install_finish/task/notify_user.php (100%) rename phpBB/{ => phpbb}/install/module/install_finish/task/populate_migrations.php (100%) rename phpBB/{ => phpbb}/install/module/obtain_data/module.php (100%) rename phpBB/{ => phpbb}/install/module/obtain_data/task/obtain_admin_data.php (100%) rename phpBB/{ => phpbb}/install/module/obtain_data/task/obtain_board_data.php (100%) rename phpBB/{ => phpbb}/install/module/obtain_data/task/obtain_database_data.php (100%) rename phpBB/{ => phpbb}/install/module/obtain_data/task/obtain_email_data.php (100%) rename phpBB/{ => phpbb}/install/module/obtain_data/task/obtain_imagick_path.php (100%) rename phpBB/{ => phpbb}/install/module/obtain_data/task/obtain_server_data.php (100%) rename phpBB/{ => phpbb}/install/module/requirements/module.php (100%) rename phpBB/{ => phpbb}/install/module/requirements/task/check_filesystem.php (100%) rename phpBB/{ => phpbb}/install/module/requirements/task/check_server_environment.php (100%) rename phpBB/{ => phpbb}/install/module_base.php (100%) rename phpBB/{ => phpbb}/install/module_interface.php (100%) rename phpBB/{ => phpbb}/install/schemas/index.htm (100%) rename phpBB/{ => phpbb}/install/schemas/oracle_schema.sql (100%) rename phpBB/{ => phpbb}/install/schemas/postgres_schema.sql (100%) rename phpBB/{ => phpbb}/install/schemas/schema_data.sql (100%) rename phpBB/{ => phpbb}/install/task_base.php (100%) rename phpBB/{ => phpbb}/install/task_interface.php (100%) diff --git a/phpBB/install/app.php b/phpBB/install/app.php index 58ca141af7..09a8faf592 100644 --- a/phpBB/install/app.php +++ b/phpBB/install/app.php @@ -26,9 +26,6 @@ $phpEx = substr(strrchr(__FILE__, '.'), 1); require($phpbb_root_path . 'includes/startup.' . $phpEx); require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx); -$phpbb_class_loader = new \phpbb\class_loader('phpbb\\install\\', "{$phpbb_root_path}install/", $phpEx); -$phpbb_class_loader->register(); - $phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx); $phpbb_class_loader->register(); diff --git a/phpBB/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php similarity index 100% rename from phpBB/install/controller/helper.php rename to phpBB/phpbb/install/controller/helper.php diff --git a/phpBB/install/controller/install.php b/phpBB/phpbb/install/controller/install.php similarity index 100% rename from phpBB/install/controller/install.php rename to phpBB/phpbb/install/controller/install.php diff --git a/phpBB/install/controller/installer_index.php b/phpBB/phpbb/install/controller/installer_index.php similarity index 100% rename from phpBB/install/controller/installer_index.php rename to phpBB/phpbb/install/controller/installer_index.php diff --git a/phpBB/install/exception/cannot_build_container_exception.php b/phpBB/phpbb/install/exception/cannot_build_container_exception.php similarity index 100% rename from phpBB/install/exception/cannot_build_container_exception.php rename to phpBB/phpbb/install/exception/cannot_build_container_exception.php diff --git a/phpBB/install/exception/installer_config_not_writable_exception.php b/phpBB/phpbb/install/exception/installer_config_not_writable_exception.php similarity index 100% rename from phpBB/install/exception/installer_config_not_writable_exception.php rename to phpBB/phpbb/install/exception/installer_config_not_writable_exception.php diff --git a/phpBB/install/exception/installer_exception.php b/phpBB/phpbb/install/exception/installer_exception.php similarity index 100% rename from phpBB/install/exception/installer_exception.php rename to phpBB/phpbb/install/exception/installer_exception.php diff --git a/phpBB/install/exception/invalid_dbms_exception.php b/phpBB/phpbb/install/exception/invalid_dbms_exception.php similarity index 100% rename from phpBB/install/exception/invalid_dbms_exception.php rename to phpBB/phpbb/install/exception/invalid_dbms_exception.php diff --git a/phpBB/install/exception/invalid_service_name_exception.php b/phpBB/phpbb/install/exception/invalid_service_name_exception.php similarity index 100% rename from phpBB/install/exception/invalid_service_name_exception.php rename to phpBB/phpbb/install/exception/invalid_service_name_exception.php diff --git a/phpBB/install/exception/module_not_found_exception.php b/phpBB/phpbb/install/exception/module_not_found_exception.php similarity index 100% rename from phpBB/install/exception/module_not_found_exception.php rename to phpBB/phpbb/install/exception/module_not_found_exception.php diff --git a/phpBB/install/exception/task_not_found_exception.php b/phpBB/phpbb/install/exception/task_not_found_exception.php similarity index 100% rename from phpBB/install/exception/task_not_found_exception.php rename to phpBB/phpbb/install/exception/task_not_found_exception.php diff --git a/phpBB/install/exception/user_interaction_required_exception.php b/phpBB/phpbb/install/exception/user_interaction_required_exception.php similarity index 100% rename from phpBB/install/exception/user_interaction_required_exception.php rename to phpBB/phpbb/install/exception/user_interaction_required_exception.php diff --git a/phpBB/install/helper/config.php b/phpBB/phpbb/install/helper/config.php similarity index 100% rename from phpBB/install/helper/config.php rename to phpBB/phpbb/install/helper/config.php diff --git a/phpBB/install/helper/container_factory.php b/phpBB/phpbb/install/helper/container_factory.php similarity index 100% rename from phpBB/install/helper/container_factory.php rename to phpBB/phpbb/install/helper/container_factory.php diff --git a/phpBB/install/helper/database.php b/phpBB/phpbb/install/helper/database.php similarity index 100% rename from phpBB/install/helper/database.php rename to phpBB/phpbb/install/helper/database.php diff --git a/phpBB/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php similarity index 100% rename from phpBB/install/helper/iohandler/ajax_iohandler.php rename to phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php diff --git a/phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php b/phpBB/phpbb/install/helper/iohandler/exception/iohandler_not_implemented_exception.php similarity index 100% rename from phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php rename to phpBB/phpbb/install/helper/iohandler/exception/iohandler_not_implemented_exception.php diff --git a/phpBB/install/helper/iohandler/factory.php b/phpBB/phpbb/install/helper/iohandler/factory.php similarity index 100% rename from phpBB/install/helper/iohandler/factory.php rename to phpBB/phpbb/install/helper/iohandler/factory.php diff --git a/phpBB/install/helper/iohandler/iohandler_base.php b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php similarity index 100% rename from phpBB/install/helper/iohandler/iohandler_base.php rename to phpBB/phpbb/install/helper/iohandler/iohandler_base.php diff --git a/phpBB/install/helper/iohandler/iohandler_interface.php b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php similarity index 100% rename from phpBB/install/helper/iohandler/iohandler_interface.php rename to phpBB/phpbb/install/helper/iohandler/iohandler_interface.php diff --git a/phpBB/install/helper/navigation/install_navigation.php b/phpBB/phpbb/install/helper/navigation/install_navigation.php similarity index 100% rename from phpBB/install/helper/navigation/install_navigation.php rename to phpBB/phpbb/install/helper/navigation/install_navigation.php diff --git a/phpBB/install/helper/navigation/main_navigation.php b/phpBB/phpbb/install/helper/navigation/main_navigation.php similarity index 100% rename from phpBB/install/helper/navigation/main_navigation.php rename to phpBB/phpbb/install/helper/navigation/main_navigation.php diff --git a/phpBB/install/helper/navigation/navigation_interface.php b/phpBB/phpbb/install/helper/navigation/navigation_interface.php similarity index 100% rename from phpBB/install/helper/navigation/navigation_interface.php rename to phpBB/phpbb/install/helper/navigation/navigation_interface.php diff --git a/phpBB/install/helper/navigation/navigation_provider.php b/phpBB/phpbb/install/helper/navigation/navigation_provider.php similarity index 100% rename from phpBB/install/helper/navigation/navigation_provider.php rename to phpBB/phpbb/install/helper/navigation/navigation_provider.php diff --git a/phpBB/install/installer.php b/phpBB/phpbb/install/installer.php similarity index 100% rename from phpBB/install/installer.php rename to phpBB/phpbb/install/installer.php diff --git a/phpBB/install/module/install_data/module.php b/phpBB/phpbb/install/module/install_data/module.php similarity index 100% rename from phpBB/install/module/install_data/module.php rename to phpBB/phpbb/install/module/install_data/module.php diff --git a/phpBB/install/module/install_data/task/add_bots.php b/phpBB/phpbb/install/module/install_data/task/add_bots.php similarity index 100% rename from phpBB/install/module/install_data/task/add_bots.php rename to phpBB/phpbb/install/module/install_data/task/add_bots.php diff --git a/phpBB/install/module/install_data/task/add_languages.php b/phpBB/phpbb/install/module/install_data/task/add_languages.php similarity index 100% rename from phpBB/install/module/install_data/task/add_languages.php rename to phpBB/phpbb/install/module/install_data/task/add_languages.php diff --git a/phpBB/install/module/install_data/task/add_modules.php b/phpBB/phpbb/install/module/install_data/task/add_modules.php similarity index 100% rename from phpBB/install/module/install_data/task/add_modules.php rename to phpBB/phpbb/install/module/install_data/task/add_modules.php diff --git a/phpBB/install/module/install_database/module.php b/phpBB/phpbb/install/module/install_database/module.php similarity index 100% rename from phpBB/install/module/install_database/module.php rename to phpBB/phpbb/install/module/install_database/module.php diff --git a/phpBB/install/module/install_database/task/add_config_settings.php b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php similarity index 100% rename from phpBB/install/module/install_database/task/add_config_settings.php rename to phpBB/phpbb/install/module/install_database/task/add_config_settings.php diff --git a/phpBB/install/module/install_database/task/add_default_data.php b/phpBB/phpbb/install/module/install_database/task/add_default_data.php similarity index 100% rename from phpBB/install/module/install_database/task/add_default_data.php rename to phpBB/phpbb/install/module/install_database/task/add_default_data.php diff --git a/phpBB/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php similarity index 100% rename from phpBB/install/module/install_database/task/create_schema.php rename to phpBB/phpbb/install/module/install_database/task/create_schema.php diff --git a/phpBB/install/module/install_filesystem/module.php b/phpBB/phpbb/install/module/install_filesystem/module.php similarity index 100% rename from phpBB/install/module/install_filesystem/module.php rename to phpBB/phpbb/install/module/install_filesystem/module.php diff --git a/phpBB/install/module/install_filesystem/task/create_config_file.php b/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php similarity index 100% rename from phpBB/install/module/install_filesystem/task/create_config_file.php rename to phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php diff --git a/phpBB/install/module/install_finish/module.php b/phpBB/phpbb/install/module/install_finish/module.php similarity index 100% rename from phpBB/install/module/install_finish/module.php rename to phpBB/phpbb/install/module/install_finish/module.php diff --git a/phpBB/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php similarity index 100% rename from phpBB/install/module/install_finish/task/notify_user.php rename to phpBB/phpbb/install/module/install_finish/task/notify_user.php diff --git a/phpBB/install/module/install_finish/task/populate_migrations.php b/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php similarity index 100% rename from phpBB/install/module/install_finish/task/populate_migrations.php rename to phpBB/phpbb/install/module/install_finish/task/populate_migrations.php diff --git a/phpBB/install/module/obtain_data/module.php b/phpBB/phpbb/install/module/obtain_data/module.php similarity index 100% rename from phpBB/install/module/obtain_data/module.php rename to phpBB/phpbb/install/module/obtain_data/module.php diff --git a/phpBB/install/module/obtain_data/task/obtain_admin_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php similarity index 100% rename from phpBB/install/module/obtain_data/task/obtain_admin_data.php rename to phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php diff --git a/phpBB/install/module/obtain_data/task/obtain_board_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php similarity index 100% rename from phpBB/install/module/obtain_data/task/obtain_board_data.php rename to phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php diff --git a/phpBB/install/module/obtain_data/task/obtain_database_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php similarity index 100% rename from phpBB/install/module/obtain_data/task/obtain_database_data.php rename to phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php diff --git a/phpBB/install/module/obtain_data/task/obtain_email_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php similarity index 100% rename from phpBB/install/module/obtain_data/task/obtain_email_data.php rename to phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php diff --git a/phpBB/install/module/obtain_data/task/obtain_imagick_path.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php similarity index 100% rename from phpBB/install/module/obtain_data/task/obtain_imagick_path.php rename to phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php diff --git a/phpBB/install/module/obtain_data/task/obtain_server_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php similarity index 100% rename from phpBB/install/module/obtain_data/task/obtain_server_data.php rename to phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php diff --git a/phpBB/install/module/requirements/module.php b/phpBB/phpbb/install/module/requirements/module.php similarity index 100% rename from phpBB/install/module/requirements/module.php rename to phpBB/phpbb/install/module/requirements/module.php diff --git a/phpBB/install/module/requirements/task/check_filesystem.php b/phpBB/phpbb/install/module/requirements/task/check_filesystem.php similarity index 100% rename from phpBB/install/module/requirements/task/check_filesystem.php rename to phpBB/phpbb/install/module/requirements/task/check_filesystem.php diff --git a/phpBB/install/module/requirements/task/check_server_environment.php b/phpBB/phpbb/install/module/requirements/task/check_server_environment.php similarity index 100% rename from phpBB/install/module/requirements/task/check_server_environment.php rename to phpBB/phpbb/install/module/requirements/task/check_server_environment.php diff --git a/phpBB/install/module_base.php b/phpBB/phpbb/install/module_base.php similarity index 100% rename from phpBB/install/module_base.php rename to phpBB/phpbb/install/module_base.php diff --git a/phpBB/install/module_interface.php b/phpBB/phpbb/install/module_interface.php similarity index 100% rename from phpBB/install/module_interface.php rename to phpBB/phpbb/install/module_interface.php diff --git a/phpBB/install/schemas/index.htm b/phpBB/phpbb/install/schemas/index.htm similarity index 100% rename from phpBB/install/schemas/index.htm rename to phpBB/phpbb/install/schemas/index.htm diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/phpbb/install/schemas/oracle_schema.sql similarity index 100% rename from phpBB/install/schemas/oracle_schema.sql rename to phpBB/phpbb/install/schemas/oracle_schema.sql diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/phpbb/install/schemas/postgres_schema.sql similarity index 100% rename from phpBB/install/schemas/postgres_schema.sql rename to phpBB/phpbb/install/schemas/postgres_schema.sql diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/phpbb/install/schemas/schema_data.sql similarity index 100% rename from phpBB/install/schemas/schema_data.sql rename to phpBB/phpbb/install/schemas/schema_data.sql diff --git a/phpBB/install/task_base.php b/phpBB/phpbb/install/task_base.php similarity index 100% rename from phpBB/install/task_base.php rename to phpBB/phpbb/install/task_base.php diff --git a/phpBB/install/task_interface.php b/phpBB/phpbb/install/task_interface.php similarity index 100% rename from phpBB/install/task_interface.php rename to phpBB/phpbb/install/task_interface.php From aa6a1c5939e4ae98d28e593ed2e09319c1341bba Mon Sep 17 00:00:00 2001 From: CHItA Date: Sat, 13 Jun 2015 15:38:51 +0200 Subject: [PATCH 0451/1676] [ticket/13740] Fix CS PHPBB3-13740 --- .../install/module/install_data/task/add_modules.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/install/module/install_data/task/add_modules.php b/phpBB/phpbb/install/module/install_data/task/add_modules.php index 6a77f8973b..8ca2b6b215 100644 --- a/phpBB/phpbb/install/module/install_data/task/add_modules.php +++ b/phpBB/phpbb/install/module/install_data/task/add_modules.php @@ -193,7 +193,7 @@ class add_modules extends \phpbb\install\task_base $this->iohandler->add_error_message('INST_ERR_DB', $error['message']); } - $categories[$cat_name]['id'] = (int)$module_data['module_id']; + $categories[$cat_name]['id'] = (int) $module_data['module_id']; $categories[$cat_name]['parent_id'] = 0; if (is_array($subs)) @@ -207,7 +207,7 @@ class add_modules extends \phpbb\install\task_base 'module_basename' => $basename, 'module_enabled' => 1, 'module_display' => 1, - 'parent_id' => (int)$categories[$cat_name]['id'], + 'parent_id' => (int) $categories[$cat_name]['id'], 'module_class' => $module_class, 'module_langname' => $level2_name, 'module_mode' => '', @@ -223,8 +223,8 @@ class add_modules extends \phpbb\install\task_base $this->iohandler->add_error_message('INST_ERR_DB', $error['message']); } - $categories[$level2_name]['id'] = (int)$module_data['module_id']; - $categories[$level2_name]['parent_id'] = (int)$categories[$cat_name]['id']; + $categories[$level2_name]['id'] = (int) $module_data['module_id']; + $categories[$level2_name]['parent_id'] = (int) $categories[$cat_name]['id']; } } } From 5ce170dcc3f798627d95876ce6777882ffb8b83e Mon Sep 17 00:00:00 2001 From: CHItA Date: Sun, 14 Jun 2015 13:36:45 +0200 Subject: [PATCH 0452/1676] [ticket/13740] Remove ActiveXObject as it is supported by IE versions >= 8 PHPBB3-13740 --- phpBB/assets/javascript/installer.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index eafcd78f47..68a4eb499b 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -3,7 +3,6 @@ */ (function($) { // Avoid conflicts with other libraries - 'use strict'; // Installer variables @@ -26,18 +25,11 @@ * as of now, jQuery does not provide access to the response until * the connection is not closed. * - * @return XMLHttpRequest|ActiveXObject + * @return XMLHttpRequest */ function createXhrObject() { - var xhReq; - - if (window.XMLHttpRequest) { - xhReq = new XMLHttpRequest(); - } - else if (window.ActiveXObject) { - xhReq = new ActiveXObject("Msxml2.XMLHTTP"); - } - + var xhReq = new XMLHttpRequest(); + xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); return xhReq; } @@ -336,7 +328,6 @@ var xhReq = createXhrObject(); xhReq.open('POST', $form.attr('action'), true); - xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhReq.send(getFormFields($form, $submitBtn)); From c53ce3d5fbfcdc9924426aee74fb1097138a8a42 Mon Sep 17 00:00:00 2001 From: CHItA Date: Wed, 17 Jun 2015 11:00:07 +0200 Subject: [PATCH 0453/1676] [ticket/13740] Fix CS and extend phpbb extensions [ci skip] PHPBB3-13740 --- .../default/container/services_http.yml | 14 +++--- phpBB/includes/compatibility_globals.php | 20 ++++---- phpBB/phpbb/install/controller/helper.php | 21 +++++++- .../install/exception/installer_exception.php | 4 +- .../invalid_service_name_exception.php | 50 ------------------- phpBB/phpbb/install/installer.php | 11 ++-- 6 files changed, 46 insertions(+), 74 deletions(-) diff --git a/phpBB/config/default/container/services_http.yml b/phpBB/config/default/container/services_http.yml index 9c2bdd2337..1285fd1d88 100644 --- a/phpBB/config/default/container/services_http.yml +++ b/phpBB/config/default/container/services_http.yml @@ -1,4 +1,11 @@ services: + http_kernel: + class: Symfony\Component\HttpKernel\HttpKernel + arguments: + - @dispatcher + - @controller.resolver + - @request_stack + # WARNING: The Symfony request does not escape the input and should be used very carefully # prefer the phpbb request (service @request) as possible symfony_request: @@ -14,10 +21,3 @@ services: arguments: - null - %core.disable_super_globals% - - http_kernel: - class: Symfony\Component\HttpKernel\HttpKernel - arguments: - - @dispatcher - - @controller.resolver - - @request_stack diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php index cb4087d09b..fadc879640 100644 --- a/phpBB/includes/compatibility_globals.php +++ b/phpBB/includes/compatibility_globals.php @@ -1,15 +1,15 @@ - * @license GNU General Public License, version 2 (GPL-2.0) - * - * For full copyright and license information, please see - * the docs/CREDITS.txt file. - * - */ +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ /** */ diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index 0df1ae71a4..8445d80a41 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -13,6 +13,13 @@ namespace phpbb\install\controller; +use phpbb\install\helper\navigation\navigation_provider; +use phpbb\language\language; +use phpbb\language\language_file_helper; +use phpbb\path_helper; +use phpbb\routing\router; +use phpbb\symfony_request; +use phpbb\template\template; use Symfony\Component\HttpFoundation\Response; /** @@ -68,7 +75,19 @@ class helper */ protected $phpbb_root_path; - public function __construct(\phpbb\language\language $language, \phpbb\language\language_file_helper $lang_helper, \phpbb\install\helper\navigation\navigation_provider $nav, \phpbb\template\template $template, \phpbb\path_helper $path_helper, \phpbb\symfony_request $request, \phpbb\routing\router $router, $phpbb_root_path) + /** + * Constructor + * + * @param language $language + * @param language_file_helper $lang_helper + * @param navigation_provider $nav + * @param template $template + * @param path_helper $path_helper + * @param symfony_request $request + * @param router $router + * @param string $phpbb_root_path + */ + public function __construct(language $language, language_file_helper $lang_helper, navigation_provider $nav, template $template, path_helper $path_helper, symfony_request $request, router $router, $phpbb_root_path) { $this->language = $language; $this->lang_helper = $lang_helper; diff --git a/phpBB/phpbb/install/exception/installer_exception.php b/phpBB/phpbb/install/exception/installer_exception.php index c37950d05c..f17dca8f17 100644 --- a/phpBB/phpbb/install/exception/installer_exception.php +++ b/phpBB/phpbb/install/exception/installer_exception.php @@ -13,10 +13,12 @@ namespace phpbb\install\exception; +use phpbb\exception\runtime_exception; + /** * Installer's base exception */ -class installer_exception extends \Exception +class installer_exception extends runtime_exception { } diff --git a/phpBB/phpbb/install/exception/invalid_service_name_exception.php b/phpBB/phpbb/install/exception/invalid_service_name_exception.php index e64cd2026f..dff4873f3c 100644 --- a/phpBB/phpbb/install/exception/invalid_service_name_exception.php +++ b/phpBB/phpbb/install/exception/invalid_service_name_exception.php @@ -15,55 +15,5 @@ namespace phpbb\install\exception; class invalid_service_name_exception extends installer_exception { - /** - * @var string - */ - private $params; - /** - * @var string - */ - private $error; - - /** - * Constructor - * - * @param string $error The name of the missing installer module - * @param array $params Additional values for message translation - */ - public function __construct($error, $params = array()) - { - $this->error = $error; - $this->params = $params; - } - - /** - * Returns the language entry's name for the error - * - * @return string - */ - public function get_error() - { - return $this->error; - } - - /** - * Returns parameters for the language entry, if there is any - * - * @return array - */ - public function get_params() - { - return $this->params; - } - - /** - * Returns true, if there are any parameters set - * - * @return bool - */ - public function has_params() - { - return (sizeof($this->params) !== 0); - } } diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index f5da898a00..d64713e6a3 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -229,17 +229,18 @@ class installer } catch (invalid_service_name_exception $e) { - if ($e->has_params()) + $params = $e->get_parameters(); + + if (!empty($params)) { - $msg = $e->get_params(); - array_unshift($msg, $e->get_error()); + array_unshift($params, $e->getMessage()); } else { - $msg = $e->get_error(); + $params = $e->getMessage(); } - $this->iohandler->add_error_message($msg); + $this->iohandler->add_error_message($params); $flush_messages = true; } From 609eb7a4d3e2b763f3e69e8bb61adc3ee3ced328 Mon Sep 17 00:00:00 2001 From: CHItA Date: Thu, 18 Jun 2015 01:41:50 +0200 Subject: [PATCH 0454/1676] [ticket/13740] Fix AJAX HTTP header setting PHPBB3-13740 --- phpBB/assets/javascript/installer.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index 68a4eb499b..105818f82b 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -28,9 +28,7 @@ * @return XMLHttpRequest */ function createXhrObject() { - var xhReq = new XMLHttpRequest(); - xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - return xhReq; + return new XMLHttpRequest(); } /** @@ -328,6 +326,7 @@ var xhReq = createXhrObject(); xhReq.open('POST', $form.attr('action'), true); + xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhReq.send(getFormFields($form, $submitBtn)); From 69a19e48fab4cfd6243bf7ac7e0c7373651b6f41 Mon Sep 17 00:00:00 2001 From: CHItA Date: Thu, 18 Jun 2015 02:11:51 +0200 Subject: [PATCH 0455/1676] [ticket/13740] Cache installer container PHPBB3-13740 --- phpBB/install/app.php | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/install/app.php b/phpBB/install/app.php index 09a8faf592..75b28fa092 100644 --- a/phpBB/install/app.php +++ b/phpBB/install/app.php @@ -47,7 +47,6 @@ $phpbb_installer_container_builder = new \phpbb\di\container_builder($phpbb_root $phpbb_installer_container = $phpbb_installer_container_builder ->with_environment('installer') ->without_extensions() - ->without_cache() ->get_container(); // Path to templates From 0f5f62f8db4fe5816329abaca7ad6ff10c8cf749 Mon Sep 17 00:00:00 2001 From: CHItA Date: Thu, 18 Jun 2015 02:12:49 +0200 Subject: [PATCH 0456/1676] [ticket/13740] Load schema_data.sql from the correct location [ci skip] PHPBB3-13740 --- .../container/services_install_database.yml | 1 + .../install_database/task/add_default_data.php | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/phpBB/config/installer/container/services_install_database.yml b/phpBB/config/installer/container/services_install_database.yml index 865f2d8ab6..061d3f6c42 100644 --- a/phpBB/config/installer/container/services_install_database.yml +++ b/phpBB/config/installer/container/services_install_database.yml @@ -18,6 +18,7 @@ services: - @installer.helper.iohandler - @installer.helper.container_factory - @language + - %core.root_path% installer.install_database.add_config_settings: class: phpbb\install\module\install_database\task\add_config_settings diff --git a/phpBB/phpbb/install/module/install_database/task/add_default_data.php b/phpBB/phpbb/install/module/install_database/task/add_default_data.php index 5dbfbb4478..44b614f4de 100644 --- a/phpBB/phpbb/install/module/install_database/task/add_default_data.php +++ b/phpBB/phpbb/install/module/install_database/task/add_default_data.php @@ -43,6 +43,11 @@ class add_default_data extends \phpbb\install\task_base */ protected $language; + /** + * @var string + */ + protected $phpbb_root_path; + /** * Constructor * @@ -51,26 +56,26 @@ class add_default_data extends \phpbb\install\task_base * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler * @param \phpbb\install\helper\container_factory $container Installer's DI container * @param \phpbb\language\language $language Language service + * @param string $root_path Root path of phpBB */ public function __construct(\phpbb\install\helper\database $db_helper, \phpbb\install\helper\config $config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler, \phpbb\install\helper\container_factory $container, - \phpbb\language\language $language) + \phpbb\language\language $language, + $root_path) { $dbms = $db_helper->get_available_dbms($config->get('dbms')); $dbms = $dbms[$config->get('dbms')]['DRIVER']; - $this->db = $container->get('dbal.conn'); //new $dbms(); + $this->db = $container->get('dbal.conn'); $this->database_helper = $db_helper; $this->config = $config; $this->iohandler = $iohandler; $this->language = $language; + $this->phpbb_root_path = $root_path; parent::__construct(true); - - // Connect to DB - //$this->db->sql_connect($config->get('dbhost'), $config->get('dbuser'), $config->get('dbpasswd'), $config->get('dbname'), $config->get('dbport'), false, false); } /** @@ -85,7 +90,7 @@ class add_default_data extends \phpbb\install\task_base $dbms_info = $this->database_helper->get_available_dbms($dbms); // Get schema data from file - $sql_query = @file_get_contents('schemas/schema_data.sql'); + $sql_query = @file_get_contents($this->phpbb_root_path . 'phpbb/install/schemas/schema_data.sql'); // Clean up SQL $sql_query = $this->replace_dbms_specific_sql($sql_query); From 02029fe1610e5aa1792f24a4d748c6ed08bfc5fc Mon Sep 17 00:00:00 2001 From: CHItA Date: Thu, 18 Jun 2015 14:12:56 +0200 Subject: [PATCH 0457/1676] [ticket/13740] Use DBAL for retrieving DB version PHPBB3-13740 --- phpBB/phpbb/install/helper/database.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/install/helper/database.php b/phpBB/phpbb/install/helper/database.php index d728c8b93b..38823c1231 100644 --- a/phpBB/phpbb/install/helper/database.php +++ b/phpBB/phpbb/install/helper/database.php @@ -394,7 +394,7 @@ class database switch ($dbms) { case 'mysqli': - if (version_compare(mysqli_get_server_info($db->get_db_connect_id()), '4.1.3', '<')) + if (version_compare($db->sql_server_info(), '4.1.3', '<')) { $errors[] = array( 'title' => 'INST_ERR_DB_NO_MYSQLI', @@ -402,7 +402,7 @@ class database } break; case 'sqlite': - if (version_compare(sqlite_libversion(), '2.8.2', '<')) + if (version_compare($db->sql_server_info(), '2.8.2', '<')) { $errors[] = array( 'title' => 'INST_ERR_DB_NO_SQLITE', @@ -410,8 +410,7 @@ class database } break; case 'sqlite3': - $version = \SQLite3::version(); - if (version_compare($version['versionString'], '3.6.15', '<')) + if (version_compare($db->sql_server_info(), '3.6.15', '<')) { $errors[] = array( 'title' => 'INST_ERR_DB_NO_SQLITE3', From 08d9d567ca9fb52b18be5d8f709ba7b1699fd34f Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 19 Jun 2015 01:26:15 +0200 Subject: [PATCH 0458/1676] [ticket/13740] Fix database installation PHPBB3-13740 --- .../module/install_database/task/add_default_data.php | 5 +---- .../install/module/install_database/task/create_schema.php | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/phpBB/phpbb/install/module/install_database/task/add_default_data.php b/phpBB/phpbb/install/module/install_database/task/add_default_data.php index 44b614f4de..1e1eb10403 100644 --- a/phpBB/phpbb/install/module/install_database/task/add_default_data.php +++ b/phpBB/phpbb/install/module/install_database/task/add_default_data.php @@ -65,10 +65,7 @@ class add_default_data extends \phpbb\install\task_base \phpbb\language\language $language, $root_path) { - $dbms = $db_helper->get_available_dbms($config->get('dbms')); - $dbms = $dbms[$config->get('dbms')]['DRIVER']; - - $this->db = $container->get('dbal.conn'); + $this->db = $container->get('dbal.conn.driver'); $this->database_helper = $db_helper; $this->config = $config; $this->iohandler = $iohandler; diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php index 7cc521eee8..556bfd5e81 100644 --- a/phpBB/phpbb/install/module/install_database/task/create_schema.php +++ b/phpBB/phpbb/install/module/install_database/task/create_schema.php @@ -119,7 +119,7 @@ class create_schema extends \phpbb\install\task_base } } - $db_schema_path = $this->phpbb_root_path . 'install/schemas/' . $schema_name . '_schema.sql'; + $db_schema_path = $this->phpbb_root_path . 'phpbb/install/schemas/' . $schema_name . '_schema.sql'; // Load database vendor specific code if there is any if ($this->filesystem->exists($db_schema_path)) @@ -144,9 +144,9 @@ class create_schema extends \phpbb\install\task_base $change_prefix = false; // Generate database schema - if ($this->filesystem->exists($this->phpbb_root_path . 'install/schemas/schema.json')) + if ($this->filesystem->exists($this->phpbb_root_path . 'phpbb/install/schemas/schema.json')) { - $db_table_schema = @file_get_contents($this->phpbb_root_path . 'install/schemas/schema.json'); + $db_table_schema = @file_get_contents($this->phpbb_root_path . 'phpbb/install/schemas/schema.json'); $db_table_schema = json_decode($db_table_schema, true); $change_prefix = true; } From 524b98e7bd19bff7b12c7ba4c771d6d60d4300a6 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 19 Jun 2015 01:26:42 +0200 Subject: [PATCH 0459/1676] [ticket/13740] Fix controller class name in service definition PHPBB3-13740 --- .../config/installer/container/services_install_controller.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/config/installer/container/services_install_controller.yml b/phpBB/config/installer/container/services_install_controller.yml index 6e6ef4acea..c8d140aa5f 100644 --- a/phpBB/config/installer/container/services_install_controller.yml +++ b/phpBB/config/installer/container/services_install_controller.yml @@ -1,6 +1,6 @@ services: phpbb.installer.controller.welcome: - class: phpbb\install\controller\install_index + class: phpbb\install\controller\installer_index arguments: - @phpbb.installer.controller.helper - @language From 06f4ebce1b1cc8ecd5ddd84f7d2705007a685de3 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 31 May 2015 17:19:42 +0200 Subject: [PATCH 0460/1676] [ticket/13740] CLI installer and fixes [ci skip] PHPBB3-13740 --- .../container/services_install_console.yml | 44 ++++ .../container/services_installer.yml | 5 + phpBB/install-config.yml | 35 +++ phpBB/install/phpbbcli.php | 68 +++++ phpBB/phpbb/console/application.php | 2 +- .../command/install/config/default_config.php | 103 ++++++++ .../console/command/install/config/show.php | 131 ++++++++++ .../command/install/config/validate.php | 132 ++++++++++ .../console/command/install/install.php | 194 +++++++++++++++ phpBB/phpbb/install/helper/config.php | 10 + .../helper/iohandler/ajax_iohandler.php | 2 + .../helper/iohandler/cli_iohandler.php | 235 ++++++++++++++++++ .../install/helper/iohandler/factory.php | 7 +- .../helper/iohandler/iohandler_base.php | 34 ++- .../helper/iohandler/iohandler_interface.php | 27 +- .../phpbb/install/installer_configuration.php | 140 +++++++++++ .../obtain_data/task/obtain_database_data.php | 2 +- .../install/module/requirements/module.php | 1 + 18 files changed, 1165 insertions(+), 7 deletions(-) create mode 100644 phpBB/config/installer/container/services_install_console.yml create mode 100644 phpBB/install-config.yml create mode 100755 phpBB/install/phpbbcli.php create mode 100644 phpBB/phpbb/install/console/command/install/config/default_config.php create mode 100644 phpBB/phpbb/install/console/command/install/config/show.php create mode 100644 phpBB/phpbb/install/console/command/install/config/validate.php create mode 100644 phpBB/phpbb/install/console/command/install/install.php create mode 100644 phpBB/phpbb/install/helper/iohandler/cli_iohandler.php create mode 100644 phpBB/phpbb/install/installer_configuration.php diff --git a/phpBB/config/installer/container/services_install_console.yml b/phpBB/config/installer/container/services_install_console.yml new file mode 100644 index 0000000000..9a4808b6aa --- /dev/null +++ b/phpBB/config/installer/container/services_install_console.yml @@ -0,0 +1,44 @@ +services: + console.installer.command_collection: + class: phpbb\di\service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: console.installer.command } + + console.installer.command.install: + class: phpbb\install\console\command\install\install + arguments: + - @language + - @installer.helper.iohandler_factory + - @installer.installer.install + tags: + - { name: console.installer.command } + + console.installer.command.config.default: + class: phpbb\install\console\command\install\config\default_config + arguments: + - @language + - @installer.helper.iohandler_factory + - @installer.installer.install + tags: + - { name: console.installer.command } + + console.installer.command.config.show: + class: phpbb\install\console\command\install\config\show + arguments: + - @language + - @installer.helper.iohandler_factory + - @installer.installer.install + tags: + - { name: console.installer.command } + + + console.installer.command.config.validate: + class: phpbb\install\console\command\install\config\validate + arguments: + - @language + - @installer.helper.iohandler_factory + - @installer.installer.install + tags: + - { name: console.installer.command } diff --git a/phpBB/config/installer/container/services_installer.yml b/phpBB/config/installer/container/services_installer.yml index ce27ae8abd..4c171f3fe7 100644 --- a/phpBB/config/installer/container/services_installer.yml +++ b/phpBB/config/installer/container/services_installer.yml @@ -1,4 +1,5 @@ imports: + - { resource: services_install_console.yml } - { resource: services_install_controller.yml } - { resource: services_install_data.yml } - { resource: services_install_database.yml } @@ -40,6 +41,10 @@ services: - @request - @template + installer.helper.iohandler_cli: + class: phpbb\install\helper\iohandler\cli_iohandler + parent: installer.helper.iohandler_abstract + installer.helper.iohandler: class: phpbb\install\helper\iohandler\iohandler_interface factory: ["@installer.helper.iohandler_factory", get] diff --git a/phpBB/install-config.yml b/phpBB/install-config.yml new file mode 100644 index 0000000000..d49e322a1f --- /dev/null +++ b/phpBB/install-config.yml @@ -0,0 +1,35 @@ +installer: + admin: + name: admin + password: adminadmin + email: admin@example.org + + board: + lang: en + name: My Board + description: My amazing new phpBB board + + database: + dbms: sqlite3 + dbhost: /tmp/phpbb.sqlite3 + dbport: ~ + dbuser: ~ + dbpasswd: ~ + dbname: ~ + table_prefix: phpbb_ + + email: + enabled: false + smtp_delivery : ~ + smtp_host: ~ + smtp_auth: ~ + smtp_user: ~ + smtp_pass: ~ + + server: + cookie_secure: false + server_protocol: http:// + force_server_vars: false + server_name: localhost + server_port: 80 + script_path: / diff --git a/phpBB/install/phpbbcli.php b/phpBB/install/phpbbcli.php new file mode 100755 index 0000000000..20a202f584 --- /dev/null +++ b/phpBB/install/phpbbcli.php @@ -0,0 +1,68 @@ +#!/usr/bin/env php + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use Symfony\Component\Console\Input\ArgvInput; + +if (php_sapi_name() !== 'cli') +{ + echo 'This program must be run from the command line.' . PHP_EOL; + exit(1); +} + +define('IN_PHPBB', true); +define('IN_INSTALL', true); +define('PHPBB_ENVIRONMENT', 'production'); +$phpbb_root_path = __DIR__ . '/../'; +$phpEx = substr(strrchr(__FILE__, '.'), 1); + +// +// Let's do the common.php logic +// +require($phpbb_root_path . 'includes/startup.' . $phpEx); +require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx); + +$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx); +$phpbb_class_loader->register(); + +// In case $phpbb_adm_relative_path is not set (in case of an update), use the default. +$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/'; +$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path; + +// Include files +require($phpbb_root_path . 'includes/functions.' . $phpEx); +require($phpbb_root_path . 'includes/functions_content.' . $phpEx); +include($phpbb_root_path . 'includes/functions_compatibility.' . $phpEx); +require($phpbb_root_path . 'includes/functions_user.' . $phpEx); +require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); + +// Set PHP error handler to ours +set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler'); + +$phpbb_installer_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); +$phpbb_installer_container = $phpbb_installer_container_builder + ->with_environment('installer') + ->without_extensions() + ->without_cache() + ->get_container(); + +/** @var \phpbb\filesystem\filesystem $phpbb_filesystem */ +$phpbb_filesystem = $phpbb_installer_container->get('filesystem'); + +/** @var \phpbb\language\language $language */ +$language = $phpbb_installer_container->get('language'); +$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting', 'cli')); + +$application = new \phpbb\console\application('phpBB Installer', PHPBB_VERSION, $language); +$application->register_container_commands($phpbb_installer_container->get('console.installer.command_collection')); +$application->run($input); diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php index bc4897af18..0943e8a4b8 100644 --- a/phpBB/phpbb/console/application.php +++ b/phpBB/phpbb/console/application.php @@ -35,7 +35,7 @@ class application extends \Symfony\Component\Console\Application * @param string $version The version of the application * @param \phpbb\user $user The user which runs the application (used for translation) */ - public function __construct($name, $version, \phpbb\user $user) + public function __construct($name, $version, $user) { $this->user = $user; diff --git a/phpBB/phpbb/install/console/command/install/config/default_config.php b/phpBB/phpbb/install/console/command/install/config/default_config.php new file mode 100644 index 0000000000..75c9f94901 --- /dev/null +++ b/phpBB/phpbb/install/console/command/install/config/default_config.php @@ -0,0 +1,103 @@ + +* @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\install\console\command\install\config; + +use phpbb\language\language; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Yaml\Yaml; + +class default_config extends \phpbb\console\command\command +{ + /** + * @var language + */ + protected $language; + + /** + * Constructor + * + * @param language $language + */ + public function __construct(language $language) + { + $this->language = $language; + + parent::__construct(new \phpbb\user($language, 'datetime')); + } + + /** + * + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('install:config:default') + ; + } + + /** + * Display the default configuration + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * + * @return null + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $default_config = <<writeln($default_config); + } +} diff --git a/phpBB/phpbb/install/console/command/install/config/show.php b/phpBB/phpbb/install/console/command/install/config/show.php new file mode 100644 index 0000000000..4155440fc3 --- /dev/null +++ b/phpBB/phpbb/install/console/command/install/config/show.php @@ -0,0 +1,131 @@ + +* @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\install\console\command\install\config; + +use phpbb\install\helper\iohandler\factory; +use phpbb\install\installer; +use phpbb\install\installer_configuration; +use phpbb\language\language; +use Symfony\Component\Config\Definition\Exception\Exception; +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Yaml; + +class show extends \phpbb\console\command\command +{ + /** + * @var factory + */ + protected $iohandler_factory; + + /** + * @var installer + */ + protected $installer; + + /** + * @var language + */ + protected $language; + + /** + * Constructor + * + * @param language $language + * @param factory $factory + * @param installer $installer + */ + public function __construct(language $language, factory $factory, installer $installer) + { + $this->iohandler_factory = $factory; + $this->installer = $installer; + $this->language = $language; + + parent::__construct(new \phpbb\user($language, 'datetime')); + } + + /** + * + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('install:config:show') + ->addArgument( + 'config-file', + InputArgument::REQUIRED, + $this->language->lang('CLI_CONFIG_FILE')) + ->setDescription($this->language->lang('CLI_INSTALL_SHOW_CONFIG')) + ; + } + + /** + * Show the validated configuration + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * + * @return null + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->iohandler_factory->set_environment('cli'); + + /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */ + $iohandler = $this->iohandler_factory->get(); + $style = new SymfonyStyle($input, $output); + $iohandler->set_style($style, $output); + + $config_file = $input->getArgument('config-file'); + + if (!is_file($config_file)) + { + $iohandler->add_error_message(array('MISSING_FILE', array($config_file))); + + return; + } + + try + { + $config = Yaml::parse(file_get_contents($config_file), true, false); + } + catch (ParseException $e) + { + $iohandler->add_error_message('INVALID_YAML_FILE'); + + return; + } + + $processor = new Processor(); + $configuration = new installer_configuration(); + + try + { + $config = $processor->processConfiguration($configuration, $config); + } + catch (Exception $e) + { + $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage()); + + return; + } + + $iohandler->add_log_message(Yaml::dump(array('installer' => $config), 10, 4, true, false)); + } +} diff --git a/phpBB/phpbb/install/console/command/install/config/validate.php b/phpBB/phpbb/install/console/command/install/config/validate.php new file mode 100644 index 0000000000..19b6f99a8b --- /dev/null +++ b/phpBB/phpbb/install/console/command/install/config/validate.php @@ -0,0 +1,132 @@ + +* @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\install\console\command\install\config; + +use phpbb\install\helper\iohandler\factory; +use phpbb\install\installer; +use phpbb\install\installer_configuration; +use phpbb\language\language; +use Symfony\Component\Config\Definition\Exception\Exception; +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Yaml; + +class validate extends \phpbb\console\command\command +{ + /** + * @var factory + */ + protected $iohandler_factory; + + /** + * @var installer + */ + protected $installer; + + /** + * @var language + */ + protected $language; + + /** + * Constructor + * + * @param language $language + * @param factory $factory + * @param installer $installer + */ + public function __construct(language $language, factory $factory, installer $installer) + { + $this->iohandler_factory = $factory; + $this->installer = $installer; + $this->language = $language; + + parent::__construct(new \phpbb\user($language, 'datetime')); + } + + /** + * + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('install:config:validate') + ->addArgument( + 'config-file', + InputArgument::REQUIRED, + $this->language->lang('CLI_CONFIG_FILE')) + ->setDescription($this->language->lang('CLI_INSTALL_VALIDATE_CONFIG')) + ; + } + + /** + * Validate the configuration file + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * + * @return null + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->iohandler_factory->set_environment('cli'); + + /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */ + $iohandler = $this->iohandler_factory->get(); + $style = new SymfonyStyle($input, $output); + $iohandler->set_style($style, $output); + + $config_file = $input->getArgument('config-file'); + + if (!is_file($config_file)) + { + $iohandler->add_error_message(array('MISSING_FILE', array($config_file))); + + return 1; + } + + try + { + $config = Yaml::parse(file_get_contents($config_file), true, false); + } + catch (ParseException $e) + { + $iohandler->add_error_message('INVALID_YAML_FILE'); + + return 1; + } + + $processor = new Processor(); + $configuration = new installer_configuration(); + + try + { + $config = $processor->processConfiguration($configuration, $config); + } + catch (Exception $e) + { + $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage()); + + return 1; + } + + $iohandler->add_success_message('CONFIGURATION_VALID'); + return 0; + } +} diff --git a/phpBB/phpbb/install/console/command/install/install.php b/phpBB/phpbb/install/console/command/install/install.php new file mode 100644 index 0000000000..d3f6d363f8 --- /dev/null +++ b/phpBB/phpbb/install/console/command/install/install.php @@ -0,0 +1,194 @@ + +* @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\install\console\command\install; + +use phpbb\install\exception\installer_exception; +use phpbb\install\helper\iohandler\cli_iohandler; +use phpbb\install\helper\iohandler\factory; +use phpbb\install\installer; +use phpbb\install\installer_configuration; +use phpbb\language\language; +use Symfony\Component\Config\Definition\Exception\Exception; +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Yaml; + +class install extends \phpbb\console\command\command +{ + /** + * @var factory + */ + protected $iohandler_factory; + + /** + * @var installer + */ + protected $installer; + + /** + * @var language + */ + protected $language; + + /** + * Constructor + * + * @param language $language + * @param factory $factory + * @param installer $installer + */ + public function __construct(language $language, factory $factory, installer $installer) + { + $this->iohandler_factory = $factory; + $this->installer = $installer; + $this->language = $language; + + parent::__construct(new \phpbb\user($language, 'datetime')); + } + + /** + * + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('install') + ->addArgument( + 'config-file', + InputArgument::REQUIRED, + $this->language->lang('CLI_CONFIG_FILE')) + ->setDescription($this->language->lang('CLI_INSTALL_BOARD')) + ; + } + + /** + * Executes the command install. + * + * Install the board + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * + * @return null + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + // @todo check that phpBB is not already installed + + $this->iohandler_factory->set_environment('cli'); + + /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */ + $iohandler = $this->iohandler_factory->get(); + $style = new SymfonyStyle($input, $output); + $iohandler->set_style($style, $output); + + $this->installer->set_iohandler($iohandler); + + $config_file = $input->getArgument('config-file'); + + if (!is_file($config_file)) + { + $iohandler->add_error_message(array('MISSING_FILE', array($config_file))); + + return; + } + + try + { + $config = Yaml::parse(file_get_contents($config_file), true, false); + } + catch (ParseException $e) + { + $iohandler->add_error_message('INVALID_YAML_FILE'); + + return; + } + + $processor = new Processor(); + $configuration = new installer_configuration(); + + try + { + $config = $processor->processConfiguration($configuration, $config); + } + catch (Exception $e) + { + $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage()); + + return; + } + + $this->register_configuration($iohandler, $config); + + try + { + $this->installer->run(); + } + catch (installer_exception $e) + { + $iohandler->add_error_message($e->getMessage()); + return; + } + } + + /** + * Register the configuration to simulate the forms. + * + * @param cli_iohandler $iohandler + * @param array $config + */ + private function register_configuration(cli_iohandler $iohandler, $config) + { + $iohandler->set_input('admin_name', $config['admin']['name']); + $iohandler->set_input('admin_pass1', $config['admin']['password']); + $iohandler->set_input('admin_pass2', $config['admin']['password']); + $iohandler->set_input('board_email', $config['admin']['email']); + $iohandler->set_input('submit_admin', 'submit'); + + $iohandler->set_input('default_lang', $config['board']['lang']); + $iohandler->set_input('board_name', $config['board']['name']); + $iohandler->set_input('board_description', $config['board']['description']); + $iohandler->set_input('submit_board', 'submit'); + + $iohandler->set_input('dbms', $config['database']['dbms']); + $iohandler->set_input('dbhost', $config['database']['dbhost']); + $iohandler->set_input('dbport', $config['database']['dbport']); + $iohandler->set_input('dbuser', $config['database']['dbuser']); + $iohandler->set_input('dbpasswd', $config['database']['dbpasswd']); + $iohandler->set_input('dbname', $config['database']['dbname']); + $iohandler->set_input('table_prefix', $config['database']['table_prefix']); + $iohandler->set_input('submit_database', 'submit'); + + $iohandler->set_input('email_enable', $config['email']['enabled']); + $iohandler->set_input('smtp_delivery', $config['email']['smtp_delivery']); + $iohandler->set_input('smtp_host', $config['email']['smtp_host']); + $iohandler->set_input('smtp_auth', $config['email']['smtp_auth']); + $iohandler->set_input('smtp_user', $config['email']['smtp_user']); + $iohandler->set_input('smtp_pass', $config['email']['smtp_pass']); + $iohandler->set_input('submit_email', 'submit'); + + $iohandler->set_input('cookie_secure', $config['server']['cookie_secure']); + $iohandler->set_input('server_protocol', $config['server']['server_protocol']); + $iohandler->set_input('force_server_vars', $config['server']['force_server_vars']); + $iohandler->set_input('server_name', $config['server']['server_name']); + $iohandler->set_input('server_port', $config['server']['server_port']); + $iohandler->set_input('script_path', $config['server']['script_path']); + $iohandler->set_input('submit_server', 'submit'); + } +} diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php index 5c1348c06d..cf51432332 100644 --- a/phpBB/phpbb/install/helper/config.php +++ b/phpBB/phpbb/install/helper/config.php @@ -147,6 +147,11 @@ class config */ public function get_time_remaining() { + if ($this->system_data['max_execution_time'] <= 0) + { + return 1; + } + return ($this->system_data['start_time'] + $this->system_data['max_execution_time']) - time(); } @@ -157,6 +162,11 @@ class config */ public function get_memory_remaining() { + if ($this->system_data['memory_limit'] <= 0) + { + return 1; + } + if (function_exists('memory_get_usage')) { return ($this->system_data['memory_limit'] - memory_get_usage()); diff --git a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php index 71571fecba..85cb2ca753 100644 --- a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php @@ -182,6 +182,7 @@ class ajax_iohandler extends iohandler_base 'errors' => $this->errors, 'warnings' => $this->warnings, 'logs' => $this->logs, + 'success' => $this->success, ); if (!empty($this->form)) @@ -208,6 +209,7 @@ class ajax_iohandler extends iohandler_base $this->errors = array(); $this->warnings = array(); $this->logs = array(); + $this->success = array(); $this->nav_data = array(); if ($this->request_client_refresh) diff --git a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php new file mode 100644 index 0000000000..d990f48925 --- /dev/null +++ b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php @@ -0,0 +1,235 @@ + + * @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\install\helper\iohandler; + +use phpbb\install\exception\installer_exception; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\OutputStyle; + +/** + * Input-Output handler for the CLI frontend + */ +class cli_iohandler extends iohandler_base +{ + /** + * @var OutputInterface + */ + protected $output; + + /** + * @var OutputStyle + */ + protected $io; + + /** + * @var array + */ + protected $input_values = array(); + + /** + * @var ProgressBar + */ + protected $progress_bar; + + /** + * Set the style and output used to display feedback; + * + * @param OutputStyle $style + */ + public function set_style(OutputStyle $style, OutputInterface $output) + { + $this->io = $style; + $this->output = $output; + } + + /** + * {@inheritdoc} + */ + public function get_input($name, $default, $multibyte = false) + { + $result = $default; + + if (isset($this->input_values[$name])) + { + $result = $this->input_values[$name]; + } + + + if ($multibyte) + { + return utf8_normalize_nfc($result); + } + + return $result; + } + + public function set_input($name, $value) + { + $this->input_values[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function get_server_variable($name, $default = '') + { + return $default; + } + + /** + * {@inheritdoc} + */ + public function get_header_variable($name, $default = '') + { + return $default; + } + + /** + * {@inheritdoc} + */ + public function is_secure() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function add_user_form_group($title, $form) + { + throw new installer_exception('MISSING_DATA'); + } + + /** + * {@inheritdoc} + */ + public function send_response() + { + } + + /** + * {@inheritdoc + */ + public function add_error_message($error_title, $error_description = false) + { + $this->io->newLine(); + + $message = $this->translate_message($error_title, $error_description); + $this->io->error($message['title'] . "\n" . $message['description']); + + if ($this->progress_bar !== null) + { + $this->io->newLine(2); + $this->progress_bar->display(); + } + } + + /** + * {@inheritdoc + */ + public function add_warning_message($warning_title, $warning_description = false) + { + $this->io->newLine(); + + $message = $this->translate_message($warning_title, $warning_description); + $this->io->warning($message['title'] . "\n" . $message['description']); + + if ($this->progress_bar !== null) + { + $this->io->newLine(2); + $this->progress_bar->display(); + } + } + + /** + * {@inheritdoc + */ + public function add_log_message($log_title, $log_description = false) + { + if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) + { + $this->output->writeln(sprintf('[%3d/%-3d] ---- %s', $this->current_task_progress, $this->task_progress_count, $this->translate_message($log_title, $log_description)['title'])); + } + } + + /** + * {@inheritdoc + */ + public function add_success_message($error_title, $error_description = false) + { + $this->io->newLine(); + + $message = $this->translate_message($error_title, $error_description); + $this->io->success($message['title'] . "\n" . $message['description']); + + if ($this->progress_bar !== null) + { + $this->io->newLine(2); + $this->progress_bar->display(); + } + } + + public function set_task_count($task_count) + { + parent::set_task_count($task_count); + + if ($this->output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) + { + $this->progress_bar = $this->io->createProgressBar($task_count); + $this->progress_bar->setFormat( + " %current:3s%/%max:-3s% %bar% %percent:3s%%\n" . + " %message%\n"); + $this->progress_bar->setBarWidth(60); + + if (!defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->progress_bar->setEmptyBarCharacter('â–‘'); // light shade character \u2591 + $this->progress_bar->setProgressCharacter(''); + $this->progress_bar->setBarCharacter('â–“'); // dark shade character \u2593 + } + $this->progress_bar->setMessage(''); + $this->io->newLine(2); + $this->progress_bar->start(); + } + } + + public function set_progress($task_lang_key, $task_number) + { + parent::set_progress($task_lang_key, $task_number); + + if ($this->progress_bar !== null) + { + $this->progress_bar->setProgress($this->current_task_progress); + $this->progress_bar->setMessage($this->current_task_name); + } + else + { + $this->output->writeln(sprintf('[%3d/%-3d] %s', $this->current_task_progress, $this->task_progress_count, $this->current_task_name)); + } + } + + /** + * {@inheritdoc} + */ + public function finish_progress($message_lang_key) + { + parent::finish_progress($message_lang_key); + + if ($this->progress_bar !== null) + { + $this->progress_bar->finish(); + $this->progress_bar = null; + } + } +} diff --git a/phpBB/phpbb/install/helper/iohandler/factory.php b/phpBB/phpbb/install/helper/iohandler/factory.php index 0af75b78ae..7081af06a5 100644 --- a/phpBB/phpbb/install/helper/iohandler/factory.php +++ b/phpBB/phpbb/install/helper/iohandler/factory.php @@ -59,7 +59,7 @@ class factory */ public function get() { - switch ($this->environment) + if ($this->container->has('installer.helper.iohandler_' . $this->environment)) { case 'ajax': return $this->container->get('installer.helper.iohandler_ajax'); @@ -68,9 +68,14 @@ class factory // @todo replace this return $this->container->get('installer.helper.iohandler_ajax'); break; + case 'cli': + return $this->container->get('installer.helper.iohandler_cli'); + break; default: throw new iohandler_not_implemented_exception(); break; } + + throw new iohandler_not_implemented_exception(); } } diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php index f767ecf4e9..006411f1e3 100644 --- a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php +++ b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php @@ -43,6 +43,13 @@ abstract class iohandler_base implements iohandler_interface */ protected $logs; + /** + * Array of success messages + * + * @var array + */ + protected $success; + /** * @var \phpbb\language\language */ @@ -71,6 +78,7 @@ abstract class iohandler_base implements iohandler_interface $this->errors = array(); $this->warnings = array(); $this->logs = array(); + $this->success = array(); $this->task_progress_count = 0; $this->current_task_progress = 0; @@ -111,6 +119,14 @@ abstract class iohandler_base implements iohandler_interface $this->logs[] = $this->translate_message($log_title, $log_description); } + /** + * {@inheritdoc} + */ + public function add_success_message($success_title, $success_description = false) + { + $this->success[] = $this->translate_message($success_title, $success_description); + } + /** * {@inheritdoc} */ @@ -124,11 +140,27 @@ abstract class iohandler_base implements iohandler_interface */ public function set_progress($task_lang_key, $task_number) { + $this->current_task_name = ''; + if (!empty($task_lang_key)) { $this->current_task_name = $this->language->lang($task_lang_key); - $this->current_task_progress = $task_number; } + + $this->current_task_progress = $task_number; + } + + /** + * {@inheritdoc} + */ + public function finish_progress($message_lang_key) + { + if (!empty($message_lang_key)) + { + $this->current_task_name = $this->language->lang($message_lang_key); + } + + $this->current_task_progress = $this->task_progress_count; } /** diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php index c40fea24ce..44b409bb0a 100644 --- a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php +++ b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php @@ -85,7 +85,7 @@ interface iohandler_interface * * @param string|array $warning_title Title of the warning message * @param string|bool|array $warning_description Description of the warning (and possibly guidelines to resolve it), - * or false if the error description is not available + * or false if the warning description is not available */ public function add_warning_message($warning_title, $warning_description = false); @@ -96,11 +96,25 @@ interface iohandler_interface * resolved as printf($param[0], $param[1], ...). * * @param string|array $log_title Title of the log message - * @param string|bool|array $log_description Description of the log (and possibly guidelines to resolve it), - * or false if the error description is not available + * @param string|bool|array $log_description Description of the log, + * or false if the log description is not available */ public function add_log_message($log_title, $log_description = false); + /** + * Adds a success message to the rendering queue + * + * Note: When an array is passed into the parameters below, it will be + * resolved as printf($param[0], $param[1], ...). + * + * @param string|array $success_title Title of the success message + * @param string|bool|array $success_description Description of the success, + * or false if the success description is not available + * + * @return null + */ + public function add_success_message($success_title, $success_description = false); + /** * Adds a requested data group to the rendering queue * @@ -142,4 +156,11 @@ interface iohandler_interface * @param array $menu_path Array to the navigation elem */ public function set_finished_stage_menu($menu_path); + + /** + * Finish the progress bar + * + * @param string $message_lang_key Language key for the message + */ + public function finish_progress($message_lang_key); } diff --git a/phpBB/phpbb/install/installer_configuration.php b/phpBB/phpbb/install/installer_configuration.php new file mode 100644 index 0000000000..ab02da8686 --- /dev/null +++ b/phpBB/phpbb/install/installer_configuration.php @@ -0,0 +1,140 @@ + +* @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\install; + +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; + +class installer_configuration implements ConfigurationInterface +{ + + /** + * Generates the configuration tree builder. + * + * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder + */ + public function getConfigTreeBuilder() + { + $treeBuilder = new TreeBuilder(); + $rootNode = $treeBuilder->root('installer'); + $rootNode + ->children() + ->arrayNode('admin') + ->children() + ->scalarNode('name')->defaultValue('admin')->cannotBeEmpty()->end() + ->scalarNode('password')->defaultValue('adminadmin')->cannotBeEmpty()->end() + ->scalarNode('email')->defaultValue('admin@example.org')->cannotBeEmpty()->end() + ->end() + ->end() + ->arrayNode('board') + ->children() + ->scalarNode('lang') + ->defaultValue('en') + ->cannotBeEmpty() + ->end() + ->scalarNode('name') + ->defaultValue('My Board') + ->cannotBeEmpty() + ->end() + ->scalarNode('description') + ->defaultValue('My amazing new phpBB board') + ->cannotBeEmpty() + ->end() + ->end() + ->end() + ->arrayNode('database') + ->children() + ->scalarNode('dbms') + ->defaultValue('sqlite3') + ->cannotBeEmpty() + ->isRequired() + ->end() + ->scalarNode('dbhost') + ->defaultValue(null) + ->end() + ->scalarNode('dbport') + ->defaultValue(null) + ->end() + ->scalarNode('dbuser') + ->defaultValue(null) + ->end() + ->scalarNode('dbpasswd') + ->defaultValue(null) + ->end() + ->scalarNode('dbname') + ->defaultValue(null) + ->end() + ->scalarNode('table_prefix') + ->defaultValue('phpbb_') + ->cannotBeEmpty() + ->isRequired() + ->end() + ->end() + ->end() + ->arrayNode('email') + ->canBeEnabled() + ->addDefaultsIfNotSet() + ->children() + ->booleanNode('smtp_delivery') + ->defaultValue(false) + ->treatNullLike(false) + ->end() + ->scalarNode('smtp_host') + ->defaultValue(null) + ->end() + ->scalarNode('smtp_auth') + ->defaultValue(null) + ->end() + ->scalarNode('smtp_user') + ->defaultValue(null) + ->end() + ->scalarNode('smtp_pass') + ->defaultValue(null) + ->end() + ->end() + ->end() + ->arrayNode('server') + ->children() + ->booleanNode('cookie_secure') + ->defaultValue(false) + ->treatNullLike(false) + ->end() + ->scalarNode('server_protocol') + ->defaultValue('http://') + ->cannotBeEmpty() + ->end() + ->booleanNode('force_server_vars') + ->defaultValue(false) + ->treatNullLike(false) + ->end() + ->scalarNode('server_name') + ->defaultValue('localhost') + ->cannotBeEmpty() + ->end() + ->integerNode('server_port') + ->defaultValue(80) + ->min(1) + ->cannotBeEmpty() + ->end() + ->scalarNode('script_path') + ->defaultValue('/') + ->cannotBeEmpty() + ->end() + ->end() + ->end() + ->end() + ; + return $treeBuilder; + } +} diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php index 0c1146d9f5..f0e7f1f686 100644 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php @@ -238,7 +238,7 @@ class obtain_database_data extends \phpbb\install\task_base implements \phpbb\in $connect_test = $this->database_helper->check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix); if (is_array($connect_test)) { - foreach ($prefix_valid as $error) + foreach ($connect_test as $error) { $this->io_handler->add_error_message( $error['title'], diff --git a/phpBB/phpbb/install/module/requirements/module.php b/phpBB/phpbb/install/module/requirements/module.php index d87ca15128..208cb5aad6 100644 --- a/phpBB/phpbb/install/module/requirements/module.php +++ b/phpBB/phpbb/install/module/requirements/module.php @@ -14,6 +14,7 @@ namespace phpbb\install\module\requirements; use phpbb\install\exception\user_interaction_required_exception; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; class module extends \phpbb\install\module_base { From 249345d9cc6d6bff380436d6e05f24918d762c0d Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Sat, 27 Jun 2015 17:10:42 +0200 Subject: [PATCH 0461/1676] [ticket/13740] Clean up CLI merge [ci skip] PHPBB3-13740 --- .../helper/iohandler/cli_iohandler.php | 21 +++++++++++++++++++ .../install/helper/iohandler/factory.php | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php index d990f48925..f711abe431 100644 --- a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php @@ -232,4 +232,25 @@ class cli_iohandler extends iohandler_base $this->progress_bar = null; } } + + /** + * {@inheritdoc} + */ + public function request_refresh() + { + } + + /** + * {@inheritdoc} + */ + public function set_active_stage_menu($menu_path) + { + } + + /** + * {@inheritdoc} + */ + public function set_finished_stage_menu($menu_path) + { + } } diff --git a/phpBB/phpbb/install/helper/iohandler/factory.php b/phpBB/phpbb/install/helper/iohandler/factory.php index 7081af06a5..52d24e49b2 100644 --- a/phpBB/phpbb/install/helper/iohandler/factory.php +++ b/phpBB/phpbb/install/helper/iohandler/factory.php @@ -59,7 +59,7 @@ class factory */ public function get() { - if ($this->container->has('installer.helper.iohandler_' . $this->environment)) + switch ($this->environment) { case 'ajax': return $this->container->get('installer.helper.iohandler_ajax'); From 10f6716566fce9d9c38f3dd99419595b2a1cba4c Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 30 Jun 2015 16:36:34 +0200 Subject: [PATCH 0462/1676] [ticket/13740] Restore original install folder This reverts commit 934e2821f1cef5e2e21ad6d96f7beb45647ed81c. PHPBB3-13740 --- phpBB/common.php | 2 +- .../convertors/convert_phpbb20.php | 0 .../convertors/functions_phpbb20.php | 0 .../data/confusables.php | 0 .../database_update.php | 2 +- phpBB/{install_old => install}/index.php | 2 +- .../install_convert.php | 0 phpBB/install/install_install.php | 2368 +++++++++++++++++ phpBB/install/install_main.php | 78 + .../install_update.php | 0 phpBB/{install_old => install}/phpinfo.php | 0 phpBB/install/schemas/index.htm | 10 + phpBB/install/schemas/oracle_schema.sql | 37 + phpBB/install/schemas/postgres_schema.sql | 80 + phpBB/install/schemas/schema_data.sql | 821 ++++++ phpBB/{install => install_new}/app.php | 0 phpBB/{install => install_new}/phpbbcli.php | 0 17 files changed, 3397 insertions(+), 3 deletions(-) rename phpBB/{install_old => install}/convertors/convert_phpbb20.php (100%) rename phpBB/{install_old => install}/convertors/functions_phpbb20.php (100%) rename phpBB/{install_old => install}/data/confusables.php (100%) rename phpBB/{install_old => install}/database_update.php (99%) rename phpBB/{install_old => install}/index.php (99%) rename phpBB/{install_old => install}/install_convert.php (100%) create mode 100644 phpBB/install/install_install.php create mode 100644 phpBB/install/install_main.php rename phpBB/{install_old => install}/install_update.php (100%) rename phpBB/{install_old => install}/phpinfo.php (100%) create mode 100644 phpBB/install/schemas/index.htm create mode 100644 phpBB/install/schemas/oracle_schema.sql create mode 100644 phpBB/install/schemas/postgres_schema.sql create mode 100644 phpBB/install/schemas/schema_data.sql rename phpBB/{install => install_new}/app.php (100%) rename phpBB/{install => install_new}/phpbbcli.php (100%) mode change 100755 => 100644 diff --git a/phpBB/common.php b/phpBB/common.php index 38761cfadc..0b898d9553 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -52,7 +52,7 @@ if (!defined('PHPBB_INSTALLED')) } // $phpbb_root_path accounts for redirects from e.g. /adm - $script_path = trim(dirname($script_name)) . '/' . $phpbb_root_path . 'install/app.' . $phpEx; + $script_path = trim(dirname($script_name)) . '/' . $phpbb_root_path . 'install/index.' . $phpEx; // Replace any number of consecutive backslashes and/or slashes with a single slash // (could happen on some proxy setups and/or Windows servers) $script_path = preg_replace('#[\\\\/]{2,}#', '/', $script_path); diff --git a/phpBB/install_old/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php similarity index 100% rename from phpBB/install_old/convertors/convert_phpbb20.php rename to phpBB/install/convertors/convert_phpbb20.php diff --git a/phpBB/install_old/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php similarity index 100% rename from phpBB/install_old/convertors/functions_phpbb20.php rename to phpBB/install/convertors/functions_phpbb20.php diff --git a/phpBB/install_old/data/confusables.php b/phpBB/install/data/confusables.php similarity index 100% rename from phpBB/install_old/data/confusables.php rename to phpBB/install/data/confusables.php diff --git a/phpBB/install_old/database_update.php b/phpBB/install/database_update.php similarity index 99% rename from phpBB/install_old/database_update.php rename to phpBB/install/database_update.php index 853848d637..7ba11c37c4 100644 --- a/phpBB/install_old/database_update.php +++ b/phpBB/install/database_update.php @@ -122,7 +122,7 @@ if (!isset($config['version_update_from'])) $orig_version = $config['version_update_from']; -$user->add_lang(array('common', 'acp/common', 'install', 'migrator')); +$user->add_lang(array('common', 'acp/common', 'old_install', 'migrator')); // Add own hook handler, if present. :o if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx)) diff --git a/phpBB/install_old/index.php b/phpBB/install/index.php similarity index 99% rename from phpBB/install_old/index.php rename to phpBB/install/index.php index 3559a10971..a1a8fc02b6 100644 --- a/phpBB/install_old/index.php +++ b/phpBB/install/index.php @@ -210,7 +210,7 @@ if (!file_exists($phpbb_root_path . 'language/' . $language) || !is_dir($phpbb_r } // And finally, load the relevant language files -$load_lang_files = array('common', 'acp/common', 'acp/board', 'install', 'posting'); +$load_lang_files = array('common', 'acp/common', 'acp/board', 'old_install', 'posting'); $new_path = $phpbb_root_path . 'install/update/new/language/' . $language . '/'; $old_path = $phpbb_root_path . 'language/' . $language . '/'; diff --git a/phpBB/install_old/install_convert.php b/phpBB/install/install_convert.php similarity index 100% rename from phpBB/install_old/install_convert.php rename to phpBB/install/install_convert.php diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php new file mode 100644 index 0000000000..0e223866b1 --- /dev/null +++ b/phpBB/install/install_install.php @@ -0,0 +1,2368 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +*/ +if (!defined('IN_INSTALL')) +{ + // Someone has tried to access the file direct. This is not a good idea, so exit + exit; +} + +if (!empty($setmodules)) +{ + // If phpBB is already installed we do not include this module + if (phpbb_check_installation_exists($phpbb_root_path, $phpEx) && !file_exists($phpbb_root_path . 'cache/install_lock')) + { + return; + } + + $module[] = array( + 'module_type' => 'install', + 'module_title' => 'INSTALL', + 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1), + 'module_order' => 10, + 'module_subs' => '', + 'module_stages' => array('INTRO', 'REQUIREMENTS', 'DATABASE', 'ADMINISTRATOR', 'CONFIG_FILE', 'ADVANCED', 'CREATE_TABLE', 'FINAL'), + 'module_reqs' => '' + ); +} + +/** +* Installation +*/ +class install_install extends module +{ + /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + function install_install(&$p_master) + { + $this->p_master = &$p_master; + $this->filesystem = new \phpbb\filesystem\filesystem(); + } + + function main($mode, $sub) + { + global $lang, $template, $language, $phpbb_root_path, $phpEx; + global $phpbb_container, $cache, $phpbb_log, $request, $phpbb_config_php_file; + + switch ($sub) + { + case 'intro': + $phpbb_container->get('cache.driver')->purge(); + + $this->page_title = $lang['SUB_INTRO']; + + $template->assign_vars(array( + 'TITLE' => $lang['INSTALL_INTRO'], + 'BODY' => $lang['INSTALL_INTRO_BODY'], + 'L_SUBMIT' => $lang['NEXT_STEP'], + 'S_LANG_SELECT' => '', + 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&sub=requirements&language=$language", + )); + + break; + + case 'requirements': + $this->check_server_requirements($mode, $sub); + + break; + + case 'database': + $this->obtain_database_settings($mode, $sub); + + break; + + case 'administrator': + $this->obtain_admin_settings($mode, $sub); + + break; + + case 'config_file': + $this->create_config_file($mode, $sub); + + break; + + case 'advanced': + $this->obtain_advanced_settings($mode, $sub); + + break; + + case 'create_table': + $this->load_schema($mode, $sub); + break; + + case 'final': + // Enable super globals to prevent issues with the new \phpbb\request\request object + $request->enable_super_globals(); + + // Create a normal container now + $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); + $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container(); + + // Sets the global variables + /* @var $cache \phpbb\cache\service */ + $cache = $phpbb_container->get('cache'); + + /* @var $phpbb_log \phpbb\log\log_interface */ + $phpbb_log = $phpbb_container->get('log'); + + $this->build_search_index($mode, $sub); + $this->add_modules($mode, $sub); + $this->add_language($mode, $sub); + $this->add_bots($mode, $sub); + $this->email_admin($mode, $sub); + $this->disable_avatars_if_unwritable(); + $this->populate_migrations($phpbb_container->get('ext.manager'), $phpbb_container->get('migrator')); + + // Remove the lock file + @unlink($phpbb_root_path . 'cache/install_lock'); + + break; + } + + $this->tpl_name = 'install_install'; + } + + /** + * Checks that the server we are installing on meets the requirements for running phpBB + */ + function check_server_requirements($mode, $sub) + { + global $lang, $template, $phpbb_root_path, $phpEx, $language; + + $this->page_title = $lang['STAGE_REQUIREMENTS']; + + $template->assign_vars(array( + 'TITLE' => $lang['REQUIREMENTS_TITLE'], + 'BODY' => $lang['REQUIREMENTS_EXPLAIN'], + )); + + $passed = array('php' => false, 'db' => false, 'files' => false, 'pcre' => false, 'imagesize' => false, 'json' => false,); + + // Test for basic PHP settings + $template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang['PHP_SETTINGS'], + 'LEGEND_EXPLAIN' => $lang['PHP_SETTINGS_EXPLAIN'], + )); + + // Test the minimum PHP version + $php_version = PHP_VERSION; + + if (version_compare($php_version, '5.3.9') < 0) + { + $result = '' . $lang['NO'] . ''; + } + else + { + $passed['php'] = true; + + // We also give feedback on whether we're running in safe mode + $result = '' . $lang['YES']; + if (@ini_get('safe_mode') == '1' || strtolower(@ini_get('safe_mode')) == 'on') + { + $result .= ', ' . $lang['PHP_SAFE_MODE']; + } + $result .= ''; + } + + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['PHP_VERSION_REQD'], + 'RESULT' => $result, + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + + // Don't check for register_globals on 5.4+ + if (version_compare($php_version, '5.4.0-dev') < 0) + { + // Check for register_globals being enabled + if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on') + { + $result = '' . $lang['NO'] . ''; + } + else + { + $result = '' . $lang['YES'] . ''; + } + + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['PHP_REGISTER_GLOBALS'], + 'TITLE_EXPLAIN' => $lang['PHP_REGISTER_GLOBALS_EXPLAIN'], + 'RESULT' => $result, + + 'S_EXPLAIN' => true, + 'S_LEGEND' => false, + )); + } + + // Check for url_fopen + if (@ini_get('allow_url_fopen') == '1' || strtolower(@ini_get('allow_url_fopen')) == 'on') + { + $result = '' . $lang['YES'] . ''; + } + else + { + $result = '' . $lang['NO'] . ''; + } + + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['PHP_URL_FOPEN_SUPPORT'], + 'TITLE_EXPLAIN' => $lang['PHP_URL_FOPEN_SUPPORT_EXPLAIN'], + 'RESULT' => $result, + + 'S_EXPLAIN' => true, + 'S_LEGEND' => false, + )); + + // Check for getimagesize + if (@function_exists('getimagesize')) + { + $passed['imagesize'] = true; + $result = '' . $lang['YES'] . ''; + } + else + { + $result = '' . $lang['NO'] . ''; + } + + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['PHP_GETIMAGESIZE_SUPPORT'], + 'TITLE_EXPLAIN' => $lang['PHP_GETIMAGESIZE_SUPPORT_EXPLAIN'], + 'RESULT' => $result, + + 'S_EXPLAIN' => true, + 'S_LEGEND' => false, + )); + + // Check for PCRE UTF-8 support + if (@preg_match('//u', '')) + { + $passed['pcre'] = true; + $result = '' . $lang['YES'] . ''; + } + else + { + $result = '' . $lang['NO'] . ''; + } + + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['PCRE_UTF_SUPPORT'], + 'TITLE_EXPLAIN' => $lang['PCRE_UTF_SUPPORT_EXPLAIN'], + 'RESULT' => $result, + + 'S_EXPLAIN' => true, + 'S_LEGEND' => false, + )); + + // Check for php json support + if (@extension_loaded('json')) + { + $passed['json'] = true; + $result = '' . $lang['YES'] . ''; + } + else + { + $result = '' . $lang['NO'] . ''; + } + + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['PHP_JSON_SUPPORT'], + 'TITLE_EXPLAIN' => $lang['PHP_JSON_SUPPORT_EXPLAIN'], + 'RESULT' => $result, + + 'S_EXPLAIN' => true, + 'S_LEGEND' => false, + )); + + $passed['mbstring'] = true; + if (@extension_loaded('mbstring')) + { + // Test for available database modules + $template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang['MBSTRING_CHECK'], + 'LEGEND_EXPLAIN' => $lang['MBSTRING_CHECK_EXPLAIN'], + )); + + $checks = array( + array('func_overload', '&', MB_OVERLOAD_MAIL|MB_OVERLOAD_STRING), + array('encoding_translation', '!=', 0), + array('http_input', '!=', array('pass', '')), + array('http_output', '!=', array('pass', '')) + ); + + foreach ($checks as $mb_checks) + { + $ini_val = @ini_get('mbstring.' . $mb_checks[0]); + switch ($mb_checks[1]) + { + case '&': + if (intval($ini_val) & $mb_checks[2]) + { + $result = '' . $lang['NO'] . ''; + $passed['mbstring'] = false; + } + else + { + $result = '' . $lang['YES'] . ''; + } + break; + + case '!=': + if (!is_array($mb_checks[2]) && $ini_val != $mb_checks[2] || + is_array($mb_checks[2]) && !in_array($ini_val, $mb_checks[2])) + { + $result = '' . $lang['NO'] . ''; + $passed['mbstring'] = false; + } + else + { + $result = '' . $lang['YES'] . ''; + } + break; + } + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['MBSTRING_' . strtoupper($mb_checks[0])], + 'TITLE_EXPLAIN' => $lang['MBSTRING_' . strtoupper($mb_checks[0]) . '_EXPLAIN'], + 'RESULT' => $result, + + 'S_EXPLAIN' => true, + 'S_LEGEND' => false, + )); + } + } + + // Test for available database modules + $template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang['PHP_SUPPORTED_DB'], + 'LEGEND_EXPLAIN' => $lang['PHP_SUPPORTED_DB_EXPLAIN'], + )); + + $available_dbms = get_available_dbms(false, true); + $passed['db'] = $available_dbms['ANY_DB_SUPPORT']; + unset($available_dbms['ANY_DB_SUPPORT']); + + foreach ($available_dbms as $db_name => $db_ary) + { + if (!$db_ary['AVAILABLE']) + { + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['DLL_' . strtoupper($db_name)], + 'RESULT' => '' . $lang['UNAVAILABLE'] . '', + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + } + else + { + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['DLL_' . strtoupper($db_name)], + 'RESULT' => '' . $lang['AVAILABLE'] . '', + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + } + } + + // Test for other modules + $template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang['PHP_OPTIONAL_MODULE'], + 'LEGEND_EXPLAIN' => $lang['PHP_OPTIONAL_MODULE_EXPLAIN'], + )); + + foreach ($this->php_dlls_other as $dll) + { + if (!@extension_loaded($dll)) + { + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['DLL_' . strtoupper($dll)], + 'RESULT' => '' . $lang['UNAVAILABLE'] . '', + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + continue; + } + + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['DLL_' . strtoupper($dll)], + 'RESULT' => '' . $lang['AVAILABLE'] . '', + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + } + + // Can we find Imagemagick anywhere on the system? + $exe = (DIRECTORY_SEPARATOR == '\\') ? '.exe' : ''; + + $magic_home = getenv('MAGICK_HOME'); + $img_imagick = ''; + if (empty($magic_home)) + { + $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/'); + $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH')))); + + $locations = array_merge($path_locations, $locations); + foreach ($locations as $location) + { + // The path might not end properly, fudge it + if (substr($location, -1, 1) !== '/') + { + $location .= '/'; + } + + if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) + { + $img_imagick = str_replace('\\', '/', $location); + continue; + } + } + } + else + { + $img_imagick = str_replace('\\', '/', $magic_home); + } + + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['APP_MAGICK'], + 'RESULT' => ($img_imagick) ? '' . $lang['AVAILABLE'] . ', ' . $img_imagick . '' : '' . $lang['NO_LOCATION'] . '', + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + + // Check permissions on files/directories we need access to + $template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang['FILES_REQUIRED'], + 'LEGEND_EXPLAIN' => $lang['FILES_REQUIRED_EXPLAIN'], + )); + + $directories = array('cache/', 'files/', 'store/'); + + umask(0); + + $passed['files'] = true; + foreach ($directories as $dir) + { + $exists = $write = false; + + // Try to create the directory if it does not exist + if (!file_exists($phpbb_root_path . $dir)) + { + @mkdir($phpbb_root_path . $dir, 0777); + + try + { + $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + } + + // Now really check + if (file_exists($phpbb_root_path . $dir) && is_dir($phpbb_root_path . $dir)) + { + try + { + $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + + $exists = true; + } + + // Now check if it is writable by storing a simple file + $fp = @fopen($phpbb_root_path . $dir . 'test_lock', 'wb'); + if ($fp !== false) + { + $write = true; + } + @fclose($fp); + + @unlink($phpbb_root_path . $dir . 'test_lock'); + + $passed['files'] = ($exists && $write && $passed['files']) ? true : false; + + $exists = ($exists) ? '' . $lang['FOUND'] . '' : '' . $lang['NOT_FOUND'] . ''; + $write = ($write) ? ', ' . $lang['WRITABLE'] . '' : (($exists) ? ', ' . $lang['UNWRITABLE'] . '' : ''); + + $template->assign_block_vars('checks', array( + 'TITLE' => $dir, + 'RESULT' => $exists . $write, + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + } + + // Check permissions on files/directories it would be useful access to + $template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang['FILES_OPTIONAL'], + 'LEGEND_EXPLAIN' => $lang['FILES_OPTIONAL_EXPLAIN'], + )); + + $directories = array('config.' . $phpEx, 'images/avatars/upload/'); + + foreach ($directories as $dir) + { + $write = $exists = true; + if (file_exists($phpbb_root_path . $dir)) + { + if (!$this->filesystem->is_writable($phpbb_root_path . $dir)) + { + $write = false; + } + } + else + { + $write = $exists = false; + } + + $exists_str = ($exists) ? '' . $lang['FOUND'] . '' : '' . $lang['NOT_FOUND'] . ''; + $write_str = ($write) ? ', ' . $lang['WRITABLE'] . '' : (($exists) ? ', ' . $lang['UNWRITABLE'] . '' : ''); + + $template->assign_block_vars('checks', array( + 'TITLE' => $dir, + 'RESULT' => $exists_str . $write_str, + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + } + + // And finally where do we want to go next (well today is taken isn't it :P) + $s_hidden_fields = ($img_imagick) ? '' : ''; + + $url = (!in_array(false, $passed)) ? $this->p_master->module_url . "?mode=$mode&sub=database&language=$language" : $this->p_master->module_url . "?mode=$mode&sub=requirements&language=$language "; + $submit = (!in_array(false, $passed)) ? $lang['INSTALL_START'] : $lang['INSTALL_TEST']; + + $template->assign_vars(array( + 'L_SUBMIT' => $submit, + 'S_HIDDEN' => $s_hidden_fields, + 'U_ACTION' => $url, + )); + } + + /** + * Obtain the information required to connect to the database + */ + function obtain_database_settings($mode, $sub) + { + global $lang, $template, $phpEx; + + $this->page_title = $lang['STAGE_DATABASE']; + + // Obtain any submitted data + $data = $this->get_submitted_data(); + + $connect_test = false; + $error = array(); + $available_dbms = get_available_dbms(false, true); + + // Has the user opted to test the connection? + if (isset($_POST['testdb'])) + { + if (!isset($available_dbms[$data['dbms']]) || !$available_dbms[$data['dbms']]['AVAILABLE']) + { + $error[] = $lang['INST_ERR_NO_DB']; + $connect_test = false; + } + else if (!preg_match(get_preg_expression('table_prefix'), $data['table_prefix'])) + { + $error[] = $lang['INST_ERR_DB_INVALID_PREFIX']; + $connect_test = false; + } + else + { + $connect_test = connect_check_db(true, $error, $available_dbms[$data['dbms']], $data['table_prefix'], $data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport']); + } + + $template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang['DB_CONNECTION'], + 'LEGEND_EXPLAIN' => false, + )); + + if ($connect_test) + { + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['DB_TEST'], + 'RESULT' => '' . $lang['SUCCESSFUL_CONNECT'] . '', + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + } + else + { + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['DB_TEST'], + 'RESULT' => '' . implode('
            ', $error) . '
            ', + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + } + } + + if (!$connect_test) + { + // Update the list of available DBMS modules to only contain those which can be used + $available_dbms_temp = array(); + foreach ($available_dbms as $type => $dbms_ary) + { + if (!$dbms_ary['AVAILABLE']) + { + continue; + } + + $available_dbms_temp[$type] = $dbms_ary; + } + + $available_dbms = &$available_dbms_temp; + + // And now for the main part of this page + $data['table_prefix'] = (!empty($data['table_prefix']) ? $data['table_prefix'] : 'phpbb_'); + + foreach ($this->db_config_options as $config_key => $vars) + { + if (!is_array($vars) && strpos($config_key, 'legend') === false) + { + continue; + } + + if (strpos($config_key, 'legend') !== false) + { + $template->assign_block_vars('options', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang[$vars]) + ); + + continue; + } + + $options = isset($vars['options']) ? $vars['options'] : ''; + + $template->assign_block_vars('options', array( + 'KEY' => $config_key, + 'TITLE' => $lang[$vars['lang']], + 'S_EXPLAIN' => $vars['explain'], + 'S_LEGEND' => false, + 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '', + 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options), + ) + ); + } + } + + // And finally where do we want to go next (well today is taken isn't it :P) + $s_hidden_fields = ($data['img_imagick']) ? '' : ''; + $s_hidden_fields .= ''; + if ($connect_test) + { + foreach ($this->db_config_options as $config_key => $vars) + { + if (!is_array($vars)) + { + continue; + } + $s_hidden_fields .= ''; + } + } + + $url = ($connect_test) ? $this->p_master->module_url . "?mode=$mode&sub=administrator" : $this->p_master->module_url . "?mode=$mode&sub=database"; + $s_hidden_fields .= ($connect_test) ? '' : ''; + + $submit = $lang['NEXT_STEP']; + + $template->assign_vars(array( + 'L_SUBMIT' => $submit, + 'S_HIDDEN' => $s_hidden_fields, + 'U_ACTION' => $url, + )); + } + + /** + * Obtain the administrator's name, password and email address + */ + function obtain_admin_settings($mode, $sub) + { + global $lang, $template, $phpEx; + + $this->page_title = $lang['STAGE_ADMINISTRATOR']; + + // Obtain any submitted data + $data = $this->get_submitted_data(); + + if ($data['dbms'] == '') + { + // Someone's been silly and tried calling this page direct + // So we send them back to the start to do it again properly + $this->p_master->redirect("index.$phpEx?mode=install"); + } + + $s_hidden_fields = ($data['img_imagick']) ? '' : ''; + $passed = false; + + $data['default_lang'] = ($data['default_lang'] !== '') ? $data['default_lang'] : $data['language']; + + if (isset($_POST['check'])) + { + $error = array(); + + // Check the entered email address and password + if ($data['admin_name'] == '' || $data['admin_pass1'] == '' || $data['admin_pass2'] == '' || $data['board_email'] == '') + { + $error[] = $lang['INST_ERR_MISSING_DATA']; + } + + if ($data['admin_pass1'] != $data['admin_pass2'] && $data['admin_pass1'] != '') + { + $error[] = $lang['INST_ERR_PASSWORD_MISMATCH']; + } + + // Test against the default username rules + if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) < 3) + { + $error[] = $lang['INST_ERR_USER_TOO_SHORT']; + } + + if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) > 20) + { + $error[] = $lang['INST_ERR_USER_TOO_LONG']; + } + + // Test against the default password rules + if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) < 6) + { + $error[] = $lang['INST_ERR_PASSWORD_TOO_SHORT']; + } + + if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) > 30) + { + $error[] = $lang['INST_ERR_PASSWORD_TOO_LONG']; + } + + if ($data['board_email'] != '' && !preg_match('/^' . get_preg_expression('email') . '$/i', $data['board_email'])) + { + $error[] = $lang['INST_ERR_EMAIL_INVALID']; + } + + $template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang['STAGE_ADMINISTRATOR'], + 'LEGEND_EXPLAIN' => false, + )); + + if (!sizeof($error)) + { + $passed = true; + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['ADMIN_TEST'], + 'RESULT' => '' . $lang['TESTS_PASSED'] . '', + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + } + else + { + $template->assign_block_vars('checks', array( + 'TITLE' => $lang['ADMIN_TEST'], + 'RESULT' => '' . implode('
            ', $error) . '
            ', + + 'S_EXPLAIN' => false, + 'S_LEGEND' => false, + )); + } + } + + if (!$passed) + { + foreach ($this->admin_config_options as $config_key => $vars) + { + if (!is_array($vars) && strpos($config_key, 'legend') === false) + { + continue; + } + + if (strpos($config_key, 'legend') !== false) + { + $template->assign_block_vars('options', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang[$vars]) + ); + + continue; + } + + $options = isset($vars['options']) ? $vars['options'] : ''; + + $template->assign_block_vars('options', array( + 'KEY' => $config_key, + 'TITLE' => $lang[$vars['lang']], + 'S_EXPLAIN' => $vars['explain'], + 'S_LEGEND' => false, + 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '', + 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options), + ) + ); + } + } + else + { + foreach ($this->admin_config_options as $config_key => $vars) + { + if (!is_array($vars)) + { + continue; + } + $s_hidden_fields .= ''; + } + } + + $s_hidden_fields .= ($data['img_imagick']) ? '' : ''; + $s_hidden_fields .= ''; + + foreach ($this->db_config_options as $config_key => $vars) + { + if (!is_array($vars)) + { + continue; + } + $s_hidden_fields .= ''; + } + + $submit = $lang['NEXT_STEP']; + + $url = ($passed) ? $this->p_master->module_url . "?mode=$mode&sub=config_file" : $this->p_master->module_url . "?mode=$mode&sub=administrator"; + $s_hidden_fields .= ($passed) ? '' : ''; + + $template->assign_vars(array( + 'L_SUBMIT' => $submit, + 'S_HIDDEN' => $s_hidden_fields, + 'U_ACTION' => $url, + )); + } + + /** + * Writes the config file to disk, or if unable to do so offers alternative methods + */ + function create_config_file($mode, $sub) + { + global $lang, $template, $phpbb_root_path, $phpEx; + + $this->page_title = $lang['STAGE_CONFIG_FILE']; + + // Obtain any submitted data + $data = $this->get_submitted_data(); + + if ($data['dbms'] == '') + { + // Someone's been silly and tried calling this page direct + // So we send them back to the start to do it again properly + $this->p_master->redirect("index.$phpEx?mode=install"); + } + + $s_hidden_fields = ($data['img_imagick']) ? '' : ''; + $s_hidden_fields .= ''; + $written = false; + + // Create a list of any PHP modules we wish to have loaded + $available_dbms = get_available_dbms($data['dbms']); + + // Create a lock file to indicate that there is an install in progress + $fp = @fopen($phpbb_root_path . 'cache/install_lock', 'wb'); + if ($fp === false) + { + // We were unable to create the lock file - abort + $this->p_master->error($lang['UNABLE_WRITE_LOCK'], __LINE__, __FILE__); + } + @fclose($fp); + + @chmod($phpbb_root_path . 'cache/install_lock', 0777); + + // Time to convert the data provided into a config file + $config_data = phpbb_create_config_file_data($data, $available_dbms[$data['dbms']]['DRIVER']); + + // Attempt to write out the config file directly. If it works, this is the easiest way to do it ... + if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && $this->filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx)) || $this->filesystem->is_writable($phpbb_root_path)) + { + // Assume it will work ... if nothing goes wrong below + $written = true; + + if (!($fp = @fopen($phpbb_root_path . 'config.' . $phpEx, 'w'))) + { + // Something went wrong ... so let's try another method + $written = false; + } + + if (!(@fwrite($fp, $config_data))) + { + // Something went wrong ... so let's try another method + $written = false; + } + + @fclose($fp); + + if ($written) + { + // We may revert back to chmod() if we see problems with users not able to change their config.php file directly + try + { + $this->filesystem->phpbb_chmod($phpbb_root_path . 'config.' . $phpEx, CHMOD_READ); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + } + } + + if (isset($_POST['dldone'])) + { + // Do a basic check to make sure that the file has been uploaded + // Note that all we check is that the file has _something_ in it + // We don't compare the contents exactly - if they can't upload + // a single file correctly, it's likely they will have other problems.... + if (filesize($phpbb_root_path . 'config.' . $phpEx) > 10) + { + $written = true; + } + } + + $config_options = array_merge($this->db_config_options, $this->admin_config_options); + + foreach ($config_options as $config_key => $vars) + { + if (!is_array($vars)) + { + continue; + } + $s_hidden_fields .= ''; + } + + if (!$written) + { + // OK, so it didn't work let's try the alternatives + + if (isset($_POST['dlconfig'])) + { + // They want a copy of the file to download, so send the relevant headers and dump out the data + header("Content-Type: text/x-delimtext; name=\"config.$phpEx\""); + header("Content-disposition: attachment; filename=config.$phpEx"); + echo $config_data; + exit; + } + + // The option to download the config file is always available, so output it here + $template->assign_vars(array( + 'BODY' => $lang['CONFIG_FILE_UNABLE_WRITE'], + 'L_DL_CONFIG' => $lang['DL_CONFIG'], + 'L_DL_CONFIG_EXPLAIN' => $lang['DL_CONFIG_EXPLAIN'], + 'L_DL_DONE' => $lang['DONE'], + 'L_DL_DOWNLOAD' => $lang['DL_DOWNLOAD'], + 'S_HIDDEN' => $s_hidden_fields, + 'S_SHOW_DOWNLOAD' => true, + 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&sub=config_file", + )); + return; + } + else + { + $template->assign_vars(array( + 'BODY' => $lang['CONFIG_FILE_WRITTEN'], + 'L_SUBMIT' => $lang['NEXT_STEP'], + 'S_HIDDEN' => $s_hidden_fields, + 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&sub=advanced", + )); + return; + } + } + + /** + * Provide an opportunity to customise some advanced settings during the install + * in case it is necessary for them to be set to access later + */ + function obtain_advanced_settings($mode, $sub) + { + global $lang, $template, $phpEx, $request; + + $this->page_title = $lang['STAGE_ADVANCED']; + + // Obtain any submitted data + $data = $this->get_submitted_data(); + + if ($data['dbms'] == '') + { + // Someone's been silly and tried calling this page direct + // So we send them back to the start to do it again properly + $this->p_master->redirect("index.$phpEx?mode=install"); + } + + $s_hidden_fields = ($data['img_imagick']) ? '' : ''; + $s_hidden_fields .= ''; + + // HTTP_HOST is having the correct browser url in most cases... + $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME')))); + + // HTTP HOST can carry a port number... + if (strpos($server_name, ':') !== false) + { + $server_name = substr($server_name, 0, strpos($server_name, ':')); + } + + $data['email_enable'] = ($data['email_enable'] !== '') ? $data['email_enable'] : true; + $data['server_name'] = ($data['server_name'] !== '') ? $data['server_name'] : $server_name; + $data['server_port'] = ($data['server_port'] !== '') ? $data['server_port'] : $request->server('SERVER_PORT', 0); + $data['server_protocol'] = ($data['server_protocol'] !== '') ? $data['server_protocol'] : ($request->is_secure() ? 'https://' : 'http://'); + $data['cookie_secure'] = ($data['cookie_secure'] !== '') ? $data['cookie_secure'] : $request->is_secure(); + + if ($data['script_path'] === '') + { + $name = htmlspecialchars_decode($request->server('PHP_SELF')); + if (!$name) + { + $name = htmlspecialchars_decode($request->server('REQUEST_URI')); + } + + // Replace backslashes and doubled slashes (could happen on some proxy setups) + $name = str_replace(array('\\', '//'), '/', $name); + $data['script_path'] = trim(dirname(dirname($name))); + } + + foreach ($this->advanced_config_options as $config_key => $vars) + { + if (!is_array($vars) && strpos($config_key, 'legend') === false) + { + continue; + } + + if (strpos($config_key, 'legend') !== false) + { + $template->assign_block_vars('options', array( + 'S_LEGEND' => true, + 'LEGEND' => $lang[$vars]) + ); + + continue; + } + + $options = isset($vars['options']) ? $vars['options'] : ''; + + $template->assign_block_vars('options', array( + 'KEY' => $config_key, + 'TITLE' => $lang[$vars['lang']], + 'S_EXPLAIN' => $vars['explain'], + 'S_LEGEND' => false, + 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '', + 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options), + ) + ); + } + + $config_options = array_merge($this->db_config_options, $this->admin_config_options); + foreach ($config_options as $config_key => $vars) + { + if (!is_array($vars)) + { + continue; + } + $s_hidden_fields .= ''; + } + + $submit = $lang['NEXT_STEP']; + + $url = $this->p_master->module_url . "?mode=$mode&sub=create_table"; + + $template->assign_vars(array( + 'BODY' => $lang['STAGE_ADVANCED_EXPLAIN'], + 'L_SUBMIT' => $submit, + 'S_HIDDEN' => $s_hidden_fields, + 'U_ACTION' => $url, + )); + } + + /** + * Load the contents of the schema into the database and then alter it based on what has been input during the installation + */ + function load_schema($mode, $sub) + { + global $db, $lang, $template, $phpbb_root_path, $phpEx, $request; + + $this->page_title = $lang['STAGE_CREATE_TABLE']; + $s_hidden_fields = ''; + + // Obtain any submitted data + $data = $this->get_submitted_data(); + + if ($data['dbms'] == '') + { + // Someone's been silly and tried calling this page direct + // So we send them back to the start to do it again properly + $this->p_master->redirect("index.$phpEx?mode=install"); + } + + // HTTP_HOST is having the correct browser url in most cases... + $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME')))); + $referer = strtolower($request->header('Referer')); + + // HTTP HOST can carry a port number... + if (strpos($server_name, ':') !== false) + { + $server_name = substr($server_name, 0, strpos($server_name, ':')); + } + + $cookie_domain = ($data['server_name'] != '') ? $data['server_name'] : $server_name; + + // Try to come up with the best solution for cookie domain... + if (strpos($cookie_domain, 'www.') === 0) + { + $cookie_domain = str_replace('www.', '.', $cookie_domain); + } + + // If we get here and the extension isn't loaded it should be safe to just go ahead and load it + $available_dbms = get_available_dbms($data['dbms']); + + if (!isset($available_dbms[$data['dbms']])) + { + // Someone's been silly and tried providing a non-existant dbms + $this->p_master->redirect("index.$phpEx?mode=install"); + } + + $dbms = $available_dbms[$data['dbms']]['DRIVER']; + + // Instantiate the database + $db = new $dbms(); + $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false); + + // NOTE: trigger_error does not work here. + $db->sql_return_on_error(true); + + // If mysql is chosen, we need to adjust the schema filename slightly to reflect the correct version. ;) + if ($data['dbms'] == 'mysql') + { + if (version_compare($db->sql_server_info(true), '4.1.3', '>=')) + { + $available_dbms[$data['dbms']]['SCHEMA'] .= '_41'; + } + else + { + $available_dbms[$data['dbms']]['SCHEMA'] .= '_40'; + } + } + + // Ok we have the db info go ahead and read in the relevant schema + // and work on building the table + $dbms_schema = 'schemas/' . $available_dbms[$data['dbms']]['SCHEMA'] . '_schema.sql'; + + // How should we treat this schema? + $delimiter = $available_dbms[$data['dbms']]['DELIM']; + + if (file_exists($dbms_schema)) + { + $sql_query = @file_get_contents($dbms_schema); + $sql_query = preg_replace('#phpbb_#i', $data['table_prefix'], $sql_query); + $sql_query = phpbb_remove_comments($sql_query); + $sql_query = split_sql_file($sql_query, $delimiter); + + foreach ($sql_query as $sql) + { + // Ignore errors when the functions or types already exist + // to allow installing phpBB twice in the same database with + // a different prefix + $db->sql_query($sql); + } + unset($sql_query); + } + + // Ok we have the db info go ahead and work on building the table + if (file_exists('schemas/schema.json')) + { + $db_table_schema = @file_get_contents('schemas/schema.json'); + $db_table_schema = json_decode($db_table_schema, true); + } + else + { + global $phpbb_root_path, $phpEx, $table_prefix; + $table_prefix = 'phpbb_'; + + if (!defined('CONFIG_TABLE')) + { + // We need to include the constants file for the table constants + // when we generate the schema from the migration files. + include($phpbb_root_path . 'includes/constants.' . $phpEx); + } + + $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx); + $classes = $finder->core_path('phpbb/db/migration/data/') + ->get_classes(); + + $sqlite_db = new \phpbb\db\driver\sqlite(); + $factory = new \phpbb\db\tools\factory(); + $db_tools = $factory->get($sqlite_db, true); + $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $sqlite_db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix); + $db_table_schema = $schema_generator->get_schema(); + } + + if (!defined('CONFIG_TABLE')) + { + // CONFIG_TABLE is required by sql_create_index() to check the + // length of index names. However table_prefix is not defined + // here yet, so we need to create the constant ourselves. + define('CONFIG_TABLE', $data['table_prefix'] . 'config'); + } + + $factory = new \phpbb\db\tools\factory(); + $db_tools = $factory->get($db); + foreach ($db_table_schema as $table_name => $table_data) + { + $db_tools->sql_create_table( + $data['table_prefix'] . substr($table_name, 6), + $table_data + ); + } + + // Ok tables have been built, let's fill in the basic information + $sql_query = file_get_contents('schemas/schema_data.sql'); + + // Deal with any special comments and characters + switch ($data['dbms']) + { + case 'mssql': + case 'mssql_odbc': + case 'mssqlnative': + $sql_query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $sql_query); + break; + + case 'postgres': + $sql_query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $sql_query); + break; + + case 'mysql': + case 'mysqli': + $sql_query = str_replace('\\', '\\\\', $sql_query); + break; + } + + // Change prefix + $sql_query = preg_replace('# phpbb_([^\s]*) #i', ' ' . $data['table_prefix'] . '\1 ', $sql_query); + + // Change language strings... + $sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', 'adjust_language_keys_callback', $sql_query); + + $sql_query = phpbb_remove_comments($sql_query); + $sql_query = split_sql_file($sql_query, ';'); + + foreach ($sql_query as $sql) + { + //$sql = trim(str_replace('|', ';', $sql)); + if (!$db->sql_query($sql)) + { + $error = $db->sql_error(); + $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__); + } + } + unset($sql_query); + + $current_time = time(); + + $user_ip = $request->server('REMOTE_ADDR') ? phpbb_ip_normalise($request->server('REMOTE_ADDR')) : ''; + + if ($data['script_path'] !== '/') + { + // Adjust destination path (no trailing slash) + if (substr($data['script_path'], -1) == '/') + { + $data['script_path'] = substr($data['script_path'], 0, -1); + } + + $data['script_path'] = str_replace(array('../', './'), '', $data['script_path']); + + if ($data['script_path'][0] != '/') + { + $data['script_path'] = '/' . $data['script_path']; + } + } + + // Set default config and post data, this applies to all DB's + $sql_ary = array( + 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value) + VALUES ('board_startdate', '$current_time')", + + 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value) + VALUES ('default_lang', '" . $db->sql_escape($data['default_lang']) . "')", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['img_imagick']) . "' + WHERE config_name = 'img_imagick'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['server_name']) . "' + WHERE config_name = 'server_name'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['server_port']) . "' + WHERE config_name = 'server_port'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['board_email']) . "' + WHERE config_name = 'board_email'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['board_email']) . "' + WHERE config_name = 'board_contact'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($cookie_domain) . "' + WHERE config_name = 'cookie_domain'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($lang['default_dateformat']) . "' + WHERE config_name = 'default_dateformat'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['email_enable']) . "' + WHERE config_name = 'email_enable'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['smtp_delivery']) . "' + WHERE config_name = 'smtp_delivery'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['smtp_host']) . "' + WHERE config_name = 'smtp_host'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['smtp_auth']) . "' + WHERE config_name = 'smtp_auth_method'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['smtp_user']) . "' + WHERE config_name = 'smtp_username'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['smtp_pass']) . "' + WHERE config_name = 'smtp_password'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['cookie_secure']) . "' + WHERE config_name = 'cookie_secure'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['force_server_vars']) . "' + WHERE config_name = 'force_server_vars'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['script_path']) . "' + WHERE config_name = 'script_path'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['server_protocol']) . "' + WHERE config_name = 'server_protocol'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($data['admin_name']) . "' + WHERE config_name = 'newest_username'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . md5(mt_rand()) . "' + WHERE config_name = 'avatar_salt'", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . md5(mt_rand()) . "' + WHERE config_name = 'plupload_salt'", + + 'UPDATE ' . $data['table_prefix'] . "users + SET username = '" . $db->sql_escape($data['admin_name']) . "', user_password='" . $db->sql_escape(md5($data['admin_pass1'])) . "', user_ip = '" . $db->sql_escape($user_ip) . "', user_lang = '" . $db->sql_escape($data['default_lang']) . "', user_email='" . $db->sql_escape($data['board_email']) . "', user_dateformat='" . $db->sql_escape($lang['default_dateformat']) . "', user_email_hash = " . $db->sql_escape(phpbb_email_hash($data['board_email'])) . ", username_clean = '" . $db->sql_escape(utf8_clean_string($data['admin_name'])) . "' + WHERE username = 'Admin'", + + 'UPDATE ' . $data['table_prefix'] . "moderator_cache + SET username = '" . $db->sql_escape($data['admin_name']) . "' + WHERE username = 'Admin'", + + 'UPDATE ' . $data['table_prefix'] . "forums + SET forum_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "' + WHERE forum_last_poster_name = 'Admin'", + + 'UPDATE ' . $data['table_prefix'] . "topics + SET topic_first_poster_name = '" . $db->sql_escape($data['admin_name']) . "', topic_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "' + WHERE topic_first_poster_name = 'Admin' + OR topic_last_poster_name = 'Admin'", + + 'UPDATE ' . $data['table_prefix'] . "users + SET user_regdate = $current_time", + + 'UPDATE ' . $data['table_prefix'] . "posts + SET post_time = $current_time, poster_ip = '" . $db->sql_escape($user_ip) . "'", + + 'UPDATE ' . $data['table_prefix'] . "topics + SET topic_time = $current_time, topic_last_post_time = $current_time", + + 'UPDATE ' . $data['table_prefix'] . "forums + SET forum_last_post_time = $current_time", + + 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($db->sql_server_info(true)) . "' + WHERE config_name = 'dbms_version'", + ); + + if (@extension_loaded('gd')) + { + $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = 'core.captcha.plugins.gd' + WHERE config_name = 'captcha_plugin'"; + + $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '1' + WHERE config_name = 'captcha_gd'"; + } + + $ref = substr($referer, strpos($referer, '://') + 3); + + if (!(stripos($ref, $server_name) === 0)) + { + $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '0' + WHERE config_name = 'referer_validation'"; + } + + // We set a (semi-)unique cookie name to bypass login issues related to the cookie name. + $cookie_name = 'phpbb3_'; + $rand_str = md5(mt_rand()); + $rand_str = str_replace('0', 'z', base_convert($rand_str, 16, 35)); + $rand_str = substr($rand_str, 0, 5); + $cookie_name .= strtolower($rand_str); + + $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config + SET config_value = '" . $db->sql_escape($cookie_name) . "' + WHERE config_name = 'cookie_name'"; + + foreach ($sql_ary as $sql) + { + //$sql = trim(str_replace('|', ';', $sql)); + + if (!$db->sql_query($sql)) + { + $error = $db->sql_error(); + $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__); + } + } + + $submit = $lang['NEXT_STEP']; + + $url = $this->p_master->module_url . "?mode=$mode&sub=final"; + + $template->assign_vars(array( + 'BODY' => $lang['STAGE_CREATE_TABLE_EXPLAIN'], + 'L_SUBMIT' => $submit, + 'S_HIDDEN' => build_hidden_fields($data), + 'U_ACTION' => $url, + )); + } + + /** + * Build the search index... + */ + function build_search_index($mode, $sub) + { + global $db, $lang, $phpbb_root_path, $phpbb_dispatcher, $phpEx, $config, $auth, $user; + + // Obtain any submitted data + $data = $this->get_submitted_data(); + $table_prefix = $data['table_prefix']; + + // If we get here and the extension isn't loaded it should be safe to just go ahead and load it + $available_dbms = get_available_dbms($data['dbms']); + + if (!isset($available_dbms[$data['dbms']])) + { + // Someone's been silly and tried providing a non-existant dbms + $this->p_master->redirect("index.$phpEx?mode=install"); + } + + $dbms = $available_dbms[$data['dbms']]['DRIVER']; + + // Instantiate the database + $db = new $dbms(); + $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false); + + // NOTE: trigger_error does not work here. + $db->sql_return_on_error(true); + + include_once($phpbb_root_path . 'includes/constants.' . $phpEx); + include_once($phpbb_root_path . 'phpbb/search/fulltext_native.' . $phpEx); + + // We need to fill the config to let internal functions correctly work + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); + + $error = false; + $search = new \phpbb\search\fulltext_native($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); + + $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id + FROM ' . POSTS_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); + } + $db->sql_freeresult($result); + } + + /** + * Populate the module tables + */ + function add_modules($mode, $sub) + { + global $db, $lang, $phpbb_root_path, $phpEx, $phpbb_extension_manager, $config, $phpbb_container; + + // modules require an extension manager + if (empty($phpbb_extension_manager)) + { + /* @var $phpbb_extension_manager \phpbb\extension\manager */ + $phpbb_extension_manager = $phpbb_container->get('ext.manager'); + } + + $_module = new \phpbb\module\module_manager( + new \phpbb\cache\driver\dummy(), + $db, + $phpbb_extension_manager, + MODULES_TABLE, + $phpbb_root_path, + $phpEx + ); + $module_classes = array('acp', 'mcp', 'ucp'); + + // Add categories + foreach ($module_classes as $module_class) + { + $categories = array(); + + // Set the module class + $_module->module_class = $module_class; + + foreach ($this->module_categories[$module_class] as $cat_name => $subs) + { + $basename = ''; + // Check if this sub-category has a basename. If it has, use it. + if (isset($this->module_categories_basenames[$cat_name])) + { + $basename = $this->module_categories_basenames[$cat_name]; + } + $module_data = array( + 'module_basename' => $basename, + 'module_enabled' => 1, + 'module_display' => 1, + 'parent_id' => 0, + 'module_class' => $module_class, + 'module_langname' => $cat_name, + 'module_mode' => '', + 'module_auth' => '', + ); + + // Add category + $_module->update_module_data($module_data); + + // Check for last sql error happened + if ($db->get_sql_error_triggered()) + { + $error = $db->sql_error($db->get_sql_error_sql()); + $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); + } + + $categories[$cat_name]['id'] = (int) $module_data['module_id']; + $categories[$cat_name]['parent_id'] = 0; + + // Create sub-categories... + if (is_array($subs)) + { + foreach ($subs as $level2_name) + { + $basename = ''; + // Check if this sub-category has a basename. If it has, use it. + if (isset($this->module_categories_basenames[$level2_name])) + { + $basename = $this->module_categories_basenames[$level2_name]; + } + $module_data = array( + 'module_basename' => $basename, + 'module_enabled' => 1, + 'module_display' => 1, + 'parent_id' => (int) $categories[$cat_name]['id'], + 'module_class' => $module_class, + 'module_langname' => $level2_name, + 'module_mode' => '', + 'module_auth' => '', + ); + + $_module->update_module_data($module_data); + + // Check for last sql error happened + if ($db->get_sql_error_triggered()) + { + $error = $db->sql_error($db->get_sql_error_sql()); + $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); + } + + $categories[$level2_name]['id'] = (int) $module_data['module_id']; + $categories[$level2_name]['parent_id'] = (int) $categories[$cat_name]['id']; + } + } + } + + // Get the modules we want to add... returned sorted by name + $module_info = $_module->get_module_infos($module_class); + + foreach ($module_info as $module_basename => $fileinfo) + { + foreach ($fileinfo['modes'] as $module_mode => $row) + { + foreach ($row['cat'] as $cat_name) + { + if (!isset($categories[$cat_name])) + { + continue; + } + + $module_data = array( + 'module_basename' => $module_basename, + 'module_enabled' => 1, + 'module_display' => (isset($row['display'])) ? (int) $row['display'] : 1, + 'parent_id' => (int) $categories[$cat_name]['id'], + 'module_class' => $module_class, + 'module_langname' => $row['title'], + 'module_mode' => $module_mode, + 'module_auth' => $row['auth'], + ); + + $_module->update_module_data($module_data); + + // Check for last sql error happened + if ($db->get_sql_error_triggered()) + { + $error = $db->sql_error($db->get_sql_error_sql()); + $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); + } + } + } + } + + // Move some of the modules around since the code above will put them in the wrong place + if ($module_class == 'acp') + { + // Move main module 4 up... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'acp_main' + AND module_class = 'acp' + AND module_mode = 'main'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'acp', 'move_up', 4); + + // Move permissions intro screen module 4 up... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'acp_permissions' + AND module_class = 'acp' + AND module_mode = 'intro'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'acp', 'move_up', 4); + + // Move manage users screen module 5 up... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'acp_users' + AND module_class = 'acp' + AND module_mode = 'overview'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'acp', 'move_up', 5); + + // Move extension management module 1 up... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_langname = 'ACP_EXTENSION_MANAGEMENT' + AND module_class = 'acp' + AND module_mode = '' + AND module_basename = ''"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'acp', 'move_up', 1); + } + + if ($module_class == 'mcp') + { + // Move pm report details module 3 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'mcp_pm_reports' + AND module_class = 'mcp' + AND module_mode = 'pm_report_details'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'mcp', 'move_down', 3); + + // Move closed pm reports module 3 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'mcp_pm_reports' + AND module_class = 'mcp' + AND module_mode = 'pm_reports_closed'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'mcp', 'move_down', 3); + + // Move open pm reports module 3 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'mcp_pm_reports' + AND module_class = 'mcp' + AND module_mode = 'pm_reports'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'mcp', 'move_down', 3); + } + + if ($module_class == 'ucp') + { + // Move attachment module 4 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'ucp_attachments' + AND module_class = 'ucp' + AND module_mode = 'attachments'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'ucp', 'move_down', 4); + + // Move notification options module 4 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'ucp_notifications' + AND module_class = 'ucp' + AND module_mode = 'notification_options'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'ucp', 'move_down', 4); + + // Move OAuth module 5 down... + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'ucp_auth_link' + AND module_class = 'ucp' + AND module_mode = 'auth_link'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_module->move_module_by($row, 'ucp', 'move_down', 5); + } + + // And now for the special ones + // (these are modules which appear in multiple categories and thus get added manually to some for more control) + if (isset($this->module_extras[$module_class])) + { + foreach ($this->module_extras[$module_class] as $cat_name => $mods) + { + $sql = 'SELECT module_id, left_id, right_id + FROM ' . MODULES_TABLE . " + WHERE module_langname = '" . $db->sql_escape($cat_name) . "' + AND module_class = '" . $db->sql_escape($module_class) . "'"; + $result = $db->sql_query_limit($sql, 1); + $row2 = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + foreach ($mods as $mod_name) + { + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_langname = '" . $db->sql_escape($mod_name) . "' + AND module_class = '" . $db->sql_escape($module_class) . "' + AND module_basename <> ''"; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $module_data = array( + 'module_basename' => $row['module_basename'], + 'module_enabled' => (int) $row['module_enabled'], + 'module_display' => (int) $row['module_display'], + 'parent_id' => (int) $row2['module_id'], + 'module_class' => $row['module_class'], + 'module_langname' => $row['module_langname'], + 'module_mode' => $row['module_mode'], + 'module_auth' => $row['module_auth'], + ); + + $_module->update_module_data($module_data); + + // Check for last sql error happened + if ($db->get_sql_error_triggered()) + { + $error = $db->sql_error($db->get_sql_error_sql()); + $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); + } + } + } + } + + $_module->remove_cache_file($module_class); + } + } + + /** + * Populate the language tables + */ + function add_language($mode, $sub) + { + global $db, $lang, $phpbb_root_path, $phpEx; + + $dir = @opendir($phpbb_root_path . 'language'); + + if (!$dir) + { + $this->error('Unable to access the language directory', __LINE__, __FILE__); + } + + $installed_languages = array(); + while (($file = readdir($dir)) !== false) + { + $path = $phpbb_root_path . 'language/' . $file; + + if ($file == '.' || $file == '..' || is_link($path) || is_file($path) || $file == 'CVS') + { + continue; + } + + if (is_dir($path) && file_exists($path . '/iso.txt')) + { + $lang_file = file("$path/iso.txt"); + + $lang_pack = array( + 'lang_iso' => basename($path), + 'lang_dir' => basename($path), + 'lang_english_name' => trim(htmlspecialchars($lang_file[0])), + 'lang_local_name' => trim(htmlspecialchars($lang_file[1], ENT_COMPAT, 'UTF-8')), + 'lang_author' => trim(htmlspecialchars($lang_file[2], ENT_COMPAT, 'UTF-8')), + ); + + $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $lang_pack)); + + $installed_languages[] = (int) $db->sql_nextid(); + if ($db->get_sql_error_triggered()) + { + $error = $db->sql_error($db->get_sql_error_sql()); + $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__); + } + } + } + closedir($dir); + + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_TABLE; + $result = $db->sql_query($sql); + + $profile_fields = array(); + $insert_buffer = new \phpbb\db\sql_insert_buffer($db, PROFILE_LANG_TABLE); + while ($row = $db->sql_fetchrow($result)) + { + foreach ($installed_languages as $lang_id) + { + $insert_buffer->insert(array( + 'field_id' => $row['field_id'], + 'lang_id' => $lang_id, + 'lang_name' => strtoupper(substr($row['field_name'], 6)),// Remove phpbb_ from field name + 'lang_explain' => '', + 'lang_default_value' => '', + )); + } + } + $db->sql_freeresult($result); + + $insert_buffer->flush(); + } + + /** + * Add search robots to the database + */ + function add_bots($mode, $sub) + { + global $db, $lang, $phpbb_root_path, $phpEx, $config; + + // Obtain any submitted data + $data = $this->get_submitted_data(); + + // We need to fill the config to let internal functions correctly work + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); + + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . " + WHERE group_name = 'BOTS'"; + $result = $db->sql_query($sql); + $group_id = (int) $db->sql_fetchfield('group_id'); + $db->sql_freeresult($result); + + if (!$group_id) + { + // If we reach this point then something has gone very wrong + $this->p_master->error($lang['NO_GROUP'], __LINE__, __FILE__); + } + + if (!function_exists('user_add')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } + + foreach ($this->bot_list as $bot_name => $bot_ary) + { + $user_row = array( + 'user_type' => USER_IGNORE, + 'group_id' => $group_id, + 'username' => $bot_name, + 'user_regdate' => time(), + 'user_password' => '', + 'user_colour' => '9E8DA7', + 'user_email' => '', + 'user_lang' => $data['default_lang'], + 'user_style' => 1, + 'user_timezone' => 'UTC', + 'user_dateformat' => $lang['default_dateformat'], + 'user_allow_massemail' => 0, + 'user_allow_pm' => 0, + ); + + $user_id = user_add($user_row); + + if (!$user_id) + { + // If we can't insert this user then continue to the next one to avoid inconsistent data + $this->p_master->db_error('Unable to insert bot into users table', $db->get_sql_error_sql(), __LINE__, __FILE__, true); + continue; + } + + $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'bot_active' => 1, + 'bot_name' => (string) $bot_name, + 'user_id' => (int) $user_id, + 'bot_agent' => (string) $bot_ary[0], + 'bot_ip' => (string) $bot_ary[1], + )); + + $db->sql_query($sql); + } + } + + /** + * Sends an email to the board administrator with their password and some useful links + */ + function email_admin($mode, $sub) + { + global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; + + $this->page_title = $lang['STAGE_FINAL']; + + // Obtain any submitted data + $data = $this->get_submitted_data(); + + // We need to fill the config to let internal functions correctly work + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); + + $user->session_begin(); + $auth->login($data['admin_name'], $data['admin_pass1'], false, true, true); + + // OK, Now that we've reached this point we can be confident that everything + // is installed and working......I hope :) + // So it's time to send an email to the administrator confirming the details + // they entered + + if ($config['email_enable']) + { + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $messenger = new messenger(false); + + $messenger->template('installed', $data['language']); + + $messenger->to($data['board_email'], $data['admin_name']); + + $messenger->anti_abuse_headers($config, $user); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($data['admin_name']), + 'PASSWORD' => htmlspecialchars_decode($data['admin_pass1'])) + ); + + $messenger->send(NOTIFY_EMAIL); + } + + // And finally, add a note to the log + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_INSTALLED', false, array($config['version'])); + + $template->assign_vars(array( + 'TITLE' => $lang['INSTALL_CONGRATS'], + 'BODY' => sprintf($lang['INSTALL_CONGRATS_EXPLAIN'], $config['version'], append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=convert&language=' . $data['language']), '../docs/README.html'), + 'L_SUBMIT' => $lang['INSTALL_LOGIN'], + 'U_ACTION' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'i=send_statistics&mode=send_statistics'), + )); + } + + /** + * Check if the avatar directory is writable and disable avatars + * if it isn't writable. + */ + function disable_avatars_if_unwritable() + { + global $config, $phpbb_root_path; + + if (!$this->filesystem->is_writable($phpbb_root_path . 'images/avatars/upload/')) + { + $config->set('allow_avatar', 0); + $config->set('allow_avatar_upload', 0); + } + } + + /** + * Populate migrations for the installation + * + * This "installs" all migrations from (root path)/phpbb/db/migrations/data. + * "installs" means it adds all migrations to the migrations table, but does not + * perform any of the actions in the migrations. + * + * @param \phpbb\extension\manager $extension_manager + * @param \phpbb\db\migrator $migrator + */ + function populate_migrations($extension_manager, $migrator) + { + $finder = $extension_manager->get_finder(); + + $migrations = $finder + ->core_path('phpbb/db/migration/data/') + ->get_classes(); + $migrator->populate_migrations($migrations); + } + + /** + * Generate a list of available mail server authentication methods + */ + function mail_auth_select($selected_method) + { + global $lang; + + $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP'); + $s_smtp_auth_options = ''; + + foreach ($auth_methods as $method) + { + $s_smtp_auth_options .= ''; + } + + return $s_smtp_auth_options; + } + + /** + * Get submitted data + */ + function get_submitted_data() + { + global $request; + + return array( + 'language' => basename($request->variable('language', '')), + 'dbms' => $request->variable('dbms', ''), + 'dbhost' => $request->variable('dbhost', ''), + 'dbport' => $request->variable('dbport', ''), + 'dbuser' => $request->variable('dbuser', ''), + 'dbpasswd' => $request->variable('dbpasswd', '', true), + 'dbname' => $request->variable('dbname', ''), + 'table_prefix' => $request->variable('table_prefix', ''), + 'default_lang' => basename($request->variable('default_lang', '')), + 'admin_name' => $request->variable('admin_name', '', true), + 'admin_pass1' => $request->variable('admin_pass1', '', true), + 'admin_pass2' => $request->variable('admin_pass2', '', true), + 'board_email' => strtolower($request->variable('board_email', '')), + 'img_imagick' => $request->variable('img_imagick', ''), + 'ftp_path' => $request->variable('ftp_path', ''), + 'ftp_user' => $request->variable('ftp_user', ''), + 'ftp_pass' => $request->variable('ftp_pass', ''), + 'email_enable' => $request->variable('email_enable', ''), + 'smtp_delivery' => $request->variable('smtp_delivery', ''), + 'smtp_host' => $request->variable('smtp_host', ''), + 'smtp_auth' => $request->variable('smtp_auth', ''), + 'smtp_user' => $request->variable('smtp_user', ''), + 'smtp_pass' => $request->variable('smtp_pass', ''), + 'cookie_secure' => $request->variable('cookie_secure', ''), + 'force_server_vars' => $request->variable('force_server_vars', ''), + 'server_protocol' => $request->variable('server_protocol', ''), + 'server_name' => $request->variable('server_name', ''), + 'server_port' => $request->variable('server_port', ''), + 'script_path' => $request->variable('script_path', ''), + ); + } + + /** + * The information below will be used to build the input fields presented to the user + */ + var $db_config_options = array( + 'legend1' => 'DB_CONFIG', + 'dbms' => array('lang' => 'DBMS', 'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\')', 'explain' => false), + 'dbhost' => array('lang' => 'DB_HOST', 'type' => 'text:25:100', 'explain' => true), + 'dbport' => array('lang' => 'DB_PORT', 'type' => 'text:25:100', 'explain' => true), + 'dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false), + 'dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false), + 'dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false), + 'table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => true), + ); + var $admin_config_options = array( + 'legend1' => 'ADMIN_CONFIG', + 'default_lang' => array('lang' => 'DEFAULT_LANG', 'type' => 'select', 'options' => '$this->module->inst_language_select(\'{VALUE}\')', 'explain' => false), + 'admin_name' => array('lang' => 'ADMIN_USERNAME', 'type' => 'text:25:100', 'explain' => true), + 'admin_pass1' => array('lang' => 'ADMIN_PASSWORD', 'type' => 'password:25:100', 'explain' => true), + 'admin_pass2' => array('lang' => 'ADMIN_PASSWORD_CONFIRM', 'type' => 'password:25:100', 'explain' => false), + 'board_email' => array('lang' => 'CONTACT_EMAIL', 'type' => 'email:25:100', 'explain' => false), + ); + var $advanced_config_options = array( + 'legend1' => 'ACP_EMAIL_SETTINGS', + 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'type' => 'radio:enabled_disabled', 'explain' => true), + 'smtp_delivery' => array('lang' => 'USE_SMTP', 'type' => 'radio:yes_no', 'explain' => true), + 'smtp_host' => array('lang' => 'SMTP_SERVER', 'type' => 'text:25:50', 'explain' => false), + 'smtp_auth' => array('lang' => 'SMTP_AUTH_METHOD', 'type' => 'select', 'options' => '$this->module->mail_auth_select(\'{VALUE}\')', 'explain' => true), + 'smtp_user' => array('lang' => 'SMTP_USERNAME', 'type' => 'text:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')), + 'smtp_pass' => array('lang' => 'SMTP_PASSWORD', 'type' => 'password:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')), + + 'legend2' => 'SERVER_URL_SETTINGS', + 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'type' => 'radio:enabled_disabled', 'explain' => true), + 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'type' => 'radio:yes_no', 'explain' => true), + 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'type' => 'text:10:10', 'explain' => true), + 'server_name' => array('lang' => 'SERVER_NAME', 'type' => 'text:40:255', 'explain' => true), + 'server_port' => array('lang' => 'SERVER_PORT', 'type' => 'text:5:5', 'explain' => true), + 'script_path' => array('lang' => 'SCRIPT_PATH', 'type' => 'text::255', 'explain' => true), + ); + + /** + * Specific PHP modules we may require for certain optional or extended features + */ + var $php_dlls_other = array('zlib', 'ftp', 'gd', 'xml'); + + /** + * A list of the web-crawlers/bots we recognise by default + * + * Candidates but not included: + * 'Accoona [Bot]' 'Accoona-AI-Agent/' + * 'ASPseek [Crawler]' 'ASPseek/' + * 'Boitho [Crawler]' 'boitho.com-dc/' + * 'Bunnybot [Bot]' 'powered by www.buncat.de' + * 'Cosmix [Bot]' 'cfetch/' + * 'Crawler Search [Crawler]' '.Crawler-Search.de' + * 'Findexa [Crawler]' 'Findexa Crawler (' + * 'GBSpider [Spider]' 'GBSpider v' + * 'genie [Bot]' 'genieBot (' + * 'Hogsearch [Bot]' 'oegp v. 1.3.0' + * 'Insuranco [Bot]' 'InsurancoBot' + * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler' + * 'ISC Systems [Bot]' 'ISC Systems iRc Search' + * 'Jyxobot [Bot]' 'Jyxobot/' + * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/' + * 'LinkWalker' 'LinkWalker' + * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html' + * 'Naver [Bot]' 'nhnbot@naver.com)' + * 'NetResearchServer' 'NetResearchServer/' + * 'Nimble [Crawler]' 'NimbleCrawler' + * 'Ocelli [Bot]' 'Ocelli/' + * 'Onsearch [Bot]' 'onCHECK-Robot' + * 'Orange [Spider]' 'OrangeSpider' + * 'Sproose [Bot]' 'http://www.sproose.com/bot' + * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)' + * 'Tbot [Bot]' 'Tbot/' + * 'Thumbshots [Capture]' 'thumbshots-de-Bot' + * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/' + * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)' + * 'WissenOnline [Bot]' 'WissenOnline-Bot' + * 'WWWeasel [Bot]' 'WWWeasel Robot v' + * 'Xaldon [Spider]' 'Xaldon WebSpider' + */ + var $bot_list = array( + 'AdsBot [Google]' => array('AdsBot-Google', ''), + 'Alexa [Bot]' => array('ia_archiver', ''), + 'Alta Vista [Bot]' => array('Scooter/', ''), + 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''), + 'Baidu [Spider]' => array('Baiduspider', ''), + 'Bing [Bot]' => array('bingbot/', ''), + 'Exabot [Bot]' => array('Exabot', ''), + 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''), + 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''), + 'Francis [Bot]' => array('http://www.neomo.de/', ''), + 'Gigabot [Bot]' => array('Gigabot/', ''), + 'Google Adsense [Bot]' => array('Mediapartners-Google', ''), + 'Google Desktop' => array('Google Desktop', ''), + 'Google Feedfetcher' => array('Feedfetcher-Google', ''), + 'Google [Bot]' => array('Googlebot', ''), + 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''), + 'Heritrix [Crawler]' => array('heritrix/1.', ''), + 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''), + 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''), + 'ichiro [Crawler]' => array('ichiro/', ''), + 'Majestic-12 [Bot]' => array('MJ12bot/', ''), + 'Metager [Bot]' => array('MetagerBot/', ''), + 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''), + 'MSN [Bot]' => array('msnbot/', ''), + 'MSNbot Media' => array('msnbot-media/', ''), + 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''), + 'Online link [Validator]' => array('online link validator', ''), + 'psbot [Picsearch]' => array('psbot/0', ''), + 'Sensis [Crawler]' => array('Sensis Web Crawler', ''), + 'SEO Crawler' => array('SEO search Crawler/', ''), + 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''), + 'SEOSearch [Crawler]' => array('SEOsearch/', ''), + 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''), + 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''), + 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''), + 'TurnitinBot [Bot]' => array('TurnitinBot/', ''), + 'Voyager [Bot]' => array('voyager/', ''), + 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''), + 'W3C [Linkcheck]' => array('W3C-checklink/', ''), + 'W3C [Validator]' => array('W3C_Validator', ''), + 'YaCy [Bot]' => array('yacybot', ''), + 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''), + 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''), + 'Yahoo [Bot]' => array('Yahoo! Slurp', ''), + 'YahooSeeker [Bot]' => array('YahooSeeker/', ''), + ); + + /** + * Define the module structure so that we can populate the database without + * needing to hard-code module_id values + */ + var $module_categories = array( + 'acp' => array( + 'ACP_CAT_GENERAL' => array( + 'ACP_QUICK_ACCESS', + 'ACP_BOARD_CONFIGURATION', + 'ACP_CLIENT_COMMUNICATION', + 'ACP_SERVER_CONFIGURATION', + ), + 'ACP_CAT_FORUMS' => array( + 'ACP_MANAGE_FORUMS', + 'ACP_FORUM_BASED_PERMISSIONS', + ), + 'ACP_CAT_POSTING' => array( + 'ACP_MESSAGES', + 'ACP_ATTACHMENTS', + ), + 'ACP_CAT_USERGROUP' => array( + 'ACP_CAT_USERS', + 'ACP_GROUPS', + 'ACP_USER_SECURITY', + ), + 'ACP_CAT_PERMISSIONS' => array( + 'ACP_GLOBAL_PERMISSIONS', + 'ACP_FORUM_BASED_PERMISSIONS', + 'ACP_PERMISSION_ROLES', + 'ACP_PERMISSION_MASKS', + ), + 'ACP_CAT_CUSTOMISE' => array( + 'ACP_STYLE_MANAGEMENT', + 'ACP_EXTENSION_MANAGEMENT', + 'ACP_LANGUAGE', + ), + 'ACP_CAT_MAINTENANCE' => array( + 'ACP_FORUM_LOGS', + 'ACP_CAT_DATABASE', + ), + 'ACP_CAT_SYSTEM' => array( + 'ACP_AUTOMATION', + 'ACP_GENERAL_TASKS', + 'ACP_MODULE_MANAGEMENT', + ), + 'ACP_CAT_DOT_MODS' => null, + ), + 'mcp' => array( + 'MCP_MAIN' => null, + 'MCP_QUEUE' => null, + 'MCP_REPORTS' => null, + 'MCP_NOTES' => null, + 'MCP_WARN' => null, + 'MCP_LOGS' => null, + 'MCP_BAN' => null, + ), + 'ucp' => array( + 'UCP_MAIN' => null, + 'UCP_PROFILE' => null, + 'UCP_PREFS' => null, + 'UCP_PM' => null, + 'UCP_USERGROUPS' => null, + 'UCP_ZEBRA' => null, + ), + ); + var $module_categories_basenames = array( + 'UCP_PM' => 'ucp_pm', + ); + + var $module_extras = array( + 'acp' => array( + 'ACP_QUICK_ACCESS' => array( + 'ACP_MANAGE_USERS', + 'ACP_GROUPS_MANAGE', + 'ACP_MANAGE_FORUMS', + 'ACP_MOD_LOGS', + 'ACP_BOTS', + 'ACP_PHP_INFO', + ), + 'ACP_FORUM_BASED_PERMISSIONS' => array( + 'ACP_FORUM_PERMISSIONS', + 'ACP_FORUM_PERMISSIONS_COPY', + 'ACP_FORUM_MODERATORS', + 'ACP_USERS_FORUM_PERMISSIONS', + 'ACP_GROUPS_FORUM_PERMISSIONS', + ), + ), + ); +} diff --git a/phpBB/install/install_main.php b/phpBB/install/install_main.php new file mode 100644 index 0000000000..d5874dac83 --- /dev/null +++ b/phpBB/install/install_main.php @@ -0,0 +1,78 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +*/ + +if ( !defined('IN_INSTALL') ) +{ + // Someone has tried to access the file direct. This is not a good idea, so exit + exit; +} + +if (!empty($setmodules)) +{ + $module[] = array( + 'module_type' => 'install', + 'module_title' => 'OVERVIEW', + 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1), + 'module_order' => 0, + 'module_subs' => array('INTRO', 'LICENSE', 'SUPPORT'), + 'module_stages' => '', + 'module_reqs' => '' + ); +} + +/** +* Main Tab - Installation +*/ +class install_main extends module +{ + function install_main(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($mode, $sub) + { + global $lang, $template, $language; + + switch ($sub) + { + case 'intro' : + $title = $lang['SUB_INTRO']; + $body = $lang['OVERVIEW_BODY']; + break; + + case 'license' : + $title = $lang['GPL']; + $body = implode("
            \n", file(__DIR__ . '/../docs/LICENSE.txt')); + break; + + case 'support' : + $title = $lang['SUB_SUPPORT']; + $body = $lang['SUPPORT_BODY']; + break; + } + + $this->tpl_name = 'install_main'; + $this->page_title = $title; + + $template->assign_vars(array( + 'TITLE' => $title, + 'BODY' => $body, + + 'S_LANG_SELECT' => '', + )); + } +} diff --git a/phpBB/install_old/install_update.php b/phpBB/install/install_update.php similarity index 100% rename from phpBB/install_old/install_update.php rename to phpBB/install/install_update.php diff --git a/phpBB/install_old/phpinfo.php b/phpBB/install/phpinfo.php similarity index 100% rename from phpBB/install_old/phpinfo.php rename to phpBB/install/phpinfo.php diff --git a/phpBB/install/schemas/index.htm b/phpBB/install/schemas/index.htm new file mode 100644 index 0000000000..ee1f723a7d --- /dev/null +++ b/phpBB/install/schemas/index.htm @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql new file mode 100644 index 0000000000..2473d31aab --- /dev/null +++ b/phpBB/install/schemas/oracle_schema.sql @@ -0,0 +1,37 @@ +/* + This first section is optional, however its probably the best method + of running phpBB on Oracle. If you already have a tablespace and user created + for phpBB you can leave this section commented out! + + The first set of statements create a phpBB tablespace and a phpBB user, + make sure you change the password of the phpBB user before you run this script!! +*/ + +/* +CREATE TABLESPACE "PHPBB" + LOGGING + DATAFILE 'E:\ORACLE\ORADATA\LOCAL\PHPBB.ora' + SIZE 10M + AUTOEXTEND ON NEXT 10M + MAXSIZE 100M; + +CREATE USER "PHPBB" + PROFILE "DEFAULT" + IDENTIFIED BY "phpbb_password" + DEFAULT TABLESPACE "PHPBB" + QUOTA UNLIMITED ON "PHPBB" + ACCOUNT UNLOCK; + +GRANT ANALYZE ANY TO "PHPBB"; +GRANT CREATE SEQUENCE TO "PHPBB"; +GRANT CREATE SESSION TO "PHPBB"; +GRANT CREATE TABLE TO "PHPBB"; +GRANT CREATE TRIGGER TO "PHPBB"; +GRANT CREATE VIEW TO "PHPBB"; +GRANT "CONNECT" TO "PHPBB"; + +COMMIT; +DISCONNECT; + +CONNECT phpbb/phpbb_password; +*/ diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql new file mode 100644 index 0000000000..65caba8d1c --- /dev/null +++ b/phpBB/install/schemas/postgres_schema.sql @@ -0,0 +1,80 @@ + +BEGIN; + +/* + Domain definition +*/ +CREATE DOMAIN varchar_ci AS varchar(255) NOT NULL DEFAULT ''::character varying; + +/* + Operation Functions +*/ +CREATE FUNCTION _varchar_ci_equal(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) = LOWER($2)' LANGUAGE SQL STRICT; +CREATE FUNCTION _varchar_ci_not_equal(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) != LOWER($2)' LANGUAGE SQL STRICT; +CREATE FUNCTION _varchar_ci_less_than(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) < LOWER($2)' LANGUAGE SQL STRICT; +CREATE FUNCTION _varchar_ci_less_equal(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) <= LOWER($2)' LANGUAGE SQL STRICT; +CREATE FUNCTION _varchar_ci_greater_than(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) > LOWER($2)' LANGUAGE SQL STRICT; +CREATE FUNCTION _varchar_ci_greater_equals(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) >= LOWER($2)' LANGUAGE SQL STRICT; + +/* + Operators +*/ +CREATE OPERATOR <( + PROCEDURE = _varchar_ci_less_than, + LEFTARG = varchar_ci, + RIGHTARG = varchar_ci, + COMMUTATOR = >, + NEGATOR = >=, + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel); + +CREATE OPERATOR <=( + PROCEDURE = _varchar_ci_less_equal, + LEFTARG = varchar_ci, + RIGHTARG = varchar_ci, + COMMUTATOR = >=, + NEGATOR = >, + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel); + +CREATE OPERATOR >( + PROCEDURE = _varchar_ci_greater_than, + LEFTARG = varchar_ci, + RIGHTARG = varchar_ci, + COMMUTATOR = <, + NEGATOR = <=, + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel); + +CREATE OPERATOR >=( + PROCEDURE = _varchar_ci_greater_equals, + LEFTARG = varchar_ci, + RIGHTARG = varchar_ci, + COMMUTATOR = <=, + NEGATOR = <, + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel); + +CREATE OPERATOR <>( + PROCEDURE = _varchar_ci_not_equal, + LEFTARG = varchar_ci, + RIGHTARG = varchar_ci, + COMMUTATOR = <>, + NEGATOR = =, + RESTRICT = neqsel, + JOIN = neqjoinsel); + +CREATE OPERATOR =( + PROCEDURE = _varchar_ci_equal, + LEFTARG = varchar_ci, + RIGHTARG = varchar_ci, + COMMUTATOR = =, + NEGATOR = <>, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES, + SORT1= <); + +COMMIT; + diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql new file mode 100644 index 0000000000..1f856f016c --- /dev/null +++ b/phpBB/install/schemas/schema_data.sql @@ -0,0 +1,821 @@ +# +# $Id$ +# + +# POSTGRES BEGIN # + +# -- Config +INSERT INTO phpbb_config (config_name, config_value) VALUES ('active_sessions', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_attachments', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_autologin', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_gravatar', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_local', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_remote', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_upload', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_remote_upload', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_bbcode', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_birthdays', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_bookmarks', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_cdn', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_emailreuse', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_password_reset', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_forum_notify', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_live_searches', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_mass_pm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_name_chars', 'USERNAME_CHARS_ANY'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_namechange', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_nocensors', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_pm_attach', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_pm_report', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_post_flash', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_post_links', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_privmsg', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_quick_reply', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_bbcode', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_flash', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_img', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_links', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_pm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_smilies', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_smilies', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_topic_notify', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('assets_version', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('attachment_quota', '52428800'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_bbcode_pm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_flash_pm', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_img_pm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_method', 'db'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_smilies_pm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_filesize', '6144'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_gallery_path', 'images/avatars/gallery'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_height', '90'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_width', '90'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_min_height', '20'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_min_width', '20'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_path', 'images/avatars/upload'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_salt', 'phpbb_avatar'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_contact', 'contact@yourdomain.tld'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_contact_name', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_disable', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_disable_msg', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email', 'address@yourdomain.tld'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_sig', '{L_CONFIG_BOARD_EMAIL_SIG}'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_hide_emails', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_index_text', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_timezone', 'UTC'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('browser_check', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_interval', '10'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_type', 'd'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('cache_gc', '7200'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_plugin', 'core.captcha.plugins.nogd'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_foreground_noise', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_x_grid', '25'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_y_grid', '25'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_wave', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_3d_noise', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_fonts', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('confirm_refresh', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_attachment_content', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_dnsbl', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('chg_passforce', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('contact_admin_form_enable', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_domain', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_name', 'phpbb3'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_path', '/'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_secure', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_enable', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_fax', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_mail', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('database_gc', '604800'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('dbms_version', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('default_dateformat', 'D M d, Y g:i a'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('default_style', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_last_edited', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_last_subject', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_order', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('edit_time', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('extension_force_unstable', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('delete_time', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_check_mx', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_enable', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_function_name', 'mail'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_max_chunk_size', '50'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_package_size', '20'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_confirm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_mod_rewrite', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_pm_icons', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_post_confirm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_enable', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_http_auth', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_limit_post', '15'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_limit_topic', '10'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_overall_forums', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_overall', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_forum', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_topic', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_topics_new', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_topics_active', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_item_statistics', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval', '15'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('force_server_vars', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_lifetime', '7200'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_mintime', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_sid_guests', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('forward_pm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('forwarded_for_check', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('full_folder_action', '2'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_mysql_max_word_len', '254'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_mysql_min_word_len', '4'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_common_thres', '5'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_load_upd', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_max_chars', '14'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_min_chars', '3'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_max_word_len', '254'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_min_word_len', '4'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_ts_name', 'simple'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_indexer_mem_limit', '512'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_stopwords', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('gzip_compress', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('hot_threshold', '25'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('icons_path', 'images/icons'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_create_thumbnail', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_display_inlined', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_imagick', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_link_height', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_link_width', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_height', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_thumb_width', '400'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_width', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_min_thumb_filesize', '12000'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_check', '3'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_login_limit_max', '50'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_login_limit_time', '21600'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_login_limit_use_forwarded', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_enable', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_host', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_password', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_package_size', '20'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_port', '5222'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_use_ssl', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_username', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_base_dn', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_email', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_password', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_port', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_server', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_uid', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_user', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_user_filter', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('legend_sort_groupname', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('limit_load', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('limit_search_load', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_anon_lastread', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_birthdays', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_memberlist', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_pm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewprofile', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewtopic', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_lastread', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_track', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jumpbox', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_moderators', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_notifications', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online_guests', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online_time', '5'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_onlinetrack', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_search', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_tplcompile', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_unreads_search', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_user_activity', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_attachments', '3'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_attachments_pm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_autologin_time', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_filesize', '262144'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_filesize_pm', '262144'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '3'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_name_chars', '20'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_num_search_keywords', '10'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_pass_chars', '100'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_poll_options', '10'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_chars', '60000'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_font_size', '200'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_img_height', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_img_width', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_smilies', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_urls', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_quote_depth', '3'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_reg_attempts', '5'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_chars', '255'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_font_size', '200'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_img_height', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_img_width', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_smilies', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_urls', '5'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_name_chars', '3'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_pass_chars', '6'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_post_chars', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_search_author_chars', '3'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('mime_triggers', 'body|head|html|img|plaintext|a href|pre|script|table|title'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('new_member_post_limit', '3'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('new_member_group_default', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('override_user_style', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('pass_complex', 'PASS_TYPE_ANY'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('plupload_salt', 'phpbb_plupload'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_edit_time', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_boxes', '4'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_msgs', '50'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_recipients', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('posts_per_page', '10'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('print_pm', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('queue_interval', '60'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('ranks_path', 'images/ranks'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_expire_days', '30'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_gc', '86400'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('referer_validation', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('script_path', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_block_size', '250'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_gc', '7200'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_interval', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_anonymous_interval', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_type', '\phpbb\search\fulltext_native'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_store_results', '1800'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_deny', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_empty_referer', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_downloads', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('server_name', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('server_port', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('server_protocol', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('session_gc', '3600'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('session_length', '3600'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('site_desc', '{L_CONFIG_SITE_DESC}'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('site_home_url', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('site_home_text', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('sitename', '{L_CONFIG_SITENAME}'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('smilies_path', 'images/smilies'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('smilies_per_page', '50'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_auth_method', 'PLAIN'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_delivery', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_host', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_port', '25'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_username', ''); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_memberships', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_forums', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('topics_per_page', '25'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-a1-dev'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); + +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cache_last_gc', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cron_lock', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('database_last_gc', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('last_queue_run', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('newest_user_colour', 'AA0000', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('newest_user_id', '2', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('newest_username', '', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_files', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_posts', '1', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_topics', '1', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_users', '1', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('plupload_last_gc', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('rand_seed', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('rand_seed_last_update', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('read_notification_last_gc', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('record_online_date', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('record_online_users', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('search_indexing_state', '', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('search_last_gc', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('session_last_gc', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('upload_dir_size', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('warnings_last_gc', '0', 1); + +# Config text +INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info', ''); +INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_uid', ''); +INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_bitfield', ''); +INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_flags', '7'); + +# -- Forum related auth options +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_announce', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_attach', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bbcode', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bump', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_delete', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_download', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_edit', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_email', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_flash', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_icons', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_ignoreflood', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_img', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_list', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_noapprove', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_poll', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_post', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_postcount', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_print', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_read', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_reply', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_report', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_search', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_sigs', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_smilies', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_sticky', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_subscribe', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_user_lock', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_vote', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_votechg', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_softdelete', 1); + +# -- Moderator related auth options +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_approve', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_chgposter', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_delete', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_edit', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_info', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_lock', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_merge', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_move', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_report', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_split', 1, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_softdelete', 1, 1); + +# -- Global moderator auth option (not a local option) +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_ban', 0, 1); +INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_warn', 0, 1); + +# -- Admin related auth options +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_aauth', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_attach', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_authgroups', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_authusers', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_backup', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_ban', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_bbcode', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_board', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_bots', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_clearlogs', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_email', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_extensions', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_fauth', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forum', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forumadd', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forumdel', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_group', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_groupadd', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_groupdel', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_icons', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_jabber', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_language', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_mauth', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_modules', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_names', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_phpinfo', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_profile', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_prune', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_ranks', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_reasons', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_roles', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_search', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_server', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_styles', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_switchperm', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_uauth', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_user', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_userdel', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_viewauth', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_viewlogs', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_words', 1); + +# -- User related auth options +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_attach', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgavatar', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgcensors', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgemail', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chggrp', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgname', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgpasswd', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgprofileinfo', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_download', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_hideonline', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_ignoreflood', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_masspm', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_masspm_group', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_attach', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_bbcode', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_delete', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_download', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_edit', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_emailpm', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_flash', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_forward', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_img', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_printpm', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_smilies', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_readpm', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_savedrafts', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_search', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sendemail', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sendim', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sendpm', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sig', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_viewonline', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_viewprofile', 1); + + +# -- standard auth roles +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_STANDARD', 'ROLE_DESCRIPTION_ADMIN_STANDARD', 'a_', 1); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_FORUM', 'ROLE_DESCRIPTION_ADMIN_FORUM', 'a_', 3); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_USERGROUP', 'ROLE_DESCRIPTION_ADMIN_USERGROUP', 'a_', 4); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_FULL', 'ROLE_DESCRIPTION_ADMIN_FULL', 'a_', 2); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_FULL', 'ROLE_DESCRIPTION_USER_FULL', 'u_', 3); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_STANDARD', 'ROLE_DESCRIPTION_USER_STANDARD', 'u_', 1); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_LIMITED', 'ROLE_DESCRIPTION_USER_LIMITED', 'u_', 2); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NOPM', 'ROLE_DESCRIPTION_USER_NOPM', 'u_', 4); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NOAVATAR', 'ROLE_DESCRIPTION_USER_NOAVATAR', 'u_', 5); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_FULL', 'ROLE_DESCRIPTION_MOD_FULL', 'm_', 3); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_STANDARD', 'ROLE_DESCRIPTION_MOD_STANDARD', 'm_', 1); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_SIMPLE', 'ROLE_DESCRIPTION_MOD_SIMPLE', 'm_', 2); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_QUEUE', 'ROLE_DESCRIPTION_MOD_QUEUE', 'm_', 4); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_FULL', 'ROLE_DESCRIPTION_FORUM_FULL', 'f_', 7); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_STANDARD', 'ROLE_DESCRIPTION_FORUM_STANDARD', 'f_', 5); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NOACCESS', 'ROLE_DESCRIPTION_FORUM_NOACCESS', 'f_', 1); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_READONLY', 'ROLE_DESCRIPTION_FORUM_READONLY', 'f_', 2); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_LIMITED', 'ROLE_DESCRIPTION_FORUM_LIMITED', 'f_', 3); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_BOT', 'ROLE_DESCRIPTION_FORUM_BOT', 'f_', 9); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_ONQUEUE', 'ROLE_DESCRIPTION_FORUM_ONQUEUE', 'f_', 8); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_POLLS', 'ROLE_DESCRIPTION_FORUM_POLLS', 'f_', 6); +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_LIMITED_POLLS', 'ROLE_DESCRIPTION_FORUM_LIMITED_POLLS', 'f_', 4); + +# 23 +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NEW_MEMBER', 'ROLE_DESCRIPTION_USER_NEW_MEMBER', 'u_', 6); + +# 24 +INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NEW_MEMBER', 'ROLE_DESCRIPTION_FORUM_NEW_MEMBER', 'f_', 10); + +# -- phpbb_styles +INSERT INTO phpbb_styles (style_name, style_copyright, style_active, style_path, bbcode_bitfield, style_parent_id, style_parent_tree) VALUES ('prosilver', '© phpBB Limited', 1, 'prosilver', 'kNg=', 0, ''); + +# -- Forums +INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, forum_type, forum_posts_approved, forum_posts_unapproved, forum_posts_softdeleted, forum_topics_approved, forum_topics_unapproved, forum_topics_softdeleted, forum_last_post_id, forum_last_poster_id, forum_last_poster_name, forum_last_poster_colour, forum_last_post_time, forum_link, forum_password, forum_image, forum_rules, forum_rules_link, forum_rules_uid, forum_desc_uid, prune_days, prune_viewed, forum_parents) VALUES ('{L_FORUMS_FIRST_CATEGORY}', '', 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 'Admin', 'AA0000', 972086460, '', '', '', '', '', '', '', 0, 0, ''); + +INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, forum_type, forum_posts_approved, forum_posts_unapproved, forum_posts_softdeleted, forum_topics_approved, forum_topics_unapproved, forum_topics_softdeleted, forum_last_post_id, forum_last_poster_id, forum_last_poster_name, forum_last_poster_colour, forum_last_post_subject, forum_last_post_time, forum_link, forum_password, forum_image, forum_rules, forum_rules_link, forum_rules_uid, forum_desc_uid, prune_days, prune_viewed, forum_parents, forum_flags) VALUES ('{L_FORUMS_TEST_FORUM_TITLE}', '{L_FORUMS_TEST_FORUM_DESC}', 2, 3, 1, 1, 1, 0, 0, 1, 0, 0, 1, 2, 'Admin', 'AA0000', '{L_TOPICS_TOPIC_TITLE}', 972086460, '', '', '', '', '', '', '', 0, 0, '', 48); + +# -- Users / Anonymous user +INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_jabber, user_actkey, user_newpasswd, user_allow_massemail) VALUES (2, 1, 'Anonymous', 'anonymous', 0, '', '', 'en', 1, 0, '', 0, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', '', 0); + +# -- username: Admin password: admin (change this or remove it once everything is working!) +INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_jabber, user_actkey, user_newpasswd) VALUES (3, 5, 'Admin', 'admin', 0, '21232f297a57a5a743894a0e4a801fc3', 'admin@yourdomain.com', 'en', 1, 1, 'AA0000', 1, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', ''); + +# -- Groups +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('GUESTS', 3, 0, '', 0, '', '', '', 5); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('REGISTERED', 3, 0, '', 0, '', '', '', 5); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('REGISTERED_COPPA', 3, 0, '', 0, '', '', '', 5); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('GLOBAL_MODERATORS', 3, 0, '00AA00', 2, '', '', '', 0); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('ADMINISTRATORS', 3, 1, 'AA0000', 1, '', '', '', 0); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('BOTS', 3, 0, '9E8DA7', 0, '', '', '', 5); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('NEWLY_REGISTERED', 3, 0, '', 0, '', '', '', 5); + +# -- Teampage +INSERT INTO phpbb_teampage (group_id, teampage_name, teampage_position, teampage_parent) VALUES (5, '', 1, 0); +INSERT INTO phpbb_teampage (group_id, teampage_name, teampage_position, teampage_parent) VALUES (4, '', 2, 0); + +# -- User -> Group +INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (1, 1, 0, 0); +INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (2, 2, 0, 0); +INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (4, 2, 0, 0); +INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (5, 2, 0, 1); + +# -- Ranks +INSERT INTO phpbb_ranks (rank_title, rank_min, rank_special, rank_image) VALUES ('{L_RANKS_SITE_ADMIN_TITLE}', 0, 1, ''); + +# -- Roles data + +# Standard Admin (a_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 1, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%' AND auth_option NOT IN ('a_switchperm', 'a_jabber', 'a_phpinfo', 'a_server', 'a_backup', 'a_styles', 'a_clearlogs', 'a_modules', 'a_language', 'a_email', 'a_bots', 'a_search', 'a_aauth', 'a_roles'); + +# Forum admin (a_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 2, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%' AND auth_option IN ('a_', 'a_authgroups', 'a_authusers', 'a_fauth', 'a_forum', 'a_forumadd', 'a_forumdel', 'a_mauth', 'a_prune', 'a_uauth', 'a_viewauth', 'a_viewlogs'); + +# User and Groups Admin (a_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 3, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%' AND auth_option IN ('a_', 'a_authgroups', 'a_authusers', 'a_ban', 'a_group', 'a_groupadd', 'a_groupdel', 'a_ranks', 'a_uauth', 'a_user', 'a_viewauth', 'a_viewlogs'); + +# Full Admin (a_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 4, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%'; + +# All Features (u_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 5, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%'; + +# Standard Features (u_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 6, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_flash', 'u_pm_forward'); + +# Limited Features (u_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 7, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim', 'u_masspm', 'u_masspm_group'); + +# No Private Messages (u_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 8, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_', 'u_chgavatar', 'u_chgcensors', 'u_chgemail', 'u_chgpasswd', 'u_download', 'u_hideonline', 'u_sig', 'u_viewprofile'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 8, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_readpm', 'u_sendpm', 'u_masspm', 'u_masspm_group'); + +# No Avatar (u_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_chgavatar', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim', 'u_masspm', 'u_masspm_group'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_chgavatar'); + +# Full Moderator (m_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 10, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%'; + +# Standard Moderator (m_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 11, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%' AND auth_option NOT IN ('m_ban', 'm_chgposter'); + +# Simple Moderator (m_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 12, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%' AND auth_option IN ('m_', 'm_delete', 'm_softdelete', 'm_edit', 'm_info', 'm_report'); + +# Queue Moderator (m_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 13, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%' AND auth_option IN ('m_', 'm_approve', 'm_edit'); + +# Full Access (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 14, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%'; + +# Standard Access (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 15, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock'); + +# No Access (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 16, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option = 'f_'; + +# Read Only Access (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 17, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_search', 'f_subscribe', 'f_print'); + +# Limited Access (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 18, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg'); + +# Bot Access (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 19, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_print'); + +# On Moderation Queue (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg', 'f_noapprove'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove'); + +# Standard Access + Polls (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 21, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_sticky', 'f_user_lock'); + +# Limited Access + Polls (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 22, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_sticky', 'f_user_lock', 'f_votechg'); + +# New Member (u_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 23, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group', 'u_chgprofileinfo'); + +# New Member (f_) +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 24, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove'); + + +# Permissions + +# GUESTS - u_download and u_search ability +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) SELECT 1, 0, auth_option_id, 0, 1 FROM phpbb_acl_options WHERE auth_option IN ('u_', 'u_download', 'u_search'); + +# Admin user - full user features +INSERT INTO phpbb_acl_users (user_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 0, 0, 5, 0); + +# ADMINISTRATOR Group - full user features +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 0, 0, 5, 0); + +# ADMINISTRATOR Group - standard admin +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 0, 0, 1, 0); + +# REGISTERED and REGISTERED_COPPA having standard user features +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 0, 0, 6, 0); +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (3, 0, 0, 6, 0); + +# GLOBAL_MODERATORS having full user features +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (4, 0, 0, 5, 0); + +# GLOBAL_MODERATORS having full global moderator access +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (4, 0, 0, 10, 0); + +# Giving all groups read only access to the first category +# since administrators and moderators are already within the registered users group we do not need to set them here +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (1, 1, 0, 17, 0); +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 1, 0, 17, 0); +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (3, 1, 0, 17, 0); +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (6, 1, 0, 17, 0); + +# Giving access to the first forum + +# guests having read only access +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (1, 2, 0, 17, 0); + +# registered and registered_coppa having standard access +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 2, 0, 15, 0); +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (3, 2, 0, 15, 0); + +# global moderators having standard access + polls +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (4, 2, 0, 21, 0); + +# administrators having full forum and full moderator access +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 2, 0, 14, 0); +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 2, 0, 10, 0); + +# Bots having bot access +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (6, 2, 0, 19, 0); + +# NEW MEMBERS are not allowed to send private messages +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (7, 0, 0, 23, 0); + +# NEW MEMBERS on the queue +INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (7, 2, 0, 24, 0); + + +# -- Demo Topic +INSERT INTO phpbb_topics (topic_title, topic_poster, topic_time, topic_views, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, forum_id, topic_status, topic_type, topic_first_post_id, topic_first_poster_name, topic_first_poster_colour, topic_last_post_id, topic_last_poster_id, topic_last_poster_name, topic_last_poster_colour, topic_last_post_subject, topic_last_post_time, topic_last_view_time, poll_title, topic_visibility) VALUES ('{L_TOPICS_TOPIC_TITLE}', 2, 972086460, 0, 1, 0, 0, 2, 0, 0, 1, 'Admin', 'AA0000', 1, 2, 'Admin', 'AA0000', '{L_TOPICS_TOPIC_TITLE}', 972086460, 972086460, '', 1); + +# -- Demo Post +INSERT INTO phpbb_posts (topic_id, forum_id, poster_id, icon_id, post_time, post_username, poster_ip, post_subject, post_text, post_checksum, bbcode_uid, post_visibility) VALUES (1, 2, 2, 0, 972086460, '', '127.0.0.1', '{L_TOPICS_TOPIC_TITLE}', '{L_DEFAULT_INSTALL_POST}', '5dd683b17f641daf84c040bfefc58ce9', '', 1); + +# -- Admin posted to the demo topic +INSERT INTO phpbb_topics_posted (user_id, topic_id, topic_posted) VALUES (2, 1, 1); + +# -- Smilies +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':D', 'icon_e_biggrin.gif', '{L_SMILIES_VERY_HAPPY}', 15, 17, 1); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-D', 'icon_e_biggrin.gif', '{L_SMILIES_VERY_HAPPY}', 15, 17, 2); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':grin:', 'icon_e_biggrin.gif', '{L_SMILIES_VERY_HAPPY}', 15, 17, 3); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':)', 'icon_e_smile.gif', '{L_SMILIES_SMILE}', 15, 17, 4); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-)', 'icon_e_smile.gif', '{L_SMILIES_SMILE}', 15, 17, 5); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':smile:', 'icon_e_smile.gif', '{L_SMILIES_SMILE}', 15, 17, 6); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (';)', 'icon_e_wink.gif', '{L_SMILIES_WINK}', 15, 17, 7); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (';-)', 'icon_e_wink.gif', '{L_SMILIES_WINK}', 15, 17, 8); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':wink:', 'icon_e_wink.gif', '{L_SMILIES_WINK}', 15, 17, 9); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':(', 'icon_e_sad.gif', '{L_SMILIES_SAD}', 15, 17, 10); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-(', 'icon_e_sad.gif', '{L_SMILIES_SAD}', 15, 17, 11); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':sad:', 'icon_e_sad.gif', '{L_SMILIES_SAD}', 15, 17, 12); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':o', 'icon_e_surprised.gif', '{L_SMILIES_SURPRISED}', 15, 17, 13); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-o', 'icon_e_surprised.gif', '{L_SMILIES_SURPRISED}', 15, 17, 14); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':eek:', 'icon_e_surprised.gif', '{L_SMILIES_SURPRISED}', 15, 17, 15); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':shock:', 'icon_eek.gif', '{L_SMILIES_SHOCKED}', 15, 17, 16); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':?', 'icon_e_confused.gif', '{L_SMILIES_CONFUSED}', 15, 17, 17); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-?', 'icon_e_confused.gif', '{L_SMILIES_CONFUSED}', 15, 17, 18); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':???:', 'icon_e_confused.gif', '{L_SMILIES_CONFUSED}', 15, 17, 19); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES ('8-)', 'icon_cool.gif', '{L_SMILIES_COOL}', 15, 17, 20); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':cool:', 'icon_cool.gif', '{L_SMILIES_COOL}', 15, 17, 21); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':lol:', 'icon_lol.gif', '{L_SMILIES_LAUGHING}', 15, 17, 22); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':x', 'icon_mad.gif', '{L_SMILIES_MAD}', 15, 17, 23); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-x', 'icon_mad.gif', '{L_SMILIES_MAD}', 15, 17, 24); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':mad:', 'icon_mad.gif', '{L_SMILIES_MAD}', 15, 17, 25); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':P', 'icon_razz.gif', '{L_SMILIES_RAZZ}', 15, 17, 26); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-P', 'icon_razz.gif', '{L_SMILIES_RAZZ}', 15, 17, 27); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':razz:', 'icon_razz.gif', '{L_SMILIES_RAZZ}', 15, 17, 28); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':oops:', 'icon_redface.gif', '{L_SMILIES_EMARRASSED}', 15, 17, 29); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':cry:', 'icon_cry.gif', '{L_SMILIES_CRYING}', 15, 17, 30); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':evil:', 'icon_evil.gif', '{L_SMILIES_EVIL}', 15, 17, 31); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':twisted:', 'icon_twisted.gif', '{L_SMILIES_TWISTED_EVIL}', 15, 17, 32); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':roll:', 'icon_rolleyes.gif', '{L_SMILIES_ROLLING_EYES}', 15, 17, 33); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':!:', 'icon_exclaim.gif', '{L_SMILIES_EXCLAMATION}', 15, 17, 34); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':?:', 'icon_question.gif', '{L_SMILIES_QUESTION}', 15, 17, 35); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':idea:', 'icon_idea.gif', '{L_SMILIES_IDEA}', 15, 17, 36); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':arrow:', 'icon_arrow.gif', '{L_SMILIES_ARROW}', 15, 17, 37); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':|', 'icon_neutral.gif', '{L_SMILIES_NEUTRAL}', 15, 17, 38); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-|', 'icon_neutral.gif', '{L_SMILIES_NEUTRAL}', 15, 17, 39); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':mrgreen:', 'icon_mrgreen.gif', '{L_SMILIES_MR_GREEN}', 15, 17, 40); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':geek:', 'icon_e_geek.gif', '{L_SMILIES_GEEK}', 17, 17, 41); +INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':ugeek:', 'icon_e_ugeek.gif', '{L_SMILIES_UBER_GEEK}', 17, 18, 42); + +# -- icons +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/fire.gif', 16, 16, 1, 1); +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/redface.gif', 16, 16, 9, 1); +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/mrgreen.gif', 16, 16, 10, 1); +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/heart.gif', 16, 16, 4, 1); +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/star.gif', 16, 16, 2, 1); +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/radioactive.gif', 16, 16, 3, 1); +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/thinking.gif', 16, 16, 5, 1); +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/info.gif', 16, 16, 8, 1); +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/question.gif', 16, 16, 6, 1); +INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/alert.gif', 16, 16, 7, 1); + +# -- reasons +INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('warez', '{L_REPORT_WAREZ}', 1); +INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('spam', '{L_REPORT_SPAM}', 2); +INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('off_topic', '{L_REPORT_OFF_TOPIC}', 3); +INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('other', '{L_REPORT_OTHER}', 4); + +# -- extension_groups +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('IMAGES', 1, 1, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('ARCHIVES', 0, 1, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('PLAIN_TEXT', 0, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOCUMENTS', 0, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('REAL_MEDIA', 3, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('WINDOWS_MEDIA', 2, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('FLASH_FILES', 5, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('QUICKTIME_MEDIA', 6, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOWNLOADABLE_FILES', 0, 0, 1, '', 0, ''); + +# -- extensions +INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'gif'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'png'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'jpeg'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'jpg'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'tif'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'tiff'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'tga'); + +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'gtar'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'gz'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'tar'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'zip'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'rar'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'ace'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'torrent'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'tgz'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'bz2'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, '7z'); + +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'txt'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'c'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'h'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'cpp'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'hpp'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'diz'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'csv'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'ini'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'log'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'js'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'xml'); + +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xls'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xlsx'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xlsm'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xlsb'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'doc'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'docx'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'docm'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'dot'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'dotx'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'dotm'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'pdf'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ai'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ps'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ppt'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'pptx'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'pptm'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odg'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odp'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ods'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odt'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'rtf'); + +INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'rm'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'ram'); + +INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wma'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wmv'); + +INSERT INTO phpbb_extensions (group_id, extension) VALUES (7, 'swf'); + +INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mov'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4v'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4a'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mp4'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3gp'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3g2'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'qt'); + +INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpeg'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpg'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mp3'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogg'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogm'); + +# Add default profile fields +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_location', 'profilefields.type.string', 'phpbb_location', '20', '2', '100', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, '', ''); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_website', 'profilefields.type.url', 'phpbb_website', '40', '12', '255', '', '', '', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 2, 1, 'VISIT_WEBSITE', '%s'); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_interests', 'profilefields.type.text', 'phpbb_interests', '3|30', '2', '500', '', '', '.*', 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, '', ''); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_occupation', 'profilefields.type.text', 'phpbb_occupation', '3|30', '2', '500', '', '', '.*', 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, '', ''); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_aol', 'profilefields.type.string', 'phpbb_aol', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 5, 1, '', ''); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_icq', 'profilefields.type.string', 'phpbb_icq', '20', '3', '15', '', '', '[0-9]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 6, 1, 'SEND_ICQ_MESSAGE', 'https://www.icq.com/people/%s/'); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_wlm', 'profilefields.type.string', 'phpbb_wlm', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 7, 1, '', ''); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_yahoo', 'profilefields.type.string', 'phpbb_yahoo', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 8, 1, 'SEND_YIM_MESSAGE', 'ymsgr:sendim?%s'); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_facebook', 'profilefields.type.string', 'phpbb_facebook', '20', '5', '50', '', '', '[\w.]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 9, 1, 'VIEW_FACEBOOK_PROFILE', 'http://facebook.com/%s/'); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_twitter', 'profilefields.type.string', 'phpbb_twitter', '20', '1', '15', '', '', '[\w_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 10, 1, 'VIEW_TWITTER_PROFILE', 'http://twitter.com/%s'); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_skype', 'profilefields.type.string', 'phpbb_skype', '20', '6', '32', '', '', '[a-zA-Z][\w\.,\-_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 11, 1, 'VIEW_SKYPE_PROFILE', 'skype:%s?userinfo'); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_youtube', 'profilefields.type.string', 'phpbb_youtube', '20', '3', '60', '', '', '[a-zA-Z][\w\.,\-_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 12, 1, 'VIEW_YOUTUBE_CHANNEL', 'http://youtube.com/user/%s'); +INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_googleplus', 'profilefields.type.googleplus', 'phpbb_googleplus', '20', '3', '255', '', '', '[\w]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 13, 1, 'VIEW_GOOGLEPLUS_PROFILE', 'http://plus.google.com/%s'); + +# User Notification Options (for first user) +INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, ''); +INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, 'notification.method.email'); +INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, ''); +INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, 'notification.method.email'); + +# POSTGRES COMMIT # diff --git a/phpBB/install/app.php b/phpBB/install_new/app.php similarity index 100% rename from phpBB/install/app.php rename to phpBB/install_new/app.php diff --git a/phpBB/install/phpbbcli.php b/phpBB/install_new/phpbbcli.php old mode 100755 new mode 100644 similarity index 100% rename from phpBB/install/phpbbcli.php rename to phpBB/install_new/phpbbcli.php From 8bfd29e86dac675919d3572aac3ba5891d9d844e Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 30 Jun 2015 18:54:46 +0200 Subject: [PATCH 0463/1676] [ticket/13740] Clean up CLI CS PHPBB3-13740 --- .../phpbb/install/helper/iohandler/cli_iohandler.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php index f711abe431..f9c19f6d85 100644 --- a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php @@ -14,7 +14,6 @@ namespace phpbb\install\helper\iohandler; use phpbb\install\exception\installer_exception; -use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\OutputStyle; @@ -39,7 +38,7 @@ class cli_iohandler extends iohandler_base protected $input_values = array(); /** - * @var ProgressBar + * @var \Symfony\Component\Console\Helper\ProgressBar */ protected $progress_bar; @@ -66,7 +65,6 @@ class cli_iohandler extends iohandler_base $result = $this->input_values[$name]; } - if ($multibyte) { return utf8_normalize_nfc($result); @@ -160,7 +158,8 @@ class cli_iohandler extends iohandler_base { if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { - $this->output->writeln(sprintf('[%3d/%-3d] ---- %s', $this->current_task_progress, $this->task_progress_count, $this->translate_message($log_title, $log_description)['title'])); + $message = $this->translate_message($log_title, $log_description); + $this->output->writeln(sprintf('[%3d/%-3d] ---- %s', $this->current_task_progress, $this->task_progress_count, $message['title'])); } } @@ -193,11 +192,13 @@ class cli_iohandler extends iohandler_base " %message%\n"); $this->progress_bar->setBarWidth(60); - if (!defined('PHP_WINDOWS_VERSION_BUILD')) { + if (!defined('PHP_WINDOWS_VERSION_BUILD')) + { $this->progress_bar->setEmptyBarCharacter('â–‘'); // light shade character \u2591 $this->progress_bar->setProgressCharacter(''); $this->progress_bar->setBarCharacter('â–“'); // dark shade character \u2593 } + $this->progress_bar->setMessage(''); $this->io->newLine(2); $this->progress_bar->start(); From 5ad0af3d3df698f7c749fee1f65962e0ba3cf663 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 7 Jul 2015 19:16:58 +0200 Subject: [PATCH 0464/1676] [ticket/13740] Fixes and Tests for database helper PHPBB3-13740 --- phpBB/phpbb/install/helper/database.php | 3 +- tests/installer/database_helper_test.php | 151 +++++++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 tests/installer/database_helper_test.php diff --git a/phpBB/phpbb/install/helper/database.php b/phpBB/phpbb/install/helper/database.php index 38823c1231..d8751582f7 100644 --- a/phpBB/phpbb/install/helper/database.php +++ b/phpBB/phpbb/install/helper/database.php @@ -43,7 +43,8 @@ class database */ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path) { - $this->filesystem = $filesystem; + $this->filesystem = $filesystem; + $this->phpbb_root_path = $phpbb_root_path; // DBMS supported by phpBB $this->supported_dbms = array( diff --git a/tests/installer/database_helper_test.php b/tests/installer/database_helper_test.php new file mode 100644 index 0000000000..80c76c004b --- /dev/null +++ b/tests/installer/database_helper_test.php @@ -0,0 +1,151 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_installer_database_helper_test extends phpbb_test_case +{ + /** + * @var phpbb\install\helper\database + */ + private $database_helper; + + /** + * @var phpbb\db\driver\driver_interface + */ + private $dbms_mock; + + public function setUp() + { + $filesystem = new \phpbb\filesystem\filesystem(); + $phpbb_root_path = ''; + $this->database_helper = new \phpbb\install\helper\database($filesystem, $phpbb_root_path); + + // I used oracle because it tolerates the shortest table prefixes + // so it's the simplest to write test cases for + $this->dbms_mock = $this->getMock('\phpbb\db\driver\oracle'); + } + + /** + * @param string $input + * @param string $expected + * + * @dataProvider comment_string_provider + */ + public function test_remove_comments($input, $expected) + { + $this->assertEquals($expected, $this->database_helper->remove_comments($input)); + } + + /** + * @param array $expected + * @param string $sql + * @param string $delimiter + * + * @dataProvider sql_file_string_provider + */ + public function test_split_sql($expected, $sql, $delimiter) + { + $this->assertEquals($expected, $this->database_helper->split_sql_file($sql, $delimiter)); + } + + /** + * @param bool|array $expected + * @param string $test_string + * + * @dataProvider prefix_test_case_provider + */ + public function test_validate_table_prefix($expected, $test_string) + { + $this->assertEquals($expected, $this->database_helper->validate_table_prefix($this->dbms_mock, $test_string)); + } + + // Data provider for the remove comments function + public function comment_string_provider() + { + return array( + array( + 'abc', + 'abc', + ), + array( + 'abc /* asdf */', + "abc \n", + ), + array( + 'abc /* asdf */ f', + "abc \n f", + ), + array( + '# abc', + "\n", + ), + ); + } + + // Data provider for the sql file splitter function + public function sql_file_string_provider() + { + return array( + array( + array( + 'abcd "efgh"' . "\n" . 'qwerty', + 'SELECT * FROM table', + ), + 'abcd "efgh" + qwerty; + SELECT * FROM table', + ';', + ), + array( + array( + 'SELECT * FROM table1', + 'SELECT * FROM table2 WHERE i_am="king"', + ), + 'SELECT * FROM table1; SELECT * FROM table2 WHERE i_am="king"', + ';', + ), + ); + } + + // Test data for prefix test + public function prefix_test_case_provider() + { + return array( + array( + true, + 'phpbb_', + ), + array( + true, + 'phpbb', + ), + array( + array( + array('title' => 'INST_ERR_DB_INVALID_PREFIX'), + ), + '1hpbb_', + ), + array( + array( + array('title' => 'INST_ERR_DB_INVALID_PREFIX'), + ), + '?hpbb_', + ), + array( + array( + array('title' => 'INST_ERR_PREFIX_TOO_LONG'), + ), + 'php_bb_', + ), + ); + } +} From 9d54867485300eefe7fcd8e8c2080eb655e713ed Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 8 Jul 2015 01:00:28 +0200 Subject: [PATCH 0465/1676] [ticket/13740] Test navigation provider PHPBB3-13740 --- tests/installer/navigation_provider_test.php | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/installer/navigation_provider_test.php diff --git a/tests/installer/navigation_provider_test.php b/tests/installer/navigation_provider_test.php new file mode 100644 index 0000000000..5bfce0eba8 --- /dev/null +++ b/tests/installer/navigation_provider_test.php @@ -0,0 +1,34 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_installer_navigation_provider_test extends phpbb_test_case +{ + public function test_navigation() + { + // Mock nav interface + $nav_mock = $this->getMockBuilder('\phpbb\install\helper\navigation\navigation_interface') + ->method('get') + ->willReturn(array('foo' => 'bar')) + ->getMock(); + + // Set up dependencies + $container = new phpbb_mock_container_builder(); + $container->set('foo', $nav_mock); + $nav_collection = new \phpbb\di\service_collection($container); + $nav_collection->add('foo'); + + // Let's test + $nav_provider = new \phpbb\install\helper\navigation\navigation_provider($nav_collection); + $this->assertEquals(array('foo' => 'bar'), $nav_provider->get()); + } +} From 612eead5a9932d459d8b65f9217f895c33b51c39 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 8 Jul 2015 01:27:05 +0200 Subject: [PATCH 0466/1676] [ticket/13740] Installer config test PHPBB3-13740 --- tests/installer/installer_config_test.php | 86 +++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 tests/installer/installer_config_test.php diff --git a/tests/installer/installer_config_test.php b/tests/installer/installer_config_test.php new file mode 100644 index 0000000000..d1110bf8f8 --- /dev/null +++ b/tests/installer/installer_config_test.php @@ -0,0 +1,86 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +use phpbb\install\helper\config; + +class phpbb_installer_config_test extends phpbb_test_case +{ + /** + * @var \phpbb\install\helper\config + */ + private $config; + + public function setUp() + { + $phpbb_root_path = __DIR__ . './../../phpBB/'; + $filesystem = $this->getMock('\phpbb\filesystem\filesystem'); + $php_ini = $this->getMockBuilder('\phpbb\php\ini') + ->method('get_int') + ->willReturn(-1) + ->method('get_bytes') + ->willReturn(-1) + ->getMock(); + + $this->config = new config($filesystem, $php_ini, $phpbb_root_path); + } + + /** + * @covers config::set + * @covers config::get + */ + public function test_set_get_var() + { + $this->config->set('foo', 'bar'); + $this->assertEquals('bar', $this->config->get('foo')); + } + + public function test_get_time_remaining() + { + $this->assertGreaterThan(0, $this->config->get_time_remaining()); + } + + public function test_get_memory_remaining() + { + $this->assertGreaterThan(0, $this->config->get_memory_remaining()); + } + + /** + * @covers config::set_finished_task + * @covers config::set_active_module + * @covers config::set_task_progress_count + * @covers config::increment_current_task_progress + * @covers config::get_progress_data + */ + public function test_progress_tracking() + { + $this->config->set_finished_task('foo', 3); + $this->config->set_active_module('bar', 4); + $this->config->set_task_progress_count(10); + $this->config->increment_current_task_progress(); + + $this->assertContains(array('current_task_progress' => 1), $this->config->get_progress_data()); + + $this->config->increment_current_task_progress(2); + + $this->assertEquals(array( + 'last_task_module_index' => 4, + 'last_task_module_name' => 'bar', // Stores the service name of the latest finished module + 'last_task_index' => 3, + 'last_task_name' => 'foo', // Stores the service name of the latest finished task + 'max_task_progress' => 10, + 'current_task_progress' => 3, + ), + $this->config->get_progress_data() + ); + } +} From 1c01252b5d899c488e007659234b6224ac3f4c19 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 8 Jul 2015 13:17:42 +0200 Subject: [PATCH 0467/1676] [ticket/13740] Fix test stubs PHPBB3-13740 --- tests/installer/database_helper_test.php | 20 ++++---------------- tests/installer/installer_config_test.php | 11 ++++++----- tests/installer/navigation_provider_test.php | 8 ++++---- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/tests/installer/database_helper_test.php b/tests/installer/database_helper_test.php index 80c76c004b..84445c86c5 100644 --- a/tests/installer/database_helper_test.php +++ b/tests/installer/database_helper_test.php @@ -28,10 +28,6 @@ class phpbb_installer_database_helper_test extends phpbb_test_case $filesystem = new \phpbb\filesystem\filesystem(); $phpbb_root_path = ''; $this->database_helper = new \phpbb\install\helper\database($filesystem, $phpbb_root_path); - - // I used oracle because it tolerates the shortest table prefixes - // so it's the simplest to write test cases for - $this->dbms_mock = $this->getMock('\phpbb\db\driver\oracle'); } /** @@ -65,7 +61,7 @@ class phpbb_installer_database_helper_test extends phpbb_test_case */ public function test_validate_table_prefix($expected, $test_string) { - $this->assertEquals($expected, $this->database_helper->validate_table_prefix($this->dbms_mock, $test_string)); + $this->assertEquals($expected, $this->database_helper->validate_table_prefix('oracle', $test_string)); } // Data provider for the remove comments function @@ -100,17 +96,9 @@ class phpbb_installer_database_helper_test extends phpbb_test_case 'abcd "efgh"' . "\n" . 'qwerty', 'SELECT * FROM table', ), - 'abcd "efgh" - qwerty; - SELECT * FROM table', - ';', - ), - array( - array( - 'SELECT * FROM table1', - 'SELECT * FROM table2 WHERE i_am="king"', - ), - 'SELECT * FROM table1; SELECT * FROM table2 WHERE i_am="king"', + 'abcd "efgh"' . "\n" . + 'qwerty' . "\n" . + 'SELECT * FROM table', ';', ), ); diff --git a/tests/installer/installer_config_test.php b/tests/installer/installer_config_test.php index d1110bf8f8..6c0079a1ec 100644 --- a/tests/installer/installer_config_test.php +++ b/tests/installer/installer_config_test.php @@ -25,11 +25,11 @@ class phpbb_installer_config_test extends phpbb_test_case $phpbb_root_path = __DIR__ . './../../phpBB/'; $filesystem = $this->getMock('\phpbb\filesystem\filesystem'); $php_ini = $this->getMockBuilder('\phpbb\php\ini') - ->method('get_int') - ->willReturn(-1) - ->method('get_bytes') - ->willReturn(-1) ->getMock(); + $php_ini->method('get_int') + ->willReturn(-1); + $php_ini->method('get_bytes') + ->willReturn(-1); $this->config = new config($filesystem, $php_ini, $phpbb_root_path); } @@ -68,7 +68,8 @@ class phpbb_installer_config_test extends phpbb_test_case $this->config->set_task_progress_count(10); $this->config->increment_current_task_progress(); - $this->assertContains(array('current_task_progress' => 1), $this->config->get_progress_data()); + $progress_data = $this->config->get_progress_data(); + $this->assertEquals(1, $progress_data['current_task_progress']); $this->config->increment_current_task_progress(2); diff --git a/tests/installer/navigation_provider_test.php b/tests/installer/navigation_provider_test.php index 5bfce0eba8..ea39af66cd 100644 --- a/tests/installer/navigation_provider_test.php +++ b/tests/installer/navigation_provider_test.php @@ -16,14 +16,14 @@ class phpbb_installer_navigation_provider_test extends phpbb_test_case public function test_navigation() { // Mock nav interface - $nav_mock = $this->getMockBuilder('\phpbb\install\helper\navigation\navigation_interface') - ->method('get') - ->willReturn(array('foo' => 'bar')) + $nav_stub = $this->getMockBuilder('\phpbb\install\helper\navigation\navigation_interface') ->getMock(); + $nav_stub->method('get') + ->willReturn(array('foo' => 'bar')); // Set up dependencies $container = new phpbb_mock_container_builder(); - $container->set('foo', $nav_mock); + $container->set('foo', $nav_stub); $nav_collection = new \phpbb\di\service_collection($container); $nav_collection->add('foo'); From 80f91da9b9ab7f4c2d66ba5632802a3a5dfa489f Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Wed, 8 Jul 2015 15:11:10 -0700 Subject: [PATCH 0468/1676] [ticket/13995] Fix errors in tests from merge conflict PHPBB3-13995 --- tests/template/template_includecss_test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/template/template_includecss_test.php b/tests/template/template_includecss_test.php index ea851e3568..ac62e820ae 100644 --- a/tests/template/template_includecss_test.php +++ b/tests/template/template_includecss_test.php @@ -103,11 +103,11 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te ), array( array('TEST' => 3), - '', + '', ), array( array('TEST' => 4), - '', + '', ), ); } From 98ab5478e6a74b4325f002c1a5daae9d6dbe80e1 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 12 Jun 2014 14:20:58 +0200 Subject: [PATCH 0469/1676] [ticket/12692] Add a console command to manage the thumbnails PHPBB3-12692 --- .../default/container/services_console.yml | 27 ++++ phpBB/language/en/acp/common.php | 6 + .../console/command/thumbnail/delete.php | 111 +++++++++++++++ .../console/command/thumbnail/generate.php | 133 ++++++++++++++++++ .../console/command/thumbnail/recreate.php | 84 +++++++++++ 5 files changed, 361 insertions(+) create mode 100644 phpBB/phpbb/console/command/thumbnail/delete.php create mode 100644 phpBB/phpbb/console/command/thumbnail/generate.php create mode 100644 phpBB/phpbb/console/command/thumbnail/recreate.php diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index f39218ed9c..15f597520c 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -156,3 +156,30 @@ services: - @text_reparser_collection tags: - { name: console.command } + + console.command.thumbnail.generate: + class: phpbb\console\command\thumbnail\generate + arguments: + - @dbal.conn + - @user + - @cache + - %core.root_path% + - %core.php_ext% + tags: + - { name: console.command } + + console.command.thumbnail.recreate: + class: phpbb\console\command\thumbnail\recreate + arguments: + - @user + tags: + - { name: console.command } + + console.command.thumbnail.delete: + class: phpbb\console\command\thumbnail\delete + arguments: + - @dbal.conn + - @user + - %core.root_path% + tags: + - { name: console.command } diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index fdbc4aebd0..77dc5b6b62 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -225,6 +225,12 @@ $lang = array_merge($lang, array( 'BACK' => 'Back', + 'CLI_DESCRIPTION_CRON_LIST' => 'Prints a list of ready and unready cron jobs.', + 'CLI_DESCRIPTION_CRON_RUN' => 'Runs all ready cron tasks.', + 'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1' => 'Name of the task to be run', + + 'CLI_DESCRIPTION_OPTION_SHELL' => 'Launch the shell.', + 'COLOUR_SWATCH' => 'Web-safe colour swatch', 'CONFIG_UPDATED' => 'Configuration updated successfully.', 'CRON_LOCK_ERROR' => 'Could not obtain cron lock.', diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php new file mode 100644 index 0000000000..81f1baf1db --- /dev/null +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -0,0 +1,111 @@ + +* @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\console\command\thumbnail; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\OutputInterface; + +class delete extends \phpbb\console\command\command +{ + /** @var \phpbb\db\driver\driver_interface */ + protected $db; + + /** @var \phpbb\user */ + protected $user; + + /** + * phpBB root path + * @var string + */ + protected $phpbb_root_path; + + /** + * Constructor + * + * @param \phpbb\db\driver\driver_interface $db Database connection + * @param \phpbb\user $user The user object (used to get language information) + * @param string $phpbb_root_path Root path + */ + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path) + { + $this->db = $db; + $this->user = $user; + $this->phpbb_root_path = $phpbb_root_path; + parent::__construct(); + } + + /** + * Sets the command name and description + * + * @return null + */ + protected function configure() + { + $this + ->setName('thumbnail:delete') + ->setDescription($this->user->lang('CLI_DESCRIPTION_THUMBNAIL_DELETE')) + ; + } + + /** + * Executes the command thumbnail:delete. + * + * @param InputInterface $input The input stream used to get the argument and verboe option. + * @param OutputInterface $output The output stream, used for printing verbose-mode and error information. + * + * @return int 0 if all is ok, 1 if a thumbnail couldn't be deleted. + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $sql = 'SELECT attach_id, physical_filename, extension, real_filename, mimetype + FROM ' . ATTACHMENTS_TABLE . ' + WHERE thumbnail = 1'; + $result = $this->db->sql_query($sql); + + $thumbnail_deleted = array(); + $return = 0; + while ($row = $this->db->sql_fetchrow($result)) + { + $thumbnail_path = $this->phpbb_root_path . 'files/thumb_' . $row['physical_filename']; + + if (@unlink($thumbnail_path)) + { + $thumbnail_deleted[] = $row['attach_id']; + if ($input->getOption('verbose')) + { + $output->writeln($this->user->lang('THUMBNAIL_DELETED', $row['real_filename'], $row['physical_filename'])); + } + } + else + { + if ($input->getOption('verbose')) + { + $return = 1; + $output->writeln('' . $this->user->lang('THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); + } + } + } + $this->db->sql_freeresult($result); + + if (sizeof($thumbnail_deleted)) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET thumbnail = 0 + WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_deleted); + $this->db->sql_query($sql); + } + + return $return; + } +} diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php new file mode 100644 index 0000000000..dcf60e4fe2 --- /dev/null +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -0,0 +1,133 @@ + +* @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\console\command\thumbnail; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class generate extends \phpbb\console\command\command +{ + /** @var \phpbb\db\driver\driver_interface */ + protected $db; + + /** @var \phpbb\user */ + protected $user; + + /** @var \phpbb\cache\service */ + protected $cache; + + /** + * phpBB root path + * @var string + */ + protected $phpbb_root_path; + + /** + * PHP extension. + * + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param \phpbb\db\driver\driver_interface $db Database connection + * @param \phpbb\user $user The user object (used to get language information) + * @param \phpbb\cache\service $cache The cache service + * @param string $phpbb_root_path Root path + * @param string $php_ext PHP extension + */ + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\cache\service $cache, $phpbb_root_path, $php_ext) + { + $this->db = $db; + $this->user = $user; + $this->cache = $cache; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + parent::__construct(); + } + + /** + * Sets the command name and description + * + * @return null + */ + protected function configure() + { + $this + ->setName('thumbnail:generate') + ->setDescription($this->user->lang('CLI_DESCRIPTION_THUMBNAIL_GENERATE')) + ; + } + + /** + * Executes the command thumbnail:generate. + * + * @param InputInterface $input The input stream used to get the argument and verboe option. + * @param OutputInterface $output The output stream, used for printing verbose-mode and error information. + * + * @return int 0. + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $extensions = $this->cache->obtain_attach_extensions(true); + + $sql = 'SELECT attach_id, physical_filename, extension, real_filename, mimetype + FROM ' . ATTACHMENTS_TABLE . ' + WHERE thumbnail = 0'; + $result = $this->db->sql_query($sql); + + if (!function_exists('create_thumbnail')) + { + require($this->phpbb_root_path . 'includes/functions_posting.' . $this->php_ext); + } + + $thumbnail_created = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + if (isset($extensions[$row['extension']]['display_cat']) && $extensions[$row['extension']]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE) + { + $source = $this->phpbb_root_path . 'files/' . $row['physical_filename']; + $destination = $this->phpbb_root_path . 'files/thumb_' . $row['physical_filename']; + + if (!create_thumbnail($source, $destination, $row['mimetype'])) + { + if ($input->getOption('verbose')) + { + $output->writeln('' . $this->user->lang('THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); + } + } + else + { + $thumbnail_created[] = $row['attach_id']; + if ($input->getOption('verbose')) + { + $output->writeln($this->user->lang('THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename'])); + } + } + } + } + $this->db->sql_freeresult($result); + + if (sizeof($thumbnail_created)) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET thumbnail = 1 + WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_created); + $this->db->sql_query($sql); + } + + return 0; + } +} diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php new file mode 100644 index 0000000000..569642f2a4 --- /dev/null +++ b/phpBB/phpbb/console/command/thumbnail/recreate.php @@ -0,0 +1,84 @@ + +* @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\console\command\thumbnail; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\OutputInterface; + +class recreate extends \phpbb\console\command\command +{ + /** @var \phpbb\user */ + protected $user; + + /** + * Constructor + * + * @param \phpbb\user $user The user object (used to get language information) + */ + public function __construct(\phpbb\user $user) + { + $this->user = $user; + parent::__construct(); + } + + /** + * Sets the command name and description + * + * @return null + */ + protected function configure() + { + $this + ->setName('thumbnail:recreate') + ->setDescription($this->user->lang('CLI_DESCRIPTION_THUMBNAIL_RECREATE')) + ; + } + + /** + * Executes the command thumbnail:recreate. + * + * @param InputInterface $input The input stream used to get the argument and verboe option. + * @param OutputInterface $output The output stream, used for printing verbose-mode and error information. + * + * @return int 0 if all is ok, 1 if a thumbnail couldn't be deleted. + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $parameters = array( + 'command' => 'thumbnail:delete' + ); + + if ($input->getOption('verbose')) + { + $parameters['-v'] = true; + } + + $this->getApplication()->setAutoExit(false); + + $input_delete = new ArrayInput($parameters); + $return = $this->getApplication()->run($input_delete, $output); + + if ($return == 0) + { + $parameters['command'] = 'thumbnail:generate'; + + $input_create = new ArrayInput($parameters); + $return = $this->getApplication()->run($input_create, $output); + } + + $this->getApplication()->setAutoExit(true); + + return $return; + } +} From d517ed846be665ec04d9ca000d5f26f8a9571206 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 12 Jun 2014 23:16:51 +0200 Subject: [PATCH 0470/1676] [ticket/12692] Add unit test PHPBB3-12692 --- tests/console/fixtures/png | Bin 0 -> 129 bytes tests/console/fixtures/thumbnail.xml | 40 ++++++++++ tests/console/fixtures/txt | 2 + tests/console/thumbnail_test.php | 107 +++++++++++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 tests/console/fixtures/png create mode 100644 tests/console/fixtures/thumbnail.xml create mode 100644 tests/console/fixtures/txt create mode 100644 tests/console/thumbnail_test.php diff --git a/tests/console/fixtures/png b/tests/console/fixtures/png new file mode 100644 index 0000000000000000000000000000000000000000..c143a26a06cad7fc560ea51b8d716883c664a64a GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1|(O0oL2{=7>k44ofy`glX(e}Nq6*hWMJ6X z&;2Kn70Bl-@Q5sCVBk9f!i-b3`J{n@VxBIJArj%qfB0E=JQ_H?4l^n;vavC+#j>!> TyE$hqPz8ghtDnm{r-UW|uGbvP literal 0 HcmV?d00001 diff --git a/tests/console/fixtures/thumbnail.xml b/tests/console/fixtures/thumbnail.xml new file mode 100644 index 0000000000..8037523633 --- /dev/null +++ b/tests/console/fixtures/thumbnail.xml @@ -0,0 +1,40 @@ + + +

            + attach_id + physical_filename + real_filename + thumbnail + extension + mimetype + attach_comment + + + 1 + test_png_1 + real_test.png + 0 + png + image/png + + + + 2 + test_png_2 + real_test.png + 1 + png + image/png + + + + 10 + test_txt + real_test.txt + 0 + txt + text/plain + + +
            + diff --git a/tests/console/fixtures/txt b/tests/console/fixtures/txt new file mode 100644 index 0000000000..a78c858f5c --- /dev/null +++ b/tests/console/fixtures/txt @@ -0,0 +1,2 @@ +mime trigger +The HTML tags should remain uppercase so that case-insensitivity can be checked. diff --git a/tests/console/thumbnail_test.php b/tests/console/thumbnail_test.php new file mode 100644 index 0000000000..7ac18d931a --- /dev/null +++ b/tests/console/thumbnail_test.php @@ -0,0 +1,107 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use phpbb\console\command\thumbnail\generate; +use phpbb\console\command\thumbnail\delete; +use phpbb\console\command\thumbnail\recreate; + +class phpbb_console_command_thumbnail_test extends phpbb_database_test_case +{ + protected $db; + protected $config; + protected $cache; + protected $user; + protected $phpEx; + protected $phpbb_root_path; + protected $application; + + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/thumbnail.xml'); + } + + public function setUp() + { + global $config, $phpbb_root_path, $phpEx; + + parent::setUp(); + + $config = $this->config = new \phpbb\config\config(array( + 'img_min_thumb_filesize' => 2, + 'img_max_thumb_width' => 2, + 'img_imagick' => '', + )); + + $this->db = $this->db = $this->new_dbal(); + $this->user = $this->getMock('\phpbb\user'); + $this->phpbb_root_path = $phpbb_root_path; + $this->phpEx = $phpEx; + + $this->cache = $this->getMock('\phpbb\cache\service', array(), array(new phpbb_mock_cache(), $this->config, $this->db, $this->phpbb_root_path, $this->phpEx)); + $this->cache->expects($this->any())->method('obtain_attach_extensions')->will($this->returnValue(array( + 'png' => array('display_cat' => ATTACHMENT_CATEGORY_IMAGE), + 'txt' => array('display_cat' => ATTACHMENT_CATEGORY_NONE), + ))); + + $this->application = new Application(); + $this->application->add(new generate($this->db, $this->user, $this->cache, $this->phpbb_root_path, $this->phpEx)); + $this->application->add(new delete($this->db, $this->user, $this->phpbb_root_path)); + $this->application->add(new recreate($this->user)); + } + + public function test_thumbnails() + { + copy(dirname(__FILE__) . '/fixtures/png', $this->phpbb_root_path . 'files/test_png_1'); + copy(dirname(__FILE__) . '/fixtures/png', $this->phpbb_root_path . 'files/test_png_2'); + copy(dirname(__FILE__) . '/fixtures/png', $this->phpbb_root_path . 'files/thumb_test_png_2'); + copy(dirname(__FILE__) . '/fixtures/txt', $this->phpbb_root_path . 'files/test_txt'); + + $command_tester = $this->get_command_tester('thumbnail:generate'); + $exit_status = $command_tester->execute(array('command' => 'thumbnail:generate')); + + $this->assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); + $this->assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); + $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); + $this->assertSame(0, $exit_status); + + $command_tester = $this->get_command_tester('thumbnail:delete'); + $exit_status = $command_tester->execute(array('command' => 'thumbnail:delete')); + + $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); + $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); + $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); + $this->assertSame(0, $exit_status); + + $command_tester = $this->get_command_tester('thumbnail:recreate'); + $exit_status = $command_tester->execute(array('command' => 'thumbnail:recreate')); + + $this->assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); + $this->assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); + $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); + $this->assertSame(0, $exit_status); + + unlink($this->phpbb_root_path . 'files/test_png_1'); + unlink($this->phpbb_root_path . 'files/test_png_2'); + unlink($this->phpbb_root_path . 'files/test_txt'); + unlink($this->phpbb_root_path . 'files/thumb_test_png_1'); + unlink($this->phpbb_root_path . 'files/thumb_test_png_2'); + } + + public function get_command_tester($command_name) + { + $command = $this->application->find($command_name); + return new CommandTester($command); + } +} From 074dfdbdfea364cc2796d69c4d27535ab19fdac7 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 13 Jun 2014 15:46:09 +0200 Subject: [PATCH 0471/1676] [ticket/12692] Update doc blocks PHPBB3-12692 --- phpBB/language/en/acp/common.php | 2 +- phpBB/phpbb/console/command/thumbnail/delete.php | 4 +++- phpBB/phpbb/console/command/thumbnail/generate.php | 2 ++ phpBB/phpbb/console/command/thumbnail/recreate.php | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 77dc5b6b62..c2c3fda7a0 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -308,7 +308,7 @@ $lang = array_merge($lang, array( 'SHOW_ALL_OPERATIONS' => 'Show all operations', - 'TASKS_NOT_READY' => 'Not ready tasks:', + 'TASKS_NOT_READY' => 'Not ready tasks:', 'TASKS_READY' => 'Ready tasks:', 'TOTAL_SIZE' => 'Total size', diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index 81f1baf1db..707c05ffea 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -61,7 +61,9 @@ class delete extends \phpbb\console\command\command /** * Executes the command thumbnail:delete. * - * @param InputInterface $input The input stream used to get the argument and verboe option. + * Delete all the existing thumbnails (and update the database in consequences). + * + * @param InputInterface $input The input stream used to get the argument and verbose option. * @param OutputInterface $output The output stream, used for printing verbose-mode and error information. * * @return int 0 if all is ok, 1 if a thumbnail couldn't be deleted. diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index dcf60e4fe2..bbe6677650 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -74,6 +74,8 @@ class generate extends \phpbb\console\command\command /** * Executes the command thumbnail:generate. * + * Generate a thumbnail for all attachments which need one and don't have it yet. + * * @param InputInterface $input The input stream used to get the argument and verboe option. * @param OutputInterface $output The output stream, used for printing verbose-mode and error information. * diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php index 569642f2a4..71c5d90654 100644 --- a/phpBB/phpbb/console/command/thumbnail/recreate.php +++ b/phpBB/phpbb/console/command/thumbnail/recreate.php @@ -48,6 +48,8 @@ class recreate extends \phpbb\console\command\command /** * Executes the command thumbnail:recreate. * + * This command is a "macro" to execute thumbnail:delete and then thumbnail:generate. + * * @param InputInterface $input The input stream used to get the argument and verboe option. * @param OutputInterface $output The output stream, used for printing verbose-mode and error information. * From 3a0883e93ebd542c1cf67203b4c17456d8308426 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 13 Jun 2014 21:43:44 +0200 Subject: [PATCH 0472/1676] [ticket/12692] Use !empty() instead of sizeof() PHPBB3-12692 --- phpBB/phpbb/console/command/thumbnail/delete.php | 2 +- phpBB/phpbb/console/command/thumbnail/generate.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index 707c05ffea..ba6fdf7ce6 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -100,7 +100,7 @@ class delete extends \phpbb\console\command\command } $this->db->sql_freeresult($result); - if (sizeof($thumbnail_deleted)) + if (!empty($thumbnail_deleted)) { $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET thumbnail = 0 diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index bbe6677650..ac9d18d933 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -122,7 +122,7 @@ class generate extends \phpbb\console\command\command } $this->db->sql_freeresult($result); - if (sizeof($thumbnail_created)) + if (!empty($thumbnail_created)) { $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET thumbnail = 1 From 3924428050d4225c073876bd0e22cf4e9f54138e Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 13 Jun 2014 21:47:35 +0200 Subject: [PATCH 0473/1676] [ticket/12692] Use strict comparison in thumbnail:recreate PHPBB3-12692 --- phpBB/phpbb/console/command/thumbnail/recreate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php index 71c5d90654..69ea67e410 100644 --- a/phpBB/phpbb/console/command/thumbnail/recreate.php +++ b/phpBB/phpbb/console/command/thumbnail/recreate.php @@ -71,7 +71,7 @@ class recreate extends \phpbb\console\command\command $input_delete = new ArrayInput($parameters); $return = $this->getApplication()->run($input_delete, $output); - if ($return == 0) + if ($return === 0) { $parameters['command'] = 'thumbnail:generate'; From ed0e1590800e00b19115ad1712e75f33d3080a5e Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 17 Jun 2014 22:13:34 +0200 Subject: [PATCH 0474/1676] [ticket/12692] Fix coding style PHPBB3-12692 --- phpBB/phpbb/console/command/thumbnail/delete.php | 2 +- phpBB/phpbb/console/command/thumbnail/recreate.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index ba6fdf7ce6..52a6c424e6 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -16,7 +16,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\OutputInterface; -class delete extends \phpbb\console\command\command +class delete extends \phpbb\console\command\command { /** @var \phpbb\db\driver\driver_interface */ protected $db; diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php index 69ea67e410..dd10da9106 100644 --- a/phpBB/phpbb/console/command/thumbnail/recreate.php +++ b/phpBB/phpbb/console/command/thumbnail/recreate.php @@ -16,7 +16,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\OutputInterface; -class recreate extends \phpbb\console\command\command +class recreate extends \phpbb\console\command\command { /** @var \phpbb\user */ protected $user; From 3f0fa70e3afb0ce2dbca72bd74b17c93a2756e02 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 17 Jun 2014 22:14:26 +0200 Subject: [PATCH 0475/1676] [ticket/12692] Update comments PHPBB3-12692 --- phpBB/phpbb/console/command/thumbnail/delete.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index 52a6c424e6..82a53727ab 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -61,7 +61,7 @@ class delete extends \phpbb\console\command\command /** * Executes the command thumbnail:delete. * - * Delete all the existing thumbnails (and update the database in consequences). + * Deletes all existing thumbnails and updates the database accordingly. * * @param InputInterface $input The input stream used to get the argument and verbose option. * @param OutputInterface $output The output stream, used for printing verbose-mode and error information. From 6b5fdc730fe1b73bab9ecfe748009bc90d1950f3 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 17 Jun 2014 22:16:28 +0200 Subject: [PATCH 0476/1676] [ticket/12692] Remove a not and swap the blocks in the corresponding if PHPBB3-12692 --- .../phpbb/console/command/thumbnail/generate.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index ac9d18d933..1cfb2159d9 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -103,14 +103,7 @@ class generate extends \phpbb\console\command\command $source = $this->phpbb_root_path . 'files/' . $row['physical_filename']; $destination = $this->phpbb_root_path . 'files/thumb_' . $row['physical_filename']; - if (!create_thumbnail($source, $destination, $row['mimetype'])) - { - if ($input->getOption('verbose')) - { - $output->writeln('' . $this->user->lang('THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); - } - } - else + if (create_thumbnail($source, $destination, $row['mimetype'])) { $thumbnail_created[] = $row['attach_id']; if ($input->getOption('verbose')) @@ -118,6 +111,13 @@ class generate extends \phpbb\console\command\command $output->writeln($this->user->lang('THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename'])); } } + else + { + if ($input->getOption('verbose')) + { + $output->writeln('' . $this->user->lang('THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); + } + } } } $this->db->sql_freeresult($result); From c96cc2cb05de05c9599ca27241e903ea6fada3a3 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 17 Jun 2014 22:17:26 +0200 Subject: [PATCH 0477/1676] [ticket/12692] Cast the ids to int PHPBB3-12692 --- phpBB/phpbb/console/command/thumbnail/generate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index 1cfb2159d9..1070b7b37a 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -105,7 +105,7 @@ class generate extends \phpbb\console\command\command if (create_thumbnail($source, $destination, $row['mimetype'])) { - $thumbnail_created[] = $row['attach_id']; + $thumbnail_created[] = (int) $row['attach_id']; if ($input->getOption('verbose')) { $output->writeln($this->user->lang('THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename'])); From 54be6b1f622cf394f3cb2c7eb5f2c27072018baa Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 17 Jun 2014 22:24:45 +0200 Subject: [PATCH 0478/1676] [ticket/12692] Update the database regularly PHPBB3-12692 --- .../console/command/thumbnail/delete.php | 25 ++++++++++++++++--- .../console/command/thumbnail/generate.php | 25 ++++++++++++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index 82a53727ab..7c66011d5c 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -84,6 +84,13 @@ class delete extends \phpbb\console\command\command if (@unlink($thumbnail_path)) { $thumbnail_deleted[] = $row['attach_id']; + + if (sizeof($thumbnail_deleted) === 250) + { + $this->commit_changes($thumbnail_deleted); + $thumbnail_deleted = array(); + } + if ($input->getOption('verbose')) { $output->writeln($this->user->lang('THUMBNAIL_DELETED', $row['real_filename'], $row['physical_filename'])); @@ -102,12 +109,22 @@ class delete extends \phpbb\console\command\command if (!empty($thumbnail_deleted)) { - $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' - SET thumbnail = 0 - WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_deleted); - $this->db->sql_query($sql); + $this->commit_changes($thumbnail_deleted); } return $return; } + + /** + * Commits the changes to the database + * + * @param array $thumbnail_deleted + */ + protected function commit_changes(array $thumbnail_deleted) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET thumbnail = 0 + WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_deleted); + $this->db->sql_query($sql); + } } diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index 1070b7b37a..c27d91d4d5 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -106,6 +106,13 @@ class generate extends \phpbb\console\command\command if (create_thumbnail($source, $destination, $row['mimetype'])) { $thumbnail_created[] = (int) $row['attach_id']; + + if (sizeof($thumbnail_created) === 250) + { + $this->commit_changes($thumbnail_created); + $thumbnail_created = array(); + } + if ($input->getOption('verbose')) { $output->writeln($this->user->lang('THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename'])); @@ -124,12 +131,22 @@ class generate extends \phpbb\console\command\command if (!empty($thumbnail_created)) { - $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' - SET thumbnail = 1 - WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_created); - $this->db->sql_query($sql); + $this->commit_changes($thumbnail_created); } return 0; } + + /** + * Commits the changes to the database + * + * @param array $thumbnail_created + */ + protected function commit_changes(array $thumbnail_created) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET thumbnail = 1 + WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_created); + $this->db->sql_query($sql); + } } From 487fea8cfffe872e888ebcc3e1f5538b72bcaec1 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 22 Jul 2014 16:24:40 +0200 Subject: [PATCH 0479/1676] [ticket/12692] Move the language strings to cli.php PHPBB3-12692 --- .../default/container/services_console.yml | 4 ++-- phpBB/language/en/cli.php | 13 ++++++++++--- .../console/command/thumbnail/delete.php | 16 +++++++--------- .../console/command/thumbnail/generate.php | 19 ++++++++++--------- .../console/command/thumbnail/recreate.php | 14 -------------- tests/console/thumbnail_test.php | 4 ++-- 6 files changed, 31 insertions(+), 39 deletions(-) diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 15f597520c..010bde025d 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -160,8 +160,8 @@ services: console.command.thumbnail.generate: class: phpbb\console\command\thumbnail\generate arguments: - - @dbal.conn - @user + - @dbal.conn - @cache - %core.root_path% - %core.php_ext% @@ -178,8 +178,8 @@ services: console.command.thumbnail.delete: class: phpbb\console\command\thumbnail\delete arguments: - - @dbal.conn - @user + - @dbal.conn - %core.root_path% tags: - { name: console.command } diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index d45c52ac5d..f0e5dd6120 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -72,6 +72,10 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_SET_ATOMIC_CONFIG' => 'Sets a configuration option’s value only if the old matches the current value', 'CLI_DESCRIPTION_SET_CONFIG' => 'Sets a configuration option’s value', + 'CLI_DESCRIPTION_THUMBNAIL_DELETE' => 'Delete all existing thumbnails.', + 'CLI_DESCRIPTION_THUMBNAIL_GENERATE' => 'Generate all missing thumbnails.', + 'CLI_DESCRIPTION_THUMBNAIL_RECREATE' => 'Recreate all thumbnails.', + 'CLI_EXTENSION_DISABLE_FAILURE' => 'Could not disable extension %s', 'CLI_EXTENSION_DISABLE_SUCCESS' => 'Successfully disabled extension %s', 'CLI_EXTENSION_ENABLE_FAILURE' => 'Could not enable extension %s', @@ -80,13 +84,16 @@ $lang = array_merge($lang, array( 'CLI_EXTENSION_PURGE_FAILURE' => 'Could not purge extension %s', 'CLI_EXTENSION_PURGE_SUCCESS' => 'Successfully purged extension %s', 'CLI_EXTENSION_NOT_FOUND' => 'No extensions were found.', - 'CLI_EXTENSIONS_AVAILABLE' => 'Available', - 'CLI_EXTENSIONS_DISABLED' => 'Disabled', - 'CLI_EXTENSIONS_ENABLED' => 'Enabled', 'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.', 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s (range %2$d..%3$d)', 'CLI_REPARSER_REPARSE_REPARSING_START' => 'Reparsing %s...', 'CLI_REPARSER_REPARSE_SUCCESS' => 'Reparsing ended with success', + + // In all the case %1$s is the logical name of the file and %2$s the real name on the filesystem + // eg: big_image.png (2_a51529ae7932008cf8454a95af84cacd) generated. + 'THUMBNAIL_DELETED' => '%1$s (%2$s) deleted.', + 'THUMBNAIL_SKIPPED' => '%1$s (%2$s) skipped.', + 'THUMBNAIL_GENERATED' => '%1$s (%2$s) generated.', )); diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index 7c66011d5c..b60ea5238f 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -13,17 +13,15 @@ namespace phpbb\console\command\thumbnail; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\OutputInterface; class delete extends \phpbb\console\command\command { - /** @var \phpbb\db\driver\driver_interface */ + /** + * @var \phpbb\db\driver\driver_interface + */ protected $db; - /** @var \phpbb\user */ - protected $user; - /** * phpBB root path * @var string @@ -33,16 +31,16 @@ class delete extends \phpbb\console\command\command /** * Constructor * - * @param \phpbb\db\driver\driver_interface $db Database connection * @param \phpbb\user $user The user object (used to get language information) + * @param \phpbb\db\driver\driver_interface $db Database connection * @param string $phpbb_root_path Root path */ - public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path) + public function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db, $phpbb_root_path) { $this->db = $db; - $this->user = $user; $this->phpbb_root_path = $phpbb_root_path; - parent::__construct(); + + parent::__construct($user); } /** diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index c27d91d4d5..640d971b5d 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -17,13 +17,14 @@ use Symfony\Component\Console\Output\OutputInterface; class generate extends \phpbb\console\command\command { - /** @var \phpbb\db\driver\driver_interface */ + /** + * @var \phpbb\db\driver\driver_interface + */ protected $db; - /** @var \phpbb\user */ - protected $user; - - /** @var \phpbb\cache\service */ + /** + * @var \phpbb\cache\service + */ protected $cache; /** @@ -42,20 +43,20 @@ class generate extends \phpbb\console\command\command /** * Constructor * - * @param \phpbb\db\driver\driver_interface $db Database connection * @param \phpbb\user $user The user object (used to get language information) + * @param \phpbb\db\driver\driver_interface $db Database connection * @param \phpbb\cache\service $cache The cache service * @param string $phpbb_root_path Root path * @param string $php_ext PHP extension */ - public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\cache\service $cache, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $phpbb_root_path, $php_ext) { $this->db = $db; - $this->user = $user; $this->cache = $cache; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - parent::__construct(); + + parent::__construct($user); } /** diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php index dd10da9106..624e4e507f 100644 --- a/phpBB/phpbb/console/command/thumbnail/recreate.php +++ b/phpBB/phpbb/console/command/thumbnail/recreate.php @@ -18,20 +18,6 @@ use Symfony\Component\Console\Output\OutputInterface; class recreate extends \phpbb\console\command\command { - /** @var \phpbb\user */ - protected $user; - - /** - * Constructor - * - * @param \phpbb\user $user The user object (used to get language information) - */ - public function __construct(\phpbb\user $user) - { - $this->user = $user; - parent::__construct(); - } - /** * Sets the command name and description * diff --git a/tests/console/thumbnail_test.php b/tests/console/thumbnail_test.php index 7ac18d931a..11d2717f73 100644 --- a/tests/console/thumbnail_test.php +++ b/tests/console/thumbnail_test.php @@ -56,8 +56,8 @@ class phpbb_console_command_thumbnail_test extends phpbb_database_test_case ))); $this->application = new Application(); - $this->application->add(new generate($this->db, $this->user, $this->cache, $this->phpbb_root_path, $this->phpEx)); - $this->application->add(new delete($this->db, $this->user, $this->phpbb_root_path)); + $this->application->add(new generate($this->user, $this->db, $this->cache, $this->phpbb_root_path, $this->phpEx)); + $this->application->add(new delete($this->user, $this->db, $this->phpbb_root_path)); $this->application->add(new recreate($this->user)); } From a55c83b77168e77fd4d0101b8c58741f442b2d39 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 8 Aug 2014 15:22:05 +0200 Subject: [PATCH 0480/1676] [ticket/12692] Add a proper extension to the fixtures PHPBB3-12692 --- tests/console/fixtures/{png => png.png} | Bin tests/console/fixtures/{txt => txt.txt} | 0 tests/console/thumbnail_test.php | 10 ++++++---- 3 files changed, 6 insertions(+), 4 deletions(-) rename tests/console/fixtures/{png => png.png} (100%) rename tests/console/fixtures/{txt => txt.txt} (100%) diff --git a/tests/console/fixtures/png b/tests/console/fixtures/png.png similarity index 100% rename from tests/console/fixtures/png rename to tests/console/fixtures/png.png diff --git a/tests/console/fixtures/txt b/tests/console/fixtures/txt.txt similarity index 100% rename from tests/console/fixtures/txt rename to tests/console/fixtures/txt.txt diff --git a/tests/console/thumbnail_test.php b/tests/console/thumbnail_test.php index 11d2717f73..6af8e7e174 100644 --- a/tests/console/thumbnail_test.php +++ b/tests/console/thumbnail_test.php @@ -11,6 +11,8 @@ * */ +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + use Symfony\Component\Console\Application; use Symfony\Component\Console\Tester\CommandTester; use phpbb\console\command\thumbnail\generate; @@ -63,10 +65,10 @@ class phpbb_console_command_thumbnail_test extends phpbb_database_test_case public function test_thumbnails() { - copy(dirname(__FILE__) . '/fixtures/png', $this->phpbb_root_path . 'files/test_png_1'); - copy(dirname(__FILE__) . '/fixtures/png', $this->phpbb_root_path . 'files/test_png_2'); - copy(dirname(__FILE__) . '/fixtures/png', $this->phpbb_root_path . 'files/thumb_test_png_2'); - copy(dirname(__FILE__) . '/fixtures/txt', $this->phpbb_root_path . 'files/test_txt'); + copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/test_png_1'); + copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/test_png_2'); + copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/thumb_test_png_2'); + copy(dirname(__FILE__) . '/fixtures/txt.txt', $this->phpbb_root_path . 'files/test_txt'); $command_tester = $this->get_command_tester('thumbnail:generate'); $exit_status = $command_tester->execute(array('command' => 'thumbnail:generate')); From 24e39545ae77a78fb1f5350b4fe5658c924ad75c Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 18 Aug 2014 15:18:08 +0200 Subject: [PATCH 0481/1676] [ticket/12692] Add output PHPBB3-12692 --- phpBB/language/en/cli.php | 6 ++++ .../console/command/thumbnail/delete.php | 30 +++++++++++++++++++ .../console/command/thumbnail/generate.php | 30 +++++++++++++++++++ .../console/command/thumbnail/recreate.php | 3 ++ 4 files changed, 69 insertions(+) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index f0e5dd6120..7dd8403ed4 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -96,4 +96,10 @@ $lang = array_merge($lang, array( 'THUMBNAIL_DELETED' => '%1$s (%2$s) deleted.', 'THUMBNAIL_SKIPPED' => '%1$s (%2$s) skipped.', 'THUMBNAIL_GENERATED' => '%1$s (%2$s) generated.', + + 'THUMBNAIL_DELETING' => 'Deleting the thumbnails...', + 'THUMBNAIL_GENERATING' => 'Generating the thumbnails...', + + 'NO_THUMBNAIL_TO_GENERATE' => 'No thumbnail to generate.', + 'NO_THUMBNAIL_TO_DELETE' => 'No thumbnail to delete.', )); diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index b60ea5238f..b57fcc681f 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -68,11 +68,31 @@ class delete extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { + $sql = 'SELECT COUNT(*) AS nb_missing_thumbnails + FROM ' . ATTACHMENTS_TABLE . ' + WHERE thumbnail = 1'; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $nb_missing_thumbnails = (int) $row['nb_missing_thumbnails']; + if ($nb_missing_thumbnails === 0) + { + $output->writeln('' . $this->user->lang('NO_THUMBNAIL_TO_DELETE') . ''); + return 0; + } + $sql = 'SELECT attach_id, physical_filename, extension, real_filename, mimetype FROM ' . ATTACHMENTS_TABLE . ' WHERE thumbnail = 1'; $result = $this->db->sql_query($sql); + if (!$input->getOption('verbose')) + { + $progress = $this->getHelper('progress'); + $progress->start($output, $nb_missing_thumbnails); + } + $thumbnail_deleted = array(); $return = 0; while ($row = $this->db->sql_fetchrow($result)) @@ -102,6 +122,11 @@ class delete extends \phpbb\console\command\command $output->writeln('' . $this->user->lang('THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); } } + + if (!$input->getOption('verbose')) + { + $progress->advance(); + } } $this->db->sql_freeresult($result); @@ -110,6 +135,11 @@ class delete extends \phpbb\console\command\command $this->commit_changes($thumbnail_deleted); } + if (!$input->getOption('verbose')) + { + $progress->finish(); + } + return $return; } diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index 640d971b5d..068bd0ff94 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -84,6 +84,20 @@ class generate extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { + $sql = 'SELECT COUNT(*) AS nb_missing_thumbnails + FROM ' . ATTACHMENTS_TABLE . ' + WHERE thumbnail = 0'; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $nb_missing_thumbnails = (int) $row['nb_missing_thumbnails']; + if ($nb_missing_thumbnails === 0) + { + $output->writeln('' . $this->user->lang('NO_THUMBNAIL_TO_GENERATE') . ''); + return 0; + } + $extensions = $this->cache->obtain_attach_extensions(true); $sql = 'SELECT attach_id, physical_filename, extension, real_filename, mimetype @@ -96,6 +110,12 @@ class generate extends \phpbb\console\command\command require($this->phpbb_root_path . 'includes/functions_posting.' . $this->php_ext); } + if (!$input->getOption('verbose')) + { + $progress = $this->getHelper('progress'); + $progress->start($output, $nb_missing_thumbnails); + } + $thumbnail_created = array(); while ($row = $this->db->sql_fetchrow($result)) { @@ -127,6 +147,11 @@ class generate extends \phpbb\console\command\command } } } + + if (!$input->getOption('verbose')) + { + $progress->advance(); + } } $this->db->sql_freeresult($result); @@ -135,6 +160,11 @@ class generate extends \phpbb\console\command\command $this->commit_changes($thumbnail_created); } + if (!$input->getOption('verbose')) + { + $progress->finish(); + } + return 0; } diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php index 624e4e507f..ec093161af 100644 --- a/phpBB/phpbb/console/command/thumbnail/recreate.php +++ b/phpBB/phpbb/console/command/thumbnail/recreate.php @@ -54,6 +54,7 @@ class recreate extends \phpbb\console\command\command $this->getApplication()->setAutoExit(false); + $output->writeln('' . $this->user->lang('THUMBNAIL_DELETING') . ''); $input_delete = new ArrayInput($parameters); $return = $this->getApplication()->run($input_delete, $output); @@ -61,6 +62,8 @@ class recreate extends \phpbb\console\command\command { $parameters['command'] = 'thumbnail:generate'; + $output->writeln(''); + $output->writeln('' . $this->user->lang('THUMBNAIL_GENERATING') . ''); $input_create = new ArrayInput($parameters); $return = $this->getApplication()->run($input_create, $output); } From 0f789f4d5ac39f056569544eb1fad3545d80e9d3 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 18 Aug 2014 16:23:12 +0200 Subject: [PATCH 0482/1676] [ticket/12692] Fix languages files PHPBB3-12692 --- phpBB/language/en/acp/common.php | 8 +------- phpBB/phpbb/console/command/thumbnail/delete.php | 3 +-- phpBB/phpbb/console/command/thumbnail/generate.php | 3 +-- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index c2c3fda7a0..fdbc4aebd0 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -225,12 +225,6 @@ $lang = array_merge($lang, array( 'BACK' => 'Back', - 'CLI_DESCRIPTION_CRON_LIST' => 'Prints a list of ready and unready cron jobs.', - 'CLI_DESCRIPTION_CRON_RUN' => 'Runs all ready cron tasks.', - 'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1' => 'Name of the task to be run', - - 'CLI_DESCRIPTION_OPTION_SHELL' => 'Launch the shell.', - 'COLOUR_SWATCH' => 'Web-safe colour swatch', 'CONFIG_UPDATED' => 'Configuration updated successfully.', 'CRON_LOCK_ERROR' => 'Could not obtain cron lock.', @@ -308,7 +302,7 @@ $lang = array_merge($lang, array( 'SHOW_ALL_OPERATIONS' => 'Show all operations', - 'TASKS_NOT_READY' => 'Not ready tasks:', + 'TASKS_NOT_READY' => 'Not ready tasks:', 'TASKS_READY' => 'Ready tasks:', 'TOTAL_SIZE' => 'Total size', diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index b57fcc681f..3a60271fc2 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -72,10 +72,9 @@ class delete extends \phpbb\console\command\command FROM ' . ATTACHMENTS_TABLE . ' WHERE thumbnail = 1'; $result = $this->db->sql_query($sql); - $row = $this->db->sql_fetchrow($result); + $nb_missing_thumbnails = (int) $this->db->sql_fetchfield('nb_missing_thumbnails'); $this->db->sql_freeresult($result); - $nb_missing_thumbnails = (int) $row['nb_missing_thumbnails']; if ($nb_missing_thumbnails === 0) { $output->writeln('' . $this->user->lang('NO_THUMBNAIL_TO_DELETE') . ''); diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index 068bd0ff94..d7530881f1 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -88,10 +88,9 @@ class generate extends \phpbb\console\command\command FROM ' . ATTACHMENTS_TABLE . ' WHERE thumbnail = 0'; $result = $this->db->sql_query($sql); - $row = $this->db->sql_fetchrow($result); + $nb_missing_thumbnails = (int) $this->db->sql_fetchfield('nb_missing_thumbnails'); $this->db->sql_freeresult($result); - $nb_missing_thumbnails = (int) $row['nb_missing_thumbnails']; if ($nb_missing_thumbnails === 0) { $output->writeln('' . $this->user->lang('NO_THUMBNAIL_TO_GENERATE') . ''); From 556504df24a72d0cd5fbbd5b266f815f1353ab4c Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 18 Aug 2014 16:27:09 +0200 Subject: [PATCH 0483/1676] [ticket/12692] Fix tests PHPBB3-12692 --- tests/console/thumbnail_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/console/thumbnail_test.php b/tests/console/thumbnail_test.php index 6af8e7e174..094d8ca051 100644 --- a/tests/console/thumbnail_test.php +++ b/tests/console/thumbnail_test.php @@ -47,7 +47,7 @@ class phpbb_console_command_thumbnail_test extends phpbb_database_test_case )); $this->db = $this->db = $this->new_dbal(); - $this->user = $this->getMock('\phpbb\user'); + $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); $this->phpbb_root_path = $phpbb_root_path; $this->phpEx = $phpEx; From 96c5165a655062bb12cf8150262459d883911d8c Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 27 Aug 2014 16:22:10 +0200 Subject: [PATCH 0484/1676] [ticket/12692] Fix languages vars and services order PHPBB3-12692 --- .../default/container/services_console.yml | 18 +++++++++--------- phpBB/language/en/cli.php | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 010bde025d..0e6a1b7706 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -157,6 +157,15 @@ services: tags: - { name: console.command } + console.command.thumbnail.delete: + class: phpbb\console\command\thumbnail\delete + arguments: + - @user + - @dbal.conn + - %core.root_path% + tags: + - { name: console.command } + console.command.thumbnail.generate: class: phpbb\console\command\thumbnail\generate arguments: @@ -174,12 +183,3 @@ services: - @user tags: - { name: console.command } - - console.command.thumbnail.delete: - class: phpbb\console\command\thumbnail\delete - arguments: - - @user - - @dbal.conn - - %core.root_path% - tags: - - { name: console.command } diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 7dd8403ed4..28fae83d5f 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -97,9 +97,9 @@ $lang = array_merge($lang, array( 'THUMBNAIL_SKIPPED' => '%1$s (%2$s) skipped.', 'THUMBNAIL_GENERATED' => '%1$s (%2$s) generated.', - 'THUMBNAIL_DELETING' => 'Deleting the thumbnails...', - 'THUMBNAIL_GENERATING' => 'Generating the thumbnails...', + 'THUMBNAIL_DELETING' => 'Deleting thumbnails…', + 'THUMBNAIL_GENERATING' => 'Generating thumbnails…', - 'NO_THUMBNAIL_TO_GENERATE' => 'No thumbnail to generate.', - 'NO_THUMBNAIL_TO_DELETE' => 'No thumbnail to delete.', + 'NO_THUMBNAIL_TO_GENERATE' => 'No thumbnails to generate.', + 'NO_THUMBNAIL_TO_DELETE' => 'No thumbnails to delete.', )); From e3e293f5a6b38bb85f57841756a362e26b09088b Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 30 Aug 2014 18:17:23 +0200 Subject: [PATCH 0485/1676] [ticket/12692] Cleanup language file PHPBB3-12692 --- phpBB/language/en/cli.php | 15 +++++++-------- phpBB/phpbb/console/command/thumbnail/delete.php | 6 +++--- .../phpbb/console/command/thumbnail/generate.php | 6 +++--- .../phpbb/console/command/thumbnail/recreate.php | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 28fae83d5f..d494ef8c55 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -93,13 +93,12 @@ $lang = array_merge($lang, array( // In all the case %1$s is the logical name of the file and %2$s the real name on the filesystem // eg: big_image.png (2_a51529ae7932008cf8454a95af84cacd) generated. - 'THUMBNAIL_DELETED' => '%1$s (%2$s) deleted.', - 'THUMBNAIL_SKIPPED' => '%1$s (%2$s) skipped.', - 'THUMBNAIL_GENERATED' => '%1$s (%2$s) generated.', + 'CLI_THUMBNAIL_DELETED' => '%1$s (%2$s) deleted.', + 'CLI_THUMBNAIL_DELETING' => 'Deleting thumbnails…', + 'CLI_THUMBNAIL_SKIPPED' => '%1$s (%2$s) skipped.', + 'CLI_THUMBNAIL_GENERATED' => '%1$s (%2$s) generated.', + 'CLI_THUMBNAIL_GENERATING' => 'Generating thumbnails…', - 'THUMBNAIL_DELETING' => 'Deleting thumbnails…', - 'THUMBNAIL_GENERATING' => 'Generating thumbnails…', - - 'NO_THUMBNAIL_TO_GENERATE' => 'No thumbnails to generate.', - 'NO_THUMBNAIL_TO_DELETE' => 'No thumbnails to delete.', + 'CLI_THUMBNAIL_NOTHING_TO_GENERATE' => 'No thumbnails to generate.', + 'CLI_THUMBNAIL_NOTHING_TO_DELETE' => 'No thumbnails to delete.', )); diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index 3a60271fc2..fb63f7c510 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -77,7 +77,7 @@ class delete extends \phpbb\console\command\command if ($nb_missing_thumbnails === 0) { - $output->writeln('' . $this->user->lang('NO_THUMBNAIL_TO_DELETE') . ''); + $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_NOTHING_TO_DELETE') . ''); return 0; } @@ -110,7 +110,7 @@ class delete extends \phpbb\console\command\command if ($input->getOption('verbose')) { - $output->writeln($this->user->lang('THUMBNAIL_DELETED', $row['real_filename'], $row['physical_filename'])); + $output->writeln($this->user->lang('CLI_THUMBNAIL_DELETED', $row['real_filename'], $row['physical_filename'])); } } else @@ -118,7 +118,7 @@ class delete extends \phpbb\console\command\command if ($input->getOption('verbose')) { $return = 1; - $output->writeln('' . $this->user->lang('THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); + $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); } } diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index d7530881f1..0f4a40bd9f 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -93,7 +93,7 @@ class generate extends \phpbb\console\command\command if ($nb_missing_thumbnails === 0) { - $output->writeln('' . $this->user->lang('NO_THUMBNAIL_TO_GENERATE') . ''); + $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_NOTHING_TO_GENERATE') . ''); return 0; } @@ -135,14 +135,14 @@ class generate extends \phpbb\console\command\command if ($input->getOption('verbose')) { - $output->writeln($this->user->lang('THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename'])); + $output->writeln($this->user->lang('CLI_THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename'])); } } else { if ($input->getOption('verbose')) { - $output->writeln('' . $this->user->lang('THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); + $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); } } } diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php index ec093161af..5d3edbd699 100644 --- a/phpBB/phpbb/console/command/thumbnail/recreate.php +++ b/phpBB/phpbb/console/command/thumbnail/recreate.php @@ -54,7 +54,7 @@ class recreate extends \phpbb\console\command\command $this->getApplication()->setAutoExit(false); - $output->writeln('' . $this->user->lang('THUMBNAIL_DELETING') . ''); + $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_DELETING') . ''); $input_delete = new ArrayInput($parameters); $return = $this->getApplication()->run($input_delete, $output); @@ -63,7 +63,7 @@ class recreate extends \phpbb\console\command\command $parameters['command'] = 'thumbnail:generate'; $output->writeln(''); - $output->writeln('' . $this->user->lang('THUMBNAIL_GENERATING') . ''); + $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_GENERATING') . ''); $input_create = new ArrayInput($parameters); $return = $this->getApplication()->run($input_create, $output); } From 794726a464452a6056d8a2ba06c4394767d4c497 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 8 Jul 2015 18:08:50 +0200 Subject: [PATCH 0486/1676] [ticket/13740] Fix database test PHPBB3-13740 --- tests/installer/database_helper_test.php | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/installer/database_helper_test.php b/tests/installer/database_helper_test.php index 84445c86c5..d2ebe76ad5 100644 --- a/tests/installer/database_helper_test.php +++ b/tests/installer/database_helper_test.php @@ -18,11 +18,6 @@ class phpbb_installer_database_helper_test extends phpbb_test_case */ private $database_helper; - /** - * @var phpbb\db\driver\driver_interface - */ - private $dbms_mock; - public function setUp() { $filesystem = new \phpbb\filesystem\filesystem(); @@ -61,7 +56,7 @@ class phpbb_installer_database_helper_test extends phpbb_test_case */ public function test_validate_table_prefix($expected, $test_string) { - $this->assertEquals($expected, $this->database_helper->validate_table_prefix('oracle', $test_string)); + $this->assertEquals($expected, $this->database_helper->validate_table_prefix('sqlite3', $test_string)); } // Data provider for the remove comments function @@ -97,7 +92,7 @@ class phpbb_installer_database_helper_test extends phpbb_test_case 'SELECT * FROM table', ), 'abcd "efgh"' . "\n" . - 'qwerty' . "\n" . + 'qwerty;' . "\n" . 'SELECT * FROM table', ';', ), @@ -130,9 +125,16 @@ class phpbb_installer_database_helper_test extends phpbb_test_case ), array( array( - array('title' => 'INST_ERR_PREFIX_TOO_LONG'), + array('title' => array('INST_ERR_PREFIX_TOO_LONG', 200)), ), - 'php_bb_', + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + ), + array( + array( + array('title' => 'INST_ERR_DB_INVALID_PREFIX'), + array('title' => array('INST_ERR_PREFIX_TOO_LONG', 200)), + ), + '_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', ), ); } From 62103cec300ddadb904862ee2a74d68f71eb32ca Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 9 Jul 2015 15:26:48 +0200 Subject: [PATCH 0487/1676] [ticket/13740] Use service collection instead of array of task names PHPBB3-13740 --- .../container/services_install_data.yml | 17 +- .../container/services_install_database.yml | 18 ++- .../container/services_install_filesystem.yml | 13 +- .../container/services_install_finish.yml | 15 +- .../services_install_obtain_data.yml | 23 ++- .../services_install_requirements.yml | 15 +- .../container/services_installer.yml | 9 +- .../exception/module_not_found_exception.php | 42 ----- .../resource_limit_reached_exception.php | 19 +++ .../exception/task_not_found_exception.php | 42 ----- phpBB/phpbb/install/helper/config.php | 10 +- phpBB/phpbb/install/installer.php | 148 +++++++----------- phpBB/phpbb/install/module_base.php | 82 +++++----- tests/installer/installer_config_test.php | 10 +- 14 files changed, 221 insertions(+), 242 deletions(-) delete mode 100644 phpBB/phpbb/install/exception/module_not_found_exception.php create mode 100644 phpBB/phpbb/install/exception/resource_limit_reached_exception.php delete mode 100644 phpBB/phpbb/install/exception/task_not_found_exception.php diff --git a/phpBB/config/installer/container/services_install_data.yml b/phpBB/config/installer/container/services_install_data.yml index 5e01be2bce..40885b6ed9 100644 --- a/phpBB/config/installer/container/services_install_data.yml +++ b/phpBB/config/installer/container/services_install_data.yml @@ -8,6 +8,8 @@ services: - @language - %core.root_path% - %core.php_ext% + tags: + - { name: install_data_install, order: 2 } installer.install_data.add_languages: class: phpbb\install\module\install_data\task\add_languages @@ -15,15 +17,28 @@ services: - @installer.helper.iohandler - @installer.helper.container_factory - @language.helper.language_file + tags: + - { name: install_data_install, order: 1 } installer.install_data.add_modules: class: phpbb\install\module\install_data\task\add_modules arguments: - @installer.helper.iohandler - @installer.helper.container_factory + tags: + - { name: install_data_install, order: 3 } + + installer.module.data_install_collection: + class: phpbb\di\ordered_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: install_data_install } installer.module.data_install: class: phpbb\install\module\install_data\module parent: installer.module_base arguments: - - ["installer.install_data.add_languages", "installer.install_data.add_bots", "installer.install_data.add_modules"] + - @installer.module.data_install_collection + tags: + - { name: installer_install_module, order: 5 } diff --git a/phpBB/config/installer/container/services_install_database.yml b/phpBB/config/installer/container/services_install_database.yml index 061d3f6c42..efbfa82623 100644 --- a/phpBB/config/installer/container/services_install_database.yml +++ b/phpBB/config/installer/container/services_install_database.yml @@ -6,9 +6,10 @@ services: - @installer.helper.database - @filesystem - @installer.helper.iohandler - # - @installer.helper.container_factory - %core.root_path% - %core.php_ext% + tags: + - { name: install_database_install, order: 1 } installer.install_database.add_default_data: class: phpbb\install\module\install_database\task\add_default_data @@ -19,6 +20,8 @@ services: - @installer.helper.container_factory - @language - %core.root_path% + tags: + - { name: install_database_install, order: 2 } installer.install_database.add_config_settings: class: phpbb\install\module\install_database\task\add_config_settings @@ -29,9 +32,20 @@ services: - @installer.helper.container_factory - @language - %core.root_path% + tags: + - { name: install_database_install, order: 3 } + + installer.module.install_database_collection: + class: phpbb\di\ordered_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: install_database_install } installer.module.database_install: class: phpbb\install\module\install_database\module parent: installer.module_base arguments: - - ["installer.install_database.create_schema", "installer.install_database.add_default_data", "installer.install_database.add_config_settings"] + - @installer.module.install_database_collection + tags: + - { name: installer_install_module, order: 4 } diff --git a/phpBB/config/installer/container/services_install_filesystem.yml b/phpBB/config/installer/container/services_install_filesystem.yml index 077b1ccb98..71b2f697e0 100644 --- a/phpBB/config/installer/container/services_install_filesystem.yml +++ b/phpBB/config/installer/container/services_install_filesystem.yml @@ -8,9 +8,20 @@ services: - @installer.helper.iohandler - %core.root_path% - %core.php_ext% + tags: + - { name: install_filesystem_install, order: 1 } + + installer.module.install_filesystem_collection: + class: phpbb\di\ordered_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: install_filesystem_install } installer.module.filesystem_install: class: phpbb\install\module\install_filesystem\module parent: installer.module_base arguments: - - ["installer.install_filesystem.create_config_file"] + - @installer.module.install_filesystem_collection + tags: + - { name: installer_install_module, order: 3 } diff --git a/phpBB/config/installer/container/services_install_finish.yml b/phpBB/config/installer/container/services_install_finish.yml index d2002f9fd7..f70fefad84 100644 --- a/phpBB/config/installer/container/services_install_finish.yml +++ b/phpBB/config/installer/container/services_install_finish.yml @@ -3,6 +3,8 @@ services: class: phpbb\install\module\install_finish\task\populate_migrations arguments: - @installer.helper.container_factory + tags: + - { name: install_finish, order: 1 } installer.install_finish.notify_user: class: phpbb\install\module\install_finish\task\notify_user @@ -12,9 +14,20 @@ services: - @installer.helper.iohandler - %core.root_path% - %core.php_ext% + tags: + - { name: install_finish, order: 2 } + + installer.module.install_finish_collection: + class: phpbb\di\ordered_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: install_finish } installer.module.finish_install: class: phpbb\install\module\install_filesystem\module parent: installer.module_base arguments: - - ["installer.install_finish.populate_migrations", "installer.install_finish.notify_user"] + - @installer.module.install_finish_collection + tags: + - { name: installer_install_module, order: 6 } diff --git a/phpBB/config/installer/container/services_install_obtain_data.yml b/phpBB/config/installer/container/services_install_obtain_data.yml index ecbd3d6d37..b4077c2ecd 100644 --- a/phpBB/config/installer/container/services_install_obtain_data.yml +++ b/phpBB/config/installer/container/services_install_obtain_data.yml @@ -4,6 +4,8 @@ services: arguments: - @installer.helper.config - @installer.helper.iohandler + tags: + - { name: install_obtain_data, order: 1 } installer.obtain_data.obtain_board_data: class: phpbb\install\module\obtain_data\task\obtain_board_data @@ -11,6 +13,8 @@ services: - @installer.helper.config - @installer.helper.iohandler - @language.helper.language_file + tags: + - { name: install_obtain_data, order: 5 } installer.obtain_data.obtain_database_data: class: phpbb\install\module\obtain_data\task\obtain_database_data @@ -18,28 +22,45 @@ services: - @installer.helper.database - @installer.helper.config - @installer.helper.iohandler + tags: + - { name: install_obtain_data, order: 2 } installer.obtain_data.obtain_email_data: class: phpbb\install\module\obtain_data\task\obtain_email_data arguments: - @installer.helper.config - @installer.helper.iohandler + tags: + - { name: install_obtain_data, order: 4 } installer.obtain_data.obtain_imagick_path: class: phpbb\install\module\obtain_data\task\obtain_imagick_path arguments: - @installer.helper.config + tags: + - { name: install_obtain_data, order: 6 } installer.obtain_data.obtain_server_data: class: phpbb\install\module\obtain_data\task\obtain_server_data arguments: - @installer.helper.config - @installer.helper.iohandler + tags: + - { name: install_obtain_data, order: 3 } + + installer.module.install_obtain_data_collection: + class: phpbb\di\ordered_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: install_obtain_data } installer.module.obtain_data_install: class: phpbb\install\module\obtain_data\module parent: installer.module_base arguments: - - ["installer.obtain_data.obtain_admin_data", "installer.obtain_data.obtain_database_data", "installer.obtain_data.obtain_server_data", "installer.obtain_data.obtain_email_data", "installer.obtain_data.obtain_board_data", "installer.obtain_data.obtain_imagick_path"] + - @installer.module.install_obtain_data_collection - true - false + tags: + - { name: installer_install_module, order: 2 } diff --git a/phpBB/config/installer/container/services_install_requirements.yml b/phpBB/config/installer/container/services_install_requirements.yml index c93856837d..af640e0cff 100644 --- a/phpBB/config/installer/container/services_install_requirements.yml +++ b/phpBB/config/installer/container/services_install_requirements.yml @@ -6,18 +6,31 @@ services: - @installer.helper.iohandler - %core.root_path% - %core.php_ext% + tags: + - { name: installer_requirements, order: 1 } installer.requirements.check_server_environment: class: phpbb\install\module\requirements\task\check_server_environment arguments: - @installer.helper.database - @installer.helper.iohandler + tags: + - { name: installer_requirements, order: 2 } + + installer.module.install_requirements_collection: + class: phpbb\di\ordered_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: installer_requirements } # Please note, that the name of this module is hard coded in the installer service installer.module.requirements_install: class: phpbb\install\module\requirements\module parent: installer.module_base arguments: - - ["installer.requirements.check_filesystem", "installer.requirements.check_server_environment"] + - @installer.module.install_requirements_collection - true - false + tags: + - { name: installer_install_module, order: 1 } diff --git a/phpBB/config/installer/container/services_installer.yml b/phpBB/config/installer/container/services_installer.yml index 4c171f3fe7..4403a1ee51 100644 --- a/phpBB/config/installer/container/services_installer.yml +++ b/phpBB/config/installer/container/services_installer.yml @@ -69,7 +69,14 @@ services: - @installer.helper.config - @service_container + installer.install.module_collection: + class: phpbb\di\ordered_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: installer_install_module } + installer.installer.install: parent: installer.installer.abstract calls: - - [set_modules, [["installer.module.requirements_install", "installer.module.obtain_data_install", "installer.module.filesystem_install", "installer.module.database_install", "installer.module.data_install", "installer.module.finish_install"]]] + - [set_modules, [@installer.install.module_collection]] diff --git a/phpBB/phpbb/install/exception/module_not_found_exception.php b/phpBB/phpbb/install/exception/module_not_found_exception.php deleted file mode 100644 index 9fa03fad6e..0000000000 --- a/phpBB/phpbb/install/exception/module_not_found_exception.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @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\install\exception; - -class module_not_found_exception extends installer_exception -{ - /** - * @var string - */ - private $module_service_name; - - /** - * Constructor - * - * @param string $module_service_name The name of the missing installer module - */ - public function __construct($module_service_name) - { - $this->module_service_name = $module_service_name; - } - - /** - * Returns the missing installer module's service name - * - * @return string - */ - public function get_module_service_name() - { - return $this->module_service_name; - } -} diff --git a/phpBB/phpbb/install/exception/resource_limit_reached_exception.php b/phpBB/phpbb/install/exception/resource_limit_reached_exception.php new file mode 100644 index 0000000000..0b841747e6 --- /dev/null +++ b/phpBB/phpbb/install/exception/resource_limit_reached_exception.php @@ -0,0 +1,19 @@ + + * @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\install\exception; + +class resource_limit_reached_exception extends installer_exception +{ + +} diff --git a/phpBB/phpbb/install/exception/task_not_found_exception.php b/phpBB/phpbb/install/exception/task_not_found_exception.php deleted file mode 100644 index 11486cc6b0..0000000000 --- a/phpBB/phpbb/install/exception/task_not_found_exception.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @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\install\exception; - -class task_not_found_exception extends installer_exception -{ - /** - * @var string - */ - private $task_service_name; - - /** - * Constructor - * - * @param string $task_service_name The name of the missing installer module - */ - public function __construct($task_service_name) - { - $this->task_service_name = $task_service_name; - } - - /** - * Returns the missing installer task's service name - * - * @return string - */ - public function get_task_service_name() - { - return $this->task_service_name; - } -} diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php index cf51432332..38fdf960f7 100644 --- a/phpBB/phpbb/install/helper/config.php +++ b/phpBB/phpbb/install/helper/config.php @@ -87,9 +87,7 @@ class config $this->installer_config = array(); $this->system_data = array(); $this->progress_data = array( - 'last_task_module_index' => 0, 'last_task_module_name' => '', // Stores the service name of the latest finished module - 'last_task_index' => 0, 'last_task_name' => '', // Stores the service name of the latest finished task 'max_task_progress' => 0, 'current_task_progress' => 0, @@ -180,24 +178,20 @@ class config * Saves the latest executed task * * @param string $task_service_name Name of the installer task service - * @param int $task_index Index of the task in the task list array */ - public function set_finished_task($task_service_name, $task_index) + public function set_finished_task($task_service_name) { $this->progress_data['last_task_name'] = $task_service_name; - $this->progress_data['last_task_index'] = $task_index; } /** * Set active module * * @param string $module_service_name Name of the installer module service - * @param int $module_index Index of the module in the module list array */ - public function set_active_module($module_service_name, $module_index) + public function set_active_module($module_service_name) { $this->progress_data['last_task_module_name'] = $module_service_name; - $this->progress_data['last_task_module_index'] = $module_index; } /** diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index d64713e6a3..3e73d90453 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -13,10 +13,10 @@ namespace phpbb\install; +use phpbb\di\ordered_service_collection; use phpbb\install\exception\installer_config_not_writable_exception; use phpbb\install\exception\invalid_service_name_exception; -use phpbb\install\exception\module_not_found_exception; -use phpbb\install\exception\task_not_found_exception; +use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\exception\user_interaction_required_exception; use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; @@ -62,7 +62,7 @@ class installer { $this->install_config = $config; $this->container = $container; - $this->installer_modules = array(); + $this->installer_modules = null; } /** @@ -71,12 +71,10 @@ class installer * Note: The installer will run modules in the order they are set in * the array. * - * @param array $modules Array of module service names + * @param ordered_service_collection $modules Service collection of module service names */ - public function set_modules($modules) + public function set_modules(ordered_service_collection $modules) { - $modules = (array) $modules; - $this->installer_modules = $modules; } @@ -99,7 +97,8 @@ class installer $this->install_config->load_config(); // Recover install progress - $module_index = $this->recover_progress(); + $module_name = $this->recover_progress(); + $module_found = false; // Variable used to check if the install process have been finished $install_finished = false; @@ -111,64 +110,53 @@ class installer $this->install_config->set_finished_navigation_stage(array('install', 0, 'introduction')); $this->iohandler->set_finished_stage_menu(array('install', 0, 'introduction')); - try + if ($this->install_config->get_task_progress_count() === 0) { - if ($this->install_config->get_task_progress_count() === 0) + // Count all tasks in the current installer modules + $step_count = 0; + + /** @var \phpbb\install\module_interface $module */ + foreach ($this->installer_modules as $name => $module) { - // Count all tasks in the current installer modules - $step_count = 0; - foreach ($this->installer_modules as $index => $name) - { - try - { - /** @var \phpbb\install\module_interface $module */ - $module = $this->container->get($name); - } - catch (InvalidArgumentException $e) - { - throw new module_not_found_exception($name); - } - - $module_step_count = $module->get_step_count(); - $step_count += $module_step_count; - $this->module_step_count[$index] = $module_step_count; - } - - // Set task count - $this->install_config->set_task_progress_count($step_count); + $module_step_count = $module->get_step_count(); + $step_count += $module_step_count; + $this->module_step_count[$name] = $module_step_count; } - // Set up progress information - $this->iohandler->set_task_count( - $this->install_config->get_task_progress_count() - ); + // Set task count + $this->install_config->set_task_progress_count($step_count); + } - // Run until there are available resources - while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0) + // Set up progress information + $this->iohandler->set_task_count( + $this->install_config->get_task_progress_count() + ); + + try + { + foreach ($this->installer_modules as $name => $module) { - // Check if module exists, if not the install is completed - if (!isset($this->installer_modules[$module_index])) + // Skip forward until the current task is reached + if (!empty($task_name) && !$module_found) { - $install_finished = true; - break; + if ($module_name === $name) + { + $module_found = true; + } + else + { + continue; + } } // Log progress - $module_service_name = $this->installer_modules[$module_index]; - $this->install_config->set_active_module($module_service_name, $module_index); + $this->install_config->set_active_module($name); - // Get module from container - try + // Run until there are available resources + if ($this->install_config->get_time_remaining() <= 0 && $this->install_config->get_memory_remaining() <= 0) { - /** @var \phpbb\install\module_interface $module */ - $module = $this->container->get($module_service_name); + throw new resource_limit_reached_exception(); } - catch (InvalidArgumentException $e) - { - throw new module_not_found_exception($module_service_name); - } - - $module_index++; // Check if module should be executed if (!$module->is_essential() && !$module->check_requirements()) @@ -178,9 +166,9 @@ class installer $this->iohandler->add_log_message(array( 'SKIP_MODULE', - $module_service_name, + $name, )); - $this->install_config->increment_current_task_progress($this->module_step_count[$module_index - 1]); + $this->install_config->increment_current_task_progress($this->module_step_count[$name]); continue; } @@ -192,40 +180,18 @@ class installer $this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path()); $this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path()); - - // Clear task progress - $this->install_config->set_finished_task('', 0); } - if ($install_finished) - { - // Send install finished message - $this->iohandler->set_progress('INSTALLER_FINISHED', $this->install_config->get_task_progress_count()); - } - else - { - $this->iohandler->request_refresh(); - } + // Installation finished + $install_finished = true; } catch (user_interaction_required_exception $e) { // Do nothing } - catch (module_not_found_exception $e) + catch (resource_limit_reached_exception $e) { - $this->iohandler->add_error_message('MODULE_NOT_FOUND', array( - 'MODULE_NOT_FOUND_DESCRIPTION', - $e->get_module_service_name(), - )); - $flush_messages = true; - } - catch (task_not_found_exception $e) - { - $this->iohandler->add_error_message('TASK_NOT_FOUND', array( - 'TASK_NOT_FOUND_DESCRIPTION', - $e->get_task_service_name(), - )); - $flush_messages = true; + // Do nothing } catch (invalid_service_name_exception $e) { @@ -244,6 +210,16 @@ class installer $flush_messages = true; } + if ($install_finished) + { + // Send install finished message + $this->iohandler->set_progress('INSTALLER_FINISHED', $this->install_config->get_task_progress_count()); + } + else + { + $this->iohandler->request_refresh(); + } + if ($flush_messages) { $this->iohandler->send_response(); @@ -274,14 +250,6 @@ class installer protected function recover_progress() { $progress_array = $this->install_config->get_progress_data(); - $module_service = $progress_array['last_task_module_name']; - $module_index = $progress_array['last_task_module_index']; - - if ($this->installer_modules[$module_index] === $module_service) - { - return $module_index; - } - - return 0; + return $progress_array['last_task_module_name']; } } diff --git a/phpBB/phpbb/install/module_base.php b/phpBB/phpbb/install/module_base.php index 6c0c0e0c30..6099eb35f8 100644 --- a/phpBB/phpbb/install/module_base.php +++ b/phpBB/phpbb/install/module_base.php @@ -13,12 +13,13 @@ namespace phpbb\install; +use phpbb\di\ordered_service_collection; use phpbb\install\exception\invalid_service_name_exception; -use phpbb\install\exception\task_not_found_exception; +use phpbb\install\exception\resource_limit_reached_exception; +use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use phpbb\install\helper\config; /** * Base class for installer module @@ -48,7 +49,7 @@ abstract class module_base implements module_interface /** * Array of tasks for installer module * - * @var array + * @var ordered_service_collection */ protected $task_collection; @@ -60,11 +61,11 @@ abstract class module_base implements module_interface /** * Installer module constructor * - * @param array $tasks array of installer tasks for installer module - * @param bool $essential flag indicating whether the module is essential or not - * @param bool $allow_progress_bar flag indicating whether or not to send progress information from within the module + * @param ordered_service_collection $tasks array of installer tasks for installer module + * @param bool $essential flag indicating whether the module is essential or not + * @param bool $allow_progress_bar flag indicating whether or not to send progress information from within the module */ - public function __construct(array $tasks, $essential = true, $allow_progress_bar = true) + public function __construct(ordered_service_collection $tasks, $essential = true, $allow_progress_bar = true) { $this->task_collection = $tasks; $this->is_essential = $essential; @@ -109,26 +110,30 @@ abstract class module_base implements module_interface public function run() { // Recover install progress - $task_index = $this->recover_progress(); + $task_name = $this->recover_progress(); + $name_found = false; - // Run until there are available resources - while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0) + /** + * @var string $name ID of the service + * @var \phpbb\install\task_interface $task Task object + */ + foreach ($this->task_collection as $name => $task) { - // Check if task exists - if (!isset($this->task_collection[$task_index])) + // Run until there are available resources + if ($this->install_config->get_time_remaining() <= 0 && $this->install_config->get_memory_remaining() <= 0) { - break; + throw new resource_limit_reached_exception(); } - // Recover task to be executed - try + // Skip forward until the next task is reached + if (!empty($task_name) && !$name_found) { - /** @var \phpbb\install\task_interface $task */ - $task = $this->container->get($this->task_collection[$task_index]); - } - catch (InvalidArgumentException $e) - { - throw new task_not_found_exception($this->task_collection[$task_index]); + if ($name === $task_name) + { + $name_found = true; + } + + continue; } // Send progress information @@ -140,17 +145,15 @@ abstract class module_base implements module_interface ); } - // Iterate to the next task - $task_index++; - // Check if we can run the task if (!$task->is_essential() && !$task->check_requirements()) { $this->iohandler->add_log_message(array( 'SKIP_TASK', - $this->task_collection[$task_index], + $name, )); - $class_name = $this->get_class_from_service_name($this->task_collection[$task_index - 1]); + + $class_name = $this->get_class_from_service_name($name); $this->install_config->increment_current_task_progress($class_name::get_step_count()); continue; } @@ -174,9 +177,11 @@ abstract class module_base implements module_interface $this->iohandler->send_response(); // Log install progress - $current_task_index = $task_index - 1; - $this->install_config->set_finished_task($this->task_collection[$current_task_index], $current_task_index); + $this->install_config->set_finished_task($name); } + + // Module finished, so clear task progress + $this->install_config->set_finished_task(''); } /** @@ -187,24 +192,7 @@ abstract class module_base implements module_interface protected function recover_progress() { $progress_array = $this->install_config->get_progress_data(); - $last_finished_task_name = $progress_array['last_task_name']; - $last_finished_task_index = $progress_array['last_task_index']; - - // Check if the data is relevant to this module - if (isset($this->task_collection[$last_finished_task_index])) - { - if ($this->task_collection[$last_finished_task_index] === $last_finished_task_name) - { - // Return the task index of the next task - return $last_finished_task_index + 1; - } - } - - // As of now if the progress has not been resolved we assume that it is because - // the task progress belongs to the previous module, - // so just default to the first task - // @todo make module aware of it's service name that way this can be improved - return 0; + return $progress_array['last_task_name']; } /** @@ -214,11 +202,13 @@ abstract class module_base implements module_interface { $step_count = 0; + /** @todo: Fix this foreach ($this->task_collection as $task_service_name) { $class_name = $this->get_class_from_service_name($task_service_name); $step_count += $class_name::get_step_count(); } + */ return $step_count; } diff --git a/tests/installer/installer_config_test.php b/tests/installer/installer_config_test.php index 6c0079a1ec..4b83eb9a8f 100644 --- a/tests/installer/installer_config_test.php +++ b/tests/installer/installer_config_test.php @@ -63,8 +63,8 @@ class phpbb_installer_config_test extends phpbb_test_case */ public function test_progress_tracking() { - $this->config->set_finished_task('foo', 3); - $this->config->set_active_module('bar', 4); + $this->config->set_finished_task('foo'); + $this->config->set_active_module('bar'); $this->config->set_task_progress_count(10); $this->config->increment_current_task_progress(); @@ -74,10 +74,8 @@ class phpbb_installer_config_test extends phpbb_test_case $this->config->increment_current_task_progress(2); $this->assertEquals(array( - 'last_task_module_index' => 4, - 'last_task_module_name' => 'bar', // Stores the service name of the latest finished module - 'last_task_index' => 3, - 'last_task_name' => 'foo', // Stores the service name of the latest finished task + 'last_task_module_name' => 'bar', + 'last_task_name' => 'foo', 'max_task_progress' => 10, 'current_task_progress' => 3, ), From b284e31a9e55e5fc617a229439282cc6d746432a Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 9 Jul 2015 15:29:49 +0200 Subject: [PATCH 0488/1676] [ticket/13740] Add option to have class names in service collections PHPBB3-13740 --- phpBB/phpbb/di/service_collection.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/phpBB/phpbb/di/service_collection.php b/phpBB/phpbb/di/service_collection.php index 82ca9bf679..24f358ca84 100644 --- a/phpBB/phpbb/di/service_collection.php +++ b/phpBB/phpbb/di/service_collection.php @@ -25,6 +25,11 @@ class service_collection extends \ArrayObject */ protected $container; + /** + * @var array + */ + protected $service_classes; + /** * Constructor * @@ -33,6 +38,7 @@ class service_collection extends \ArrayObject public function __construct(ContainerInterface $container) { $this->container = $container; + $this->service_classes = array(); } /** @@ -76,4 +82,25 @@ class service_collection extends \ArrayObject { $this->offsetSet($name, null); } + + /** + * Add a service's class to the collection + * + * @param string $service_id + * @param string $class + */ + public function add_service_classes($service_id, $class) + { + $this->service_classes[$service_id] = $class; + } + + /** + * Get services' classes + * + * @return array + */ + public function get_service_classes() + { + return $this->service_classes; + } } From e967f3c1a81eab0f14daf314b7fb1b2001e4d220 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 9 Jul 2015 19:08:28 +0200 Subject: [PATCH 0489/1676] [ticket/13740] Fix itteration problems, implement class name aware collections PHPBB3-13740 --- .../container/services_install_data.yml | 2 +- .../container/services_install_database.yml | 2 +- .../container/services_install_filesystem.yml | 2 +- .../container/services_install_finish.yml | 2 +- .../services_install_obtain_data.yml | 2 +- .../services_install_requirements.yml | 2 +- phpBB/phpbb/di/pass/collection_pass.php | 13 ++- phpBB/phpbb/di/service_collection.php | 2 +- phpBB/phpbb/install/installer.php | 6 +- .../install/module/requirements/module.php | 55 ++++++++----- phpBB/phpbb/install/module_base.php | 79 ++++++++----------- phpBB/phpbb/install/task_interface.php | 4 - 12 files changed, 88 insertions(+), 83 deletions(-) diff --git a/phpBB/config/installer/container/services_install_data.yml b/phpBB/config/installer/container/services_install_data.yml index 40885b6ed9..c21f859406 100644 --- a/phpBB/config/installer/container/services_install_data.yml +++ b/phpBB/config/installer/container/services_install_data.yml @@ -33,7 +33,7 @@ services: arguments: - @service_container tags: - - { name: service_collection, tag: install_data_install } + - { name: service_collection, tag: install_data_install, class_name_aware: true } installer.module.data_install: class: phpbb\install\module\install_data\module diff --git a/phpBB/config/installer/container/services_install_database.yml b/phpBB/config/installer/container/services_install_database.yml index efbfa82623..f42fa65239 100644 --- a/phpBB/config/installer/container/services_install_database.yml +++ b/phpBB/config/installer/container/services_install_database.yml @@ -40,7 +40,7 @@ services: arguments: - @service_container tags: - - { name: service_collection, tag: install_database_install } + - { name: service_collection, tag: install_database_install, class_name_aware: true } installer.module.database_install: class: phpbb\install\module\install_database\module diff --git a/phpBB/config/installer/container/services_install_filesystem.yml b/phpBB/config/installer/container/services_install_filesystem.yml index 71b2f697e0..cbd8381d02 100644 --- a/phpBB/config/installer/container/services_install_filesystem.yml +++ b/phpBB/config/installer/container/services_install_filesystem.yml @@ -16,7 +16,7 @@ services: arguments: - @service_container tags: - - { name: service_collection, tag: install_filesystem_install } + - { name: service_collection, tag: install_filesystem_install, class_name_aware: true } installer.module.filesystem_install: class: phpbb\install\module\install_filesystem\module diff --git a/phpBB/config/installer/container/services_install_finish.yml b/phpBB/config/installer/container/services_install_finish.yml index f70fefad84..7f4c4d99bf 100644 --- a/phpBB/config/installer/container/services_install_finish.yml +++ b/phpBB/config/installer/container/services_install_finish.yml @@ -22,7 +22,7 @@ services: arguments: - @service_container tags: - - { name: service_collection, tag: install_finish } + - { name: service_collection, tag: install_finish, class_name_aware: true } installer.module.finish_install: class: phpbb\install\module\install_filesystem\module diff --git a/phpBB/config/installer/container/services_install_obtain_data.yml b/phpBB/config/installer/container/services_install_obtain_data.yml index b4077c2ecd..49c2b99f19 100644 --- a/phpBB/config/installer/container/services_install_obtain_data.yml +++ b/phpBB/config/installer/container/services_install_obtain_data.yml @@ -53,7 +53,7 @@ services: arguments: - @service_container tags: - - { name: service_collection, tag: install_obtain_data } + - { name: service_collection, tag: install_obtain_data, class_name_aware: true } installer.module.obtain_data_install: class: phpbb\install\module\obtain_data\module diff --git a/phpBB/config/installer/container/services_install_requirements.yml b/phpBB/config/installer/container/services_install_requirements.yml index af640e0cff..1a6ed634cf 100644 --- a/phpBB/config/installer/container/services_install_requirements.yml +++ b/phpBB/config/installer/container/services_install_requirements.yml @@ -22,7 +22,7 @@ services: arguments: - @service_container tags: - - { name: service_collection, tag: installer_requirements } + - { name: service_collection, tag: installer_requirements, class_name_aware: true } # Please note, that the name of this module is hard coded in the installer service installer.module.requirements_install: diff --git a/phpBB/phpbb/di/pass/collection_pass.php b/phpBB/phpbb/di/pass/collection_pass.php index ccc1250c20..341f88518d 100644 --- a/phpBB/phpbb/di/pass/collection_pass.php +++ b/phpBB/phpbb/di/pass/collection_pass.php @@ -34,10 +34,12 @@ class collection_pass implements CompilerPassInterface foreach ($container->findTaggedServiceIds('service_collection') as $id => $data) { $definition = $container->getDefinition($id); + $is_ordered_collection = (substr($definition->getClass(), -strlen('ordered_service_collection')) === 'ordered_service_collection'); + $is_class_name_aware = (isset($data[0]['class_name_aware']) && $data[0]['class_name_aware']); foreach ($container->findTaggedServiceIds($data[0]['tag']) as $service_id => $service_data) { - if (substr($definition->getClass(), -strlen('ordered_service_collection')) === 'ordered_service_collection') + if ($is_ordered_collection) { $arguments = array($service_id, $service_data[0]['order']); } @@ -46,6 +48,15 @@ class collection_pass implements CompilerPassInterface $arguments = array($service_id); } + if ($is_class_name_aware) + { + $service_definition = $container->getDefinition($service_id); + $definition->addMethodCall('add_service_class', array( + $service_id, + $service_definition->getClass() + )); + } + $definition->addMethodCall('add', $arguments); } } diff --git a/phpBB/phpbb/di/service_collection.php b/phpBB/phpbb/di/service_collection.php index 24f358ca84..8e9175e204 100644 --- a/phpBB/phpbb/di/service_collection.php +++ b/phpBB/phpbb/di/service_collection.php @@ -89,7 +89,7 @@ class service_collection extends \ArrayObject * @param string $service_id * @param string $class */ - public function add_service_classes($service_id, $class) + public function add_service_class($service_id, $class) { $this->service_classes[$service_id] = $class; } diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index 3e73d90453..c1ac2de7f9 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -137,9 +137,9 @@ class installer foreach ($this->installer_modules as $name => $module) { // Skip forward until the current task is reached - if (!empty($task_name) && !$module_found) + if (!$module_found) { - if ($module_name === $name) + if ($module_name === $name || empty($module_name)) { $module_found = true; } @@ -245,7 +245,7 @@ class installer /** * Recover install progress * - * @return int Index of the next installer module to execute + * @return string Index of the next installer module to execute */ protected function recover_progress() { diff --git a/phpBB/phpbb/install/module/requirements/module.php b/phpBB/phpbb/install/module/requirements/module.php index 208cb5aad6..794a35bef5 100644 --- a/phpBB/phpbb/install/module/requirements/module.php +++ b/phpBB/phpbb/install/module/requirements/module.php @@ -13,6 +13,7 @@ namespace phpbb\install\module\requirements; +use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\exception\user_interaction_required_exception; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; @@ -23,30 +24,38 @@ class module extends \phpbb\install\module_base $tests_passed = true; // Recover install progress - $task_index = 0; + $task_name = $this->recover_progress(); + $task_found = false; - // Run until there are available resources - while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0) + /** + * @var string $name ID of the service + * @var \phpbb\install\task_interface $task Task object + */ + foreach ($this->task_collection as $name => $task) { - // Check if task exists - if (!isset($this->task_collection[$task_index])) + // Run until there are available resources + if ($this->install_config->get_time_remaining() <= 0 && $this->install_config->get_memory_remaining() <= 0) { - break; + throw new resource_limit_reached_exception(); } - // Recover task to be executed - try + // Skip forward until the next task is reached + if (!$task_found) { - /** @var \phpbb\install\task_interface $task */ - $task = $this->container->get($this->task_collection[$task_index]); - } - catch (InvalidArgumentException $e) - { - throw new task_not_found_exception($this->task_collection[$task_index]); - } + if ($name === $task_name || empty($task_name)) + { + $task_found = true; - // Iterate to the next task - $task_index++; + if ($name === $task_name) + { + continue; + } + } + else + { + continue; + } + } // Check if we can run the task if (!$task->is_essential() && !$task->check_requirements()) @@ -54,10 +63,18 @@ class module extends \phpbb\install\module_base continue; } + if ($this->allow_progress_bar) + { + $this->install_config->increment_current_task_progress(); + } + $test_result = $task->run(); $tests_passed = ($tests_passed) ? $test_result : false; } + // Module finished, so clear task progress + $this->install_config->set_finished_task(''); + // Check if tests have failed if (!$tests_passed) { @@ -74,10 +91,6 @@ class module extends \phpbb\install\module_base $this->iohandler->send_response(); throw new user_interaction_required_exception(); } - - // Log install progress - $current_task_index = $task_index - 1; - $this->install_config->set_finished_task($this->task_collection[$current_task_index], $current_task_index); } /** diff --git a/phpBB/phpbb/install/module_base.php b/phpBB/phpbb/install/module_base.php index 6099eb35f8..e0cb862be9 100644 --- a/phpBB/phpbb/install/module_base.php +++ b/phpBB/phpbb/install/module_base.php @@ -14,7 +14,6 @@ namespace phpbb\install; use phpbb\di\ordered_service_collection; -use phpbb\install\exception\invalid_service_name_exception; use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; @@ -53,6 +52,11 @@ abstract class module_base implements module_interface */ protected $task_collection; + /** + * @var array + */ + protected $task_step_count; + /** * @var bool */ @@ -111,7 +115,7 @@ abstract class module_base implements module_interface { // Recover install progress $task_name = $this->recover_progress(); - $name_found = false; + $task_found = false; /** * @var string $name ID of the service @@ -126,14 +130,21 @@ abstract class module_base implements module_interface } // Skip forward until the next task is reached - if (!empty($task_name) && !$name_found) + if (!$task_found) { - if ($name === $task_name) + if ($name === $task_name || empty($task_name)) { - $name_found = true; - } + $task_found = true; - continue; + if ($name === $task_name) + { + continue; + } + } + else + { + continue; + } } // Send progress information @@ -153,18 +164,22 @@ abstract class module_base implements module_interface $name, )); - $class_name = $this->get_class_from_service_name($name); - $this->install_config->increment_current_task_progress($class_name::get_step_count()); + $this->install_config->increment_current_task_progress($this->task_step_count[$name]); continue; } if ($this->allow_progress_bar) { + // Only increment progress by one, as if a task has more than one steps + // then that should be incremented in the task itself $this->install_config->increment_current_task_progress(); } $task->run(); + // Log install progress + $this->install_config->set_finished_task($name); + // Send progress information if ($this->allow_progress_bar) { @@ -175,9 +190,6 @@ abstract class module_base implements module_interface } $this->iohandler->send_response(); - - // Log install progress - $this->install_config->set_finished_task($name); } // Module finished, so clear task progress @@ -187,7 +199,7 @@ abstract class module_base implements module_interface /** * Returns the next task's index * - * @return int index of the array element of the next task + * @return string index of the array element of the next task */ protected function recover_progress() { @@ -200,43 +212,16 @@ abstract class module_base implements module_interface */ public function get_step_count() { - $step_count = 0; + $task_step_count = 0; + $task_class_names = $this->task_collection->get_service_classes(); - /** @todo: Fix this - foreach ($this->task_collection as $task_service_name) + foreach ($task_class_names as $name => $task_class) { - $class_name = $this->get_class_from_service_name($task_service_name); - $step_count += $class_name::get_step_count(); - } - */ - - return $step_count; - } - - /** - * Returns the name of the class form the service name - * - * @param string $task_service_name Name of the service - * - * @return string Name of the class - * - * @throws invalid_service_name_exception When the service name does not meet the requirements described in task_interface - */ - protected function get_class_from_service_name($task_service_name) - { - $task_service_name_parts = explode('.', $task_service_name); - - if ($task_service_name_parts[0] !== 'installer') - { - throw new invalid_service_name_exception('TASK_SERVICE_INSTALLER_MISSING'); + $step_count = $task_class::get_step_count(); + $task_step_count += $step_count; + $this->task_step_count[$name] = $step_count; } - $class_name = '\\phpbb\\install\\module\\' . $task_service_name_parts[1] . '\\task\\' . $task_service_name_parts[2]; - if (!class_exists($class_name)) - { - throw new invalid_service_name_exception('TASK_CLASS_NOT_FOUND', array($task_service_name, $class_name)); - } - - return $class_name; + return $task_step_count; } } diff --git a/phpBB/phpbb/install/task_interface.php b/phpBB/phpbb/install/task_interface.php index 14cde23a56..794cb16482 100644 --- a/phpBB/phpbb/install/task_interface.php +++ b/phpBB/phpbb/install/task_interface.php @@ -15,10 +15,6 @@ namespace phpbb\install; /** * Interface for installer tasks - * - * Note: The task service ID must match up with the namespace and class name. - * For example: if your task is located at \phpbb\install\module\module_name\task\task_name - * then the service ID must be installer.module_name.task_name. */ interface task_interface { From 3309c89b05a46a03d09ffef693ed309699a3f59b Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 9 Jul 2015 19:32:30 +0200 Subject: [PATCH 0490/1676] [ticket/13740] Fix CS PHPBB3-13740 --- phpBB/phpbb/install/installer.php | 1 - phpBB/phpbb/install/module/requirements/module.php | 1 - phpBB/phpbb/install/module_base.php | 1 - 3 files changed, 3 deletions(-) diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index c1ac2de7f9..33b9214cfa 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -21,7 +21,6 @@ use phpbb\install\exception\user_interaction_required_exception; use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; class installer { diff --git a/phpBB/phpbb/install/module/requirements/module.php b/phpBB/phpbb/install/module/requirements/module.php index 794a35bef5..79a031bad9 100644 --- a/phpBB/phpbb/install/module/requirements/module.php +++ b/phpBB/phpbb/install/module/requirements/module.php @@ -15,7 +15,6 @@ namespace phpbb\install\module\requirements; use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\exception\user_interaction_required_exception; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; class module extends \phpbb\install\module_base { diff --git a/phpBB/phpbb/install/module_base.php b/phpBB/phpbb/install/module_base.php index e0cb862be9..eb04379f8e 100644 --- a/phpBB/phpbb/install/module_base.php +++ b/phpBB/phpbb/install/module_base.php @@ -18,7 +18,6 @@ use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * Base class for installer module From 4d2212a3c2c8528e6d2adde6c57090bf8e26ba7d Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 9 Jul 2015 21:52:36 +0200 Subject: [PATCH 0491/1676] [ticket/13740] Fix database version comparison PHPBB3-13740 --- phpBB/phpbb/install/helper/database.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/install/helper/database.php b/phpBB/phpbb/install/helper/database.php index d8751582f7..27cb2dc828 100644 --- a/phpBB/phpbb/install/helper/database.php +++ b/phpBB/phpbb/install/helper/database.php @@ -395,7 +395,7 @@ class database switch ($dbms) { case 'mysqli': - if (version_compare($db->sql_server_info(), '4.1.3', '<')) + if (version_compare($db->sql_server_info(true), '4.1.3', '<')) { $errors[] = array( 'title' => 'INST_ERR_DB_NO_MYSQLI', @@ -403,7 +403,7 @@ class database } break; case 'sqlite': - if (version_compare($db->sql_server_info(), '2.8.2', '<')) + if (version_compare($db->sql_server_info(true), '2.8.2', '<')) { $errors[] = array( 'title' => 'INST_ERR_DB_NO_SQLITE', @@ -411,7 +411,7 @@ class database } break; case 'sqlite3': - if (version_compare($db->sql_server_info(), '3.6.15', '<')) + if (version_compare($db->sql_server_info(true), '3.6.15', '<')) { $errors[] = array( 'title' => 'INST_ERR_DB_NO_SQLITE3', From e46689a0cdbb418673741234f55e843f1bdd8016 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 9 Jul 2015 23:23:40 +0200 Subject: [PATCH 0492/1676] [ticket/13740] Remove service container from modules PHPBB3-13740 --- phpBB/config/installer/container/services_installer.yml | 3 +-- phpBB/phpbb/install/installer.php | 4 +--- phpBB/phpbb/install/module_base.php | 9 +++------ 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/phpBB/config/installer/container/services_installer.yml b/phpBB/config/installer/container/services_installer.yml index 4403a1ee51..8e19be5c0c 100644 --- a/phpBB/config/installer/container/services_installer.yml +++ b/phpBB/config/installer/container/services_installer.yml @@ -60,14 +60,13 @@ services: installer.module_base: abstract: true calls: - - [setup, [@service_container, @installer.helper.config, @installer.helper.iohandler]] + - [setup, [@installer.helper.config, @installer.helper.iohandler]] installer.installer.abstract: class: phpbb\install\installer abstract: true arguments: - @installer.helper.config - - @service_container installer.install.module_collection: class: phpbb\di\ordered_service_collection diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index 33b9214cfa..f69b48ce3b 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -55,12 +55,10 @@ class installer * Constructor * * @param config $config Installer config handler - * @param ContainerInterface $container Dependency injection container */ - public function __construct(config $config, ContainerInterface $container) + public function __construct(config $config) { $this->install_config = $config; - $this->container = $container; $this->installer_modules = null; } diff --git a/phpBB/phpbb/install/module_base.php b/phpBB/phpbb/install/module_base.php index eb04379f8e..60eaa79139 100644 --- a/phpBB/phpbb/install/module_base.php +++ b/phpBB/phpbb/install/module_base.php @@ -17,7 +17,6 @@ use phpbb\di\ordered_service_collection; use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Base class for installer module @@ -78,13 +77,11 @@ abstract class module_base implements module_interface /** * Dependency getter * - * @param ContainerInterface $container * @param config $config * @param iohandler_interface $iohandler */ - public function setup(ContainerInterface $container, config $config, iohandler_interface $iohandler) + public function setup(config $config, iohandler_interface $iohandler) { - $this->container = $container; $this->install_config = $config; $this->iohandler = $iohandler; } @@ -196,9 +193,9 @@ abstract class module_base implements module_interface } /** - * Returns the next task's index + * Returns the next task's name * - * @return string index of the array element of the next task + * @return string Index of the array element of the next task */ protected function recover_progress() { From 59d22eff497ea1107851067aa99eed4c979c0766 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 10 Jul 2015 00:47:28 +0200 Subject: [PATCH 0493/1676] [ticket/13740] Fix CS PHPBB3-13740 --- phpBB/phpbb/install/installer.php | 6 ------ phpBB/phpbb/install/module_base.php | 5 ----- 2 files changed, 11 deletions(-) diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index f69b48ce3b..548615cb1d 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -20,15 +20,9 @@ use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\exception\user_interaction_required_exception; use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; -use Symfony\Component\DependencyInjection\ContainerInterface; class installer { - /** - * @var ContainerInterface - */ - protected $container; - /** * @var config */ diff --git a/phpBB/phpbb/install/module_base.php b/phpBB/phpbb/install/module_base.php index 60eaa79139..a933d4987c 100644 --- a/phpBB/phpbb/install/module_base.php +++ b/phpBB/phpbb/install/module_base.php @@ -23,11 +23,6 @@ use phpbb\install\helper\iohandler\iohandler_interface; */ abstract class module_base implements module_interface { - /** - * @var ContainerInterface - */ - protected $container; - /** * @var config */ From 051b7d1867351df293d055b62e0eb051758f90da Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 10 Jul 2015 14:54:21 +0200 Subject: [PATCH 0494/1676] [ticket/13740] Module base test PHPBB3-13740 --- .../installer/mocks/test_installer_module.php | 20 ++++++ .../mocks/test_installer_task_mock.php | 44 +++++++++++++ tests/installer/module_base_test.php | 65 +++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 tests/installer/mocks/test_installer_module.php create mode 100644 tests/installer/mocks/test_installer_task_mock.php create mode 100644 tests/installer/module_base_test.php diff --git a/tests/installer/mocks/test_installer_module.php b/tests/installer/mocks/test_installer_module.php new file mode 100644 index 0000000000..e6ebbba263 --- /dev/null +++ b/tests/installer/mocks/test_installer_module.php @@ -0,0 +1,20 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class test_installer_module extends \phpbb\install\module_base +{ + public function get_navigation_stage_path() + { + return array(); + } +} diff --git a/tests/installer/mocks/test_installer_task_mock.php b/tests/installer/mocks/test_installer_task_mock.php new file mode 100644 index 0000000000..ccd62b3bf4 --- /dev/null +++ b/tests/installer/mocks/test_installer_task_mock.php @@ -0,0 +1,44 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class test_installer_task_mock extends \phpbb\install\task_base +{ + private $task_was_runned; + + public function __construct() + { + $this->task_was_runned = false; + + parent::__construct(); + } + + public function run() + { + $this->task_was_runned = true; + } + + public function was_task_runned() + { + return $this->task_was_runned; + } + + public function get_task_lang_name() + { + return ''; + } + + public static function get_step_count() + { + return 2; + } +} diff --git a/tests/installer/module_base_test.php b/tests/installer/module_base_test.php new file mode 100644 index 0000000000..fd92c9b674 --- /dev/null +++ b/tests/installer/module_base_test.php @@ -0,0 +1,65 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +require_once __DIR__ . '/mocks/test_installer_task_mock.php'; +require_once __DIR__ . '/mocks/test_installer_module.php'; + +class module_base_test extends phpbb_test_case +{ + /** + * @var \phpbb\install\module_interface + */ + protected $module; + + /** + * @var phpbb_mock_container_builder + */ + protected $container; + + public function setUp() + { + // DI container mock + $this->container = new phpbb_mock_container_builder(); + $this->container->set('task_one', new test_installer_task_mock()); + $this->container->set('task_two', new test_installer_task_mock()); + + // the collection + $module_collection = new \phpbb\di\ordered_service_collection($this->container); + $module_collection->add('task_one'); + $module_collection->add('task_two'); + $module_collection->add_service_class('task_one', 'test_installer_task_mock'); + $module_collection->add_service_class('task_two', 'test_installer_task_mock'); + + $this->module = new test_installer_module($module_collection, true, false); + + $iohandler = $this->getMock('\phpbb\install\helper\iohandler\iohandler_interface'); + $config = new \phpbb\install\helper\config(new \phpbb\filesystem\filesystem(), new \phpbb\php\ini(), '', 'php'); + $this->module->setup($config, $iohandler); + } + + public function test_run() + { + $this->module->run(); + + $task = $this->container->get('task_one'); + $this->assertTrue($task->was_task_runned()); + + $task = $this->container->get('task_two'); + $this->assertTrue($task->was_task_runned()); + } + + public function test_step_count() + { + $this->assertEquals(4, $this->module->get_step_count()); + } +} From ca671708cb3ed4fbf218373f5ac310cf955676a4 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 12 Jul 2015 18:55:23 +0200 Subject: [PATCH 0495/1676] [ticket/14000] Added support for emoji PHPBB3-14000 --- phpBB/composer.lock | 9 +++++---- phpBB/phpbb/textformatter/s9e/factory.php | 5 +++++ .../s9e/default_formatting_test.php | 19 ++++++++++++++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index cff4bd6289..74e554f2f0 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -220,12 +220,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "326a5a0bbaee59a3d5542fc8e38fe41971931cce" + "reference": "beee0e5693f7ca8ed16a94294acf53b6e6207e7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/326a5a0bbaee59a3d5542fc8e38fe41971931cce", - "reference": "326a5a0bbaee59a3d5542fc8e38fe41971931cce", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/beee0e5693f7ca8ed16a94294acf53b6e6207e7c", + "reference": "beee0e5693f7ca8ed16a94294acf53b6e6207e7c", "shasum": "" }, "require": { @@ -253,6 +253,7 @@ "MIT" ], "description": "Multi-purpose text formatting and markup library. Plugins offer support for BBCodes, Markdown, emoticons, HTML, embedding media (YouTube, etc...), enhanced typography and more.", + "homepage": "https://github.com/s9e/TextFormatter/", "keywords": [ "bbcode", "bbcodes", @@ -270,7 +271,7 @@ "parser", "shortcodes" ], - "time": "2015-07-05 23:13:46" + "time": "2015-07-12 16:53:32" }, { "name": "symfony/config", diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 2f6498197f..2aab97b667 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -324,6 +324,11 @@ class factory implements \phpbb\textformatter\cache_interface $configurator->registeredVars['max_img_height'] = 0; $configurator->registeredVars['max_img_width'] = 0; + // Load the Emoji plugin and modify its tag's template to obey viewsmilies + $configurator->Emoji->setImageSize(18); + $tag = $configurator->Emoji->getTag(); + $tag->template = '' . str_replace('class="emoji"', 'class="smilies"', $tag->template) . ''; + /** * Modify the s9e\TextFormatter configurator after the default settings are set * diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index c67976301f..390bc65264 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -29,7 +29,7 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case /** * @dataProvider get_default_formatting_tests */ - public function test_default_formatting($original, $expected) + public function test_default_formatting($original, $expected, $setup = null) { $fixture = __DIR__ . '/fixtures/default_formatting.xml'; $container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture); @@ -37,6 +37,11 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case $parser = $container->get('text_formatter.parser'); $renderer = $container->get('text_formatter.renderer'); + if (isset($setup)) + { + call_user_func($setup, $container); + } + $parsed_text = $parser->parse($original); $this->assertSame($expected, $renderer->render($parsed_text)); @@ -263,6 +268,18 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case '[quote=\'[quote="foo"]\']...[/quote]', '
            [quote="foo"] wrote:...
            ' ), + array( + "Emoji: \xF0\x9F\x98\x80", + 'Emoji: ' . ' + ), + array( + "Emoji: \xF0\x9F\x98\x80", + "Emoji: \xF0\x9F\x98\x80", + function ($container) + { + $container->get('text_formatter.renderer')->set_viewsmilies(false); + } + ), ); } } From 0d52d36b37e0434824e93af592bbe0ce3c994da6 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 13 Jul 2015 10:31:07 +0200 Subject: [PATCH 0496/1676] [ticket/14000] Replaced test content with non-emoji characters PHPBB3-14000 --- tests/functional/posting_test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index e9b62c0b6c..724c42b289 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -57,9 +57,9 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $this->login(); $post = $this->create_topic(2, 'Test Topic 1', 'This is a test topic posted by the testing framework.'); - $this->create_post(2, $post['topic_id'], 'Re: Test Topic 1', "This is a test with these weird characters: \xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6"); + $this->create_post(2, $post['topic_id'], 'Re: Test Topic 1', "This is a test with these weird characters: \xF0\x9F\x84\x90 \xF0\x9F\x84\x91"); $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); - $this->assertContains("\xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6", $crawler->text()); + $this->assertContains("\xF0\x9F\x84\x90 \xF0\x9F\x84\x91", $crawler->text()); } public function test_html_entities() From 675cf5e897944318f9666b088a5053f339fe1032 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 13 Jul 2015 16:08:57 +0200 Subject: [PATCH 0497/1676] [ticket/14008] Do not add a user_id value to quotes from guests PHPBB3-14008 --- phpBB/phpbb/textformatter/s9e/utils.php | 6 ++++++ tests/text_formatter/s9e/utils_test.php | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index 40479b3423..b317fe4a8d 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -70,6 +70,12 @@ class utils implements \phpbb\textformatter\utils_interface $quote .= '=' . $this->format_attribute_value($attributes['author']); unset($attributes['author']); } + + if (isset($attributes['user_id']) && $attributes['user_id'] == ANONYMOUS) + { + unset($attributes['user_id']); + } + ksort($attributes); foreach ($attributes as $name => $value) { diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php index 1c03783792..dade259790 100644 --- a/tests/text_formatter/s9e/utils_test.php +++ b/tests/text_formatter/s9e/utils_test.php @@ -175,6 +175,15 @@ class phpbb_textformatter_s9e_utils_test extends phpbb_test_case ), '[quote=user post_id=123 url=http://example.org]...[/quote]', ), + array( + '...', + array( + 'author' => 'user', + 'post_id' => 123, + 'user_id' => ANONYMOUS + ), + '[quote=user post_id=123]...[/quote]', + ), array( '...', array('author' => ' '), From be0d4e20d4be8bc3217e5d025058e065b8f2071a Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Mon, 28 Apr 2014 14:00:27 +0200 Subject: [PATCH 0498/1676] [ticket/11444] Moving the in-board notifications to a method class Currently the in-board method for the notifications is hardcoded and cannot be disabled. This method should be in his own class extending `phpbb\notification\method\method_interface`. It also add the possibility, for each method, to be enabled by default (ie: no entry in the DB => notification enabled). https://tracker.phpbb.com/browse/PHPBB3-11444 https://tracker.phpbb.com/browse/PHPBB3-11967 PHPBB3-11444 --- .../container/services_notification.yml | 38 +- phpBB/includes/acp/acp_board.php | 1 + phpBB/includes/functions.php | 16 +- phpBB/includes/functions_privmsgs.php | 2 +- phpBB/includes/mcp/mcp_pm_reports.php | 2 +- phpBB/includes/mcp/mcp_queue.php | 10 +- phpBB/includes/mcp/mcp_reports.php | 2 +- phpBB/includes/ucp/info/ucp_notifications.php | 2 +- phpBB/includes/ucp/ucp_notifications.php | 19 +- phpBB/index.php | 2 +- phpBB/install/schemas/schema_data.sql | 5 +- phpBB/language/en/acp/board.php | 1 + phpBB/language/en/common.php | 1 + phpBB/language/en/ucp.php | 1 + .../data/v310/notifications_board.php | 73 +++ phpBB/phpbb/notification/manager.php | 463 ++++++++---------- phpBB/phpbb/notification/method/base.php | 79 +++ phpBB/phpbb/notification/method/board.php | 390 +++++++++++++++ .../notification/method/method_interface.php | 104 ++++ .../notification/type/admin_activate_user.php | 2 +- .../phpbb/notification/type/approve_post.php | 23 +- .../phpbb/notification/type/approve_topic.php | 24 +- phpBB/phpbb/notification/type/base.php | 50 +- phpBB/phpbb/notification/type/bookmark.php | 33 +- .../notification/type/disapprove_post.php | 21 +- .../notification/type/disapprove_topic.php | 21 +- .../phpbb/notification/type/group_request.php | 2 +- .../type/group_request_approved.php | 4 +- phpBB/phpbb/notification/type/pm.php | 10 +- phpBB/phpbb/notification/type/post.php | 43 +- .../phpbb/notification/type/post_in_queue.php | 21 +- phpBB/phpbb/notification/type/quote.php | 24 +- phpBB/phpbb/notification/type/report_pm.php | 10 +- .../notification/type/report_pm_closed.php | 23 +- phpBB/phpbb/notification/type/report_post.php | 10 +- .../notification/type/report_post_closed.php | 23 +- phpBB/phpbb/notification/type/topic.php | 10 +- .../notification/type/topic_in_queue.php | 21 +- .../notification/type/type_interface.php | 8 +- .../prosilver/template/ucp_notifications.html | 2 - tests/functional/notification_test.php | 8 +- tests/mock/container_builder.php | 10 +- tests/mock/notification_manager.php | 7 +- tests/mock/notification_type_post.php | 5 +- tests/notification/base.php | 33 +- .../ext/test/notification/type/test.php | 5 +- ...submit_post_notification.type.bookmark.xml | 10 +- .../submit_post_notification.type.post.xml | 14 +- ...t_post_notification.type.post_in_queue.xml | 14 +- .../submit_post_notification.type.quote.xml | 10 +- .../submit_post_notification.type.topic.xml | 8 +- tests/notification/manager_helper.php | 7 +- tests/notification/notification_test.php | 48 +- tests/notification/submit_post_base.php | 61 ++- tests/notification/user_list_trim_test.php | 2 +- 55 files changed, 1229 insertions(+), 609 deletions(-) create mode 100644 phpBB/phpbb/db/migration/data/v310/notifications_board.php create mode 100644 phpBB/phpbb/notification/method/board.php diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index c3bbcddfa6..7c335eaba0 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -14,7 +14,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% # ----- Notification's types ----- @@ -39,7 +38,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -57,7 +55,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -75,7 +72,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -93,7 +89,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -111,7 +106,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -129,7 +123,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -147,7 +140,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -165,7 +157,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -183,7 +174,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -201,7 +191,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -219,7 +208,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% calls: - [set_utils, [@text_formatter.utils]] @@ -239,7 +227,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -257,7 +244,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -275,7 +261,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -293,7 +278,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -311,7 +295,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -329,7 +312,6 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } @@ -347,11 +329,10 @@ services: - %core.root_path% - %core.php_ext% - %tables.notification_types% - - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type } - + # ----- Notification's methods ----- # Scope MUST be prototype for all the plugins to work. notification.method_collection: @@ -361,6 +342,23 @@ services: tags: - { name: service_collection, tag: notification.method } + notification.method.board: + class: phpbb\notification\method\board + scope: prototype # scope MUST be prototype for this to work! + arguments: + - @user_loader + - @dbal.conn + - @cache.driver + - @user + - @auth + - @config + - %core.root_path% + - %core.php_ext% + - %tables.notification_types% + - %tables.notifications% + tags: + - { name: notification.method } + notification.method.email: class: phpbb\notification\method\email scope: prototype diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 018eedda2a..6e636d2f7d 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -94,6 +94,7 @@ class acp_board 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_board_notifications' => array('lang' => 'ALLOW_BOARD_NOTIFICATIONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_birthdays' => array('lang' => 'ALLOW_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index d109fe0648..a987213337 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -624,7 +624,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $phpbb_notifications = $phpbb_container->get('notification_manager'); // Mark all topic notifications read for this user - $phpbb_notifications->mark_notifications_read(array( + $phpbb_notifications->mark_notifications(array( 'notification.type.topic', 'notification.type.quote', 'notification.type.bookmark', @@ -694,7 +694,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->mark_notifications_read_by_parent(array( + $phpbb_notifications->mark_notifications_by_parent(array( 'notification.type.topic', 'notification.type.approve_topic', ), $forum_id, $user->data['user_id'], $post_time); @@ -711,7 +711,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ } $db->sql_freeresult($result); - $phpbb_notifications->mark_notifications_read_by_parent(array( + $phpbb_notifications->mark_notifications_by_parent(array( 'notification.type.quote', 'notification.type.bookmark', 'notification.type.post', @@ -818,12 +818,12 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $phpbb_notifications = $phpbb_container->get('notification_manager'); // Mark post notifications read for this user in this topic - $phpbb_notifications->mark_notifications_read(array( + $phpbb_notifications->mark_notifications(array( 'notification.type.topic', 'notification.type.approve_topic', ), $topic_id, $user->data['user_id'], $post_time); - $phpbb_notifications->mark_notifications_read_by_parent(array( + $phpbb_notifications->mark_notifications_by_parent(array( 'notification.type.quote', 'notification.type.bookmark', 'notification.type.post', @@ -4254,12 +4254,12 @@ function page_header($page_title = '', $display_online_list = false, $item_id = // Output the notifications $notifications = false; - if ($config['load_notifications'] && $user->data['user_id'] != ANONYMOUS && $user->data['user_type'] != USER_IGNORE) + if ($config['load_notifications'] && $config['allow_board_notifications'] && $user->data['user_id'] != ANONYMOUS && $user->data['user_type'] != USER_IGNORE) { /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $notifications = $phpbb_notifications->load_notifications(array( + $notifications = $phpbb_notifications->load_notifications('notification.method.board', array( 'all_unread' => true, 'limit' => 5, )); @@ -4296,7 +4296,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = 'U_VIEW_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications'), 'U_MARK_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications&mode=notification_list&mark=all&token=' . $notification_mark_hash), 'U_NOTIFICATION_SETTINGS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications&mode=notification_options'), - 'S_NOTIFICATIONS_DISPLAY' => $config['load_notifications'], + 'S_NOTIFICATIONS_DISPLAY' => $config['load_notifications'] && $config['allow_board_notifications'], 'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'], 'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'], diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 26df5b9954..c8c2670986 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -884,7 +884,7 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id) /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->mark_notifications_read('notification.type.pm', $msg_id, $user_id); + $phpbb_notifications->mark_notifications('notification.type.pm', $msg_id, $user_id); $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " SET pm_unread = 0 diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php index cc8e48dc91..6e1d594135 100644 --- a/phpBB/includes/mcp/mcp_pm_reports.php +++ b/phpBB/includes/mcp/mcp_pm_reports.php @@ -97,7 +97,7 @@ class mcp_pm_reports /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->mark_notifications_read_by_parent('notification.type.report_pm', $report_id, $user->data['user_id']); + $phpbb_notifications->mark_notifications_by_parent('report_pm', $report_id, $user->data['user_id']); $pm_id = $report['pm_id']; $report_id = $report['report_id']; diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index 596364cefd..3488ea326d 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -166,7 +166,7 @@ class mcp_queue { $post_id = (int) $topic_info[$topic_id]['topic_first_post_id']; - $phpbb_notifications->mark_notifications_read('notification.type.topic_in_queue', $topic_id, $user->data['user_id']); + $phpbb_notifications->mark_notifications('topic_in_queue', $topic_id, $user->data['user_id']); } else { @@ -174,7 +174,7 @@ class mcp_queue } } - $phpbb_notifications->mark_notifications_read('notification.type.post_in_queue', $post_id, $user->data['user_id']); + $phpbb_notifications->mark_notifications('post_in_queue', $post_id, $user->data['user_id']); $post_info = phpbb_get_post_data(array($post_id), 'm_approve', true); @@ -738,7 +738,7 @@ class mcp_queue $phpbb_notifications->add_notifications(array('notification.type.quote'), $post_data); $phpbb_notifications->delete_notifications('notification.type.post_in_queue', $post_id); - $phpbb_notifications->mark_notifications_read(array( + $phpbb_notifications->mark_notifications(array( 'notification.type.quote', 'notification.type.bookmark', 'notification.type.post', @@ -974,8 +974,8 @@ class mcp_queue ), $topic_data); } - $phpbb_notifications->mark_notifications_read('notification.type.quote', $topic_data['post_id'], $user->data['user_id']); - $phpbb_notifications->mark_notifications_read('notification.type.topic', $topic_id, $user->data['user_id']); + $phpbb_notifications->mark_notifications('quote', $topic_data['post_id'], $user->data['user_id']); + $phpbb_notifications->mark_notifications('topic', $topic_id, $user->data['user_id']); if ($notify_poster) { diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 30a2188b98..3970237058 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -142,7 +142,7 @@ class mcp_reports /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->mark_notifications_read('notification.type.report_post', $post_id, $user->data['user_id']); + $phpbb_notifications->mark_notifications('report_post', $post_id, $user->data['user_id']); if (!$report_id && $report['report_closed']) { diff --git a/phpBB/includes/ucp/info/ucp_notifications.php b/phpBB/includes/ucp/info/ucp_notifications.php index 0f6a7a8d71..94e0467ccb 100644 --- a/phpBB/includes/ucp/info/ucp_notifications.php +++ b/phpBB/includes/ucp/info/ucp_notifications.php @@ -20,7 +20,7 @@ class ucp_notifications_info 'title' => 'UCP_NOTIFICATION_OPTIONS', 'modes' => array( 'notification_options' => array('title' => 'UCP_NOTIFICATION_OPTIONS', 'auth' => '', 'cat' => array('UCP_PREFS')), - 'notification_list' => array('title' => 'UCP_NOTIFICATION_LIST', 'auth' => '', 'cat' => array('UCP_MAIN')), + 'notification_list' => array('title' => 'UCP_NOTIFICATION_LIST', 'auth' => 'cfg_allow_board_notifications', 'cat' => array('UCP_MAIN')), ), ); } diff --git a/phpBB/includes/ucp/ucp_notifications.php b/phpBB/includes/ucp/ucp_notifications.php index 6d0d4f06a6..8e9fe2dfc1 100644 --- a/phpBB/includes/ucp/ucp_notifications.php +++ b/phpBB/includes/ucp/ucp_notifications.php @@ -70,15 +70,6 @@ class ucp_notifications $phpbb_notifications->delete_subscription($type, 0, $method_data['id']); } } - - if ($request->is_set_post(str_replace('.', '_', $type) . '_notification') && !isset($subscriptions[$type])) - { - $phpbb_notifications->add_subscription($type); - } - else if (!$request->is_set_post(str_replace('.', '_', $type) . '_notification') && isset($subscriptions[$type])) - { - $phpbb_notifications->delete_subscription($type); - } } } @@ -100,7 +91,7 @@ class ucp_notifications // Mark all items read if ($request->variable('mark', '') == 'all' && check_link_hash($request->variable('token', ''), 'mark_all_notifications_read')) { - $phpbb_notifications->mark_notifications_read(false, false, $user->data['user_id'], $form_time); + $phpbb_notifications->mark_notifications(false, false, $user->data['user_id'], $form_time); meta_refresh(3, $this->u_action); $message = $user->lang['NOTIFICATIONS_MARK_ALL_READ_SUCCESS']; @@ -131,11 +122,11 @@ class ucp_notifications if (!empty($mark_read)) { - $phpbb_notifications->mark_notifications_read_by_id($mark_read, $form_time); + $phpbb_notifications->mark_notifications_by_id($mark_read, $form_time); } } - $notifications = $phpbb_notifications->load_notifications(array( + $notifications = $phpbb_notifications->load_notifications('notification.method.board', array( 'start' => $start, 'limit' => $config['topics_per_page'], 'count_total' => true, @@ -196,8 +187,6 @@ class ucp_notifications 'NAME' => $user->lang($data['lang']), 'EXPLAIN' => (isset($user->lang[$data['lang'] . '_EXPLAIN'])) ? $user->lang($data['lang'] . '_EXPLAIN') : '', - - 'SUBSCRIBED' => (isset($subscriptions[$type])) ? true : false, )); foreach ($notification_methods as $method => $method_data) @@ -230,7 +219,7 @@ class ucp_notifications { $notification_methods = $phpbb_notifications->get_subscription_methods(); - foreach ($notification_methods as $method => $method_data) + foreach($notification_methods as $method => $method_data) { $template->assign_block_vars($block, array( 'METHOD' => $method_data['id'], diff --git a/phpBB/index.php b/phpBB/index.php index 132cbd444f..dba961feb8 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -45,7 +45,7 @@ if (($mark_notification = $request->variable('mark_notification', 0))) /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $notification = $phpbb_notifications->load_notifications(array( + $notification = $phpbb_notifications->load_notifications('notification.method.board', array( 'notification_id' => $mark_notification, )); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 1f856f016c..c53c252e2f 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -107,6 +107,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_max_chunk_si INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_package_size', '20'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_confirm', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_mod_rewrite', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_board_notifications', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_pm_icons', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_post_confirm', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_enable', '1'); @@ -813,9 +814,9 @@ INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_len INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_googleplus', 'profilefields.type.googleplus', 'phpbb_googleplus', '20', '3', '255', '', '', '[\w]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 13, 1, 'VIEW_GOOGLEPLUS_PROFILE', 'http://plus.google.com/%s'); # User Notification Options (for first user) -INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, ''); +INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, 'notification.method.board'); INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, 'notification.method.email'); -INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, ''); +INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, 'notification.method.board'); INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, 'notification.method.email'); # POSTGRES COMMIT # diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 8d6c1c141d..001775349a 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -99,6 +99,7 @@ $lang = array_merge($lang, array( 'ALLOW_TOPIC_NOTIFY' => 'Allow subscribing to topics', 'BOARD_PM' => 'Private messaging', 'BOARD_PM_EXPLAIN' => 'Enable private messaging for all users.', + 'ALLOW_BOARD_NOTIFICATIONS' => 'Allow board notifications', )); // Avatar Settings diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 79d504a67d..cb99183dd8 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -447,6 +447,7 @@ $lang = array_merge($lang, array( 'NOTIFICATION_FORUM' => 'Forum: %1$s', 'NOTIFICATION_GROUP_REQUEST' => 'Group request from %1$s to join the group %2$s.', 'NOTIFICATION_GROUP_REQUEST_APPROVED' => 'Group request approved to join the group %1$s.', + 'NOTIFICATION_METHOD_INVALID' => 'The method "%s" does not refer to a valid notification method.', 'NOTIFICATION_PM' => 'Private Message from %1$s:', 'NOTIFICATION_POST' => array( 1 => 'Reply from %1$s in topic:', diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php index 07751d1f7f..b346051108 100644 --- a/phpBB/language/en/ucp.php +++ b/phpBB/language/en/ucp.php @@ -327,6 +327,7 @@ $lang = array_merge($lang, array( 'NOTIFICATION_GROUP_MODERATION' => 'Moderation Notifications', 'NOTIFICATION_GROUP_ADMINISTRATION' => 'Administration Notifications', 'NOTIFICATION_GROUP_POSTING' => 'Posting Notifications', + 'NOTIFICATION_METHOD_BOARD' => 'Notifications', 'NOTIFICATION_METHOD_EMAIL' => 'Email', 'NOTIFICATION_METHOD_JABBER' => 'Jabber', 'NOTIFICATION_TYPE' => 'Notification type', diff --git a/phpBB/phpbb/db/migration/data/v310/notifications_board.php b/phpBB/phpbb/db/migration/data/v310/notifications_board.php new file mode 100644 index 0000000000..525d94e984 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/notifications_board.php @@ -0,0 +1,73 @@ + +* @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\v310; + +class notifications_board extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\notifications'); + } + + public function update_data() + { + return array( + array('config.add', array('allow_board_notifications', 1)), + array('custom', array(array($this, 'update_user_subscriptions'))), + array('custom', array(array($this, 'update_module'))), + ); + } + + public function update_module() + { + $sql = 'UPDATE ' . MODULES_TABLE . " + SET auth = 'cfg_allow_board_notifications' + WHERE module_basename = 'ucp_notifications' + AND module_mode = 'notification_list'"; + $this->sql_query($sql); + } + + public function update_user_subscriptions() + { + $sql = 'UPDATE ' . USER_NOTIFICATIONS_TABLE . " + SET method = 'notification.method.board' + WHERE method = ''"; + $this->sql_query($sql); + } + + public function revert_data() + { + return array( + array('custom', array(array($this, 'revert_user_subscriptions'))), + array('custom', array(array($this, 'revert_module'))), + ); + } + + public function revert_user_subscriptions() + { + $sql = 'UPDATE ' . USER_NOTIFICATIONS_TABLE . " + SET method = '' + WHERE method = 'notification.method.board'"; + $this->sql_query($sql); + } + + public function revert_module() + { + $sql = 'UPDATE ' . MODULES_TABLE . " + SET auth = '' + WHERE module_basename = 'ucp_notifications' + AND module_mode = 'notification_list'"; + $this->sql_query($sql); + } +} diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index 38d7a13165..6b69dca817 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -13,7 +13,7 @@ namespace phpbb\notification; -use Symfony\Component\DependencyInjection\ContainerInterface; +use \Symfony\Component\DependencyInjection\ContainerInterface; /** * Notifications service class @@ -59,9 +59,6 @@ class manager /** @var string */ protected $notification_types_table; - /** @var string */ - protected $notifications_table; - /** @var string */ protected $user_notifications_table; @@ -80,12 +77,11 @@ class manager * @param string $phpbb_root_path * @param string $php_ext * @param string $notification_types_table - * @param string $notifications_table * @param string $user_notifications_table * * @return \phpbb\notification\manager */ - public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) + public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $user_notifications_table) { $this->notification_types = $notification_types; $this->notification_methods = $notification_methods; @@ -102,13 +98,13 @@ class manager $this->php_ext = $php_ext; $this->notification_types_table = $notification_types_table; - $this->notifications_table = $notifications_table; $this->user_notifications_table = $user_notifications_table; } /** - * Load the user's notifications + * Load the user's notifications for a given method * + * @param string $method_name * @param array $options Optional options to control what notifications are loaded * notification_id Notification id to load (or array of notification ids) * user_id User id to load notifications for (Default: $user->data['user_id']) @@ -123,27 +119,21 @@ class manager * 'notifications' array of notification type objects * 'unread_count' number of unread notifications the user has if count_unread is true in the options * 'total_count' number of notifications the user has if count_total is true in the options + * @throws \phpbb\notification\exception when the method doesn't refer to a class extending \phpbb\notification\method\method_interface */ - public function load_notifications(array $options = array()) + public function load_notifications($method_name, array $options = array()) { - // Merge default options - $options = array_merge(array( - 'notification_id' => false, - 'user_id' => $this->user->data['user_id'], - 'order_by' => 'notification_time', - 'order_dir' => 'DESC', - 'limit' => 0, - 'start' => 0, - 'all_unread' => false, - 'count_unread' => false, - 'count_total' => false, - ), $options); + $method = $this->get_method_class($method_name); - // If all_unread, count_unread must be true - $options['count_unread'] = ($options['all_unread']) ? true : $options['count_unread']; - - // Anonymous users and bots never receive notifications - if ($options['user_id'] == $this->user->data['user_id'] && ($this->user->data['user_id'] == ANONYMOUS || $this->user->data['user_type'] == USER_IGNORE)) + if (! $method instanceof \phpbb\notification\method\method_interface) + { + throw new \phpbb\notification\exception($this->user->lang('NOTIFICATION_METHOD_INVALID', $method_name)); + } + else if ($method->is_available()) + { + return $method->load_notifications($options); + } + else { return array( 'notifications' => array(), @@ -151,172 +141,80 @@ class manager 'total_count' => 0, ); } - - $notifications = $user_ids = array(); - $load_special = array(); - $total_count = $unread_count = 0; - - if ($options['count_unread']) - { - // Get the total number of unread notifications - $sql = 'SELECT COUNT(n.notification_id) AS unread_count - FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt - WHERE n.user_id = ' . (int) $options['user_id'] . ' - AND n.notification_read = 0 - AND nt.notification_type_id = n.notification_type_id - AND nt.notification_type_enabled = 1'; - $result = $this->db->sql_query($sql); - $unread_count = (int) $this->db->sql_fetchfield('unread_count'); - $this->db->sql_freeresult($result); - } - - if ($options['count_total']) - { - // Get the total number of notifications - $sql = 'SELECT COUNT(n.notification_id) AS total_count - FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt - WHERE n.user_id = ' . (int) $options['user_id'] . ' - AND nt.notification_type_id = n.notification_type_id - AND nt.notification_type_enabled = 1'; - $result = $this->db->sql_query($sql); - $total_count = (int) $this->db->sql_fetchfield('total_count'); - $this->db->sql_freeresult($result); - } - - if (!$options['count_total'] || $total_count) - { - $rowset = array(); - - // Get the main notifications - $sql = 'SELECT n.*, nt.notification_type_name - FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt - WHERE n.user_id = ' . (int) $options['user_id'] . - (($options['notification_id']) ? ((is_array($options['notification_id'])) ? ' AND ' . $this->db->sql_in_set('n.notification_id', $options['notification_id']) : ' AND n.notification_id = ' . (int) $options['notification_id']) : '') . ' - AND nt.notification_type_id = n.notification_type_id - AND nt.notification_type_enabled = 1 - ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']); - $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']); - - while ($row = $this->db->sql_fetchrow($result)) - { - $rowset[$row['notification_id']] = $row; - } - $this->db->sql_freeresult($result); - - // Get all unread notifications - if ($unread_count && $options['all_unread'] && !empty($rowset)) - { - $sql = 'SELECT n.*, nt.notification_type_name - FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt - WHERE n.user_id = ' . (int) $options['user_id'] . ' - AND n.notification_read = 0 - AND ' . $this->db->sql_in_set('n.notification_id', array_keys($rowset), true) . ' - AND nt.notification_type_id = n.notification_type_id - AND nt.notification_type_enabled = 1 - ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']); - $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']); - - while ($row = $this->db->sql_fetchrow($result)) - { - $rowset[$row['notification_id']] = $row; - } - $this->db->sql_freeresult($result); - } - - foreach ($rowset as $row) - { - $notification = $this->get_item_type_class($row['notification_type_name'], $row); - - // Array of user_ids to query all at once - $user_ids = array_merge($user_ids, $notification->users_to_query()); - - // Some notification types also require querying additional tables themselves - if (!isset($load_special[$row['notification_type_name']])) - { - $load_special[$row['notification_type_name']] = array(); - } - $load_special[$row['notification_type_name']] = array_merge($load_special[$row['notification_type_name']], $notification->get_load_special()); - - $notifications[$row['notification_id']] = $notification; - } - - $this->user_loader->load_users($user_ids); - - // Allow each type to load its own special items - foreach ($load_special as $item_type => $data) - { - $item_class = $this->get_item_type_class($item_type); - - $item_class->load_special($data, $notifications); - } - } - - return array( - 'notifications' => $notifications, - 'unread_count' => $unread_count, - 'total_count' => $total_count, - ); } /** - * Mark notifications read + * Mark notifications read or unread for all available methods * * @param bool|string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types * @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False) + * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True) */ - public function mark_notifications_read($notification_type_name, $item_id, $user_id, $time = false) + public function mark_notifications($notification_type_name, $item_id, $user_id, $time = false, $mark_read = true) { - $time = ($time !== false) ? $time : time(); + if (is_array($notification_type_name)) + { + $notification_type_id = $this->get_notification_type_ids($notification_type_name); + } + else if ($notification_type_name !== false) + { + $notification_type_id = $this->get_notification_type_id($notification_type_name); + } + else + { + $notification_type_id = false; + } - $sql = 'UPDATE ' . $this->notifications_table . " - SET notification_read = 1 - WHERE notification_time <= " . (int) $time . - (($notification_type_name !== false) ? ' AND ' . - (is_array($notification_type_name) ? $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : 'notification_type_id = ' . $this->get_notification_type_id($notification_type_name)) : '') . - (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '') . - (($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : ''); - $this->db->sql_query($sql); + foreach ($this->get_available_subscription_methods() as $method) + { + $method->mark_notifications($notification_type_id, $item_id, $user_id, $time, $mark_read); + } } /** - * Mark notifications read from a parent identifier + * Mark notifications read or unread from a parent identifier for all available methods * * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types) * @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False) + * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True) */ - public function mark_notifications_read_by_parent($notification_type_name, $item_parent_id, $user_id, $time = false) + public function mark_notifications_by_parent($notification_type_name, $item_parent_id, $user_id, $time = false, $mark_read = true) { - $time = ($time !== false) ? $time : time(); + if (is_array($notification_type_name)) + { + $notification_type_id = $this->get_notification_type_ids($notification_type_name); + } + else + { + $notification_type_id = $this->get_notification_type_id($notification_type_name); + } - $sql = 'UPDATE ' . $this->notifications_table . " - SET notification_read = 1 - WHERE notification_time <= " . (int) $time . - (($notification_type_name !== false) ? ' AND ' . - (is_array($notification_type_name) ? $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : 'notification_type_id = ' . $this->get_notification_type_id($notification_type_name)) : '') . - (($item_parent_id !== false) ? ' AND ' . (is_array($item_parent_id) ? $this->db->sql_in_set('item_parent_id', $item_parent_id, false, true) : 'item_parent_id = ' . (int) $item_parent_id) : '') . - (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : ''); - $this->db->sql_query($sql); + foreach ($this->get_available_subscription_methods() as $method) + { + $method->mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time, $mark_read); + } } /** - * Mark notifications read + * Mark notifications read or unread for a given method * + * @param string $method_name * @param int|array $notification_id Notification id or array of notification ids. * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False) + * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True) */ - public function mark_notifications_read_by_id($notification_id, $time = false) + public function mark_notifications_by_id($method_name, $notification_id, $time = false, $mark_read = true) { - $time = ($time !== false) ? $time : time(); + $method = $this->get_method_class($method_name); - $sql = 'UPDATE ' . $this->notifications_table . " - SET notification_read = 1 - WHERE notification_time <= " . (int) $time . ' - AND ' . ((is_array($notification_id)) ? $this->db->sql_in_set('notification_id', $notification_id) : 'notification_id = ' . (int) $notification_id); - $this->db->sql_query($sql); + if ($method instanceof \phpbb\notification\method\method_interface && $method->is_available()) + { + $method->mark_notifications_by_id($notification_id, $time, $mark_read); + } } /** @@ -411,18 +309,15 @@ class manager // Make sure not to send new notifications to users who've already been notified about this item // This may happen when an item was added, but now new users are able to see the item - $sql = 'SELECT n.user_id - FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt - WHERE n.notification_type_id = ' . (int) $notification_type_id . ' - AND n.item_id = ' . (int) $item_id . ' - AND nt.notification_type_id = n.notification_type_id - AND nt.notification_type_enabled = 1'; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) + // We remove each user which was already notified by at least one method. + foreach ($this->get_subscription_methods_instances() as $method) { - unset($notify_users[$row['user_id']]); + $notified_users = $method->get_notified_users($notification_type_id, array('item_id' => $item_id)); + foreach ($notified_users as $user => $notifications) + { + unset($notify_users[$user]); + } } - $this->db->sql_freeresult($result); if (!sizeof($notify_users)) { @@ -434,8 +329,6 @@ class manager $pre_create_data = $notification->pre_create_insert_array($data, $notify_users); unset($notification); - $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->notifications_table); - // Go through each user so we can insert a row in the DB and then notify them by their desired means foreach ($notify_users as $user => $methods) { @@ -443,8 +336,8 @@ class manager $notification->user_id = (int) $user; - // Insert notification row using buffer. - $insert_buffer->insert($notification->create_insert_array($data, $pre_create_data)); + // Generate the insert_array + $notification->create_insert_array($data, $pre_create_data); // Users are needed to send notifications $user_ids = array_merge($user_ids, $notification->users_to_query()); @@ -452,20 +345,15 @@ class manager foreach ($methods as $method) { // setup the notification methods and add the notification to the queue - if ($method) // blank means we just insert it as a notification, but do not notify them by any other means + if (!isset($notification_methods[$method])) { - if (!isset($notification_methods[$method])) - { - $notification_methods[$method] = $this->get_method_class($method); - } - - $notification_methods[$method]->add_to_queue($notification); + $notification_methods[$method] = $this->get_method_class($method); } + + $notification_methods[$method]->add_to_queue($notification); } } - $insert_buffer->flush(); - // We need to load all of the users to send notifications $this->user_loader->load_users($user_ids); @@ -477,12 +365,13 @@ class manager } /** - * Update a notification + * Update notification * * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types) * @param array $data Data specific for this type that will be updated + * @param array $options */ - public function update_notifications($notification_type_name, $data) + public function update_notifications($notification_type_name, array $data, array $options = array()) { if (is_array($notification_type_name)) { @@ -494,27 +383,27 @@ class manager return; } - $notification = $this->get_item_type_class($notification_type_name); + $this->update_notification($this->get_item_type_class($notification_type_name), $data, $options); + } - // Allow the notifications class to over-ride the update_notifications functionality - if (method_exists($notification, 'update_notifications')) + /** + * Update a notification + * + * @param \phpbb\notification\type\type_interface $notification The notification + * @param array $data Data specific for this type that will be updated + * @param array $options + */ + public function update_notification(\phpbb\notification\type\type_interface $notification, array $data, array $options = array()) + { + if (empty($options)) { - // Return False to over-ride the rest of the update - if ($notification->update_notifications($data) === false) - { - return; - } + $options['item_id'] = $notification->get_item_id($data); } - $notification_type_id = $this->get_notification_type_id($notification_type_name); - $item_id = $notification->get_item_id($data); - $update_array = $notification->create_update_array($data); - - $sql = 'UPDATE ' . $this->notifications_table . ' - SET ' . $this->db->sql_build_array('UPDATE', $update_array) . ' - WHERE notification_type_id = ' . (int) $notification_type_id . ' - AND item_id = ' . (int) $item_id; - $this->db->sql_query($sql); + foreach ($this->get_available_subscription_methods() as $method) + { + $method->update_notification($notification, $data, $options); + } } /** @@ -523,14 +412,15 @@ class manager * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $item_id is identical for the specified types) * @param int|array $item_id Identifier within the type (or array of ids) * @param mixed $parent_id Parent identifier within the type (or array of ids), used in combination with item_id if specified (Default: false; not checked) + * @param mixed $user_id User id (Default: false; not checked) */ - public function delete_notifications($notification_type_name, $item_id, $parent_id = false) + public function delete_notifications($notification_type_name, $item_id, $parent_id = false, $user_id = false) { if (is_array($notification_type_name)) { foreach ($notification_type_name as $type) { - $this->delete_notifications($type, $item_id, $parent_id); + $this->delete_notifications($type, $item_id, $parent_id, $user_id); } return; @@ -538,11 +428,10 @@ class manager $notification_type_id = $this->get_notification_type_id($notification_type_name); - $sql = 'DELETE FROM ' . $this->notifications_table . ' - WHERE notification_type_id = ' . (int) $notification_type_id . ' - AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) . - (($parent_id !== false) ? ' AND ' . ((is_array($parent_id) ? $this->db->sql_in_set('item_parent_id', $parent_id) : 'item_parent_id = ' . (int) $parent_id)) : ''); - $this->db->sql_query($sql); + foreach ($this->get_available_subscription_methods() as $method) + { + $method->delete_notifications($notification_type_id, $item_id, $parent_id, $user_id); + } } /** @@ -593,16 +482,53 @@ class manager { $subscription_methods = array(); + foreach ($this->get_available_subscription_methods() as $method_name => $method) + { + $subscription_methods[$method_name] = array( + 'id' => $method->get_type(), + 'lang' => str_replace('.', '_', strtoupper($method->get_type())), + ); + } + + return $subscription_methods; + } + + /** + * Get all of the subscription methods + * + * @return array Array of method's instances + */ + private function get_subscription_methods_instances() + { + $subscription_methods = array(); + foreach ($this->notification_methods as $method_name => $data) { $method = $this->get_method_class($method_name); - if ($method instanceof \phpbb\notification\method\method_interface && $method->is_available()) + if ($method instanceof \phpbb\notification\method\method_interface) { - $subscription_methods[$method_name] = array( - 'id' => $method->get_type(), - 'lang' => str_replace('.', '_', strtoupper($method->get_type())), - ); + $subscription_methods[$method_name] = $method; + } + } + + return $subscription_methods; + } + + /** + * Get all of the available subscription methods + * + * @return array Array of method's instances + */ + private function get_available_subscription_methods() + { + $subscription_methods = array(); + + foreach ($this->get_subscription_methods_instances() as $method_name => $method) + { + if ($method->is_available()) + { + $subscription_methods[$method_name] = $method; } } @@ -646,7 +572,7 @@ class manager */ public function get_global_subscriptions($user_id = false) { - $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id; + $user_id = $user_id ?: $this->user->data['user_id']; $subscriptions = array(); @@ -656,11 +582,9 @@ class manager { foreach ($types as $id => $type) { - if (empty($user_notifications[$id])) { - // No rows at all, default to '' - $subscriptions[$id] = array(''); + $subscriptions[$id] = $this->get_default_methods(); } else { @@ -690,15 +614,20 @@ class manager * * @param string $item_type Type identifier of the subscription * @param int $item_id The id of the item - * @param string $method The method of the notification e.g. '', 'email', or 'jabber' + * @param string $method The method of the notification e.g. 'board', 'email', or 'jabber' + * (if null a subscription will be added for all the defaults methods) * @param bool|int $user_id The user_id to add the subscription for (bool false for current user) */ - public function add_subscription($item_type, $item_id = 0, $method = '', $user_id = false) + public function add_subscription($item_type, $item_id = 0, $method = null, $user_id = false) { - if ($method !== '') + if ($method === null) { - // Make sure to subscribe them to the base subscription - $this->add_subscription($item_type, $item_id, '', $user_id); + foreach ($this->get_default_methods() as $method_name) + { + $this->add_subscription($item_type, $item_id, $method_name, $user_id); + } + + return; } $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id; @@ -742,33 +671,23 @@ class manager * * @param string $item_type Type identifier of the subscription * @param int $item_id The id of the item - * @param string $method The method of the notification e.g. '', 'email', or 'jabber' + * @param string $method The method of the notification e.g. 'board', 'email', or 'jabber' * @param bool|int $user_id The user_id to add the subscription for (bool false for current user) */ - public function delete_subscription($item_type, $item_id = 0, $method = '', $user_id = false) + public function delete_subscription($item_type, $item_id = 0, $method = null, $user_id = false) { - $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id; - - // If no method, make sure that no other notification methods for this item are selected before deleting - if ($method === '') + if ($method === null) { - $sql = 'SELECT COUNT(*) as num_notifications - FROM ' . $this->user_notifications_table . " - WHERE item_type = '" . $this->db->sql_escape($item_type) . "' - AND item_id = " . (int) $item_id . ' - AND user_id = ' .(int) $user_id . " - AND method <> '' - AND notify = 1"; - $this->db->sql_query($sql); - $num_notifications = $this->db->sql_fetchfield('num_notifications'); - $this->db->sql_freeresult(); - - if ($num_notifications) + foreach ($this->get_default_methods() as $method_name) { - return; + $this->delete_subscription($item_type, $item_id, $method_name, $user_id); } + + return; } + $user_id = $user_id ?: $this->user->data['user_id']; + $sql = 'UPDATE ' . $this->user_notifications_table . " SET notify = 0 WHERE item_type = '" . $this->db->sql_escape($item_type) . "' @@ -828,15 +747,11 @@ class manager { $notification_type_id = $this->get_notification_type_id($notification_type_name); - $sql = 'DELETE FROM ' . $this->notifications_table . ' - WHERE notification_type_id = ' . (int) $notification_type_id; - $this->db->sql_query($sql); + foreach ($this->get_available_subscription_methods() as $method) + { + $method->purge_notifications($notification_type_id); + } - $sql = 'DELETE FROM ' . $this->notification_types_table . ' - WHERE notification_type_id = ' . (int) $notification_type_id; - $this->db->sql_query($sql); - - $this->cache->destroy('notification_type_ids'); } catch (\phpbb\notification\exception $e) { @@ -869,12 +784,28 @@ class manager */ public function prune_notifications($timestamp, $only_read = true) { - $sql = 'DELETE FROM ' . $this->notifications_table . ' - WHERE notification_time < ' . (int) $timestamp . - (($only_read) ? ' AND notification_read = 1' : ''); - $this->db->sql_query($sql); + foreach ($this->get_available_subscription_methods() as $method) + { + $method->prune_notifications($timestamp, $only_read); + } + } - $this->config->set('read_notification_last_gc', time(), false); + /** + * Helper to get the list of methods enabled by default + */ + public function get_default_methods() + { + $default_methods = array(); + + foreach ($this->notification_methods as $method) + { + if ($method->is_enabled_by_default() && $method->is_available()) + { + $default_methods[] = $method->get_type(); + } + } + + return $default_methods; } /** @@ -977,4 +908,24 @@ class manager return $notification_type_ids; } + + /** + * Find the users which are already notified + * + * @param bool|string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to retrieve all item types + * @param array $options + * @return array The list of the notified users + */ + public function get_notified_users($notification_type_name, array $options) + { + $notification_type_id = $this->get_notification_type_id($notification_type_name); + + $notified_users = array(); + foreach ($this->get_available_subscription_methods() as $method) + { + $notified_users = $notified_users + $method->get_notified_users($notification_type_id, $options); + } + + return $notified_users; + } } diff --git a/phpBB/phpbb/notification/method/base.php b/phpBB/phpbb/notification/method/base.php index 6ee1d2984a..240b2ddbac 100644 --- a/phpBB/phpbb/notification/method/base.php +++ b/phpBB/phpbb/notification/method/base.php @@ -93,6 +93,36 @@ abstract class base implements \phpbb\notification\method\method_interface $this->notification_manager = $notification_manager; } + /** + * Is the method enable by default? + * + * @return bool + */ + public function is_enabled_by_default() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function get_notified_users($notification_type_id, array $options) + { + return array(); + } + + /** + * {@inheritdoc} + */ + public function load_notifications(array $options = array()) + { + return array( + 'notifications' => array(), + 'unread_count' => 0, + 'total_count' => 0, + ); + } + /** * Add a notification to the queue * @@ -103,6 +133,55 @@ abstract class base implements \phpbb\notification\method\method_interface $this->queue[] = $notification; } + /** + * {@inheritdoc} + */ + public function update_notification($notification, array $data, array $options) + { + } + + /** + * {@inheritdoc + */ + public function mark_notifications($notification_type_id, $item_id, $user_id, $time = false, $mark_read = true) + { + } + + /** + * {@inheritdoc} + */ + public function mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time = false, $mark_read = true) + { + } + + /** + * {@inheritdoc} + */ + public function mark_notifications_by_id($notification_id, $time = false, $mark_read = true) + { + } + + /** + * {@inheritdoc} + */ + public function delete_notifications($notification_type_id, $item_id, $parent_id = false, $user_id = false) + { + } + + /** + * {@inheritdoc} + */ + public function prune_notifications($timestamp, $only_read = true) + { + } + + /** + * {@inheritdoc} + */ + public function purge_notifications($notification_type_id) + { + } + /** * Empty the queue */ diff --git a/phpBB/phpbb/notification/method/board.php b/phpBB/phpbb/notification/method/board.php new file mode 100644 index 0000000000..99853e2f81 --- /dev/null +++ b/phpBB/phpbb/notification/method/board.php @@ -0,0 +1,390 @@ + +* @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\notification\method; + +/** +* In Board notification method class +* This class handles in board notifications. This method is enabled by default. +* +* @package notifications +*/ +class board extends \phpbb\notification\method\base +{ + /** @var string */ + protected $notification_types_table; + + /** @var string */ + protected $notifications_table; + + /** + * Notification Method Board Constructor + * + * @param \phpbb\user_loader $user_loader + * @param \phpbb\db\driver\driver_interface $db + * @param \phpbb\cache\driver\driver_interface $cache + * @param \phpbb\user $user + * @param \phpbb\auth\auth $auth + * @param \phpbb\config\config $config + * @param string $phpbb_root_path + * @param string $php_ext + * @param string $notification_types_table + * @param string $notifications_table + * @return \phpbb\notification\method\board + */ + public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table) + { + $this->user_loader = $user_loader; + $this->db = $db; + $this->cache = $cache; + $this->user = $user; + $this->auth = $auth; + $this->config = $config; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + + $this->notification_types_table = $notification_types_table; + $this->notifications_table = $notifications_table; + } + + /** + * {@inheritdoc} + */ + public function add_to_queue(\phpbb\notification\type\type_interface $notification) + { + $this->queue[] = $notification; + } + + /** + * {@inheritdoc} + */ + public function get_type() + { + return 'notification.method.board'; + } + + /** + * {@inheritdoc} + */ + public function is_available() + { + return $this->config['allow_board_notifications']; + } + + /** + * {@inheritdoc} + */ + public function is_enabled_by_default() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function get_notified_users($notification_type_id, array $options) + { + $notified_users = array(); + $sql = 'SELECT n.* + FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt + WHERE n.notification_type_id = ' . (int) $notification_type_id . + (isset($options['item_id']) ? ' AND n.item_id = ' . (int) $options['item_id'] : '') . + (isset($options['item_parent_id']) ? ' AND n.item_parent_id = ' . (int) $options['item_parent_id'] : '') . + (isset($options['user_id']) ? ' AND n.user_id = ' . (int) $options['user_id'] : '') . + (isset($options['read']) ? ' AND n.notification_read = ' . (int) $options['read'] : '') .' + AND nt.notification_type_id = n.notification_type_id + AND nt.notification_type_enabled = 1'; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $notified_users[$row['user_id']] = $row; + } + $this->db->sql_freeresult($result); + + return $notified_users; + } + + /** + * {@inheritdoc} + */ + public function load_notifications(array $options = array()) + { + // Merge default options + $options = array_merge(array( + 'notification_id' => false, + 'user_id' => $this->user->data['user_id'], + 'order_by' => 'notification_time', + 'order_dir' => 'DESC', + 'limit' => 0, + 'start' => 0, + 'all_unread' => false, + 'count_unread' => false, + 'count_total' => false, + ), $options); + + // If all_unread, count_unread must be true + $options['count_unread'] = ($options['all_unread']) ? true : $options['count_unread']; + + // Anonymous users and bots never receive notifications + if ($options['user_id'] == $this->user->data['user_id'] && ($this->user->data['user_id'] == ANONYMOUS || $this->user->data['user_type'] == USER_IGNORE)) + { + return array( + 'notifications' => array(), + 'unread_count' => 0, + 'total_count' => 0, + ); + } + + $notifications = $user_ids = array(); + $load_special = array(); + $total_count = $unread_count = 0; + + if ($options['count_unread']) + { + // Get the total number of unread notifications + $sql = 'SELECT COUNT(n.notification_id) AS unread_count + FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt + WHERE n.user_id = ' . (int) $options['user_id'] . ' + AND n.notification_read = 0 + AND nt.notification_type_id = n.notification_type_id + AND nt.notification_type_enabled = 1'; + $result = $this->db->sql_query($sql); + $unread_count = (int) $this->db->sql_fetchfield('unread_count'); + $this->db->sql_freeresult($result); + } + + if ($options['count_total']) + { + // Get the total number of notifications + $sql = 'SELECT COUNT(n.notification_id) AS total_count + FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt + WHERE n.user_id = ' . (int) $options['user_id'] . ' + AND nt.notification_type_id = n.notification_type_id + AND nt.notification_type_enabled = 1'; + $result = $this->db->sql_query($sql); + $total_count = (int) $this->db->sql_fetchfield('total_count'); + $this->db->sql_freeresult($result); + } + + if (!$options['count_total'] || $total_count) + { + $rowset = array(); + + // Get the main notifications + $sql = 'SELECT n.*, nt.notification_type_name + FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt + WHERE n.user_id = ' . (int) $options['user_id'] . + (($options['notification_id']) ? ((is_array($options['notification_id'])) ? ' AND ' . $this->db->sql_in_set('n.notification_id', $options['notification_id']) : ' AND n.notification_id = ' . (int) $options['notification_id']) : '') . ' + AND nt.notification_type_id = n.notification_type_id + AND nt.notification_type_enabled = 1 + ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']); + $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']); + + while ($row = $this->db->sql_fetchrow($result)) + { + $rowset[$row['notification_id']] = $row; + } + $this->db->sql_freeresult($result); + + // Get all unread notifications + if ($unread_count && $options['all_unread'] && !empty($rowset)) + { + $sql = 'SELECT n.*, nt.notification_type_name + FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt + WHERE n.user_id = ' . (int) $options['user_id'] . ' + AND n.notification_read = 0 + AND ' . $this->db->sql_in_set('n.notification_id', array_keys($rowset), true) . ' + AND nt.notification_type_id = n.notification_type_id + AND nt.notification_type_enabled = 1 + ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']); + $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']); + + while ($row = $this->db->sql_fetchrow($result)) + { + $rowset[$row['notification_id']] = $row; + } + $this->db->sql_freeresult($result); + } + + foreach ($rowset as $row) + { + $notification = $this->notification_manager->get_item_type_class($row['notification_type_name'], $row); + + // Array of user_ids to query all at once + $user_ids = array_merge($user_ids, $notification->users_to_query()); + + // Some notification types also require querying additional tables themselves + if (!isset($load_special[$row['notification_type_name']])) + { + $load_special[$row['notification_type_name']] = array(); + } + $load_special[$row['notification_type_name']] = array_merge($load_special[$row['notification_type_name']], $notification->get_load_special()); + + $notifications[$row['notification_id']] = $notification; + } + + $this->user_loader->load_users($user_ids); + + // Allow each type to load its own special items + foreach ($load_special as $item_type => $data) + { + $item_class = $this->notification_manager->get_item_type_class($item_type); + + $item_class->load_special($data, $notifications); + } + } + + return array( + 'notifications' => $notifications, + 'unread_count' => $unread_count, + 'total_count' => $total_count, + ); + } + + /** + * {@inheritdoc} + */ + public function notify() + { + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->notifications_table); + + foreach ($this->queue as $notification) + { + $data = $notification->get_insert_array(); + $insert_buffer->insert($data); + } + + $insert_buffer->flush(); + + // We're done, empty the queue + $this->empty_queue(); + } + + /** + * {@inheritdoc} + */ + public function update_notification($notification, array $data, array $options) + { + // Allow the notifications class to over-ride the update_notifications functionality + if (method_exists($notification, 'update_notifications')) + { + // Return False to over-ride the rest of the update + if ($notification->update_notifications($data) === false) + { + return; + } + } + + $notification_type_id = $this->notification_manager->get_notification_type_id($notification->get_type()); + $update_array = $notification->create_update_array($data); + + $sql = 'UPDATE ' . $this->notifications_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $update_array) . ' + WHERE notification_type_id = ' . (int) $notification_type_id . + (isset($options['item_id']) ? ' AND item_id = ' . (int) $options['item_id'] : '') . + (isset($options['item_parent_id']) ? ' AND item_parent_id = ' . (int) $options['item_parent_id'] : '') . + (isset($options['user_id']) ? ' AND user_id = ' . (int) $options['user_id'] : '') . + (isset($options['read']) ? ' AND notification_read = ' . (int) $options['read'] : ''); + $this->db->sql_query($sql); + } + + /** + * {@inheritdoc} + */ + public function mark_notifications($notification_type_id, $item_id, $user_id, $time = false, $mark_read = true) + { + $time = ($time !== false) ? $time : time(); + + $sql = 'UPDATE ' . $this->notifications_table . ' + SET notification_read = ' . ($mark_read ? 1 : 0) . ' + WHERE notification_time <= ' . (int) $time . + (($notification_type_id !== false) ? ' AND ' . + (is_array($notification_type_id) ? $this->db->sql_in_set('notification_type_id', $notification_type_id) : 'notification_type_id = ' . $notification_type_id) : '') . + (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '') . + (($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : ''); + $this->db->sql_query($sql); + } + + /** + * {@inheritdoc} + */ + public function mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time = false, $mark_read = true) + { + $time = ($time !== false) ? $time : time(); + + $sql = 'UPDATE ' . $this->notifications_table . ' + SET notification_read = ' . ($mark_read ? 1 : 0) . ' + WHERE notification_time <= ' . (int) $time . + (($notification_type_id !== false) ? ' AND ' . + (is_array($notification_type_id) ? $this->db->sql_in_set('notification_type_id', $notification_type_id) : 'notification_type_id = ' . $notification_type_id) : '') . + (($item_parent_id !== false) ? ' AND ' . (is_array($item_parent_id) ? $this->db->sql_in_set('item_parent_id', $item_parent_id, false, true) : 'item_parent_id = ' . (int) $item_parent_id) : '') . + (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : ''); + $this->db->sql_query($sql); + } + + /** + * {@inheritdoc} + */ + public function mark_notifications_by_id($notification_id, $time = false, $mark_read = true) + { + $time = ($time !== false) ? $time : time(); + + $sql = 'UPDATE ' . $this->notifications_table . ' + SET notification_read = ' . ($mark_read ? 1 : 0) . ' + WHERE notification_time <= ' . (int) $time . ' + AND ' . ((is_array($notification_id)) ? $this->db->sql_in_set('notification_id', $notification_id) : 'notification_id = ' . (int) $notification_id); + $this->db->sql_query($sql); + } + + /** + * {@inheritdoc} + */ + public function delete_notifications($notification_type_id, $item_id, $parent_id = false, $user_id = false) + { + $sql = 'DELETE FROM ' . $this->notifications_table . ' + WHERE notification_type_id = ' . (int) $notification_type_id . ' + AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) . + (($parent_id !== false) ? ' AND ' . ((is_array($parent_id) ? $this->db->sql_in_set('item_parent_id', $parent_id) : 'item_parent_id = ' . (int) $parent_id)) : '') . + (($user_id !== false) ? ' AND ' . ((is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id)) : ''); + $this->db->sql_query($sql); + } + + /** + * {@inheritdoc} + */ + public function prune_notifications($timestamp, $only_read = true) + { + $sql = 'DELETE FROM ' . $this->notifications_table . ' + WHERE notification_time < ' . (int) $timestamp . + (($only_read) ? ' AND notification_read = 1' : ''); + $this->db->sql_query($sql); + + $this->config->set('read_notification_last_gc', time(), false); + } + + /** + * {@inheritdoc} + */ + public function purge_notifications($notification_type_id) + { + $sql = 'DELETE FROM ' . $this->notifications_table . ' + WHERE notification_type_id = ' . (int) $notification_type_id; + $this->db->sql_query($sql); + + $sql = 'DELETE FROM ' . $this->notification_types_table . ' + WHERE notification_type_id = ' . (int) $notification_type_id; + $this->db->sql_query($sql); + + $this->cache->destroy('notification_type_ids'); + } +} diff --git a/phpBB/phpbb/notification/method/method_interface.php b/phpBB/phpbb/notification/method/method_interface.php index 76b0de179c..c2e4940485 100644 --- a/phpBB/phpbb/notification/method/method_interface.php +++ b/phpBB/phpbb/notification/method/method_interface.php @@ -25,12 +25,48 @@ interface method_interface */ public function get_type(); + /** + * Is the method enable by default? + * + * @return bool + */ + public function is_enabled_by_default(); + /** * Is this method available for the user? * This is checked on the notifications options */ public function is_available(); + /** + * Return the list of the users already notified + * + * @param int $notification_type_id Type of the notification + * @param array $options + * @return array User + */ + public function get_notified_users($notification_type_id, array $options); + + /** + * Load the user's notifications + * + * @param array $options Optional options to control what notifications are loaded + * notification_id Notification id to load (or array of notification ids) + * user_id User id to load notifications for (Default: $user->data['user_id']) + * order_by Order by (Default: notification_time) + * order_dir Order direction (Default: DESC) + * limit Number of notifications to load (Default: 5) + * start Notifications offset (Default: 0) + * all_unread Load all unread notifications? If set to true, count_unread is set to true (Default: false) + * count_unread Count all unread notifications? (Default: false) + * count_total Count all notifications? (Default: false) + * @return array Array of information based on the request with keys: + * 'notifications' array of notification type objects + * 'unread_count' number of unread notifications the user has if count_unread is true in the options + * 'total_count' number of notifications the user has if count_total is true in the options + */ + public function load_notifications(array $options = array()); + /** * Add a notification to the queue * @@ -42,4 +78,72 @@ interface method_interface * Parse the queue and notify the users */ public function notify(); + + /** + * Update a notification + * + * @param \phpbb\notification\type\type_interface $notification Notification to update + * @param array $data Data specific for this type that will be updated + * @param array $options + */ + public function update_notification($notification, array $data, array $options); + + /** + * Mark notifications read or unread + * + * @param bool|string $notification_type_id Type identifier of item types. False to mark read for all item types + * @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids + * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids + * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False) + * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True) + */ + public function mark_notifications($notification_type_id, $item_id, $user_id, $time = false, $mark_read = true); + + /** + * Mark notifications read or unread from a parent identifier + * + * @param string $notification_type_id Type identifier of item types + * @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids + * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids + * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False) + * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True) + */ + public function mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time = false, $mark_read = true); + + /** + * Mark notifications read or unread + * + * @param int $notification_id Notification id of notification ids. + * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False) + * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True) + */ + public function mark_notifications_by_id($notification_id, $time = false, $mark_read = true); + + /** + * Delete a notification + * + * @param string $notification_type_id Type identifier of item types + * @param int|array $item_id Identifier within the type (or array of ids) + * @param mixed $parent_id Parent identifier within the type (or array of ids), used in combination with item_id if specified (Default: false; not checked) + * @param mixed $user_id User id (Default: false; not checked) + */ + public function delete_notifications($notification_type_id, $item_id, $parent_id = false, $user_id = false); + + /** + * Delete all notifications older than a certain time + * + * @param int $timestamp Unix timestamp to delete all notifications that were created before + * @param bool $only_read True (default) to only prune read notifications + */ + public function prune_notifications($timestamp, $only_read = true); + + /** + * Purge all notifications of a certain type + * + * This should be called when an extension which has notification types + * is purged so that all those notifications are removed + * + * @param string $notification_type_id Type identifier of the subscription + */ + public function purge_notifications($notification_type_id); } diff --git a/phpBB/phpbb/notification/type/admin_activate_user.php b/phpBB/phpbb/notification/type/admin_activate_user.php index 0e2924e29c..5b7e58bd92 100644 --- a/phpBB/phpbb/notification/type/admin_activate_user.php +++ b/phpBB/phpbb/notification/type/admin_activate_user.php @@ -164,6 +164,6 @@ class admin_activate_user extends \phpbb\notification\type\base $this->set_data('user_actkey', $user['user_actkey']); $this->notification_time = $user['user_regdate']; - return parent::create_insert_array($user, $pre_create_data); + parent::create_insert_array($user, $pre_create_data); } } diff --git a/phpBB/phpbb/notification/type/approve_post.php b/phpBB/phpbb/notification/type/approve_post.php index e6c38b2ede..9666647bd8 100644 --- a/phpBB/phpbb/notification/type/approve_post.php +++ b/phpBB/phpbb/notification/type/approve_post.php @@ -79,7 +79,7 @@ class approve_post extends \phpbb\notification\type\post ), $options); $users = array(); - $users[$post['poster_id']] = array(''); + $users[$post['poster_id']] = $this->notification_manager->get_default_methods(); return $this->get_authorised_recipients(array_keys($users), $post['forum_id'], array_merge($options, array( 'item_type' => self::$notification_option['id'], @@ -107,21 +107,24 @@ class approve_post extends \phpbb\notification\type\post } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { $this->set_data('post_subject', $post['post_subject']); - $data = parent::create_insert_array($post, $pre_create_data); + parent::create_insert_array($post, $pre_create_data); - $this->notification_time = $data['notification_time'] = time(); + $this->notification_time = time(); + } + + /** + * {@inheritdoc} + */ + public function get_insert_array() + { + $data = parent::get_insert_array(); + $data['notification_time'] = $this->notification_time; return $data; } diff --git a/phpBB/phpbb/notification/type/approve_topic.php b/phpBB/phpbb/notification/type/approve_topic.php index 5f5b96f335..e9f4c32852 100644 --- a/phpBB/phpbb/notification/type/approve_topic.php +++ b/phpBB/phpbb/notification/type/approve_topic.php @@ -79,7 +79,7 @@ class approve_topic extends \phpbb\notification\type\topic ), $options); $users = array(); - $users[$post['poster_id']] = array(''); + $users[$post['poster_id']] = $this->notification_manager->get_default_methods(); return $this->get_authorised_recipients(array_keys($users), $post['forum_id'], array_merge($options, array( 'item_type' => self::$notification_option['id'], @@ -107,19 +107,23 @@ class approve_topic extends \phpbb\notification\type\topic } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { - $data = parent::create_insert_array($post, $pre_create_data); - $this->notification_time = $data['notification_time'] = time(); + parent::create_insert_array($post, $pre_create_data); + + $this->notification_time = time(); + } + + /** + * {@inheritdoc} + */ + public function get_insert_array() + { + $data = parent::get_insert_array(); + $data['notification_time'] = $this->notification_time; return $data; } diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php index 1cf0498138..843ab98de8 100644 --- a/phpBB/phpbb/notification/type/base.php +++ b/phpBB/phpbb/notification/type/base.php @@ -51,9 +51,6 @@ abstract class base implements \phpbb\notification\type\type_interface /** @var string */ protected $notification_types_table; - /** @var string */ - protected $notifications_table; - /** @var string */ protected $user_notifications_table; @@ -100,11 +97,10 @@ abstract class base implements \phpbb\notification\type\type_interface * @param string $phpbb_root_path * @param string $php_ext * @param string $notification_types_table - * @param string $notifications_table * @param string $user_notifications_table * @return \phpbb\notification\type\base */ - public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) + public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $user_notifications_table) { $this->user_loader = $user_loader; $this->db = $db; @@ -117,7 +113,6 @@ abstract class base implements \phpbb\notification\type\type_interface $this->php_ext = $php_ext; $this->notification_types_table = $notification_types_table; - $this->notifications_table = $notifications_table; $this->user_notifications_table = $user_notifications_table; } @@ -207,12 +202,7 @@ abstract class base implements \phpbb\notification\type\type_interface } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $type_data Data unique to this notification type - * @param array $pre_create_data Data from pre_create_insert_array() - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($type_data, $pre_create_data = array()) { @@ -227,7 +217,13 @@ abstract class base implements \phpbb\notification\type\type_interface 'notification_data' => array(), ), $this->data); + } + /** + * {@inheritdoc} + */ + public function get_insert_array() + { $data = $this->data; $data['notification_data'] = serialize($data['notification_data']); @@ -244,7 +240,8 @@ abstract class base implements \phpbb\notification\type\type_interface */ public function create_update_array($type_data) { - $data = $this->create_insert_array($type_data); + $this->create_insert_array($type_data); + $data = $this->get_insert_array(); // Unset data unique to each row unset( @@ -497,8 +494,8 @@ abstract class base implements \phpbb\notification\type\type_interface { if (!in_array($user_id, $resulting_user_ids) && !isset($options['ignore_users'][$user_id])) { - // No rows at all for this user, default to '' - $rowset[$user_id] = array(''); + // No rows at all for this user, use the default methods + $rowset[$user_id] = $this->notification_manager->get_default_methods(); } } @@ -516,22 +513,21 @@ abstract class base implements \phpbb\notification\type\type_interface { $this->notification_read = (bool) !$unread; - $where = array( - 'notification_type_id = ' . (int) $this->notification_type_id, - 'item_id = ' . (int) $this->item_id, - 'user_id = ' . (int) $this->user_id, - ); - $where = implode(' AND ', $where); - if ($return) { + $where = array( + 'notification_type_id = ' . (int) $this->notification_type_id, + 'item_id = ' . (int) $this->item_id, + 'user_id = ' . (int) $this->user_id, + ); + + $where = implode(' AND ', $where); return $where; } - - $sql = 'UPDATE ' . $this->notifications_table . ' - SET notification_read = ' . (int) $this->notification_read . ' - WHERE ' . $where; - $this->db->sql_query($sql); + else + { + $this->notification_manager->mark_notifications($this->get_type(), (int) $this->item_id, (int) $this->user_id, $this->notification_read); + } } /** diff --git a/phpBB/phpbb/notification/type/bookmark.php b/phpBB/phpbb/notification/type/bookmark.php index e6a695e875..4f66a1ef5c 100644 --- a/phpBB/phpbb/notification/type/bookmark.php +++ b/phpBB/phpbb/notification/type/bookmark.php @@ -91,31 +91,26 @@ class bookmark extends \phpbb\notification\type\post } // Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications - $update_notifications = array(); - $sql = 'SELECT n.* - FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt - WHERE n.notification_type_id = ' . (int) $this->notification_type_id . ' - AND n.item_parent_id = ' . (int) self::get_item_parent_id($post) . ' - AND n.notification_read = 0 - AND nt.notification_type_id = n.notification_type_id - AND nt.notification_type_enabled = 1'; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // Do not create a new notification - unset($notify_users[$row['user_id']]); + $notified_users = $this->notification_manager->get_notified_users($this->get_type(), array( + 'item_parent_id' => self::get_item_parent_id($post), + 'read' => 0, + )); - $notification = $this->notification_manager->get_item_type_class($this->get_type(), $row); + foreach ($notified_users as $user => $notification_data) + { + unset($notify_users[$user]); + + $notification = $this->notification_manager->get_item_type_class($this->get_type(), $notification_data); $update_responders = $notification->add_responders($post); if (!empty($update_responders)) { - $sql = 'UPDATE ' . $this->notifications_table . ' - SET ' . $this->db->sql_build_array('UPDATE', $update_responders) . ' - WHERE notification_id = ' . $row['notification_id']; - $this->db->sql_query($sql); + $this->notification_manager->update_notification($notification, $update_responders, array( + 'item_parent_id' => self::get_item_parent_id($post), + 'read' => 0, + 'user_id' => $user, + )); } } - $this->db->sql_freeresult($result); return $notify_users; } diff --git a/phpBB/phpbb/notification/type/disapprove_post.php b/phpBB/phpbb/notification/type/disapprove_post.php index 7021cdc837..21338bddb7 100644 --- a/phpBB/phpbb/notification/type/disapprove_post.php +++ b/phpBB/phpbb/notification/type/disapprove_post.php @@ -125,21 +125,24 @@ class disapprove_post extends \phpbb\notification\type\approve_post } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { $this->set_data('disapprove_reason', $post['disapprove_reason']); - $data = parent::create_insert_array($post); + parent::create_insert_array($post, $pre_create_data); - $this->notification_time = $data['notification_time'] = time(); + $this->notification_time = time(); + } + + /** + * {@inheritdoc} + */ + public function get_insert_array() + { + $data = parent::get_insert_array(); + $data['notification_time'] = $this->notification_time; return $data; } diff --git a/phpBB/phpbb/notification/type/disapprove_topic.php b/phpBB/phpbb/notification/type/disapprove_topic.php index 419cc5b2a6..30a23a83fe 100644 --- a/phpBB/phpbb/notification/type/disapprove_topic.php +++ b/phpBB/phpbb/notification/type/disapprove_topic.php @@ -125,21 +125,24 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { $this->set_data('disapprove_reason', $post['disapprove_reason']); - $data = parent::create_insert_array($post, $pre_create_data); + parent::create_insert_array($post, $pre_create_data); - $this->notification_time = $data['notification_time'] = time(); + $this->notification_time = time(); + } + + /** + * {@inheritdoc} + */ + public function get_insert_array() + { + $data = parent::get_insert_array(); + $data['notification_time'] = $this->notification_time; return $data; } diff --git a/phpBB/phpbb/notification/type/group_request.php b/phpBB/phpbb/notification/type/group_request.php index 2d7925c1b4..9a5746bcce 100644 --- a/phpBB/phpbb/notification/type/group_request.php +++ b/phpBB/phpbb/notification/type/group_request.php @@ -156,6 +156,6 @@ class group_request extends \phpbb\notification\type\base { $this->set_data('group_name', $group['group_name']); - return parent::create_insert_array($group, $pre_create_data); + parent::create_insert_array($group, $pre_create_data); } } diff --git a/phpBB/phpbb/notification/type/group_request_approved.php b/phpBB/phpbb/notification/type/group_request_approved.php index f282cdd158..dc353f3380 100644 --- a/phpBB/phpbb/notification/type/group_request_approved.php +++ b/phpBB/phpbb/notification/type/group_request_approved.php @@ -58,7 +58,7 @@ class group_request_approved extends \phpbb\notification\type\base foreach ($group['user_ids'] as $user_id) { - $users[$user_id] = array(''); + $users[$user_id] = $this->notification_manager->get_default_methods(); } return $users; @@ -87,7 +87,7 @@ class group_request_approved extends \phpbb\notification\type\base { $this->set_data('group_name', $group['group_name']); - return parent::create_insert_array($group, $pre_create_data); + parent::create_insert_array($group, $pre_create_data); } /** diff --git a/phpBB/phpbb/notification/type/pm.php b/phpBB/phpbb/notification/type/pm.php index 5d4f7fe0c6..6c66c9c057 100644 --- a/phpBB/phpbb/notification/type/pm.php +++ b/phpBB/phpbb/notification/type/pm.php @@ -176,13 +176,7 @@ class pm extends \phpbb\notification\type\base } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $pm Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($pm, $pre_create_data = array()) { @@ -190,6 +184,6 @@ class pm extends \phpbb\notification\type\base $this->set_data('message_subject', $pm['message_subject']); - return parent::create_insert_array($pm, $pre_create_data); + parent::create_insert_array($pm, $pre_create_data); } } diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php index f6b3136a21..e310484187 100644 --- a/phpBB/phpbb/notification/type/post.php +++ b/phpBB/phpbb/notification/type/post.php @@ -131,31 +131,26 @@ class post extends \phpbb\notification\type\base } // Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications - $update_notifications = array(); - $sql = 'SELECT n.* - FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt - WHERE n.notification_type_id = ' . (int) $this->notification_type_id . ' - AND n.item_parent_id = ' . (int) self::get_item_parent_id($post) . ' - AND n.notification_read = 0 - AND nt.notification_type_id = n.notification_type_id - AND nt.notification_type_enabled = 1'; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // Do not create a new notification - unset($notify_users[$row['user_id']]); + $notified_users = $this->notification_manager->get_notified_users($this->get_type(), array( + 'item_parent_id' => self::get_item_parent_id($post), + 'read' => 0, + )); - $notification = $this->notification_manager->get_item_type_class($this->get_type(), $row); + foreach ($notified_users as $user => $notification_data) + { + unset($notify_users[$user]); + + $notification = $this->notification_manager->get_item_type_class($this->get_type(), $notification_data); $update_responders = $notification->add_responders($post); if (!empty($update_responders)) { - $sql = 'UPDATE ' . $this->notifications_table . ' - SET ' . $this->db->sql_build_array('UPDATE', $update_responders) . ' - WHERE notification_id = ' . $row['notification_id']; - $this->db->sql_query($sql); + $this->notification_manager->update_notification($notification, $update_responders, array( + 'item_parent_id' => self::get_item_parent_id($post), + 'read' => 0, + 'user_id' => $user, + )); } } - $this->db->sql_freeresult($result); return $notify_users; } @@ -363,13 +358,7 @@ class post extends \phpbb\notification\type\base } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { @@ -394,7 +383,7 @@ class post extends \phpbb\notification\type\base $this->notification_read = true; } - return parent::create_insert_array($post, $pre_create_data); + parent::create_insert_array($post, $pre_create_data); } /** diff --git a/phpBB/phpbb/notification/type/post_in_queue.php b/phpBB/phpbb/notification/type/post_in_queue.php index e500ad33bc..8b21d77cdd 100644 --- a/phpBB/phpbb/notification/type/post_in_queue.php +++ b/phpBB/phpbb/notification/type/post_in_queue.php @@ -131,19 +131,22 @@ class post_in_queue extends \phpbb\notification\type\post } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { - $data = parent::create_insert_array($post, $pre_create_data); + parent::create_insert_array($post, $pre_create_data); - $this->notification_time = $data['notification_time'] = time(); + $this->notification_time = time(); + } + + /** + * {@inheritdoc} + */ + public function get_insert_array() + { + $data = parent::get_insert_array(); + $data['notification_time'] = $this->notification_time; return $data; } diff --git a/phpBB/phpbb/notification/type/quote.php b/phpBB/phpbb/notification/type/quote.php index 51edfec6f7..57f77bba83 100644 --- a/phpBB/phpbb/notification/type/quote.php +++ b/phpBB/phpbb/notification/type/quote.php @@ -109,22 +109,12 @@ class quote extends \phpbb\notification\type\post */ public function update_notifications($post) { - $old_notifications = array(); - $sql = 'SELECT n.user_id - FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt - WHERE n.notification_type_id = ' . (int) $this->notification_type_id . ' - AND n.item_id = ' . self::get_item_id($post) . ' - AND nt.notification_type_id = n.notification_type_id - AND nt.notification_type_enabled = 1'; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - $old_notifications[] = $row['user_id']; - } - $this->db->sql_freeresult($result); + $old_notifications = $this->notification_manager->get_notified_users($this->get_type(), array( + 'item_id' => self::get_item_id($post), + )); // Find the new users to notify - $notifications = $this->find_users_for_notification($post); + $notifications = array_keys($this->find_users_for_notification($post)); // Find the notifications we must delete $remove_notifications = array_diff($old_notifications, array_keys($notifications)); @@ -142,11 +132,7 @@ class quote extends \phpbb\notification\type\post // Remove the necessary notifications if (!empty($remove_notifications)) { - $sql = 'DELETE FROM ' . $this->notifications_table . ' - WHERE notification_type_id = ' . (int) $this->notification_type_id . ' - AND item_id = ' . self::get_item_id($post) . ' - AND ' . $this->db->sql_in_set('user_id', $remove_notifications); - $this->db->sql_query($sql); + $this->notification_manager->delete_notifications($this->get_type(), self::get_item_id($post), false, $remove_notifications); } // return true to continue with the update code in the notifications service (this will update the rest of the notifications) diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php index e7d385f59f..a68685547a 100644 --- a/phpBB/phpbb/notification/type/report_pm.php +++ b/phpBB/phpbb/notification/type/report_pm.php @@ -237,13 +237,7 @@ class report_pm extends \phpbb\notification\type\pm } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { @@ -252,6 +246,6 @@ class report_pm extends \phpbb\notification\type\pm $this->set_data('reason_description', $post['reason_description']); $this->set_data('report_text', $post['report_text']); - return parent::create_insert_array($post, $pre_create_data); + parent::create_insert_array($post, $pre_create_data); } } diff --git a/phpBB/phpbb/notification/type/report_pm_closed.php b/phpBB/phpbb/notification/type/report_pm_closed.php index 1c99db60c3..f793c7df9a 100644 --- a/phpBB/phpbb/notification/type/report_pm_closed.php +++ b/phpBB/phpbb/notification/type/report_pm_closed.php @@ -64,7 +64,7 @@ class report_pm_closed extends \phpbb\notification\type\pm return array(); } - return array($pm['reporter'] => array('')); + return array($pm['reporter'] => $this->notification_manager->get_default_methods()); } /** @@ -144,21 +144,24 @@ class report_pm_closed extends \phpbb\notification\type\pm } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $pm PM Data - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($pm, $pre_create_data = array()) { $this->set_data('closer_id', $pm['closer_id']); - $data = parent::create_insert_array($pm, $pre_create_data); + parent::create_insert_array($pm, $pre_create_data); - $this->notification_time = $data['notification_time'] = time(); + $this->notification_time = time(); + } + + /** + * {@inheritdoc} + */ + public function get_insert_array() + { + $data = parent::get_insert_array(); + $data['notification_time'] = $this->notification_time; return $data; } diff --git a/phpBB/phpbb/notification/type/report_post.php b/phpBB/phpbb/notification/type/report_post.php index 8289a04cf1..6eefd53832 100644 --- a/phpBB/phpbb/notification/type/report_post.php +++ b/phpBB/phpbb/notification/type/report_post.php @@ -210,13 +210,7 @@ class report_post extends \phpbb\notification\type\post_in_queue } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { @@ -225,6 +219,6 @@ class report_post extends \phpbb\notification\type\post_in_queue $this->set_data('reason_description', $post['reason_description']); $this->set_data('report_text', $post['report_text']); - return parent::create_insert_array($post, $pre_create_data); + parent::create_insert_array($post, $pre_create_data); } } diff --git a/phpBB/phpbb/notification/type/report_post_closed.php b/phpBB/phpbb/notification/type/report_post_closed.php index 3f4378628b..6327011f2d 100644 --- a/phpBB/phpbb/notification/type/report_post_closed.php +++ b/phpBB/phpbb/notification/type/report_post_closed.php @@ -71,7 +71,7 @@ class report_post_closed extends \phpbb\notification\type\post return array(); } - return array($post['reporter'] => array('')); + return array($post['reporter'] => $this->notification_manager->get_default_methods()); } /** @@ -151,21 +151,24 @@ class report_post_closed extends \phpbb\notification\type\post } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { $this->set_data('closer_id', $post['closer_id']); - $data = parent::create_insert_array($post, $pre_create_data); + parent::create_insert_array($post, $pre_create_data); - $this->notification_time = $data['notification_time'] = time(); + $this->notification_time = time(); + } + + /** + * {@inheritdoc} + */ + public function get_insert_array() + { + $data = parent::get_insert_array(); + $data['notification_time'] = $this->notification_time; return $data; } diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php index f0681b9eb8..22eb4bd526 100644 --- a/phpBB/phpbb/notification/type/topic.php +++ b/phpBB/phpbb/notification/type/topic.php @@ -263,13 +263,7 @@ class topic extends \phpbb\notification\type\base } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $post Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($post, $pre_create_data = array()) { @@ -290,6 +284,6 @@ class topic extends \phpbb\notification\type\base $this->notification_read = true; } - return parent::create_insert_array($post, $pre_create_data); + parent::create_insert_array($post, $pre_create_data); } } diff --git a/phpBB/phpbb/notification/type/topic_in_queue.php b/phpBB/phpbb/notification/type/topic_in_queue.php index cfdf748d38..ad2961525e 100644 --- a/phpBB/phpbb/notification/type/topic_in_queue.php +++ b/phpBB/phpbb/notification/type/topic_in_queue.php @@ -123,19 +123,22 @@ class topic_in_queue extends \phpbb\notification\type\topic } /** - * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) - * - * @param array $topic Data from submit_post - * @param array $pre_create_data Data from pre_create_insert_array() - * - * @return array Array of data ready to be inserted into the database + * {@inheritdoc} */ public function create_insert_array($topic, $pre_create_data = array()) { - $data = parent::create_insert_array($topic, $pre_create_data); + parent::create_insert_array($topic, $pre_create_data); - $this->notification_time = $data['notification_time'] = time(); + $this->notification_time = time(); + } + + /** + * {@inheritdoc} + */ + public function get_insert_array() + { + $data = parent::get_insert_array(); + $data['notification_time'] = $this->notification_time; return $data; } diff --git a/phpBB/phpbb/notification/type/type_interface.php b/phpBB/phpbb/notification/type/type_interface.php index 8844ce1a38..9b4446ac47 100644 --- a/phpBB/phpbb/notification/type/type_interface.php +++ b/phpBB/phpbb/notification/type/type_interface.php @@ -177,14 +177,18 @@ interface type_interface /** * Function for preparing the data for insertion in an SQL query - * (The service handles insertion) * * @param array $type_data The type specific data * @param array $pre_create_data Data from pre_create_insert_array() + */ + public function create_insert_array($type_data, $pre_create_data); + + /** + * Function for getting the data for insertion in an SQL query * * @return array Array of data ready to be inserted into the database */ - public function create_insert_array($type_data, $pre_create_data); + public function get_insert_array(); /** * Function for preparing the data for update in an SQL query diff --git a/phpBB/styles/prosilver/template/ucp_notifications.html b/phpBB/styles/prosilver/template/ucp_notifications.html index 500bae0c47..1255d7a0d0 100644 --- a/phpBB/styles/prosilver/template/ucp_notifications.html +++ b/phpBB/styles/prosilver/template/ucp_notifications.html @@ -16,7 +16,6 @@ {notification_methods.NAME} - {L_NOTIFICATIONS} @@ -34,7 +33,6 @@ checked="checked" /> - checked="checked" /> diff --git a/tests/functional/notification_test.php b/tests/functional/notification_test.php index ec03f7a6a4..5c6b87d50b 100644 --- a/tests/functional/notification_test.php +++ b/tests/functional/notification_test.php @@ -21,15 +21,15 @@ class phpbb_functional_notification_test extends phpbb_functional_test_case return array( // Rows inserted by phpBB/install/schemas/schema_data.sql // Also see PHPBB3-11460 - array('notification.type.post_notification', true), - array('notification.type.topic_notification', true), + array('notification.type.post_notification.method.board', true), + array('notification.type.topic_notification.method.board', true), array('notification.type.post_notification.method.email', true), array('notification.type.topic_notification.method.email', true), // Default behaviour for in-board notifications: // If user did not opt-out, in-board notifications are on. - array('notification.type.bookmark_notification', true), - array('notification.type.quote_notification', true), + array('notification.type.bookmark_notification.method.board', true), + array('notification.type.quote_notification.method.board', true), // Default behaviour for email notifications: // If user did not opt-in, email notifications are off. diff --git a/tests/mock/container_builder.php b/tests/mock/container_builder.php index 297e3a65e6..e04a83804d 100644 --- a/tests/mock/container_builder.php +++ b/tests/mock/container_builder.php @@ -52,7 +52,15 @@ class phpbb_mock_container_builder implements ContainerInterface { if ($this->has($id)) { - return $this->services[$id]; + $service = $this->services[$id]; + if (is_array($service) && is_callable($service[0])) + { + return call_user_func_array($service[0], $service[1]); + } + else + { + return $service; + } } throw new Exception('Could not find service: ' . $id); diff --git a/tests/mock/notification_manager.php b/tests/mock/notification_manager.php index 6a590bc0ca..952c0db489 100644 --- a/tests/mock/notification_manager.php +++ b/tests/mock/notification_manager.php @@ -32,19 +32,18 @@ class phpbb_mock_notification_manager ); } - public function mark_notifications_read() + public function mark_notifications() { } - public function mark_notifications_read_by_parent() + public function mark_notifications_by_parent() { } - public function mark_notifications_read_by_id() + public function mark_notifications_by_id() { } - public function add_notifications() { return array(); diff --git a/tests/mock/notification_type_post.php b/tests/mock/notification_type_post.php index 6d8f6dc504..fd2d1b63cd 100644 --- a/tests/mock/notification_type_post.php +++ b/tests/mock/notification_type_post.php @@ -21,7 +21,7 @@ if (!defined('IN_PHPBB')) class phpbb_mock_notification_type_post extends \phpbb\notification\type\post { - public function __construct($user_loader, $db, $cache, $user, $auth, $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) + public function __construct($user_loader, $db, $cache, $user, $auth, $config, $phpbb_root_path, $php_ext, $notification_types_table, $user_notifications_table) { $this->user_loader = $user_loader; $this->db = $db; @@ -34,7 +34,6 @@ class phpbb_mock_notification_type_post extends \phpbb\notification\type\post $this->php_ext = $php_ext; $this->notification_types_table = $notification_types_table; - $this->notifications_table = $notifications_table; - $this->user_notifications_table = $user_notifications_table; + $this->user_notifications_table = $user_notifications_table; } } diff --git a/tests/notification/base.php b/tests/notification/base.php index 45b0b6f179..c898c76947 100644 --- a/tests/notification/base.php +++ b/tests/notification/base.php @@ -39,6 +39,13 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case ); } + protected function get_notification_methods() + { + return array( + 'notification.method.board', + ); + } + protected function setUp() { parent::setUp(); @@ -55,6 +62,7 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case 'allow_bookmarks' => true, 'allow_topic_notify' => true, 'allow_forum_notify' => true, + 'allow_board_notifications' => true, )); $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); $lang = new \phpbb\language\language($lang_loader); @@ -87,7 +95,6 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case $phpbb_root_path, $phpEx, 'phpbb_notification_types', - 'phpbb_notifications', 'phpbb_user_notifications' ); @@ -107,6 +114,18 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case $this->notifications->set_var('notification_types', $types); + $methods = array(); + foreach ($this->get_notification_methods() as $method) + { + $method_parts = explode('.', $method); + $class = $this->build_type('phpbb\notification\method\\' . array_pop($method_parts)); + + $methods[$method] = $class; + $this->container->set($method, $class); + } + + $this->notifications->set_var('notification_methods', $methods); + $this->db->sql_query('DELETE FROM phpbb_notification_types'); $this->db->sql_query('DELETE FROM phpbb_notifications'); $this->db->sql_query('DELETE FROM phpbb_user_notifications'); @@ -116,7 +135,7 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case { global $phpbb_root_path, $phpEx; - $instance = new $type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_notifications', 'phpbb_user_notifications'); + $instance = new $type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_user_notifications'); if ($type === 'phpbb\\notification\\type\\quote') { @@ -126,9 +145,17 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case return $instance; } + protected function build_method($method) + { + global $phpbb_root_path, $phpEx; + + return new $method($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, + $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_notifications', 'phpbb_user_notifications'); + } + protected function assert_notifications($expected, $options = array()) { - $notifications = $this->notifications->load_notifications(array_merge(array( + $notifications = $this->notifications->load_notifications('notification.method.board', array_merge(array( 'count_unread' => true, 'order_by' => 'notification_time', 'order_dir' => 'ASC', diff --git a/tests/notification/ext/test/notification/type/test.php b/tests/notification/ext/test/notification/type/test.php index b02a563f06..7f3b4a4ef1 100644 --- a/tests/notification/ext/test/notification/type/test.php +++ b/tests/notification/ext/test/notification/type/test.php @@ -47,12 +47,13 @@ class test extends \phpbb\notification\type\base { $this->notification_time = $post['post_time']; - return parent::create_insert_array($post, $pre_create_data); + parent::create_insert_array($post, $pre_create_data); } public function create_update_array($type_data) { - $data = $this->create_insert_array($type_data); + $this->create_insert_array($type_data); + $data = $this->get_insert_array(); // Unset data unique to each row unset( diff --git a/tests/notification/fixtures/submit_post_notification.type.bookmark.xml b/tests/notification/fixtures/submit_post_notification.type.bookmark.xml index a1413e2cf8..7f069abc59 100644 --- a/tests/notification/fixtures/submit_post_notification.type.bookmark.xml +++ b/tests/notification/fixtures/submit_post_notification.type.bookmark.xml @@ -126,35 +126,35 @@ notification.type.bookmark 0 2 - + notification.method.board 1
            notification.type.bookmark 0 3 - + notification.method.board 1 notification.type.bookmark 0 4 - + notification.method.board 1 notification.type.bookmark 0 5 - + notification.method.board 1 notification.type.bookmark 0 6 - + notification.method.board 0 diff --git a/tests/notification/fixtures/submit_post_notification.type.post.xml b/tests/notification/fixtures/submit_post_notification.type.post.xml index ed75787c70..a4bf9d3ee4 100644 --- a/tests/notification/fixtures/submit_post_notification.type.post.xml +++ b/tests/notification/fixtures/submit_post_notification.type.post.xml @@ -156,49 +156,49 @@ notification.type.post 0 2 - + notification.method.board 1 notification.type.post 0 3 - + notification.method.board 1 notification.type.post 0 4 - + notification.method.board 1 notification.type.post 0 5 - + notification.method.board 1 notification.type.post 0 6 - + notification.method.board 1 notification.type.post 0 7 - + notification.method.board 1 notification.type.post 0 8 - + notification.method.board 1 diff --git a/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml b/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml index 2dea8e34dd..0a955c48d2 100644 --- a/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml +++ b/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml @@ -110,49 +110,49 @@ notification.type.needs_approval 0 2 - + notification.method.board 1 notification.type.needs_approval 0 3 - + notification.method.board 1 notification.type.needs_approval 0 4 - + notification.method.board 1 notification.type.needs_approval 0 5 - + notification.method.board 1 notification.type.needs_approval 0 6 - + notification.method.board 1 notification.type.needs_approval 0 7 - + notification.method.board 0 notification.type.needs_approval 0 9 - + notification.method.board 1 diff --git a/tests/notification/fixtures/submit_post_notification.type.quote.xml b/tests/notification/fixtures/submit_post_notification.type.quote.xml index dd5bc620cd..c66830fbf5 100644 --- a/tests/notification/fixtures/submit_post_notification.type.quote.xml +++ b/tests/notification/fixtures/submit_post_notification.type.quote.xml @@ -98,35 +98,35 @@ notification.type.quote 0 2 - + notification.method.board 1 notification.type.quote 0 3 - + notification.method.board 1 notification.type.quote 0 4 - + notification.method.board 1 notification.type.quote 0 5 - + notification.method.board 1 notification.type.quote 0 6 - + notification.method.board 0 diff --git a/tests/notification/fixtures/submit_post_notification.type.topic.xml b/tests/notification/fixtures/submit_post_notification.type.topic.xml index 1ba8d05699..e0f6583f48 100644 --- a/tests/notification/fixtures/submit_post_notification.type.topic.xml +++ b/tests/notification/fixtures/submit_post_notification.type.topic.xml @@ -106,28 +106,28 @@ notification.type.topic 0 2 - + notification.method.board 1 notification.type.topic 0 6 - + notification.method.board 1 notification.type.topic 0 7 - + notification.method.board 1 notification.type.topic 0 8 - + notification.method.board 1 diff --git a/tests/notification/manager_helper.php b/tests/notification/manager_helper.php index 48bf5b177b..40cf9b3ad4 100644 --- a/tests/notification/manager_helper.php +++ b/tests/notification/manager_helper.php @@ -46,7 +46,7 @@ class phpbb_notification_manager_helper extends \phpbb\notification\manager $item_parts = explode('.', $item_type); $item_type = 'phpbb\notification\type\\' . array_pop($item_parts); - $item = new $item_type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, $this->notifications_table, $this->user_notifications_table); + $item = new $item_type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, $this->user_notifications_table); if ($item_type === 'phpbb\\notification\\type\\quote') { @@ -65,9 +65,10 @@ class phpbb_notification_manager_helper extends \phpbb\notification\manager */ public function get_method_class($method_name) { - $method_name = 'phpbb\notification\method\\' . $method_name; + $method_parts = explode('.', $method_name); + $method_name = 'phpbb\notification\method\\' . array_pop($method_parts); - $method = new $method_name($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, $this->notifications_table, $this->user_notifications_table); + $method = new $method_name($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, NOTIFICATIONS_TABLE, $this->user_notifications_table); $method->set_notification_manager($this); diff --git a/tests/notification/notification_test.php b/tests/notification/notification_test.php index 79fa5338c4..167cde13ca 100644 --- a/tests/notification/notification_test.php +++ b/tests/notification/notification_test.php @@ -29,7 +29,7 @@ class phpbb_notification_test extends phpbb_tests_notification_base $quote_type_id = $this->notifications->get_notification_type_id('notification.type.quote'); $test_type_id = $this->notifications->get_notification_type_id('test'); - $this->assertEquals(array( + self::assertEquals(array( 'test' => $test_type_id, 'notification.type.quote' => $quote_type_id, 'notification.type.post' => $post_type_id, @@ -40,13 +40,13 @@ class phpbb_notification_test extends phpbb_tests_notification_base 'notification.type.post', ) )); - $this->assertEquals($quote_type_id, $this->notifications->get_notification_type_id('notification.type.quote')); + self::assertEquals($quote_type_id, $this->notifications->get_notification_type_id('notification.type.quote')); try { - $this->assertEquals(false, $this->notifications->get_notification_type_id('fail')); + self::assertEquals(false, $this->notifications->get_notification_type_id('fail')); - $this->fail('Non-existent type should throw an exception'); + self::fail('Non-existent type should throw an exception'); } catch (Exception $e) {} } @@ -55,15 +55,15 @@ class phpbb_notification_test extends phpbb_tests_notification_base { $subscription_types = $this->notifications->get_subscription_types(); - $this->assertArrayHasKey('NOTIFICATION_GROUP_MISCELLANEOUS', $subscription_types); - $this->assertArrayHasKey('NOTIFICATION_GROUP_POSTING', $subscription_types); + self::assertArrayHasKey('NOTIFICATION_GROUP_MISCELLANEOUS', $subscription_types); + self::assertArrayHasKey('NOTIFICATION_GROUP_POSTING', $subscription_types); - $this->assertArrayHasKey('notification.type.bookmark', $subscription_types['NOTIFICATION_GROUP_POSTING']); - $this->assertArrayHasKey('notification.type.post', $subscription_types['NOTIFICATION_GROUP_POSTING']); - $this->assertArrayHasKey('notification.type.quote', $subscription_types['NOTIFICATION_GROUP_POSTING']); - $this->assertArrayHasKey('notification.type.topic', $subscription_types['NOTIFICATION_GROUP_POSTING']); + self::assertArrayHasKey('notification.type.bookmark', $subscription_types['NOTIFICATION_GROUP_POSTING']); + self::assertArrayHasKey('notification.type.post', $subscription_types['NOTIFICATION_GROUP_POSTING']); + self::assertArrayHasKey('notification.type.quote', $subscription_types['NOTIFICATION_GROUP_POSTING']); + self::assertArrayHasKey('notification.type.topic', $subscription_types['NOTIFICATION_GROUP_POSTING']); - $this->assertArrayHasKey('notification.type.pm', $subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']); + self::assertArrayHasKey('notification.type.pm', $subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']); //get_subscription_types //get_subscription_methods @@ -72,12 +72,12 @@ class phpbb_notification_test extends phpbb_tests_notification_base public function test_subscriptions() { $expected_subscriptions = array( - 'notification.type.post' => array(''), - 'notification.type.topic' => array(''), - 'notification.type.quote' => array(''), - 'notification.type.bookmark' => array(''), - 'test' => array(''), - 'notification.type.pm' => array(''), + 'notification.type.post' => array('notification.method.board'), + 'notification.type.topic' => array('notification.method.board'), + 'notification.type.quote' => array('notification.method.board'), + 'notification.type.bookmark' => array('notification.method.board'), + 'test' => array('notification.method.board'), + 'notification.type.pm' => array('notification.method.board'), ); $subscriptions = $this->notifications->get_global_subscriptions(2); @@ -89,16 +89,16 @@ class phpbb_notification_test extends phpbb_tests_notification_base foreach ($subscriptions as $item_type => $methods) { - $this->assert_array_content_equals($methods, $expected_subscriptions[$item_type]); + $this->assert_array_content_equals($methods, $expected_subscriptions[$item_type]); } - $this->notifications->delete_subscription('notification.type.post', 0, '', 2); + $this->notifications->delete_subscription('notification.type.post', 0, 'notification.method.board', 2); - $this->assertArrayNotHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2)); + self::assertArrayNotHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2)); - $this->notifications->add_subscription('notification.type.post', 0, '', 2); + $this->notifications->add_subscription('notification.type.post', 0, 'notification.method.board', 2); - $this->assertArrayHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2)); + self::assertArrayHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2)); } public function test_notifications() @@ -124,11 +124,11 @@ class phpbb_notification_test extends phpbb_tests_notification_base 'user_id' => 0, ))); - $this->assertEquals(array( + self::assertEquals(array( 'notifications' => array(), 'unread_count' => 0, 'total_count' => 0, - ), $this->notifications->load_notifications(array( + ), $this->notifications->load_notifications('notification.method.board', array( 'count_unread' => true, ))); diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php index 04fb6658c3..73711369ed 100644 --- a/tests/notification/submit_post_base.php +++ b/tests/notification/submit_post_base.php @@ -50,7 +50,7 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c { parent::setUp(); - global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $request, $phpEx, $phpbb_root_path; + global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $request, $phpEx, $phpbb_root_path, $user_loader; // Database $this->db = $this->new_dbal(); @@ -69,7 +69,11 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c ))); // Config - $config = new \phpbb\config\config(array('num_topics' => 1,'num_posts' => 1,)); + $config = new \phpbb\config\config(array( + 'num_topics' => 1, + 'num_posts' => 1, + 'allow_board_notifications' => true, + )); $cache = new \phpbb\cache\service( new \phpbb\cache\driver\dummy(), @@ -111,30 +115,46 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c $notification_types_array = array(); foreach ($notification_types as $type) { - $class_name = '\phpbb\notification\type\\' . $type; - $class = new $class_name( - $user_loader, $db, $cache->get_driver(), $user, $auth, $config, - $phpbb_root_path, $phpEx, - NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE, USER_NOTIFICATIONS_TABLE); - - if ($type === 'quote') - { - $class->set_utils(new \phpbb\textformatter\s9e\utils); - } - - $phpbb_container->set('notification.type.' . $type, $class); - + $class = $this->build_type($type); + $phpbb_container->set('notification.type.' . $type, array(array($this, 'build_type'), array($type))); $notification_types_array['notification.type.' . $type] = $class; } + // Methods Types + $class_name = 'phpbb\notification\method\board'; + $class = new $class_name( + $user_loader, $db, $cache->get_driver(), $user, $auth, $config, + $phpbb_root_path, $phpEx, + NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE); + $phpbb_container->set('notification.method.board', $class); + $notification_methods_array = array('notification.method.board' => $class); + // Notification Manager - $phpbb_notifications = new \phpbb\notification\manager($notification_types_array, array(), + $phpbb_notifications = new \phpbb\notification\manager($notification_types_array, $notification_methods_array, $phpbb_container, $user_loader, $config, $phpbb_dispatcher, $db, $cache, $user, $phpbb_root_path, $phpEx, - NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE, USER_NOTIFICATIONS_TABLE); + NOTIFICATION_TYPES_TABLE, USER_NOTIFICATIONS_TABLE); $phpbb_container->set('notification_manager', $phpbb_notifications); } + public function build_type($type) + { + global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $request, $phpEx, $phpbb_root_path, $user_loader; + + $class_name = '\phpbb\notification\type\\' . $type; + $class = new $class_name( + $user_loader, $db, $cache->get_driver(), $user, $auth, $config, + $phpbb_root_path, $phpEx, + NOTIFICATION_TYPES_TABLE, USER_NOTIFICATIONS_TABLE); + + if ($type === 'quote') + { + $class->set_utils(new \phpbb\textformatter\s9e\utils); + } + + return $class; + } + /** * @dataProvider submit_post_data */ @@ -157,4 +177,11 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c $this->assertEquals($expected_after, $this->db->sql_fetchrowset($result)); $this->db->sql_freeresult($result); } + + protected function build_method($method) + { + global $phpbb_root_path, $phpEx; + + return new $method($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_notifications', 'phpbb_user_notifications'); + } } diff --git a/tests/notification/user_list_trim_test.php b/tests/notification/user_list_trim_test.php index f7b4fcb215..d57fbf0485 100644 --- a/tests/notification/user_list_trim_test.php +++ b/tests/notification/user_list_trim_test.php @@ -61,7 +61,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case $user_loader->load_users(array(2, 3, 4, 5, 6)); $this->notification = new phpbb_mock_notification_type_post( - $user_loader, null, null, $user, null, null, $phpbb_root_path, $phpEx, null, null, null + $user_loader, null, null, $user, null, null, $phpbb_root_path, $phpEx, null, null ); } From 06077d9970d16338f34c67dfec82e20ee703ddb0 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 8 Jul 2015 23:42:29 +0200 Subject: [PATCH 0499/1676] [ticket/11444] BC layer PHPBB3-11444 --- phpBB/includes/ucp/ucp_notifications.php | 2 +- phpBB/phpbb/notification/manager.php | 30 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/ucp/ucp_notifications.php b/phpBB/includes/ucp/ucp_notifications.php index 8e9fe2dfc1..c291cc1ddf 100644 --- a/phpBB/includes/ucp/ucp_notifications.php +++ b/phpBB/includes/ucp/ucp_notifications.php @@ -219,7 +219,7 @@ class ucp_notifications { $notification_methods = $phpbb_notifications->get_subscription_methods(); - foreach($notification_methods as $method => $method_data) + foreach ($notification_methods as $method => $method_data) { $template->assign_block_vars($block, array( 'METHOD' => $method_data['id'], diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index 6b69dca817..92c0703321 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -143,6 +143,21 @@ class manager } } + /** + * Mark notifications read or unread for all available methods + * + * @param bool|string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types + * @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids + * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids + * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False) + * + * @deprecated since 3.2 + */ + public function mark_notifications_read($notification_type_name, $item_id, $user_id, $time = false) + { + $this->mark_notifications($notification_type_name, $item_id, $user_id, $time); + } + /** * Mark notifications read or unread for all available methods * @@ -173,6 +188,21 @@ class manager } } + /** + * Mark notifications read or unread from a parent identifier for all available methods + * + * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types) + * @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids + * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids + * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False) + * + * @deprecated since 3.2 + */ + public function mark_notifications_read_by_parent($notification_type_name, $item_parent_id, $user_id, $time = false) + { + $this->mark_notifications_by_parent($notification_type_name, $item_parent_id, $user_id, $time); + } + /** * Mark notifications read or unread from a parent identifier for all available methods * From f29b12e35397ef4a4996ea7d212f0ab5a7a1dba6 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 9 Jul 2015 14:28:34 +0200 Subject: [PATCH 0500/1676] [ticket/11444] Cleanup method constructors PHPBB3-11444 --- .../container/services_notification.yml | 12 ---- phpBB/phpbb/notification/manager.php | 20 +------ phpBB/phpbb/notification/method/base.php | 55 ------------------- phpBB/phpbb/notification/method/board.php | 26 ++++++--- phpBB/phpbb/notification/method/email.php | 23 ++++++++ phpBB/phpbb/notification/method/jabber.php | 25 ++++++++- .../notification/method/messenger_base.php | 24 +++++++- 7 files changed, 89 insertions(+), 96 deletions(-) diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index 7c335eaba0..264ed1dbb9 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -6,13 +6,10 @@ services: - @notification.method_collection - @service_container - @user_loader - - @config - @dispatcher - @dbal.conn - @cache - @user - - %core.root_path% - - %core.php_ext% - %tables.notification_types% - %tables.user_notifications% @@ -350,10 +347,7 @@ services: - @dbal.conn - @cache.driver - @user - - @auth - @config - - %core.root_path% - - %core.php_ext% - %tables.notification_types% - %tables.notifications% tags: @@ -364,10 +358,7 @@ services: scope: prototype arguments: - @user_loader - - @dbal.conn - - @cache.driver - @user - - @auth - @config - %core.root_path% - %core.php_ext% @@ -379,10 +370,7 @@ services: scope: prototype arguments: - @user_loader - - @dbal.conn - - @cache.driver - @user - - @auth - @config - %core.root_path% - %core.php_ext% diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index 92c0703321..9a8b671ef8 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -13,7 +13,7 @@ namespace phpbb\notification; -use \Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Notifications service class @@ -35,9 +35,6 @@ class manager /** @var \phpbb\user_loader */ protected $user_loader; - /** @var \phpbb\config\config */ - protected $config; - /** @var \phpbb\event\dispatcher_interface */ protected $phpbb_dispatcher; @@ -50,12 +47,6 @@ class manager /** @var \phpbb\user */ protected $user; - /** @var string */ - protected $phpbb_root_path; - - /** @var string */ - protected $php_ext; - /** @var string */ protected $notification_types_table; @@ -69,34 +60,27 @@ class manager * @param array $notification_methods * @param ContainerInterface $phpbb_container * @param \phpbb\user_loader $user_loader - * @param \phpbb\config\config $config * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher * @param \phpbb\db\driver\driver_interface $db * @param \phpbb\cache\service $cache * @param \phpbb\user $user - * @param string $phpbb_root_path - * @param string $php_ext * @param string $notification_types_table * @param string $user_notifications_table * * @return \phpbb\notification\manager */ - public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $user_notifications_table) + public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\user $user, $notification_types_table, $user_notifications_table) { $this->notification_types = $notification_types; $this->notification_methods = $notification_methods; $this->phpbb_container = $phpbb_container; $this->user_loader = $user_loader; - $this->config = $config; $this->phpbb_dispatcher = $phpbb_dispatcher; $this->db = $db; $this->cache = $cache; $this->user = $user; - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $php_ext; - $this->notification_types_table = $notification_types_table; $this->user_notifications_table = $user_notifications_table; } diff --git a/phpBB/phpbb/notification/method/base.php b/phpBB/phpbb/notification/method/base.php index 240b2ddbac..4a183ca508 100644 --- a/phpBB/phpbb/notification/method/base.php +++ b/phpBB/phpbb/notification/method/base.php @@ -21,36 +21,6 @@ abstract class base implements \phpbb\notification\method\method_interface /** @var \phpbb\notification\manager */ protected $notification_manager; - /** @var \phpbb\user_loader */ - protected $user_loader; - - /** @var \phpbb\db\driver\driver_interface */ - protected $db; - - /** @var \phpbb\cache\driver\driver_interface */ - protected $cache; - - /** @var \phpbb\template\template */ - protected $template; - - /** @var \phpbb\extension\manager */ - protected $extension_manager; - - /** @var \phpbb\user */ - protected $user; - - /** @var \phpbb\auth\auth */ - protected $auth; - - /** @var \phpbb\config\config */ - protected $config; - - /** @var string */ - protected $phpbb_root_path; - - /** @var string */ - protected $php_ext; - /** * Queue of messages to be sent * @@ -58,31 +28,6 @@ abstract class base implements \phpbb\notification\method\method_interface */ protected $queue = array(); - /** - * Notification Method Base Constructor - * - * @param \phpbb\user_loader $user_loader - * @param \phpbb\db\driver\driver_interface $db - * @param \phpbb\cache\driver\driver_interface $cache - * @param \phpbb\user $user - * @param \phpbb\auth\auth $auth - * @param \phpbb\config\config $config - * @param string $phpbb_root_path - * @param string $php_ext - * @return \phpbb\notification\method\base - */ - public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext) - { - $this->user_loader = $user_loader; - $this->db = $db; - $this->cache = $cache; - $this->user = $user; - $this->auth = $auth; - $this->config = $config; - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $php_ext; - } - /** * Set notification manager (required) * diff --git a/phpBB/phpbb/notification/method/board.php b/phpBB/phpbb/notification/method/board.php index 99853e2f81..c45f3a8caa 100644 --- a/phpBB/phpbb/notification/method/board.php +++ b/phpBB/phpbb/notification/method/board.php @@ -21,6 +21,21 @@ namespace phpbb\notification\method; */ class board extends \phpbb\notification\method\base { + /** @var \phpbb\user_loader */ + protected $user_loader; + + /** @var \phpbb\db\driver\driver_interface */ + protected $db; + + /** @var \phpbb\cache\driver\driver_interface */ + protected $cache; + + /** @var \phpbb\user */ + protected $user; + + /** @var \phpbb\config\config */ + protected $config; + /** @var string */ protected $notification_types_table; @@ -34,27 +49,20 @@ class board extends \phpbb\notification\method\base * @param \phpbb\db\driver\driver_interface $db * @param \phpbb\cache\driver\driver_interface $cache * @param \phpbb\user $user - * @param \phpbb\auth\auth $auth * @param \phpbb\config\config $config - * @param string $phpbb_root_path - * @param string $php_ext * @param string $notification_types_table * @param string $notifications_table - * @return \phpbb\notification\method\board */ - public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table) + public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, \phpbb\user $user, \phpbb\config\config $config, $notification_types_table, $notifications_table) { $this->user_loader = $user_loader; $this->db = $db; $this->cache = $cache; $this->user = $user; - $this->auth = $auth; $this->config = $config; - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $php_ext; - $this->notification_types_table = $notification_types_table; $this->notifications_table = $notifications_table; + } /** diff --git a/phpBB/phpbb/notification/method/email.php b/phpBB/phpbb/notification/method/email.php index a4b93bc85c..21a6559012 100644 --- a/phpBB/phpbb/notification/method/email.php +++ b/phpBB/phpbb/notification/method/email.php @@ -20,6 +20,29 @@ namespace phpbb\notification\method; class email extends \phpbb\notification\method\messenger_base { + /** @var \phpbb\user */ + protected $user; + + /** @var \phpbb\config\config */ + protected $config; + + /** + * Notification Method email Constructor + * + * @param \phpbb\user_loader $user_loader + * @param \phpbb\user $user + * @param \phpbb\config\config $config + * @param string $phpbb_root_path + * @param string $php_ext + */ + public function __construct(\phpbb\user_loader $user_loader, \phpbb\user $user, \phpbb\config\config $config, $phpbb_root_path, $php_ext) + { + parent::__construct($user_loader, $phpbb_root_path, $php_ext); + + $this->user = $user; + $this->config = $config; + } + /** * Get notification method name * diff --git a/phpBB/phpbb/notification/method/jabber.php b/phpBB/phpbb/notification/method/jabber.php index 09f186e3ca..509c6b432c 100644 --- a/phpBB/phpbb/notification/method/jabber.php +++ b/phpBB/phpbb/notification/method/jabber.php @@ -20,6 +20,29 @@ namespace phpbb\notification\method; class jabber extends \phpbb\notification\method\messenger_base { + /** @var \phpbb\user */ + protected $user; + + /** @var \phpbb\config\config */ + protected $config; + + /** + * Notification Method jabber Constructor + * + * @param \phpbb\user_loader $user_loader + * @param \phpbb\user $user + * @param \phpbb\config\config $config + * @param string $phpbb_root_path + * @param string $php_ext + */ + public function __construct(\phpbb\user_loader $user_loader, \phpbb\user $user, \phpbb\config\config $config, $phpbb_root_path, $php_ext) + { + parent::__construct($user_loader, $phpbb_root_path, $php_ext); + + $this->user = $user; + $this->config = $config; + } + /** * Get notification method name * @@ -61,6 +84,6 @@ class jabber extends \phpbb\notification\method\messenger_base return; } - return $this->notify_using_messenger(NOTIFY_IM, 'short/'); + $this->notify_using_messenger(NOTIFY_IM, 'short/'); } } diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index bde4573117..74a1811155 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -19,6 +19,29 @@ namespace phpbb\notification\method; */ abstract class messenger_base extends \phpbb\notification\method\base { + /** @var \phpbb\user_loader */ + protected $user_loader; + + /** @var string */ + protected $phpbb_root_path; + + /** @var string */ + protected $php_ext; + + /** + * Notification Method Board Constructor + * + * @param \phpbb\user_loader $user_loader + * @param string $phpbb_root_path + * @param string $php_ext + */ + public function __construct(\phpbb\user_loader $user_loader, $phpbb_root_path, $php_ext) + { + $this->user_loader = $user_loader; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + } + /** * Notify using phpBB messenger * @@ -57,7 +80,6 @@ abstract class messenger_base extends \phpbb\notification\method\base include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); } $messenger = new \messenger(); - $board_url = generate_board_url(); // Time to go through the queue and send emails foreach ($this->queue as $notification) From fc34057f288c6b8c656a0ed1ac2cb5a86f86206d Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 9 Jul 2015 17:04:40 +0200 Subject: [PATCH 0501/1676] [ticket/11444] Update tests and cleanup types/methods PHPBB3-11444 --- .../container/services_notification.yml | 254 ++++-------------- phpBB/phpbb/notification/manager.php | 26 +- .../notification/type/admin_activate_user.php | 16 ++ phpBB/phpbb/notification/type/base.php | 25 +- phpBB/phpbb/notification/type/bookmark.php | 9 + .../phpbb/notification/type/group_request.php | 8 + phpBB/phpbb/notification/type/pm.php | 16 ++ phpBB/phpbb/notification/type/post.php | 17 ++ phpBB/phpbb/notification/type/report_pm.php | 2 + phpBB/phpbb/notification/type/topic.php | 16 ++ tests/mock/container_builder.php | 5 + tests/notification/base.php | 54 ++-- .../fixtures/services_notification.yml | 70 +++++ tests/notification/manager_helper.php | 37 --- tests/notification/notification_test.php | 2 +- tests/notification/submit_post_base.php | 71 +++-- .../submit_post_type_quote_test.php | 3 +- .../phpbb_test_case_helpers.php | 34 ++- 18 files changed, 309 insertions(+), 356 deletions(-) create mode 100644 tests/notification/fixtures/services_notification.yml diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index 264ed1dbb9..f82dd4b5a5 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -22,190 +22,110 @@ services: tags: - { name: service_collection, tag: notification.type } + notification.type.base: + abstract: true + arguments: + - @dbal.conn + - @user + - @auth + - %core.root_path% + - %core.php_ext% + - %tables.user_notifications% + + notification.type.admin_activate_user: + class: phpbb\notification\type\admin_activate_user + scope: prototype + parent: notification.type.base + calls: + - [set_user_loader, ["@user_loader"]] + - [set_config, ["@config"]] + tags: + - { name: notification.type } + notification.type.approve_post: class: phpbb\notification\type\approve_post scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.approve_topic: class: phpbb\notification\type\approve_topic scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.bookmark: class: phpbb\notification\type\bookmark scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base + calls: + - [set_config, ["@config"]] tags: - { name: notification.type } notification.type.disapprove_post: class: phpbb\notification\type\disapprove_post scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.disapprove_topic: class: phpbb\notification\type\disapprove_topic scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.group_request: class: phpbb\notification\type\group_request scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base + calls: + - [set_user_loader, ["@user_loader"]] tags: - { name: notification.type } notification.type.group_request_approved: class: phpbb\notification\type\group_request_approved scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.pm: class: phpbb\notification\type\pm scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base + calls: + - [set_user_loader, ["@user_loader"]] + - [set_config, ["@config"]] tags: - { name: notification.type } notification.type.post: class: phpbb\notification\type\post scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base + calls: + - [set_user_loader, ["@user_loader"]] + - [set_config, ["@config"]] tags: - { name: notification.type } notification.type.post_in_queue: class: phpbb\notification\type\post_in_queue scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.quote: class: phpbb\notification\type\quote scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base calls: - [set_utils, [@text_formatter.utils]] tags: @@ -214,119 +134,45 @@ services: notification.type.report_pm: class: phpbb\notification\type\report_pm scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.report_pm_closed: class: phpbb\notification\type\report_pm_closed scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.report_post: class: phpbb\notification\type\report_post scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.report_post_closed: class: phpbb\notification\type\report_post_closed scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } notification.type.topic: class: phpbb\notification\type\topic scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base + calls: + - [set_user_loader, ["@user_loader"]] + - [set_config, ["@config"]] tags: - { name: notification.type } notification.type.topic_in_queue: class: phpbb\notification\type\topic_in_queue scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% - tags: - - { name: notification.type } - - notification.type.admin_activate_user: - class: phpbb\notification\type\admin_activate_user - scope: prototype - arguments: - - @user_loader - - @dbal.conn - - @cache.driver - - @user - - @auth - - @config - - %core.root_path% - - %core.php_ext% - - %tables.notification_types% - - %tables.user_notifications% + parent: notification.type.base tags: - { name: notification.type } diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index 9a8b671ef8..04259382ba 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -26,7 +26,7 @@ class manager /** @var array */ protected $subscription_types; - /** @var array */ + /** @var method\method_interface[] */ protected $notification_methods; /** @var ContainerInterface */ @@ -805,8 +805,10 @@ class manager } /** - * Helper to get the list of methods enabled by default - */ + * Helper to get the list of methods enabled by default + * + * @return method\method_interface[] + */ public function get_default_methods() { $default_methods = array(); @@ -823,8 +825,10 @@ class manager } /** - * Helper to get the notifications item type class and set it up - */ + * Helper to get the notifications item type class and set it up + * + * @return type\type_interface + */ public function get_item_type_class($notification_type_name, $data = array()) { $item = $this->load_object($notification_type_name); @@ -835,16 +839,20 @@ class manager } /** - * Helper to get the notifications method class and set it up - */ + * Helper to get the notifications method class and set it up + * + * @return method\method_interface + */ public function get_method_class($method_name) { return $this->load_object($method_name); } /** - * Helper to load objects (notification types/methods) - */ + * Helper to load objects (notification types/methods) + * + * @return method\method_interface|type\type_interface + */ protected function load_object($object_name) { $object = $this->phpbb_container->get($object_name); diff --git a/phpBB/phpbb/notification/type/admin_activate_user.php b/phpBB/phpbb/notification/type/admin_activate_user.php index 5b7e58bd92..b191fa62ae 100644 --- a/phpBB/phpbb/notification/type/admin_activate_user.php +++ b/phpBB/phpbb/notification/type/admin_activate_user.php @@ -41,6 +41,22 @@ class admin_activate_user extends \phpbb\notification\type\base 'group' => 'NOTIFICATION_GROUP_ADMINISTRATION', ); + /** @var \phpbb\user_loader */ + protected $user_loader; + + /** @var \phpbb\config\config */ + protected $config; + + public function set_config(\phpbb\config\config $config) + { + $this->config = $config; + } + + public function set_user_loader(\phpbb\user_loader $user_loader) + { + $this->user_loader = $user_loader; + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php index 843ab98de8..06f7f9c615 100644 --- a/phpBB/phpbb/notification/type/base.php +++ b/phpBB/phpbb/notification/type/base.php @@ -21,36 +21,21 @@ abstract class base implements \phpbb\notification\type\type_interface /** @var \phpbb\notification\manager */ protected $notification_manager; - /** @var \phpbb\user_loader */ - protected $user_loader; - /** @var \phpbb\db\driver\driver_interface */ protected $db; - /** @var \phpbb\cache\driver\driver_interface */ - protected $cache; - - /** @var \phpbb\template\template */ - protected $template; - /** @var \phpbb\user */ protected $user; /** @var \phpbb\auth\auth */ protected $auth; - /** @var \phpbb\config\config */ - protected $config; - /** @var string */ protected $phpbb_root_path; /** @var string */ protected $php_ext; - /** @var string */ - protected $notification_types_table; - /** @var string */ protected $user_notifications_table; @@ -88,31 +73,23 @@ abstract class base implements \phpbb\notification\type\type_interface /** * Notification Type Base Constructor * - * @param \phpbb\user_loader $user_loader * @param \phpbb\db\driver\driver_interface $db - * @param \phpbb\cache\driver\driver_interface $cache * @param \phpbb\user $user * @param \phpbb\auth\auth $auth - * @param \phpbb\config\config $config * @param string $phpbb_root_path * @param string $php_ext - * @param string $notification_types_table * @param string $user_notifications_table * @return \phpbb\notification\type\base */ - public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $user_notifications_table) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext, $user_notifications_table) { - $this->user_loader = $user_loader; $this->db = $db; - $this->cache = $cache; $this->user = $user; $this->auth = $auth; - $this->config = $config; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - $this->notification_types_table = $notification_types_table; $this->user_notifications_table = $user_notifications_table; } diff --git a/phpBB/phpbb/notification/type/bookmark.php b/phpBB/phpbb/notification/type/bookmark.php index 4f66a1ef5c..59423ca248 100644 --- a/phpBB/phpbb/notification/type/bookmark.php +++ b/phpBB/phpbb/notification/type/bookmark.php @@ -48,6 +48,14 @@ class bookmark extends \phpbb\notification\type\post 'group' => 'NOTIFICATION_GROUP_POSTING', ); + /** @var \phpbb\config\config */ + protected $config; + + public function set_config(\phpbb\config\config $config) + { + $this->config = $config; + } + /** * Is available */ @@ -100,6 +108,7 @@ class bookmark extends \phpbb\notification\type\post { unset($notify_users[$user]); + /** @var bookmark $notification */ $notification = $this->notification_manager->get_item_type_class($this->get_type(), $notification_data); $update_responders = $notification->add_responders($post); if (!empty($update_responders)) diff --git a/phpBB/phpbb/notification/type/group_request.php b/phpBB/phpbb/notification/type/group_request.php index 9a5746bcce..8a0027bfec 100644 --- a/phpBB/phpbb/notification/type/group_request.php +++ b/phpBB/phpbb/notification/type/group_request.php @@ -30,6 +30,14 @@ class group_request extends \phpbb\notification\type\base 'lang' => 'NOTIFICATION_TYPE_GROUP_REQUEST', ); + /** @var \phpbb\user_loader */ + protected $user_loader; + + public function set_user_loader(\phpbb\user_loader $user_loader) + { + $this->user_loader = $user_loader; + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/notification/type/pm.php b/phpBB/phpbb/notification/type/pm.php index 6c66c9c057..2de2dcfa0b 100644 --- a/phpBB/phpbb/notification/type/pm.php +++ b/phpBB/phpbb/notification/type/pm.php @@ -40,6 +40,22 @@ class pm extends \phpbb\notification\type\base 'lang' => 'NOTIFICATION_TYPE_PM', ); + /** @var \phpbb\user_loader */ + protected $user_loader; + + /** @var \phpbb\config\config */ + protected $config; + + public function set_config(\phpbb\config\config $config) + { + $this->config = $config; + } + + public function set_user_loader(\phpbb\user_loader $user_loader) + { + $this->user_loader = $user_loader; + } + /** * Is available */ diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php index e310484187..f3dd6d531a 100644 --- a/phpBB/phpbb/notification/type/post.php +++ b/phpBB/phpbb/notification/type/post.php @@ -55,6 +55,22 @@ class post extends \phpbb\notification\type\base 'group' => 'NOTIFICATION_GROUP_POSTING', ); + /** @var \phpbb\user_loader */ + protected $user_loader; + + /** @var \phpbb\config\config */ + protected $config; + + public function set_config(\phpbb\config\config $config) + { + $this->config = $config; + } + + public function set_user_loader(\phpbb\user_loader $user_loader) + { + $this->user_loader = $user_loader; + } + /** * Is available */ @@ -140,6 +156,7 @@ class post extends \phpbb\notification\type\base { unset($notify_users[$user]); + /** @var post $notification */ $notification = $this->notification_manager->get_item_type_class($this->get_type(), $notification_data); $update_responders = $notification->add_responders($post); if (!empty($update_responders)) diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php index a68685547a..0f7dce0a68 100644 --- a/phpBB/phpbb/notification/type/report_pm.php +++ b/phpBB/phpbb/notification/type/report_pm.php @@ -141,6 +141,8 @@ class report_pm extends \phpbb\notification\type\pm */ public function get_email_template_variables() { + $user_data = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile'); + return array( 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']), 'SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))), diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php index 22eb4bd526..4812e8b5af 100644 --- a/phpBB/phpbb/notification/type/topic.php +++ b/phpBB/phpbb/notification/type/topic.php @@ -55,6 +55,22 @@ class topic extends \phpbb\notification\type\base 'group' => 'NOTIFICATION_GROUP_POSTING', ); + /** @var \phpbb\user_loader */ + protected $user_loader; + + /** @var \phpbb\config\config */ + protected $config; + + public function set_config(\phpbb\config\config $config) + { + $this->config = $config; + } + + public function set_user_loader(\phpbb\user_loader $user_loader) + { + $this->user_loader = $user_loader; + } + /** * Is available */ diff --git a/tests/mock/container_builder.php b/tests/mock/container_builder.php index e04a83804d..134589b0b8 100644 --- a/tests/mock/container_builder.php +++ b/tests/mock/container_builder.php @@ -188,4 +188,9 @@ class phpbb_mock_container_builder implements ContainerInterface public function isScopeActive($name) { } + + public function isFrozen() + { + return false; + } } diff --git a/tests/notification/base.php b/tests/notification/base.php index c898c76947..1295f099f0 100644 --- a/tests/notification/base.php +++ b/tests/notification/base.php @@ -11,6 +11,10 @@ * */ +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + require_once dirname(__FILE__) . '/manager_helper.php'; abstract class phpbb_tests_notification_base extends phpbb_database_test_case @@ -70,8 +74,9 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case $this->user = $user; $this->user_loader = new \phpbb\user_loader($this->db, $phpbb_root_path, $phpEx, 'phpbb_users'); $auth = $this->auth = new phpbb_mock_notifications_auth(); + $cache_driver = new \phpbb\cache\driver\dummy(); $cache = $this->cache = new \phpbb\cache\service( - new \phpbb\cache\driver\dummy(), + $cache_driver, $this->config, $this->db, $phpbb_root_path, @@ -80,36 +85,48 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case $this->phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $phpbb_container = $this->container = new phpbb_mock_container_builder(); + $phpbb_container = $this->container = new ContainerBuilder(); + $loader = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__ . '/fixtures')); + $loader->load('services_notification.yml'); + $phpbb_container->set('user_loader', $this->user_loader); + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $this->config); + $phpbb_container->set('dbal.conn', $this->db); + $phpbb_container->set('auth', $auth); + $phpbb_container->set('cache.driver', $cache_driver); + $phpbb_container->set('cache', $cache); + $phpbb_container->set('text_formatter.utils', new \phpbb\textformatter\s9e\utils()); + $phpbb_container->set('dispatcher', $this->phpbb_dispatcher); + $phpbb_container->setParameter('core.root_path', $phpbb_root_path); + $phpbb_container->setParameter('core.php_ext', $phpEx); + $phpbb_container->setParameter('tables.notifications', 'phpbb_notifications'); + $phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications'); + $phpbb_container->setParameter('tables.notification_types', 'phpbb_notification_types'); $this->notifications = new phpbb_notification_manager_helper( array(), array(), $this->container, $this->user_loader, - $this->config, $this->phpbb_dispatcher, $this->db, $this->cache, $this->user, - $phpbb_root_path, - $phpEx, 'phpbb_notification_types', 'phpbb_user_notifications' ); $phpbb_container->set('notification_manager', $this->notifications); + $phpbb_container->compile(); $this->notifications->setDependencies($this->auth, $this->config); $types = array(); foreach ($this->get_notification_types() as $type) { - $type_parts = explode('.', $type); - $class = $this->build_type('phpbb\notification\type\\' . array_pop($type_parts)); + $class = $this->build_type($type); $types[$type] = $class; - $this->container->set($type, $class); } $this->notifications->set_var('notification_types', $types); @@ -117,11 +134,9 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case $methods = array(); foreach ($this->get_notification_methods() as $method) { - $method_parts = explode('.', $method); - $class = $this->build_type('phpbb\notification\method\\' . array_pop($method_parts)); + $class = $this->container->get($method); $methods[$method] = $class; - $this->container->set($method, $class); } $this->notifications->set_var('notification_methods', $methods); @@ -133,26 +148,11 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case protected function build_type($type) { - global $phpbb_root_path, $phpEx; - - $instance = new $type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_user_notifications'); - - if ($type === 'phpbb\\notification\\type\\quote') - { - $instance->set_utils(new \phpbb\textformatter\s9e\utils); - } + $instance = $this->container->get($type); return $instance; } - protected function build_method($method) - { - global $phpbb_root_path, $phpEx; - - return new $method($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, - $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_notifications', 'phpbb_user_notifications'); - } - protected function assert_notifications($expected, $options = array()) { $notifications = $this->notifications->load_notifications('notification.method.board', array_merge(array( diff --git a/tests/notification/fixtures/services_notification.yml b/tests/notification/fixtures/services_notification.yml new file mode 100644 index 0000000000..7eaa7e81ec --- /dev/null +++ b/tests/notification/fixtures/services_notification.yml @@ -0,0 +1,70 @@ +imports: + - { resource: ../../../phpBB/config/default/container/services_notification.yml } + +services: + notification_manager: + synthetic: true + + user_loader: + synthetic: true + + user: + synthetic: true + + config: + synthetic: true + + dbal.conn: + synthetic: true + + auth: + synthetic: true + + cache.driver: + synthetic: true + + path_helper: + synthetic: true + + groupposition.legend: + synthetic: true + + groupposition.teampage: + synthetic: true + + groupposition.teampage: + synthetic: true + + text_formatter.s9e.factory: + synthetic: true + + text_formatter.s9e.quote_helper: + synthetic: true + + text_formatter.parser: + synthetic: true + + text_formatter.s9e.parser: + synthetic: true + + text_formatter.renderer: + synthetic: true + + text_formatter.s9e.renderer: + synthetic: true + + text_formatter.utils: + synthetic: true + + text_formatter.s9e.utils: + synthetic: true + + text_formatter.data_access: + synthetic: true + + test: + class: phpbb\notification\type\test + scope: prototype + parent: notification.type.base + tags: + - { name: notification.type } diff --git a/tests/notification/manager_helper.php b/tests/notification/manager_helper.php index 40cf9b3ad4..2e8699e1e0 100644 --- a/tests/notification/manager_helper.php +++ b/tests/notification/manager_helper.php @@ -37,41 +37,4 @@ class phpbb_notification_manager_helper extends \phpbb\notification\manager $this->auth = $auth; $this->config = $config; } - - /** - * Helper to get the notifications item type class and set it up - */ - public function get_item_type_class($item_type, $data = array()) - { - $item_parts = explode('.', $item_type); - $item_type = 'phpbb\notification\type\\' . array_pop($item_parts); - - $item = new $item_type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, $this->user_notifications_table); - - if ($item_type === 'phpbb\\notification\\type\\quote') - { - $item->set_utils(new \phpbb\textformatter\s9e\utils); - } - - $item->set_notification_manager($this); - - $item->set_initial_data($data); - - return $item; - } - - /** - * Helper to get the notifications method class and set it up - */ - public function get_method_class($method_name) - { - $method_parts = explode('.', $method_name); - $method_name = 'phpbb\notification\method\\' . array_pop($method_parts); - - $method = new $method_name($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, NOTIFICATIONS_TABLE, $this->user_notifications_table); - - $method->set_notification_manager($this); - - return $method; - } } diff --git a/tests/notification/notification_test.php b/tests/notification/notification_test.php index 167cde13ca..ec42aa193c 100644 --- a/tests/notification/notification_test.php +++ b/tests/notification/notification_test.php @@ -81,9 +81,9 @@ class phpbb_notification_test extends phpbb_tests_notification_base ); $subscriptions = $this->notifications->get_global_subscriptions(2); - foreach ($expected_subscriptions as $item_type => $methods) { + self::assertArrayHasKey($item_type, $subscriptions); $this->assert_array_content_equals($methods, $subscriptions[$item_type]); } diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php index 73711369ed..72b25abf0a 100644 --- a/tests/notification/submit_post_base.php +++ b/tests/notification/submit_post_base.php @@ -11,6 +11,10 @@ * */ +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php'; @@ -75,8 +79,9 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c 'allow_board_notifications' => true, )); + $cache_driver = new \phpbb\cache\driver\dummy(); $cache = new \phpbb\cache\service( - new \phpbb\cache\driver\dummy(), + $cache_driver, $config, $db, $phpbb_root_path, @@ -103,58 +108,49 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c $type_cast_helper = $this->getMock('\phpbb\request\type_cast_helper_interface'); $request = $this->getMock('\phpbb\request\request'); - // Container - $phpbb_container = new phpbb_mock_container_builder(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE)); - $user_loader = new \phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE); + // Container + $phpbb_container = new ContainerBuilder(); + $loader = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__ . '/fixtures')); + $loader->load('services_notification.yml'); + $phpbb_container->set('user_loader', $user_loader); + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $config); + $phpbb_container->set('dbal.conn', $db); + $phpbb_container->set('auth', $auth); + $phpbb_container->set('cache.driver', $cache_driver); + $phpbb_container->set('cache', $cache); + $phpbb_container->set('text_formatter.utils', new \phpbb\textformatter\s9e\utils()); + $phpbb_container->set('dispatcher', $phpbb_dispatcher); + $phpbb_container->setParameter('core.root_path', $phpbb_root_path); + $phpbb_container->setParameter('core.php_ext', $phpEx); + $phpbb_container->setParameter('tables.notifications', 'phpbb_notifications'); + $phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications'); + $phpbb_container->setParameter('tables.notification_types', 'phpbb_notification_types'); + $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE)); + $phpbb_container->compile(); + // Notification Types $notification_types = array('quote', 'bookmark', 'post', 'post_in_queue', 'topic', 'topic_in_queue', 'approve_topic', 'approve_post'); $notification_types_array = array(); foreach ($notification_types as $type) { - $class = $this->build_type($type); - $phpbb_container->set('notification.type.' . $type, array(array($this, 'build_type'), array($type))); + $class = $phpbb_container->get('notification.type.' . $type); $notification_types_array['notification.type.' . $type] = $class; } // Methods Types - $class_name = 'phpbb\notification\method\board'; - $class = new $class_name( - $user_loader, $db, $cache->get_driver(), $user, $auth, $config, - $phpbb_root_path, $phpEx, - NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE); - $phpbb_container->set('notification.method.board', $class); - $notification_methods_array = array('notification.method.board' => $class); + $notification_methods_array = array('notification.method.board' => $phpbb_container->get('notification.method.board')); // Notification Manager $phpbb_notifications = new \phpbb\notification\manager($notification_types_array, $notification_methods_array, - $phpbb_container, $user_loader, $config, $phpbb_dispatcher, $db, $cache, $user, - $phpbb_root_path, $phpEx, + $phpbb_container, $user_loader, $phpbb_dispatcher, $db, $cache, $user, NOTIFICATION_TYPES_TABLE, USER_NOTIFICATIONS_TABLE); $phpbb_container->set('notification_manager', $phpbb_notifications); } - public function build_type($type) - { - global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $request, $phpEx, $phpbb_root_path, $user_loader; - - $class_name = '\phpbb\notification\type\\' . $type; - $class = new $class_name( - $user_loader, $db, $cache->get_driver(), $user, $auth, $config, - $phpbb_root_path, $phpEx, - NOTIFICATION_TYPES_TABLE, USER_NOTIFICATIONS_TABLE); - - if ($type === 'quote') - { - $class->set_utils(new \phpbb\textformatter\s9e\utils); - } - - return $class; - } - /** * @dataProvider submit_post_data */ @@ -177,11 +173,4 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c $this->assertEquals($expected_after, $this->db->sql_fetchrowset($result)); $this->db->sql_freeresult($result); } - - protected function build_method($method) - { - global $phpbb_root_path, $phpEx; - - return new $method($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_notifications', 'phpbb_user_notifications'); - } } diff --git a/tests/notification/submit_post_type_quote_test.php b/tests/notification/submit_post_type_quote_test.php index 8ad6a62b09..3fab8c05ba 100644 --- a/tests/notification/submit_post_type_quote_test.php +++ b/tests/notification/submit_post_type_quote_test.php @@ -51,7 +51,8 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_ */ public function submit_post_data() { - $parser = $this->get_test_case_helpers()->set_s9e_services()->get('text_formatter.parser'); + // The new mock container is needed because the data providers may be executed before phpunit call setUp() + $parser = $this->get_test_case_helpers()->set_s9e_services(new phpbb_mock_container_builder())->get('text_formatter.parser'); return array( /** diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 62a56ed693..70bd309653 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -426,24 +426,34 @@ class phpbb_test_case_helpers $cache_key_parser = $prefix . '_parser'; $cache_key_renderer = $prefix . '_renderer'; $container->set('cache.driver', $cache); - $container->setParameter('cache.dir', $cache_dir); + + if (!$container->isFrozen()) + { + $container->setParameter('cache.dir', $cache_dir); + } // Create a path_helper - if (!$container->has('path_helper')) + if (!$container->has('path_helper') || $container->getDefinition('path_helper')->isSynthetic()) { + $path_helper = new \phpbb\path_helper( + new \phpbb\symfony_request( + new phpbb_mock_request() + ), + new \phpbb\filesystem(), + $this->test_case->getMock('\phpbb\request\request'), + $phpbb_root_path, + $phpEx + ); + $container->set( 'path_helper', - new \phpbb\path_helper( - new \phpbb\symfony_request( - new phpbb_mock_request() - ), - new \phpbb\filesystem(), - $this->test_case->getMock('\phpbb\request\request'), - $phpbb_root_path, - $phpEx - ) + $path_helper ); } + else + { + $path_helper = $container->get('path_helper'); + } // Create an event dispatcher if ($container->has('dispatcher')) @@ -534,7 +544,7 @@ class phpbb_test_case_helpers // Calls configured in services.yml $renderer->configure_quote_helper($quote_helper); - $renderer->configure_smilies_path($config, $container->get('path_helper')); + $renderer->configure_smilies_path($config, $path_helper); $renderer->configure_user($user, $config, $auth); $container->set('text_formatter.renderer', $renderer); From c1deeab318b5a2c168f044a6a3d0f2d0897b8cd9 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 9 Jul 2015 21:50:34 +0200 Subject: [PATCH 0502/1676] [ticket/11444] Fix services definition PHPBB3-11444 --- .../container/services_notification.yml | 22 +++++++++---------- phpBB/phpbb/notification/type/bookmark.php | 8 ------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index f82dd4b5a5..1076d13cce 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -23,7 +23,7 @@ services: - { name: service_collection, tag: notification.type } notification.type.base: - abstract: true + abstract: true arguments: - @dbal.conn - @user @@ -45,7 +45,7 @@ services: notification.type.approve_post: class: phpbb\notification\type\approve_post scope: prototype - parent: notification.type.base + parent: notification.type.post tags: - { name: notification.type } @@ -59,16 +59,14 @@ services: notification.type.bookmark: class: phpbb\notification\type\bookmark scope: prototype - parent: notification.type.base - calls: - - [set_config, ["@config"]] + parent: notification.type.post tags: - { name: notification.type } notification.type.disapprove_post: class: phpbb\notification\type\disapprove_post scope: prototype - parent: notification.type.base + parent: notification.type.post tags: - { name: notification.type } @@ -118,14 +116,14 @@ services: notification.type.post_in_queue: class: phpbb\notification\type\post_in_queue scope: prototype - parent: notification.type.base + parent: notification.type.post tags: - { name: notification.type } notification.type.quote: class: phpbb\notification\type\quote scope: prototype - parent: notification.type.base + parent: notification.type.post calls: - [set_utils, [@text_formatter.utils]] tags: @@ -134,28 +132,28 @@ services: notification.type.report_pm: class: phpbb\notification\type\report_pm scope: prototype - parent: notification.type.base + parent: notification.type.pm tags: - { name: notification.type } notification.type.report_pm_closed: class: phpbb\notification\type\report_pm_closed scope: prototype - parent: notification.type.base + parent: notification.type.pm tags: - { name: notification.type } notification.type.report_post: class: phpbb\notification\type\report_post scope: prototype - parent: notification.type.base + parent: notification.type.post tags: - { name: notification.type } notification.type.report_post_closed: class: phpbb\notification\type\report_post_closed scope: prototype - parent: notification.type.base + parent: notification.type.post tags: - { name: notification.type } diff --git a/phpBB/phpbb/notification/type/bookmark.php b/phpBB/phpbb/notification/type/bookmark.php index 59423ca248..5b3fc3a1f2 100644 --- a/phpBB/phpbb/notification/type/bookmark.php +++ b/phpBB/phpbb/notification/type/bookmark.php @@ -48,14 +48,6 @@ class bookmark extends \phpbb\notification\type\post 'group' => 'NOTIFICATION_GROUP_POSTING', ); - /** @var \phpbb\config\config */ - protected $config; - - public function set_config(\phpbb\config\config $config) - { - $this->config = $config; - } - /** * Is available */ From 11bef3e22ed8cc2109ab7a5b4229f393d3648862 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 10 Jul 2015 00:15:58 +0200 Subject: [PATCH 0503/1676] [ticket/11444] Update tests PHPBB3-11444 --- .../container/services_notification.yml | 24 +++++++++---------- tests/functional/notification_test.php | 2 ++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index 1076d13cce..c842656575 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -37,8 +37,8 @@ services: scope: prototype parent: notification.type.base calls: - - [set_user_loader, ["@user_loader"]] - - [set_config, ["@config"]] + - [set_user_loader, [@user_loader]] + - [set_config, [@config]] tags: - { name: notification.type } @@ -52,7 +52,7 @@ services: notification.type.approve_topic: class: phpbb\notification\type\approve_topic scope: prototype - parent: notification.type.base + parent: notification.type.topic tags: - { name: notification.type } @@ -73,7 +73,7 @@ services: notification.type.disapprove_topic: class: phpbb\notification\type\disapprove_topic scope: prototype - parent: notification.type.base + parent: notification.type.topic tags: - { name: notification.type } @@ -82,7 +82,7 @@ services: scope: prototype parent: notification.type.base calls: - - [set_user_loader, ["@user_loader"]] + - [set_user_loader, [@user_loader]] tags: - { name: notification.type } @@ -98,8 +98,8 @@ services: scope: prototype parent: notification.type.base calls: - - [set_user_loader, ["@user_loader"]] - - [set_config, ["@config"]] + - [set_user_loader, [@user_loader]] + - [set_config, [@config]] tags: - { name: notification.type } @@ -108,8 +108,8 @@ services: scope: prototype parent: notification.type.base calls: - - [set_user_loader, ["@user_loader"]] - - [set_config, ["@config"]] + - [set_user_loader, [@user_loader]] + - [set_config, [@config]] tags: - { name: notification.type } @@ -162,15 +162,15 @@ services: scope: prototype parent: notification.type.base calls: - - [set_user_loader, ["@user_loader"]] - - [set_config, ["@config"]] + - [set_user_loader, [@user_loader]] + - [set_config, [@config]] tags: - { name: notification.type } notification.type.topic_in_queue: class: phpbb\notification\type\topic_in_queue scope: prototype - parent: notification.type.base + parent: notification.type.topic tags: - { name: notification.type } diff --git a/tests/functional/notification_test.php b/tests/functional/notification_test.php index 5c6b87d50b..87c36dd4d1 100644 --- a/tests/functional/notification_test.php +++ b/tests/functional/notification_test.php @@ -11,6 +11,8 @@ * */ +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + /** * @group functional */ From c5c98b7ca2dfb85925bc3ec1d6057ec554f9b4f9 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 14 Jul 2015 23:14:35 +0200 Subject: [PATCH 0504/1676] [ticket/13740] Implement navigation sorting PHPBB3-13740 --- phpBB/phpbb/install/controller/helper.php | 35 ++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index 8445d80a41..5ef98ac2bb 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -158,8 +158,7 @@ class helper { // Get navigation items $nav_array = $this->navigation_provider->get(); - - // @todo Sort navs by order + $nav_array = $this->sort_navigation_level($nav_array); $active_main_menu = $this->get_active_main_menu($nav_array); @@ -174,7 +173,7 @@ class helper if (is_array($entry[0]) && $active_main_menu === $key) { - // @todo Sort navs by order + $entry[0] = $this->sort_navigation_level($entry[0]); foreach ($entry[0] as $name => $sub_entry) { @@ -220,6 +219,7 @@ class helper protected function render_language_select() { $langs = $this->lang_helper->get_available_languages(); + // @todo } /** @@ -246,7 +246,7 @@ class helper { foreach ($nav_options[0] as $sub_menus) { - if (isset($sub_menus['route']) &&$sub_menus['route'] === $active_route) + if (isset($sub_menus['route']) && $sub_menus['route'] === $active_route) { return $current_menu; } @@ -256,4 +256,31 @@ class helper return false; } + + /** + * Sorts the top level of navigation array + * + * @param array $nav_array Navigation array + * + * @return array + */ + protected function sort_navigation_level($nav_array) + { + $sorted = array(); + foreach ($nav_array as $nav) + { + $order = (isset($nav['order'])) ? $nav['order'] : 0; + $sorted[$order][] = $nav; + } + + // Linearization of navigation array + $nav_array = array(); + ksort($sorted); + foreach ($sorted as $nav) + { + $nav_array = array_merge($nav_array, $nav); + } + + return $nav_array; + } } From da7fc9e5daf6e72f9b86dbc5e002febb202f516e Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 10 Jun 2015 15:11:27 +0200 Subject: [PATCH 0505/1676] [ticket/13935] Allow more admin-configurable schemes in post links PHPBB3-13935 --- .../container/services_text_formatter.yml | 1 + phpBB/includes/acp/acp_board.php | 7 ++++ phpBB/install/schemas/schema_data.sql | 1 + phpBB/language/en/acp/board.php | 2 + .../data/v320/allowed_schemes_links.php | 24 +++++++++++ phpBB/phpbb/textformatter/s9e/factory.php | 19 ++++++++- tests/functional/posting_test.php | 41 +++++++++++++++++++ .../phpbb_test_case_helpers.php | 30 +++++++++++--- tests/text_formatter/s9e/factory_test.php | 1 + 9 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index ae698af9e4..5a3307175f 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -32,6 +32,7 @@ services: - @text_formatter.data_access - @cache.driver - @dispatcher + - @config - %text_formatter.cache.dir% - %text_formatter.cache.parser.key% - %text_formatter.cache.renderer.key% diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 6e636d2f7d..b1ddd4be70 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -197,6 +197,7 @@ class acp_board 'allow_post_flash' => array('lang' => 'ALLOW_POST_FLASH', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_post_links' => array('lang' => 'ALLOW_POST_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allowed_schemes_links' => array('lang' => 'ALLOWED_SCHEMES_LINKS', 'validate' => 'string', 'type' => 'text:0:255', 'explain' => true), 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), @@ -550,6 +551,12 @@ class acp_board } } + // Invalidate the text_formatter cache when posting options are changed + if ($mode == 'post' && $submit) + { + $phpbb_container->get('text_formatter.cache')->invalidate(); + } + // Store news and exclude ids if ($mode == 'feed' && $submit) { diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index c53c252e2f..ca561ec35d 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -41,6 +41,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_pm', '1' INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_smilies', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_smilies', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_topic_notify', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('allowed_schemes_links', 'http,https,ftp'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('assets_version', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('attachment_quota', '52428800'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_bbcode_pm', '1'); diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 001775349a..69d6158241 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -161,6 +161,8 @@ $lang = array_merge($lang, array( 'ACP_POST_SETTINGS_EXPLAIN' => 'Here you can set all default settings for posting.', 'ALLOW_POST_LINKS' => 'Allow links in posts/private messages', 'ALLOW_POST_LINKS_EXPLAIN' => 'If disallowed the [URL] BBCode tag and automatic/magic URLs are disabled.', + 'ALLOWED_SCHEMES_LINKS' => 'Allowed schemes in links', + 'ALLOWED_SCHEMES_LINKS_EXPLAIN' => 'Users can only post schemeless URLs or one of the comma-separated list of allowed schemes.', 'ALLOW_POST_FLASH' => 'Allow use of [FLASH] BBCode tag in posts', 'ALLOW_POST_FLASH_EXPLAIN' => 'If disallowed the [FLASH] BBCode tag is disabled in posts. Otherwise the permission system controls which users can use the [FLASH] BBCode tag.', diff --git a/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php b/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php new file mode 100644 index 0000000000..de127e3745 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php @@ -0,0 +1,24 @@ + +* @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\v320; + +class allowed_schemes_links extends \phpbb\db\migration\migration +{ + public function update_data() + { + return array( + array('config.add', array('allowed_schemes_links', 'http,https,ftp')), + ); + } +} diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 2aab97b667..4a04b34cd8 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -42,6 +42,11 @@ class factory implements \phpbb\textformatter\cache_interface */ protected $cache_key_renderer; + /** + * @var \phpbb\config\config + */ + protected $config; + /** * @var array Custom tokens used in bbcode.html and their corresponding token from the definition */ @@ -127,16 +132,18 @@ class factory implements \phpbb\textformatter\cache_interface * @param \phpbb\textformatter\data_access $data_access * @param \phpbb\cache\driver\driver_interface $cache * @param \phpbb\event\dispatcher_interface $dispatcher + * @param \phpbb\config\config $config * @param string $cache_dir Path to the cache dir * @param string $cache_key_parser Cache key used for the parser * @param string $cache_key_renderer Cache key used for the renderer */ - public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, \phpbb\event\dispatcher_interface $dispatcher, $cache_dir, $cache_key_parser, $cache_key_renderer) + public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\config\config $config, $cache_dir, $cache_key_parser, $cache_key_renderer) { $this->cache = $cache; $this->cache_dir = $cache_dir; $this->cache_key_parser = $cache_key_parser; $this->cache_key_renderer = $cache_key_renderer; + $this->config = $config; $this->data_access = $data_access; $this->dispatcher = $dispatcher; } @@ -190,6 +197,16 @@ class factory implements \phpbb\textformatter\cache_interface $vars = array('configurator'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_configure_before', compact($vars))); + // Reset the list of allowed schemes + foreach ($configurator->urlConfig->getAllowedSchemes() as $scheme) + { + $configurator->urlConfig->disallowScheme($scheme); + } + foreach (explode(',', $this->config['allowed_schemes_links']) as $scheme) + { + $configurator->urlConfig->allowScheme(trim($scheme)); + } + // Convert newlines to br elements by default $configurator->rootRules->enableAutoLineBreaks(); diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 724c42b289..fa9ff028da 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -205,4 +205,45 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $crawler->filter('#preview .signature')->html() ); } + + public function test_allowed_schemes_links() + { + $text = 'http://example.org/ tcp://localhost:22/ServiceName'; + + $this->login(); + $this->admin_login(); + + // Post with default settings + $crawler = self::request('GET', 'posting.php?mode=post&f=2'); + $form = $crawler->selectButton('Preview')->form(array( + 'subject' => 'Test subject', + 'message' => $text, + )); + $crawler = self::submit($form); + $this->assertContains( + 'http://example.org/ tcp://localhost:22/ServiceName', + $crawler->filter('#preview .content')->html() + ); + + // Update allowed schemes + $crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post'); + $form = $crawler->selectButton('Submit')->form(); + $values = $form->getValues(); + $values['config[allowed_schemes_links]'] = 'https,tcp'; + $form->setValues($values); + $crawler = self::submit($form); + $this->assertEquals(1, $crawler->filter('.successbox')->count()); + + // Post with new settings + $crawler = self::request('GET', 'posting.php?mode=post&f=2'); + $form = $crawler->selectButton('Preview')->form(array( + 'subject' => 'Test subject', + 'message' => $text, + )); + $crawler = self::submit($form); + $this->assertContains( + 'http://example.org/ tcp://localhost:22/ServiceName', + $crawler->filter('#preview .content')->html() + ); + } } diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 70bd309653..3eefcdc5e3 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -473,8 +473,30 @@ class phpbb_test_case_helpers $phpbb_dispatcher = $dispatcher; } + // Set up the a minimum config + if ($container->has('config')) + { + $config = $container->get('config'); + } + else + { + $config = new \phpbb\config\config(array()); + } + $default_config = array( + 'allow_nocensors' => false, + 'allowed_schemes_links' => 'http,https,ftp', + 'smilies_path' => 'images/smilies', + ); + foreach ($default_config as $config_name => $config_value) + { + if (!isset($config[$config_name])) + { + $config[$config_name] = $config_value; + } + } + // Create and register the text_formatter.s9e.factory service - $factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $dispatcher, $cache_dir, $cache_key_parser, $cache_key_renderer); + $factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $dispatcher, $config, $cache_dir, $cache_key_parser, $cache_key_renderer); $container->set('text_formatter.s9e.factory', $factory); // Create a user if none was provided, and add the common lang strings @@ -537,12 +559,8 @@ class phpbb_test_case_helpers $dispatcher ); - $config = ($container->has('config')) - ? $container->get('config') - : new \phpbb\config\config(array('smilies_path' => 'images/smilies', 'allow_nocensors' => false)); - $auth = ($container->has('auth')) ? $container->get('auth') : new \phpbb\auth\auth; - // Calls configured in services.yml + $auth = ($container->has('auth')) ? $container->get('auth') : new \phpbb\auth\auth; $renderer->configure_quote_helper($quote_helper); $renderer->configure_smilies_path($config, $path_helper); $renderer->configure_user($user, $config, $auth); diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php index 8382097544..c8bf595092 100644 --- a/tests/text_formatter/s9e/factory_test.php +++ b/tests/text_formatter/s9e/factory_test.php @@ -49,6 +49,7 @@ class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case $dal, $this->cache, $this->dispatcher, + new \phpbb\config\config(array('allowed_schemes_links' => 'http,https,ftp')), $this->get_cache_dir(), '_foo_parser', '_foo_renderer' From 9129cd0e9e62007e23c9b57d3c157a68119b431f Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 13 Jul 2015 18:23:42 +0200 Subject: [PATCH 0506/1676] [ticket/13935] Removed UI PHPBB3-13935 --- phpBB/includes/acp/acp_board.php | 1 - phpBB/language/en/acp/board.php | 2 -- tests/functional/posting_test.php | 41 ------------------------------- 3 files changed, 44 deletions(-) diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index b1ddd4be70..cacda4db18 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -197,7 +197,6 @@ class acp_board 'allow_post_flash' => array('lang' => 'ALLOW_POST_FLASH', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_post_links' => array('lang' => 'ALLOW_POST_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), - 'allowed_schemes_links' => array('lang' => 'ALLOWED_SCHEMES_LINKS', 'validate' => 'string', 'type' => 'text:0:255', 'explain' => true), 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 69d6158241..001775349a 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -161,8 +161,6 @@ $lang = array_merge($lang, array( 'ACP_POST_SETTINGS_EXPLAIN' => 'Here you can set all default settings for posting.', 'ALLOW_POST_LINKS' => 'Allow links in posts/private messages', 'ALLOW_POST_LINKS_EXPLAIN' => 'If disallowed the [URL] BBCode tag and automatic/magic URLs are disabled.', - 'ALLOWED_SCHEMES_LINKS' => 'Allowed schemes in links', - 'ALLOWED_SCHEMES_LINKS_EXPLAIN' => 'Users can only post schemeless URLs or one of the comma-separated list of allowed schemes.', 'ALLOW_POST_FLASH' => 'Allow use of [FLASH] BBCode tag in posts', 'ALLOW_POST_FLASH_EXPLAIN' => 'If disallowed the [FLASH] BBCode tag is disabled in posts. Otherwise the permission system controls which users can use the [FLASH] BBCode tag.', diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index fa9ff028da..724c42b289 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -205,45 +205,4 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $crawler->filter('#preview .signature')->html() ); } - - public function test_allowed_schemes_links() - { - $text = 'http://example.org/ tcp://localhost:22/ServiceName'; - - $this->login(); - $this->admin_login(); - - // Post with default settings - $crawler = self::request('GET', 'posting.php?mode=post&f=2'); - $form = $crawler->selectButton('Preview')->form(array( - 'subject' => 'Test subject', - 'message' => $text, - )); - $crawler = self::submit($form); - $this->assertContains( - 'http://example.org/ tcp://localhost:22/ServiceName', - $crawler->filter('#preview .content')->html() - ); - - // Update allowed schemes - $crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post'); - $form = $crawler->selectButton('Submit')->form(); - $values = $form->getValues(); - $values['config[allowed_schemes_links]'] = 'https,tcp'; - $form->setValues($values); - $crawler = self::submit($form); - $this->assertEquals(1, $crawler->filter('.successbox')->count()); - - // Post with new settings - $crawler = self::request('GET', 'posting.php?mode=post&f=2'); - $form = $crawler->selectButton('Preview')->form(array( - 'subject' => 'Test subject', - 'message' => $text, - )); - $crawler = self::submit($form); - $this->assertContains( - 'http://example.org/ tcp://localhost:22/ServiceName', - $crawler->filter('#preview .content')->html() - ); - } } From 88348e1ccc32e8ba731ee079383061792ab01a16 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 15 Jul 2015 22:08:20 +0200 Subject: [PATCH 0507/1676] [ticket/13935] Removed cache invalidation from acp_board PHPBB3-13935 --- phpBB/includes/acp/acp_board.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index cacda4db18..6e636d2f7d 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -550,12 +550,6 @@ class acp_board } } - // Invalidate the text_formatter cache when posting options are changed - if ($mode == 'post' && $submit) - { - $phpbb_container->get('text_formatter.cache')->invalidate(); - } - // Store news and exclude ids if ($mode == 'feed' && $submit) { From af7872473d41b4fd82a850e87f9e74a72a5b3230 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Thu, 16 Jul 2015 22:52:25 -0700 Subject: [PATCH 0508/1676] [ticket/14033] Fix errors in docblocks PHPBB3-14033 --- phpBB/phpbb/console/command/reparser/reparse.php | 2 +- phpBB/phpbb/filesystem/filesystem_interface.php | 2 +- phpBB/phpbb/help/manager.php | 1 + phpBB/phpbb/user.php | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 151e196358..a58bf20193 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -35,7 +35,7 @@ class reparse extends \phpbb\console\command\command * Constructor * * @param \phpbb\user $user - * @param \phpbb\di\service_collection $reparser_collection + * @param \phpbb\di\service_collection $reparsers */ public function __construct(\phpbb\user $user, \phpbb\di\service_collection $reparsers) { diff --git a/phpBB/phpbb/filesystem/filesystem_interface.php b/phpBB/phpbb/filesystem/filesystem_interface.php index 21ad8252f8..1093be2499 100644 --- a/phpBB/phpbb/filesystem/filesystem_interface.php +++ b/phpBB/phpbb/filesystem/filesystem_interface.php @@ -64,7 +64,7 @@ interface filesystem_interface * or the user can specify octal values (or any integer if it makes sense). All directories will have * an execution bit appended, if the user group (owner, group or other) has any bit specified. * - * @param string|array|\Traversable $file The file/directory to be chmodded + * @param string|array|\Traversable $files The file/directory to be chmodded * @param int $perms Permissions to set * @param bool $recursive If the permissions should be changed recursively * @param bool $force_chmod_link Try to apply permissions to symlinks as well diff --git a/phpBB/phpbb/help/manager.php b/phpBB/phpbb/help/manager.php index d6991c0733..39f52d343b 100644 --- a/phpBB/phpbb/help/manager.php +++ b/phpBB/phpbb/help/manager.php @@ -49,6 +49,7 @@ class manager * * @param string $block_name Name or language key with the name of the block * @param bool $switch_column Switch the column of the menu + * @param array $questions Array of frequently asked questions */ public function add_block($block_name, $switch_column = false, $questions = array()) { diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php index c33070d6f4..fc125f5edc 100644 --- a/phpBB/phpbb/user.php +++ b/phpBB/phpbb/user.php @@ -54,8 +54,8 @@ class user extends \phpbb\session /** * Constructor to set the lang path * - * @param string $datetime_class Class name of datetime class - * @param \phpbb\language\language $lang phpBB's Language loader + * @param \phpbb\language\language $lang phpBB's Language loader + * @param string $datetime_class Class name of datetime class */ function __construct(\phpbb\language\language $lang, $datetime_class) { From e7763cd273a88e4b99c67e2a74b83ed3ef86727f Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 17 Jul 2015 08:26:14 +0200 Subject: [PATCH 0509/1676] [ticket/14034] Fix reparser names that contain "text_reparser" in the middle PHPBB3-14034 --- phpBB/phpbb/console/command/reparser/list_all.php | 2 +- phpBB/phpbb/console/command/reparser/reparse.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/console/command/reparser/list_all.php b/phpBB/phpbb/console/command/reparser/list_all.php index 1589836ddd..e42c3ac782 100644 --- a/phpBB/phpbb/console/command/reparser/list_all.php +++ b/phpBB/phpbb/console/command/reparser/list_all.php @@ -36,7 +36,7 @@ class list_all extends \phpbb\console\command\command foreach ($reparsers as $name => $reparser) { // Store the names without the "text_reparser." prefix - $this->reparser_names[] = str_replace('text_reparser.', '', $name); + $this->reparser_names[] = preg_replace('(^text_reparser\\.)', '', $name); } } diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 151e196358..81d1aa0421 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -149,7 +149,7 @@ class reparse extends \phpbb\console\command\command return; } - $this->io->section($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $min, $max)); + $this->io->section($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', preg_replace('(^text_reparser\\.)', '', $name), $min, $max)); $progress = $this->io->createProgressBar($max); if ($output->getVerbosity() === OutputInterface::VERBOSITY_VERBOSE) @@ -171,7 +171,7 @@ class reparse extends \phpbb\console\command\command $progress->setBarWidth(60); } - $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING_START', str_replace('text_reparser.', '', $name))); + $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING_START', preg_replace('(^text_reparser\\.)', '', $name))); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { @@ -189,7 +189,7 @@ class reparse extends \phpbb\console\command\command $start = max($min, $current + 1 - $size); $end = max($min, $current); - $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', str_replace('text_reparser.', '', $name), $start, $end)); + $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', preg_replace('(^text_reparser\\.)', '', $name), $start, $end)); $reparser->reparse_range($start, $end); $current = $start - 1; From 15ea66c0962d1d7fb17eca08cb76682560f8ca05 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 17 Jul 2015 00:13:23 +0200 Subject: [PATCH 0510/1676] [ticket/14015] Update Symfony - Removing symfony/filesystem (2.8.x-dev 45cc231) - Installing symfony/filesystem (2.8.x-dev 9f70c56) Cloning 9f70c5625a32b2f1e6fc37222f52b4e0eb437b0e - Removing symfony/config (2.8.x-dev 291e3f1) - Installing symfony/config (2.8.x-dev 358ec92) Cloning 358ec929e494b6f12d8508d88357cbd7383a10ca - Removing symfony/console (2.8.x-dev 7e857a2) - Installing symfony/console (2.8.x-dev fd85e75) Cloning fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a - Removing symfony/dependency-injection (2.8.x-dev 90a7527) - Installing symfony/dependency-injection (2.8.x-dev f279142) Cloning f279142fb6bc21e83fcd40e0a01a62ff527268be - Removing symfony/finder (2.8.x-dev fd26bdb) - Installing symfony/finder (2.8.x-dev 8712d5e) Cloning 8712d5e8c4ad65e6b936ed9b6a581e5e6a87fddf - Removing symfony/http-foundation (2.8.x-dev 06aa08b) - Installing symfony/http-foundation (2.8.x-dev 5339030) Cloning 5339030f5af0d6fef7c897130291ac168278289f - Removing symfony/event-dispatcher (2.8.x-dev 8766ceb) - Installing symfony/event-dispatcher (2.8.x-dev d724688) Cloning d7246885b7fe4cb5a2786bda34362d2f0e40b730 - Removing symfony/debug (2.8.x-dev eda866d) - Installing symfony/debug (2.8.x-dev d1114d8) Cloning d1114d892ae70f833871dc55599f17084191efaa - Removing symfony/http-kernel (2.8.x-dev c587069) - Installing symfony/http-kernel (2.8.x-dev f24d2cb) Cloning f24d2cb4778ecc5f6c8e8f7f31bc4691099a920d - Removing symfony/routing (2.8.x-dev 76b18ed) - Installing symfony/routing (2.8.x-dev 9e797cd) Cloning 9e797cd70762db18d87c59dc6bc1ab7c3eb963ed - Removing symfony/security-core (2.8.x-dev 2c21845) - Installing symfony/security-core (2.8.x-dev 8253e02) Cloning 8253e027bf8a1c9c573a7b3c494027847058c959 - Removing symfony/twig-bridge (2.8.x-dev 2e072a1) - Installing symfony/twig-bridge (2.8.x-dev a02e3a8) Cloning a02e3a8ff1f8eda04d0e0655d2cefcbe9ecc4e14 - Removing symfony/yaml (2.8.x-dev 2396832) - Installing symfony/yaml (2.8.x-dev 000e7fc) Cloning 000e7fc2653335cd42c6d21405dac1c74224a387 - Removing symfony/dom-crawler (2.8.x-dev 3a523d1) - Installing symfony/dom-crawler (2.8.x-dev 3aed431) Cloning 3aed431721a4a779d1ec30210bd53075da9623f5 - Removing symfony/browser-kit (2.8.x-dev 4916397) - Installing symfony/browser-kit (2.8.x-dev 4f297d7) Cloning 4f297d7e00c375b6ab03732e076f65799a73937d - Removing symfony/process (2.8.x-dev daf96f1) - Installing symfony/process (2.8.x-dev 25d74c9) Cloning 25d74c90d79e66905013714d8d188e4ccb5ff466 PHPBB3-14015 --- phpBB/composer.lock | 154 ++++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 74e554f2f0..aaff9a8968 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -1,7 +1,7 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], "hash": "94d0f6dab53f11dab1de63c0ae519ee6", @@ -224,7 +224,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/beee0e5693f7ca8ed16a94294acf53b6e6207e7c", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/6c568ac8b01b33650d9d77b5b6399eed9c18ac94", "reference": "beee0e5693f7ca8ed16a94294acf53b6e6207e7c", "shasum": "" }, @@ -279,12 +279,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "291e3f1ce92fec71632eada0d492833b41531718" + "reference": "358ec929e494b6f12d8508d88357cbd7383a10ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/291e3f1ce92fec71632eada0d492833b41531718", - "reference": "291e3f1ce92fec71632eada0d492833b41531718", + "url": "https://api.github.com/repos/symfony/Config/zipball/358ec929e494b6f12d8508d88357cbd7383a10ca", + "reference": "358ec929e494b6f12d8508d88357cbd7383a10ca", "shasum": "" }, "require": { @@ -321,7 +321,7 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2015-05-15 14:11:12" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/console", @@ -329,12 +329,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "7e857a2b52b5833ed27d78a6b1b846bd440ee8bd" + "reference": "fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/7e857a2b52b5833ed27d78a6b1b846bd440ee8bd", - "reference": "7e857a2b52b5833ed27d78a6b1b846bd440ee8bd", + "url": "https://api.github.com/repos/symfony/Console/zipball/fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a", + "reference": "fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a", "shasum": "" }, "require": { @@ -378,7 +378,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-05-15 14:11:12" + "time": "2015-07-16 12:22:14" }, { "name": "symfony/debug", @@ -386,12 +386,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Debug.git", - "reference": "eda866deb149108bfeb4185593083919b186a463" + "reference": "d1114d892ae70f833871dc55599f17084191efaa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Debug/zipball/eda866deb149108bfeb4185593083919b186a463", - "reference": "eda866deb149108bfeb4185593083919b186a463", + "url": "https://api.github.com/repos/symfony/Debug/zipball/d1114d892ae70f833871dc55599f17084191efaa", + "reference": "d1114d892ae70f833871dc55599f17084191efaa", "shasum": "" }, "require": { @@ -438,7 +438,7 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2015-05-15 14:11:12" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/dependency-injection", @@ -446,12 +446,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "90a75274cb85bd6f9aaf4a017e5dee616ffe8a1d" + "reference": "f279142fb6bc21e83fcd40e0a01a62ff527268be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/90a75274cb85bd6f9aaf4a017e5dee616ffe8a1d", - "reference": "90a75274cb85bd6f9aaf4a017e5dee616ffe8a1d", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/f279142fb6bc21e83fcd40e0a01a62ff527268be", + "reference": "f279142fb6bc21e83fcd40e0a01a62ff527268be", "shasum": "" }, "require": { @@ -498,7 +498,7 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2015-05-12 15:16:46" + "time": "2015-07-16 10:10:53" }, { "name": "symfony/event-dispatcher", @@ -506,12 +506,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "8766cebf28beac9a45b511d7dba053da9d35eb9f" + "reference": "d7246885b7fe4cb5a2786bda34362d2f0e40b730" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/8766cebf28beac9a45b511d7dba053da9d35eb9f", - "reference": "8766cebf28beac9a45b511d7dba053da9d35eb9f", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/d7246885b7fe4cb5a2786bda34362d2f0e40b730", + "reference": "d7246885b7fe4cb5a2786bda34362d2f0e40b730", "shasum": "" }, "require": { @@ -556,7 +556,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2015-05-12 15:16:46" + "time": "2015-06-24 15:32:32" }, { "name": "symfony/filesystem", @@ -564,12 +564,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "45cc231f1ecac70a8790bf1c88a823af8ce57056" + "reference": "9f70c5625a32b2f1e6fc37222f52b4e0eb437b0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/45cc231f1ecac70a8790bf1c88a823af8ce57056", - "reference": "45cc231f1ecac70a8790bf1c88a823af8ce57056", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/9f70c5625a32b2f1e6fc37222f52b4e0eb437b0e", + "reference": "9f70c5625a32b2f1e6fc37222f52b4e0eb437b0e", "shasum": "" }, "require": { @@ -605,7 +605,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2015-05-15 14:11:12" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/finder", @@ -613,12 +613,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "fd26bdbb67bc8753884eff5767a4f1ee90e2284b" + "reference": "8712d5e8c4ad65e6b936ed9b6a581e5e6a87fddf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/fd26bdbb67bc8753884eff5767a4f1ee90e2284b", - "reference": "fd26bdbb67bc8753884eff5767a4f1ee90e2284b", + "url": "https://api.github.com/repos/symfony/Finder/zipball/8712d5e8c4ad65e6b936ed9b6a581e5e6a87fddf", + "reference": "8712d5e8c4ad65e6b936ed9b6a581e5e6a87fddf", "shasum": "" }, "require": { @@ -654,7 +654,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2015-05-15 14:11:12" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/http-foundation", @@ -662,12 +662,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/HttpFoundation.git", - "reference": "06aa08b5d9157abc10bee99712124b8b994d4259" + "reference": "5339030f5af0d6fef7c897130291ac168278289f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/06aa08b5d9157abc10bee99712124b8b994d4259", - "reference": "06aa08b5d9157abc10bee99712124b8b994d4259", + "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/5339030f5af0d6fef7c897130291ac168278289f", + "reference": "5339030f5af0d6fef7c897130291ac168278289f", "shasum": "" }, "require": { @@ -707,7 +707,7 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2015-05-15 14:11:12" + "time": "2015-07-16 12:22:14" }, { "name": "symfony/http-kernel", @@ -715,12 +715,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/HttpKernel.git", - "reference": "c587069bb67bea9db7ed8aa82e4fe0c9b7867fa2" + "reference": "f24d2cb4778ecc5f6c8e8f7f31bc4691099a920d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/c587069bb67bea9db7ed8aa82e4fe0c9b7867fa2", - "reference": "c587069bb67bea9db7ed8aa82e4fe0c9b7867fa2", + "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/f24d2cb4778ecc5f6c8e8f7f31bc4691099a920d", + "reference": "f24d2cb4778ecc5f6c8e8f7f31bc4691099a920d", "shasum": "" }, "require": { @@ -745,7 +745,7 @@ "symfony/finder": "~2.0,>=2.0.5|~3.0.0", "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/process": "~2.0,>=2.0.5|~3.0.0", - "symfony/routing": "~2.2|~3.0.0", + "symfony/routing": "~2.8|~3.0.0", "symfony/stopwatch": "~2.3|~3.0.0", "symfony/templating": "~2.2|~3.0.0", "symfony/translation": "~2.0,>=2.0.5|~3.0.0", @@ -787,7 +787,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2015-05-15 14:11:12" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/routing", @@ -795,12 +795,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Routing.git", - "reference": "76b18edcf09a967590d6e132851d0f964866e2e8" + "reference": "9e797cd70762db18d87c59dc6bc1ab7c3eb963ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Routing/zipball/76b18edcf09a967590d6e132851d0f964866e2e8", - "reference": "76b18edcf09a967590d6e132851d0f964866e2e8", + "url": "https://api.github.com/repos/symfony/Routing/zipball/9e797cd70762db18d87c59dc6bc1ab7c3eb963ed", + "reference": "9e797cd70762db18d87c59dc6bc1ab7c3eb963ed", "shasum": "" }, "require": { @@ -858,7 +858,7 @@ "uri", "url" ], - "time": "2015-05-15 14:11:12" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/security-core", @@ -866,12 +866,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "2c218453a47553aadc3fef60f44b9c10cdee34ac" + "reference": "8253e027bf8a1c9c573a7b3c494027847058c959" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/2c218453a47553aadc3fef60f44b9c10cdee34ac", - "reference": "2c218453a47553aadc3fef60f44b9c10cdee34ac", + "url": "https://api.github.com/repos/symfony/security-core/zipball/8253e027bf8a1c9c573a7b3c494027847058c959", + "reference": "8253e027bf8a1c9c573a7b3c494027847058c959", "shasum": "" }, "require": { @@ -921,7 +921,7 @@ ], "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", - "time": "2015-05-15 14:11:12" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/security-csrf", @@ -983,12 +983,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/TwigBridge.git", - "reference": "2e072a1ff57989abf76a04dc6b02838b7bdccb44" + "reference": "a02e3a8ff1f8eda04d0e0655d2cefcbe9ecc4e14" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/TwigBridge/zipball/2e072a1ff57989abf76a04dc6b02838b7bdccb44", - "reference": "2e072a1ff57989abf76a04dc6b02838b7bdccb44", + "url": "https://api.github.com/repos/symfony/TwigBridge/zipball/a02e3a8ff1f8eda04d0e0655d2cefcbe9ecc4e14", + "reference": "a02e3a8ff1f8eda04d0e0655d2cefcbe9ecc4e14", "shasum": "" }, "require": { @@ -1053,7 +1053,7 @@ ], "description": "Symfony Twig Bridge", "homepage": "https://symfony.com", - "time": "2015-05-20 08:44:53" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/yaml", @@ -1061,12 +1061,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "2396832f6f9ab2b8f62f00b5d3f2e722fc773d65" + "reference": "000e7fc2653335cd42c6d21405dac1c74224a387" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/2396832f6f9ab2b8f62f00b5d3f2e722fc773d65", - "reference": "2396832f6f9ab2b8f62f00b5d3f2e722fc773d65", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/000e7fc2653335cd42c6d21405dac1c74224a387", + "reference": "000e7fc2653335cd42c6d21405dac1c74224a387", "shasum": "" }, "require": { @@ -1102,7 +1102,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-05-12 15:16:46" + "time": "2015-07-01 14:16:54" }, { "name": "twig/twig", @@ -1225,12 +1225,12 @@ "target-dir": "Guzzle/Common", "source": { "type": "git", - "url": "https://github.com/guzzle/common.git", + "url": "https://github.com/Guzzle3/common.git", "reference": "bf73c87375f60861f8c7ccc7b95878023ade5306" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/common/zipball/bf73c87375f60861f8c7ccc7b95878023ade5306", + "url": "https://api.github.com/repos/Guzzle3/common/zipball/bf73c87375f60861f8c7ccc7b95878023ade5306", "reference": "bf73c87375f60861f8c7ccc7b95878023ade5306", "shasum": "" }, @@ -1269,12 +1269,12 @@ "target-dir": "Guzzle/Http", "source": { "type": "git", - "url": "https://github.com/guzzle/http.git", + "url": "https://github.com/Guzzle3/http.git", "reference": "1034125dfd906b73119e535f03153a62fccb1989" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/http/zipball/1034125dfd906b73119e535f03153a62fccb1989", + "url": "https://api.github.com/repos/Guzzle3/http/zipball/1034125dfd906b73119e535f03153a62fccb1989", "reference": "1034125dfd906b73119e535f03153a62fccb1989", "shasum": "" }, @@ -1326,12 +1326,12 @@ "target-dir": "Guzzle/Parser", "source": { "type": "git", - "url": "https://github.com/guzzle/parser.git", + "url": "https://github.com/Guzzle3/parser.git", "reference": "a25c2ddda1c52fb69a4ee56eb530b13ddd9573c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/parser/zipball/a25c2ddda1c52fb69a4ee56eb530b13ddd9573c2", + "url": "https://api.github.com/repos/Guzzle3/parser/zipball/a25c2ddda1c52fb69a4ee56eb530b13ddd9573c2", "reference": "a25c2ddda1c52fb69a4ee56eb530b13ddd9573c2", "shasum": "" }, @@ -1370,12 +1370,12 @@ "target-dir": "Guzzle/Stream", "source": { "type": "git", - "url": "https://github.com/guzzle/stream.git", + "url": "https://github.com/Guzzle3/stream.git", "reference": "a86111d9ac7db31d65a053c825869409fe8fc83f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/stream/zipball/a86111d9ac7db31d65a053c825869409fe8fc83f", + "url": "https://api.github.com/repos/Guzzle3/stream/zipball/a86111d9ac7db31d65a053c825869409fe8fc83f", "reference": "a86111d9ac7db31d65a053c825869409fe8fc83f", "shasum": "" }, @@ -2007,12 +2007,12 @@ "version": "v1.0.2", "source": { "type": "git", - "url": "https://github.com/fabpot/Pimple.git", + "url": "https://github.com/silexphp/Pimple.git", "reference": "ae11e57e8c2bb414b2ff93396dbbfc0eb92feb94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fabpot/Pimple/zipball/ae11e57e8c2bb414b2ff93396dbbfc0eb92feb94", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/ae11e57e8c2bb414b2ff93396dbbfc0eb92feb94", "reference": "ae11e57e8c2bb414b2ff93396dbbfc0eb92feb94", "shasum": "" }, @@ -2454,12 +2454,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/BrowserKit.git", - "reference": "491639704334283b5f1d87bb3298400f1f5cd2bf" + "reference": "4f297d7e00c375b6ab03732e076f65799a73937d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/491639704334283b5f1d87bb3298400f1f5cd2bf", - "reference": "491639704334283b5f1d87bb3298400f1f5cd2bf", + "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/4f297d7e00c375b6ab03732e076f65799a73937d", + "reference": "4f297d7e00c375b6ab03732e076f65799a73937d", "shasum": "" }, "require": { @@ -2501,7 +2501,7 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2015-05-12 15:16:46" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/css-selector", @@ -2562,12 +2562,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/DomCrawler.git", - "reference": "3a523d1725d5835e4a7277358190e7efae7d872f" + "reference": "3aed431721a4a779d1ec30210bd53075da9623f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/3a523d1725d5835e4a7277358190e7efae7d872f", - "reference": "3a523d1725d5835e4a7277358190e7efae7d872f", + "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/3aed431721a4a779d1ec30210bd53075da9623f5", + "reference": "3aed431721a4a779d1ec30210bd53075da9623f5", "shasum": "" }, "require": { @@ -2607,7 +2607,7 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2015-05-12 15:16:46" + "time": "2015-07-09 16:11:14" }, { "name": "symfony/process", @@ -2615,12 +2615,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "daf96f1491cf0b8d8de60e6d3b5fda8e502b3798" + "reference": "25d74c90d79e66905013714d8d188e4ccb5ff466" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/daf96f1491cf0b8d8de60e6d3b5fda8e502b3798", - "reference": "daf96f1491cf0b8d8de60e6d3b5fda8e502b3798", + "url": "https://api.github.com/repos/symfony/Process/zipball/25d74c90d79e66905013714d8d188e4ccb5ff466", + "reference": "25d74c90d79e66905013714d8d188e4ccb5ff466", "shasum": "" }, "require": { @@ -2656,7 +2656,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2015-05-15 14:11:12" + "time": "2015-07-01 14:16:54" } ], "aliases": [], From 903f100c5120ad516e248ee30b18dd9a64468656 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 17 Jul 2015 11:53:28 +0200 Subject: [PATCH 0511/1676] [ticket/13986] Add --resume option to reparser CLI PHPBB3-13986 --- .../default/container/services_console.yml | 1 + phpBB/language/en/cli.php | 1 + .../console/command/reparser/reparse.php | 241 +++++++++++++----- 3 files changed, 174 insertions(+), 69 deletions(-) diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index f39218ed9c..49d0626b4f 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -154,5 +154,6 @@ services: arguments: - @user - @text_reparser_collection + - @config_text tags: - { name: console.command } diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index d45c52ac5d..9ba481e705 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -68,6 +68,7 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MIN' => 'Lowest record ID to process', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MAX' => 'Highest record ID to process', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_SIZE' => 'Approximate number of records to process at a time', + 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RESUME' => 'Start reparsing where the last execution stopped', 'CLI_DESCRIPTION_RECALCULATE_EMAIL_HASH' => 'Recalculates the user_email_hash column of the users table.', 'CLI_DESCRIPTION_SET_ATOMIC_CONFIG' => 'Sets a configuration option’s value only if the old matches the current value', 'CLI_DESCRIPTION_SET_CONFIG' => 'Sets a configuration option’s value', diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 50d4bd01d6..44a4691981 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -22,25 +22,47 @@ use Symfony\Component\Console\Style\SymfonyStyle; class reparse extends \phpbb\console\command\command { /** - * @var \phpbb\di\service_collection + * @var \phpbb\config\db_text */ - protected $reparsers; + protected $config_text; + + /** + * @var InputInterface + */ + protected $input; /** * @var SymfonyStyle */ protected $io; + /** + * @var OutputInterface + */ + protected $output; + + /** + * @var \phpbb\di\service_collection + */ + protected $reparsers; + + /** + * @var array Reparser names as keys, and their last $current ID as values + */ + protected $resume_data; + /** * Constructor * * @param \phpbb\user $user * @param \phpbb\di\service_collection $reparsers + * @param \phpbb\config\db_text $config_text */ - public function __construct(\phpbb\user $user, \phpbb\di\service_collection $reparsers) + public function __construct(\phpbb\user $user, \phpbb\di\service_collection $reparsers, \phpbb\config\db_text $config_text) { require_once __DIR__ . '/../../../../includes/functions_content.php'; + $this->config_text = $config_text; $this->reparsers = $reparsers; parent::__construct($user); } @@ -62,6 +84,12 @@ class reparse extends \phpbb\console\command\command InputOption::VALUE_NONE, $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_DRY_RUN') ) + ->addOption( + 'resume', + null, + InputOption::VALUE_NONE, + $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RESUME') + ) ->addOption( 'range-min', null, @@ -86,78 +114,20 @@ class reparse extends \phpbb\console\command\command } /** - * Executes the command reparser:reparse + * Create a styled progress bar * - * @param InputInterface $input - * @param OutputInterface $output - * @return integer + * @param integer $max Max value for the progress bar + * @return \Symfony\Component\Console\Helper\ProgressBar */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function create_progress_bar($max) { - $this->io = new SymfonyStyle($input, $output); - - $name = $input->getArgument('reparser-name'); - if (isset($name)) - { - // Allow "post_text" to be an alias for "text_reparser.post_text" - if (!isset($this->reparsers[$name])) - { - $name = 'text_reparser.' . $name; - } - $this->reparse($input, $output, $name); - } - else - { - foreach ($this->reparsers as $name => $service) - { - $this->reparse($input, $output, $name); - } - } - - $this->io->success($this->user->lang('CLI_REPARSER_REPARSE_SUCCESS')); - - return 0; - } - - /** - * Reparse all text handled by given reparser within given range - * - * @param InputInterface $input - * @param OutputInterface $output - * @param string $name Reparser name - * @return null - */ - protected function reparse(InputInterface $input, OutputInterface $output, $name) - { - $reparser = $this->reparsers[$name]; - if ($input->getOption('dry-run')) - { - $reparser->disable_save(); - } - else - { - $reparser->enable_save(); - } - - // Start at range-max if specified or at the highest ID otherwise - $max = (is_null($input->getOption('range-max'))) ? $reparser->get_max_id() : $input->getOption('range-max'); - $min = $input->getOption('range-min'); - $size = $input->getOption('range-size'); - - if ($max === 0) - { - return; - } - - $this->io->section($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', preg_replace('(^text_reparser\\.)', '', $name), $min, $max)); - $progress = $this->io->createProgressBar($max); - if ($output->getVerbosity() === OutputInterface::VERBOSITY_VERBOSE) + if ($this->output->getVerbosity() === OutputInterface::VERBOSITY_VERBOSE) { $progress->setFormat('[%percent:3s%%] %message%'); $progress->setOverwrite(false); } - else if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) + else if ($this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) { $progress->setFormat('[%current:s%/%max:s%][%elapsed%/%estimated%][%memory%] %message%'); $progress->setOverwrite(false); @@ -171,8 +141,6 @@ class reparse extends \phpbb\console\command\command $progress->setBarWidth(60); } - $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING_START', preg_replace('(^text_reparser\\.)', '', $name))); - if (!defined('PHP_WINDOWS_VERSION_BUILD')) { $progress->setEmptyBarCharacter('░'); // light shade character \u2591 @@ -180,6 +148,115 @@ class reparse extends \phpbb\console\command\command $progress->setBarCharacter('▓'); // dark shade character \u2593 } + return $progress; + } + + /** + * Executes the command reparser:reparse + * + * @param InputInterface $input + * @param OutputInterface $output + * @return integer + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->input = $input; + $this->output = $output; + $this->io = new SymfonyStyle($input, $output); + $this->load_resume_data(); + + $name = $input->getArgument('reparser-name'); + if (isset($name)) + { + // Allow "post_text" to be an alias for "text_reparser.post_text" + if (!isset($this->reparsers[$name])) + { + $name = 'text_reparser.' . $name; + } + $this->reparse($name); + } + else + { + foreach ($this->reparsers as $name => $service) + { + $this->reparse($name); + } + } + + $this->io->success($this->user->lang('CLI_REPARSER_REPARSE_SUCCESS')); + + return 0; + } + + /** + * Get an option value, adjusted for given reparser + * + * Will use the last saved value if --resume is set and the option was not specified + * on the command line + * + * @param string $reparser_name Reparser name + * @param string $option_name Option name + * @return integer + */ + protected function get_option($reparser_name, $option_name) + { + // Return the option from the resume_data if applicable + if ($this->input->getOption('resume') && isset($this->resume_data[$reparser_name][$option_name]) && !$this->input->hasParameterOption('--' . $option_name)) + { + return $this->resume_data[$reparser_name][$option_name]; + } + + $value = $this->input->getOption($option_name); + + // range-max has no default value, it must be computed for each reparser + if ($option_name === 'range-max' && $value === null) + { + $value = $this->reparsers[$reparser_name]->get_max_id(); + } + + return $value; + } + + /** + * Load the resume data from the database + */ + protected function load_resume_data() + { + $resume_data = $this->config_text->get('reparser_resume'); + $this->resume_data = (empty($resume_data)) ? array() : unserialize($resume_data); + } + + /** + * Reparse all text handled by given reparser within given range + * + * @param string $name Reparser name + */ + protected function reparse($name) + { + $reparser = $this->reparsers[$name]; + if ($this->input->getOption('dry-run')) + { + $reparser->disable_save(); + } + else + { + $reparser->enable_save(); + } + + // Start at range-max if specified or at the highest ID otherwise + $max = $this->get_option($name, 'range-max'); + $min = $this->get_option($name, 'range-min'); + $size = $this->get_option($name, 'range-size'); + + if ($max === 0) + { + return; + } + + $this->io->section($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', preg_replace('(^text_reparser\\.)', '', $name), $min, $max)); + + $progress = $this->create_progress_bar($max); + $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING_START', preg_replace('(^text_reparser\\.)', '', $name))); $progress->start(); // Start from $max and decrement $current by $size until we reach $min @@ -194,9 +271,35 @@ class reparse extends \phpbb\console\command\command $current = $start - 1; $progress->setProgress($max + 1 - $start); + + $this->update_resume_data($name, $current); } $progress->finish(); $this->io->newLine(2); } + + /** + * Save the resume data to the database + */ + protected function save_resume_data() + { + $this->config_text->set('reparser_resume', serialize($this->resume_data)); + } + + /** + * Save the resume data to the database + * + * @param string $name Reparser name + * @param string $current Current ID + */ + protected function update_resume_data($name, $current) + { + $this->resume_data[$name] = array( + 'range-min' => $this->input->getOption('range-min'), + 'range-max' => $current, + 'range-size' => $this->input->getOption('range-size'), + ); + $this->save_resume_data(); + } } From 9274bc4e3263b4aa9e278009fbc17f10985c439e Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 17 Jul 2015 14:00:47 +0200 Subject: [PATCH 0512/1676] [ticket/13986] Fixed resume data to carry through multiple runs Options restored from a previous execution should carry to the next resumed execution PHPBB3-13986 --- phpBB/phpbb/console/command/reparser/reparse.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index 44a4691981..f81ebfa8ca 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -296,9 +296,9 @@ class reparse extends \phpbb\console\command\command protected function update_resume_data($name, $current) { $this->resume_data[$name] = array( - 'range-min' => $this->input->getOption('range-min'), + 'range-min' => $this->get_option($name, 'range-min'), 'range-max' => $current, - 'range-size' => $this->input->getOption('range-size'), + 'range-size' => $this->get_option($name, 'range-size'), ); $this->save_resume_data(); } From c8e209a2dee7548031b4d2b5137c2ef064d6f588 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 17 Jul 2015 16:52:52 +0200 Subject: [PATCH 0513/1676] [ticket/13986] Replaced hardcoded value PHPBB3-13986 --- phpBB/phpbb/console/command/reparser/reparse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index f81ebfa8ca..63124b4b8c 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -248,7 +248,7 @@ class reparse extends \phpbb\console\command\command $min = $this->get_option($name, 'range-min'); $size = $this->get_option($name, 'range-size'); - if ($max === 0) + if ($max < $min) { return; } From ca141f2e1ed7a83c21aaea0e7cc711017e7d140b Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 17 Jul 2015 18:28:27 +0200 Subject: [PATCH 0514/1676] [ticket/14036] Replace path_helper with a mock PHPBB3-14036 --- .../phpbb_test_case_helpers.php | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 70bd309653..3ad4d95039 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -435,20 +435,15 @@ class phpbb_test_case_helpers // Create a path_helper if (!$container->has('path_helper') || $container->getDefinition('path_helper')->isSynthetic()) { - $path_helper = new \phpbb\path_helper( - new \phpbb\symfony_request( - new phpbb_mock_request() - ), - new \phpbb\filesystem(), - $this->test_case->getMock('\phpbb\request\request'), - $phpbb_root_path, - $phpEx - ); + $path_helper = $this->test_case->getMockBuilder('phpbb\\path_helper') + ->disableOriginalConstructor() + ->setMethods(array('get_web_root_path')) + ->getMock(); + $path_helper->expects($this->test_case->any()) + ->method('get_web_root_path') + ->will($this->test_case->returnValue('./')); - $container->set( - 'path_helper', - $path_helper - ); + $container->set('path_helper', $path_helper); } else { From 6cc2510cee581370ed103a87f2c38d2aee282641 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Fri, 17 Jul 2015 19:10:36 +0200 Subject: [PATCH 0515/1676] [ticket/14036] Fixed mocked web root path ...to match what it would return normally PHPBB3-14036 --- tests/test_framework/phpbb_test_case_helpers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 3ad4d95039..c0f278c130 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -441,7 +441,7 @@ class phpbb_test_case_helpers ->getMock(); $path_helper->expects($this->test_case->any()) ->method('get_web_root_path') - ->will($this->test_case->returnValue('./')); + ->will($this->test_case->returnValue('phpBB/')); $container->set('path_helper', $path_helper); } From df56b2ed364e24f803047c9f64d168432ba2680c Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Wed, 16 Jul 2014 18:30:27 +0200 Subject: [PATCH 0516/1676] [ticket/8708] Add f_announce_global permission PHPBB3-8708 --- phpBB/develop/add_permissions.php | 1 + .../install/convertors/functions_phpbb20.php | 4 +- phpBB/install/schemas/schema_data.sql | 11 ++--- phpBB/language/en/acp/permissions_phpbb.php | 1 + .../data/v320/announce_global_permission.php | 41 +++++++++++++++++++ phpBB/phpbb/permissions.php | 1 + 6 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 phpBB/phpbb/db/migration/data/v320/announce_global_permission.php diff --git a/phpBB/develop/add_permissions.php b/phpBB/develop/add_permissions.php index a5279f8f13..88c2c35ac0 100644 --- a/phpBB/develop/add_permissions.php +++ b/phpBB/develop/add_permissions.php @@ -64,6 +64,7 @@ $f_permissions = array( 'f_vote' => array(1, 0), 'f_votechg' => array(1, 0), 'f_announce'=> array(1, 0), + 'f_announce_global' => array(1, 0), 'f_sticky' => array(1, 0), 'f_attach' => array(1, 0), 'f_download'=> array(1, 0), diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php index 48cff426b8..aa2c59f28c 100644 --- a/phpBB/install/convertors/functions_phpbb20.php +++ b/phpBB/install/convertors/functions_phpbb20.php @@ -661,7 +661,7 @@ function phpbb_convert_authentication($mode) 'auth_delete' => 'f_delete', 'auth_pollcreate' => 'f_poll', 'auth_vote' => 'f_vote', - 'auth_announce' => 'f_announce', + 'auth_announce' => array('f_announce', 'f_announce_global'), 'auth_sticky' => 'f_sticky', 'auth_attachments' => array('f_attach', 'f_download'), 'auth_download' => 'f_download', @@ -990,7 +990,7 @@ function phpbb_convert_authentication($mode) // We make sure that they have at least standard access to the forums they moderate in addition to the moderating permissions $mod_post_map = array( - 'auth_announce' => 'f_announce', + 'auth_announce' => array('f_announce', 'f_announce_global'), 'auth_sticky' => 'f_sticky' ); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index c53c252e2f..06626b4617 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -310,6 +310,7 @@ INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin # -- Forum related auth options INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_announce', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_announce_global', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_attach', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bbcode', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bump', 1); @@ -552,7 +553,7 @@ INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 14, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%'; # Standard Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 15, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 15, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_flash', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock'); # No Access (f_) INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 16, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option = 'f_'; @@ -561,20 +562,20 @@ INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 17, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_search', 'f_subscribe', 'f_print'); # Limited Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 18, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 18, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg'); # Bot Access (f_) INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 19, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_print'); # On Moderation Queue (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg', 'f_noapprove'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg', 'f_noapprove'); INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove'); # Standard Access + Polls (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 21, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_sticky', 'f_user_lock'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 21, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_flash', 'f_ignoreflood', 'f_sticky', 'f_user_lock'); # Limited Access + Polls (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 22, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_sticky', 'f_user_lock', 'f_votechg'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 22, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_sticky', 'f_user_lock', 'f_votechg'); # New Member (u_) INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 23, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group', 'u_chgprofileinfo'); diff --git a/phpBB/language/en/acp/permissions_phpbb.php b/phpBB/language/en/acp/permissions_phpbb.php index b9aeed8fcb..8d826e4cbf 100644 --- a/phpBB/language/en/acp/permissions_phpbb.php +++ b/phpBB/language/en/acp/permissions_phpbb.php @@ -120,6 +120,7 @@ $lang = array_merge($lang, array( 'ACL_F_POST' => 'Can start new topics', 'ACL_F_STICKY' => 'Can post stickies', 'ACL_F_ANNOUNCE' => 'Can post announcements', + 'ACL_F_ANNOUNCE_GLOBAL' => 'Can post global announcements', 'ACL_F_REPLY' => 'Can reply to topics', 'ACL_F_EDIT' => 'Can edit own posts', 'ACL_F_DELETE' => 'Can permanently delete own posts', diff --git a/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php b/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php new file mode 100644 index 0000000000..fe30a1c1b8 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php @@ -0,0 +1,41 @@ + +* @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\v320; + +class announce_global_permission extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + $sql = 'SELECT auth_option_id + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option = 'f_announce_global'"; + $result = $this->db->sql_query($sql); + $auth_option_id = $this->db->sql_fetchfield('auth_option_id'); + $this->db->sql_freeresult($result); + + return $auth_option_id !== false; + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\rc2'); + } + + public function update_data() + { + return array( + array('permission.add', array('f_announce_global', false, 'f_announce')), + ); + } +} diff --git a/phpBB/phpbb/permissions.php b/phpBB/phpbb/permissions.php index 82f59b5c20..c462f72a73 100644 --- a/phpBB/phpbb/permissions.php +++ b/phpBB/phpbb/permissions.php @@ -251,6 +251,7 @@ class permissions 'f_post' => array('lang' => 'ACL_F_POST', 'cat' => 'post'), 'f_sticky' => array('lang' => 'ACL_F_STICKY', 'cat' => 'post'), 'f_announce' => array('lang' => 'ACL_F_ANNOUNCE', 'cat' => 'post'), + 'f_announce_global' => array('lang' => 'ACL_F_ANNOUNCE_GLOBAL', 'cat' => 'post'), 'f_reply' => array('lang' => 'ACL_F_REPLY', 'cat' => 'post'), 'f_edit' => array('lang' => 'ACL_F_EDIT', 'cat' => 'post'), 'f_delete' => array('lang' => 'ACL_F_DELETE', 'cat' => 'post'), From 7d31232846e29311e5b76bf32f41f64da7985a79 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Wed, 16 Jul 2014 18:31:12 +0200 Subject: [PATCH 0517/1676] [ticket/8708] Apply permission 'f_announce_global' PHPBB3-8708 --- phpBB/includes/functions_posting.php | 13 +++++-------- phpBB/includes/mcp/mcp_forum.php | 3 ++- phpBB/includes/mcp/mcp_main.php | 2 +- phpBB/mcp.php | 4 ++-- phpBB/posting.php | 3 +++ phpBB/styles/prosilver/template/mcp_forum.html | 6 ++---- phpBB/viewtopic.php | 4 ++-- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 9109c48ab6..e4520d7f03 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -337,18 +337,15 @@ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) $toggle = false; $topic_types = array( - 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'), - 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'), - 'global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL') + 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'), + 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'), + 'announce_global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL') ); $topic_type_array = array(); foreach ($topic_types as $auth_key => $topic_value) { - // We do not have a special post global announcement permission - $auth_key = ($auth_key == 'global') ? 'announce' : $auth_key; - if ($auth->acl_get('f_' . $auth_key, $forum_id)) { $toggle = true; @@ -378,8 +375,8 @@ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) $template->assign_vars(array( 'S_TOPIC_TYPE_STICKY' => ($auth->acl_get('f_sticky', $forum_id)), - 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_get('f_announce', $forum_id))) - ); + 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_gets('f_announce', 'f_announce_global', $forum_id)), + )); } return $toggle; diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index 9a280c0ea5..06bbf1ce41 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -131,9 +131,10 @@ function mcp_forum_view($id, $mode, $action, $forum_info) 'S_CAN_SYNC' => $auth->acl_get('m_', $forum_id), 'S_CAN_APPROVE' => $auth->acl_get('m_approve', $forum_id), 'S_MERGE_SELECT' => ($merge_select) ? true : false, - 'S_CAN_MAKE_NORMAL' => $auth->acl_gets('f_sticky', 'f_announce', $forum_id), + 'S_CAN_MAKE_NORMAL' => $auth->acl_gets('f_sticky', 'f_announce', 'f_announce_global', $forum_id), 'S_CAN_MAKE_STICKY' => $auth->acl_get('f_sticky', $forum_id), 'S_CAN_MAKE_ANNOUNCE' => $auth->acl_get('f_announce', $forum_id), + 'S_CAN_MAKE_ANNOUNCE_GLOBAL' => $auth->acl_get('f_announce_global', $forum_id), 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id), 'U_VIEW_FORUM_LOGS' => ($auth->acl_gets('a_', 'm_', $forum_id) && $module->loaded('logs')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=logs&mode=forum_logs&f=' . $forum_id) : '', diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 2659a4bf01..66e59bb74d 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -362,7 +362,7 @@ function change_topic_type($action, $topic_ids) case 'make_global': $new_topic_type = POST_GLOBAL; - $check_acl = 'f_announce'; + $check_acl = 'f_announce_global'; $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS'; break; diff --git a/phpBB/mcp.php b/phpBB/mcp.php index cb53f4eec9..a5fa09ba2b 100644 --- a/phpBB/mcp.php +++ b/phpBB/mcp.php @@ -111,8 +111,8 @@ if (!$auth->acl_getf_global('m_')) 'lock' => 'f_user_lock', 'make_sticky' => 'f_sticky', 'make_announce' => 'f_announce', - 'make_global' => 'f_announce', - 'make_normal' => array('f_announce', 'f_sticky') + 'make_global' => 'f_announce_global', + 'make_normal' => array('f_announce', 'f_announce_global', 'f_sticky') ); $allow_user = false; diff --git a/phpBB/posting.php b/phpBB/posting.php index 7f89bdbadf..52cd1093c0 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1202,6 +1202,9 @@ if ($submit || $preview || $refresh) switch ($post_data['topic_type']) { case POST_GLOBAL: + $auth_option = 'f_announce_global'; + break; + case POST_ANNOUNCE: $auth_option = 'f_announce'; break; diff --git a/phpBB/styles/prosilver/template/mcp_forum.html b/phpBB/styles/prosilver/template/mcp_forum.html index 8fdec01212..f0d8d45e40 100644 --- a/phpBB/styles/prosilver/template/mcp_forum.html +++ b/phpBB/styles/prosilver/template/mcp_forum.html @@ -131,10 +131,8 @@ - - - - + + diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 4a42d78b2b..b9cb226920 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -583,10 +583,10 @@ $quickmod_array = array( 'merge' => array('MERGE_POSTS', $auth->acl_get('m_merge', $forum_id)), 'merge_topic' => array('MERGE_TOPIC', $auth->acl_get('m_merge', $forum_id)), 'fork' => array('FORK_TOPIC', $auth->acl_get('m_move', $forum_id)), - 'make_normal' => array('MAKE_NORMAL', ($allow_change_type && $auth->acl_gets('f_sticky', 'f_announce', $forum_id) && $topic_data['topic_type'] != POST_NORMAL)), + 'make_normal' => array('MAKE_NORMAL', ($allow_change_type && $auth->acl_gets('f_sticky', 'f_announce', 'f_announce_global', $forum_id) && $topic_data['topic_type'] != POST_NORMAL)), 'make_sticky' => array('MAKE_STICKY', ($allow_change_type && $auth->acl_get('f_sticky', $forum_id) && $topic_data['topic_type'] != POST_STICKY)), 'make_announce' => array('MAKE_ANNOUNCE', ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_data['topic_type'] != POST_ANNOUNCE)), - 'make_global' => array('MAKE_GLOBAL', ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_data['topic_type'] != POST_GLOBAL)), + 'make_global' => array('MAKE_GLOBAL', ($allow_change_type && $auth->acl_get('f_announce_global', $forum_id) && $topic_data['topic_type'] != POST_GLOBAL)), 'topic_logs' => array('VIEW_TOPIC_LOGS', $auth->acl_get('m_', $forum_id)), ); From c89b226a7ae03c2e4ff12e60d36a27fe269583d4 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Mon, 20 Jul 2015 18:06:02 +0200 Subject: [PATCH 0518/1676] [ticket/13740] Add more room for further tasks PHPBB3-13740 --- .../installer/container/services_install_data.yml | 8 ++++---- .../container/services_install_database.yml | 8 ++++---- .../container/services_install_filesystem.yml | 4 ++-- .../container/services_install_finish.yml | 6 +++--- .../container/services_install_obtain_data.yml | 14 +++++++------- .../container/services_install_requirements.yml | 6 +++--- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/phpBB/config/installer/container/services_install_data.yml b/phpBB/config/installer/container/services_install_data.yml index c21f859406..ea5b5a2c52 100644 --- a/phpBB/config/installer/container/services_install_data.yml +++ b/phpBB/config/installer/container/services_install_data.yml @@ -9,7 +9,7 @@ services: - %core.root_path% - %core.php_ext% tags: - - { name: install_data_install, order: 2 } + - { name: install_data_install, order: 20 } installer.install_data.add_languages: class: phpbb\install\module\install_data\task\add_languages @@ -18,7 +18,7 @@ services: - @installer.helper.container_factory - @language.helper.language_file tags: - - { name: install_data_install, order: 1 } + - { name: install_data_install, order: 10 } installer.install_data.add_modules: class: phpbb\install\module\install_data\task\add_modules @@ -26,7 +26,7 @@ services: - @installer.helper.iohandler - @installer.helper.container_factory tags: - - { name: install_data_install, order: 3 } + - { name: install_data_install, order: 30 } installer.module.data_install_collection: class: phpbb\di\ordered_service_collection @@ -41,4 +41,4 @@ services: arguments: - @installer.module.data_install_collection tags: - - { name: installer_install_module, order: 5 } + - { name: installer_install_module, order: 50 } diff --git a/phpBB/config/installer/container/services_install_database.yml b/phpBB/config/installer/container/services_install_database.yml index f42fa65239..743d62bae5 100644 --- a/phpBB/config/installer/container/services_install_database.yml +++ b/phpBB/config/installer/container/services_install_database.yml @@ -9,7 +9,7 @@ services: - %core.root_path% - %core.php_ext% tags: - - { name: install_database_install, order: 1 } + - { name: install_database_install, order: 10 } installer.install_database.add_default_data: class: phpbb\install\module\install_database\task\add_default_data @@ -21,7 +21,7 @@ services: - @language - %core.root_path% tags: - - { name: install_database_install, order: 2 } + - { name: install_database_install, order: 20 } installer.install_database.add_config_settings: class: phpbb\install\module\install_database\task\add_config_settings @@ -33,7 +33,7 @@ services: - @language - %core.root_path% tags: - - { name: install_database_install, order: 3 } + - { name: install_database_install, order: 30 } installer.module.install_database_collection: class: phpbb\di\ordered_service_collection @@ -48,4 +48,4 @@ services: arguments: - @installer.module.install_database_collection tags: - - { name: installer_install_module, order: 4 } + - { name: installer_install_module, order: 40 } diff --git a/phpBB/config/installer/container/services_install_filesystem.yml b/phpBB/config/installer/container/services_install_filesystem.yml index cbd8381d02..776d7b9198 100644 --- a/phpBB/config/installer/container/services_install_filesystem.yml +++ b/phpBB/config/installer/container/services_install_filesystem.yml @@ -9,7 +9,7 @@ services: - %core.root_path% - %core.php_ext% tags: - - { name: install_filesystem_install, order: 1 } + - { name: install_filesystem_install, order: 10 } installer.module.install_filesystem_collection: class: phpbb\di\ordered_service_collection @@ -24,4 +24,4 @@ services: arguments: - @installer.module.install_filesystem_collection tags: - - { name: installer_install_module, order: 3 } + - { name: installer_install_module, order: 30 } diff --git a/phpBB/config/installer/container/services_install_finish.yml b/phpBB/config/installer/container/services_install_finish.yml index 7f4c4d99bf..1dd280306a 100644 --- a/phpBB/config/installer/container/services_install_finish.yml +++ b/phpBB/config/installer/container/services_install_finish.yml @@ -4,7 +4,7 @@ services: arguments: - @installer.helper.container_factory tags: - - { name: install_finish, order: 1 } + - { name: install_finish, order: 10 } installer.install_finish.notify_user: class: phpbb\install\module\install_finish\task\notify_user @@ -15,7 +15,7 @@ services: - %core.root_path% - %core.php_ext% tags: - - { name: install_finish, order: 2 } + - { name: install_finish, order: 20 } installer.module.install_finish_collection: class: phpbb\di\ordered_service_collection @@ -30,4 +30,4 @@ services: arguments: - @installer.module.install_finish_collection tags: - - { name: installer_install_module, order: 6 } + - { name: installer_install_module, order: 60 } diff --git a/phpBB/config/installer/container/services_install_obtain_data.yml b/phpBB/config/installer/container/services_install_obtain_data.yml index 49c2b99f19..a1fab313c4 100644 --- a/phpBB/config/installer/container/services_install_obtain_data.yml +++ b/phpBB/config/installer/container/services_install_obtain_data.yml @@ -5,7 +5,7 @@ services: - @installer.helper.config - @installer.helper.iohandler tags: - - { name: install_obtain_data, order: 1 } + - { name: install_obtain_data, order: 10 } installer.obtain_data.obtain_board_data: class: phpbb\install\module\obtain_data\task\obtain_board_data @@ -14,7 +14,7 @@ services: - @installer.helper.iohandler - @language.helper.language_file tags: - - { name: install_obtain_data, order: 5 } + - { name: install_obtain_data, order: 50 } installer.obtain_data.obtain_database_data: class: phpbb\install\module\obtain_data\task\obtain_database_data @@ -23,7 +23,7 @@ services: - @installer.helper.config - @installer.helper.iohandler tags: - - { name: install_obtain_data, order: 2 } + - { name: install_obtain_data, order: 20 } installer.obtain_data.obtain_email_data: class: phpbb\install\module\obtain_data\task\obtain_email_data @@ -31,14 +31,14 @@ services: - @installer.helper.config - @installer.helper.iohandler tags: - - { name: install_obtain_data, order: 4 } + - { name: install_obtain_data, order: 40 } installer.obtain_data.obtain_imagick_path: class: phpbb\install\module\obtain_data\task\obtain_imagick_path arguments: - @installer.helper.config tags: - - { name: install_obtain_data, order: 6 } + - { name: install_obtain_data, order: 60 } installer.obtain_data.obtain_server_data: class: phpbb\install\module\obtain_data\task\obtain_server_data @@ -46,7 +46,7 @@ services: - @installer.helper.config - @installer.helper.iohandler tags: - - { name: install_obtain_data, order: 3 } + - { name: install_obtain_data, order: 30 } installer.module.install_obtain_data_collection: class: phpbb\di\ordered_service_collection @@ -63,4 +63,4 @@ services: - true - false tags: - - { name: installer_install_module, order: 2 } + - { name: installer_install_module, order: 20 } diff --git a/phpBB/config/installer/container/services_install_requirements.yml b/phpBB/config/installer/container/services_install_requirements.yml index 1a6ed634cf..f368031707 100644 --- a/phpBB/config/installer/container/services_install_requirements.yml +++ b/phpBB/config/installer/container/services_install_requirements.yml @@ -7,7 +7,7 @@ services: - %core.root_path% - %core.php_ext% tags: - - { name: installer_requirements, order: 1 } + - { name: installer_requirements, order: 10 } installer.requirements.check_server_environment: class: phpbb\install\module\requirements\task\check_server_environment @@ -15,7 +15,7 @@ services: - @installer.helper.database - @installer.helper.iohandler tags: - - { name: installer_requirements, order: 2 } + - { name: installer_requirements, order: 20 } installer.module.install_requirements_collection: class: phpbb\di\ordered_service_collection @@ -33,4 +33,4 @@ services: - true - false tags: - - { name: installer_install_module, order: 1 } + - { name: installer_install_module, order: 10 } From 846ab1d22fd33aaeeb1f122c14a4ba6156b7d6d5 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Mon, 20 Jul 2015 18:12:50 +0200 Subject: [PATCH 0519/1676] [ticket/13740] Move install-config.yml to docs/ PHPBB3-13740 --- phpBB/{install-config.yml => docs/install-config.sample..yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename phpBB/{install-config.yml => docs/install-config.sample..yml} (100%) diff --git a/phpBB/install-config.yml b/phpBB/docs/install-config.sample..yml similarity index 100% rename from phpBB/install-config.yml rename to phpBB/docs/install-config.sample..yml From 88bf1d7f5802fc37bf77277a8ee65c6fb1f34c87 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Mon, 20 Jul 2015 18:22:53 +0200 Subject: [PATCH 0520/1676] [ticket/13740] Clean up install config file when installation has finished PHPBB3-13740 --- phpBB/phpbb/install/helper/config.php | 23 +++++++++++++++++++++++ phpBB/phpbb/install/installer.php | 9 ++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php index 38fdf960f7..457b64b301 100644 --- a/phpBB/phpbb/install/helper/config.php +++ b/phpBB/phpbb/install/helper/config.php @@ -73,6 +73,13 @@ class config */ protected $navigation_data; + /** + * Flag indicating that config file should be cleaned up + * + * @var bool + */ + protected $do_clean_up; + /** * Constructor */ @@ -81,6 +88,7 @@ class config $this->filesystem = $filesystem; $this->php_ini = $php_ini; $this->phpbb_root_path = $phpbb_root_path; + $this->do_clean_up = false; // Set up data arrays $this->navigation_data = array(); @@ -228,6 +236,12 @@ class config */ public function save_config() { + if ($this->do_clean_up) + { + @unlink($this->install_config_file); + return; + } + // Create array to save $save_array = array( 'installer_config' => $this->installer_config, @@ -336,6 +350,15 @@ class config return $this->navigation_data; } + /** + * Removes install config file + */ + public function clean_up_config_file() + { + $this->do_clean_up = true; + @unlink($this->install_config_file); + } + /** * Filling up system_data array */ diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index 548615cb1d..695632472a 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -219,7 +219,14 @@ class installer // Save install progress try { - $this->install_config->save_config(); + if ($install_finished) + { + $this->install_config->clean_up_config_file(); + } + else + { + $this->install_config->save_config(); + } } catch (installer_config_not_writable_exception $e) { From 6216007caaa884bdbca8bbb5e098ff231b5a36a6 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Mon, 20 Jul 2015 18:47:10 +0200 Subject: [PATCH 0521/1676] [ticket/13740] Fix docblocks and comments PHPBB3-13740 --- phpBB/phpbb/install/controller/install.php | 1 + phpBB/phpbb/install/helper/iohandler/cli_iohandler.php | 3 ++- phpBB/phpbb/install/module/install_finish/task/notify_user.php | 2 +- .../install/module/requirements/task/check_filesystem.php | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php index c1329b6456..c742906305 100644 --- a/phpBB/phpbb/install/controller/install.php +++ b/phpBB/phpbb/install/controller/install.php @@ -77,6 +77,7 @@ class install * @param factory $factory * @param navigation_provider $nav_provider * @param language $language + * @param template $template * @param request_interface $request * @param installer $installer */ diff --git a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php index f9c19f6d85..bf68f363c3 100644 --- a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php @@ -45,7 +45,8 @@ class cli_iohandler extends iohandler_base /** * Set the style and output used to display feedback; * - * @param OutputStyle $style + * @param OutputStyle $style + * @param OutputInterface $output */ public function set_style(OutputStyle $style, OutputInterface $output) { diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php index 4ab6ec56c6..baffaf2228 100644 --- a/phpBB/phpbb/install/module/install_finish/task/notify_user.php +++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php @@ -85,7 +85,7 @@ class notify_user extends \phpbb\install\task_base */ public function run() { - // @todo + // @todo Login user after installation has been finished //$this->user->setup('common'); //$this->user->session_begin(); diff --git a/phpBB/phpbb/install/module/requirements/task/check_filesystem.php b/phpBB/phpbb/install/module/requirements/task/check_filesystem.php index 5b944b8415..ab6b1091e2 100644 --- a/phpBB/phpbb/install/module/requirements/task/check_filesystem.php +++ b/phpBB/phpbb/install/module/requirements/task/check_filesystem.php @@ -47,7 +47,7 @@ class check_filesystem extends \phpbb\install\task_base * Constructor * * @param \phpbb\filesystem\filesystem_interface $filesystem filesystem handler - * @parma \phpbb\install\helper\iohandler\iohandler_interface $response response helper + * @param \phpbb\install\helper\iohandler\iohandler_interface $response response helper * @param string $phpbb_root_path relative path to phpBB's root * @param string $php_ext extension of php files */ From 0488c49116f77de55da3ddf36aa2b08f6a5fd085 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Mon, 20 Jul 2015 19:26:07 +0200 Subject: [PATCH 0522/1676] [ticket/13740] Exit from installation if phpBB is already installed PHPBB3-13740 --- .../container/services_install_console.yml | 1 + .../container/services_install_controller.yml | 1 + .../container/services_installer.yml | 6 ++ phpBB/language/en/install.php | 3 +- .../console/command/install/install.php | 24 +++++--- phpBB/phpbb/install/controller/helper.php | 2 +- phpBB/phpbb/install/controller/install.php | 18 +++++- phpBB/phpbb/install/helper/install_helper.php | 60 +++++++++++++++++++ 8 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 phpBB/phpbb/install/helper/install_helper.php diff --git a/phpBB/config/installer/container/services_install_console.yml b/phpBB/config/installer/container/services_install_console.yml index 9a4808b6aa..5a1e898754 100644 --- a/phpBB/config/installer/container/services_install_console.yml +++ b/phpBB/config/installer/container/services_install_console.yml @@ -21,6 +21,7 @@ services: - @language - @installer.helper.iohandler_factory - @installer.installer.install + - @installer.helper.install_helper tags: - { name: console.installer.command } diff --git a/phpBB/config/installer/container/services_install_controller.yml b/phpBB/config/installer/container/services_install_controller.yml index c8d140aa5f..7acc7025a6 100644 --- a/phpBB/config/installer/container/services_install_controller.yml +++ b/phpBB/config/installer/container/services_install_controller.yml @@ -30,3 +30,4 @@ services: - @template - @request - @installer.installer.install + - @installer.helper.install_helper diff --git a/phpBB/config/installer/container/services_installer.yml b/phpBB/config/installer/container/services_installer.yml index 8e19be5c0c..62137aa9d8 100644 --- a/phpBB/config/installer/container/services_installer.yml +++ b/phpBB/config/installer/container/services_installer.yml @@ -56,6 +56,12 @@ services: - %core.root_path% - %core.php_ext% + installer.helper.install_helper: + class: phpbb\install\helper\install_helper + arguments: + - %core.root_path% + - %core.php_ext% + # -------- Installer -------------------------------- installer.module_base: abstract: true diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index f050d49ebd..10d25b0311 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -113,7 +113,8 @@ $lang = array_merge($lang, array( // General error messages $lang = array_merge($lang, array( - 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.', + 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.', + 'PHPBB_ALREADY_INSTALLED' => 'phpBB is already installed.' )); // Data obtaining translations diff --git a/phpBB/phpbb/install/console/command/install/install.php b/phpBB/phpbb/install/console/command/install/install.php index d3f6d363f8..e9b4192ded 100644 --- a/phpBB/phpbb/install/console/command/install/install.php +++ b/phpBB/phpbb/install/console/command/install/install.php @@ -14,6 +14,7 @@ namespace phpbb\install\console\command\install; use phpbb\install\exception\installer_exception; +use phpbb\install\helper\install_helper; use phpbb\install\helper\iohandler\cli_iohandler; use phpbb\install\helper\iohandler\factory; use phpbb\install\installer; @@ -40,6 +41,11 @@ class install extends \phpbb\console\command\command */ protected $installer; + /** + * @var install_helper + */ + protected $install_helper; + /** * @var language */ @@ -48,21 +54,22 @@ class install extends \phpbb\console\command\command /** * Constructor * - * @param language $language - * @param factory $factory - * @param installer $installer + * @param language $language + * @param factory $factory + * @param installer $installer + * @param install_helper $install_helper */ - public function __construct(language $language, factory $factory, installer $installer) + public function __construct(language $language, factory $factory, installer $installer, install_helper $install_helper) { $this->iohandler_factory = $factory; $this->installer = $installer; $this->language = $language; + $this->install_helper = $install_helper; parent::__construct(new \phpbb\user($language, 'datetime')); } /** - * * {@inheritdoc} */ protected function configure() @@ -89,8 +96,6 @@ class install extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { - // @todo check that phpBB is not already installed - $this->iohandler_factory->set_environment('cli'); /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */ @@ -102,6 +107,11 @@ class install extends \phpbb\console\command\command $config_file = $input->getArgument('config-file'); + if ($this->install_helper->is_phpbb_installed()) + { + $iohandler->add_error_message('PHPBB_ALREADY_INSTALLED'); + } + if (!is_file($config_file)) { $iohandler->add_error_message(array('MISSING_FILE', array($config_file))); diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index 5ef98ac2bb..a16298c525 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -219,7 +219,7 @@ class helper protected function render_language_select() { $langs = $this->lang_helper->get_available_languages(); - // @todo + // @todo Implement language change option } /** diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php index c742906305..5cd42fcb84 100644 --- a/phpBB/phpbb/install/controller/install.php +++ b/phpBB/phpbb/install/controller/install.php @@ -13,7 +13,9 @@ namespace phpbb\install\controller; +use phpbb\exception\http_exception; use phpbb\install\helper\config; +use phpbb\install\helper\install_helper; use phpbb\install\helper\navigation\navigation_provider; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\Response; @@ -69,6 +71,11 @@ class install */ protected $installer; + /** + * @var install_helper + */ + protected $install_helper; + /** * Constructor * @@ -80,8 +87,9 @@ class install * @param template $template * @param request_interface $request * @param installer $installer + * @param install_helper $install_helper */ - public function __construct(helper $helper, config $install_config, factory $factory, navigation_provider $nav_provider, language $language, template $template, request_interface $request, installer $installer) + public function __construct(helper $helper, config $install_config, factory $factory, navigation_provider $nav_provider, language $language, template $template, request_interface $request, installer $installer, install_helper $install_helper) { $this->controller_helper = $helper; $this->installer_config = $install_config; @@ -91,6 +99,7 @@ class install $this->template = $template; $this->request = $request; $this->installer = $installer; + $this->install_helper = $install_helper; } /** @@ -100,8 +109,6 @@ class install */ public function handle() { - // @todo check that phpBB is not already installed - $this->template->assign_vars(array( 'U_ACTION' => $this->controller_helper->route('phpbb_installer_install'), )); @@ -124,6 +131,11 @@ class install /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */ $iohandler = $this->iohandler_factory->get(); + if ($this->install_helper->is_phpbb_installed()) + { + throw new http_exception(404, 'PAGE_NOT_FOUND'); + } + // Set active navigation stage if (isset($nav_data['active']) && is_array($nav_data['active'])) { diff --git a/phpBB/phpbb/install/helper/install_helper.php b/phpBB/phpbb/install/helper/install_helper.php new file mode 100644 index 0000000000..c1506de5bf --- /dev/null +++ b/phpBB/phpbb/install/helper/install_helper.php @@ -0,0 +1,60 @@ + + * @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\install\helper; + +/** + * General helper functionality for the installer + */ +class install_helper +{ + /** + * @var string + */ + protected $php_ext; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * Constructor + * + * @param string $phpbb_root_path path to phpBB's root + * @param string $php_ext Extension of PHP files + */ + public function __construct($phpbb_root_path, $php_ext) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + } + + /** + * Check whether phpBB is installed. + * + * @return bool + */ + public function is_phpbb_installed() + { + $config_path = $this->phpbb_root_path . 'config' . $this->php_ext; + $install_lock_path = $this->phpbb_root_path . 'cache/install_lock'; + + if (file_exists($config_path) && !file_exists($install_lock_path)) + { + include_once $config_path; + } + + return defined('PHPBB_INSTALLED'); + } +} From b2b9fb1df2e6d37c8a327b7b6c380f19e1ff6496 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 21 Jul 2015 14:42:15 +0200 Subject: [PATCH 0523/1676] [ticket/13740] Fix CS and docblocks PHPBB3-13740 --- .../console/command/install/install.php | 10 +++++--- phpBB/phpbb/install/controller/install.php | 10 ++++---- .../cannot_build_container_exception.php | 2 +- ...nstaller_config_not_writable_exception.php | 2 +- .../exception/invalid_dbms_exception.php | 2 +- .../invalid_service_name_exception.php | 19 -------------- .../resource_limit_reached_exception.php | 3 +++ .../install/helper/container_factory.php | 17 +++++++++++++ .../helper/iohandler/ajax_iohandler.php | 8 ++---- phpBB/phpbb/install/installer.php | 25 ------------------- 10 files changed, 36 insertions(+), 62 deletions(-) delete mode 100644 phpBB/phpbb/install/exception/invalid_service_name_exception.php diff --git a/phpBB/phpbb/install/console/command/install/install.php b/phpBB/phpbb/install/console/command/install/install.php index e9b4192ded..81ad1039f6 100644 --- a/phpBB/phpbb/install/console/command/install/install.php +++ b/phpBB/phpbb/install/console/command/install/install.php @@ -110,13 +110,15 @@ class install extends \phpbb\console\command\command if ($this->install_helper->is_phpbb_installed()) { $iohandler->add_error_message('PHPBB_ALREADY_INSTALLED'); + + return 1; } if (!is_file($config_file)) { $iohandler->add_error_message(array('MISSING_FILE', array($config_file))); - return; + return 1; } try @@ -127,7 +129,7 @@ class install extends \phpbb\console\command\command { $iohandler->add_error_message('INVALID_YAML_FILE'); - return; + return 1; } $processor = new Processor(); @@ -141,7 +143,7 @@ class install extends \phpbb\console\command\command { $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage()); - return; + return 1; } $this->register_configuration($iohandler, $config); @@ -153,7 +155,7 @@ class install extends \phpbb\console\command\command catch (installer_exception $e) { $iohandler->add_error_message($e->getMessage()); - return; + return 1; } } diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php index 5cd42fcb84..b3103c8284 100644 --- a/phpBB/phpbb/install/controller/install.php +++ b/phpBB/phpbb/install/controller/install.php @@ -109,6 +109,11 @@ class install */ public function handle() { + if ($this->install_helper->is_phpbb_installed()) + { + throw new http_exception(404, 'PAGE_NOT_FOUND'); + } + $this->template->assign_vars(array( 'U_ACTION' => $this->controller_helper->route('phpbb_installer_install'), )); @@ -131,11 +136,6 @@ class install /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */ $iohandler = $this->iohandler_factory->get(); - if ($this->install_helper->is_phpbb_installed()) - { - throw new http_exception(404, 'PAGE_NOT_FOUND'); - } - // Set active navigation stage if (isset($nav_data['active']) && is_array($nav_data['active'])) { diff --git a/phpBB/phpbb/install/exception/cannot_build_container_exception.php b/phpBB/phpbb/install/exception/cannot_build_container_exception.php index 11be507bc9..6cf12b008b 100644 --- a/phpBB/phpbb/install/exception/cannot_build_container_exception.php +++ b/phpBB/phpbb/install/exception/cannot_build_container_exception.php @@ -14,7 +14,7 @@ namespace phpbb\install\exception; /** - * This exception should be thrown when + * Thrown when the container cannot be built */ class cannot_build_container_exception extends installer_exception { diff --git a/phpBB/phpbb/install/exception/installer_config_not_writable_exception.php b/phpBB/phpbb/install/exception/installer_config_not_writable_exception.php index 3f3b03f178..51864c5dca 100644 --- a/phpBB/phpbb/install/exception/installer_config_not_writable_exception.php +++ b/phpBB/phpbb/install/exception/installer_config_not_writable_exception.php @@ -14,7 +14,7 @@ namespace phpbb\install\exception; /** - * Exception for the event when installer config is not writable to disk + * Thrown when installer config is not writable to disk */ class installer_config_not_writable_exception extends installer_exception { diff --git a/phpBB/phpbb/install/exception/invalid_dbms_exception.php b/phpBB/phpbb/install/exception/invalid_dbms_exception.php index ccb35bc237..38de5f613a 100644 --- a/phpBB/phpbb/install/exception/invalid_dbms_exception.php +++ b/phpBB/phpbb/install/exception/invalid_dbms_exception.php @@ -14,7 +14,7 @@ namespace phpbb\install\exception; /** - * This exception should be thrown when + * Thrown when an unavailable DBMS has been selected */ class invalid_dbms_exception extends installer_exception { diff --git a/phpBB/phpbb/install/exception/invalid_service_name_exception.php b/phpBB/phpbb/install/exception/invalid_service_name_exception.php deleted file mode 100644 index dff4873f3c..0000000000 --- a/phpBB/phpbb/install/exception/invalid_service_name_exception.php +++ /dev/null @@ -1,19 +0,0 @@ - - * @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\install\exception; - -class invalid_service_name_exception extends installer_exception -{ - -} diff --git a/phpBB/phpbb/install/exception/resource_limit_reached_exception.php b/phpBB/phpbb/install/exception/resource_limit_reached_exception.php index 0b841747e6..025e09fbd3 100644 --- a/phpBB/phpbb/install/exception/resource_limit_reached_exception.php +++ b/phpBB/phpbb/install/exception/resource_limit_reached_exception.php @@ -13,6 +13,9 @@ namespace phpbb\install\exception; +/** + * Thrown when the installer is out of memory or time + */ class resource_limit_reached_exception extends installer_exception { diff --git a/phpBB/phpbb/install/helper/container_factory.php b/phpBB/phpbb/install/helper/container_factory.php index 255f8f428e..eb44b470b7 100644 --- a/phpBB/phpbb/install/helper/container_factory.php +++ b/phpBB/phpbb/install/helper/container_factory.php @@ -93,9 +93,26 @@ class container_factory * @param string $param_name * * @return mixed + * + * @throws \phpbb\install\exception\cannot_build_container_exception When container cannot be built */ public function get_parameter($param_name) { + // Check if container was built, if not try to build it + if ($this->container === null) + { + // Check whether container can be built + // We need config.php for that so let's check if it has been set up yet + if (filesize($this->phpbb_root_path . 'config.' . $this->php_ext)) + { + $this->build_container(); + } + else + { + throw new cannot_build_container_exception(); + } + } + return $this->container->getParameter($param_name); } diff --git a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php index 85cb2ca753..ce1112c7a1 100644 --- a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php @@ -96,10 +96,6 @@ class ajax_iohandler extends iohandler_base */ public function add_user_form_group($title, $form) { - // - // This code is pretty ugly... but works - // - $this->template->assign_var('S_FORM_ELEM_COUNT', sizeof($form)); $this->template->assign_block_vars('options', array( @@ -166,8 +162,8 @@ class ajax_iohandler extends iohandler_base $json_data = json_encode($json_data_array); // Try to push content to the browser - print (str_pad(' ', 4096) . "\n"); - print ($json_data . "\n\n"); + print(str_pad(' ', 4096) . "\n"); + print($json_data . "\n\n"); flush(); } diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index 695632472a..0e19129247 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -15,7 +15,6 @@ namespace phpbb\install; use phpbb\di\ordered_service_collection; use phpbb\install\exception\installer_config_not_writable_exception; -use phpbb\install\exception\invalid_service_name_exception; use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\exception\user_interaction_required_exception; use phpbb\install\helper\config; @@ -94,9 +93,6 @@ class installer // Variable used to check if the install process have been finished $install_finished = false; - // Flag used by exception handling, whether or not we need to flush output buffer once again - $flush_messages = false; - // We are installing something, so the introduction stage can go now... $this->install_config->set_finished_navigation_stage(array('install', 0, 'introduction')); $this->iohandler->set_finished_stage_menu(array('install', 0, 'introduction')); @@ -184,22 +180,6 @@ class installer { // Do nothing } - catch (invalid_service_name_exception $e) - { - $params = $e->get_parameters(); - - if (!empty($params)) - { - array_unshift($params, $e->getMessage()); - } - else - { - $params = $e->getMessage(); - } - - $this->iohandler->add_error_message($params); - $flush_messages = true; - } if ($install_finished) { @@ -211,11 +191,6 @@ class installer $this->iohandler->request_refresh(); } - if ($flush_messages) - { - $this->iohandler->send_response(); - } - // Save install progress try { From 3a3dd941452eca6f487bb8ab2d21c99f89846f24 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 21 Jul 2015 15:06:15 +0200 Subject: [PATCH 0524/1676] [ticket/13740] Remove default config CLI command PHPBB3-13740 --- .../container/services_install_console.yml | 10 -- .../command/install/config/default_config.php | 103 ------------------ 2 files changed, 113 deletions(-) delete mode 100644 phpBB/phpbb/install/console/command/install/config/default_config.php diff --git a/phpBB/config/installer/container/services_install_console.yml b/phpBB/config/installer/container/services_install_console.yml index 5a1e898754..6f931c5031 100644 --- a/phpBB/config/installer/container/services_install_console.yml +++ b/phpBB/config/installer/container/services_install_console.yml @@ -15,16 +15,6 @@ services: tags: - { name: console.installer.command } - console.installer.command.config.default: - class: phpbb\install\console\command\install\config\default_config - arguments: - - @language - - @installer.helper.iohandler_factory - - @installer.installer.install - - @installer.helper.install_helper - tags: - - { name: console.installer.command } - console.installer.command.config.show: class: phpbb\install\console\command\install\config\show arguments: diff --git a/phpBB/phpbb/install/console/command/install/config/default_config.php b/phpBB/phpbb/install/console/command/install/config/default_config.php deleted file mode 100644 index 75c9f94901..0000000000 --- a/phpBB/phpbb/install/console/command/install/config/default_config.php +++ /dev/null @@ -1,103 +0,0 @@ - -* @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\install\console\command\install\config; - -use phpbb\language\language; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Yaml\Yaml; - -class default_config extends \phpbb\console\command\command -{ - /** - * @var language - */ - protected $language; - - /** - * Constructor - * - * @param language $language - */ - public function __construct(language $language) - { - $this->language = $language; - - parent::__construct(new \phpbb\user($language, 'datetime')); - } - - /** - * - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName('install:config:default') - ; - } - - /** - * Display the default configuration - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * - * @return null - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $default_config = <<writeln($default_config); - } -} From 3d4f21c1f87f88c6cf6efd6e3844672d7784f09f Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 21 Jul 2015 15:13:54 +0200 Subject: [PATCH 0525/1676] [ticket/13740] Check navigation requirements PHPBB3-13740 --- .../container/services_install_navigation.yml | 2 ++ .../helper/navigation/install_navigation.php | 25 +++++++++++++++++++ .../helper/navigation/main_navigation.php | 3 +++ 3 files changed, 30 insertions(+) diff --git a/phpBB/config/installer/container/services_install_navigation.yml b/phpBB/config/installer/container/services_install_navigation.yml index 88c495825b..53e20e89cc 100644 --- a/phpBB/config/installer/container/services_install_navigation.yml +++ b/phpBB/config/installer/container/services_install_navigation.yml @@ -19,6 +19,8 @@ services: installer.navigation.install_navigation: class: phpbb\install\helper\navigation\install_navigation + arguments: + - @installer.helper.install_helper scope: prototype tags: - { name: installer.navigation } diff --git a/phpBB/phpbb/install/helper/navigation/install_navigation.php b/phpBB/phpbb/install/helper/navigation/install_navigation.php index 1389f11fa0..f690f8de76 100644 --- a/phpBB/phpbb/install/helper/navigation/install_navigation.php +++ b/phpBB/phpbb/install/helper/navigation/install_navigation.php @@ -13,10 +13,35 @@ namespace phpbb\install\helper\navigation; +use phpbb\install\helper\install_helper; + class install_navigation implements navigation_interface { + /** + * @var install_helper + */ + private $install_helper; + + /** + * Constructor + * + * @param install_helper $install_helper + */ + public function __construct(install_helper $install_helper) + { + $this->install_helper = $install_helper; + } + + /** + * {@inheritdoc} + */ public function get() { + if ($this->install_helper->is_phpbb_installed()) + { + return array(); + } + return array( 'install' => array( 'label' => 'INSTALL', diff --git a/phpBB/phpbb/install/helper/navigation/main_navigation.php b/phpBB/phpbb/install/helper/navigation/main_navigation.php index ad67840424..214bb04963 100644 --- a/phpBB/phpbb/install/helper/navigation/main_navigation.php +++ b/phpBB/phpbb/install/helper/navigation/main_navigation.php @@ -15,6 +15,9 @@ namespace phpbb\install\helper\navigation; class main_navigation implements navigation_interface { + /** + * {@inheritdoc} + */ public function get() { return array( From 030f6da9118a30541fe56403893e3679457a0684 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 21 Jul 2015 15:30:31 +0200 Subject: [PATCH 0526/1676] [ticket/13740] Remove extra dot from config sample's name PHPBB3-13740 --- .../{install-config.sample..yml => install-config.sample.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename phpBB/docs/{install-config.sample..yml => install-config.sample.yml} (100%) diff --git a/phpBB/docs/install-config.sample..yml b/phpBB/docs/install-config.sample.yml similarity index 100% rename from phpBB/docs/install-config.sample..yml rename to phpBB/docs/install-config.sample.yml From 136ec8d7e25efe7b466cb41f80dc5a75a51eaa68 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 21 Jul 2015 15:53:26 +0200 Subject: [PATCH 0527/1676] [ticket/13740] Keep keys when sorting navigation PHPBB3-13740 --- phpBB/phpbb/install/controller/helper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index a16298c525..569938be09 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -267,10 +267,10 @@ class helper protected function sort_navigation_level($nav_array) { $sorted = array(); - foreach ($nav_array as $nav) + foreach ($nav_array as $key => $nav) { $order = (isset($nav['order'])) ? $nav['order'] : 0; - $sorted[$order][] = $nav; + $sorted[$order][$key] = $nav; } // Linearization of navigation array From 11642a5f9481e4e25402833edb2bac903c23c627 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 22 Jul 2015 02:42:13 +0200 Subject: [PATCH 0528/1676] [ticket/13740] Keep language file's names PHPBB3-13740 --- phpBB/install/database_update.php | 2 +- phpBB/install/index.php | 2 +- phpBB/install_new/app.php | 2 +- phpBB/install_new/phpbbcli.php | 2 +- phpBB/language/en/install.php | 683 ++++++++++++++++++++++-------- phpBB/language/en/install_new.php | 305 +++++++++++++ phpBB/language/en/old_install.php | 629 --------------------------- 7 files changed, 813 insertions(+), 812 deletions(-) create mode 100644 phpBB/language/en/install_new.php delete mode 100644 phpBB/language/en/old_install.php diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 7ba11c37c4..853848d637 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -122,7 +122,7 @@ if (!isset($config['version_update_from'])) $orig_version = $config['version_update_from']; -$user->add_lang(array('common', 'acp/common', 'old_install', 'migrator')); +$user->add_lang(array('common', 'acp/common', 'install', 'migrator')); // Add own hook handler, if present. :o if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx)) diff --git a/phpBB/install/index.php b/phpBB/install/index.php index a1a8fc02b6..3559a10971 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -210,7 +210,7 @@ if (!file_exists($phpbb_root_path . 'language/' . $language) || !is_dir($phpbb_r } // And finally, load the relevant language files -$load_lang_files = array('common', 'acp/common', 'acp/board', 'old_install', 'posting'); +$load_lang_files = array('common', 'acp/common', 'acp/board', 'install', 'posting'); $new_path = $phpbb_root_path . 'install/update/new/language/' . $language . '/'; $old_path = $phpbb_root_path . 'language/' . $language . '/'; diff --git a/phpBB/install_new/app.php b/phpBB/install_new/app.php index 75b28fa092..b173f40dfc 100644 --- a/phpBB/install_new/app.php +++ b/phpBB/install_new/app.php @@ -67,7 +67,7 @@ $template->set_custom_style(array( /** @var \phpbb\language\language $language */ $language = $phpbb_installer_container->get('language'); -$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting')); +$language->add_lang(array('common', 'acp/common', 'acp/board', 'install_new', 'posting')); /* @var $http_kernel \Symfony\Component\HttpKernel\HttpKernel */ $http_kernel = $phpbb_installer_container->get('http_kernel'); diff --git a/phpBB/install_new/phpbbcli.php b/phpBB/install_new/phpbbcli.php index 20a202f584..4c8034be4e 100644 --- a/phpBB/install_new/phpbbcli.php +++ b/phpBB/install_new/phpbbcli.php @@ -61,7 +61,7 @@ $phpbb_filesystem = $phpbb_installer_container->get('filesystem'); /** @var \phpbb\language\language $language */ $language = $phpbb_installer_container->get('language'); -$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting', 'cli')); +$language->add_lang(array('common', 'acp/common', 'acp/board', 'install_new', 'posting', 'cli')); $application = new \phpbb\console\application('phpBB Installer', PHPBB_VERSION, $language); $application->register_container_commands($phpbb_installer_container->get('console.installer.command_collection')); diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 10d25b0311..a776a539ed 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -36,26 +36,166 @@ if (empty($lang) || !is_array($lang)) // equally where a string contains only two placeholders which are used to wrap text // in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine -// Common installer pages $lang = array_merge($lang, array( - 'INSTALL_PANEL' => 'Installation Panel', + 'ADMIN_CONFIG' => 'Administrator configuration', + 'ADMIN_PASSWORD' => 'Administrator password', + 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password', + 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.', + 'ADMIN_TEST' => 'Check administrator settings', + 'ADMIN_USERNAME' => 'Administrator username', + 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.', + 'APP_MAGICK' => 'Imagemagick support [ Attachments ]', + 'AUTHOR_NOTES' => 'Author notes
            » %s', + 'AVAILABLE' => 'Available', + 'AVAILABLE_CONVERTORS' => 'Available convertors', - 'STAGE_INSTALL' => 'Installing phpBB', + 'BEGIN_CONVERT' => 'Begin conversion', + 'BLANK_PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using no table prefix.', + 'BOARD_NOT_INSTALLED' => 'No installation found', + 'BOARD_NOT_INSTALLED_EXPLAIN' => 'The phpBB Unified Convertor Framework requires a default installation of phpBB3 to function, please proceed by first installing phpBB3.', + 'BACKUP_NOTICE' => 'Please backup your board before updating in case any problems arise during the update process.', - // Introduction page - 'INTRODUCTION_TITLE' => 'Introduction', - 'INTRODUCTION_BODY' => 'Welcome to phpBB3!

            phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.

            This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read the installation guide.

            To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.', + 'CATEGORY' => 'Category', + 'CACHE_STORE' => 'Cache type', + 'CACHE_STORE_EXPLAIN' => 'The physical location where data is cached, filesystem is preferred.', + 'CAT_CONVERT' => 'Convert', + 'CAT_INSTALL' => 'Install', + 'CAT_OVERVIEW' => 'Overview', + 'CAT_UPDATE' => 'Update', + 'CHANGE' => 'Change', + 'CHECK_TABLE_PREFIX' => 'Please check your table prefix and try again.', + 'CLEAN_VERIFY' => 'Cleaning up and verifying the final structure', + 'CLEANING_USERNAMES' => 'Cleaning usernames', + 'COLLIDING_CLEAN_USERNAME' => '%s is the clean username for:', + 'COLLIDING_USERNAMES_FOUND' => 'Colliding usernames were found on your old board. In order to complete the conversion please delete or rename these users so that there is only one user on your old board for each clean username.', + 'COLLIDING_USER' => '» user id: %d username: %s (%d posts)', + 'CONFIG_CONVERT' => 'Converting the configuration', + 'CONFIG_FILE_UNABLE_WRITE' => 'It was not possible to write the configuration file. Alternative methods for this file to be created are presented below.', + 'CONFIG_FILE_WRITTEN' => 'The configuration file has been written. You may now proceed to the next step of the installation.', + 'CONFIG_PHPBB_EMPTY' => 'The phpBB3 config variable for “%s†is empty.', + 'CONFIG_RETRY' => 'Retry', + 'CONTINUE_CONVERT' => 'Continue conversion', + 'CONTINUE_CONVERT_BODY' => 'A previous conversion attempt has been determined. You are now able to choose between starting a new conversion or continuing the conversion.', + 'CONTINUE_LAST' => 'Continue last statements', + 'CONTINUE_OLD_CONVERSION' => 'Continue previously started conversion', + 'CONVERT' => 'Convert', + 'CONVERT_COMPLETE' => 'Conversion completed', + 'CONVERT_COMPLETE_EXPLAIN' => 'You have now successfully converted your board to phpBB 3.1. You can now login and access your board. Please ensure that the settings were transferred correctly before enabling your board by deleting the install directory. Remember that help on using phpBB is available online via the Documentation and the support forums.', + 'CONVERT_INTRO' => 'Welcome to the phpBB Unified Convertor Framework', + 'CONVERT_INTRO_BODY' => 'From here, you are able to import data from other (installed) board systems. The list below shows all the conversion modules currently available. If there is no convertor shown in this list for the board software you wish to convert from, please check our website where further conversion modules may be available for download.', + 'CONVERT_NEW_CONVERSION' => 'New conversion', + 'CONVERT_NOT_EXIST' => 'The specified convertor does not exist.', + 'CONVERT_OPTIONS' => 'Options', + 'CONVERT_SETTINGS_VERIFIED' => 'The information you entered has been verified. To start the conversion process, please push the button below.', + 'CONV_ERR_FATAL' => 'Fatal conversion error', - // Support page - 'SUPPORT_TITLE' => 'Support', - 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:

            • installation
            • configuration
            • technical questions
            • problems relating to potential bugs in the software
            • updating from Release Candidate (RC) versions to the latest stable version
            • converting from phpBB 2.0.x to phpBB3
            • converting from other discussion board software to phpBB3 (please see the Convertors Forum)

            We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.

            Extensions / Styles

            For issues relating to Extensions, please post in the appropriate Extensions Forum.
            For issues relating to styles, templates and themes, please post in the appropriate Styles Forum.

            If your question relates to a specific package, please post directly in the topic dedicated to the package.

            Obtaining Support

            The phpBB Welcome Package
            Support Section
            Quick Start Guide

            To ensure you stay up to date with the latest news and releases, why not subscribe to our mailing list?

            ', + 'CONV_ERROR_ATTACH_FTP_DIR' => 'FTP upload for attachments is enabled at the old board. Please disable the FTP upload option and make sure a valid upload directory is specified, then copy all attachment files to this new web accessible directory. Once you have done this, restart the convertor.', + 'CONV_ERROR_CONFIG_EMPTY' => 'There is no configuration information available for the conversion.', + 'CONV_ERROR_FORUM_ACCESS' => 'Unable to get forum access information.', + 'CONV_ERROR_GET_CATEGORIES' => 'Unable to get categories.', + 'CONV_ERROR_GET_CONFIG' => 'Could not retrieve your board configuration.', + 'CONV_ERROR_COULD_NOT_READ' => 'Unable to access/read “%sâ€.', + 'CONV_ERROR_GROUP_ACCESS' => 'Unable to get group authentication information.', + 'CONV_ERROR_INCONSISTENT_GROUPS' => 'Inconsistency in groups table detected in add_bots() - you need to add all special groups if you do it manually.', + 'CONV_ERROR_INSERT_BOT' => 'Unable to insert bot into users table.', + 'CONV_ERROR_INSERT_BOTGROUP' => 'Unable to insert bot into bots table.', + 'CONV_ERROR_INSERT_USER_GROUP' => 'Unable to insert user into user_group table.', + 'CONV_ERROR_MESSAGE_PARSER' => 'Message parser error', + 'CONV_ERROR_NO_AVATAR_PATH' => 'Note to developer: you must specify $convertor[\'avatar_path\'] to use %s.', + 'CONV_ERROR_NO_FORUM_PATH' => 'The relative path to the source board has not been specified.', + 'CONV_ERROR_NO_GALLERY_PATH' => 'Note to developer: you must specify $convertor[\'avatar_gallery_path\'] to use %s.', + 'CONV_ERROR_NO_GROUP' => 'Group “%1$s†could not be found in %2$s.', + 'CONV_ERROR_NO_RANKS_PATH' => 'Note to developer: you must specify $convertor[\'ranks_path\'] to use %s.', + 'CONV_ERROR_NO_SMILIES_PATH' => 'Note to developer: you must specify $convertor[\'smilies_path\'] to use %s.', + 'CONV_ERROR_NO_UPLOAD_DIR' => 'Note to developer: you must specify $convertor[\'upload_path\'] to use %s.', + 'CONV_ERROR_PERM_SETTING' => 'Unable to insert/update permission setting.', + 'CONV_ERROR_PM_COUNT' => 'Unable to select folder pm count.', + 'CONV_ERROR_REPLACE_CATEGORY' => 'Unable to insert new forum replacing old category.', + 'CONV_ERROR_REPLACE_FORUM' => 'Unable to insert new forum replacing old forum.', + 'CONV_ERROR_USER_ACCESS' => 'Unable to get user authentication information.', + 'CONV_ERROR_WRONG_GROUP' => 'Wrong group “%1$s†defined in %2$s.', + 'CONV_OPTIONS_BODY' => 'This page collects the data required to access the source board. Enter the database details of your former board; the converter will not change anything in the database given below. The source board should be disabled to allow a consistent conversion.', + 'CONV_SAVED_MESSAGES' => 'Saved messages', - // License - 'LICENSE_TITLE' => 'General Public License', + 'COULD_NOT_COPY' => 'Could not copy file %1$s to %2$s

            Please check that the target directory exists and is writable by the webserver.', + 'COULD_NOT_FIND_PATH' => 'Could not find path to your former board. Please check your settings and try again.
            » %s was specified as the source path.', - // Install page - 'INSTALL_INTRO' => 'Welcome to Installation', - 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.

            In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:

            + 'DBMS' => 'Database type', + 'DB_CONFIG' => 'Database configuration', + 'DB_CONNECTION' => 'Database connection', + 'DB_ERR_INSERT' => 'Error while processing INSERT query.', + 'DB_ERR_LAST' => 'Error while processing query_last.', + 'DB_ERR_QUERY_FIRST' => 'Error while executing query_first.', + 'DB_ERR_QUERY_FIRST_TABLE' => 'Error while executing query_first, %s (“%sâ€).', + 'DB_ERR_SELECT' => 'Error while running SELECT query.', + 'DB_HOST' => 'Database server hostname or DSN', + 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.', + 'DB_NAME' => 'Database name', + 'DB_PASSWORD' => 'Database password', + 'DB_PORT' => 'Database server port', + 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.', + 'DB_UPDATE_NOT_SUPPORTED' => 'We are sorry, but this script does not support updating from versions of phpBB prior to “%1$sâ€. The version you currently have installed is “%2$sâ€. Please update to a previous version before running this script. Assistance with this is available in the Support Forum on phpBB.com.', + 'DB_USERNAME' => 'Database username', + 'DB_TEST' => 'Test connection', + 'DEFAULT_LANG' => 'Default board language', + 'DEFAULT_PREFIX_IS' => 'The convertor was not able to find tables with the specified prefix. Please make sure you have entered the correct details for the board you are converting from. The default table prefix for %1$s is %2$s.', + 'DEV_NO_TEST_FILE' => 'No value has been specified for the test_file variable in the convertor. If you are a user of this convertor, you should not be seeing this error, please report this message to the convertor author. If you are a convertor author, you must specify the name of a file which exists in the source board to allow the path to it to be verified.', + 'DIRECTORIES_AND_FILES' => 'Directory and file setup', + 'DISABLE_KEYS' => 'Disabling keys', + 'DLL_FTP' => 'Remote FTP support [ Installation ]', + 'DLL_GD' => 'GD graphics support [ Visual Confirmation ]', + 'DLL_MBSTRING' => 'Multi-byte character support', + 'DLL_MSSQL' => 'MSSQL Server 2000+', + 'DLL_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC', + 'DLL_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]', + 'DLL_MYSQL' => 'MySQL', + 'DLL_MYSQLI' => 'MySQL with MySQLi Extension', + 'DLL_ORACLE' => 'Oracle', + 'DLL_POSTGRES' => 'PostgreSQL', + 'DLL_SQLITE' => 'SQLite 2', + 'DLL_SQLITE3' => 'SQLite 3', + 'DLL_XML' => 'XML support [ Jabber ]', + 'DLL_ZLIB' => 'zlib compression support [ gz, .tar.gz, .zip ]', + 'DL_CONFIG' => 'Download config', + 'DL_CONFIG_EXPLAIN' => 'You may download the complete config.php to your own PC. You will then need to upload the file manually, replacing any existing config.php in your phpBB 3.1 root directory. Please remember to upload the file in ASCII format (see your FTP application documentation if you are unsure how to achieve this). When you have uploaded the config.php please click “Done†to move to the next stage.', + 'DL_DOWNLOAD' => 'Download', + 'DONE' => 'Done', + + 'ENABLE_KEYS' => 'Re-enabling keys. This can take a while.', + + 'FILES_OPTIONAL' => 'Optional files and directories', + 'FILES_OPTIONAL_EXPLAIN' => 'Optional - These files, directories or permission settings are not required. The installation system will attempt to use various techniques to create them if they do not exist or cannot be written to. However, the presence of these will speed installation.', + 'FILES_REQUIRED' => 'Files and Directories', + 'FILES_REQUIRED_EXPLAIN' => 'Required - In order to function correctly phpBB needs to be able to access or write to certain files or directories. If you see “Not Found†you need to create the relevant file or directory. If you see “Unwritable†you need to change the permissions on the file or directory to allow phpBB to write to it.', + 'FILLING_TABLE' => 'Filling table %s', + 'FILLING_TABLES' => 'Filling tables', + + 'FINAL_STEP' => 'Process final step', + 'FORUM_ADDRESS' => 'Board address', + 'FORUM_ADDRESS_EXPLAIN' => 'This is the URL of your former board, for example http://www.example.com/phpBB2/. If an address is entered here and not left empty every instance of this address will be replaced by your new board address within messages, private messages and signatures.', + 'FORUM_PATH' => 'Board path', + 'FORUM_PATH_EXPLAIN' => 'This is the relative path on disk to your former board from the root of this phpBB3 installation.', + 'FOUND' => 'Found', + 'FTP_CONFIG' => 'Transfer config by FTP', + 'FTP_CONFIG_EXPLAIN' => 'phpBB has detected the presence of the FTP module on this server. You may attempt to install your config.php via this if you wish. You will need to supply the information listed below. Remember your username and password are those to your server! (ask your hosting provider for details if you are unsure what these are).', + 'FTP_PATH' => 'FTP path', + 'FTP_PATH_EXPLAIN' => 'This is the path from your root directory to that of phpBB, e.g. htdocs/phpBB3/.', + 'FTP_UPLOAD' => 'Upload', + + 'GPL' => 'General Public License', + + 'INITIAL_CONFIG' => 'Basic configuration', + 'INITIAL_CONFIG_EXPLAIN' => 'Now that install has determined your server can run phpBB you need to supply some specific information. If you do not know how to connect to your database please contact your hosting provider (in the first instance) or use the phpBB support forums. When entering data please ensure you check it thoroughly before continuing.', + 'INSTALL_CONGRATS' => 'Congratulations!', + 'INSTALL_CONGRATS_EXPLAIN' => ' + You have successfully installed phpBB %1$s. Please proceed by choosing one of the following options:

            +

            Convert an existing board to phpBB3

            +

            The phpBB Unified Convertor Framework supports the conversion of phpBB 2.0.x and other board systems to phpBB3. If you have an existing board that you wish to convert, please proceed to the convertor.

            +

            Go live with your phpBB3!

            +

            Clicking the button below will take you to a form for submitting statistical data to phpBB in your Administration Control Panel (ACP). We would appreciate it if you could help us by sending that information. Afterwards you should take some time to examine the options available to you. Remember that help is available online via the Documentation, README and the Support Forums.

            Please delete, move or rename the install directory before using your board. While this directory exists, only the Administration Control Panel (ACP) will be accessible.', + 'INSTALL_INTRO' => 'Welcome to Installation', + + 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.

            In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:

            • The Database Type - the database you will be using.
            • @@ -79,134 +219,367 @@ $lang = array_merge($lang, array(

            Only those databases supported on your server will be displayed.', -)); - -// Requirements translation -$lang = array_merge($lang, array( - // Filesystem requirements - 'FILE_NOT_EXISTS' => 'File not exists', - 'FILE_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s file need to exist.', - 'FILE_NOT_WRITABLE' => 'File not writable', - 'FILE_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s file need to be writable.', - - 'DIRECTORY_NOT_EXISTS' => 'Directory not exists', - 'DIRECTORY_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s directory need to exist.', - 'DIRECTORY_NOT_WRITABLE' => 'Directory not writable', - 'DIRECTORY_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s directory need to be writable.', - - // Server requirements - 'PHP_VERSION_REQD' => 'PHP version', - 'PHP_VERSION_REQD_EXPLAIN' => 'phpBB requires PHP version 5.3.9 or higher.', - 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP getimagesize() function is required', - 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the getimagesize function needs to be available.', - 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support', - 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.', - 'PHP_JSON_SUPPORT' => 'PHP JSON support', - 'PHP_JSON_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the PHP JSON extension needs to be available.', - 'PHP_SUPPORTED_DB' => 'Supported databases', - 'PHP_SUPPORTED_DB_EXPLAIN' => 'You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.', - - 'RETEST_REQUIREMENTS' => 'Retest requirements', - - 'STAGE_REQUIREMENTS' => 'Check requirements' -)); - -// General error messages -$lang = array_merge($lang, array( + 'INSTALL_INTRO_NEXT' => 'To commence the installation, please press the button below.', + 'INSTALL_LOGIN' => 'Login', + 'INSTALL_NEXT' => 'Next stage', + 'INSTALL_NEXT_FAIL' => 'Some tests failed and you should correct these problems before proceeding to the next stage. Failure to do so may result in an incomplete installation.', + 'INSTALL_NEXT_PASS' => 'All the basic tests have been passed and you may proceed to the next stage of installation. If you have changed any permissions, modules, etc. and wish to re-test you can do so if you wish.', + 'INSTALL_PANEL' => 'Installation Panel', + 'INSTALL_SEND_CONFIG' => 'Unfortunately phpBB could not write the configuration information directly to your config.php. This may be because the file does not exist or is not writable. A number of options will be listed below enabling you to complete installation of config.php.', + 'INSTALL_START' => 'Start install', + 'INSTALL_TEST' => 'Test again', + 'INST_ERR' => 'Installation error', + 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.', + 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.', + 'INST_ERR_DB_INVALID_PREFIX'=> 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.', + 'INST_ERR_DB_NO_ERROR' => 'No error message given.', + 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension†option you have selected. Please try the “MySQL†option instead.', + 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.', + 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.', + 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the NLS_CHARACTERSET parameter to UTF8. Either upgrade your installation to 9.2+ or change the parameter.', + 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in UNICODE or UTF8 encoding. Try installing with a database in UNICODE or UTF8 encoding.', + 'INST_ERR_DB_NO_NAME' => 'No database name specified.', + 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.', + 'INST_ERR_EMAIL_MISMATCH' => 'The emails you entered did not match.', + 'INST_ERR_FATAL' => 'Fatal installation error', + 'INST_ERR_FATAL_DB' => 'A fatal and unrecoverable database error has occurred. This may be because the specified user does not have appropriate permissions to CREATE TABLES or INSERT data, etc. Further information may be given below. Please contact your hosting provider in the first instance or the support forums of phpBB for further assistance.', + 'INST_ERR_FTP_PATH' => 'Could not change to the given directory, please check the path.', + 'INST_ERR_FTP_LOGIN' => 'Could not login to FTP server, check your username and password.', 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.', - 'PHPBB_ALREADY_INSTALLED' => 'phpBB is already installed.' -)); - -// Data obtaining translations -$lang = array_merge($lang, array( - 'STAGE_OBTAIN_DATA' => 'Set installation data', - - // - // Admin data - // - 'STAGE_ADMINISTRATOR' => 'Administrator details', - - // Form labels - 'ADMIN_CONFIG' => 'Administrator configuration', - 'ADMIN_PASSWORD' => 'Administrator password', - 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password', - 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.', - 'ADMIN_USERNAME' => 'Administrator username', - 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.', - - // Errors - 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.', + 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.', 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.', 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.', 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.', - 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.', - 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.', + 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.', + 'INST_ERR_PREFIX_INVALID' => 'The table prefix you have specified is invalid for your database. Please try another, removing characters such as the hyphen.', + 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.', + 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.', + 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.', + 'INVALID_PRIMARY_KEY' => 'Invalid primary key : %s', - // - // Board data - // - // Form labels - 'BOARD_CONFIG' => 'Bulletin board configuration', - 'DEFAULT_LANGUAGE' => 'Default language', - 'BOARD_NAME' => 'Title of the board', - 'BOARD_DESCRIPTION' => 'Short description of the board', + 'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.', - // - // Database data - // - 'STAGE_DATABASE' => 'Database settings', + // mbstring + 'MBSTRING_CHECK' => 'mbstring extension check', + 'MBSTRING_CHECK_EXPLAIN' => 'Required - mbstring is a PHP extension that provides multibyte string functions. Certain features of mbstring are not compatible with phpBB and must be disabled.', + 'MBSTRING_FUNC_OVERLOAD' => 'Function overloading', + 'MBSTRING_FUNC_OVERLOAD_EXPLAIN' => 'mbstring.func_overload must be set to either 0 or 4.', + 'MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding', + 'MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => 'mbstring.encoding_translation must be set to 0.', + 'MBSTRING_HTTP_INPUT' => 'HTTP input character conversion', + 'MBSTRING_HTTP_INPUT_EXPLAIN' => 'mbstring.http_input must be set to pass.', + 'MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion', + 'MBSTRING_HTTP_OUTPUT_EXPLAIN' => 'mbstring.http_output must be set to pass.', - // Form labels - 'DB_CONFIG' => 'Database configuration', - 'DBMS' => 'Database type', - 'DB_HOST' => 'Database server hostname or DSN', - 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.', - 'DB_PORT' => 'Database server port', - 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.', - 'DB_PASSWORD' => 'Database password', - 'DB_NAME' => 'Database name', - 'DB_USERNAME' => 'Database username', - 'TABLE_PREFIX' => 'Prefix for tables in database', - 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.', + 'MAKE_FOLDER_WRITABLE' => 'Please make sure that this folder exists and is writable by the webserver then try again:
            »%s.', + 'MAKE_FOLDERS_WRITABLE' => 'Please make sure that these folders exist and are writable by the webserver then try again:
            »%s.', - // Database options - 'DB_OPTION_MSSQL' => 'MSSQL Server 2000+', - 'DB_OPTION_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC', - 'DB_OPTION_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]', - 'DB_OPTION_MYSQL' => 'MySQL', - 'DB_OPTION_MYSQLI' => 'MySQL with MySQLi Extension', - 'DB_OPTION_ORACLE' => 'Oracle', - 'DB_OPTION_POSTGRES' => 'PostgreSQL', - 'DB_OPTION_SQLITE' => 'SQLite 2', - 'DB_OPTION_SQLITE3' => 'SQLite 3', + 'MYSQL_SCHEMA_UPDATE_REQUIRED' => 'Your MySQL database schema for phpBB is outdated. phpBB detected a schema for MySQL 3.x/4.x, but the server runs on MySQL %2$s.
            Before you proceed the update, you need to upgrade the schema.

            Please refer to the Knowledge Base article about upgrading the MySQL schema. If you encounter problems, please use our support forums.', - // Errors - 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.', - 'INST_ERR_DB_INVALID_PREFIX' => 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.', - 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.', - 'INST_ERR_DB_NO_NAME' => 'No database name specified.', - 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.', - 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.', - 'INST_ERR_DB_NO_ERROR' => 'No error message given.', - 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.', - 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension†option you have selected. Please try the “MySQL†option instead.', - 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.', - 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.', - 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the NLS_CHARACTERSET parameter to UTF8. Either upgrade your installation to 9.2+ or change the parameter.', - 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in UNICODE or UTF8 encoding. Try installing with a database in UNICODE or UTF8 encoding.', + 'NAMING_CONFLICT' => 'Naming conflict: %s and %s are both aliases

            %s', + 'NEXT_STEP' => 'Proceed to next step', + 'NOT_FOUND' => 'Cannot find', + 'NOT_UNDERSTAND' => 'Could not understand %s #%d, table %s (“%sâ€)', + 'NO_CONVERTORS' => 'No convertors are available for use.', + 'NO_CONVERT_SPECIFIED' => 'No convertor specified.', + 'NO_LOCATION' => 'Cannot determine location. If you know Imagemagick is installed, you may specify the location later within your administration control panel', + 'NO_TABLES_FOUND' => 'No tables found.', - // - // Email data - // - 'EMAIL_CONFIG' => 'E-mail configuration', + 'OVERVIEW_BODY' => 'Welcome to phpBB3!

            phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.

            This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read the installation guide.

            To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.', - // - // Server data - // - // Form labels - 'SERVER_CONFIG' => 'Server configuration', - 'SCRIPT_PATH' => 'Script path', - 'SCRIPT_PATH_EXPLAIN' => 'The path where phpBB is located relative to the domain name, e.g. /phpBB3.', + 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support', + 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.', + 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP function getimagesize() is available', + 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'Required - In order for phpBB to function correctly, the getimagesize function needs to be available.', + 'PHP_JSON_SUPPORT' => 'PHP JSON support', + 'PHP_JSON_SUPPORT_EXPLAIN' => 'Required - In order for phpBB to function correctly, the PHP JSON extension needs to be available.', + 'PHP_OPTIONAL_MODULE' => 'Optional modules', + 'PHP_OPTIONAL_MODULE_EXPLAIN' => 'Optional - These modules or applications are optional. However, if they are available they will enable extra features.', + 'PHP_SUPPORTED_DB' => 'Supported databases', + 'PHP_SUPPORTED_DB_EXPLAIN' => 'Required - You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.', + 'PHP_REGISTER_GLOBALS' => 'PHP setting register_globals is disabled', + 'PHP_REGISTER_GLOBALS_EXPLAIN' => 'phpBB will still run if this setting is enabled, but if possible, it is recommended that register_globals is disabled on your PHP install for security reasons.', + 'PHP_SAFE_MODE' => 'Safe mode', + 'PHP_SETTINGS' => 'PHP version and settings', + 'PHP_SETTINGS_EXPLAIN' => 'Required - You must be running at least version 5.3.9 of PHP in order to install phpBB. If safe mode is displayed below your PHP installation is running in that mode. This will impose limitations on remote administration and similar features.', + 'PHP_URL_FOPEN_SUPPORT' => 'PHP setting allow_url_fopen is enabled', + 'PHP_URL_FOPEN_SUPPORT_EXPLAIN' => 'Optional - This setting is optional, however certain phpBB functions like off-site avatars will not work properly without it.', + 'PHP_VERSION_REQD' => 'PHP version >= 5.3.9', + 'POST_ID' => 'Post ID', + 'PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using %s as table prefix.', + 'PREPROCESS_STEP' => 'Executing pre-processing functions/queries', + 'PRE_CONVERT_COMPLETE' => 'All pre-conversion steps have successfully been completed. You may now begin the actual conversion process. Please note that you may have to manually do and adjust several things. After conversion, especially check the permissions assigned, rebuild your search index which is not converted and also make sure files got copied correctly, for example avatars and smilies.', + 'PROCESS_LAST' => 'Processing last statements', + + 'REFRESH_PAGE' => 'Refresh page to continue conversion', + 'REFRESH_PAGE_EXPLAIN' => 'If set to yes, the convertor will refresh the page to continue the conversion after having finished a step. If this is your first conversion for testing purposes and to determine any errors in advance, we suggest to set this to No.', + 'REQUIREMENTS_TITLE' => 'Installation compatibility', + 'REQUIREMENTS_EXPLAIN' => 'Before proceeding with the full installation phpBB will carry out some tests on your server configuration and files to ensure that you are able to install and run phpBB. Please ensure you read through the results thoroughly and do not proceed until all the required tests are passed. If you wish to use any of the features depending on the optional tests, you should ensure that these tests are passed also.', + 'RETRY_WRITE' => 'Retry writing config', + 'RETRY_WRITE_EXPLAIN' => 'If you wish you can change the permissions on config.php to allow phpBB to write to it. Should you wish to do that you can click Retry below to try again. Remember to return the permissions on config.php after phpBB has finished installation.', + + 'SELECT_LANG' => 'Select language', + 'SEARCH_INDEX_UNCONVERTED' => 'Search index was not converted', + 'SEARCH_INDEX_UNCONVERTED_EXPLAIN' => 'Your old search index was not converted. Searching will always yield an empty result. To create a new search index go to the Administration Control Panel, select Maintenance and then choose Search index from the submenu.', + 'SELECT_FORUM_GA' => 'In phpBB 3.1 the global announcements are linked to forums. Select a forum for your current global announcements (can be moved later):', + 'SOFTWARE' => 'Board software', + 'SPECIFY_OPTIONS' => 'Specify conversion options', + 'STAGE_ADMINISTRATOR' => 'Administrator details', + 'STAGE_ADVANCED' => 'Advanced settings', + 'STAGE_ADVANCED_EXPLAIN' => 'The settings on this page are only necessary to set if you know that you require something different from the default. If you are unsure, just proceed to the next page, as these settings can be altered from the Administration Control Panel later.', + 'STAGE_CONFIG_FILE' => 'Configuration file', + 'STAGE_CREATE_TABLE' => 'Create database tables', + 'STAGE_CREATE_TABLE_EXPLAIN' => 'The database tables used by phpBB 3.1 have been created and populated with some initial data. Proceed to the next screen to finish installing phpBB.', + 'STAGE_DATABASE' => 'Database settings', + 'STAGE_FINAL' => 'Final stage', + 'STAGE_INTRO' => 'Introduction', + 'STAGE_IN_PROGRESS' => 'Conversion in progress', + 'STAGE_REQUIREMENTS' => 'Requirements', + 'STAGE_SETTINGS' => 'Settings', + 'STARTING_CONVERT' => 'Starting conversion process', + 'STEP_PERCENT_COMPLETED' => 'Step %d of %d', + 'SUB_INTRO' => 'Introduction', + 'SUB_LICENSE' => 'License', + 'SUB_SUPPORT' => 'Support', + 'SUCCESSFUL_CONNECT' => 'Successful connection', + 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:

            • installation
            • configuration
            • technical questions
            • problems relating to potential bugs in the software
            • updating from Release Candidate (RC) versions to the latest stable version
            • converting from phpBB 2.0.x to phpBB3
            • converting from other discussion board software to phpBB3 (please see the Convertors Forum)

            We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.

            Extensions / Styles

            For issues relating to Extensions, please post in the appropriate Extensions Forum.
            For issues relating to styles, templates and themes, please post in the appropriate Styles Forum.

            If your question relates to a specific package, please post directly in the topic dedicated to the package.

            Obtaining Support

            The phpBB Welcome Package
            Support Section
            Quick Start Guide

            To ensure you stay up to date with the latest news and releases, why not subscribe to our mailing list?

            ', + 'SYNC_FORUMS' => 'Starting to synchronise forums', + 'SYNC_POST_COUNT' => 'Synchronising post_counts', + 'SYNC_POST_COUNT_ID' => 'Synchronising post_counts from entry %1$s to %2$s.', + 'SYNC_TOPICS' => 'Starting to synchronise topics', + 'SYNC_TOPIC_ID' => 'Synchronising topics from topic_id %1$s to %2$s.', + + 'TABLES_MISSING' => 'Could not find these tables
            » %s.', + 'TABLE_PREFIX' => 'Prefix for tables in database', + 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.', + 'TABLE_PREFIX_SAME' => 'The table prefix needs to be the one used by the software you are converting from.
            » Specified table prefix was %s.', + 'TESTS_PASSED' => 'Tests passed', + 'TESTS_FAILED' => 'Tests failed', + + 'UNABLE_WRITE_LOCK' => 'Unable to write lock file.', + 'UNAVAILABLE' => 'Unavailable', + 'UNWRITABLE' => 'Unwritable', + 'UPDATE_TOPICS_POSTED' => 'Generating topics posted information', + 'UPDATE_TOPICS_POSTED_ERR' => 'An error occurred while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.', + 'VERIFY_OPTIONS' => 'Verifying conversion options', + 'VERSION' => 'Version', + + 'WELCOME_INSTALL' => 'Welcome to phpBB3 Installation', + 'WRITABLE' => 'Writable', +)); + +// Updater +$lang = array_merge($lang, array( + 'ALL_FILES_UP_TO_DATE' => 'All files are up to date with the latest phpBB version.', + 'ARCHIVE_FILE' => 'Source file within archive', + + 'BACK' => 'Back', + 'BINARY_FILE' => 'Binary file', + 'BOT' => 'Spider/Robot', + + 'CHANGE_CLEAN_NAMES' => 'The method used to make sure a username is not used by multiple users has been changed. There are some users which have the same name when compared with the new method. You have to delete or rename these users to make sure that each name is only used by one user before you can proceed.', + 'CHECK_FILES' => 'Check files', + 'CHECK_FILES_AGAIN' => 'Check files again', + 'CHECK_FILES_EXPLAIN' => 'Within the next step all files will be checked against the update files - this can take a while if this is the first file check.', + 'CHECK_FILES_UP_TO_DATE' => 'According to your database your version is up to date. You may want to proceed with the file check to make sure all files are really up to date with the latest phpBB version.', + 'CHECK_UPDATE_DATABASE' => 'Continue update process', + 'COLLECTED_INFORMATION' => 'File information', + 'COLLECTED_INFORMATION_EXPLAIN' => 'The list below shows information about the files needing an update. Please read the information in front of every status block to see what they mean and what you may need to do to perform a successful update.', + 'COLLECTING_FILE_DIFFS' => 'Collecting file differences', + 'COMPLETE_LOGIN_TO_BOARD' => 'You should now login to your board and check if everything is working fine. Do not forget to delete, rename or move your install directory!', + 'CONTINUE_UPDATE_NOW' => 'Continue the update process now', // Shown within the database update script at the end if called from the updater + 'CONTINUE_UPDATE' => 'Continue update now', // Shown after file upload to indicate the update process is not yet finished + 'CURRENT_FILE' => 'Begin of Conflict - Original File code before update', + 'CURRENT_VERSION' => 'Current version', + + 'DATABASE_TYPE' => 'Database type', + 'DATABASE_UPDATE_COMPLETE' => 'Database updater has completed!', + 'DATABASE_UPDATE_CONTINUE' => 'Continue database update', + 'DATABASE_UPDATE_INFO_OLD' => 'The database update file within the install directory is outdated. Please make sure you uploaded the correct version of the file.', + 'DATABASE_UPDATE_NOT_COMPLETED' => 'The database update has not yet completed.', + 'DELETE_USER_REMOVE' => 'Delete user and remove posts', + 'DELETE_USER_RETAIN' => 'Delete user but keep posts', + 'DESTINATION' => 'Destination file', + 'DIFF_INLINE' => 'Inline', + 'DIFF_RAW' => 'Raw unified diff', + 'DIFF_SEP_EXPLAIN' => 'Code block used within the updated/new file', + 'DIFF_SIDE_BY_SIDE' => 'Side by Side', + 'DIFF_UNIFIED' => 'Unified diff', + 'DO_NOT_UPDATE' => 'Do not update this file', + 'DONE' => 'Done', + 'DOWNLOAD' => 'Download', + 'DOWNLOAD_AS' => 'Download as', + 'DOWNLOAD_UPDATE_METHOD_BUTTON' => 'Download modified files archive (recommended)', + 'DOWNLOAD_CONFLICTS' => 'Download conflicts for this file', + 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for <<< to spot conflicts', + 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive', + 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, please check the files again with the other button below.', + + 'EDIT_USERNAME' => 'Edit username', + 'ERROR' => 'Error', + 'EVERYTHING_UP_TO_DATE' => 'Everything is up to date with the latest phpBB version. You should now login to your board and check if everything is working fine. Do not forget to delete, rename or move your install directory! Please send us updated information about your server and board configurations from the Send statistics module in your ACP.', + + 'FILE_ALREADY_UP_TO_DATE' => 'File is already up to date.', + 'FILE_DIFF_NOT_ALLOWED' => 'File not allowed to be diffed.', + 'FILE_USED' => 'Information used from', // Single file + 'FILES_CONFLICT' => 'Conflict files', + 'FILES_CONFLICT_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. phpBB determined that these files create conflicts if they are tried to be merged. Please investigate the conflicts and try to manually resolve them or continue the update choosing the preferred merging method. If you resolve the conflicts manually check the files again after you modified them. You are also able to choose between the preferred merge method for every file. The first one will result in a file where the conflicting lines from your old file will be lost, the other one will result in losing the changes from the newer file.', + 'FILES_DELETED' => 'Deleted files', + 'FILES_DELETED_EXPLAIN' => 'The following files do not exist in the new version. These files have to be deleted from your installation.', + 'FILES_MODIFIED' => 'Modified files', + 'FILES_MODIFIED_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. The updated file will be a merge between your modifications and the new file.', + 'FILES_NEW' => 'New files', + 'FILES_NEW_EXPLAIN' => 'The following files currently do not exist within your installation. These files will be added to your installation.', + 'FILES_NEW_CONFLICT' => 'New conflicting files', + 'FILES_NEW_CONFLICT_EXPLAIN' => 'The following files are new within the latest version but it has been determined that there is already a file with the same name within the same position. This file will be overwritten by the new file.', + 'FILES_NOT_MODIFIED' => 'Not modified files', + 'FILES_NOT_MODIFIED_EXPLAIN' => 'The following files are not modified and represent the original phpBB files from the version you want to update from.', + 'FILES_UP_TO_DATE' => 'Already updated files', + 'FILES_UP_TO_DATE_EXPLAIN' => 'The following files are already up to date and do not need to be updated.', + 'FTP_SETTINGS' => 'FTP settings', + 'FTP_UPDATE_METHOD' => 'FTP upload', + + 'INCOMPATIBLE_UPDATE_FILES' => 'The update files found are incompatible with your installed version. Your installed version is %1$s and the update file is for updating phpBB %2$s to %3$s.', + 'INCOMPLETE_UPDATE_FILES' => 'The update files are incomplete.', + 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful. Now you need to continue the update process.', + + 'KEEP_OLD_NAME' => 'Keep username', + + 'LATEST_VERSION' => 'Latest version', + 'LINE' => 'Line', + 'LINE_ADDED' => 'Added', + 'LINE_MODIFIED' => 'Modified', + 'LINE_REMOVED' => 'Removed', + 'LINE_UNMODIFIED' => 'Unmodified', + 'LOGIN_UPDATE_EXPLAIN' => 'In order to update your installation you need to login first.', + + 'MAPPING_FILE_STRUCTURE' => 'To ease the upload here are the file locations which map your phpBB installation.', + + 'MERGE_MODIFICATIONS_OPTION' => 'Merge modifications', + + 'MERGE_NO_MERGE_NEW_OPTION' => 'Do not merge - use new file', + 'MERGE_NO_MERGE_MOD_OPTION' => 'Do not merge - use currently installed file', + 'MERGE_MOD_FILE_OPTION' => 'Merge modifications (removes new phpBB code within conflicting block)', + 'MERGE_NEW_FILE_OPTION' => 'Merge modifications (removes modified code within conflicting block)', + 'MERGE_SELECT_ERROR' => 'Conflicting file merge modes are not correctly selected.', + 'MERGING_FILES' => 'Merging differences', + 'MERGING_FILES_EXPLAIN' => 'Currently collecting final file changes.

            Please wait until phpBB has completed all operations on changed files.', + + 'NEW_FILE' => 'End of Conflict', + 'NEW_USERNAME' => 'New username', + 'NO_AUTH_UPDATE' => 'Not authorised to update', + 'NO_ERRORS' => 'No errors', + 'NO_UPDATE_FILES' => 'Not updating the following files', + 'NO_UPDATE_FILES_EXPLAIN' => 'The following files are new or modified but the directory they normally reside in could not be found on your installation. If this list contains files to other directories than language/ or styles/ than you may have modified your directory structure and the update may be incomplete.', + 'NO_UPDATE_FILES_OUTDATED' => 'No valid update directory was found, please make sure you uploaded the relevant files.

            Your installation does not seem to be up to date. Updates are available for your version of phpBB %1$s, please visit https://www.phpbb.com/downloads/ to obtain the correct package to update from Version %2$s to Version %3$s.', + 'NO_UPDATE_FILES_UP_TO_DATE' => 'Your version is up to date. There is no need to run the update tool. If you want to make an integrity check on your files make sure you uploaded the correct update files.', + 'NO_UPDATE_INFO' => 'Update file information could not be found.', + 'NO_UPDATES_REQUIRED' => 'No updates required', + 'NO_VISIBLE_CHANGES' => 'No visible changes', + 'NOTICE' => 'Notice', + 'NUM_CONFLICTS' => 'Number of conflicts', + 'NUMBER_OF_FILES_COLLECTED' => 'Currently differences from %1$d of %2$d files have been checked.
            Please wait until all files are checked.', + + 'OLD_UPDATE_FILES' => 'Update files are out of date. The update files found are for updating from phpBB %1$s to phpBB %2$s but the latest version of phpBB is %3$s.', + + 'PACKAGE_UPDATES_TO' => 'Current package updates to version', + 'PERFORM_DATABASE_UPDATE' => 'Perform database update', + 'PERFORM_DATABASE_UPDATE_EXPLAIN' => 'Below you will find a button to the database update script. The database update can take a while, so please do not stop the execution if it seems to hang. After the database update has been performed just follow the instructions to continue the update process.', + 'PREVIOUS_VERSION' => 'Previous version', + 'PROGRESS' => 'Progress', + + 'RELEASE_ANNOUNCEMENT' => 'Announcement', + 'RESULT' => 'Result', + 'RUN_DATABASE_SCRIPT' => 'Update my database now', + + 'SELECT_DIFF_MODE' => 'Select diff mode', + 'SELECT_DOWNLOAD_FORMAT' => 'Select download archive format', + 'SELECT_FTP_SETTINGS' => 'Select FTP settings', + 'SHOW_DIFF_CONFLICT' => 'Show differences/conflicts', + 'SHOW_DIFF_DELETED' => 'Show file contents', + 'SHOW_DIFF_FINAL' => 'Show resulting file', + 'SHOW_DIFF_MODIFIED' => 'Show merged differences', + 'SHOW_DIFF_NEW' => 'Show file contents', + 'SHOW_DIFF_NEW_CONFLICT' => 'Show differences', + 'SHOW_DIFF_NOT_MODIFIED' => 'Show differences', + 'SOME_QUERIES_FAILED' => 'Some queries failed, the statements and errors are listed below.', + 'SQL' => 'SQL', + 'SQL_FAILURE_EXPLAIN' => 'This is probably nothing to worry about, update will continue. Should this fail to complete you may need to seek help at our support forums. See README for details on how to obtain advice.', + 'STAGE_FILE_CHECK' => 'Check files', + 'STAGE_UPDATE_DB' => 'Update database', + 'STAGE_UPDATE_FILES' => 'Update files', + 'STAGE_VERSION_CHECK' => 'Version check', + 'STATUS_CONFLICT' => 'Modified file producing conflicts', + 'STATUS_DELETED' => 'Deleted file', + 'STATUS_MODIFIED' => 'Modified file', + 'STATUS_NEW' => 'New file', + 'STATUS_NEW_CONFLICT' => 'Conflicting new file', + 'STATUS_NOT_MODIFIED' => 'Not modified file', + 'STATUS_UP_TO_DATE' => 'Already updated file', + + 'TOGGLE_DISPLAY' => 'View/Hide file list', + 'TRY_DOWNLOAD_METHOD' => 'You may want to try the download modified files method.
            This method always works and is also the recommended update path.', + 'TRY_DOWNLOAD_METHOD_BUTTON'=> 'Try this method now', + + 'UPDATE_COMPLETED' => 'Update completed', + 'UPDATE_DATABASE' => 'Update database', + 'UPDATE_DATABASE_EXPLAIN' => 'Within the next step the database will be updated.', + 'UPDATE_DATABASE_SCHEMA' => 'Updating database schema', + 'UPDATE_FILES' => 'Update files', + 'UPDATE_FILES_NOTICE' => 'Please make sure you have updated your board files too, this file is only updating your database.', + 'UPDATE_INSTALLATION' => 'Update phpBB installation', + 'UPDATE_INSTALLATION_EXPLAIN' => 'With this option, it is possible to update your phpBB installation to the latest version.
            During the process all of your files will be checked for their integrity. You are able to review all differences and files before the update.

            The file update itself can be done in two different ways.

            Manual Update

            With this update you only download your personal set of changed files to make sure you do not lose your file modifications you may have done. After you downloaded this package you need to manually upload the files to their correct position under your phpBB root directory. Once done, you are able to do the file check stage again to see if you moved the files to their correct location.

            Automatic Update with FTP

            This method is similar to the first one but without the need to download the changed files and uploading them on your own. This will be done for you. In order to use this method you need to know your FTP login details since you will be asked for them. Once finished you will be redirected to the file check again to make sure everything got updated correctly.

            ', + 'UPDATE_INSTRUCTIONS' => ' + +

            Release announcement

            + +

            Please read the release announcement for the latest version before you continue your update process, it may contain useful information. It also contains full download links as well as the change log.

            + +
            + +

            How to update your installation with the Automatic Update Package

            + +

            The recommended way of updating your installation listed here is only valid for the automatic update package. You are also able to update your installation using the methods listed within the INSTALL.html document. The steps for updating phpBB3 automatically are:

            + +
              +
            • Go to the phpBB.com downloads page and download the "Automatic Update Package" archive.

            • +
            • Unpack the archive.

            • +
            • Upload the complete uncompressed "install" and "vendor" folders to your phpBB root directory (where your config.php file is).

            • +
            + +

            Once uploaded your board will be offline for normal users due to the install directory you uploaded now present.

            + Now start the update process by pointing your browser to the install folder.
            +
            + You will then be guided through the update process. You will be notified once the update is complete. +

            + ', + 'UPDATE_METHOD' => 'Update method', + 'UPDATE_METHOD_EXPLAIN' => 'You are now able to choose your preferred update method. Using the FTP upload will present you with a form you need to enter your FTP account details into. With this method the files will be automatically moved to the new location and backups of the old files being created by appending .bak to the filename. If you choose to download the modified files you are able to unpack and upload them to their correct location manually later.', + 'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s', + 'UPDATE_SUCCESS' => 'Update was successful', + 'UPDATE_SUCCESS_EXPLAIN' => 'Successfully updated all files. The next step involves checking all files again to make sure the files got updated correctly.', + 'UPDATE_VERSION_OPTIMIZE' => 'Updating version and optimising tables', + 'UPDATING_DATA' => 'Updating data', + 'UPDATING_TO_LATEST_STABLE' => 'Updating database to latest stable release', + 'UPDATED_VERSION' => 'Updated version', + 'UPLOAD_METHOD' => 'Upload method', + + 'UPDATE_DB_SUCCESS' => 'Database update was successful.', + 'UPDATE_FILE_SUCCESS' => 'File update was successful.', + 'USER_ACTIVE' => 'Active user', + 'USER_INACTIVE' => 'Inactive user', + + 'VERSION_CHECK' => 'Version check', + 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.', + 'VERSION_NOT_UP_TO_DATE' => 'Your phpBB installation is not up to date. Please continue the update process.', + 'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.
            Below is a link to the release announcement, which contains more information as well as instructions on updating.', + 'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.', + 'VERSION_UP_TO_DATE' => 'Your phpBB installation is up to date. Although there are no updates available at this time, you may continue in order to perform a file validity check.', + 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.', + 'VIEWING_FILE_CONTENTS' => 'Viewing file contents', + 'VIEWING_FILE_DIFF' => 'Viewing file differences', + + 'WRONG_INFO_FILE_FORMAT' => 'Wrong info file format', )); // Default database schema entries... @@ -254,51 +627,3 @@ $lang = array_merge($lang, array( 'TOPICS_TOPIC_TITLE' => 'Welcome to phpBB3', )); - -// Common navigation items' translation -$lang = array_merge($lang, array( - 'MENU_OVERVIEW' => 'Overview', - 'MENU_INTRO' => 'Introduction', - 'MENU_LICENSE' => 'License', - 'MENU_SUPPORT' => 'Support', -)); - -// Task names -$lang = array_merge($lang, array( - // Install filesystem - 'TASK_CREATE_CONFIG_FILE' => 'Creating configuration file', - - // Install database - 'TASK_ADD_CONFIG_SETTINGS' => 'Adding configuration settings', - 'TASK_ADD_DEFAULT_DATA' => 'Adding default settings to the database', - 'TASK_CREATE_DATABASE_SCHEMA' => 'Creating database schema', - - // Install data - 'TASK_ADD_BOTS' => 'Registering bots', - 'TASK_ADD_LANGUAGES' => 'Installing available languages', - 'TASK_ADD_MODULES' => 'Installing modules', - - // Install finish tasks - 'TASK_NOTIFY_USER' => 'Sending notification e-mail', - 'TASK_POPULATE_MIGRATIONS' => 'Populating migrations', - - // Installer general progress messages - 'INSTALLER_FINISHED' => 'The installer has finished successfully', -)); - -// Installer's general messages -$lang = array_merge($lang, array( - 'MODULE_NOT_FOUND' => 'Module not found', - 'MODULE_NOT_FOUND_DESCRIPTION' => 'No module is found under the service definition “%s†is not defined.', - - 'TASK_NOT_FOUND' => 'Task not found', - 'TASK_NOT_FOUND_DESCRIPTION' => 'No task is found under the service definition “%s†is not defined.', - - 'SKIP_MODULE' => 'Skip “%s†module', - 'SKIP_TASK' => 'Skip “%s†task', - - 'TASK_SERVICE_INSTALLER_MISSING' => 'All installer task services should start with “installerâ€', - 'TASK_CLASS_NOT_FOUND' => 'Installer task service definition is invalid. Service name “%1$s†given, the expected class namespace is “%2$s†for that. For more information please see the documentation of task_interface.', - - 'INSTALLER_CONFIG_NOT_WRITABLE' => 'The installer config file is not writable.', -)); diff --git a/phpBB/language/en/install_new.php b/phpBB/language/en/install_new.php new file mode 100644 index 0000000000..607565fcd0 --- /dev/null +++ b/phpBB/language/en/install_new.php @@ -0,0 +1,305 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* DO NOT CHANGE +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +if (empty($lang) || !is_array($lang)) +{ + $lang = array(); +} + +// DEVELOPERS PLEASE NOTE +// +// All language files should use UTF-8 as their encoding and the files must not contain a BOM. +// +// Placeholders can now contain order information, e.g. instead of +// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows +// translators to re-order the output of data while ensuring it remains correct +// +// You do not need this where single placeholders are used, e.g. 'Message %d' is fine +// equally where a string contains only two placeholders which are used to wrap text +// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine + +// Common installer pages +$lang = array_merge($lang, array( + 'INSTALL_PANEL' => 'Installation Panel', + 'SELECT_LANG' => 'Select language', + + 'STAGE_INSTALL' => 'Installing phpBB', + + // Introduction page + 'INTRODUCTION_TITLE' => 'Introduction', + 'INTRODUCTION_BODY' => 'Welcome to phpBB3!

            phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.

            This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read the installation guide.

            To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.', + + // Support page + 'SUPPORT_TITLE' => 'Support', + 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:

            • installation
            • configuration
            • technical questions
            • problems relating to potential bugs in the software
            • updating from Release Candidate (RC) versions to the latest stable version
            • converting from phpBB 2.0.x to phpBB3
            • converting from other discussion board software to phpBB3 (please see the Convertors Forum)

            We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.

            Extensions / Styles

            For issues relating to Extensions, please post in the appropriate Extensions Forum.
            For issues relating to styles, templates and themes, please post in the appropriate Styles Forum.

            If your question relates to a specific package, please post directly in the topic dedicated to the package.

            Obtaining Support

            The phpBB Welcome Package
            Support Section
            Quick Start Guide

            To ensure you stay up to date with the latest news and releases, why not subscribe to our mailing list?

            ', + + // License + 'LICENSE_TITLE' => 'General Public License', + + // Install page + 'INSTALL_INTRO' => 'Welcome to Installation', + 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.

            In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:

            + +
              +
            • The Database Type - the database you will be using.
            • +
            • The Database server hostname or DSN - the address of the database server.
            • +
            • The Database server port - the port of the database server (most of the time this is not needed).
            • +
            • The Database name - the name of the database on the server.
            • +
            • The Database username and Database password - the login data to access the database.
            • +
            + +

            Note: if you are installing using SQLite, you should enter the full path to your database file in the DSN field and leave the username and password fields blank. For security reasons, you should make sure that the database file is not stored in a location accessible from the web.

            + +

            phpBB3 supports the following databases:

            +
              +
            • MySQL 3.23 or above (MySQLi supported)
            • +
            • PostgreSQL 8.3+
            • +
            • SQLite 2.8.2+
            • +
            • SQLite 3.6.15+
            • +
            • MS SQL Server 2000 or above (directly or via ODBC)
            • +
            • MS SQL Server 2005 or above (native)
            • +
            • Oracle
            • +
            + +

            Only those databases supported on your server will be displayed.', +)); + +// Requirements translation +$lang = array_merge($lang, array( + // Filesystem requirements + 'FILE_NOT_EXISTS' => 'File not exists', + 'FILE_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s file need to exist.', + 'FILE_NOT_WRITABLE' => 'File not writable', + 'FILE_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s file need to be writable.', + + 'DIRECTORY_NOT_EXISTS' => 'Directory not exists', + 'DIRECTORY_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s directory need to exist.', + 'DIRECTORY_NOT_WRITABLE' => 'Directory not writable', + 'DIRECTORY_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s directory need to be writable.', + + // Server requirements + 'PHP_VERSION_REQD' => 'PHP version', + 'PHP_VERSION_REQD_EXPLAIN' => 'phpBB requires PHP version 5.3.9 or higher.', + 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP getimagesize() function is required', + 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the getimagesize function needs to be available.', + 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support', + 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.', + 'PHP_JSON_SUPPORT' => 'PHP JSON support', + 'PHP_JSON_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the PHP JSON extension needs to be available.', + 'PHP_SUPPORTED_DB' => 'Supported databases', + 'PHP_SUPPORTED_DB_EXPLAIN' => 'You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.', + + 'RETEST_REQUIREMENTS' => 'Retest requirements', + + 'STAGE_REQUIREMENTS' => 'Check requirements' +)); + +// General error messages +$lang = array_merge($lang, array( + 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.', + 'PHPBB_ALREADY_INSTALLED' => 'phpBB is already installed.' +)); + +// Data obtaining translations +$lang = array_merge($lang, array( + 'STAGE_OBTAIN_DATA' => 'Set installation data', + + // + // Admin data + // + 'STAGE_ADMINISTRATOR' => 'Administrator details', + + // Form labels + 'ADMIN_CONFIG' => 'Administrator configuration', + 'ADMIN_PASSWORD' => 'Administrator password', + 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password', + 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.', + 'ADMIN_USERNAME' => 'Administrator username', + 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.', + + // Errors + 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.', + 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.', + 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.', + 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.', + 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.', + 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.', + + // + // Board data + // + // Form labels + 'BOARD_CONFIG' => 'Bulletin board configuration', + 'DEFAULT_LANGUAGE' => 'Default language', + 'BOARD_NAME' => 'Title of the board', + 'BOARD_DESCRIPTION' => 'Short description of the board', + + // + // Database data + // + 'STAGE_DATABASE' => 'Database settings', + + // Form labels + 'DB_CONFIG' => 'Database configuration', + 'DBMS' => 'Database type', + 'DB_HOST' => 'Database server hostname or DSN', + 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.', + 'DB_PORT' => 'Database server port', + 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.', + 'DB_PASSWORD' => 'Database password', + 'DB_NAME' => 'Database name', + 'DB_USERNAME' => 'Database username', + 'TABLE_PREFIX' => 'Prefix for tables in database', + 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.', + + // Database options + 'DB_OPTION_MSSQL' => 'MSSQL Server 2000+', + 'DB_OPTION_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC', + 'DB_OPTION_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]', + 'DB_OPTION_MYSQL' => 'MySQL', + 'DB_OPTION_MYSQLI' => 'MySQL with MySQLi Extension', + 'DB_OPTION_ORACLE' => 'Oracle', + 'DB_OPTION_POSTGRES' => 'PostgreSQL', + 'DB_OPTION_SQLITE' => 'SQLite 2', + 'DB_OPTION_SQLITE3' => 'SQLite 3', + + // Errors + 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.', + 'INST_ERR_DB_INVALID_PREFIX' => 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.', + 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.', + 'INST_ERR_DB_NO_NAME' => 'No database name specified.', + 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.', + 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.', + 'INST_ERR_DB_NO_ERROR' => 'No error message given.', + 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.', + 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension†option you have selected. Please try the “MySQL†option instead.', + 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.', + 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.', + 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the NLS_CHARACTERSET parameter to UTF8. Either upgrade your installation to 9.2+ or change the parameter.', + 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in UNICODE or UTF8 encoding. Try installing with a database in UNICODE or UTF8 encoding.', + + // + // Email data + // + 'EMAIL_CONFIG' => 'E-mail configuration', + + // + // Server data + // + // Form labels + 'SERVER_CONFIG' => 'Server configuration', + 'SCRIPT_PATH' => 'Script path', + 'SCRIPT_PATH_EXPLAIN' => 'The path where phpBB is located relative to the domain name, e.g. /phpBB3.', +)); + +// Default database schema entries... +$lang = array_merge($lang, array( + 'CONFIG_BOARD_EMAIL_SIG' => 'Thanks, The Management', + 'CONFIG_SITE_DESC' => 'A short text to describe your forum', + 'CONFIG_SITENAME' => 'yourdomain.com', + + 'DEFAULT_INSTALL_POST' => 'This is an example post in your phpBB3 installation. Everything seems to be working. You may delete this post if you like and continue to set up your board. During the installation process your first category and your first forum are assigned an appropriate set of permissions for the predefined usergroups administrators, bots, global moderators, guests, registered users and registered COPPA users. If you also choose to delete your first category and your first forum, do not forget to assign permissions for all these usergroups for all new categories and forums you create. It is recommended to rename your first category and your first forum and copy permissions from these while creating new categories and forums. Have fun!', + + 'FORUMS_FIRST_CATEGORY' => 'Your first category', + 'FORUMS_TEST_FORUM_DESC' => 'Description of your first forum.', + 'FORUMS_TEST_FORUM_TITLE' => 'Your first forum', + + 'RANKS_SITE_ADMIN_TITLE' => 'Site Admin', + 'REPORT_WAREZ' => 'The post contains links to illegal or pirated software.', + 'REPORT_SPAM' => 'The reported post has the only purpose to advertise for a website or another product.', + 'REPORT_OFF_TOPIC' => 'The reported post is off topic.', + 'REPORT_OTHER' => 'The reported post does not fit into any other category, please use the further information field.', + + 'SMILIES_ARROW' => 'Arrow', + 'SMILIES_CONFUSED' => 'Confused', + 'SMILIES_COOL' => 'Cool', + 'SMILIES_CRYING' => 'Crying or Very Sad', + 'SMILIES_EMARRASSED' => 'Embarrassed', + 'SMILIES_EVIL' => 'Evil or Very Mad', + 'SMILIES_EXCLAMATION' => 'Exclamation', + 'SMILIES_GEEK' => 'Geek', + 'SMILIES_IDEA' => 'Idea', + 'SMILIES_LAUGHING' => 'Laughing', + 'SMILIES_MAD' => 'Mad', + 'SMILIES_MR_GREEN' => 'Mr. Green', + 'SMILIES_NEUTRAL' => 'Neutral', + 'SMILIES_QUESTION' => 'Question', + 'SMILIES_RAZZ' => 'Razz', + 'SMILIES_ROLLING_EYES' => 'Rolling Eyes', + 'SMILIES_SAD' => 'Sad', + 'SMILIES_SHOCKED' => 'Shocked', + 'SMILIES_SMILE' => 'Smile', + 'SMILIES_SURPRISED' => 'Surprised', + 'SMILIES_TWISTED_EVIL' => 'Twisted Evil', + 'SMILIES_UBER_GEEK' => 'Uber Geek', + 'SMILIES_VERY_HAPPY' => 'Very Happy', + 'SMILIES_WINK' => 'Wink', + + 'TOPICS_TOPIC_TITLE' => 'Welcome to phpBB3', +)); + +// Common navigation items' translation +$lang = array_merge($lang, array( + 'MENU_OVERVIEW' => 'Overview', + 'MENU_INTRO' => 'Introduction', + 'MENU_LICENSE' => 'License', + 'MENU_SUPPORT' => 'Support', +)); + +// Task names +$lang = array_merge($lang, array( + // Install filesystem + 'TASK_CREATE_CONFIG_FILE' => 'Creating configuration file', + + // Install database + 'TASK_ADD_CONFIG_SETTINGS' => 'Adding configuration settings', + 'TASK_ADD_DEFAULT_DATA' => 'Adding default settings to the database', + 'TASK_CREATE_DATABASE_SCHEMA' => 'Creating database schema', + + // Install data + 'TASK_ADD_BOTS' => 'Registering bots', + 'TASK_ADD_LANGUAGES' => 'Installing available languages', + 'TASK_ADD_MODULES' => 'Installing modules', + + // Install finish tasks + 'TASK_NOTIFY_USER' => 'Sending notification e-mail', + 'TASK_POPULATE_MIGRATIONS' => 'Populating migrations', + + // Installer general progress messages + 'INSTALLER_FINISHED' => 'The installer has finished successfully', +)); + +// Installer's general messages +$lang = array_merge($lang, array( + 'MODULE_NOT_FOUND' => 'Module not found', + 'MODULE_NOT_FOUND_DESCRIPTION' => 'No module is found under the service definition “%s†is not defined.', + + 'TASK_NOT_FOUND' => 'Task not found', + 'TASK_NOT_FOUND_DESCRIPTION' => 'No task is found under the service definition “%s†is not defined.', + + 'SKIP_MODULE' => 'Skip “%s†module', + 'SKIP_TASK' => 'Skip “%s†task', + + 'TASK_SERVICE_INSTALLER_MISSING' => 'All installer task services should start with “installerâ€', + 'TASK_CLASS_NOT_FOUND' => 'Installer task service definition is invalid. Service name “%1$s†given, the expected class namespace is “%2$s†for that. For more information please see the documentation of task_interface.', + + 'INSTALLER_CONFIG_NOT_WRITABLE' => 'The installer config file is not writable.', +)); diff --git a/phpBB/language/en/old_install.php b/phpBB/language/en/old_install.php deleted file mode 100644 index a776a539ed..0000000000 --- a/phpBB/language/en/old_install.php +++ /dev/null @@ -1,629 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -/** -* DO NOT CHANGE -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -if (empty($lang) || !is_array($lang)) -{ - $lang = array(); -} - -// DEVELOPERS PLEASE NOTE -// -// All language files should use UTF-8 as their encoding and the files must not contain a BOM. -// -// Placeholders can now contain order information, e.g. instead of -// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows -// translators to re-order the output of data while ensuring it remains correct -// -// You do not need this where single placeholders are used, e.g. 'Message %d' is fine -// equally where a string contains only two placeholders which are used to wrap text -// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine - -$lang = array_merge($lang, array( - 'ADMIN_CONFIG' => 'Administrator configuration', - 'ADMIN_PASSWORD' => 'Administrator password', - 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password', - 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.', - 'ADMIN_TEST' => 'Check administrator settings', - 'ADMIN_USERNAME' => 'Administrator username', - 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.', - 'APP_MAGICK' => 'Imagemagick support [ Attachments ]', - 'AUTHOR_NOTES' => 'Author notes
            » %s', - 'AVAILABLE' => 'Available', - 'AVAILABLE_CONVERTORS' => 'Available convertors', - - 'BEGIN_CONVERT' => 'Begin conversion', - 'BLANK_PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using no table prefix.', - 'BOARD_NOT_INSTALLED' => 'No installation found', - 'BOARD_NOT_INSTALLED_EXPLAIN' => 'The phpBB Unified Convertor Framework requires a default installation of phpBB3 to function, please proceed by first installing phpBB3.', - 'BACKUP_NOTICE' => 'Please backup your board before updating in case any problems arise during the update process.', - - 'CATEGORY' => 'Category', - 'CACHE_STORE' => 'Cache type', - 'CACHE_STORE_EXPLAIN' => 'The physical location where data is cached, filesystem is preferred.', - 'CAT_CONVERT' => 'Convert', - 'CAT_INSTALL' => 'Install', - 'CAT_OVERVIEW' => 'Overview', - 'CAT_UPDATE' => 'Update', - 'CHANGE' => 'Change', - 'CHECK_TABLE_PREFIX' => 'Please check your table prefix and try again.', - 'CLEAN_VERIFY' => 'Cleaning up and verifying the final structure', - 'CLEANING_USERNAMES' => 'Cleaning usernames', - 'COLLIDING_CLEAN_USERNAME' => '%s is the clean username for:', - 'COLLIDING_USERNAMES_FOUND' => 'Colliding usernames were found on your old board. In order to complete the conversion please delete or rename these users so that there is only one user on your old board for each clean username.', - 'COLLIDING_USER' => '» user id: %d username: %s (%d posts)', - 'CONFIG_CONVERT' => 'Converting the configuration', - 'CONFIG_FILE_UNABLE_WRITE' => 'It was not possible to write the configuration file. Alternative methods for this file to be created are presented below.', - 'CONFIG_FILE_WRITTEN' => 'The configuration file has been written. You may now proceed to the next step of the installation.', - 'CONFIG_PHPBB_EMPTY' => 'The phpBB3 config variable for “%s†is empty.', - 'CONFIG_RETRY' => 'Retry', - 'CONTINUE_CONVERT' => 'Continue conversion', - 'CONTINUE_CONVERT_BODY' => 'A previous conversion attempt has been determined. You are now able to choose between starting a new conversion or continuing the conversion.', - 'CONTINUE_LAST' => 'Continue last statements', - 'CONTINUE_OLD_CONVERSION' => 'Continue previously started conversion', - 'CONVERT' => 'Convert', - 'CONVERT_COMPLETE' => 'Conversion completed', - 'CONVERT_COMPLETE_EXPLAIN' => 'You have now successfully converted your board to phpBB 3.1. You can now login and access your board. Please ensure that the settings were transferred correctly before enabling your board by deleting the install directory. Remember that help on using phpBB is available online via the Documentation and the support forums.', - 'CONVERT_INTRO' => 'Welcome to the phpBB Unified Convertor Framework', - 'CONVERT_INTRO_BODY' => 'From here, you are able to import data from other (installed) board systems. The list below shows all the conversion modules currently available. If there is no convertor shown in this list for the board software you wish to convert from, please check our website where further conversion modules may be available for download.', - 'CONVERT_NEW_CONVERSION' => 'New conversion', - 'CONVERT_NOT_EXIST' => 'The specified convertor does not exist.', - 'CONVERT_OPTIONS' => 'Options', - 'CONVERT_SETTINGS_VERIFIED' => 'The information you entered has been verified. To start the conversion process, please push the button below.', - 'CONV_ERR_FATAL' => 'Fatal conversion error', - - 'CONV_ERROR_ATTACH_FTP_DIR' => 'FTP upload for attachments is enabled at the old board. Please disable the FTP upload option and make sure a valid upload directory is specified, then copy all attachment files to this new web accessible directory. Once you have done this, restart the convertor.', - 'CONV_ERROR_CONFIG_EMPTY' => 'There is no configuration information available for the conversion.', - 'CONV_ERROR_FORUM_ACCESS' => 'Unable to get forum access information.', - 'CONV_ERROR_GET_CATEGORIES' => 'Unable to get categories.', - 'CONV_ERROR_GET_CONFIG' => 'Could not retrieve your board configuration.', - 'CONV_ERROR_COULD_NOT_READ' => 'Unable to access/read “%sâ€.', - 'CONV_ERROR_GROUP_ACCESS' => 'Unable to get group authentication information.', - 'CONV_ERROR_INCONSISTENT_GROUPS' => 'Inconsistency in groups table detected in add_bots() - you need to add all special groups if you do it manually.', - 'CONV_ERROR_INSERT_BOT' => 'Unable to insert bot into users table.', - 'CONV_ERROR_INSERT_BOTGROUP' => 'Unable to insert bot into bots table.', - 'CONV_ERROR_INSERT_USER_GROUP' => 'Unable to insert user into user_group table.', - 'CONV_ERROR_MESSAGE_PARSER' => 'Message parser error', - 'CONV_ERROR_NO_AVATAR_PATH' => 'Note to developer: you must specify $convertor[\'avatar_path\'] to use %s.', - 'CONV_ERROR_NO_FORUM_PATH' => 'The relative path to the source board has not been specified.', - 'CONV_ERROR_NO_GALLERY_PATH' => 'Note to developer: you must specify $convertor[\'avatar_gallery_path\'] to use %s.', - 'CONV_ERROR_NO_GROUP' => 'Group “%1$s†could not be found in %2$s.', - 'CONV_ERROR_NO_RANKS_PATH' => 'Note to developer: you must specify $convertor[\'ranks_path\'] to use %s.', - 'CONV_ERROR_NO_SMILIES_PATH' => 'Note to developer: you must specify $convertor[\'smilies_path\'] to use %s.', - 'CONV_ERROR_NO_UPLOAD_DIR' => 'Note to developer: you must specify $convertor[\'upload_path\'] to use %s.', - 'CONV_ERROR_PERM_SETTING' => 'Unable to insert/update permission setting.', - 'CONV_ERROR_PM_COUNT' => 'Unable to select folder pm count.', - 'CONV_ERROR_REPLACE_CATEGORY' => 'Unable to insert new forum replacing old category.', - 'CONV_ERROR_REPLACE_FORUM' => 'Unable to insert new forum replacing old forum.', - 'CONV_ERROR_USER_ACCESS' => 'Unable to get user authentication information.', - 'CONV_ERROR_WRONG_GROUP' => 'Wrong group “%1$s†defined in %2$s.', - 'CONV_OPTIONS_BODY' => 'This page collects the data required to access the source board. Enter the database details of your former board; the converter will not change anything in the database given below. The source board should be disabled to allow a consistent conversion.', - 'CONV_SAVED_MESSAGES' => 'Saved messages', - - 'COULD_NOT_COPY' => 'Could not copy file %1$s to %2$s

            Please check that the target directory exists and is writable by the webserver.', - 'COULD_NOT_FIND_PATH' => 'Could not find path to your former board. Please check your settings and try again.
            » %s was specified as the source path.', - - 'DBMS' => 'Database type', - 'DB_CONFIG' => 'Database configuration', - 'DB_CONNECTION' => 'Database connection', - 'DB_ERR_INSERT' => 'Error while processing INSERT query.', - 'DB_ERR_LAST' => 'Error while processing query_last.', - 'DB_ERR_QUERY_FIRST' => 'Error while executing query_first.', - 'DB_ERR_QUERY_FIRST_TABLE' => 'Error while executing query_first, %s (“%sâ€).', - 'DB_ERR_SELECT' => 'Error while running SELECT query.', - 'DB_HOST' => 'Database server hostname or DSN', - 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.', - 'DB_NAME' => 'Database name', - 'DB_PASSWORD' => 'Database password', - 'DB_PORT' => 'Database server port', - 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.', - 'DB_UPDATE_NOT_SUPPORTED' => 'We are sorry, but this script does not support updating from versions of phpBB prior to “%1$sâ€. The version you currently have installed is “%2$sâ€. Please update to a previous version before running this script. Assistance with this is available in the Support Forum on phpBB.com.', - 'DB_USERNAME' => 'Database username', - 'DB_TEST' => 'Test connection', - 'DEFAULT_LANG' => 'Default board language', - 'DEFAULT_PREFIX_IS' => 'The convertor was not able to find tables with the specified prefix. Please make sure you have entered the correct details for the board you are converting from. The default table prefix for %1$s is %2$s.', - 'DEV_NO_TEST_FILE' => 'No value has been specified for the test_file variable in the convertor. If you are a user of this convertor, you should not be seeing this error, please report this message to the convertor author. If you are a convertor author, you must specify the name of a file which exists in the source board to allow the path to it to be verified.', - 'DIRECTORIES_AND_FILES' => 'Directory and file setup', - 'DISABLE_KEYS' => 'Disabling keys', - 'DLL_FTP' => 'Remote FTP support [ Installation ]', - 'DLL_GD' => 'GD graphics support [ Visual Confirmation ]', - 'DLL_MBSTRING' => 'Multi-byte character support', - 'DLL_MSSQL' => 'MSSQL Server 2000+', - 'DLL_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC', - 'DLL_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]', - 'DLL_MYSQL' => 'MySQL', - 'DLL_MYSQLI' => 'MySQL with MySQLi Extension', - 'DLL_ORACLE' => 'Oracle', - 'DLL_POSTGRES' => 'PostgreSQL', - 'DLL_SQLITE' => 'SQLite 2', - 'DLL_SQLITE3' => 'SQLite 3', - 'DLL_XML' => 'XML support [ Jabber ]', - 'DLL_ZLIB' => 'zlib compression support [ gz, .tar.gz, .zip ]', - 'DL_CONFIG' => 'Download config', - 'DL_CONFIG_EXPLAIN' => 'You may download the complete config.php to your own PC. You will then need to upload the file manually, replacing any existing config.php in your phpBB 3.1 root directory. Please remember to upload the file in ASCII format (see your FTP application documentation if you are unsure how to achieve this). When you have uploaded the config.php please click “Done†to move to the next stage.', - 'DL_DOWNLOAD' => 'Download', - 'DONE' => 'Done', - - 'ENABLE_KEYS' => 'Re-enabling keys. This can take a while.', - - 'FILES_OPTIONAL' => 'Optional files and directories', - 'FILES_OPTIONAL_EXPLAIN' => 'Optional - These files, directories or permission settings are not required. The installation system will attempt to use various techniques to create them if they do not exist or cannot be written to. However, the presence of these will speed installation.', - 'FILES_REQUIRED' => 'Files and Directories', - 'FILES_REQUIRED_EXPLAIN' => 'Required - In order to function correctly phpBB needs to be able to access or write to certain files or directories. If you see “Not Found†you need to create the relevant file or directory. If you see “Unwritable†you need to change the permissions on the file or directory to allow phpBB to write to it.', - 'FILLING_TABLE' => 'Filling table %s', - 'FILLING_TABLES' => 'Filling tables', - - 'FINAL_STEP' => 'Process final step', - 'FORUM_ADDRESS' => 'Board address', - 'FORUM_ADDRESS_EXPLAIN' => 'This is the URL of your former board, for example http://www.example.com/phpBB2/. If an address is entered here and not left empty every instance of this address will be replaced by your new board address within messages, private messages and signatures.', - 'FORUM_PATH' => 'Board path', - 'FORUM_PATH_EXPLAIN' => 'This is the relative path on disk to your former board from the root of this phpBB3 installation.', - 'FOUND' => 'Found', - 'FTP_CONFIG' => 'Transfer config by FTP', - 'FTP_CONFIG_EXPLAIN' => 'phpBB has detected the presence of the FTP module on this server. You may attempt to install your config.php via this if you wish. You will need to supply the information listed below. Remember your username and password are those to your server! (ask your hosting provider for details if you are unsure what these are).', - 'FTP_PATH' => 'FTP path', - 'FTP_PATH_EXPLAIN' => 'This is the path from your root directory to that of phpBB, e.g. htdocs/phpBB3/.', - 'FTP_UPLOAD' => 'Upload', - - 'GPL' => 'General Public License', - - 'INITIAL_CONFIG' => 'Basic configuration', - 'INITIAL_CONFIG_EXPLAIN' => 'Now that install has determined your server can run phpBB you need to supply some specific information. If you do not know how to connect to your database please contact your hosting provider (in the first instance) or use the phpBB support forums. When entering data please ensure you check it thoroughly before continuing.', - 'INSTALL_CONGRATS' => 'Congratulations!', - 'INSTALL_CONGRATS_EXPLAIN' => ' - You have successfully installed phpBB %1$s. Please proceed by choosing one of the following options:

            -

            Convert an existing board to phpBB3

            -

            The phpBB Unified Convertor Framework supports the conversion of phpBB 2.0.x and other board systems to phpBB3. If you have an existing board that you wish to convert, please proceed to the convertor.

            -

            Go live with your phpBB3!

            -

            Clicking the button below will take you to a form for submitting statistical data to phpBB in your Administration Control Panel (ACP). We would appreciate it if you could help us by sending that information. Afterwards you should take some time to examine the options available to you. Remember that help is available online via the Documentation, README and the Support Forums.

            Please delete, move or rename the install directory before using your board. While this directory exists, only the Administration Control Panel (ACP) will be accessible.', - 'INSTALL_INTRO' => 'Welcome to Installation', - - 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.

            In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:

            - -
              -
            • The Database Type - the database you will be using.
            • -
            • The Database server hostname or DSN - the address of the database server.
            • -
            • The Database server port - the port of the database server (most of the time this is not needed).
            • -
            • The Database name - the name of the database on the server.
            • -
            • The Database username and Database password - the login data to access the database.
            • -
            - -

            Note: if you are installing using SQLite, you should enter the full path to your database file in the DSN field and leave the username and password fields blank. For security reasons, you should make sure that the database file is not stored in a location accessible from the web.

            - -

            phpBB3 supports the following databases:

            -
              -
            • MySQL 3.23 or above (MySQLi supported)
            • -
            • PostgreSQL 8.3+
            • -
            • SQLite 2.8.2+
            • -
            • SQLite 3.6.15+
            • -
            • MS SQL Server 2000 or above (directly or via ODBC)
            • -
            • MS SQL Server 2005 or above (native)
            • -
            • Oracle
            • -
            - -

            Only those databases supported on your server will be displayed.', - 'INSTALL_INTRO_NEXT' => 'To commence the installation, please press the button below.', - 'INSTALL_LOGIN' => 'Login', - 'INSTALL_NEXT' => 'Next stage', - 'INSTALL_NEXT_FAIL' => 'Some tests failed and you should correct these problems before proceeding to the next stage. Failure to do so may result in an incomplete installation.', - 'INSTALL_NEXT_PASS' => 'All the basic tests have been passed and you may proceed to the next stage of installation. If you have changed any permissions, modules, etc. and wish to re-test you can do so if you wish.', - 'INSTALL_PANEL' => 'Installation Panel', - 'INSTALL_SEND_CONFIG' => 'Unfortunately phpBB could not write the configuration information directly to your config.php. This may be because the file does not exist or is not writable. A number of options will be listed below enabling you to complete installation of config.php.', - 'INSTALL_START' => 'Start install', - 'INSTALL_TEST' => 'Test again', - 'INST_ERR' => 'Installation error', - 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.', - 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.', - 'INST_ERR_DB_INVALID_PREFIX'=> 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.', - 'INST_ERR_DB_NO_ERROR' => 'No error message given.', - 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension†option you have selected. Please try the “MySQL†option instead.', - 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.', - 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.', - 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the NLS_CHARACTERSET parameter to UTF8. Either upgrade your installation to 9.2+ or change the parameter.', - 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in UNICODE or UTF8 encoding. Try installing with a database in UNICODE or UTF8 encoding.', - 'INST_ERR_DB_NO_NAME' => 'No database name specified.', - 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.', - 'INST_ERR_EMAIL_MISMATCH' => 'The emails you entered did not match.', - 'INST_ERR_FATAL' => 'Fatal installation error', - 'INST_ERR_FATAL_DB' => 'A fatal and unrecoverable database error has occurred. This may be because the specified user does not have appropriate permissions to CREATE TABLES or INSERT data, etc. Further information may be given below. Please contact your hosting provider in the first instance or the support forums of phpBB for further assistance.', - 'INST_ERR_FTP_PATH' => 'Could not change to the given directory, please check the path.', - 'INST_ERR_FTP_LOGIN' => 'Could not login to FTP server, check your username and password.', - 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.', - 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.', - 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.', - 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.', - 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.', - 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.', - 'INST_ERR_PREFIX_INVALID' => 'The table prefix you have specified is invalid for your database. Please try another, removing characters such as the hyphen.', - 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.', - 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.', - 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.', - 'INVALID_PRIMARY_KEY' => 'Invalid primary key : %s', - - 'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.', - - // mbstring - 'MBSTRING_CHECK' => 'mbstring extension check', - 'MBSTRING_CHECK_EXPLAIN' => 'Required - mbstring is a PHP extension that provides multibyte string functions. Certain features of mbstring are not compatible with phpBB and must be disabled.', - 'MBSTRING_FUNC_OVERLOAD' => 'Function overloading', - 'MBSTRING_FUNC_OVERLOAD_EXPLAIN' => 'mbstring.func_overload must be set to either 0 or 4.', - 'MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding', - 'MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => 'mbstring.encoding_translation must be set to 0.', - 'MBSTRING_HTTP_INPUT' => 'HTTP input character conversion', - 'MBSTRING_HTTP_INPUT_EXPLAIN' => 'mbstring.http_input must be set to pass.', - 'MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion', - 'MBSTRING_HTTP_OUTPUT_EXPLAIN' => 'mbstring.http_output must be set to pass.', - - 'MAKE_FOLDER_WRITABLE' => 'Please make sure that this folder exists and is writable by the webserver then try again:
            »%s.', - 'MAKE_FOLDERS_WRITABLE' => 'Please make sure that these folders exist and are writable by the webserver then try again:
            »%s.', - - 'MYSQL_SCHEMA_UPDATE_REQUIRED' => 'Your MySQL database schema for phpBB is outdated. phpBB detected a schema for MySQL 3.x/4.x, but the server runs on MySQL %2$s.
            Before you proceed the update, you need to upgrade the schema.

            Please refer to the Knowledge Base article about upgrading the MySQL schema. If you encounter problems, please use our support forums.', - - 'NAMING_CONFLICT' => 'Naming conflict: %s and %s are both aliases

            %s', - 'NEXT_STEP' => 'Proceed to next step', - 'NOT_FOUND' => 'Cannot find', - 'NOT_UNDERSTAND' => 'Could not understand %s #%d, table %s (“%sâ€)', - 'NO_CONVERTORS' => 'No convertors are available for use.', - 'NO_CONVERT_SPECIFIED' => 'No convertor specified.', - 'NO_LOCATION' => 'Cannot determine location. If you know Imagemagick is installed, you may specify the location later within your administration control panel', - 'NO_TABLES_FOUND' => 'No tables found.', - - 'OVERVIEW_BODY' => 'Welcome to phpBB3!

            phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.

            This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read the installation guide.

            To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.', - - 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support', - 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.', - 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP function getimagesize() is available', - 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'Required - In order for phpBB to function correctly, the getimagesize function needs to be available.', - 'PHP_JSON_SUPPORT' => 'PHP JSON support', - 'PHP_JSON_SUPPORT_EXPLAIN' => 'Required - In order for phpBB to function correctly, the PHP JSON extension needs to be available.', - 'PHP_OPTIONAL_MODULE' => 'Optional modules', - 'PHP_OPTIONAL_MODULE_EXPLAIN' => 'Optional - These modules or applications are optional. However, if they are available they will enable extra features.', - 'PHP_SUPPORTED_DB' => 'Supported databases', - 'PHP_SUPPORTED_DB_EXPLAIN' => 'Required - You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.', - 'PHP_REGISTER_GLOBALS' => 'PHP setting register_globals is disabled', - 'PHP_REGISTER_GLOBALS_EXPLAIN' => 'phpBB will still run if this setting is enabled, but if possible, it is recommended that register_globals is disabled on your PHP install for security reasons.', - 'PHP_SAFE_MODE' => 'Safe mode', - 'PHP_SETTINGS' => 'PHP version and settings', - 'PHP_SETTINGS_EXPLAIN' => 'Required - You must be running at least version 5.3.9 of PHP in order to install phpBB. If safe mode is displayed below your PHP installation is running in that mode. This will impose limitations on remote administration and similar features.', - 'PHP_URL_FOPEN_SUPPORT' => 'PHP setting allow_url_fopen is enabled', - 'PHP_URL_FOPEN_SUPPORT_EXPLAIN' => 'Optional - This setting is optional, however certain phpBB functions like off-site avatars will not work properly without it.', - 'PHP_VERSION_REQD' => 'PHP version >= 5.3.9', - 'POST_ID' => 'Post ID', - 'PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using %s as table prefix.', - 'PREPROCESS_STEP' => 'Executing pre-processing functions/queries', - 'PRE_CONVERT_COMPLETE' => 'All pre-conversion steps have successfully been completed. You may now begin the actual conversion process. Please note that you may have to manually do and adjust several things. After conversion, especially check the permissions assigned, rebuild your search index which is not converted and also make sure files got copied correctly, for example avatars and smilies.', - 'PROCESS_LAST' => 'Processing last statements', - - 'REFRESH_PAGE' => 'Refresh page to continue conversion', - 'REFRESH_PAGE_EXPLAIN' => 'If set to yes, the convertor will refresh the page to continue the conversion after having finished a step. If this is your first conversion for testing purposes and to determine any errors in advance, we suggest to set this to No.', - 'REQUIREMENTS_TITLE' => 'Installation compatibility', - 'REQUIREMENTS_EXPLAIN' => 'Before proceeding with the full installation phpBB will carry out some tests on your server configuration and files to ensure that you are able to install and run phpBB. Please ensure you read through the results thoroughly and do not proceed until all the required tests are passed. If you wish to use any of the features depending on the optional tests, you should ensure that these tests are passed also.', - 'RETRY_WRITE' => 'Retry writing config', - 'RETRY_WRITE_EXPLAIN' => 'If you wish you can change the permissions on config.php to allow phpBB to write to it. Should you wish to do that you can click Retry below to try again. Remember to return the permissions on config.php after phpBB has finished installation.', - - 'SELECT_LANG' => 'Select language', - 'SEARCH_INDEX_UNCONVERTED' => 'Search index was not converted', - 'SEARCH_INDEX_UNCONVERTED_EXPLAIN' => 'Your old search index was not converted. Searching will always yield an empty result. To create a new search index go to the Administration Control Panel, select Maintenance and then choose Search index from the submenu.', - 'SELECT_FORUM_GA' => 'In phpBB 3.1 the global announcements are linked to forums. Select a forum for your current global announcements (can be moved later):', - 'SOFTWARE' => 'Board software', - 'SPECIFY_OPTIONS' => 'Specify conversion options', - 'STAGE_ADMINISTRATOR' => 'Administrator details', - 'STAGE_ADVANCED' => 'Advanced settings', - 'STAGE_ADVANCED_EXPLAIN' => 'The settings on this page are only necessary to set if you know that you require something different from the default. If you are unsure, just proceed to the next page, as these settings can be altered from the Administration Control Panel later.', - 'STAGE_CONFIG_FILE' => 'Configuration file', - 'STAGE_CREATE_TABLE' => 'Create database tables', - 'STAGE_CREATE_TABLE_EXPLAIN' => 'The database tables used by phpBB 3.1 have been created and populated with some initial data. Proceed to the next screen to finish installing phpBB.', - 'STAGE_DATABASE' => 'Database settings', - 'STAGE_FINAL' => 'Final stage', - 'STAGE_INTRO' => 'Introduction', - 'STAGE_IN_PROGRESS' => 'Conversion in progress', - 'STAGE_REQUIREMENTS' => 'Requirements', - 'STAGE_SETTINGS' => 'Settings', - 'STARTING_CONVERT' => 'Starting conversion process', - 'STEP_PERCENT_COMPLETED' => 'Step %d of %d', - 'SUB_INTRO' => 'Introduction', - 'SUB_LICENSE' => 'License', - 'SUB_SUPPORT' => 'Support', - 'SUCCESSFUL_CONNECT' => 'Successful connection', - 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:

            • installation
            • configuration
            • technical questions
            • problems relating to potential bugs in the software
            • updating from Release Candidate (RC) versions to the latest stable version
            • converting from phpBB 2.0.x to phpBB3
            • converting from other discussion board software to phpBB3 (please see the Convertors Forum)

            We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.

            Extensions / Styles

            For issues relating to Extensions, please post in the appropriate Extensions Forum.
            For issues relating to styles, templates and themes, please post in the appropriate Styles Forum.

            If your question relates to a specific package, please post directly in the topic dedicated to the package.

            Obtaining Support

            The phpBB Welcome Package
            Support Section
            Quick Start Guide

            To ensure you stay up to date with the latest news and releases, why not subscribe to our mailing list?

            ', - 'SYNC_FORUMS' => 'Starting to synchronise forums', - 'SYNC_POST_COUNT' => 'Synchronising post_counts', - 'SYNC_POST_COUNT_ID' => 'Synchronising post_counts from entry %1$s to %2$s.', - 'SYNC_TOPICS' => 'Starting to synchronise topics', - 'SYNC_TOPIC_ID' => 'Synchronising topics from topic_id %1$s to %2$s.', - - 'TABLES_MISSING' => 'Could not find these tables
            » %s.', - 'TABLE_PREFIX' => 'Prefix for tables in database', - 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.', - 'TABLE_PREFIX_SAME' => 'The table prefix needs to be the one used by the software you are converting from.
            » Specified table prefix was %s.', - 'TESTS_PASSED' => 'Tests passed', - 'TESTS_FAILED' => 'Tests failed', - - 'UNABLE_WRITE_LOCK' => 'Unable to write lock file.', - 'UNAVAILABLE' => 'Unavailable', - 'UNWRITABLE' => 'Unwritable', - 'UPDATE_TOPICS_POSTED' => 'Generating topics posted information', - 'UPDATE_TOPICS_POSTED_ERR' => 'An error occurred while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.', - 'VERIFY_OPTIONS' => 'Verifying conversion options', - 'VERSION' => 'Version', - - 'WELCOME_INSTALL' => 'Welcome to phpBB3 Installation', - 'WRITABLE' => 'Writable', -)); - -// Updater -$lang = array_merge($lang, array( - 'ALL_FILES_UP_TO_DATE' => 'All files are up to date with the latest phpBB version.', - 'ARCHIVE_FILE' => 'Source file within archive', - - 'BACK' => 'Back', - 'BINARY_FILE' => 'Binary file', - 'BOT' => 'Spider/Robot', - - 'CHANGE_CLEAN_NAMES' => 'The method used to make sure a username is not used by multiple users has been changed. There are some users which have the same name when compared with the new method. You have to delete or rename these users to make sure that each name is only used by one user before you can proceed.', - 'CHECK_FILES' => 'Check files', - 'CHECK_FILES_AGAIN' => 'Check files again', - 'CHECK_FILES_EXPLAIN' => 'Within the next step all files will be checked against the update files - this can take a while if this is the first file check.', - 'CHECK_FILES_UP_TO_DATE' => 'According to your database your version is up to date. You may want to proceed with the file check to make sure all files are really up to date with the latest phpBB version.', - 'CHECK_UPDATE_DATABASE' => 'Continue update process', - 'COLLECTED_INFORMATION' => 'File information', - 'COLLECTED_INFORMATION_EXPLAIN' => 'The list below shows information about the files needing an update. Please read the information in front of every status block to see what they mean and what you may need to do to perform a successful update.', - 'COLLECTING_FILE_DIFFS' => 'Collecting file differences', - 'COMPLETE_LOGIN_TO_BOARD' => 'You should now login to your board and check if everything is working fine. Do not forget to delete, rename or move your install directory!', - 'CONTINUE_UPDATE_NOW' => 'Continue the update process now', // Shown within the database update script at the end if called from the updater - 'CONTINUE_UPDATE' => 'Continue update now', // Shown after file upload to indicate the update process is not yet finished - 'CURRENT_FILE' => 'Begin of Conflict - Original File code before update', - 'CURRENT_VERSION' => 'Current version', - - 'DATABASE_TYPE' => 'Database type', - 'DATABASE_UPDATE_COMPLETE' => 'Database updater has completed!', - 'DATABASE_UPDATE_CONTINUE' => 'Continue database update', - 'DATABASE_UPDATE_INFO_OLD' => 'The database update file within the install directory is outdated. Please make sure you uploaded the correct version of the file.', - 'DATABASE_UPDATE_NOT_COMPLETED' => 'The database update has not yet completed.', - 'DELETE_USER_REMOVE' => 'Delete user and remove posts', - 'DELETE_USER_RETAIN' => 'Delete user but keep posts', - 'DESTINATION' => 'Destination file', - 'DIFF_INLINE' => 'Inline', - 'DIFF_RAW' => 'Raw unified diff', - 'DIFF_SEP_EXPLAIN' => 'Code block used within the updated/new file', - 'DIFF_SIDE_BY_SIDE' => 'Side by Side', - 'DIFF_UNIFIED' => 'Unified diff', - 'DO_NOT_UPDATE' => 'Do not update this file', - 'DONE' => 'Done', - 'DOWNLOAD' => 'Download', - 'DOWNLOAD_AS' => 'Download as', - 'DOWNLOAD_UPDATE_METHOD_BUTTON' => 'Download modified files archive (recommended)', - 'DOWNLOAD_CONFLICTS' => 'Download conflicts for this file', - 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for <<< to spot conflicts', - 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive', - 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, please check the files again with the other button below.', - - 'EDIT_USERNAME' => 'Edit username', - 'ERROR' => 'Error', - 'EVERYTHING_UP_TO_DATE' => 'Everything is up to date with the latest phpBB version. You should now login to your board and check if everything is working fine. Do not forget to delete, rename or move your install directory! Please send us updated information about your server and board configurations from the Send statistics module in your ACP.', - - 'FILE_ALREADY_UP_TO_DATE' => 'File is already up to date.', - 'FILE_DIFF_NOT_ALLOWED' => 'File not allowed to be diffed.', - 'FILE_USED' => 'Information used from', // Single file - 'FILES_CONFLICT' => 'Conflict files', - 'FILES_CONFLICT_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. phpBB determined that these files create conflicts if they are tried to be merged. Please investigate the conflicts and try to manually resolve them or continue the update choosing the preferred merging method. If you resolve the conflicts manually check the files again after you modified them. You are also able to choose between the preferred merge method for every file. The first one will result in a file where the conflicting lines from your old file will be lost, the other one will result in losing the changes from the newer file.', - 'FILES_DELETED' => 'Deleted files', - 'FILES_DELETED_EXPLAIN' => 'The following files do not exist in the new version. These files have to be deleted from your installation.', - 'FILES_MODIFIED' => 'Modified files', - 'FILES_MODIFIED_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. The updated file will be a merge between your modifications and the new file.', - 'FILES_NEW' => 'New files', - 'FILES_NEW_EXPLAIN' => 'The following files currently do not exist within your installation. These files will be added to your installation.', - 'FILES_NEW_CONFLICT' => 'New conflicting files', - 'FILES_NEW_CONFLICT_EXPLAIN' => 'The following files are new within the latest version but it has been determined that there is already a file with the same name within the same position. This file will be overwritten by the new file.', - 'FILES_NOT_MODIFIED' => 'Not modified files', - 'FILES_NOT_MODIFIED_EXPLAIN' => 'The following files are not modified and represent the original phpBB files from the version you want to update from.', - 'FILES_UP_TO_DATE' => 'Already updated files', - 'FILES_UP_TO_DATE_EXPLAIN' => 'The following files are already up to date and do not need to be updated.', - 'FTP_SETTINGS' => 'FTP settings', - 'FTP_UPDATE_METHOD' => 'FTP upload', - - 'INCOMPATIBLE_UPDATE_FILES' => 'The update files found are incompatible with your installed version. Your installed version is %1$s and the update file is for updating phpBB %2$s to %3$s.', - 'INCOMPLETE_UPDATE_FILES' => 'The update files are incomplete.', - 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful. Now you need to continue the update process.', - - 'KEEP_OLD_NAME' => 'Keep username', - - 'LATEST_VERSION' => 'Latest version', - 'LINE' => 'Line', - 'LINE_ADDED' => 'Added', - 'LINE_MODIFIED' => 'Modified', - 'LINE_REMOVED' => 'Removed', - 'LINE_UNMODIFIED' => 'Unmodified', - 'LOGIN_UPDATE_EXPLAIN' => 'In order to update your installation you need to login first.', - - 'MAPPING_FILE_STRUCTURE' => 'To ease the upload here are the file locations which map your phpBB installation.', - - 'MERGE_MODIFICATIONS_OPTION' => 'Merge modifications', - - 'MERGE_NO_MERGE_NEW_OPTION' => 'Do not merge - use new file', - 'MERGE_NO_MERGE_MOD_OPTION' => 'Do not merge - use currently installed file', - 'MERGE_MOD_FILE_OPTION' => 'Merge modifications (removes new phpBB code within conflicting block)', - 'MERGE_NEW_FILE_OPTION' => 'Merge modifications (removes modified code within conflicting block)', - 'MERGE_SELECT_ERROR' => 'Conflicting file merge modes are not correctly selected.', - 'MERGING_FILES' => 'Merging differences', - 'MERGING_FILES_EXPLAIN' => 'Currently collecting final file changes.

            Please wait until phpBB has completed all operations on changed files.', - - 'NEW_FILE' => 'End of Conflict', - 'NEW_USERNAME' => 'New username', - 'NO_AUTH_UPDATE' => 'Not authorised to update', - 'NO_ERRORS' => 'No errors', - 'NO_UPDATE_FILES' => 'Not updating the following files', - 'NO_UPDATE_FILES_EXPLAIN' => 'The following files are new or modified but the directory they normally reside in could not be found on your installation. If this list contains files to other directories than language/ or styles/ than you may have modified your directory structure and the update may be incomplete.', - 'NO_UPDATE_FILES_OUTDATED' => 'No valid update directory was found, please make sure you uploaded the relevant files.

            Your installation does not seem to be up to date. Updates are available for your version of phpBB %1$s, please visit https://www.phpbb.com/downloads/ to obtain the correct package to update from Version %2$s to Version %3$s.', - 'NO_UPDATE_FILES_UP_TO_DATE' => 'Your version is up to date. There is no need to run the update tool. If you want to make an integrity check on your files make sure you uploaded the correct update files.', - 'NO_UPDATE_INFO' => 'Update file information could not be found.', - 'NO_UPDATES_REQUIRED' => 'No updates required', - 'NO_VISIBLE_CHANGES' => 'No visible changes', - 'NOTICE' => 'Notice', - 'NUM_CONFLICTS' => 'Number of conflicts', - 'NUMBER_OF_FILES_COLLECTED' => 'Currently differences from %1$d of %2$d files have been checked.
            Please wait until all files are checked.', - - 'OLD_UPDATE_FILES' => 'Update files are out of date. The update files found are for updating from phpBB %1$s to phpBB %2$s but the latest version of phpBB is %3$s.', - - 'PACKAGE_UPDATES_TO' => 'Current package updates to version', - 'PERFORM_DATABASE_UPDATE' => 'Perform database update', - 'PERFORM_DATABASE_UPDATE_EXPLAIN' => 'Below you will find a button to the database update script. The database update can take a while, so please do not stop the execution if it seems to hang. After the database update has been performed just follow the instructions to continue the update process.', - 'PREVIOUS_VERSION' => 'Previous version', - 'PROGRESS' => 'Progress', - - 'RELEASE_ANNOUNCEMENT' => 'Announcement', - 'RESULT' => 'Result', - 'RUN_DATABASE_SCRIPT' => 'Update my database now', - - 'SELECT_DIFF_MODE' => 'Select diff mode', - 'SELECT_DOWNLOAD_FORMAT' => 'Select download archive format', - 'SELECT_FTP_SETTINGS' => 'Select FTP settings', - 'SHOW_DIFF_CONFLICT' => 'Show differences/conflicts', - 'SHOW_DIFF_DELETED' => 'Show file contents', - 'SHOW_DIFF_FINAL' => 'Show resulting file', - 'SHOW_DIFF_MODIFIED' => 'Show merged differences', - 'SHOW_DIFF_NEW' => 'Show file contents', - 'SHOW_DIFF_NEW_CONFLICT' => 'Show differences', - 'SHOW_DIFF_NOT_MODIFIED' => 'Show differences', - 'SOME_QUERIES_FAILED' => 'Some queries failed, the statements and errors are listed below.', - 'SQL' => 'SQL', - 'SQL_FAILURE_EXPLAIN' => 'This is probably nothing to worry about, update will continue. Should this fail to complete you may need to seek help at our support forums. See README for details on how to obtain advice.', - 'STAGE_FILE_CHECK' => 'Check files', - 'STAGE_UPDATE_DB' => 'Update database', - 'STAGE_UPDATE_FILES' => 'Update files', - 'STAGE_VERSION_CHECK' => 'Version check', - 'STATUS_CONFLICT' => 'Modified file producing conflicts', - 'STATUS_DELETED' => 'Deleted file', - 'STATUS_MODIFIED' => 'Modified file', - 'STATUS_NEW' => 'New file', - 'STATUS_NEW_CONFLICT' => 'Conflicting new file', - 'STATUS_NOT_MODIFIED' => 'Not modified file', - 'STATUS_UP_TO_DATE' => 'Already updated file', - - 'TOGGLE_DISPLAY' => 'View/Hide file list', - 'TRY_DOWNLOAD_METHOD' => 'You may want to try the download modified files method.
            This method always works and is also the recommended update path.', - 'TRY_DOWNLOAD_METHOD_BUTTON'=> 'Try this method now', - - 'UPDATE_COMPLETED' => 'Update completed', - 'UPDATE_DATABASE' => 'Update database', - 'UPDATE_DATABASE_EXPLAIN' => 'Within the next step the database will be updated.', - 'UPDATE_DATABASE_SCHEMA' => 'Updating database schema', - 'UPDATE_FILES' => 'Update files', - 'UPDATE_FILES_NOTICE' => 'Please make sure you have updated your board files too, this file is only updating your database.', - 'UPDATE_INSTALLATION' => 'Update phpBB installation', - 'UPDATE_INSTALLATION_EXPLAIN' => 'With this option, it is possible to update your phpBB installation to the latest version.
            During the process all of your files will be checked for their integrity. You are able to review all differences and files before the update.

            The file update itself can be done in two different ways.

            Manual Update

            With this update you only download your personal set of changed files to make sure you do not lose your file modifications you may have done. After you downloaded this package you need to manually upload the files to their correct position under your phpBB root directory. Once done, you are able to do the file check stage again to see if you moved the files to their correct location.

            Automatic Update with FTP

            This method is similar to the first one but without the need to download the changed files and uploading them on your own. This will be done for you. In order to use this method you need to know your FTP login details since you will be asked for them. Once finished you will be redirected to the file check again to make sure everything got updated correctly.

            ', - 'UPDATE_INSTRUCTIONS' => ' - -

            Release announcement

            - -

            Please read the release announcement for the latest version before you continue your update process, it may contain useful information. It also contains full download links as well as the change log.

            - -
            - -

            How to update your installation with the Automatic Update Package

            - -

            The recommended way of updating your installation listed here is only valid for the automatic update package. You are also able to update your installation using the methods listed within the INSTALL.html document. The steps for updating phpBB3 automatically are:

            - -
              -
            • Go to the phpBB.com downloads page and download the "Automatic Update Package" archive.

            • -
            • Unpack the archive.

            • -
            • Upload the complete uncompressed "install" and "vendor" folders to your phpBB root directory (where your config.php file is).

            • -
            - -

            Once uploaded your board will be offline for normal users due to the install directory you uploaded now present.

            - Now start the update process by pointing your browser to the install folder.
            -
            - You will then be guided through the update process. You will be notified once the update is complete. -

            - ', - 'UPDATE_METHOD' => 'Update method', - 'UPDATE_METHOD_EXPLAIN' => 'You are now able to choose your preferred update method. Using the FTP upload will present you with a form you need to enter your FTP account details into. With this method the files will be automatically moved to the new location and backups of the old files being created by appending .bak to the filename. If you choose to download the modified files you are able to unpack and upload them to their correct location manually later.', - 'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s', - 'UPDATE_SUCCESS' => 'Update was successful', - 'UPDATE_SUCCESS_EXPLAIN' => 'Successfully updated all files. The next step involves checking all files again to make sure the files got updated correctly.', - 'UPDATE_VERSION_OPTIMIZE' => 'Updating version and optimising tables', - 'UPDATING_DATA' => 'Updating data', - 'UPDATING_TO_LATEST_STABLE' => 'Updating database to latest stable release', - 'UPDATED_VERSION' => 'Updated version', - 'UPLOAD_METHOD' => 'Upload method', - - 'UPDATE_DB_SUCCESS' => 'Database update was successful.', - 'UPDATE_FILE_SUCCESS' => 'File update was successful.', - 'USER_ACTIVE' => 'Active user', - 'USER_INACTIVE' => 'Inactive user', - - 'VERSION_CHECK' => 'Version check', - 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.', - 'VERSION_NOT_UP_TO_DATE' => 'Your phpBB installation is not up to date. Please continue the update process.', - 'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.
            Below is a link to the release announcement, which contains more information as well as instructions on updating.', - 'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.', - 'VERSION_UP_TO_DATE' => 'Your phpBB installation is up to date. Although there are no updates available at this time, you may continue in order to perform a file validity check.', - 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.', - 'VIEWING_FILE_CONTENTS' => 'Viewing file contents', - 'VIEWING_FILE_DIFF' => 'Viewing file differences', - - 'WRONG_INFO_FILE_FORMAT' => 'Wrong info file format', -)); - -// Default database schema entries... -$lang = array_merge($lang, array( - 'CONFIG_BOARD_EMAIL_SIG' => 'Thanks, The Management', - 'CONFIG_SITE_DESC' => 'A short text to describe your forum', - 'CONFIG_SITENAME' => 'yourdomain.com', - - 'DEFAULT_INSTALL_POST' => 'This is an example post in your phpBB3 installation. Everything seems to be working. You may delete this post if you like and continue to set up your board. During the installation process your first category and your first forum are assigned an appropriate set of permissions for the predefined usergroups administrators, bots, global moderators, guests, registered users and registered COPPA users. If you also choose to delete your first category and your first forum, do not forget to assign permissions for all these usergroups for all new categories and forums you create. It is recommended to rename your first category and your first forum and copy permissions from these while creating new categories and forums. Have fun!', - - 'FORUMS_FIRST_CATEGORY' => 'Your first category', - 'FORUMS_TEST_FORUM_DESC' => 'Description of your first forum.', - 'FORUMS_TEST_FORUM_TITLE' => 'Your first forum', - - 'RANKS_SITE_ADMIN_TITLE' => 'Site Admin', - 'REPORT_WAREZ' => 'The post contains links to illegal or pirated software.', - 'REPORT_SPAM' => 'The reported post has the only purpose to advertise for a website or another product.', - 'REPORT_OFF_TOPIC' => 'The reported post is off topic.', - 'REPORT_OTHER' => 'The reported post does not fit into any other category, please use the further information field.', - - 'SMILIES_ARROW' => 'Arrow', - 'SMILIES_CONFUSED' => 'Confused', - 'SMILIES_COOL' => 'Cool', - 'SMILIES_CRYING' => 'Crying or Very Sad', - 'SMILIES_EMARRASSED' => 'Embarrassed', - 'SMILIES_EVIL' => 'Evil or Very Mad', - 'SMILIES_EXCLAMATION' => 'Exclamation', - 'SMILIES_GEEK' => 'Geek', - 'SMILIES_IDEA' => 'Idea', - 'SMILIES_LAUGHING' => 'Laughing', - 'SMILIES_MAD' => 'Mad', - 'SMILIES_MR_GREEN' => 'Mr. Green', - 'SMILIES_NEUTRAL' => 'Neutral', - 'SMILIES_QUESTION' => 'Question', - 'SMILIES_RAZZ' => 'Razz', - 'SMILIES_ROLLING_EYES' => 'Rolling Eyes', - 'SMILIES_SAD' => 'Sad', - 'SMILIES_SHOCKED' => 'Shocked', - 'SMILIES_SMILE' => 'Smile', - 'SMILIES_SURPRISED' => 'Surprised', - 'SMILIES_TWISTED_EVIL' => 'Twisted Evil', - 'SMILIES_UBER_GEEK' => 'Uber Geek', - 'SMILIES_VERY_HAPPY' => 'Very Happy', - 'SMILIES_WINK' => 'Wink', - - 'TOPICS_TOPIC_TITLE' => 'Welcome to phpBB3', -)); From 97d08d6f56cf448fd4def8a4d29c570da91faa89 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 22 Jul 2015 03:16:16 +0200 Subject: [PATCH 0529/1676] [ticket/13740] Allow language change in the installer PHPBB3-13740 --- phpBB/adm/style/install_header.html | 8 +- phpBB/assets/javascript/installer.js | 3 + .../container/services_install_controller.yml | 1 + phpBB/phpbb/install/controller/helper.php | 243 ++++++++++++------ phpBB/phpbb/install/controller/install.php | 2 +- .../install/controller/installer_index.php | 2 +- phpBB/phpbb/language/language.php | 48 +++- 7 files changed, 212 insertions(+), 95 deletions(-) diff --git a/phpBB/adm/style/install_header.html b/phpBB/adm/style/install_header.html index b162fa3e89..9d0f9a56de 100644 --- a/phpBB/adm/style/install_header.html +++ b/phpBB/adm/style/install_header.html @@ -15,10 +15,14 @@

            {L_INSTALL_PANEL}

            {L_SKIP}

            -
            +
            - {S_LANG_SELECT} +
            diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index 105818f82b..91e8eb4797 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -330,6 +330,9 @@ xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhReq.send(getFormFields($form, $submitBtn)); + // Disable language selector + $('#language_selector :input, label').css('display', 'none'); + // Clear content setupAjaxLayout(); $('#loading_indicator').css('display', 'block'); diff --git a/phpBB/config/installer/container/services_install_controller.yml b/phpBB/config/installer/container/services_install_controller.yml index 7acc7025a6..a3595ff0a3 100644 --- a/phpBB/config/installer/container/services_install_controller.yml +++ b/phpBB/config/installer/container/services_install_controller.yml @@ -15,6 +15,7 @@ services: - @installer.navigation.provider - @template - @path_helper + - @request - @symfony_request - @router - %core.root_path% diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index 569938be09..5fd0abf9c7 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -17,10 +17,13 @@ use phpbb\install\helper\navigation\navigation_provider; use phpbb\language\language; use phpbb\language\language_file_helper; use phpbb\path_helper; +use phpbb\request\request; +use phpbb\request\request_interface; use phpbb\routing\router; use phpbb\symfony_request; use phpbb\template\template; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Cookie; /** * A duplicate of \phpbb\controller\helper @@ -35,6 +38,11 @@ class helper */ protected $language; + /** + * @var bool|string + */ + protected $language_cookie; + /** * @var \phpbb\language\language_file_helper */ @@ -55,6 +63,11 @@ class helper */ protected $path_helper; + /** + * @var \phpbb\request\request + */ + protected $phpbb_request; + /** * @var \phpbb\symfony_request */ @@ -83,120 +96,58 @@ class helper * @param navigation_provider $nav * @param template $template * @param path_helper $path_helper + * @param request $phpbb_request * @param symfony_request $request * @param router $router * @param string $phpbb_root_path */ - public function __construct(language $language, language_file_helper $lang_helper, navigation_provider $nav, template $template, path_helper $path_helper, symfony_request $request, router $router, $phpbb_root_path) + public function __construct(language $language, language_file_helper $lang_helper, navigation_provider $nav, template $template, path_helper $path_helper, request $phpbb_request, symfony_request $request, router $router, $phpbb_root_path) { $this->language = $language; + $this->language_cookie = false; $this->lang_helper = $lang_helper; $this->navigation_provider = $nav; $this->template = $template; $this->path_helper = $path_helper; + $this->phpbb_request = $phpbb_request; $this->request = $request; $this->router = $router; $this->phpbb_root_path = $phpbb_root_path; $this->phpbb_admin_path = $phpbb_root_path . 'adm/'; + + $this->handle_language_select(); } /** * Automate setting up the page and creating the response object. * - * @param string $template_file The template handle to render - * @param string $page_title The title of the page to output - * @param int $status_code The status code to be sent to the page header + * @param string $template_file The template handle to render + * @param string $page_title The title of the page to output + * @param bool $selected_language True to enable language selector it, false otherwise + * @param int $status_code The status code to be sent to the page header * * @return Response object containing rendered page */ - public function render($template_file, $page_title = '', $status_code = 200) + public function render($template_file, $page_title = '', $selected_language = false, $status_code = 200) { - $this->page_header($page_title); + $this->page_header($page_title, $selected_language); $this->template->set_filenames(array( 'body' => $template_file, )); - return new Response($this->template->assign_display('body'), $status_code); - } + $response = new Response($this->template->assign_display('body'), $status_code); - /** - * Set default template variables - * - * @param string $page_title - */ - protected function page_header($page_title) - { - $this->template->assign_vars(array( - 'L_CHANGE' => $this->language->lang('CHANGE'), - 'L_COLON' => $this->language->lang('COLON'), - 'L_INSTALL_PANEL' => $this->language->lang('INSTALL_PANEL'), - 'L_SELECT_LANG' => $this->language->lang('SELECT_LANG'), - 'L_SKIP' => $this->language->lang('SKIP'), - 'PAGE_TITLE' => $this->language->lang($page_title), - 'T_IMAGE_PATH' => htmlspecialchars($this->phpbb_admin_path) . 'images/', - 'T_JQUERY_LINK' => $this->path_helper->get_web_root_path() . 'assets/javascript/jquery.min.js', - 'T_TEMPLATE_PATH' => $this->path_helper->get_web_root_path() . 'adm/style', - 'T_ASSETS_PATH' => $this->path_helper->get_web_root_path() . 'assets/', - - 'S_CONTENT_DIRECTION' => $this->language->lang('DIRECTION'), - 'S_CONTENT_FLOW_BEGIN' => ($this->language->lang('DIRECTION') === 'ltr') ? 'left' : 'right', - 'S_CONTENT_FLOW_END' => ($this->language->lang('DIRECTION') === 'ltr') ? 'right' : 'left', - 'S_CONTENT_ENCODING' => 'UTF-8', - - 'S_USER_LANG' => $this->language->lang('USER_LANG'), - ) - ); - - $this->render_navigation(); - } - - /** - * Render navigation - */ - protected function render_navigation() - { - // Get navigation items - $nav_array = $this->navigation_provider->get(); - $nav_array = $this->sort_navigation_level($nav_array); - - $active_main_menu = $this->get_active_main_menu($nav_array); - - // Pass navigation to template - foreach ($nav_array as $key => $entry) + // Set language cookie + if ($this->language_cookie !== false) { - $this->template->assign_block_vars('t_block1', array( - 'L_TITLE' => $this->language->lang($entry['label']), - 'S_SELECTED' => ($active_main_menu === $key), - 'U_TITLE' => $this->route($entry['route']), - )); + $cookie = new Cookie('lang', $this->language_cookie, time() + 3600); + $response->headers->setCookie($cookie); - if (is_array($entry[0]) && $active_main_menu === $key) - { - $entry[0] = $this->sort_navigation_level($entry[0]); - - foreach ($entry[0] as $name => $sub_entry) - { - if (isset($sub_entry['stage']) && $sub_entry['stage'] === true) - { - $this->template->assign_block_vars('l_block2', array( - 'L_TITLE' => $this->language->lang($sub_entry['label']), - 'S_SELECTED' => (isset($sub_entry['selected']) && $sub_entry['selected'] === true), - 'S_COMPLETE' => (isset($sub_entry['completed']) && $sub_entry['completed'] === true), - 'STAGE_NAME' => $name, - )); - } - else - { - $this->template->assign_block_vars('l_block1', array( - 'L_TITLE' => $this->language->lang($sub_entry['label']), - 'S_SELECTED' => (isset($sub_entry['route']) && $sub_entry['route'] === $this->request->get('_route')), - 'U_TITLE' => $this->route($sub_entry['route']), - )); - } - } - } + $this->language_cookie = false; } + + return $response; } /** @@ -214,12 +165,134 @@ class helper } /** - * Render language select form + * Handles language selector form */ - protected function render_language_select() + protected function handle_language_select() + { + $lang = null; + + // Check if language form has been submited + $submit = $this->phpbb_request->variable('change_lang', ''); + if (!empty($submit)) + { + $lang = $this->phpbb_request->variable('language', ''); + + if (!empty($lang)) + { + $this->language_cookie = $lang; + } + } + + // Retrive language from cookie + $lang_cookie = $this->phpbb_request->variable('lang', '', false, request_interface::COOKIE); + if (empty($lang) && !empty($lang_cookie)) + { + $lang = $lang_cookie; + $this->language_cookie = $lang; + } + + $lang = (!empty($lang)) ? $lang : null; + $this->render_language_select($lang); + + if ($lang !== null) + { + $this->language->set_user_language($lang, true); + } + } + + /** + * Set default template variables + * + * @param string $page_title Title of the page + * @param bool $selected_language True to enable language selector it, false otherwise + */ + protected function page_header($page_title, $selected_language = false) + { + $this->template->assign_vars(array( + 'L_CHANGE' => $this->language->lang('CHANGE'), + 'L_COLON' => $this->language->lang('COLON'), + 'L_INSTALL_PANEL' => $this->language->lang('INSTALL_PANEL'), + 'L_SELECT_LANG' => $this->language->lang('SELECT_LANG'), + 'L_SKIP' => $this->language->lang('SKIP'), + 'PAGE_TITLE' => $this->language->lang($page_title), + 'T_IMAGE_PATH' => htmlspecialchars($this->phpbb_admin_path) . 'images/', + 'T_JQUERY_LINK' => $this->path_helper->get_web_root_path() . 'assets/javascript/jquery.min.js', + 'T_TEMPLATE_PATH' => $this->path_helper->get_web_root_path() . 'adm/style', + 'T_ASSETS_PATH' => $this->path_helper->get_web_root_path() . 'assets/', + + 'S_CONTENT_DIRECTION' => $this->language->lang('DIRECTION'), + 'S_CONTENT_FLOW_BEGIN' => ($this->language->lang('DIRECTION') === 'ltr') ? 'left' : 'right', + 'S_CONTENT_FLOW_END' => ($this->language->lang('DIRECTION') === 'ltr') ? 'right' : 'left', + 'S_CONTENT_ENCODING' => 'UTF-8', + 'S_LANG_SELECT' => $selected_language, + + 'S_USER_LANG' => $this->language->lang('USER_LANG'), + ) + ); + + $this->render_navigation(); + } + + + + /** + * Render navigation + */ + protected function render_navigation() + { + // Get navigation items + $nav_array = $this->navigation_provider->get(); + $nav_array = $this->sort_navigation_level($nav_array); + + $active_main_menu = $this->get_active_main_menu($nav_array); + + // Pass navigation to template + foreach ($nav_array as $key => $entry) { + $this->template->assign_block_vars('t_block1', array( + 'L_TITLE' => $this->language->lang($entry['label']), + 'S_SELECTED' => ($active_main_menu === $key), + 'U_TITLE' => $this->route($entry['route']), + )); + + if (is_array($entry[0]) && $active_main_menu === $key) { + $entry[0] = $this->sort_navigation_level($entry[0]); + + foreach ($entry[0] as $name => $sub_entry) { + if (isset($sub_entry['stage']) && $sub_entry['stage'] === true) { + $this->template->assign_block_vars('l_block2', array( + 'L_TITLE' => $this->language->lang($sub_entry['label']), + 'S_SELECTED' => (isset($sub_entry['selected']) && $sub_entry['selected'] === true), + 'S_COMPLETE' => (isset($sub_entry['completed']) && $sub_entry['completed'] === true), + 'STAGE_NAME' => $name, + )); + } else { + $this->template->assign_block_vars('l_block1', array( + 'L_TITLE' => $this->language->lang($sub_entry['label']), + 'S_SELECTED' => (isset($sub_entry['route']) && $sub_entry['route'] === $this->request->get('_route')), + 'U_TITLE' => $this->route($sub_entry['route']), + )); + } + } + } + } + } + + /** + * Render language select form + * + * @param string $selected_language + */ + protected function render_language_select($selected_language = null) { $langs = $this->lang_helper->get_available_languages(); - // @todo Implement language change option + foreach ($langs as $lang) + { + $this->template->assign_block_vars('language_select_item', array( + 'VALUE' => $lang['iso'], + 'NAME' => $lang['local_name'], + 'SELECTED' => ($lang['iso'] === $selected_language), + )); + } } /** diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php index b3103c8284..da806948fb 100644 --- a/phpBB/phpbb/install/controller/install.php +++ b/phpBB/phpbb/install/controller/install.php @@ -189,7 +189,7 @@ class install 'TITLE' => $this->language->lang('INSTALL_INTRO'), 'CONTENT' => $this->language->lang('INSTALL_INTRO_BODY'), )); - return $this->controller_helper->render('installer_install.html', 'INSTALL'); + return $this->controller_helper->render('installer_install.html', 'INSTALL', true); } // @todo: implement no js controller logic diff --git a/phpBB/phpbb/install/controller/installer_index.php b/phpBB/phpbb/install/controller/installer_index.php index 3d5224f1be..0a1855f4e5 100644 --- a/phpBB/phpbb/install/controller/installer_index.php +++ b/phpBB/phpbb/install/controller/installer_index.php @@ -74,6 +74,6 @@ class installer_index 'BODY' => $body, )); - return $this->helper->render('install_main.html', $title); + return $this->helper->render('install_main.html', $title, true); } } diff --git a/phpBB/phpbb/language/language.php b/phpBB/phpbb/language/language.php index b2b9f5ce12..44131e3da3 100644 --- a/phpBB/phpbb/language/language.php +++ b/phpBB/phpbb/language/language.php @@ -109,25 +109,27 @@ class language /** * Function to set user's language to display. * - * @param string $user_lang_iso ISO code of the User's language + * @param string $user_lang_iso ISO code of the User's language + * @param bool $reload Whether or not to reload language files */ - public function set_user_language($user_lang_iso) + public function set_user_language($user_lang_iso, $reload = false) { $this->user_language = $user_lang_iso; - $this->set_fallback_array(); + $this->set_fallback_array($reload); } /** * Function to set the board's default language to display. * * @param string $default_lang_iso ISO code of the board's default language + * @param bool $reload Whether or not to reload language files */ - public function set_default_language($default_lang_iso) + public function set_default_language($default_lang_iso, $reload = false) { $this->default_language = $default_lang_iso; - $this->set_fallback_array(); + $this->set_fallback_array($reload); } /** @@ -508,9 +510,11 @@ class language /** * Returns language fallback data * + * @param bool $reload Whether or not to reload language files + * * @return array */ - protected function set_fallback_array() + protected function set_fallback_array($reload = false) { $fallback_array = array(); @@ -527,6 +531,11 @@ class language $fallback_array[] = self::FALLBACK_LANGUAGE; $this->language_fallback = $fallback_array; + + if ($reload) + { + $this->reload_language_files(); + } } /** @@ -563,4 +572,31 @@ class language $this->loader->load_extension($extension_name, $component, $this->language_fallback, $this->lang); $this->loaded_language_sets['ext'][$extension_name][$component] = true; } + + /** + * Reload language files + */ + protected function reload_language_files() + { + $loaded_files = $this->loaded_language_sets; + $this->loaded_language_sets = array( + 'core' => array(), + 'ext' => array(), + ); + + // Reload core files + foreach ($loaded_files['core'] as $component => $value) + { + $this->load_core_file($component); + } + + // Reload extension files + foreach ($loaded_files['ext'] as $ext_name => $ext_info) + { + foreach ($ext_info as $ext_component => $value) + { + $this->load_extension($ext_name, $ext_component); + } + } + } } From 0c49b88dde77894a91145314d2d3bf4388082075 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 22 Jul 2015 04:01:52 +0200 Subject: [PATCH 0530/1676] [ticket/13740] Fix CS PHPBB3-13740 --- phpBB/phpbb/install/controller/helper.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index 5fd0abf9c7..f3400e6ef0 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -233,8 +233,6 @@ class helper $this->render_navigation(); } - - /** * Render navigation */ @@ -247,25 +245,31 @@ class helper $active_main_menu = $this->get_active_main_menu($nav_array); // Pass navigation to template - foreach ($nav_array as $key => $entry) { + foreach ($nav_array as $key => $entry) + { $this->template->assign_block_vars('t_block1', array( 'L_TITLE' => $this->language->lang($entry['label']), 'S_SELECTED' => ($active_main_menu === $key), 'U_TITLE' => $this->route($entry['route']), )); - if (is_array($entry[0]) && $active_main_menu === $key) { + if (is_array($entry[0]) && $active_main_menu === $key) + { $entry[0] = $this->sort_navigation_level($entry[0]); - foreach ($entry[0] as $name => $sub_entry) { - if (isset($sub_entry['stage']) && $sub_entry['stage'] === true) { + foreach ($entry[0] as $name => $sub_entry) + { + if (isset($sub_entry['stage']) && $sub_entry['stage'] === true) + { $this->template->assign_block_vars('l_block2', array( 'L_TITLE' => $this->language->lang($sub_entry['label']), 'S_SELECTED' => (isset($sub_entry['selected']) && $sub_entry['selected'] === true), 'S_COMPLETE' => (isset($sub_entry['completed']) && $sub_entry['completed'] === true), 'STAGE_NAME' => $name, )); - } else { + } + else + { $this->template->assign_block_vars('l_block1', array( 'L_TITLE' => $this->language->lang($sub_entry['label']), 'S_SELECTED' => (isset($sub_entry['route']) && $sub_entry['route'] === $this->request->get('_route')), From 3356130ce2adf82248cf64fcaa81a47713ce7987 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 22 Jul 2015 12:43:17 +0200 Subject: [PATCH 0531/1676] [ticket/13740] Separate new installer style templates PHPBB3-13740 --- phpBB/adm/style/install_header.html | 10 +--- phpBB/adm/style/installer_footer.html | 21 +++++++ phpBB/adm/style/installer_header.html | 57 +++++++++++++++++++ phpBB/adm/style/installer_install.html | 4 +- phpBB/adm/style/installer_main.html | 6 ++ .../install/controller/installer_index.php | 2 +- 6 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 phpBB/adm/style/installer_footer.html create mode 100644 phpBB/adm/style/installer_header.html create mode 100644 phpBB/adm/style/installer_main.html diff --git a/phpBB/adm/style/install_header.html b/phpBB/adm/style/install_header.html index 9d0f9a56de..8debfc69c0 100644 --- a/phpBB/adm/style/install_header.html +++ b/phpBB/adm/style/install_header.html @@ -15,14 +15,10 @@

            {L_INSTALL_PANEL}

            {L_SKIP}

            -
            +
            - + {S_LANG_SELECT}
            @@ -47,7 +43,7 @@ id="activemenu">{l_block1.L_TITLE} - id="activemenu"> class="completed" id="installer-stage-{l_block2.STAGE_NAME}">{l_block2.L_TITLE} + id="activemenu"> class="completed">{l_block2.L_TITLE}
          diff --git a/phpBB/adm/style/installer_footer.html b/phpBB/adm/style/installer_footer.html new file mode 100644 index 0000000000..2c70d4d5d3 --- /dev/null +++ b/phpBB/adm/style/installer_footer.html @@ -0,0 +1,21 @@ +
        + + + + + + + + + + + + +{$SCRIPTS} + + + diff --git a/phpBB/adm/style/installer_header.html b/phpBB/adm/style/installer_header.html new file mode 100644 index 0000000000..ada6553aec --- /dev/null +++ b/phpBB/adm/style/installer_header.html @@ -0,0 +1,57 @@ + + + + + + {META} + {PAGE_TITLE} + + + + + +
        + + +
        +
        + +
        + +
        +
        + + +
        +
        diff --git a/phpBB/adm/style/installer_install.html b/phpBB/adm/style/installer_install.html index 7700c79036..175c6eac67 100644 --- a/phpBB/adm/style/installer_install.html +++ b/phpBB/adm/style/installer_install.html @@ -1,4 +1,4 @@ - +

        {TITLE}

        {CONTENT}

        @@ -10,4 +10,4 @@ - + diff --git a/phpBB/adm/style/installer_main.html b/phpBB/adm/style/installer_main.html new file mode 100644 index 0000000000..ed65da8a68 --- /dev/null +++ b/phpBB/adm/style/installer_main.html @@ -0,0 +1,6 @@ + + +

        {TITLE}

        +

        {BODY}

        + + diff --git a/phpBB/phpbb/install/controller/installer_index.php b/phpBB/phpbb/install/controller/installer_index.php index 0a1855f4e5..8e1874984b 100644 --- a/phpBB/phpbb/install/controller/installer_index.php +++ b/phpBB/phpbb/install/controller/installer_index.php @@ -74,6 +74,6 @@ class installer_index 'BODY' => $body, )); - return $this->helper->render('install_main.html', $title, true); + return $this->helper->render('installer_main.html', $title, true); } } From 98d9d92aa7794316239fbda2a15a91618aef0879 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 23 Jul 2015 04:27:31 +0200 Subject: [PATCH 0532/1676] [ticket/13740] Secure installer config against corrupted config data PHPBB3-13740 --- phpBB/phpbb/install/helper/config.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php index 457b64b301..38376da82a 100644 --- a/phpBB/phpbb/install/helper/config.php +++ b/phpBB/phpbb/install/helper/config.php @@ -224,11 +224,19 @@ class config $file_content = @file_get_contents($this->install_config_file); $serialized_data = trim(substr($file_content, 8)); - $unserialized_data = unserialize($serialized_data); - $this->installer_config = $unserialized_data['installer_config']; - $this->progress_data = $unserialized_data['progress_data']; - $this->navigation_data = $unserialized_data['navigation_data']; + $this->installer_config = array(); + $this->progress_data = array(); + $this->navigation_data = array(); + + if (!empty($serialized_data)) + { + $unserialized_data = unserialize($serialized_data); + + $this->installer_config = (is_array($unserialized_data['installer_config'])) ? $unserialized_data['installer_config'] : array(); + $this->progress_data = (is_array($unserialized_data['progress_data'])) ? $unserialized_data['progress_data'] : array(); + $this->navigation_data = (is_array($unserialized_data['navigation_data'])) ? $unserialized_data['navigation_data'] : array(); + } } /** From dd31020fb3dd4ab96b48dd1854f73190900319b1 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 23 Jul 2015 16:43:20 +0200 Subject: [PATCH 0533/1676] [ticket/13740] Enhance server output buffer bypass PHPBB3-13740 --- phpBB/phpbb/install/controller/install.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php index da806948fb..469e2608a4 100644 --- a/phpBB/phpbb/install/controller/install.php +++ b/phpBB/phpbb/install/controller/install.php @@ -167,6 +167,9 @@ class install $installer->run(); }); + // Try to bypass any server output buffers + $response->headers->set('X-Accel-Buffering', 'no'); + return $response; } else From fbd5929606169d3f780f0a59760c171b20bd906d Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 23 Jul 2015 20:50:33 +0200 Subject: [PATCH 0534/1676] [ticket/13740] Login admin when install finished PHPBB3-13740 --- phpBB/assets/javascript/installer.js | 18 ++++++++ .../install/helper/container_factory.php | 5 +++ .../helper/iohandler/ajax_iohandler.php | 23 +++++++++++ .../helper/iohandler/cli_iohandler.php | 7 ++++ .../helper/iohandler/iohandler_interface.php | 8 ++++ .../install_finish/task/notify_user.php | 41 +++++++++++++++---- phpBB/phpbb/session.php | 6 +++ 7 files changed, 101 insertions(+), 7 deletions(-) diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index 91e8eb4797..4640d03de7 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -165,6 +165,19 @@ } } + // Set cookies + function setCookies(cookies) { + var cookie; + + for (var i = 0; i < cookies.length; i++) { + // Set cookie name and value + cookie = encodeURIComponent(cookies[i].name) + '=' + encodeURIComponent(cookies[i].value); + // Set path + cookie += '; path=/'; + document.cookie = cookie; + } + } + /** * Parse messages from the response object * @@ -199,6 +212,10 @@ if (responseObject.hasOwnProperty('nav')) { updateNavbarStatus(responseObject.nav); } + + if (responseObject.hasOwnProperty('cookies')) { + setCookies(responseObject.cookies); + } } /** @@ -321,6 +338,7 @@ $contentWrapper.append($spinner); } + // Submits a form function submitForm($form, $submitBtn) { $form.css('display', 'none'); diff --git a/phpBB/phpbb/install/helper/container_factory.php b/phpBB/phpbb/install/helper/container_factory.php index eb44b470b7..e09e43be34 100644 --- a/phpBB/phpbb/install/helper/container_factory.php +++ b/phpBB/phpbb/install/helper/container_factory.php @@ -13,6 +13,7 @@ namespace phpbb\install\helper; +use phpbb\cache\driver\dummy; use phpbb\install\exception\cannot_build_container_exception; class container_factory @@ -152,6 +153,10 @@ class container_factory // this container $this->container->register('request')->setSynthetic(true); $this->container->set('request', $this->request); + + // Replace cache service, as config gets cached, and we don't want that + $this->container->register('cache.driver')->setSynthetic(true); + $this->container->set('cache.driver', new dummy()); $this->container->compile(); // Restore super globals to previous state diff --git a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php index ce1112c7a1..fa628f3365 100644 --- a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php @@ -43,6 +43,11 @@ class ajax_iohandler extends iohandler_base */ protected $nav_data; + /** + * @var array + */ + protected $cookies; + /** * Constructor * @@ -55,6 +60,7 @@ class ajax_iohandler extends iohandler_base $this->template = $template; $this->form = ''; $this->nav_data = array(); + $this->cookies = array(); parent::__construct(); } @@ -214,6 +220,12 @@ class ajax_iohandler extends iohandler_base $this->request_client_refresh = false; } + if (!empty($this->cookies)) + { + $json_array['cookies'] = $this->cookies; + $this->cookies = array(); + } + return $json_array; } @@ -252,6 +264,17 @@ class ajax_iohandler extends iohandler_base $this->send_response(); } + /** + * {@inheritdoc} + */ + public function set_cookie($cookie_name, $cookie_value) + { + $this->cookies[] = array( + 'name' => $cookie_name, + 'value' => $cookie_value + ); + } + /** * Callback function for language replacing * diff --git a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php index bf68f363c3..c5b2bb06bc 100644 --- a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php @@ -255,4 +255,11 @@ class cli_iohandler extends iohandler_base public function set_finished_stage_menu($menu_path) { } + + /** + * {@inheritdoc} + */ + public function set_cookie($cookie_name, $cookie_value) + { + } } diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php index 44b409bb0a..5f5f8499d6 100644 --- a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php +++ b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php @@ -163,4 +163,12 @@ interface iohandler_interface * @param string $message_lang_key Language key for the message */ public function finish_progress($message_lang_key); + + /** + * Sends and sets cookies + * + * @param string $cookie_name Name of the cookie to set + * @param string $cookie_value Value of the cookie to set + */ + public function set_cookie($cookie_name, $cookie_value); } diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php index baffaf2228..a433d342d0 100644 --- a/phpBB/phpbb/install/module/install_finish/task/notify_user.php +++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php @@ -12,6 +12,7 @@ */ namespace phpbb\install\module\install_finish\task; +use phpbb\config\db; /** * Logs installation and sends an email to the admin @@ -73,11 +74,17 @@ class notify_user extends \phpbb\install\task_base $this->iohandler = $iohandler; $this->auth = $container->get('auth'); - $this->config = $container->get('config'); $this->log = $container->get('log'); $this->user = $container->get('user'); $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; + + // We need to reload config for cases when it doesn't have all values + $this->config = new db( + $container->get('dbal.conn'), + $container->get('cache.driver'), + $container->get_parameter('tables.config') + ); } /** @@ -85,11 +92,8 @@ class notify_user extends \phpbb\install\task_base */ public function run() { - // @todo Login user after installation has been finished - //$this->user->setup('common'); - - //$this->user->session_begin(); - //$this->auth->login($this->install_config->get('admin_name'), $this->install_config->get('admin_pass1'), false, true, true); + $this->user->session_begin(); + $this->user->setup('common'); if ($this->config['email_enable']) { @@ -106,8 +110,31 @@ class notify_user extends \phpbb\install\task_base $messenger->send(NOTIFY_EMAIL); } - $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_INSTALL_INSTALLED', false, array($this->config['version'])); + // Login admin + // Ugly but works + $this->auth->login( + $this->install_config->get('admin_name'), + $this->install_config->get('admin_passwd'), + false, + true, + true + ); + $this->iohandler->set_cookie($this->config['cookie_name'] . '_sid', $this->user->session_id); + $this->iohandler->set_cookie($this->config['cookie_name'] . '_u', $this->user->cookie_data['u']); + $this->iohandler->set_cookie($this->config['cookie_name'] . '_k', $this->user->cookie_data['k']); + + // Create log + $this->log->add( + 'admin', + $this->user->data['user_id'], + $this->user->ip, + 'LOG_INSTALL_INSTALLED', + false, + array($this->config['version']) + ); + + // Remove install_lock @unlink($this->phpbb_root_path . 'cache/install_lock'); } diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 6154f384f3..91b657262c 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1076,6 +1076,12 @@ class session { global $config; + // If headers are already set, we just return + if (headers_sent()) + { + return; + } + $name_data = rawurlencode($config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata); $expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime); $domain = (!$config['cookie_domain'] || $config['cookie_domain'] == '127.0.0.1' || strpos($config['cookie_domain'], '.') === false) ? '' : '; domain=' . $config['cookie_domain']; From e08f1341127792e378580a10bbb0bdeafe93ff8d Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 23 Jul 2015 22:55:31 +0200 Subject: [PATCH 0535/1676] [ticket/13740] Fix is_phpbb_installed() method PHPBB3-13740 --- phpBB/phpbb/install/controller/install.php | 2 +- phpBB/phpbb/install/helper/install_helper.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php index 469e2608a4..904f5920c2 100644 --- a/phpBB/phpbb/install/controller/install.php +++ b/phpBB/phpbb/install/controller/install.php @@ -111,7 +111,7 @@ class install { if ($this->install_helper->is_phpbb_installed()) { - throw new http_exception(404, 'PAGE_NOT_FOUND'); + die ('phpBB is already installed'); } $this->template->assign_vars(array( diff --git a/phpBB/phpbb/install/helper/install_helper.php b/phpBB/phpbb/install/helper/install_helper.php index c1506de5bf..ffe36cd645 100644 --- a/phpBB/phpbb/install/helper/install_helper.php +++ b/phpBB/phpbb/install/helper/install_helper.php @@ -47,14 +47,14 @@ class install_helper */ public function is_phpbb_installed() { - $config_path = $this->phpbb_root_path . 'config' . $this->php_ext; + $config_path = $this->phpbb_root_path . 'config.' . $this->php_ext; $install_lock_path = $this->phpbb_root_path . 'cache/install_lock'; - if (file_exists($config_path) && !file_exists($install_lock_path)) + if (file_exists($config_path) && !file_exists($install_lock_path) && filesize($config_path)) { - include_once $config_path; + return true; } - return defined('PHPBB_INSTALLED'); + return false; } } From 115029b6012d4adf11f773a31463c8f8daf9529e Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 23 Jul 2015 23:23:06 +0200 Subject: [PATCH 0536/1676] [ticket/13740] Fix $script_path in obtain_data PHPBB3-13740 --- .../install/module/obtain_data/task/obtain_server_data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php index 2d1e37b10e..654b5534a9 100644 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php @@ -73,7 +73,7 @@ class obtain_server_data extends \phpbb\install\task_base implements \phpbb\inst } $script_path = str_replace(array('\\', '//'), '/', $script_path); - $script_path = trim(dirname(dirname($script_path))); + $script_path = trim(dirname(dirname(dirname($script_path)))); // Because we are in install/app.php/route_name // Server data $cookie_secure = $this->io_handler->get_input('cookie_secure', $cookie_secure); From 3840882b93e96f8f510d4086d650bb9df55873ca Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 23 Jul 2015 23:35:20 +0200 Subject: [PATCH 0537/1676] [ticket/13740] Add success message when install finished PHPBB3-13740 --- phpBB/assets/javascript/installer.js | 10 +++++++++- phpBB/language/en/install_new.php | 2 ++ phpBB/phpbb/install/installer.php | 29 ++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index 4640d03de7..da30f136bd 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -52,7 +52,7 @@ if (messages[i].hasOwnProperty('description')) { $description = $(document.createElement('p')); - $description.text(messages[i].description); + $description.html(messages[i].description); $msgElement.append($description); } @@ -69,6 +69,10 @@ $msgElement.addClass('log'); $logContainer.append($msgElement); break; + case 'success': + $msgElement.addClass('successbox'); + $errorContainer.prepend($msgElement); + break; } } } @@ -201,6 +205,10 @@ addMessage('log', responseObject.logs); } + if (responseObject.hasOwnProperty('success')) { + addMessage('success', responseObject.success); + } + if (responseObject.hasOwnProperty('form')) { addForm(responseObject.form); } diff --git a/phpBB/language/en/install_new.php b/phpBB/language/en/install_new.php index 607565fcd0..923601b110 100644 --- a/phpBB/language/en/install_new.php +++ b/phpBB/language/en/install_new.php @@ -80,6 +80,8 @@ $lang = array_merge($lang, array(

      Only those databases supported on your server will be displayed.', + + 'ACP_LINK' => 'Take me to the ACP', )); // Requirements translation diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index 0e19129247..cb4ddb8783 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -18,6 +18,7 @@ use phpbb\install\exception\installer_config_not_writable_exception; use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\exception\user_interaction_required_exception; use phpbb\install\helper\config; +use phpbb\install\helper\iohandler\cli_iohandler; use phpbb\install\helper\iohandler\iohandler_interface; class installer @@ -171,6 +172,34 @@ class installer // Installation finished $install_finished = true; + + if ($this->iohandler instanceof cli_iohandler) + { + $this->iohandler->add_success_message('INSTALLER_FINISHED'); + } + else + { + global $SID; + + // Construct ACP url + $acp_url = $protocol = $this->install_config->get('server_protocol'); + $acp_url .= $this->install_config->get('server_name'); + $port = $this->install_config->get('server_port'); + + if (!((strpos($protocol, 'https:') === 0 && $port === 443) + || (strpos($protocol, 'http:') === 0 && $port === 80))) + { + $acp_url .= ':' . $port; + } + + $acp_url .= $this->install_config->get('script_path'); + $acp_url .= '/adm/index.php' . $SID; + + $this->iohandler->add_success_message('INSTALLER_FINISHED', array( + 'ACP_LINK', + $acp_url, + )); + } } catch (user_interaction_required_exception $e) { From 27d2d58e0529172de7d0403292bc10842a45ef98 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Thu, 23 Jul 2015 23:46:36 +0200 Subject: [PATCH 0538/1676] [ticket/13740] Use tabs instead of spaces in JS file PHPBB3-13740 --- phpBB/assets/javascript/installer.js | 660 +++++++++++++-------------- 1 file changed, 330 insertions(+), 330 deletions(-) diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index da30f136bd..4e44e2755c 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -3,398 +3,398 @@ */ (function($) { // Avoid conflicts with other libraries - 'use strict'; + 'use strict'; - // Installer variables - var pollTimer = null; - var nextReadPosition = 0; - var progressBarTriggered = false; - var progressTimer = null; - var currentProgress = 0; + // Installer variables + var pollTimer = null; + var nextReadPosition = 0; + var progressBarTriggered = false; + var progressTimer = null; + var currentProgress = 0; - // Template related variables - var $contentWrapper = $('.install-body').find('.main'); + // Template related variables + var $contentWrapper = $('.install-body').find('.main'); - // Intercept form submits - interceptFormSubmit($('#install_install')); + // Intercept form submits + interceptFormSubmit($('#install_install')); - /** - * Creates an XHR object - * - * jQuery cannot be used as the response is streamed, and - * as of now, jQuery does not provide access to the response until - * the connection is not closed. - * - * @return XMLHttpRequest - */ - function createXhrObject() { - return new XMLHttpRequest(); - } + /** + * Creates an XHR object + * + * jQuery cannot be used as the response is streamed, and + * as of now, jQuery does not provide access to the response until + * the connection is not closed. + * + * @return XMLHttpRequest + */ + function createXhrObject() { + return new XMLHttpRequest(); + } - /** - * Displays error, warning and log messages - * - * @param type - * @param messages - */ - function addMessage(type, messages) { - // Get message containers - var $errorContainer = $('#error-container'); - var $warningContainer = $('#warning-container'); - var $logContainer = $('#log-container'); + /** + * Displays error, warning and log messages + * + * @param type + * @param messages + */ + function addMessage(type, messages) { + // Get message containers + var $errorContainer = $('#error-container'); + var $warningContainer = $('#warning-container'); + var $logContainer = $('#log-container'); - var $title, $description, $msgElement, arraySize = messages.length; - for (var i = 0; i < arraySize; i++) { - $msgElement = $('

      '); - $title = $(document.createElement('strong')); - $title.text(messages[i].title); - $msgElement.append($title); + var $title, $description, $msgElement, arraySize = messages.length; + for (var i = 0; i < arraySize; i++) { + $msgElement = $('
      '); + $title = $(document.createElement('strong')); + $title.text(messages[i].title); + $msgElement.append($title); - if (messages[i].hasOwnProperty('description')) { - $description = $(document.createElement('p')); - $description.html(messages[i].description); - $msgElement.append($description); - } + if (messages[i].hasOwnProperty('description')) { + $description = $(document.createElement('p')); + $description.html(messages[i].description); + $msgElement.append($description); + } - switch (type) { - case 'error': - $msgElement.addClass('errorbox'); - $errorContainer.append($msgElement); - break; - case 'warning': - $msgElement.addClass('warningbox'); - $warningContainer.append($msgElement); - break; - case 'log': - $msgElement.addClass('log'); - $logContainer.append($msgElement); - break; - case 'success': - $msgElement.addClass('successbox'); - $errorContainer.prepend($msgElement); - break; - } - } - } + switch (type) { + case 'error': + $msgElement.addClass('errorbox'); + $errorContainer.append($msgElement); + break; + case 'warning': + $msgElement.addClass('warningbox'); + $warningContainer.append($msgElement); + break; + case 'log': + $msgElement.addClass('log'); + $logContainer.append($msgElement); + break; + case 'success': + $msgElement.addClass('successbox'); + $errorContainer.prepend($msgElement); + break; + } + } + } - /** - * Displays a form from the response - * - * @param formHtml - */ - function addForm(formHtml) { - var $formContainer = $('#content-container'); - $formContainer.html(formHtml); - var $form = $('#install_install'); - interceptFormSubmit($form); - } + /** + * Displays a form from the response + * + * @param formHtml + */ + function addForm(formHtml) { + var $formContainer = $('#content-container'); + $formContainer.html(formHtml); + var $form = $('#install_install'); + interceptFormSubmit($form); + } - /** - * Handles navigation status updates - * - * @param navObj - */ - function updateNavbarStatus(navObj) { - var navID, $stage, $stageListItem, $active; - $active = $('#activemenu'); + /** + * Handles navigation status updates + * + * @param navObj + */ + function updateNavbarStatus(navObj) { + var navID, $stage, $stageListItem, $active; + $active = $('#activemenu'); - if (navObj.hasOwnProperty('finished')) { - // This should be an Array - var navItems = navObj.finished; + if (navObj.hasOwnProperty('finished')) { + // This should be an Array + var navItems = navObj.finished; - for (var i = 0; i < navItems.length; i++) { - navID = 'installer-stage-' + navItems[i]; - $stage = $('#' + navID); - $stageListItem = $stage.parent(); + for (var i = 0; i < navItems.length; i++) { + navID = 'installer-stage-' + navItems[i]; + $stage = $('#' + navID); + $stageListItem = $stage.parent(); - if ($active.length && $active.is($stageListItem)) { - $active.removeAttr('id'); - } + if ($active.length && $active.is($stageListItem)) { + $active.removeAttr('id'); + } - $stage.addClass('completed'); - } - } + $stage.addClass('completed'); + } + } - if (navObj.hasOwnProperty('active')) { - navID = 'installer-stage-' + navObj.active; - $stage = $('#' + navID); - $stageListItem = $stage.parent(); + if (navObj.hasOwnProperty('active')) { + navID = 'installer-stage-' + navObj.active; + $stage = $('#' + navID); + $stageListItem = $stage.parent(); - if ($active.length && !$active.is($stageListItem)) { - $active.removeAttr('id'); - } + if ($active.length && !$active.is($stageListItem)) { + $active.removeAttr('id'); + } - $stageListItem.attr('id', 'activemenu'); - } - } + $stageListItem.attr('id', 'activemenu'); + } + } - /** - * Renders progress bar - * - * @param progressObject - */ - function setProgress(progressObject) { - var $statusText, $progressBar, $progressText, $progressFiller; + /** + * Renders progress bar + * + * @param progressObject + */ + function setProgress(progressObject) { + var $statusText, $progressBar, $progressText, $progressFiller; - if (progressObject.task_name.length) { - if (!progressBarTriggered) { - // Create progress bar - var $contentContainer = $('#content-container'); + if (progressObject.task_name.length) { + if (!progressBarTriggered) { + // Create progress bar + var $contentContainer = $('#content-container'); - // Create progress bar elements - $progressBar = $('
      '); - $progressBar.attr('id', 'progress-bar'); - $progressText = $('

      '); - $progressText.attr('id', 'progress-bar-text'); - $progressFiller = $(''); - $progressFiller.attr('id', 'progress-bar-filler'); + // Create progress bar elements + $progressBar = $('

      '); + $progressBar.attr('id', 'progress-bar'); + $progressText = $('

      '); + $progressText.attr('id', 'progress-bar-text'); + $progressFiller = $(''); + $progressFiller.attr('id', 'progress-bar-filler'); - $statusText = $('

      '); - $statusText.attr('id', 'progress-status-text'); + $statusText = $('

      '); + $statusText.attr('id', 'progress-status-text'); - $progressBar.append($progressFiller); - $progressBar.append($progressText); + $progressBar.append($progressFiller); + $progressBar.append($progressText); - $contentContainer.append($statusText); - $contentContainer.append($progressBar); + $contentContainer.append($statusText); + $contentContainer.append($progressBar); - progressBarTriggered = true; - } else { - $statusText = $('#progress-status-text'); - } + progressBarTriggered = true; + } else { + $statusText = $('#progress-status-text'); + } - // Update progress bar - $statusText.text(progressObject.task_name + '…'); - incrementProgressBar(Math.round(progressObject.task_num / progressObject.task_count * 100)); - } - } + // Update progress bar + $statusText.text(progressObject.task_name + '…'); + incrementProgressBar(Math.round(progressObject.task_num / progressObject.task_count * 100)); + } + } - // Set cookies - function setCookies(cookies) { - var cookie; + // Set cookies + function setCookies(cookies) { + var cookie; - for (var i = 0; i < cookies.length; i++) { - // Set cookie name and value - cookie = encodeURIComponent(cookies[i].name) + '=' + encodeURIComponent(cookies[i].value); - // Set path - cookie += '; path=/'; - document.cookie = cookie; - } - } + for (var i = 0; i < cookies.length; i++) { + // Set cookie name and value + cookie = encodeURIComponent(cookies[i].name) + '=' + encodeURIComponent(cookies[i].value); + // Set path + cookie += '; path=/'; + document.cookie = cookie; + } + } - /** - * Parse messages from the response object - * - * @param messageJSON - */ - function parseMessage(messageJSON) { - $('#loading_indicator').css('display', 'none'); + /** + * Parse messages from the response object + * + * @param messageJSON + */ + function parseMessage(messageJSON) { + $('#loading_indicator').css('display', 'none'); - var responseObject = JSON.parse(messageJSON); + var responseObject = JSON.parse(messageJSON); - // Parse object - if (responseObject.hasOwnProperty('errors')) { - addMessage('error', responseObject.errors); - } + // Parse object + if (responseObject.hasOwnProperty('errors')) { + addMessage('error', responseObject.errors); + } - if (responseObject.hasOwnProperty('warnings')) { - addMessage('warning', responseObject.warnings); - } + if (responseObject.hasOwnProperty('warnings')) { + addMessage('warning', responseObject.warnings); + } - if (responseObject.hasOwnProperty('logs')) { - addMessage('log', responseObject.logs); - } + if (responseObject.hasOwnProperty('logs')) { + addMessage('log', responseObject.logs); + } - if (responseObject.hasOwnProperty('success')) { - addMessage('success', responseObject.success); - } + if (responseObject.hasOwnProperty('success')) { + addMessage('success', responseObject.success); + } - if (responseObject.hasOwnProperty('form')) { - addForm(responseObject.form); - } + if (responseObject.hasOwnProperty('form')) { + addForm(responseObject.form); + } - if (responseObject.hasOwnProperty('progress')) { - setProgress(responseObject.progress); - } + if (responseObject.hasOwnProperty('progress')) { + setProgress(responseObject.progress); + } - if (responseObject.hasOwnProperty('nav')) { - updateNavbarStatus(responseObject.nav); - } + if (responseObject.hasOwnProperty('nav')) { + updateNavbarStatus(responseObject.nav); + } - if (responseObject.hasOwnProperty('cookies')) { - setCookies(responseObject.cookies); - } - } + if (responseObject.hasOwnProperty('cookies')) { + setCookies(responseObject.cookies); + } + } - /** - * Process updates in streamed response - * - * @param xhReq XHR object - */ - function pollContent(xhReq) { - var messages = xhReq.responseText; - var msgSeparator = '}\n\n'; - var unprocessed, messageEndIndex, endOfMessageIndex, message; + /** + * Process updates in streamed response + * + * @param xhReq XHR object + */ + function pollContent(xhReq) { + var messages = xhReq.responseText; + var msgSeparator = '}\n\n'; + var unprocessed, messageEndIndex, endOfMessageIndex, message; - do { - unprocessed = messages.substring(nextReadPosition); - messageEndIndex = unprocessed.indexOf(msgSeparator); + do { + unprocessed = messages.substring(nextReadPosition); + messageEndIndex = unprocessed.indexOf(msgSeparator); - if (messageEndIndex !== -1) { - endOfMessageIndex = messageEndIndex + msgSeparator.length; - message = unprocessed.substring(0, endOfMessageIndex); - parseMessage(message); - nextReadPosition += endOfMessageIndex; - } - } while (messageEndIndex !== -1); + if (messageEndIndex !== -1) { + endOfMessageIndex = messageEndIndex + msgSeparator.length; + message = unprocessed.substring(0, endOfMessageIndex); + parseMessage(message); + nextReadPosition += endOfMessageIndex; + } + } while (messageEndIndex !== -1); - if (xhReq.readyState === 4) { - $('#loading_indicator').css('display', 'none'); - resetPolling(); - } - } + if (xhReq.readyState === 4) { + $('#loading_indicator').css('display', 'none'); + resetPolling(); + } + } - /** - * Animates the progress bar - * - * @param $progressText - * @param $progressFiller - * @param progressLimit - */ - function incrementFiller($progressText, $progressFiller, progressLimit) { - if (currentProgress >= progressLimit || currentProgress >= 100) { - clearInterval(progressTimer); - return; - } + /** + * Animates the progress bar + * + * @param $progressText + * @param $progressFiller + * @param progressLimit + */ + function incrementFiller($progressText, $progressFiller, progressLimit) { + if (currentProgress >= progressLimit || currentProgress >= 100) { + clearInterval(progressTimer); + return; + } - currentProgress++; - $progressText.text(currentProgress + '%'); - $progressFiller.css('width', currentProgress + '%'); - } + currentProgress++; + $progressText.text(currentProgress + '%'); + $progressFiller.css('width', currentProgress + '%'); + } - /** - * Wrapper function for progress bar rendering and animating - * - * @param progressLimit - */ - function incrementProgressBar(progressLimit) { - var $progressFiller = $('#progress-bar-filler'); - var $progressText = $('#progress-bar-text'); - var progressStart = $progressFiller.width() / $progressFiller.offsetParent().width() * 100; - currentProgress = Math.floor(progressStart); + /** + * Wrapper function for progress bar rendering and animating + * + * @param progressLimit + */ + function incrementProgressBar(progressLimit) { + var $progressFiller = $('#progress-bar-filler'); + var $progressText = $('#progress-bar-text'); + var progressStart = $progressFiller.width() / $progressFiller.offsetParent().width() * 100; + currentProgress = Math.floor(progressStart); - clearInterval(progressTimer); - progressTimer = setInterval(function() { - incrementFiller($progressText, $progressFiller, progressLimit); - }, 10); - } + clearInterval(progressTimer); + progressTimer = setInterval(function() { + incrementFiller($progressText, $progressFiller, progressLimit); + }, 10); + } - /** - * Resets the polling timer - */ - function resetPolling() { - clearInterval(pollTimer); - nextReadPosition = 0; - } + /** + * Resets the polling timer + */ + function resetPolling() { + clearInterval(pollTimer); + nextReadPosition = 0; + } - /** - * Sets up timer for processing the streamed HTTP response - * - * @param xhReq - */ - function startPolling(xhReq) { - resetPolling(); - pollTimer = setInterval(function () { - pollContent(xhReq); - }, 250); - } + /** + * Sets up timer for processing the streamed HTTP response + * + * @param xhReq + */ + function startPolling(xhReq) { + resetPolling(); + pollTimer = setInterval(function () { + pollContent(xhReq); + }, 250); + } - /** - * Renders the AJAX UI layout - */ - function setupAjaxLayout() { - // Clear content - $contentWrapper.html(''); + /** + * Renders the AJAX UI layout + */ + function setupAjaxLayout() { + // Clear content + $contentWrapper.html(''); - var $header = $('

      '); - $header.attr('id', 'header-container'); - $contentWrapper.append($header); + var $header = $('
      '); + $header.attr('id', 'header-container'); + $contentWrapper.append($header); - var $description = $('
      '); - $description.attr('id', 'description-container'); - $contentWrapper.append($description); + var $description = $('
      '); + $description.attr('id', 'description-container'); + $contentWrapper.append($description); - var $errorContainer = $('
      '); - $errorContainer.attr('id', 'error-container'); - $contentWrapper.append($errorContainer); + var $errorContainer = $('
      '); + $errorContainer.attr('id', 'error-container'); + $contentWrapper.append($errorContainer); - var $warningContainer = $('
      '); - $warningContainer.attr('id', 'warning-container'); - $contentWrapper.append($warningContainer); + var $warningContainer = $('
      '); + $warningContainer.attr('id', 'warning-container'); + $contentWrapper.append($warningContainer); - var $installerContentWrapper = $('
      '); - $installerContentWrapper.attr('id', 'content-container'); - $contentWrapper.append($installerContentWrapper); + var $installerContentWrapper = $('
      '); + $installerContentWrapper.attr('id', 'content-container'); + $contentWrapper.append($installerContentWrapper); - var $logContainer = $('
      '); - $logContainer.attr('id', 'log-container'); - $contentWrapper.append($logContainer); + var $logContainer = $('
      '); + $logContainer.attr('id', 'log-container'); + $contentWrapper.append($logContainer); - var $spinner = $('
      '); - $spinner.attr('id', 'loading_indicator'); - $spinner.html(' '); - $contentWrapper.append($spinner); - } + var $spinner = $('
      '); + $spinner.attr('id', 'loading_indicator'); + $spinner.html(' '); + $contentWrapper.append($spinner); + } - // Submits a form - function submitForm($form, $submitBtn) { - $form.css('display', 'none'); + // Submits a form + function submitForm($form, $submitBtn) { + $form.css('display', 'none'); - var xhReq = createXhrObject(); - xhReq.open('POST', $form.attr('action'), true); - xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - xhReq.send(getFormFields($form, $submitBtn)); + var xhReq = createXhrObject(); + xhReq.open('POST', $form.attr('action'), true); + xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xhReq.send(getFormFields($form, $submitBtn)); - // Disable language selector - $('#language_selector :input, label').css('display', 'none'); + // Disable language selector + $('#language_selector :input, label').css('display', 'none'); - // Clear content - setupAjaxLayout(); - $('#loading_indicator').css('display', 'block'); + // Clear content + setupAjaxLayout(); + $('#loading_indicator').css('display', 'block'); - startPolling(xhReq); - } + startPolling(xhReq); + } - /** - * Add submit button to the POST information - * - * @param $form - * @param $submitBtn - * - * @returns {*} - */ - function getFormFields($form, $submitBtn) { - var formData = $form.serialize(); - formData += ((formData.length) ? '&' : '') + encodeURIComponent($submitBtn.attr('name')) + '='; - formData += encodeURIComponent($submitBtn.attr('value')); + /** + * Add submit button to the POST information + * + * @param $form + * @param $submitBtn + * + * @returns {*} + */ + function getFormFields($form, $submitBtn) { + var formData = $form.serialize(); + formData += ((formData.length) ? '&' : '') + encodeURIComponent($submitBtn.attr('name')) + '='; + formData += encodeURIComponent($submitBtn.attr('value')); - return formData; - } + return formData; + } - /** - * Intercept form submit events and determine the submit button used - * - * @param $form - */ - function interceptFormSubmit($form) { - if (!$form.length) { - return; - } + /** + * Intercept form submit events and determine the submit button used + * + * @param $form + */ + function interceptFormSubmit($form) { + if (!$form.length) { + return; + } - $form.find(':submit').bind('click', function (event) { - event.preventDefault(); - submitForm($form, $(this)); - }); - } + $form.find(':submit').bind('click', function (event) { + event.preventDefault(); + submitForm($form, $(this)); + }); + } })(jQuery); // Avoid conflicts with other libraries From cb593c0e04fc9f3318443fe42b596d27498729c3 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 24 Jul 2015 00:04:40 +0200 Subject: [PATCH 0539/1676] [ticket/13740] Filter basic directory change attempts in lang change PHPBB3-13740 --- phpBB/phpbb/install/controller/helper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index f3400e6ef0..8530a0defe 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -191,7 +191,8 @@ class helper $this->language_cookie = $lang; } - $lang = (!empty($lang)) ? $lang : null; + $lang = (!empty($lang) && strpos($lang, '/')) ? $lang : null; + $this->render_language_select($lang); if ($lang !== null) From 22786a5b6fcdab1610b609ae069065c5d6691496 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 24 Jul 2015 02:37:00 +0200 Subject: [PATCH 0540/1676] [ticket/13740] Fix CS PHPBB3-13740 --- phpBB/phpbb/install/controller/install.php | 1 - phpBB/phpbb/install/module/install_finish/task/notify_user.php | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php index 904f5920c2..c21b0d831b 100644 --- a/phpBB/phpbb/install/controller/install.php +++ b/phpBB/phpbb/install/controller/install.php @@ -13,7 +13,6 @@ namespace phpbb\install\controller; -use phpbb\exception\http_exception; use phpbb\install\helper\config; use phpbb\install\helper\install_helper; use phpbb\install\helper\navigation\navigation_provider; diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php index a433d342d0..0af76f6f60 100644 --- a/phpBB/phpbb/install/module/install_finish/task/notify_user.php +++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php @@ -12,6 +12,7 @@ */ namespace phpbb\install\module\install_finish\task; + use phpbb\config\db; /** From b4552a8ba303881d53995d334cc22aa175d5c46f Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 24 Jul 2015 08:33:02 +0200 Subject: [PATCH 0541/1676] [ticket/13740] Replace more spaces with tabs PHPBB3-13740 --- phpBB/adm/style/admin.css | 38 +++++------ phpBB/adm/style/install_header.html | 4 +- phpBB/adm/style/installer_footer.html | 20 +++--- phpBB/adm/style/installer_form.html | 86 ++++++++++++------------ phpBB/adm/style/installer_header.html | 92 +++++++++++++------------- phpBB/adm/style/installer_install.html | 8 +-- phpBB/adm/style/installer_main.html | 4 +- 7 files changed, 126 insertions(+), 126 deletions(-) diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index ca5daf5bc5..992af0997f 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -1801,7 +1801,7 @@ li.pagination ul { } .warningbox { - background-color: #fca600; + background-color: #fca600; } .successbox h3, .errorbox h3 { @@ -2523,28 +2523,28 @@ fieldset.permissions .padding { } #progress-bar { - position: relative; - width: 90%; - height: 25px; - margin: 20px auto; - border: 1px solid #cecece; + position: relative; + width: 90%; + height: 25px; + margin: 20px auto; + border: 1px solid #cecece; } #progress-bar #progress-bar-text { - position: absolute; - top: 0; - width: 100%; - text-align: center; - line-height: 25px; - font-weight: bold; + position: absolute; + top: 0; + width: 100%; + text-align: center; + line-height: 25px; + font-weight: bold; } #progress-bar #progress-bar-filler { - display: block; - position: relative; - top: 0; - left: 0; - background-color: #3c84ad; - width: 0; - height: 25px; + display: block; + position: relative; + top: 0; + left: 0; + background-color: #3c84ad; + width: 0; + height: 25px; } diff --git a/phpBB/adm/style/install_header.html b/phpBB/adm/style/install_header.html index 8debfc69c0..6f7f129d39 100644 --- a/phpBB/adm/style/install_header.html +++ b/phpBB/adm/style/install_header.html @@ -18,7 +18,7 @@
      - {S_LANG_SELECT} + {S_LANG_SELECT}
      @@ -43,7 +43,7 @@ id="activemenu">{l_block1.L_TITLE} - id="activemenu"> class="completed">{l_block2.L_TITLE} + id="activemenu"> class="completed">{l_block2.L_TITLE}
      diff --git a/phpBB/adm/style/installer_footer.html b/phpBB/adm/style/installer_footer.html index 2c70d4d5d3..617d3dc254 100644 --- a/phpBB/adm/style/installer_footer.html +++ b/phpBB/adm/style/installer_footer.html @@ -1,14 +1,14 @@ -
      -
      -
      -
      -
      +
      +
      +
      +
      +
      - +
      diff --git a/phpBB/adm/style/installer_form.html b/phpBB/adm/style/installer_form.html index 3cb4185bc6..669f7aa834 100644 --- a/phpBB/adm/style/installer_form.html +++ b/phpBB/adm/style/installer_form.html @@ -4,53 +4,53 @@
      - - - -
      + + + + -
      - - {options.LEGEND} - +
      + + {options.LEGEND} + - -
      -

      {options.TITLE_EXPLAIN}
      -
      - - - - - - - - - - - - - - - checked /> {options.OPTIONS.label} - - -
      -
      - + +
      +

      {options.TITLE_EXPLAIN}
      +
      + + + + + + + + + + + + + + + checked /> {options.OPTIONS.label} + + +
      +
      +
      -
      - {L_SUBMIT} - -
      - - - +
      + {L_SUBMIT} + +
      + + + diff --git a/phpBB/adm/style/installer_header.html b/phpBB/adm/style/installer_header.html index ada6553aec..775caa7c67 100644 --- a/phpBB/adm/style/installer_header.html +++ b/phpBB/adm/style/installer_header.html @@ -1,57 +1,57 @@ - - - {META} - {PAGE_TITLE} + + + {META} + {PAGE_TITLE} - +
      - + -
      -
      - -
      +
      +
      + +
      -
      -
      - +
      +
      + -
      -
      +
      +
      diff --git a/phpBB/adm/style/installer_install.html b/phpBB/adm/style/installer_install.html index 175c6eac67..53a91f2700 100644 --- a/phpBB/adm/style/installer_install.html +++ b/phpBB/adm/style/installer_install.html @@ -3,10 +3,10 @@

      {CONTENT}

      -
      - {L_SUBMIT} - -
      +
      + {L_SUBMIT} + +
      diff --git a/phpBB/adm/style/installer_main.html b/phpBB/adm/style/installer_main.html index ed65da8a68..f14fe4da70 100644 --- a/phpBB/adm/style/installer_main.html +++ b/phpBB/adm/style/installer_main.html @@ -1,6 +1,6 @@ -

      {TITLE}

      -

      {BODY}

      +

      {TITLE}

      +

      {BODY}

      From 0d88b3f9e9f8d845044febce3c5df4f7e73b61f6 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 24 Jul 2015 11:06:50 +0200 Subject: [PATCH 0542/1676] [ticket/13740] Fix message element creation in JS PHPBB3-13740 --- phpBB/assets/javascript/installer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index 4e44e2755c..56bfd6aea9 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -46,12 +46,12 @@ var $title, $description, $msgElement, arraySize = messages.length; for (var i = 0; i < arraySize; i++) { $msgElement = $('
      '); - $title = $(document.createElement('strong')); + $title = $(''); $title.text(messages[i].title); $msgElement.append($title); if (messages[i].hasOwnProperty('description')) { - $description = $(document.createElement('p')); + $description = $('

      '); $description.html(messages[i].description); $msgElement.append($description); } From fc46dec81397ef0183a91aeba795f65a4d755178 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 24 Jul 2015 17:36:04 +0200 Subject: [PATCH 0543/1676] [ticket/13740] Fix CS in compatibilty_globals.php PHPBB3-13740 --- phpBB/includes/compatibility_globals.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php index fadc879640..ae532c0f13 100644 --- a/phpBB/includes/compatibility_globals.php +++ b/phpBB/includes/compatibility_globals.php @@ -12,7 +12,7 @@ */ /** - */ +*/ if (!defined('IN_PHPBB')) { exit; From be7e1ba7a0d35a86c4b41ab037e82a3a114108cb Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Fri, 24 Jul 2015 18:05:10 +0200 Subject: [PATCH 0544/1676] [ticket/13740] Use language service in console application PHPBB3-13740 --- phpBB/bin/phpbbcli.php | 3 ++- phpBB/phpbb/console/application.php | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index c847b884e0..18657aed0a 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -68,7 +68,8 @@ require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx); $user = $phpbb_container->get('user'); $user->add_lang('acp/common'); $user->add_lang('cli'); +$lang = $phpbb_container->get('language'); -$application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $user); +$application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $lang); $application->register_container_commands($phpbb_container->get('console.command_collection')); $application->run($input); diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php index 0943e8a4b8..2c69a3cc73 100644 --- a/phpBB/phpbb/console/application.php +++ b/phpBB/phpbb/console/application.php @@ -26,18 +26,18 @@ class application extends \Symfony\Component\Console\Application protected $in_shell = false; /** - * @var \phpbb\user User object + * @var \phpbb\language\language User object */ - protected $user; + protected $language; /** - * @param string $name The name of the application - * @param string $version The version of the application - * @param \phpbb\user $user The user which runs the application (used for translation) + * @param string $name The name of the application + * @param string $version The version of the application + * @param \phpbb\language\language $language The user which runs the application (used for translation) */ - public function __construct($name, $version, $user) + public function __construct($name, $version, \phpbb\language\language $language) { - $this->user = $user; + $this->language = $language; parent::__construct($name, $version); } @@ -53,7 +53,7 @@ class application extends \Symfony\Component\Console\Application 'safe-mode', null, InputOption::VALUE_NONE, - $this->user->lang('CLI_DESCRIPTION_OPTION_SAFE_MODE') + $this->language->lang('CLI_DESCRIPTION_OPTION_SAFE_MODE') )); return $input_definition; @@ -80,7 +80,7 @@ class application extends \Symfony\Component\Console\Application '--shell', '-s', InputOption::VALUE_NONE, - $this->user->lang('CLI_DESCRIPTION_OPTION_SHELL') + $this->language->lang('CLI_DESCRIPTION_OPTION_SHELL') )); return parent::getHelp(); From 04186e8498c78d16f8eb5402c19d70e9e7795e83 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Sat, 25 Jul 2015 14:42:17 +0200 Subject: [PATCH 0545/1676] [ticket/13740] Fix comment PHPBB3-13740 --- phpBB/phpbb/install/controller/helper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index 8530a0defe..6d591786c4 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -183,7 +183,7 @@ class helper } } - // Retrive language from cookie + // Retrieve language from cookie $lang_cookie = $this->phpbb_request->variable('lang', '', false, request_interface::COOKIE); if (empty($lang) && !empty($lang_cookie)) { From 723337d2f68940eff64586cc91151fad2c40ea6e Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Sat, 25 Jul 2015 14:42:37 +0200 Subject: [PATCH 0546/1676] [ticket/13740] Use JSON for installer config PHPBB3-13740 --- phpBB/phpbb/install/helper/config.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php index 38376da82a..b0480e7e5b 100644 --- a/phpBB/phpbb/install/helper/config.php +++ b/phpBB/phpbb/install/helper/config.php @@ -231,7 +231,7 @@ class config if (!empty($serialized_data)) { - $unserialized_data = unserialize($serialized_data); + $unserialized_data = json_decode($serialized_data, true); $this->installer_config = (is_array($unserialized_data['installer_config'])) ? $unserialized_data['installer_config'] : array(); $this->progress_data = (is_array($unserialized_data['progress_data'])) ? $unserialized_data['progress_data'] : array(); @@ -259,7 +259,7 @@ class config // Create file content $file_content = ' Date: Sat, 25 Jul 2015 14:43:54 +0200 Subject: [PATCH 0547/1676] [ticket/13740] Deduplicate container builder's checks PHPBB3-13740 --- .../install/helper/container_factory.php | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/phpBB/phpbb/install/helper/container_factory.php b/phpBB/phpbb/install/helper/container_factory.php index e09e43be34..dab16b81fd 100644 --- a/phpBB/phpbb/install/helper/container_factory.php +++ b/phpBB/phpbb/install/helper/container_factory.php @@ -73,16 +73,7 @@ class container_factory // Check if container was built, if not try to build it if ($this->container === null) { - // Check whether container can be built - // We need config.php for that so let's check if it has been set up yet - if (filesize($this->phpbb_root_path . 'config.' . $this->php_ext)) - { - $this->build_container(); - } - else - { - throw new cannot_build_container_exception(); - } + $this->build_container(); } return ($service_name === null) ? $this->container : $this->container->get($service_name); @@ -102,16 +93,7 @@ class container_factory // Check if container was built, if not try to build it if ($this->container === null) { - // Check whether container can be built - // We need config.php for that so let's check if it has been set up yet - if (filesize($this->phpbb_root_path . 'config.' . $this->php_ext)) - { - $this->build_container(); - } - else - { - throw new cannot_build_container_exception(); - } + $this->build_container(); } return $this->container->getParameter($param_name); @@ -119,6 +101,8 @@ class container_factory /** * Build dependency injection container + * + * @throws \phpbb\install\exception\cannot_build_container_exception When container cannot be built */ protected function build_container() { @@ -129,6 +113,17 @@ class container_factory return; } + // Check whether container can be built + // We need config.php for that so let's check if it has been set up yet + if (filesize($this->phpbb_root_path . 'config.' . $this->php_ext)) + { + $this->build_container(); + } + else + { + throw new cannot_build_container_exception(); + } + $phpbb_config_php_file = new \phpbb\config_php_file($this->phpbb_root_path, $this->php_ext); $phpbb_container_builder = new \phpbb\di\container_builder($this->phpbb_root_path, $this->php_ext); From 0befa9f10900238a2be2c3e50d85de3de9c5edec Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Sat, 25 Jul 2015 14:44:39 +0200 Subject: [PATCH 0548/1676] [ticket/13740] Move default data settings out of constructors PHPBB3-13740 --- phpBB/phpbb/install/helper/database.php | 173 +++++++++--------- .../module/install_data/task/add_bots.php | 169 +++++++++-------- .../module/install_data/task/add_modules.php | 172 +++++++++-------- 3 files changed, 251 insertions(+), 263 deletions(-) diff --git a/phpBB/phpbb/install/helper/database.php b/phpBB/phpbb/install/helper/database.php index 27cb2dc828..627e9ea9b0 100644 --- a/phpBB/phpbb/install/helper/database.php +++ b/phpBB/phpbb/install/helper/database.php @@ -33,7 +33,91 @@ class database /** * @var array */ - protected $supported_dbms; + protected $supported_dbms = array( + // Note: php 5.5 alpha 2 deprecated mysql. + // Keep mysqli before mysql in this list. + 'mysqli' => array( + 'LABEL' => 'MySQL with MySQLi Extension', + 'SCHEMA' => 'mysql_41', + 'MODULE' => 'mysqli', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\mysqli', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mysql' => array( + 'LABEL' => 'MySQL', + 'SCHEMA' => 'mysql', + 'MODULE' => 'mysql', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\mysql', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mssql' => array( + 'LABEL' => 'MS SQL Server 2000+', + 'SCHEMA' => 'mssql', + 'MODULE' => 'mssql', + 'DELIM' => 'GO', + 'DRIVER' => 'phpbb\db\driver\mssql', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mssql_odbc'=> array( + 'LABEL' => 'MS SQL Server [ ODBC ]', + 'SCHEMA' => 'mssql', + 'MODULE' => 'odbc', + 'DELIM' => 'GO', + 'DRIVER' => 'phpbb\db\driver\mssql_odbc', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mssqlnative' => array( + 'LABEL' => 'MS SQL Server 2005+ [ Native ]', + 'SCHEMA' => 'mssql', + 'MODULE' => 'sqlsrv', + 'DELIM' => 'GO', + 'DRIVER' => 'phpbb\db\driver\mssqlnative', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + 'oracle' => array( + 'LABEL' => 'Oracle', + 'SCHEMA' => 'oracle', + 'MODULE' => 'oci8', + 'DELIM' => '/', + 'DRIVER' => 'phpbb\db\driver\oracle', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + 'postgres' => array( + 'LABEL' => 'PostgreSQL 8.3+', + 'SCHEMA' => 'postgres', + 'MODULE' => 'pgsql', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\postgres', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'sqlite' => array( + 'LABEL' => 'SQLite', + 'SCHEMA' => 'sqlite', + 'MODULE' => 'sqlite', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\sqlite', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + 'sqlite3' => array( + 'LABEL' => 'SQLite3', + 'SCHEMA' => 'sqlite', + 'MODULE' => 'sqlite3', + 'DELIM' => ';', + 'DRIVER' => 'phpbb\db\driver\sqlite3', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + ); /** * Constructor @@ -45,93 +129,6 @@ class database { $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; - - // DBMS supported by phpBB - $this->supported_dbms = array( - // Note: php 5.5 alpha 2 deprecated mysql. - // Keep mysqli before mysql in this list. - 'mysqli' => array( - 'LABEL' => 'MySQL with MySQLi Extension', - 'SCHEMA' => 'mysql_41', - 'MODULE' => 'mysqli', - 'DELIM' => ';', - 'DRIVER' => 'phpbb\db\driver\mysqli', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'mysql' => array( - 'LABEL' => 'MySQL', - 'SCHEMA' => 'mysql', - 'MODULE' => 'mysql', - 'DELIM' => ';', - 'DRIVER' => 'phpbb\db\driver\mysql', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'mssql' => array( - 'LABEL' => 'MS SQL Server 2000+', - 'SCHEMA' => 'mssql', - 'MODULE' => 'mssql', - 'DELIM' => 'GO', - 'DRIVER' => 'phpbb\db\driver\mssql', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'mssql_odbc'=> array( - 'LABEL' => 'MS SQL Server [ ODBC ]', - 'SCHEMA' => 'mssql', - 'MODULE' => 'odbc', - 'DELIM' => 'GO', - 'DRIVER' => 'phpbb\db\driver\mssql_odbc', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'mssqlnative' => array( - 'LABEL' => 'MS SQL Server 2005+ [ Native ]', - 'SCHEMA' => 'mssql', - 'MODULE' => 'sqlsrv', - 'DELIM' => 'GO', - 'DRIVER' => 'phpbb\db\driver\mssqlnative', - 'AVAILABLE' => true, - '2.0.x' => false, - ), - 'oracle' => array( - 'LABEL' => 'Oracle', - 'SCHEMA' => 'oracle', - 'MODULE' => 'oci8', - 'DELIM' => '/', - 'DRIVER' => 'phpbb\db\driver\oracle', - 'AVAILABLE' => true, - '2.0.x' => false, - ), - 'postgres' => array( - 'LABEL' => 'PostgreSQL 8.3+', - 'SCHEMA' => 'postgres', - 'MODULE' => 'pgsql', - 'DELIM' => ';', - 'DRIVER' => 'phpbb\db\driver\postgres', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'sqlite' => array( - 'LABEL' => 'SQLite', - 'SCHEMA' => 'sqlite', - 'MODULE' => 'sqlite', - 'DELIM' => ';', - 'DRIVER' => 'phpbb\db\driver\sqlite', - 'AVAILABLE' => true, - '2.0.x' => false, - ), - 'sqlite3' => array( - 'LABEL' => 'SQLite3', - 'SCHEMA' => 'sqlite', - 'MODULE' => 'sqlite3', - 'DELIM' => ';', - 'DRIVER' => 'phpbb\db\driver\sqlite3', - 'AVAILABLE' => true, - '2.0.x' => false, - ), - ); } /** diff --git a/phpBB/phpbb/install/module/install_data/task/add_bots.php b/phpBB/phpbb/install/module/install_data/task/add_bots.php index c31700e97f..b45d3808db 100644 --- a/phpBB/phpbb/install/module/install_data/task/add_bots.php +++ b/phpBB/phpbb/install/module/install_data/task/add_bots.php @@ -16,9 +16,91 @@ namespace phpbb\install\module\install_data\task; class add_bots extends \phpbb\install\task_base { /** + * A list of the web-crawlers/bots we recognise by default + * + * Candidates but not included: + * 'Accoona [Bot]' 'Accoona-AI-Agent/' + * 'ASPseek [Crawler]' 'ASPseek/' + * 'Boitho [Crawler]' 'boitho.com-dc/' + * 'Bunnybot [Bot]' 'powered by www.buncat.de' + * 'Cosmix [Bot]' 'cfetch/' + * 'Crawler Search [Crawler]' '.Crawler-Search.de' + * 'Findexa [Crawler]' 'Findexa Crawler (' + * 'GBSpider [Spider]' 'GBSpider v' + * 'genie [Bot]' 'genieBot (' + * 'Hogsearch [Bot]' 'oegp v. 1.3.0' + * 'Insuranco [Bot]' 'InsurancoBot' + * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler' + * 'ISC Systems [Bot]' 'ISC Systems iRc Search' + * 'Jyxobot [Bot]' 'Jyxobot/' + * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/' + * 'LinkWalker' 'LinkWalker' + * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html' + * 'Naver [Bot]' 'nhnbot@naver.com)' + * 'NetResearchServer' 'NetResearchServer/' + * 'Nimble [Crawler]' 'NimbleCrawler' + * 'Ocelli [Bot]' 'Ocelli/' + * 'Onsearch [Bot]' 'onCHECK-Robot' + * 'Orange [Spider]' 'OrangeSpider' + * 'Sproose [Bot]' 'http://www.sproose.com/bot' + * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)' + * 'Tbot [Bot]' 'Tbot/' + * 'Thumbshots [Capture]' 'thumbshots-de-Bot' + * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/' + * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)' + * 'WissenOnline [Bot]' 'WissenOnline-Bot' + * 'WWWeasel [Bot]' 'WWWeasel Robot v' + * 'Xaldon [Spider]' 'Xaldon WebSpider' + * * @var array */ - protected $bot_list; + protected $bot_list = array( + 'AdsBot [Google]' => array('AdsBot-Google', ''), + 'Alexa [Bot]' => array('ia_archiver', ''), + 'Alta Vista [Bot]' => array('Scooter/', ''), + 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''), + 'Baidu [Spider]' => array('Baiduspider', ''), + 'Bing [Bot]' => array('bingbot/', ''), + 'Exabot [Bot]' => array('Exabot', ''), + 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''), + 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''), + 'Francis [Bot]' => array('http://www.neomo.de/', ''), + 'Gigabot [Bot]' => array('Gigabot/', ''), + 'Google Adsense [Bot]' => array('Mediapartners-Google', ''), + 'Google Desktop' => array('Google Desktop', ''), + 'Google Feedfetcher' => array('Feedfetcher-Google', ''), + 'Google [Bot]' => array('Googlebot', ''), + 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''), + 'Heritrix [Crawler]' => array('heritrix/1.', ''), + 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''), + 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''), + 'ichiro [Crawler]' => array('ichiro/', ''), + 'Majestic-12 [Bot]' => array('MJ12bot/', ''), + 'Metager [Bot]' => array('MetagerBot/', ''), + 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''), + 'MSN [Bot]' => array('msnbot/', ''), + 'MSNbot Media' => array('msnbot-media/', ''), + 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''), + 'Online link [Validator]' => array('online link validator', ''), + 'psbot [Picsearch]' => array('psbot/0', ''), + 'Sensis [Crawler]' => array('Sensis Web Crawler', ''), + 'SEO Crawler' => array('SEO search Crawler/', ''), + 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''), + 'SEOSearch [Crawler]' => array('SEOsearch/', ''), + 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''), + 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''), + 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''), + 'TurnitinBot [Bot]' => array('TurnitinBot/', ''), + 'Voyager [Bot]' => array('voyager/', ''), + 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''), + 'W3C [Linkcheck]' => array('W3C-checklink/', ''), + 'W3C [Validator]' => array('W3C_Validator', ''), + 'YaCy [Bot]' => array('yacybot', ''), + 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''), + 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''), + 'Yahoo [Bot]' => array('Yahoo! Slurp', ''), + 'YahooSeeker [Bot]' => array('YahooSeeker/', ''), + ); /** * @var \phpbb\db\driver\driver_interface @@ -75,91 +157,6 @@ class add_bots extends \phpbb\install\task_base $this->language = $language; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - - /** - * A list of the web-crawlers/bots we recognise by default - * - * Candidates but not included: - * 'Accoona [Bot]' 'Accoona-AI-Agent/' - * 'ASPseek [Crawler]' 'ASPseek/' - * 'Boitho [Crawler]' 'boitho.com-dc/' - * 'Bunnybot [Bot]' 'powered by www.buncat.de' - * 'Cosmix [Bot]' 'cfetch/' - * 'Crawler Search [Crawler]' '.Crawler-Search.de' - * 'Findexa [Crawler]' 'Findexa Crawler (' - * 'GBSpider [Spider]' 'GBSpider v' - * 'genie [Bot]' 'genieBot (' - * 'Hogsearch [Bot]' 'oegp v. 1.3.0' - * 'Insuranco [Bot]' 'InsurancoBot' - * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler' - * 'ISC Systems [Bot]' 'ISC Systems iRc Search' - * 'Jyxobot [Bot]' 'Jyxobot/' - * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/' - * 'LinkWalker' 'LinkWalker' - * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html' - * 'Naver [Bot]' 'nhnbot@naver.com)' - * 'NetResearchServer' 'NetResearchServer/' - * 'Nimble [Crawler]' 'NimbleCrawler' - * 'Ocelli [Bot]' 'Ocelli/' - * 'Onsearch [Bot]' 'onCHECK-Robot' - * 'Orange [Spider]' 'OrangeSpider' - * 'Sproose [Bot]' 'http://www.sproose.com/bot' - * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)' - * 'Tbot [Bot]' 'Tbot/' - * 'Thumbshots [Capture]' 'thumbshots-de-Bot' - * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/' - * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)' - * 'WissenOnline [Bot]' 'WissenOnline-Bot' - * 'WWWeasel [Bot]' 'WWWeasel Robot v' - * 'Xaldon [Spider]' 'Xaldon WebSpider' - */ - $this->bot_list = array( - 'AdsBot [Google]' => array('AdsBot-Google', ''), - 'Alexa [Bot]' => array('ia_archiver', ''), - 'Alta Vista [Bot]' => array('Scooter/', ''), - 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''), - 'Baidu [Spider]' => array('Baiduspider', ''), - 'Bing [Bot]' => array('bingbot/', ''), - 'Exabot [Bot]' => array('Exabot', ''), - 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''), - 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''), - 'Francis [Bot]' => array('http://www.neomo.de/', ''), - 'Gigabot [Bot]' => array('Gigabot/', ''), - 'Google Adsense [Bot]' => array('Mediapartners-Google', ''), - 'Google Desktop' => array('Google Desktop', ''), - 'Google Feedfetcher' => array('Feedfetcher-Google', ''), - 'Google [Bot]' => array('Googlebot', ''), - 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''), - 'Heritrix [Crawler]' => array('heritrix/1.', ''), - 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''), - 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''), - 'ichiro [Crawler]' => array('ichiro/', ''), - 'Majestic-12 [Bot]' => array('MJ12bot/', ''), - 'Metager [Bot]' => array('MetagerBot/', ''), - 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''), - 'MSN [Bot]' => array('msnbot/', ''), - 'MSNbot Media' => array('msnbot-media/', ''), - 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''), - 'Online link [Validator]' => array('online link validator', ''), - 'psbot [Picsearch]' => array('psbot/0', ''), - 'Sensis [Crawler]' => array('Sensis Web Crawler', ''), - 'SEO Crawler' => array('SEO search Crawler/', ''), - 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''), - 'SEOSearch [Crawler]' => array('SEOsearch/', ''), - 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''), - 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''), - 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''), - 'TurnitinBot [Bot]' => array('TurnitinBot/', ''), - 'Voyager [Bot]' => array('voyager/', ''), - 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''), - 'W3C [Linkcheck]' => array('W3C-checklink/', ''), - 'W3C [Validator]' => array('W3C_Validator', ''), - 'YaCy [Bot]' => array('yacybot', ''), - 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''), - 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''), - 'Yahoo [Bot]' => array('Yahoo! Slurp', ''), - 'YahooSeeker [Bot]' => array('YahooSeeker/', ''), - ); } /** diff --git a/phpBB/phpbb/install/module/install_data/task/add_modules.php b/phpBB/phpbb/install/module/install_data/task/add_modules.php index 8ca2b6b215..bfbe6282bc 100644 --- a/phpBB/phpbb/install/module/install_data/task/add_modules.php +++ b/phpBB/phpbb/install/module/install_data/task/add_modules.php @@ -41,17 +41,97 @@ class add_modules extends \phpbb\install\task_base * * @var array */ - protected $module_categories; + protected $module_categories = array( + 'acp' => array( + 'ACP_CAT_GENERAL' => array( + 'ACP_QUICK_ACCESS', + 'ACP_BOARD_CONFIGURATION', + 'ACP_CLIENT_COMMUNICATION', + 'ACP_SERVER_CONFIGURATION', + ), + 'ACP_CAT_FORUMS' => array( + 'ACP_MANAGE_FORUMS', + 'ACP_FORUM_BASED_PERMISSIONS', + ), + 'ACP_CAT_POSTING' => array( + 'ACP_MESSAGES', + 'ACP_ATTACHMENTS', + ), + 'ACP_CAT_USERGROUP' => array( + 'ACP_CAT_USERS', + 'ACP_GROUPS', + 'ACP_USER_SECURITY', + ), + 'ACP_CAT_PERMISSIONS' => array( + 'ACP_GLOBAL_PERMISSIONS', + 'ACP_FORUM_BASED_PERMISSIONS', + 'ACP_PERMISSION_ROLES', + 'ACP_PERMISSION_MASKS', + ), + 'ACP_CAT_CUSTOMISE' => array( + 'ACP_STYLE_MANAGEMENT', + 'ACP_EXTENSION_MANAGEMENT', + 'ACP_LANGUAGE', + ), + 'ACP_CAT_MAINTENANCE' => array( + 'ACP_FORUM_LOGS', + 'ACP_CAT_DATABASE', + ), + 'ACP_CAT_SYSTEM' => array( + 'ACP_AUTOMATION', + 'ACP_GENERAL_TASKS', + 'ACP_MODULE_MANAGEMENT', + ), + 'ACP_CAT_DOT_MODS' => null, + ), + 'mcp' => array( + 'MCP_MAIN' => null, + 'MCP_QUEUE' => null, + 'MCP_REPORTS' => null, + 'MCP_NOTES' => null, + 'MCP_WARN' => null, + 'MCP_LOGS' => null, + 'MCP_BAN' => null, + ), + 'ucp' => array( + 'UCP_MAIN' => null, + 'UCP_PROFILE' => null, + 'UCP_PREFS' => null, + 'UCP_PM' => null, + 'UCP_USERGROUPS' => null, + 'UCP_ZEBRA' => null, + ), + ); /** * @var array */ - protected $module_categories_basenames; + protected $module_categories_basenames = array( + 'UCP_PM' => 'ucp_pm', + ); /** * @var array */ - protected $module_extras; + protected $module_extras = array( + 'acp' => array( + 'ACP_QUICK_ACCESS' => array( + 'ACP_MANAGE_USERS', + 'ACP_GROUPS_MANAGE', + 'ACP_MANAGE_FORUMS', + 'ACP_MOD_LOGS', + 'ACP_BOTS', + 'ACP_PHP_INFO', + ), + 'ACP_FORUM_BASED_PERMISSIONS' => array( + 'ACP_FORUM_PERMISSIONS', + 'ACP_FORUM_PERMISSIONS_COPY', + 'ACP_FORUM_MODERATORS', + 'ACP_USERS_FORUM_PERMISSIONS', + 'ACP_GROUPS_FORUM_PERMISSIONS', + ), + ), + ); /** * Constructor @@ -68,92 +148,6 @@ class add_modules extends \phpbb\install\task_base $this->module_manager = $container->get('module.manager'); parent::__construct(true); - - $this->module_categories = array( - 'acp' => array( - 'ACP_CAT_GENERAL' => array( - 'ACP_QUICK_ACCESS', - 'ACP_BOARD_CONFIGURATION', - 'ACP_CLIENT_COMMUNICATION', - 'ACP_SERVER_CONFIGURATION', - ), - 'ACP_CAT_FORUMS' => array( - 'ACP_MANAGE_FORUMS', - 'ACP_FORUM_BASED_PERMISSIONS', - ), - 'ACP_CAT_POSTING' => array( - 'ACP_MESSAGES', - 'ACP_ATTACHMENTS', - ), - 'ACP_CAT_USERGROUP' => array( - 'ACP_CAT_USERS', - 'ACP_GROUPS', - 'ACP_USER_SECURITY', - ), - 'ACP_CAT_PERMISSIONS' => array( - 'ACP_GLOBAL_PERMISSIONS', - 'ACP_FORUM_BASED_PERMISSIONS', - 'ACP_PERMISSION_ROLES', - 'ACP_PERMISSION_MASKS', - ), - 'ACP_CAT_CUSTOMISE' => array( - 'ACP_STYLE_MANAGEMENT', - 'ACP_EXTENSION_MANAGEMENT', - 'ACP_LANGUAGE', - ), - 'ACP_CAT_MAINTENANCE' => array( - 'ACP_FORUM_LOGS', - 'ACP_CAT_DATABASE', - ), - 'ACP_CAT_SYSTEM' => array( - 'ACP_AUTOMATION', - 'ACP_GENERAL_TASKS', - 'ACP_MODULE_MANAGEMENT', - ), - 'ACP_CAT_DOT_MODS' => null, - ), - 'mcp' => array( - 'MCP_MAIN' => null, - 'MCP_QUEUE' => null, - 'MCP_REPORTS' => null, - 'MCP_NOTES' => null, - 'MCP_WARN' => null, - 'MCP_LOGS' => null, - 'MCP_BAN' => null, - ), - 'ucp' => array( - 'UCP_MAIN' => null, - 'UCP_PROFILE' => null, - 'UCP_PREFS' => null, - 'UCP_PM' => null, - 'UCP_USERGROUPS' => null, - 'UCP_ZEBRA' => null, - ), - ); - - $this->module_categories_basenames = array( - 'UCP_PM' => 'ucp_pm', - ); - - $this->module_extras = array( - 'acp' => array( - 'ACP_QUICK_ACCESS' => array( - 'ACP_MANAGE_USERS', - 'ACP_GROUPS_MANAGE', - 'ACP_MANAGE_FORUMS', - 'ACP_MOD_LOGS', - 'ACP_BOTS', - 'ACP_PHP_INFO', - ), - 'ACP_FORUM_BASED_PERMISSIONS' => array( - 'ACP_FORUM_PERMISSIONS', - 'ACP_FORUM_PERMISSIONS_COPY', - 'ACP_FORUM_MODERATORS', - 'ACP_USERS_FORUM_PERMISSIONS', - 'ACP_GROUPS_FORUM_PERMISSIONS', - ), - ), - ); } /** From f7641cd506bd8ad98e923ce84f9f39960a938a69 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Sat, 25 Jul 2015 15:41:10 +0200 Subject: [PATCH 0549/1676] [ticket/13740] Fix infinite config.php check loop PHPBB3-13740 --- phpBB/phpbb/install/helper/container_factory.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/phpBB/phpbb/install/helper/container_factory.php b/phpBB/phpbb/install/helper/container_factory.php index dab16b81fd..dc0eef6485 100644 --- a/phpBB/phpbb/install/helper/container_factory.php +++ b/phpBB/phpbb/install/helper/container_factory.php @@ -115,11 +115,7 @@ class container_factory // Check whether container can be built // We need config.php for that so let's check if it has been set up yet - if (filesize($this->phpbb_root_path . 'config.' . $this->php_ext)) - { - $this->build_container(); - } - else + if (!filesize($this->phpbb_root_path . 'config.' . $this->php_ext)) { throw new cannot_build_container_exception(); } From 495c0c6fb32ac0b720fccfeb640a0b3d5a32b98f Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Sun, 26 Jul 2015 22:20:32 +0200 Subject: [PATCH 0550/1676] [ticket/13740] Move handle_language_select calls to the controllers PHPBB3-13740 --- phpBB/phpbb/install/controller/helper.php | 4 +--- phpBB/phpbb/install/controller/install.php | 2 ++ phpBB/phpbb/install/controller/installer_index.php | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index 6d591786c4..fdfa6821ed 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -114,8 +114,6 @@ class helper $this->router = $router; $this->phpbb_root_path = $phpbb_root_path; $this->phpbb_admin_path = $phpbb_root_path . 'adm/'; - - $this->handle_language_select(); } /** @@ -167,7 +165,7 @@ class helper /** * Handles language selector form */ - protected function handle_language_select() + public function handle_language_select() { $lang = null; diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php index c21b0d831b..80f6651a39 100644 --- a/phpBB/phpbb/install/controller/install.php +++ b/phpBB/phpbb/install/controller/install.php @@ -176,6 +176,8 @@ class install // Determine whether the installation was started or not if (true) { + $this->controller_helper->handle_language_select(); + // Set active stage $this->menu_provider->set_nav_property( array('install', 0, 'introduction'), diff --git a/phpBB/phpbb/install/controller/installer_index.php b/phpBB/phpbb/install/controller/installer_index.php index 8e1874984b..c2d9572284 100644 --- a/phpBB/phpbb/install/controller/installer_index.php +++ b/phpBB/phpbb/install/controller/installer_index.php @@ -53,6 +53,8 @@ class installer_index public function handle($mode) { + $this->helper->handle_language_select(); + switch ($mode) { case "intro": From 11dfe503aac699b88a333967a1d0e594998414ae Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Sun, 26 Jul 2015 23:00:40 +0200 Subject: [PATCH 0551/1676] [ticket/13740] Reduce number of references in nav provider PHPBB3-13740 --- .../helper/navigation/navigation_provider.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/phpBB/phpbb/install/helper/navigation/navigation_provider.php b/phpBB/phpbb/install/helper/navigation/navigation_provider.php index 1f58cbea83..d52aec8999 100644 --- a/phpBB/phpbb/install/helper/navigation/navigation_provider.php +++ b/phpBB/phpbb/install/helper/navigation/navigation_provider.php @@ -58,7 +58,7 @@ class navigation_provider public function register(navigation_interface $navigation) { $nav_arry = $navigation->get(); - $this->merge($nav_arry, $this->menu_collection); + $this->menu_collection = $this->merge($nav_arry, $this->menu_collection); } /** @@ -79,7 +79,7 @@ class navigation_provider $array_pointer = $property_array; - $this->merge($array_root_pointer, $this->menu_collection); + $this->menu_collection = $this->merge($array_root_pointer, $this->menu_collection); } /** @@ -90,26 +90,32 @@ class navigation_provider * * @param array $array_to_merge * @param array $array_to_merge_into + * + * @return array Merged array */ - private function merge(&$array_to_merge, &$array_to_merge_into) + private function merge($array_to_merge, $array_to_merge_into) { + $merged_array = $array_to_merge_into; + foreach ($array_to_merge as $key => $value) { if (isset($array_to_merge_into[$key])) { if (is_array($array_to_merge_into[$key]) && is_array($value)) { - $this->merge($value, $array_to_merge_into[$key]); + $merged_array[$key] = $this->merge($value, $array_to_merge_into[$key]); } else { - $array_to_merge_into[$key] = $value; + $merged_array[$key] = $value; } } else { - $array_to_merge_into[$key] = $value; + $merged_array[$key] = $value; } } + + return $merged_array; } } From 6499a8a6c04778c04458ce8c7eb5bf5c73c6fa43 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 27 Jul 2015 11:40:12 +0200 Subject: [PATCH 0552/1676] [ticket/14052] Translate installer commands PHPBB3-14052 --- .../installer/container/services_install_console.yml | 1 + phpBB/install_new/phpbbcli.php | 2 -- phpBB/language/en/install_new.php | 8 ++++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/phpBB/config/installer/container/services_install_console.yml b/phpBB/config/installer/container/services_install_console.yml index 6f931c5031..1c1b819e82 100644 --- a/phpBB/config/installer/container/services_install_console.yml +++ b/phpBB/config/installer/container/services_install_console.yml @@ -12,6 +12,7 @@ services: - @language - @installer.helper.iohandler_factory - @installer.installer.install + - @installer.helper.install_helper tags: - { name: console.installer.command } diff --git a/phpBB/install_new/phpbbcli.php b/phpBB/install_new/phpbbcli.php index 4c8034be4e..508d051945 100644 --- a/phpBB/install_new/phpbbcli.php +++ b/phpBB/install_new/phpbbcli.php @@ -12,8 +12,6 @@ * */ -use Symfony\Component\Console\Input\ArgvInput; - if (php_sapi_name() !== 'cli') { echo 'This program must be run from the command line.' . PHP_EOL; diff --git a/phpBB/language/en/install_new.php b/phpBB/language/en/install_new.php index 923601b110..35153973de 100644 --- a/phpBB/language/en/install_new.php +++ b/phpBB/language/en/install_new.php @@ -305,3 +305,11 @@ $lang = array_merge($lang, array( 'INSTALLER_CONFIG_NOT_WRITABLE' => 'The installer config file is not writable.', )); + +// CLI messages +$lang = array_merge($lang, array( + 'CLI_INSTALL_BOARD' => 'Install phpBB', + 'CLI_INSTALL_SHOW_CONFIG' => 'Show the configuration which will be used', + 'CLI_INSTALL_VALIDATE_CONFIG' => 'Validate a configuration file', + 'CLI_CONFIG_FILE' => 'Config file to use', +)); From 172b021c898846b06924dc258804271715e9a4ba Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Mon, 27 Jul 2015 16:04:34 +0200 Subject: [PATCH 0553/1676] [ticket/14053] Fix tests for installer config @covers annotations causing build failures on bamboo, so removed them PHPBB3-14053 --- tests/installer/installer_config_test.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/installer/installer_config_test.php b/tests/installer/installer_config_test.php index 4b83eb9a8f..c7334ebd93 100644 --- a/tests/installer/installer_config_test.php +++ b/tests/installer/installer_config_test.php @@ -34,10 +34,6 @@ class phpbb_installer_config_test extends phpbb_test_case $this->config = new config($filesystem, $php_ini, $phpbb_root_path); } - /** - * @covers config::set - * @covers config::get - */ public function test_set_get_var() { $this->config->set('foo', 'bar'); @@ -54,13 +50,6 @@ class phpbb_installer_config_test extends phpbb_test_case $this->assertGreaterThan(0, $this->config->get_memory_remaining()); } - /** - * @covers config::set_finished_task - * @covers config::set_active_module - * @covers config::set_task_progress_count - * @covers config::increment_current_task_progress - * @covers config::get_progress_data - */ public function test_progress_tracking() { $this->config->set_finished_task('foo'); From 6eb284b23af0568922e787e5875dc1ee8783e71f Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 29 Jul 2015 20:24:52 +0200 Subject: [PATCH 0554/1676] [ticket/14056] Keep install schema resources in the install folder PHPBB3-14056 --- .../task/add_default_data.php | 2 +- .../install_database/task/create_schema.php | 4 +- phpBB/phpbb/install/schemas/index.htm | 10 - phpBB/phpbb/install/schemas/oracle_schema.sql | 37 - .../phpbb/install/schemas/postgres_schema.sql | 80 -- phpBB/phpbb/install/schemas/schema_data.sql | 821 ------------------ 6 files changed, 3 insertions(+), 951 deletions(-) delete mode 100644 phpBB/phpbb/install/schemas/index.htm delete mode 100644 phpBB/phpbb/install/schemas/oracle_schema.sql delete mode 100644 phpBB/phpbb/install/schemas/postgres_schema.sql delete mode 100644 phpBB/phpbb/install/schemas/schema_data.sql diff --git a/phpBB/phpbb/install/module/install_database/task/add_default_data.php b/phpBB/phpbb/install/module/install_database/task/add_default_data.php index 1e1eb10403..3d73a74618 100644 --- a/phpBB/phpbb/install/module/install_database/task/add_default_data.php +++ b/phpBB/phpbb/install/module/install_database/task/add_default_data.php @@ -87,7 +87,7 @@ class add_default_data extends \phpbb\install\task_base $dbms_info = $this->database_helper->get_available_dbms($dbms); // Get schema data from file - $sql_query = @file_get_contents($this->phpbb_root_path . 'phpbb/install/schemas/schema_data.sql'); + $sql_query = @file_get_contents($this->phpbb_root_path . 'install/schemas/schema_data.sql'); // Clean up SQL $sql_query = $this->replace_dbms_specific_sql($sql_query); diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php index 556bfd5e81..cbec5edb6d 100644 --- a/phpBB/phpbb/install/module/install_database/task/create_schema.php +++ b/phpBB/phpbb/install/module/install_database/task/create_schema.php @@ -144,9 +144,9 @@ class create_schema extends \phpbb\install\task_base $change_prefix = false; // Generate database schema - if ($this->filesystem->exists($this->phpbb_root_path . 'phpbb/install/schemas/schema.json')) + if ($this->filesystem->exists($this->phpbb_root_path . 'install/schemas/schema.json')) { - $db_table_schema = @file_get_contents($this->phpbb_root_path . 'phpbb/install/schemas/schema.json'); + $db_table_schema = @file_get_contents($this->phpbb_root_path . 'install/schemas/schema.json'); $db_table_schema = json_decode($db_table_schema, true); $change_prefix = true; } diff --git a/phpBB/phpbb/install/schemas/index.htm b/phpBB/phpbb/install/schemas/index.htm deleted file mode 100644 index ee1f723a7d..0000000000 --- a/phpBB/phpbb/install/schemas/index.htm +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/phpBB/phpbb/install/schemas/oracle_schema.sql b/phpBB/phpbb/install/schemas/oracle_schema.sql deleted file mode 100644 index 2473d31aab..0000000000 --- a/phpBB/phpbb/install/schemas/oracle_schema.sql +++ /dev/null @@ -1,37 +0,0 @@ -/* - This first section is optional, however its probably the best method - of running phpBB on Oracle. If you already have a tablespace and user created - for phpBB you can leave this section commented out! - - The first set of statements create a phpBB tablespace and a phpBB user, - make sure you change the password of the phpBB user before you run this script!! -*/ - -/* -CREATE TABLESPACE "PHPBB" - LOGGING - DATAFILE 'E:\ORACLE\ORADATA\LOCAL\PHPBB.ora' - SIZE 10M - AUTOEXTEND ON NEXT 10M - MAXSIZE 100M; - -CREATE USER "PHPBB" - PROFILE "DEFAULT" - IDENTIFIED BY "phpbb_password" - DEFAULT TABLESPACE "PHPBB" - QUOTA UNLIMITED ON "PHPBB" - ACCOUNT UNLOCK; - -GRANT ANALYZE ANY TO "PHPBB"; -GRANT CREATE SEQUENCE TO "PHPBB"; -GRANT CREATE SESSION TO "PHPBB"; -GRANT CREATE TABLE TO "PHPBB"; -GRANT CREATE TRIGGER TO "PHPBB"; -GRANT CREATE VIEW TO "PHPBB"; -GRANT "CONNECT" TO "PHPBB"; - -COMMIT; -DISCONNECT; - -CONNECT phpbb/phpbb_password; -*/ diff --git a/phpBB/phpbb/install/schemas/postgres_schema.sql b/phpBB/phpbb/install/schemas/postgres_schema.sql deleted file mode 100644 index 65caba8d1c..0000000000 --- a/phpBB/phpbb/install/schemas/postgres_schema.sql +++ /dev/null @@ -1,80 +0,0 @@ - -BEGIN; - -/* - Domain definition -*/ -CREATE DOMAIN varchar_ci AS varchar(255) NOT NULL DEFAULT ''::character varying; - -/* - Operation Functions -*/ -CREATE FUNCTION _varchar_ci_equal(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) = LOWER($2)' LANGUAGE SQL STRICT; -CREATE FUNCTION _varchar_ci_not_equal(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) != LOWER($2)' LANGUAGE SQL STRICT; -CREATE FUNCTION _varchar_ci_less_than(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) < LOWER($2)' LANGUAGE SQL STRICT; -CREATE FUNCTION _varchar_ci_less_equal(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) <= LOWER($2)' LANGUAGE SQL STRICT; -CREATE FUNCTION _varchar_ci_greater_than(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) > LOWER($2)' LANGUAGE SQL STRICT; -CREATE FUNCTION _varchar_ci_greater_equals(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) >= LOWER($2)' LANGUAGE SQL STRICT; - -/* - Operators -*/ -CREATE OPERATOR <( - PROCEDURE = _varchar_ci_less_than, - LEFTARG = varchar_ci, - RIGHTARG = varchar_ci, - COMMUTATOR = >, - NEGATOR = >=, - RESTRICT = scalarltsel, - JOIN = scalarltjoinsel); - -CREATE OPERATOR <=( - PROCEDURE = _varchar_ci_less_equal, - LEFTARG = varchar_ci, - RIGHTARG = varchar_ci, - COMMUTATOR = >=, - NEGATOR = >, - RESTRICT = scalarltsel, - JOIN = scalarltjoinsel); - -CREATE OPERATOR >( - PROCEDURE = _varchar_ci_greater_than, - LEFTARG = varchar_ci, - RIGHTARG = varchar_ci, - COMMUTATOR = <, - NEGATOR = <=, - RESTRICT = scalargtsel, - JOIN = scalargtjoinsel); - -CREATE OPERATOR >=( - PROCEDURE = _varchar_ci_greater_equals, - LEFTARG = varchar_ci, - RIGHTARG = varchar_ci, - COMMUTATOR = <=, - NEGATOR = <, - RESTRICT = scalargtsel, - JOIN = scalargtjoinsel); - -CREATE OPERATOR <>( - PROCEDURE = _varchar_ci_not_equal, - LEFTARG = varchar_ci, - RIGHTARG = varchar_ci, - COMMUTATOR = <>, - NEGATOR = =, - RESTRICT = neqsel, - JOIN = neqjoinsel); - -CREATE OPERATOR =( - PROCEDURE = _varchar_ci_equal, - LEFTARG = varchar_ci, - RIGHTARG = varchar_ci, - COMMUTATOR = =, - NEGATOR = <>, - RESTRICT = eqsel, - JOIN = eqjoinsel, - HASHES, - MERGES, - SORT1= <); - -COMMIT; - diff --git a/phpBB/phpbb/install/schemas/schema_data.sql b/phpBB/phpbb/install/schemas/schema_data.sql deleted file mode 100644 index 1f856f016c..0000000000 --- a/phpBB/phpbb/install/schemas/schema_data.sql +++ /dev/null @@ -1,821 +0,0 @@ -# -# $Id$ -# - -# POSTGRES BEGIN # - -# -- Config -INSERT INTO phpbb_config (config_name, config_value) VALUES ('active_sessions', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_attachments', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_autologin', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_gravatar', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_local', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_remote', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_upload', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_remote_upload', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_bbcode', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_birthdays', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_bookmarks', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_cdn', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_emailreuse', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_password_reset', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_forum_notify', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_live_searches', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_mass_pm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_name_chars', 'USERNAME_CHARS_ANY'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_namechange', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_nocensors', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_pm_attach', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_pm_report', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_post_flash', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_post_links', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_privmsg', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_quick_reply', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_bbcode', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_flash', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_img', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_links', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_pm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_smilies', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_smilies', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_topic_notify', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('assets_version', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('attachment_quota', '52428800'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_bbcode_pm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_flash_pm', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_img_pm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_method', 'db'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_smilies_pm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_filesize', '6144'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_gallery_path', 'images/avatars/gallery'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_height', '90'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_width', '90'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_min_height', '20'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_min_width', '20'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_path', 'images/avatars/upload'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_salt', 'phpbb_avatar'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_contact', 'contact@yourdomain.tld'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_contact_name', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_disable', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_disable_msg', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email', 'address@yourdomain.tld'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_sig', '{L_CONFIG_BOARD_EMAIL_SIG}'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_hide_emails', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_index_text', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_timezone', 'UTC'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('browser_check', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_interval', '10'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_type', 'd'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('cache_gc', '7200'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_plugin', 'core.captcha.plugins.nogd'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_foreground_noise', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_x_grid', '25'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_y_grid', '25'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_wave', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_3d_noise', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_fonts', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('confirm_refresh', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_attachment_content', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_dnsbl', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('chg_passforce', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('contact_admin_form_enable', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_domain', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_name', 'phpbb3'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_path', '/'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_secure', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_enable', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_fax', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_mail', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('database_gc', '604800'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('dbms_version', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('default_dateformat', 'D M d, Y g:i a'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('default_style', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_last_edited', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_last_subject', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_order', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('edit_time', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('extension_force_unstable', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('delete_time', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_check_mx', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_enable', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_function_name', 'mail'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_max_chunk_size', '50'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_package_size', '20'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_confirm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_mod_rewrite', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_pm_icons', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_post_confirm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_enable', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_http_auth', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_limit_post', '15'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_limit_topic', '10'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_overall_forums', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_overall', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_forum', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_topic', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_topics_new', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_topics_active', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_item_statistics', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval', '15'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('force_server_vars', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_lifetime', '7200'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_mintime', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_sid_guests', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('forward_pm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('forwarded_for_check', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('full_folder_action', '2'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_mysql_max_word_len', '254'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_mysql_min_word_len', '4'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_common_thres', '5'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_load_upd', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_max_chars', '14'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_min_chars', '3'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_max_word_len', '254'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_min_word_len', '4'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_ts_name', 'simple'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_indexer_mem_limit', '512'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_stopwords', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('gzip_compress', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('hot_threshold', '25'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('icons_path', 'images/icons'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_create_thumbnail', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_display_inlined', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_imagick', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_link_height', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_link_width', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_height', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_thumb_width', '400'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_width', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_min_thumb_filesize', '12000'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_check', '3'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_login_limit_max', '50'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_login_limit_time', '21600'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_login_limit_use_forwarded', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_enable', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_host', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_password', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_package_size', '20'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_port', '5222'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_use_ssl', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_username', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_base_dn', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_email', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_password', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_port', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_server', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_uid', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_user', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_user_filter', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('legend_sort_groupname', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('limit_load', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('limit_search_load', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_anon_lastread', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_birthdays', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_memberlist', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_pm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewprofile', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewtopic', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_lastread', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_track', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jumpbox', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_moderators', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_notifications', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online_guests', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online_time', '5'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_onlinetrack', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_search', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_tplcompile', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_unreads_search', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_user_activity', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_attachments', '3'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_attachments_pm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_autologin_time', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_filesize', '262144'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_filesize_pm', '262144'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '3'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_name_chars', '20'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_num_search_keywords', '10'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_pass_chars', '100'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_poll_options', '10'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_chars', '60000'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_font_size', '200'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_img_height', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_img_width', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_smilies', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_urls', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_quote_depth', '3'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_reg_attempts', '5'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_chars', '255'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_font_size', '200'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_img_height', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_img_width', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_smilies', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_urls', '5'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_name_chars', '3'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_pass_chars', '6'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_post_chars', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_search_author_chars', '3'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('mime_triggers', 'body|head|html|img|plaintext|a href|pre|script|table|title'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('new_member_post_limit', '3'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('new_member_group_default', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('override_user_style', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('pass_complex', 'PASS_TYPE_ANY'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('plupload_salt', 'phpbb_plupload'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_edit_time', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_boxes', '4'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_msgs', '50'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_recipients', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('posts_per_page', '10'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('print_pm', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('queue_interval', '60'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('ranks_path', 'images/ranks'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_expire_days', '30'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_gc', '86400'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('referer_validation', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('script_path', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_block_size', '250'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_gc', '7200'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_interval', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_anonymous_interval', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_type', '\phpbb\search\fulltext_native'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_store_results', '1800'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_deny', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_empty_referer', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_downloads', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('server_name', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('server_port', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('server_protocol', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('session_gc', '3600'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('session_length', '3600'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('site_desc', '{L_CONFIG_SITE_DESC}'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('site_home_url', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('site_home_text', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('sitename', '{L_CONFIG_SITENAME}'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smilies_path', 'images/smilies'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smilies_per_page', '50'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_auth_method', 'PLAIN'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_delivery', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_host', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_port', '25'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_username', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_memberships', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_forums', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('topics_per_page', '25'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-a1-dev'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); - -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cache_last_gc', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cron_lock', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('database_last_gc', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('last_queue_run', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('newest_user_colour', 'AA0000', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('newest_user_id', '2', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('newest_username', '', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_files', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_posts', '1', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_topics', '1', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_users', '1', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('plupload_last_gc', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('rand_seed', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('rand_seed_last_update', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('read_notification_last_gc', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('record_online_date', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('record_online_users', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('search_indexing_state', '', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('search_last_gc', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('session_last_gc', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('upload_dir_size', '0', 1); -INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('warnings_last_gc', '0', 1); - -# Config text -INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info', ''); -INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_uid', ''); -INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_bitfield', ''); -INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_flags', '7'); - -# -- Forum related auth options -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_announce', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_attach', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bbcode', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bump', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_delete', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_download', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_edit', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_email', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_flash', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_icons', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_ignoreflood', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_img', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_list', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_noapprove', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_poll', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_post', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_postcount', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_print', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_read', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_reply', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_report', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_search', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_sigs', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_smilies', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_sticky', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_subscribe', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_user_lock', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_vote', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_votechg', 1); -INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_softdelete', 1); - -# -- Moderator related auth options -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_approve', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_chgposter', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_delete', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_edit', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_info', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_lock', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_merge', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_move', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_report', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_split', 1, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_softdelete', 1, 1); - -# -- Global moderator auth option (not a local option) -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_ban', 0, 1); -INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_warn', 0, 1); - -# -- Admin related auth options -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_aauth', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_attach', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_authgroups', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_authusers', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_backup', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_ban', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_bbcode', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_board', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_bots', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_clearlogs', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_email', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_extensions', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_fauth', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forum', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forumadd', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forumdel', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_group', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_groupadd', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_groupdel', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_icons', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_jabber', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_language', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_mauth', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_modules', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_names', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_phpinfo', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_profile', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_prune', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_ranks', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_reasons', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_roles', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_search', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_server', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_styles', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_switchperm', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_uauth', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_user', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_userdel', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_viewauth', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_viewlogs', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_words', 1); - -# -- User related auth options -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_attach', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgavatar', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgcensors', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgemail', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chggrp', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgname', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgpasswd', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgprofileinfo', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_download', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_hideonline', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_ignoreflood', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_masspm', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_masspm_group', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_attach', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_bbcode', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_delete', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_download', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_edit', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_emailpm', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_flash', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_forward', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_img', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_printpm', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_smilies', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_readpm', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_savedrafts', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_search', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sendemail', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sendim', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sendpm', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sig', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_viewonline', 1); -INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_viewprofile', 1); - - -# -- standard auth roles -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_STANDARD', 'ROLE_DESCRIPTION_ADMIN_STANDARD', 'a_', 1); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_FORUM', 'ROLE_DESCRIPTION_ADMIN_FORUM', 'a_', 3); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_USERGROUP', 'ROLE_DESCRIPTION_ADMIN_USERGROUP', 'a_', 4); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_FULL', 'ROLE_DESCRIPTION_ADMIN_FULL', 'a_', 2); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_FULL', 'ROLE_DESCRIPTION_USER_FULL', 'u_', 3); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_STANDARD', 'ROLE_DESCRIPTION_USER_STANDARD', 'u_', 1); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_LIMITED', 'ROLE_DESCRIPTION_USER_LIMITED', 'u_', 2); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NOPM', 'ROLE_DESCRIPTION_USER_NOPM', 'u_', 4); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NOAVATAR', 'ROLE_DESCRIPTION_USER_NOAVATAR', 'u_', 5); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_FULL', 'ROLE_DESCRIPTION_MOD_FULL', 'm_', 3); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_STANDARD', 'ROLE_DESCRIPTION_MOD_STANDARD', 'm_', 1); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_SIMPLE', 'ROLE_DESCRIPTION_MOD_SIMPLE', 'm_', 2); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_QUEUE', 'ROLE_DESCRIPTION_MOD_QUEUE', 'm_', 4); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_FULL', 'ROLE_DESCRIPTION_FORUM_FULL', 'f_', 7); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_STANDARD', 'ROLE_DESCRIPTION_FORUM_STANDARD', 'f_', 5); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NOACCESS', 'ROLE_DESCRIPTION_FORUM_NOACCESS', 'f_', 1); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_READONLY', 'ROLE_DESCRIPTION_FORUM_READONLY', 'f_', 2); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_LIMITED', 'ROLE_DESCRIPTION_FORUM_LIMITED', 'f_', 3); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_BOT', 'ROLE_DESCRIPTION_FORUM_BOT', 'f_', 9); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_ONQUEUE', 'ROLE_DESCRIPTION_FORUM_ONQUEUE', 'f_', 8); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_POLLS', 'ROLE_DESCRIPTION_FORUM_POLLS', 'f_', 6); -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_LIMITED_POLLS', 'ROLE_DESCRIPTION_FORUM_LIMITED_POLLS', 'f_', 4); - -# 23 -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NEW_MEMBER', 'ROLE_DESCRIPTION_USER_NEW_MEMBER', 'u_', 6); - -# 24 -INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NEW_MEMBER', 'ROLE_DESCRIPTION_FORUM_NEW_MEMBER', 'f_', 10); - -# -- phpbb_styles -INSERT INTO phpbb_styles (style_name, style_copyright, style_active, style_path, bbcode_bitfield, style_parent_id, style_parent_tree) VALUES ('prosilver', '© phpBB Limited', 1, 'prosilver', 'kNg=', 0, ''); - -# -- Forums -INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, forum_type, forum_posts_approved, forum_posts_unapproved, forum_posts_softdeleted, forum_topics_approved, forum_topics_unapproved, forum_topics_softdeleted, forum_last_post_id, forum_last_poster_id, forum_last_poster_name, forum_last_poster_colour, forum_last_post_time, forum_link, forum_password, forum_image, forum_rules, forum_rules_link, forum_rules_uid, forum_desc_uid, prune_days, prune_viewed, forum_parents) VALUES ('{L_FORUMS_FIRST_CATEGORY}', '', 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 'Admin', 'AA0000', 972086460, '', '', '', '', '', '', '', 0, 0, ''); - -INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, forum_type, forum_posts_approved, forum_posts_unapproved, forum_posts_softdeleted, forum_topics_approved, forum_topics_unapproved, forum_topics_softdeleted, forum_last_post_id, forum_last_poster_id, forum_last_poster_name, forum_last_poster_colour, forum_last_post_subject, forum_last_post_time, forum_link, forum_password, forum_image, forum_rules, forum_rules_link, forum_rules_uid, forum_desc_uid, prune_days, prune_viewed, forum_parents, forum_flags) VALUES ('{L_FORUMS_TEST_FORUM_TITLE}', '{L_FORUMS_TEST_FORUM_DESC}', 2, 3, 1, 1, 1, 0, 0, 1, 0, 0, 1, 2, 'Admin', 'AA0000', '{L_TOPICS_TOPIC_TITLE}', 972086460, '', '', '', '', '', '', '', 0, 0, '', 48); - -# -- Users / Anonymous user -INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_jabber, user_actkey, user_newpasswd, user_allow_massemail) VALUES (2, 1, 'Anonymous', 'anonymous', 0, '', '', 'en', 1, 0, '', 0, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', '', 0); - -# -- username: Admin password: admin (change this or remove it once everything is working!) -INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_jabber, user_actkey, user_newpasswd) VALUES (3, 5, 'Admin', 'admin', 0, '21232f297a57a5a743894a0e4a801fc3', 'admin@yourdomain.com', 'en', 1, 1, 'AA0000', 1, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', ''); - -# -- Groups -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('GUESTS', 3, 0, '', 0, '', '', '', 5); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('REGISTERED', 3, 0, '', 0, '', '', '', 5); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('REGISTERED_COPPA', 3, 0, '', 0, '', '', '', 5); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('GLOBAL_MODERATORS', 3, 0, '00AA00', 2, '', '', '', 0); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('ADMINISTRATORS', 3, 1, 'AA0000', 1, '', '', '', 0); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('BOTS', 3, 0, '9E8DA7', 0, '', '', '', 5); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('NEWLY_REGISTERED', 3, 0, '', 0, '', '', '', 5); - -# -- Teampage -INSERT INTO phpbb_teampage (group_id, teampage_name, teampage_position, teampage_parent) VALUES (5, '', 1, 0); -INSERT INTO phpbb_teampage (group_id, teampage_name, teampage_position, teampage_parent) VALUES (4, '', 2, 0); - -# -- User -> Group -INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (1, 1, 0, 0); -INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (2, 2, 0, 0); -INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (4, 2, 0, 0); -INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (5, 2, 0, 1); - -# -- Ranks -INSERT INTO phpbb_ranks (rank_title, rank_min, rank_special, rank_image) VALUES ('{L_RANKS_SITE_ADMIN_TITLE}', 0, 1, ''); - -# -- Roles data - -# Standard Admin (a_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 1, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%' AND auth_option NOT IN ('a_switchperm', 'a_jabber', 'a_phpinfo', 'a_server', 'a_backup', 'a_styles', 'a_clearlogs', 'a_modules', 'a_language', 'a_email', 'a_bots', 'a_search', 'a_aauth', 'a_roles'); - -# Forum admin (a_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 2, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%' AND auth_option IN ('a_', 'a_authgroups', 'a_authusers', 'a_fauth', 'a_forum', 'a_forumadd', 'a_forumdel', 'a_mauth', 'a_prune', 'a_uauth', 'a_viewauth', 'a_viewlogs'); - -# User and Groups Admin (a_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 3, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%' AND auth_option IN ('a_', 'a_authgroups', 'a_authusers', 'a_ban', 'a_group', 'a_groupadd', 'a_groupdel', 'a_ranks', 'a_uauth', 'a_user', 'a_viewauth', 'a_viewlogs'); - -# Full Admin (a_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 4, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%'; - -# All Features (u_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 5, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%'; - -# Standard Features (u_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 6, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_flash', 'u_pm_forward'); - -# Limited Features (u_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 7, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim', 'u_masspm', 'u_masspm_group'); - -# No Private Messages (u_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 8, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_', 'u_chgavatar', 'u_chgcensors', 'u_chgemail', 'u_chgpasswd', 'u_download', 'u_hideonline', 'u_sig', 'u_viewprofile'); -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 8, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_readpm', 'u_sendpm', 'u_masspm', 'u_masspm_group'); - -# No Avatar (u_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_chgavatar', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim', 'u_masspm', 'u_masspm_group'); -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_chgavatar'); - -# Full Moderator (m_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 10, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%'; - -# Standard Moderator (m_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 11, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%' AND auth_option NOT IN ('m_ban', 'm_chgposter'); - -# Simple Moderator (m_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 12, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%' AND auth_option IN ('m_', 'm_delete', 'm_softdelete', 'm_edit', 'm_info', 'm_report'); - -# Queue Moderator (m_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 13, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%' AND auth_option IN ('m_', 'm_approve', 'm_edit'); - -# Full Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 14, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%'; - -# Standard Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 15, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock'); - -# No Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 16, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option = 'f_'; - -# Read Only Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 17, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_search', 'f_subscribe', 'f_print'); - -# Limited Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 18, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg'); - -# Bot Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 19, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_print'); - -# On Moderation Queue (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg', 'f_noapprove'); -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove'); - -# Standard Access + Polls (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 21, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_sticky', 'f_user_lock'); - -# Limited Access + Polls (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 22, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_sticky', 'f_user_lock', 'f_votechg'); - -# New Member (u_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 23, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group', 'u_chgprofileinfo'); - -# New Member (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 24, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove'); - - -# Permissions - -# GUESTS - u_download and u_search ability -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) SELECT 1, 0, auth_option_id, 0, 1 FROM phpbb_acl_options WHERE auth_option IN ('u_', 'u_download', 'u_search'); - -# Admin user - full user features -INSERT INTO phpbb_acl_users (user_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 0, 0, 5, 0); - -# ADMINISTRATOR Group - full user features -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 0, 0, 5, 0); - -# ADMINISTRATOR Group - standard admin -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 0, 0, 1, 0); - -# REGISTERED and REGISTERED_COPPA having standard user features -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 0, 0, 6, 0); -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (3, 0, 0, 6, 0); - -# GLOBAL_MODERATORS having full user features -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (4, 0, 0, 5, 0); - -# GLOBAL_MODERATORS having full global moderator access -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (4, 0, 0, 10, 0); - -# Giving all groups read only access to the first category -# since administrators and moderators are already within the registered users group we do not need to set them here -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (1, 1, 0, 17, 0); -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 1, 0, 17, 0); -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (3, 1, 0, 17, 0); -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (6, 1, 0, 17, 0); - -# Giving access to the first forum - -# guests having read only access -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (1, 2, 0, 17, 0); - -# registered and registered_coppa having standard access -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 2, 0, 15, 0); -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (3, 2, 0, 15, 0); - -# global moderators having standard access + polls -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (4, 2, 0, 21, 0); - -# administrators having full forum and full moderator access -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 2, 0, 14, 0); -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 2, 0, 10, 0); - -# Bots having bot access -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (6, 2, 0, 19, 0); - -# NEW MEMBERS are not allowed to send private messages -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (7, 0, 0, 23, 0); - -# NEW MEMBERS on the queue -INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (7, 2, 0, 24, 0); - - -# -- Demo Topic -INSERT INTO phpbb_topics (topic_title, topic_poster, topic_time, topic_views, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, forum_id, topic_status, topic_type, topic_first_post_id, topic_first_poster_name, topic_first_poster_colour, topic_last_post_id, topic_last_poster_id, topic_last_poster_name, topic_last_poster_colour, topic_last_post_subject, topic_last_post_time, topic_last_view_time, poll_title, topic_visibility) VALUES ('{L_TOPICS_TOPIC_TITLE}', 2, 972086460, 0, 1, 0, 0, 2, 0, 0, 1, 'Admin', 'AA0000', 1, 2, 'Admin', 'AA0000', '{L_TOPICS_TOPIC_TITLE}', 972086460, 972086460, '', 1); - -# -- Demo Post -INSERT INTO phpbb_posts (topic_id, forum_id, poster_id, icon_id, post_time, post_username, poster_ip, post_subject, post_text, post_checksum, bbcode_uid, post_visibility) VALUES (1, 2, 2, 0, 972086460, '', '127.0.0.1', '{L_TOPICS_TOPIC_TITLE}', '{L_DEFAULT_INSTALL_POST}', '5dd683b17f641daf84c040bfefc58ce9', '', 1); - -# -- Admin posted to the demo topic -INSERT INTO phpbb_topics_posted (user_id, topic_id, topic_posted) VALUES (2, 1, 1); - -# -- Smilies -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':D', 'icon_e_biggrin.gif', '{L_SMILIES_VERY_HAPPY}', 15, 17, 1); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-D', 'icon_e_biggrin.gif', '{L_SMILIES_VERY_HAPPY}', 15, 17, 2); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':grin:', 'icon_e_biggrin.gif', '{L_SMILIES_VERY_HAPPY}', 15, 17, 3); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':)', 'icon_e_smile.gif', '{L_SMILIES_SMILE}', 15, 17, 4); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-)', 'icon_e_smile.gif', '{L_SMILIES_SMILE}', 15, 17, 5); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':smile:', 'icon_e_smile.gif', '{L_SMILIES_SMILE}', 15, 17, 6); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (';)', 'icon_e_wink.gif', '{L_SMILIES_WINK}', 15, 17, 7); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (';-)', 'icon_e_wink.gif', '{L_SMILIES_WINK}', 15, 17, 8); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':wink:', 'icon_e_wink.gif', '{L_SMILIES_WINK}', 15, 17, 9); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':(', 'icon_e_sad.gif', '{L_SMILIES_SAD}', 15, 17, 10); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-(', 'icon_e_sad.gif', '{L_SMILIES_SAD}', 15, 17, 11); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':sad:', 'icon_e_sad.gif', '{L_SMILIES_SAD}', 15, 17, 12); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':o', 'icon_e_surprised.gif', '{L_SMILIES_SURPRISED}', 15, 17, 13); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-o', 'icon_e_surprised.gif', '{L_SMILIES_SURPRISED}', 15, 17, 14); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':eek:', 'icon_e_surprised.gif', '{L_SMILIES_SURPRISED}', 15, 17, 15); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':shock:', 'icon_eek.gif', '{L_SMILIES_SHOCKED}', 15, 17, 16); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':?', 'icon_e_confused.gif', '{L_SMILIES_CONFUSED}', 15, 17, 17); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-?', 'icon_e_confused.gif', '{L_SMILIES_CONFUSED}', 15, 17, 18); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':???:', 'icon_e_confused.gif', '{L_SMILIES_CONFUSED}', 15, 17, 19); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES ('8-)', 'icon_cool.gif', '{L_SMILIES_COOL}', 15, 17, 20); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':cool:', 'icon_cool.gif', '{L_SMILIES_COOL}', 15, 17, 21); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':lol:', 'icon_lol.gif', '{L_SMILIES_LAUGHING}', 15, 17, 22); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':x', 'icon_mad.gif', '{L_SMILIES_MAD}', 15, 17, 23); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-x', 'icon_mad.gif', '{L_SMILIES_MAD}', 15, 17, 24); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':mad:', 'icon_mad.gif', '{L_SMILIES_MAD}', 15, 17, 25); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':P', 'icon_razz.gif', '{L_SMILIES_RAZZ}', 15, 17, 26); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-P', 'icon_razz.gif', '{L_SMILIES_RAZZ}', 15, 17, 27); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':razz:', 'icon_razz.gif', '{L_SMILIES_RAZZ}', 15, 17, 28); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':oops:', 'icon_redface.gif', '{L_SMILIES_EMARRASSED}', 15, 17, 29); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':cry:', 'icon_cry.gif', '{L_SMILIES_CRYING}', 15, 17, 30); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':evil:', 'icon_evil.gif', '{L_SMILIES_EVIL}', 15, 17, 31); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':twisted:', 'icon_twisted.gif', '{L_SMILIES_TWISTED_EVIL}', 15, 17, 32); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':roll:', 'icon_rolleyes.gif', '{L_SMILIES_ROLLING_EYES}', 15, 17, 33); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':!:', 'icon_exclaim.gif', '{L_SMILIES_EXCLAMATION}', 15, 17, 34); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':?:', 'icon_question.gif', '{L_SMILIES_QUESTION}', 15, 17, 35); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':idea:', 'icon_idea.gif', '{L_SMILIES_IDEA}', 15, 17, 36); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':arrow:', 'icon_arrow.gif', '{L_SMILIES_ARROW}', 15, 17, 37); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':|', 'icon_neutral.gif', '{L_SMILIES_NEUTRAL}', 15, 17, 38); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-|', 'icon_neutral.gif', '{L_SMILIES_NEUTRAL}', 15, 17, 39); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':mrgreen:', 'icon_mrgreen.gif', '{L_SMILIES_MR_GREEN}', 15, 17, 40); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':geek:', 'icon_e_geek.gif', '{L_SMILIES_GEEK}', 17, 17, 41); -INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':ugeek:', 'icon_e_ugeek.gif', '{L_SMILIES_UBER_GEEK}', 17, 18, 42); - -# -- icons -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/fire.gif', 16, 16, 1, 1); -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/redface.gif', 16, 16, 9, 1); -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/mrgreen.gif', 16, 16, 10, 1); -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/heart.gif', 16, 16, 4, 1); -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/star.gif', 16, 16, 2, 1); -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/radioactive.gif', 16, 16, 3, 1); -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/thinking.gif', 16, 16, 5, 1); -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/info.gif', 16, 16, 8, 1); -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/question.gif', 16, 16, 6, 1); -INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/alert.gif', 16, 16, 7, 1); - -# -- reasons -INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('warez', '{L_REPORT_WAREZ}', 1); -INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('spam', '{L_REPORT_SPAM}', 2); -INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('off_topic', '{L_REPORT_OFF_TOPIC}', 3); -INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('other', '{L_REPORT_OTHER}', 4); - -# -- extension_groups -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('IMAGES', 1, 1, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('ARCHIVES', 0, 1, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('PLAIN_TEXT', 0, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOCUMENTS', 0, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('REAL_MEDIA', 3, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('WINDOWS_MEDIA', 2, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('FLASH_FILES', 5, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('QUICKTIME_MEDIA', 6, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOWNLOADABLE_FILES', 0, 0, 1, '', 0, ''); - -# -- extensions -INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'gif'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'png'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'jpeg'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'jpg'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'tif'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'tiff'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'tga'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'gtar'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'gz'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'tar'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'zip'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'rar'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'ace'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'torrent'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'tgz'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'bz2'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, '7z'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'txt'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'c'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'h'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'cpp'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'hpp'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'diz'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'csv'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'ini'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'log'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'js'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'xml'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xls'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xlsx'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xlsm'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xlsb'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'doc'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'docx'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'docm'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'dot'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'dotx'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'dotm'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'pdf'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ai'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ps'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ppt'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'pptx'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'pptm'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odg'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odp'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ods'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odt'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'rtf'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'rm'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'ram'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wma'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wmv'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (7, 'swf'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mov'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4v'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4a'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mp4'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3gp'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3g2'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'qt'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpeg'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpg'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mp3'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogg'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogm'); - -# Add default profile fields -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_location', 'profilefields.type.string', 'phpbb_location', '20', '2', '100', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, '', ''); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_website', 'profilefields.type.url', 'phpbb_website', '40', '12', '255', '', '', '', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 2, 1, 'VISIT_WEBSITE', '%s'); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_interests', 'profilefields.type.text', 'phpbb_interests', '3|30', '2', '500', '', '', '.*', 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, '', ''); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_occupation', 'profilefields.type.text', 'phpbb_occupation', '3|30', '2', '500', '', '', '.*', 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, '', ''); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_aol', 'profilefields.type.string', 'phpbb_aol', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 5, 1, '', ''); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_icq', 'profilefields.type.string', 'phpbb_icq', '20', '3', '15', '', '', '[0-9]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 6, 1, 'SEND_ICQ_MESSAGE', 'https://www.icq.com/people/%s/'); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_wlm', 'profilefields.type.string', 'phpbb_wlm', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 7, 1, '', ''); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_yahoo', 'profilefields.type.string', 'phpbb_yahoo', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 8, 1, 'SEND_YIM_MESSAGE', 'ymsgr:sendim?%s'); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_facebook', 'profilefields.type.string', 'phpbb_facebook', '20', '5', '50', '', '', '[\w.]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 9, 1, 'VIEW_FACEBOOK_PROFILE', 'http://facebook.com/%s/'); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_twitter', 'profilefields.type.string', 'phpbb_twitter', '20', '1', '15', '', '', '[\w_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 10, 1, 'VIEW_TWITTER_PROFILE', 'http://twitter.com/%s'); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_skype', 'profilefields.type.string', 'phpbb_skype', '20', '6', '32', '', '', '[a-zA-Z][\w\.,\-_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 11, 1, 'VIEW_SKYPE_PROFILE', 'skype:%s?userinfo'); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_youtube', 'profilefields.type.string', 'phpbb_youtube', '20', '3', '60', '', '', '[a-zA-Z][\w\.,\-_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 12, 1, 'VIEW_YOUTUBE_CHANNEL', 'http://youtube.com/user/%s'); -INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_googleplus', 'profilefields.type.googleplus', 'phpbb_googleplus', '20', '3', '255', '', '', '[\w]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 13, 1, 'VIEW_GOOGLEPLUS_PROFILE', 'http://plus.google.com/%s'); - -# User Notification Options (for first user) -INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, ''); -INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, 'notification.method.email'); -INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, ''); -INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, 'notification.method.email'); - -# POSTGRES COMMIT # From 4ae83e426663d129d7068b312097ad968242f41f Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Wed, 29 Jul 2015 22:08:37 +0200 Subject: [PATCH 0555/1676] [ticket/14056] Fix remaining schema path PHPBB3-14056 --- .../install/module/install_database/task/create_schema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php index cbec5edb6d..7cc521eee8 100644 --- a/phpBB/phpbb/install/module/install_database/task/create_schema.php +++ b/phpBB/phpbb/install/module/install_database/task/create_schema.php @@ -119,7 +119,7 @@ class create_schema extends \phpbb\install\task_base } } - $db_schema_path = $this->phpbb_root_path . 'phpbb/install/schemas/' . $schema_name . '_schema.sql'; + $db_schema_path = $this->phpbb_root_path . 'install/schemas/' . $schema_name . '_schema.sql'; // Load database vendor specific code if there is any if ($this->filesystem->exists($db_schema_path)) From 2b30e632b6e266ef64d075ac0897972a8bb43bf1 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Thu, 28 May 2015 15:45:47 +0200 Subject: [PATCH 0556/1676] [ticket/12143] Add is_set method to language service We need that. PHPBB3-12143 --- phpBB/phpbb/language/language.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/phpBB/phpbb/language/language.php b/phpBB/phpbb/language/language.php index 44131e3da3..3ffb466c19 100644 --- a/phpBB/phpbb/language/language.php +++ b/phpBB/phpbb/language/language.php @@ -193,6 +193,36 @@ class language } } + /** + * @param $key array|string The language key we want to know more about. Can be string or array. + * + * @return bool Returns whether the language key is set. + */ + public function is_set($key) + { + // Load common language files if they not loaded yet + if (!$this->common_language_files_loaded) + { + $this->load_common_language_files(); + } + + if (is_array($key)) + { + $lang = &$this->lang[array_shift($key)]; + + foreach ($key as $_key) + { + $lang = &$lang[$_key]; + } + } + else + { + $lang = &$this->lang[$key]; + } + + return isset($lang); + } + /** * Advanced language substitution * From 4b3343e756be45ac1ca26e976ba79e6353f41de3 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Thu, 28 May 2015 15:57:20 +0200 Subject: [PATCH 0557/1676] [ticket/12143] Add group helper class to translate groupnames We can translate groupnames now even though these groups aren't special PHPBB3-12143 --- phpBB/config/default/container/services.yml | 5 +++ phpBB/phpbb/group/helper.php | 40 +++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 phpBB/phpbb/group/helper.php diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 841b50c38b..1daf35b3fb 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -113,6 +113,11 @@ services: file_downloader: class: phpbb\file_downloader + group_helper: + class: phpbb\group\helper + arguments: + - @language + log: class: phpbb\log\log arguments: diff --git a/phpBB/phpbb/group/helper.php b/phpBB/phpbb/group/helper.php new file mode 100644 index 0000000000..5befddfc53 --- /dev/null +++ b/phpBB/phpbb/group/helper.php @@ -0,0 +1,40 @@ + + * @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\group; + +class helper +{ + /** @var \phpbb\language\language */ + protected $language; + + /** + * Constructor + * + * @param \phpbb\language\language $language Language object + */ + public function __construct(\phpbb\language\language $language) + { + $this->language = $language; + } + + /** + * @param $group_name string The stored group name + * + * @return string Group name or translated group name if it exists + */ + public function get_name($group_name) + { + return $this->language->is_set('G_' . utf8_strtoupper($group_name)) ? $this->language->lang('G_' . utf8_strtoupper($group_name)) : $group_name; + } +} From 185fbe41c954640a0aa5632b541055005ef776c2 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Thu, 28 May 2015 17:31:21 +0200 Subject: [PATCH 0558/1676] [ticket/12143] Replace group name output So now we can use translated group names for non-special groups PHPBB3-12143 --- phpBB/includes/acp/acp_groups.php | 26 ++++++++++++++++---------- phpBB/includes/acp/acp_permissions.php | 22 ++++++++++++++++------ phpBB/includes/acp/acp_prune.php | 7 +++++-- phpBB/includes/acp/acp_users.php | 5 ++++- phpBB/includes/acp/auth.php | 20 ++++++++++---------- phpBB/includes/functions_admin.php | 7 +++++-- phpBB/includes/functions_display.php | 6 +++++- phpBB/includes/functions_privmsgs.php | 16 +++++++++++----- phpBB/includes/functions_user.php | 14 ++++++++++---- phpBB/includes/ucp/ucp_groups.php | 19 +++++++++++-------- phpBB/includes/ucp/ucp_pm_compose.php | 7 +++++-- phpBB/includes/ucp/ucp_pm_options.php | 9 ++++++--- phpBB/index.php | 5 ++++- phpBB/memberlist.php | 21 +++++++++------------ phpBB/viewonline.php | 5 ++++- 15 files changed, 121 insertions(+), 68 deletions(-) diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index 57fa52fba3..138234caee 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -54,6 +54,9 @@ class acp_groups $start = $request->variable('start', 0); $update = (isset($_POST['update'])) ? true : false; + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + // Clear some vars $group_row = array(); @@ -98,7 +101,7 @@ class acp_groups } // Approve, demote or promote - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); $error = group_user_attributes($action, $group_id, $mark_ary, false, $group_name); if (!$error) @@ -139,7 +142,7 @@ class acp_groups if (confirm_box(true)) { - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); } @@ -158,7 +161,7 @@ class acp_groups case 'set_default_on_all': if (confirm_box(true)) { - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); $start = 0; @@ -236,7 +239,7 @@ class acp_groups break; case 'deleteusers': - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); $error = group_user_del($group_id, $mark_ary, false, $group_name); break; } @@ -280,7 +283,7 @@ class acp_groups } $name_ary = array_unique(explode("\n", $name_ary)); - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); // Add user/s to group if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, $leader, 0, $group_row)) @@ -720,7 +723,7 @@ class acp_groups 'S_AVATARS_ENABLED' => ($config['allow_avatar'] && $avatars_enabled), 'ERROR_MSG' => (sizeof($error)) ? implode('
      ', $error) : '', - 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, + 'GROUP_NAME' => $group_helper->get_name($group_name), 'GROUP_INTERNAL_NAME' => $group_name, 'GROUP_DESC' => $group_desc_data['text'], 'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '', @@ -855,7 +858,7 @@ class acp_groups 'S_GROUP_SPECIAL' => ($group_row['group_type'] == GROUP_SPECIAL) ? true : false, 'S_ACTION_OPTIONS' => $s_action_options, - 'GROUP_NAME' => ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'], + 'GROUP_NAME' => $group_helper->get_name($group_row['group_name']), 'U_ACTION' => $this->u_action . "&g=$group_id", 'U_BACK' => $this->u_action, @@ -984,6 +987,9 @@ class acp_groups $teampage_id = $request->variable('t', 0); $category_id = $request->variable('c', 0); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + if ($field && !in_array($field, array('legend', 'teampage'))) { // Invalid mode @@ -1086,7 +1092,7 @@ class acp_groups $s_group_select_legend = ''; while ($row = $db->sql_fetchrow($result)) { - $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $group_name = $group_helper->get_name($row['group_name']); if ($row['group_legend']) { $template->assign_block_vars('legend', array( @@ -1134,7 +1140,7 @@ class acp_groups if ($row['group_id']) { - $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $group_name = $group_helper->get_name($row['group_name']); $group_type = $user->lang[\phpbb\groupposition\teampage::group_type_language($row['group_type'])]; } else @@ -1167,7 +1173,7 @@ class acp_groups $s_group_select_teampage = ''; while ($row = $db->sql_fetchrow($result)) { - $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $group_name = $group_helper->get_name($row['group_name']); $template->assign_block_vars('add_teampage', array( 'GROUP_ID' => (int) $row['group_id'], 'GROUP_NAME' => $group_name, diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index b36eae0f93..edd0a836f2 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -909,7 +909,7 @@ class acp_permissions */ function log_action($mode, $action, $permission_type, $ug_type, $ug_id, $forum_id) { - global $db, $user, $phpbb_log; + global $db, $user, $phpbb_log, $phpbb_container; if (!is_array($ug_id)) { @@ -926,10 +926,14 @@ class acp_permissions $sql .= $db->sql_in_set(($ug_type == 'group') ? 'group_id' : 'user_id', array_map('intval', $ug_id)); $result = $db->sql_query($sql); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + $l_ug_list = ''; while ($row = $db->sql_fetchrow($result)) { - $l_ug_list .= (($l_ug_list != '') ? ', ' : '') . ((isset($row['group_type']) && $row['group_type'] == GROUP_SPECIAL) ? '' . $user->lang['G_' . $row['name']] . '' : $row['name']); + $group_name = $group_helper->get_name($row['group_name']); + $l_ug_list .= (($l_ug_list != '') ? ', ' : '') . ((isset($row['group_type']) && $row['group_type'] == GROUP_SPECIAL) ? '' . $group_name . '' : $group_name); } $db->sql_freeresult($result); @@ -963,7 +967,7 @@ class acp_permissions */ function permission_trace($user_id, $forum_id, $permission) { - global $db, $template, $user, $auth, $request; + global $db, $template, $user, $auth, $request, $phpbb_container; if ($user_id != $user->data['user_id']) { @@ -979,6 +983,9 @@ class acp_permissions trigger_error('NO_USERS', E_USER_ERROR); } + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + $forum_name = false; if ($forum_id) @@ -1025,7 +1032,7 @@ class acp_permissions { $groups[$row['group_id']] = array( 'auth_setting' => ACL_NO, - 'group_name' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'] + 'group_name' => $group_helper->get_name($row['group_name']), ); } $db->sql_freeresult($result); @@ -1233,7 +1240,10 @@ class acp_permissions */ function retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type) { - global $db, $user; + global $db, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $sql_forum_id = ($permission_scope == 'global') ? 'AND a.forum_id = 0' : ((sizeof($forum_id)) ? 'AND ' . $db->sql_in_set('a.forum_id', $forum_id) : 'AND a.forum_id <> 0'); @@ -1308,7 +1318,7 @@ class acp_permissions $defined_group_ids = array(); while ($row = $db->sql_fetchrow($result)) { - $s_defined_group_options .= '' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . ''; + $s_defined_group_options .= '' . $group_helper->get_name($row['group_name']) . ''; $defined_group_ids[] = $row['group_id']; } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php index ed40b0d424..025ace9809 100644 --- a/phpBB/includes/acp/acp_prune.php +++ b/phpBB/includes/acp/acp_prune.php @@ -230,7 +230,10 @@ class acp_prune function prune_users($id, $mode) { global $db, $user, $auth, $template, $cache, $phpbb_log, $request; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $user->add_lang('memberlist'); @@ -342,7 +345,7 @@ class acp_prune $s_group_list = ''; while ($row = $db->sql_fetchrow($result)) { - $s_group_list .= ''; + $s_group_list .= ''; } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 0ec17ccf0c..bbc8e73cb8 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -2348,6 +2348,9 @@ class acp_users $error = array(); } + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + $sql = 'SELECT ug.*, g.* FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . " ug WHERE ug.user_id = $user_id @@ -2392,7 +2395,7 @@ class acp_users continue; } - $s_group_options .= '' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . ''; + $s_group_options .= '' . $group_helper->get_name($row['group_name']) . ''; } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index b13b1ee040..2c4c82fcc7 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -271,6 +271,9 @@ class auth_admin extends \phpbb\auth\auth /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + // Define names for template loops, might be able to be set $tpl_pmask = 'p_mask'; $tpl_fmask = 'f_mask'; @@ -302,7 +305,7 @@ class auth_admin extends \phpbb\auth\auth $ug_names_ary = array(); while ($row = $db->sql_fetchrow($result)) { - $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['ug_name']] : $row['ug_name']); + $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : $group_helper->get_name($row['ug_name']); } $db->sql_freeresult($result); @@ -410,14 +413,7 @@ class auth_admin extends \phpbb\auth\auth { foreach ($memberships as $row) { - if ($groups[$row['group_id']]['group_type'] == GROUP_SPECIAL) - { - $user_groups_default[$row['user_id']][] = $user->lang['G_' . $groups[$row['group_id']]['group_name']]; - } - else - { - $user_groups_custom[$row['user_id']][] = $groups[$row['group_id']]['group_name']; - } + $user_groups_default[$row['user_id']][] = $group_helper->get_name($groups[$row['group_id']]['group_name']); } } unset($memberships, $groups); @@ -612,12 +608,16 @@ class auth_admin extends \phpbb\auth\auth function display_role_mask(&$hold_ary) { global $db, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $phpbb_container; if (!sizeof($hold_ary)) { return; } + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + // Get forum names $sql = 'SELECT forum_id, forum_name FROM ' . FORUMS_TABLE . ' @@ -673,7 +673,7 @@ class auth_admin extends \phpbb\auth\auth { $template->assign_block_vars('role_mask.groups', array( 'GROUP_ID' => $row['group_id'], - 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_NAME' => $group_helper->get_name($row['group_name']), 'U_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=group&g={$row['group_id']}")) ); } diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 7ca1f621ff..cd8dcc2734 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -171,7 +171,10 @@ function size_select_options($size_compare) */ function group_select_options($group_id, $exclude_ids = false, $manage_founder = false) { - global $db, $user, $config; + global $db, $config, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE ' . $db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : ''; $sql_and = (!$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name <> 'REGISTERED_COPPA'" : ''; @@ -189,7 +192,7 @@ function group_select_options($group_id, $exclude_ids = false, $manage_founder = while ($row = $db->sql_fetchrow($result)) { $selected = ($row['group_id'] == $group_id) ? ' selected="selected"' : ''; - $s_group_options .= '' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . ''; + $s_group_options .= '' . $group_helper->get_name($row['group_name']) . ''; } $db->sql_freeresult($result); diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 3a96119dbe..c53a9f3bc0 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -886,6 +886,7 @@ function get_forum_parents(&$forum_data) function get_moderators(&$forum_moderators, $forum_id = false) { global $config, $template, $db, $phpbb_root_path, $phpEx, $user, $auth; + global $phpbb_container; $forum_id_ary = array(); @@ -921,6 +922,9 @@ function get_moderators(&$forum_moderators, $forum_id = false) 'WHERE' => 'm.display_on_index = 1', ); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + // We query every forum here because for caching we should not have any parameter. $sql = $db->sql_build_query('SELECT', $sql_array); $result = $db->sql_query($sql, 3600); @@ -940,7 +944,7 @@ function get_moderators(&$forum_moderators, $forum_id = false) } else { - $group_name = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']); + $group_name = $group_helper->get_name($row['group_name']); if ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) { diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index c8c2670986..7b6540cda7 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1436,7 +1436,10 @@ function rebuild_header($check_ary) */ function write_pm_addresses($check_ary, $author_id, $plaintext = false) { - global $db, $user, $template, $phpbb_root_path, $phpEx; + global $db, $user, $template, $phpbb_root_path, $phpEx, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $addresses = array(); @@ -1497,7 +1500,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) { if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) { - $address[] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $address[] = $group_helper->get_name($row['group_name']); } } $db->sql_freeresult($result); @@ -1517,7 +1520,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) { if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) { - $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $row['group_name'] = $group_helper->get_name($row['group_name']); $address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']); } } @@ -2178,7 +2181,10 @@ function phpbb_get_max_setting_from_group(\phpbb\db\driver\driver_interface $db, */ function get_recipient_strings($pm_by_id) { - global $db, $phpbb_root_path, $phpEx, $user; + global $db, $phpbb_root_path, $phpEx, $user, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $address_list = $recipient_list = $address = array(); @@ -2224,7 +2230,7 @@ function get_recipient_strings($pm_by_id) { if ($ug_type == 'g') { - $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name']; + $row['name'] = $group_helper->get_name($row['name']); } $recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']); diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 45263ad018..e17a8b8d73 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -2215,6 +2215,9 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow { global $phpbb_root_path, $config, $db, $user, $file_upload, $phpbb_container, $phpbb_log; + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + $error = array(); // Attributes which also affect the users table @@ -2466,7 +2469,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow group_set_user_default($group_id, $user_ary, $sql_ary); } - $name = ($type == GROUP_SPECIAL) ? $user->lang['G_' . $name] : $name; + $name = $group_helper->get_name($name); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($name)); group_update_listings($group_id); @@ -3320,7 +3323,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal */ function get_group_name($group_id) { - global $db, $user; + global $db, $user, $phpbb_container; $sql = 'SELECT group_name, group_type FROM ' . GROUPS_TABLE . ' @@ -3329,12 +3332,15 @@ function get_group_name($group_id) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if (!$row || ($row['group_type'] == GROUP_SPECIAL && !$user->is_setup())) + if (!$row || !$user->is_setup()) { return ''; } - return ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + + return $group_helper->get_name($row['group_name']); } /** diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index 3228ffb469..2746e74ffe 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -41,6 +41,9 @@ class ucp_groups $delete = $request->variable('delete', false, false, \phpbb\request\request_interface::POST); $error = $data = array(); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + switch ($mode) { case 'membership': @@ -65,7 +68,7 @@ class ucp_groups $group_row = array(); while ($row = $db->sql_fetchrow($result)) { - $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $row['group_name'] = $group_helper->get_name($row['group_name']); $group_row[$row['group_id']] = $row; } $db->sql_freeresult($result); @@ -307,7 +310,7 @@ class ucp_groups $template->assign_block_vars($block, array( 'GROUP_ID' => $row['group_id'], - 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_NAME' => $group_helper->get_name($row['group_name']), 'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'], 'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true, 'GROUP_STATUS' => $user->lang['GROUP_IS_' . $group_status], @@ -361,7 +364,7 @@ class ucp_groups $template->assign_block_vars('nonmember', array( 'GROUP_ID' => $row['group_id'], - 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_NAME' => $group_helper->get_name($row['group_name']), 'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'], 'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true, 'GROUP_CLOSED' => ($row['group_type'] <> GROUP_CLOSED || $auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? false : true, @@ -426,7 +429,7 @@ class ucp_groups $avatar = phpbb_get_group_avatar($group_row, 'GROUP_AVATAR', true); $template->assign_vars(array( - 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, + 'GROUP_NAME' => $group_helper->get_name($group_name), 'GROUP_INTERNAL_NAME' => $group_name, 'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '', 'GROUP_DESC_DISP' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']), @@ -901,7 +904,7 @@ class ucp_groups trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); } - $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_row['group_name'] = $group_helper->get_name($group_row['group_name']); if (confirm_box(true)) { @@ -980,7 +983,7 @@ class ucp_groups trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); } - $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_row['group_name'] = $group_helper->get_name($group_row['group_name']); if (confirm_box(true)) { @@ -1042,7 +1045,7 @@ class ucp_groups } $name_ary = array_unique(explode("\n", $names)); - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); $default = $request->variable('default', 0); @@ -1088,7 +1091,7 @@ class ucp_groups while ($value = $db->sql_fetchrow($result)) { $template->assign_block_vars('leader', array( - 'GROUP_NAME' => ($value['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $value['group_name']] : $value['group_name'], + 'GROUP_NAME' => $group_helper->get_name($value['group_name']), 'GROUP_DESC' => generate_text_for_display($value['group_desc'], $value['group_desc_uid'], $value['group_desc_bitfield'], $value['group_desc_options']), 'GROUP_TYPE' => $value['group_type'], 'GROUP_ID' => $value['group_id'], diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index c00363bee9..5c32a23ad6 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -76,6 +76,9 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $error = array(); $current_time = time(); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + // Was cancel pressed? If so then redirect to the appropriate page if ($cancel || ($current_time - $lastclick < 2 && $submit)) { @@ -145,7 +148,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $group_options = ''; while ($row = $db->sql_fetchrow($result)) { - $group_options .= '' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . ''; + $group_options .= '' . $group_helper->get_name($row['group_name']) . ''; } $db->sql_freeresult($result); } @@ -1059,7 +1062,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { if ($type == 'g') { - $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name']; + $row['name'] = $group_helper->get_name($row['name']); } ${$type}[$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']); diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php index b674a457c1..2ccd4a7728 100644 --- a/phpBB/includes/ucp/ucp_pm_options.php +++ b/phpBB/includes/ucp/ucp_pm_options.php @@ -700,7 +700,10 @@ function define_rule_option($hardcoded, $rule_option, $rule_lang, $check_ary) */ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule_conditions) { - global $db, $template, $auth, $user, $request; + global $db, $template, $auth, $user, $request, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $template->assign_vars(array( 'S_COND_DEFINED' => true, @@ -812,13 +815,13 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule { if ($rule_group_id && ($row['group_id'] == $rule_group_id)) { - $rule_string = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']); + $rule_string = $group_helper->get_name($row['group_name']); } $s_class = ($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : ''; $s_selected = ($row['group_id'] == $rule_group_id) ? ' selected="selected"' : ''; - $s_group_options .= ''; + $s_group_options .= ''; } $db->sql_freeresult($result); diff --git a/phpBB/index.php b/phpBB/index.php index dba961feb8..73a5989bcb 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -100,11 +100,14 @@ else } $result = $db->sql_query($sql); +/** @var \phpbb\group\helper $group_helper */ +$group_helper = $phpbb_container->get('group_helper'); + $legend = array(); while ($row = $db->sql_fetchrow($result)) { $colour_text = ($row['group_colour']) ? ' style="color:#' . $row['group_colour'] . '"' : ''; - $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $group_name = $group_helper->get_name($row['group_name']); if ($row['group_name'] == 'BOTS' || ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile'))) { diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index 36c760f298..67f535ad0c 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -83,6 +83,9 @@ switch ($mode) break; } +/** @var \phpbb\group\helper $group_helper */ +$group_helper = $phpbb_container->get('group_helper'); + $start = $request->variable('start', 0); $submit = (isset($_POST['submit'])) ? true : false; @@ -136,7 +139,7 @@ switch ($mode) } else { - $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $row['group_name'] = $group_helper->get_name($row['group_name']); $row['u_group'] = append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $row['group_id']); } @@ -536,20 +539,14 @@ switch ($mode) $group_data = $group_sort = array(); foreach ($profile_groups as $row) { - if ($row['group_type'] == GROUP_SPECIAL) - { - // Lookup group name in language dictionary - if (isset($user->lang['G_' . $row['group_name']])) - { - $row['group_name'] = $user->lang['G_' . $row['group_name']]; - } - } - else if (!$auth_hidden_groups && $row['group_type'] == GROUP_HIDDEN && !isset($user_groups[$row['group_id']])) + if (!$auth_hidden_groups && $row['group_type'] == GROUP_HIDDEN && !isset($user_groups[$row['group_id']])) { // Skip over hidden groups the user cannot see continue; } + $row['group_name'] = $group_helper->get_name($row['group_name']); + $group_sort[$row['group_id']] = utf8_clean_string($row['group_name']); $group_data[$row['group_id']] = $row; } @@ -1136,7 +1133,7 @@ switch ($mode) $template->assign_vars(array( 'GROUP_DESC' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']), - 'GROUP_NAME' => ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'], + 'GROUP_NAME' => $group_helper->get_name($row['group_name']), 'GROUP_COLOR' => $group_row['group_colour'], 'GROUP_TYPE' => $user->lang['GROUP_IS_' . $group_row['l_group_type']], 'GROUP_RANK' => $user_rank_data['title'], @@ -1315,7 +1312,7 @@ switch ($mode) while ($row = $db->sql_fetchrow($result)) { $group_ids[] = $row['group_id']; - $s_group_select .= ''; + $s_group_select .= ''; } $db->sql_freeresult($result); diff --git a/phpBB/viewonline.php b/phpBB/viewonline.php index 2f58646722..a44a4b218e 100644 --- a/phpBB/viewonline.php +++ b/phpBB/viewonline.php @@ -182,6 +182,9 @@ $logged_visible_online = $logged_hidden_online = $counter = 0; /** @var \phpbb\controller\helper $controller_helper */ $controller_helper = $phpbb_container->get('controller.helper'); +/** @var \phpbb\group\helper $group_helper */ +$group_helper = $phpbb_container->get('group_helper'); + while ($row = $db->sql_fetchrow($result)) { if ($row['user_id'] != ANONYMOUS && !isset($prev_id[$row['user_id']])) @@ -467,7 +470,7 @@ while ($row = $db->sql_fetchrow($result)) } else { - $legend .= (($legend != '') ? ', ' : '') . '' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . ''; + $legend .= (($legend != '') ? ', ' : '') . '' . $group_helper->get_name($row['group_name']) . ''; } } $db->sql_freeresult($result); From d4095bb11d3181f9d1fbd9fd3600142ef57d6200 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Fri, 29 May 2015 10:48:54 +0200 Subject: [PATCH 0559/1676] [ticket/12143] Oops, fixed array index PHPBB3-12143 --- phpBB/includes/acp/acp_permissions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index edd0a836f2..1c54ce2c65 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -932,7 +932,7 @@ class acp_permissions $l_ug_list = ''; while ($row = $db->sql_fetchrow($result)) { - $group_name = $group_helper->get_name($row['group_name']); + $group_name = $group_helper->get_name($row['name']); $l_ug_list .= (($l_ug_list != '') ? ', ' : '') . ((isset($row['group_type']) && $row['group_type'] == GROUP_SPECIAL) ? '' . $group_name . '' : $group_name); } $db->sql_freeresult($result); From ca17bc7187c8836be7650209886b1024d01b268c Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Fri, 29 May 2015 11:31:47 +0200 Subject: [PATCH 0560/1676] [ticket/12143] Add some tests PHPBB3-12143 --- tests/group/helper_test.php | 68 ++++++++++++++++++++++++++++++++ tests/language/language_test.php | 14 +++++++ 2 files changed, 82 insertions(+) create mode 100644 tests/group/helper_test.php diff --git a/tests/group/helper_test.php b/tests/group/helper_test.php new file mode 100644 index 0000000000..a325ac7ac9 --- /dev/null +++ b/tests/group/helper_test.php @@ -0,0 +1,68 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_group_helper_test extends phpbb_test_case +{ + /** @var \phpbb\group\helper */ + protected $group_helper; + + public function setUp() + { + global $phpbb_root_path, $phpEx; + + // Set up language service + $lang = new \phpbb\language\language( + new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx) + ); + + // Set up language data for testing + $reflection_class = new ReflectionClass('\phpbb\language\language'); + + // Set default language files loaded flag to true + $loaded_flag = $reflection_class->getProperty('common_language_files_loaded'); + $loaded_flag->setAccessible(true); + $loaded_flag->setValue($lang, true); + + // Set up test language data + $lang_array = $reflection_class->getProperty('lang'); + $lang_array->setAccessible(true); + $lang_array->setValue($lang, $this->get_test_language_data_set()); + + // Set up group helper + $this->group_helper = new \phpbb\group\helper($lang); + } + + public function test_get_name() + { + // They should be totally fine + $this->assertEquals('Bots', 'Bots'); + $this->assertEquals('Some new group', 'new_group'); + $this->assertEquals('Should work', 'group_with_ümlauts'); + + // This should fail (obviously) + $this->assertNotEquals('They key does not contain uppercase letters', 'not_uppercase'); + + // The key doesn't exist so just return group name... + $this->assertEquals('Awesome group', 'Awesome group'); + } + + protected function get_test_language_data_set() + { + return array( + 'G_BOTS' => 'Bots', + 'G_NEW_GROUP' => 'Some new group', + 'G_not_uppercase' => 'The key does not contain uppercase letters', + 'G_GROUP_WITH_ÜMLAUTS' => 'Should work', + ); + } +} diff --git a/tests/language/language_test.php b/tests/language/language_test.php index 95de403bd4..6a814e39dc 100644 --- a/tests/language/language_test.php +++ b/tests/language/language_test.php @@ -39,6 +39,20 @@ class phpbb_language_test extends phpbb_test_case $lang_array->setValue($this->lang, $this->get_test_data_set()); } + public function test_is_set() + { + // Check for non-existing key + $this->assertFalse($this->lang->is_set('VALUE')); + $this->assertFalse($this->lang->is_set(array('dateformat', 'MAYBE'))); + + // Check for existing key + $this->assertTrue($this->lang->is_set('FOO')); + $this->assertTrue($this->lang->is_set(array('dateformat', 'AGO'))); + + // Array doesn't exist at all... + $this->assertFalse($this->lang->is_set(array('PHPBB', 'PHP'))); + } + public function test_lang() { // No param From 981bd8bed4f126ec01e02d9e1737c4d42994461c Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Fri, 29 May 2015 14:40:23 +0200 Subject: [PATCH 0561/1676] [ticket/12143] Fix those tests I always have to fix them.. :( PHPBB3-12143 --- phpBB/memberlist.php | 2 +- tests/group/helper_test.php | 10 +++++----- tests/notification/group_request_test.php | 5 +++++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index 67f535ad0c..eaaae4aaab 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -1133,7 +1133,7 @@ switch ($mode) $template->assign_vars(array( 'GROUP_DESC' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']), - 'GROUP_NAME' => $group_helper->get_name($row['group_name']), + 'GROUP_NAME' => $group_helper->get_name($group_row['group_name']), 'GROUP_COLOR' => $group_row['group_colour'], 'GROUP_TYPE' => $user->lang['GROUP_IS_' . $group_row['l_group_type']], 'GROUP_RANK' => $user_rank_data['title'], diff --git a/tests/group/helper_test.php b/tests/group/helper_test.php index a325ac7ac9..2377a6f47c 100644 --- a/tests/group/helper_test.php +++ b/tests/group/helper_test.php @@ -45,15 +45,15 @@ class phpbb_group_helper_test extends phpbb_test_case public function test_get_name() { // They should be totally fine - $this->assertEquals('Bots', 'Bots'); - $this->assertEquals('Some new group', 'new_group'); - $this->assertEquals('Should work', 'group_with_ümlauts'); + $this->assertEquals('Bots', $this->group_helper->get_name('Bots')); + $this->assertEquals('Some new group', $this->group_helper->get_name('new_group')); + $this->assertEquals('Should work', $this->group_helper->get_name('group_with_ümlauts')); // This should fail (obviously) - $this->assertNotEquals('They key does not contain uppercase letters', 'not_uppercase'); + $this->assertNotEquals('They key does not contain uppercase letters', $this->group_helper->get_name('not_uppercase')); // The key doesn't exist so just return group name... - $this->assertEquals('Awesome group', 'Awesome group'); + $this->assertEquals('Awesome group', $this->group_helper->get_name('Awesome group')); } protected function get_test_language_data_set() diff --git a/tests/notification/group_request_test.php b/tests/notification/group_request_test.php index a24808fbbd..d16e198861 100644 --- a/tests/notification/group_request_test.php +++ b/tests/notification/group_request_test.php @@ -49,6 +49,11 @@ class phpbb_notification_group_request_test extends phpbb_tests_notification_bas $this->user, $this->cache->get_driver() )); + $this->container->set('group_helper', new \phpbb\group\helper( + new \phpbb\language\language( + new phpbb\language\language_file_loader($phpbb_root_path, $phpEx) + ) + )); $phpbb_dispatcher = new phpbb_mock_event_dispatcher; $phpbb_log = new \phpbb\log\dummy(); $this->get_test_case_helpers()->set_s9e_services(); From c3e5185135c1e918ac0e07d6d5b4392971121bf9 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sun, 19 Jul 2015 22:19:44 +0200 Subject: [PATCH 0562/1676] [ticket/12143] Avoid no output from get_group_name() PHPBB3-12143 --- phpBB/includes/functions_user.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index e17a8b8d73..98ffb4227d 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -3332,7 +3332,7 @@ function get_group_name($group_id) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if (!$row || !$user->is_setup()) + if (!$row) { return ''; } From 25103698040977fd0d655d6e658157a07bb24990 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sun, 19 Jul 2015 22:53:28 +0200 Subject: [PATCH 0563/1676] [ticket/12143] Fix tests after rebase PHPBB3-12143 --- tests/notification/fixtures/services_notification.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/notification/fixtures/services_notification.yml b/tests/notification/fixtures/services_notification.yml index 7eaa7e81ec..e0a404b12b 100644 --- a/tests/notification/fixtures/services_notification.yml +++ b/tests/notification/fixtures/services_notification.yml @@ -23,6 +23,9 @@ services: cache.driver: synthetic: true + group_helper: + synthetic: true + path_helper: synthetic: true From 618065ec16030f1d142667473ee2ff42cd80e72b Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 8 Jul 2015 16:58:45 +0200 Subject: [PATCH 0564/1676] [ticket/12692] Fix tests and update style PHPBB3-12692 --- phpBB/language/en/cli.php | 11 ++- .../console/command/thumbnail/delete.php | 63 +++++++++++------ .../console/command/thumbnail/generate.php | 64 +++++++++++------ .../console/command/thumbnail/recreate.php | 5 +- tests/console/thumbnail_test.php | 69 +++++++++++-------- 5 files changed, 134 insertions(+), 78 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index d494ef8c55..ec1d63eabf 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -84,20 +84,25 @@ $lang = array_merge($lang, array( 'CLI_EXTENSION_PURGE_FAILURE' => 'Could not purge extension %s', 'CLI_EXTENSION_PURGE_SUCCESS' => 'Successfully purged extension %s', 'CLI_EXTENSION_NOT_FOUND' => 'No extensions were found.', + 'CLI_EXTENSIONS_AVAILABLE' => 'Available', + 'CLI_EXTENSIONS_DISABLED' => 'Disabled', + 'CLI_EXTENSIONS_ENABLED' => 'Enabled', 'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.', 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s (range %2$d..%3$d)', 'CLI_REPARSER_REPARSE_REPARSING_START' => 'Reparsing %s...', 'CLI_REPARSER_REPARSE_SUCCESS' => 'Reparsing ended with success', - + // In all the case %1$s is the logical name of the file and %2$s the real name on the filesystem // eg: big_image.png (2_a51529ae7932008cf8454a95af84cacd) generated. 'CLI_THUMBNAIL_DELETED' => '%1$s (%2$s) deleted.', - 'CLI_THUMBNAIL_DELETING' => 'Deleting thumbnails…', + 'CLI_THUMBNAIL_DELETING' => 'Deleting thumbnails', 'CLI_THUMBNAIL_SKIPPED' => '%1$s (%2$s) skipped.', 'CLI_THUMBNAIL_GENERATED' => '%1$s (%2$s) generated.', - 'CLI_THUMBNAIL_GENERATING' => 'Generating thumbnails…', + 'CLI_THUMBNAIL_GENERATING' => 'Generating thumbnails', + 'CLI_THUMBNAIL_GENERATING_DONE' => 'All thumbnails have been regenerated.', + 'CLI_THUMBNAIL_DELETING_DONE' => 'All thumbnails have been deleted.', 'CLI_THUMBNAIL_NOTHING_TO_GENERATE' => 'No thumbnails to generate.', 'CLI_THUMBNAIL_NOTHING_TO_DELETE' => 'No thumbnails to delete.', diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index fb63f7c510..e8e4cf568e 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -14,6 +14,7 @@ namespace phpbb\console\command\thumbnail; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class delete extends \phpbb\console\command\command { @@ -68,6 +69,10 @@ class delete extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + + $io->section($this->user->lang('CLI_THUMBNAIL_DELETING')); + $sql = 'SELECT COUNT(*) AS nb_missing_thumbnails FROM ' . ATTACHMENTS_TABLE . ' WHERE thumbnail = 1'; @@ -77,7 +82,7 @@ class delete extends \phpbb\console\command\command if ($nb_missing_thumbnails === 0) { - $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_NOTHING_TO_DELETE') . ''); + $io->warning($this->user->lang('CLI_THUMBNAIL_NOTHING_TO_DELETE')); return 0; } @@ -86,11 +91,36 @@ class delete extends \phpbb\console\command\command WHERE thumbnail = 1'; $result = $this->db->sql_query($sql); - if (!$input->getOption('verbose')) + $progress = $io->createProgressBar($nb_missing_thumbnails); + if ($output->getVerbosity() === OutputInterface::VERBOSITY_VERBOSE) { - $progress = $this->getHelper('progress'); - $progress->start($output, $nb_missing_thumbnails); + $progress->setFormat('[%percent:3s%%] %message%'); + $progress->setOverwrite(false); } + else if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) + { + $progress->setFormat('[%current:s%/%max:s%][%elapsed%/%estimated%][%memory%] %message%'); + $progress->setOverwrite(false); + } + else + { + $io->newLine(2); + $progress->setFormat( + " %current:s%/%max:s% %bar% %percent:3s%%\n" . + " %elapsed:6s%/%estimated:-6s% %memory:6s%\n"); + $progress->setBarWidth(60); + } + + if (!defined('PHP_WINDOWS_VERSION_BUILD')) + { + $progress->setEmptyBarCharacter('░'); // light shade character \u2591 + $progress->setProgressCharacter(''); + $progress->setBarCharacter('▓'); // dark shade character \u2593 + } + + $progress->setMessage($this->user->lang('CLI_THUMBNAIL_DELETING')); + + $progress->start(); $thumbnail_deleted = array(); $return = 0; @@ -108,24 +138,15 @@ class delete extends \phpbb\console\command\command $thumbnail_deleted = array(); } - if ($input->getOption('verbose')) - { - $output->writeln($this->user->lang('CLI_THUMBNAIL_DELETED', $row['real_filename'], $row['physical_filename'])); - } + $progress->setMessage($this->user->lang('CLI_THUMBNAIL_DELETED', $row['real_filename'], $row['physical_filename'])); } else { - if ($input->getOption('verbose')) - { - $return = 1; - $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); - } + $return = 1; + $progress->setMessage('' . $this->user->lang('CLI_THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); } - if (!$input->getOption('verbose')) - { - $progress->advance(); - } + $progress->advance(); } $this->db->sql_freeresult($result); @@ -134,10 +155,10 @@ class delete extends \phpbb\console\command\command $this->commit_changes($thumbnail_deleted); } - if (!$input->getOption('verbose')) - { - $progress->finish(); - } + $progress->finish(); + + $io->newLine(2); + $io->success($this->user->lang('CLI_THUMBNAIL_DELETING_DONE')); return $return; } diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index 0f4a40bd9f..e677db3a97 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -10,10 +10,12 @@ * the docs/CREDITS.txt file. * */ + namespace phpbb\console\command\thumbnail; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class generate extends \phpbb\console\command\command { @@ -84,6 +86,10 @@ class generate extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + + $io->section($this->user->lang('CLI_THUMBNAIL_GENERATING')); + $sql = 'SELECT COUNT(*) AS nb_missing_thumbnails FROM ' . ATTACHMENTS_TABLE . ' WHERE thumbnail = 0'; @@ -93,7 +99,7 @@ class generate extends \phpbb\console\command\command if ($nb_missing_thumbnails === 0) { - $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_NOTHING_TO_GENERATE') . ''); + $io->warning($this->user->lang('CLI_THUMBNAIL_NOTHING_TO_GENERATE')); return 0; } @@ -109,11 +115,36 @@ class generate extends \phpbb\console\command\command require($this->phpbb_root_path . 'includes/functions_posting.' . $this->php_ext); } - if (!$input->getOption('verbose')) + $progress = $io->createProgressBar($nb_missing_thumbnails); + if ($output->getVerbosity() === OutputInterface::VERBOSITY_VERBOSE) { - $progress = $this->getHelper('progress'); - $progress->start($output, $nb_missing_thumbnails); + $progress->setFormat('[%percent:3s%%] %message%'); + $progress->setOverwrite(false); } + else if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) + { + $progress->setFormat('[%current:s%/%max:s%][%elapsed%/%estimated%][%memory%] %message%'); + $progress->setOverwrite(false); + } + else + { + $io->newLine(2); + $progress->setFormat( + " %current:s%/%max:s% %bar% %percent:3s%%\n" . + " %elapsed:6s%/%estimated:-6s% %memory:6s%\n"); + $progress->setBarWidth(60); + } + + if (!defined('PHP_WINDOWS_VERSION_BUILD')) + { + $progress->setEmptyBarCharacter('░'); // light shade character \u2591 + $progress->setProgressCharacter(''); + $progress->setBarCharacter('▓'); // dark shade character \u2593 + } + + $progress->setMessage($this->user->lang('CLI_THUMBNAIL_GENERATING')); + + $progress->start(); $thumbnail_created = array(); while ($row = $this->db->sql_fetchrow($result)) @@ -127,30 +158,21 @@ class generate extends \phpbb\console\command\command { $thumbnail_created[] = (int) $row['attach_id']; - if (sizeof($thumbnail_created) === 250) + if (count($thumbnail_created) === 250) { $this->commit_changes($thumbnail_created); $thumbnail_created = array(); } - if ($input->getOption('verbose')) - { - $output->writeln($this->user->lang('CLI_THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename'])); - } + $progress->setMessage($this->user->lang('CLI_THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename'])); } else { - if ($input->getOption('verbose')) - { - $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); - } + $progress->setMessage('' . $this->user->lang('CLI_THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . ''); } } - if (!$input->getOption('verbose')) - { - $progress->advance(); - } + $progress->advance(); } $this->db->sql_freeresult($result); @@ -159,10 +181,10 @@ class generate extends \phpbb\console\command\command $this->commit_changes($thumbnail_created); } - if (!$input->getOption('verbose')) - { - $progress->finish(); - } + $progress->finish(); + + $io->newLine(2); + $io->success($this->user->lang('CLI_THUMBNAIL_GENERATING_DONE')); return 0; } diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php index 5d3edbd699..382da290bf 100644 --- a/phpBB/phpbb/console/command/thumbnail/recreate.php +++ b/phpBB/phpbb/console/command/thumbnail/recreate.php @@ -49,12 +49,11 @@ class recreate extends \phpbb\console\command\command if ($input->getOption('verbose')) { - $parameters['-v'] = true; + $parameters['-' . str_repeat('v', $output->getVerbosity() - 1)] = true; } $this->getApplication()->setAutoExit(false); - $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_DELETING') . ''); $input_delete = new ArrayInput($parameters); $return = $this->getApplication()->run($input_delete, $output); @@ -62,8 +61,6 @@ class recreate extends \phpbb\console\command\command { $parameters['command'] = 'thumbnail:generate'; - $output->writeln(''); - $output->writeln('' . $this->user->lang('CLI_THUMBNAIL_GENERATING') . ''); $input_create = new ArrayInput($parameters); $return = $this->getApplication()->run($input_create, $output); } diff --git a/tests/console/thumbnail_test.php b/tests/console/thumbnail_test.php index 094d8ca051..b5ed02b5e7 100644 --- a/tests/console/thumbnail_test.php +++ b/tests/console/thumbnail_test.php @@ -11,6 +11,7 @@ * */ +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_compatibility.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; use Symfony\Component\Console\Application; @@ -36,7 +37,7 @@ class phpbb_console_command_thumbnail_test extends phpbb_database_test_case public function setUp() { - global $config, $phpbb_root_path, $phpEx; + global $config, $phpbb_root_path, $phpEx, $phpbb_filesystem; parent::setUp(); @@ -47,12 +48,15 @@ class phpbb_console_command_thumbnail_test extends phpbb_database_test_case )); $this->db = $this->db = $this->new_dbal(); - $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); + $this->user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime') + ); $this->phpbb_root_path = $phpbb_root_path; $this->phpEx = $phpEx; $this->cache = $this->getMock('\phpbb\cache\service', array(), array(new phpbb_mock_cache(), $this->config, $this->db, $this->phpbb_root_path, $this->phpEx)); - $this->cache->expects($this->any())->method('obtain_attach_extensions')->will($this->returnValue(array( + $this->cache->expects(self::any())->method('obtain_attach_extensions')->will(self::returnValue(array( 'png' => array('display_cat' => ATTACHMENT_CATEGORY_IMAGE), 'txt' => array('display_cat' => ATTACHMENT_CATEGORY_NONE), ))); @@ -61,38 +65,18 @@ class phpbb_console_command_thumbnail_test extends phpbb_database_test_case $this->application->add(new generate($this->user, $this->db, $this->cache, $this->phpbb_root_path, $this->phpEx)); $this->application->add(new delete($this->user, $this->db, $this->phpbb_root_path)); $this->application->add(new recreate($this->user)); - } - public function test_thumbnails() - { + $phpbb_filesystem = new \phpbb\filesystem\filesystem(); + copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/test_png_1'); copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/test_png_2'); copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/thumb_test_png_2'); copy(dirname(__FILE__) . '/fixtures/txt.txt', $this->phpbb_root_path . 'files/test_txt'); + } - $command_tester = $this->get_command_tester('thumbnail:generate'); - $exit_status = $command_tester->execute(array('command' => 'thumbnail:generate')); - - $this->assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); - $this->assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); - $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); - $this->assertSame(0, $exit_status); - - $command_tester = $this->get_command_tester('thumbnail:delete'); - $exit_status = $command_tester->execute(array('command' => 'thumbnail:delete')); - - $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); - $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); - $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); - $this->assertSame(0, $exit_status); - - $command_tester = $this->get_command_tester('thumbnail:recreate'); - $exit_status = $command_tester->execute(array('command' => 'thumbnail:recreate')); - - $this->assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); - $this->assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); - $this->assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); - $this->assertSame(0, $exit_status); + protected function tearDown() + { + parent::tearDown(); unlink($this->phpbb_root_path . 'files/test_png_1'); unlink($this->phpbb_root_path . 'files/test_png_2'); @@ -101,6 +85,33 @@ class phpbb_console_command_thumbnail_test extends phpbb_database_test_case unlink($this->phpbb_root_path . 'files/thumb_test_png_2'); } + public function test_thumbnails() + { + $command_tester = $this->get_command_tester('thumbnail:generate'); + $exit_status = $command_tester->execute(array('command' => 'thumbnail:generate')); + + self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); + self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); + self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); + self::assertSame(0, $exit_status); + + $command_tester = $this->get_command_tester('thumbnail:delete'); + $exit_status = $command_tester->execute(array('command' => 'thumbnail:delete')); + + self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); + self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); + self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); + self::assertSame(0, $exit_status); + + $command_tester = $this->get_command_tester('thumbnail:recreate'); + $exit_status = $command_tester->execute(array('command' => 'thumbnail:recreate')); + + self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); + self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); + self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); + self::assertSame(0, $exit_status); + } + public function get_command_tester($command_name) { $command = $this->application->find($command_name); From 2260533d47ae11014679ca94787212723b1c184c Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 7 Aug 2015 16:14:40 +0200 Subject: [PATCH 0565/1676] [ticket/14074] Fix mark notifications as read in the ucp PHPBB3-14074 --- phpBB/includes/ucp/ucp_notifications.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/ucp/ucp_notifications.php b/phpBB/includes/ucp/ucp_notifications.php index c291cc1ddf..51bd77bd4c 100644 --- a/phpBB/includes/ucp/ucp_notifications.php +++ b/phpBB/includes/ucp/ucp_notifications.php @@ -122,7 +122,7 @@ class ucp_notifications if (!empty($mark_read)) { - $phpbb_notifications->mark_notifications_by_id($mark_read, $form_time); + $phpbb_notifications->mark_notifications_by_id('notification.method.board', $mark_read, $form_time); } } From 7e62b3a4b0b86b23c594d6b3644439a9c7f63153 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 7 Aug 2015 16:38:12 +0200 Subject: [PATCH 0566/1676] [ticket/14076] Fix notification settings PHPBB3-14076 --- phpBB/phpbb/notification/manager.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index 04259382ba..eb9a93be3d 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -589,6 +589,7 @@ class manager $user_id = $user_id ?: $this->user->data['user_id']; $subscriptions = array(); + $default_methods = $this->get_default_methods(); $user_notifications = $this->get_user_notifications($user_id); @@ -596,11 +597,8 @@ class manager { foreach ($types as $id => $type) { - if (empty($user_notifications[$id])) - { - $subscriptions[$id] = $this->get_default_methods(); - } - else + $subscriptions[$id] = array(); + if (!empty($user_notifications[$id])) { foreach ($user_notifications[$id] as $user_notification) { @@ -617,6 +615,8 @@ class manager $subscriptions[$id][] = $user_notification['method']; } } + + $subscriptions[$id] = array_merge($subscriptions[$id], $default_methods); } } From 05d583bba7faaf82487305e892f7758d4161f303 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 8 Aug 2015 17:43:15 +0200 Subject: [PATCH 0567/1676] [ticket/14079] Correctly mark notifications as read PHPBB3-14079 --- phpBB/phpbb/notification/manager.php | 21 ++++++++++++------- phpBB/phpbb/notification/type/base.php | 2 +- .../notification/type/type_interface.php | 4 ++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index eb9a93be3d..4be678ac91 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -166,6 +166,7 @@ class manager $notification_type_id = false; } + /** @var method_interface $method */ foreach ($this->get_available_subscription_methods() as $method) { $method->mark_notifications($notification_type_id, $item_id, $user_id, $time, $mark_read); @@ -597,26 +598,32 @@ class manager { foreach ($types as $id => $type) { - $subscriptions[$id] = array(); + $type_subscriptions = $default_methods; if (!empty($user_notifications[$id])) { foreach ($user_notifications[$id] as $user_notification) { + $key = array_search($user_notification['method'], $type_subscriptions, true); if (!$user_notification['notify']) { + if ($key !== false) + { + unset($type_subscriptions[$key]); + } + continue; } - - if (!isset($subscriptions[$id])) + else if ($key === false) { - $subscriptions[$id] = array(); + $type_subscriptions[] = $user_notification['method']; } - - $subscriptions[$id][] = $user_notification['method']; } } - $subscriptions[$id] = array_merge($subscriptions[$id], $default_methods); + if (!empty($type_subscriptions)) + { + $subscriptions[$id] = $type_subscriptions; + } } } diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php index 06f7f9c615..31e853d7d9 100644 --- a/phpBB/phpbb/notification/type/base.php +++ b/phpBB/phpbb/notification/type/base.php @@ -503,7 +503,7 @@ abstract class base implements \phpbb\notification\type\type_interface } else { - $this->notification_manager->mark_notifications($this->get_type(), (int) $this->item_id, (int) $this->user_id, $this->notification_read); + $this->notification_manager->mark_notifications($this->get_type(), (int) $this->item_id, (int) $this->user_id, false, $this->notification_read); } } diff --git a/phpBB/phpbb/notification/type/type_interface.php b/phpBB/phpbb/notification/type/type_interface.php index 9b4446ac47..f9f832bdda 100644 --- a/phpBB/phpbb/notification/type/type_interface.php +++ b/phpBB/phpbb/notification/type/type_interface.php @@ -206,7 +206,7 @@ interface type_interface * @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False) * @return string */ - public function mark_read($return); + public function mark_read($return = false); /** * Mark this item unread @@ -214,5 +214,5 @@ interface type_interface * @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False) * @return string */ - public function mark_unread($return); + public function mark_unread($return = false); } From df334b1da8049c57c09eb052313c0e4d869f6cce Mon Sep 17 00:00:00 2001 From: rxu Date: Wed, 12 Aug 2015 17:13:51 +0700 Subject: [PATCH 0568/1676] [ticket/14094] Fix segmentation fault error on PHP 7 tests PHPBB3-14094 --- tests/datetime/from_format_test.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/datetime/from_format_test.php b/tests/datetime/from_format_test.php index 7ecb546768..32b88ff588 100644 --- a/tests/datetime/from_format_test.php +++ b/tests/datetime/from_format_test.php @@ -113,6 +113,10 @@ class phpbb_datetime_from_format_test extends phpbb_test_case { global $phpbb_root_path, $phpEx; + // This magically fixes the segmentation fault error on PHP7 tests + // while date_default_timezone_set('UTC') does not + date_default_timezone_set('Europe/Paris'); + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); $lang = new \phpbb\language\language($lang_loader); $user = new \phpbb\user($lang, '\phpbb\datetime'); From cd37b32b3d4ecf7dd183e9fb4efe5322bf4b06f5 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 12 Aug 2015 14:47:47 +0200 Subject: [PATCH 0569/1676] [ticket/14096] Update Symfony PHPBB3-14096 --- phpBB/composer.lock | 179 +++++++++++++++++--------------------------- 1 file changed, 67 insertions(+), 112 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index aaff9a8968..16058b448c 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -224,7 +224,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/6c568ac8b01b33650d9d77b5b6399eed9c18ac94", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/fb39bdd38f6706b96422a7583b89c9283a58960f", "reference": "beee0e5693f7ca8ed16a94294acf53b6e6207e7c", "shasum": "" }, @@ -279,12 +279,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "358ec929e494b6f12d8508d88357cbd7383a10ca" + "reference": "3f495530550377a55c0cced5ddf8f58cfcd9ce5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/358ec929e494b6f12d8508d88357cbd7383a10ca", - "reference": "358ec929e494b6f12d8508d88357cbd7383a10ca", + "url": "https://api.github.com/repos/symfony/Config/zipball/3f495530550377a55c0cced5ddf8f58cfcd9ce5b", + "reference": "3f495530550377a55c0cced5ddf8f58cfcd9ce5b", "shasum": "" }, "require": { @@ -321,7 +321,7 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2015-07-09 16:11:14" + "time": "2015-08-03 08:27:53" }, { "name": "symfony/console", @@ -329,12 +329,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a" + "reference": "eb0fcf6f58054ac9d07539451e27aa4e17aebfe0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a", - "reference": "fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a", + "url": "https://api.github.com/repos/symfony/Console/zipball/eb0fcf6f58054ac9d07539451e27aa4e17aebfe0", + "reference": "eb0fcf6f58054ac9d07539451e27aa4e17aebfe0", "shasum": "" }, "require": { @@ -378,7 +378,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-07-16 12:22:14" + "time": "2015-08-04 15:59:05" }, { "name": "symfony/debug", @@ -386,12 +386,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Debug.git", - "reference": "d1114d892ae70f833871dc55599f17084191efaa" + "reference": "e6ce720c140d144e2b2e2b14d36b887011e2a578" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Debug/zipball/d1114d892ae70f833871dc55599f17084191efaa", - "reference": "d1114d892ae70f833871dc55599f17084191efaa", + "url": "https://api.github.com/repos/symfony/Debug/zipball/e6ce720c140d144e2b2e2b14d36b887011e2a578", + "reference": "e6ce720c140d144e2b2e2b14d36b887011e2a578", "shasum": "" }, "require": { @@ -403,14 +403,9 @@ }, "require-dev": { "symfony/class-loader": "~2.2|~3.0.0", - "symfony/http-foundation": "~2.1|~3.0.0", "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2|~3.0.0", "symfony/phpunit-bridge": "~2.7|~3.0.0" }, - "suggest": { - "symfony/http-foundation": "", - "symfony/http-kernel": "" - }, "type": "library", "extra": { "branch-alias": { @@ -438,7 +433,7 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2015-07-09 16:11:14" + "time": "2015-08-01 06:34:55" }, { "name": "symfony/dependency-injection", @@ -446,12 +441,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "f279142fb6bc21e83fcd40e0a01a62ff527268be" + "reference": "b0e1cef8acbc3b6df877c47b8e0b8449defcfc5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/f279142fb6bc21e83fcd40e0a01a62ff527268be", - "reference": "f279142fb6bc21e83fcd40e0a01a62ff527268be", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/b0e1cef8acbc3b6df877c47b8e0b8449defcfc5f", + "reference": "b0e1cef8acbc3b6df877c47b8e0b8449defcfc5f", "shasum": "" }, "require": { @@ -498,7 +493,7 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2015-07-16 10:10:53" + "time": "2015-08-05 15:50:26" }, { "name": "symfony/event-dispatcher", @@ -662,12 +657,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/HttpFoundation.git", - "reference": "5339030f5af0d6fef7c897130291ac168278289f" + "reference": "caede1f3361223098395b955bdbf3fe59d58d3ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/5339030f5af0d6fef7c897130291ac168278289f", - "reference": "5339030f5af0d6fef7c897130291ac168278289f", + "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/caede1f3361223098395b955bdbf3fe59d58d3ba", + "reference": "caede1f3361223098395b955bdbf3fe59d58d3ba", "shasum": "" }, "require": { @@ -707,7 +702,7 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2015-07-16 12:22:14" + "time": "2015-08-05 15:58:16" }, { "name": "symfony/http-kernel", @@ -715,19 +710,19 @@ "source": { "type": "git", "url": "https://github.com/symfony/HttpKernel.git", - "reference": "f24d2cb4778ecc5f6c8e8f7f31bc4691099a920d" + "reference": "8480ac939c8f6441e3575badb2306b936e14184a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/f24d2cb4778ecc5f6c8e8f7f31bc4691099a920d", - "reference": "f24d2cb4778ecc5f6c8e8f7f31bc4691099a920d", + "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/8480ac939c8f6441e3575badb2306b936e14184a", + "reference": "8480ac939c8f6441e3575badb2306b936e14184a", "shasum": "" }, "require": { "php": ">=5.3.9", "psr/log": "~1.0", "symfony/debug": "~2.6,>=2.6.2", - "symfony/event-dispatcher": "~2.5.9|~2.6,>=2.6.2|~3.0.0", + "symfony/event-dispatcher": "~2.6,>=2.6.7|~3.0.0", "symfony/http-foundation": "~2.5,>=2.5.4|~3.0.0" }, "conflict": { @@ -739,7 +734,7 @@ "symfony/config": "~2.7", "symfony/console": "~2.3|~3.0.0", "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0", - "symfony/dependency-injection": "~2.2|~3.0.0", + "symfony/dependency-injection": "~2.8|~3.0.0", "symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", "symfony/finder": "~2.0,>=2.0.5|~3.0.0", @@ -787,7 +782,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2015-07-09 16:11:14" + "time": "2015-08-01 06:34:21" }, { "name": "symfony/routing", @@ -795,12 +790,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Routing.git", - "reference": "9e797cd70762db18d87c59dc6bc1ab7c3eb963ed" + "reference": "b7c7ba4300592b5127318301d3d5aef537c05664" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Routing/zipball/9e797cd70762db18d87c59dc6bc1ab7c3eb963ed", - "reference": "9e797cd70762db18d87c59dc6bc1ab7c3eb963ed", + "url": "https://api.github.com/repos/symfony/Routing/zipball/b7c7ba4300592b5127318301d3d5aef537c05664", + "reference": "b7c7ba4300592b5127318301d3d5aef537c05664", "shasum": "" }, "require": { @@ -858,40 +853,53 @@ "uri", "url" ], - "time": "2015-07-09 16:11:14" + "time": "2015-08-05 15:58:16" }, { - "name": "symfony/security-core", + "name": "symfony/security", "version": "2.8.x-dev", "source": { "type": "git", - "url": "https://github.com/symfony/security-core.git", - "reference": "8253e027bf8a1c9c573a7b3c494027847058c959" + "url": "https://github.com/symfony/Security.git", + "reference": "b57956299e1d75663d748645564d76efcb9e72f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/8253e027bf8a1c9c573a7b3c494027847058c959", - "reference": "8253e027bf8a1c9c573a7b3c494027847058c959", + "url": "https://api.github.com/repos/symfony/Security/zipball/b57956299e1d75663d748645564d76efcb9e72f3", + "reference": "b57956299e1d75663d748645564d76efcb9e72f3", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.9", + "symfony/event-dispatcher": "~2.2|~3.0.0", + "symfony/http-foundation": "~2.1|~3.0.0", + "symfony/http-kernel": "~2.4|~3.0.0" + }, + "replace": { + "symfony/security-acl": "self.version", + "symfony/security-core": "self.version", + "symfony/security-csrf": "self.version", + "symfony/security-http": "self.version" }, "require-dev": { - "ircmaxell/password-compat": "1.0.*", + "doctrine/common": "~2.2", + "doctrine/dbal": "~2.2", + "ircmaxell/password-compat": "~1.0", "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1|~3.0.0", "symfony/expression-language": "~2.6|~3.0.0", - "symfony/http-foundation": "~2.4|~3.0.0", + "symfony/intl": "~2.3|~3.0.0", "symfony/phpunit-bridge": "~2.7|~3.0.0", + "symfony/routing": "~2.2|~3.0.0", "symfony/translation": "~2.0,>=2.0.5|~3.0.0", "symfony/validator": "~2.5,>=2.5.5|~3.0.0" }, "suggest": { + "doctrine/dbal": "For using the built-in ACL implementation", "ircmaxell/password-compat": "For using the BCrypt password encoder in PHP <5.5", - "symfony/event-dispatcher": "", + "symfony/class-loader": "For using the ACL generateSql script", "symfony/expression-language": "For using the expression voter", - "symfony/http-foundation": "", + "symfony/finder": "For using the ACL generateSql script", + "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", "symfony/validator": "For using the user password constraint" }, "type": "library", @@ -902,7 +910,7 @@ }, "autoload": { "psr-4": { - "Symfony\\Component\\Security\\Core\\": "" + "Symfony\\Component\\Security\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -919,76 +927,22 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Security Component - Core Library", + "description": "Symfony Security Component", "homepage": "https://symfony.com", "time": "2015-07-09 16:11:14" }, - { - "name": "symfony/security-csrf", - "version": "2.8.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-csrf.git", - "reference": "9e859301e5b19953338a50a5d3e1aeb01d37e9d1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/9e859301e5b19953338a50a5d3e1aeb01d37e9d1", - "reference": "9e859301e5b19953338a50a5d3e1aeb01d37e9d1", - "shasum": "" - }, - "require": { - "php": ">=5.3.9", - "symfony/security-core": "~2.4|~3.0.0" - }, - "require-dev": { - "symfony/http-foundation": "~2.1|~3.0.0", - "symfony/phpunit-bridge": "~2.7|~3.0.0" - }, - "suggest": { - "symfony/http-foundation": "For using the class SessionTokenStorage." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Security\\Csrf\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Security Component - CSRF Library", - "homepage": "https://symfony.com", - "time": "2015-05-13 11:36:16" - }, { "name": "symfony/twig-bridge", "version": "2.8.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/TwigBridge.git", - "reference": "a02e3a8ff1f8eda04d0e0655d2cefcbe9ecc4e14" + "reference": "f7cbabeaaaf27c904951876f4a5bde5363833382" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/TwigBridge/zipball/a02e3a8ff1f8eda04d0e0655d2cefcbe9ecc4e14", - "reference": "a02e3a8ff1f8eda04d0e0655d2cefcbe9ecc4e14", + "url": "https://api.github.com/repos/symfony/TwigBridge/zipball/f7cbabeaaaf27c904951876f4a5bde5363833382", + "reference": "f7cbabeaaaf27c904951876f4a5bde5363833382", "shasum": "" }, "require": { @@ -1000,12 +954,13 @@ "symfony/console": "~2.7|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", "symfony/finder": "~2.3|~3.0.0", - "symfony/form": "~2.8|~3.0.0", + "symfony/form": "~2.8", "symfony/http-kernel": "~2.3|~3.0.0", "symfony/intl": "~2.3|~3.0.0", "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/routing": "~2.2|~3.0.0", "symfony/security": "~2.6|~3.0.0", + "symfony/security-acl": "~2.6|~3.0.0", "symfony/stopwatch": "~2.2|~3.0.0", "symfony/templating": "~2.1|~3.0.0", "symfony/translation": "~2.7|~3.0.0", @@ -1053,7 +1008,7 @@ ], "description": "Symfony Twig Bridge", "homepage": "https://symfony.com", - "time": "2015-07-09 16:11:14" + "time": "2015-08-01 09:43:59" }, { "name": "symfony/yaml", @@ -1061,12 +1016,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "000e7fc2653335cd42c6d21405dac1c74224a387" + "reference": "6eef1477f3c4451b6024fadb1254009be4602908" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/000e7fc2653335cd42c6d21405dac1c74224a387", - "reference": "000e7fc2653335cd42c6d21405dac1c74224a387", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/6eef1477f3c4451b6024fadb1254009be4602908", + "reference": "6eef1477f3c4451b6024fadb1254009be4602908", "shasum": "" }, "require": { @@ -1102,7 +1057,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-07-01 14:16:54" + "time": "2015-07-29 07:12:56" }, { "name": "twig/twig", From f4f0ff0eec78c85b4ec2962a0de06d9aa2bd37a5 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Mon, 17 Aug 2015 18:38:07 +0200 Subject: [PATCH 0570/1676] [ticket/14097] Improve error and failure handling in the installer PHPBB3-14097 --- phpBB/phpbb/install/installer.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index cb4ddb8783..78a0de0241 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -92,7 +92,8 @@ class installer $module_found = false; // Variable used to check if the install process have been finished - $install_finished = false; + $install_finished = false; + $fail_cleanup = false; // We are installing something, so the introduction stage can go now... $this->install_config->set_finished_navigation_stage(array('install', 0, 'introduction')); @@ -209,6 +210,13 @@ class installer { // Do nothing } + catch (\Exception $e) + { + // Most likely there were a PHP failure, so let's die like a gentleman + $this->iohandler->add_error_message($e->getMessage()); + $this->iohandler->send_response(); + $fail_cleanup = true; + } if ($install_finished) { @@ -223,7 +231,7 @@ class installer // Save install progress try { - if ($install_finished) + if ($install_finished || $fail_cleanup) { $this->install_config->clean_up_config_file(); } From 4fac568d5e02188a533ca0c38d1b013b3ff48067 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Sun, 16 Aug 2015 16:50:04 +0200 Subject: [PATCH 0571/1676] [ticket/12719] Add normalize & base phpbb3-12719 --- phpBB/styles/prosilver/theme/base.css | 107 +++++++ phpBB/styles/prosilver/theme/normalize.css | 331 ++++++++++++++++++++ phpBB/styles/prosilver/theme/stylesheet.css | 3 + phpBB/styles/prosilver/theme/utilities.css | 57 ++++ 4 files changed, 498 insertions(+) create mode 100644 phpBB/styles/prosilver/theme/base.css create mode 100644 phpBB/styles/prosilver/theme/normalize.css create mode 100644 phpBB/styles/prosilver/theme/utilities.css diff --git a/phpBB/styles/prosilver/theme/base.css b/phpBB/styles/prosilver/theme/base.css new file mode 100644 index 0000000000..8c03e4891d --- /dev/null +++ b/phpBB/styles/prosilver/theme/base.css @@ -0,0 +1,107 @@ +/* -------------------------------------------------------------- + $Base +-------------------------------------------------------------- */ + +/** { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +}*/ + +/* Define your base font-size here; most elements will inherit this. _NO__DOTCOMMA__AFTER__*/ +html { + font-size: 1em; /* Assuming 16px... */ + line-height: 1.5; /* 24px (This is now our magic number; all subsequent margin-bottoms and line-heights want to be a multiple of this number in order to maintain vertical rhythm.) _NO__DOTCOMMA__AFTER__*/ + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #333333; + background-color: #ffffff; +} + +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +figure { margin: 0 } +img { vertical-align: middle } + +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #e5e5e5; +} + +a { + color: #428bca; + text-decoration: none; +} + +a:hover, +a:focus, +a:active { + color: #2a6496; + text-decoration: underline; +} + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +figure, +p, +pre { margin: 0 } +button { + background: transparent; + border: 0; + padding: 0; +} + +/** + * Work around a Firefox/IE bug where the transparent `button` background + * results in a loss of the default `button` focus styles. + */ +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +fieldset { + border: 0; + margin: 0; + padding: 0; +} + +iframe { border: 0 } +ol, +ul { + list-style: none; + margin: 0; + padding: 0; +} + +/** + * Suppress the focus outline on links that cannot be accessed via keyboard. + * This prevents an unwanted focus outline from appearing around elements that + * might still respond to pointer events. + */ +[tabindex="-1"]:focus { outline: none !important } diff --git a/phpBB/styles/prosilver/theme/normalize.css b/phpBB/styles/prosilver/theme/normalize.css new file mode 100644 index 0000000000..80194760ff --- /dev/null +++ b/phpBB/styles/prosilver/theme/normalize.css @@ -0,0 +1,331 @@ +/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Remove default margin. + */ +body { margin: 0 } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { display: block } + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ +[hidden], +template { display: none } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { background: transparent } + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ +a:active, +a:hover { outline: 0 } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { border-bottom: 1px dotted } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { font-weight: bold } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { font-style: italic } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Address styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { font-size: 80% } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { top: -0.5em } +sub { bottom: -0.25em } + +/* Embedded content + ========================================================================== */ +/** + * Remove border when inside `a` element in IE 8/9/10. + */ +img { border: 0 } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { overflow: hidden } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { margin: 1em 40px } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ +pre { overflow: auto } + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { overflow: visible } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { text-transform: none } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { cursor: default } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { line-height: normal } + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { height: auto } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { -webkit-appearance: none } + +/** + * Define consistent border, margin, and padding. + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { overflow: auto } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { font-weight: bold } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { padding: 0 } diff --git a/phpBB/styles/prosilver/theme/stylesheet.css b/phpBB/styles/prosilver/theme/stylesheet.css index 77c7c88b07..78fb2e4bbe 100644 --- a/phpBB/styles/prosilver/theme/stylesheet.css +++ b/phpBB/styles/prosilver/theme/stylesheet.css @@ -7,6 +7,9 @@ -------------------------------------------------------------- */ +@import url("normalize.css"); +@import url("base.css"); +@import url("utilities.css"); @import url("common.css"); @import url("links.css"); @import url("content.css"); diff --git a/phpBB/styles/prosilver/theme/utilities.css b/phpBB/styles/prosilver/theme/utilities.css new file mode 100644 index 0000000000..811291ac58 --- /dev/null +++ b/phpBB/styles/prosilver/theme/utilities.css @@ -0,0 +1,57 @@ +/* -------------------------------------------------------------- + $Utilities +-------------------------------------------------------------- */ + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +.clearfix:before, +.clearfix:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after { + content: " "; + display: table; +} +.clearfix:after, +.container:after, +.container-fluid:after, +.row:after { clear: both } + +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} + +.pull-right { float: right !important } +.pull-left { float: left !important } +.hide { display: none !important } +.show { display: block !important } +.invisible { visibility: hidden } + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +/*.hidden { + display: none !important; + visibility: hidden !important; +}*/ + +.affix { position: fixed } From 922f631a468f186f6e110beaf8ad5ee26eb35f46 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Sun, 16 Aug 2015 16:53:39 +0200 Subject: [PATCH 0572/1676] [ticket/12719] Fix Buttons --- phpBB/styles/prosilver/theme/buttons.css | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/phpBB/styles/prosilver/theme/buttons.css b/phpBB/styles/prosilver/theme/buttons.css index a816c7f7f2..c62ee832f2 100644 --- a/phpBB/styles/prosilver/theme/buttons.css +++ b/phpBB/styles/prosilver/theme/buttons.css @@ -4,7 +4,6 @@ .button { cursor: pointer; display: inline-block; - height: 18px; font-size: 1.2em; white-space: nowrap; border: 1px solid transparent; @@ -28,7 +27,6 @@ display: inline-block; float: right; height: 12px; - margin: 3px 0 0 2px; width: 12px; } @@ -55,6 +53,10 @@ float: left; } +.buttons .button:before { + margin: 3px 0 0 2px; +} + .buttons .button, .dropdown-select { margin-right: 5px; } @@ -194,7 +196,7 @@ ul.linklist.bulletin > li.small-icon:before { } .post-buttons .icon-button { - padding: 0 5px; + padding: 5px; } .hastouch .post-buttons .icon-button { From 6105f98219ed9d7dc8fa7885df9dd9ba679f47ff Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Sun, 16 Aug 2015 16:54:13 +0200 Subject: [PATCH 0573/1676] [ticket/12719] Fix pagination --- phpBB/styles/prosilver/theme/common.css | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index 19b0f65a2d..d92e7e15d5 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -841,9 +841,9 @@ fieldset.fields1 dl.pmlist dd.recipients { border: 1px solid transparent; border-radius: 2px; display: block; - font-size: 0.9em; + font-size: 10px; font-weight: normal; - line-height: 1.4em; + line-height: 14px; min-width: 10px; padding: 3px; text-align: center; @@ -862,7 +862,7 @@ fieldset.fields1 dl.pmlist dd.recipients { .pagination li.page-jump a, .pagination li.next a, .pagination li.previous a { background-repeat: no-repeat; font-size: 0; - height: 13px; + height: 14px; width: 11px; } @@ -880,15 +880,15 @@ fieldset.fields1 dl.pmlist dd.recipients { } .pagination li.page-jump a:hover, .pagination .dropdown-visible a.dropdown-trigger, .nojs .pagination .dropdown-container:hover a.dropdown-trigger { background-position: 0 -18px; } -.pagination li.next a:hover { background-position: -50px -18px; } -.pagination li.previous a:hover { background-position: -30px -18px; } +.pagination li.next a:hover { background-position: -48px -16px; } +.pagination li.previous a:hover { background-position: -29px -16px; } /* Pagination in viewforum for multipage topics */ .row .pagination { display: block; margin-top: 0; padding: 1px 0 1px 15px; - font-size: 0.9em; + font-size: 10px; background: none 0 50% no-repeat; } From 53ef8815b177d2c4826d80db6ab3d15c9b76accf Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Sun, 16 Aug 2015 16:54:37 +0200 Subject: [PATCH 0574/1676] [ticket/12719] Fix hamburger menu icon --- phpBB/styles/prosilver/theme/common.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index d92e7e15d5..7b47386fed 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -342,7 +342,7 @@ ul.linklist li.responsive-menu a.responsive-menu-link:before { position: absolute; left: 0; top: 7px; - height: .125em; + height: 2px; width: 14px; border-bottom: 0.125em solid transparent; border-top: 0.375em double transparent; From dd1b777ca779b60b3624e90a9c7a6831fbddf7c4 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Mon, 17 Aug 2015 20:24:01 +0200 Subject: [PATCH 0575/1676] [ticket/14097] Remove auto refresh on install failure PHPBB3-14097 --- phpBB/phpbb/install/installer.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index 78a0de0241..755edb5297 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -212,7 +212,6 @@ class installer } catch (\Exception $e) { - // Most likely there were a PHP failure, so let's die like a gentleman $this->iohandler->add_error_message($e->getMessage()); $this->iohandler->send_response(); $fail_cleanup = true; @@ -223,7 +222,7 @@ class installer // Send install finished message $this->iohandler->set_progress('INSTALLER_FINISHED', $this->install_config->get_task_progress_count()); } - else + else if (!$fail_cleanup) { $this->iohandler->request_refresh(); } From 8e5e954438b232f4ce7aec6a5db3d52b974c07a8 Mon Sep 17 00:00:00 2001 From: Nicofuma Date: Sun, 22 Feb 2015 23:36:27 +0100 Subject: [PATCH 0576/1676] [ticket/13645] Move the feeds to controllers PHPBB3-13645 --- .gitignore | 1 + phpBB/config/default/container/services.yml | 5 +- .../default/container/services_feed.yml | 21 +- .../default/container/services_routing.yml | 11 + .../default/container/services_twig.yml | 4 +- phpBB/config/default/routing/feed.yml | 35 ++ phpBB/config/default/routing/routing.yml | 8 + phpBB/feed.php | 220 +--------- phpBB/includes/functions.php | 2 +- phpBB/language/en/common.php | 1 + phpBB/phpbb/controller/helper.php | 93 +---- phpBB/phpbb/di/container_builder.php | 2 +- phpBB/phpbb/feed/controller/feed.php | 387 ++++++++++++++++++ phpBB/phpbb/feed/exception/feed_exception.php | 21 + .../exception/feed_unavailable_exception.php | 19 + .../feed/exception/no_feed_exception.php | 22 + .../feed/exception/no_forum_exception.php | 22 + .../feed/exception/no_topic_exception.php | 22 + .../feed/exception/unauthorized_exception.php | 19 + .../unauthorized_forum_exception.php | 22 + .../unauthorized_topic_exception.php | 22 + phpBB/phpbb/feed/factory.php | 127 ------ phpBB/phpbb/feed/forum.php | 14 +- phpBB/phpbb/feed/topic.php | 15 +- phpBB/phpbb/routing/helper.php | 153 +++++++ .../phpbb/template/twig/extension/routing.php | 43 ++ phpBB/styles/all/template/feed.xml.twig | 37 ++ .../prosilver/template/overall_header.html | 16 +- tests/controller/common_helper_route.php | 25 +- tests/functional/browse_test.php | 2 +- .../controllers_compatibility_test.php | 13 + tests/functional/feed_test.php | 133 +++--- tests/mock/controller_helper.php | 13 - tests/pagination/pagination_test.php | 3 +- 34 files changed, 1019 insertions(+), 534 deletions(-) create mode 100644 phpBB/config/default/routing/feed.yml create mode 100644 phpBB/phpbb/feed/controller/feed.php create mode 100644 phpBB/phpbb/feed/exception/feed_exception.php create mode 100644 phpBB/phpbb/feed/exception/feed_unavailable_exception.php create mode 100644 phpBB/phpbb/feed/exception/no_feed_exception.php create mode 100644 phpBB/phpbb/feed/exception/no_forum_exception.php create mode 100644 phpBB/phpbb/feed/exception/no_topic_exception.php create mode 100644 phpBB/phpbb/feed/exception/unauthorized_exception.php create mode 100644 phpBB/phpbb/feed/exception/unauthorized_forum_exception.php create mode 100644 phpBB/phpbb/feed/exception/unauthorized_topic_exception.php delete mode 100644 phpBB/phpbb/feed/factory.php create mode 100644 phpBB/phpbb/routing/helper.php create mode 100644 phpBB/phpbb/template/twig/extension/routing.php create mode 100644 phpBB/styles/all/template/feed.xml.twig diff --git a/.gitignore b/.gitignore index ef3470488c..8fd9b40073 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ /phpBB/store/* /phpBB/styles/* !/phpBB/styles/prosilver +!/phpBB/styles/all /phpBB/vendor /tests/phpbb_unit_tests.sqlite* /tests/test_config*.php diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 841b50c38b..1943381f4a 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -84,12 +84,9 @@ services: - @template - @user - @config - - @router - @symfony_request - @request - - @filesystem - - %core.root_path% - - %core.php_ext% + - @routing.helper controller.resolver: class: phpbb\controller\resolver diff --git a/phpBB/config/default/container/services_feed.yml b/phpBB/config/default/container/services_feed.yml index 48bd9fe76f..2133b3c489 100644 --- a/phpBB/config/default/container/services_feed.yml +++ b/phpBB/config/default/container/services_feed.yml @@ -1,4 +1,18 @@ services: + phpbb.feed.controller: + class: phpbb\feed\controller\feed + arguments: + - @template.twig.environment + - @symfony_request + - @controller.helper + - @config + - @dbal.conn + - @service_container + - @feed.helper + - @user + - @auth + - %core.php_ext% + feed.helper: class: phpbb\feed\helper arguments: @@ -7,13 +21,6 @@ services: - %core.root_path% - %core.php_ext% - feed.factory: - class: phpbb\feed\factory - arguments: - - @service_container - - @config - - @dbal.conn - feed.forum: class: phpbb\feed\forum scope: prototype diff --git a/phpBB/config/default/container/services_routing.yml b/phpBB/config/default/container/services_routing.yml index f76b5e5ede..ec5ccd3b89 100644 --- a/phpBB/config/default/container/services_routing.yml +++ b/phpBB/config/default/container/services_routing.yml @@ -18,3 +18,14 @@ services: - @request_stack tags: - { name: kernel.event_subscriber } + + routing.helper: + class: phpbb\routing\helper + arguments: + - @config + - @router + - @symfony_request + - @request + - @filesystem + - %core.root_path% + - %core.php_ext% diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index 2799892376..4132be49fa 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -40,9 +40,9 @@ services: - { name: twig.extension } template.twig.extensions.routing: - class: Symfony\Bridge\Twig\Extension\RoutingExtension + class: phpbb\template\twig\extension\routing arguments: - - @router + - @routing.helper tags: - { name: twig.extension } diff --git a/phpBB/config/default/routing/feed.yml b/phpBB/config/default/routing/feed.yml new file mode 100644 index 0000000000..22c9ea5755 --- /dev/null +++ b/phpBB/config/default/routing/feed.yml @@ -0,0 +1,35 @@ +phpbb_feed_forums: + path: /forums + defaults: { _controller: phpbb.feed.controller:forums } + +phpbb_feed_news: + path: /news + defaults: { _controller: phpbb.feed.controller:news } + +phpbb_feed_topics: + path: /topics + defaults: { _controller: phpbb.feed.controller:topics } + +phpbb_feed_topics_active: + path: /topics_active + defaults: { _controller: phpbb.feed.controller:topics_active } + +phpbb_feed_topics_new: + path: /topics_new + defaults: { _controller: phpbb.feed.controller:topics_new } + +phpbb_feed_forum: + path: /forum/{forum_id} + defaults: { _controller: phpbb.feed.controller:forum } + requirements: + forum_id: \d+ + +phpbb_feed_topic: + path: /topic/{topic_id} + defaults: { _controller: phpbb.feed.controller:topic } + requirements: + topic_id: \d+ + +phpbb_feed_overall: + path: /{mode} + defaults: { _controller: phpbb.feed.controller:overall } diff --git a/phpBB/config/default/routing/routing.yml b/phpBB/config/default/routing/routing.yml index b7e7a69b4f..073984841a 100644 --- a/phpBB/config/default/routing/routing.yml +++ b/phpBB/config/default/routing/routing.yml @@ -8,6 +8,14 @@ # instantiate the "foo_service" service and call the "method" method. # +phpbb_feed_routing: + resource: "feed.yml" + prefix: /feed + +phpbb_feed_index: + path: /feed + defaults: { _controller: phpbb.feed.controller:overall } + phpbb_help_routing: resource: "help.yml" prefix: /help diff --git a/phpBB/feed.php b/phpBB/feed.php index a7428ea846..1480867d6c 100644 --- a/phpBB/feed.php +++ b/phpBB/feed.php @@ -16,6 +16,9 @@ * **/ +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\Routing\Exception\InvalidParameterException; + /** * @ignore **/ @@ -23,222 +26,33 @@ define('IN_PHPBB', true); $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './'; $phpEx = substr(strrchr(__FILE__, '.'), 1); include($phpbb_root_path . 'common.' . $phpEx); -include($phpbb_root_path . 'includes/functions_display.' . $phpEx); -if (!$config['feed_enable']) -{ - trigger_error('NO_FEED_ENABLED'); -} +/** @var \phpbb\controller\helper $controller_helper */ +$controller_helper = $phpbb_container->get('controller.helper'); -// Start session -$user->session_begin(); - -if (!empty($config['feed_http_auth']) && $request->variable('auth', '') == 'http') -{ - phpbb_http_login(array( - 'auth_message' => 'Feed', - 'viewonline' => $request->variable('viewonline', true), - )); -} - -$auth->acl($user->data); -$user->setup('viewtopic'); - -// Initial var setup $forum_id = $request->variable('f', 0); $topic_id = $request->variable('t', 0); -$mode = $request->variable('mode', ''); +$mode = $request->variable('mode', ''); -// We do not use a template, therefore we simply define the global template variables here -$global_vars = $item_vars = array(); -$feed_updated_time = 0; - -// Generate params array for use in append_sid() to correctly link back to this page -$params = false; -if ($forum_id || $topic_id || $mode) +if ($forum_id !== 0) { - $params = array( - 'f' => ($forum_id) ? $forum_id : NULL, - 't' => ($topic_id) ? $topic_id : NULL, - 'mode' => ($mode) ? $mode : NULL, - ); + $url = $controller_helper->route('phpbb_feed_forum', array('forum_id' => $forum_id)); } - -// This boards URL -/* @var $phpbb_feed_helper \phpbb\feed\helper */ -$phpbb_feed_helper = $phpbb_container->get('feed.helper'); -$board_url = $phpbb_feed_helper->get_board_url(); - -// Get correct feed object -/* @var $phpbb_feed_factory \phpbb\feed\factory */ -$phpbb_feed_factory = $phpbb_container->get('feed.factory'); -$feed = $phpbb_feed_factory->get_feed($mode, $forum_id, $topic_id); - -// No feed found -if ($feed === false) +else if ($topic_id !== 0) { - trigger_error('NO_FEED'); + $url = $controller_helper->route('phpbb_feed_topic', array('topic_id' => $topic_id)); } - -// Open Feed -$feed->open(); - -// Iterate through items -while ($row = $feed->get_item()) +else { - // BBCode options to correctly disable urls, smilies, bbcode... - if ($feed->get('options') === NULL) + try { - // Allow all combinations - $options = 7; - - if ($feed->get('enable_bbcode') !== NULL && $feed->get('enable_smilies') !== NULL && $feed->get('enable_magic_url') !== NULL) - { - $options = (($row[$feed->get('enable_bbcode')]) ? OPTION_FLAG_BBCODE : 0) + (($row[$feed->get('enable_smilies')]) ? OPTION_FLAG_SMILIES : 0) + (($row[$feed->get('enable_magic_url')]) ? OPTION_FLAG_LINKS : 0); - } + $url = $controller_helper->route('phpbb_feed_overall', array('mode' => $mode)); } - else + catch (InvalidParameterException $e) { - $options = $row[$feed->get('options')]; - } - - $title = (isset($row[$feed->get('title')]) && $row[$feed->get('title')] !== '') ? $row[$feed->get('title')] : ((isset($row[$feed->get('title2')])) ? $row[$feed->get('title2')] : ''); - - $published = ($feed->get('published') !== NULL) ? (int) $row[$feed->get('published')] : 0; - $updated = ($feed->get('updated') !== NULL) ? (int) $row[$feed->get('updated')] : 0; - - $display_attachments = ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && isset($row['post_attachment']) && $row['post_attachment']) ? true : false; - - $item_row = array( - 'author' => ($feed->get('creator') !== NULL) ? $row[$feed->get('creator')] : '', - 'published' => ($published > 0) ? $phpbb_feed_helper->format_date($published) : '', - 'updated' => ($updated > 0) ? $phpbb_feed_helper->format_date($updated) : '', - 'link' => '', - 'title' => censor_text($title), - 'category' => ($config['feed_item_statistics'] && !empty($row['forum_id'])) ? $board_url . '/viewforum.' . $phpEx . '?f=' . $row['forum_id'] : '', - 'category_name' => ($config['feed_item_statistics'] && isset($row['forum_name'])) ? $row['forum_name'] : '', - 'description' => censor_text($phpbb_feed_helper->generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options, $row['forum_id'], ($display_attachments ? $feed->get_attachments($row['post_id']) : array()))), - 'statistics' => '', - ); - - // Adjust items, fill link, etc. - $feed->adjust_item($item_row, $row); - - $item_vars[] = $item_row; - - $feed_updated_time = max($feed_updated_time, $published, $updated); -} - -// If we do not have any items at all, sending the current time is better than sending no time. -if (!$feed_updated_time) -{ - $feed_updated_time = time(); -} - -// Some default assignments -// FEED_IMAGE is not used (atom) -$global_vars = array_merge($global_vars, array( - 'FEED_IMAGE' => '', - 'SELF_LINK' => $phpbb_feed_helper->append_sid('feed.' . $phpEx, $params), - 'FEED_LINK' => $board_url . '/index.' . $phpEx, - 'FEED_TITLE' => $config['sitename'], - 'FEED_SUBTITLE' => $config['site_desc'], - 'FEED_UPDATED' => $phpbb_feed_helper->format_date($feed_updated_time), - 'FEED_LANG' => $user->lang['USER_LANG'], - 'FEED_AUTHOR' => $config['sitename'], -)); - -$feed->close(); - -// Output page - -// gzip_compression -if ($config['gzip_compress']) -{ - if (@extension_loaded('zlib') && !headers_sent()) - { - ob_start('ob_gzhandler'); + $url = $controller_helper->route('phpbb_feed_index'); } } -// IF debug extra is enabled and admin want to "explain" the page we need to set other headers... -if (defined('DEBUG') && $request->variable('explain', 0) && $auth->acl_get('a_')) -{ - header('Content-type: text/html; charset=UTF-8'); - header('Cache-Control: private, no-cache="set-cookie"'); - header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT'); - - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; - - if (method_exists($db, 'sql_report')) - { - $db->sql_report('display'); - } - - garbage_collection(); - exit_handler(); -} - -header("Content-Type: application/atom+xml; charset=UTF-8"); -header("Last-Modified: " . gmdate('D, d M Y H:i:s', $feed_updated_time) . ' GMT'); - -if (!empty($user->data['is_bot'])) -{ - // Let reverse proxies know we detected a bot. - header('X-PHPBB-IS-BOT: yes'); -} - -echo '' . "\n"; -echo '' . "\n"; -echo '' . "\n\n"; - -echo (!empty($global_vars['FEED_TITLE'])) ? '' . $global_vars['FEED_TITLE'] . '' . "\n" : ''; -echo (!empty($global_vars['FEED_SUBTITLE'])) ? '' . $global_vars['FEED_SUBTITLE'] . '' . "\n" : ''; -echo (!empty($global_vars['FEED_LINK'])) ? '' . "\n" : ''; -echo '' . $global_vars['FEED_UPDATED'] . '' . "\n\n"; - -echo '' . "\n"; -echo '' . $global_vars['SELF_LINK'] . '' . "\n"; - -foreach ($item_vars as $row) -{ - echo '' . "\n"; - - if (!empty($row['author'])) - { - echo '' . "\n"; - } - - echo '' . ((!empty($row['updated'])) ? $row['updated'] : $row['published']) . '' . "\n"; - - if (!empty($row['published'])) - { - echo '' . $row['published'] . '' . "\n"; - } - - echo '' . $row['link'] . '' . "\n"; - echo '' . "\n"; - echo '<![CDATA[' . $row['title'] . ']]>' . "\n\n"; - - if (!empty($row['category']) && isset($row['category_name']) && $row['category_name'] !== '') - { - echo '' . "\n"; - } - - echo '' . $user->lang['STATISTICS'] . ': ' . $row['statistics'] . '

      '; - } - - echo '
      ' . "\n" . ']]>' . "\n"; - echo '' . "\n"; -} - -echo ''; - -garbage_collection(); -exit_handler(); +$response = new RedirectResponse($url, 301); +$response->send(); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index c6d63e13f4..56068242dd 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4351,7 +4351,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = 'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'), 'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'), 'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '', - 'U_FEED' => generate_board_url() . "/feed.$phpEx", + 'U_FEED' => $controller_helper->route('phpbb_feed_index'), 'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false, 'S_AUTOLOGIN_ENABLED' => ($config['allow_autologin']) ? true : false, diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index cb99183dd8..76fa1c15f7 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -691,6 +691,7 @@ $lang = array_merge($lang, array( 'SKYPE' => 'Skype', 'SMTP_NO_AUTH_SUPPORT' => 'SMTP server does not support authentication.', 'SORRY_AUTH_READ' => 'You are not authorised to read this forum.', + 'SORRY_AUTH_READ_TOPIC' => 'You are not authorised to read this topic.', 'SORRY_AUTH_VIEW_ATTACH' => 'You are not authorised to download this attachment.', 'SORT_BY' => 'Sort by', 'SORT_JOINED' => 'Joined date', diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index 3782512fa4..5722951278 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -16,7 +16,6 @@ namespace phpbb\controller; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\RequestContext; /** * Controller helper class, contains methods that do things for controllers @@ -41,12 +40,6 @@ class helper */ protected $config; - /** - * phpBB router - * @var \phpbb\routing\router - */ - protected $router; - /* @var \phpbb\symfony_request */ protected $symfony_request; @@ -54,21 +47,9 @@ class helper protected $request; /** - * @var \phpbb\filesystem\filesystem_interface The filesystem object - */ - protected $filesystem; - - /** - * phpBB root path - * @var string - */ - protected $phpbb_root_path; - - /** - * PHP file extension - * @var string - */ - protected $php_ext; + * @var \phpbb\routing\helper + */ + protected $routing_helper; /** * Constructor @@ -76,24 +57,18 @@ class helper * @param \phpbb\template\template $template Template object * @param \phpbb\user $user User object * @param \phpbb\config\config $config Config object - * @param \phpbb\routing\router $router phpBB router * @param \phpbb\symfony_request $symfony_request Symfony Request object * @param \phpbb\request\request_interface $request phpBB request object - * @param \phpbb\filesystem\filesystem_interface $filesystem The filesystem object - * @param string $phpbb_root_path phpBB root path - * @param string $php_ext PHP file extension + * @param \phpbb\routing\helper $routing_helper Helper to generate the routes */ - public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\routing\helper $routing_helper) { $this->template = $template; $this->user = $user; $this->config = $config; - $this->router = $router; $this->symfony_request = $symfony_request; $this->request = $request; - $this->filesystem = $filesystem; - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $php_ext; + $this->routing_helper = $routing_helper; } /** @@ -131,61 +106,7 @@ class helper */ public function route($route, array $params = array(), $is_amp = true, $session_id = false, $reference_type = UrlGeneratorInterface::ABSOLUTE_PATH) { - $anchor = ''; - if (isset($params['#'])) - { - $anchor = '#' . $params['#']; - unset($params['#']); - } - - $context = new RequestContext(); - $context->fromRequest($this->symfony_request); - - $script_name = $this->symfony_request->getScriptName(); - $page_name = substr($script_name, -1, 1) == '/' ? '' : utf8_basename($script_name); - - $base_url = $context->getBaseUrl(); - - // Append page name if base URL does not contain it - if (!empty($page_name) && strpos($base_url, '/' . $page_name) === false) - { - $base_url .= '/' . $page_name; - } - - // If enable_mod_rewrite is false we need to replace the current front-end by app.php, otherwise we need to remove it. - $base_url = str_replace('/' . $page_name, empty($this->config['enable_mod_rewrite']) ? '/app.' . $this->php_ext : '', $base_url); - - // We need to update the base url to move to the directory of the app.php file if the current script is not app.php - if ($page_name !== 'app.php') - { - if (empty($this->config['enable_mod_rewrite'])) - { - $base_url = str_replace('/app.' . $this->php_ext, '/' . $this->phpbb_root_path . 'app.' . $this->php_ext, $base_url); - } - else - { - $base_url .= preg_replace(get_preg_expression('path_remove_dot_trailing_slash'), '$2', $this->phpbb_root_path); - } - } - - $base_url = $this->request->escape($this->filesystem->clean_path($base_url), true); - - $context->setBaseUrl($base_url); - - $this->router->setContext($context); - $route_url = $this->router->generate($route, $params, $reference_type); - - if ($is_amp) - { - $route_url = str_replace(array('&', '&'), array('&', '&'), $route_url); - } - - if ($reference_type === UrlGeneratorInterface::RELATIVE_PATH && empty($this->config['enable_mod_rewrite'])) - { - $route_url = 'app.' . $this->php_ext . '/' . $route_url; - } - - return append_sid($route_url . $anchor, false, $is_amp, $session_id, true); + return $this->routing_helper->route($route, $params, $is_amp, $session_id, $reference_type); } /** diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index c9adbe7d63..fb391760ce 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -465,7 +465,7 @@ class container_builder 'core.root_path' => $this->phpbb_root_path, 'core.php_ext' => $this->php_ext, 'core.environment' => $this->get_environment(), - 'core.debug' => DEBUG, + 'core.debug' => defined('DEBUG') ? DEBUG : false, ), $this->get_env_parameters() ); diff --git a/phpBB/phpbb/feed/controller/feed.php b/phpBB/phpbb/feed/controller/feed.php new file mode 100644 index 0000000000..a2dd9393f6 --- /dev/null +++ b/phpBB/phpbb/feed/controller/feed.php @@ -0,0 +1,387 @@ + +* @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\feed\controller; + +use phpbb\auth\auth; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\exception\http_exception; +use phpbb\feed\base; +use phpbb\feed\exception\feed_unavailable_exception; +use phpbb\feed\exception\unauthorized_exception; +use phpbb\feed\helper as feed_helper; +use phpbb\controller\helper as controller_helper; +use phpbb\symfony_request; +use phpbb\user; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; + +class feed +{ + /** + * @var \Twig_Environment + */ + protected $template; + + /** + * @var symfony_request + */ + protected $request; + + /** + * @var controller_helper + */ + protected $controller_helper; + + /** + * @var config + */ + protected $config; + + /** + * @var driver_interface + */ + protected $db; + + /** + * @var ContainerInterface + */ + protected $container; + + /** + * @var feed_helper + */ + protected $feed_helper; + + /** + * @var user + */ + protected $user; + + /** + * @var auth + */ + protected $auth; + + /** + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param symfony_request $request; + * @param controller_helper $controller_helper + * @param config $config + * @param driver_interface $db + * @param ContainerInterface $container + * @param feed_helper $feed_helper + * @param user $user + * @param auth $auth + */ + public function __construct(\Twig_Environment $twig, symfony_request $request, controller_helper $controller_helper, config $config, driver_interface $db, ContainerInterface $container, feed_helper $feed_helper, user $user, auth $auth, $php_ext) + { + $this->request = $request; + $this->controller_helper = $controller_helper; + $this->config = $config; + $this->db = $db; + $this->container = $container; + $this->feed_helper = $feed_helper; + $this->user = $user; + $this->auth = $auth; + $this->php_ext = $php_ext; + $this->template = $twig; + } + + /** + * Controller for /feed/forums route + * + * @return Response + * + * @throws http_exception when the feed is disabled + */ + public function forums() + { + if (!$this->config['feed_overall_forums']) + { + $this->send_unavailable(); + } + + return $this->send_feed($this->container->get('feed.forums')); + } + + /** + * Controller for /feed/news route + * + * @return Response + * + * @throws http_exception when the feed is disabled + */ + public function news() + { + // Get at least one news forum + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0'); + $result = $this->db->sql_query_limit($sql, 1, 0, 600); + $s_feed_news = (int) $this->db->sql_fetchfield('forum_id'); + $this->db->sql_freeresult($result); + + if (!$s_feed_news) + { + $this->send_unavailable(); + } + + return $this->send_feed($this->container->get('feed.news')); + } + + /** + * Controller for /feed/topics route + * + * @return Response + * + * @throws http_exception when the feed is disabled + */ + public function topics() + { + if (!$this->config['feed_topics_new']) + { + $this->send_unavailable(); + } + + return $this->send_feed($this->container->get('feed.topics')); + } + + /** + * Controller for /feed/topics_new route + * + * @return Response + * + * @throws http_exception when the feed is disabled + */ + public function topics_new() + { + return $this->topics(); + } + + /** + * Controller for /feed/topics_active route + * + * @return Response + * + * @throws http_exception when the feed is disabled + */ + public function topics_active() + { + if (!$this->config['feed_topics_active']) + { + $this->send_unavailable(); + } + + return $this->send_feed($this->container->get('feed.topics_active')); + } + + /** + * Controller for /feed/forum/{forum_id} route + * + * @param int $forum_id + * + * @return Response + * + * @throws http_exception when the feed is disabled + */ + public function forum($forum_id) + { + if (!$this->config['feed_forum']) + { + $this->send_unavailable(); + } + + return $this->send_feed($this->container->get('feed.forum')->set_forum_id($forum_id)); + } + + /** + * Controller for /feed/topic/{topic_id} route + * + * @param int $topic_id + * + * @return Response + * + * @throws http_exception when the feed is disabled + */ + public function topic($topic_id) + { + if (!$this->config['feed_topic']) + { + $this->send_unavailable(); + } + + return $this->send_feed($this->container->get('feed.topic')->set_topic_id($topic_id)); + } + + /** + * Controller for /feed/{mode] route + * + * @return Response + * + * @throws http_exception when the feed is disabled + */ + public function overall() + { + if (!$this->config['feed_overall']) + { + $this->send_unavailable(); + } + + return $this->send_feed($this->container->get('feed.overall')); + } + + /** + * Display a given feed + * + * @param base $feed + * + * @return Response + */ + protected function send_feed(base $feed) + { + try + { + return $this->send_feed_do($feed); + } + catch (feed_unavailable_exception $e) + { + throw new http_exception(Response::HTTP_NOT_FOUND, $e->getMessage(), $e->get_parameters(), $e); + } + catch (unauthorized_exception $e) + { + throw new http_exception(Response::HTTP_FORBIDDEN, $e->getMessage(), $e->get_parameters(), $e); + } + } + + /** + * Really send the feed + * + * @param base $feed + * + * @return Response + * + * @throw exception\feed_exception + */ + protected function send_feed_do(base $feed) + { + $feed_updated_time = 0; + $item_vars = array(); + + $board_url = $this->feed_helper->get_board_url(); + + // Open Feed + $feed->open(); + + // Iterate through items + while ($row = $feed->get_item()) + { + // BBCode options to correctly disable urls, smilies, bbcode... + if ($feed->get('options') === null) + { + // Allow all combinations + $options = 7; + + if ($feed->get('enable_bbcode') !== null && $feed->get('enable_smilies') !== null && $feed->get('enable_magic_url') !== null) + { + $options = (($row[$feed->get('enable_bbcode')]) ? OPTION_FLAG_BBCODE : 0) + (($row[$feed->get('enable_smilies')]) ? OPTION_FLAG_SMILIES : 0) + (($row[$feed->get('enable_magic_url')]) ? OPTION_FLAG_LINKS : 0); + } + } + else + { + $options = $row[$feed->get('options')]; + } + + $title = (isset($row[$feed->get('title')]) && $row[$feed->get('title')] !== '') ? $row[$feed->get('title')] : ((isset($row[$feed->get('title2')])) ? $row[$feed->get('title2')] : ''); + + $published = ($feed->get('published') !== null) ? (int) $row[$feed->get('published')] : 0; + $updated = ($feed->get('updated') !== null) ? (int) $row[$feed->get('updated')] : 0; + + $display_attachments = ($this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $row['forum_id']) && isset($row['post_attachment']) && $row['post_attachment']) ? true : false; + + $item_row = array( + 'author' => ($feed->get('creator') !== null) ? $row[$feed->get('creator')] : '', + 'published' => ($published > 0) ? $this->feed_helper->format_date($published) : '', + 'updated' => ($updated > 0) ? $this->feed_helper->format_date($updated) : '', + 'link' => '', + 'title' => censor_text($title), + 'category' => ($this->config['feed_item_statistics'] && !empty($row['forum_id'])) ? $board_url . '/viewforum.' . $this->php_ext . '?f=' . $row['forum_id'] : '', + 'category_name' => ($this->config['feed_item_statistics'] && isset($row['forum_name'])) ? $row['forum_name'] : '', + 'description' => censor_text($this->feed_helper->generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options, $row['forum_id'], ($display_attachments ? $feed->get_attachments($row['post_id']) : array()))), + 'statistics' => '', + ); + + // Adjust items, fill link, etc. + $feed->adjust_item($item_row, $row); + + $item_vars[] = $item_row; + + $feed_updated_time = max($feed_updated_time, $published, $updated); + } + + // If we do not have any items at all, sending the current time is better than sending no time. + if (!$feed_updated_time) + { + $feed_updated_time = time(); + } + + $feed->close(); + + $content = $this->template->render('feed.xml.twig', array( + // Some default assignments + // FEED_IMAGE is not used (atom) + 'FEED_IMAGE' => '', + 'SELF_LINK' => $this->controller_helper->route($this->request->attributes->get('_route'), $this->request->attributes->get('_route_params'), true, '', UrlGeneratorInterface::ABSOLUTE_URL), + 'FEED_LINK' => $board_url . '/index.' . $this->php_ext, + 'FEED_TITLE' => $this->config['sitename'], + 'FEED_SUBTITLE' => $this->config['site_desc'], + 'FEED_UPDATED' => $this->feed_helper->format_date($feed_updated_time), + 'FEED_LANG' => $this->user->lang['USER_LANG'], + 'FEED_AUTHOR' => $this->config['sitename'], + + // Feed entries + 'FEED_ROWS' => $item_vars, + )); + + $response = new Response($content); + $response->headers->set('Content-Type', 'application/atom+xml'); + $response->setCharset('UTF-8'); + $response->setLastModified(new \DateTime('@' . $feed_updated_time)); + + if (!empty($this->user->data['is_bot'])) + { + // Let reverse proxies know we detected a bot. + $response->headers->set('X-PHPBB-IS-BOT', 'yes'); + } + + return $response; + } + + /** + * Throw and exception saying that the feed isn't available + * + * @throw http_exception + */ + protected function send_unavailable() + { + throw new http_exception(404, 'FEATURE_NOT_AVAILABLE'); + } +} diff --git a/phpBB/phpbb/feed/exception/feed_exception.php b/phpBB/phpbb/feed/exception/feed_exception.php new file mode 100644 index 0000000000..c9c888211e --- /dev/null +++ b/phpBB/phpbb/feed/exception/feed_exception.php @@ -0,0 +1,21 @@ + + * @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\feed\exception; + +use phpbb\exception\runtime_exception; + +abstract class feed_exception extends runtime_exception +{ + +} diff --git a/phpBB/phpbb/feed/exception/feed_unavailable_exception.php b/phpBB/phpbb/feed/exception/feed_unavailable_exception.php new file mode 100644 index 0000000000..4b6605b47d --- /dev/null +++ b/phpBB/phpbb/feed/exception/feed_unavailable_exception.php @@ -0,0 +1,19 @@ + + * @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\feed\exception; + +abstract class feed_unavailable_exception extends feed_exception +{ + +} diff --git a/phpBB/phpbb/feed/exception/no_feed_exception.php b/phpBB/phpbb/feed/exception/no_feed_exception.php new file mode 100644 index 0000000000..af6357b74c --- /dev/null +++ b/phpBB/phpbb/feed/exception/no_feed_exception.php @@ -0,0 +1,22 @@ + + * @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\feed\exception; + +class no_feed_exception extends feed_unavailable_exception +{ + public function __construct(\Exception $previous = null, $code = 0) + { + parent::__construct('NO_FEED', array(), $previous, $code); + } +} diff --git a/phpBB/phpbb/feed/exception/no_forum_exception.php b/phpBB/phpbb/feed/exception/no_forum_exception.php new file mode 100644 index 0000000000..a60832957a --- /dev/null +++ b/phpBB/phpbb/feed/exception/no_forum_exception.php @@ -0,0 +1,22 @@ + + * @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\feed\exception; + +class no_forum_exception extends feed_unavailable_exception +{ + public function __construct($forum_id, \Exception $previous = null, $code = 0) + { + parent::__construct('NO_FORUM', array($forum_id), $previous, $code); + } +} diff --git a/phpBB/phpbb/feed/exception/no_topic_exception.php b/phpBB/phpbb/feed/exception/no_topic_exception.php new file mode 100644 index 0000000000..b961a65d1c --- /dev/null +++ b/phpBB/phpbb/feed/exception/no_topic_exception.php @@ -0,0 +1,22 @@ + + * @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\feed\exception; + +class no_topic_exception extends feed_unavailable_exception +{ + public function __construct($topic_id, \Exception $previous = null, $code = 0) + { + parent::__construct('NO_TOPIC', array($topic_id), $previous, $code); + } +} diff --git a/phpBB/phpbb/feed/exception/unauthorized_exception.php b/phpBB/phpbb/feed/exception/unauthorized_exception.php new file mode 100644 index 0000000000..7868975779 --- /dev/null +++ b/phpBB/phpbb/feed/exception/unauthorized_exception.php @@ -0,0 +1,19 @@ + + * @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\feed\exception; + +abstract class unauthorized_exception extends feed_exception +{ + +} diff --git a/phpBB/phpbb/feed/exception/unauthorized_forum_exception.php b/phpBB/phpbb/feed/exception/unauthorized_forum_exception.php new file mode 100644 index 0000000000..4384c7b39b --- /dev/null +++ b/phpBB/phpbb/feed/exception/unauthorized_forum_exception.php @@ -0,0 +1,22 @@ + + * @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\feed\exception; + +class unauthorized_forum_exception extends unauthorized_exception +{ + public function __construct($forum_id, \Exception $previous = null, $code = 0) + { + parent::__construct('SORRY_AUTH_READ', array($forum_id), $previous, $code); + } +} diff --git a/phpBB/phpbb/feed/exception/unauthorized_topic_exception.php b/phpBB/phpbb/feed/exception/unauthorized_topic_exception.php new file mode 100644 index 0000000000..f49f0a0476 --- /dev/null +++ b/phpBB/phpbb/feed/exception/unauthorized_topic_exception.php @@ -0,0 +1,22 @@ + + * @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\feed\exception; + +class unauthorized_topic_exception extends unauthorized_exception +{ + public function __construct($topic_id, \Exception $previous = null, $code = 0) + { + parent::__construct('SORRY_AUTH_READ_TOPIC', array($topic_id), $previous, $code); + } +} diff --git a/phpBB/phpbb/feed/factory.php b/phpBB/phpbb/feed/factory.php deleted file mode 100644 index f364f06d03..0000000000 --- a/phpBB/phpbb/feed/factory.php +++ /dev/null @@ -1,127 +0,0 @@ - -* @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\feed; - -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** -* Factory class to return correct object -*/ -class factory -{ - /** - * Service container object - * @var ContainerInterface - */ - protected $container; - - /** @var \phpbb\config\config */ - protected $config; - - /** @var \phpbb\db\driver\driver_interface */ - protected $db; - - /** - * Constructor - * - * @param ContainerInterface $container Container object - * @param \phpbb\config\config $config Config object - * @param \phpbb\db\driver\driver_interface $db Database connection - */ - public function __construct(ContainerInterface $container, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db) - { - $this->container = $container; - $this->config = $config; - $this->db = $db; - } - - /** - * Return correct object for specified mode - * - * @param string $mode The feeds mode. - * @param int $forum_id Forum id specified by the script if forum feed provided. - * @param int $topic_id Topic id specified by the script if topic feed provided. - * - * @return object Returns correct feeds object for specified mode. - */ - function get_feed($mode, $forum_id, $topic_id) - { - switch ($mode) - { - case 'forums': - if (!$this->config['feed_overall_forums']) - { - return false; - } - - return $this->container->get('feed.forums'); - break; - - case 'topics': - case 'topics_new': - if (!$this->config['feed_topics_new']) - { - return false; - } - - return $this->container->get('feed.topics'); - break; - - case 'topics_active': - if (!$this->config['feed_topics_active']) - { - return false; - } - - return $this->container->get('feed.topics_active'); - break; - - case 'news': - // Get at least one news forum - $sql = 'SELECT forum_id - FROM ' . FORUMS_TABLE . ' - WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0'); - $result = $this->db->sql_query_limit($sql, 1, 0, 600); - $s_feed_news = (int) $this->db->sql_fetchfield('forum_id'); - $this->db->sql_freeresult($result); - - if (!$s_feed_news) - { - return false; - } - - return $this->container->get('feed.news'); - break; - - default: - if ($topic_id && $this->config['feed_topic']) - { - return $this->container->get('feed.topic') - ->set_topic_id($topic_id); - } - else if ($forum_id && $this->config['feed_forum']) - { - return $this->container->get('feed.forum') - ->set_forum_id($forum_id); - } - else if ($this->config['feed_overall']) - { - return $this->container->get('feed.overall'); - } - - return false; - break; - } - } -} diff --git a/phpBB/phpbb/feed/forum.php b/phpBB/phpbb/feed/forum.php index 7a2087c1cd..f493c4729a 100644 --- a/phpBB/phpbb/feed/forum.php +++ b/phpBB/phpbb/feed/forum.php @@ -13,6 +13,10 @@ namespace phpbb\feed; +use phpbb\feed\exception\no_feed_exception; +use phpbb\feed\exception\no_forum_exception; +use phpbb\feed\exception\unauthorized_forum_exception; + /** * Forum feed * @@ -49,25 +53,25 @@ class forum extends \phpbb\feed\post_base if (empty($this->forum_data)) { - trigger_error('NO_FORUM'); + throw new no_forum_exception($this->forum_id); } // Forum needs to be postable if ($this->forum_data['forum_type'] != FORUM_POST) { - trigger_error('NO_FEED'); + throw new no_feed_exception(); } // Make sure forum is not excluded from feed if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->forum_data['forum_options'])) { - trigger_error('NO_FEED'); + throw new no_feed_exception(); } // Make sure we can read this forum if (!$this->auth->acl_get('f_read', $this->forum_id)) { - trigger_error('SORRY_AUTH_READ'); + throw new unauthorized_forum_exception($this->forum_id); } // Make sure forum is not passworded or user is authed @@ -77,7 +81,7 @@ class forum extends \phpbb\feed\post_base if (isset($forum_ids_passworded[$this->forum_id])) { - trigger_error('SORRY_AUTH_READ'); + throw new unauthorized_forum_exception($this->forum_id); } unset($forum_ids_passworded); diff --git a/phpBB/phpbb/feed/topic.php b/phpBB/phpbb/feed/topic.php index 66c49e55cf..c916d3bccc 100644 --- a/phpBB/phpbb/feed/topic.php +++ b/phpBB/phpbb/feed/topic.php @@ -13,6 +13,11 @@ namespace phpbb\feed; +use phpbb\feed\exception\no_feed_exception; +use phpbb\feed\exception\no_topic_exception; +use phpbb\feed\exception\unauthorized_forum_exception; +use phpbb\feed\exception\unauthorized_topic_exception; + /** * Topic feed for a specific topic * @@ -50,7 +55,7 @@ class topic extends \phpbb\feed\post_base if (empty($this->topic_data)) { - trigger_error('NO_TOPIC'); + throw new no_topic_exception($this->topic_id); } $this->forum_id = (int) $this->topic_data['forum_id']; @@ -58,19 +63,19 @@ class topic extends \phpbb\feed\post_base // Make sure topic is either approved or user authed if ($this->topic_data['topic_visibility'] != ITEM_APPROVED && !$this->auth->acl_get('m_approve', $this->forum_id)) { - trigger_error('SORRY_AUTH_READ'); + throw new unauthorized_topic_exception($this->topic_id); } // Make sure forum is not excluded from feed if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->topic_data['forum_options'])) { - trigger_error('NO_FEED'); + throw new no_feed_exception(); } // Make sure we can read this forum if (!$this->auth->acl_get('f_read', $this->forum_id)) { - trigger_error('SORRY_AUTH_READ'); + throw new unauthorized_forum_exception($this->forum_id); } // Make sure forum is not passworded or user is authed @@ -80,7 +85,7 @@ class topic extends \phpbb\feed\post_base if (isset($forum_ids_passworded[$this->forum_id])) { - trigger_error('SORRY_AUTH_READ'); + throw new unauthorized_forum_exception($this->forum_id); } unset($forum_ids_passworded); diff --git a/phpBB/phpbb/routing/helper.php b/phpBB/phpbb/routing/helper.php new file mode 100644 index 0000000000..f56974a354 --- /dev/null +++ b/phpBB/phpbb/routing/helper.php @@ -0,0 +1,153 @@ + +* @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\routing; + +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RequestContext; + +/** +* Controller helper class, contains methods that do things for controllers +*/ +class helper +{ + /** + * config object + * @var \phpbb\config\config + */ + protected $config; + + /** + * phpBB router + * @var \phpbb\routing\router + */ + protected $router; + + /** + * @var \phpbb\symfony_request + */ + protected $symfony_request; + + /** + * @var \phpbb\request\request_interface + */ + protected $request; + + /** + * @var \phpbb\filesystem The filesystem object + */ + protected $filesystem; + + /** + * phpBB root path + * @var string + */ + protected $phpbb_root_path; + + /** + * PHP file extension + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param \phpbb\config\config $config Config object + * @param \phpbb\routing\router $router phpBB router + * @param \phpbb\symfony_request $symfony_request Symfony Request object + * @param \phpbb\request\request_interface $request phpBB request object + * @param \phpbb\filesystem\filesystem $filesystem The filesystem object + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP file extension + */ + public function __construct(\phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem\filesystem $filesystem, $phpbb_root_path, $php_ext) + { + $this->config = $config; + $this->router = $router; + $this->symfony_request = $symfony_request; + $this->request = $request; + $this->filesystem = $filesystem; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + } + + /** + * Generate a URL to a route + * + * @param string $route Name of the route to travel + * @param array $params String or array of additional url parameters + * @param bool $is_amp Is url using & (true) or & (false) + * @param string|bool $session_id Possibility to use a custom session id instead of the global one + * @param bool|string $reference_type The type of reference to be generated (one of the constants) + * @return string The URL already passed through append_sid() + */ + public function route($route, array $params = array(), $is_amp = true, $session_id = false, $reference_type = UrlGeneratorInterface::ABSOLUTE_PATH) + { + $anchor = ''; + if (isset($params['#'])) + { + $anchor = '#' . $params['#']; + unset($params['#']); + } + + $context = new RequestContext(); + $context->fromRequest($this->symfony_request); + + $script_name = $this->symfony_request->getScriptName(); + $page_name = substr($script_name, -1, 1) == '/' ? '' : utf8_basename($script_name); + + $base_url = $context->getBaseUrl(); + + // Append page name if base URL does not contain it + if (!empty($page_name) && strpos($base_url, '/' . $page_name) === false) + { + $base_url .= '/' . $page_name; + } + + // If enable_mod_rewrite is false we need to replace the current front-end by app.php, otherwise we need to remove it. + $base_url = str_replace('/' . $page_name, empty($this->config['enable_mod_rewrite']) ? '/app.' . $this->php_ext : '', $base_url); + + // We need to update the base url to move to the directory of the app.php file if the current script is not app.php + if ($page_name !== 'app.php') + { + if (empty($this->config['enable_mod_rewrite'])) + { + $base_url = str_replace('/app.' . $this->php_ext, '/' . $this->phpbb_root_path . 'app.' . $this->php_ext, $base_url); + } + else + { + $base_url .= preg_replace(get_preg_expression('path_remove_dot_trailing_slash'), '$2', $this->phpbb_root_path); + } + } + + $base_url = $this->request->escape($this->filesystem->clean_path($base_url), true); + + $context->setBaseUrl($base_url); + + $this->router->setContext($context); + $route_url = $this->router->generate($route, $params, $reference_type); + + if ($is_amp) + { + $route_url = str_replace(array('&', '&'), array('&', '&'), $route_url); + } + + if ($reference_type === UrlGeneratorInterface::RELATIVE_PATH && empty($this->config['enable_mod_rewrite'])) + { + $route_url = 'app.' . $this->php_ext . '/' . $route_url; + } + + return append_sid($route_url . $anchor, false, $is_amp, $session_id, true); + } +} diff --git a/phpBB/phpbb/template/twig/extension/routing.php b/phpBB/phpbb/template/twig/extension/routing.php new file mode 100644 index 0000000000..829ce738eb --- /dev/null +++ b/phpBB/phpbb/template/twig/extension/routing.php @@ -0,0 +1,43 @@ + +* @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\template\twig\extension; + +use Symfony\Bridge\Twig\Extension\RoutingExtension; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; + +class routing extends RoutingExtension +{ + /** @var \phpbb\controller\helper */ + protected $helper; + + /** + * Constructor + * + * @param \phpbb\routing\helper $helper + */ + public function __construct(\phpbb\routing\helper $helper) + { + $this->helper = $helper; + } + + public function getPath($name, $parameters = array(), $relative = false) + { + return $this->helper->route($name, $parameters, true, false, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH); + } + + public function getUrl($name, $parameters = array(), $schemeRelative = false) + { + return $this->helper->route($name, $parameters, true, false, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL); + } +} diff --git a/phpBB/styles/all/template/feed.xml.twig b/phpBB/styles/all/template/feed.xml.twig new file mode 100644 index 0000000000..91467c62cd --- /dev/null +++ b/phpBB/styles/all/template/feed.xml.twig @@ -0,0 +1,37 @@ + + + + + {% if not FEED_TITLE is empty %}{{ FEED_TITLE }}{% endif %} + + {% if not FEED_SUBTITLE is empty %}{{ FEED_SUBTITLE }}{% endif %} + + {% if not FEED_LINK is empty %}{% endif %} + + {{ FEED_UPDATED }} + + + {{ SELF_LINK }} + + {% for row in FEED_ROWS %} + + {% if not row.author is empty %}{% endif %} + + {% if not row.updated is empty %}{{ row.updated }} {% else %}{{ row.published }}{% endif %} + + {% if not row.published is empty %}{{ row.published }}{% endif %} + + {{ row.link }} + + <![CDATA[{{ row.title }}]]> + + {% if not row.category is empty and row.category_name is defined and row.category_name != '' %} + + {% endif %} + + {{ lang('STATISTICS') }}: {{ row.statistics }}

      {% endif %}
      +]]>
      +
      + {% endfor %} +
      diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index 45f8eaa1c9..40e735c5c2 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -7,13 +7,13 @@ <!-- IF UNREAD_NOTIFICATIONS_COUNT -->({UNREAD_NOTIFICATIONS_COUNT}) <!-- ENDIF --><!-- IF not S_VIEWTOPIC and not S_VIEWFORUM -->{SITENAME} - <!-- ENDIF --><!-- IF S_IN_MCP -->{L_MCP} - <!-- ELSEIF S_IN_UCP -->{L_UCP} - <!-- ENDIF -->{PAGE_TITLE}<!-- IF S_VIEWTOPIC or S_VIEWFORUM --> - {SITENAME}<!-- ENDIF --> - - - - - - - + + + + + + + @@ -46,7 +46,7 @@ - + diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index 3c74c16bae..4c0c8569a3 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -125,6 +125,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case $this->router = new phpbb_mock_router($container, $this->filesystem, dirname(__FILE__) . '/', 'php', PHPBB_ENVIRONMENT, $this->extension_manager); $this->router->find_routing_files($this->extension_manager->all_enabled(false)); $this->router->find(dirname(__FILE__) . '/'); + // Set correct current phpBB root path $this->root_path = $this->get_phpbb_root_path(); } @@ -168,7 +169,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_no_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id), $description); } @@ -211,7 +213,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id), $description); } @@ -254,7 +257,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_absolute($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description); } @@ -297,7 +301,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_relative_path($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description); } @@ -340,7 +345,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_network($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description); } @@ -383,7 +389,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_absolute_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description); } @@ -423,7 +430,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_relative_path_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description); } @@ -466,7 +474,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case public function test_helper_url_network_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description) { $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); + $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); $this->assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description); } } diff --git a/tests/functional/browse_test.php b/tests/functional/browse_test.php index 4f28879687..280e814c06 100644 --- a/tests/functional/browse_test.php +++ b/tests/functional/browse_test.php @@ -48,7 +48,7 @@ class phpbb_functional_browse_test extends phpbb_functional_test_case public function test_feed() { - $crawler = self::request('GET', 'feed.php', array(), false); + $crawler = self::request('GET', 'app.php/feed', array(), false); self::assert_response_xml(); $this->assertGreaterThan(0, $crawler->filter('entry')->count()); } diff --git a/tests/functional/controllers_compatibility_test.php b/tests/functional/controllers_compatibility_test.php index 7ba0b0d991..9499888a1a 100644 --- a/tests/functional/controllers_compatibility_test.php +++ b/tests/functional/controllers_compatibility_test.php @@ -24,6 +24,19 @@ class phpbb_functional_controllers_compatibility_test extends phpbb_functional_t $this->assert301('report.php?pm=1', 'app.php/pm/1/report'); } + public function test_feed_compatibility() + { + $this->assert301('feed.php', 'app.php/feed'); + $this->assert301('feed.php?mode=foobar', 'app.php/feed/foobar'); + $this->assert301('feed.php?mode=news', 'app.php/feed/news'); + $this->assert301('feed.php?mode=topics', 'app.php/feed/topics'); + $this->assert301('feed.php?mode=topics_news', 'app.php/feed/topics_news'); + $this->assert301('feed.php?mode=topics_active', 'app.php/feed/topics_active'); + $this->assert301('feed.php?mode=forums', 'app.php/feed/forums'); + $this->assert301('feed.php?f=1', 'app.php/feed/forum/1'); + $this->assert301('feed.php?t=1', 'app.php/feed/topic/1'); + } + protected function assert301($from, $to) { self::$client->followRedirects(false); diff --git a/tests/functional/feed_test.php b/tests/functional/feed_test.php index 9041c8dc69..fc3f052e91 100644 --- a/tests/functional/feed_test.php +++ b/tests/functional/feed_test.php @@ -11,6 +11,8 @@ * */ +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + /** * @group functional */ @@ -24,9 +26,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case { parent::__construct($name, $data, $dataName); - $this->backupStaticAttributesBlacklist += array( - 'phpbb_functional_feed_test' => array('init_values'), - ); + $this->backupStaticAttributesBlacklist['phpbb_functional_feed_test'] = array('init_values'); + + $this->purge_cache(); } public function test_setup_config_before_state() @@ -55,66 +57,64 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $form->setValues($values); $crawler = self::submit($form); - $this->assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text()); + self::assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text()); // Special config (Guest can't see attachments) $this->add_lang('acp/permissions'); $crawler = self::request('GET', "adm/index.php?i=acp_permissions&sid={$this->sid}&icat=16&mode=setting_group_global&group_id[0]=1"); - $this->assertContains($this->lang('ACL_SET'), $crawler->filter('h1')->eq(1)->text()); + self::assertContains($this->lang('ACL_SET'), $crawler->filter('h1')->eq(1)->text()); $form = $crawler->selectButton($this->lang('APPLY_PERMISSIONS'))->form(); $form['setting[1][0][u_download]']->select(-1); $crawler = self::submit($form); - $this->assertContainsLang('AUTH_UPDATED', $crawler->filter('.successbox')->text()); + self::assertContainsLang('AUTH_UPDATED', $crawler->filter('.successbox')->text()); } public function test_dump_board_state() { - $crawler = self::request('GET', 'feed.php?mode=forums', array(), false); + $crawler = self::request('GET', 'app.php/feed/forums', array(), false); self::assert_response_xml(); self::$init_values['disapprove_user']['forums_value'] = $crawler->filterXPath('//entry')->count(); - $crawler = self::request('GET', 'feed.php?mode=overall', array(), false); + $crawler = self::request('GET', 'app.php/feed/overall', array(), false); self::assert_response_xml(); self::$init_values['disapprove_user']['overall_value'] = $crawler->filterXPath('//entry')->count(); - $crawler = self::request('GET', 'feed.php?mode=topics', array(), false); + $crawler = self::request('GET', 'app.php/feed/topics', array(), false); self::assert_response_xml(); self::$init_values['disapprove_user']['topics_value'] = $crawler->filterXPath('//entry')->count(); - $crawler = self::request('GET', 'feed.php?mode=topics_new', array(), false); + $crawler = self::request('GET', 'app.php/feed/topics_new', array(), false); self::assert_response_xml(); self::$init_values['disapprove_user']['topics_new_value'] = $crawler->filterXPath('//entry')->count(); - $crawler = self::request('GET', 'feed.php?mode=topics_active', array(), false); + $crawler = self::request('GET', 'app.php/feed/topics_active', array(), false); self::assert_response_xml(); self::$init_values['disapprove_user']['topics_active_value'] = $crawler->filterXPath('//entry')->count(); $this->login(); - $crawler = self::request('GET', 'feed.php?mode=forums', array(), false); + $crawler = self::request('GET', 'app.php/feed/forums', array(), false); self::assert_response_xml(); self::$init_values['admin']['forums_value'] = $crawler->filterXPath('//entry')->count(); - $crawler = self::request('GET', 'feed.php?mode=overall', array(), false); + $crawler = self::request('GET', 'app.php/feed/overall', array(), false); self::assert_response_xml(); self::$init_values['admin']['overall_value'] = $crawler->filterXPath('//entry')->count(); - $crawler = self::request('GET', 'feed.php?mode=topics', array(), false); + $crawler = self::request('GET', 'app.php/feed/topics', array(), false); self::assert_response_xml(); self::$init_values['admin']['topics_value'] = $crawler->filterXPath('//entry')->count(); - $crawler = self::request('GET', 'feed.php?mode=topics_new', array(), false); + $crawler = self::request('GET', 'app.php/feed/topics_new', array(), false); self::assert_response_xml(); self::$init_values['admin']['topics_new_value'] = $crawler->filterXPath('//entry')->count(); - $crawler = self::request('GET', 'feed.php?mode=topics_active', array(), false); + $crawler = self::request('GET', 'app.php/feed/topics_active', array(), false); self::assert_response_xml(); self::$init_values['admin']['topics_active_value'] = $crawler->filterXPath('//entry')->count(); - - } public function test_setup_forums() @@ -132,7 +132,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $form = $crawler->selectButton('update')->form(array( 'forum_perm_from' => 2, )); - $crawler = self::submit($form); + self::submit($form); $this->load_ids(array( 'forums' => array( @@ -149,7 +149,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $form = $crawler->selectButton('update')->form(array( 'forum_perm_from' => 2, )); - $crawler = self::submit($form); + self::submit($form); // 'Feeds #news' will be used for feed.php?mode=news $crawler = self::request('GET', "adm/index.php?i=acp_forums&mode=manage&sid={$this->sid}"); @@ -160,9 +160,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $form = $crawler->selectButton('update')->form(array( 'forum_perm_from' => 2, )); - $crawler = self::submit($form); + self::submit($form); - // 'Feeds #exclude' will not be displayed on feed.php?mode=forums + // 'Feeds #exclude' will not be displayed on app.php/feed/forums $crawler = self::request('GET', "adm/index.php?i=acp_forums&mode=manage&sid={$this->sid}"); $form = $crawler->selectButton('addforum')->form(array( 'forum_name' => 'Feeds #exclude', @@ -171,7 +171,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $form = $crawler->selectButton('update')->form(array( 'forum_perm_from' => 2, )); - $crawler = self::submit($form); + self::submit($form); } public function test_setup_config_after_forums() @@ -195,7 +195,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $form['feed_exclude_id']->select(array($this->data['forums']['Feeds #exclude'])); $crawler = self::submit($form); - $this->assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text()); + self::assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text()); } public function test_feeds_empty() @@ -266,6 +266,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case 'id' => $this->data['forums']['Feeds #exclude'], 'contents_lang' => array('NO_FEED'), 'invalid' => true, + 'response_code' => 404, ), ), 't' => array( @@ -273,6 +274,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case 'id' => $this->data['topics']['Feeds #exclude - Topic #1'], 'contents_lang' => array('NO_FEED'), 'invalid' => true, + 'response_code' => 404, ), ), 'overall' => array( @@ -325,7 +327,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $post = $this->create_topic($this->data['forums']['Feeds #news'], 'Feeds #news - Topic #2', 'This is a test topic posted by the testing framework.'); $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); - $this->assertContains('Feeds #news - Topic #2', $crawler->filter('html')->text()); + self::assertContains('Feeds #news - Topic #2', $crawler->filter('html')->text()); $this->data['topics']['Feeds #news - Topic #2'] = (int) $post['topic_id']; $this->data['posts']['Feeds #news - Topic #2'] = (int) $this->get_parameter_from_link($crawler->filter('.post')->selectLink($this->lang('POST', '', ''))->link()->getUri(), 'p'); @@ -333,7 +335,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $post2 = $this->create_post($this->data['forums']['Feeds #news'], $post['topic_id'], 'Re: Feeds #news - Topic #2', 'This is a test post posted by the testing framework.'); $crawler = self::request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}"); - $this->assertContains('Re: Feeds #news - Topic #2', $crawler->filter('html')->text()); + self::assertContains('Re: Feeds #news - Topic #2', $crawler->filter('html')->text()); $this->data['posts']['Re: Feeds #news - Topic #2'] = (int) $post2['post_id']; } @@ -489,7 +491,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $post2 = $this->create_post($this->data['forums']['Feeds #1'], $post['topic_id'], 'Re: Feeds #1 - Topic #2', 'This is a test post posted by the testing framework.'); $crawler = self::request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}"); - $this->assertContains('Re: Feeds #1 - Topic #2', $crawler->filter('html')->text()); + self::assertContains('Re: Feeds #1 - Topic #2', $crawler->filter('html')->text()); $this->data['posts']['Re: Feeds #1 - Topic #2'] = (int) $post2['post_id']; } @@ -510,14 +512,14 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $this->add_lang('posting'); $crawler = self::request('GET', "posting.php?mode=delete&f={$this->data['forums']['Feeds #1']}&p={$this->data['posts']['Re: Feeds #1 - Topic #2']}&sid={$this->sid}"); - $this->assertContainsLang('DELETE_PERMANENTLY', $crawler->text()); + self::assertContainsLang('DELETE_PERMANENTLY', $crawler->text()); $form = $crawler->selectButton('Yes')->form(); $crawler = self::submit($form); - $this->assertContainsLang('POST_DELETED', $crawler->text()); + self::assertContainsLang('POST_DELETED', $crawler->text()); $crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Feeds #1 - Topic #2']}&sid={$this->sid}"); - $this->assertContains($this->lang('POST_DISPLAY', '', ''), $crawler->text()); + self::assertContains($this->lang('POST_DISPLAY', '', ''), $crawler->text()); } public function test_feeds_softdeleted_post_admin() @@ -609,15 +611,15 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $this->add_lang('posting'); $crawler = $this->get_quickmod_page($this->data['topics']['Feeds #1 - Topic #2'], 'DELETE_TOPIC'); - $this->assertContainsLang('DELETE_PERMANENTLY', $crawler->text()); + self::assertContainsLang('DELETE_PERMANENTLY', $crawler->text()); $this->add_lang('mcp'); $form = $crawler->selectButton('Yes')->form(); $crawler = self::submit($form); - $this->assertContainsLang('TOPIC_DELETED_SUCCESS', $crawler->text()); + self::assertContainsLang('TOPIC_DELETED_SUCCESS', $crawler->text()); $crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Feeds #1 - Topic #2']}&sid={$this->sid}"); - $this->assertContains('Feeds #1 - Topic #2', $crawler->filter('h2')->text()); + self::assertContains('Feeds #1 - Topic #2', $crawler->filter('h2')->text()); } public function test_feeds_softdeleted_topic_admin() @@ -710,8 +712,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case 't' => array( array( 'id' => $this->data['topics']['Feeds #1 - Topic #2'], - 'contents_lang' => array('SORRY_AUTH_READ'), + 'contents_lang' => array('SORRY_AUTH_READ_TOPIC'), 'invalid' => true, + 'response_code' => 403, ), ), 'overall' => array( @@ -752,10 +755,10 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case // Test creating a reply $this->login('disapprove_user'); - $post2 = $this->create_post($this->data['forums']['Feeds #1.1'], $post['topic_id'], 'Re: Feeds #1.1 - Topic #2', 'This is a test post posted by the testing framework.', array(), 'POST_STORED_MOD'); + $this->create_post($this->data['forums']['Feeds #1.1'], $post['topic_id'], 'Re: Feeds #1.1 - Topic #2', 'This is a test post posted by the testing framework.', array(), 'POST_STORED_MOD'); $crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Feeds #1.1 - Topic #2']}&sid={$this->sid}"); - $this->assertNotContains('Re: Feeds #1.1 - Topic #2', $crawler->filter('html')->text()); + self::assertNotContains('Re: Feeds #1.1 - Topic #2', $crawler->filter('html')->text()); } public function test_feeds_unapproved_post_admin() @@ -847,7 +850,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $this->data['topics']['Feeds #1 - Topic #3'] = (int) $post['topic_id']; $crawler = self::request('GET', "viewforum.php?f={$this->data['forums']['Feeds #1.1']}&sid={$this->sid}"); - $this->assertNotContains('Feeds #1.1 - Topic #3', $crawler->filter('html')->text()); + self::assertNotContains('Feeds #1.1 - Topic #3', $crawler->filter('html')->text()); $this->logout(); $this->set_flood_interval(15); @@ -863,10 +866,10 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $form = $crawler->selectButton('Submit')->form(); $values = $form->getValues(); - $values["config[flood_interval]"] = $flood_interval; + $values['config[flood_interval]'] = $flood_interval; $form->setValues($values); $crawler = self::submit($form); - $this->assertGreaterThan(0, $crawler->filter('.successbox')->count()); + self::assertGreaterThan(0, $crawler->filter('.successbox')->count()); $this->logout(); } @@ -958,8 +961,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case 't' => array( array( 'id' => $this->data['topics']['Feeds #1.1 - Topic #3'], - 'contents_lang' => array('SORRY_AUTH_READ'), + 'contents_lang' => array('SORRY_AUTH_READ_TOPIC'), 'invalid' => true, + 'response_code' => 403, ), ), 'overall' => array( @@ -998,7 +1002,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $post = $this->create_topic($this->data['forums']['Feeds #1'], 'Feeds #1 - Topic #3', 'This is a test topic posted by the testing framework. [attachment=0]Attachment #0[/attachment]', array('upload_files' => 1)); $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); - $this->assertContains('Feeds #1 - Topic #3', $crawler->filter('html')->text()); + self::assertContains('Feeds #1 - Topic #3', $crawler->filter('html')->text()); $this->data['topics']['Feeds #1 - Topic #3'] = (int) $post['topic_id']; } @@ -1216,7 +1220,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $post2 = $this->create_post($this->data['forums']['Feeds #1'], $this->data['topics']['Feeds #1 - Topic #3'], 'Re: Feeds #1 - Topic #3-1', 'This is a test post posted by the testing framework. [attachment=0]Attachment #0[/attachment]'); $crawler = self::request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}"); - $this->assertContains('Re: Feeds #1 - Topic #3-1', $crawler->filter('html')->text()); + self::assertContains('Re: Feeds #1 - Topic #3-1', $crawler->filter('html')->text()); $this->data['posts']['Re: Feeds #1 - Topic #3-1'] = (int) $post2['post_id']; } @@ -1316,9 +1320,14 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case { foreach ($feeds as $feed_data) { - if ($mode === 'f' || $mode === 't') + if ($mode === 'f') { - $params = "?{$mode}={$feed_data['id']}"; + $params = "/forum/{$feed_data['id']}"; + $this->assert_feed($params, $feed_data); + } + else if ($mode === 't') + { + $params = "/topic/{$feed_data['id']}"; $this->assert_feed($params, $feed_data); } else @@ -1342,10 +1351,10 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case case 'news': break; default: - $this->fail('Unsupported feed mode: ' . $mode); + self::fail('Unsupported feed mode: ' . $mode); } - $params = "?mode={$mode}"; + $params = "/{$mode}"; $this->assert_feed($params, $feed_data); } } @@ -1354,19 +1363,19 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case protected function assert_feed($params, $data) { - $crawler = self::request('GET', 'feed.php' . $params, array(), false); + $crawler = self::request('GET', 'app.php/feed' . $params, array(), false); if (empty($data['invalid'])) { self::assert_response_xml(); - $this->assertEquals($data['nb_entries'], $crawler->filter('entry')->count(), "Tested feed : 'feed.php{$params}'"); + self::assertEquals($data['nb_entries'], $crawler->filter('entry')->count(), "Tested feed : 'app.php/feed{$params}'"); if (!empty($data['xpath'])) { foreach($data['xpath'] as $xpath => $count_expected) { - $this->assertCount($count_expected, $crawler->filterXPath($xpath), "Tested feed : 'feed.php{$params}', Search for {$xpath}"); + self::assertCount($count_expected, $crawler->filterXPath($xpath), "Tested feed : 'app.php/feed{$params}', Search for {$xpath}"); } } @@ -1375,7 +1384,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case foreach($data['contents'] as $entry_id => $string) { $content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text(); - $this->assertContains($string, $content, "Tested feed : 'feed.php{$params}'"); + self::assertContains($string, $content, "Tested feed : 'app.php/feed{$params}'"); } } @@ -1384,7 +1393,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case foreach($data['contents_lang'] as $entry_id => $string) { $content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text(); - $this->assertContainsLang($string, $content, "Tested feed : 'feed.php{$params}'"); + self::assertContainsLang($string, $content, "Tested feed : 'app.php/feed{$params}'"); } } @@ -1392,21 +1401,21 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case { foreach($data['attachments'] as $entry_id => $attachments) { + $content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text(); foreach ($attachments as $i => $attachment) { - $content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text(); $url = "./download/file.php?id={$attachment['id']}"; $string = "Attachment #{$i}"; if ($attachment['displayed']) { - $this->assertContains($url, $content, "Tested feed : 'feed.php{$params}'"); - $this->assertNotContains($string, $content, "Tested feed : 'feed.php{$params}'"); + self::assertContains($url, $content, "Tested feed : 'app.php/feed{$params}'"); + self::assertNotContains($string, $content, "Tested feed : 'app.php/feed{$params}'"); } else { - $this->assertContains($string, $content, "Tested feed : 'feed.php{$params}'"); - $this->assertNotContains($url, $content, "Tested feed : 'feed.php{$params}'"); + self::assertContains($string, $content, "Tested feed : 'app.php/feed{$params}'"); + self::assertNotContains($url, $content, "Tested feed : 'app.php/feed{$params}'"); } } } @@ -1414,14 +1423,14 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case } else { - self::assert_response_html(); + self::assert_response_html($data['response_code'] ?: 202); if (!empty($data['contents_lang'])) { + $content = $crawler->filter('html')->text(); foreach($data['contents_lang'] as $string) { - $content = $crawler->filter('html')->text(); - $this->assertContainsLang($string, $content, "Tested feed : 'feed.php{$params}'"); + self::assertContainsLang($string, $content, "Tested feed : 'app.php/feed{$params}'"); } } } @@ -1439,7 +1448,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - if (in_array($row['forum_name'], $data['forums'])) + if (in_array($row['forum_name'], $data['forums'], false)) { $this->data['forums'][$row['forum_name']] = (int) $row['forum_id']; } @@ -1455,7 +1464,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - if (in_array($row['topic_title'], $data['topics'])) + if (in_array($row['topic_title'], $data['topics'], false)) { $this->data['topics'][$row['topic_title']] = (int) $row['topic_id']; } @@ -1472,7 +1481,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - if (in_array($row['post_subject'], $data['posts'])) + if (in_array($row['post_subject'], $data['posts'], false)) { $this->data['posts'][$row['post_subject']] = (int) $row['post_id']; $post_ids[] = (int) $row['post_id']; diff --git a/tests/mock/controller_helper.php b/tests/mock/controller_helper.php index 1d9f5dc5bf..0116dced49 100644 --- a/tests/mock/controller_helper.php +++ b/tests/mock/controller_helper.php @@ -13,19 +13,6 @@ class phpbb_mock_controller_helper extends \phpbb\controller\helper { - public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext, $phpbb_root_path_ext) - { - $this->template = $template; - $this->user = $user; - $this->config = $config; - $this->symfony_request = $symfony_request; - $this->request = $request; - $this->filesystem = $filesystem; - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $php_ext; - $this->router = $router; - } - public function get_current_url() { return ''; diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index 07f9ec9c56..0607098d93 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -54,7 +54,8 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case $request ); - $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $router, $symfony_request, $request, $filesystem, '', 'php', dirname(__FILE__) . '/'); + $this->routing_helper = new \phpbb\routing\helper($this->config, $router, $symfony_request, $request, $filesystem, '', 'php'); + $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $symfony_request, $request, $this->routing_helper); $this->pagination = new \phpbb\pagination($this->template, $this->user, $this->helper, $phpbb_dispatcher); } From 5df9a4547337ef90300c21d0f997bc67e43cba9e Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 6 Aug 2015 14:20:06 +0200 Subject: [PATCH 0577/1676] [ticket/13645] Proper OOP for feeds PHPBB3-13645 --- phpBB/language/en/common.php | 1 + phpBB/phpbb/feed/attachments_base.php | 2 +- phpBB/phpbb/feed/base.php | 217 +++++++++++++++----------- phpBB/phpbb/feed/controller/feed.php | 10 +- phpBB/phpbb/feed/feed_interface.php | 67 ++++++++ phpBB/phpbb/feed/forum.php | 68 ++++---- phpBB/phpbb/feed/forums.php | 49 +++--- phpBB/phpbb/feed/helper.php | 78 ++++----- phpBB/phpbb/feed/news.php | 43 ++--- phpBB/phpbb/feed/overall.php | 46 +++--- phpBB/phpbb/feed/post_base.php | 39 +++-- phpBB/phpbb/feed/topic.php | 68 ++++---- phpBB/phpbb/feed/topic_base.php | 38 +++-- phpBB/phpbb/feed/topics.php | 42 ++--- phpBB/phpbb/feed/topics_active.php | 58 ++++--- 15 files changed, 506 insertions(+), 320 deletions(-) create mode 100644 phpBB/phpbb/feed/feed_interface.php diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 76fa1c15f7..aadf6bd921 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -229,6 +229,7 @@ $lang = array_merge($lang, array( 'FACEBOOK' => 'Facebook', 'FAQ' => 'FAQ', 'FAQ_EXPLAIN' => 'Frequently Asked Questions', + 'FEATURE_NOT_AVAILABLE' => 'The requested feature is not available on this board.', 'FILENAME' => 'Filename', 'FILESIZE' => 'File size', 'FILEDATE' => 'File date', diff --git a/phpBB/phpbb/feed/attachments_base.php b/phpBB/phpbb/feed/attachments_base.php index 04812f1570..b14dafe15a 100644 --- a/phpBB/phpbb/feed/attachments_base.php +++ b/phpBB/phpbb/feed/attachments_base.php @@ -16,7 +16,7 @@ namespace phpbb\feed; /** * Abstract class for feeds displaying attachments */ -abstract class attachments_base extends \phpbb\feed\base +abstract class attachments_base extends base { /** * Attachments that may be displayed diff --git a/phpBB/phpbb/feed/base.php b/phpBB/phpbb/feed/base.php index 322e2ee9f1..188d229515 100644 --- a/phpBB/phpbb/feed/base.php +++ b/phpBB/phpbb/feed/base.php @@ -1,27 +1,27 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; /** -* Base class with some generic functions and settings. -*/ -abstract class base + * Base class with some generic functions and settings. + */ +abstract class base implements feed_interface { /** - * Feed helper object - * @var \phpbb\feed\helper - */ + * Feed helper object + * @var \phpbb\feed\helper + */ protected $helper; /** @var \phpbb\config\config */ @@ -43,46 +43,46 @@ abstract class base protected $phpEx; /** - * SQL Query to be executed to get feed items - */ - var $sql = array(); + * SQL Query to be executed to get feed items + */ + protected $sql = array(); /** - * Keys specified for retrieval of title, content, etc. - */ - var $keys = array(); + * Keys specified for retrieval of title, content, etc. + */ + protected $keys = array(); /** - * Number of items to fetch. Usually overwritten by $config['feed_something'] - */ - var $num_items = 15; + * Number of items to fetch. Usually overwritten by $config['feed_something'] + */ + protected $num_items = 15; /** - * Separator for title elements to separate items (for example forum / topic) - */ - var $separator = "\xE2\x80\xA2"; // • + * Separator for title elements to separate items (for example forum / topic) + */ + protected $separator = "\xE2\x80\xA2"; // • /** - * Separator for the statistics row (Posted by, post date, replies, etc.) - */ - var $separator_stats = "\xE2\x80\x94"; // — + * Separator for the statistics row (Posted by, post date, replies, etc.) + */ + protected $separator_stats = "\xE2\x80\x94"; // — /** @var mixed Query result handle */ protected $result; /** - * Constructor - * - * @param \phpbb\feed\helper $helper Feed helper - * @param \phpbb\config\config $config Config object - * @param \phpbb\db\driver\driver_interface $db Database connection - * @param \phpbb\cache\driver\driver_interface $cache Cache object - * @param \phpbb\user $user User object - * @param \phpbb\auth\auth $auth Auth object - * @param \phpbb\content_visibility $content_visibility Auth object - * @param string $phpEx php file extension - */ - function __construct(\phpbb\feed\helper $helper, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, \phpbb\user $user, \phpbb\auth\auth $auth, \phpbb\content_visibility $content_visibility, $phpEx) + * Constructor + * + * @param \phpbb\feed\helper $helper Feed helper + * @param \phpbb\config\config $config Config object + * @param \phpbb\db\driver\driver_interface $db Database connection + * @param \phpbb\cache\driver\driver_interface $cache Cache object + * @param \phpbb\user $user User object + * @param \phpbb\auth\auth $auth Auth object + * @param \phpbb\content_visibility $content_visibility Auth object + * @param string $phpEx php file extension + */ + public function __construct(\phpbb\feed\helper $helper, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, \phpbb\user $user, \phpbb\auth\auth $auth, \phpbb\content_visibility $content_visibility, $phpEx) { $this->config = $config; $this->helper = $helper; @@ -109,23 +109,23 @@ abstract class base } /** - * Set keys. - */ - function set_keys() + * {@inheritdoc} + */ + public function set_keys() { } /** - * Open feed - */ - function open() + * {@inheritdoc} + */ + public function open() { } /** - * Close feed - */ - function close() + * {@inheritdoc} + */ + public function close() { if (!empty($this->result)) { @@ -134,28 +134,47 @@ abstract class base } /** - * Set key - * - * @param string $key Key - * @param mixed $value Value - */ - function set($key, $value) + * {@inheritdoc} + */ + public function set($key, $value) { $this->keys[$key] = $value; } /** - * Get key - * - * @param string $key Key - * @return mixed - */ - function get($key) + * {@inheritdoc} + */ + public function get($key) { return (isset($this->keys[$key])) ? $this->keys[$key] : null; } - function get_readable_forums() + /** + * {@inheritdoc} + */ + public function get_item() + { + if (!isset($this->result)) + { + if (!$this->get_sql()) + { + return false; + } + + // Query database + $sql = $this->db->sql_build_query('SELECT', $this->sql); + $this->result = $this->db->sql_query_limit($sql, $this->num_items); + } + + return $this->db->sql_fetchrow($this->result); + } + + /** + * Returns the ids of the forums readable by the current user. + * + * @return int[] + */ + protected function get_readable_forums() { static $forum_ids; @@ -167,7 +186,12 @@ abstract class base return $forum_ids; } - function get_moderator_approve_forums() + /** + * Returns the ids of the forum for which the current user can approve the post in the moderation queue. + * + * @return int[] + */ + protected function get_moderator_approve_forums() { static $forum_ids; @@ -179,7 +203,13 @@ abstract class base return $forum_ids; } - function is_moderator_approve_forum($forum_id) + /** + * Returns true if the current user can approve the post of the given forum + * + * @param int $forum_id Forum id to check + * @return bool + */ + protected function is_moderator_approve_forum($forum_id) { static $forum_ids; @@ -191,7 +221,12 @@ abstract class base return (isset($forum_ids[$forum_id])) ? true : false; } - function get_excluded_forums() + /** + * Returns the ids of the forum excluded from the feeds + * + * @return int[] + */ + protected function get_excluded_forums() { static $forum_ids; @@ -218,36 +253,35 @@ abstract class base return $forum_ids; } - function is_excluded_forum($forum_id) + /** + * Returns true if the given id is in the excluded forums list. + * + * @param int $forum_id Id to check + * @return bool + */ + protected function is_excluded_forum($forum_id) { $forum_ids = $this->get_excluded_forums(); return isset($forum_ids[$forum_id]) ? true : false; } - function get_passworded_forums() + /** + * Returns all password protected forum ids the current user is currently NOT authenticated for. + * + * @return array Array of forum ids + */ + protected function get_passworded_forums() { return $this->user->get_passworded_forums(); } - function get_item() - { - if (!isset($this->result)) - { - if (!$this->get_sql()) - { - return false; - } - - // Query database - $sql = $this->db->sql_build_query('SELECT', $this->sql); - $this->result = $this->db->sql_query_limit($sql, $this->num_items); - } - - return $this->db->sql_fetchrow($this->result); - } - - function user_viewprofile($row) + /** + * Returns the link to the user profile. + * + * @return string + */ + protected function user_viewprofile($row) { $author_id = (int) $row[$this->get('author_id')]; @@ -260,4 +294,11 @@ abstract class base return '' . $row[$this->get('creator')] . ''; } + + /** + * Returns the SQL query used to retrieve the posts of the feed. + * + * @return string SQL SELECT query + */ + protected abstract function get_sql(); } diff --git a/phpBB/phpbb/feed/controller/feed.php b/phpBB/phpbb/feed/controller/feed.php index a2dd9393f6..1cc960b1cb 100644 --- a/phpBB/phpbb/feed/controller/feed.php +++ b/phpBB/phpbb/feed/controller/feed.php @@ -17,7 +17,7 @@ use phpbb\auth\auth; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\exception\http_exception; -use phpbb\feed\base; +use phpbb\feed\feed_interface; use phpbb\feed\exception\feed_unavailable_exception; use phpbb\feed\exception\unauthorized_exception; use phpbb\feed\helper as feed_helper; @@ -252,11 +252,11 @@ class feed /** * Display a given feed * - * @param base $feed + * @param feed_interface $feed * * @return Response */ - protected function send_feed(base $feed) + protected function send_feed(feed_interface $feed) { try { @@ -275,13 +275,13 @@ class feed /** * Really send the feed * - * @param base $feed + * @param feed_interface $feed * * @return Response * * @throw exception\feed_exception */ - protected function send_feed_do(base $feed) + protected function send_feed_do(feed_interface $feed) { $feed_updated_time = 0; $item_vars = array(); diff --git a/phpBB/phpbb/feed/feed_interface.php b/phpBB/phpbb/feed/feed_interface.php new file mode 100644 index 0000000000..c185cd249c --- /dev/null +++ b/phpBB/phpbb/feed/feed_interface.php @@ -0,0 +1,67 @@ + + * @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\feed; + +/** + * Interface implemented by all feeds types + */ +interface feed_interface +{ + /** + * Set keys. + */ + public function set_keys(); + + /** + * Open feed + */ + public function open(); + + /** + * Close feed + */ + public function close(); + + /** + * Set key + * + * @param string $key Key + * @param mixed $value Value + */ + public function set($key, $value); + + /** + * Get key + * + * @param string $key Key + * @return mixed + */ + public function get($key); + + /** + * Get the next post in the feed + * + * @return array + */ + public function get_item(); + + /** + * Adjust a feed entry + * + * @param $item_row + * @param $row + * @return array + */ + public function adjust_item(&$item_row, &$row); +} diff --git a/phpBB/phpbb/feed/forum.php b/phpBB/phpbb/feed/forum.php index f493c4729a..6701c4d9e7 100644 --- a/phpBB/phpbb/feed/forum.php +++ b/phpBB/phpbb/feed/forum.php @@ -1,15 +1,15 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; @@ -18,22 +18,22 @@ use phpbb\feed\exception\no_forum_exception; use phpbb\feed\exception\unauthorized_forum_exception; /** -* Forum feed -* -* This will give you the last {$this->num_items} posts made -* within a specific forum. -*/ -class forum extends \phpbb\feed\post_base + * Forum feed + * + * This will give you the last {$this->num_items} posts made + * within a specific forum. + */ +class forum extends post_base { - var $forum_id = 0; - var $forum_data = array(); + protected $forum_id = 0; + protected $forum_data = array(); /** - * Set the Forum ID - * - * @param int $forum_id Forum ID - * @return \phpbb\feed\forum - */ + * Set the Forum ID + * + * @param int $forum_id Forum ID + * @return \phpbb\feed\forum + */ public function set_forum_id($forum_id) { $this->forum_id = (int) $forum_id; @@ -41,7 +41,10 @@ class forum extends \phpbb\feed\post_base return $this; } - function open() + /** + * {@inheritdoc} + */ + public function open() { // Check if forum exists $sql = 'SELECT forum_id, forum_name, forum_password, forum_type, forum_options @@ -90,7 +93,10 @@ class forum extends \phpbb\feed\post_base parent::open(); } - function get_sql() + /** + * {@inheritdoc} + */ + protected function get_sql() { // Determine topics with recent activity $sql = 'SELECT topic_id, topic_last_post_time @@ -118,7 +124,7 @@ class forum extends \phpbb\feed\post_base $this->sql = array( 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' . - 'u.username, u.user_id', + 'u.username, u.user_id', 'FROM' => array( POSTS_TABLE => 'p', USERS_TABLE => 'u', @@ -133,7 +139,10 @@ class forum extends \phpbb\feed\post_base return true; } - function adjust_item(&$item_row, &$row) + /** + * {@inheritdoc} + */ + public function adjust_item(&$item_row, &$row) { parent::adjust_item($item_row, $row); @@ -141,7 +150,10 @@ class forum extends \phpbb\feed\post_base $item_row['forum_id'] = $this->forum_id; } - function get_item() + /** + * {@inheritdoc} + */ + public function get_item() { return ($row = parent::get_item()) ? array_merge($this->forum_data, $row) : $row; } diff --git a/phpBB/phpbb/feed/forums.php b/phpBB/phpbb/feed/forums.php index ee14a5bc76..92f2b2dd4d 100644 --- a/phpBB/phpbb/feed/forums.php +++ b/phpBB/phpbb/feed/forums.php @@ -1,29 +1,32 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; /** -* 'All Forums' feed -* -* This will give you a list of all postable forums where feeds are enabled -* including forum description, topic stats and post stats -*/ -class forums extends \phpbb\feed\base + * 'All Forums' feed + * + * This will give you a list of all postable forums where feeds are enabled + * including forum description, topic stats and post stats + */ +class forums extends base { - var $num_items = 0; + protected $num_items = 0; - function set_keys() + /** + * {@inheritdoc} + */ + public function set_keys() { $this->set('title', 'forum_name'); $this->set('text', 'forum_desc'); @@ -33,7 +36,10 @@ class forums extends \phpbb\feed\base $this->set('options', 'forum_desc_options'); } - function get_sql() + /** + * {@inheritdoc} + */ + public function get_sql() { $in_fid_ary = array_diff($this->get_readable_forums(), $this->get_excluded_forums()); if (empty($in_fid_ary)) @@ -55,7 +61,10 @@ class forums extends \phpbb\feed\base return true; } - function adjust_item(&$item_row, &$row) + /** + * {@inheritdoc} + */ + public function adjust_item(&$item_row, &$row) { $item_row['link'] = $this->helper->append_sid('viewforum.' . $this->phpEx, 'f=' . $row['forum_id']); diff --git a/phpBB/phpbb/feed/helper.php b/phpBB/phpbb/feed/helper.php index 198134cdcf..75736bc981 100644 --- a/phpBB/phpbb/feed/helper.php +++ b/phpBB/phpbb/feed/helper.php @@ -1,21 +1,21 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; /** -* Class with some helpful functions used in feeds -*/ + * Class with some helpful functions used in feeds + */ class helper { /** @var \phpbb\config\config */ @@ -31,13 +31,13 @@ class helper protected $phpEx; /** - * Constructor - * - * @param \phpbb\config\config $config Config object - * @param \phpbb\user $user User object - * @param string $phpbb_root_path Root path - * @param string $phpEx PHP file extension - */ + * Constructor + * + * @param \phpbb\config\config $config Config object + * @param \phpbb\user $user User object + * @param string $phpbb_root_path Root path + * @param string $phpEx PHP file extension + */ public function __construct(\phpbb\config\config $config, \phpbb\user $user, $phpbb_root_path, $phpEx) { $this->config = $config; @@ -47,8 +47,8 @@ class helper } /** - * Run links through append_sid(), prepend generate_board_url() and remove session id - */ + * Run links through append_sid(), prepend generate_board_url() and remove session id + */ public function get_board_url() { static $board_url; @@ -62,16 +62,16 @@ class helper } /** - * Run links through append_sid(), prepend generate_board_url() and remove session id - */ + * Run links through append_sid(), prepend generate_board_url() and remove session id + */ public function append_sid($url, $params) { return append_sid($this->get_board_url() . '/' . $url, $params, true, ''); } /** - * Generate ISO 8601 date string (RFC 3339) - */ + * Generate ISO 8601 date string (RFC 3339) + */ public function format_date($time) { static $zone_offset; @@ -87,16 +87,16 @@ class helper } /** - * Generate text content - * - * @param string $content is feed text content - * @param string $uid is bbcode_uid - * @param string $bitfield is bbcode bitfield - * @param int $options bbcode flag options - * @param int $forum_id is the forum id - * @param array $post_attachments is an array containing the attachments and their respective info - * @return string the html content to be printed for the feed - */ + * Generate text content + * + * @param string $content is feed text content + * @param string $uid is bbcode_uid + * @param string $bitfield is bbcode bitfield + * @param int $options bbcode flag options + * @param int $forum_id is the forum id + * @param array $post_attachments is an array containing the attachments and their respective info + * @return string the html content to be printed for the feed + */ public function generate_content($content, $uid, $bitfield, $options, $forum_id, $post_attachments) { if (empty($content)) @@ -122,16 +122,16 @@ class helper // Firefox does not support CSS for feeds, though // Remove font sizes - // $content = preg_replace('#([^>]+)#iU', '\1', $content); + // $content = preg_replace('#([^>]+)#iU', '\1', $content); // Make text strong :P - // $content = preg_replace('#(.*?)#iU', '\1', $content); + // $content = preg_replace('#(.*?)#iU', '\1', $content); // Italic - // $content = preg_replace('#([^<]+)#iU', '\1', $content); + // $content = preg_replace('#([^<]+)#iU', '\1', $content); // Underline - // $content = preg_replace('#([^<]+)#iU', '\1', $content); + // $content = preg_replace('#([^<]+)#iU', '\1', $content); // Remove embed Windows Media Streams $content = preg_replace( '#<\!--\[if \!IE\]>-->([^[]+)<\!--#si', '', $content); diff --git a/phpBB/phpbb/feed/news.php b/phpBB/phpbb/feed/news.php index a02c199d85..fb6fa09278 100644 --- a/phpBB/phpbb/feed/news.php +++ b/phpBB/phpbb/feed/news.php @@ -1,27 +1,31 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; /** -* News feed -* -* This will give you {$this->num_items} first posts -* of all topics in the selected news forums. -*/ -class news extends \phpbb\feed\topic_base + * News feed + * + * This will give you {$this->num_items} first posts + * of all topics in the selected news forums. + */ +class news extends topic_base { - function get_news_forums() + /** + * Returns the ids of the 'news forums' + * @return int[] + */ + private function get_news_forums() { static $forum_ids; @@ -48,7 +52,10 @@ class news extends \phpbb\feed\topic_base return $forum_ids; } - function get_sql() + /** + * {@inheritdoc} + */ + protected function get_sql() { // Determine forum ids $in_fid_ary = array_intersect($this->get_news_forums(), $this->get_readable_forums()); diff --git a/phpBB/phpbb/feed/overall.php b/phpBB/phpbb/feed/overall.php index ab452f5386..40cf94ace0 100644 --- a/phpBB/phpbb/feed/overall.php +++ b/phpBB/phpbb/feed/overall.php @@ -1,27 +1,30 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; /** -* Board wide feed (aka overall feed) -* -* This will give you the newest {$this->num_items} posts -* from the whole board. -*/ -class overall extends \phpbb\feed\post_base + * Board wide feed (aka overall feed) + * + * This will give you the newest {$this->num_items} posts + * from the whole board. + */ +class overall extends post_base { - function get_sql() + /** + * {@inheritdoc} + */ + protected function get_sql() { $forum_ids = array_diff($this->get_readable_forums(), $this->get_excluded_forums(), $this->get_passworded_forums()); if (empty($forum_ids)) @@ -55,8 +58,8 @@ class overall extends \phpbb\feed\post_base // Get the actual data $this->sql = array( 'SELECT' => 'f.forum_id, f.forum_name, ' . - 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' . - 'u.username, u.user_id', + 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' . + 'u.username, u.user_id', 'FROM' => array( USERS_TABLE => 'u', POSTS_TABLE => 'p', @@ -77,7 +80,10 @@ class overall extends \phpbb\feed\post_base return true; } - function adjust_item(&$item_row, &$row) + /** + * {@inheritdoc} + */ + public function adjust_item(&$item_row, &$row) { parent::adjust_item($item_row, $row); diff --git a/phpBB/phpbb/feed/post_base.php b/phpBB/phpbb/feed/post_base.php index 011775b6af..f6dc39cbec 100644 --- a/phpBB/phpbb/feed/post_base.php +++ b/phpBB/phpbb/feed/post_base.php @@ -1,27 +1,29 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; /** -* Abstract class for post based feeds -*/ -abstract class post_base extends \phpbb\feed\attachments_base + * Abstract class for post based feeds + */ +abstract class post_base extends attachments_base { - var $num_items = 'feed_limit_post'; - var $attachments = array(); + protected $num_items = 'feed_limit_post'; - function set_keys() + /** + * {@inheritdoc} + */ + public function set_keys() { $this->set('title', 'post_subject'); $this->set('title2', 'topic_title'); @@ -40,7 +42,10 @@ abstract class post_base extends \phpbb\feed\attachments_base $this->set('enable_magic_url', 'enable_magic_url'); } - function adjust_item(&$item_row, &$row) + /** + * {@inheritdoc} + */ + public function adjust_item(&$item_row, &$row) { $item_row['link'] = $this->helper->append_sid('viewtopic.' . $this->phpEx, "t={$row['topic_id']}&p={$row['post_id']}#p{$row['post_id']}"); diff --git a/phpBB/phpbb/feed/topic.php b/phpBB/phpbb/feed/topic.php index c916d3bccc..f029c2b00e 100644 --- a/phpBB/phpbb/feed/topic.php +++ b/phpBB/phpbb/feed/topic.php @@ -1,15 +1,15 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; @@ -19,22 +19,22 @@ use phpbb\feed\exception\unauthorized_forum_exception; use phpbb\feed\exception\unauthorized_topic_exception; /** -* Topic feed for a specific topic -* -* This will give you the last {$this->num_items} posts made within this topic. -*/ -class topic extends \phpbb\feed\post_base + * Topic feed for a specific topic + * + * This will give you the last {$this->num_items} posts made within this topic. + */ +class topic extends post_base { - var $topic_id = 0; - var $forum_id = 0; - var $topic_data = array(); + protected $topic_id = 0; + protected $forum_id = 0; + protected $topic_data = array(); /** - * Set the Topic ID - * - * @param int $topic_id Topic ID - * @return \phpbb\feed\topic - */ + * Set the Topic ID + * + * @param int $topic_id Topic ID + * @return \phpbb\feed\topic + */ public function set_topic_id($topic_id) { $this->topic_id = (int) $topic_id; @@ -42,7 +42,10 @@ class topic extends \phpbb\feed\post_base return $this; } - function open() + /** + * {@inheritdoc} + */ + public function open() { $sql = 'SELECT f.forum_options, f.forum_password, t.topic_id, t.forum_id, t.topic_visibility, t.topic_title, t.topic_time, t.topic_views, t.topic_posts_approved, t.topic_type FROM ' . TOPICS_TABLE . ' t @@ -94,11 +97,14 @@ class topic extends \phpbb\feed\post_base parent::open(); } - function get_sql() + /** + * {@inheritdoc} + */ + protected function get_sql() { $this->sql = array( 'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' . - 'u.username, u.user_id', + 'u.username, u.user_id', 'FROM' => array( POSTS_TABLE => 'p', USERS_TABLE => 'u', @@ -112,14 +118,20 @@ class topic extends \phpbb\feed\post_base return true; } - function adjust_item(&$item_row, &$row) + /** + * {@inheritdoc} + */ + public function adjust_item(&$item_row, &$row) { parent::adjust_item($item_row, $row); $item_row['forum_id'] = $this->forum_id; } - function get_item() + /** + * {@inheritdoc} + */ + public function get_item() { return ($row = parent::get_item()) ? array_merge($this->topic_data, $row) : $row; } diff --git a/phpBB/phpbb/feed/topic_base.php b/phpBB/phpbb/feed/topic_base.php index f9ff368cba..0f1a9ccb70 100644 --- a/phpBB/phpbb/feed/topic_base.php +++ b/phpBB/phpbb/feed/topic_base.php @@ -1,26 +1,29 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; /** -* Abstract class for topic based feeds -*/ -abstract class topic_base extends \phpbb\feed\attachments_base + * Abstract class for topic based feeds + */ +abstract class topic_base extends attachments_base { - var $num_items = 'feed_limit_topic'; + protected $num_items = 'feed_limit_topic'; - function set_keys() + /** + * {@inheritdoc} + */ + public function set_keys() { $this->set('title', 'topic_title'); $this->set('title2', 'forum_name'); @@ -39,7 +42,10 @@ abstract class topic_base extends \phpbb\feed\attachments_base $this->set('enable_magic_url', 'enable_magic_url'); } - function adjust_item(&$item_row, &$row) + /** + * {@inheritdoc} + */ + public function adjust_item(&$item_row, &$row) { $item_row['link'] = $this->helper->append_sid('viewtopic.' . $this->phpEx, 't=' . $row['topic_id'] . '&p=' . $row['post_id'] . '#p' . $row['post_id']); diff --git a/phpBB/phpbb/feed/topics.php b/phpBB/phpbb/feed/topics.php index 2b9cb3501a..cf4a2e579e 100644 --- a/phpBB/phpbb/feed/topics.php +++ b/phpBB/phpbb/feed/topics.php @@ -1,27 +1,30 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; /** -* New Topics feed -* -* This will give you the last {$this->num_items} created topics -* including the first post. -*/ -class topics extends \phpbb\feed\topic_base + * New Topics feed + * + * This will give you the last {$this->num_items} created topics + * including the first post. + */ +class topics extends topic_base { - function get_sql() + /** + * {@inheritdoc} + */ + protected function get_sql() { $forum_ids_read = $this->get_readable_forums(); if (empty($forum_ids_read)) @@ -77,7 +80,10 @@ class topics extends \phpbb\feed\topic_base return true; } - function adjust_item(&$item_row, &$row) + /** + * {@inheritdoc} + */ + public function adjust_item(&$item_row, &$row) { parent::adjust_item($item_row, $row); diff --git a/phpBB/phpbb/feed/topics_active.php b/phpBB/phpbb/feed/topics_active.php index 6d5eddfc16..52340dc2d5 100644 --- a/phpBB/phpbb/feed/topics_active.php +++ b/phpBB/phpbb/feed/topics_active.php @@ -1,30 +1,33 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @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\feed; /** -* Active Topics feed -* -* This will give you the last {$this->num_items} topics -* with replies made withing the last {$this->sort_days} days -* including the last post. -*/ -class topics_active extends \phpbb\feed\topic_base + * Active Topics feed + * + * This will give you the last {$this->num_items} topics + * with replies made withing the last {$this->sort_days} days + * including the last post. + */ +class topics_active extends topic_base { - var $sort_days = 7; + protected $sort_days = 7; - function set_keys() + /** + * {@inheritdoc} + */ + public function set_keys() { parent::set_keys(); @@ -32,7 +35,10 @@ class topics_active extends \phpbb\feed\topic_base $this->set('creator', 'topic_last_poster_name'); } - function get_sql() + /** + * {@inheritdoc} + */ + protected function get_sql() { $forum_ids_read = $this->get_readable_forums(); if (empty($forum_ids_read)) @@ -94,7 +100,12 @@ class topics_active extends \phpbb\feed\topic_base return true; } - function get_forum_ids() + /** + * Returns the ids of the forums not excluded from the active list + * + * @return int[] + */ + private function get_forum_ids() { static $forum_ids; @@ -122,7 +133,10 @@ class topics_active extends \phpbb\feed\topic_base return $forum_ids; } - function adjust_item(&$item_row, &$row) + /** + * {@inheritdoc} + */ + public function adjust_item(&$item_row, &$row) { parent::adjust_item($item_row, $row); From 626dfbdd861e0e28876fa1b3d973aacf987fc83a Mon Sep 17 00:00:00 2001 From: n-aleha Date: Thu, 15 May 2014 07:52:27 +0300 Subject: [PATCH 0578/1676] [ticket/12505] Remove outdated media handing in attachments Remove code for handling media in RealPlayer, QuickTime, and Windows Media Player. PHPBB3-12505 --- phpBB/includes/functions_content.php | 32 ---------------------------- phpBB/language/en/common.php | 1 - 2 files changed, 33 deletions(-) diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index fd39c61b14..345df1d47a 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -1171,38 +1171,6 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, $update_count[] = $attachment['attach_id']; break; - // Windows Media Streams - case ATTACHMENT_CATEGORY_WM: - - // Giving the filename directly because within the wm object all variables are in local context making it impossible - // to validate against a valid session (all params can differ) - // $download_link = $filename; - - $block_array += array( - 'U_FORUM' => generate_board_url(), - 'ATTACH_ID' => $attachment['attach_id'], - 'S_WM_FILE' => true, - ); - - // Viewed/Heared File ... update the download count - $update_count[] = $attachment['attach_id']; - break; - - // Real Media Streams - case ATTACHMENT_CATEGORY_RM: - case ATTACHMENT_CATEGORY_QUICKTIME: - - $block_array += array( - 'S_RM_FILE' => ($display_cat == ATTACHMENT_CATEGORY_RM) ? true : false, - 'S_QUICKTIME_FILE' => ($display_cat == ATTACHMENT_CATEGORY_QUICKTIME) ? true : false, - 'U_FORUM' => generate_board_url(), - 'ATTACH_ID' => $attachment['attach_id'], - ); - - // Viewed/Heared File ... update the download count - $update_count[] = $attachment['attach_id']; - break; - // Macromedia Flash Files case ATTACHMENT_CATEGORY_FLASH: list($width, $height) = @getimagesize($filename); diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index cb99183dd8..5c8a2d175e 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -553,7 +553,6 @@ $lang = array_merge($lang, array( 1 => '%d pixel', 2 => '%d pixels', ), - 'PLAY_QUICKTIME_FILE' => 'Play Quicktime file', 'PLEASE_WAIT' => 'Please wait.', 'PM' => 'PM', 'PM_REPORTED' => 'Click to view report', From 436b020f9e93eb19f52fa8ce65f6b596d4d7f20d Mon Sep 17 00:00:00 2001 From: n-aleha Date: Mon, 24 Aug 2015 00:36:07 +0300 Subject: [PATCH 0579/1676] [ticket/12505] Remove outdated media handling from prosilver PHPBB3-12505 --- .../styles/prosilver/template/attachment.html | 79 +------------------ 1 file changed, 2 insertions(+), 77 deletions(-) diff --git a/phpBB/styles/prosilver/template/attachment.html b/phpBB/styles/prosilver/template/attachment.html index 4546f53d6c..0978d9189e 100644 --- a/phpBB/styles/prosilver/template/attachment.html +++ b/phpBB/styles/prosilver/template/attachment.html @@ -29,36 +29,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -68,53 +39,7 @@ - - - - - - - - - - - - - - - - - -
      - - - - - - - - - - -

      - [ {L_PLAY_QUICKTIME_FILE} ] - {_file.DOWNLOAD_NAME} [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ]

      +

      {_file.DOWNLOAD_NAME} [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ]

      From c60b92bf61eea2b907c7bad5cba596d6b60958af Mon Sep 17 00:00:00 2001 From: n-aleha Date: Thu, 15 May 2014 09:43:47 +0300 Subject: [PATCH 0580/1676] [ticket/12505] Remove outdated media handling from acp Remove outdated media handling from acp PHPBB3-12505 --- phpBB/includes/acp/acp_attachments.php | 6 ------ phpBB/language/en/acp/attachments.php | 6 ------ 2 files changed, 12 deletions(-) diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 7413152e7a..7ff9846a75 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -620,10 +620,7 @@ class acp_attachments $cat_lang = array( ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], - ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], - ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], - ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'], ); $group_id = $request->variable('g', 0); @@ -1371,10 +1368,7 @@ class acp_attachments $types = array( ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], - ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], - ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], - ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'], ); if ($group_id) diff --git a/phpBB/language/en/acp/attachments.php b/phpBB/language/en/acp/attachments.php index cf2f0a45d2..5ff904f9fc 100644 --- a/phpBB/language/en/acp/attachments.php +++ b/phpBB/language/en/acp/attachments.php @@ -70,9 +70,6 @@ $lang = array_merge($lang, array( 'CAT_FLASH_FILES' => 'Flash files', 'CAT_IMAGES' => 'Images', - 'CAT_QUICKTIME_FILES' => 'Quicktime media files', - 'CAT_RM_FILES' => 'RealMedia media files', - 'CAT_WM_FILES' => 'Windows Media media files', 'CHECK_CONTENT' => 'Check attachment files', 'CHECK_CONTENT_EXPLAIN' => 'Some browsers can be tricked to assume an incorrect mimetype for uploaded files. This option ensures that such files likely to cause this are rejected.', 'CREATE_GROUP' => 'Create new group', @@ -105,9 +102,6 @@ $lang = array_merge($lang, array( 'EXT_GROUP_FLASH_FILES' => 'Flash Files', 'EXT_GROUP_IMAGES' => 'Images', 'EXT_GROUP_PLAIN_TEXT' => 'Plain Text', - 'EXT_GROUP_QUICKTIME_MEDIA' => 'Quicktime Media', - 'EXT_GROUP_REAL_MEDIA' => 'Real Media', - 'EXT_GROUP_WINDOWS_MEDIA' => 'Windows Media', 'FILES_GONE' => 'Some of the attachments you selected for deletion do not exist. They may have been already deleted. Attachments that did exist were deleted.', 'FILES_STATS_WRONG' => 'Your file statistics are likely inaccurate and need to be resynchronised. Actual values: number of attachments = %1$d, total size of attachments = %2$s.
      Click %3$shere%4$s to resynchronise them.', From 83f45bdac01ceff58d7dfcc3011f65adad7069c9 Mon Sep 17 00:00:00 2001 From: n-aleha Date: Thu, 15 May 2014 09:52:54 +0300 Subject: [PATCH 0581/1676] [ticket/12505] Remove outdated media extensions Update constants and data schema for new installations. Mark outdated media constants as deprecated. PHPBB3-12505 --- phpBB/includes/constants.php | 6 +++--- phpBB/install/schemas/schema_data.sql | 29 ++++++--------------------- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 126cf44842..16e249d4a5 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -171,11 +171,11 @@ define('CONFIRM_REPORT', 4); // Categories - Attachments define('ATTACHMENT_CATEGORY_NONE', 0); define('ATTACHMENT_CATEGORY_IMAGE', 1); // Inline Images -define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming -define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming +define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming - @deprecated 3.1 +define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming - @deprecated 3.1 define('ATTACHMENT_CATEGORY_THUMB', 4); // Not used within the database, only while displaying posts define('ATTACHMENT_CATEGORY_FLASH', 5); // Flash/SWF files -define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files +define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files - @deprecated 3.1 // BBCode UID length define('BBCODE_UID_LEN', 8); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index f02bca2985..6c993d7d68 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -718,10 +718,7 @@ INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mo INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('ARCHIVES', 0, 1, 1, '', 0, ''); INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('PLAIN_TEXT', 0, 0, 1, '', 0, ''); INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOCUMENTS', 0, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('REAL_MEDIA', 3, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('WINDOWS_MEDIA', 2, 0, 1, '', 0, ''); INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('FLASH_FILES', 5, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('QUICKTIME_MEDIA', 6, 0, 1, '', 0, ''); INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOWNLOADABLE_FILES', 0, 0, 1, '', 0, ''); # -- extensions @@ -778,27 +775,13 @@ INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ods'); INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odt'); INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'rtf'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'rm'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'ram'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'swf'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wma'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wmv'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (7, 'swf'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mov'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4v'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4a'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mp4'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3gp'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3g2'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'qt'); - -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpeg'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpg'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mp3'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogg'); -INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogm'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'mp3'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'mpeg'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'mpg'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'ogg'); +INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'ogm'); # Add default profile fields INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_location', 'profilefields.type.string', 'phpbb_location', '20', '2', '100', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, '', ''); From 5cc6370cea882a10c576c4478748b2758150b76b Mon Sep 17 00:00:00 2001 From: n-aleha Date: Sun, 5 Apr 2015 23:51:04 +0300 Subject: [PATCH 0582/1676] [ticket/12505] Set deprecations for constants to 3.2 PHPBB3-12505 --- phpBB/includes/constants.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 16e249d4a5..bd73201290 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -171,11 +171,11 @@ define('CONFIRM_REPORT', 4); // Categories - Attachments define('ATTACHMENT_CATEGORY_NONE', 0); define('ATTACHMENT_CATEGORY_IMAGE', 1); // Inline Images -define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming - @deprecated 3.1 -define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming - @deprecated 3.1 +define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming - @deprecated 3.2 +define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming - @deprecated 3.2 define('ATTACHMENT_CATEGORY_THUMB', 4); // Not used within the database, only while displaying posts define('ATTACHMENT_CATEGORY_FLASH', 5); // Flash/SWF files -define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files - @deprecated 3.1 +define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files - @deprecated 3.2 // BBCode UID length define('BBCODE_UID_LEN', 8); From 1f16704d347277ca1923bd2e532bc25bafacf51c Mon Sep 17 00:00:00 2001 From: n-aleha Date: Sat, 18 Jul 2015 02:12:12 +0300 Subject: [PATCH 0583/1676] [ticket/12505] Add migration PHPBB3-12505 --- .../data/v320/remove_outdated_media.php | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php diff --git a/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php new file mode 100644 index 0000000000..b2a0a79187 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php @@ -0,0 +1,83 @@ + +* @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\v320; + +class remove_outdated_media extends \phpbb\db\migration\migration +{ + protected $cat_id = array( + ATTACHMENT_CATEGORY_WM, + ATTACHMENT_CATEGORY_RM, + ATTACHMENT_CATEGORY_QUICKTIME, + ); + + public function update_data() + { + return array( + array('custom', array(array($this, 'change_extension_group'))), + ); + } + + public function change_extension_group() + { + // select group ids of outdated media + $sql = 'SELECT group_id + FROM ' . EXTENSION_GROUPS_TABLE . ' + WHERE ' . $this->db->sql_in_set('cat_id', $cat_id); + $result = $this->db->sql_query($sql); + + $group_ids = array(); + while ($group_id = (int) $this->db->sql_fetchfield('group_id')) + { + $group_ids[] = $group_id; + } + $this->db->sql_freeresult($result); + + // nothing to do, admin has removed all the outdated media extension groups + if (empty($group_ids)) + { + return true; + } + + // get the group id of downloadable files + $sql = 'SELECT group_id + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE group_name = 'DOWNLOADABLE_FILES'"; + $result = $this->db->sql_query($sql); + $download_id = (int) $this->db->sql_fetchfield('group_id'); + $this->db->sql_freeresult($result); + + if (empty($download_id)) + { + $sql = 'UPDATE ' . EXTENSIONS_TABLE . ' + SET group_id = 0 + WHERE ' . $this->db->sql_in_set('group_id', $group_ids); + } + else + { + // move outdated media extensions to downloadable files + $sql = 'UPDATE ' . EXTENSIONS_TABLE . " + SET group_id = $download_id" . ' + WHERE ' . $this->db->sql_in_set('group_id', $group_ids); + } + + $result = $this->db->sql_query($sql); + $this->db->sql_freeresult($result); + + // delete the now empty, outdated media extension groups + $sql = 'DELETE FROM ' . EXTENSION_GROUPS_TABLE . ' + WHERE ' . $this->db->sql_in_set('group_id', $group_ids); + $result = $this->db->sql_query($sql); + $this->db->sql_freeresult($result); + } +} From afccb9cb49ce8e96079d3f0b1ea1f9084194a316 Mon Sep 17 00:00:00 2001 From: n-aleha Date: Tue, 21 Jul 2015 00:42:34 +0300 Subject: [PATCH 0584/1676] [ticket/12505] Fix variable usage in migration file PHPBB3-12505 --- phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php index b2a0a79187..59208be4dc 100644 --- a/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php +++ b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php @@ -33,7 +33,7 @@ class remove_outdated_media extends \phpbb\db\migration\migration // select group ids of outdated media $sql = 'SELECT group_id FROM ' . EXTENSION_GROUPS_TABLE . ' - WHERE ' . $this->db->sql_in_set('cat_id', $cat_id); + WHERE ' . $this->db->sql_in_set('cat_id', $this->cat_id); $result = $this->db->sql_query($sql); $group_ids = array(); From c9ec16f6149f104c016980375c8fd04a31e57616 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 10 Aug 2015 09:38:26 +0200 Subject: [PATCH 0585/1676] [ticket/13645] Fix docblocks PHPBB3-13645 --- phpBB/phpbb/feed/controller/feed.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/feed/controller/feed.php b/phpBB/phpbb/feed/controller/feed.php index 1cc960b1cb..31476b7317 100644 --- a/phpBB/phpbb/feed/controller/feed.php +++ b/phpBB/phpbb/feed/controller/feed.php @@ -83,7 +83,8 @@ class feed /** * Constructor * - * @param symfony_request $request; + * @param \Twig_Environment $twig + * @param symfony_request $request * @param controller_helper $controller_helper * @param config $config * @param driver_interface $db @@ -91,6 +92,7 @@ class feed * @param feed_helper $feed_helper * @param user $user * @param auth $auth + * @param string $php_ext */ public function __construct(\Twig_Environment $twig, symfony_request $request, controller_helper $controller_helper, config $config, driver_interface $db, ContainerInterface $container, feed_helper $feed_helper, user $user, auth $auth, $php_ext) { From c868582e4412d482853e7975b1cff1965f51ce25 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 24 Aug 2015 17:45:24 +0200 Subject: [PATCH 0586/1676] [ticket/14125] Add --env option to all CLI commands PHPBB3-14125 --- phpBB/bin/phpbbcli.php | 10 ++++- phpBB/language/en/cli.php | 3 ++ phpBB/phpbb/console/application.php | 57 +++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index 18657aed0a..e5992f7536 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -46,13 +46,17 @@ require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file); -$phpbb_container_builder->without_cache(); - $input = new ArgvInput(); +if ($input->hasParameterOption(array('--env'))) +{ + $phpbb_container_builder->with_environment($input->getParameterOption('--env')); +} + if ($input->hasParameterOption(array('--safe-mode'))) { $phpbb_container_builder->without_extensions(); + $phpbb_container_builder->without_cache(); } else { @@ -68,6 +72,8 @@ require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx); $user = $phpbb_container->get('user'); $user->add_lang('acp/common'); $user->add_lang('cli'); + +/* @var $lang \phpbb\language\language */ $lang = $phpbb_container->get('language'); $application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $lang); diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index f3d6417945..e529fc0bde 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -58,8 +58,11 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_GET_CONFIG' => 'Gets a configuration option’s value', 'CLI_DESCRIPTION_INCREMENT_CONFIG' => 'Increments a configuration option’s value', 'CLI_DESCRIPTION_LIST_EXTENSIONS' => 'Lists all extensions in the database and on the filesystem.', + + 'CLI_DESCRIPTION_OPTION_ENV' => 'The Environment name.', 'CLI_DESCRIPTION_OPTION_SAFE_MODE' => 'Run in Safe Mode (without extensions).', 'CLI_DESCRIPTION_OPTION_SHELL' => 'Launch the shell.', + 'CLI_DESCRIPTION_PURGE_EXTENSION' => 'Purges the specified extension.', 'CLI_DESCRIPTION_REPARSER_LIST' => 'Lists the types of text that can be reparsed.', 'CLI_DESCRIPTION_REPARSER_REPARSE' => 'Reparses stored text with the current text_formatter services.', diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php index 2c69a3cc73..dc9b8016b2 100644 --- a/phpBB/phpbb/console/application.php +++ b/phpBB/phpbb/console/application.php @@ -13,6 +13,7 @@ namespace phpbb\console; +use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Shell; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -49,12 +50,7 @@ class application extends \Symfony\Component\Console\Application { $input_definition = parent::getDefaultInputDefinition(); - $input_definition->addOption(new InputOption( - 'safe-mode', - null, - InputOption::VALUE_NONE, - $this->language->lang('CLI_DESCRIPTION_OPTION_SAFE_MODE') - )); + $this->register_global_options($input_definition); return $input_definition; } @@ -76,12 +72,20 @@ class application extends \Symfony\Component\Console\Application return parent::getHelp(); } - $this->getDefinition()->addOption(new InputOption( - '--shell', - '-s', - InputOption::VALUE_NONE, - $this->language->lang('CLI_DESCRIPTION_OPTION_SHELL') - )); + try + { + $definition = $this->getDefinition(); + $definition->addOption(new InputOption( + '--shell', + '-s', + InputOption::VALUE_NONE, + $this->language->lang('CLI_DESCRIPTION_OPTION_SHELL') + )); + } + catch (\LogicException $e) + { + // Do nothing + } return parent::getHelp(); } @@ -117,4 +121,33 @@ class application extends \Symfony\Component\Console\Application return parent::doRun($input, $output); } + + /** + * Register global options + * + * @param InputDefinition $definition An InputDefinition instance + */ + protected function register_global_options(InputDefinition $definition) + { + try + { + $definition->addOption(new InputOption( + 'safe-mode', + null, + InputOption::VALUE_NONE, + $this->language->lang('CLI_DESCRIPTION_OPTION_SAFE_MODE') + )); + + $definition->addOption(new InputOption( + 'env', + 'e', + InputOption::VALUE_REQUIRED, + $this->language->lang('CLI_DESCRIPTION_OPTION_ENV') + )); + } + catch (\LogicException $e) + { + // Do nothing + } + } } From 6af8c579e0162064785c1b729389bdfd41beba95 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 24 Aug 2015 23:09:52 +0200 Subject: [PATCH 0587/1676] [ticket/13897] Make dependency to the filesystem optional in error handler PHPBB3-13897 --- phpBB/includes/functions.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index c6d63e13f4..0be3e289e2 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -3475,7 +3475,15 @@ function phpbb_filter_root_path($errfile) if (empty($root_path)) { - $root_path = $phpbb_filesystem->realpath(dirname(__FILE__) . '/../'); + if ($phpbb_filesystem) + { + $root_path = $phpbb_filesystem->realpath(dirname(__FILE__) . '/../'); + } + else + { + $filesystem = new \phpbb\filesystem\filesystem(); + $root_path = $filesystem->realpath(dirname(__FILE__) . '/../'); + } } return str_replace(array($root_path, '\\'), array('[ROOT]', '/'), $errfile); From 17e7a89a60f700efc8a0b082b7a82005e6288e80 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 24 Aug 2015 12:04:22 +0200 Subject: [PATCH 0588/1676] [ticket/14124] Automatically translate exceptions in CLI PHPBB3-14124 --- phpBB/bin/phpbbcli.php | 1 + .../default/container/services_console.yml | 8 ++ phpBB/config/development/config.yml | 3 + phpBB/config/installer/container/services.yml | 8 ++ phpBB/install_new/phpbbcli.php | 1 + phpBB/phpbb/console/application.php | 1 + phpBB/phpbb/console/exception_subscriber.php | 74 +++++++++++++++++++ .../di/extension/container_configuration.php | 6 ++ phpBB/phpbb/di/extension/core.php | 7 ++ 9 files changed, 109 insertions(+) create mode 100644 phpBB/phpbb/console/exception_subscriber.php diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index 18657aed0a..d85b9a8d46 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -71,5 +71,6 @@ $user->add_lang('cli'); $lang = $phpbb_container->get('language'); $application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $lang); +$application->setDispatcher($phpbb_container->get('dispatcher')); $application->register_container_commands($phpbb_container->get('console.command_collection')); $application->run($input); diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index aee3cbdee6..71b6244e13 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -1,4 +1,12 @@ services: + console.exception_subscriber: + class: phpbb\console\exception_subscriber + arguments: + - @language + - %debug.exceptions% + tags: + - { name: kernel.event_subscriber } + console.command_collection: class: phpbb\di\service_collection arguments: diff --git a/phpBB/config/development/config.yml b/phpBB/config/development/config.yml index 93ae07fb3f..f39eb52e73 100644 --- a/phpBB/config/development/config.yml +++ b/phpBB/config/development/config.yml @@ -4,6 +4,9 @@ imports: core: require_dev_dependencies: true + debug: + exceptions: true + twig: debug: true auto_reload: true diff --git a/phpBB/config/installer/container/services.yml b/phpBB/config/installer/container/services.yml index 8296bcc079..5cd30f9222 100644 --- a/phpBB/config/installer/container/services.yml +++ b/phpBB/config/installer/container/services.yml @@ -68,3 +68,11 @@ services: - null - @template.twig.loader - [] + + console.exception_subscriber: + class: phpbb\console\exception_subscriber + arguments: + - @language + - %debug.exceptions% + tags: + - { name: kernel.event_subscriber } diff --git a/phpBB/install_new/phpbbcli.php b/phpBB/install_new/phpbbcli.php index 508d051945..c1e9a9eaef 100644 --- a/phpBB/install_new/phpbbcli.php +++ b/phpBB/install_new/phpbbcli.php @@ -62,5 +62,6 @@ $language = $phpbb_installer_container->get('language'); $language->add_lang(array('common', 'acp/common', 'acp/board', 'install_new', 'posting', 'cli')); $application = new \phpbb\console\application('phpBB Installer', PHPBB_VERSION, $language); +$application->setDispatcher($phpbb_installer_container->get('dispatcher')); $application->register_container_commands($phpbb_installer_container->get('console.installer.command_collection')); $application->run($input); diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php index 2c69a3cc73..f9f2213da6 100644 --- a/phpBB/phpbb/console/application.php +++ b/phpBB/phpbb/console/application.php @@ -13,6 +13,7 @@ namespace phpbb\console; +use phpbb\exception\exception_interface; use Symfony\Component\Console\Shell; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; diff --git a/phpBB/phpbb/console/exception_subscriber.php b/phpBB/phpbb/console/exception_subscriber.php new file mode 100644 index 0000000000..b920d4abae --- /dev/null +++ b/phpBB/phpbb/console/exception_subscriber.php @@ -0,0 +1,74 @@ + + * @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\console; + +use phpbb\exception\exception_interface; +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleExceptionEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class exception_subscriber implements EventSubscriberInterface +{ + /** + * @var \phpbb\language\language + */ + protected $language; + + /** + * Construct method + * + * @param \phpbb\language\language $language Language object + * @param bool $debug Debug mode + */ + public function __construct(\phpbb\language\language $language, $debug = false) + { + $this->language = $language; + $this->debug = $debug; + } + + /** + * This listener is run when the ConsoleEvents::EXCEPTION event is triggered. + * It translate the exception message. If din debug mode the original exception is embedded. + * + * @param ConsoleExceptionEvent $event + */ + public function on_exception(ConsoleExceptionEvent $event) + { + $original_exception = $event->getException(); + + if ($original_exception instanceof exception_interface) + { + $parameters = array_merge(array($original_exception->getMessage()), $original_exception->get_parameters()); + $message = call_user_func_array(array($this->language, 'lang'), $parameters); + + if ($this->debug) + { + $exception = new \RuntimeException($message , $original_exception->getCode(), $original_exception); + } + else + { + $exception = new \RuntimeException($message , $original_exception->getCode()); + } + + $event->setException($exception); + } + } + + static public function getSubscribedEvents() + { + return array( + ConsoleEvents::EXCEPTION => 'on_exception', + ); + } +} diff --git a/phpBB/phpbb/di/extension/container_configuration.php b/phpBB/phpbb/di/extension/container_configuration.php index 4cc7c7c0d1..4585d6509e 100644 --- a/phpBB/phpbb/di/extension/container_configuration.php +++ b/phpBB/phpbb/di/extension/container_configuration.php @@ -31,6 +31,12 @@ class container_configuration implements ConfigurationInterface $rootNode ->children() ->booleanNode('require_dev_dependencies')->defaultValue(false)->end() + ->arrayNode('debug') + ->addDefaultsIfNotSet() + ->children() + ->booleanNode('exceptions')->defaultValue(false)->end() + ->end() + ->end() ->arrayNode('twig') ->addDefaultsIfNotSet() ->children() diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index 91b321a684..c48a80a558 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -80,6 +80,7 @@ class core extends Extension { $twig_environment_options['auto_reload'] = true; } + // Replace the 8th argument, the options passed to the environment $definition->replaceArgument(7, $twig_environment_options); @@ -88,6 +89,12 @@ class core extends Extension $definition = $container->getDefinition('template.twig.extensions.debug'); $definition->addTag('twig.extension'); } + + // Set the debug options + foreach ($config['debug'] as $name => $value) + { + $container->setParameter('debug.' . $name, $value); + } } /** From 2a07de70c2decb9669990286391cef1d427244bc Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Tue, 25 Aug 2015 22:24:37 +0200 Subject: [PATCH 0589/1676] [ticket/14124] Migrate cron:run exceptions PHPBB3-14124 --- phpBB/phpbb/console/command/cron/run.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/console/command/cron/run.php b/phpBB/phpbb/console/command/cron/run.php index 72ad1205ef..da185b81b3 100644 --- a/phpBB/phpbb/console/command/cron/run.php +++ b/phpBB/phpbb/console/command/cron/run.php @@ -13,6 +13,7 @@ namespace phpbb\console\command\cron; +use phpbb\exception\runtime_exception; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; @@ -92,8 +93,7 @@ class run extends \phpbb\console\command\command } else { - $output->writeln('' . $this->user->lang('CRON_LOCK_ERROR') . ''); - return 1; + throw new runtime_exception('CRON_LOCK_ERROR', array(), null, 1); } } @@ -164,8 +164,7 @@ class run extends \phpbb\console\command\command } else { - $output->writeln('' . $this->user->lang('CRON_NO_SUCH_TASK', $task_name) . ''); - return 2; + throw new runtime_exception('CRON_NO_SUCH_TASK', array( $task_name), null, 2); } } } From 69039054a05c983c33e1246915bc2b2aa03aafa0 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Wed, 26 Aug 2015 06:44:04 +0200 Subject: [PATCH 0590/1676] [ticket/12719] Remove old reset --- phpBB/styles/prosilver/theme/common.css | 49 ------------------------- 1 file changed, 49 deletions(-) diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index 7b47386fed..7ecb1bb83f 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -1,52 +1,3 @@ -/* CSS Reset http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 ----------------------------------------- */ -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -b, u, i, center, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, -menu, nav, output, ruby, section, summary, -time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} -/* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; -} -body { - line-height: 1; -} -ol, ul { - list-style: none; -} -blockquote, q { - quotes: none; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; -} -table { - border-collapse: collapse; - border-spacing: 0; -} -abbr { - text-decoration: none; -} - /* General Markup Styles ---------------------------------------- */ html { From 2e81771c6e18009a16b11b515e869a6a9afb0d2e Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 26 Aug 2015 12:49:18 +0200 Subject: [PATCH 0591/1676] [ticket/14124] Update cron tests PHPBB3-14124 --- tests/console/cron/run_test.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/console/cron/run_test.php b/tests/console/cron/run_test.php index 51ea49b282..d6c7b21781 100644 --- a/tests/console/cron/run_test.php +++ b/tests/console/cron/run_test.php @@ -78,6 +78,10 @@ class phpbb_console_command_cron_run_test extends phpbb_database_test_case $this->assertSame(false, $this->lock->owns_lock()); } + /** + * @expectedException \phpbb\exception\runtime_exception + * @expectedExceptionMessage CRON_LOCK_ERROR + */ public function test_error_lock() { $this->lock->acquire(); @@ -126,6 +130,10 @@ class phpbb_console_command_cron_run_test extends phpbb_database_test_case $this->assertSame(false, $this->lock->owns_lock()); } + /** + * @expectedException \phpbb\exception\runtime_exception + * @expectedExceptionMessage CRON_NO_SUCH_TASK + */ public function test_arg_invalid() { $command_tester = $this->get_command_tester(); From d13d66fc01688e0e9f49bae5cf368dc16220aa40 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 26 Aug 2015 14:09:42 +0200 Subject: [PATCH 0592/1676] [ticket/14124] CS PHPBB3-14124 --- phpBB/phpbb/console/application.php | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php index f9f2213da6..2c69a3cc73 100644 --- a/phpBB/phpbb/console/application.php +++ b/phpBB/phpbb/console/application.php @@ -13,7 +13,6 @@ namespace phpbb\console; -use phpbb\exception\exception_interface; use Symfony\Component\Console\Shell; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; From b8692e459c728da7d84c492fbed689e4a69e67b1 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Wed, 26 Aug 2015 17:39:14 +0200 Subject: [PATCH 0593/1676] [ticket/12719] normalize 3.0.3 and firefox 40 fx --- phpBB/styles/prosilver/theme/base.css | 8 + phpBB/styles/prosilver/theme/normalize.css | 251 ++++++++++++++------- 2 files changed, 180 insertions(+), 79 deletions(-) diff --git a/phpBB/styles/prosilver/theme/base.css b/phpBB/styles/prosilver/theme/base.css index 8c03e4891d..88f591492a 100644 --- a/phpBB/styles/prosilver/theme/base.css +++ b/phpBB/styles/prosilver/theme/base.css @@ -105,3 +105,11 @@ ul { * might still respond to pointer events. */ [tabindex="-1"]:focus { outline: none !important } + +/** + * Remove double underline from recent version of firefox + */ +abbr[title] { + text-decoration: none; +} + diff --git a/phpBB/styles/prosilver/theme/normalize.css b/phpBB/styles/prosilver/theme/normalize.css index 80194760ff..a7ebfad424 100644 --- a/phpBB/styles/prosilver/theme/normalize.css +++ b/phpBB/styles/prosilver/theme/normalize.css @@ -1,28 +1,35 @@ -/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ /** * 1. Set default font family to sans-serif. - * 2. Prevent iOS text size adjust after orientation change, without disabling - * user zoom. + * 2. Prevent iOS and IE text size adjust after device orientation change, + * without disabling user zoom. */ + html { - font-family: sans-serif; /* 1 */ - -ms-text-size-adjust: 100%; /* 2 */ - -webkit-text-size-adjust: 100%; /* 2 */ + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ } /** * Remove default margin. */ -body { margin: 0 } + +body { + margin: 0; +} /* HTML5 display definitions - ========================================================================== */ + ========================================================================== */ + /** * Correct `block` display not defined for any HTML5 element in IE 8/9. - * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. * Correct `block` display not defined for `main` in IE 11. */ + article, aside, details, @@ -32,175 +39,233 @@ footer, header, hgroup, main, +menu, nav, section, -summary { display: block } +summary { + display: block; +} /** * 1. Correct `inline-block` display not defined in IE 8/9. * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. */ + audio, canvas, progress, video { - display: inline-block; /* 1 */ - vertical-align: baseline; /* 2 */ + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ } /** * Prevent modern browsers from displaying `audio` without controls. * Remove excess height in iOS 5 devices. */ + audio:not([controls]) { - display: none; - height: 0; + display: none; + height: 0; } /** * Address `[hidden]` styling not present in IE 8/9/10. - * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. */ + [hidden], -template { display: none } +template { + display: none; +} /* Links - ========================================================================== */ + ========================================================================== */ + /** * Remove the gray background color from active links in IE 10. */ -a { background: transparent } + +a { + background-color: transparent; +} /** - * Improve readability when focused and also mouse hovered in all browsers. + * Improve readability of focused elements when they are also in an + * active/hover state. */ + a:active, -a:hover { outline: 0 } +a:hover { + outline: 0; +} /* Text-level semantics - ========================================================================== */ + ========================================================================== */ + /** * Address styling not present in IE 8/9/10/11, Safari, and Chrome. */ -abbr[title] { border-bottom: 1px dotted } + +abbr[title] { + border-bottom: 1px dotted; +} /** * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. */ + b, -strong { font-weight: bold } +strong { + font-weight: bold; +} /** * Address styling not present in Safari and Chrome. */ -dfn { font-style: italic } + +dfn { + font-style: italic; +} /** * Address variable `h1` font-size and margin within `section` and `article` * contexts in Firefox 4+, Safari, and Chrome. */ + h1 { - font-size: 2em; - margin: 0.67em 0; + font-size: 2em; + margin: 0.67em 0; } /** * Address styling not present in IE 8/9. */ + mark { - background: #ff0; - color: #000; + background: #ff0; + color: #000; } /** * Address inconsistent and variable font size in all browsers. */ -small { font-size: 80% } + +small { + font-size: 80%; +} /** * Prevent `sub` and `sup` affecting `line-height` in all browsers. */ + sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } -sup { top: -0.5em } -sub { bottom: -0.25em } +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} /* Embedded content - ========================================================================== */ + ========================================================================== */ + /** * Remove border when inside `a` element in IE 8/9/10. */ -img { border: 0 } + +img { + border: 0; +} /** * Correct overflow not hidden in IE 9/10/11. */ -svg:not(:root) { overflow: hidden } + +svg:not(:root) { + overflow: hidden; +} /* Grouping content - ========================================================================== */ + ========================================================================== */ + /** * Address margin not present in IE 8/9 and Safari. */ -figure { margin: 1em 40px } + +figure { + margin: 1em 40px; +} /** * Address differences between Firefox and other browsers. */ + hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; + box-sizing: content-box; + height: 0; } /** * Contain overflow in all browsers. */ -pre { overflow: auto } + +pre { + overflow: auto; +} /** * Address odd `em`-unit font size rendering in all browsers. */ + code, kbd, pre, samp { - font-family: monospace, monospace; - font-size: 1em; + font-family: monospace, monospace; + font-size: 1em; } /* Forms - ========================================================================== */ + ========================================================================== */ + /** * Known limitation: by default, Chrome and Safari on OS X allow very limited * styling of `select`, unless a `border` property is set. */ + /** * 1. Correct color not being inherited. * Known issue: affects color of disabled elements. * 2. Correct font properties not being inherited. * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. */ + button, input, optgroup, select, textarea { - color: inherit; /* 1 */ - font: inherit; /* 2 */ - margin: 0; /* 3 */ + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ } /** * Address `overflow` set to `hidden` in IE 8/9/10/11. */ -button { overflow: visible } + +button { + overflow: visible; +} /** * Address inconsistent `text-transform` inheritance for `button` and `select`. @@ -208,8 +273,11 @@ button { overflow: visible } * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. * Correct `select` style inheritance in Firefox. */ + button, -select { text-transform: none } +select { + text-transform: none; +} /** * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` @@ -218,34 +286,42 @@ select { text-transform: none } * 3. Improve usability and consistency of cursor style between image-type * `input` and others. */ + button, html input[type="button"], /* 1 */ input[type="reset"], input[type="submit"] { - -webkit-appearance: button; /* 2 */ - cursor: pointer; /* 3 */ + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ } /** * Re-set default cursor for disabled elements. */ + button[disabled], -html input[disabled] { cursor: default } +html input[disabled] { + cursor: default; +} /** * Remove inner padding and border in Firefox 4+. */ + button::-moz-focus-inner, input::-moz-focus-inner { - border: 0; - padding: 0; + border: 0; + padding: 0; } /** * Address Firefox 4+ setting `line-height` on `input` using `!important` in * the UA stylesheet. */ -input { line-height: normal } + +input { + line-height: normal; +} /** * It's recommended that you don't attempt to style these elements. @@ -254,10 +330,11 @@ input { line-height: normal } * 1. Address box sizing set to `content-box` in IE 8/9/10. * 2. Remove excess padding in IE 8/9/10. */ + input[type="checkbox"], input[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ } /** @@ -265,19 +342,20 @@ input[type="radio"] { * `font-size` values of the `input`, it causes the cursor style of the * decrement button to change from `default` to `text`. */ + input[type="number"]::-webkit-inner-spin-button, -input[type="number"]::-webkit-outer-spin-button { height: auto } +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} /** * 1. Address `appearance` set to `searchfield` in Safari and Chrome. - * 2. Address `box-sizing` set to `border-box` in Safari and Chrome - * (include `-moz` to future-proof). + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome. */ + input[type="search"] { - -webkit-appearance: textfield; /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; /* 2 */ - box-sizing: content-box; + -webkit-appearance: textfield; /* 1 */ + box-sizing: content-box; /* 2 */ } /** @@ -285,47 +363,62 @@ input[type="search"] { * Safari (but not Chrome) clips the cancel button when the search input has * padding (and `textfield` appearance). */ + input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { -webkit-appearance: none } +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} /** * Define consistent border, margin, and padding. */ + fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } /** * 1. Correct `color` not being inherited in IE 8/9/10/11. * 2. Remove padding so people aren't caught out if they zero out fieldsets. */ + legend { - border: 0; /* 1 */ - padding: 0; /* 2 */ + border: 0; /* 1 */ + padding: 0; /* 2 */ } /** * Remove default vertical scrollbar in IE 8/9/10/11. */ -textarea { overflow: auto } + +textarea { + overflow: auto; +} /** * Don't inherit the `font-weight` (applied by a rule above). * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. */ -optgroup { font-weight: bold } + +optgroup { + font-weight: bold; +} /* Tables - ========================================================================== */ + ========================================================================== */ + /** * Remove most spacing between table cells. */ + table { - border-collapse: collapse; - border-spacing: 0; + border-collapse: collapse; + border-spacing: 0; } td, -th { padding: 0 } +th { + padding: 0; +} \ No newline at end of file From e19d446881ba98d8a1082732585da3f6d4bd262f Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Wed, 26 Aug 2015 10:05:14 -0700 Subject: [PATCH 0594/1676] [ticket/14128] Fix img bbcode regression, lost postimage class PHPBB3-14128 --- phpBB/phpbb/textformatter/s9e/factory.php | 2 +- tests/text_formatter/s9e/default_formatting_test.php | 2 +- .../s9e/fixtures/styles/bar/template/bbcode.html | 2 +- .../s9e/fixtures/styles/barplus/template/bbcode.html | 2 +- .../s9e/fixtures/styles/foo/template/bbcode.html | 2 +- tests/text_formatter/s9e/renderer_test.php | 4 ++-- tests/text_processing/generate_text_for_display_test.php | 2 +- tests/text_processing/tickets_data/PHPBB3-12195.html | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 4a04b34cd8..63b23d2fd0 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -104,7 +104,7 @@ class factory implements \phpbb\textformatter\cache_interface 'b' => '', 'i' => '', 'u' => '', - 'img' => '{L_IMAGE}', + 'img' => '{L_IMAGE}', 'size' => '', 'color' => '', 'email' => ' diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index 390bc65264..3047653d51 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -132,7 +132,7 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case ), array( '[img]https://area51.phpbb.com/images/area51.png[/img]', - 'Image' + 'Image' ), array( '[url]https://area51.phpbb.com/[/url]', diff --git a/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html index a17446581a..76a35542be 100644 --- a/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html +++ b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html @@ -31,7 +31,7 @@ {TEXT} -{L_IMAGE} +{L_IMAGE} {DESCRIPTION} diff --git a/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html index cd2f0acae3..fad8d828fd 100644 --- a/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html +++ b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html @@ -31,7 +31,7 @@ {TEXT} -{L_IMAGE} +{L_IMAGE} {DESCRIPTION} diff --git a/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html index 909c09df5a..3e38d13a32 100644 --- a/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html +++ b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html @@ -31,7 +31,7 @@ {TEXT} -{L_IMAGE} +{L_IMAGE} {DESCRIPTION} diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php index 3c0bbb96c7..ad5bfa78fc 100644 --- a/tests/text_formatter/s9e/renderer_test.php +++ b/tests/text_formatter/s9e/renderer_test.php @@ -112,7 +112,7 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case ), array( '[img]http://example.org/foo.png[/img]', - 'Image', + 'Image', array('set_viewimg' => true) ), array( @@ -231,7 +231,7 @@ class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case ), array( '[img]http://localhost/mrgreen.gif[/img]', - 'Image' + 'Image' ), array( '[img]http://localhost/mrgreen.gif[/img]', diff --git a/tests/text_processing/generate_text_for_display_test.php b/tests/text_processing/generate_text_for_display_test.php index f2b0d6c78b..dba3713447 100644 --- a/tests/text_processing/generate_text_for_display_test.php +++ b/tests/text_processing/generate_text_for_display_test.php @@ -173,7 +173,7 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca ), array( '[img]http://localhost/mrgreen.gif[/img]', - 'Image' + 'Image' ), array( '[img]http://localhost/mrgreen.gif[/img]', diff --git a/tests/text_processing/tickets_data/PHPBB3-12195.html b/tests/text_processing/tickets_data/PHPBB3-12195.html index d8e0f8d523..c286c0fee9 100644 --- a/tests/text_processing/tickets_data/PHPBB3-12195.html +++ b/tests/text_processing/tickets_data/PHPBB3-12195.html @@ -1 +1 @@ -Image \ No newline at end of file +Image \ No newline at end of file From 5b112b974f7229fc6aa5e08b332dd3b53e0112ad Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Sun, 30 Aug 2015 14:01:56 +0200 Subject: [PATCH 0595/1676] [ticket/14038] Give links some visual love --- phpBB/styles/prosilver/template/jumpbox.html | 2 +- phpBB/styles/prosilver/theme/links.css | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/template/jumpbox.html b/phpBB/styles/prosilver/template/jumpbox.html index 3096d08318..5cc8a8ca83 100644 --- a/phpBB/styles/prosilver/template/jumpbox.html +++ b/phpBB/styles/prosilver/template/jumpbox.html @@ -20,7 +20,7 @@ diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index a2f512443c..7e7f7011ff 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -58,6 +58,8 @@ li.breadcrumbs span:first-child > a { width: 40px; } +.jumpbox-header-link { font-weight: bold; } + /* Links for forum/topic lists */ a.forumtitle { font-family: "Trebuchet MS", Helvetica, Arial, Sans-serif; From 0e26b4e68f36d7c98ee049b48fc5c0f0e89b7f46 Mon Sep 17 00:00:00 2001 From: Michael Miday Date: Sun, 30 Aug 2015 18:30:40 +0200 Subject: [PATCH 0596/1676] [ticket/14038] Stylize & differintiate --- phpBB/styles/prosilver/template/jumpbox.html | 6 ++-- phpBB/styles/prosilver/theme/colours.css | 26 +++++++++++++++ phpBB/styles/prosilver/theme/common.css | 33 ++++++++++++++++++-- phpBB/styles/prosilver/theme/links.css | 4 ++- 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/phpBB/styles/prosilver/template/jumpbox.html b/phpBB/styles/prosilver/template/jumpbox.html index 5cc8a8ca83..cacf54b478 100644 --- a/phpBB/styles/prosilver/template/jumpbox.html +++ b/phpBB/styles/prosilver/template/jumpbox.html @@ -11,7 +11,7 @@ -
      @@ -84,24 +84,24 @@ - {NEW_POST} + {NEW_POST} {searchresults.TOPIC_TITLE} - {TOPIC_UNAPPROVED} + {TOPIC_UNAPPROVED} - {TOPIC_DELETED} + {TOPIC_DELETED} - {TOPIC_REPORTED} + {TOPIC_REPORTED}
      @@ -119,8 +119,8 @@
      - - + + {L_POST_BY_AUTHOR} {searchresults.TOPIC_AUTHOR_FULL} » {searchresults.FIRST_POST_TIME} » {L_IN} {searchresults.FORUM_TITLE} @@ -133,7 +133,7 @@ {L_POST_BY_AUTHOR} {searchresults.LAST_POST_AUTHOR_FULL} - {VIEW_LATEST_POST} + {VIEW_LATEST_POST}
      @@ -190,7 +190,7 @@ diff --git a/phpBB/styles/prosilver/template/simple_footer.html b/phpBB/styles/prosilver/template/simple_footer.html index defe2c9456..76a58ed218 100644 --- a/phpBB/styles/prosilver/template/simple_footer.html +++ b/phpBB/styles/prosilver/template/simple_footer.html @@ -12,13 +12,13 @@ diff --git a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html index 7aa4313910..72d23e7da1 100644 --- a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html +++ b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html @@ -40,17 +40,17 @@
      - + {L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} » {topicrow.FIRST_POST_TIME}
      @@ -81,7 +81,7 @@
      {L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} - {VIEW_LATEST_POST} + {VIEW_LATEST_POST}
      {topicrow.LAST_POST_TIME}
      diff --git a/phpBB/styles/prosilver/template/ucp_main_front.html b/phpBB/styles/prosilver/template/ucp_main_front.html index d5eb6f91a7..1351af914b 100644 --- a/phpBB/styles/prosilver/template/ucp_main_front.html +++ b/phpBB/styles/prosilver/template/ucp_main_front.html @@ -19,7 +19,7 @@
      - + {L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} » {topicrow.FIRST_POST_TIME}
      @@ -50,7 +50,7 @@
      {L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} - {VIEW_LATEST_POST} + {VIEW_LATEST_POST}
      {topicrow.LAST_POST_TIME}
      @@ -70,7 +70,7 @@
      {L_TOTAL_POSTS}{L_COLON}
      {POSTS} | {L_SEARCH_YOUR_POSTS}
      ({POSTS_DAY} / {POSTS_PCT}){POSTS}
      {L_ACTIVE_IN_FORUM}{L_COLON}
      {ACTIVE_FORUM}
      ({ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT})
      {L_ACTIVE_IN_TOPIC}{L_COLON}
      {ACTIVE_TOPIC}
      ({ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT})
      -
      {L_YOUR_WARNINGS}{L_COLON}
      [{WARNINGS}]
      +
      {L_YOUR_WARNINGS}{L_COLON}
      [{WARNINGS}]
      diff --git a/phpBB/styles/prosilver/template/ucp_main_subscribed.html b/phpBB/styles/prosilver/template/ucp_main_subscribed.html index 332330c5b1..3405a44f60 100644 --- a/phpBB/styles/prosilver/template/ucp_main_subscribed.html +++ b/phpBB/styles/prosilver/template/ucp_main_subscribed.html @@ -39,7 +39,7 @@ {L_LAST_POST} {L_POST_BY_AUTHOR} {forumrow.LAST_POST_AUTHOR_FULL} - {VIEW_LATEST_POST} + {VIEW_LATEST_POST}
      {forumrow.LAST_POST_TIME}
      @@ -83,17 +83,17 @@
      - + {L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} » {topicrow.FIRST_POST_TIME}
      {L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} - {VIEW_LATEST_POST} + {VIEW_LATEST_POST}
      {topicrow.LAST_POST_TIME}
      diff --git a/phpBB/styles/prosilver/template/ucp_pm_history.html b/phpBB/styles/prosilver/template/ucp_pm_history.html index d3aed8ffee..57f6cf14b5 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_history.html +++ b/phpBB/styles/prosilver/template/ucp_pm_history.html @@ -26,7 +26,7 @@
    • href="{history_row.U_QUOTE}"href="#postingbox" onclick="addquote({history_row.MSG_ID}, '{history_row.MESSAGE_AUTHOR_QUOTE}', '{LA_WROTE}', {time:{history_row.MESSAGE_TIME},user_id:{history_row.USER_ID}});" title="{L_QUOTE} {history_row.MESSAGE_AUTHOR}" class="button"> - {L_QUOTE} {history_row.MESSAGE_AUTHOR} + {L_QUOTE} {history_row.MESSAGE_AUTHOR}
    • @@ -36,7 +36,7 @@

      - {history_row.MINI_POST} {L_SENT_AT}{L_COLON} {history_row.SENT_DATE} + {history_row.MINI_POST} {L_SENT_AT}{L_COLON} {history_row.SENT_DATE}
      {L_MESSAGE_BY_AUTHOR} {history_row.MESSAGE_AUTHOR_FULL}

      @@ -53,7 +53,7 @@

      - {L_BACK_TO_TOP} + {L_BACK_TO_TOP}

      diff --git a/phpBB/styles/prosilver/template/ucp_pm_message_header.html b/phpBB/styles/prosilver/template/ucp_pm_message_header.html index f629c3d5f1..c49649e619 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_message_header.html +++ b/phpBB/styles/prosilver/template/ucp_pm_message_header.html @@ -10,21 +10,21 @@ - {L_BUTTON_PM_REPLY} + {L_BUTTON_PM_REPLY} - {L_BUTTON_PM_NEW} + {L_BUTTON_PM_NEW} - {L_BUTTON_PM_FORWARD} + {L_BUTTON_PM_FORWARD} - {L_BUTTON_PM_REPLY_ALL} + {L_BUTTON_PM_REPLY_ALL} @@ -32,8 +32,8 @@
      - {S_HIDDEN_FIELDS}  + {S_HIDDEN_FIELDS}  {S_FORM_TOKEN}
      diff --git a/phpBB/styles/prosilver/template/viewonline_body.html b/phpBB/styles/prosilver/template/viewonline_body.html index 52733afbcf..dd0ca72502 100644 --- a/phpBB/styles/prosilver/template/viewonline_body.html +++ b/phpBB/styles/prosilver/template/viewonline_body.html @@ -5,9 +5,9 @@
      @@ -15,7 +15,7 @@
      - + @@ -43,7 +43,7 @@
      - +
      @@ -51,9 +51,9 @@
      diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html index 0df6956181..522151cf7d 100644 --- a/phpBB/styles/prosilver/template/viewtopic_body.html +++ b/phpBB/styles/prosilver/template/viewtopic_body.html @@ -288,7 +288,7 @@ {postrow.MINI_POST} - {L_POST_BY_AUTHOR} {postrow.POST_AUTHOR_FULL} » {postrow.POST_DATE} + {L_POST_BY_AUTHOR} {postrow.POST_AUTHOR_FULL} » {postrow.POST_DATE}

      @@ -421,7 +421,7 @@
      - + diff --git a/phpBB/styles/prosilver/theme/buttons.css b/phpBB/styles/prosilver/theme/buttons.css index 7f93dbdf89..4c8283fdc0 100644 --- a/phpBB/styles/prosilver/theme/buttons.css +++ b/phpBB/styles/prosilver/theme/buttons.css @@ -158,7 +158,7 @@ button::-moz-focus-inner { border: 0 } -/* Deprecated as of version 3.2 +/* Deprecated as of version 3.2 -------------------------------------------------*/ .small-icon { background-position: 0 50%; @@ -178,7 +178,7 @@ button::-moz-focus-inner { ul.linklist.bulletin > li.small-icon:before { display: none; } - + .dropdown .small-icon > a { display: block; } diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index 4458a59502..d76fd0852a 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -255,7 +255,7 @@ dl.details dd { color: #FFFFFF; } -.jumpbox-cat-link:hover { +.jumpbox-cat-link:hover { background-color: #12A3EB; border-top-color: #12A3EB; color: #FFFFFF; diff --git a/phpBB/styles/prosilver/theme/icons.css b/phpBB/styles/prosilver/theme/icons.css index f5d1b00795..9fb7244f4b 100644 --- a/phpBB/styles/prosilver/theme/icons.css +++ b/phpBB/styles/prosilver/theme/icons.css @@ -2,11 +2,11 @@ $Icons -------------------------------------------------------------- */ -/* Global module setup +/* Global module setup --------------------------------*/ /* Renamed version of .fa class for agnostic useage of icon fonts. - * Just change the name of the font after the 14/1 to the name of + * Just change the name of the font after the 14/1 to the name of * the font you wish to use. */ .icon, .button .icon { @@ -31,7 +31,7 @@ /* Icon size classes - Default size is 14px, use these for small variations */ .icon.icon-xl { - font-size: 20px; + font-size: 20px; } .icon.icon-lg { @@ -61,7 +61,7 @@ .arrow-right .icon { float: right; -} +} .arrow-right:hover .icon { margin-left: 5px; diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index a018bbc792..6da14c9326 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -8,7 +8,7 @@ a { text-decoration: none; /* we use links inline more often then not so to address several bugs with IE and some other browsers we render all links as inlineblock by default */ - display: inline-block; + display: inline-block; } @@ -151,7 +151,7 @@ a.lastsubject:hover { } .arrow-up:hover { - + } .arrow-down { @@ -159,7 +159,7 @@ a.lastsubject:hover { } .arrow-down:hover { - + } .arrow-left:hover { diff --git a/phpBB/styles/prosilver/theme/normalize.css b/phpBB/styles/prosilver/theme/normalize.css index a7ebfad424..23d84492c8 100644 --- a/phpBB/styles/prosilver/theme/normalize.css +++ b/phpBB/styles/prosilver/theme/normalize.css @@ -421,4 +421,4 @@ table { td, th { padding: 0; -} \ No newline at end of file +} diff --git a/phpBB/styles/prosilver/theme/stylesheet.css b/phpBB/styles/prosilver/theme/stylesheet.css index 4fe97d144b..f235f6030e 100644 --- a/phpBB/styles/prosilver/theme/stylesheet.css +++ b/phpBB/styles/prosilver/theme/stylesheet.css @@ -1,7 +1,7 @@ /* phpBB3 Style Sheet -------------------------------------------------------------- Style name: prosilver (the default phpBB 3.1.x style) - Based on style: + Based on style: Original author: Tom Beddard ( http://www.subblue.com/ ) Modified by: phpBB Limited ( https://www.phpbb.com/ ) -------------------------------------------------------------- From debd1bb9d655106eb5454ac4687837c9323a99ae Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 2 Feb 2016 17:53:10 +0100 Subject: [PATCH 1046/1676] [ticket/14321] Clean up arcihve controller logic PHPBB3-14321 --- phpBB/phpbb/install/controller/archive_download.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/install/controller/archive_download.php b/phpBB/phpbb/install/controller/archive_download.php index a0f0ba181d..eabc0a9976 100644 --- a/phpBB/phpbb/install/controller/archive_download.php +++ b/phpBB/phpbb/install/controller/archive_download.php @@ -46,9 +46,9 @@ class archive_download */ public function conflict_archive() { - $filename = $this->installer_config->get('update_file_conflict_archive', false); + $filename = $this->installer_config->get('update_file_conflict_archive', ''); - if (!$filename) + if (empty($filename)) { throw new http_exception(404, 'URL_NOT_FOUND'); } @@ -65,7 +65,7 @@ class archive_download { $filename = $this->installer_config->get('update_file_archive', ''); - if (!$filename) + if (empty($filename)) { throw new http_exception(404, 'URL_NOT_FOUND'); } From 8f4889da58e0aa4779ec6bf7c0e747c26a13aee3 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Tue, 2 Feb 2016 17:16:15 +0100 Subject: [PATCH 1047/1676] [ticket/14445] Force refresh before schema generation PHPBB3-14445 --- phpBB/phpbb/install/helper/config.php | 6 +++--- .../module/install_database/task/create_schema.php | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php index 0f0840f470..ab5af86320 100644 --- a/phpBB/phpbb/install/helper/config.php +++ b/phpBB/phpbb/install/helper/config.php @@ -157,10 +157,10 @@ class config { if ($this->system_data['max_execution_time'] <= 0) { - return 1; + return PHP_INT_MAX; } - return ($this->system_data['start_time'] + $this->system_data['max_execution_time']) - time(); + return ($this->system_data['start_time'] + $this->system_data['max_execution_time']) - microtime(true); } /** @@ -430,7 +430,7 @@ class config $this->system_data['max_execution_time'] = $execution_time; // Set start time - $this->system_data['start_time'] = time(); + $this->system_data['start_time'] = microtime(true); // Get memory limit $this->system_data['memory_limit'] = $this->php_ini->getBytes('memory_limit'); diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php index cabb78787f..a5635d5dbe 100644 --- a/phpBB/phpbb/install/module/install_database/task/create_schema.php +++ b/phpBB/phpbb/install/module/install_database/task/create_schema.php @@ -13,6 +13,8 @@ namespace phpbb\install\module\install_database\task; +use phpbb\install\exception\resource_limit_reached_exception; + /** * Create database schema */ @@ -106,6 +108,17 @@ class create_schema extends \phpbb\install\task_base */ public function run() { + // As this task may take a large amount of time to complete refreshing the page might be necessary for some + // server configurations with limited resources + if (!$this->config->get('pre_schema_forced_refresh')) + { + if ($this->config->get_time_remaining() < 5) + { + $this->config->set('pre_schema_forced_refresh', true); + throw new resource_limit_reached_exception(); + } + } + $this->db->sql_return_on_error(true); $dbms = $this->config->get('dbms'); From cec63974c393b71770eae7d740e136b43ed1c78f Mon Sep 17 00:00:00 2001 From: Scott Dutton Date: Mon, 25 Jan 2016 21:45:43 +0000 Subject: [PATCH 1048/1676] [ticket/14431] Remote avatar uploading replace the 3.1 way with guzzle Adds guzzle as a dependency Removed a test as it wont wont with guzzle (as far as I know) PHPBB3-14431 --- phpBB/composer.json | 1 + phpBB/phpbb/files/types/remote.php | 122 +++++------------------------ 2 files changed, 20 insertions(+), 103 deletions(-) diff --git a/phpBB/composer.json b/phpBB/composer.json index 89bbce4588..c5e4824c0f 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -28,6 +28,7 @@ "php": ">=5.4,<7.1", "bantu/ini-get-wrapper": "1.0.*", "google/recaptcha": "~1.1", + "guzzle/guzzle": "~5.3", "lusitanian/oauth": "^0.8.1", "marc1706/fast-image-size": "1.1.*", "patchwork/utf8": "1.1.*", diff --git a/phpBB/phpbb/files/types/remote.php b/phpBB/phpbb/files/types/remote.php index d311face98..e990149501 100644 --- a/phpBB/phpbb/files/types/remote.php +++ b/phpBB/phpbb/files/types/remote.php @@ -86,19 +86,6 @@ class remote extends base $url = parse_url($upload_url); - $default_port = 80; - $hostname = $url['host']; - - if ($url['scheme'] == 'https') - { - $default_port = 443; - $hostname = 'tls://' . $url['host']; - } - - $host = $url['host']; - $path = $url['path']; - $port = (!empty($url['port'])) ? (int) $url['port'] : $default_port; - $upload_ary['type'] = 'application/octet-stream'; $url['path'] = explode('.', $url['path']); @@ -110,103 +97,32 @@ class remote extends base $remote_max_filesize = $this->get_max_file_size(); - $errno = 0; - $errstr = ''; + $client = new \Guzzle\Http\Client([ + 'timeout' => $this->upload->upload_timeout, + 'connect_timeout' => $this->upload->upload_timeout, + ]); - if (!($fsock = @fsockopen($hostname, $port, $errno, $errstr))) - { + try { + $response = $client->get($upload_url)->send(); + } catch (\Guzzle\Http\Exception\ClientErrorResponseException $responseException) { + return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'URL_NOT_FOUND'); + } catch (\Guzzle\Http\Exception\CurlException $curlException) { + //curl exceptions are when the DNS fails etc + return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED')); + } catch (\Guzzle\Http\Exception\RequestException $requestException) { + return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'REMOTE_UPLOAD_TIMEOUT'); + } catch (\Exception $e) { return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED')); } - // Make sure $path not beginning with / - if (strpos($path, '/') === 0) + if ($remote_max_filesize && $response->getContentType() > $remote_max_filesize) { - $path = substr($path, 1); + $max_filesize = get_formatted_filesize($remote_max_filesize, false); + + return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit'])); } - fputs($fsock, 'GET /' . $path . " HTTP/1.1\r\n"); - fputs($fsock, "HOST: " . $host . "\r\n"); - fputs($fsock, "Connection: close\r\n\r\n"); - - // Set a proper timeout for the socket - socket_set_timeout($fsock, $this->upload->upload_timeout); - - $get_info = false; - $data = ''; - $length = false; - $timer_stop = time() + $this->upload->upload_timeout; - - while ((!$length || $filesize < $length) && !@feof($fsock)) - { - if ($get_info) - { - if ($length) - { - // Don't attempt to read past end of file if server indicated length - $block = @fread($fsock, min($length - $filesize, 1024)); - } - else - { - $block = @fread($fsock, 1024); - } - - $filesize += strlen($block); - - if ($remote_max_filesize && $filesize > $remote_max_filesize) - { - $max_filesize = get_formatted_filesize($remote_max_filesize, false); - - return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit'])); - } - - $data .= $block; - } - else - { - $line = @fgets($fsock, 1024); - - if ($line == "\r\n") - { - $get_info = true; - } - else - { - if (stripos($line, 'content-type: ') !== false) - { - $upload_ary['type'] = rtrim(str_replace('content-type: ', '', strtolower($line))); - } - else if ($this->upload->max_filesize && stripos($line, 'content-length: ') !== false) - { - $length = (int) str_replace('content-length: ', '', strtolower($line)); - - if ($remote_max_filesize && $length && $length > $remote_max_filesize) - { - $max_filesize = get_formatted_filesize($remote_max_filesize, false); - - return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit'])); - } - } - else if (stripos($line, '404 not found') !== false) - { - return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'URL_NOT_FOUND'); - } - } - } - - $stream_meta_data = stream_get_meta_data($fsock); - - // Cancel upload if we exceed timeout - if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop) - { - return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'REMOTE_UPLOAD_TIMEOUT'); - } - } - @fclose($fsock); - - if (empty($data)) - { - return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'EMPTY_REMOTE_DATA'); - } + $data = $response->getBody(); $filename = tempnam(sys_get_temp_dir(), unique_id() . '-'); From 49dd9f021924551bf0cfc5db3962ddb50c9e98a2 Mon Sep 17 00:00:00 2001 From: Scott Dutton Date: Wed, 3 Feb 2016 05:45:24 +0000 Subject: [PATCH 1049/1676] [ticket/14431] Remote avatar uploading Fixed content length bug Ran composer update PHPBB3-14431 --- phpBB/phpbb/files/types/remote.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/files/types/remote.php b/phpBB/phpbb/files/types/remote.php index e990149501..92e0e3b9bc 100644 --- a/phpBB/phpbb/files/types/remote.php +++ b/phpBB/phpbb/files/types/remote.php @@ -115,13 +115,19 @@ class remote extends base return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED')); } - if ($remote_max_filesize && $response->getContentType() > $remote_max_filesize) + $content_length = $response->getContentLength(); + if ($remote_max_filesize && $content_length > $remote_max_filesize) { $max_filesize = get_formatted_filesize($remote_max_filesize, false); return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit'])); } + if ($content_length == 0) + { + return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'EMPTY_REMOTE_DATA'); + } + $data = $response->getBody(); $filename = tempnam(sys_get_temp_dir(), unique_id() . '-'); From 5ee559d5240fb0fa239ce87657ce109a35ab37f8 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 3 Feb 2016 11:30:15 +0100 Subject: [PATCH 1050/1676] [ticket/14448] Update composer.json and lock file for guzzlehttp PHPBB3-14448 --- phpBB/composer.json | 2 +- phpBB/composer.lock | 410 ++++++++++++++++++++++---------------------- 2 files changed, 206 insertions(+), 206 deletions(-) diff --git a/phpBB/composer.json b/phpBB/composer.json index c5e4824c0f..a6c3a2aa93 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -28,7 +28,7 @@ "php": ">=5.4,<7.1", "bantu/ini-get-wrapper": "1.0.*", "google/recaptcha": "~1.1", - "guzzle/guzzle": "~5.3", + "guzzlehttp/guzzle": "~5.3", "lusitanian/oauth": "^0.8.1", "marc1706/fast-image-size": "1.1.*", "patchwork/utf8": "1.1.*", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 6412029b0b..09e558049d 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "f76b5185058599cad6a87ef7c8c35fbf", - "content-hash": "b89d3c18f8d9b3c4dc476f92030a83a1", + "hash": "d4e2fb7ee961c4734df4e385db2e6995", + "content-hash": "b15dfee84d1e9f3e2f5a3cc290b0be58", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -82,6 +82,165 @@ ], "time": "2015-09-02 17:23:59" }, + { + "name": "guzzlehttp/guzzle", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "f3c8c22471cb55475105c14769644a49c3262b93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", + "reference": "f3c8c22471cb55475105c14769644a49c3262b93", + "shasum": "" + }, + "require": { + "guzzlehttp/ringphp": "^1.1", + "php": ">=5.4.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2015-05-20 03:47:55" + }, + { + "name": "guzzlehttp/ringphp", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/RingPHP.git", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "shasum": "" + }, + "require": { + "guzzlehttp/streams": "~3.0", + "php": ">=5.4.0", + "react/promise": "~2.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "ext-curl": "Guzzle will use specific adapters if cURL is present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Ring\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", + "time": "2015-05-20 03:37:09" + }, + { + "name": "guzzlehttp/streams", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/streams.git", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple abstraction over streams of data", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "stream" + ], + "time": "2014-10-12 19:18:40" + }, { "name": "ircmaxell/password-compat", "version": "v1.0.4", @@ -331,6 +490,50 @@ ], "time": "2012-12-21 11:40:51" }, + { + "name": "react/promise", + "version": "v2.2.1", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/3b6fca09c7d56321057fa8867c8dbe1abf648627", + "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "React\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "time": "2015-07-03 13:48:55" + }, { "name": "s9e/text-formatter", "version": "0.4.8", @@ -1498,165 +1701,6 @@ ], "time": "2015-03-18 18:23:50" }, - { - "name": "guzzlehttp/guzzle", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93", - "shasum": "" - }, - "require": { - "guzzlehttp/ringphp": "^1.1", - "php": ">=5.4.0" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0", - "psr/log": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2015-05-20 03:47:55" - }, - { - "name": "guzzlehttp/ringphp", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/RingPHP.git", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", - "shasum": "" - }, - "require": { - "guzzlehttp/streams": "~3.0", - "php": ">=5.4.0", - "react/promise": "~2.0" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "ext-curl": "Guzzle will use specific adapters if cURL is present" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Ring\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20 03:37:09" - }, - { - "name": "guzzlehttp/streams", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/streams.git", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Stream\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Provides a simple abstraction over streams of data", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "Guzzle", - "stream" - ], - "time": "2014-10-12 19:18:40" - }, { "name": "michelf/php-markdown", "version": "1.6.0", @@ -2281,50 +2325,6 @@ ], "time": "2013-03-08 08:21:40" }, - { - "name": "react/promise", - "version": "v2.2.1", - "source": { - "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/3b6fca09c7d56321057fa8867c8dbe1abf648627", - "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "React\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com" - } - ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "time": "2015-07-03 13:48:55" - }, { "name": "sami/sami", "version": "v1.4.1", From b9df08e97f8838e9c121fed8fcce4b84e92f8cdb Mon Sep 17 00:00:00 2001 From: Richard McGirr Date: Wed, 3 Feb 2016 06:29:21 -0500 Subject: [PATCH 1051/1676] [ticket/14416] Revert changes and use twig spaceless PHPBB3-14416 --- .../styles/prosilver/template/navbar_footer.html | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/phpBB/styles/prosilver/template/navbar_footer.html b/phpBB/styles/prosilver/template/navbar_footer.html index aab5c7e198..4e3d1e295e 100644 --- a/phpBB/styles/prosilver/template/navbar_footer.html +++ b/phpBB/styles/prosilver/template/navbar_footer.html @@ -4,10 +4,22 @@
      + + diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index 0e54654ff1..d9f446a28d 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -374,8 +374,8 @@ if (timeoutDetected) { addMessage('error', [{ - title:'The installer detected a timeout.', - description: 'The installer has detected a timeout, you may try to refresh the page, that may lead to data corruption. We suggest that you either increase your timeout settings or try to use the CLI.' + title: installLang.title, + description: installLang.msg }] ); } diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 3ce034e590..41eef61c50 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -120,7 +120,11 @@ $lang = array_merge($lang, array( // General error messages $lang = array_merge($lang, array( 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.', - 'PHPBB_ALREADY_INSTALLED' => 'phpBB is already installed.' + + 'PHPBB_ALREADY_INSTALLED' => 'phpBB is already installed.', + + 'TIMEOUT_DETECTED_TITLE' => 'The installer detected a timeout', + 'TIMEOUT_DETECTED_MESSAGE' => 'The installer has detected a timeout, you may try to refresh the page, which may lead to data corruption. We suggest that you either increase your timeout settings or try to use the CLI.', )); // Data obtaining translations From d330ef8c1b52bb93e02de3992edb9041f2c99fb5 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 14 Feb 2016 16:24:00 +0100 Subject: [PATCH 1086/1676] [ticket/14478] Move facebook/webdriver dependency to main composer file Also updated to latest version and now using proper version in composer.json. PHPBB3-14478 --- phpBB/composer.json | 1 + phpBB/composer.lock | 47 ++++++++++++++- tests/composer.json | 5 -- tests/composer.lock | 66 --------------------- tests/test_framework/phpbb_ui_test_case.php | 11 +++- 5 files changed, 54 insertions(+), 76 deletions(-) delete mode 100644 tests/composer.json delete mode 100644 tests/composer.lock diff --git a/phpBB/composer.json b/phpBB/composer.json index a6c3a2aa93..88df2bfa3d 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -49,6 +49,7 @@ }, "require-dev": { "fabpot/goutte": "~2.0", + "facebook/webdriver": "~1.1", "phing/phing": "2.4.*", "phpunit/dbunit": "1.3.*", "phpunit/phpunit": "4.1.*", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index cad14d8913..9a278fa8cf 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "d4e2fb7ee961c4734df4e385db2e6995", - "content-hash": "b15dfee84d1e9f3e2f5a3cc290b0be58", + "hash": "2de20b0ffe0ca05fb62a7c685a25ca79", + "content-hash": "6e427257e82c0d33fc94040d9685f516", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -1606,6 +1606,49 @@ ], "time": "2015-05-05 21:14:57" }, + { + "name": "facebook/webdriver", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/facebook/php-webdriver.git", + "reference": "1c98108ba3eb435b681655764de11502a0653705" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/1c98108ba3eb435b681655764de11502a0653705", + "reference": "1c98108ba3eb435b681655764de11502a0653705", + "shasum": "" + }, + "require": { + "php": ">=5.3.19" + }, + "require-dev": { + "phpunit/phpunit": "4.6.*" + }, + "suggest": { + "phpdocumentor/phpdocumentor": "2.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "A PHP client for WebDriver", + "homepage": "https://github.com/facebook/php-webdriver", + "keywords": [ + "facebook", + "php", + "selenium", + "webdriver" + ], + "time": "2015-12-31 15:58:49" + }, { "name": "michelf/php-markdown", "version": "1.6.0", diff --git a/tests/composer.json b/tests/composer.json deleted file mode 100644 index 69512f30a6..0000000000 --- a/tests/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require-dev": { - "facebook/webdriver": "dev-master" - } -} diff --git a/tests/composer.lock b/tests/composer.lock deleted file mode 100644 index f714495d84..0000000000 --- a/tests/composer.lock +++ /dev/null @@ -1,66 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" - ], - "hash": "cf1d8a4841e5e669b148e0df6645a788", - "packages": [ - - ], - "packages-dev": [ - { - "name": "facebook/webdriver", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/facebook/php-webdriver.git", - "reference": "b6e002e5bf811a8edba393ce6872322c1b7cf796" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/b6e002e5bf811a8edba393ce6872322c1b7cf796", - "reference": "b6e002e5bf811a8edba393ce6872322c1b7cf796", - "shasum": "" - }, - "require": { - "php": ">=5.3.19" - }, - "require-dev": { - "phpdocumentor/phpdocumentor": "2.*", - "phpunit/phpunit": "3.7.*" - }, - "type": "library", - "autoload": { - "classmap": [ - "lib/" - ] - }, - "notification-url": "http://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "description": "A php client for WebDriver", - "homepage": "https://github.com/facebook/php-webdriver", - "keywords": [ - "facebook", - "php", - "selenium", - "webdriver" - ], - "time": "2014-08-05 02:55:46" - } - ], - "aliases": [ - - ], - "minimum-stability": "stable", - "stability-flags": { - "facebook/webdriver": 20 - }, - "platform": [ - - ], - "platform-dev": [ - - ] -} diff --git a/tests/test_framework/phpbb_ui_test_case.php b/tests/test_framework/phpbb_ui_test_case.php index e118801972..3c09ff96d1 100644 --- a/tests/test_framework/phpbb_ui_test_case.php +++ b/tests/test_framework/phpbb_ui_test_case.php @@ -11,6 +11,11 @@ * */ +use Facebook\WebDriver\WebDriverBy; +use Facebook\WebDriver\Exception\WebDriverCurlException; +use Facebook\WebDriver\Remote\RemoteWebDriver; +use Facebook\WebDriver\Remote\DesiredCapabilities; + require_once __DIR__ . '/mock/phpbb_mock_null_installer_task.php'; class phpbb_ui_test_case extends phpbb_test_case @@ -19,7 +24,7 @@ class phpbb_ui_test_case extends phpbb_test_case static protected $port = 8910; /** - * @var \RemoteWebDriver + * @var RemoteWebDriver */ static protected $webDriver; @@ -35,7 +40,7 @@ class phpbb_ui_test_case extends phpbb_test_case { self::markTestSkipped('UI test case requires at least PHP 5.3.19.'); } - else if (!class_exists('\RemoteWebDriver')) + else if (!class_exists('\Facebook\WebDriver\Remote\RemoteWebDriver')) { self::markTestSkipped( 'Could not find RemoteWebDriver class. ' . @@ -60,7 +65,7 @@ class phpbb_ui_test_case extends phpbb_test_case if (!self::$webDriver) { try { - $capabilities = array(\WebDriverCapabilityType::BROWSER_NAME => 'firefox'); + $capabilities = DesiredCapabilities::firefox(); self::$webDriver = RemoteWebDriver::create(self::$host . ':' . self::$port, $capabilities); } catch (WebDriverCurlException $e) { self::markTestSkipped('PhantomJS webserver is not running.'); From 469f2008217f1c345c6fb79de5ab68b3079a4954 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 14 Feb 2016 16:28:08 +0100 Subject: [PATCH 1087/1676] [ticket/14478] Remove no longer required shell script PHPBB3-14478 --- travis/install-phpbb-test-dependencies.sh | 16 ---------------- travis/setup-phpbb.sh | 1 - 2 files changed, 17 deletions(-) delete mode 100755 travis/install-phpbb-test-dependencies.sh diff --git a/travis/install-phpbb-test-dependencies.sh b/travis/install-phpbb-test-dependencies.sh deleted file mode 100755 index 25743ff2b1..0000000000 --- a/travis/install-phpbb-test-dependencies.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -# -# This file is part of the phpBB Forum Software package. -# -# @copyright (c) phpBB Limited -# @license GNU General Public License, version 2 (GPL-2.0) -# -# For full copyright and license information, please see -# the docs/CREDITS.txt file. -# -set -e -set -x - -cd tests -php ../composer.phar install --dev --no-interaction --prefer-source -cd .. diff --git a/travis/setup-phpbb.sh b/travis/setup-phpbb.sh index 30f79ee0cb..0beaa9ec8c 100755 --- a/travis/setup-phpbb.sh +++ b/travis/setup-phpbb.sh @@ -34,7 +34,6 @@ fi if [ "$NOTESTS" != '1' ] then travis/setup-webserver.sh - travis/install-phpbb-test-dependencies.sh fi cd phpBB From 6debd9a1bea4ee69a06eac43cc6b2f856f601604 Mon Sep 17 00:00:00 2001 From: Mate Bartus Date: Sun, 14 Feb 2016 19:27:24 +0100 Subject: [PATCH 1088/1676] [ticket/14462] Not show timeout messages in convertors PHPBB3-14462 --- phpBB/install/convert/controller/convertor.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/install/convert/controller/convertor.php b/phpBB/install/convert/controller/convertor.php index 9b52fdda32..a40f1d0b52 100644 --- a/phpBB/install/convert/controller/convertor.php +++ b/phpBB/install/convert/controller/convertor.php @@ -592,7 +592,7 @@ class convertor $url = $this->controller_helper->route('phpbb_convert_convert', array('converter' => $convertor)); $this->iohandler->redirect($url); - $this->iohandler->send_response(); + $this->iohandler->send_response(true); } else { @@ -686,7 +686,7 @@ class convertor if ($this->request->is_ajax()) { $this->iohandler->add_user_form_group($form_title, $form_data); - $this->iohandler->send_response(); + $this->iohandler->send_response(true); } else { @@ -779,7 +779,7 @@ class convertor if ($this->request->is_ajax()) { $this->iohandler->add_error_message($msg, $desc); - $this->iohandler->send_response(); + $this->iohandler->send_response(true); } else { @@ -803,7 +803,7 @@ class convertor public function redirect_to_html($url) { $this->iohandler->redirect($url); - $this->iohandler->send_response(); + $this->iohandler->send_response(true); } private function setup_navigation($stage) From 49736322887029b409ff177eafca9581c6622e83 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 5 Feb 2016 23:48:57 +0100 Subject: [PATCH 1089/1676] [ticket/14315] Only add role options specified for each group PHPBB3-14315 --- phpBB/adm/style/permission_mask.html | 2 ++ phpBB/includes/acp/auth.php | 1 + 2 files changed, 3 insertions(+) diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 347da3181e..75e76b157d 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -46,7 +46,9 @@ diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index 11478842d7..a3972158a2 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -477,6 +477,7 @@ class auth_admin extends \phpbb\auth\auth $template->assign_block_vars('role_options', array( 'ID' => $role_id, + 'UG_ID' => $ug_id, 'ROLE_NAME' => $role_name, 'TITLE' => $role_description, 'SELECTED' => $role_id == $current_role_id, From eab1b1ad11ae2e42cf4f6c3af9f7171d6dd0837b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 5 Feb 2016 23:59:19 +0100 Subject: [PATCH 1090/1676] [ticket/14315] Correctly set default values and reset values The permissions tooltip javascript failed at correctly passing the default values to the page. The same applied to the display_mask() method in includes/acp/auth.php. PHPBB3-14315 --- phpBB/adm/style/permission_mask.html | 2 +- phpBB/adm/style/tooltip.js | 32 ++++++++++++++-------------- phpBB/includes/acp/auth.php | 8 +++---- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 75e76b157d..aa18a40cb7 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -52,7 +52,7 @@ {% endfor %}
      - +
      {% else %} diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 68964034f0..3abeefbffe 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -141,20 +141,32 @@ phpbb.positionTooltip = function ($element) { */ phpbb.prepareRolesDropdown = function () { var $options = $('.roles-options li'); - var $rolesOptions = $options.closest('.roles-options'); - var $span = $rolesOptions.children('span'); // Prepare highlighting of select options and settings update $options.each(function () { var $this = $(this); + var $rolesOptions = $this.closest('.roles-options'); + var $span = $rolesOptions.children('span'); // Correctly show selected option if (typeof $this.attr('data-selected') !== 'undefined') { - $rolesOptions.closest('.roles-options') + $rolesOptions .children('span') .text($this.text()) .attr('data-default', $this.text()) .attr('data-default-val', $this.attr('data-id')); + + // Save default text of drop down if there is no default set yet + if (typeof $span.attr('data-default') === 'undefined') { + $span.attr('data-default', $span.text()); + } + + // Prepare resetting drop down on form reset + $this.closest('form').on('reset', function () { + $span.text($span.attr('data-default')); + $rolesOptions.children('input[type=hidden]') + .val($span.attr('data-default-val')); + }); } $this.on('mouseover', function () { @@ -163,6 +175,7 @@ phpbb.prepareRolesDropdown = function () { $this.addClass('roles-highlight'); }).on('click', function () { var $this = $(this); + var $rolesOptions = $this.closest('.roles-options'); // Update settings set_role_settings($this.attr('data-id'), $this.attr('data-target-id')); @@ -178,19 +191,6 @@ phpbb.prepareRolesDropdown = function () { $('body').trigger('click'); }); }); - - // Save default text of drop down if there is no default set yet - if (typeof $span.attr('data-default') === 'undefined') { - $span.attr('data-default', $span.text()); - } - - // Prepare resetting drop down on form reset - $options.closest('form').on('reset', function () { - $span.text($span.attr('data-default')); - $rolesOptions.children('input[type=hidden]') - .val($span.attr('data-id')); - }); - }; // Run onload functions for RolesDropdown and tooltips diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index a3972158a2..755923ff8c 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -466,9 +466,6 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; - // Output current role id to template - $template->assign_var('S_ROLE_ID', $current_role_id); - @reset($roles); while (list($role_id, $role_row) = each($roles)) { @@ -506,8 +503,9 @@ class auth_admin extends \phpbb\auth\auth 'NAME' => $ug_names_ary[$ug_id], 'UG_ID' => $ug_id, 'S_CUSTOM' => $s_custom_permissions, - 'FORUM_ID' => $forum_id) - ); + 'FORUM_ID' => $forum_id, + 'S_ROLE_ID' => $current_role_id, + )); $this->assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace); From 4cfba8f3a40c424d831b6034bdf1dc4975822406 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 6 Feb 2016 09:33:33 +0100 Subject: [PATCH 1091/1676] [ticket/14315] Build role options for each permission group Previously all role options were put into one array. This required filtering the options. Instead, these are now passed to the template via template loops. PHPBB3-14315 --- phpBB/adm/style/permission_mask.html | 6 ++---- phpBB/includes/acp/auth.php | 9 ++++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index aa18a40cb7..721fc42473 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -39,16 +39,14 @@
      - {% if role_options %} + {% if p_mask.f_mask.role_options %}
      -
      - - -
      diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index afa0bd5d31..d4df01dba7 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -2624,72 +2624,73 @@ fieldset.permissions .padding { } .send-stats-data-row { - background: #f9f9f9; - border-radius: 6px; - border: #DEDEDE 1px solid; - padding: 10px; - border-top-width: 0; - border-top-right-radius: 0; - border-top-left-radius: 0; + background: #f9f9f9; + border-radius: 6px; + border: #DEDEDE 1px solid; + padding: 10px; + border-top-width: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; } .send-stats-data-hidden .configlist { - display: none; + display: none; } .send-stats-data-only-row { - border-radius: 6px !important; - border-bottom-width: 1px !important; + border-radius: 6px !important; + border-bottom-width: 1px !important; } .send-stats-data-hidden { - padding: 0; - border: none; + padding: 0; + border: none; } .send-stats-row > .send-stats-data-row:first-child { - background-color: #d9edf7; - border-bottom-width: 0; - border-top-right-radius: 6px; - border-top-left-radius: 6px; - border-top-width: 1px; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; + background-color: #d9edf7; + border-bottom-width: 0; + border-top-right-radius: 6px; + border-top-left-radius: 6px; + border-top-width: 1px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } .send-stats-settings dt, .send-stats-settings dd { - min-width: 25px; + min-width: 25px; } .send-stats-settings dd { - line-height: 1.5em; + line-height: 1.5em; } .send-stats-settings input { - display: none; + display: none; } .send-stats-settings input[type=checkbox] + label:before { - content: "\f096"; - font-family: FontAwesome; - font-size: 1.5em; + content: "\f096"; + font-family: FontAwesome; + font-size: 1.5em; } .send-stats-settings input[type=checkbox]:checked + label:before { - content: "\f14a"; - color: #3c763d; + content: "\f14a"; + color: #3c763d; } .send-stats-data-row a:hover span { - text-decoration: underline; + text-decoration: underline; } .send-stats-data-row a { - text-decoration: none; + text-decoration: none; + cursor: default; } .send-stats-data-row i { - padding-left: 6px; + padding-left: 6px; } .configlist { diff --git a/phpBB/includes/acp/acp_send_statistics.php b/phpBB/includes/acp/acp_help_phpbb.php similarity index 96% rename from phpBB/includes/acp/acp_send_statistics.php rename to phpBB/includes/acp/acp_help_phpbb.php index 74da5996f1..cfe9619898 100644 --- a/phpBB/includes/acp/acp_send_statistics.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -19,7 +19,7 @@ if (!defined('IN_PHPBB')) exit; } -class acp_send_statistics +class acp_help_phpbb { var $u_action; @@ -34,7 +34,7 @@ class acp_send_statistics $collect_url = "https://www.phpbb.com/stats/receive_stats.php"; - $this->tpl_name = 'acp_send_statistics'; + $this->tpl_name = 'acp_help_phpbb'; $this->page_title = 'ACP_SEND_STATISTICS'; // generate a unique id if necessary diff --git a/phpBB/includes/acp/info/acp_send_statistics.php b/phpBB/includes/acp/info/acp_help_phpbb.php similarity index 68% rename from phpBB/includes/acp/info/acp_send_statistics.php rename to phpBB/includes/acp/info/acp_help_phpbb.php index a0db1a48c4..17a07ec4f6 100644 --- a/phpBB/includes/acp/info/acp_send_statistics.php +++ b/phpBB/includes/acp/info/acp_help_phpbb.php @@ -11,15 +11,15 @@ * */ -class acp_send_statistics_info +class acp_help_phpbb_info { function module() { return array( - 'filename' => 'acp_send_statistics', + 'filename' => 'acp_help_phpbb', 'title' => 'ACP_SEND_STATISTICS', 'modes' => array( - 'send_statistics' => array('title' => 'ACP_SEND_STATISTICS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'help_phpbb' => array('title' => 'ACP_SEND_STATISTICS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), ), ); } diff --git a/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php b/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php new file mode 100644 index 0000000000..4274f53520 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php @@ -0,0 +1,49 @@ + +* @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\v320; + +class add_help_phpbb extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v320\v320a2', + ); + } + + public function effectively_installed() + { + return isset($this->config['help_send_statistics']); + } + + public function update_data() + { + return array( + array('config.add', array('help_send_statistics', true)), + array('module.remove', array( + 'acp', + false, + 'ACP_SEND_STATISTICS', + )), + array('module.add', array( + 'acp', + 'ACP_SERVER_CONFIGURATION', + array( + 'module_basename' => 'acp_help_phpbb', + 'modes' => array('help_phpbb'), + ), + )), + ); + } +} From 9fb2a5d5f8ed4c23689843178a4a06a151d146e6 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 1 Feb 2016 00:01:26 +0100 Subject: [PATCH 1347/1676] [ticket/14492] Update language variables and trigger details text PHPBB3-14492 --- phpBB/adm/style/acp_help_phpbb.html | 6 +++--- phpBB/includes/acp/acp_help_phpbb.php | 2 +- phpBB/includes/acp/info/acp_help_phpbb.php | 4 ++-- phpBB/language/en/acp/common.php | 8 +++++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/phpBB/adm/style/acp_help_phpbb.html b/phpBB/adm/style/acp_help_phpbb.html index a984b25b25..347d39af86 100644 --- a/phpBB/adm/style/acp_help_phpbb.html +++ b/phpBB/adm/style/acp_help_phpbb.html @@ -2,7 +2,7 @@ -

      {L_SEND_STATISTICS}

      +

      {L_ACP_HELP_PHPBB}

      @@ -10,7 +10,7 @@

      {L_EXPLAIN_SEND_STATISTICS}

      @@ -33,7 +33,7 @@ -
      {L_SEND_STATISTICS}
      +
      {L_SEND_STATISTICS_LONG}
      diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index cfe9619898..2ac90eee48 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -35,7 +35,7 @@ class acp_help_phpbb $collect_url = "https://www.phpbb.com/stats/receive_stats.php"; $this->tpl_name = 'acp_help_phpbb'; - $this->page_title = 'ACP_SEND_STATISTICS'; + $this->page_title = 'ACP_HELP_PHPBB'; // generate a unique id if necessary if (!isset($config['questionnaire_unique_id'])) diff --git a/phpBB/includes/acp/info/acp_help_phpbb.php b/phpBB/includes/acp/info/acp_help_phpbb.php index 17a07ec4f6..dee8ef41d7 100644 --- a/phpBB/includes/acp/info/acp_help_phpbb.php +++ b/phpBB/includes/acp/info/acp_help_phpbb.php @@ -17,9 +17,9 @@ class acp_help_phpbb_info { return array( 'filename' => 'acp_help_phpbb', - 'title' => 'ACP_SEND_STATISTICS', + 'title' => 'ACP_HELP_PHPBB', 'modes' => array( - 'help_phpbb' => array('title' => 'ACP_SEND_STATISTICS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'help_phpbb' => array('title' => 'ACP_HELP_PHPBB', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), ), ); } diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 0acc18e373..a233547c7e 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -108,6 +108,8 @@ $lang = array_merge($lang, array( 'ACP_GROUPS_PERMISSIONS' => 'Group permissions', 'ACP_GROUPS_POSITION' => 'Manage group positions', + 'ACP_HELP_PHPBB' => 'Help support phpBB', + 'ACP_ICONS' => 'Topic icons', 'ACP_ICONS_SMILIES' => 'Topic icons/smilies', 'ACP_INACTIVE_USERS' => 'Inactive users', @@ -167,7 +169,6 @@ $lang = array_merge($lang, array( 'ACP_SEARCH_SETTINGS' => 'Search settings', 'ACP_SECURITY_SETTINGS' => 'Security settings', - 'ACP_SEND_STATISTICS' => 'Send statistical information', 'ACP_SERVER_CONFIGURATION' => 'Server configuration', 'ACP_SERVER_SETTINGS' => 'Server settings', 'ACP_SIGNATURE_SETTINGS' => 'Signature settings', @@ -474,14 +475,15 @@ $lang = array_merge($lang, array( 'USER_IS_INACTIVE' => 'User is inactive', )); -// Send statistics page +// Help support phpBB page $lang = array_merge($lang, array( 'EXPLAIN_SEND_STATISTICS' => 'Please send information about your server and board configurations to phpBB for statistical analysis. All information that could identify you or your website has been removed - the data is entirely anonymous. We base decisions about future phpBB versions on this information. The statistics are made available publically. We also share this data with the PHP project, the programming language phpBB is made with.', 'EXPLAIN_SHOW_STATISTICS' => 'Using the button below you can preview all variables that will be transmitted.', 'DONT_SEND_STATISTICS' => 'Return to the ACP if you do not wish to send statistical information to phpBB.', 'GO_ACP_MAIN' => 'Go to the ACP start page', 'HIDE_STATISTICS' => 'Hide details', - 'SEND_STATISTICS' => 'Send statistical information', + 'SEND_STATISTICS' => 'Send statistics', + 'SEND_STATISTICS_LONG' => 'Send statistical information', 'SHOW_STATISTICS' => 'Show details', 'THANKS_SEND_STATISTICS' => 'Thank you for submitting your information.', 'EXPLAIN_ENABLE_VIGLINK' => 'Viglink is a non-invasive third-party service that will monetize existing links posted by users of your forum. When visitors click on those existing links and perform certain actions, such as shopping, the merchants pay VigLink a commission, of which a share is donated to the phpBB project. By agreeing to enable VigLink and donating proceeds to the phpBB project, you are supporting our open source organization and ensuring our continued financial security.

      You can change these settings at any time in VigLink settings panel.', From cc7a0aa4fb2d6c8efd5c78df7d68328c9f8d4d32 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 1 Feb 2016 13:55:36 +0100 Subject: [PATCH 1348/1676] [ticket/14492] Use guzzle for submitting data to stats service PHPBB3-14492 --- phpBB/adm/style/acp_help_phpbb.html | 8 +++++ phpBB/includes/acp/acp_help_phpbb.php | 43 ++++++++++++++++++++++++++- phpBB/language/en/acp/common.php | 1 + 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/phpBB/adm/style/acp_help_phpbb.html b/phpBB/adm/style/acp_help_phpbb.html index 347d39af86..cbbe42e8c7 100644 --- a/phpBB/adm/style/acp_help_phpbb.html +++ b/phpBB/adm/style/acp_help_phpbb.html @@ -4,6 +4,7 @@

      {L_ACP_HELP_PHPBB}

      +

      Send statistics

      @@ -47,6 +48,13 @@
      Enable
      +
      +

      + +

      + {S_FORM_TOKEN} +
      +
      diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index 2ac90eee48..c981cf79df 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -25,7 +25,7 @@ class acp_help_phpbb function main($id, $mode) { - global $config, $template, $phpbb_admin_path, $phpbb_root_path, $phpEx; + global $config, $request, $template, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx; if (!class_exists('phpbb_questionnaire_data_collector')) { @@ -37,6 +37,22 @@ class acp_help_phpbb $this->tpl_name = 'acp_help_phpbb'; $this->page_title = 'ACP_HELP_PHPBB'; + $submit = ($request->is_set_post('submit')) ? true : false; + + $form_key = 'acp_help_phpbb'; + add_form_key($form_key); + $error = array(); + + if ($submit && !check_form_key($form_key)) + { + $error[] = $user->lang['FORM_INVALID']; + } + // Do not write values if there is an error + if (sizeof($error)) + { + $submit = false; + } + // generate a unique id if necessary if (!isset($config['questionnaire_unique_id'])) { @@ -55,6 +71,31 @@ class acp_help_phpbb $collector->add_data_provider(new phpbb_questionnaire_system_data_provider()); $collector->add_data_provider(new phpbb_questionnaire_phpbb_data_provider($config)); + if ($submit) + { + $client = new \Guzzle\Http\Client( + $this->u_action, + array( + 'timeout' => 6, + 'connect_timeout' => 6, + ) + ); + + $collect_request = $client->post($collect_url, [], [ + 'systemdata' => $collector->get_data_for_form(), + ]); + + $response = $collect_request->send(); + if ($response->isSuccessful()) + { + trigger_error($user->lang('THANKS_SEND_STATISTICS') . adm_back_link($this->u_action)); + } + else + { + trigger_error($user->lang('FAIL_SEND_STATISTICS') . adm_back_link($this->u_action)); + } + } + $template->assign_vars(array( 'U_COLLECT_STATS' => $collect_url, 'RAW_DATA' => $collector->get_data_for_form(), diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index a233547c7e..592021624b 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -486,6 +486,7 @@ $lang = array_merge($lang, array( 'SEND_STATISTICS_LONG' => 'Send statistical information', 'SHOW_STATISTICS' => 'Show details', 'THANKS_SEND_STATISTICS' => 'Thank you for submitting your information.', + 'FAIL_SEND_STATISTICS' => 'phpBB was unable to send statistics', 'EXPLAIN_ENABLE_VIGLINK' => 'Viglink is a non-invasive third-party service that will monetize existing links posted by users of your forum. When visitors click on those existing links and perform certain actions, such as shopping, the merchants pay VigLink a commission, of which a share is donated to the phpBB project. By agreeing to enable VigLink and donating proceeds to the phpBB project, you are supporting our open source organization and ensuring our continued financial security.

      You can change these settings at any time in VigLink settings panel.', )); From c07ecb060dd04c76d8bd166a0a8a7226a8167f06 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 2 Feb 2016 12:19:55 +0100 Subject: [PATCH 1349/1676] [ticket/14492] Add events for modifying help phpBB page PHPBB3-14492 --- phpBB/adm/style/acp_help_phpbb.html | 17 ++------- phpBB/adm/style/admin.css | 6 --- phpBB/docs/events.md | 12 ++++++ phpBB/includes/acp/acp_help_phpbb.php | 54 +++++++++++++++++---------- 4 files changed, 51 insertions(+), 38 deletions(-) diff --git a/phpBB/adm/style/acp_help_phpbb.html b/phpBB/adm/style/acp_help_phpbb.html index cbbe42e8c7..a9406e2c2e 100644 --- a/phpBB/adm/style/acp_help_phpbb.html +++ b/phpBB/adm/style/acp_help_phpbb.html @@ -6,6 +6,7 @@
      +

      Send statistics

      {L_EXPLAIN_SEND_STATISTICS}

      @@ -31,23 +32,13 @@
      - - + checked="checked" /> +
      {L_SEND_STATISTICS_LONG}
      -
      -

      VigLink

      -

      {L_EXPLAIN_ENABLE_VIGLINK}

      -
      -
      - - -
      -
      Enable
      -
      -
      +

      diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index d4df01dba7..bcf01fe597 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -2612,12 +2612,6 @@ fieldset.permissions .padding { padding-right: 0.3em; } -.viglink-header { - background: url('http://www.viglink.com/wp-content/uploads/2015/05/favicon-96x96.png') no-repeat 0 0; - padding-left: 30px; - background-size: 25px; -} - .icon { font-family: FontAwesome; font-style: normal; diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index a939c6ff7e..caaff7cb0e 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -196,6 +196,18 @@ acp_groups_position_teampage_add_button_before * Since: 3.1.7-RC1 * Purpose: Add content before adding group to teampage submit button +acp_help_phpbb_stats_after +=== +* Location: adm/style/acp_help_phpbb.html +* Since: 3.2.0-b2 +* Purpose: Add content after send statistics tile + +acp_help_phpbb_stats_before +=== +* Location: adm/style/acp_help_phpbb.html +* Since: 3.2.0-b2 +* Purpose: Add content before send statistics tile + acp_logs_quick_select_forum_button_append === * Location: adm/style/acp_logs.html diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index c981cf79df..9dd641dfd5 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -25,7 +25,7 @@ class acp_help_phpbb function main($id, $mode) { - global $config, $request, $template, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx; + global $config, $request, $template, $user, $phpbb_dispatcher, $phpbb_admin_path, $phpbb_root_path, $phpEx; if (!class_exists('phpbb_questionnaire_data_collector')) { @@ -71,33 +71,49 @@ class acp_help_phpbb $collector->add_data_provider(new phpbb_questionnaire_system_data_provider()); $collector->add_data_provider(new phpbb_questionnaire_phpbb_data_provider($config)); + /** + * Event to add and/or modify acp_board configurations + * + * @event core.acp_help_phpbb_submit_before + * @var boolean submit Do we display the form or process the submission + * @since 3.2.0-b2 + */ + $vars = array('submit'); + extract($phpbb_dispatcher->trigger_event('core.acp_help_phpbb_submit_before', compact($vars))); + if ($submit) { - $client = new \Guzzle\Http\Client( - $this->u_action, - array( - 'timeout' => 6, - 'connect_timeout' => 6, - ) - ); + $config->set('help_send_statistics', $request->variable('help_send_statistics', false)); - $collect_request = $client->post($collect_url, [], [ - 'systemdata' => $collector->get_data_for_form(), - ]); + if ($config['help_send_statistics']) + { + $client = new \Guzzle\Http\Client( + $this->u_action, + array( + 'timeout' => 6, + 'connect_timeout' => 6, + ) + ); - $response = $collect_request->send(); - if ($response->isSuccessful()) - { - trigger_error($user->lang('THANKS_SEND_STATISTICS') . adm_back_link($this->u_action)); - } - else - { - trigger_error($user->lang('FAIL_SEND_STATISTICS') . adm_back_link($this->u_action)); + $collect_request = $client->post($collect_url, [], [ + 'systemdata' => $collector->get_data_for_form(), + ]); + + $response = $collect_request->send(); + if ($response->isSuccessful()) + { + trigger_error($user->lang('THANKS_SEND_STATISTICS') . adm_back_link($this->u_action)); + } + else + { + trigger_error($user->lang('FAIL_SEND_STATISTICS') . adm_back_link($this->u_action)); + } } } $template->assign_vars(array( 'U_COLLECT_STATS' => $collect_url, + 'S_COLLECT_STATS' => (!empty($config['help_send_statistics'])) ? true : false, 'RAW_DATA' => $collector->get_data_for_form(), 'U_ACP_MAIN' => append_sid("{$phpbb_admin_path}index.$phpEx"), )); From 90a5e22eb51fa20c94d576ffc5cdb49fb31dab3a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 4 Feb 2016 09:45:32 +0100 Subject: [PATCH 1350/1676] [ticket/14492] Correctly check if extension was enabled during install Also fixed some incorrectly generated log messages and improved the regex. PHPBB3-14492 --- .../task/install_extensions.php | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index d5086e7b82..c9a35a309a 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -49,6 +49,12 @@ class install_extensions extends \phpbb\install\task_base /** @var \Symfony\Component\Finder\Finder */ protected $finder; + /** @var string Extension table */ + protected $extension_table; + + /** @var \phpbb\db\driver\driver_interface */ + protected $db; + /** * Constructor * @@ -61,11 +67,13 @@ class install_extensions extends \phpbb\install\task_base { $this->install_config = $install_config; $this->iohandler = $iohandler; + $this->extension_table = $container->get_parameter('tables.ext'); $this->log = $container->get('log'); $this->user = $container->get('user'); $this->extension_manager = $container->get('ext.manager'); $this->config = $container->get('config'); + $this->db = $container->get('dbal.conn'); $this->finder = new \Symfony\Component\Finder\Finder(); $this->finder->in($phpbb_root_path . 'ext/') ->ignoreUnreadableDirs() @@ -101,14 +109,14 @@ class install_extensions extends \phpbb\install\task_base foreach ($this->finder as $file) { /** @var \SplFileInfo $file */ - $ext_name = preg_replace('#(.+ext[\\/\\\])#', '', dirname($file->getRealPath())); + $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])([^\\/\\\]+)[\\/\\\]([^\\/\\\]+)#', '$2/$3', dirname($file->getRealPath())); if ($this->extension_manager->is_available($ext_name)) { $this->extension_manager->enable($ext_name); - $this->extension_manager->load_extensions(); + $extensions = $this->get_extensions(); - if (!$this->extension_manager->is_enabled($ext_name)) + if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active']) { // Create log $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); @@ -116,7 +124,7 @@ class install_extensions extends \phpbb\install\task_base } else { - $this->iohandler->add_log_message('CLI_EXTENSION_ENABLE_FAILURE', array($ext_name)); + $this->iohandler->add_log_message(array('CLI_EXTENSION_ENABLE_FAILURE', $ext_name)); } } } @@ -136,4 +144,30 @@ class install_extensions extends \phpbb\install\task_base { return 'TASK_INSTALL_EXTENSIONS'; } + + /** + * Get extensions from database + * + * @return array List of extensions + */ + private function get_extensions() + { + $sql = 'SELECT * + FROM ' . $this->extension_table; + + $result = $this->db->sql_query($sql); + $extensions_row = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + $extensions = array(); + + foreach ($extensions_row as $extension) + { + $extensions[$extension['ext_name']] = $extension; + } + + ksort($extensions); + + return $extensions; + } } From ade5183ba1f10e3ba1aea927204e25f3b218ceb2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 4 Feb 2016 11:20:59 +0100 Subject: [PATCH 1351/1676] [ticket/14492] Pass u_action to acp form and add stats config PHPBB3-14492 --- phpBB/includes/acp/acp_help_phpbb.php | 1 + phpBB/install/schemas/schema_data.sql | 1 + 2 files changed, 2 insertions(+) diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index 9dd641dfd5..bcbe61adb8 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -116,6 +116,7 @@ class acp_help_phpbb 'S_COLLECT_STATS' => (!empty($config['help_send_statistics'])) ? true : false, 'RAW_DATA' => $collector->get_data_for_form(), 'U_ACP_MAIN' => append_sid("{$phpbb_admin_path}index.$phpEx"), + 'U_ACTION' => $this->u_action, )); $raw = $collector->get_data_raw(); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 0cff26977e..450d2d2a52 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -142,6 +142,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_ INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_indexer_mem_limit', '512'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_stopwords', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('gzip_compress', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('help_send_statistics', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('hot_threshold', '25'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('icons_path', 'images/icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_create_thumbnail', '0'); From 4451db9f225d7a0e8a12503f0ff2f1393ee42467 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 4 Feb 2016 11:43:29 +0100 Subject: [PATCH 1352/1676] [ticket/14492] Apply fixes to update extensions task The regex was also simplified. PHPBB3-14492 --- .../task/install_extensions.php | 2 +- .../task/update_extensions.php | 40 +++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index c9a35a309a..d92f420202 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -109,7 +109,7 @@ class install_extensions extends \phpbb\install\task_base foreach ($this->finder as $file) { /** @var \SplFileInfo $file */ - $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])([^\\/\\\]+)[\\/\\\]([^\\/\\\]+)#', '$2/$3', dirname($file->getRealPath())); + $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); if ($this->extension_manager->is_available($ext_name)) { diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index c7437d4746..a6648084a6 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -59,6 +59,12 @@ class enable_extensions extends task_base /** @var Finder */ protected $finder; + /** @var string Extension table */ + protected $extension_table; + + /** @var \phpbb\db\driver\driver_interface */ + protected $db; + /** * Constructor * @@ -72,11 +78,13 @@ class enable_extensions extends task_base { $this->install_config = $install_config; $this->iohandler = $iohandler; + $this->extension_table = $container->get_parameter('tables.ext'); $this->log = $container->get('log'); $this->user = $container->get('user'); $this->extension_manager = $container->get('ext.manager'); $this->config = $container->get('config'); + $this->db = $container->get('dbal.conn'); $this->finder = new Finder(); $this->finder->in($phpbb_root_path . 'ext/') ->ignoreUnreadableDirs() @@ -111,7 +119,7 @@ class enable_extensions extends task_base foreach ($this->finder as $file) { /** @var \SplFileInfo $file */ - $ext_name = preg_replace('#(.+ext[\\/\\\])#', '', dirname($file->getRealPath())); + $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); // Skip extensions that were not added or updated during update if (!count(preg_grep('#ext/' . $ext_name . '#', $update_info['files']))) @@ -128,9 +136,9 @@ class enable_extensions extends task_base if ($this->extension_manager->is_available($ext_name)) { $this->extension_manager->enable($ext_name); - $this->extension_manager->load_extensions(); + $extensions = $this->get_extensions(); - if (!$this->extension_manager->is_enabled($ext_name)) + if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active']) { // Create log $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); @@ -159,4 +167,30 @@ class enable_extensions extends task_base { return 'TASK_UPDATE_EXTENSIONS'; } + + /** + * Get extensions from database + * + * @return array List of extensions + */ + private function get_extensions() + { + $sql = 'SELECT * + FROM ' . $this->extension_table; + + $result = $this->db->sql_query($sql); + $extensions_row = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + $extensions = array(); + + foreach ($extensions_row as $extension) + { + $extensions[$extension['ext_name']] = $extension; + } + + ksort($extensions); + + return $extensions; + } } From cba4f4f568028d2eb019ddde0eded62799e1b377 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 12 Feb 2016 12:28:21 +0100 Subject: [PATCH 1353/1676] [ticket/14492] Use new guzzlehttp client PHPBB3-14492 --- phpBB/includes/acp/acp_help_phpbb.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index bcbe61adb8..fa4de60456 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -87,20 +87,19 @@ class acp_help_phpbb if ($config['help_send_statistics']) { - $client = new \Guzzle\Http\Client( - $this->u_action, - array( + $client = new \GuzzleHttp\Client([ 'timeout' => 6, 'connect_timeout' => 6, - ) - ); - - $collect_request = $client->post($collect_url, [], [ - 'systemdata' => $collector->get_data_for_form(), ]); - $response = $collect_request->send(); - if ($response->isSuccessful()) + $response = $client->post($collect_url, [ + 'body' => [ + 'systemdata' => $collector->get_data_for_form(), + ] + ]); + $response_status = $response->getStatusCode(); + + if ($response_status >= 200 && $response_status < 300) { trigger_error($user->lang('THANKS_SEND_STATISTICS') . adm_back_link($this->u_action)); } From f9b46a4ae7d106cb765a762acf2e6a362e5b636d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 19 Feb 2016 21:28:52 +0100 Subject: [PATCH 1354/1676] [ticket/14492] Remove not needed language entry PHPBB3-14492 --- phpBB/language/en/acp/common.php | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 592021624b..5b747acd55 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -487,7 +487,6 @@ $lang = array_merge($lang, array( 'SHOW_STATISTICS' => 'Show details', 'THANKS_SEND_STATISTICS' => 'Thank you for submitting your information.', 'FAIL_SEND_STATISTICS' => 'phpBB was unable to send statistics', - 'EXPLAIN_ENABLE_VIGLINK' => 'Viglink is a non-invasive third-party service that will monetize existing links posted by users of your forum. When visitors click on those existing links and perform certain actions, such as shopping, the merchants pay VigLink a commission, of which a share is donated to the phpBB project. By agreeing to enable VigLink and donating proceeds to the phpBB project, you are supporting our open source organization and ensuring our continued financial security.

      You can change these settings at any time in VigLink settings panel.', )); // Log Entries From 80a63a9a94af042da37227ed747eba0feeac1049 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 20 Feb 2016 11:58:36 +0100 Subject: [PATCH 1355/1676] [ticket/14492] Add missing input name PHPBB3-14492 --- phpBB/adm/style/acp_help_phpbb.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/adm/style/acp_help_phpbb.html b/phpBB/adm/style/acp_help_phpbb.html index a9406e2c2e..d2f5e76916 100644 --- a/phpBB/adm/style/acp_help_phpbb.html +++ b/phpBB/adm/style/acp_help_phpbb.html @@ -32,7 +32,7 @@

      - checked="checked" /> + checked="checked" />
      {L_SEND_STATISTICS_LONG}
      From 89fef2ce13a183c7b963032274f455a09a05f325 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 21 Feb 2016 22:14:58 +0100 Subject: [PATCH 1356/1676] [ticket/14492] Send statistics via ajax request Flooding ajax requests will try to be prevented and sending stats without JS will also properly work. PHPBB3-14492 --- phpBB/adm/style/acp_help_phpbb.html | 16 ++- phpBB/adm/style/admin.js | 7 +- phpBB/adm/style/ajax.js | 99 +++++++++++++++++++ phpBB/includes/acp/acp_help_phpbb.php | 36 ++++--- .../db/migration/data/v320/add_help_phpbb.php | 1 + 5 files changed, 136 insertions(+), 23 deletions(-) diff --git a/phpBB/adm/style/acp_help_phpbb.html b/phpBB/adm/style/acp_help_phpbb.html index d2f5e76916..48a4595913 100644 --- a/phpBB/adm/style/acp_help_phpbb.html +++ b/phpBB/adm/style/acp_help_phpbb.html @@ -4,7 +4,7 @@

      {L_ACP_HELP_PHPBB}

      - +
      @@ -12,9 +12,9 @@

      {L_EXPLAIN_SEND_STATISTICS}

      -
      +
      @@ -41,11 +41,21 @@

      + +

      {S_FORM_TOKEN}
      +
      +
      +

      + + +

      +
      +
      diff --git a/phpBB/adm/style/admin.js b/phpBB/adm/style/admin.js index e42fdb380a..551c78a4a3 100644 --- a/phpBB/adm/style/admin.js +++ b/phpBB/adm/style/admin.js @@ -243,11 +243,16 @@ function parse_document(container) parse_document($('body')); - $('#trigger-configlist').on('click', function () { + $('#questionnaire-form').css('display', 'none'); + var $triggerConfiglist = $('#trigger-configlist'); + + $triggerConfiglist.on('click', function () { var $configlist = $('#configlist'); $configlist.closest('.send-stats-data-row').toggleClass('send-stats-data-hidden'); $configlist.closest('.send-stats-row').find('.send-stats-data-row:first-child').toggleClass('send-stats-data-only-row'); $(this).find('i').toggleClass('fa-angle-down fa-angle-up'); }); + + $('#configlist').closest('.send-stats-data-row').addClass('send-stats-data-hidden'); }); })(jQuery); diff --git a/phpBB/adm/style/ajax.js b/phpBB/adm/style/ajax.js index 3c1c57505b..1d4e00dfa4 100644 --- a/phpBB/adm/style/ajax.js +++ b/phpBB/adm/style/ajax.js @@ -4,6 +4,101 @@ 'use strict'; + +phpbb.prepareSendStats = function () { + var $form = $('#acp_help_phpbb'); + var $dark = $('#darkenwrapper'); + var $loadingIndicator; + + $form.on('submit', function () { + var $this = $(this), + currentTime = Math.floor(new Date().getTime() / 1000), + statsTime = parseInt($this.find('input[name=help_send_statistics_time]').val(), 10); + + event.preventDefault(); + $this.unbind('submit'); + + // Skip ajax request if form is submitted too early or send stats + // checkbox is not checked + if (!$this.find('input[name=help_send_statistics]').is(':checked') || + statsTime > currentTime) { + $form.find('input[type=submit]').click(); + setTimeout(function () { + $form.find('input[type=submit]').click(); + }, 300); + return; + } + + /** + * Handler for AJAX errors + */ + function errorHandler(jqXHR, textStatus, errorThrown) { + if (typeof console !== 'undefined' && console.log) { + console.log('AJAX error. status: ' + textStatus + ', message: ' + errorThrown); + } + phpbb.clearLoadingTimeout(); + var errorText = ''; + + if (typeof errorThrown === 'string' && errorThrown.length > 0) { + errorText = errorThrown; + } else { + errorText = $dark.attr('data-ajax-error-text-' + textStatus); + if (typeof errorText !== 'string' || !errorText.length) { + errorText = $dark.attr('data-ajax-error-text'); + } + } + phpbb.alert($dark.attr('data-ajax-error-title'), errorText); + } + + /** + * This is a private function used to handle the callbacks, refreshes + * and alert. It calls the callback, refreshes the page if necessary, and + * displays an alert to the user and removes it after an amount of time. + * + * It cannot be called from outside this function, and is purely here to + * avoid repetition of code. + * + * @param {object} res The object sent back by the server. + */ + function returnHandler(res) { + phpbb.clearLoadingTimeout(); + + // If a confirmation is not required, display an alert and call the + // callbacks. + $dark.fadeOut(phpbb.alertTime); + + if ($loadingIndicator) { + $loadingIndicator.fadeOut(phpbb.alertTime); + } + + var $sendStatisticsSuccess = $('', { + type: 'hidden', + name: 'send_statistics_response', + value: res + }); + $sendStatisticsSuccess.appendTo('p.submit-buttons'); + + // Finish actual form submission + $form.find('input[type=submit]').click(); + } + + $loadingIndicator = phpbb.loadingIndicator(); + + $.ajax({ + url: $this.attr('data-ajax-action').replace('&', '&'), + type: 'POST', + data: 'systemdata=' + $this.find('input[name=systemdata]').val(), + success: returnHandler, + error: errorHandler, + cache: false + }).always(function() { + if ($loadingIndicator && $loadingIndicator.is(':visible')) { + $loadingIndicator.fadeOut(phpbb.alertTime); + } + }); + }); +}; + /** * The following callbacks are for reording items. row_down * is triggered when an item is moved down, and row_up is triggered when @@ -225,6 +320,10 @@ $(function() { $(this).attr('data-clicked', true); }); } + + if ($('#acp_help_phpbb')) { + phpbb.prepareSendStats(); + } }); diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index fa4de60456..cc353376cd 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -84,23 +84,17 @@ class acp_help_phpbb if ($submit) { $config->set('help_send_statistics', $request->variable('help_send_statistics', false)); + $response = $request->variable('send_statistics_response', ''); - if ($config['help_send_statistics']) + if (!empty($response)) { - $client = new \GuzzleHttp\Client([ - 'timeout' => 6, - 'connect_timeout' => 6, - ]); - - $response = $client->post($collect_url, [ - 'body' => [ - 'systemdata' => $collector->get_data_for_form(), - ] - ]); - $response_status = $response->getStatusCode(); - - if ($response_status >= 200 && $response_status < 300) + if ((strpos($response, 'Thank you') !== false || strpos($response, 'Flood protection') !== false)) { + // Update time when statistics were actually sent + if (strpos($response, 'Thank you') !== false) + { + $config->set('help_send_statistics_time', time()); + } trigger_error($user->lang('THANKS_SEND_STATISTICS') . adm_back_link($this->u_action)); } else @@ -108,14 +102,18 @@ class acp_help_phpbb trigger_error($user->lang('FAIL_SEND_STATISTICS') . adm_back_link($this->u_action)); } } + + trigger_error($user->lang('CONFIG_UPDATED') . adm_back_link($this->u_action)); } $template->assign_vars(array( - 'U_COLLECT_STATS' => $collect_url, - 'S_COLLECT_STATS' => (!empty($config['help_send_statistics'])) ? true : false, - 'RAW_DATA' => $collector->get_data_for_form(), - 'U_ACP_MAIN' => append_sid("{$phpbb_admin_path}index.$phpEx"), - 'U_ACTION' => $this->u_action, + 'U_COLLECT_STATS' => $collect_url, + 'S_COLLECT_STATS' => (!empty($config['help_send_statistics'])) ? true : false, + 'RAW_DATA' => $collector->get_data_for_form(), + 'U_ACP_MAIN' => append_sid("{$phpbb_admin_path}index.$phpEx"), + 'U_ACTION' => $this->u_action, + // Pass earliest time we should try to send stats again + 'COLLECT_STATS_TIME' => intval($config['help_send_statistics_time']) + 86400, )); $raw = $collector->get_data_raw(); diff --git a/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php b/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php index 4274f53520..2634cee643 100644 --- a/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php +++ b/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php @@ -31,6 +31,7 @@ class add_help_phpbb extends \phpbb\db\migration\migration { return array( array('config.add', array('help_send_statistics', true)), + array('config.add', array('help_send_statistics_time', 0)), array('module.remove', array( 'acp', false, From eb1ade67681ee7c88845978eade07ad3ac96357a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 24 Feb 2016 13:49:20 +0100 Subject: [PATCH 1357/1676] [ticket/14492] Set install extensions to synthetic and fix step count PHPBB3-14492 --- .../module/install_finish/task/install_extensions.php | 7 +------ .../module/update_database/task/update_extensions.php | 2 +- tests/test_framework/phpbb_functional_test_case.php | 2 ++ 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index d92f420202..bc13795188 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -97,11 +97,6 @@ class install_extensions extends \phpbb\install\task_base */ public function run() { - if (defined('PHPBB_ENVIRONMENT') && PHPBB_ENVIRONMENT === 'test') - { - return; - } - $this->user->session_begin(); $this->user->setup(array('common', 'acp/common', 'cli')); @@ -134,7 +129,7 @@ class install_extensions extends \phpbb\install\task_base */ static public function get_step_count() { - return 0; + return 1; } /** diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index a6648084a6..a73fa9b854 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -157,7 +157,7 @@ class enable_extensions extends task_base */ static public function get_step_count() { - return 0; + return 1; } /** diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 20b89aba4e..2a37ca0e53 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -309,6 +309,8 @@ class phpbb_functional_test_case extends phpbb_test_case $container->register('installer.install_finish.notify_user')->setSynthetic(true); $container->set('installer.install_finish.notify_user', new phpbb_mock_null_installer_task()); + $container->register('installer.install_finish.install_extensions')->setSynthetic(true); + $container->set('installer.install_finish.install_extensions', new phpbb_mock_null_installer_task()); $container->compile(); $language = $container->get('language'); From 65d6e338a99baa2f100d6bd4dea5cd76ac146ac3 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 24 Feb 2016 15:05:01 +0100 Subject: [PATCH 1358/1676] [ticket/14492] Allow specifying extensions to update & install PHPBB3-14492 --- phpBB/language/en/install.php | 1 + .../console/command/install/install.php | 18 ++++++++++++++++++ .../install_finish/task/install_extensions.php | 9 +++++++++ .../update_database/task/update_extensions.php | 7 ++++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 45ed51f641..054bc0a182 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -330,6 +330,7 @@ $lang = array_merge($lang, array( $lang = array_merge($lang, array( 'CLI_INSTALL_BOARD' => 'Install phpBB', 'CLI_UPDATE_BOARD' => 'Update phpBB', + 'CLI_INSTALL_EXTENSIONS' => 'Extensions to install. Multiple extensions can be specified using a comma separated list.', 'CLI_INSTALL_SHOW_CONFIG' => 'Show the configuration which will be used', 'CLI_INSTALL_VALIDATE_CONFIG' => 'Validate a configuration file', 'CLI_CONFIG_FILE' => 'Config file to use', diff --git a/phpBB/phpbb/install/console/command/install/install.php b/phpBB/phpbb/install/console/command/install/install.php index de3a2e2d61..3378f5fdac 100644 --- a/phpBB/phpbb/install/console/command/install/install.php +++ b/phpBB/phpbb/install/console/command/install/install.php @@ -80,6 +80,10 @@ class install extends \phpbb\console\command\command 'config-file', InputArgument::REQUIRED, $this->language->lang('CLI_CONFIG_FILE')) + ->addArgument( + 'install-extensions', + InputArgument::OPTIONAL, + $this->language->lang('CLI_INSTALL_EXTENSIONS')) ->setDescription($this->language->lang('CLI_INSTALL_BOARD')) ; } @@ -147,6 +151,7 @@ class install extends \phpbb\console\command\command } $this->register_configuration($iohandler, $config); + $this->register_install_extensions($iohandler, $input); try { @@ -204,4 +209,17 @@ class install extends \phpbb\console\command\command $iohandler->set_input('script_path', $config['server']['script_path']); $iohandler->set_input('submit_server', 'submit'); } + + /** + * Register extensions to install during installation + * + * @param cli_iohandler $iohandler + * @param InputInterface $input + */ + private function register_install_extensions(cli_iohandler $iohandler, InputInterface $input) + { + $install_extensions = $input->getArgument('install-extensions'); + $install_extensions = !empty($install_extensions) ? explode(',', $install_extensions) : array(); + $iohandler->set_input('install-extensions', $install_extensions); + } } diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index bc13795188..c42d17fc18 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -13,6 +13,8 @@ namespace phpbb\install\module\install_finish\task; +use Symfony\Component\Console\Input\ArgvInput; + /** * Installs extensions that exist in ext folder upon install */ @@ -100,12 +102,19 @@ class install_extensions extends \phpbb\install\task_base $this->user->session_begin(); $this->user->setup(array('common', 'acp/common', 'cli')); + $install_extensions = $this->iohandler->get_input('install-extensions', array()); + // Find available extensions foreach ($this->finder as $file) { /** @var \SplFileInfo $file */ $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); + if (!empty($install_extensions) && !in_array($ext_name, $install_extensions)) + { + continue; + } + if ($this->extension_manager->is_available($ext_name)) { $this->extension_manager->enable($ext_name); diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index a73fa9b854..7a65ff1803 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -18,6 +18,7 @@ use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; use phpbb\install\helper\update_helper; use phpbb\install\task_base; +use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Finder\Finder; /** @@ -111,6 +112,9 @@ class enable_extensions extends task_base $this->user->session_begin(); $this->user->setup(array('common', 'acp/common', 'cli')); + $input = new ArgvInput(); + $update_extensions = explode(',', $input->getArgument('update-extensions')); + $update_info = $this->install_config->get('update_info_unprocessed', array()); if (!empty($update_info)) @@ -122,7 +126,8 @@ class enable_extensions extends task_base $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); // Skip extensions that were not added or updated during update - if (!count(preg_grep('#ext/' . $ext_name . '#', $update_info['files']))) + if (!count(preg_grep('#ext/' . $ext_name . '#', $update_info['files'])) && + !in_array($ext_name, $update_extensions) && $ext_name !== 'phpbb/viglink') { continue; } From 67c3bd4a90c29a2b5c1250d3353faf823be48fad Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 29 Feb 2016 11:29:33 +0100 Subject: [PATCH 1359/1676] [ticket/14492] Remove incorrect changes to module order PHPBB3-14492 --- phpBB/config/installer/container/services_install_finish.yml | 2 +- phpBB/config/installer/container/services_update_database.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/config/installer/container/services_install_finish.yml b/phpBB/config/installer/container/services_install_finish.yml index 7537d86727..6a46d8f9d9 100644 --- a/phpBB/config/installer/container/services_install_finish.yml +++ b/phpBB/config/installer/container/services_install_finish.yml @@ -41,4 +41,4 @@ services: arguments: - '@installer.module.install_finish_collection' tags: - - { name: installer_install_module, order: 80 } + - { name: installer_install_module, order: 60 } diff --git a/phpBB/config/installer/container/services_update_database.yml b/phpBB/config/installer/container/services_update_database.yml index aabfceca58..bb97cff489 100644 --- a/phpBB/config/installer/container/services_update_database.yml +++ b/phpBB/config/installer/container/services_update_database.yml @@ -37,4 +37,4 @@ services: - true - false tags: - - { name: installer_update_module, order: 60 } + - { name: installer_update_module, order: 40 } From e519b21b2e563f9d751aa8f9157ccc489b660ec8 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 29 Feb 2016 11:31:33 +0100 Subject: [PATCH 1360/1676] [ticket/14492] Only show fail of extension install if it's available PHPBB3-14492 --- .../module/install_finish/task/install_extensions.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index c42d17fc18..cef2abe0cb 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -125,10 +125,10 @@ class install_extensions extends \phpbb\install\task_base // Create log $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); } - } - else - { - $this->iohandler->add_log_message(array('CLI_EXTENSION_ENABLE_FAILURE', $ext_name)); + else + { + $this->iohandler->add_log_message(array('CLI_EXTENSION_ENABLE_FAILURE', $ext_name)); + } } } } From 69dece6197d6289199a713e7db57cc80574aae69 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 29 Feb 2016 15:04:55 +0100 Subject: [PATCH 1361/1676] [ticket/14492] Removed unused use statement PHPBB3-14492 --- .../install/module/install_finish/task/install_extensions.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index cef2abe0cb..9db922b7f4 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -13,8 +13,6 @@ namespace phpbb\install\module\install_finish\task; -use Symfony\Component\Console\Input\ArgvInput; - /** * Installs extensions that exist in ext folder upon install */ From ffe900c72d358ba0337c607f2ed76f893715f686 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Mar 2016 11:53:20 +0100 Subject: [PATCH 1362/1676] [ticket/14492] Define extensions to install in config not via cli argument PHPBB3-14492 --- phpBB/docs/install-config.sample.yml | 2 ++ phpBB/docs/update-config.sample.yml | 1 + phpBB/language/en/install.php | 1 - .../console/command/install/install.php | 19 ++----------------- .../install/console/command/update/update.php | 3 +++ .../phpbb/install/installer_configuration.php | 4 ++++ phpBB/phpbb/install/updater_configuration.php | 4 ++++ 7 files changed, 16 insertions(+), 18 deletions(-) diff --git a/phpBB/docs/install-config.sample.yml b/phpBB/docs/install-config.sample.yml index 47c0324599..a354e52e2f 100644 --- a/phpBB/docs/install-config.sample.yml +++ b/phpBB/docs/install-config.sample.yml @@ -34,3 +34,5 @@ installer: server_name: localhost server_port: 80 script_path: / + + extensions: ['phpbb/viglink'] diff --git a/phpBB/docs/update-config.sample.yml b/phpBB/docs/update-config.sample.yml index f3b52a8c01..caa1a9ef1e 100644 --- a/phpBB/docs/update-config.sample.yml +++ b/phpBB/docs/update-config.sample.yml @@ -1,2 +1,3 @@ updater: type: all + extensions: ['phpbb/viglink'] diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 054bc0a182..45ed51f641 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -330,7 +330,6 @@ $lang = array_merge($lang, array( $lang = array_merge($lang, array( 'CLI_INSTALL_BOARD' => 'Install phpBB', 'CLI_UPDATE_BOARD' => 'Update phpBB', - 'CLI_INSTALL_EXTENSIONS' => 'Extensions to install. Multiple extensions can be specified using a comma separated list.', 'CLI_INSTALL_SHOW_CONFIG' => 'Show the configuration which will be used', 'CLI_INSTALL_VALIDATE_CONFIG' => 'Validate a configuration file', 'CLI_CONFIG_FILE' => 'Config file to use', diff --git a/phpBB/phpbb/install/console/command/install/install.php b/phpBB/phpbb/install/console/command/install/install.php index 3378f5fdac..52a348fe44 100644 --- a/phpBB/phpbb/install/console/command/install/install.php +++ b/phpBB/phpbb/install/console/command/install/install.php @@ -80,10 +80,6 @@ class install extends \phpbb\console\command\command 'config-file', InputArgument::REQUIRED, $this->language->lang('CLI_CONFIG_FILE')) - ->addArgument( - 'install-extensions', - InputArgument::OPTIONAL, - $this->language->lang('CLI_INSTALL_EXTENSIONS')) ->setDescription($this->language->lang('CLI_INSTALL_BOARD')) ; } @@ -151,11 +147,11 @@ class install extends \phpbb\console\command\command } $this->register_configuration($iohandler, $config); - $this->register_install_extensions($iohandler, $input); try { $this->installer->run(); + return 0; } catch (installer_exception $e) { @@ -208,18 +204,7 @@ class install extends \phpbb\console\command\command $iohandler->set_input('server_port', $config['server']['server_port']); $iohandler->set_input('script_path', $config['server']['script_path']); $iohandler->set_input('submit_server', 'submit'); - } - /** - * Register extensions to install during installation - * - * @param cli_iohandler $iohandler - * @param InputInterface $input - */ - private function register_install_extensions(cli_iohandler $iohandler, InputInterface $input) - { - $install_extensions = $input->getArgument('install-extensions'); - $install_extensions = !empty($install_extensions) ? explode(',', $install_extensions) : array(); - $iohandler->set_input('install-extensions', $install_extensions); + $iohandler->set_input('install-extensions', $config['extensions']); } } diff --git a/phpBB/phpbb/install/console/command/update/update.php b/phpBB/phpbb/install/console/command/update/update.php index 116f42f758..e827761d1c 100644 --- a/phpBB/phpbb/install/console/command/update/update.php +++ b/phpBB/phpbb/install/console/command/update/update.php @@ -151,6 +151,7 @@ class update extends \phpbb\console\command\command try { $this->installer->run(); + return 0; } catch (installer_exception $e) { @@ -175,5 +176,7 @@ class update extends \phpbb\console\command\command $iohandler->set_input('submit_update_file', 'submit'); $iohandler->set_input('submit_continue_file_update', 'submit'); + + $iohandler->set_input('update-extensions', $config['extensions']); } } diff --git a/phpBB/phpbb/install/installer_configuration.php b/phpBB/phpbb/install/installer_configuration.php index c660c99d0f..805140338c 100644 --- a/phpBB/phpbb/install/installer_configuration.php +++ b/phpBB/phpbb/install/installer_configuration.php @@ -136,6 +136,10 @@ class installer_configuration implements ConfigurationInterface ->end() ->end() ->end() + ->arrayNode('extensions') + ->prototype('scalar')->end() + ->defaultValue([]) + ->end() ->end() ; return $treeBuilder; diff --git a/phpBB/phpbb/install/updater_configuration.php b/phpBB/phpbb/install/updater_configuration.php index e992356290..5c1c29f1da 100644 --- a/phpBB/phpbb/install/updater_configuration.php +++ b/phpBB/phpbb/install/updater_configuration.php @@ -32,6 +32,10 @@ class updater_configuration implements ConfigurationInterface ->addDefaultsIfNotSet() ->children() ->enumNode('type')->values(['all','db_only'])->defaultValue('all')->end() + ->arrayNode('extensions') + ->prototype('scalar')->end() + ->defaultValue([]) + ->end() ->end() ; From 930b02342e4f27f1c72fe0590f7153298331c3a6 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Mar 2016 13:02:44 +0100 Subject: [PATCH 1363/1676] [ticket/14492] Check if composer.json exists in viglink folder on file_check PHPBB3-14492 --- .../phpbb/install/module/update_filesystem/task/file_check.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php index e4e0be0531..8777b747de 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php @@ -142,7 +142,7 @@ class file_check extends task_base // with it but it does not exist (e.g. deleted by admin) if (strpos($file, $this->phpbb_root_path . 'ext/phpbb/viglink') !== false && $this->update_helper->phpbb_version_compare($update_info['version']['from'], '3.2.0', '>=') && - !$this->filesystem->exists($this->phpbb_root_path . 'ext/phpbb/viglink')) + !$this->filesystem->exists($this->phpbb_root_path . 'ext/phpbb/viglink/composer.json')) { continue; } From f604e1ab5d5d780ff4bed1e39fa83cc264a8af71 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Mar 2016 13:54:02 +0100 Subject: [PATCH 1364/1676] [ticket/14492] Rework logic for selecting which extensions to update PHPBB3-14492 --- .../task/update_extensions.php | 81 ++++++++++++------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index 7a65ff1803..f3a977a013 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -24,7 +24,7 @@ use Symfony\Component\Finder\Finder; /** * Installs extensions that exist in ext folder upon install */ -class enable_extensions extends task_base +class update_extensions extends task_base { /** * @var config @@ -66,6 +66,14 @@ class enable_extensions extends task_base /** @var \phpbb\db\driver\driver_interface */ protected $db; + /** + * @var array List of default extensions to update, grouped by version + * they were added + */ + private $default_update = [ + '3.2.0-b2' => ['phpbb/viglink'] + ]; + /** * Constructor * @@ -112,47 +120,66 @@ class enable_extensions extends task_base $this->user->session_begin(); $this->user->setup(array('common', 'acp/common', 'cli')); - $input = new ArgvInput(); - $update_extensions = explode(',', $input->getArgument('update-extensions')); + $update_info = $this->install_config->get('update_info_unprocessed', []); - $update_info = $this->install_config->get('update_info_unprocessed', array()); - - if (!empty($update_info)) + if (empty($update_info)) { - // Find available extensions - foreach ($this->finder as $file) + return; + } + + $update_extensions = $this->iohandler->get_input('update-extensions', []); + + // Create list of default extensions that need to be enabled in update + $default_update_extensions = []; + foreach ($this->default_update as $version => $extensions) + { + if ($this->update_helper->phpbb_version_compare($update_info['version']['from'], $version, '<')) { - /** @var \SplFileInfo $file */ - $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); + $default_update_extensions = array_merge($default_update_extensions, $extensions); + } + } - // Skip extensions that were not added or updated during update - if (!count(preg_grep('#ext/' . $ext_name . '#', $update_info['files'])) && - !in_array($ext_name, $update_extensions) && $ext_name !== 'phpbb/viglink') - { - continue; - } + // Find available extensions + foreach ($this->finder as $file) + { + /** @var \SplFileInfo $file */ + $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); - // Disable enabled extensions in order to run migrations if needed - if ($this->extension_manager->is_enabled($ext_name)) + // Update extensions if: + // 1) Extension is currently enabled + // 2) Extension was implicitly defined as needing an update + // 3) Extension was newly added as default phpBB extension in + // this update and should be enabled by default. + if ($this->extension_manager->is_available($ext_name) && + ( + $this->extension_manager->is_enabled($ext_name) || + in_array($ext_name, $update_extensions) || + in_array($ext_name, $default_update_extensions) + )) + { + $extension_enabled = $this->extension_manager->is_enabled($ext_name); + if ($extension_enabled) { $this->extension_manager->disable($ext_name); } + $this->extension_manager->enable($ext_name); + $extensions = $this->get_extensions(); - if ($this->extension_manager->is_available($ext_name)) + if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active']) { - $this->extension_manager->enable($ext_name); - $extensions = $this->get_extensions(); - - if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active']) - { - // Create log - $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); - } + // Create log + $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); } else { $this->iohandler->add_log_message('CLI_EXTENSION_ENABLE_FAILURE', array($ext_name)); } + + // Disable extensions if it was disabled by the admin before + if (!$extension_enabled && !in_array($ext_name, $default_update_extensions)) + { + $this->extension_manager->disable($ext_name); + } } } } From 64f0d74489515ad76d0caf6cfdf100ef92e16328 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Mar 2016 16:35:18 +0100 Subject: [PATCH 1365/1676] [ticket/14492] Properly retrieve version updating from PHPBB3-14492 --- .../module/update_database/task/update.php | 2 - .../task/update_extensions.php | 116 ++++++++++-------- 2 files changed, 64 insertions(+), 54 deletions(-) diff --git a/phpBB/phpbb/install/module/update_database/task/update.php b/phpBB/phpbb/install/module/update_database/task/update.php index 9d7ba2f919..fb9eb44e6a 100644 --- a/phpBB/phpbb/install/module/update_database/task/update.php +++ b/phpBB/phpbb/install/module/update_database/task/update.php @@ -211,8 +211,6 @@ class update extends task_base $this->iohandler->add_success_message('INLINE_UPDATE_SUCCESSFUL'); - $this->config->delete('version_update_from'); - $this->cache->purge(); $this->config->increment('assets_version', 1); diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index f3a977a013..cb5cd90952 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -26,6 +26,11 @@ use Symfony\Component\Finder\Finder; */ class update_extensions extends task_base { + /** + * @var \phpbb\cache\driver\driver_interface + */ + protected $cache; + /** * @var config */ @@ -92,8 +97,10 @@ class update_extensions extends task_base $this->log = $container->get('log'); $this->user = $container->get('user'); $this->extension_manager = $container->get('ext.manager'); + $this->cache = $container->get('cache.driver'); $this->config = $container->get('config'); $this->db = $container->get('dbal.conn'); + $this->update_helper = $update_helper; $this->finder = new Finder(); $this->finder->in($phpbb_root_path . 'ext/') ->ignoreUnreadableDirs() @@ -121,67 +128,72 @@ class update_extensions extends task_base $this->user->setup(array('common', 'acp/common', 'cli')); $update_info = $this->install_config->get('update_info_unprocessed', []); + $version_from = !empty($update_info) ? $update_info['version']['from'] : $this->config['version_update_from']; - if (empty($update_info)) + if (!empty($version_from)) { - return; - } + $update_extensions = $this->iohandler->get_input('update-extensions', []); - $update_extensions = $this->iohandler->get_input('update-extensions', []); - - // Create list of default extensions that need to be enabled in update - $default_update_extensions = []; - foreach ($this->default_update as $version => $extensions) - { - if ($this->update_helper->phpbb_version_compare($update_info['version']['from'], $version, '<')) + // Create list of default extensions that need to be enabled in update + $default_update_extensions = []; + foreach ($this->default_update as $version => $extensions) { - $default_update_extensions = array_merge($default_update_extensions, $extensions); + if ($this->update_helper->phpbb_version_compare($version_from, $version, '<')) + { + $default_update_extensions = array_merge($default_update_extensions, $extensions); + } + } + + // Find available extensions + foreach ($this->finder as $file) + { + /** @var \SplFileInfo $file */ + $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); + + // Update extensions if: + // 1) Extension is currently enabled + // 2) Extension was implicitly defined as needing an update + // 3) Extension was newly added as default phpBB extension in + // this update and should be enabled by default. + if ($this->extension_manager->is_available($ext_name) && + ( + $this->extension_manager->is_enabled($ext_name) || + in_array($ext_name, $update_extensions) || + in_array($ext_name, $default_update_extensions) + ) + ) + { + $extension_enabled = $this->extension_manager->is_enabled($ext_name); + if ($extension_enabled) + { + $this->extension_manager->disable($ext_name); + } + $this->extension_manager->enable($ext_name); + $extensions = $this->get_extensions(); + + if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active']) + { + // Create log + $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); + } else + { + $this->iohandler->add_log_message('CLI_EXTENSION_ENABLE_FAILURE', array($ext_name)); + } + + // Disable extensions if it was disabled by the admin before + if (!$extension_enabled && !in_array($ext_name, $default_update_extensions)) + { + $this->extension_manager->disable($ext_name); + } + } } } - // Find available extensions - foreach ($this->finder as $file) - { - /** @var \SplFileInfo $file */ - $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); + $this->config->delete('version_update_from'); - // Update extensions if: - // 1) Extension is currently enabled - // 2) Extension was implicitly defined as needing an update - // 3) Extension was newly added as default phpBB extension in - // this update and should be enabled by default. - if ($this->extension_manager->is_available($ext_name) && - ( - $this->extension_manager->is_enabled($ext_name) || - in_array($ext_name, $update_extensions) || - in_array($ext_name, $default_update_extensions) - )) - { - $extension_enabled = $this->extension_manager->is_enabled($ext_name); - if ($extension_enabled) - { - $this->extension_manager->disable($ext_name); - } - $this->extension_manager->enable($ext_name); - $extensions = $this->get_extensions(); + $this->cache->purge(); - if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active']) - { - // Create log - $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); - } - else - { - $this->iohandler->add_log_message('CLI_EXTENSION_ENABLE_FAILURE', array($ext_name)); - } - - // Disable extensions if it was disabled by the admin before - if (!$extension_enabled && !in_array($ext_name, $default_update_extensions)) - { - $this->extension_manager->disable($ext_name); - } - } - } + $this->config->increment('assets_version', 1); } /** From d62d35ad46baf9a7563a9f58038b16272cdf7c2d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Mar 2016 21:56:22 +0100 Subject: [PATCH 1366/1676] [ticket/14492] Redirect to help phpBB page after installation PHPBB3-14492 --- phpBB/phpbb/install/installer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index 240423ae78..b8eef34a1d 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -244,7 +244,7 @@ class installer else { global $SID; - $acp_url = $this->web_root . 'adm/index.php' . $SID; + $acp_url = $this->web_root . 'adm/index.php' . $SID . '&i=acp_help_phpbb&mode=help_phpbb'; $this->iohandler->add_success_message('INSTALLER_FINISHED', array( 'ACP_LINK', $acp_url, From fd37919ecb8e6e6618145aafae9de864fe16ded8 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Mar 2016 22:00:08 +0100 Subject: [PATCH 1367/1676] [ticket/14492] Remove unused use statement PHPBB3-14492 --- .../install/module/update_database/task/update_extensions.php | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index cb5cd90952..0a339f11e8 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -18,7 +18,6 @@ use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; use phpbb\install\helper\update_helper; use phpbb\install\task_base; -use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Finder\Finder; /** From 88f197e67aab9e40e4688d6da7096dac59934101 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 3 Mar 2016 12:33:20 +0100 Subject: [PATCH 1368/1676] [ticket/14492] Checkout viglink for each version depending on tags PHPBB3-14492 --- build/build.xml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/build/build.xml b/build/build.xml index 0fdf6c0cb0..ab7085eda6 100644 --- a/build/build.xml +++ b/build/build.xml @@ -289,16 +289,31 @@ + - + + + + - + + + + + + + + + From e308093d7507258855c14dcfb7214e81beac187e Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 3 Mar 2016 22:26:29 +0100 Subject: [PATCH 1369/1676] [ticket/14492] Use extension manager instead of finder and add try/catch PHPBB3-14492 --- .../task/install_extensions.php | 17 ++++-- .../task/update_extensions.php | 61 ++++++++++--------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index 9db922b7f4..eb44bb780b 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -102,18 +102,17 @@ class install_extensions extends \phpbb\install\task_base $install_extensions = $this->iohandler->get_input('install-extensions', array()); - // Find available extensions - foreach ($this->finder as $file) - { - /** @var \SplFileInfo $file */ - $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); + $available_extensions = $this->extension_manager->all_available(); + // Install extensions + foreach ($available_extensions as $ext_name => $ext_path) + { if (!empty($install_extensions) && !in_array($ext_name, $install_extensions)) { continue; } - if ($this->extension_manager->is_available($ext_name)) + try { $this->extension_manager->enable($ext_name); $extensions = $this->get_extensions(); @@ -122,12 +121,18 @@ class install_extensions extends \phpbb\install\task_base { // Create log $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); + $this->iohandler->add_success_message(array('CLI_EXTENSION_ENABLE_SUCCESS', $ext_name)); } else { $this->iohandler->add_log_message(array('CLI_EXTENSION_ENABLE_FAILURE', $ext_name)); } } + catch (\Exception $e) + { + // Add fail log and continue + $this->iohandler->add_log_message(array('CLI_EXTENSION_ENABLE_FAILURE', $ext_name)); + } } } diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index 0a339f11e8..e8b73db25a 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -143,47 +143,52 @@ class update_extensions extends task_base } } - // Find available extensions - foreach ($this->finder as $file) - { - /** @var \SplFileInfo $file */ - $ext_name = preg_replace('#(.+[\\/\\\]ext[\\/\\\])(\w+)[\\/\\\](\w+)#', '$2/$3', dirname($file->getRealPath())); + $available_extensions = $this->extension_manager->all_available(); + // Update available extensions + foreach ($available_extensions as $ext_name => $ext_path) + { // Update extensions if: // 1) Extension is currently enabled // 2) Extension was implicitly defined as needing an update // 3) Extension was newly added as default phpBB extension in // this update and should be enabled by default. - if ($this->extension_manager->is_available($ext_name) && - ( - $this->extension_manager->is_enabled($ext_name) || - in_array($ext_name, $update_extensions) || - in_array($ext_name, $default_update_extensions) - ) + if ($this->extension_manager->is_enabled($ext_name) || + in_array($ext_name, $update_extensions) || + in_array($ext_name, $default_update_extensions) ) { - $extension_enabled = $this->extension_manager->is_enabled($ext_name); - if ($extension_enabled) + try { - $this->extension_manager->disable($ext_name); - } - $this->extension_manager->enable($ext_name); - $extensions = $this->get_extensions(); + $extension_enabled = $this->extension_manager->is_enabled($ext_name); + if ($extension_enabled) + { + $this->extension_manager->disable($ext_name); + } + $this->extension_manager->enable($ext_name); + $extensions = $this->get_extensions(); - if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active']) - { - // Create log - $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); - } else + if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active']) + { + // Create log + $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); + $this->iohandler->add_success_message(array('CLI_EXTENSION_ENABLE_SUCCESS', $ext_name)); + } else + { + $this->iohandler->add_log_message('CLI_EXTENSION_ENABLE_FAILURE', array($ext_name)); + } + + // Disable extensions if it was disabled by the admin before + if (!$extension_enabled && !in_array($ext_name, $default_update_extensions)) + { + $this->extension_manager->disable($ext_name); + } + } + catch (\Exception $e) { + // Add fail log and continue $this->iohandler->add_log_message('CLI_EXTENSION_ENABLE_FAILURE', array($ext_name)); } - - // Disable extensions if it was disabled by the admin before - if (!$extension_enabled && !in_array($ext_name, $default_update_extensions)) - { - $this->extension_manager->disable($ext_name); - } } } } From 2fa23c9b3f55e024f6a35c268cd7878e68ad08c2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 3 Mar 2016 22:28:51 +0100 Subject: [PATCH 1370/1676] [ticket/14492] Unify version check for installing default extensions PHPBB3-14492 --- .../install/module/update_database/task/update_extensions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index e8b73db25a..6d0016ddb3 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -75,7 +75,7 @@ class update_extensions extends task_base * they were added */ private $default_update = [ - '3.2.0-b2' => ['phpbb/viglink'] + '3.2.0-b3' => ['phpbb/viglink'] ]; /** @@ -137,7 +137,7 @@ class update_extensions extends task_base $default_update_extensions = []; foreach ($this->default_update as $version => $extensions) { - if ($this->update_helper->phpbb_version_compare($version_from, $version, '<')) + if ($this->update_helper->phpbb_version_compare($version_from, $version, '<=')) { $default_update_extensions = array_merge($default_update_extensions, $extensions); } From 4f0627de035e7539a78e05139cfb9a5e8d59163a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 3 Mar 2016 23:54:35 +0100 Subject: [PATCH 1371/1676] [ticket/14492] Add missing config to schema_data.sql PHPBB3-14492 --- phpBB/install/schemas/schema_data.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 450d2d2a52..56a4efa230 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -143,6 +143,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_in INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_stopwords', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('gzip_compress', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('help_send_statistics', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('help_send_statistics_time', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('hot_threshold', '25'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('icons_path', 'images/icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_create_thumbnail', '0'); From edfc4f3efc742342a37a5d510909aece6ae4c95d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 4 Mar 2016 00:24:04 +0100 Subject: [PATCH 1372/1676] [ticket/14492] Use same list for checking if extension should be updated PHPBB3-14492 --- .../task/update_extensions.php | 4 +-- .../update_filesystem/task/file_check.php | 35 +++++++++++++++---- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index 6d0016ddb3..64215e2f30 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -74,7 +74,7 @@ class update_extensions extends task_base * @var array List of default extensions to update, grouped by version * they were added */ - private $default_update = [ + static public $default_extensions_update = [ '3.2.0-b3' => ['phpbb/viglink'] ]; @@ -135,7 +135,7 @@ class update_extensions extends task_base // Create list of default extensions that need to be enabled in update $default_update_extensions = []; - foreach ($this->default_update as $version => $extensions) + foreach (self::$default_extensions_update as $version => $extensions) { if ($this->update_helper->phpbb_version_compare($version_from, $version, '<=')) { diff --git a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php index 8777b747de..5b48350e73 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php @@ -118,6 +118,17 @@ class file_check extends task_base $this->iohandler->set_task_count($task_count); $this->iohandler->set_progress('UPDATE_CHECK_FILES', 0); + // Create list of default extensions that should have been added prior + // to this update + $default_update_extensions = []; + foreach (\phpbb\install\module\update_database\task\update_extensions::$default_extensions_update as $version => $extensions) + { + if ($this->update_helper->phpbb_version_compare($update_info['version']['from'], $version, '>')) + { + $default_update_extensions = array_merge($default_update_extensions, $extensions); + } + } + foreach ($update_info['files'] as $key => $filename) { $old_file = $old_path . $filename; @@ -138,13 +149,25 @@ class file_check extends task_base $progress_count++; $this->iohandler->set_progress('UPDATE_CHECK_FILES', $progress_count); - // Do not copy viglink again if the previous version was packaged - // with it but it does not exist (e.g. deleted by admin) - if (strpos($file, $this->phpbb_root_path . 'ext/phpbb/viglink') !== false && - $this->update_helper->phpbb_version_compare($update_info['version']['from'], '3.2.0', '>=') && - !$this->filesystem->exists($this->phpbb_root_path . 'ext/phpbb/viglink/composer.json')) + // Do not copy default extension again if the previous version was + // packaged with it but it does not exist (e.g. deleted by admin) + if (strpos($file, $this->phpbb_root_path . 'ext/') !== false) { - continue; + $skip_file = false; + foreach ($default_update_extensions as $ext_name) + { + if (strpos($file, $this->phpbb_root_path . 'ext/' . $ext_name) !== false && + !$this->filesystem->exists($this->phpbb_root_path . 'ext/' . $ext_name . '/composer.json')) + { + $skip_file = true; + break; + } + } + + if ($skip_file) + { + continue; + } } if (!$this->filesystem->exists($file)) From b1596fda7f88bc0e2817a1143be6ff94ef3aae2a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 4 Mar 2016 17:27:27 +0100 Subject: [PATCH 1373/1676] [ticket/14492] Prevent timeouts in install & update extensions tasks PHPBB3-14492 --- .../task/install_extensions.php | 21 ++++++++++++++++++- .../task/update_extensions.php | 20 +++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index eb44bb780b..b8a04685f6 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -13,6 +13,8 @@ namespace phpbb\install\module\install_finish\task; +use phpbb\install\exception\resource_limit_reached_exception; + /** * Installs extensions that exist in ext folder upon install */ @@ -102,7 +104,9 @@ class install_extensions extends \phpbb\install\task_base $install_extensions = $this->iohandler->get_input('install-extensions', array()); - $available_extensions = $this->extension_manager->all_available(); + $all_available_extensions = $this->extension_manager->all_available(); + $i = $this->install_config->get('install_extensions_index', 0); + $available_extensions = array_slice($all_available_extensions, $i); // Install extensions foreach ($available_extensions as $ext_name => $ext_path) @@ -133,6 +137,21 @@ class install_extensions extends \phpbb\install\task_base // Add fail log and continue $this->iohandler->add_log_message(array('CLI_EXTENSION_ENABLE_FAILURE', $ext_name)); } + + $i++; + + // Stop execution if resource limit is reached + if ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0) + { + break; + } + } + + $this->install_config->set('install_extensions_index', $i); + + if ($i < sizeof($all_available_extensions)) + { + throw new resource_limit_reached_exception(); } } diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index 64215e2f30..24b72f7b42 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -13,6 +13,7 @@ namespace phpbb\install\module\update_database\task; +use phpbb\install\exception\resource_limit_reached_exception; use phpbb\install\helper\container_factory; use phpbb\install\helper\config; use phpbb\install\helper\iohandler\iohandler_interface; @@ -143,7 +144,9 @@ class update_extensions extends task_base } } - $available_extensions = $this->extension_manager->all_available(); + $all_available_extensions = $this->extension_manager->all_available(); + $i = $this->install_config->get('update_extensions_index', 0); + $available_extensions = array_slice($all_available_extensions, $i); // Update available extensions foreach ($available_extensions as $ext_name => $ext_path) @@ -190,6 +193,21 @@ class update_extensions extends task_base $this->iohandler->add_log_message('CLI_EXTENSION_ENABLE_FAILURE', array($ext_name)); } } + + $i++; + + // Stop execution if resource limit is reached + if ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0) + { + break; + } + } + + $this->install_config->set('update_extensions_index', $i); + + if ($i < sizeof($all_available_extensions)) + { + throw new resource_limit_reached_exception(); } } From dee5e6e07636db7e35a82919a723907e734fbcd1 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 4 Mar 2016 17:32:25 +0100 Subject: [PATCH 1374/1676] [ticket/14492] Add language variables for updating extensions PHPBB3-14492 --- phpBB/language/en/acp/common.php | 1 + phpBB/language/en/cli.php | 2 ++ .../module/update_database/task/update_extensions.php | 8 ++++---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 5b747acd55..053671e1a2 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -819,4 +819,5 @@ $lang = array_merge($lang, array( 'LOG_EXT_ENABLE' => 'Extension enabled
      » %s', 'LOG_EXT_DISABLE' => 'Extension disabled
      » %s', 'LOG_EXT_PURGE' => 'Extension’s data deleted
      » %s', + 'LOG_EXT_UPDATE' => 'Extension updated
      » %s', )); diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index db4b5f9ec6..09f46a5cee 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -104,6 +104,8 @@ $lang = array_merge($lang, array( 'CLI_EXTENSION_NAME' => 'Name of the extension', 'CLI_EXTENSION_PURGE_FAILURE' => 'Could not purge extension %s', 'CLI_EXTENSION_PURGE_SUCCESS' => 'Successfully purged extension %s', + 'CLI_EXTENSION_UPDATE_FAILURE' => 'Could not update extension %s', + 'CLI_EXTENSION_UPDATE_SUCCESS' => 'Successfully updated extension %s', 'CLI_EXTENSION_NOT_FOUND' => 'No extensions were found.', 'CLI_EXTENSIONS_AVAILABLE' => 'Available', 'CLI_EXTENSIONS_DISABLED' => 'Disabled', diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index 24b72f7b42..76904f80f1 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -174,11 +174,11 @@ class update_extensions extends task_base if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active']) { // Create log - $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($ext_name)); - $this->iohandler->add_success_message(array('CLI_EXTENSION_ENABLE_SUCCESS', $ext_name)); + $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_UPDATE', time(), array($ext_name)); + $this->iohandler->add_success_message(array('CLI_EXTENSION_UPDATE_SUCCESS', $ext_name)); } else { - $this->iohandler->add_log_message('CLI_EXTENSION_ENABLE_FAILURE', array($ext_name)); + $this->iohandler->add_log_message('CLI_EXTENSION_UPDATE_FAILURE', array($ext_name)); } // Disable extensions if it was disabled by the admin before @@ -190,7 +190,7 @@ class update_extensions extends task_base catch (\Exception $e) { // Add fail log and continue - $this->iohandler->add_log_message('CLI_EXTENSION_ENABLE_FAILURE', array($ext_name)); + $this->iohandler->add_log_message('CLI_EXTENSION_UPDATE_FAILURE', array($ext_name)); } } From 9f3b151dabd9cfeefd40c89c79c9e57ca5354bae Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 4 Mar 2016 22:29:28 +0100 Subject: [PATCH 1375/1676] [ticket/14492] Checkout master if viglink tag does not exist for latest version PHPBB3-14492 --- build/build.xml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/build/build.xml b/build/build.xml index ab7085eda6..69ecaa896c 100644 --- a/build/build.xml +++ b/build/build.xml @@ -142,6 +142,7 @@ + @@ -308,7 +309,18 @@ - + + + + + + + + + + From 1f270972084cd228e135481b766ada9941582155 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 6 Mar 2016 14:59:34 +0100 Subject: [PATCH 1376/1676] [ticket/14492] Install all extensions if 'all' is specified for extensions PHPBB3-14492 --- .../install/module/install_finish/task/install_extensions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index b8a04685f6..553a30ea28 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -111,7 +111,7 @@ class install_extensions extends \phpbb\install\task_base // Install extensions foreach ($available_extensions as $ext_name => $ext_path) { - if (!empty($install_extensions) && !in_array($ext_name, $install_extensions)) + if (!empty($install_extensions) && $install_extensions !== ['all'] && !in_array($ext_name, $install_extensions)) { continue; } From b9c284d85be82e2a8f50c20e147d1ca2352453d4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 22 Aug 2016 20:59:57 +0200 Subject: [PATCH 1377/1676] [ticket/14492] Update phpBB version and fix miscellaneous code issues PHPBB3-14492 --- build/build.xml | 2 +- phpBB/includes/acp/acp_help_phpbb.php | 2 +- .../install/module/update_database/task/update_extensions.php | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build/build.xml b/build/build.xml index 69ecaa896c..4fe6e0e908 100644 --- a/build/build.xml +++ b/build/build.xml @@ -291,7 +291,7 @@ diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index cc353376cd..89f2f3d160 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -72,7 +72,7 @@ class acp_help_phpbb $collector->add_data_provider(new phpbb_questionnaire_phpbb_data_provider($config)); /** - * Event to add and/or modify acp_board configurations + * Event to modify ACP help phpBB page and/or listen to submit * * @event core.acp_help_phpbb_submit_before * @var boolean submit Do we display the form or process the submission diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index 76904f80f1..01b88344e8 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -176,7 +176,8 @@ class update_extensions extends task_base // Create log $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_UPDATE', time(), array($ext_name)); $this->iohandler->add_success_message(array('CLI_EXTENSION_UPDATE_SUCCESS', $ext_name)); - } else + } + else { $this->iohandler->add_log_message('CLI_EXTENSION_UPDATE_FAILURE', array($ext_name)); } From e02aca839921792d9074177ddbb2bde4dae35b3f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 31 Aug 2016 21:33:56 +0200 Subject: [PATCH 1378/1676] [ticket/14492] Don't explicitly pass data providers by refs PHPBB3-14492 --- phpBB/includes/questionnaire/questionnaire.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php index 6350f4bc5a..9699843db4 100644 --- a/phpBB/includes/questionnaire/questionnaire.php +++ b/phpBB/includes/questionnaire/questionnaire.php @@ -46,9 +46,9 @@ class phpbb_questionnaire_data_collector $this->providers = array(); } - function add_data_provider(&$provider) + function add_data_provider($provider) { - $this->providers[] = &$provider; + $this->providers[] = $provider; } /** @@ -80,7 +80,7 @@ class phpbb_questionnaire_data_collector { foreach (array_keys($this->providers) as $key) { - $provider = &$this->providers[$key]; + $provider = $this->providers[$key]; $this->data[$provider->get_identifier()] = $provider->get_data(); } $this->data['install_id'] = $this->install_id; From afe16a62724451cb5c7eca7864a3c110404f4e2a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 3 Sep 2016 10:47:20 +0200 Subject: [PATCH 1379/1676] [ticket/14492] Add missing event variable PHPBB3-14492 --- phpBB/adm/style/ajax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/adm/style/ajax.js b/phpBB/adm/style/ajax.js index 1d4e00dfa4..28f761bc0b 100644 --- a/phpBB/adm/style/ajax.js +++ b/phpBB/adm/style/ajax.js @@ -10,7 +10,7 @@ phpbb.prepareSendStats = function () { var $dark = $('#darkenwrapper'); var $loadingIndicator; - $form.on('submit', function () { + $form.on('submit', function (event) { var $this = $(this), currentTime = Math.floor(new Date().getTime() / 1000), statsTime = parseInt($this.find('input[name=help_send_statistics_time]').val(), 10); From c54838b25f50dca71a2f516175621a7ccd39a071 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 9 Sep 2016 22:59:58 +0200 Subject: [PATCH 1380/1676] [ticket/14492] Update versions in files PHPBB3-14492 --- phpBB/docs/events.md | 4 ++-- phpBB/includes/acp/acp_help_phpbb.php | 2 +- phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php | 2 +- .../install/module/update_database/task/update_extensions.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index caaff7cb0e..619ba06c5f 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -199,13 +199,13 @@ acp_groups_position_teampage_add_button_before acp_help_phpbb_stats_after === * Location: adm/style/acp_help_phpbb.html -* Since: 3.2.0-b2 +* Since: 3.2.0-RC2 * Purpose: Add content after send statistics tile acp_help_phpbb_stats_before === * Location: adm/style/acp_help_phpbb.html -* Since: 3.2.0-b2 +* Since: 3.2.0-RC2 * Purpose: Add content before send statistics tile acp_logs_quick_select_forum_button_append diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index 89f2f3d160..ba17ae3fb4 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -76,7 +76,7 @@ class acp_help_phpbb * * @event core.acp_help_phpbb_submit_before * @var boolean submit Do we display the form or process the submission - * @since 3.2.0-b2 + * @since 3.2.0-RC2 */ $vars = array('submit'); extract($phpbb_dispatcher->trigger_event('core.acp_help_phpbb_submit_before', compact($vars))); diff --git a/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php b/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php index 2634cee643..afa67fbc58 100644 --- a/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php +++ b/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php @@ -18,7 +18,7 @@ class add_help_phpbb extends \phpbb\db\migration\migration static public function depends_on() { return array( - '\phpbb\db\migration\data\v320\v320a2', + '\phpbb\db\migration\data\v320\v320rc1', ); } diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index 01b88344e8..13c1591dcd 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -76,7 +76,7 @@ class update_extensions extends task_base * they were added */ static public $default_extensions_update = [ - '3.2.0-b3' => ['phpbb/viglink'] + '3.2.0-RC2' => ['phpbb/viglink'] ]; /** From 15f433f00fb84fa8afa97ae95372b7dc6826f5f5 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 11 Sep 2016 16:57:33 +0200 Subject: [PATCH 1381/1676] [ticket/14492] Always update the time the stats were sent PHPBB3-14492 --- phpBB/includes/acp/acp_help_phpbb.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index ba17ae3fb4..7991a0dad6 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -86,15 +86,12 @@ class acp_help_phpbb $config->set('help_send_statistics', $request->variable('help_send_statistics', false)); $response = $request->variable('send_statistics_response', ''); + $config->set('help_send_statistics_time', time()); + if (!empty($response)) { if ((strpos($response, 'Thank you') !== false || strpos($response, 'Flood protection') !== false)) { - // Update time when statistics were actually sent - if (strpos($response, 'Thank you') !== false) - { - $config->set('help_send_statistics_time', time()); - } trigger_error($user->lang('THANKS_SEND_STATISTICS') . adm_back_link($this->u_action)); } else From 9b4190e1365aed639068d341cb4296e895ad4ba1 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 9 Nov 2016 22:02:46 +0100 Subject: [PATCH 1382/1676] [ticket/14492] Encode URI components in systemdata for stats The stats data needs to be URI encoded to prevent issues when submitting the data to the receive_stats script on www.phpbb.com. PHPBB3-14492 --- phpBB/adm/style/ajax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/adm/style/ajax.js b/phpBB/adm/style/ajax.js index 28f761bc0b..d5154b2a61 100644 --- a/phpBB/adm/style/ajax.js +++ b/phpBB/adm/style/ajax.js @@ -87,7 +87,7 @@ phpbb.prepareSendStats = function () { $.ajax({ url: $this.attr('data-ajax-action').replace('&', '&'), type: 'POST', - data: 'systemdata=' + $this.find('input[name=systemdata]').val(), + data: 'systemdata=' + encodeURIComponent($this.find('input[name=systemdata]').val()), success: returnHandler, error: errorHandler, cache: false From 8ded30bbbe1e12ed301c2deb43d52da5a22d5b05 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 22 Nov 2016 18:39:01 +0100 Subject: [PATCH 1383/1676] [ticket/14492] Fix redirection to help phpBB page PHPBB3-14492 --- phpBB/phpbb/install/installer.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index b8eef34a1d..abdb172cf3 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -59,6 +59,11 @@ class installer */ protected $web_root; + /** + * @var \phpbb\user + */ + protected $user; + /** * Stores the number of steps that a given module has * @@ -87,6 +92,7 @@ class installer $this->installer_modules = null; $this->web_root = $path_helper->get_web_root_path(); $this->purge_cache_before = false; + $this->user = $container->get('user'); } /** @@ -243,8 +249,14 @@ class installer } else { - global $SID; - $acp_url = $this->web_root . 'adm/index.php' . $SID . '&i=acp_help_phpbb&mode=help_phpbb'; + // Start session and try to apply session id + $auth = $this->container_factory->get('auth'); + $this->user->session_begin(); + $auth->acl($this->user->data); + $this->user->setup(); + $phpbb_root_path = $this->container_factory->get_parameter('core.root_path'); + + $acp_url = append_sid($phpbb_root_path . 'adm/index.php', 'i=acp_help_phpbb&mode=help_phpbb', true, $this->user->session_id); $this->iohandler->add_success_message('INSTALLER_FINISHED', array( 'ACP_LINK', $acp_url, From 5895f56de05b637765a6583b8c51c1db3daabe91 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 24 Nov 2016 20:38:29 +0100 Subject: [PATCH 1384/1676] [ticket/14492] Add user service to installer & only instantiate if needed PHPBB3-14492 --- phpBB/config/installer/container/services.yml | 6 ++++++ phpBB/phpbb/install/installer.php | 15 +++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/phpBB/config/installer/container/services.yml b/phpBB/config/installer/container/services.yml index 4c3ed3bfcb..c16547c649 100644 --- a/phpBB/config/installer/container/services.yml +++ b/phpBB/config/installer/container/services.yml @@ -88,6 +88,12 @@ services: calls: - [setLexer, ['@template.twig.lexer']] + user: + class: phpbb\user + arguments: + - '@language' + - '%datetime.class%' + console.exception_subscriber: class: phpbb\console\exception_subscriber arguments: diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index abdb172cf3..a7d3b99dcb 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -59,11 +59,6 @@ class installer */ protected $web_root; - /** - * @var \phpbb\user - */ - protected $user; - /** * Stores the number of steps that a given module has * @@ -92,7 +87,6 @@ class installer $this->installer_modules = null; $this->web_root = $path_helper->get_web_root_path(); $this->purge_cache_before = false; - $this->user = $container->get('user'); } /** @@ -251,12 +245,13 @@ class installer { // Start session and try to apply session id $auth = $this->container_factory->get('auth'); - $this->user->session_begin(); - $auth->acl($this->user->data); - $this->user->setup(); + $user = $this->container_factory->get('user'); + $user->session_begin(); + $auth->acl($user->data); + $user->setup(); $phpbb_root_path = $this->container_factory->get_parameter('core.root_path'); - $acp_url = append_sid($phpbb_root_path . 'adm/index.php', 'i=acp_help_phpbb&mode=help_phpbb', true, $this->user->session_id); + $acp_url = append_sid($phpbb_root_path . 'adm/index.php', 'i=acp_help_phpbb&mode=help_phpbb', true, $user->session_id); $this->iohandler->add_success_message('INSTALLER_FINISHED', array( 'ACP_LINK', $acp_url, From 346f31a03156839d1b1931d2fc69cd2ab5656bc0 Mon Sep 17 00:00:00 2001 From: Etienne Baroux Date: Mon, 2 Jun 2014 10:12:18 +0200 Subject: [PATCH 1385/1676] [ticket/12610] Add command to check if the board is up to date. PHPBB3-12610 --- phpBB/config/default/container/services.yml | 2 +- .../default/container/services_console.yml | 9 + phpBB/includes/acp/acp_extensions.php | 46 +-- phpBB/language/en/acp/common.php | 4 + phpBB/language/en/cli.php | 29 +- phpBB/phpbb/console/command/update/check.php | 302 ++++++++++++++++++ phpBB/phpbb/extension/manager.php | 38 ++- phpBB/phpbb/extension/metadata_manager.php | 18 +- phpBB/phpbb/finder.php | 4 +- tests/console/update/check_test.php | 99 ++++++ tests/extension/manager_test.php | 2 +- tests/extension/metadata_manager_test.php | 5 +- tests/pagination/pagination_test.php | 3 +- .../phpbb_functional_test_case.php | 2 +- 14 files changed, 491 insertions(+), 72 deletions(-) create mode 100644 phpBB/phpbb/console/command/update/check.php create mode 100644 tests/console/update/check_test.php diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 2ccda6a38e..9bb1d673f4 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -108,7 +108,7 @@ services: - '%tables.ext%' - '%core.root_path%' - '%core.php_ext%' - - '@cache.driver' + - '@cache' file_downloader: class: phpbb\file_downloader diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 3f27ee666a..c3db4c29a5 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -220,6 +220,15 @@ services: tags: - { name: console.command } + console.command.update.check: + class: phpbb\console\command\update\check + arguments: + - @user + - @config + - @service_container + tags: + - { name: console.command } + console.command.user.activate: class: phpbb\console\command\user\activate arguments: diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index d2e01c80cc..ec88a4a392 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -86,7 +86,7 @@ class acp_extensions // If they've specified an extension, let's load the metadata manager and validate it. if ($ext_name) { - $md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $template, $phpbb_root_path); + $md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $phpbb_root_path); try { @@ -303,11 +303,11 @@ class acp_extensions case 'details': // Output it to the template - $md_manager->output_template_data(); + $md_manager->output_template_data($template); try { - $updates_available = $this->version_check($md_manager, $request->variable('versioncheck_force', false)); + $updates_available = $phpbb_extension_manager->version_check($md_manager, $request->variable('versioncheck_force', false), $this->config['extension_force_unstable'] ? 'unstable' : null); $template->assign_vars(array( 'S_UP_TO_DATE' => empty($updates_available), @@ -350,7 +350,7 @@ class acp_extensions foreach ($phpbb_extension_manager->all_enabled() as $name => $location) { - $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template); + $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name); try { @@ -361,7 +361,7 @@ class acp_extensions ); $force_update = $this->request->variable('versioncheck_force', false); - $updates = $this->version_check($md_manager, $force_update, !$force_update); + $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); $enabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; @@ -408,7 +408,7 @@ class acp_extensions foreach ($phpbb_extension_manager->all_disabled() as $name => $location) { - $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template); + $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name); try { @@ -419,7 +419,7 @@ class acp_extensions ); $force_update = $this->request->variable('versioncheck_force', false); - $updates = $this->version_check($md_manager, $force_update, !$force_update); + $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); $disabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; @@ -469,7 +469,7 @@ class acp_extensions foreach ($uninstalled as $name => $location) { - $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template); + $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name); try { @@ -480,7 +480,7 @@ class acp_extensions ); $force_update = $this->request->variable('versioncheck_force', false); - $updates = $this->version_check($md_manager, $force_update, !$force_update); + $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); $available_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); $available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; @@ -533,34 +533,6 @@ class acp_extensions } } - /** - * Check the version and return the available updates. - * - * @param \phpbb\extension\metadata_manager $md_manager The metadata manager for the version to check. - * @param bool $force_update Ignores cached data. Defaults to false. - * @param bool $force_cache Force the use of the cache. Override $force_update. - * @return string - * @throws RuntimeException - */ - protected function version_check(\phpbb\extension\metadata_manager $md_manager, $force_update = false, $force_cache = false) - { - $meta = $md_manager->get_metadata('all'); - - if (!isset($meta['extra']['version-check'])) - { - throw new \RuntimeException($this->user->lang('NO_VERSIONCHECK'), 1); - } - - $version_check = $meta['extra']['version-check']; - - $version_helper = new \phpbb\version_helper($this->cache, $this->config, new \phpbb\file_downloader(), $this->user); - $version_helper->set_current_version($meta['version']); - $version_helper->set_file_location($version_check['host'], $version_check['directory'], $version_check['filename'], isset($version_check['ssl']) ? $version_check['ssl'] : false); - $version_helper->force_stability($this->config['extension_force_unstable'] ? 'unstable' : null); - - return $updates = $version_helper->get_suggested_updates($force_update, $force_cache); - } - /** * Sort helper for the table containing the metadata about the extensions. */ diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 053671e1a2..acd9776dd7 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -328,6 +328,10 @@ $lang = array_merge($lang, array( 'USERNAMES_EXPLAIN' => 'Place each username on a separate line.', 'USER_CONTROL_PANEL' => 'User Control Panel', + 'UPDATE_NEEDED' => 'The board is not up to date.', + 'UPDATE_NOT_NEEDED' => 'The board is up to date.', + 'UPDATES_AVAILABLE' => 'Updates available:', + 'WARNING' => 'Warning', )); diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 09f46a5cee..9198f9a653 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -50,6 +50,9 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_CRON_LIST' => 'Prints a list of ready and unready cron jobs.', 'CLI_DESCRIPTION_CRON_RUN' => 'Runs all ready cron tasks.', 'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1' => 'Name of the task to be run', + 'CLI_DESCRIPTION_CRON_RUN_OPTION_CACHE' => 'Run check command with cache.', + 'CLI_DESCRIPTION_CRON_RUN_OPTION_STABILITY' => 'Run command choosing to check only stable or unstable versions.', + 'CLI_DESCRIPTION_DB_LIST' => 'List all installed and available migrations.', 'CLI_DESCRIPTION_DB_MIGRATE' => 'Updates the database by applying migrations.', 'CLI_DESCRIPTION_DB_REVERT' => 'Revert a migration.', @@ -66,21 +69,29 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_OPTION_SHELL' => 'Launch the shell.', 'CLI_DESCRIPTION_PURGE_EXTENSION' => 'Purges the specified extension.', - 'CLI_DESCRIPTION_REPARSER_LIST' => 'Lists the types of text that can be reparsed.', - 'CLI_DESCRIPTION_REPARSER_REPARSE' => 'Reparses stored text with the current text_formatter services.', - 'CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1' => 'Type of text to reparse. Leave blank to reparse everything.', + + 'CLI_DESCRIPTION_REPARSER_LIST' => 'Lists the types of text that can be reparsed.', + 'CLI_DESCRIPTION_REPARSER_REPARSE' => 'Reparses stored text with the current text_formatter services.', + 'CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1' => 'Type of text to reparse. Leave blank to reparse everything.', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_DRY_RUN' => 'Do not save any changes; just print what would happen', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MIN' => 'Lowest record ID to process', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MAX' => 'Highest record ID to process', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_SIZE' => 'Approximate number of records to process at a time', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RESUME' => 'Start reparsing where the last execution stopped', - 'CLI_DESCRIPTION_RECALCULATE_EMAIL_HASH' => 'Recalculates the user_email_hash column of the users table.', - 'CLI_DESCRIPTION_SET_ATOMIC_CONFIG' => 'Sets a configuration option’s value only if the old matches the current value', - 'CLI_DESCRIPTION_SET_CONFIG' => 'Sets a configuration option’s value', - 'CLI_DESCRIPTION_THUMBNAIL_DELETE' => 'Delete all existing thumbnails.', - 'CLI_DESCRIPTION_THUMBNAIL_GENERATE' => 'Generate all missing thumbnails.', - 'CLI_DESCRIPTION_THUMBNAIL_RECREATE' => 'Recreate all thumbnails.', + 'CLI_DESCRIPTION_RECALCULATE_EMAIL_HASH' => 'Recalculates the user_email_hash column of the users table.', + + 'CLI_DESCRIPTION_SET_ATOMIC_CONFIG' => 'Sets a configuration option’s value only if the old matches the current value', + 'CLI_DESCRIPTION_SET_CONFIG' => 'Sets a configuration option’s value', + + 'CLI_DESCRIPTION_THUMBNAIL_DELETE' => 'Delete all existing thumbnails.', + 'CLI_DESCRIPTION_THUMBNAIL_GENERATE' => 'Generate all missing thumbnails.', + 'CLI_DESCRIPTION_THUMBNAIL_RECREATE' => 'Recreate all thumbnails.', + + 'CLI_DESCRIPTION_UPDATE_CHECK' => 'Check if the board is up to date.', + 'CLI_DESCRIPTION_UPDATE_CHECK_ARGUMENT_1' => 'Name of the extension to check (if all, checks all the extensions)', + + 'CLI_ERROR_INVALID_STABILITY' => '"%s" is not a valid stability.', 'CLI_DESCRIPTION_USER_ACTIVATE' => 'Activate (or deactivate) a user account.', 'CLI_DESCRIPTION_USER_ACTIVATE_USERNAME' => 'Username of the account to activate.', diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php new file mode 100644 index 0000000000..0ef3c970ac --- /dev/null +++ b/phpBB/phpbb/console/command/update/check.php @@ -0,0 +1,302 @@ + +* @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\console\command\update; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class check extends \phpbb\console\command\command +{ + /** @var \phpbb\config\config */ + protected $config; + + /** @var \Symfony\Component\DependencyInjection\ContainerBuilder */ + protected $phpbb_container; + + /** + * Construct method + */ + public function __construct(\phpbb\user $user, \phpbb\config\config $config, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container) + { + parent::__construct($user); + + $this->config = $config; + $this->phpbb_container = $phpbb_container; + $this->user->add_lang(array('acp/common', 'acp/extensions')); + } + + /** + * Configures the service. + * + * Sets the name and description of the command. + * + * @return null + */ + protected function configure() + { + $this + ->setName('update:check') + ->setDescription($this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK')) + ->addArgument('ext-name', InputArgument::OPTIONAL, $this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK_ARGUMENT_1')) + ->addOption('stability', null, InputOption::VALUE_REQUIRED, 'CLI_DESCRIPTION_CRON_RUN_OPTION_STABILITY') + ->addOption('cache', 'c', InputOption::VALUE_NONE, 'CLI_DESCRIPTION_CRON_RUN_OPTION_CACHE') + ; + } + + /** + * Executes the command. + * + * Checks if an update is available. + * If at least one is available, a message is printed and if verbose mode is set the list of possible updates is printed. + * If their is none, nothing is printed unless verbose mode is set. + * + * @param InputInterface $input Input stream, used to get the options. + * @param OutputInterface $output Output stream, used to print messages. + * @return int 0 if the board is up to date, 1 if it is not and 2 if an error occured. + * @throws \RuntimeException + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $recheck = true; + if ($input->getOption('cache')) + { + $recheck = false; + } + + $stability = null; + if ($input->getOption('stability')) + { + $stability = $input->getOption('stability'); + if (!($stability == 'stable') && !($stability == 'unstable')) + { + throw new \RuntimeException($this->user->lang('CLI_ERROR_INVALID_STABILITY', $stability)); + } + } + + $ext_name = $input->getArgument('ext-name'); + if ($ext_name != null) + { + if ($ext_name == 'all') + { + return $this->check_all_ext($input, $output, $stability, $recheck); + } + else + { + return $this->check_ext($input, $output, $stability, $recheck, $ext_name); + } + } + else + { + return $this->check_core($input, $output, $stability, $recheck); + } + } + + /** + * Check if a given extension is up to date + * + * @param InputInterface $input Input stream, used to get the options. + * @param OutputInterface $output Output stream, used to print messages. + * @param OutputInterface $stability Force a given stability + * @param bool $recheck Disallow the use of the cache + * @param string $ext_name The extension name + * @return int + */ + protected function check_ext(InputInterface $input, OutputInterface $output, $stability, $recheck, $ext_name) + { + try + { + $ext_manager = $this->phpbb_container->get('ext.manager'); + $md_manager = $ext_manager->create_extension_metadata_manager($ext_name, null); + $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); + } + catch (\RuntimeException $e) + { + $output->writeln('' . $e->getMessage() . ''); + + return 2; + } + + $metadata = $md_manager->get_metadata('all'); + if ($input->getOption('verbose')) + { + $output->writeln('' . $md_manager->get_metadata('display-name') . ''); + $output->writeln(''); + + $output->writeln('' . $this->user->lang('CURRENT_VERSION') . $this->user->lang('COLON') . ' ' . $metadata['version']); + } + + if (!empty($updates_available)) + { + $output->writeln(''); + $output->writeln('' . $this->user->lang('NOT_UP_TO_DATE', $metadata['name']) . ''); + + if ($input->getOption('verbose')) + { + $this->display_versions($output, $updates_available); + } + + return 1; + } + else + { + $output->writeln(''); + $output->writeln('' . $this->user->lang('NOT_UP_TO_DATE', $metadata['name']) . ''); + + if ($input->getOption('verbose')) + { + $output->writeln('' . $this->user->lang('UPDATE_NOT_NEEDED') . ''); + } + + return 0; + } + } + + /** + * Check if the core is up to date + * + * @param InputInterface $input Input stream, used to get the options. + * @param OutputInterface $output Output stream, used to print messages. + * @param OutputInterface $stability Force a given stability + * @param bool $recheck Disallow the use of the cache + * @return int + */ + protected function check_core(InputInterface $input, OutputInterface $output, $stability, $recheck) + { + $version_helper = $this->phpbb_container->get('version_helper'); + $version_helper->force_stability($stability); + + try + { + $updates_available = $version_helper->get_suggested_updates($recheck); + } + catch (\RuntimeException $e) + { + $output->writeln('' . $this->user->lang('VERSIONCHECK_FAIL') . ''); + + return 2; + } + + if ($input->getOption('verbose')) + { + $output->writeln('phpBB core'); + $output->writeln(''); + + $output->writeln('' . $this->user->lang('CURRENT_VERSION') . $this->user->lang('COLON') . ' ' . $this->config['version']); + } + + if (!empty($updates_available)) + { + $output->writeln(''); + $output->writeln('' . $this->user->lang('UPDATE_NEEDED') . ''); + + if ($input->getOption('verbose')) + { + $this->display_versions($output, $updates_available); + } + + return 1; + } + else + { + if ($input->getOption('verbose')) + { + $output->writeln(''); + $output->writeln('' . $this->user->lang('UPDATE_NOT_NEEDED') . ''); + } + + return 0; + } + } + + /** + * Check if all the available extensions are up to date + * + * @param InputInterface $input Input stream, used to get the options. + * @param OutputInterface $output Output stream, used to print messages. + * @param OutputInterface $stability Force a given stability + * @param bool $recheck Disallow the use of the cache + * @return int + */ + protected function check_all_ext(InputInterface $input, OutputInterface $output, $stability, $recheck) + { + $ext_manager = $this->phpbb_container->get('ext.manager'); + + $ext_name_length = max(30, strlen($this->user->lang('EXTENSION_NAME'))); + $current_version_length = max(15, strlen($this->user->lang('CURRENT_VERSION'))); + $latest_version_length = max(15, strlen($this->user->lang('LATEST_VERSION'))); + + $output->writeln(sprintf("%-{$ext_name_length}s | %-{$current_version_length}s | %s", $this->user->lang('EXTENSION_NAME'), $this->user->lang('CURRENT_VERSION'), $this->user->lang('LATEST_VERSION'))); + $output->writeln(sprintf("%'-{$ext_name_length}s-+-%'-{$current_version_length}s-+-%'-{$latest_version_length}s", '', '', '')); + foreach ($ext_manager->all_available() as $ext_name => $ext_path) + { + $message = sprintf("%-{$ext_name_length}s", $ext_name); + $md_manager = $ext_manager->create_extension_metadata_manager($ext_name, null); + try + { + $metadata = $md_manager->get_metadata('all'); + $message .= sprintf(" | %-{$current_version_length}s", $metadata['version']); + try + { + $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); + $message .= sprintf(" | %s", implode(', ', array_keys($updates_available))); + } + catch (\RuntimeException $e) + { + $message .= ' | '; + } + } + catch (\RuntimeException $e) + { + $message .= ('' . $e->getMessage() . ''); + } + + $output->writeln($message); + } + + return 0; + } + + /** + * Display the details of the available updates + * + * @param OutputInterface $output Output stream, used to print messages. + * @param array $updates_available The list of the available updates + */ + protected function display_versions(OutputInterface $output, $updates_available) + { + $output->writeln(''); + $output->writeln('' . $this->user->lang('UPDATES_AVAILABLE') . ''); + foreach ($updates_available as $version_data) + { + $messages = array(); + $messages[] = sprintf("\t%-30s| %s", $this->user->lang('VERSION'), $version_data['current']); + + if (isset($version_data['announcement'])) + { + $messages[] = sprintf("\t%-30s| %s", $this->user->lang('ANNOUNCEMENT_TOPIC'), $version_data['announcement']); + } + + if (isset($version_data['download'])) + { + $messages[] = sprintf("\t%-30s| %s", $this->user->lang('DOWNLOAD_LATEST'), $version_data['download']); + } + + $messages[] = ''; + + $output->writeln(implode("\n", $messages)); + } + } +} diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 98d2d27278..6cdc8c0cc7 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -42,10 +42,10 @@ class manager * @param string $extension_table The name of the table holding extensions * @param string $phpbb_root_path Path to the phpbb includes directory. * @param string $php_ext php file extension, defaults to php - * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null + * @param \phpbb\cache\service $cache A cache instance or null * @param string $cache_name The name of the cache variable, defaults to _ext */ - public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem\filesystem_interface $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext') + public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem\filesystem_interface $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\service $cache = null, $cache_name = '_ext') { $this->cache = $cache; $this->cache_name = $cache_name; @@ -146,12 +146,11 @@ class manager * Instantiates the metadata manager for the extension with the given name * * @param string $name The extension name - * @param \phpbb\template\template $template The template manager * @return \phpbb\extension\metadata_manager Instance of the metadata manager */ - public function create_extension_metadata_manager($name, \phpbb\template\template $template) + public function create_extension_metadata_manager($name) { - return new \phpbb\extension\metadata_manager($name, $this->config, $this, $template, $this->phpbb_root_path); + return new \phpbb\extension\metadata_manager($name, $this->config, $this, $this->phpbb_root_path); } /** @@ -565,6 +564,35 @@ class manager return isset($this->extensions[$name]); } + /** + * Check the version and return the available updates (for an extension). + * + * @param \phpbb\extension\metadata_manager $md_manager The metadata manager for the version to check. + * @param bool $force_update Ignores cached data. Defaults to false. + * @param bool $force_cache Force the use of the cache. Override $force_update. + * @param string $stability Force the stability (null by default). + * @return string + * @throws \RuntimeException + */ + public function version_check(\phpbb\extension\metadata_manager $md_manager, $force_update = false, $force_cache = false, $stability = null) + { + $meta = $md_manager->get_metadata('all'); + + if (!isset($meta['extra']['version-check'])) + { + throw new \RuntimeException($this->user->lang('NO_VERSIONCHECK'), 1); + } + + $version_check = $meta['extra']['version-check']; + + $version_helper = new \phpbb\version_helper($this->cache, $this->config, $this->user); + $version_helper->set_current_version($meta['version']); + $version_helper->set_file_location($version_check ['host'], $version_check ['directory'], $version_check ['filename']); + $version_helper->force_stability($stability); + + return $updates = $version_helper->get_suggested_updates($force_update, $force_cache); + } + /** * Check to see if a given extension is purged * diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index 4f080647c8..fe64c92ee1 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -30,12 +30,6 @@ class metadata_manager */ protected $extension_manager; - /** - * phpBB Template instance - * @var \phpbb\template\template - */ - protected $template; - /** * phpBB root path * @var string @@ -66,14 +60,12 @@ class metadata_manager * @param string $ext_name Name (including vendor) of the extension * @param \phpbb\config\config $config phpBB Config instance * @param \phpbb\extension\manager $extension_manager An instance of the phpBB extension manager - * @param \phpbb\template\template $template phpBB Template instance * @param string $phpbb_root_path Path to the phpbb includes directory. */ - public function __construct($ext_name, \phpbb\config\config $config, \phpbb\extension\manager $extension_manager, \phpbb\template\template $template, $phpbb_root_path) + public function __construct($ext_name, \phpbb\config\config $config, \phpbb\extension\manager $extension_manager, $phpbb_root_path) { $this->config = $config; $this->extension_manager = $extension_manager; - $this->template = $template; $this->phpbb_root_path = $phpbb_root_path; $this->ext_name = $ext_name; @@ -336,11 +328,11 @@ class metadata_manager /** * Outputs the metadata into the template * - * @return null + * @param \phpbb\template\template $template phpBB Template instance */ - public function output_template_data() + public function output_template_data(\phpbb\template\template $template) { - $this->template->assign_vars(array( + $template->assign_vars(array( 'META_NAME' => $this->metadata['name'], 'META_TYPE' => $this->metadata['type'], 'META_DESCRIPTION' => (isset($this->metadata['description'])) ? $this->metadata['description'] : '', @@ -360,7 +352,7 @@ class metadata_manager foreach ($this->metadata['authors'] as $author) { - $this->template->assign_block_vars('meta_authors', array( + $template->assign_block_vars('meta_authors', array( 'AUTHOR_NAME' => $author['name'], 'AUTHOR_EMAIL' => (isset($author['email'])) ? $author['email'] : '', 'AUTHOR_HOMEPAGE' => (isset($author['homepage'])) ? $author['homepage'] : '', diff --git a/phpBB/phpbb/finder.php b/phpBB/phpbb/finder.php index 58bc27084e..1f1d931880 100644 --- a/phpBB/phpbb/finder.php +++ b/phpBB/phpbb/finder.php @@ -50,12 +50,12 @@ class finder * * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem instance * @param string $phpbb_root_path Path to the phpbb root directory - * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null + * @param \phpbb\cache\service $cache A cache instance or null * @param string $php_ext php file extension * @param string $cache_name The name of the cache variable, defaults to * _ext_finder */ - public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder') + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path = '', \phpbb\cache\service $cache = null, $php_ext = 'php', $cache_name = '_ext_finder') { $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; diff --git a/tests/console/update/check_test.php b/tests/console/update/check_test.php new file mode 100644 index 0000000000..d257ef6c0a --- /dev/null +++ b/tests/console/update/check_test.php @@ -0,0 +1,99 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use phpbb\console\command\update\check; + +require_once dirname(__FILE__) . '/../../../phpBB/includes/functions_admin.php'; +require_once dirname(__FILE__) . '/../../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../../phpBB/includes/utf/utf_tools.php'; + +/** +* @slow +*/ +class phpbb_console_command_check_test extends phpbb_test_case +{ + protected $command_name; + + protected $version_helper; + + public function test_up_to_date() + { + $command_tester = $this->get_command_tester('100000'); + $status = $command_tester->execute(array('command' => $this->command_name, '--no-ansi' => true)); + $this->assertSame('', $command_tester->getDisplay()); + $this->assertSame($status, 0); + } + + public function test_up_to_date_verbose() + { + $command_tester = $this->get_command_tester('100000'); + $status = $command_tester->execute(array('command' => $this->command_name, '--no-ansi' => true, '--verbose' => true)); + $this->assertContains('UPDATE_NOT_NEEDED', $command_tester->getDisplay()); + $this->assertSame($status, 0); + } + + + public function test_not_up_to_date() + { + $command_tester = $this->get_command_tester('0'); + $status = $command_tester->execute(array('command' => $this->command_name, '--no-ansi' => true)); + $this->assertContains('UPDATE_NEEDED', $command_tester->getDisplay()); + $this->assertSame($status, 1); + } + + public function test_not_up_to_date_verbose() + { + $command_tester = $this->get_command_tester('0'); + $status = $command_tester->execute(array('command' => $this->command_name, '--no-ansi' => true, '--verbose' => true)); + $this->assertContains('UPDATE_NEEDED', $command_tester->getDisplay()); + $this->assertContains('UPDATES_AVAILABLE', $command_tester->getDisplay()); + $this->assertSame($status, 1); + } + + public function test_error() + { + $command_tester = $this->get_command_tester('1'); + $this->version_helper->set_file_location('acme.corp','foo', 'bar.json'); + + $status = $command_tester->execute(array('command' => $this->command_name, '--no-ansi' => true)); + $this->assertContains('VERSIONCHECK_FAIL', $command_tester->getDisplay()); + $this->assertSame($status, 2); + } + + public function get_command_tester($current_version) + { + global $user; + + $user = $this->getMock('\phpbb\user'); + $user->method('lang')->will($this->returnArgument(0)); + + $cache = $this->getMockBuilder('\phpbb\cache\service') + ->disableOriginalConstructor() + ->getMock(); + + $config = new \phpbb\config\config(array('version' => $current_version)); + $this->version_helper = new \phpbb\version_helper($cache, $config, $user); + + $container = new phpbb_mock_container_builder; + $container->set('version_helper', $this->version_helper); + + $application = new Application(); + $application->add(new check($user, $config, $container)); + + $command = $application->find('update:check'); + $this->command_name = $command->getName(); + return new CommandTester($command); + } +} diff --git a/tests/extension/manager_test.php b/tests/extension/manager_test.php index a24b0cf178..f619d4c19d 100644 --- a/tests/extension/manager_test.php +++ b/tests/extension/manager_test.php @@ -180,7 +180,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case 'phpbb_ext', dirname(__FILE__) . '/', $php_ext, - ($with_cache) ? new phpbb_mock_cache() : null + ($with_cache) ? new \phpbb\cache\service(new phpbb_mock_cache(), $config, $db, $phpbb_root_path, $php_ext) : null ); } } diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index 19b99ee0ce..ce675f0d36 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -36,7 +36,6 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case { parent::setUp(); - $this->cache = new phpbb_mock_cache(); $this->config = new \phpbb\config\config(array( 'version' => '3.1.0', )); @@ -45,6 +44,9 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $this->db_tools = $factory->get($this->db); $this->phpbb_root_path = dirname(__FILE__) . '/'; $this->phpEx = 'php'; + + $this->cache = new \phpbb\cache\service(new phpbb_mock_cache(), $this->config, $this->db, $this->phpbb_root_path, $this->phpEx); + $this->table_prefix = 'phpbb_'; $container = new phpbb_mock_container_builder(); @@ -364,7 +366,6 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case $ext_name, $this->config, $this->extension_manager, - $this->template, $this->phpbb_root_path ); } diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index 024b6fc02d..30b25913f7 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -37,10 +37,11 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case ->method('lang') ->will($this->returnCallback(array($this, 'return_callback_implode'))); + $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); + $filesystem = new \phpbb\filesystem\filesystem(); $manager = new phpbb_mock_extension_manager(dirname(__FILE__) . '/', array()); - $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); $loader = new \Symfony\Component\Routing\Loader\YamlFileLoader( new \phpbb\routing\file_locator($filesystem, dirname(__FILE__) . '/') diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 2a37ca0e53..d5e78d1d60 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -263,7 +263,7 @@ class phpbb_functional_test_case extends phpbb_test_case self::$config['table_prefix'] . 'ext', dirname(__FILE__) . '/', $phpEx, - $this->get_cache_driver() + new \phpbb\cache\service($this->get_cache_driver(), $config, $this->db, $phpbb_root_path, $phpEx) ); return $extension_manager; From 376042d845a18058d93d289a1227096794da06d2 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 24 Aug 2015 10:26:05 +0200 Subject: [PATCH 1386/1676] [ticket/12610] Fix tests PHPBB3-12610 --- tests/console/update/check_test.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/console/update/check_test.php b/tests/console/update/check_test.php index d257ef6c0a..2101a3f33a 100644 --- a/tests/console/update/check_test.php +++ b/tests/console/update/check_test.php @@ -76,7 +76,10 @@ class phpbb_console_command_check_test extends phpbb_test_case { global $user; - $user = $this->getMock('\phpbb\user'); + $user = $this->getMock('\phpbb\user', array(), array( + new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + '\phpbb\datetime' + )); $user->method('lang')->will($this->returnArgument(0)); $cache = $this->getMockBuilder('\phpbb\cache\service') @@ -84,7 +87,7 @@ class phpbb_console_command_check_test extends phpbb_test_case ->getMock(); $config = new \phpbb\config\config(array('version' => $current_version)); - $this->version_helper = new \phpbb\version_helper($cache, $config, $user); + $this->version_helper = new \phpbb\version_helper($cache, $config, new \phpbb\file_downloader(), $user); $container = new phpbb_mock_container_builder; $container->set('version_helper', $this->version_helper); From 8481bd4e1831e3f9911263957637f4095fb088b0 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Mon, 24 Aug 2015 12:33:32 +0200 Subject: [PATCH 1387/1676] [ticket/12610] Use exception_interface PHPBB3-12610 --- phpBB/includes/acp/acp_extensions.php | 16 ++++++---- phpBB/includes/acp/acp_main.php | 3 +- phpBB/phpbb/console/command/update/check.php | 32 ++++++------------- phpBB/phpbb/extension/manager.php | 8 +++-- phpBB/phpbb/version_helper.php | 33 ++++++-------------- tests/console/update/check_test.php | 5 ++- tests/version/version_fetch_test.php | 5 +-- tests/version/version_helper_remote_test.php | 7 ++--- tests/version/version_test.php | 5 +-- 9 files changed, 46 insertions(+), 68 deletions(-) diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index ec88a4a392..5b9ee6c53e 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -11,6 +11,8 @@ * */ +use phpbb\exception\exception_interface; + /** * @ignore */ @@ -92,7 +94,7 @@ class acp_extensions { $md_manager->get_metadata('all'); } - catch (\phpbb\extension\exception $e) + catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); trigger_error($message, E_USER_WARNING); @@ -320,11 +322,13 @@ class acp_extensions $template->assign_block_vars('updates_available', $version_data); } } - catch (\RuntimeException $e) + catch (exception_interface $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $template->assign_vars(array( 'S_VERSIONCHECK_STATUS' => $e->getCode(), - 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== $user->lang('VERSIONCHECK_FAIL')) ? $e->getMessage() : '', + 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== 'VERSIONCHECK_FAIL') ? $message : '', )); } @@ -367,7 +371,7 @@ class acp_extensions $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch (\phpbb\extension\exception $e) + catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( @@ -425,7 +429,7 @@ class acp_extensions $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $disabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch (\phpbb\extension\exception $e) + catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( @@ -486,7 +490,7 @@ class acp_extensions $available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $available_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch (\phpbb\extension\exception $e) + catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index fe9657aecb..8dec7c69bd 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -450,9 +450,10 @@ class acp_main } catch (\RuntimeException $e) { + $message = call_user_func_array(array($user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $template->assign_vars(array( 'S_VERSIONCHECK_FAIL' => true, - 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== $user->lang('VERSIONCHECK_FAIL')) ? $e->getMessage() : '', + 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== 'VERSIONCHECK_FAIL') ? $message : '', )); } } diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php index 0ef3c970ac..982c86bf8c 100644 --- a/phpBB/phpbb/console/command/update/check.php +++ b/phpBB/phpbb/console/command/update/check.php @@ -13,6 +13,7 @@ namespace phpbb\console\command\update; +use phpbb\exception\exception_interface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; @@ -116,18 +117,9 @@ class check extends \phpbb\console\command\command */ protected function check_ext(InputInterface $input, OutputInterface $output, $stability, $recheck, $ext_name) { - try - { - $ext_manager = $this->phpbb_container->get('ext.manager'); - $md_manager = $ext_manager->create_extension_metadata_manager($ext_name, null); - $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); - } - catch (\RuntimeException $e) - { - $output->writeln('' . $e->getMessage() . ''); - - return 2; - } + $ext_manager = $this->phpbb_container->get('ext.manager'); + $md_manager = $ext_manager->create_extension_metadata_manager($ext_name, null); + $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); $metadata = $md_manager->get_metadata('all'); if ($input->getOption('verbose')) @@ -178,16 +170,7 @@ class check extends \phpbb\console\command\command $version_helper = $this->phpbb_container->get('version_helper'); $version_helper->force_stability($stability); - try - { - $updates_available = $version_helper->get_suggested_updates($recheck); - } - catch (\RuntimeException $e) - { - $output->writeln('' . $this->user->lang('VERSIONCHECK_FAIL') . ''); - - return 2; - } + $updates_available = $version_helper->get_suggested_updates($recheck); if ($input->getOption('verbose')) { @@ -258,6 +241,11 @@ class check extends \phpbb\console\command\command $message .= ' | '; } } + catch (exception_interface $e) + { + $exception_message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $message .= ('' . $exception_message . ''); + } catch (\RuntimeException $e) { $message .= ('' . $e->getMessage() . ''); diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 6cdc8c0cc7..da1f06c885 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -13,6 +13,8 @@ namespace phpbb\extension; +use phpbb\exception\runtime_exception; +use phpbb\file_downloader; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -572,7 +574,7 @@ class manager * @param bool $force_cache Force the use of the cache. Override $force_update. * @param string $stability Force the stability (null by default). * @return string - * @throws \RuntimeException + * @throws runtime_exception */ public function version_check(\phpbb\extension\metadata_manager $md_manager, $force_update = false, $force_cache = false, $stability = null) { @@ -580,12 +582,12 @@ class manager if (!isset($meta['extra']['version-check'])) { - throw new \RuntimeException($this->user->lang('NO_VERSIONCHECK'), 1); + throw new runtime_exception('NO_VERSIONCHECK'); } $version_check = $meta['extra']['version-check']; - $version_helper = new \phpbb\version_helper($this->cache, $this->config, $this->user); + $version_helper = new \phpbb\version_helper($this->cache, $this->config, new file_downloader()); $version_helper->set_current_version($meta['version']); $version_helper->set_file_location($version_check ['host'], $version_check ['directory'], $version_check ['filename']); $version_helper->force_stability($stability); diff --git a/phpBB/phpbb/version_helper.php b/phpBB/phpbb/version_helper.php index a1e66ba8fe..227bb72403 100644 --- a/phpBB/phpbb/version_helper.php +++ b/phpBB/phpbb/version_helper.php @@ -12,6 +12,7 @@ */ namespace phpbb; +use phpbb\exception\runtime_exception; /** * Class to handle version checking and comparison @@ -58,23 +59,18 @@ class version_helper /** @var \phpbb\file_downloader */ protected $file_downloader; - /** @var \phpbb\user */ - protected $user; - /** * Constructor * * @param \phpbb\cache\service $cache * @param \phpbb\config\config $config * @param \phpbb\file_downloader $file_downloader - * @param \phpbb\user $user */ - public function __construct(\phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\file_downloader $file_downloader, \phpbb\user $user) + public function __construct(\phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\file_downloader $file_downloader) { $this->cache = $cache; $this->config = $config; $this->file_downloader = $file_downloader; - $this->user = $user; if (defined('PHPBB_QA')) { @@ -175,7 +171,7 @@ class version_helper * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return string - * @throws \RuntimeException + * @throws runtime_exception */ public function get_latest_on_current_branch($force_update = false, $force_cache = false) { @@ -206,7 +202,7 @@ class version_helper * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return string - * @throws \RuntimeException + * @throws runtime_exception */ public function get_suggested_updates($force_update = false, $force_cache = false) { @@ -227,7 +223,7 @@ class version_helper * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return string Version info - * @throws \RuntimeException + * @throws runtime_exception */ public function get_versions_matching_stability($force_update = false, $force_cache = false) { @@ -247,7 +243,7 @@ class version_helper * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return string Version info, includes stable and unstable data - * @throws \RuntimeException + * @throws runtime_exception */ public function get_versions($force_update = false, $force_cache = false) { @@ -257,23 +253,16 @@ class version_helper if ($info === false && $force_cache) { - throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL')); + throw new runtime_exception('VERSIONCHECK_FAIL'); } else if ($info === false || $force_update) { - try { - $info = $this->file_downloader->get($this->host, $this->path, $this->file, $this->use_ssl ? 443 : 80); - } - catch (\phpbb\exception\runtime_exception $exception) - { - $prepare_parameters = array_merge(array($exception->getMessage()), $exception->get_parameters()); - throw new \RuntimeException(call_user_func_array(array($this->user, 'lang'), $prepare_parameters)); - } + $info = $this->file_downloader->get($this->host, $this->path, $this->file, $this->use_ssl ? 443 : 80); $error_string = $this->file_downloader->get_error_string(); if (!empty($error_string)) { - throw new \RuntimeException($error_string); + throw new runtime_exception($error_string); } $info = json_decode($info, true); @@ -290,9 +279,7 @@ class version_helper if (empty($info['stable']) && empty($info['unstable'])) { - $this->user->add_lang('acp/common'); - - throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL')); + throw new runtime_exception('VERSIONCHECK_FAIL'); } $info['stable'] = (empty($info['stable'])) ? array() : $info['stable']; diff --git a/tests/console/update/check_test.php b/tests/console/update/check_test.php index 2101a3f33a..de57e4df08 100644 --- a/tests/console/update/check_test.php +++ b/tests/console/update/check_test.php @@ -62,6 +62,9 @@ class phpbb_console_command_check_test extends phpbb_test_case $this->assertSame($status, 1); } + /** + * @expectedException phpbb\exception\runtime_exception + */ public function test_error() { $command_tester = $this->get_command_tester('1'); @@ -87,7 +90,7 @@ class phpbb_console_command_check_test extends phpbb_test_case ->getMock(); $config = new \phpbb\config\config(array('version' => $current_version)); - $this->version_helper = new \phpbb\version_helper($cache, $config, new \phpbb\file_downloader(), $user); + $this->version_helper = new \phpbb\version_helper($cache, $config, new \phpbb\file_downloader()); $container = new phpbb_mock_container_builder; $container->set('version_helper', $this->version_helper); diff --git a/tests/version/version_fetch_test.php b/tests/version/version_fetch_test.php index 6ecc9b7223..c44bd5514a 100644 --- a/tests/version/version_fetch_test.php +++ b/tests/version/version_fetch_test.php @@ -28,15 +28,12 @@ class phpbb_version_helper_fetch_test extends phpbb_test_case ->disableOriginalConstructor() ->getMock(); - $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); - $this->version_helper = new \phpbb\version_helper( $this->cache, new \phpbb\config\config(array( 'version' => '3.1.0', )), - new \phpbb\file_downloader(), - new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime') + new \phpbb\file_downloader() ); } diff --git a/tests/version/version_helper_remote_test.php b/tests/version/version_helper_remote_test.php index 724c4c970c..fa383d487f 100644 --- a/tests/version/version_helper_remote_test.php +++ b/tests/version/version_helper_remote_test.php @@ -42,8 +42,7 @@ class version_helper_remote_test extends \phpbb_test_case $this->version_helper = new \phpbb\version_helper( $this->cache, $config, - $this->file_downloader, - new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime') + $this->file_downloader ); $this->user = new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime'); $this->user->add_lang('acp/common'); @@ -161,8 +160,8 @@ class version_helper_remote_test extends \phpbb_test_case { try { $return = $this->version_helper->get_versions(); - } catch (\RuntimeException $e) { - $this->assertEquals((string)$e->getMessage(), $this->user->lang('VERSIONCHECK_FAIL')); + } catch (\phpbb\exception\runtime_exception $e) { + $this->assertEquals((string)$e->getMessage(), 'VERSIONCHECK_FAIL'); } } else diff --git a/tests/version/version_test.php b/tests/version/version_test.php index 05577f6a18..93d47a40a6 100644 --- a/tests/version/version_test.php +++ b/tests/version/version_test.php @@ -25,15 +25,12 @@ class phpbb_version_helper_test extends phpbb_test_case ->disableOriginalConstructor() ->getMock(); - $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); - $this->version_helper = new \phpbb\version_helper( $this->cache, new \phpbb\config\config(array( 'version' => '3.1.0', )), - new \phpbb\file_downloader(), - new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime') + new \phpbb\file_downloader() ); } From 1f305e40252d6b13f30c6243f24864f534037b93 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 26 Aug 2015 11:38:23 +0200 Subject: [PATCH 1388/1676] [ticket/12610] Skip extensions with no update info PHPBB3-12610 --- phpBB/includes/acp/acp_extensions.php | 51 +++++++++++++++++++-------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 5b9ee6c53e..6fc4b6c617 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -364,12 +364,19 @@ class acp_extensions 'META_VERSION' => $meta['version'], ); - $force_update = $this->request->variable('versioncheck_force', false); - $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); + if (isset($meta['extra']['version-check'])) + { + $force_update = $this->request->variable('versioncheck_force', false); + $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); - $enabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); - $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; - $enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); + $enabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); + $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; + $enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); + } + else + { + $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false; + } } catch (exception_interface $e) { @@ -422,12 +429,19 @@ class acp_extensions 'META_VERSION' => $meta['version'], ); - $force_update = $this->request->variable('versioncheck_force', false); - $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); + if (isset($meta['extra']['version-check'])) + { + $force_update = $this->request->variable('versioncheck_force', false); + $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); - $disabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); - $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; - $disabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); + $disabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); + $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; + $disabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); + } + else + { + $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false; + } } catch (exception_interface $e) { @@ -483,12 +497,19 @@ class acp_extensions 'META_VERSION' => $meta['version'], ); - $force_update = $this->request->variable('versioncheck_force', false); - $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); + if (isset($meta['extra']['version-check'])) + { + $force_update = $this->request->variable('versioncheck_force', false); + $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); - $available_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); - $available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; - $available_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); + $available_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); + $available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; + $available_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); + } + else + { + $available_extension_meta_data[$name]['S_VERSIONCHECK'] = false; + } } catch (exception_interface $e) { From 45dda53310bb618dce0813d61a85948cb334e4a9 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 26 Aug 2015 12:06:56 +0200 Subject: [PATCH 1389/1676] [ticket/12610] Improve output PHPBB3-12610 --- phpBB/bin/phpbbcli.php | 10 +++--- phpBB/language/en/cli.php | 9 +++--- phpBB/phpbb/console/command/update/check.php | 32 +++++++++++++++----- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index 2bca6e7b89..2c3675bbf1 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -71,16 +71,16 @@ require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx); register_compatibility_globals(); +/** @var \phpbb\language\language $language */ +$language = $phpbb_container->get('language'); +$language->add_lang(array('common', 'acp/common', 'cli')); + /* @var $user \phpbb\user */ $user = $phpbb_container->get('user'); $user->data['user_id'] = ANONYMOUS; $user->ip = '127.0.0.1'; -$user->add_lang('acp/common'); -$user->add_lang('cli'); - -/* @var $lang \phpbb\language\language */ -$lang = $phpbb_container->get('language'); +$application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $language); $application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $lang); $application->setDispatcher($phpbb_container->get('dispatcher')); $application->register_container_commands($phpbb_container->get('console.command_collection')); diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 9198f9a653..6e86c75ec0 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -50,9 +50,6 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_CRON_LIST' => 'Prints a list of ready and unready cron jobs.', 'CLI_DESCRIPTION_CRON_RUN' => 'Runs all ready cron tasks.', 'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1' => 'Name of the task to be run', - 'CLI_DESCRIPTION_CRON_RUN_OPTION_CACHE' => 'Run check command with cache.', - 'CLI_DESCRIPTION_CRON_RUN_OPTION_STABILITY' => 'Run command choosing to check only stable or unstable versions.', - 'CLI_DESCRIPTION_DB_LIST' => 'List all installed and available migrations.', 'CLI_DESCRIPTION_DB_MIGRATE' => 'Updates the database by applying migrations.', 'CLI_DESCRIPTION_DB_REVERT' => 'Revert a migration.', @@ -88,8 +85,10 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_THUMBNAIL_GENERATE' => 'Generate all missing thumbnails.', 'CLI_DESCRIPTION_THUMBNAIL_RECREATE' => 'Recreate all thumbnails.', - 'CLI_DESCRIPTION_UPDATE_CHECK' => 'Check if the board is up to date.', - 'CLI_DESCRIPTION_UPDATE_CHECK_ARGUMENT_1' => 'Name of the extension to check (if all, checks all the extensions)', + 'CLI_DESCRIPTION_UPDATE_CHECK' => 'Check if the board is up to date.', + 'CLI_DESCRIPTION_UPDATE_CHECK_ARGUMENT_1' => 'Name of the extension to check (if all, checks all the extensions)', + 'CLI_DESCRIPTION_UPDATE_CHECK_OPTION_CACHE' => 'Run check command with cache.', + 'CLI_DESCRIPTION_UPDATE_CHECK_OPTION_STABILITY' => 'Run command choosing to check only stable or unstable versions.', 'CLI_ERROR_INVALID_STABILITY' => '"%s" is not a valid stability.', diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php index 982c86bf8c..03dd313291 100644 --- a/phpBB/phpbb/console/command/update/check.php +++ b/phpBB/phpbb/console/command/update/check.php @@ -52,8 +52,8 @@ class check extends \phpbb\console\command\command ->setName('update:check') ->setDescription($this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK')) ->addArgument('ext-name', InputArgument::OPTIONAL, $this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK_ARGUMENT_1')) - ->addOption('stability', null, InputOption::VALUE_REQUIRED, 'CLI_DESCRIPTION_CRON_RUN_OPTION_STABILITY') - ->addOption('cache', 'c', InputOption::VALUE_NONE, 'CLI_DESCRIPTION_CRON_RUN_OPTION_CACHE') + ->addOption('stability', null, InputOption::VALUE_REQUIRED, $this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK_OPTION_STABILITY')) + ->addOption('cache', 'c', InputOption::VALUE_NONE, $this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK_OPTION_CACHE')) ; } @@ -215,6 +215,7 @@ class check extends \phpbb\console\command\command */ protected function check_all_ext(InputInterface $input, OutputInterface $output, $stability, $recheck) { + /** @var \phpbb\extension\manager $ext_manager */ $ext_manager = $this->phpbb_container->get('ext.manager'); $ext_name_length = max(30, strlen($this->user->lang('EXTENSION_NAME'))); @@ -230,15 +231,30 @@ class check extends \phpbb\console\command\command try { $metadata = $md_manager->get_metadata('all'); - $message .= sprintf(" | %-{$current_version_length}s", $metadata['version']); - try + if (isset($metadata['extra']['version-check'])) { - $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); - $message .= sprintf(" | %s", implode(', ', array_keys($updates_available))); + try { + $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); + if (!empty($updates_available)) + { + $message .= sprintf(" | %-{$current_version_length}s | %s", + $metadata['version'], + implode(', ', array_keys($updates_available)) + ); + } + else + { + $message .= sprintf(" | %-{$current_version_length}s | ", + $metadata['version'] + ); + } + } catch (\RuntimeException $e) { + $message .= ' | '; + } } - catch (\RuntimeException $e) + else { - $message .= ' | '; + $message .= sprintf(" | %-{$current_version_length}s | ", $metadata['version']); } } catch (exception_interface $e) From 0256c69191db7b2102d5fb338401ab3f58b118c6 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Wed, 26 Aug 2015 13:33:38 +0200 Subject: [PATCH 1390/1676] [ticket/12610] CS PHPBB3-12610 --- phpBB/bin/phpbbcli.php | 1 - phpBB/phpbb/extension/manager.php | 2 +- phpBB/phpbb/version_helper.php | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index 2c3675bbf1..6bd217ec07 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -81,7 +81,6 @@ $user->data['user_id'] = ANONYMOUS; $user->ip = '127.0.0.1'; $application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $language); -$application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $lang); $application->setDispatcher($phpbb_container->get('dispatcher')); $application->register_container_commands($phpbb_container->get('console.command_collection')); $application->run($input); diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index da1f06c885..b2b60aaa9b 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -589,7 +589,7 @@ class manager $version_helper = new \phpbb\version_helper($this->cache, $this->config, new file_downloader()); $version_helper->set_current_version($meta['version']); - $version_helper->set_file_location($version_check ['host'], $version_check ['directory'], $version_check ['filename']); + $version_helper->set_file_location($version_check['host'], $version_check['directory'], $version_check['filename']); $version_helper->force_stability($stability); return $updates = $version_helper->get_suggested_updates($force_update, $force_cache); diff --git a/phpBB/phpbb/version_helper.php b/phpBB/phpbb/version_helper.php index 227bb72403..b1dcdf10d9 100644 --- a/phpBB/phpbb/version_helper.php +++ b/phpBB/phpbb/version_helper.php @@ -12,6 +12,7 @@ */ namespace phpbb; + use phpbb\exception\runtime_exception; /** From c9e493a911d8296ce1ccca5de8ec4c9f84e1983d Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 18 Feb 2016 22:33:39 +0100 Subject: [PATCH 1391/1676] [ticket/12610] Display the latest version and not the branch name in CLI PHPBB3-12610 --- phpBB/ext/index.htm | 10 ---------- phpBB/phpbb/console/command/update/check.php | 7 ++++++- 2 files changed, 6 insertions(+), 11 deletions(-) delete mode 100644 phpBB/ext/index.htm diff --git a/phpBB/ext/index.htm b/phpBB/ext/index.htm deleted file mode 100644 index ee1f723a7d..0000000000 --- a/phpBB/ext/index.htm +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php index 03dd313291..7c1e52c955 100644 --- a/phpBB/phpbb/console/command/update/check.php +++ b/phpBB/phpbb/console/command/update/check.php @@ -237,9 +237,14 @@ class check extends \phpbb\console\command\command $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); if (!empty($updates_available)) { + $versions = array_map(function($entry) + { + return $entry['current']; + }, $updates_available); + $message .= sprintf(" | %-{$current_version_length}s | %s", $metadata['version'], - implode(', ', array_keys($updates_available)) + implode(', ', $versions) ); } else From ab58bb8744b98478437cefd7af362aea1274621e Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 18 Feb 2016 22:42:25 +0100 Subject: [PATCH 1392/1676] [ticket/12610] Ignor exception due to the version check in extensions list PHPBB3-12610 --- phpBB/includes/acp/acp_extensions.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 6fc4b6c617..904dd2e960 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -366,12 +366,19 @@ class acp_extensions if (isset($meta['extra']['version-check'])) { - $force_update = $this->request->variable('versioncheck_force', false); - $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); + try + { + $force_update = $this->request->variable('versioncheck_force', false); + $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); - $enabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); - $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; - $enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); + $enabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); + $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; + $enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); + } + catch (exception_interface $e) + { + // Ignore exceptions due to the version check + } } else { From 57915a8aaa842064d42fee419c9e0eaf7288140a Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 1 Sep 2016 16:12:04 +0200 Subject: [PATCH 1393/1676] [ticket/12610] Correctly handle empty cache PHPBB3-12610 --- .../default/container/services_console.yml | 6 +++--- phpBB/ext/index.htm | 10 +++++++++ phpBB/includes/acp/acp_extensions.php | 9 ++++---- .../exception/version_check_exception.php | 21 +++++++++++++++++++ phpBB/phpbb/version_helper.php | 16 +++++++------- 5 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 phpBB/ext/index.htm create mode 100644 phpBB/phpbb/exception/version_check_exception.php diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index c3db4c29a5..4420b6e345 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -223,9 +223,9 @@ services: console.command.update.check: class: phpbb\console\command\update\check arguments: - - @user - - @config - - @service_container + - '@user' + - '@config' + - '@service_container' tags: - { name: console.command } diff --git a/phpBB/ext/index.htm b/phpBB/ext/index.htm new file mode 100644 index 0000000000..ee1f723a7d --- /dev/null +++ b/phpBB/ext/index.htm @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 904dd2e960..ea6feb3e6a 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -12,6 +12,7 @@ */ use phpbb\exception\exception_interface; +use phpbb\exception\version_check_exception; /** * @ignore @@ -518,6 +519,10 @@ class acp_extensions $available_extension_meta_data[$name]['S_VERSIONCHECK'] = false; } } + catch (version_check_exception $e) + { + $available_extension_meta_data[$name]['S_VERSIONCHECK'] = false; + } catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); @@ -526,10 +531,6 @@ class acp_extensions 'S_VERSIONCHECK' => false, )); } - catch (\RuntimeException $e) - { - $available_extension_meta_data[$name]['S_VERSIONCHECK'] = false; - } } uasort($available_extension_meta_data, array($this, 'sort_extension_meta_data_table')); diff --git a/phpBB/phpbb/exception/version_check_exception.php b/phpBB/phpbb/exception/version_check_exception.php new file mode 100644 index 0000000000..0810263ade --- /dev/null +++ b/phpBB/phpbb/exception/version_check_exception.php @@ -0,0 +1,21 @@ + +* @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\exception; + +/** + * Define an exception related to the version checker. + */ +class version_check_exception extends runtime_exception +{ +} diff --git a/phpBB/phpbb/version_helper.php b/phpBB/phpbb/version_helper.php index b1dcdf10d9..17caaa4a60 100644 --- a/phpBB/phpbb/version_helper.php +++ b/phpBB/phpbb/version_helper.php @@ -13,7 +13,7 @@ namespace phpbb; -use phpbb\exception\runtime_exception; +use phpbb\exception\version_check_exception; /** * Class to handle version checking and comparison @@ -172,7 +172,7 @@ class version_helper * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return string - * @throws runtime_exception + * @throws version_check_exception */ public function get_latest_on_current_branch($force_update = false, $force_cache = false) { @@ -203,7 +203,7 @@ class version_helper * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return string - * @throws runtime_exception + * @throws version_check_exception */ public function get_suggested_updates($force_update = false, $force_cache = false) { @@ -224,7 +224,7 @@ class version_helper * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return string Version info - * @throws runtime_exception + * @throws version_check_exception */ public function get_versions_matching_stability($force_update = false, $force_cache = false) { @@ -244,7 +244,7 @@ class version_helper * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return string Version info, includes stable and unstable data - * @throws runtime_exception + * @throws version_check_exception */ public function get_versions($force_update = false, $force_cache = false) { @@ -254,7 +254,7 @@ class version_helper if ($info === false && $force_cache) { - throw new runtime_exception('VERSIONCHECK_FAIL'); + throw new version_check_exception('VERSIONCHECK_FAIL'); } else if ($info === false || $force_update) { @@ -263,7 +263,7 @@ class version_helper if (!empty($error_string)) { - throw new runtime_exception($error_string); + throw new version_check_exception($error_string); } $info = json_decode($info, true); @@ -280,7 +280,7 @@ class version_helper if (empty($info['stable']) && empty($info['unstable'])) { - throw new runtime_exception('VERSIONCHECK_FAIL'); + throw new version_check_exception('VERSIONCHECK_FAIL'); } $info['stable'] = (empty($info['stable'])) ? array() : $info['stable']; From 6c35ca80edd76906638326468b15aa9f355b477b Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 4 Dec 2016 10:37:17 +0100 Subject: [PATCH 1394/1676] [ticket/12610] Add a better error message when an extension is missing PHPBB3-12610 --- phpBB/language/en/acp/extensions.php | 1 + phpBB/phpbb/console/command/update/check.php | 113 +++++++++++-------- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/phpBB/language/en/acp/extensions.php b/phpBB/language/en/acp/extensions.php index e5d6789764..8d6f8ece84 100644 --- a/phpBB/language/en/acp/extensions.php +++ b/phpBB/language/en/acp/extensions.php @@ -43,6 +43,7 @@ $lang = array_merge($lang, array( 'EXTENSION_NOT_AVAILABLE' => 'The selected extension is not available for this board, please verify your phpBB and PHP versions are allowed (see the details page).', 'EXTENSION_DIR_INVALID' => 'The selected extension has an invalid directory structure and cannot be enabled.', 'EXTENSION_NOT_ENABLEABLE' => 'The selected extension cannot be enabled, please verify the extension’s requirements.', + 'EXTENSION_NOT_INSTALLED' => 'The extension %s is not available. PLease check that you have installed it correctly.', 'DETAILS' => 'Details', diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php index 7c1e52c955..19da2318ca 100644 --- a/phpBB/phpbb/console/command/update/check.php +++ b/phpBB/phpbb/console/command/update/check.php @@ -13,11 +13,15 @@ namespace phpbb\console\command\update; +use phpbb\config\config; use phpbb\exception\exception_interface; +use phpbb\language\language; +use phpbb\user; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; class check extends \phpbb\console\command\command { @@ -26,17 +30,23 @@ class check extends \phpbb\console\command\command /** @var \Symfony\Component\DependencyInjection\ContainerBuilder */ protected $phpbb_container; + /** + * @var language + */ + private $language; /** * Construct method */ - public function __construct(\phpbb\user $user, \phpbb\config\config $config, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container) + public function __construct(user $user, config $config, ContainerInterface $phpbb_container, language $language) { parent::__construct($user); $this->config = $config; $this->phpbb_container = $phpbb_container; - $this->user->add_lang(array('acp/common', 'acp/extensions')); + $this->language = $language; + + $this->language->add_lang(array('acp/common', 'acp/extensions')); } /** @@ -50,10 +60,10 @@ class check extends \phpbb\console\command\command { $this ->setName('update:check') - ->setDescription($this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK')) - ->addArgument('ext-name', InputArgument::OPTIONAL, $this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK_ARGUMENT_1')) - ->addOption('stability', null, InputOption::VALUE_REQUIRED, $this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK_OPTION_STABILITY')) - ->addOption('cache', 'c', InputOption::VALUE_NONE, $this->user->lang('CLI_DESCRIPTION_UPDATE_CHECK_OPTION_CACHE')) + ->setDescription($this->language->lang('CLI_DESCRIPTION_UPDATE_CHECK')) + ->addArgument('ext-name', InputArgument::OPTIONAL, $this->language->lang('CLI_DESCRIPTION_UPDATE_CHECK_ARGUMENT_1')) + ->addOption('stability', null, InputOption::VALUE_REQUIRED, $this->language->lang('CLI_DESCRIPTION_UPDATE_CHECK_OPTION_STABILITY')) + ->addOption('cache', 'c', InputOption::VALUE_NONE, $this->language->lang('CLI_DESCRIPTION_UPDATE_CHECK_OPTION_CACHE')) ; } @@ -83,7 +93,7 @@ class check extends \phpbb\console\command\command $stability = $input->getOption('stability'); if (!($stability == 'stable') && !($stability == 'unstable')) { - throw new \RuntimeException($this->user->lang('CLI_ERROR_INVALID_STABILITY', $stability)); + throw new \RuntimeException($this->language->lang('CLI_ERROR_INVALID_STABILITY', $stability)); } } @@ -117,43 +127,52 @@ class check extends \phpbb\console\command\command */ protected function check_ext(InputInterface $input, OutputInterface $output, $stability, $recheck, $ext_name) { - $ext_manager = $this->phpbb_container->get('ext.manager'); - $md_manager = $ext_manager->create_extension_metadata_manager($ext_name, null); - $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); - - $metadata = $md_manager->get_metadata('all'); - if ($input->getOption('verbose')) + try { - $output->writeln('' . $md_manager->get_metadata('display-name') . ''); - $output->writeln(''); - - $output->writeln('' . $this->user->lang('CURRENT_VERSION') . $this->user->lang('COLON') . ' ' . $metadata['version']); - } - - if (!empty($updates_available)) - { - $output->writeln(''); - $output->writeln('' . $this->user->lang('NOT_UP_TO_DATE', $metadata['name']) . ''); + $ext_manager = $this->phpbb_container->get('ext.manager'); + $md_manager = $ext_manager->create_extension_metadata_manager($ext_name, null); + $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); + $metadata = $md_manager->get_metadata('all'); if ($input->getOption('verbose')) { - $this->display_versions($output, $updates_available); + $output->writeln('' . $md_manager->get_metadata('display-name') . ''); + $output->writeln(''); + + $output->writeln('' . $this->language->lang('CURRENT_VERSION') . $this->language->lang('COLON') . ' ' . $metadata['version']); } + if (!empty($updates_available)) + { + $output->writeln(''); + $output->writeln('' . $this->language->lang('NOT_UP_TO_DATE', $metadata['name']) . ''); + + if ($input->getOption('verbose')) + { + $this->display_versions($output, $updates_available); + } + + return 1; + } + else + { + $output->writeln(''); + $output->writeln('' . $this->language->lang('NOT_UP_TO_DATE', $metadata['name']) . ''); + + if ($input->getOption('verbose')) + { + $output->writeln('' . $this->language->lang('UPDATE_NOT_NEEDED') . ''); + } + + return 0; + } + } + catch (\RuntimeException $e) + { + $output->writeln(''.$this->language->lang('EXTENSION_NOT_INSTALLED', $ext_name).''); + return 1; } - else - { - $output->writeln(''); - $output->writeln('' . $this->user->lang('NOT_UP_TO_DATE', $metadata['name']) . ''); - - if ($input->getOption('verbose')) - { - $output->writeln('' . $this->user->lang('UPDATE_NOT_NEEDED') . ''); - } - - return 0; - } } /** @@ -177,13 +196,13 @@ class check extends \phpbb\console\command\command $output->writeln('phpBB core'); $output->writeln(''); - $output->writeln('' . $this->user->lang('CURRENT_VERSION') . $this->user->lang('COLON') . ' ' . $this->config['version']); + $output->writeln('' . $this->language->lang('CURRENT_VERSION') . $this->language->lang('COLON') . ' ' . $this->config['version']); } if (!empty($updates_available)) { $output->writeln(''); - $output->writeln('' . $this->user->lang('UPDATE_NEEDED') . ''); + $output->writeln('' . $this->language->lang('UPDATE_NEEDED') . ''); if ($input->getOption('verbose')) { @@ -197,7 +216,7 @@ class check extends \phpbb\console\command\command if ($input->getOption('verbose')) { $output->writeln(''); - $output->writeln('' . $this->user->lang('UPDATE_NOT_NEEDED') . ''); + $output->writeln('' . $this->language->lang('UPDATE_NOT_NEEDED') . ''); } return 0; @@ -218,11 +237,11 @@ class check extends \phpbb\console\command\command /** @var \phpbb\extension\manager $ext_manager */ $ext_manager = $this->phpbb_container->get('ext.manager'); - $ext_name_length = max(30, strlen($this->user->lang('EXTENSION_NAME'))); - $current_version_length = max(15, strlen($this->user->lang('CURRENT_VERSION'))); - $latest_version_length = max(15, strlen($this->user->lang('LATEST_VERSION'))); + $ext_name_length = max(30, strlen($this->language->lang('EXTENSION_NAME'))); + $current_version_length = max(15, strlen($this->language->lang('CURRENT_VERSION'))); + $latest_version_length = max(15, strlen($this->language->lang('LATEST_VERSION'))); - $output->writeln(sprintf("%-{$ext_name_length}s | %-{$current_version_length}s | %s", $this->user->lang('EXTENSION_NAME'), $this->user->lang('CURRENT_VERSION'), $this->user->lang('LATEST_VERSION'))); + $output->writeln(sprintf("%-{$ext_name_length}s | %-{$current_version_length}s | %s", $this->language->lang('EXTENSION_NAME'), $this->language->lang('CURRENT_VERSION'), $this->language->lang('LATEST_VERSION'))); $output->writeln(sprintf("%'-{$ext_name_length}s-+-%'-{$current_version_length}s-+-%'-{$latest_version_length}s", '', '', '')); foreach ($ext_manager->all_available() as $ext_name => $ext_path) { @@ -287,20 +306,20 @@ class check extends \phpbb\console\command\command protected function display_versions(OutputInterface $output, $updates_available) { $output->writeln(''); - $output->writeln('' . $this->user->lang('UPDATES_AVAILABLE') . ''); + $output->writeln('' . $this->language->lang('UPDATES_AVAILABLE') . ''); foreach ($updates_available as $version_data) { $messages = array(); - $messages[] = sprintf("\t%-30s| %s", $this->user->lang('VERSION'), $version_data['current']); + $messages[] = sprintf("\t%-30s| %s", $this->language->lang('VERSION'), $version_data['current']); if (isset($version_data['announcement'])) { - $messages[] = sprintf("\t%-30s| %s", $this->user->lang('ANNOUNCEMENT_TOPIC'), $version_data['announcement']); + $messages[] = sprintf("\t%-30s| %s", $this->language->lang('ANNOUNCEMENT_TOPIC'), $version_data['announcement']); } if (isset($version_data['download'])) { - $messages[] = sprintf("\t%-30s| %s", $this->user->lang('DOWNLOAD_LATEST'), $version_data['download']); + $messages[] = sprintf("\t%-30s| %s", $this->language->lang('DOWNLOAD_LATEST'), $version_data['download']); } $messages[] = ''; From 32aa0596f3750ff19f3da799d649e7b2a3429c47 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 4 Dec 2016 17:43:51 +0100 Subject: [PATCH 1395/1676] [ticket/12610] Use Symfony style guide PHPBB3-12610 --- .../default/container/services_console.yml | 1 + phpBB/phpbb/console/command/update/check.php | 173 +++++++++--------- 2 files changed, 87 insertions(+), 87 deletions(-) diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 4420b6e345..0c609a8051 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -226,6 +226,7 @@ services: - '@user' - '@config' - '@service_container' + - '@language' tags: - { name: console.command } diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php index 19da2318ca..aaccfa4983 100644 --- a/phpBB/phpbb/console/command/update/check.php +++ b/phpBB/phpbb/console/command/update/check.php @@ -21,6 +21,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\DependencyInjection\ContainerInterface; class check extends \phpbb\console\command\command @@ -40,13 +41,13 @@ class check extends \phpbb\console\command\command */ public function __construct(user $user, config $config, ContainerInterface $phpbb_container, language $language) { - parent::__construct($user); - $this->config = $config; $this->phpbb_container = $phpbb_container; $this->language = $language; $this->language->add_lang(array('acp/common', 'acp/extensions')); + + parent::__construct($user); } /** @@ -81,6 +82,8 @@ class check extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $recheck = true; if ($input->getOption('cache')) { @@ -93,7 +96,8 @@ class check extends \phpbb\console\command\command $stability = $input->getOption('stability'); if (!($stability == 'stable') && !($stability == 'unstable')) { - throw new \RuntimeException($this->language->lang('CLI_ERROR_INVALID_STABILITY', $stability)); + $io->error($this->language->lang('CLI_ERROR_INVALID_STABILITY', $stability)); + return 3; } } @@ -102,30 +106,29 @@ class check extends \phpbb\console\command\command { if ($ext_name == 'all') { - return $this->check_all_ext($input, $output, $stability, $recheck); + return $this->check_all_ext($io, $stability, $recheck); } else { - return $this->check_ext($input, $output, $stability, $recheck, $ext_name); + return $this->check_ext($io, $stability, $recheck, $ext_name); } } else { - return $this->check_core($input, $output, $stability, $recheck); + return $this->check_core($io,$stability, $recheck); } } /** - * Check if a given extension is up to date - * - * @param InputInterface $input Input stream, used to get the options. - * @param OutputInterface $output Output stream, used to print messages. - * @param OutputInterface $stability Force a given stability - * @param bool $recheck Disallow the use of the cache - * @param string $ext_name The extension name - * @return int - */ - protected function check_ext(InputInterface $input, OutputInterface $output, $stability, $recheck, $ext_name) + * Check if a given extension is up to date + * + * @param SymfonyStyle $io IO handler, for formatted and unified IO + * @param string $stability Force a given stability + * @param bool $recheck Disallow the use of the cache + * @param string $ext_name The extension name + * @return int + */ + protected function check_ext(SymfonyStyle $io, $stability, $recheck, $ext_name) { try { @@ -134,34 +137,29 @@ class check extends \phpbb\console\command\command $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); $metadata = $md_manager->get_metadata('all'); - if ($input->getOption('verbose')) + if ($io->isVerbose()) { - $output->writeln('' . $md_manager->get_metadata('display-name') . ''); - $output->writeln(''); + $io->title($md_manager->get_metadata('display-name')); - $output->writeln('' . $this->language->lang('CURRENT_VERSION') . $this->language->lang('COLON') . ' ' . $metadata['version']); + $io->note($this->language->lang('CURRENT_VERSION') . $this->language->lang('COLON') . ' ' . $metadata['version']); } if (!empty($updates_available)) { - $output->writeln(''); - $output->writeln('' . $this->language->lang('NOT_UP_TO_DATE', $metadata['name']) . ''); - - if ($input->getOption('verbose')) + if ($io->isVerbose()) { - $this->display_versions($output, $updates_available); + $io->caution($this->language->lang('NOT_UP_TO_DATE', $metadata['name'])); + + $this->display_versions($io, $updates_available); } return 1; } else { - $output->writeln(''); - $output->writeln('' . $this->language->lang('NOT_UP_TO_DATE', $metadata['name']) . ''); - - if ($input->getOption('verbose')) + if ($io->isVerbose()) { - $output->writeln('' . $this->language->lang('UPDATE_NOT_NEEDED') . ''); + $io->success($this->language->lang('UPDATE_NOT_NEEDED')); } return 0; @@ -169,54 +167,50 @@ class check extends \phpbb\console\command\command } catch (\RuntimeException $e) { - $output->writeln(''.$this->language->lang('EXTENSION_NOT_INSTALLED', $ext_name).''); + $io->error($this->language->lang('EXTENSION_NOT_INSTALLED', $ext_name)); return 1; } } /** - * Check if the core is up to date - * - * @param InputInterface $input Input stream, used to get the options. - * @param OutputInterface $output Output stream, used to print messages. - * @param OutputInterface $stability Force a given stability - * @param bool $recheck Disallow the use of the cache - * @return int - */ - protected function check_core(InputInterface $input, OutputInterface $output, $stability, $recheck) + * Check if the core is up to date + * + * @param SymfonyStyle $io IO handler, for formatted and unified IO + * @param string $stability Force a given stability + * @param bool $recheck Disallow the use of the cache + * @return int + */ + protected function check_core(SymfonyStyle $io, $stability, $recheck) { $version_helper = $this->phpbb_container->get('version_helper'); $version_helper->force_stability($stability); $updates_available = $version_helper->get_suggested_updates($recheck); - if ($input->getOption('verbose')) + if ($io->isVerbose()) { - $output->writeln('phpBB core'); - $output->writeln(''); + $io->title('phpBB core'); - $output->writeln('' . $this->language->lang('CURRENT_VERSION') . $this->language->lang('COLON') . ' ' . $this->config['version']); + $io->note( $this->language->lang('CURRENT_VERSION') . $this->language->lang('COLON') . ' ' . $this->config['version']); } if (!empty($updates_available)) { - $output->writeln(''); - $output->writeln('' . $this->language->lang('UPDATE_NEEDED') . ''); + $io->caution($this->language->lang('UPDATE_NEEDED')); - if ($input->getOption('verbose')) + if ($io->isVerbose()) { - $this->display_versions($output, $updates_available); + $this->display_versions($io, $updates_available); } return 1; } else { - if ($input->getOption('verbose')) + if ($io->isVerbose()) { - $output->writeln(''); - $output->writeln('' . $this->language->lang('UPDATE_NOT_NEEDED') . ''); + $io->success($this->language->lang('UPDATE_NOT_NEEDED')); } return 0; @@ -226,27 +220,22 @@ class check extends \phpbb\console\command\command /** * Check if all the available extensions are up to date * - * @param InputInterface $input Input stream, used to get the options. - * @param OutputInterface $output Output stream, used to print messages. - * @param OutputInterface $stability Force a given stability - * @param bool $recheck Disallow the use of the cache + * @param SymfonyStyle $io IO handler, for formatted and unified IO + * @param bool $recheck Disallow the use of the cache * @return int */ - protected function check_all_ext(InputInterface $input, OutputInterface $output, $stability, $recheck) + protected function check_all_ext(SymfonyStyle $io, $stability, $recheck) { /** @var \phpbb\extension\manager $ext_manager */ $ext_manager = $this->phpbb_container->get('ext.manager'); - $ext_name_length = max(30, strlen($this->language->lang('EXTENSION_NAME'))); - $current_version_length = max(15, strlen($this->language->lang('CURRENT_VERSION'))); - $latest_version_length = max(15, strlen($this->language->lang('LATEST_VERSION'))); + $rows = []; - $output->writeln(sprintf("%-{$ext_name_length}s | %-{$current_version_length}s | %s", $this->language->lang('EXTENSION_NAME'), $this->language->lang('CURRENT_VERSION'), $this->language->lang('LATEST_VERSION'))); - $output->writeln(sprintf("%'-{$ext_name_length}s-+-%'-{$current_version_length}s-+-%'-{$latest_version_length}s", '', '', '')); foreach ($ext_manager->all_available() as $ext_name => $ext_path) { - $message = sprintf("%-{$ext_name_length}s", $ext_name); - $md_manager = $ext_manager->create_extension_metadata_manager($ext_name, null); + $row = []; + $row[] = sprintf("%s", $ext_name); + $md_manager = $ext_manager->create_extension_metadata_manager($ext_name); try { $metadata = $md_manager->get_metadata('all'); @@ -261,70 +250,80 @@ class check extends \phpbb\console\command\command return $entry['current']; }, $updates_available); - $message .= sprintf(" | %-{$current_version_length}s | %s", - $metadata['version'], - implode(', ', $versions) - ); + $row[] = sprintf("%s", $metadata['version']); + $row[] = implode(', ', $versions); } else { - $message .= sprintf(" | %-{$current_version_length}s | ", - $metadata['version'] - ); + $row[] = sprintf("%s", $metadata['version']); + $row[] = ''; } } catch (\RuntimeException $e) { - $message .= ' | '; + $row[] = $metadata['version']; + $row[] = ''; } } else { - $message .= sprintf(" | %-{$current_version_length}s | ", $metadata['version']); + $row[] = $metadata['version']; + $row[] = ''; } } catch (exception_interface $e) { $exception_message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); - $message .= ('' . $exception_message . ''); + $row[] = '' . $exception_message . ''; } catch (\RuntimeException $e) { - $message .= ('' . $e->getMessage() . ''); + $row[] = '' . $e->getMessage() . ''; } - $output->writeln($message); + $rows[] = $row; } + $io->table([ + $this->language->lang('EXTENSION_NAME'), + $this->language->lang('CURRENT_VERSION'), + $this->language->lang('LATEST_VERSION'), + ], $rows); + return 0; } /** * Display the details of the available updates * - * @param OutputInterface $output Output stream, used to print messages. - * @param array $updates_available The list of the available updates + * @param SymfonyStyle $io IO handler, for formatted and unified IO + * @param array $updates_available The list of the available updates */ - protected function display_versions(OutputInterface $output, $updates_available) + protected function display_versions(SymfonyStyle $io, $updates_available) { - $output->writeln(''); - $output->writeln('' . $this->language->lang('UPDATES_AVAILABLE') . ''); + $io->section($this->language->lang('UPDATES_AVAILABLE')); + + $rows = []; foreach ($updates_available as $version_data) { - $messages = array(); - $messages[] = sprintf("\t%-30s| %s", $this->language->lang('VERSION'), $version_data['current']); + $row = ['', '', '']; + $row[0] = $version_data['current']; if (isset($version_data['announcement'])) { - $messages[] = sprintf("\t%-30s| %s", $this->language->lang('ANNOUNCEMENT_TOPIC'), $version_data['announcement']); + $row[1] = $version_data['announcement']; } if (isset($version_data['download'])) { - $messages[] = sprintf("\t%-30s| %s", $this->language->lang('DOWNLOAD_LATEST'), $version_data['download']); + $row[2] = $version_data['download']; } - $messages[] = ''; - - $output->writeln(implode("\n", $messages)); + $rows[] = $row; } + + $io->table([ + $this->language->lang('VERSION'), + $this->language->lang('ANNOUNCEMENT_TOPIC'), + $this->language->lang('DOWNLOAD_LATEST'), + ], $rows); } } From 103d344cd4476b452e42cd7ba0007b5a85caeaaf Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 5 Dec 2016 15:46:05 +0100 Subject: [PATCH 1396/1676] [ticket/12610] Fix tests and use getOption() for console PHPBB3-12610 --- phpBB/phpbb/console/command/update/check.php | 38 ++++++++++---------- tests/console/update/check_test.php | 19 ++++++---- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php index aaccfa4983..1f1cfa25d2 100644 --- a/phpBB/phpbb/console/command/update/check.php +++ b/phpBB/phpbb/console/command/update/check.php @@ -110,25 +110,26 @@ class check extends \phpbb\console\command\command } else { - return $this->check_ext($io, $stability, $recheck, $ext_name); + return $this->check_ext($input, $io, $stability, $recheck, $ext_name); } } else { - return $this->check_core($io,$stability, $recheck); + return $this->check_core($input, $io, $stability, $recheck); } } /** * Check if a given extension is up to date * - * @param SymfonyStyle $io IO handler, for formatted and unified IO - * @param string $stability Force a given stability - * @param bool $recheck Disallow the use of the cache - * @param string $ext_name The extension name + * @param InputInterface $input Input stream, used to get the options. + * @param SymfonyStyle $io IO handler, for formatted and unified IO + * @param string $stability Force a given stability + * @param bool $recheck Disallow the use of the cache + * @param string $ext_name The extension name * @return int */ - protected function check_ext(SymfonyStyle $io, $stability, $recheck, $ext_name) + protected function check_ext(InputInterface $input, SymfonyStyle $io, $stability, $recheck, $ext_name) { try { @@ -137,7 +138,7 @@ class check extends \phpbb\console\command\command $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); $metadata = $md_manager->get_metadata('all'); - if ($io->isVerbose()) + if ($input->getOption('verbose')) { $io->title($md_manager->get_metadata('display-name')); @@ -146,7 +147,7 @@ class check extends \phpbb\console\command\command if (!empty($updates_available)) { - if ($io->isVerbose()) + if ($input->getOption('verbose')) { $io->caution($this->language->lang('NOT_UP_TO_DATE', $metadata['name'])); @@ -157,7 +158,7 @@ class check extends \phpbb\console\command\command } else { - if ($io->isVerbose()) + if ($input->getOption('verbose')) { $io->success($this->language->lang('UPDATE_NOT_NEEDED')); } @@ -176,19 +177,20 @@ class check extends \phpbb\console\command\command /** * Check if the core is up to date * - * @param SymfonyStyle $io IO handler, for formatted and unified IO - * @param string $stability Force a given stability - * @param bool $recheck Disallow the use of the cache + * @param InputInterface $input Input stream, used to get the options. + * @param SymfonyStyle $io IO handler, for formatted and unified IO + * @param string $stability Force a given stability + * @param bool $recheck Disallow the use of the cache * @return int */ - protected function check_core(SymfonyStyle $io, $stability, $recheck) + protected function check_core(InputInterface $input, SymfonyStyle $io, $stability, $recheck) { $version_helper = $this->phpbb_container->get('version_helper'); $version_helper->force_stability($stability); $updates_available = $version_helper->get_suggested_updates($recheck); - if ($io->isVerbose()) + if ($input->getOption('verbose')) { $io->title('phpBB core'); @@ -199,7 +201,7 @@ class check extends \phpbb\console\command\command { $io->caution($this->language->lang('UPDATE_NEEDED')); - if ($io->isVerbose()) + if ($input->getOption('verbose')) { $this->display_versions($io, $updates_available); } @@ -208,7 +210,7 @@ class check extends \phpbb\console\command\command } else { - if ($io->isVerbose()) + if ($input->getOption('verbose')) { $io->success($this->language->lang('UPDATE_NOT_NEEDED')); } @@ -220,7 +222,7 @@ class check extends \phpbb\console\command\command /** * Check if all the available extensions are up to date * - * @param SymfonyStyle $io IO handler, for formatted and unified IO + * @param SymfonyStyle $io IO handler, for formatted and unified IO * @param bool $recheck Disallow the use of the cache * @return int */ diff --git a/tests/console/update/check_test.php b/tests/console/update/check_test.php index de57e4df08..5cadc5cc97 100644 --- a/tests/console/update/check_test.php +++ b/tests/console/update/check_test.php @@ -28,6 +28,9 @@ class phpbb_console_command_check_test extends phpbb_test_case protected $version_helper; + /** @var \phpbb\language\language */ + protected $language; + public function test_up_to_date() { $command_tester = $this->get_command_tester('100000'); @@ -40,7 +43,7 @@ class phpbb_console_command_check_test extends phpbb_test_case { $command_tester = $this->get_command_tester('100000'); $status = $command_tester->execute(array('command' => $this->command_name, '--no-ansi' => true, '--verbose' => true)); - $this->assertContains('UPDATE_NOT_NEEDED', $command_tester->getDisplay()); + $this->assertContains($this->language->lang('UPDATE_NOT_NEEDED'), $command_tester->getDisplay()); $this->assertSame($status, 0); } @@ -49,7 +52,7 @@ class phpbb_console_command_check_test extends phpbb_test_case { $command_tester = $this->get_command_tester('0'); $status = $command_tester->execute(array('command' => $this->command_name, '--no-ansi' => true)); - $this->assertContains('UPDATE_NEEDED', $command_tester->getDisplay()); + $this->assertContains($this->language->lang('UPDATE_NEEDED'), $command_tester->getDisplay()); $this->assertSame($status, 1); } @@ -57,8 +60,8 @@ class phpbb_console_command_check_test extends phpbb_test_case { $command_tester = $this->get_command_tester('0'); $status = $command_tester->execute(array('command' => $this->command_name, '--no-ansi' => true, '--verbose' => true)); - $this->assertContains('UPDATE_NEEDED', $command_tester->getDisplay()); - $this->assertContains('UPDATES_AVAILABLE', $command_tester->getDisplay()); + $this->assertContains($this->language->lang('UPDATE_NEEDED'), $command_tester->getDisplay()); + $this->assertContains($this->language->lang('UPDATES_AVAILABLE'), $command_tester->getDisplay()); $this->assertSame($status, 1); } @@ -77,10 +80,12 @@ class phpbb_console_command_check_test extends phpbb_test_case public function get_command_tester($current_version) { - global $user; + global $user, $phpbb_root_path, $phpEx; + + $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); $user = $this->getMock('\phpbb\user', array(), array( - new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), + $this->language, '\phpbb\datetime' )); $user->method('lang')->will($this->returnArgument(0)); @@ -96,7 +101,7 @@ class phpbb_console_command_check_test extends phpbb_test_case $container->set('version_helper', $this->version_helper); $application = new Application(); - $application->add(new check($user, $config, $container)); + $application->add(new check($user, $config, $container, $this->language)); $command = $application->find('update:check'); $this->command_name = $command->getName(); From e5504b74f0b44621003fe7826155069adc31b900 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 6 Dec 2016 14:42:14 +0100 Subject: [PATCH 1397/1676] [ticket/14892] Revert to twig 1.24 to have working assets again Twig 1.25 and after introduced a way of handling both relative and absolute paths. However, it seems to handle absolute windows paths as relative paths. This breaks any assets or similar ways of including files into the main template files. PHPBB3-14892 --- phpBB/composer.json | 2 +- phpBB/composer.lock | 172 ++++++++++++++++++++++---------------------- 2 files changed, 87 insertions(+), 87 deletions(-) diff --git a/phpBB/composer.json b/phpBB/composer.json index bffc4077c9..7145265e55 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -47,7 +47,7 @@ "symfony/routing": "^2.8", "symfony/twig-bridge": "^2.8", "symfony/yaml": "^2.8", - "twig/twig": "^1.0,<1.27" + "twig/twig": "^1.0,<1.25" }, "require-dev": { "fabpot/goutte": "~2.0", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index d3190b2dae..ec69331b13 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "307b109497afe134eca8bfff8370292f", - "content-hash": "fa6f8c1c0f46a226f55caeecda0233e4", + "hash": "9e6c5df052c3e795ad5985862bbb5797", + "content-hash": "47456b70d82a0df10e5faa0a3dc1c2ae", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -658,16 +658,16 @@ }, { "name": "s9e/text-formatter", - "version": "0.8.3", + "version": "0.8.4", "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "34668fccbe259fbca0331e7a34409c4502ee71bd" + "reference": "919fd772aae4dd889618da1cb18ae746f2a14bb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/34668fccbe259fbca0331e7a34409c4502ee71bd", - "reference": "34668fccbe259fbca0331e7a34409c4502ee71bd", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/919fd772aae4dd889618da1cb18ae746f2a14bb6", + "reference": "919fd772aae4dd889618da1cb18ae746f2a14bb6", "shasum": "" }, "require": { @@ -714,20 +714,20 @@ "parser", "shortcodes" ], - "time": "2016-11-02 08:14:58" + "time": "2016-11-22 20:10:24" }, { "name": "symfony/config", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "f8b1922bbda9d2ac86aecd649399040bce849fde" + "reference": "1361bc4e66f97b6202ae83f4190e962c624b5e61" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/f8b1922bbda9d2ac86aecd649399040bce849fde", - "reference": "f8b1922bbda9d2ac86aecd649399040bce849fde", + "url": "https://api.github.com/repos/symfony/config/zipball/1361bc4e66f97b6202ae83f4190e962c624b5e61", + "reference": "1361bc4e66f97b6202ae83f4190e962c624b5e61", "shasum": "" }, "require": { @@ -767,20 +767,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-09-14 20:31:12" + "time": "2016-11-03 07:52:58" }, { "name": "symfony/console", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "7350016c8abcab897046f1aead2b766b84d3eff8" + "reference": "a871ba00e0f604dceac64c56c27f99fbeaf4854e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/7350016c8abcab897046f1aead2b766b84d3eff8", - "reference": "7350016c8abcab897046f1aead2b766b84d3eff8", + "url": "https://api.github.com/repos/symfony/console/zipball/a871ba00e0f604dceac64c56c27f99fbeaf4854e", + "reference": "a871ba00e0f604dceac64c56c27f99fbeaf4854e", "shasum": "" }, "require": { @@ -828,20 +828,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-10-06 01:43:09" + "time": "2016-11-15 23:02:12" }, { "name": "symfony/debug", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "8c29235936a47473af16fb91c7c4b7b193c5693c" + "reference": "62a68f640456f6761d752c62d81631428ef0d8a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/8c29235936a47473af16fb91c7c4b7b193c5693c", - "reference": "8c29235936a47473af16fb91c7c4b7b193c5693c", + "url": "https://api.github.com/repos/symfony/debug/zipball/62a68f640456f6761d752c62d81631428ef0d8a1", + "reference": "62a68f640456f6761d752c62d81631428ef0d8a1", "shasum": "" }, "require": { @@ -885,20 +885,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2016-09-06 10:55:00" + "time": "2016-11-15 12:53:17" }, { "name": "symfony/dependency-injection", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "3d61c765daa1a5832f1d7c767f48886b8d8ea64c" + "reference": "9d2c5033ca70ceade8d7584f997a9d3943f0fe5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/3d61c765daa1a5832f1d7c767f48886b8d8ea64c", - "reference": "3d61c765daa1a5832f1d7c767f48886b8d8ea64c", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/9d2c5033ca70ceade8d7584f997a9d3943f0fe5f", + "reference": "9d2c5033ca70ceade8d7584f997a9d3943f0fe5f", "shasum": "" }, "require": { @@ -948,11 +948,11 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2016-10-24 15:52:36" + "time": "2016-11-18 21:10:01" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -1012,7 +1012,7 @@ }, { "name": "symfony/filesystem", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -1061,16 +1061,16 @@ }, { "name": "symfony/finder", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "bc24c8f5674c6f6841f2856b70e5d60784be5691" + "reference": "0023b024363dfc0cd21262e556f25a291fe8d7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/bc24c8f5674c6f6841f2856b70e5d60784be5691", - "reference": "bc24c8f5674c6f6841f2856b70e5d60784be5691", + "url": "https://api.github.com/repos/symfony/finder/zipball/0023b024363dfc0cd21262e556f25a291fe8d7fd", + "reference": "0023b024363dfc0cd21262e556f25a291fe8d7fd", "shasum": "" }, "require": { @@ -1106,20 +1106,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-09-28 00:10:16" + "time": "2016-11-03 07:52:58" }, { "name": "symfony/http-foundation", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "a6e6c34d337f3c74c39b29c5f54d33023de8897c" + "reference": "4f8c167732bbf3ba4284c0915f57b332091f6b68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a6e6c34d337f3c74c39b29c5f54d33023de8897c", - "reference": "a6e6c34d337f3c74c39b29c5f54d33023de8897c", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4f8c167732bbf3ba4284c0915f57b332091f6b68", + "reference": "4f8c167732bbf3ba4284c0915f57b332091f6b68", "shasum": "" }, "require": { @@ -1161,20 +1161,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2016-10-24 15:52:36" + "time": "2016-11-15 23:02:12" }, { "name": "symfony/http-kernel", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "ba7249f746da1544512c942c50ef3bc4026296e6" + "reference": "29d9bb59c6d895e65d8fea3859c96c3b6e9368ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ba7249f746da1544512c942c50ef3bc4026296e6", - "reference": "ba7249f746da1544512c942c50ef3bc4026296e6", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/29d9bb59c6d895e65d8fea3859c96c3b6e9368ba", + "reference": "29d9bb59c6d895e65d8fea3859c96c3b6e9368ba", "shasum": "" }, "require": { @@ -1243,7 +1243,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2016-10-27 02:18:22" + "time": "2016-11-21 02:24:42" }, { "name": "symfony/polyfill-mbstring", @@ -1420,7 +1420,7 @@ }, { "name": "symfony/proxy-manager-bridge", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/proxy-manager-bridge.git", @@ -1474,7 +1474,7 @@ }, { "name": "symfony/routing", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", @@ -1549,21 +1549,21 @@ }, { "name": "symfony/twig-bridge", - "version": "v2.8.12", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "5586685d161c411ab33a9ea72d3b25a337337942" + "reference": "5e9679f7085e99adb5248e07b4677494b8f884b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/5586685d161c411ab33a9ea72d3b25a337337942", - "reference": "5586685d161c411ab33a9ea72d3b25a337337942", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/5e9679f7085e99adb5248e07b4677494b8f884b5", + "reference": "5e9679f7085e99adb5248e07b4677494b8f884b5", "shasum": "" }, "require": { "php": ">=5.3.9", - "twig/twig": "~1.26|~2.0" + "twig/twig": "~1.23|~2.0" }, "require-dev": { "symfony/asset": "~2.7|~3.0.0", @@ -1626,20 +1626,20 @@ ], "description": "Symfony Twig Bridge", "homepage": "https://symfony.com", - "time": "2016-10-03 15:49:46" + "time": "2016-09-06 10:55:00" }, { "name": "symfony/yaml", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "396784cd06b91f3db576f248f2402d547a077787" + "reference": "befb26a3713c97af90d25dd12e75621ef14d91ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/396784cd06b91f3db576f248f2402d547a077787", - "reference": "396784cd06b91f3db576f248f2402d547a077787", + "url": "https://api.github.com/repos/symfony/yaml/zipball/befb26a3713c97af90d25dd12e75621ef14d91ff", + "reference": "befb26a3713c97af90d25dd12e75621ef14d91ff", "shasum": "" }, "require": { @@ -1675,20 +1675,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-10-21 20:59:10" + "time": "2016-11-14 16:15:57" }, { "name": "twig/twig", - "version": "v1.26.1", + "version": "v1.24.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "a09d8ee17ac1cfea29ed60c83960ad685c6a898d" + "reference": "33093f6e310e6976baeac7b14f3a6ec02f2d79b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/a09d8ee17ac1cfea29ed60c83960ad685c6a898d", - "reference": "a09d8ee17ac1cfea29ed60c83960ad685c6a898d", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/33093f6e310e6976baeac7b14f3a6ec02f2d79b7", + "reference": "33093f6e310e6976baeac7b14f3a6ec02f2d79b7", "shasum": "" }, "require": { @@ -1701,7 +1701,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.26-dev" + "dev-master": "1.24-dev" } }, "autoload": { @@ -1736,7 +1736,7 @@ "keywords": [ "templating" ], - "time": "2016-10-05 18:57:41" + "time": "2016-09-01 17:50:53" }, { "name": "zendframework/zend-code", @@ -2716,22 +2716,22 @@ }, { "name": "sebastian/comparator", - "version": "1.2.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { "phpunit/phpunit": "~4.4" @@ -2776,7 +2776,7 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2016-11-19 09:18:40" }, { "name": "sebastian/diff", @@ -3037,16 +3037,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "2.7.0", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed" + "reference": "9b324f3a1132459a7274a0ace2e1b766ba80930f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", - "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9b324f3a1132459a7274a0ace2e1b766ba80930f", + "reference": "9b324f3a1132459a7274a0ace2e1b766ba80930f", "shasum": "" }, "require": { @@ -3111,11 +3111,11 @@ "phpcs", "standards" ], - "time": "2016-09-01 23:53:02" + "time": "2016-11-30 04:02:31" }, { "name": "symfony/browser-kit", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", @@ -3172,16 +3172,16 @@ }, { "name": "symfony/css-selector", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "71c8c3a04c126300c37089b1baa7c6322dfb845f" + "reference": "981abbbd6ba49af338a98490cbe29e7f39ca9fa9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/71c8c3a04c126300c37089b1baa7c6322dfb845f", - "reference": "71c8c3a04c126300c37089b1baa7c6322dfb845f", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/981abbbd6ba49af338a98490cbe29e7f39ca9fa9", + "reference": "981abbbd6ba49af338a98490cbe29e7f39ca9fa9", "shasum": "" }, "require": { @@ -3221,20 +3221,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2016-09-06 10:55:00" + "time": "2016-11-03 07:52:58" }, { "name": "symfony/dom-crawler", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "a94f3fe6f179d6453e5ed8188cf4bfdf933d85f4" + "reference": "7f565fe00e580c1edf732234a6d26e9b796bd105" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/a94f3fe6f179d6453e5ed8188cf4bfdf933d85f4", - "reference": "a94f3fe6f179d6453e5ed8188cf4bfdf933d85f4", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/7f565fe00e580c1edf732234a6d26e9b796bd105", + "reference": "7f565fe00e580c1edf732234a6d26e9b796bd105", "shasum": "" }, "require": { @@ -3277,11 +3277,11 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2016-10-18 15:35:45" + "time": "2016-11-14 16:15:57" }, { "name": "symfony/process", - "version": "v2.8.13", + "version": "v2.8.14", "source": { "type": "git", "url": "https://github.com/symfony/process.git", From fd95da909aff360c7c41c04ff2cadedb9ab2e222 Mon Sep 17 00:00:00 2001 From: rxu Date: Tue, 6 Dec 2016 23:42:49 +0700 Subject: [PATCH 1398/1676] [ticket/14893] Fix undefined variable on reporting PM notification PHPBB3-14893 --- phpBB/phpbb/notification/type/report_pm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php index 239805204c..7e53ffb3ca 100644 --- a/phpBB/phpbb/notification/type/report_pm.php +++ b/phpBB/phpbb/notification/type/report_pm.php @@ -142,7 +142,7 @@ class report_pm extends \phpbb\notification\type\pm */ public function get_email_template_variables() { - $user_data = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile'); + $user_data = $this->user_loader->get_user($this->get_data('reporter_id')); return array( 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']), From 74cd513a8892285032a248322e3ce52b19645075 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Wed, 7 Dec 2016 10:13:09 -0800 Subject: [PATCH 1399/1676] [ticket/14895] CLI reparser:list should display proper list PHPBB3-14895 --- phpBB/language/en/cli.php | 1 + phpBB/phpbb/console/command/reparser/list_all.php | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 6e86c75ec0..9940609364 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -68,6 +68,7 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_PURGE_EXTENSION' => 'Purges the specified extension.', 'CLI_DESCRIPTION_REPARSER_LIST' => 'Lists the types of text that can be reparsed.', + 'CLI_DESCRIPTION_REPARSER_AVAILABLE' => 'Available reparsers:', 'CLI_DESCRIPTION_REPARSER_REPARSE' => 'Reparses stored text with the current text_formatter services.', 'CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1' => 'Type of text to reparse. Leave blank to reparse everything.', 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_DRY_RUN' => 'Do not save any changes; just print what would happen', diff --git a/phpBB/phpbb/console/command/reparser/list_all.php b/phpBB/phpbb/console/command/reparser/list_all.php index e42c3ac782..7dd0571975 100644 --- a/phpBB/phpbb/console/command/reparser/list_all.php +++ b/phpBB/phpbb/console/command/reparser/list_all.php @@ -54,7 +54,7 @@ class list_all extends \phpbb\console\command\command } /** - * Executes the command reparser:reparse + * Executes the command reparser:list * * @param InputInterface $input * @param OutputInterface $output @@ -62,7 +62,11 @@ class list_all extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { - $output->writeln('' . implode(', ', $this->reparser_names) . ''); + $output->writeln('' . $this->user->lang('CLI_DESCRIPTION_REPARSER_AVAILABLE') . ''); + foreach ($this->reparser_names as $reparser_name) + { + $output->writeln($reparser_name); + } return 0; } From 829e1475044f1a72f68958923a0900ed4e62f78e Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 7 Dec 2016 17:55:57 +0100 Subject: [PATCH 1400/1676] [ticket/14896] Do not overwrite login when finishing install Otherwise the user will be "logged in" again as guest user which will prevent any redirectiong to the ACP after the installation. PHPBB3-14896 --- phpBB/phpbb/install/installer.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php index a7d3b99dcb..e04e233a76 100644 --- a/phpBB/phpbb/install/installer.php +++ b/phpBB/phpbb/install/installer.php @@ -243,12 +243,18 @@ class installer } else { - // Start session and try to apply session id - $auth = $this->container_factory->get('auth'); + // Start session if not installing and get user object + // to allow redirecting to ACP $user = $this->container_factory->get('user'); - $user->session_begin(); - $auth->acl($user->data); - $user->setup(); + if (!isset($module) || !($module instanceof \phpbb\install\module\install_finish\module)) + { + $auth = $this->container_factory->get('auth'); + + $user->session_begin(); + $auth->acl($user->data); + $user->setup(); + } + $phpbb_root_path = $this->container_factory->get_parameter('core.root_path'); $acp_url = append_sid($phpbb_root_path . 'adm/index.php', 'i=acp_help_phpbb&mode=help_phpbb', true, $user->session_id); From f2fde5e7a32943017f7f22b070c974f161d14d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Bartus?= Date: Wed, 7 Dec 2016 21:01:47 +0100 Subject: [PATCH 1401/1676] [ticket/14897] Add $restart_progress_bar to iohandler base PHPBB3-14897 --- phpBB/phpbb/install/helper/iohandler/iohandler_base.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php index fed4bc101f..1797a6c9ad 100644 --- a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php +++ b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php @@ -70,6 +70,11 @@ abstract class iohandler_base implements iohandler_interface */ protected $current_task_name; + /** + * @var bool + */ + protected $restart_progress_bar; + /** * Constructor */ From d275fefc69bae24f547802d824607c9a054ff6d2 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Wed, 7 Dec 2016 23:49:54 -0800 Subject: [PATCH 1402/1676] [ticket/14895] Use SymfonyIO styling PHPBB3-14895 --- phpBB/phpbb/console/command/reparser/list_all.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/console/command/reparser/list_all.php b/phpBB/phpbb/console/command/reparser/list_all.php index 7dd0571975..028468649d 100644 --- a/phpBB/phpbb/console/command/reparser/list_all.php +++ b/phpBB/phpbb/console/command/reparser/list_all.php @@ -15,6 +15,7 @@ namespace phpbb\console\command\reparser; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class list_all extends \phpbb\console\command\command { @@ -62,11 +63,9 @@ class list_all extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { - $output->writeln('' . $this->user->lang('CLI_DESCRIPTION_REPARSER_AVAILABLE') . ''); - foreach ($this->reparser_names as $reparser_name) - { - $output->writeln($reparser_name); - } + $io = new SymfonyStyle($input, $output); + $io->section($this->user->lang('CLI_DESCRIPTION_REPARSER_AVAILABLE')); + $io->listing($this->reparser_names); return 0; } From 4c36ca4b8581a63083e8508d90949d5ccdde6d75 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 8 Dec 2016 21:17:50 +0100 Subject: [PATCH 1403/1676] [ticket/14900] Do not state missing cached version check means ext is invalid Also fixed typo in code that was looming there for a while. PHPBB3-14900 --- phpBB/includes/acp/acp_extensions.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index ea6feb3e6a..e081eae975 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -451,6 +451,10 @@ class acp_extensions $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false; } } + catch (version_check_exception $e) + { + $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false; + } catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); @@ -461,7 +465,7 @@ class acp_extensions } catch (\RuntimeException $e) { - $disabeld_extension_meta_data[$name]['S_VERSIONCHECK'] = false; + $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false; } } From b17fa7dfa588fc191f4ed268b88dcaec40294acb Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Thu, 8 Dec 2016 14:24:02 -0800 Subject: [PATCH 1404/1676] [ticket/14895] Use SymfonyStyle in all CLI PHPBB3-14895 --- phpBB/phpbb/console/command/cache/purge.php | 4 +- phpBB/phpbb/console/command/config/delete.php | 7 +++- phpBB/phpbb/console/command/config/get.php | 5 ++- .../console/command/config/increment.php | 5 ++- phpBB/phpbb/console/command/config/set.php | 5 ++- .../console/command/config/set_atomic.php | 7 +++- .../phpbb/console/command/cron/cron_list.php | 39 ++++++------------- .../phpbb/console/command/db/list_command.php | 30 ++++++++------ phpBB/phpbb/console/command/db/migrate.php | 7 +++- phpBB/phpbb/console/command/db/revert.php | 10 +++-- .../console/command/extension/disable.php | 7 +++- .../console/command/extension/enable.php | 7 +++- .../phpbb/console/command/extension/purge.php | 7 +++- .../phpbb/console/command/extension/show.php | 28 +++++-------- .../command/fixup/recalculate_email_hash.php | 15 +++---- 15 files changed, 100 insertions(+), 83 deletions(-) diff --git a/phpBB/phpbb/console/command/cache/purge.php b/phpBB/phpbb/console/command/cache/purge.php index d0c2ef6f72..1da97624f5 100644 --- a/phpBB/phpbb/console/command/cache/purge.php +++ b/phpBB/phpbb/console/command/cache/purge.php @@ -14,6 +14,7 @@ namespace phpbb\console\command\cache; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class purge extends \phpbb\console\command\command { @@ -84,6 +85,7 @@ class purge extends \phpbb\console\command\command $this->log->add('admin', ANONYMOUS, '', 'LOG_PURGE_CACHE', time(), array()); - $output->writeln($this->user->lang('PURGE_CACHE_SUCCESS')); + $io = new SymfonyStyle($input, $output); + $io->success($this->user->lang('PURGE_CACHE_SUCCESS')); } } diff --git a/phpBB/phpbb/console/command/config/delete.php b/phpBB/phpbb/console/command/config/delete.php index efd276d7e3..a1ccefe286 100644 --- a/phpBB/phpbb/console/command/config/delete.php +++ b/phpBB/phpbb/console/command/config/delete.php @@ -15,6 +15,7 @@ namespace phpbb\console\command\config; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class delete extends command { @@ -47,17 +48,19 @@ class delete extends command */ protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $key = $input->getArgument('key'); if (isset($this->config[$key])) { $this->config->delete($key); - $output->writeln('' . $this->user->lang('CLI_CONFIG_DELETE_SUCCESS', $key) . ''); + $io->success($this->user->lang('CLI_CONFIG_DELETE_SUCCESS', $key)); } else { - $output->writeln('' . $this->user->lang('CLI_CONFIG_NOT_EXISTS', $key) . ''); + $io->error($this->user->lang('CLI_CONFIG_NOT_EXISTS', $key)); } } } diff --git a/phpBB/phpbb/console/command/config/get.php b/phpBB/phpbb/console/command/config/get.php index 9c03b49a3d..b2b824dd12 100644 --- a/phpBB/phpbb/console/command/config/get.php +++ b/phpBB/phpbb/console/command/config/get.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class get extends command { @@ -54,6 +55,8 @@ class get extends command */ protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $key = $input->getArgument('key'); if (isset($this->config[$key]) && $input->getOption('no-newline')) @@ -66,7 +69,7 @@ class get extends command } else { - $output->writeln('' . $this->user->lang('CLI_CONFIG_NOT_EXISTS', $key) . ''); + $io->error($this->user->lang('CLI_CONFIG_NOT_EXISTS', $key)); } } } diff --git a/phpBB/phpbb/console/command/config/increment.php b/phpBB/phpbb/console/command/config/increment.php index b4d7438b66..8b3acc1620 100644 --- a/phpBB/phpbb/console/command/config/increment.php +++ b/phpBB/phpbb/console/command/config/increment.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class increment extends command { @@ -59,12 +60,14 @@ class increment extends command */ protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $key = $input->getArgument('key'); $increment = $input->getArgument('increment'); $use_cache = !$input->getOption('dynamic'); $this->config->increment($key, $increment, $use_cache); - $output->writeln('' . $this->user->lang('CLI_CONFIG_INCREMENT_SUCCESS', $key) . ''); + $io->success($this->user->lang('CLI_CONFIG_INCREMENT_SUCCESS', $key)); } } diff --git a/phpBB/phpbb/console/command/config/set.php b/phpBB/phpbb/console/command/config/set.php index 695de31013..889fb630c6 100644 --- a/phpBB/phpbb/console/command/config/set.php +++ b/phpBB/phpbb/console/command/config/set.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class set extends command { @@ -59,12 +60,14 @@ class set extends command */ protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $key = $input->getArgument('key'); $value = $input->getArgument('value'); $use_cache = !$input->getOption('dynamic'); $this->config->set($key, $value, $use_cache); - $output->writeln('' . $this->user->lang('CLI_CONFIG_SET_SUCCESS', $key) . ''); + $io->success($this->user->lang('CLI_CONFIG_SET_SUCCESS', $key)); } } diff --git a/phpBB/phpbb/console/command/config/set_atomic.php b/phpBB/phpbb/console/command/config/set_atomic.php index e8c69a0885..475d8a9271 100644 --- a/phpBB/phpbb/console/command/config/set_atomic.php +++ b/phpBB/phpbb/console/command/config/set_atomic.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class set_atomic extends command { @@ -65,6 +66,8 @@ class set_atomic extends command */ protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $key = $input->getArgument('key'); $old_value = $input->getArgument('old'); $new_value = $input->getArgument('new'); @@ -72,12 +75,12 @@ class set_atomic extends command if ($this->config->set_atomic($key, $old_value, $new_value, $use_cache)) { - $output->writeln('' . $this->user->lang('CLI_CONFIG_SET_SUCCESS', $key) . ''); + $io->success($this->user->lang('CLI_CONFIG_SET_SUCCESS', $key)); return 0; } else { - $output->writeln('' . $this->user->lang('CLI_CONFIG_SET_FAILURE', $key) . ''); + $io->error($this->user->lang('CLI_CONFIG_SET_FAILURE', $key)); return 1; } } diff --git a/phpBB/phpbb/console/command/cron/cron_list.php b/phpBB/phpbb/console/command/cron/cron_list.php index c515fd9e80..0618cee4db 100644 --- a/phpBB/phpbb/console/command/cron/cron_list.php +++ b/phpBB/phpbb/console/command/cron/cron_list.php @@ -14,6 +14,7 @@ namespace phpbb\console\command\cron; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class cron_list extends \phpbb\console\command\command { @@ -55,57 +56,39 @@ class cron_list extends \phpbb\console\command\command */ protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $tasks = $this->cron_manager->get_tasks(); if (empty($tasks)) { - $output->writeln($this->user->lang('CRON_NO_TASKS')); + $io->error($this->user->lang('CRON_NO_TASKS')); return; } - $ready_tasks = array(); - $not_ready_tasks = array(); + $ready_tasks = $not_ready_tasks = array(); foreach ($tasks as $task) { if ($task->is_ready()) { - $ready_tasks[] = $task; + $ready_tasks[] = $task->get_name(); } else { - $not_ready_tasks[] = $task; + $not_ready_tasks[] = $task->get_name(); } } if (!empty($ready_tasks)) { - $output->writeln('' . $this->user->lang('TASKS_READY') . ''); - $this->print_tasks_names($ready_tasks, $output); - } - - if (!empty($ready_tasks) && !empty($not_ready_tasks)) - { - $output->writeln(''); + $io->section($this->user->lang('TASKS_READY')); + $io->listing($ready_tasks); } if (!empty($not_ready_tasks)) { - $output->writeln('' . $this->user->lang('TASKS_NOT_READY') . ''); - $this->print_tasks_names($not_ready_tasks, $output); - } - } - - /** - * Print a list of cron jobs - * - * @param array $tasks A list of task to display - * @param OutputInterface $output An OutputInterface instance - */ - protected function print_tasks_names(array $tasks, OutputInterface $output) - { - foreach ($tasks as $task) - { - $output->writeln($task->get_name()); + $io->section($this->user->lang('TASKS_NOT_READY')); + $io->listing($not_ready_tasks); } } } diff --git a/phpBB/phpbb/console/command/db/list_command.php b/phpBB/phpbb/console/command/db/list_command.php index 708107b592..77f26dd786 100644 --- a/phpBB/phpbb/console/command/db/list_command.php +++ b/phpBB/phpbb/console/command/db/list_command.php @@ -15,6 +15,7 @@ namespace phpbb\console\command\db; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class list_command extends \phpbb\console\command\db\migration_command { @@ -34,6 +35,8 @@ class list_command extends \phpbb\console\command\db\migration_command protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $show_installed = !$input->getOption('available'); $installed = $available = array(); @@ -51,23 +54,28 @@ class list_command extends \phpbb\console\command\db\migration_command if ($show_installed) { - $output->writeln('' . $this->user->lang('CLI_MIGRATIONS_INSTALLED') . $this->user->lang('COLON') . ''); - $output->writeln($installed); + $io->section($this->user->lang('CLI_MIGRATIONS_INSTALLED')); - if (empty($installed)) + if (!empty($installed)) { - $output->writeln($this->user->lang('CLI_MIGRATIONS_EMPTY')); + $io->listing($installed); + } + else + { + $io->text($this->user->lang('CLI_MIGRATIONS_EMPTY')); + $io->newLine(); } - - $output->writeln(''); } - $output->writeln('' . $this->user->lang('CLI_MIGRATIONS_AVAILABLE') . $this->user->lang('COLON') . ''); - $output->writeln($available); - - if (empty($available)) + $io->section($this->user->lang('CLI_MIGRATIONS_AVAILABLE')); + if (!empty($available)) { - $output->writeln($this->user->lang('CLI_MIGRATIONS_EMPTY')); + $io->listing($available); + } + else + { + $io->text($this->user->lang('CLI_MIGRATIONS_EMPTY')); + $io->newLine(); } } } diff --git a/phpBB/phpbb/console/command/db/migrate.php b/phpBB/phpbb/console/command/db/migrate.php index ae4211f7be..f2cc9142a6 100644 --- a/phpBB/phpbb/console/command/db/migrate.php +++ b/phpBB/phpbb/console/command/db/migrate.php @@ -15,6 +15,7 @@ namespace phpbb\console\command\db; use phpbb\db\output_handler\log_wrapper_migrator_output_handler; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class migrate extends \phpbb\console\command\db\migration_command { @@ -50,6 +51,8 @@ class migrate extends \phpbb\console\command\db\migration_command protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $this->migrator->set_output_handler(new log_wrapper_migrator_output_handler($this->language, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem)); $this->migrator->create_migrations_table(); @@ -66,7 +69,7 @@ class migrate extends \phpbb\console\command\db\migration_command } catch (\phpbb\db\migration\exception $e) { - $output->writeln('' . $e->getLocalisedMessage($this->user) . ''); + $io->error($e->getLocalisedMessage($this->user)); $this->finalise_update(); return 1; } @@ -78,6 +81,6 @@ class migrate extends \phpbb\console\command\db\migration_command } $this->finalise_update(); - $output->writeln($this->user->lang['DATABASE_UPDATE_COMPLETE']); + $io->success($this->language->lang('INLINE_UPDATE_SUCCESSFUL')); } } diff --git a/phpBB/phpbb/console/command/db/revert.php b/phpBB/phpbb/console/command/db/revert.php index 3fa2e17515..7977afc319 100644 --- a/phpBB/phpbb/console/command/db/revert.php +++ b/phpBB/phpbb/console/command/db/revert.php @@ -16,6 +16,7 @@ use phpbb\db\output_handler\log_wrapper_migrator_output_handler; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class revert extends \phpbb\console\command\db\migration_command { @@ -52,6 +53,8 @@ class revert extends \phpbb\console\command\db\migration_command protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $name = str_replace('/', '\\', $input->getArgument('name')); $this->migrator->set_output_handler(new log_wrapper_migrator_output_handler($this->language, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem)); @@ -60,12 +63,12 @@ class revert extends \phpbb\console\command\db\migration_command if (!in_array($name, $this->load_migrations())) { - $output->writeln('' . $this->user->lang('MIGRATION_NOT_VALID', $name) . ''); + $io->error($this->language->lang('MIGRATION_NOT_VALID', $name)); return 1; } else if ($this->migrator->migration_state($name) === false) { - $output->writeln('' . $this->user->lang('MIGRATION_NOT_INSTALLED', $name) . ''); + $io->error($this->language->lang('MIGRATION_NOT_INSTALLED', $name)); return 1; } @@ -78,11 +81,12 @@ class revert extends \phpbb\console\command\db\migration_command } catch (\phpbb\db\migration\exception $e) { - $output->writeln('' . $e->getLocalisedMessage($this->user) . ''); + $io->error($e->getLocalisedMessage($this->user)); $this->finalise_update(); return 1; } $this->finalise_update(); + $io->success($this->language->lang('INLINE_UPDATE_SUCCESSFUL')); } } diff --git a/phpBB/phpbb/console/command/extension/disable.php b/phpBB/phpbb/console/command/extension/disable.php index 1eee16cbd9..d022755753 100644 --- a/phpBB/phpbb/console/command/extension/disable.php +++ b/phpBB/phpbb/console/command/extension/disable.php @@ -15,6 +15,7 @@ namespace phpbb\console\command\extension; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class disable extends command { @@ -33,19 +34,21 @@ class disable extends command protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $name = $input->getArgument('extension-name'); $this->manager->disable($name); $this->manager->load_extensions(); if ($this->manager->is_enabled($name)) { - $output->writeln('' . $this->user->lang('CLI_EXTENSION_DISABLE_FAILURE', $name) . ''); + $io->error($this->user->lang('CLI_EXTENSION_DISABLE_FAILURE', $name)); return 1; } else { $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_DISABLE', time(), array($name)); - $output->writeln('' . $this->user->lang('CLI_EXTENSION_DISABLE_SUCCESS', $name) . ''); + $io->success($this->user->lang('CLI_EXTENSION_DISABLE_SUCCESS', $name)); return 0; } } diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index 59ff11e9b7..14077d688b 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -15,6 +15,7 @@ namespace phpbb\console\command\extension; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class enable extends command { @@ -33,6 +34,8 @@ class enable extends command protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $name = $input->getArgument('extension-name'); $this->manager->enable($name); $this->manager->load_extensions(); @@ -40,12 +43,12 @@ class enable extends command if ($this->manager->is_enabled($name)) { $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_ENABLE', time(), array($name)); - $output->writeln('' . $this->user->lang('CLI_EXTENSION_ENABLE_SUCCESS', $name) . ''); + $io->success($this->user->lang('CLI_EXTENSION_ENABLE_SUCCESS', $name)); return 0; } else { - $output->writeln('' . $this->user->lang('CLI_EXTENSION_ENABLE_FAILURE', $name) . ''); + $io->error($this->user->lang('CLI_EXTENSION_ENABLE_FAILURE', $name)); return 1; } } diff --git a/phpBB/phpbb/console/command/extension/purge.php b/phpBB/phpbb/console/command/extension/purge.php index 517e9a74c9..25bde503f7 100644 --- a/phpBB/phpbb/console/command/extension/purge.php +++ b/phpBB/phpbb/console/command/extension/purge.php @@ -15,6 +15,7 @@ namespace phpbb\console\command\extension; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class purge extends command { @@ -33,19 +34,21 @@ class purge extends command protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $name = $input->getArgument('extension-name'); $this->manager->purge($name); $this->manager->load_extensions(); if ($this->manager->is_enabled($name)) { - $output->writeln('' . $this->user->lang('CLI_EXTENSION_PURGE_FAILURE', $name) . ''); + $io->error($this->user->lang('CLI_EXTENSION_PURGE_FAILURE', $name)); return 1; } else { $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_PURGE', time(), array($name)); - $output->writeln('' . $this->user->lang('CLI_EXTENSION_PURGE_SUCCESS', $name) . ''); + $io->success($this->user->lang('CLI_EXTENSION_PURGE_SUCCESS', $name)); return 0; } } diff --git a/phpBB/phpbb/console/command/extension/show.php b/phpBB/phpbb/console/command/extension/show.php index f9322034d7..7bad0c0a5a 100644 --- a/phpBB/phpbb/console/command/extension/show.php +++ b/phpBB/phpbb/console/command/extension/show.php @@ -14,6 +14,7 @@ namespace phpbb\console\command\extension; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class show extends command { @@ -27,36 +28,27 @@ class show extends command protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $this->manager->load_extensions(); $all = array_keys($this->manager->all_available()); if (empty($all)) { - $output->writeln('' . $this->user->lang('CLI_EXTENSION_NOT_FOUND') . ''); + $io->note($this->user->lang('CLI_EXTENSION_NOT_FOUND')); return 3; } $enabled = array_keys($this->manager->all_enabled()); - $this->print_extension_list($output, $this->user->lang('CLI_EXTENSIONS_ENABLED') . $this->user->lang('COLON'), $enabled); - - $output->writeln(''); + $io->section($this->user->lang('CLI_EXTENSIONS_ENABLED')); + $io->listing($enabled); $disabled = array_keys($this->manager->all_disabled()); - $this->print_extension_list($output, $this->user->lang('CLI_EXTENSIONS_DISABLED') . $this->user->lang('COLON'), $disabled); - - $output->writeln(''); + $io->section($this->user->lang('CLI_EXTENSIONS_DISABLED')); + $io->listing($disabled); $purged = array_diff($all, $enabled, $disabled); - $this->print_extension_list($output, $this->user->lang('CLI_EXTENSIONS_AVAILABLE') . $this->user->lang('COLON'), $purged); - } - - protected function print_extension_list(OutputInterface $output, $type, array $extensions) - { - $output->writeln("$type"); - - foreach ($extensions as $extension) - { - $output->writeln(" - $extension"); - } + $io->section($this->user->lang('CLI_EXTENSIONS_AVAILABLE')); + $io->listing($purged); } } diff --git a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php index ec4e1b0ee7..043f181e72 100644 --- a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php +++ b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php @@ -14,6 +14,7 @@ namespace phpbb\console\command\fixup; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; class recalculate_email_hash extends \phpbb\console\command\command { @@ -37,6 +38,8 @@ class recalculate_email_hash extends \phpbb\console\command\command protected function execute(InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $sql = 'SELECT user_id, user_email, user_email_hash FROM ' . USERS_TABLE . ' WHERE user_type <> ' . USER_IGNORE . " @@ -59,17 +62,15 @@ class recalculate_email_hash extends \phpbb\console\command\command if ($output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) { - $output->writeln(sprintf( - 'user_id %d, email %s => %s', - $row['user_id'], - $row['user_email'], - $user_email_hash - )); + $io->table( + array('user_id', 'user_email', 'user_email_hash'), + array(array($row['user_id'], $row['user_email'], $user_email_hash)) + ); } } } $this->db->sql_freeresult($result); - $output->writeln('' . $this->user->lang('CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS') . ''); + $io->success($this->user->lang('CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS')); } } From cbf6d71f6859fd6c036967ed19082f3e54efc328 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Thu, 8 Dec 2016 14:25:09 -0800 Subject: [PATCH 1405/1676] [ticket/14895] Fix issues in CLI classes PHPBB3-14895 --- .../default/container/services_console.yml | 10 +------- phpBB/phpbb/console/command/cache/purge.php | 4 ++-- .../phpbb/console/command/config/command.php | 2 +- phpBB/phpbb/console/command/config/delete.php | 2 +- phpBB/phpbb/console/command/config/get.php | 2 +- .../console/command/config/increment.php | 2 +- phpBB/phpbb/console/command/config/set.php | 2 +- .../phpbb/console/command/cron/cron_list.php | 2 +- phpBB/phpbb/console/command/db/migrate.php | 6 ++--- .../console/command/db/migration_command.php | 2 +- phpBB/phpbb/console/command/db/revert.php | 24 +++---------------- .../console/command/dev/migration_tips.php | 2 +- .../command/fixup/recalculate_email_hash.php | 2 +- 13 files changed, 18 insertions(+), 44 deletions(-) diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 0c609a8051..e25ab4f03f 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -111,15 +111,7 @@ services: console.command.db.revert: class: phpbb\console\command\db\revert - arguments: - - '@user' - - '@language' - - '@migrator' - - '@ext.manager' - - '@config' - - '@cache' - - '@filesystem' - - '%core.root_path%' + parent: console.command.db.migrate tags: - { name: console.command } diff --git a/phpBB/phpbb/console/command/cache/purge.php b/phpBB/phpbb/console/command/cache/purge.php index 1da97624f5..b7a51b2bb4 100644 --- a/phpBB/phpbb/console/command/cache/purge.php +++ b/phpBB/phpbb/console/command/cache/purge.php @@ -40,7 +40,7 @@ class purge extends \phpbb\console\command\command * @param \phpbb\cache\driver\driver_interface $cache Cache instance * @param \phpbb\db\driver\driver_interface $db Database connection * @param \phpbb\auth\auth $auth Auth instance - * @param \phpbb\log\log $log Logger instance + * @param \phpbb\log\log_interface $log Logger instance * @param \phpbb\config\config $config Config instance */ public function __construct(\phpbb\user $user, \phpbb\cache\driver\driver_interface $cache, \phpbb\db\driver\driver_interface $db, \phpbb\auth\auth $auth, \phpbb\log\log_interface $log, \phpbb\config\config $config) @@ -72,7 +72,7 @@ class purge extends \phpbb\console\command\command * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * - * @return null + * @return void */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/phpBB/phpbb/console/command/config/command.php b/phpBB/phpbb/console/command/config/command.php index f0ad5d4d19..19f67d3b6c 100644 --- a/phpBB/phpbb/console/command/config/command.php +++ b/phpBB/phpbb/console/command/config/command.php @@ -17,7 +17,7 @@ abstract class command extends \phpbb\console\command\command /** @var \phpbb\config\config */ protected $config; - function __construct(\phpbb\user $user, \phpbb\config\config $config) + public function __construct(\phpbb\user $user, \phpbb\config\config $config) { $this->config = $config; diff --git a/phpBB/phpbb/console/command/config/delete.php b/phpBB/phpbb/console/command/config/delete.php index a1ccefe286..2da0801337 100644 --- a/phpBB/phpbb/console/command/config/delete.php +++ b/phpBB/phpbb/console/command/config/delete.php @@ -43,7 +43,7 @@ class delete extends command * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * - * @return null + * @return void * @see \phpbb\config\config::delete() */ protected function execute(InputInterface $input, OutputInterface $output) diff --git a/phpBB/phpbb/console/command/config/get.php b/phpBB/phpbb/console/command/config/get.php index b2b824dd12..f065787110 100644 --- a/phpBB/phpbb/console/command/config/get.php +++ b/phpBB/phpbb/console/command/config/get.php @@ -50,7 +50,7 @@ class get extends command * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * - * @return null + * @return void * @see \phpbb\config\config::offsetGet() */ protected function execute(InputInterface $input, OutputInterface $output) diff --git a/phpBB/phpbb/console/command/config/increment.php b/phpBB/phpbb/console/command/config/increment.php index 8b3acc1620..647380a0bf 100644 --- a/phpBB/phpbb/console/command/config/increment.php +++ b/phpBB/phpbb/console/command/config/increment.php @@ -55,7 +55,7 @@ class increment extends command * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * - * @return null + * @return void * @see \phpbb\config\config::increment() */ protected function execute(InputInterface $input, OutputInterface $output) diff --git a/phpBB/phpbb/console/command/config/set.php b/phpBB/phpbb/console/command/config/set.php index 889fb630c6..e9f7f8f91e 100644 --- a/phpBB/phpbb/console/command/config/set.php +++ b/phpBB/phpbb/console/command/config/set.php @@ -55,7 +55,7 @@ class set extends command * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * - * @return null + * @return void * @see \phpbb\config\config::set() */ protected function execute(InputInterface $input, OutputInterface $output) diff --git a/phpBB/phpbb/console/command/cron/cron_list.php b/phpBB/phpbb/console/command/cron/cron_list.php index 0618cee4db..8f9d63eda2 100644 --- a/phpBB/phpbb/console/command/cron/cron_list.php +++ b/phpBB/phpbb/console/command/cron/cron_list.php @@ -52,7 +52,7 @@ class cron_list extends \phpbb\console\command\command * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * - * @return null + * @return void */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/phpBB/phpbb/console/command/db/migrate.php b/phpBB/phpbb/console/command/db/migrate.php index f2cc9142a6..4270e2d703 100644 --- a/phpBB/phpbb/console/command/db/migrate.php +++ b/phpBB/phpbb/console/command/db/migrate.php @@ -31,21 +31,21 @@ class migrate extends \phpbb\console\command\db\migration_command /** @var \phpbb\language\language */ protected $language; - function __construct(\phpbb\user $user, \phpbb\language\language $language, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path) + public function __construct(\phpbb\user $user, \phpbb\language\language $language, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path) { $this->language = $language; $this->log = $log; $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; parent::__construct($user, $migrator, $extension_manager, $config, $cache); - $this->user->add_lang(array('common', 'install', 'migrator')); + $this->language->add_lang(array('common', 'install', 'migrator')); } protected function configure() { $this ->setName('db:migrate') - ->setDescription($this->user->lang('CLI_DESCRIPTION_DB_MIGRATE')) + ->setDescription($this->language->lang('CLI_DESCRIPTION_DB_MIGRATE')) ; } diff --git a/phpBB/phpbb/console/command/db/migration_command.php b/phpBB/phpbb/console/command/db/migration_command.php index b951560588..851f404fab 100644 --- a/phpBB/phpbb/console/command/db/migration_command.php +++ b/phpBB/phpbb/console/command/db/migration_command.php @@ -26,7 +26,7 @@ abstract class migration_command extends \phpbb\console\command\command /** @var \phpbb\cache\service */ protected $cache; - function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache) + public function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache) { $this->migrator = $migrator; $this->extension_manager = $extension_manager; diff --git a/phpBB/phpbb/console/command/db/revert.php b/phpBB/phpbb/console/command/db/revert.php index 7977afc319..3c79d8c554 100644 --- a/phpBB/phpbb/console/command/db/revert.php +++ b/phpBB/phpbb/console/command/db/revert.php @@ -18,35 +18,17 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -class revert extends \phpbb\console\command\db\migration_command +class revert extends \phpbb\console\command\db\migrate { - /** @var string phpBB root path */ - protected $phpbb_root_path; - - /** @var \phpbb\filesystem\filesystem_interface */ - protected $filesystem; - - /** @var \phpbb\language\language */ - protected $language; - - function __construct(\phpbb\user $user, \phpbb\language\language $language, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path) - { - $this->filesystem = $filesystem; - $this->language = $language; - $this->phpbb_root_path = $phpbb_root_path; - parent::__construct($user, $migrator, $extension_manager, $config, $cache); - $this->user->add_lang(array('common', 'migrator')); - } - protected function configure() { $this ->setName('db:revert') - ->setDescription($this->user->lang('CLI_DESCRIPTION_DB_REVERT')) + ->setDescription($this->language->lang('CLI_DESCRIPTION_DB_REVERT')) ->addArgument( 'name', InputArgument::REQUIRED, - $this->user->lang('CLI_MIGRATION_NAME') + $this->language->lang('CLI_MIGRATION_NAME') ) ; } diff --git a/phpBB/phpbb/console/command/dev/migration_tips.php b/phpBB/phpbb/console/command/dev/migration_tips.php index f9047bdac8..2ca0ddde2f 100644 --- a/phpBB/phpbb/console/command/dev/migration_tips.php +++ b/phpBB/phpbb/console/command/dev/migration_tips.php @@ -20,7 +20,7 @@ class migration_tips extends \phpbb\console\command\command /** @var \phpbb\extension\manager */ protected $extension_manager; - function __construct(\phpbb\user $user, \phpbb\extension\manager $extension_manager) + public function __construct(\phpbb\user $user, \phpbb\extension\manager $extension_manager) { $this->extension_manager = $extension_manager; parent::__construct($user); diff --git a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php index 043f181e72..6f7096296d 100644 --- a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php +++ b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php @@ -21,7 +21,7 @@ class recalculate_email_hash extends \phpbb\console\command\command /** @var \phpbb\db\driver\driver_interface */ protected $db; - function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db) + public function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db) { $this->db = $db; From 6a5b99b12b1812202843613994480cc6caf93354 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Thu, 8 Dec 2016 16:49:50 -0800 Subject: [PATCH 1406/1676] [ticket/14895] Fix broken tests PHPBB3-14895 --- phpBB/phpbb/console/command/cron/cron_list.php | 4 ++-- tests/console/cron/cron_list_test.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/console/command/cron/cron_list.php b/phpBB/phpbb/console/command/cron/cron_list.php index 8f9d63eda2..ea61e45235 100644 --- a/phpBB/phpbb/console/command/cron/cron_list.php +++ b/phpBB/phpbb/console/command/cron/cron_list.php @@ -81,13 +81,13 @@ class cron_list extends \phpbb\console\command\command if (!empty($ready_tasks)) { - $io->section($this->user->lang('TASKS_READY')); + $io->title($this->user->lang('TASKS_READY')); $io->listing($ready_tasks); } if (!empty($not_ready_tasks)) { - $io->section($this->user->lang('TASKS_NOT_READY')); + $io->title($this->user->lang('TASKS_NOT_READY')); $io->listing($not_ready_tasks); } } diff --git a/tests/console/cron/cron_list_test.php b/tests/console/cron/cron_list_test.php index 3bbe2078ba..fdc9a05cb2 100644 --- a/tests/console/cron/cron_list_test.php +++ b/tests/console/cron/cron_list_test.php @@ -50,19 +50,19 @@ class phpbb_console_command_cron_list_test extends phpbb_test_case public function test_only_ready() { $this->initiate_test(2, 0); - $this->assertContains('TASKS_READY command1 command2', preg_replace('/\s+/', ' ', trim($this->command_tester->getDisplay()))); + $this->assertContains('TASKS_READY command1 command2', preg_replace('/[\s*=]+/', ' ', trim($this->command_tester->getDisplay()))); } public function test_only_not_ready() { $this->initiate_test(0, 2); - $this->assertContains('TASKS_NOT_READY command1 command2', preg_replace('/\s+/', ' ', trim($this->command_tester->getDisplay()))); + $this->assertContains('TASKS_NOT_READY command1 command2', preg_replace('/[\s*=]+/', ' ', trim($this->command_tester->getDisplay()))); } public function test_both_ready() { $this->initiate_test(2, 2); - $this->assertSame('TASKS_READY command1 command2 TASKS_NOT_READY command3 command4', preg_replace('/\s+/', ' ', trim($this->command_tester->getDisplay()))); + $this->assertSame('TASKS_READY command1 command2 TASKS_NOT_READY command3 command4', preg_replace('/[\s*=]+/', ' ', trim($this->command_tester->getDisplay()))); } public function get_cron_manager(array $tasks) From 7fedc19cc422a00ad460f7f9dc41e916c67073ef Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 9 Dec 2016 08:17:51 +0100 Subject: [PATCH 1407/1676] [ticket/14891] Use own proxy instantiator for open_basedir compatibility Also reverted random_compat lib to 1.4.x. PHPBB3-14891 --- phpBB/composer.json | 2 +- phpBB/composer.lock | 14 ++--- phpBB/phpbb/di/container_builder.php | 2 +- phpBB/phpbb/di/proxy_instantiator.php | 74 +++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 phpBB/phpbb/di/proxy_instantiator.php diff --git a/phpBB/composer.json b/phpBB/composer.json index 7145265e55..e91430023d 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -31,7 +31,7 @@ "guzzlehttp/guzzle": "~5.3", "lusitanian/oauth": "^0.8.1", "marc1706/fast-image-size": "^1.1", - "paragonie/random_compat": "^2.0", + "paragonie/random_compat": "^1.4", "patchwork/utf8": "^1.1", "s9e/text-formatter": "~0.8.0", "symfony/config": "^2.8", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index ec69331b13..e550572fb3 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "9e6c5df052c3e795ad5985862bbb5797", - "content-hash": "47456b70d82a0df10e5faa0a3dc1c2ae", + "hash": "067b099cc97334a6a08a77e5648aa260", + "content-hash": "90198ca524b93a7e915aa6916b2f55af", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -460,16 +460,16 @@ }, { "name": "paragonie/random_compat", - "version": "v2.0.4", + "version": "v1.4.1", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e" + "reference": "c7e26a21ba357863de030f0b9e701c7d04593774" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e", - "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/c7e26a21ba357863de030f0b9e701c7d04593774", + "reference": "c7e26a21ba357863de030f0b9e701c7d04593774", "shasum": "" }, "require": { @@ -504,7 +504,7 @@ "pseudorandom", "random" ], - "time": "2016-11-07 23:38:38" + "time": "2016-03-18 20:34:03" }, { "name": "patchwork/utf8", diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index b6854673c2..6412ccea46 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -488,7 +488,7 @@ class container_builder protected function create_container(array $extensions) { $container = new ContainerBuilder(new ParameterBag($this->get_core_parameters())); - $container->setProxyInstantiator(new RuntimeInstantiator()); + $container->setProxyInstantiator(new proxy_instantiator($this->get_cache_dir())); $extensions_alias = array(); diff --git a/phpBB/phpbb/di/proxy_instantiator.php b/phpBB/phpbb/di/proxy_instantiator.php new file mode 100644 index 0000000000..28d9972cd7 --- /dev/null +++ b/phpBB/phpbb/di/proxy_instantiator.php @@ -0,0 +1,74 @@ + + * @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\di; + +use \bantu\IniGetWrapper\IniGetWrapper; +use ProxyManager\Configuration; +use ProxyManager\Factory\LazyLoadingValueHolderFactory; +use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; +use ProxyManager\Proxy\LazyLoadingInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; + +/** + * Runtime lazy loading proxy generator extended for allowing use while using + * open_basedir restrictions + * + * Original author: Marco Pivetta + */ +class proxy_instantiator implements InstantiatorInterface +{ + /** + * @var LazyLoadingValueHolderFactory + */ + private $factory; + + /** + * proxy_instantiator constructor + * @param string $cache_dir Cache dir for fall back when using open_basedir + */ + public function __construct($cache_dir) + { + $config = new Configuration(); + + // Prevent trying to write to system temp dir in case of open_basedir + // restrictions being in effect + $ini_wrapper = new IniGetWrapper(); + if ($ini_wrapper->getString('open_basedir') || !file_exists(sys_get_temp_dir())) + { + $config->setProxiesTargetDir($cache_dir); + } + $config->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); + + $this->factory = new LazyLoadingValueHolderFactory($config); + } + + /** + * {@inheritdoc} + */ + public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator) + { + return $this->factory->createProxy( + $definition->getClass(), + function (&$wrappedInstance, LazyLoadingInterface $proxy) use ($realInstantiator) { + $wrappedInstance = call_user_func($realInstantiator); + + $proxy->setProxyInitializer(null); + + return true; + } + ); + } +} From 5f56e9025b276419578507ddbab933183649b47d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 9 Dec 2016 08:56:16 +0100 Subject: [PATCH 1408/1676] [ticket/14891] Remove unused use statements PHPBB3-14891 --- phpBB/phpbb/di/container_builder.php | 1 - phpBB/phpbb/di/proxy_instantiator.php | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 6412ccea46..4d5f189f12 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -14,7 +14,6 @@ namespace phpbb\di; use phpbb\filesystem\filesystem; -use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\FileLocator; diff --git a/phpBB/phpbb/di/proxy_instantiator.php b/phpBB/phpbb/di/proxy_instantiator.php index 28d9972cd7..1f51100493 100644 --- a/phpBB/phpbb/di/proxy_instantiator.php +++ b/phpBB/phpbb/di/proxy_instantiator.php @@ -17,7 +17,6 @@ use \bantu\IniGetWrapper\IniGetWrapper; use ProxyManager\Configuration; use ProxyManager\Factory\LazyLoadingValueHolderFactory; use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; -use ProxyManager\Proxy\LazyLoadingInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; @@ -62,7 +61,7 @@ class proxy_instantiator implements InstantiatorInterface { return $this->factory->createProxy( $definition->getClass(), - function (&$wrappedInstance, LazyLoadingInterface $proxy) use ($realInstantiator) { + function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($realInstantiator) { $wrappedInstance = call_user_func($realInstantiator); $proxy->setProxyInitializer(null); From 6a568719d031544553a9e236e4128c5bfbd42600 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 9 Dec 2016 11:10:28 +0100 Subject: [PATCH 1409/1676] [ticket/14891] Use filesystem classes for checking on tmp dir The cache dir will now also only be used if tmp dir does not exist or if it's not writable. PHPBB3-14891 --- phpBB/phpbb/di/proxy_instantiator.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/di/proxy_instantiator.php b/phpBB/phpbb/di/proxy_instantiator.php index 1f51100493..47cc7b69c4 100644 --- a/phpBB/phpbb/di/proxy_instantiator.php +++ b/phpBB/phpbb/di/proxy_instantiator.php @@ -13,7 +13,8 @@ namespace phpbb\di; -use \bantu\IniGetWrapper\IniGetWrapper; +use bantu\IniGetWrapper\IniGetWrapper; +use phpbb\filesystem\filesystem; use ProxyManager\Configuration; use ProxyManager\Factory\LazyLoadingValueHolderFactory; use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; @@ -45,7 +46,10 @@ class proxy_instantiator implements InstantiatorInterface // Prevent trying to write to system temp dir in case of open_basedir // restrictions being in effect $ini_wrapper = new IniGetWrapper(); - if ($ini_wrapper->getString('open_basedir') || !file_exists(sys_get_temp_dir())) + $filesystem = new filesystem(); + $tmp_dir = sys_get_temp_dir(); + if ($ini_wrapper->getString('open_basedir') && + (!$filesystem->exists($tmp_dir) || !$filesystem->is_writable($tmp_dir))) { $config->setProxiesTargetDir($cache_dir); } From 90b59bb547844f6913cb459c21d249aec4226d56 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 9 Dec 2016 11:32:13 +0100 Subject: [PATCH 1410/1676] [ticket/14891] Don't rely on sys_get_temp_dir() being available Or actually returning a path. It might also return an empty string or null. PHPBB3-14891 --- phpBB/phpbb/di/proxy_instantiator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/di/proxy_instantiator.php b/phpBB/phpbb/di/proxy_instantiator.php index 47cc7b69c4..a388e82c0e 100644 --- a/phpBB/phpbb/di/proxy_instantiator.php +++ b/phpBB/phpbb/di/proxy_instantiator.php @@ -47,8 +47,8 @@ class proxy_instantiator implements InstantiatorInterface // restrictions being in effect $ini_wrapper = new IniGetWrapper(); $filesystem = new filesystem(); - $tmp_dir = sys_get_temp_dir(); - if ($ini_wrapper->getString('open_basedir') && + $tmp_dir = (function_exists('sys_get_temp_dir')) ? sys_get_temp_dir() : ''; + if (empty($tmp_dir) || $ini_wrapper->getString('open_basedir') && (!$filesystem->exists($tmp_dir) || !$filesystem->is_writable($tmp_dir))) { $config->setProxiesTargetDir($cache_dir); From 37a3bd131bf82becc436c72a4e01975f4381d4f6 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 9 Dec 2016 19:54:58 +0100 Subject: [PATCH 1411/1676] [ticket/14894] Use correct config name for conflicts archive extension PHPBB3-14894 --- .../install/module/update_filesystem/task/show_file_status.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php index 7f18950cf6..cf1e4cf4ac 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php @@ -92,7 +92,7 @@ class show_file_status extends task_base // Create archive for merge conflicts if (!empty($merge_conflicts)) { - $compression_method = $this->installer_config->get('compression_method', ''); + $compression_method = $this->installer_config->get('file_update_compression', ''); $conflict_archive = $this->file_updater->init($compression_method); $this->installer_config->set('update_file_conflict_archive', $conflict_archive); From a2793f24b1b4394871e897679fd407ba703d1937 Mon Sep 17 00:00:00 2001 From: Derky Date: Fri, 9 Dec 2016 20:03:00 +0100 Subject: [PATCH 1412/1676] [ticket/14901] Remove notice for extension without version check Extensions without version check should not display a notice on the details page in the ACP. PHPBB3-14901 --- phpBB/adm/style/acp_ext_details.html | 24 ++++++-------- phpBB/includes/acp/acp_extensions.php | 48 ++++++++++++++++----------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/phpBB/adm/style/acp_ext_details.html b/phpBB/adm/style/acp_ext_details.html index 830c2e3cb4..4c1feb59a9 100644 --- a/phpBB/adm/style/acp_ext_details.html +++ b/phpBB/adm/style/acp_ext_details.html @@ -7,19 +7,17 @@

      {L_EXTENSIONS_ADMIN}

      -
      -

      {UP_TO_DATE_MSG} - {L_VERSIONCHECK_FORCE_UPDATE}

      -
      - -
      -

      {L_VERSIONCHECK_FAIL}

      -

      {VERSIONCHECK_FAIL_REASON}

      -

      {L_VERSIONCHECK_FORCE_UPDATE}

      -
      - -
      -

      {VERSIONCHECK_FAIL_REASON}

      -
      + +
      +

      {L_VERSIONCHECK_FAIL}

      +

      {VERSIONCHECK_FAIL_REASON}

      +

      {L_VERSIONCHECK_FORCE_UPDATE}

      +
      + +
      +

      {UP_TO_DATE_MSG} - {L_VERSIONCHECK_FORCE_UPDATE}

      +
      +
      diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index e081eae975..e915fa8c75 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -308,29 +308,37 @@ class acp_extensions // Output it to the template $md_manager->output_template_data($template); - try + $meta = $md_manager->get_metadata('all'); + if (isset($meta['extra']['version-check'])) { - $updates_available = $phpbb_extension_manager->version_check($md_manager, $request->variable('versioncheck_force', false), $this->config['extension_force_unstable'] ? 'unstable' : null); - - $template->assign_vars(array( - 'S_UP_TO_DATE' => empty($updates_available), - 'S_VERSIONCHECK' => true, - 'UP_TO_DATE_MSG' => $this->user->lang(empty($updates_available) ? 'UP_TO_DATE' : 'NOT_UP_TO_DATE', $md_manager->get_metadata('display-name')), - )); - - foreach ($updates_available as $branch => $version_data) + try { - $template->assign_block_vars('updates_available', $version_data); - } - } - catch (exception_interface $e) - { - $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + $updates_available = $phpbb_extension_manager->version_check($md_manager, $request->variable('versioncheck_force', false), $this->config['extension_force_unstable'] ? 'unstable' : null); - $template->assign_vars(array( - 'S_VERSIONCHECK_STATUS' => $e->getCode(), - 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== 'VERSIONCHECK_FAIL') ? $message : '', - )); + $template->assign_vars(array( + 'S_UP_TO_DATE' => empty($updates_available), + 'UP_TO_DATE_MSG' => $this->user->lang(empty($updates_available) ? 'UP_TO_DATE' : 'NOT_UP_TO_DATE', $md_manager->get_metadata('display-name')), + )); + + foreach ($updates_available as $branch => $version_data) + { + $template->assign_block_vars('updates_available', $version_data); + } + } + catch (exception_interface $e) + { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + + $template->assign_vars(array( + 'S_VERSIONCHECK_FAIL' => true, + 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== 'VERSIONCHECK_FAIL') ? $message : '', + )); + } + $template->assign_var('S_VERSIONCHECK', true); + } + else + { + $template->assign_var('S_VERSIONCHECK', false); } $template->assign_vars(array( From 185bda094b9e85505526463747a30bc5bb529666 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 6 Dec 2016 15:32:48 +0100 Subject: [PATCH 1413/1676] [prep-release-3.2.0-RC2] Update version numbers to 3.2.0-RC2 --- build/build.xml | 6 +++--- phpBB/includes/constants.php | 2 +- phpBB/install/phpbbcli.php | 2 +- phpBB/install/schemas/schema_data.sql | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/build.xml b/build/build.xml index 4fe6e0e908..f337ac660d 100644 --- a/build/build.xml +++ b/build/build.xml @@ -2,9 +2,9 @@ - - - + + + diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 38017255b4..b281d8cdb5 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -28,7 +28,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -@define('PHPBB_VERSION', '3.2.0-RC2-dev'); +@define('PHPBB_VERSION', '3.2.0-RC2'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/install/phpbbcli.php b/phpBB/install/phpbbcli.php index 3803fe7034..7de40e08cf 100755 --- a/phpBB/install/phpbbcli.php +++ b/phpBB/install/phpbbcli.php @@ -23,7 +23,7 @@ if (php_sapi_name() !== 'cli') define('IN_PHPBB', true); define('IN_INSTALL', true); define('PHPBB_ENVIRONMENT', 'production'); -define('PHPBB_VERSION', '3.2.0-RC1'); +define('PHPBB_VERSION', '3.2.0-RC2'); $phpbb_root_path = __DIR__ . '/../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 56a4efa230..0c93700a19 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -278,7 +278,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0 INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-RC2-dev'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-RC2'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); From 9d72c4a66afd89e7c86905630bd813853d3f03c7 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 6 Dec 2016 15:33:46 +0100 Subject: [PATCH 1414/1676] [prep-release-3.2.0-RC2] Update version numbers to 3.2.0-RC2 --- phpBB/install/convertors/convert_phpbb20.php | 2 +- phpBB/styles/prosilver/style.cfg | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index e5866add7d..7efd6476f0 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -38,7 +38,7 @@ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms); $convertor_data = array( 'forum_name' => 'phpBB 2.0.x', 'version' => '1.0.3', - 'phpbb_version' => '3.2.0-RC1', + 'phpbb_version' => '3.2.0-RC2', 'author' => 'phpBB Limited', 'dbms' => $dbms, 'dbhost' => $dbhost, diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg index 895ee49dc4..6701ce5905 100644 --- a/phpBB/styles/prosilver/style.cfg +++ b/phpBB/styles/prosilver/style.cfg @@ -21,8 +21,8 @@ # General Information about this style name = prosilver copyright = © phpBB Limited, 2007 -style_version = 3.2.0-RC1 -phpbb_version = 3.2.0-RC1 +style_version = 3.2.0-RC2 +phpbb_version = 3.2.0-RC2 # Defining a different template bitfield # template_bitfield = lNg= From a35c8a924ee824a10468e75df375c870b550d550 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 6 Dec 2016 15:41:58 +0100 Subject: [PATCH 1415/1676] [prep-release-3.2.0-RC2] Add migration file for 3.2.0-RC2 --- .../phpbb/db/migration/data/v320/v320rc2.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 phpBB/phpbb/db/migration/data/v320/v320rc2.php diff --git a/phpBB/phpbb/db/migration/data/v320/v320rc2.php b/phpBB/phpbb/db/migration/data/v320/v320rc2.php new file mode 100644 index 0000000000..ec9bb62732 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/v320rc2.php @@ -0,0 +1,40 @@ + +* @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\v320; + +use phpbb\db\migration\migration; + +class v320rc2 extends migration +{ + public function effectively_installed() + { + return version_compare($this->config['version'], '3.2.0-RC2', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\remove_duplicate_migrations', + '\phpbb\db\migration\data\v31x\add_log_time_index', + '\phpbb\db\migration\data\v320\add_help_phpbb', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.0-RC2')), + ); + } +} From c494d8f53ec93287e54ef857f84637fa91c7e1ba Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 6 Dec 2016 15:44:43 +0100 Subject: [PATCH 1416/1676] [prep-release-3.2.0-RC2] Update changelog --- phpBB/docs/CHANGELOG.html | 77 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index f907585e28..b684de9a7f 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -50,6 +50,7 @@
      1. Changelog
          +
        • Changes since 3.2.0-RC1
        • Changes since 3.2.0-b2
        • Changes since 3.2.0-b1
        • Changes since 3.2.0-a2
        • @@ -123,6 +124,82 @@
          +

          Changes since 3.2.0-RC1

          +

          Bug

          +
            +
          • [PHPBB3-14588] - RTL Search Bar
          • +
          • [PHPBB3-14612] - Double .panel class on confirmation page (ajax error?)
          • +
          • [PHPBB3-14628] - CLI installer doesn't support the translatable error messages
          • +
          • [PHPBB3-14633] - Creating a new topic leaves a white page
          • +
          • [PHPBB3-14636] - BC compatibility broken using request_var
          • +
          • [PHPBB3-14640] - Wrong link to documentation in language/en/install.php
          • +
          • [PHPBB3-14660] - Emails are being sent unparsed
          • +
          • [PHPBB3-14663] - Incorrect unicode chars handling in custom BBCode
          • +
          • [PHPBB3-14665] - Invalid syntax in report_id_auto_increment migration
          • +
          • [PHPBB3-14684] - Extension Sniff script should use NOTESTS
          • +
          • [PHPBB3-14690] - Email queue cron task never runs for phpBB 3.2
          • +
          • [PHPBB3-14692] - Duplicate subexpression in questionnaire.php
          • +
          • [PHPBB3-14700] - Updating from 3.1 to 3.2, just stops
          • +
          • [PHPBB3-14706] - nested BB-Code [list] - shows different behaviour between 3.1 and 3.2
          • +
          • [PHPBB3-14709] - Deleting posts from mcp_main causes missing post_id notice
          • +
          • [PHPBB3-14714] - Update composer dependencies to latest versions
          • +
          • [PHPBB3-14716] - Impossible to install with open basedir restrictions
          • +
          • [PHPBB3-14717] - Quote any scalar in yaml files
          • +
          • [PHPBB3-14739] - Remove old SQLite 2.8.Ñ… database driver
          • +
          • [PHPBB3-14740] - BBcodes with quotes dont get parsed correctly
          • +
          • [PHPBB3-14742] - Improvements to migrator
          • +
          • [PHPBB3-14746] - Don't depend on container in installer msg_handler
          • +
          • [PHPBB3-14748] - Modify tests to pass PHP 7.1 tests
          • +
          • [PHPBB3-14763] - Files services definition specifies form for local type
          • +
          • [PHPBB3-14764] - Incomplete update notification points to wrong update-link
          • +
          • [PHPBB3-14765] - Parameter vs requirement spelling mismatch in installer routing config
          • +
          • [PHPBB3-14774] - Content-Range only supported for resuming downloads
          • +
          • [PHPBB3-14782] - Quick Links > Your Posts gives mysql error
          • +
          • [PHPBB3-14788] - Update developer list to reflect team changes
          • +
          • [PHPBB3-14791] - Trying to get form from wrong button in search test base
          • +
          • [PHPBB3-14793] - "A non-numeric value encountered" PHP warning on PHP 7.1+
          • +
          • [PHPBB3-14794] - Fix redirect behavior in according to parse_url() behavior changes in PHP 7.1+
          • +
          • [PHPBB3-14797] - Remove PHP 7.1 builds from allowed failures
          • +
          • [PHPBB3-14799] - purge_notifications() leaves open transaction for bad notification types.
          • +
          • [PHPBB3-14813] - functions_compatibility missing in phpbbcli
          • +
          • [PHPBB3-14814] - Text reparser reparses already correctly [re] -parsed objects
          • +
          • [PHPBB3-14821] - Do not expect parsed HTML in kernel subscriber output
          • +
          • [PHPBB3-14846] - Swapped variables in bbcode, first one doesn't get parsed
          • +
          • [PHPBB3-14873] - Missing width and height variables for smilies
          • +
          • [PHPBB3-14875] - Cannot use HTML entity type database passwords during installation
          • +
          • [PHPBB3-14883] - Text Reparser is Reparsing Empty Data
          • +
          • [PHPBB3-14892] - Assets paths broken on Windows instances
          • +
          +

          Improvement

          + +

          New Feature

          + +

          Task

          +
            +
          • [PHPBB3-10809] - Remove PHP MSSQL Support
          • +
          • [PHPBB3-13573] - Investigate ability to use set_config() and similar compatibility functions.
          • +
          • [PHPBB3-14671] - Deduplicate database schema definiton
          • +
          • [PHPBB3-14696] - Fix email template test for '0' username
          • +
          • [PHPBB3-14807] - Updates dependencies
          • +
          +

          Changes since 3.2.0-b2

          Bug

            From af7dca6acd1e7431b8f732df1f84051866da6bf8 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 9 Dec 2016 20:52:35 +0100 Subject: [PATCH 1417/1676] [prep-release-3.2.0-RC2] Update changelog --- phpBB/docs/CHANGELOG.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index b684de9a7f..6286e69f3a 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -169,6 +169,10 @@
          • [PHPBB3-14875] - Cannot use HTML entity type database passwords during installation
          • [PHPBB3-14883] - Text Reparser is Reparsing Empty Data
          • [PHPBB3-14892] - Assets paths broken on Windows instances
          • +
          • [PHPBB3-14894] - Update: download of conflict files offers .tar file without file extension
          • +
          • [PHPBB3-14896] - Link after installation fails at redirecting to ACP
          • +
          • [PHPBB3-14897] - IOHandler in the installer declares member variable only in the constructor
          • +
          • [PHPBB3-14900] - Disabled extension breakage in ACP

          Improvement

            From cff3dbf00e4a83d59398a278e78e1052abf4e08a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 10 Dec 2016 00:32:41 +0100 Subject: [PATCH 1418/1676] [3.2.x] Update version numbers to 3.2.0-RC3-dev --- build/build.xml | 6 +++--- phpBB/includes/constants.php | 2 +- phpBB/install/convertors/convert_phpbb20.php | 2 +- phpBB/install/phpbbcli.php | 2 +- phpBB/install/schemas/schema_data.sql | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/build.xml b/build/build.xml index f337ac660d..615e420a13 100644 --- a/build/build.xml +++ b/build/build.xml @@ -2,9 +2,9 @@ - - - + + + diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index b281d8cdb5..a6a5bf41cb 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -28,7 +28,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -@define('PHPBB_VERSION', '3.2.0-RC2'); +@define('PHPBB_VERSION', '3.2.0-RC3-dev'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index 7efd6476f0..c7006f9758 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -38,7 +38,7 @@ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms); $convertor_data = array( 'forum_name' => 'phpBB 2.0.x', 'version' => '1.0.3', - 'phpbb_version' => '3.2.0-RC2', + 'phpbb_version' => '3.2.0-RC3-dev', 'author' => 'phpBB Limited', 'dbms' => $dbms, 'dbhost' => $dbhost, diff --git a/phpBB/install/phpbbcli.php b/phpBB/install/phpbbcli.php index 7de40e08cf..f5dfa83712 100755 --- a/phpBB/install/phpbbcli.php +++ b/phpBB/install/phpbbcli.php @@ -23,7 +23,7 @@ if (php_sapi_name() !== 'cli') define('IN_PHPBB', true); define('IN_INSTALL', true); define('PHPBB_ENVIRONMENT', 'production'); -define('PHPBB_VERSION', '3.2.0-RC2'); +define('PHPBB_VERSION', '3.2.0-RC3-dev'); $phpbb_root_path = __DIR__ . '/../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 0c93700a19..64397904e9 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -278,7 +278,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0 INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-RC2'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-RC3-dev'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); From dfe42e96035ed63e92f8c14a553c3631c1ea08e4 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Sat, 10 Dec 2016 21:50:09 +0100 Subject: [PATCH 1419/1676] [ticket/14908] Uses lang-variable instead of english text PHPBB3-14908 --- phpBB/adm/style/acp_help_phpbb.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/adm/style/acp_help_phpbb.html b/phpBB/adm/style/acp_help_phpbb.html index 48a4595913..478ecc162a 100644 --- a/phpBB/adm/style/acp_help_phpbb.html +++ b/phpBB/adm/style/acp_help_phpbb.html @@ -8,7 +8,7 @@
            -

            Send statistics

            +

            {L_SEND_STATISTICS}

            {L_EXPLAIN_SEND_STATISTICS}

            From 28296af248b36cd796464e3941cd078345a1ccd7 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Sat, 10 Dec 2016 22:07:47 +0100 Subject: [PATCH 1420/1676] [ticket/14909] Increases CSS specifity of .header-image to avoid underline PHPBB3-14909 --- phpBB/styles/prosilver/theme/common.css | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index ee585e6abf..5cf204a7a6 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -339,18 +339,19 @@ ul.linklist.bulletin > li.no-bulletin:before { vertical-align: top; } -.header-avatar:hover { +a.header-avatar, +a.header-avatar:hover { text-decoration: none; } -.header-avatar img { +a.header-avatar img { margin-bottom: 2px; max-height: 20px; vertical-align: middle; width: auto; } -.header-avatar span:after { +a.header-avatar span:after { content: '\f0dd'; display: inline-block; font: normal normal normal 14px/1 FontAwesome; From a0adf07453fa1e8d3118d3d4b1f8eca2aba4507a Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Sun, 11 Dec 2016 14:11:55 +0100 Subject: [PATCH 1421/1676] [ticket/14910] Fixes typo PLease to Please in EXTENSION_NOT_INSTALLED PHPBB3-14910 --- phpBB/language/en/acp/extensions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/language/en/acp/extensions.php b/phpBB/language/en/acp/extensions.php index 8d6f8ece84..a96a7a2a2b 100644 --- a/phpBB/language/en/acp/extensions.php +++ b/phpBB/language/en/acp/extensions.php @@ -43,7 +43,7 @@ $lang = array_merge($lang, array( 'EXTENSION_NOT_AVAILABLE' => 'The selected extension is not available for this board, please verify your phpBB and PHP versions are allowed (see the details page).', 'EXTENSION_DIR_INVALID' => 'The selected extension has an invalid directory structure and cannot be enabled.', 'EXTENSION_NOT_ENABLEABLE' => 'The selected extension cannot be enabled, please verify the extension’s requirements.', - 'EXTENSION_NOT_INSTALLED' => 'The extension %s is not available. PLease check that you have installed it correctly.', + 'EXTENSION_NOT_INSTALLED' => 'The extension %s is not available. Please check that you have installed it correctly.', 'DETAILS' => 'Details', From 1846b90a33daa1f73586b17a871b28fa349983ee Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 17 Dec 2016 23:20:28 +0100 Subject: [PATCH 1422/1676] [ticket/14920] Force installer to only populate core migrations PHPBB3-14920 --- .../install/module/install_finish/task/populate_migrations.php | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php b/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php index 34541c361e..cebf0f425f 100644 --- a/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php +++ b/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php @@ -70,6 +70,7 @@ class populate_migrations extends \phpbb\install\task_base $migrations = $finder ->core_path('phpbb/db/migration/data/') + ->set_extensions(array()) ->get_classes(); $this->migrator->populate_migrations($migrations); } From de6942e117d4e1b27a62fd1a3bebcad53052140c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 17 Dec 2016 23:29:19 +0100 Subject: [PATCH 1423/1676] [ticket/14921] Use phpbb.com URL to prevent test failures for remote URLs PHPBB3-14921 --- tests/files/types_remote_test.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/files/types_remote_test.php b/tests/files/types_remote_test.php index d103771c04..1a7d63d790 100644 --- a/tests/files/types_remote_test.php +++ b/tests/files/types_remote_test.php @@ -84,16 +84,16 @@ class phpbb_files_types_remote_test extends phpbb_test_case public function data_get_max_file_size() { return array( - array('', 'http://example.com/foo/bar.png'), - array('2k', 'http://example.com/foo/bar.png'), - array('500k', 'http://example.com/foo/bar.png'), - array('500M', 'http://example.com/foo/bar.png'), - array('500m', 'http://example.com/foo/bar.png'), + array('', 'http://phpbb.com/foo/bar.png'), + array('2k', 'http://phpbb.com/foo/bar.png'), + array('500k', 'http://phpbb.com/foo/bar.png'), + array('500M', 'http://phpbb.com/foo/bar.png'), + array('500m', 'http://phpbb.com/foo/bar.png'), array('500k', 'http://google.com/?.png', array('DISALLOWED_EXTENSION', 'DISALLOWED_CONTENT')), array('1', 'http://google.com/?.png', array('WRONG_FILESIZE')), - array('500g', 'http://example.com/foo/bar.png'), - array('foobar', 'http://example.com/foo/bar.png'), - array('-5k', 'http://example.com/foo/bar.png'), + array('500g', 'http://phpbb.com/foo/bar.png'), + array('foobar', 'http://phpbb.com/foo/bar.png'), + array('-5k', 'http://phpbb.com/foo/bar.png'), ); } From b4748a5d1ee31084da7e78f8ffaf5b036f2e5314 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sun, 18 Dec 2016 01:28:51 -0800 Subject: [PATCH 1424/1676] [ticket/14925] Set reparser names in service definitions PHPBB3-14925 --- .../container/services_text_reparser.yml | 18 +++++++++++++ .../console/command/reparser/list_all.php | 4 +-- .../console/command/reparser/reparse.php | 16 +++++------ .../cron/task/text_reparser/reparser.php | 2 +- phpBB/phpbb/textreparser/base.php | 27 ++++++++++++++++++- phpBB/phpbb/textreparser/manager.php | 20 ++++++++++++++ .../phpbb/textreparser/reparser_interface.php | 14 ++++++++++ 7 files changed, 87 insertions(+), 14 deletions(-) diff --git a/phpBB/config/default/container/services_text_reparser.yml b/phpBB/config/default/container/services_text_reparser.yml index 6b0353cf5b..4bc49f5765 100644 --- a/phpBB/config/default/container/services_text_reparser.yml +++ b/phpBB/config/default/container/services_text_reparser.yml @@ -24,6 +24,8 @@ services: class: phpbb\textreparser\plugins\contact_admin_info arguments: - '@config_text' + calls: + - [set_name, [contact_admin_info]] tags: - { name: text_reparser.plugin } @@ -32,6 +34,8 @@ services: arguments: - '@dbal.conn' - '%tables.forums%' + calls: + - [set_name, [forum_description]] tags: - { name: text_reparser.plugin } @@ -40,6 +44,8 @@ services: arguments: - '@dbal.conn' - '%tables.forums%' + calls: + - [set_name, [forum_rules]] tags: - { name: text_reparser.plugin } @@ -48,6 +54,8 @@ services: arguments: - '@dbal.conn' - '%tables.groups%' + calls: + - [set_name, [group_description]] tags: - { name: text_reparser.plugin } @@ -56,6 +64,8 @@ services: arguments: - '@dbal.conn' - '%tables.privmsgs%' + calls: + - [set_name, [pm_text]] tags: - { name: text_reparser.plugin } @@ -63,6 +73,8 @@ services: class: phpbb\textreparser\plugins\poll_option arguments: - '@dbal.conn' + calls: + - [set_name, [poll_option]] tags: - { name: text_reparser.plugin } @@ -71,6 +83,8 @@ services: arguments: - '@dbal.conn' - '%tables.topics%' + calls: + - [set_name, [poll_title]] tags: - { name: text_reparser.plugin } @@ -79,6 +93,8 @@ services: arguments: - '@dbal.conn' - '%tables.posts%' + calls: + - [set_name, [post_text]] tags: - { name: text_reparser.plugin } @@ -87,5 +103,7 @@ services: arguments: - '@dbal.conn' - '%tables.users%' + calls: + - [set_name, [user_signature]] tags: - { name: text_reparser.plugin } diff --git a/phpBB/phpbb/console/command/reparser/list_all.php b/phpBB/phpbb/console/command/reparser/list_all.php index 028468649d..a79578abf0 100644 --- a/phpBB/phpbb/console/command/reparser/list_all.php +++ b/phpBB/phpbb/console/command/reparser/list_all.php @@ -34,10 +34,10 @@ class list_all extends \phpbb\console\command\command { parent::__construct($user); $this->reparser_names = array(); - foreach ($reparsers as $name => $reparser) + foreach ($reparsers as $reparser) { // Store the names without the "text_reparser." prefix - $this->reparser_names[] = preg_replace('(^text_reparser\\.)', '', $name); + $this->reparser_names[] = $reparser->get_name(); } } diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php index cebeee0919..f285977ea2 100644 --- a/phpBB/phpbb/console/command/reparser/reparse.php +++ b/phpBB/phpbb/console/command/reparser/reparse.php @@ -140,13 +140,9 @@ class reparse extends \phpbb\console\command\command } $name = $input->getArgument('reparser-name'); - if (isset($name)) + if ($name) { - // Allow "post_text" to be an alias for "text_reparser.post_text" - if (!isset($this->reparsers[$name])) - { - $name = 'text_reparser.' . $name; - } + $name = $this->reparser_manager->find_reparser($name); $this->reparse($name); } else @@ -187,7 +183,7 @@ class reparse extends \phpbb\console\command\command /** * Reparse all text handled by given reparser within given range * - * @param string $name Reparser name + * @param string $name Reparser service name */ protected function reparse($name) { @@ -218,10 +214,10 @@ class reparse extends \phpbb\console\command\command return; } - $this->io->section($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', preg_replace('(^text_reparser\\.)', '', $name), $min, $max)); + $this->io->section($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', $reparser->get_name(), $min, $max)); $progress = $this->create_progress_bar($max, $this->io, $this->output, true); - $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING_START', preg_replace('(^text_reparser\\.)', '', $name))); + $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING_START', $reparser->get_name())); $progress->start(); // Start from $max and decrement $current by $size until we reach $min @@ -231,7 +227,7 @@ class reparse extends \phpbb\console\command\command $start = max($min, $current + 1 - $size); $end = max($min, $current); - $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', preg_replace('(^text_reparser\\.)', '', $name), $start, $end)); + $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', $reparser->get_name(), $start, $end)); $reparser->reparse_range($start, $end); $current = $start - 1; diff --git a/phpBB/phpbb/cron/task/text_reparser/reparser.php b/phpBB/phpbb/cron/task/text_reparser/reparser.php index 7099128efd..69392f5ac9 100644 --- a/phpBB/phpbb/cron/task/text_reparser/reparser.php +++ b/phpBB/phpbb/cron/task/text_reparser/reparser.php @@ -81,7 +81,7 @@ class reparser extends \phpbb\cron\task\base */ public function set_reparser($reparser) { - $this->reparser_name = (!isset($this->reparsers[$reparser]) ? 'text_reparser.' : '') . $reparser; + $this->reparser_name = !isset($this->reparsers[$reparser]) ? $this->reparser_manager->find_reparser($reparser) : $reparser; if ($this->resume_data === null) { diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index afa5ccacad..ef97bc90d5 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -15,6 +15,11 @@ namespace phpbb\textreparser; abstract class base implements reparser_interface { + /** + * @var string The reparser name + */ + protected $name; + /** * @var bool Whether to save changes to the database */ @@ -89,6 +94,26 @@ abstract class base implements reparser_interface return $record; } + /** + * Returns the name of the reparser + * + * @return string Name of reparser + */ + public function get_name() + { + return $this->name; + } + + /** + * Sets the name of the reparser + * + * @param string $name The reparser name + */ + public function set_name($name) + { + $this->name = $name; + } + /** * Disable saving changes to the database */ @@ -231,7 +256,7 @@ abstract class base implements reparser_interface $unparsed['enable_flash_bbcode'], $unparsed['enable_quote_bbcode'], $unparsed['enable_url_bbcode'], - 'reparse' + $this->get_name() ); // Save the new text if it has changed and it's not a dry run diff --git a/phpBB/phpbb/textreparser/manager.php b/phpBB/phpbb/textreparser/manager.php index fddd867923..7ca65d708d 100644 --- a/phpBB/phpbb/textreparser/manager.php +++ b/phpBB/phpbb/textreparser/manager.php @@ -125,4 +125,24 @@ class manager $this->schedule($reparser, $interval); } } + + /** + * Finds a reparser by name. + * + * If there is no reparser with the specified name, null is returned. + * + * @param string $name Name of the reparser to look up. + * @return string A reparser service name, or null. + */ + public function find_reparser($name) + { + foreach ($this->reparsers as $service => $reparser) + { + if ($reparser->get_name() == $name) + { + return $service; + } + } + return null; + } } diff --git a/phpBB/phpbb/textreparser/reparser_interface.php b/phpBB/phpbb/textreparser/reparser_interface.php index 9ea1732870..912de10058 100644 --- a/phpBB/phpbb/textreparser/reparser_interface.php +++ b/phpBB/phpbb/textreparser/reparser_interface.php @@ -22,6 +22,20 @@ interface reparser_interface */ public function get_max_id(); + /** + * Returns the name of the reparser + * + * @return string Name of reparser + */ + public function get_name(); + + /** + * Sets the name of the reparser + * + * @param string $name The reparser name + */ + public function set_name($name); + /** * Reparse all records in given range * From 76e9f4dd2d45e8f128e59e1378dfd6778eec9d48 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sun, 18 Dec 2016 09:12:26 -0800 Subject: [PATCH 1425/1676] [ticket/14925] Prefix modes from reparser with text_reparser PHPBB3-14925 --- phpBB/phpbb/textreparser/base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index ef97bc90d5..27d7bc1f27 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -256,7 +256,7 @@ abstract class base implements reparser_interface $unparsed['enable_flash_bbcode'], $unparsed['enable_quote_bbcode'], $unparsed['enable_url_bbcode'], - $this->get_name() + 'text_reparser.' . $this->get_name() ); // Save the new text if it has changed and it's not a dry run From c6aa4a319dd2cfb76a5919fc295ab782529c6646 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 25 Dec 2016 15:04:48 +0100 Subject: [PATCH 1426/1676] [ticket/14934] Use bare PHP functions for checking for tmp dir The symfony methods will cause PHP warnings being thrown. PHPBB3-14934 --- phpBB/phpbb/di/proxy_instantiator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/di/proxy_instantiator.php b/phpBB/phpbb/di/proxy_instantiator.php index a388e82c0e..f8ef39535b 100644 --- a/phpBB/phpbb/di/proxy_instantiator.php +++ b/phpBB/phpbb/di/proxy_instantiator.php @@ -49,7 +49,7 @@ class proxy_instantiator implements InstantiatorInterface $filesystem = new filesystem(); $tmp_dir = (function_exists('sys_get_temp_dir')) ? sys_get_temp_dir() : ''; if (empty($tmp_dir) || $ini_wrapper->getString('open_basedir') && - (!$filesystem->exists($tmp_dir) || !$filesystem->is_writable($tmp_dir))) + (!@file_exists($tmp_dir) || !@is_writable($tmp_dir))) { $config->setProxiesTargetDir($cache_dir); } From 97b834c3ef6051f11b0f74e60fe445976fb7d681 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 25 Dec 2016 22:19:03 +0100 Subject: [PATCH 1427/1676] [ticket/14934] Do not rely on open basedir being properly set PHPBB3-14934 --- phpBB/phpbb/di/proxy_instantiator.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/phpBB/phpbb/di/proxy_instantiator.php b/phpBB/phpbb/di/proxy_instantiator.php index f8ef39535b..70295a3dec 100644 --- a/phpBB/phpbb/di/proxy_instantiator.php +++ b/phpBB/phpbb/di/proxy_instantiator.php @@ -13,8 +13,6 @@ namespace phpbb\di; -use bantu\IniGetWrapper\IniGetWrapper; -use phpbb\filesystem\filesystem; use ProxyManager\Configuration; use ProxyManager\Factory\LazyLoadingValueHolderFactory; use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; @@ -45,11 +43,8 @@ class proxy_instantiator implements InstantiatorInterface // Prevent trying to write to system temp dir in case of open_basedir // restrictions being in effect - $ini_wrapper = new IniGetWrapper(); - $filesystem = new filesystem(); $tmp_dir = (function_exists('sys_get_temp_dir')) ? sys_get_temp_dir() : ''; - if (empty($tmp_dir) || $ini_wrapper->getString('open_basedir') && - (!@file_exists($tmp_dir) || !@is_writable($tmp_dir))) + if (empty($tmp_dir) || !@file_exists($tmp_dir) || !@is_writable($tmp_dir)) { $config->setProxiesTargetDir($cache_dir); } From 60251cd62367aa8b50e7f717479eea5170b03e98 Mon Sep 17 00:00:00 2001 From: Jakub Senko Date: Sun, 20 Nov 2016 19:06:23 +0100 Subject: [PATCH 1428/1676] [ticket/14557] Simplify updating overloaded events for extensions PHPBB3-14557 --- phpBB/phpbb/event/data.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/phpBB/phpbb/event/data.php b/phpBB/phpbb/event/data.php index c7365aee35..42080e96d5 100644 --- a/phpBB/phpbb/event/data.php +++ b/phpBB/phpbb/event/data.php @@ -63,4 +63,17 @@ class data extends Event implements \ArrayAccess { unset($this->data[$offset]); } + + /** + * Returns data with updated key in specified offset. + * + * @param string $offset Data array offset + * @param string $key Offset key + * @param mixed $value Value to update + * @return mixed Value of $value + */ + public function update_subarray($offset, $key, $value) + { + return $this->data[$offset][$key] = $value; + } } From f111e70fc3959d979e61e8134fcaefb670b32603 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 27 Dec 2016 21:48:01 +0100 Subject: [PATCH 1429/1676] [ticket/14914] Made emoji scale in size with text PHPBB3-14914 --- phpBB/phpbb/textformatter/s9e/factory.php | 4 ++-- phpBB/styles/prosilver/theme/common.css | 7 +++++++ tests/text_formatter/s9e/default_formatting_test.php | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index a310c67359..55149b8e63 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -348,10 +348,10 @@ class factory implements \phpbb\textformatter\cache_interface $configurator->registeredVars['max_img_width'] = 0; // Load the Emoji plugin and modify its tag's template to obey viewsmilies - $configurator->Emoji->setImageSize(18); + $configurator->Emoji->omitImageSize(); $configurator->Emoji->useSVG(); $tag = $configurator->Emoji->getTag(); - $tag->template = '' . str_replace('class="emoji"', 'class="smilies"', $tag->template) . ''; + $tag->template = '' . str_replace('class="emoji"', 'class="emoji smilies"', $tag->template) . ''; /** * Modify the s9e\TextFormatter configurator after the default settings are set diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index 9da5cfe3be..8505ac13f9 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -1047,6 +1047,13 @@ ul.linklist:after, display: block; } +.emoji { + min-height: 18px; + min-width: 18px; + height: 1em; + width: 1em; +} + .smilies { vertical-align: text-bottom; } diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php index e25c3246b5..a0c57214e4 100644 --- a/tests/text_formatter/s9e/default_formatting_test.php +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -298,7 +298,7 @@ class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case ), array( "Emoji: \xF0\x9F\x98\x80", - 'Emoji: ' . ' + 'Emoji: ' . ' ), array( "Emoji: \xF0\x9F\x98\x80", From 1eb451d0d49af102ef80e5617765f01c07eebeea Mon Sep 17 00:00:00 2001 From: Jakub Senko Date: Tue, 27 Dec 2016 22:28:34 +0100 Subject: [PATCH 1430/1676] [ticket/14557] Don't return $value PHPBB3-14557 --- phpBB/phpbb/event/data.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/phpBB/phpbb/event/data.php b/phpBB/phpbb/event/data.php index 42080e96d5..00ebbcefdd 100644 --- a/phpBB/phpbb/event/data.php +++ b/phpBB/phpbb/event/data.php @@ -70,10 +70,9 @@ class data extends Event implements \ArrayAccess * @param string $offset Data array offset * @param string $key Offset key * @param mixed $value Value to update - * @return mixed Value of $value */ public function update_subarray($offset, $key, $value) { - return $this->data[$offset][$key] = $value; + $this->data[$offset][$key] = $value; } } From aa888fab3404ba8544bbcc84ef96b1003979a200 Mon Sep 17 00:00:00 2001 From: Jakub Senko Date: Tue, 27 Dec 2016 22:30:47 +0100 Subject: [PATCH 1431/1676] [ticket/14557] Rename $offset to $subarray PHPBB3-14557 --- phpBB/phpbb/event/data.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/event/data.php b/phpBB/phpbb/event/data.php index 00ebbcefdd..276ab027f2 100644 --- a/phpBB/phpbb/event/data.php +++ b/phpBB/phpbb/event/data.php @@ -67,12 +67,12 @@ class data extends Event implements \ArrayAccess /** * Returns data with updated key in specified offset. * - * @param string $offset Data array offset - * @param string $key Offset key - * @param mixed $value Value to update + * @param string $subarray Data array subarray + * @param string $key Subarray key + * @param mixed $value Value to update */ - public function update_subarray($offset, $key, $value) + public function update_subarray($subarray, $key, $value) { - $this->data[$offset][$key] = $value; + $this->data[$subarray][$key] = $value; } } From e31c895774866f4d98557b0ead087debc0b9d7c3 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Wed, 28 Dec 2016 09:18:35 -0800 Subject: [PATCH 1432/1676] [ticket/14945] Send bbcode flags in user sig previews PHPBB3-14945 --- phpBB/includes/acp/acp_users.php | 4 +++- phpBB/includes/ucp/ucp_profile.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 25e9d6f658..5a2b1445dc 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -2018,7 +2018,9 @@ class acp_users $enable_smilies = ($config['allow_sig_smilies']) ? $this->optionget($user_row, 'sig_smilies') : false; $enable_urls = ($config['allow_sig_links']) ? $this->optionget($user_row, 'sig_links') : false; - $decoded_message = generate_text_for_edit($user_row['user_sig'], $user_row['user_sig_bbcode_uid'], $user_row['user_sig_bbcode_bitfield']); + $bbcode_flags = ($enable_bbcode ? OPTION_FLAG_BBCODE : 0) + ($enable_smilies ? OPTION_FLAG_SMILIES : 0) + ($enable_urls ? OPTION_FLAG_LINKS : 0); + + $decoded_message = generate_text_for_edit($user_row['user_sig'], $user_row['user_sig_bbcode_uid'], $bbcode_flags); $signature = $request->variable('signature', $decoded_message['text'], true); $signature_preview = ''; diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index a86c4f2672..c5ce9f2ec7 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -478,7 +478,9 @@ class ucp_profile $enable_smilies = ($config['allow_sig_smilies']) ? $user->optionget('sig_smilies') : false; $enable_urls = ($config['allow_sig_links']) ? $user->optionget('sig_links') : false; - $decoded_message = generate_text_for_edit($user->data['user_sig'], $user->data['user_sig_bbcode_uid'], $user->data['user_sig_bbcode_bitfield']); + $bbcode_flags = ($enable_bbcode ? OPTION_FLAG_BBCODE : 0) + ($enable_smilies ? OPTION_FLAG_SMILIES : 0) + ($enable_urls ? OPTION_FLAG_LINKS : 0); + + $decoded_message = generate_text_for_edit($user->data['user_sig'], $user->data['user_sig_bbcode_uid'], $bbcode_flags); $signature = $request->variable('signature', $decoded_message['text'], true); $signature_preview = ''; From e88aecd3b47ec56b28c721244564d014d7a3ba1f Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 30 Dec 2016 21:58:38 +0100 Subject: [PATCH 1433/1676] [ticket/14947] Updates phpunit to 4.8 $ composer update phpunit/phpunit --with-dependencies Dependency "symfony/yaml" is also a root requirement, but is not explicitly whitelisted. Ignoring. Loading composer repositories with package information Updating dependencies (including require-dev) - Installing sebastian/global-state (1.1.1) Loading from cache - Installing doctrine/instantiator (1.0.5) Loading from cache - Removing phpunit/phpunit-mock-objects (2.1.5) - Installing phpunit/phpunit-mock-objects (2.3.8) Loading from cache - Removing phpunit/php-file-iterator (1.3.4) - Installing phpunit/php-file-iterator (1.4.2) Loading from cache - Installing phpdocumentor/reflection-docblock (2.0.4) Downloading: 100% - Installing phpspec/prophecy (v1.6.2) Loading from cache - Removing phpunit/phpunit (4.1.6) - Installing phpunit/phpunit (4.8.31) Downloading: 100% sebastian/global-state suggests installing ext-uopz (*) phpdocumentor/reflection-docblock suggests installing dflydev/markdown (~1.0) phpdocumentor/reflection-docblock suggests installing erusev/parsedown (~1.0) Writing lock file Generating autoload files > echo 'You MUST manually modify the clean-vendor-dir target in build/build.xml when adding or upgrading dependencies.' You MUST manually modify the clean-vendor-dir target in build/build.xml when adding or upgrading dependencies. PHPBB3-14947 --- phpBB/composer.json | 2 +- phpBB/composer.lock | 304 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 260 insertions(+), 46 deletions(-) diff --git a/phpBB/composer.json b/phpBB/composer.json index e91430023d..15cbd2d052 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -55,7 +55,7 @@ "laravel/homestead": "~2.2", "phing/phing": "2.4.*", "phpunit/dbunit": "1.3.*", - "phpunit/phpunit": "4.1.*", + "phpunit/phpunit": "^4.1", "sami/sami": "1.*", "squizlabs/php_codesniffer": "2.*", "symfony/browser-kit": "^2.8", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index e550572fb3..70f65a290e 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "067b099cc97334a6a08a77e5648aa260", - "content-hash": "90198ca524b93a7e915aa6916b2f55af", + "hash": "8d03337c5b9f6ae7cc1a26f84ba0270b", + "content-hash": "be4cb6437adc268d96f99bcbaad66d03", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -1894,6 +1894,60 @@ } ], "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, { "name": "fabpot/goutte", "version": "v2.0.4", @@ -2178,6 +2232,118 @@ ], "time": "2012-11-29 21:23:47" }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-03 12:10:50" + }, + { + "name": "phpspec/prophecy", + "version": "v1.6.2", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0|^2.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.0", + "phpunit/phpunit": "^4.8 || ^5.6.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2016-11-21 14:58:47" + }, { "name": "phpunit/dbunit", "version": "1.3.2", @@ -2301,31 +2467,33 @@ }, { "name": "phpunit/php-file-iterator", - "version": "1.3.4", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, "autoload": { "classmap": [ - "File/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -2342,7 +2510,7 @@ "filesystem", "iterator" ], - "time": "2013-10-10 15:34:57" + "time": "2016-10-03 07:40:28" }, { "name": "phpunit/php-text-template", @@ -2480,16 +2648,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.1.6", + "version": "4.8.31", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "241116219bb7e3b8111a36ffd8f37546888738d6" + "reference": "98b2b39a520766bec663ff5b7ff1b729db9dbfe3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/241116219bb7e3b8111a36ffd8f37546888738d6", - "reference": "241116219bb7e3b8111a36ffd8f37546888738d6", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/98b2b39a520766bec663ff5b7ff1b729db9dbfe3", + "reference": "98b2b39a520766bec663ff5b7ff1b729db9dbfe3", "shasum": "" }, "require": { @@ -2499,17 +2667,19 @@ "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", - "phpunit/php-code-coverage": "~2.0", - "phpunit/php-file-iterator": "~1.3.1", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0.2", - "phpunit/phpunit-mock-objects": "2.1.5", - "sebastian/comparator": "~1.0", - "sebastian/diff": "~1.1", - "sebastian/environment": "~1.0", - "sebastian/exporter": "~1.0", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.2.2", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", "sebastian/version": "~1.0", - "symfony/yaml": "~2.0" + "symfony/yaml": "~2.1|~3.0" }, "suggest": { "phpunit/php-invoker": "~1.1" @@ -2520,7 +2690,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1.x-dev" + "dev-master": "4.8.x-dev" } }, "autoload": { @@ -2529,10 +2699,6 @@ ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], "license": [ "BSD-3-Clause" ], @@ -2544,34 +2710,36 @@ } ], "description": "The PHP Unit Testing framework.", - "homepage": "http://www.phpunit.de/", + "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], - "time": "2014-08-17 08:07:02" + "time": "2016-12-09 02:45:31" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.1.5", + "version": "2.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "7878b9c41edb3afab92b85edf5f0981014a2713a" + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/7878b9c41edb3afab92b85edf5f0981014a2713a", - "reference": "7878b9c41edb3afab92b85edf5f0981014a2713a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", "shasum": "" }, "require": { + "doctrine/instantiator": "^1.0.2", "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2" + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" }, "require-dev": { - "phpunit/phpunit": "~4.1" + "phpunit/phpunit": "~4.4" }, "suggest": { "ext-soap": "*" @@ -2579,7 +2747,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "2.3.x-dev" } }, "autoload": { @@ -2588,9 +2756,6 @@ ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -2607,7 +2772,7 @@ "mock", "xunit" ], - "time": "2014-06-12 07:22:15" + "time": "2015-10-02 06:51:40" }, { "name": "pimple/pimple", @@ -2644,9 +2809,7 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" + "email": "fabien@symfony.com" } ], "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", @@ -2947,6 +3110,57 @@ ], "time": "2016-06-17 09:04:28" }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, { "name": "sebastian/recursion-context", "version": "1.0.4", From 429225027ecf53a359dafcfcc3b03ce40f40fa1b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 2 Jan 2017 20:39:41 +0100 Subject: [PATCH 1434/1676] [ticket/14947] Create new webdriver instance for every test PHPUnit seems to have emptied the webdriver between every test, which causes curl errors. A new webdriver instance will now be created for every test file. This does not cause a lot of overhead for ui tests. PHPBB3-14947 --- tests/test_framework/phpbb_ui_test_case.php | 72 +++++++++++---------- tests/ui/permission_roles_test.php | 12 ++-- tests/ui/quick_links_test.php | 6 +- 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/tests/test_framework/phpbb_ui_test_case.php b/tests/test_framework/phpbb_ui_test_case.php index e3f636679c..b875d3212b 100644 --- a/tests/test_framework/phpbb_ui_test_case.php +++ b/tests/test_framework/phpbb_ui_test_case.php @@ -78,14 +78,11 @@ class phpbb_ui_test_case extends phpbb_test_case self::markTestSkipped('phpbb_functional_url was not set in test_config and wasn\'t set as PHPBB_FUNCTIONAL_URL environment variable either.'); } - if (!self::$webDriver) - { - try { - $capabilities = DesiredCapabilities::firefox(); - self::$webDriver = RemoteWebDriver::create(self::$host . ':' . self::$port, $capabilities); - } catch (WebDriverCurlException $e) { - self::markTestSkipped('PhantomJS webserver is not running.'); - } + try { + $capabilities = DesiredCapabilities::firefox(); + self::$webDriver = RemoteWebDriver::create(self::$host . ':' . self::$port, $capabilities); + } catch (WebDriverCurlException $e) { + self::markTestSkipped('PhantomJS webserver is not running.'); } if (!self::$already_installed) @@ -146,9 +143,14 @@ class phpbb_ui_test_case extends phpbb_test_case } } - static public function visit($path) + public function getDriver() { - self::$webDriver->get(self::$root_url . $path); + return self::$webDriver; + } + + public function visit($path) + { + $this->getDriver()->get(self::$root_url . $path); } static protected function recreate_database($config) @@ -157,14 +159,14 @@ class phpbb_ui_test_case extends phpbb_test_case $db_conn_mgr->recreate_db(); } - static public function find_element($type, $value) + public function find_element($type, $value) { - return self::$webDriver->findElement(WebDriverBy::$type($value)); + return $this->getDriver()->findElement(WebDriverBy::$type($value)); } - static public function submit($type = 'id', $value = 'submit') + public function submit($type = 'id', $value = 'submit') { - $element = self::find_element($type, $value); + $element = $this->find_element($type, $value); $element->click(); } @@ -305,21 +307,21 @@ class phpbb_ui_test_case extends phpbb_test_case $ext_path = str_replace('/', '%2F', $extension); $this->visit('adm/index.php?i=acp_extensions&mode=main&action=enable_pre&ext_name=' . $ext_path . '&sid=' . $this->sid); - $this->assertNotEmpty(count(self::find_element('cssSelector', '.submit-buttons'))); + $this->assertNotEmpty(count($this->find_element('cssSelector', '.submit-buttons'))); - self::find_element('cssSelector', "input[value='Enable']")->submit(); + $this->find_element('cssSelector', "input[value='Enable']")->submit(); $this->add_lang('acp/extensions'); try { - $meta_refresh = self::find_element('cssSelector', 'meta[http-equiv="refresh"]'); + $meta_refresh = $this->find_element('cssSelector', 'meta[http-equiv="refresh"]'); // Wait for extension to be fully enabled while (sizeof($meta_refresh)) { preg_match('#url=.+/(adm+.+)#', $meta_refresh->getAttribute('content'), $match); - self::$webDriver->execute(array('method' => 'post', 'url' => $match[1])); - $meta_refresh = self::find_element('cssSelector', 'meta[http-equiv="refresh"]'); + $this->getDriver()->execute(array('method' => 'post', 'url' => $match[1])); + $meta_refresh = $this->find_element('cssSelector', 'meta[http-equiv="refresh"]'); } } catch (\Facebook\WebDriver\Exception\NoSuchElementException $e) @@ -327,7 +329,7 @@ class phpbb_ui_test_case extends phpbb_test_case // Probably no refresh triggered } - $this->assertContainsLang('EXTENSION_ENABLE_SUCCESS', self::find_element('cssSelector', 'div.successbox')->getText()); + $this->assertContainsLang('EXTENSION_ENABLE_SUCCESS', $this->find_element('cssSelector', 'div.successbox')->getText()); $this->logout(); } @@ -415,7 +417,7 @@ class phpbb_ui_test_case extends phpbb_test_case } $this->visit('ucp.php?sid=' . $this->sid . '&mode=logout'); - $this->assertContains($this->lang('REGISTER'), self::$webDriver->getPageSource()); + $this->assertContains($this->lang('REGISTER'), $this->getDriver()->getPageSource()); unset($this->sid); } @@ -435,17 +437,17 @@ class phpbb_ui_test_case extends phpbb_test_case return; } - self::$webDriver->manage()->deleteAllCookies(); + $this->getDriver()->manage()->deleteAllCookies(); $this->visit('adm/index.php?sid=' . $this->sid); - $this->assertContains($this->lang('LOGIN_ADMIN_CONFIRM'), self::$webDriver->getPageSource()); + $this->assertContains($this->lang('LOGIN_ADMIN_CONFIRM'), $this->getDriver()->getPageSource()); - self::find_element('cssSelector', 'input[name=username]')->clear()->sendKeys($username); - self::find_element('cssSelector', 'input[type=password]')->sendKeys($username . $username); - self::find_element('cssSelector', 'input[name=login]')->click(); + $this->find_element('cssSelector', 'input[name=username]')->clear()->sendKeys($username); + $this->find_element('cssSelector', 'input[type=password]')->sendKeys($username . $username); + $this->find_element('cssSelector', 'input[name=login]')->click(); $this->assertContains($this->lang('ADMIN_PANEL'), $this->find_element('cssSelector', 'h1')->getText()); - $cookies = self::$webDriver->manage()->getCookies(); + $cookies = $this->getDriver()->manage()->getCookies(); // The session id is stored in a cookie that ends with _sid - we assume there is only one such cookie foreach ($cookies as $cookie) @@ -550,19 +552,19 @@ class phpbb_ui_test_case extends phpbb_test_case { $this->add_lang('ucp'); - self::$webDriver->manage()->deleteAllCookies(); + $this->getDriver()->manage()->deleteAllCookies(); $this->visit('ucp.php'); - $this->assertContains($this->lang('LOGIN_EXPLAIN_UCP'), self::$webDriver->getPageSource()); + $this->assertContains($this->lang('LOGIN_EXPLAIN_UCP'), $this->getDriver()->getPageSource()); - self::$webDriver->manage()->deleteAllCookies(); + $this->getDriver()->manage()->deleteAllCookies(); - self::find_element('cssSelector', 'input[name=username]')->sendKeys($username); - self::find_element('cssSelector', 'input[name=password]')->sendKeys($username . $username); - self::find_element('cssSelector', 'input[name=login]')->click(); + $this->find_element('cssSelector', 'input[name=username]')->sendKeys($username); + $this->find_element('cssSelector', 'input[name=password]')->sendKeys($username . $username); + $this->find_element('cssSelector', 'input[name=login]')->click(); $this->assertNotContains($this->lang('LOGIN'), $this->find_element('className', 'navbar')->getText()); - $cookies = self::$webDriver->manage()->getCookies(); + $cookies = $this->getDriver()->manage()->getCookies(); // The session id is stored in a cookie that ends with _sid - we assume there is only one such cookie foreach ($cookies as $cookie) @@ -586,6 +588,6 @@ class phpbb_ui_test_case extends phpbb_test_case // Change the Path to your own settings $screenshot = time() . ".png"; - self::$webDriver->takeScreenshot($screenshot); + $this->getDriver()->takeScreenshot($screenshot); } } diff --git a/tests/ui/permission_roles_test.php b/tests/ui/permission_roles_test.php index 3501124fc1..de54cc788d 100644 --- a/tests/ui/permission_roles_test.php +++ b/tests/ui/permission_roles_test.php @@ -25,19 +25,19 @@ class ui_permission_roles_test extends phpbb_ui_test_case $this->visit('adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid); // Select forums - $elements = self::find_element('cssSelector', 'select#forum') + $elements = $this->find_element('cssSelector', 'select#forum') ->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option')); foreach ($elements as $element) { $element->click(); } - self::find_element('cssSelector', 'form#select_victim') + $this->find_element('cssSelector', 'form#select_victim') ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=submit]')) ->click(); // Select administrators and guests - $groups_form = self::find_element('cssSelector', 'form#groups'); + $groups_form = $this->find_element('cssSelector', 'form#groups'); $elements = $groups_form ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('select')) ->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option')); @@ -51,7 +51,7 @@ class ui_permission_roles_test extends phpbb_ui_test_case } $groups_form->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[name=submit_edit_options]'))->click(); - $first_fieldset = self::find_element('cssSelector', '#perm11'); + $first_fieldset = $this->find_element('cssSelector', '#perm11'); $this->assertEquals('none', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); $first_fieldset ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle')) @@ -74,14 +74,14 @@ class ui_permission_roles_test extends phpbb_ui_test_case $this->assertEquals($this->lang('ROLE_FORUM_LIMITED'), $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText()); // Check that admin settings didn't get changed - $second_fieldset = self::find_element('cssSelector', '#perm10'); + $second_fieldset = $this->find_element('cssSelector', '#perm10'); $this->assertEquals('none', $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); // Full access = 14 $this->assertEquals(14, $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value')); $this->assertEquals($this->lang('ROLE_FORUM_FULL'), $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText()); // Check that category settings were not modified - $category_fieldset = self::find_element('cssSelector', '#perm00'); + $category_fieldset = $this->find_element('cssSelector', '#perm00'); $this->assertEquals('none', $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); // No settings $this->assertEquals('', $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value')); diff --git a/tests/ui/quick_links_test.php b/tests/ui/quick_links_test.php index 582aeafcae..171ef3ca53 100644 --- a/tests/ui/quick_links_test.php +++ b/tests/ui/quick_links_test.php @@ -19,8 +19,8 @@ class quick_links_test extends phpbb_ui_test_case public function test_quick_links() { $this->visit('index.php'); - $this->assertEmpty(self::find_element('className', 'dropdown')->getText()); - self::find_element('className', 'dropdown-toggle')->click(); - $this->assertNotNull(self::find_element('className', 'dropdown')->getText()); + $this->assertEmpty($this->find_element('className', 'dropdown')->getText()); + $this->find_element('className', 'dropdown-toggle')->click(); + $this->assertNotNull($this->find_element('className', 'dropdown')->getText()); } } From 4c550c221bebed3e45dec49fa741b02c608fa446 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 2 Jan 2017 23:23:53 +0100 Subject: [PATCH 1435/1676] [ticket/14954] Properly check if topic has attachments in mcp_queue PHPBB3-14954 --- phpBB/includes/mcp/mcp_queue.php | 2 +- phpBB/styles/prosilver/template/mcp_queue.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index 9060cc1098..f379392b12 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -577,7 +577,7 @@ class mcp_queue 'POST_SUBJECT' => ($row['post_subject'] != '') ? $row['post_subject'] : $user->lang['NO_SUBJECT'], 'TOPIC_TITLE' => $row['topic_title'], 'POST_TIME' => $user->format_date($row['post_time']), - 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['post_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + 'S_HAS_ATTACHMENTS' => $auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['post_attachment'], )); } unset($rowset, $forum_names); diff --git a/phpBB/styles/prosilver/template/mcp_queue.html b/phpBB/styles/prosilver/template/mcp_queue.html index c82aae5f8c..ee69bf448d 100644 --- a/phpBB/styles/prosilver/template/mcp_queue.html +++ b/phpBB/styles/prosilver/template/mcp_queue.html @@ -48,7 +48,7 @@
            - {postrow.POST_SUBJECT}
            + {postrow.POST_SUBJECT}
            {L_POSTED} {L_POST_BY_AUTHOR} {postrow.POST_AUTHOR_FULL} » {postrow.POST_TIME}
            From a4d67c55d97598f29c1f5a1e6a8dec4b1e58df6d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 3 Jan 2017 22:53:18 +0100 Subject: [PATCH 1436/1676] [ticket/14957] Make sure config_php_file is set before injecting PHPBB3-14957 --- phpBB/phpbb/di/container_builder.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index a314def0f3..ac1a1a1733 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -525,6 +525,11 @@ class container_builder */ protected function inject_dbal_driver() { + if (empty($this->config_php_file)) + { + return; + } + $config_data = $this->config_php_file->get_all(); if (!empty($config_data)) { From 92708b290500d6b8e81b3b9bae2829958486f615 Mon Sep 17 00:00:00 2001 From: javiexin Date: Wed, 4 Jan 2017 00:36:23 +0100 Subject: [PATCH 1437/1676] [ticket/14950] Add possibility to delete a template block Adds a new mode to alter_block_array to allow for the deletion of a certain block of template variables. The selection method is the same as for the other modes for alter_block_array. The passed in vararray is ignored, and an out of bounds index is considered an error. PHPBB3-14944 --- phpBB/phpbb/template/context.php | 42 ++++++++++++++++++++++++++++++- phpBB/phpbb/template/template.php | 3 ++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 4ee48205c8..ce0fef37fc 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -280,10 +280,11 @@ class context * If key is false the position is set to 0 * If key is true the position is set to the last entry * - * @param string $mode Mode to execute (valid modes are 'insert' and 'change') + * @param string $mode Mode to execute (valid modes are 'insert', 'change' and 'delete') * * If insert, the vararray is inserted at the given position (position counting from zero). * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new \value). + * If delete, the vararray is ignored, and the block at the given position (counting from zero) is removed. * * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) @@ -408,6 +409,45 @@ class context return true; } + // Delete Block + if ($mode == 'delete') + { + // If we are exceeding last iteration, do not delete anything + if ($key > sizeof($block)) + { + return false; + } + + // If we are positioned at the end, we remove the last element + if ($key == sizeof($block)) + { + $key--; + } + + // We are deleting the last element in the block, so remove the block + if (sizeof($block) === 1) + { + $block = null; // unset($block); does not work on references + return true; + } + + // Re-position template blocks + for ($i = $key; $i < sizeof($block)-1; $i++) + { + $block[$i] = $block[$i+1]; + $block[$i]['S_ROW_COUNT'] = $block[$i]['S_ROW_NUM'] = $i; + } + + // Remove the last element + unset($block[$i]); + + // Set first and last elements again, in case they were removed + $block[0]['S_FIRST_ROW'] = true; + $block[sizeof($block)-1]['S_LAST_ROW'] = true; + + return true; + } + return false; } diff --git a/phpBB/phpbb/template/template.php b/phpBB/phpbb/template/template.php index 041ecb12e4..3d8505e204 100644 --- a/phpBB/phpbb/template/template.php +++ b/phpBB/phpbb/template/template.php @@ -160,10 +160,11 @@ interface template * If key is false the position is set to 0 * If key is true the position is set to the last entry * - * @param string $mode Mode to execute (valid modes are 'insert' and 'change') + * @param string $mode Mode to execute (valid modes are 'insert', 'change' and 'delete') * * If insert, the vararray is inserted at the given position (position counting from zero). * If change, the current block gets merged with the vararray (resulting in new \key/value pairs be added and existing keys be replaced by the new \value). + * If delete, the vararray is ignored, and the block at the given position (counting from zero) is removed. * * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) From 1db7aa712af0521f1a64e90c6fcf4972ac5b08c2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 4 Jan 2017 19:19:02 +0100 Subject: [PATCH 1438/1676] [ticket/14838] Add missing method to mock'ed feed PHPBB3-14838 --- tests/feed/attachments_mock_feed.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/feed/attachments_mock_feed.php b/tests/feed/attachments_mock_feed.php index 0e623fed24..fb67a48f7c 100644 --- a/tests/feed/attachments_mock_feed.php +++ b/tests/feed/attachments_mock_feed.php @@ -28,4 +28,9 @@ class phpbb_feed_attachments_mock_feed extends \phpbb\feed\attachments_base return true; } + + public function adjust_item(&$item_row, &$row) + { + return array(); + } } From b582a19039acb004d38927cde29f459f8bf4039f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 4 Jan 2017 19:47:10 +0100 Subject: [PATCH 1439/1676] [ticket/14838] Correctly instantiate language object PHPBB3-14838 --- tests/feed/attachments_base_test.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/feed/attachments_base_test.php b/tests/feed/attachments_base_test.php index c980dfd3d7..dd432d13f5 100644 --- a/tests/feed/attachments_base_test.php +++ b/tests/feed/attachments_base_test.php @@ -31,7 +31,12 @@ class phpbb_feed_attachments_base_test extends phpbb_database_test_case $this->filesystem = new \phpbb\filesystem(); $config = new \phpbb\config\config(array()); - $user = new \phpbb\user('\phpbb\datetime'); + $user = new \phpbb\user( + new \phpbb\language\language( + new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx) + ), + '\phpbb\datetime' + ); $feed_helper = new \phpbb\feed\helper($config, $user, $phpbb_root_path, $phpEx); $db = $this->new_dbal(); $cache = new \phpbb_mock_cache(); From c6746ab3cd02b4c8a05895c334a3f812a5a5c5b1 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 4 Jan 2017 21:40:46 +0100 Subject: [PATCH 1440/1676] [ticket/14946] Make sure to pass integers to max() PHPBB3-14946 --- phpBB/phpbb/session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index cbe2f02851..cc200b1adc 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -838,7 +838,7 @@ class session $sql = 'SELECT COUNT(session_id) AS sessions FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . (int) $this->data['user_id'] . ' - AND session_time >= ' . (int) ($this->time_now - (max($config['session_length'], $config['form_token_lifetime']))); + AND session_time >= ' . (int) ($this->time_now - (max((int) $config['session_length'], (int) $config['form_token_lifetime']))); $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); From 777a1ad916e1e01cd2e7e988497a1b49d8500923 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 4 Jan 2017 22:04:07 +0100 Subject: [PATCH 1441/1676] [ticket/14945] Parse signature preview with generate_text_for_display() PHPBB3-14945 --- phpBB/includes/ucp/ucp_pm_compose.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index b61a9fab9f..b3c0752a2f 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -889,13 +889,8 @@ function compose_pm($id, $mode, $action, $user_folders = array()) // Signature if ($enable_sig && $config['allow_sig'] && $preview_signature) { - $parse_sig = new parse_message($preview_signature); - $parse_sig->bbcode_uid = $preview_signature_uid; - $parse_sig->bbcode_bitfield = $preview_signature_bitfield; - - $parse_sig->format_display($config['allow_sig_bbcode'], $config['allow_sig_links'], $config['allow_sig_smilies']); - $preview_signature = $parse_sig->message; - unset($parse_sig); + $bbcode_flags = ($enable_bbcode ? OPTION_FLAG_BBCODE : 0) + ($enable_smilies ? OPTION_FLAG_SMILIES : 0) + ($enable_urls ? OPTION_FLAG_LINKS : 0); + $preview_signature = generate_text_for_display($preview_signature, $preview_signature_uid, $preview_signature_bitfield, $bbcode_flags); } else { From 0a68593dd2ac015749e22aae015e5b22ba460c82 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 5 Jan 2017 23:39:30 +0100 Subject: [PATCH 1442/1676] [ticket/14949] Pass full notification array and post data for updating PHPBB3-14949 --- phpBB/phpbb/notification/type/post.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php index b9afc6d70a..03221e7c7a 100644 --- a/phpBB/phpbb/notification/type/post.php +++ b/phpBB/phpbb/notification/type/post.php @@ -456,6 +456,12 @@ class post extends \phpbb\notification\type\base return array(); } - return array('notification_data' => $serialized_data); + $data_array = array_merge(array( + 'post_time' => $post['post_time'], + 'post_id' => $post['post_id'], + 'topic_id' => $post['topic_id'] + ), $this->get_data(false)); + + return $data_array; } } From e0eeea800cb51217e4511c3bcfcba6406d89f314 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 6 Jan 2017 00:57:12 +0100 Subject: [PATCH 1443/1676] [ticket/14961] Add cookie notice as enablable feature Uses Insites cookieconsent v3.0.3: https://cookieconsent.insites.com PHPBB3-14961 --- .../cookieconsent/cookieconsent.min.css | 6 ++++ .../assets/cookieconsent/cookieconsent.min.js | 1 + phpBB/includes/acp/acp_board.php | 1 + phpBB/includes/functions.php | 1 + phpBB/language/en/acp/board.php | 2 ++ phpBB/language/en/common.php | 2 ++ .../db/migration/data/v320/cookie_notice.php | 31 +++++++++++++++++++ .../prosilver/template/overall_footer.html | 22 +++++++++++++ .../prosilver/template/overall_header.html | 4 +++ 9 files changed, 70 insertions(+) create mode 100644 phpBB/assets/cookieconsent/cookieconsent.min.css create mode 100644 phpBB/assets/cookieconsent/cookieconsent.min.js create mode 100644 phpBB/phpbb/db/migration/data/v320/cookie_notice.php diff --git a/phpBB/assets/cookieconsent/cookieconsent.min.css b/phpBB/assets/cookieconsent/cookieconsent.min.css new file mode 100644 index 0000000000..03c69fe82f --- /dev/null +++ b/phpBB/assets/cookieconsent/cookieconsent.min.css @@ -0,0 +1,6 @@ +.cc-window{opacity:1;transition:opacity 1s ease}.cc-window.cc-invisible{opacity:0}.cc-animate.cc-revoke{transition:transform 1s ease}.cc-animate.cc-revoke.cc-top{transform:translateY(-2em)}.cc-animate.cc-revoke.cc-bottom{transform:translateY(2em)}.cc-animate.cc-revoke.cc-active.cc-bottom,.cc-animate.cc-revoke.cc-active.cc-top,.cc-revoke:hover{transform:translateY(0)}.cc-grower{max-height:0;overflow:hidden;transition:max-height 1s} +.cc-link,.cc-revoke:hover{text-decoration:underline}.cc-revoke,.cc-window{position:fixed;overflow:hidden;box-sizing:border-box;font-family:Helvetica,Calibri,Arial,sans-serif;font-size:16px;line-height:1.5em;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;z-index:9999}.cc-window.cc-static{position:static}.cc-window.cc-floating{padding:2em;max-width:24em;-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner{padding:1em 1.8em;width:100%;-ms-flex-direction:row;flex-direction:row}.cc-revoke{padding:.5em}.cc-header{font-size:18px;font-weight:700}.cc-btn,.cc-close,.cc-link,.cc-revoke{cursor:pointer}.cc-link{opacity:.8;display:inline-block;padding:.2em}.cc-link:hover{opacity:1}.cc-link:active,.cc-link:visited{color:initial}.cc-btn{display:block;padding:.4em .8em;font-size:.9em;font-weight:700;border-width:2px;border-style:solid;text-align:center;white-space:nowrap}.cc-banner .cc-btn:last-child{min-width:140px}.cc-highlight .cc-btn:first-child{background-color:transparent;border-color:transparent}.cc-highlight .cc-btn:first-child:focus,.cc-highlight .cc-btn:first-child:hover{background-color:transparent;text-decoration:underline}.cc-close{display:block;position:absolute;top:.5em;right:.5em;font-size:1.6em;opacity:.9;line-height:.75}.cc-close:focus,.cc-close:hover{opacity:1} +.cc-revoke.cc-top{top:0;left:3em;border-bottom-left-radius:.5em;border-bottom-right-radius:.5em}.cc-revoke.cc-bottom{bottom:0;left:3em;border-top-left-radius:.5em;border-top-right-radius:.5em}.cc-revoke.cc-left{left:3em;right:unset}.cc-revoke.cc-right{right:3em;left:unset}.cc-top{top:1em}.cc-left{left:1em}.cc-right{right:1em}.cc-bottom{bottom:1em}.cc-floating>.cc-link{margin-bottom:1em}.cc-floating .cc-message{display:block;margin-bottom:1em}.cc-window.cc-floating .cc-compliance{-ms-flex:1;flex:1}.cc-window.cc-banner{-ms-flex-align:center;align-items:center}.cc-banner.cc-top{left:0;right:0;top:0}.cc-banner.cc-bottom{left:0;right:0;bottom:0}.cc-banner .cc-message{-ms-flex:1;flex:1}.cc-compliance{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:justify;align-content:space-between}.cc-compliance>.cc-btn{-ms-flex:1;flex:1}.cc-btn+.cc-btn{margin-left:.5em} +@media print{.cc-revoke,.cc-window{display:none}}@media screen and (max-width:900px){.cc-btn{white-space:normal}}@media screen and (max-width:414px) and (orientation:portrait),screen and (max-width:736px) and (orientation:landscape){.cc-window.cc-top{top:0}.cc-window.cc-bottom{bottom:0}.cc-window.cc-banner,.cc-window.cc-left,.cc-window.cc-right{left:0;right:0}.cc-window.cc-banner{-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner .cc-compliance{-ms-flex:1;flex:1}.cc-window.cc-floating{max-width:none}.cc-window .cc-message{margin-bottom:1em}.cc-window.cc-banner{-ms-flex-align:unset;align-items:unset}} +.cc-floating.cc-theme-classic{padding:1.2em;border-radius:5px}.cc-floating.cc-type-info.cc-theme-classic .cc-compliance{text-align:center;display:inline;-ms-flex:none;flex:none}.cc-theme-classic .cc-btn{border-radius:5px}.cc-theme-classic .cc-btn:last-child{min-width:140px}.cc-floating.cc-type-info.cc-theme-classic .cc-btn{display:inline-block} +.cc-theme-edgeless.cc-window{padding:0}.cc-floating.cc-theme-edgeless .cc-message{margin:2em 2em 1.5em}.cc-banner.cc-theme-edgeless .cc-btn{margin:0;padding:.8em 1.8em;height:100%}.cc-banner.cc-theme-edgeless .cc-message{margin-left:1em}.cc-floating.cc-theme-edgeless .cc-btn+.cc-btn{margin-left:0} \ No newline at end of file diff --git a/phpBB/assets/cookieconsent/cookieconsent.min.js b/phpBB/assets/cookieconsent/cookieconsent.min.js new file mode 100644 index 0000000000..8e44bdde90 --- /dev/null +++ b/phpBB/assets/cookieconsent/cookieconsent.min.js @@ -0,0 +1 @@ +!function(e){if(!e.hasInitialised){var t={escapeRegExp:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},hasClass:function(e,t){var i=" ";return 1===e.nodeType&&(i+e.className+i).replace(/[\n\t]/g,i).indexOf(i+t+i)>=0},addClass:function(e,t){e.className+=" "+t},removeClass:function(e,t){var i=new RegExp("\\b"+this.escapeRegExp(t)+"\\b");e.className=e.className.replace(i,"")},interpolateString:function(e,t){var i=/{{([a-z][a-z0-9\-_]*)}}/gi;return e.replace(i,function(e){return t(arguments[1])||""})},getCookie:function(e){var t="; "+document.cookie,i=t.split("; "+e+"=");return 2!=i.length?void 0:i.pop().split(";").shift()},setCookie:function(e,t,i,n,o){var s=new Date;s.setDate(s.getDate()+(i||365));var r=[e+"="+t,"expires="+s.toUTCString(),"path="+(o||"/")];n&&r.push("domain="+n),document.cookie=r.join(";")},deepExtend:function(e,t){for(var i in t)t.hasOwnProperty(i)&&(i in e&&this.isPlainObject(e[i])&&this.isPlainObject(t[i])?this.deepExtend(e[i],t[i]):e[i]=t[i]);return e},throttle:function(e,t){var i=!1;return function(){i||(e.apply(this,arguments),i=!0,setTimeout(function(){i=!1},t))}},hash:function(e){var t,i,n,o=0;if(0===e.length)return o;for(t=0,n=e.length;t=128?"#000":"#fff"},getLuminance:function(e){var t=parseInt(this.normaliseHex(e),16),i=38,n=(t>>16)+i,o=(t>>8&255)+i,s=(255&t)+i,r=(16777216+65536*(n<255?n<1?0:n:255)+256*(o<255?o<1?0:o:255)+(s<255?s<1?0:s:255)).toString(16).slice(1);return"#"+r},isMobile:function(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},isPlainObject:function(e){return"object"==typeof e&&null!==e&&e.constructor==Object}};e.status={deny:"deny",allow:"allow",dismiss:"dismiss"},e.transitionEnd=function(){var e=document.createElement("div"),t={t:"transitionend",OT:"oTransitionEnd",msT:"MSTransitionEnd",MozT:"transitionend",WebkitT:"webkitTransitionEnd"};for(var i in t)if(t.hasOwnProperty(i)&&"undefined"!=typeof e.style[i+"ransition"])return t[i];return""}(),e.hasTransition=!!e.transitionEnd;var i=Object.keys(e.status).map(t.escapeRegExp);e.customStyles={},e.Popup=function(){function n(){this.initialise.apply(this,arguments)}function o(e){this.openingTimeout=null,t.removeClass(e,"cc-invisible")}function s(t){t.style.display="none",t.removeEventListener(e.transitionEnd,this.afterTransition),this.afterTransition=null}function r(){var t=this.options.onInitialise.bind(this);if(!window.navigator.cookieEnabled)return t(e.status.deny),!0;if(window.CookiesOK||window.navigator.CookiesOK)return t(e.status.allow),!0;var i=Object.keys(e.status),n=this.getStatus(),o=i.indexOf(n)>=0;return o&&t(n),o}function a(){var e=this.options.position.split("-"),t=[];return e.forEach(function(e){t.push("cc-"+e)}),t}function c(){var e=this.options,i="top"==e.position||"bottom"==e.position?"banner":"floating";t.isMobile()&&(i="floating");var n=["cc-"+i,"cc-type-"+e.type,"cc-theme-"+e.theme];e["static"]&&n.push("cc-static"),n.push.apply(n,a.call(this));p.call(this,this.options.palette);return this.customStyleSelector&&n.push(this.customStyleSelector),n}function l(){var e={},i=this.options;i.showLink||(i.elements.link="",i.elements.messagelink=i.elements.message),Object.keys(i.elements).forEach(function(n){e[n]=t.interpolateString(i.elements[n],function(e){var t=i.content[e];return e&&"string"==typeof t&&t.length?t:""})});var n=i.compliance[i.type];n||(n=i.compliance.info),e.compliance=t.interpolateString(n,function(t){return e[t]});var o=i.layouts[i.layout];return o||(o=i.layouts.basic),t.interpolateString(o,function(t){return e[t]})}function u(i){var n=this.options,o=document.createElement("div"),s=n.container&&1===n.container.nodeType?n.container:document.body;o.innerHTML=i;var r=o.children[0];return r.style.display="none",t.hasClass(r,"cc-window")&&e.hasTransition&&t.addClass(r,"cc-invisible"),this.onButtonClick=h.bind(this),r.addEventListener("click",this.onButtonClick),n.autoAttach&&(s.firstChild?s.insertBefore(r,s.firstChild):s.appendChild(r)),r}function h(n){var o=n.target;if(t.hasClass(o,"cc-btn")){var s=o.className.match(new RegExp("\\bcc-("+i.join("|")+")\\b")),r=s&&s[1]||!1;r&&(this.setStatus(r),this.close(!0))}t.hasClass(o,"cc-close")&&(this.setStatus(e.status.dismiss),this.close(!0)),t.hasClass(o,"cc-revoke")&&this.revokeChoice()}function p(e){var i=t.hash(JSON.stringify(e)),n="cc-color-override-"+i,o=t.isPlainObject(e);return this.customStyleSelector=o?n:null,o&&d(i,e,"."+n),o}function d(i,n,o){if(e.customStyles[i])return void++e.customStyles[i].references;var s={},r=n.popup,a=n.button,c=n.highlight;r&&(r.text=r.text?r.text:t.getContrast(r.background),r.link=r.link?r.link:r.text,s[o+".cc-window"]=["color: "+r.text,"background-color: "+r.background],s[o+".cc-revoke"]=["color: "+r.text,"background-color: "+r.background],s[o+" .cc-link,"+o+" .cc-link:active,"+o+" .cc-link:visited"]=["color: "+r.link],a&&(a.text=a.text?a.text:t.getContrast(a.background),a.border=a.border?a.border:"transparent",s[o+" .cc-btn"]=["color: "+a.text,"border-color: "+a.border,"background-color: "+a.background],"transparent"!=a.background&&(s[o+" .cc-btn:hover, "+o+" .cc-btn:focus"]=["background-color: "+v(a.background)]),c?(c.text=c.text?c.text:t.getContrast(c.background),c.border=c.border?c.border:"transparent",s[o+" .cc-highlight .cc-btn:first-child"]=["color: "+c.text,"border-color: "+c.border,"background-color: "+c.background]):s[o+" .cc-highlight .cc-btn:first-child"]=["color: "+r.text]));var l=document.createElement("style");document.head.appendChild(l),e.customStyles[i]={references:1,element:l.sheet};var u=-1;for(var h in s)s.hasOwnProperty(h)&&l.sheet.insertRule(h+"{"+s[h].join(";")+"}",++u)}function v(e){return e=t.normaliseHex(e),"000000"==e?"#222":t.getLuminance(e)}function f(i){if(t.isPlainObject(i)){var n=t.hash(JSON.stringify(i)),o=e.customStyles[n];if(o&&!--o.references){var s=o.element.ownerNode;s&&s.parentNode&&s.parentNode.removeChild(s),e.customStyles[n]=null}}}function m(e,t){for(var i=0,n=e.length;i=0&&(this.dismissTimeout=window.setTimeout(function(){t(e.status.dismiss)},Math.floor(i)));var n=this.options.dismissOnScroll;if("number"==typeof n&&n>=0){var o=function(i){window.pageYOffset>Math.floor(n)&&(t(e.status.dismiss),window.removeEventListener("scroll",o),this.onWindowScroll=null)};this.onWindowScroll=o,window.addEventListener("scroll",o)}}function y(){if("info"!=this.options.type&&(this.options.revokable=!0),t.isMobile()&&(this.options.animateRevokable=!1),this.options.revokable){var e=a.call(this);this.options.animateRevokable&&e.push("cc-animate"),this.customStyleSelector&&e.push(this.customStyleSelector);var i=this.options.revokeBtn.replace("{{classes}}",e.join(" "));this.revokeBtn=u.call(this,i);var n=this.revokeBtn;if(this.options.animateRevokable){var o=t.throttle(function(e){var i=!1,o=20,s=window.innerHeight-20;t.hasClass(n,"cc-top")&&e.clientYs&&(i=!0),i?t.hasClass(n,"cc-active")||t.addClass(n,"cc-active"):t.hasClass(n,"cc-active")&&t.removeClass(n,"cc-active")},200);this.onMouseMove=o,window.addEventListener("mousemove",o)}}}var g={enabled:!0,container:null,cookie:{name:"cookieconsent_status",path:"/",domain:"",expiryDays:365},onPopupOpen:function(){},onPopupClose:function(){},onInitialise:function(e){},onStatusChange:function(e,t){},onRevokeChoice:function(){},content:{header:"Cookies used on the website!",message:"This website uses cookies to ensure you get the best experience on our website.",dismiss:"Got it!",allow:"Allow cookies",deny:"Decline",link:"Learn more",href:"http://cookiesandyou.com",close:"❌"},elements:{header:'{{header}} ',message:'{{message}}',messagelink:'{{message}} {{link}}',dismiss:'{{dismiss}}',allow:'{{allow}}',deny:'{{deny}}',link:'{{link}}',close:'{{close}}'},window:'',revokeBtn:'
            Cookie Policy
            ',compliance:{info:'
            {{dismiss}}
            ',"opt-in":'
            {{dismiss}}{{allow}}
            ',"opt-out":'
            {{deny}}{{dismiss}}
            '},type:"info",layouts:{basic:"{{messagelink}}{{compliance}}","basic-close":"{{messagelink}}{{compliance}}{{close}}","basic-header":"{{header}}{{message}}{{link}}{{compliance}}"},layout:"basic",position:"bottom",theme:"block","static":!1,palette:null,revokable:!1,animateRevokable:!0,showLink:!0,dismissOnScroll:!1,dismissOnTimeout:!1,autoOpen:!0,autoAttach:!0,whitelistPage:[],blacklistPage:[],overrideHTML:null};return n.prototype.initialise=function(e){this.options&&this.destroy(),t.deepExtend(this.options={},g),t.isPlainObject(e)&&t.deepExtend(this.options,e),r.call(this)&&(this.options.enabled=!1),m(this.options.blacklistPage,location.pathname)&&(this.options.enabled=!1),m(this.options.whitelistPage,location.pathname)&&(this.options.enabled=!0);var i=this.options.window.replace("{{classes}}",c.call(this).join(" ")).replace("{{children}}",l.call(this)),n=this.options.overrideHTML;if("string"==typeof n&&n.length&&(i=n),this.options["static"]){var o=u.call(this,'
            '+i+"
            ");o.style.display="",this.element=o.firstChild,this.element.style.display="none",t.addClass(this.element,"cc-invisible")}else this.element=u.call(this,i);b.call(this),y.call(this),this.options.autoOpen&&this.autoOpen()},n.prototype.destroy=function(){this.onButtonClick&&this.element&&(this.element.removeEventListener("click",this.onButtonClick),this.onButtonClick=null),this.dismissTimeout&&(clearTimeout(this.dismissTimeout),this.dismissTimeout=null),this.onWindowScroll&&(window.removeEventListener("scroll",this.onWindowScroll),this.onWindowScroll=null),this.onMouseMove&&(window.removeEventListener("mousemove",this.onMouseMove),this.onMouseMove=null),this.element&&this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.element=null,this.revokeBtn&&this.revokeBtn.parentNode&&this.revokeBtn.parentNode.removeChild(this.revokeBtn),this.revokeBtn=null,f(this.options.palette),this.options=null},n.prototype.open=function(t){if(this.element)return this.isOpen()||(e.hasTransition?this.fadeIn():this.element.style.display="",this.options.revokable&&this.toggleRevokeButton(),this.options.onPopupOpen.call(this)),this},n.prototype.close=function(t){if(this.element)return this.isOpen()&&(e.hasTransition?this.fadeOut():this.element.style.display="none",t&&this.options.revokable&&this.toggleRevokeButton(!0),this.options.onPopupClose.call(this)),this},n.prototype.fadeIn=function(){var i=this.element;if(e.hasTransition&&i&&(this.afterTransition&&s.call(this,i),t.hasClass(i,"cc-invisible"))){if(i.style.display="",this.options["static"]){var n=this.element.clientHeight;this.element.parentNode.style.maxHeight=n+"px"}var r=20;this.openingTimeout=setTimeout(o.bind(this,i),r)}},n.prototype.fadeOut=function(){var i=this.element;e.hasTransition&&i&&(this.openingTimeout&&(clearTimeout(this.openingTimeout),o.bind(this,i)),t.hasClass(i,"cc-invisible")||(this.options["static"]&&(this.element.parentNode.style.maxHeight=""),this.afterTransition=s.bind(this,i),i.addEventListener(e.transitionEnd,this.afterTransition),t.addClass(i,"cc-invisible")))},n.prototype.isOpen=function(){return this.element&&""==this.element.style.display&&(!e.hasTransition||!t.hasClass(this.element,"cc-invisible"))},n.prototype.toggleRevokeButton=function(e){this.revokeBtn&&(this.revokeBtn.style.display=e?"":"none")},n.prototype.revokeChoice=function(e){this.options.enabled=!0,this.clearStatus(),this.options.onRevokeChoice.call(this),e||this.autoOpen()},n.prototype.hasAnswered=function(t){return Object.keys(e.status).indexOf(this.getStatus())>=0},n.prototype.hasConsented=function(t){var i=this.getStatus();return i==e.status.allow||i==e.status.dismiss},n.prototype.autoOpen=function(e){!this.hasAnswered()&&this.options.enabled&&this.open()},n.prototype.setStatus=function(i){var n=this.options.cookie,o=t.getCookie(n.name),s=Object.keys(e.status).indexOf(o)>=0;Object.keys(e.status).indexOf(i)>=0?(t.setCookie(n.name,i,n.expiryDays,n.domain,n.path),this.options.onStatusChange.call(this,i,s)):this.clearStatus()},n.prototype.getStatus=function(){return t.getCookie(this.options.cookie.name)},n.prototype.clearStatus=function(){var e=this.options.cookie;t.setCookie(e.name,"",-1,e.domain,e.path)},n}(),e.Location=function(){function e(e){t.deepExtend(this.options={},s),t.isPlainObject(e)&&t.deepExtend(this.options,e),this.currentServiceIndex=-1}function i(e,t,i){var n,o=document.createElement("script");o.type="text/"+(e.type||"javascript"),o.src=e.src||e,o.async=!1,o.onreadystatechange=o.onload=function(){var e=o.readyState;clearTimeout(n),t.done||e&&!/loaded|complete/.test(e)||(t.done=!0,t(),o.onreadystatechange=o.onload=null)},document.body.appendChild(o),n=setTimeout(function(){t.done=!0,t(),o.onreadystatechange=o.onload=null},i)}function n(e,t,i,n,o){var s=new(window.XMLHttpRequest||window.ActiveXObject)("MSXML2.XMLHTTP.3.0");if(s.open(n?"POST":"GET",e,1),s.setRequestHeader("X-Requested-With","XMLHttpRequest"),s.setRequestHeader("Content-type","application/x-www-form-urlencoded"),Array.isArray(o))for(var r=0,a=o.length;r3&&t(s)}),s.send(n)}function o(e){return new Error("Error ["+(e.code||"UNKNOWN")+"]: "+e.error)}var s={timeout:5e3,services:["freegeoip","ipinfo","maxmind"],serviceDefinitions:{freegeoip:function(){return{url:"//freegeoip.net/json/?callback={callback}",isScript:!0,callback:function(e,t){try{var i=JSON.parse(t);return i.error?o(i):{code:i.country_code}}catch(n){return o({error:"Invalid response ("+n+")"})}}}},ipinfo:function(){return{url:"//ipinfo.io",headers:["Accept: application/json"],callback:function(e,t){try{var i=JSON.parse(t);return i.error?o(i):{code:i.country}}catch(n){return o({error:"Invalid response ("+n+")"})}}}},ipinfodb:function(e){return{url:"//api.ipinfodb.com/v3/ip-country/?key={api_key}&format=json&callback={callback}",isScript:!0,callback:function(e,t){try{var i=JSON.parse(t);return"ERROR"==i.statusCode?o({error:i.statusMessage}):{code:i.countryCode}}catch(n){return o({error:"Invalid response ("+n+")"})}}}},maxmind:function(){return{url:"//js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js",isScript:!0,callback:function(e){return window.geoip2?void geoip2.country(function(t){try{e({code:t.country.iso_code})}catch(i){e(o(i))}},function(t){e(o(t))}):void e(new Error("Unexpected response format. The downloaded script should have exported `geoip2` to the global scope"))}}}}};return e.prototype.getNextService=function(){var e;do e=this.getServiceByIdx(++this.currentServiceIndex);while(this.currentServiceIndex=0,revokable:t.revokable.indexOf(e)>=0,explicitAction:t.explicitAction.indexOf(e)>=0}},e.prototype.applyLaw=function(e,t){var i=this.get(t);return i.hasLaw||(e.enabled=!1),this.options.regionalLaw&&(i.revokable&&(e.revokable=!0),i.explicitAction&&(e.dismissOnScroll=!1,e.dismissOnTimeout=!1)),e},e}(),e.initialise=function(t,i,n){var o=new e.Law(t.law);i||(i=function(){}),n||(n=function(){}),e.getCountryCode(t,function(n){delete t.law,delete t.location,n.code&&(t=o.applyLaw(t,n.code)),i(new e.Popup(t))},function(i){delete t.law,delete t.location,n(i,new e.Popup(t))})},e.getCountryCode=function(t,i,n){if(t.law&&t.law.countryCode)return void i({code:t.law.countryCode});if(t.location){var o=new e.Location(t.location);return void o.locate(function(e){i(e||{})},n)}i({})},e.utils=t,e.hasInitialised=!0,window.cookieconsent=e}}(window.cookieconsent||{}); \ No newline at end of file diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 02af98ec54..826d0007b7 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -323,6 +323,7 @@ class acp_board 'cookie_name' => array('lang' => 'COOKIE_NAME', 'validate' => 'string', 'type' => 'text::16', 'explain' => false), 'cookie_path' => array('lang' => 'COOKIE_PATH', 'validate' => 'string', 'type' => 'text::255', 'explain' => false), 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'validate' => 'bool', 'type' => 'radio:disabled_enabled', 'explain' => true), + 'cookie_notice' => array('lang' => 'COOKIE_NOTICE', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), ) ); break; diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 39d22254a2..3dabd1b46e 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4454,6 +4454,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = 'T_FONT_AWESOME_LINK' => !empty($config['allow_cdn']) && !empty($config['load_font_awesome_url']) ? $config['load_font_awesome_url'] : "{$web_path}assets/css/font-awesome.min.css?assets_version=" . $config['assets_version'], 'T_JQUERY_LINK' => !empty($config['allow_cdn']) && !empty($config['load_jquery_url']) ? $config['load_jquery_url'] : "{$web_path}assets/javascript/jquery.min.js?assets_version=" . $config['assets_version'], 'S_ALLOW_CDN' => !empty($config['allow_cdn']), + 'S_COOKIE_NOTICE' => !empty($config['cookie_notice']), 'T_THEME_NAME' => rawurlencode($user->style['style_path']), 'T_THEME_LANG_NAME' => $user->data['user_lang'], diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index e3d8e6742f..08290c9617 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -350,6 +350,8 @@ $lang = array_merge($lang, array( 'COOKIE_DOMAIN' => 'Cookie domain', 'COOKIE_NAME' => 'Cookie name', + 'COOKIE_NOTICE' => 'Cookie notice', + 'COOKIE_NOTICE_EXPLAIN' => 'If enabled a cookie notice will be displayed to users when visiting your board. This might be required by law depending on the content of your board and enabled extensions.', 'COOKIE_PATH' => 'Cookie path', 'COOKIE_SECURE' => 'Cookie secure', 'COOKIE_SECURE_EXPLAIN' => 'If your server is running via SSL set this to enabled else leave as disabled. Having this enabled and not running via SSL will result in server errors during redirects.', diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 0cc4decb40..852c997911 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -178,6 +178,8 @@ $lang = array_merge($lang, array( 'CONTACT' => 'Contact', 'CONTACT_USER' => 'Contact %s', 'CONTACT_US' => 'Contact us', + 'COOKIE_CONSENT_MSG' => 'This website uses cookies to ensure you get the best experience on our website.', + 'COOKIE_CONSENT_OK' => 'Got it!', 'COOKIES_DELETED' => 'All board cookies successfully deleted.', 'CURRENT_TIME' => 'It is currently %s', diff --git a/phpBB/phpbb/db/migration/data/v320/cookie_notice.php b/phpBB/phpbb/db/migration/data/v320/cookie_notice.php new file mode 100644 index 0000000000..75cb03b3ef --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/cookie_notice.php @@ -0,0 +1,31 @@ + +* @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\v320; + +class cookie_notice extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v320\v320rc2', + ); + } + + public function update_data() + { + return array( + array('config.add', array('cookie_notice', false)), + ); + } +} diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 39468201e5..e650d17752 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -59,6 +59,28 @@ + + + + + diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index 4a31a0adde..4438137f7d 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -57,6 +57,10 @@ + + + + From af4f477a1b23775f94c347b668e8d1a095818cd6 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 6 Jan 2017 01:04:14 +0100 Subject: [PATCH 1444/1676] [ticket/14961] Also translate "learn more" link PHPBB3-14961 --- phpBB/language/en/common.php | 1 + phpBB/styles/prosilver/template/overall_footer.html | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 852c997911..a04a06331b 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -178,6 +178,7 @@ $lang = array_merge($lang, array( 'CONTACT' => 'Contact', 'CONTACT_USER' => 'Contact %s', 'CONTACT_US' => 'Contact us', + 'COOKIE_CONSENT_INFO' => 'Learn more', 'COOKIE_CONSENT_MSG' => 'This website uses cookies to ensure you get the best experience on our website.', 'COOKIE_CONSENT_OK' => 'Got it!', 'COOKIES_DELETED' => 'All board cookies successfully deleted.', diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index e650d17752..413c93f79a 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -75,7 +75,8 @@ "theme": "classic", "content": { "message": "{LA_COOKIE_CONSENT_MSG}", - "dismiss": "{LA_COOKIE_CONSENT_OK}" + "dismiss": "{LA_COOKIE_CONSENT_OK}", + "link": "{LA_COOKIE_CONSENT_INFO}" } })}); From 743d3af3c52f21a47795b76598b0136ad261839a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 6 Jan 2017 12:06:39 +0100 Subject: [PATCH 1445/1676] [ticket/14961] Updated CREDITS.txt for cookie consent and removed subsilver2 PHPBB3-14961 --- phpBB/docs/CREDITS.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/phpBB/docs/CREDITS.txt b/phpBB/docs/CREDITS.txt index 26ff8fcc80..2df7543ce1 100644 --- a/phpBB/docs/CREDITS.txt +++ b/phpBB/docs/CREDITS.txt @@ -75,9 +75,7 @@ Major contributions by: leviatan21 (Gabriel Vazquez) Visual Confirmation: Xore (Robert Hetzler) -Original subSilver by subBlue Design, Tom Beddard, (c) 2001 phpBB Limited prosilver by subBlue Design, Tom Beddard, (c) 2004 phpBB Limited -subsilver2 by subBlue Design, Tom Beddard, (c) 2004 phpBB Limited phpBB contains code from the following applications: @@ -99,4 +97,5 @@ Pear (c) 2001-2004 PHP Group, http://pear.php.net Text_Diff-0.2.1 http://pear.php.net/package/Text_Diff MIT licenced: -Symfony2 (c) 2004-2011 Fabien Potencier, http://symfony.com/ +Symfony2 (c) 2004-2011 Fabien Potencier, https://symfony.com/ +Cookie Consent (c) 2015 Silktide Ltd, https://cookieconsent.insites.com From f82299b8e445cccfc8bad8cbe6505f3fb50d0f8f Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 6 Jan 2017 19:52:17 +0100 Subject: [PATCH 1446/1676] [ticket/14962] Introduces a new helper to check emptyness of bbcode texts PHPBB3-14962 --- phpBB/phpbb/textformatter/s9e/utils.php | 13 +++++++++++++ phpBB/phpbb/textformatter/utils_interface.php | 18 +++++++++++++----- phpBB/posting.php | 7 ++++--- tests/functional/posting_test.php | 15 +++++++++++++++ 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php index b317fe4a8d..a9a6d4b892 100644 --- a/phpBB/phpbb/textformatter/s9e/utils.php +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -136,4 +136,17 @@ class utils implements \phpbb\textformatter\utils_interface { return \s9e\TextFormatter\Unparser::unparse($xml); } + + /** + * {@inheritdoc} + */ + public function is_empty($text) + { + if ($text === null || $text === '') + { + return true; + } + + return trim($this->unparse($text)) === ''; + } } diff --git a/phpBB/phpbb/textformatter/utils_interface.php b/phpBB/phpbb/textformatter/utils_interface.php index 4810453cd1..4b7392976a 100644 --- a/phpBB/phpbb/textformatter/utils_interface.php +++ b/phpBB/phpbb/textformatter/utils_interface.php @@ -62,10 +62,18 @@ interface utils_interface public function remove_bbcode($text, $bbcode_name, $depth = 0); /** - * Return a parsed text to its original form - * - * @param string $text Parsed text - * @return string Original plain text - */ + * Return a parsed text to its original form + * + * @param string $text Parsed text + * @return string Original plain text + */ public function unparse($text); + + /** + * Return whether or not a parsed text represent an empty text. + * + * @param string $text Parsed text + * @return bool Tue if the original text is empty + */ + public function is_empty($text); } diff --git a/phpBB/posting.php b/phpBB/posting.php index b0aef2482a..aa10059796 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -816,6 +816,7 @@ if ($load && ($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_ load_drafts($topic_id, $forum_id); } +$bbcode_utils = $phpbb_container->get('text_formatter.utils'); if ($submit || $preview || $refresh) { @@ -1178,7 +1179,7 @@ if ($submit || $preview || $refresh) $post_data['poll_title'] = ''; $post_data['poll_start'] = $post_data['poll_length'] = $post_data['poll_max_options'] = $post_data['poll_last_vote'] = $post_data['poll_vote_change'] = 0; } - else if (!$auth->acl_get('f_poll', $forum_id) && ($mode == 'edit') && ($post_id == $post_data['topic_first_post_id']) && ($original_poll_data['poll_title'] != '')) + else if (!$auth->acl_get('f_poll', $forum_id) && ($mode == 'edit') && ($post_id == $post_data['topic_first_post_id']) && !$bbcode_utils->is_empty($original_poll_data['poll_title'])) { // We have a poll but the editing user is not permitted to create/edit it. // So we just keep the original poll-data. @@ -1601,7 +1602,7 @@ if ($generate_quote) if ($config['allow_bbcode']) { - $message_parser->message = $phpbb_container->get('text_formatter.utils')->generate_quote( + $message_parser->message = $bbcode_utils->generate_quote( censor_text($message_parser->message), array( 'author' => $post_data['quote_username'], @@ -1639,7 +1640,7 @@ $attachment_data = $message_parser->attachment_data; $filename_data = $message_parser->filename_data; $post_data['post_text'] = $message_parser->message; -if (sizeof($post_data['poll_options']) || !empty($post_data['poll_title'])) +if (sizeof($post_data['poll_options']) || (isset($post_data['poll_title']) && !$bbcode_utils->is_empty($post_data['poll_title']))) { $message_parser->message = $post_data['poll_title']; $message_parser->bbcode_uid = $post_data['bbcode_uid']; diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 9dd8a1dc91..4ed34eca31 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -86,6 +86,21 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $this->assertRegexp($expected, $crawler->filter('textarea#message')->text()); } + /** + * @see https://tracker.phpbb.com/browse/PHPBB3-14962 + */ + public function test_edit() + { + $this->login(); + $this->create_topic(2, 'Test Topic 1', 'Test topic'); + + $url = self::$client->getCrawler()->selectLink('Edit')->link()->getUri(); + $post_id = $this->get_parameter_from_link($url, 'p'); + $this->submit_post("posting.php?mode=edit&f=2&p={$post_id}", 'EDIT_POST', array('message' => 'Edited post')); + + $this->assertContains('Edited post', self::$client->getCrawler()->filter("#post_content{$post_id} .content")->text()); + } + /** * @testdox max_quote_depth is applied to the text populating the posting form */ From 89f0e4d54f5306a88260525e27204fae858a3fc5 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 6 Jan 2017 22:23:06 +0100 Subject: [PATCH 1447/1676] [ticket/14772] Use float to prevent pagination overwriting topic time PHPBB3-14772 --- phpBB/styles/prosilver/template/viewforum_body.html | 2 +- phpBB/styles/prosilver/theme/common.css | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html index 9824989687..7df57106e1 100644 --- a/phpBB/styles/prosilver/template/viewforum_body.html +++ b/phpBB/styles/prosilver/template/viewforum_body.html @@ -192,7 +192,7 @@ -
            +
            {L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} » {topicrow.FIRST_POST_TIME} diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index 8505ac13f9..e2211457ed 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -878,7 +878,6 @@ fieldset.fields1 dl.pmlist dd.recipients { /* Pagination in viewforum for multipage topics */ .row .pagination { display: block; - margin-top: -12px; } .row .pagination > ul { @@ -887,8 +886,13 @@ fieldset.fields1 dl.pmlist dd.recipients { .row .pagination li a, .row .pagination li span { border-radius: 2px; - padding: 1px 3px; - font-size: 9px; + padding: 1px 3px; + font-size: 9px; +} + +.topic-poster { + float: left; + padding-right: 0.5em; } /* jQuery popups From ba82dfa49ec585c9f9498c5a7f2d8ea8038e7143 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 6 Jan 2017 22:36:35 +0100 Subject: [PATCH 1448/1676] [ticket/14772] Add rtl definition for .topic-poster and small margin PHPBB3-14772 --- phpBB/styles/prosilver/theme/bidi.css | 4 ++++ phpBB/styles/prosilver/theme/common.css | 2 ++ 2 files changed, 6 insertions(+) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index f09493ab3b..5e9b4cfb2d 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -261,6 +261,10 @@ margin-right: 0; } +.rtl .topic-poster { + float: right; + padding-left: 0.5em; +} /* Action Bar styles ---------------------------------------- */ diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index e2211457ed..4765230f6c 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -878,6 +878,7 @@ fieldset.fields1 dl.pmlist dd.recipients { /* Pagination in viewforum for multipage topics */ .row .pagination { display: block; + margin-top: 0.3em; } .row .pagination > ul { @@ -893,6 +894,7 @@ fieldset.fields1 dl.pmlist dd.recipients { .topic-poster { float: left; padding-right: 0.5em; + margin-top: 0.3em; } /* jQuery popups From 538f03efb058c84daf3e677a3137be8900678f2b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 6 Jan 2017 23:46:34 +0100 Subject: [PATCH 1449/1676] [ticket/14962] Fix functional test for editing post PHPBB3-14962 --- tests/functional/posting_test.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 4ed34eca31..83acefd2f3 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -92,13 +92,16 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case public function test_edit() { $this->login(); - $this->create_topic(2, 'Test Topic 1', 'Test topic'); + $this->create_topic(2, 'Test Topic post', 'Test topic post'); $url = self::$client->getCrawler()->selectLink('Edit')->link()->getUri(); $post_id = $this->get_parameter_from_link($url, 'p'); - $this->submit_post("posting.php?mode=edit&f=2&p={$post_id}", 'EDIT_POST', array('message' => 'Edited post')); + $crawler = self::request('GET', "posting.php?mode=edit&f=2&p={$post_id}&sid={$this->sid}"); + $form = $crawler->selectButton('Submit')->form(); + $form->setValues(array('message' => 'Edited post')); + $crawler = self::submit($form); - $this->assertContains('Edited post', self::$client->getCrawler()->filter("#post_content{$post_id} .content")->text()); + $this->assertContains('Edited post', $crawler->filter("#post_content{$post_id} .content")->text()); } /** From da8ec61ab2dba1c8bb770932a6983cddbbb1251c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 7 Jan 2017 11:48:15 +0100 Subject: [PATCH 1450/1676] [prep-release-3.2.0] Update version numbers and add 3.2.0 migration --- build/build.xml | 2 +- phpBB/includes/constants.php | 2 +- phpBB/install/convertors/convert_phpbb20.php | 2 +- phpBB/install/phpbbcli.php | 2 +- phpBB/install/schemas/schema_data.sql | 2 +- phpBB/phpbb/db/migration/data/v320/v320.php | 40 ++++++++++++++++++++ phpBB/styles/prosilver/style.cfg | 4 +- 7 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 phpBB/phpbb/db/migration/data/v320/v320.php diff --git a/build/build.xml b/build/build.xml index 615e420a13..165f522047 100644 --- a/build/build.xml +++ b/build/build.xml @@ -2,7 +2,7 @@ - + diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index a6a5bf41cb..523f7adc53 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -28,7 +28,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -@define('PHPBB_VERSION', '3.2.0-RC3-dev'); +@define('PHPBB_VERSION', '3.2.0'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index c7006f9758..73d4b6b1ff 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -38,7 +38,7 @@ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms); $convertor_data = array( 'forum_name' => 'phpBB 2.0.x', 'version' => '1.0.3', - 'phpbb_version' => '3.2.0-RC3-dev', + 'phpbb_version' => '3.2.0', 'author' => 'phpBB Limited', 'dbms' => $dbms, 'dbhost' => $dbhost, diff --git a/phpBB/install/phpbbcli.php b/phpBB/install/phpbbcli.php index f5dfa83712..c67766e8a1 100755 --- a/phpBB/install/phpbbcli.php +++ b/phpBB/install/phpbbcli.php @@ -23,7 +23,7 @@ if (php_sapi_name() !== 'cli') define('IN_PHPBB', true); define('IN_INSTALL', true); define('PHPBB_ENVIRONMENT', 'production'); -define('PHPBB_VERSION', '3.2.0-RC3-dev'); +define('PHPBB_VERSION', '3.2.0'); $phpbb_root_path = __DIR__ . '/../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 64397904e9..5a9e012701 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -278,7 +278,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0 INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-RC3-dev'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); diff --git a/phpBB/phpbb/db/migration/data/v320/v320.php b/phpBB/phpbb/db/migration/data/v320/v320.php new file mode 100644 index 0000000000..20e741cb8b --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/v320.php @@ -0,0 +1,40 @@ + +* @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\v320; + +use phpbb\db\migration\migration; + +class v320 extends migration +{ + public function effectively_installed() + { + return version_compare($this->config['version'], '3.2.0', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\increase_size_of_emotion', + '\phpbb\db\migration\data\v320\cookie_notice', + ); + + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.0')), + ); + } +} diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg index 6701ce5905..725282036b 100644 --- a/phpBB/styles/prosilver/style.cfg +++ b/phpBB/styles/prosilver/style.cfg @@ -21,8 +21,8 @@ # General Information about this style name = prosilver copyright = © phpBB Limited, 2007 -style_version = 3.2.0-RC2 -phpbb_version = 3.2.0-RC2 +style_version = 3.2.0 +phpbb_version = 3.2.0 # Defining a different template bitfield # template_bitfield = lNg= From 9bbd034a4e818fbfef657e04c2a87c889af640af Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 7 Jan 2017 14:44:04 +0100 Subject: [PATCH 1451/1676] [prep-release-3.2.0] Correctly compare extensions version --- .../install/module/update_database/task/update_extensions.php | 2 +- .../phpbb/install/module/update_filesystem/task/file_check.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index 13c1591dcd..b66847b243 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -138,7 +138,7 @@ class update_extensions extends task_base $default_update_extensions = []; foreach (self::$default_extensions_update as $version => $extensions) { - if ($this->update_helper->phpbb_version_compare($version_from, $version, '<=')) + if ($this->update_helper->phpbb_version_compare($version_from, $version, '<')) { $default_update_extensions = array_merge($default_update_extensions, $extensions); } diff --git a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php index 5b48350e73..47a71eb844 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php @@ -123,7 +123,7 @@ class file_check extends task_base $default_update_extensions = []; foreach (\phpbb\install\module\update_database\task\update_extensions::$default_extensions_update as $version => $extensions) { - if ($this->update_helper->phpbb_version_compare($update_info['version']['from'], $version, '>')) + if ($this->update_helper->phpbb_version_compare($update_info['version']['from'], $version, '>=')) { $default_update_extensions = array_merge($default_update_extensions, $extensions); } From 830a384988587c817d9426fade09d6dd227def5d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 7 Jan 2017 16:16:24 +0100 Subject: [PATCH 1452/1676] [prep-release-3.2.0] Fix links to convertor --- phpBB/install/convert/controller/convertor.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/phpBB/install/convert/controller/convertor.php b/phpBB/install/convert/controller/convertor.php index 9a46117fe6..7b2a00d7b9 100644 --- a/phpBB/install/convert/controller/convertor.php +++ b/phpBB/install/convert/controller/convertor.php @@ -253,11 +253,11 @@ class convertor /** * Obtain convertor settings * - * @param string $convertor Name of the convertor + * @param string $converter Name of the convertor * * @return \Symfony\Component\HttpFoundation\Response|StreamedResponse */ - public function settings($convertor) + public function settings($converter) { $this->setup_navigation('settings'); @@ -265,7 +265,7 @@ class convertor require_once ($this->phpbb_root_path . 'includes/functions_convert.' . $this->php_ext); // Include convertor if available - $convertor_file_path = $this->phpbb_root_path . 'install/convertors/convert_' . $convertor . '.' . $this->php_ext; + $convertor_file_path = $this->phpbb_root_path . 'install/convertors/convert_' . $converter . '.' . $this->php_ext; if (!file_exists($convertor_file_path)) { if ($this->request->is_ajax()) @@ -313,8 +313,8 @@ class convertor // It must be an AJAX request at this point $response = new StreamedResponse(); $ref = $this; - $response->setCallback(function() use ($ref, $convertor) { - $ref->proccess_settings_form($convertor); + $response->setCallback(function() use ($ref, $converter) { + $ref->proccess_settings_form($converter); }); $response->headers->set('X-Accel-Buffering', 'no'); @@ -324,7 +324,7 @@ class convertor { $this->template->assign_vars(array( 'U_ACTION' => $this->controller_helper->route('phpbb_convert_settings', array( - 'convertor' => $convertor, + 'converter' => $converter, )) )); @@ -760,7 +760,7 @@ class convertor 'SOFTWARE' => $convertors[$index]['forum_name'], 'VERSION' => $convertors[$index]['version'], - 'U_CONVERT' => $this->controller_helper->route('phpbb_convert_settings', array('convertor' => $convertors[$index]['tag'])), + 'U_CONVERT' => $this->controller_helper->route('phpbb_convert_settings', array('converter' => $convertors[$index]['tag'])), )); } From 385feb0a5d21676786884aab0956976505efdf2a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 7 Jan 2017 17:19:35 +0100 Subject: [PATCH 1453/1676] [3.2.x] Update development version to 3.2.1-dev --- build/build.xml | 6 +++--- phpBB/includes/constants.php | 2 +- phpBB/install/schemas/schema_data.sql | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/build.xml b/build/build.xml index 165f522047..dd5fa4c5d8 100644 --- a/build/build.xml +++ b/build/build.xml @@ -2,9 +2,9 @@ - - - + + + diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 523f7adc53..440064140c 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -28,7 +28,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -@define('PHPBB_VERSION', '3.2.0'); +@define('PHPBB_VERSION', '3.2.1-dev'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 5a9e012701..998cf17c3d 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -278,7 +278,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0 INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.1-dev'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); From 9b2b9dd9de8d413f3f3b947b53e1a2a1e33dc477 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sat, 7 Jan 2017 22:47:26 +0100 Subject: [PATCH 1454/1676] [ticket/14950] Add possibility to delete a template block Adds a new mode to alter_block_array to allow for the deletion of a certain block of template variables. The selection method is the same as for the other modes for alter_block_array. The passed in vararray is ignored, and an out of bounds index is considered an error. Added tests for the new function. PHPBB3-14950 --- tests/template/template_test.php | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/template/template_test.php b/tests/template/template_test.php index 0bbfe3848d..d253651564 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -603,6 +603,48 @@ EOT $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring S_NUM_ROWS is correct after modification'); } + public function test_delete_alter_block_array() + { + $this->template->set_filenames(array('test' => 'loop_nested.html')); + + $this->template->assign_var('TEST_MORE', true); + + // @todo Change this + $this->template->assign_block_vars('outer', array('VARIABLE' => 'zero')); + $this->template->assign_block_vars('outer', array('VARIABLE' => 'one')); + $this->template->assign_block_vars('outer.middle', array('VARIABLE' => '1A')); + $this->template->assign_block_vars('outer', array('VARIABLE' => 'two')); + $this->template->assign_block_vars('outer.middle', array('VARIABLE' => '2A')); + $this->template->assign_block_vars('outer.middle', array('VARIABLE' => '2B')); + $this->template->assign_block_vars('outer', array('VARIABLE' => 'three')); + $this->template->assign_block_vars('outer.middle', array('VARIABLE' => '3A')); + $this->template->assign_block_vars('outer.middle', array('VARIABLE' => '3B')); + $this->template->assign_block_vars('outer.middle', array('VARIABLE' => '3C')); + + $expect = 'outer - 0 - zero[outer|4]outer - 1 - one[outer|4]middle - 0 - 1A[middle|1]outer - 2 - two[outer|4]middle - 0 - 2A[middle|2]middle - 1 - 2B[middle|2]outer - 3 - three[outer|4]middle - 0 - 3A[middle|3]middle - 1 - 3B[middle|3]middle - 2 - 3C[middle|3]'; + $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring template is built correctly before modification'); + + $this->template->alter_block_array('outer', array(), true, 'delete'); + + $expect = 'outer - 0 - one[outer|3]middle - 0 - 1A[middle|1]outer - 1 - two[outer|3]middle - 0 - 2A[middle|2]middle - 1 - 2B[middle|2]outer - 2 - three[outer|3]middle - 0 - 3A[middle|3]middle - 1 - 3B[middle|3]middle - 2 - 3C[middle|3]'; + $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Deleting at the beginning of outer loop'); + + $this->template->alter_block_array('outer[0].middle', array(), false, 'delete'); + + $expect = 'outer - 0 - one[outer|3]outer - 1 - two[outer|3]middle - 0 - 2A[middle|2]middle - 1 - 2B[middle|2]outer - 2 - three[outer|3]middle - 0 - 3A[middle|3]middle - 1 - 3B[middle|3]middle - 2 - 3C[middle|3]'; + $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Deleting at the end of first middle loop, delete complete loop'); + + $this->template->alter_block_array('outer', array(), 1, 'delete'); + + $expect = 'outer - 0 - one[outer|2]outer - 1 - three[outer|2]middle - 0 - 3A[middle|2]middle - 1 - 3C[middle|2]'; + $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Deleting by index at top level'); + + $this->template->alter_block_array('outer', array(), 4, 'delete'); + + $expect = 'outer - 0 - one[outer|2]outer - 1 - three[outer|2]middle - 0 - 3A[middle|2]middle - 1 - 3C[middle|2]'; + $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Deleting by index out of bounds, ignored'); + } + public function assign_block_vars_array_data() { return array( From 696724ac1b102d67aa765ebba7c898b0da3e8ba8 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 8 Jan 2017 00:59:26 +0100 Subject: [PATCH 1455/1676] [ticket/14950] Add possibility to delete a template block Adds a new mode to alter_block_array to allow for the deletion of a certain block of template variables. The selection method is the same as for the other modes for alter_block_array. The passed in vararray is ignored, and an out of bounds index is considered an error. Added tests for the new function, fixed. PHPBB3-14950 --- tests/template/template_test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/template/template_test.php b/tests/template/template_test.php index d253651564..2d27a5b56a 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -624,12 +624,12 @@ EOT $expect = 'outer - 0 - zero[outer|4]outer - 1 - one[outer|4]middle - 0 - 1A[middle|1]outer - 2 - two[outer|4]middle - 0 - 2A[middle|2]middle - 1 - 2B[middle|2]outer - 3 - three[outer|4]middle - 0 - 3A[middle|3]middle - 1 - 3B[middle|3]middle - 2 - 3C[middle|3]'; $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring template is built correctly before modification'); - $this->template->alter_block_array('outer', array(), true, 'delete'); + $this->template->alter_block_array('outer', array(), false, 'delete'); $expect = 'outer - 0 - one[outer|3]middle - 0 - 1A[middle|1]outer - 1 - two[outer|3]middle - 0 - 2A[middle|2]middle - 1 - 2B[middle|2]outer - 2 - three[outer|3]middle - 0 - 3A[middle|3]middle - 1 - 3B[middle|3]middle - 2 - 3C[middle|3]'; $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Deleting at the beginning of outer loop'); - $this->template->alter_block_array('outer[0].middle', array(), false, 'delete'); + $this->template->alter_block_array('outer[0].middle', array(), true, 'delete'); $expect = 'outer - 0 - one[outer|3]outer - 1 - two[outer|3]middle - 0 - 2A[middle|2]middle - 1 - 2B[middle|2]outer - 2 - three[outer|3]middle - 0 - 3A[middle|3]middle - 1 - 3B[middle|3]middle - 2 - 3C[middle|3]'; $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Deleting at the end of first middle loop, delete complete loop'); From 7f8dd6b007393482b7f9e3316a6756d0c3953e11 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 8 Jan 2017 01:19:22 +0100 Subject: [PATCH 1456/1676] [ticket/14950] Add possibility to delete a template block Adds a new mode to alter_block_array to allow for the deletion of a certain block of template variables. The selection method is the same as for the other modes for alter_block_array. The passed in vararray is ignored, and an out of bounds index is considered an error. Added tests for the new function, fixed. PHPBB3-14950 --- tests/template/template_test.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/template/template_test.php b/tests/template/template_test.php index 2d27a5b56a..3bc2f66ef0 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -636,9 +636,14 @@ EOT $this->template->alter_block_array('outer', array(), 1, 'delete'); - $expect = 'outer - 0 - one[outer|2]outer - 1 - three[outer|2]middle - 0 - 3A[middle|2]middle - 1 - 3C[middle|2]'; + $expect = 'outer - 0 - one[outer|2]outer - 1 - three[outer|3]middle - 0 - 3A[middle|3]middle - 1 - 3B[middle|3]middle - 2 - 3C[middle|3]'; $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Deleting by index at top level'); + $this->template->alter_block_array('outer.middle', array(), 1, 'delete'); + + $expect = 'outer - 0 - one[outer|2]outer - 1 - three[outer|2]middle - 0 - 3A[middle|2]middle - 1 - 3C[middle|2]'; + $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Deleting by index at middle level'); + $this->template->alter_block_array('outer', array(), 4, 'delete'); $expect = 'outer - 0 - one[outer|2]outer - 1 - three[outer|2]middle - 0 - 3A[middle|2]middle - 1 - 3C[middle|2]'; From 988865fd0a1d213a441777b3c613265365fe651a Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 8 Jan 2017 01:35:18 +0100 Subject: [PATCH 1457/1676] [ticket/14950] Add possibility to delete a template block Adds a new mode to alter_block_array to allow for the deletion of a certain block of template variables. The selection method is the same as for the other modes for alter_block_array. The passed in vararray is ignored, and an out of bounds index is considered an error. Added tests for the new function, fixed. PHPBB3-14950 --- tests/template/template_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/template/template_test.php b/tests/template/template_test.php index 3bc2f66ef0..c03da6e646 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -636,7 +636,7 @@ EOT $this->template->alter_block_array('outer', array(), 1, 'delete'); - $expect = 'outer - 0 - one[outer|2]outer - 1 - three[outer|3]middle - 0 - 3A[middle|3]middle - 1 - 3B[middle|3]middle - 2 - 3C[middle|3]'; + $expect = 'outer - 0 - one[outer|2]outer - 1 - three[outer|2]middle - 0 - 3A[middle|3]middle - 1 - 3B[middle|3]middle - 2 - 3C[middle|3]'; $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Deleting by index at top level'); $this->template->alter_block_array('outer.middle', array(), 1, 'delete'); From 40985de245d7eb5426f8379d93283331d1eab65a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 8 Jan 2017 10:48:30 +0100 Subject: [PATCH 1458/1676] [ticket/14967] Add cookie notice migration fixing invalid previous one PHPBB3-14967 --- .../migration/data/v32x/cookie_notice_p2.php | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 phpBB/phpbb/db/migration/data/v32x/cookie_notice_p2.php diff --git a/phpBB/phpbb/db/migration/data/v32x/cookie_notice_p2.php b/phpBB/phpbb/db/migration/data/v32x/cookie_notice_p2.php new file mode 100644 index 0000000000..1a83175705 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/cookie_notice_p2.php @@ -0,0 +1,36 @@ + +* @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\v32x; + +class cookie_notice_p2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v320\v320', + ); + } + + public function effectively_installed() + { + return isset($this->config['cookie_notice']); + } + + public function update_data() + { + return array( + array('config.add', array('cookie_notice', '0')), + ); + } +} From c98193a799067896e61b0df615fe49bc48814048 Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 8 Jan 2017 22:16:40 +0700 Subject: [PATCH 1459/1676] [ticket/14971] Fix pagination PHP warning on PHP 7.1 PHPBB3-14971 --- phpBB/phpbb/pagination.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/pagination.php b/phpBB/phpbb/pagination.php index 7a81c25ad2..a5a95b096d 100644 --- a/phpBB/phpbb/pagination.php +++ b/phpBB/phpbb/pagination.php @@ -284,7 +284,7 @@ class pagination */ public function get_on_page($per_page, $start) { - return floor($start / $per_page) + 1; + return floor((int) $start / (int) $per_page) + 1; } /** From 06b402bdecee8145639d50d17e1350971a5ec017 Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 8 Jan 2017 23:07:08 +0700 Subject: [PATCH 1460/1676] [ticket/14971] Add on_page test with the string arguments PHPBB3-14971 --- tests/pagination/pagination_test.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index 30b25913f7..2d7d1671a8 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -219,6 +219,12 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case 0, 'PAGE_OF-1-1', ), + array( + '10', + '10', + '0', + 'PAGE_OF-1-1', + ), ); } From 42cf311b2ff513a7d90b903f601157a7a65ba4cf Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 8 Jan 2017 18:31:10 +0100 Subject: [PATCH 1461/1676] =?UTF-8?q?[ticket/14973]=C2=A0Add=20BC=20layer?= =?UTF-8?q?=20for=20\phpbb\db\tools?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHPBB3-14973 --- phpBB/phpbb/db/tools.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 phpBB/phpbb/db/tools.php diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php new file mode 100644 index 0000000000..4d1b91f7b4 --- /dev/null +++ b/phpBB/phpbb/db/tools.php @@ -0,0 +1,21 @@ + +* @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; + +/** + * @deprecated 3.2.0-dev (To be removed 3.3.0) use \phpbb\db\tools\tools instead + */ +class tools extends \phpbb\db\tools\tools +{ +} From 29918884386d8acb738ccbc93c7e7457b5ddf3b4 Mon Sep 17 00:00:00 2001 From: hubaishan Date: Tue, 10 Jan 2017 12:27:25 +0300 Subject: [PATCH 1462/1676] [ticket/14975] Correct RTL style css display_options.html corrected to move (display and sorting option) to right jumpbox.html corrected to change arrow direction to left in RTL pagination.html corrected to change arrows direction on RTL bidi.css more edittions to correct remain style mistakes PHPBB3-14975 --- .../prosilver/template/display_options.html | 2 +- phpBB/styles/prosilver/template/jumpbox.html | 2 +- .../styles/prosilver/template/pagination.html | 4 ++-- phpBB/styles/prosilver/theme/bidi.css | 22 +++++++++++++++++-- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/phpBB/styles/prosilver/template/display_options.html b/phpBB/styles/prosilver/template/display_options.html index d1ec3dcef1..a426d08845 100644 --- a/phpBB/styles/prosilver/template/display_options.html +++ b/phpBB/styles/prosilver/template/display_options.html @@ -1,4 +1,4 @@ -
      @@ -179,7 +179,7 @@ - {L_VIEW_NEXT_PM} + {L_VIEW_NEXT_PM} diff --git a/phpBB/styles/prosilver/theme/icons.css b/phpBB/styles/prosilver/theme/icons.css index 9fb7244f4b..411fecaf3b 100644 --- a/phpBB/styles/prosilver/theme/icons.css +++ b/phpBB/styles/prosilver/theme/icons.css @@ -54,6 +54,10 @@ font-size: 16px; } +.arrow-left .icon { + float: left; +} + .arrow-left:hover .icon { margin-left: -5px; margin-right: 5px; From a3accfaf461bc963f0661bdab1befbc9ef50a514 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Wed, 11 Jan 2017 01:54:14 -0800 Subject: [PATCH 1464/1676] [ticket/14989] Allow more admin-configurable schemes in post links PHPBB3-14989 --- phpBB/includes/acp/acp_board.php | 7 ++++++ phpBB/language/en/acp/board.php | 2 ++ tests/functional/posting_test.php | 41 +++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 02af98ec54..84c3a89052 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -196,6 +196,7 @@ class acp_board 'allow_post_flash' => array('lang' => 'ALLOW_POST_FLASH', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_post_links' => array('lang' => 'ALLOW_POST_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allowed_schemes_links' => array('lang' => 'ALLOWED_SCHEMES_LINKS', 'validate' => 'string', 'type' => 'text:0:255', 'explain' => true), 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), @@ -551,6 +552,12 @@ class acp_board } } + // Invalidate the text_formatter cache when posting options are changed + if ($mode == 'post' && $submit) + { + $phpbb_container->get('text_formatter.cache')->invalidate(); + } + // Store news and exclude ids if ($mode == 'feed' && $submit) { diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index e3d8e6742f..6e9087af02 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -161,6 +161,8 @@ $lang = array_merge($lang, array( 'ACP_POST_SETTINGS_EXPLAIN' => 'Here you can set all default settings for posting.', 'ALLOW_POST_LINKS' => 'Allow links in posts/private messages', 'ALLOW_POST_LINKS_EXPLAIN' => 'If disallowed the [URL] BBCode tag and automatic/magic URLs are disabled.', + 'ALLOWED_SCHEMES_LINKS' => 'Allowed schemes in links', + 'ALLOWED_SCHEMES_LINKS_EXPLAIN' => 'Users can only post schemeless URLs or one of the comma-separated list of allowed schemes.', 'ALLOW_POST_FLASH' => 'Allow use of [FLASH] BBCode tag in posts', 'ALLOW_POST_FLASH_EXPLAIN' => 'If disallowed the [FLASH] BBCode tag is disabled in posts. Otherwise the permission system controls which users can use the [FLASH] BBCode tag.', diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 9dd8a1dc91..f3b222b388 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -246,4 +246,45 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case // Test that the preview contains the correct link $this->assertEquals($url, $crawler->filter('#preview a')->attr('href')); } + + public function test_allowed_schemes_links() + { + $text = 'http://example.org/ tcp://localhost:22/ServiceName'; + + $this->login(); + $this->admin_login(); + + // Post with default settings + $crawler = self::request('GET', 'posting.php?mode=post&f=2'); + $form = $crawler->selectButton('Preview')->form(array( + 'subject' => 'Test subject', + 'message' => $text, + )); + $crawler = self::submit($form); + $this->assertContains( + 'http://example.org/ tcp://localhost:22/ServiceName', + $crawler->filter('#preview .content')->html() + ); + + // Update allowed schemes + $crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post'); + $form = $crawler->selectButton('Submit')->form(); + $values = $form->getValues(); + $values['config[allowed_schemes_links]'] = 'https,tcp'; + $form->setValues($values); + $crawler = self::submit($form); + $this->assertEquals(1, $crawler->filter('.successbox')->count()); + + // Post with new settings + $crawler = self::request('GET', 'posting.php?mode=post&f=2'); + $form = $crawler->selectButton('Preview')->form(array( + 'subject' => 'Test subject', + 'message' => $text, + )); + $crawler = self::submit($form); + $this->assertContains( + 'http://example.org/ tcp://localhost:22/ServiceName', + $crawler->filter('#preview .content')->html() + ); + } } From ef215f573e7540bd7f26d936de4108057f9b3225 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Tue, 10 Jan 2017 18:04:16 +0100 Subject: [PATCH 1465/1676] [ticket/14985] Decode HTML special chars in plain text columns PHPBB3-14985 --- phpBB/phpbb/textformatter/data_access.php | 50 +++++++++++++++++------ phpBB/phpbb/textformatter/s9e/factory.php | 3 +- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/phpBB/phpbb/textformatter/data_access.php b/phpBB/phpbb/textformatter/data_access.php index 2103bf8e60..0d37e62c87 100644 --- a/phpBB/phpbb/textformatter/data_access.php +++ b/phpBB/phpbb/textformatter/data_access.php @@ -81,11 +81,8 @@ class data_access public function get_bbcodes() { $sql = 'SELECT bbcode_match, bbcode_tpl FROM ' . $this->bbcodes_table; - $result = $this->db->sql_query($sql); - $rows = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - return $rows; + return $this->fetch_decoded_rowset($sql, ['bbcode_match']); } /** @@ -101,11 +98,8 @@ class data_access $sql = 'SELECT code, emotion, smiley_url, smiley_width, smiley_height FROM ' . $this->smilies_table . ' ORDER BY display_on_posting DESC'; - $result = $this->db->sql_query($sql); - $rows = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - return $rows; + return $this->fetch_decoded_rowset($sql, ['code', 'emotion', 'smiley_url']); } /** @@ -116,11 +110,8 @@ class data_access protected function get_styles() { $sql = 'SELECT style_id, style_path, style_parent_id, bbcode_bitfield FROM ' . $this->styles_table; - $result = $this->db->sql_query($sql); - $rows = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - return $rows; + return $this->fetch_decoded_rowset($sql); } /** @@ -219,10 +210,43 @@ class data_access public function get_censored_words() { $sql = 'SELECT word, replacement FROM ' . $this->words_table; + + return $this->fetch_decoded_rowset($sql, ['word', 'replacement']); + } + + /** + * Decode HTML special chars in given rowset + * + * @param array $rows Original rowset + * @param array $columns List of columns to decode + * @return array Decoded rowset + */ + protected function decode_rowset(array $rows, array $columns) + { + foreach ($rows as &$row) + { + foreach ($columns as $column) + { + $row[$column] = htmlspecialchars_decode($row[$column]); + } + } + + return $rows; + } + + /** + * Fetch all rows for given query and decode plain text columns + * + * @param string $sql SELECT query + * @param array $columns List of columns to decode + * @return array + */ + protected function fetch_decoded_rowset($sql, array $columns = []) + { $result = $this->db->sql_query($sql); $rows = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); - return $rows; + return $this->decode_rowset($rows, $columns); } } diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 55149b8e63..5cbf2712f7 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -333,8 +333,7 @@ class factory implements \phpbb\textformatter\cache_interface $configurator->plugins->load('Censor', array('tagName' => 'censor:tag')); foreach ($censor as $row) { - // NOTE: words are stored as HTML, we need to decode them to plain text - $configurator->Censor->add(htmlspecialchars_decode($row['word']), htmlspecialchars_decode($row['replacement'])); + $configurator->Censor->add($row['word'], $row['replacement']); } } From 499fcbcca96c154298b355a945897aba4164ab8d Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Thu, 12 Jan 2017 09:27:00 +0100 Subject: [PATCH 1466/1676] [ticket/14985] Added functional tests for BBCodes and smilies PHPBB3-14985 --- tests/functional/acp_bbcodes_test.php | 46 +++++++++++++++++++++++++++ tests/functional/acp_smilies_test.php | 43 +++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 tests/functional/acp_bbcodes_test.php create mode 100644 tests/functional/acp_smilies_test.php diff --git a/tests/functional/acp_bbcodes_test.php b/tests/functional/acp_bbcodes_test.php new file mode 100644 index 0000000000..58681dfa07 --- /dev/null +++ b/tests/functional/acp_bbcodes_test.php @@ -0,0 +1,46 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +/** + * @group functional + */ +class phpbb_functional_acp_bbcodes_test extends phpbb_functional_test_case +{ + public function test_htmlspecialchars() + { + $this->login(); + $this->admin_login(); + + // Create the BBCode + $crawler = self::request('GET', 'adm/index.php?i=acp_bbcodes&sid=' . $this->sid . '&mode=bbcodes&action=add'); + $form = $crawler->selectButton('Submit')->form(array( + 'bbcode_match' => '[mod="{TEXT1}"]{TEXT2}[/mod]', + 'bbcode_tpl' => '
      {TEXT1}
      {TEXT2}
      ' + )); + self::submit($form); + + // Test it in the "new topic" preview + $crawler = self::request('GET', 'posting.php?mode=post&f=2&sid=' . $this->sid); + $form = $crawler->selectButton('Preview')->form(array( + 'subject' => 'subject', + 'message' => '[mod=a]b[/mod][mod="c"]d[/mod]' + )); + $crawler = self::submit($form); + + $html = $crawler->filter('#preview')->html(); + $this->assertContains('
      a
      ', $html); + $this->assertContains('
      b
      ', $html); + $this->assertContains('
      c
      ', $html); + $this->assertContains('
      d
      ', $html); + } +} diff --git a/tests/functional/acp_smilies_test.php b/tests/functional/acp_smilies_test.php new file mode 100644 index 0000000000..ebe8717fa7 --- /dev/null +++ b/tests/functional/acp_smilies_test.php @@ -0,0 +1,43 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +/** + * @group functional + */ +class phpbb_functional_acp_smilies_test extends phpbb_functional_test_case +{ + public function test_htmlspecialchars() + { + $this->login(); + $this->admin_login(); + + // Create the BBCode + $crawler = self::request('GET', 'adm/index.php?i=acp_icons&sid=' . $this->sid . '&mode=smilies&action=edit&id=1'); + $form = $crawler->selectButton('Submit')->form(array( + 'code[icon_e_biggrin.gif]' => '>:D', + 'emotion[icon_e_biggrin.gif]' => '>:D' + )); + self::submit($form); + + // Test it in the "new topic" preview + $crawler = self::request('GET', 'posting.php?mode=post&f=2&sid=' . $this->sid); + $form = $crawler->selectButton('Preview')->form(array( + 'subject' => 'subject', + 'message' => '>:D' + )); + $crawler = self::submit($form); + + $html = $crawler->filter('#preview')->html(); + $this->assertRegexp('(]+ alt=">:D" title=">:D"[^>]*>)', $html); + } +} From 136c74bd1c3d2ef1f22055d9bb14e6f524d41433 Mon Sep 17 00:00:00 2001 From: javiexin Date: Thu, 12 Jan 2017 21:28:58 +0100 Subject: [PATCH 1467/1676] [ticket/14950] Add possibility to delete a template block Adds a new mode to alter_block_array to allow for the deletion of a certain block of template variables. The selection method is the same as for the other modes for alter_block_array. The passed in vararray is ignored, and an out of bounds index is considered an error. Added tests for the new function, fixed. PHPBB3-14950 --- phpBB/phpbb/template/context.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index ce0fef37fc..b909b248aa 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -413,7 +413,7 @@ class context if ($mode == 'delete') { // If we are exceeding last iteration, do not delete anything - if ($key > sizeof($block)) + if ($key > sizeof($block) || $key < 0) { return false; } From a9a04adbd27104ca6a028e9a6ad9865b8871d8bc Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Thu, 12 Jan 2017 19:45:53 -0800 Subject: [PATCH 1468/1676] [ticket/14999] Correct Next PM Iconography PHPBB3-14999 --- phpBB/styles/prosilver/template/ucp_pm_viewmessage.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html index e2a086060c..4295867c05 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html @@ -15,7 +15,7 @@ - {L_VIEW_NEXT_HISTORY} + {L_VIEW_NEXT_HISTORY} @@ -179,7 +179,7 @@ - {L_VIEW_NEXT_PM} + {L_VIEW_NEXT_PM} From 8475632087c19a7ce684091d452b93acb0a1ad06 Mon Sep 17 00:00:00 2001 From: Jim Mossing Holsteyn Date: Fri, 13 Jan 2017 19:02:29 +0100 Subject: [PATCH 1469/1676] [ticket/15002] Show topic icons in search results --- phpBB/styles/prosilver/template/search_results.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/template/search_results.html b/phpBB/styles/prosilver/template/search_results.html index f7114567e5..ff4f3389c6 100644 --- a/phpBB/styles/prosilver/template/search_results.html +++ b/phpBB/styles/prosilver/template/search_results.html @@ -78,7 +78,7 @@
    • - style="background-image: url({T_ICONS_PATH}{searchresults.TOPIC_ICON_IMG}); background-repeat: no-repeat;" title="{searchresults.TOPIC_FOLDER_IMG_ALT}"> + style="background-image: url({T_ICONS_PATH}{searchresults.TOPIC_ICON_IMG}); background-repeat: no-repeat;" title="{searchresults.TOPIC_FOLDER_IMG_ALT}">
      From 15315ac87a68834e2d560acf62756f628a26da45 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sat, 14 Jan 2017 14:27:38 +0100 Subject: [PATCH 1470/1676] [ticket/15008] Disable emoji when smilies are disabled Will effectively disable emoji shortname and won't replace emoji with images but will not prevent a browser or OS from displaying emoji as images. PHPBB3-15008 --- phpBB/phpbb/textformatter/s9e/parser.php | 2 ++ .../tickets_data/PHPBB3-15008.before.php | 18 ++++++++++++++++++ .../tickets_data/PHPBB3-15008.html | 1 + .../tickets_data/PHPBB3-15008.txt | 1 + 4 files changed, 22 insertions(+) create mode 100644 tests/text_processing/tickets_data/PHPBB3-15008.before.php create mode 100644 tests/text_processing/tickets_data/PHPBB3-15008.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-15008.txt diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index e2653d60f0..05ddfffa11 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -142,6 +142,7 @@ class parser implements \phpbb\textformatter\parser_interface public function disable_smilies() { $this->parser->disablePlugin('Emoticons'); + $this->parser->disablePlugin('Emoji'); } /** @@ -183,6 +184,7 @@ class parser implements \phpbb\textformatter\parser_interface public function enable_smilies() { $this->parser->enablePlugin('Emoticons'); + $this->parser->enablePlugin('Emoji'); } /** diff --git a/tests/text_processing/tickets_data/PHPBB3-15008.before.php b/tests/text_processing/tickets_data/PHPBB3-15008.before.php new file mode 100644 index 0000000000..a3243e74cd --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-15008.before.php @@ -0,0 +1,18 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +function before_assert_phpbb3_15008($vars) +{ + extract($vars); + $parser->disable_smilies(); +} diff --git a/tests/text_processing/tickets_data/PHPBB3-15008.html b/tests/text_processing/tickets_data/PHPBB3-15008.html new file mode 100644 index 0000000000..7642eb63ee --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-15008.html @@ -0,0 +1 @@ +No smilies :) or shortnames :strawberry: \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-15008.txt b/tests/text_processing/tickets_data/PHPBB3-15008.txt new file mode 100644 index 0000000000..7642eb63ee --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-15008.txt @@ -0,0 +1 @@ +No smilies :) or shortnames :strawberry: \ No newline at end of file From 02b5873442de90b1d38eced87ecc7f9d780794d2 Mon Sep 17 00:00:00 2001 From: Richard McGirr Date: Sat, 14 Jan 2017 09:18:55 -0500 Subject: [PATCH 1471/1676] [ticket/15010] Fix incorrect use of request https://tracker.phpbb.com/browse/PHPBB3-15010 PHPBB3-15010 --- phpBB/phpbb/profilefields/type/type_date.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/profilefields/type/type_date.php b/phpBB/phpbb/profilefields/type/type_date.php index 414484920b..139ceabeec 100644 --- a/phpBB/phpbb/profilefields/type/type_date.php +++ b/phpBB/phpbb/profilefields/type/type_date.php @@ -72,7 +72,7 @@ class type_date extends type_base 'lang_options' => $field_data['lang_options'], ); - $always_now = $request->variable('always_now', -1); + $always_now = $this->request->variable('always_now', -1); if ($always_now == -1) { $s_checked = ($field_data['field_default_value'] == 'now') ? true : false; From abf7a4f6636d51f02ee9de0a359c5e784465a4ac Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 14 Jan 2017 22:48:24 +0100 Subject: [PATCH 1472/1676] [ticket/15012] Use valid constructor in ftp_file_updater PHPBB3-15012 --- phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php b/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php index 258a035768..5cdc331cbc 100644 --- a/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php +++ b/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php @@ -47,7 +47,7 @@ class ftp_file_updater implements file_updater_interface * @param string $phpbb_root_path * @param string $php_ext */ - public function __constructor(update_helper $update_helper, $phpbb_root_path, $php_ext) + public function __construct(update_helper $update_helper, $phpbb_root_path, $php_ext) { $this->transfer = null; $this->update_helper = $update_helper; From 52d53ef3de93f1d840f82520848a8d6b113da64a Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 15 Jan 2017 11:24:15 +0100 Subject: [PATCH 1473/1676] [ticket/15016] Fixed an issue with some parentheses in smilies PHPBB3-15016 --- phpBB/composer.json | 2 +- phpBB/composer.lock | 19 +++++--- .../tickets_data/PHPBB3-15016.html | 1 + .../tickets_data/PHPBB3-15016.txt | 1 + .../tickets_data/PHPBB3-15016.xml | 43 +++++++++++++++++++ 5 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 tests/text_processing/tickets_data/PHPBB3-15016.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-15016.txt create mode 100644 tests/text_processing/tickets_data/PHPBB3-15016.xml diff --git a/phpBB/composer.json b/phpBB/composer.json index 15cbd2d052..976c3a74cd 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -33,7 +33,7 @@ "marc1706/fast-image-size": "^1.1", "paragonie/random_compat": "^1.4", "patchwork/utf8": "^1.1", - "s9e/text-formatter": "~0.8.0", + "s9e/text-formatter": "~0.9.0", "symfony/config": "^2.8", "symfony/console": "^2.8", "symfony/debug": "^2.8", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 70f65a290e..c105fbdf6c 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "8d03337c5b9f6ae7cc1a26f84ba0270b", - "content-hash": "be4cb6437adc268d96f99bcbaad66d03", + "hash": "fa77bb5667bcac933b072b639a44aec0", + "content-hash": "da4fd9fbb589d2cffaa3f0168875475d", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -658,16 +658,16 @@ }, { "name": "s9e/text-formatter", - "version": "0.8.4", + "version": "0.9.0", "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "919fd772aae4dd889618da1cb18ae746f2a14bb6" + "reference": "9dc4227779f8a753dbf0c4f8cb129320522d325c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/919fd772aae4dd889618da1cb18ae746f2a14bb6", - "reference": "919fd772aae4dd889618da1cb18ae746f2a14bb6", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/9dc4227779f8a753dbf0c4f8cb129320522d325c", + "reference": "9dc4227779f8a753dbf0c4f8cb129320522d325c", "shasum": "" }, "require": { @@ -676,6 +676,11 @@ "lib-pcre": ">=7.2", "php": ">=5.3.3" }, + "require-dev": { + "matthiasmullie/minify": "*", + "php": ">=5.3.3", + "s9e/regexp-builder": ">=1.3.0" + }, "suggest": { "ext-curl": "Improves the performance of the MediaEmbed plugin and some JavaScript minifiers", "ext-intl": "Allows international URLs to be accepted by the URL filter", @@ -714,7 +719,7 @@ "parser", "shortcodes" ], - "time": "2016-11-22 20:10:24" + "time": "2017-01-15 10:15:45" }, { "name": "symfony/config", diff --git a/tests/text_processing/tickets_data/PHPBB3-15016.html b/tests/text_processing/tickets_data/PHPBB3-15016.html new file mode 100644 index 0000000000..47b66ad771 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-15016.html @@ -0,0 +1 @@ +)--( )-( )-- \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-15016.txt b/tests/text_processing/tickets_data/PHPBB3-15016.txt new file mode 100644 index 0000000000..081d9e3dc9 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-15016.txt @@ -0,0 +1 @@ +)--( )-( )-- \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-15016.xml b/tests/text_processing/tickets_data/PHPBB3-15016.xml new file mode 100644 index 0000000000..644481861e --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-15016.xml @@ -0,0 +1,43 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 1 + )--( + )--( + icon_lol.gif + 15 + 17 + 22 + 1 + + + 2 + )-- + )-- + icon_lol.gif + 15 + 17 + 22 + 1 + + + 3 + )-( + )-( + icon_lol.gif + 15 + 17 + 22 + 1 + +
      +
      From d6e42ec63b54c54b488d3e4112f4cd83062731ba Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 15 Jan 2017 12:00:36 +0100 Subject: [PATCH 1474/1676] [ticket/15011] Fix 3.2.x merge PHPBB3-15011 --- phpBB/phpbb/extension/metadata_manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index 9ea3c7e541..348b3c2cdf 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -216,7 +216,7 @@ class metadata_manager if (!$this->validate_enable()) { - throw new \phpbb\extension\exception($this->user->lang('META_FIELD_NOT_SET', $name)); + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array($name)); } break; From d28c016bef63123c43ac5e0303553aec807eef97 Mon Sep 17 00:00:00 2001 From: hanakin Date: Mon, 16 Jan 2017 12:27:53 -0500 Subject: [PATCH 1475/1676] [ticket/15023] undo previous changes PHPBB3-15023 --- phpBB/styles/prosilver/theme/bidi.css | 5 ----- phpBB/styles/prosilver/theme/common.css | 8 +------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 5e9b4cfb2d..f23af1b5fc 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -261,11 +261,6 @@ margin-right: 0; } -.rtl .topic-poster { - float: right; - padding-left: 0.5em; -} - /* Action Bar styles ---------------------------------------- */ .rtl .action-bar .button { diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index 4765230f6c..df9226e666 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -878,7 +878,7 @@ fieldset.fields1 dl.pmlist dd.recipients { /* Pagination in viewforum for multipage topics */ .row .pagination { display: block; - margin-top: 0.3em; + margin-top: -12px; } .row .pagination > ul { @@ -891,12 +891,6 @@ fieldset.fields1 dl.pmlist dd.recipients { font-size: 9px; } -.topic-poster { - float: left; - padding-right: 0.5em; - margin-top: 0.3em; -} - /* jQuery popups ---------------------------------------- */ .phpbb_alert { From 0d7d4b4ddd682ff9f75447c780f55911e8f739ca Mon Sep 17 00:00:00 2001 From: hanakin Date: Mon, 16 Jan 2017 12:28:52 -0500 Subject: [PATCH 1476/1676] [ticket/15023] Remove unnessecary left-box class no longer nessecary after this fix PHPPB3-15023 --- phpBB/styles/prosilver/template/viewforum_body.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html index 7df57106e1..867fd84112 100644 --- a/phpBB/styles/prosilver/template/viewforum_body.html +++ b/phpBB/styles/prosilver/template/viewforum_body.html @@ -189,7 +189,9 @@ {L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} « {topicrow.LAST_POST_TIME}
      {L_POSTED} {L_IN} {topicrow.FORUM_NAME}
      - + + +
      From c0af2072cadc94da81adc83c2522ce6ffb49ce87 Mon Sep 17 00:00:00 2001 From: hanakin Date: Mon, 16 Jan 2017 12:29:44 -0500 Subject: [PATCH 1477/1676] [ticket/15023] Remove all prev RWD and add new PHPBB3-15023 --- phpBB/styles/prosilver/theme/responsive.css | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/phpBB/styles/prosilver/theme/responsive.css b/phpBB/styles/prosilver/theme/responsive.css index d71fd142e6..bd980ecf99 100644 --- a/phpBB/styles/prosilver/theme/responsive.css +++ b/phpBB/styles/prosilver/theme/responsive.css @@ -280,11 +280,6 @@ margin: 5px 0 0; } - .row .pagination { - margin-top: 2px; - margin-bottom: 2px; - } - .row .pagination .ellipsis + li { display: none !important; } @@ -567,13 +562,11 @@ @media (max-width: 850px) { .postprofile { width: 28%; } + + } @media (min-width: 701px) and (max-width: 950px) { - .row .pagination { - margin-top: 2px; - margin-bottom: 2px; - } ul.topiclist dt { margin-right: -410px; @@ -588,3 +581,11 @@ } } +@media (max-width: 992px) { + .row .pagination { + margin-top: 4px; + margin-bottom: 4px; + float: left; + text-align: left; + } +} From 3bd01d812a3316237fc4a50235cc0c69c3448fbf Mon Sep 17 00:00:00 2001 From: hanakin Date: Mon, 16 Jan 2017 12:34:59 -0500 Subject: [PATCH 1478/1676] [ticket/15023] Fix for linting PHPBB3-15023 --- phpBB/styles/prosilver/theme/responsive.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/styles/prosilver/theme/responsive.css b/phpBB/styles/prosilver/theme/responsive.css index bd980ecf99..76033a5ce1 100644 --- a/phpBB/styles/prosilver/theme/responsive.css +++ b/phpBB/styles/prosilver/theme/responsive.css @@ -583,9 +583,9 @@ @media (max-width: 992px) { .row .pagination { + text-align: left; + float: left; margin-top: 4px; margin-bottom: 4px; - float: left; - text-align: left; } } From d0724063c4b144902eab36e98b4f0d5cce443152 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 15 Jan 2017 15:51:24 +0100 Subject: [PATCH 1479/1676] [ticket/11076] Also add notice about unsupported version to installer PHPBB3-11076 --- phpBB/install/app.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/phpBB/install/app.php b/phpBB/install/app.php index 9664f92cf1..ef59689a65 100644 --- a/phpBB/install/app.php +++ b/phpBB/install/app.php @@ -20,6 +20,11 @@ define('PHPBB_ENVIRONMENT', 'production'); $phpbb_root_path = '../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); +if (version_compare(PHP_VERSION, '5.4') < 0) +{ + die('You are running an unsupported PHP version. Please upgrade to PHP 5.4.0 or higher before trying to install or update to phpBB 3.2'); +} + $startup_new_path = $phpbb_root_path . 'install/update/update/new/install/startup.' . $phpEx; $startup_path = (file_exists($startup_new_path)) ? $startup_new_path : $phpbb_root_path . 'install/startup.' . $phpEx; require($startup_path); From b1f060a30ae89529c887db648f767578f5a8051a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 20 Jan 2017 21:20:59 +0100 Subject: [PATCH 1480/1676] [ticket/11076] Also state min PHP version when visiting forum website A lot better to have a simple message than having the complete board break, sometimes without even knowing thanks to bad host setups with no error logs. PHPBB3-11076 --- phpBB/common.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/phpBB/common.php b/phpBB/common.php index d12966168b..70feb55d04 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -12,7 +12,7 @@ */ /** -* Minimum Requirement: PHP 5.3.9 +* Minimum Requirement: PHP 5.4.0 */ if (!defined('IN_PHPBB')) @@ -20,6 +20,11 @@ if (!defined('IN_PHPBB')) exit; } +if (version_compare(PHP_VERSION, '5.4') < 0) +{ + die('You are running an unsupported PHP version. Please upgrade to PHP 5.4.0 or higher before trying to install or update to phpBB 3.2'); +} + require($phpbb_root_path . 'includes/startup.' . $phpEx); require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx); From eceb36a5463355707b9014533b3b19971f79177b Mon Sep 17 00:00:00 2001 From: kasimi Date: Fri, 20 Jan 2017 22:09:42 +0100 Subject: [PATCH 1481/1676] [ticket/15035] Add phpinfo.php to 3.2.x install directory In 3.1.x there's a phpinfo.php in the /install folder which seems to be removed in 3.2.x, perhaps by accident? https://github.com/phpbb/phpbb/commits/3.2.x/phpBB/install/phpinfo.php Let's add it back for easier troubleshooting potential issues during installation. PHPBB3-15035 --- phpBB/install/phpinfo.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 phpBB/install/phpinfo.php diff --git a/phpBB/install/phpinfo.php b/phpBB/install/phpinfo.php new file mode 100644 index 0000000000..28c3b9ff04 --- /dev/null +++ b/phpBB/install/phpinfo.php @@ -0,0 +1,14 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +phpinfo(); From 4b2a5a41a70a6c5745df8459d3c3de37af5249d2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 21 Jan 2017 10:28:08 +0100 Subject: [PATCH 1482/1676] [ticket/15036] Unlink install_config during functional testing PHPBB3-15036 --- tests/test_framework/phpbb_functional_test_case.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index e678bfbaef..eb56049515 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -291,6 +291,13 @@ class phpbb_functional_test_case extends phpbb_test_case } } + $install_config_file = $phpbb_root_path . 'store/install_config.php'; + + if (file_exists($install_config_file)) + { + unlink($install_config_file); + } + $container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); $container = $container_builder ->with_environment('installer') From f53f6d1c61f862ed4b9d17ac1f39896bb2bde0d8 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 22 Jan 2017 19:11:17 +0100 Subject: [PATCH 1483/1676] [ticket/15040] Updated s9e\TextFormatter to 0.9.1 PHPBB3-15040 --- phpBB/composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index c105fbdf6c..427fbe4d1b 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -658,16 +658,16 @@ }, { "name": "s9e/text-formatter", - "version": "0.9.0", + "version": "0.9.1", "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "9dc4227779f8a753dbf0c4f8cb129320522d325c" + "reference": "e0f1d477d5c24dff11fa3aaa408d8ead07006fe3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/9dc4227779f8a753dbf0c4f8cb129320522d325c", - "reference": "9dc4227779f8a753dbf0c4f8cb129320522d325c", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/e0f1d477d5c24dff11fa3aaa408d8ead07006fe3", + "reference": "e0f1d477d5c24dff11fa3aaa408d8ead07006fe3", "shasum": "" }, "require": { @@ -719,7 +719,7 @@ "parser", "shortcodes" ], - "time": "2017-01-15 10:15:45" + "time": "2017-01-22 17:12:21" }, { "name": "symfony/config", From 9aa8dc26b7a389f2c1d9622f8d3ef564b0abcbcd Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Sun, 22 Jan 2017 19:19:12 +0100 Subject: [PATCH 1484/1676] [ticket/14790] Added test case PHPBB3-14790 --- tests/text_processing/tickets_data/PHPBB3-14790.html | 4 ++++ tests/text_processing/tickets_data/PHPBB3-14790.txt | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 tests/text_processing/tickets_data/PHPBB3-14790.html create mode 100644 tests/text_processing/tickets_data/PHPBB3-14790.txt diff --git a/tests/text_processing/tickets_data/PHPBB3-14790.html b/tests/text_processing/tickets_data/PHPBB3-14790.html new file mode 100644 index 0000000000..7624b2d36c --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14790.html @@ -0,0 +1,4 @@ +
      • text
      • +
      • text
      • +
      • text
      • +
      • text
      \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14790.txt b/tests/text_processing/tickets_data/PHPBB3-14790.txt new file mode 100644 index 0000000000..1cd83d97d8 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14790.txt @@ -0,0 +1,4 @@ +[color=#0000FF][list][*]text +[*]text +[*]text +[*]text[/list][/color] \ No newline at end of file From 0238d850ddf708e54992ae5b11bfc4e20748c171 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 22 Jan 2017 19:36:19 +0100 Subject: [PATCH 1485/1676] [ticket/15015] Use correct explain string for enable email settings PHPBB3-15015 --- .../phpbb/install/module/obtain_data/task/obtain_email_data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php index 1cb4f04297..e8a9c971b7 100644 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php @@ -84,7 +84,7 @@ class obtain_email_data extends \phpbb\install\task_base implements \phpbb\insta $email_form = array( 'email_enable' => array( 'label' => 'ENABLE_EMAIL', - 'description' => 'COOKIE_SECURE_EXPLAIN', + 'description' => 'ENABLE_EMAIL_EXPLAIN', 'type' => 'radio', 'options' => array( array( From 9df6ef5735a32fe9c46be3891c6a4ed2308a1d27 Mon Sep 17 00:00:00 2001 From: tas2580 Date: Mon, 16 Jan 2017 19:08:25 +0100 Subject: [PATCH 1486/1676] Use SSL in version check for extension PHPBB3-15025 --- phpBB/phpbb/extension/manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index b2b60aaa9b..ca0ff31d5d 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -589,7 +589,7 @@ class manager $version_helper = new \phpbb\version_helper($this->cache, $this->config, new file_downloader()); $version_helper->set_current_version($meta['version']); - $version_helper->set_file_location($version_check['host'], $version_check['directory'], $version_check['filename']); + $version_helper->set_file_location($version_check['host'], $version_check['directory'], $version_check['filename'], isset($version_check['ssl']) ? $version_check['ssl'] : false); $version_helper->force_stability($stability); return $updates = $version_helper->get_suggested_updates($force_update, $force_cache); From 71ca228b8e33b56f75e7e977b28bbb72ada23d72 Mon Sep 17 00:00:00 2001 From: hanakin Date: Mon, 23 Jan 2017 21:19:11 -0500 Subject: [PATCH 1487/1676] [ticket/15037] Update imageset to retina PHPBB3-15037 --- phpBB/styles/prosilver/theme/content.css | 3 ++- .../prosilver/theme/images/announce_read.gif | Bin 728 -> 2656 bytes .../theme/images/announce_read_locked.gif | Bin 738 -> 2718 bytes .../images/announce_read_locked_mine.gif | Bin 753 -> 2191 bytes .../theme/images/announce_read_mine.gif | Bin 724 -> 2183 bytes .../theme/images/announce_unread.gif | Bin 730 -> 2652 bytes .../theme/images/announce_unread_locked.gif | Bin 745 -> 2715 bytes .../images/announce_unread_locked_mine.gif | Bin 755 -> 2210 bytes .../theme/images/announce_unread_mine.gif | Bin 765 -> 2206 bytes .../prosilver/theme/images/forum_link.gif | Bin 708 -> 2609 bytes .../prosilver/theme/images/forum_read.gif | Bin 662 -> 2120 bytes .../theme/images/forum_read_locked.gif | Bin 681 -> 2637 bytes .../theme/images/forum_read_subforum.gif | Bin 725 -> 2873 bytes .../prosilver/theme/images/forum_unread.gif | Bin 667 -> 2115 bytes .../theme/images/forum_unread_locked.gif | Bin 677 -> 2637 bytes .../theme/images/forum_unread_subforum.gif | Bin 725 -> 2869 bytes .../prosilver/theme/images/sticky_read.gif | Bin 625 -> 2605 bytes .../theme/images/sticky_read_locked.gif | Bin 646 -> 1982 bytes .../theme/images/sticky_read_locked_mine.gif | Bin 662 -> 2049 bytes .../theme/images/sticky_read_mine.gif | Bin 633 -> 2016 bytes .../prosilver/theme/images/sticky_unread.gif | Bin 622 -> 2589 bytes .../theme/images/sticky_unread_locked.gif | Bin 626 -> 2023 bytes .../images/sticky_unread_locked_mine.gif | Bin 682 -> 2059 bytes .../theme/images/sticky_unread_mine.gif | Bin 643 -> 2006 bytes .../prosilver/theme/images/topic_moved.gif | Bin 667 -> 2609 bytes .../prosilver/theme/images/topic_read.gif | Bin 653 -> 2109 bytes .../prosilver/theme/images/topic_read_hot.gif | Bin 1469 -> 2683 bytes .../theme/images/topic_read_hot_mine.gif | Bin 1519 -> 2223 bytes .../theme/images/topic_read_locked.gif | Bin 722 -> 2593 bytes .../theme/images/topic_read_locked_mine.gif | Bin 723 -> 2641 bytes .../theme/images/topic_read_mine.gif | Bin 669 -> 2640 bytes .../prosilver/theme/images/topic_unread.gif | Bin 652 -> 2539 bytes .../theme/images/topic_unread_hot.gif | Bin 1431 -> 2682 bytes .../theme/images/topic_unread_hot_mine.gif | Bin 1364 -> 2192 bytes .../theme/images/topic_unread_locked.gif | Bin 719 -> 2601 bytes .../theme/images/topic_unread_locked_mine.gif | Bin 738 -> 2637 bytes .../theme/images/topic_unread_mine.gif | Bin 678 -> 2622 bytes 37 files changed, 2 insertions(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 53beee621d..6431f5e0b5 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -134,6 +134,7 @@ li.header dl.row-item dt .list-inner { dl.row-item { background-position: 10px 50%; /* Position of folder icon */ background-repeat: no-repeat; + background-size: 32px; } dl.row-item dt { @@ -142,7 +143,7 @@ dl.row-item dt { } dl.row-item dt .list-inner { - padding-left: 45px; /* Space for folder icon */ + padding-left: 52px; /* Space for folder icon */ } dl.row-item dt, dl.row-item dd { diff --git a/phpBB/styles/prosilver/theme/images/announce_read.gif b/phpBB/styles/prosilver/theme/images/announce_read.gif index 9457870e6fa17727d43a132160be3076b8ea1eb9..b61cc54140c37cd29bb7f9568eb649d6d75fcf1b 100644 GIT binary patch literal 2656 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 literal 728 zcmV;}0w?`PNk%w1VH*G&0M!5h?ezKW?(xXn?ZU#sc6N63_4bmw+-jc7_4fDj^7N#n zq~YS`b)(Cv$m6rKv*+mSii(P}$Jx`<(`994SCh!U*6QNr>HPfsM~TAe>+Uptyq%q$ z$<*KE=IZeA^QXYq`1tv;&E}GllKT4kI)T3G?C<{m{w;aB?(Xj2-{1ZH{rLI$f`Wo7 zcey@x|x6$YG^!8DX#QOXD=;-L;QGo8+6$9XIFfjl{fw~3M z?E7)eM+^i7BAZYkLWF|>5>`Zxj37q2b5e%+Sb?B)%E}v3fGEv+MW1S`Lda0Df(MTq zDKPUGVY_z>6&FH~Ai|-sj2kOf+yEXUx$_$)PQg$W%!L3MJ}%sd!M%Ho8y5@-AW?}3 zgBKyp7y^Fbf(jL905pJ6KFpX30I;LUzQzU#>Tob{f(r*25JCkFY(at-a71B*e=U%} KgcD!{0RTIW+)Vla diff --git a/phpBB/styles/prosilver/theme/images/announce_read_locked.gif b/phpBB/styles/prosilver/theme/images/announce_read_locked.gif index 76ead8a02c04b60f1031ec691ab7a4f00dececc3..8c7393edf921a33aa6f6fac48bedf8909b864494 100644 GIT binary patch literal 2718 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 literal 738 zcmV<80v-KFNk%w1VH*G&0M$PL)6>)a{rwOfDD3Up{W?DP5H;^y@B z_w@Dl^78b!xVXR8>gMR{!`bVKii)Vn`ckgvi|O=<4lytJIyHouZ_s zS(eJ<=IikB^Y{1ol9H18`uefW=1q>q@9^Fe(J z`T0hQ#LeLFfsvnHY^h_WS$$=jZ3*g?|`Gc*7H z|NsC0A^8LW002J#EC2ui02=@s000L6z@Kn9yks~fLWz@k5uecCgrLgQXb@U$r6NqC zPu>!O@R`p6gae5HO9`~{%`?E*2aKB!A@W8iE-yX-Bo8?Wh=@54Bmn^zDqln$C4wIq zhlv#)0XBvhA3hfZZ9^qAJ|7PiIjyZW2NW6$ITaW!0U{+s6C4NuJQc#j7&8>d467YH zX&jOS7d{>j9o5#1#}O^p9zG5PKQto>H#`sL=!_o<2`z=_%m^+J85uqc80ilK9|jr` z0H&qGpdi4C3@#-2V8EhbLk}M|L@;3j#0`fI8Ti;Sf`EgCJVJ&HpaDmN0tGg-5Ghh4 zjU*5j4wyNB1Opr)ESxw2fB{Yani?Sx@aV$^iK9n7EC8@G0wJV5qDFl=Vuud}NRi&y zV8KEIcSpM(7;B-xhzu(Nv|zxNtql|r;^JswgRO-FAqN~VkwIL+1#KC$Fc4Qm00Srh z_rS|TuK)-?p!txYV1eZT8$f_K&;URS%RMYK9&kc{kX~h4C|FHWvxXUz6<_J9BZ z2ZWRm;i$!j4>x8Q@OiGU+k=;i3jqe*kU_q@ zj2p;L#4vHUJ1+tv$_#QuKm20tI%>Ngf*=J42fv(QMjE9FAXQWr{6WPEHHZL#1Y4v~ Uf+TJ{@xl=)P{D)~U<3gGJIzN)cK`qY diff --git a/phpBB/styles/prosilver/theme/images/announce_read_locked_mine.gif b/phpBB/styles/prosilver/theme/images/announce_read_locked_mine.gif index 2105d21f108f39e1f35041be98fd69de8428db63..e3f6e622a30e3a97e71dabfa6408708561b31c23 100644 GIT binary patch literal 2191 zcmb7Fdpy(o8z0SW=3WfpYjRR&Y$I$#?h7X;il0k3#>VC{!^&DJ8a-#s9*U|*oo~2wDW*1% z(?e$U2C)a|$wL>@j>fk*b30Do>hjL$BIR_46!y@0{jsreDJdy8Z{AGL$jr#h%FE9$ zDdq9_cgpUSm*20fdQe?k_pqU%VTg6>O?>7^QqJhLf_JGUW9j_y?7M=TdsC$~)BM_* zvij5qJ@Hk;$u%Pxb$w}%-(@zAH8eKQRW~m@Zh!xzGpA*|skx=9?Okq*ps;O%-!WCz zHC^>;wx)NkeqiBgTSt3GXV=T_m)(8iPy2fM2KomE-@F-F9emsV*F?wLrLM8%q4Al~ z@u}s}>GjdcSAvgYf|=JdtK%Ow1XHt9GYfMIiwhr?Hz#JlykDML+FV-xG`I43d1Y;J zZEJ0Pd3z6mwcAMj zQbp8$#`8z66t`>>e+zA3!ztT&e?^cPra!=~cw6hb`t7eIo^YP%YoN7KU?raw90Ffr z?@jT|=DdS!u9l=^gPr2{!wr({jvB|y1#VAje^NwAsY1p)Uhz`>;&9bZAu8n)9BLgp&=kjzX{n`hRWI#qS(1#SljB+Q6AJN5K-JeoS(iLrM#@1oTywZw-N-l9~R4F$*5p}y+YNOtzzU#Cnheu-tP>RlO*QHa}KtX1q#|3D{V29 z4A_*R>pU$^j?F)7ZHkkIaZ>j9ZOefnrgTMLWxHFI3d+WaUKRjDpujOsR?6+^$D|oD z3K|tklb|cg?)dbedRDuvq%R;2mV|{%rTMXy+q1w)Ky&1h2uK7LqL{?D44kI%lI9SJmt-%c^^SrH?j`C^T z`j|WUn~=kMoeH@C$f1nFxzCknYLrW&Uc?mf;K>Ns{aWK@9yd#Tq4KkhPSBo6JzAR~ zCF44$I{!};0y5_yamaGrHxj%jx$(NT?AG)=wKhLXT<5&7EVI0kYU4axA;bWQs7Q5g zakw_p2y}7K_HEU+iUW2M1!=(+=*5oX(C`^mM7`Z|^GOHO3NZ;$fvw6f3~rU`kBd;6 zszoC~lXH+~`YFq&EW2G?*yj4G3QIb_x?i)(SR}|}ndWiT#Vx0(UV<%a2}Yi}hd;0J zQo-uHk!`HUO6+)PDA>mAy6&G)Ql#q zq?=;v3;tf_|4}6T8U$VWx+0grx6%yM!0*+9 zqZ1vx;0i>>q+C(wGZI)Br1?YA-O&lKAQxEM(__N(E&eFAcblM|M<8G4p4|@ za5qColq1cWM5fp=BS@#1zq|M|gZ;5YxcO0tDFep{rG=8{1b`75LXE^R%-{rKm>&tZ zlkZ+5;lO`O=)q=i%iRZHSJOHyf&>`q8R`0?4KRQ)Ru656#poYF0QxAj5fX((qL1jJ z&^Qzphe88C1AY_&m_`r-a3^i>KgD*C8JtX~({M;+R8*8+l!0DYL?9B4#bS{teWbp= z?oNenXnq_q{M{FocOp{HY?`R#S78rndcZ$XV1_h zBf@E6)Xf7l z=10v;O>kI@v60~s1AR0Ksi%wh_3$B`gTH7W(1L3M8tQ8MRaKN>N{ajTD#**p%1BE= SB_R^xVxl78J;FPy&*UFMe#=P! literal 753 zcmVFe$g9Vofe z=;7n%bar^nR&v9`!>p{WEO@*2_xJ4c`SkVohO*f5^7NE9O?j%+xVX5Bi;Jkp$o~EOwsGq{%>g?|`Gc*7H z|NsC0A^8LW002J#EC2ui02=@s000L6z@Kn9bX`U($ZB+P4Si4_aY})tE;U6!QDdbb zwV%%-f=++DWk3>*9wdQ^?_de}Zqi{@!KQrx2!Q|wAts&;B{)I^E0GZh3#q9D9|tp(tsVTDAA#E0zh!-V@8atS3gWB zur$K~tTB3s75me`j$B}`(g4w+0|tRt+di1vfq{VwEDi{$z?bg~02u-k5HN#phX*kM zJUDT|-h=}a`c@F&ATWpn4q`;^ftZKl1Oa}C^8s&y=>s|j40wQ{fB@4yI(P j1~XQ$P=g8qXwXFpD^M^F;fFsMF~S!JQsBggK>z?d>^4k` diff --git a/phpBB/styles/prosilver/theme/images/announce_read_mine.gif b/phpBB/styles/prosilver/theme/images/announce_read_mine.gif index 2c88cacca0e10cc12a91767ab704a5c3fa41ece2..d57e5d04e54424e61fb07efd4c96f080c51edb59 100644 GIT binary patch literal 2183 zcmbtV`9IT-A78Gp9240VdYcaSY>qY|$3_R`C|8G#P3~h>q>D9+Mu?UxN6y?SSA1mI z$JCUGPsp7sM`FK7b&)4gRm(@v243>xnp+T!4kf*1ozrTM- z2sJ!Byiwhz32E1)d#)Md!ohpA*#&fX-hug7D+Sd8lv|$4i+3r7M}G3&?`g-?!jE)%RBUWqLPFx>l+={ew5;sx{DQ*5 zqGzRL<>eL6t6sdUsjaK8Z|I3+^+lzAzW-z(K4&l~f9P@1aC*teld`db>hYqQiPBe5 zRlWDCKPNW~rZx>VHZ@PZY@Tjto%y5f348c;GrNj2n8_Y_${8)y&nfNsE zV|aFDWNdP5VtQ(NZhCfpb#!ulW`6A3>bLpDsfD%qg{5yx8%xV8n@cOJYwKHU8>>Gz zH@CJx|DP#u2<-xad_kH!FgrH^?fwV_s_>T|DWNrG`Bo9MSVh}*)i-7_Es(IDcYbC?wnTHflhDWPwkonPPC>pm`r%|+ ziUuZRX28YrJ(FcBmyN~IWhB*lYvwMd?IoXunX1{_I*RfR?sqg-Cl@>LN$G37~s5vC9}Wcmm51EZnkEgl_?$p$K3teN&{Q@WU}k=ynWii6@GZ@x|U;h-!x!eYIUlU^@P?QaXFkWew9$`xco^|1cuhTiDBCJRsEHq64Wdpa7+Jz ztc)%*T0e15Jv1-wM$JA&L69gvG2IFacI(bg42}SS(ZwRc-TYVe*YAFP1ag)FBD}PH z2Ouw5+Vex{rt8lj9Dty?&E@mU^YzZUsMYG_JBLt2#t<+P{ zh|KxbMvNChKNFTw+cb@0SbtQNh8k${BLS$UG$;7tvT8vrcwZ4`x0qxQ6sm`=&x4bM zo`Xbarj;Pbiau=8!(CmT2I@TYmBS!9svRb&Yl9+zB&eMmG=bsb6)$`V!rtwgk^q2Q zaWmd|NtZovhiJC69C$)Ov3eE}2hb=22iMKwjc%tE=k+L>!k339N3zUZfg^Ik}<(PdNs3?aHeZ&&T|`vQ5BS2Hhw zC21^mT4}T^i7MfOggZ_gxFrF@ZsMce#-n6cI@1`jG_I$gRyExIWvrkw3uP)qM@!vY zCIH|Oc28i|=<0*evo=D4d!lpT$L#nXM~4K{iED#0r;QdynBP+vF{Hrkd}Wu5BKE!U z8n-cH#K8HDQSw}g2vlCzHdgueE=PwG0(Y9~C(HYd`HR#u?z-5;HcE*Xc<^YxzEKQ;!gw~71V9ym%l4#F4wPQaoxzCgX0`I&%^Cq zE9>fNTwltA;91~|ty9)YWZu^DT#0fkq^0D5;it;l*P_beo6LL5bygy3qC{B<%rK}Y zTk_OP3-O<`!`*qNLT|Sw!uQJJbUoP-UJ7h+LM6kfCNfH89HamyG)vrlzAx1J%mPa4!ff0ksy%rKVWAYTL4F- z61Tn4@vtDGhcB55xRbAV2N)y1H@rpw-Xvp$lfI3PO^^lI%lkw)h3pW1=A1{kuLqWd zIBp_t6lNIaALLJ_5`i#(zkm?KFk=Lf6zEPi+>Uq3NCfcT5vs2-!fdAj>~LBHQpkY5 zwt95AAgJPqw}mcPli zGh>7ol^SG-M23cjYKQ7-2U4yeQCKV%se?wM(OTORS|Qg1sKhX>fDn}(i2q^W$RQpS z?;xsoU;wa#NpugqN;O6xkUJ#E-z?kmkpJr2PX65xIbeG&lx_XH{`s}F`S;I_^|jTN z<)t5s3*YCz&CSkCf1R3~7$5sGIx;*oIMDyOueayZU)^0FJNX?S-naAKy=~*R{>f>1 z!)|`v^haaEtNOayn(CJ?s-9O?l$Vv36hA8}EXdExeVUV>xw6ttf{qm0e2Laf|3;+NC literal 724 zcmV;_0xSJTNk%w1VH*G&0M!5hn3$OT{r%I^)4J2>?CtQa#MpME%qe%d;Ns@T-0g{p ziITb7!^6XPczE>n_VV-eYM#sW_V=Wur0w(huP{!j$m6uMwCCvTWo2dI<>{nRWk-p^ z>Fe(B@$=3(TvwCGGkv_2BR=Kk>dDjJv(4o9_xSqy`Z|HW-{0Wl#LMdJ@9ysI`1$$q z$I;x5p+1Db_0`?^`uh6&`}6enQI5pl!^-E<*ZA=A_we$czuV&D==kI4*I0M&@bdrv z|J&ZYw64>dMEDKI2L2a+8k=;X1$4LN*7*eX?q1e6wHkd+$2ffjS%o@bkH{j1H2Lf zFjzsDt^FA_{w9;3VW7}6&t08yKY z6%uYH;a)#oc7+4wsr*p$!B6`*69&*YVO>6-D-bL|LIM?daRPb%`Des_2b@5I0Z#ZA G1OPkTAWkX( diff --git a/phpBB/styles/prosilver/theme/images/announce_unread.gif b/phpBB/styles/prosilver/theme/images/announce_unread.gif index 33e10b2ccceb8af430e80c2e35e885b26a674dc9..eb9edd152041d1a232202ac2e0105036bb30e0e3 100644 GIT binary patch literal 2652 zcmdUwi$Bx*AIHC&m4&0+)p0Z)_lfE7jbrXV&J0Xo1}1hLP3a_@ z>I^y66?UdOJfnx4@h&mQ2`l#|E5EG&V)@sL<(&L- zc0t9*!phz&cl!%(4-{7RU#a?X^)9>k-pA_?*rhdtCHFtyeDvj3&G3zf!#5vs%4^xx zjqC?aU#c4iA2g1X)pF%j){otP&Z~LJt9`|FXT-Kd4egvU}{1jnwS(#3Pl2;cuFuO7K$gQriG&EDbe&imp9MlOU4DV zF@cOXxiB%cAP@;f5|KzUC6d}SP>aphgEhl z)p)@m002k>-%xO%;eNp5V0!A)FAX_)+D67u0F~Yn(32T$2|x=N=XCJ<%BznkKh-fp zdig?t_>6af8J?;Dt+rCxif$kYYW?OKe1^$QD` z+lwDM#8$Z9^17L-e}EpJCdJ*TciNFkT0ITYepsYuKhgW(Shs%u4PSbC+9iX}mQH~o z0r3%*X8H2#UXKV)uON0%B6U)J-=umfz~HNCqBCM7OLISY#FQ4GwpmrtDg+C-lUyq2~0 z>U+DGju&}r<3NDMCfuE(a!AWL4Txqs3yTASGj-?^Mu&d%GXd}VsURzzJ<2qJ@z!R@ zC}jfx!Fl7|uKTW_406x_XW^aCr% zA$=*rz$b#<>%u^Rup3s15I=WV!>35$qh}#fuu9PIWRwNHzy}O?KwH6pjk#|rtZRpG z>Pc6H)On*z4@mShllGjc0@T91p#Y-J4OOZVB5s z69o7+sH<$FK+GjH@YmyD1+9XHb#xU)4>!~!JO~Q`d)l`76~Zc{?Rrrv?d#!vJ}r1~ z?$TQjZ5g=@Z}P~NbpYYi zscM9)o9o-F=-7bL-bHcSb~st|l>H|b<-6|k>6jDj;)k4i)c5(HyG*XNTF5ww3OLrr zB)+3;)nt>qM;&T7_fV-xmQHNSNH!kD0{@{WZXA((KL5CmX{P+vq&U3hB+s>A49v@p zw#4viAx~nSgPWA1P)+IFC1EX9m4R2f2U7Y8)>`vY*aX=bUB?K@75LrG3R#viv*GLA z(B%3|1%eSW4RO2j#UwUe$?QCWlRW(jvAe+8Nl`CPy0XX#RdiFotnSY%d2-46&GH<3 ztAZPpQ{c9;%-;7V?$o3PuBf$=+Q-m@dX$0L5)cSRQ^1h3z$SQHaGI${=ob8iSjd%t zGVWQJN;%XO&)8T4Hrs0sF}wp}X)Rn6fDw z-wNL%&3VD>`BQxP)(W7e?VVSlc^BViYOJQCSaCj66|4{BWIHtHP;@)+?bd%C&pTPT zF-ZD*I!d%7AUpH7a&ohdR8+a)0OEqh*)*AQmV8N{6P-qOw3ihwyzbU~S5{O|KUuTzpi^)AlI5{aP z9)mS{*#h*HZvpr%pYl|PoEXWD4e#o*$9cCC4!i3&M~9slwEeF;>}+kUtx!ly3-j$}rU(<` uZAON01K3vmU-W+7vRPM0TT4?zU2W4w)t^+9l{P>X*RO*pfaU+_&c6Z9Ji{jd literal 730 zcmV<00ww)NNk%w1VH*G&0M!5h>AJ<~>+aO3we9Zlt6FXA#LeWYxUgk*@$&Tb_V@0~ z)br`<$Xs{0dy3}h?D_8T$99X=x5DD(>H72ah&D;cn4|ps{K|oqzcp6r*W1f}lfpw{ z*v-}C=IYI3eZ);^+`q@bJY1GUSNQn(yoQta_xS$){`&j-;Ns`*-r@fI{rLI$##C_A za*6Qq^ZEMv{{8;n;pX3(tMl~s`}_R;{r#d(W8&lJ*MXMs&)4zN*}*_x!bfHA@bdrv z|J&Z(1rnt5TDSW2J^wm00n@o^$BUB zPtL}pc=*m})uZ6qaKO?KVB$Nu27&wlLGwKT7#C3*EIB?k0}eMajEpx9JvA^2AA&?6 z8#+EE0XHb0C=xC;Gl~HtJ_;CbLmL2_4iY!BvojSG4GA|A4kIuC8$%i%4<-Q;$jJd2 z6wQee9RVf}9+nsiJ}wR&+}#cfA`}NJ-UvPgAwL2P6Ep!1@bQo(GZ`yA@&OhPECLWX zK4!d=H(*4B1_wZB%a;H~3kV+!_&|`SqKgS64u}wO;6%lW<_xe1QDEZ705uw3SZOpM zK%l}2tY8!P5DB3Lj1>sdrk$~XD}fX%W~f!WLdC;%6I3LayF$PL0uX8lSRhwzf*Sk; z{GjG#ofkK?aDpk7p!!ac+l@VP;k&7;OT=0S^!qh#oz9g`aAz0KllRqC|-o zIs|~2@xr$66*W`<;6a1~O%o?ptTdA!<3SjuKaN>pc?=P79P@#Z_ zCF>Xfm^oCVxrG`v&O9&>2o47x9tu3rj%NHC1|P5jM;srta76(IZ1KSk=M7lI5j=$O M0RtL10Y(r2J0i_cNB{r; diff --git a/phpBB/styles/prosilver/theme/images/announce_unread_locked.gif b/phpBB/styles/prosilver/theme/images/announce_unread_locked.gif index 76dcc6ca715a0e29111b59b0cd49e5e24b87a038..054b0ae38d0ee65429904aa5c21d7c0a8a2d7b83 100644 GIT binary patch literal 2715 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 b!2%p?QNsY0fB^*wM|4pJ0~1bw5d;7`f8tL7 diff --git a/phpBB/styles/prosilver/theme/images/announce_unread_locked_mine.gif b/phpBB/styles/prosilver/theme/images/announce_unread_locked_mine.gif index 53782fc3dccc219027d15bbe4c36d2787a595b40..a37b165b4f1f1243d9a3b35d2e52983481db8d57 100644 GIT binary patch literal 2210 zcmcJQ`9IWc7stQ$u@h!gZhdFajhGok22=JeYK%c742H3bk)_laql{6BndDAoON%8X zOZGKuktSPcDC8zfw=6|HJWsFtKX}eB*LAMzygu*O=bRsom5rr7hNul_18V@_=jRs` z6ciN|6&o8{r*2=5bZFEeH0ryy7`eAv__SL4b=U=V;6pndLOWd|dOc!#eB%536Z*&r z{QESu++<0?i-pO8lU65pBWjOANjEI zW_awwrp!dCwpQ2H*EhD;H`X^cx3{-}|9`+Y`FQ}q6VTX2?al-c`bqVqCDM~FUrA=9 zFlmlRs3Zi!&z~*{MdFh|k5nc>O_Y^ia9>!BK)2;b-c5FZ3a}tDAQG*sr>CofM95^Y zp$;@Te&IW%iSEkJ1f(^wmJTi+gF^%dORT1J1_WuDkM5?~=JCs-O&o_7mj+!NZ5`b_ zB=d!*kr|>$kK-^{&0L;GV`H`b2)iDu-rx_@u%lFa&Ah%6pe>yD2~3!xq_`YJ`q^a zdAWIbEH&CNR5vL zOMjTtb{wXmQnB?FpO~f!Bh)RwOpQ03S!NwiQ#XE*l6lKR%G}k)W4Lt~=19ON>W;p% z%1Ydr1VvT;#9bba-Ei=`iq#>1ZMTt@C%VP2W6z$sJUP8=0>RL$ETFiY>NJ>TK|d2z zz{w?D5Z5E;U1!0iTZIpS(i048#hNgDIttb^$yp&s3MW*F8-q z-^e7po*m$$+3}iLVJoxt3J58ec}j%D(eGb!@5M1dN6pVkw?mN40Ka`|*?~RcaRdvw zAuaVn-A*_NQNdC^k>v;;SK9NOl#LT)PAC|6^QCIrk_x>8XYaxEaN24-7b9vO7UF_y zR3({rakgUFDY1`BDoaPzc>-Dj9~D1HQ7e*({zIv#xWchTkA*Vc-wxd z>U)gq7Vh&F=`)P8{cgcpA>C-NS`PiLSuW!|)t2YnIiDmU4{(+;h&pJg%^h^IAYA>BK%@#TpQ=i z7PHxK@78HvxV%Z)AP0XW`13_2{nW}KuV3eR;Z;xZS1*ujYulj~Tpuc*vi^!UG%+k! zU~G~81tpynP6Y&<>#L7UW}G~+Il+!LiGe12=IaAE*(v!$hEr!Y=WfYNSiszZO!tUrq_k}zd z7-Rb~&9Xg}Z6=&c7Ew!;GQG<7k-Ek;R!$=e+u7wZowxG#v85pZ{Fmq{dmLy^q!4#b zqhm4QM4uoM1@tEQ2ZUk~OSO#%Fu)g!aM86#+lQNx$N|=I5hTaB69k{QARmk`;@D9U zqZosjknj)^g$Txk1cyc%#9$Fb-!N~I!Ong68HE73<|A{($?18snCp!4W$rcG(#hmb|wC&VNQzli3kX% z1cZfxyP8DruqX-^fk5p-P`@cV_E7)&+e!ZI5Gi!0EfG8Zd4B!e-um%sIDXHY+3jM%wjj zS5uiOjN~hqljw=G1nQ-W@fXg=#l}RRi=sqEoDB~P4G9hk3?Tdak$io;iC&%_XWUP_ zxt?-yb|N_99dIX4*xMbqwXwFcv@ka_H8DPR6l-K?fYCpqr+ZjOTMLasYHA!(S5y7- tpo+2*0uCNf{6k^?zP<7=sGO|K9%(5_32`w|5n+gspa4G~@6I+f{15Sd!^r>u literal 755 zcmV=jyDhtNHo*qKc5}yT<+f{jp_t#YSZ*6Bz96 z@X>OJt6FXD%hcYMr`Us->&4Hyd5H4z^}#$_>Fe&~s<_Nqb@SBQ=jiPD@$>Zc_IhJ! z`0en>m!sn4>4SuX>DSxOWq$D8;pFD(!iJRg_xRPNv6Vqp;G3-6y~Tibc*reM$53qG z;^&DTIPmfF@9^^6kD=e;=JWLS`}_RYw7jBEW8&lJ^5W(E`T6kA*VkBf>g?|`Gc*7H z|NsC0A^8LW002J#EC2ui02=@s000L6z@Kn9)ICCo2_p2+4Si4_aT=Sj9;gDOfLgF7 zj-T%oflhycWrGuq8aR-Q&v1J9aMEG5Ag8?)6oCp7G(I&h2LKiC>KH^2p2vj6gMraEgmlhGZ;6o3!W%uKL`b<7#=sjzcU?V8nYcPC_5{7 zKQSR020R|q)D$29*c>AYH3xSgrau!6J})EZ=pz^$CjbWn=L!QQJ{b=`1r`}JJQ)7} z7+{ph0Ac_PfIMhqumItK9Ssx!Vo*?`MuY%!N7tCEGqbr5UAvf3?vSmIB|eR z$&wO$RIo4s!bl!CaTvw7PTN!gW0Y$A~0ak!C==99|Y+Apu)m~1qKF47(94JfVm7r z445%EFHQvlHay4&O#@*G156w^5W#?n0G4|Qcq||R1aagBXjt7b<$(?+QmEF@;{%VR zDiR2B#%6ZMi<}$G7Jyc7=>!6V=rRzvL0grD7Jflg#1SYg(JOI>f zc7H(FQE#!k-ezAT^%*&bnH3P0`R%YzM<$Ok$uQ zSuk}SBV!Xh-o)5QM?Ete$%sP&iUpN7=_|sav;$n}_OE#SvVlGS*^FnvaDvDmc*%?2pyeRt&|9cdBm5t*T&lD!U@R z)T*yHC(;c-^`W(GO>LP-AU}J*4y4l&iuMM!K`XC6%`?oVc9-*U5G8kw^J%*|kI9DC zVaMxkefH_trEO9&Z>1n%7^C2Kw+e9Y zI0vR96|q^a6u71=k6TrZ@pxs?2s-R;WE>k*lpAW5R?q(yO|U`Jlyh<8Vw9ebb_d!d z5bCJXAzXkZTJqoqLSyJ)oZ{N5nM*X?(ZHu_hDDMt2OanixfpHP*IJmVtF+^=#zq0i z(D*s%#ZA-PLSib_sPH@BuhnLKMLYO9Foar~k4Te6O}?7Ll6--oHkpF0SYx7a_>#y+ zsR8g$M=5Br0A0U)7C6sDWPebRAl7cq^VhNgB{WUNR1}btyg`2BW|CF#Q$#w0-j?8D zsT+V&NX`=%D=|g;0#z*$%#w*hfQW4?t|_8J`73_zWOKQ`XRLP>jCF`Job5lyTdjgxT!cY{D>Jy)M?L#U+$F{aC)= z2HTet6%f=Zsw7DiY?pp z71|rIW{kpqme-!Cqp!iNMgR&QpPB2{Kd`GA4tr+-j|wb2M9x(T2JiJ8*6bct7O$ey z0AoOWA8plz2cUXO5tzPcCuauEZk12Ff+yt&W^c}=z-rWaLg|;W{1Y03YMNRgotxY$+7&p?SnXsqg? znZ`Ae%S-@E(>2nCu1bNZ;xt4E6Z1x7T3Ry}ADdhfEkDgtg8}P*s(QJzK_*AQSw5*- zg%KQXh@SxT@e2sz*<+?_>oH)EuRX?->`ru#aPSKZa*pBq?TXpHn;R3trTAjDZb49m zw!*N8Fh2nY6o!TJB5j5C7>;kakDu*wzH&{#fd4HKgxF)~D-Ym`rb9U24+N~_rn^ffef{d?i_YgA&z`pb{iLn61N{Abxjr24-wq!-cwqlN zFVDSucJJD`gYB{1eVd!Bi?b8Uk?Fvo)3$E0r`p+4Y^<%wmKNqDBEifQZ?f5V)5Z-r rtPy5CXlS6nPES{7?HcXXtI#NFe&~s<^Oa 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 diff --git a/phpBB/styles/prosilver/theme/images/forum_read.gif b/phpBB/styles/prosilver/theme/images/forum_read.gif index 845618c1a266a23aa575c2f12db1d75830e2c1f9..79d605ad7c0c1c45ce7176960c19e445c51a44e2 100644 GIT binary patch literal 2120 zcmY+FcU05a62}t^HGm*ZTKpx1q5?^fAc=rT7h!1%xT4QMf}peqp%`2rf>c@56<6Ff zN?S#+pe{vZ1ze>o0SmecDI}zk5NZ;dFWKkWbKduS&bfEy&Y3wg_mA=4@8^mmIDwo% z%M?(2e7tFLi&;vGc}lBAYAY;FK^u_XW|h&tJ-Y*)+v!%&?NQjhx3DMdQs0rEhmKYa zk*KeeYDdU-#xn1`EqwH`=*h>jmQR=4zf?Z^a)4^4`PCucuTFh5UDeW9}_=MElZabNM%w5GWn8xO}erslgVZB6}f^H1*o`HhlDQ=Q7%x_TYcNGcU;s9LGH*~kKpu(CqHEsQp6R;n6e@0KQ*sDUAR z=GKmZQ3+WTN>)Ntprf_99t5mrlF(D=3JCStAL@-^!#n=U~Nm= zXhD1}WMDM*Rhcm^-v?8tJ5;KxtzsdQ1aGp|L{@p$?Xp(Ca1ro6JB%sRb+$nwL&q)+ zvOrLqH@qHi-`)$qx@HK@zzeis?k9qxx9a6t*KG!?9S_j=A2EYrY6Gc(S9e^*Qdsrf zo|Ux-vlaXL{yHwS!ZhJ+|@se=I<5TpT>mAbB4{f|2m3&X| z!2%~pUY=KoT}}_a;XkvsVw@t6`<>{2^iL$K8W=b>@_I zi6;oA;j|BAWEWM*c6L?Us8;vg))Ov#8)ir$v{_he`P>DNoxYQ8dIX?}s9ng&4F;nn zp{2l7IVgBbReU4=_KhsT_S>{_PtD&{qVZgVhTDyT#(S-TleZ`(X5H0b!^S?tPZurCOQgdo`e&bw$=IK8tZGMLp7q-zkV7JwJ{>W*M3RT z+FyS;kys<{5Nt5S&mwDHNz$VZwQsg?-`L8A z86A@anHcfQEJUOWjr6{+c%#uBO6!KOqi)|6&H zegl5<-0d*SxO%F~c;j7a>)9vovyQ;av5YEMMrDn3@{Cj@rDqUZKOH?SD$F)3v3($8 zm7`!e7R94=AK}MU0pr7&4K?!V8`)y{^vZzmI5^8XzcM`N^`e^jy*BZR@L|{7mB<)X z#(RWg5AsTG>Y{jcwtMx#woos9lA*1!YTji(+81!&0?mKhx}~7HK0J)hwj%8P>RF%; zBWCu)H)NS-=rnKrVDbozSsw8Q$8Y|#VvnTXJA^OQju^%a*uM?Jk5w08n`?AZf>M6S zkM`YZ4}l)0y)bU4siIUE7oNf;xN6{)>vULIM9d}qioEkkJA!6V0;|BzhX8;;@UPJ5 z;84JaKqe?ox4k)Ogt${AG7w8Tk(lC+n0?lT01}Drh$w6@IylXnl#m!eNhd{6zB?F4 zITeQ^BKCS{x#i$>o;h<(ZjKv~l} zHJt=t9bFvaFuPoV-8e@K7U$~ZY!5i0F)k=H4ux@cKx6P|93G7Uz6s%>1-PXX ze&32IEO$f#nVg14p|Z2H9kX{irly}jVQ@Gc3hjh)a&k~aIAokoAro>OQZlTRDgKwk zhm;YQo|r~XOicllISH|;nPhha0;Md1`c_5J9_pX|6vjUjBBdzClCJ0<{B>h}ZFNO1 zlP)hUF3itKX2qfzp@7fhPIK5(EGC0KIq~K5U!OjXe|Z1y?bs-7o#%{pEVqwV$t6 zUisjs%Ih~W8l}XM>|94tyN^;VvlZgo@;z`7~ zSi$ucD6RwNX0Gzw!thd%*{-?P literal 662 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 OSFKcA0a9L^&VK``rDCf9 literal 681 zcmV;a0#^M;Nk%w1VH*G&0M!5h$_dg%Ixj%$H>gP(dBh@b#*(t3legF1G1aU_W0Y~;q>+Q&(YP>)!0mixcK?`>g@0D@bdEW_51w%UteE>f`U+u!$U+w>+<;6 z+ur&5`tb4dT0g1-0o`MbTrqP*1e^!7i6z>bcOz{14z_4e`d^zQHRnVFepW@Z2Y z0NdW`2Bij}s4|2L6GI0Z92y<79X&j^x3sz%92;Lh3=W_<#Kp$P#Hs}h zKQtFCGBqaCCZj#q*gn)IH8LC*3IYcsA3Eme=;`PmG6Gx*GA1SS^FG-3JoNJ>G7uMX zGIZ=1NU)&6f;wcd0$5^z!-o(_ka$p`;sc2#IxJ(bpu-M{AVX3Nkimn=3;`Yt$ieCY zjSo8>$dtKa1rG$bJcIx-s^@^l5B}Vlh&l5?g9J#Cf*^1W*EJpPoWamRv7*(A0a_5i zVQVIj9x%WGD`0{|g#c)4HfV68Edn1ry!zlHY_e8TMxO@ZpP-f)YE> zW>~SdaRVNsaE)p}1c00u14w4rtdjuXuh&qZNa5qjffxk_p5+|kFWj3q8l)f%Wr~6b zh$&_WvDF6x(H4RmC=Er7iUkn{#N185$J*JZi2Gp>LjVK_6d+(g(X;ysI6{mdQ6d5Z P4G`!-glOSGNDu%!s-)XF_wT;1>*wn3Vr@gP z04#tN1`re!L?V&MWHOaX)eL*Hi~L55T%{deg^Z{|UKF?0C`z?nWX*2sTZ2n)4KKen zih5^utqyyw4!l-pcbj1!%W#NeIL0yY2_Kvj8$41Pz0;cgvfIwyYa`}=3VGN;delLE z(sk)cH?_3uN?A`_d_sJDLPA1fV&a|Tl)JgPx%m$s78E`zDk`e2t&REPYuu~8xYvF0 z6@5u>zR_!bWY+%3svEff=U_f_sGiyIh&5c=JX+c^`mB{x_L1|vjq|d7>~+UPWyi#u z&WY+T+;`oRwPJfF>w2c@dZ#`#G&ZoBSS(g!V{>cUr}j^sot<4x{nO3;(=9({S_fv@ z24~s_XZr_+`v*sV3~>gAIG@?G18mL!du(W!Gsqqr92R%RhepPGIP<+6!Phat5N~O8 zbd)_jHZnTK9vNqkOt42MhB@4kvB}Y~NzVAx*aUBaJ2f#mHO}RYPx2=w`P?ZUcXFCL zH9f`SPx5A__+n>y)3a>e(#Z5OXJ&bPc7-=R#}_*@H$5{yJv%=mQ7|(nm=!y}z@1x} zoL`+1tnvgx{(^93acypXVNS3xH@`S9SQIQQ2^Ny?R)uRqv1?-2*Tk+%5Uy{muZz}2qBYUR`o^Y6!iH!= zf@ouNV`K9#w!{Gc&*%!JAppPxOe94}?gRka1a8Y~yOkF(Z^KlLf5yN&Q{h?$APPrg z#%|NS3v%3uVbdHit;9A)hvLBpxU!1fxcKFBSk zF=CYWr;>!KlWJIhMs$ACVsIN>OGg>*1&;c3-Xdb)7&g-t;dHF<*;&P`oC0G9J2e!p zu>Dkwy*j+S;C7P!n_}fJgd!P5byE^o+qn4T4up<6%!E7ND|-m;0(I)mO7zU`C^&dC zD8p@M56%VWRY~u94beP)1hP;JQ_AVDiR6t#UFcZDXr95PEkBvw*TBC zkB3L|*M2|AAfG98%6t96;wo|Tv`~iBoeOfi%g%K;wC8#kO>2S_FBY?e1ElWRJbA8@rq`p#RhZ!JMLsRf02}fFW8F^4?h$_tT3;fu&uI5IK;ODQJ?unK?5ZI78;L!GvIXr^1 z(bNV<$XlLN@e=ATv|Ik?=L%!5-E@e%J~1uU*UgJVfq*N1EnnOWUs!h4r3)a3cBIe_ z!uQFs_&xTjfzZykU=x%NT5Y>k9j(WAiF!Xt)h~pcy9%zVFm+TAyn^CbtyG!r^33SOyxE zFaiTww}8snG@o)qs2dxWz9%+Wy)PaQG^o3#0gyy64Y%zXBB!N57OSgo0F25=YdC4r z=98>n6i8#72?|`bB8wCnfOYH6{mxPJ3>=BK?zycTg;Dem@%P(I1Df=$h_?{(IG+qa zR)4BECI;tz_-2fZVToI#@lm>+o+5NW1eh6e*vaR7Zq*3ba{ldTm~=GYM5)v(P5hu5 z5nGftvS3j875?rl-YnR5iXeJ1WOI z?Tmnf6!WB`R|OfT^=axc-glh!p)$$7c(gIW#qt>)wW>?Ik(-h1(gPJaHJ!_;U$z9`R6#i#Z9&S{pc~n@uMM z^>iuvT4$>Fcs!8GmP7bfjy%$Mk1;Jk!+0tvdBxV`$7_O|OTvJi;xj$vQ*D;{5wBj; z*BBlWd;of#rbp29IP*C@`;BEP@LTc^4l=~1oj_C5(LC&(nx0u~x!aVaN0VY3?0t=C9;^52}K&Mto^6OZiCAyjIF zEfyOU6=fE+*DRb8j5W8hvB82CSPKhN@e0$(D`YAm+LRorCkgSt7|z7V^OVpCYG^na zC5cH02){(NN29TlB-p>Rh|9zNQ=fS7&khmE;%%Xb>xXP@Ziv>`gsUsdON$GF`MKGd zX+Cdik~=Xz#u*(MW)BSx{OJGwt?xfydwaUOzI1kc{?y*~v9+bSsgc$2fyt=<^L<_I zySFvfRc|UQUcV~;IzWzU|LJ}D`FT=b~0;NgS(yx(*0-^w~KW4+&MpXFW)a}aB0YO=@J2xDll tTVD^Yi~1K*M_X%`rp8WngqrFO75H}LZAyv?@-R7B8EGk~_$T4Oe*uttDCz(J literal 725 zcmV;`0xJDSNk%w1VH*G&0M!5hX`RXA<>{lm(^`qKhKY^J)Ze_({r&#i-O} z_V)Pt`uoh?>-F{b>G1aW`S~n)x|*`c#o6oZ^Z5Jx{LatQDR;T~`ug|y`Q_~M@A30c zj>IByw7 z&jMvb0x`~L6R6gT6~I!_qjWae@1}F8(@qWkzoPxdmdy!!E|64(S{2)EU-WfE>Pe?3;-xF HL=XTw3P?}z diff --git a/phpBB/styles/prosilver/theme/images/forum_unread.gif b/phpBB/styles/prosilver/theme/images/forum_unread.gif index 1a397cb21697b8e1cf170c79895099c149422eb0..8df11e778268a27785035cc4e30ff88a3cca4b84 100644 GIT binary patch literal 2115 zcmYk73pf*cAIJZ)GMB?vq7r5?DzWF;qi%K&fKTb z;Zg3F(TOi(6C-21(QyU*Q4W8MJ2^ff;7ka(yr~JkP&^^vO$vDe5nmvh6o@CM!~)^; zlxRjMo>?5{Espag{3#h%AmdFfO^TKTVxd?fnwE&CrQ#Xsw31o5SR$X9otDhbNMW(Y#%)MnUnOSUCVDzTP~ZV< zBY=~8wdzU}W(LcWG>xB|vXAM)0U5BAFC-Nuao8Z#1n_K5Gi5g zO#pUW^pI1UwIY*ndhY6sWEBxD5rFN4(#^79#f-J5K;&R3wM5q~fJ%x0K=q=P3fN%b zNP)n%1w$ce(69n3e4wDU$08{Sw5nQ(q?s_QdNxuE(~08b+BQy(8?b6602o7YDnJk6 z{T}9`=N_cxX0cYuz3#Ci)XdNA6ljH{*#jpvUs38txLzQ>NuAUPuB~ZEY7y5n%pvwOU^-Xu7OwZyc1!9 z@`B(h%kutfPU>YUZgLCVviz{A%8K8r!tSt`8m)H$q)~0F_h6W?`YEqUSmT42qm0Ar z8;e!UeUhn8In3!+Xp@Ye24 zH;Sq*O*ct`i#v_Hy)3hHP}A5fz178@=q8}{pr&Q*^)H+Z%Qj6TN0j&@kIH$4o# z<~-z@ZK^$PoDvZ;ChhX`%-z8@4txhu)7c#BpJ;o2prZ$~$7HS-|H03;7sHZLF08=c z48^TCt916e=ts^ExanUGWO8oWu_GG}QZl#sP^@v5zLe9O@N7$ZHvL{`P}jDg8_5eO z+KuEh5s%)TfCheNU$15uJQyh(X7a1;3~xoopY&(Fs_q<3*N<8n%bc_BqRyk@p{GE$ zYrbK)Pt@{60X=FtId*`Saykc5u1m3P8|V~N{9e;I6|-8l^(0_E$@ai>KQ`L=lwY$l z-7un-M|RoXk>d&i%HVkBi{jPUUfZi#4ya0>LAzzp?{r|@>BbSG_};OvvNQ1!BmK^B z5<|y$ESK_{AgFD>vR}e>)|r%PQF^gEQSG_5Vo%Ct^_}d_eU0ayA9_%-bxT@?RR~qn zZ!%3ENHRWauy>O0S%5iIhb4*)J>qm|b6zdP0^ioQIUfT9ChMA~NMwWyl|fa^jt7`A z)WC2W196r{4~-%sXPR1&h|nM+^5k9;h7{vW3kh{gjHOW$y?g=_!vhIH$OGSNI5HiW zkui}p1{J}KjEIVJU=oqkpy;zS2gO=xMk5h_xiG?s$b-rQgfgddbSw?A*Jht}AlB9% zVMnmR?j_jc@Ky*M2D=Z9A)v8%YYf%_LvX-g5#NOTUIXD68x-tt+~x4MWQrXT8Ny)1 zIH1u92?;g{wl>kRbTpPgAfPcgG!AF2@UV_MAH|?Dt)t>hl_CBY!-WA~zOJswmzQLV3-fccQpwD; zSR|YhO!9dXT+aB|=*XAhq0j&M^zp;{cY|-=4D|QCe%0IavYXx2+3}+N-)*fe&!06n zH8wo`v;N8BM|BTt|EQ^caKEau;`iUm%Sua%@7=vqRCxPew+epEznORA`Y+e6Ub&om z>F1p6tjvt`i)pDTKV3*pVkMquCdB{9h>JZJ6CD*95gryALJy_|1)ik_obf;H_s<{x zaq8p=UmwbGZ}KrOlBdT}cef*lU0s|H9dtVIJ<)N$1Hs;I-(I{e4vRtCSX=GcZHd~Y tc+5?aCJ19A!<_~@wr|td+p4=|GaRO){hgMkhB{Pj(?*Eu2E})^|G)h8{b~RJ literal 667 zcmV;M0%ZM1Nk%w1VH*G&0M!5h*_NlqTz2j5@yvjg{r>*x>+ZfaR^;aD_U!NM%hTe* z%gTI_*v-|!Lt?~CY2v%a_4fDNpRfA*`|85X^!4}6Zie{z`N?;U=jrV7^YzPPedV^o z@bUA&JY4JH=G?Bj+^Dwc-s9A^!o^Z=@8;>@g@0F^7Oqt zTif2_A^8LW002J#EC2ui02=@s000L6z@Kn96kP(1P9ty;5uecCz%Uv_PLmU$;^+*b zPewzNKoHJo0%D?RFu>Bz$xLY3@2xXpWB5WBBMEgg5-f&?ED|#j8HvRo7 z;sU1d*DnK%2qWac=&_@r!-o(b_JA?Vzyt_3bZFeju_H$t5GEMt@BqRN9w<|)T&Z#g z1QQKLM4+&vfK8j=#NFIkU#6Xm2uU{#OD(%_h9*q$sdKADxwW`&tR15SV zq3(wP1sQnYI6yXMKow*U;NX$rfi)=sJoLbDqpsb%cro2FxDq2!pR2bR4L$qOxVnH4fcjX;UoA0Ct!jA06RN% BL<|4` diff --git a/phpBB/styles/prosilver/theme/images/forum_unread_locked.gif b/phpBB/styles/prosilver/theme/images/forum_unread_locked.gif index 34f1d46ad76d7826d739a5bbb7d772e1d2bb488c..63ac3fbedf5538987117f0d94a6a7c7dd268993a 100644 GIT binary patch literal 2637 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 UTND+L@(4Lu8Mw5R_=B+fe_yi^zyJUM literal 725 zcmV;`0xJDSNk%w1VH*G&0M!5h;Fe&}<>}?s z+p@E^r&MXjTzA*i+ULQ`sF*BE?(gyD=42)e9@tkduro!U zm(T`tlE@@x^Xah(UB1!}plp`e@8=WX;Dwq{7-lg9goTAMb{HsqLn$GFgNBlaG8hMM zLm>b%geodNJ^`Wuo}~nX03kyr8z(U;8nHVtw6w6Xu_`eF8+`{DuROxT#Kpq843|;)L99%Wz-NRA5D9z=B}zk#5j#>yX)uCB1-c1Z z+`s{0#|Q#FX4UGUfkp!ZLIMovK!NTG5keX4V8Mez#ezL(Oei4a0z?uz=(c2hz`_h2 z)U5RoaCudL2LUT6#<5_>01!IJChTG15|JqbMoe5$;%oy8V#y*P!D7M$C>H`W0AQg4 zbsQ)rC?G+C0=yA>9DFgcBfx3{1~P;Q@j`+B0Tb+i2^;_%5yB23Fu*_v2kdY_2p-5M HL=XTwA2m*W diff --git a/phpBB/styles/prosilver/theme/images/sticky_read.gif b/phpBB/styles/prosilver/theme/images/sticky_read.gif index e1af585da5a2681188faa39f4110fe7135457139..c56a3833f9e5e2336d286654a3b273b8b691616a 100644 GIT binary patch literal 2605 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 diff --git a/phpBB/styles/prosilver/theme/images/sticky_read_locked.gif b/phpBB/styles/prosilver/theme/images/sticky_read_locked.gif index 79f581be79318432809028e06cdb23a165c9e13e..854a8f06ded87b500fcaa44663a5dfab802eec56 100644 GIT binary patch literal 1982 zcmdT_=U764p@;+-0|)|&Wy7w&`5*TAa_%|z{GR7L=YF`}zEmfWPJ|F4 z>kvq2XlPVaG?&XwNJubcz%E6t^Tv6&r?!T#A0zyPEKB4UP?}(97V+?rKP36NhIavE@mvR_&?Fkk&dTK86SU3~j~b?x2S z#`|}hTc19ChW!7)^gRp;fp|kO+aqtk2}I?y&|7pqIVJT%+Qsxs=RtEFxH1f;4A(IS z#n;oRmKs?Fw+b{YsW*y57_}@_T{BAz7Q5H-s%n-RrdaHyn*}$=I=XpL+o@h4h&6|2 z>3Y?rxgoMqSg>PstQ(bya2rf<>w{a3bhx`XIM_M3xVN=~R()#IGu~c(8W^{BieNxr z$~sBf?UJUy)zl1yDnDrr03^Z`B!fI0F)l63z5Ek3SyD{(FoN&5at|FZeqh#Z0uS&R zOnKaCtt}-s4|j2k+T#rAySq$9?g~Lge*W2XgenQ*f7>%<<%&58Xg}&iN_wqp!8mls zQv=dyPAd2-9YhUG(KHo4s~pwuu3^n}SGWu<%$ZiUK^3mq&Ra+ zNmvcG=L|O9_2pcK%uk!~S0@bk?)jSI-b20}YUqt7W5+eUT?NMl9uwfzMOe7*NxHah zYr^fcYKCJ3*(K=~e-h>=0&Hc^#DP@m6u^o^R)`2jKEJs16V*7`6s zDl?=v_w^XG7C@pUmbr%OYQjRQzq;^Fy6SX~;&qd!3s>;&J6rN{O+u_oO3F(*wMy+W z6r4}=#WyM4wl0h+99^qblfZxsQF(>tN?27J;z5g2K%1oHAt@S}18=Yn+@ZwzzLZr~ zQl|FYLd&Q6q;`eQlY4)xmoJvlZj6gO32S{N77!!eQ3~PBabZ(4qF?XO=`LdziniOx z{)J{F#b~@t>n#ujD_)8e-6X6HE+)}TjKmU}VXJhzzi!!q;4RLV}n}9yf&A)T@^%=Wt*J`P*6CC zjuaz72>?~MI`FfWnaGgst6qM8ISrk8t}m{>KwtO)tqHsP!NQ*A--}kl`!{J+%F12%+U>jXH0HUxXniD-ubhY84o(+3BXsNT-5;= z4kOe#kV5?`CeO&Ia2}8CjKlHyd>g*4O)Mu2M*u+(hbQ8QM6A36%RR&5(FIr**KC{O ze;gDhH-r7_)5on3 z?>9Hr->t2_U0Gg|z4>eL^@4Q%)!fV3ndzxNCnv_oMn{HU3_XALbnwYQe_wA;_v5b4 zj`p_Jmgc6$M-6|}*VX=B^RT+AvZDNfXtPY-uDSF#Jq8FX@Vu(z`% z67V=1Ean^Qy;hbM=4dmNDX_=H*vN3Vfxh0ZojY`Ow2@kx8VI<$nyQMj5=>D+{!@_t E1B^-<@&Et; literal 646 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 diff --git a/phpBB/styles/prosilver/theme/images/sticky_read_mine.gif b/phpBB/styles/prosilver/theme/images/sticky_read_mine.gif index 8f5f28fe5e3f88713baad319c16301c27cb4825b..3cd077355a3184c4fbce823f194b5eaacd17050b 100644 GIT binary patch literal 2016 zcmb_d`#;kQAD>HeNtj|Ar^hUchF#2Mi#2CMDm6_}t=Q(f*>Rg$kLl{nEW>CJR$a}Q@q?cvDQUgw@=bQOMBsy+2otm%+78N$Zg|YZ~OJm zpUKIRYu9p%if>D$(o&i1{)4jeipr|$n$GCV?u4wKq@3QAy!Yn|`z{rKxO%5Qr)216 z`EYT?i1cyd{VqvG&xNYqtS5bAW%BW==My!JH=YklUk=}E9W877SgshWX#ZH%G5)f- zMe(|$v%9amr+50*+qsT+^3I96?oUncr{47qF7ytz_D}Z>jI{O7bPUaQjn03VT>`57XH+}qsx2NZUe8zbGl)DaGZ#41_hJ98K zD|zYfCugd|0)V>?-IcS(ZUOi$Nk8$J>FQv(=(@`>*!!cg*t_N{Gs-1q zExFdftKwTS<$Dy4-}^4^&5`sXTJDntXhRY$Uqxa)7bDOpv;GbeZ$*7+Jcv5dYFW(d zH_xZ75^wJbcRvyY0x1=(F0)*fJjF@H7!kR!=;=igv!Z%1HEc^3SiJpcVVsh>g#t$Z z1DR<I9A{5V!5`&H(D8ZEX+!c*_LIK zeWwIw$ysoNYvki|LuW5T^$pw&S+Hh(OL3i>lFrHN5o4^^5T>rPZa+0c)80&nv~gwb zYfUqL^JqoZqE?xn@4fJLNiY`%mZZNY?II4T-XYzEly^Ta>tyd)59Sk%Wzdid1dy_CoaRB78Ds-mQf(J#V zmDk4Q2p$>h+v8`Vk4r##Z(KN0CU*)0^x*RJ2SoKvu-!AtRHs;3g%U)Tl0FGF6CbXH z=HQn1OR4d5rZR3c)>Dl#1AyUdp&?k0Ws)9<_tR=u+UrL{sY7K!GjR-s(8yfF6k`O2 zx6@`R<`90~6ylS%o$8Ih2ryTO3oNP>Un(1$ej3*+kG`N-HV?WN$L>cpxZ9KWH$I9q z2nu@$9-4Fkwu&6ZrTVGupJ6*xb>$kcDy>$XxLcNu(F*Z^;40g!#p>DSiI#8}JT-m9 zXGdj=6@ELo_<`xpy>(V_a`NGNh3e3!=vQ36!qC?{)f23VEAX>@!in~TtNHDV>Lvnd zVW;5BF-^x_5HF2`blV1(7xo6RRjE0CxdSnPNAc#;ArIL_!5|$kmmf;mMM|jOU^?PnEoOL1Ty))(Z_>^pfZKbHSf4v#AmVt0U?3~aCsq4 z$my!5NCeN{3F&R?f$`u|fB@c}(*l5g`hXYvbRe7HkK9etbQBRq!TexA$V7;OgF?cI zA}1u%Ka>R!*W&du8j1Mth%nFz>Ac=RtaDOA1pva<+RloNwQ)e$6Rfee1P2`65`n{D z?a&wk8jH8WV2Kz45rakiFeFJ6;VAIu5D!sZe~_(ZPRIbEkWWOTBO)TKBW$cg1za?i zKp>zoI5ZAtwKicD9vLEJimXDyx2;3`4}%JXvjsf9kQW+)SjS|tLQe^ukVy183Hk@i znmqJB`qq+vHUxyMtwpe=U+Mem%3sU>`L^`+%i_ZP-0aNs)aOr=6XPGpMn{H+1_$~- z^u6zW*VEnA`S#C_H?P|jZLeBenqM|GzIfhHUswA~{`5&rb=BiXl@BY*%O2dnCo8>M zBE56_R&mkI8-)e=dDnBVT2K(sw&EBzhu|nft_`L literal 633 zcmV-<0*3uZNk%w1VH*G&0M!5hxXRng-tK2-XLX~@mX?;Xva{Ic^N_gNWt_|G?eOE~ z>FMk4hK7c(Fit0Sx&8kBNsGf+lgIY=_~PyMq)}yab93nN_|H6F=jrUy+2N?g-}w3Z z*VouMfWF1i-jpLgGkm=C_4eT6=koLP_xk+7!o%I*<+su2Edc`?=oD;Y!Q(-fGV#PoV8O8f zItDCRNbq669i9OZCisvrf(3_`S_MY9m}%i8o*xkq=;RT?1%nD4LTvC+vl_((LfrSncu9h9rA%&w5BSJg~;9#y4039qm;J|=E2_G~* z`5jUN0*wdA7`Px2;lN@cfM0PqR^mZoXqSJ~bpvCK55A!>ci_Y3fdL2uQVSWd0)Yk% T13(~*hUMFtbo8f~>gcBV`#X_u`H zZQJV3k|br^XOM_ujF@p5!??^Cxf{QCcK7U`@cX`>^S;mJd!Fxko^#&w>_6b;^$ zwqTwIs&@KTSwIfGK_7mDCcMS?SK9_w+XYqI2UR;9sdhYCy(^gIc$DRItj0N{#wCR1 z8d~cXTDRw99rk3MM_9dQcs(wn0e`CgU{oW-JF3Y$y3r@P=}-*&Fq!Qa%l3=o_{XyY z;yI8Y3g>8I)3I|cA?KPylUhzBw;rdpkuJ5INo_xq)9hJ4;PgWKdu;gQaSSM^~kfT(ZAmE%UGk3@>aY#6U>7^`d?d)+t=se&|#-!zHevc=ULadq?OPksH}pT(?}iMrN_`nHLN zw!!z^)9*e?+CK5Q0|M@Vw1X@Cz@6#h&3uIP$+|zwdirJD0bc)5-@ve-mp|M;B zIVGK(mQGDe7bhi4)6!|l%#1`Tk;)`9GO5Ds3`F)tHVc{iG7CL(U*_iL=H{2BvgMiC zW!abI*|`;9MPEgI;AyKd=*w@?}Sy}#`spzjB@yz36q4a1r=G~j<4YRWPa>_s3n8KnUqg@6Ui zd=%SbuJyHVB{lkBPx(V7xWkXV7@*_h=k|1cA+I7)ysay$*O3sQ1Jvp|xy@UWu&%bG z2d`wpE1C!Ltv>sWyY2zOm}Ff9&^mKn9_~WLo8j$-J0CaY1Ts|sfsg?RxK76~`poTo z+P3PoH99C|ZrcZRY7e9WKGx{?zHD}yj+eP0oq^LmVx$d_Y%gy>fN$m*m$K>Cs)&OO z^Ls^V4AXB)wKh9|_IfW2z~Hv?Dr(u+GbdhdF?O30H9P*M2?Ls&VgXjaikx`Bl;Ak{ zd-C@<^^vVSiS9bEiEMUb<8hBcb}s4XXki{HB$&BTKh}P|5#Aj&dWYJ~QQdM*xTxk& z@)>>rC~sN^-6l^0$gEcNQG}cAd^^>3nS$2H}`cl<|>i%2`x0VDFT(#5;v0Pn3V6^$qA!aU@Y;uqwh1DCDH>B?YN zR|(TLH!vplg=KD2?ThZ6rM{c@n3QyE2Dp?A2VQYDr*h&HDm{5`S&NkgFF4Ih8Su|$ zs{-Q^jw2@*C1E|7C7#%#{MDUS$J@rR6jgI)7)v#V8q~7G@bm?QvWZ8**+$Nh(neL_ zbXnI<59lZ(c_g^^PE3=JC*Ho^*v^tmhU0aB4@>j#QP7Uva4%(>h6UbqazFl(8MDmt zA;W(k9E24fVWQ|I2U{vC248d=`lQ!%pBT!P?F^?=%!rktAO#VTnc8JrRu#T$gPtF8 zUT#rlnbu_vQw(A2->W0gqX*rk@Tt60mqY0(y->n?ppauvmhCnIS9|m-3 z9W7<0_jhaPV2gHNd-;ZD0s|Y!N=sNbkdkJM?i^g6W-Z?>HFg55x=FZtTm5z(GOaqr*V#*d(WuyRc=t6O;` z85^Ag;A$WSXsRIgrltZF&mV5|egg-DE2q+n40UEb@E1T$ctw#>5CHJLBqg9@qR*pe z*my-{>id|jGqd-yFJF&90lxB7%XLj`juxp$lHpWFY!e~jV1;$@6^(V(;8Ka!8S^1J z-UsDSF4aKi?mId4EewRTtHh=Vje=WI1_8e_9m@c)pyXraSOA+X&^}^$&;FA+b8DRE zrgNgpKuw}*gD_JE=B%&!Fq*}*NW-`V4;aW&cGbqIu6_^OIDth_KVH-Sj$fP( z;EVC4ct%D=7;!!(!kL8Hvm4wzjcH zV{BY7&Mp`mFo4I|^m3C}RC@6=-|b z|LqUz{C7f;anP|OK>LTS$yZmFmlhZ1p<7QjBb7`~O-_i%$3&yTk>R010e_(Xb04pl z+tdB&V^`;gj`sI$?^;`$Iqas!hWfhN8dmk&H&w4IUsb#;e^FNYS4r{nXHTCze)O>D z&j)|p|NUNJLH^y}?%e)0FZY+9Z{^&~zLE9Qb!O(Zs|@;&8CTNNQZJ|caOvWO@6RXG zlD<1fO-wjTiI0mV$DE0dI(;gV6cJ7gJ9*-G=(i!qf{z{v3Jmb~BOE^D>*Ia!0DiyM zKAh)X5A2@Z?ryFw&Q7}=9qjFFZ7|kWXiJNoJIuFl+iGTtGC^+nX0!38uZ;{h8f?(l a(_OFgmA00q20~p;Rb`zrTnV}eUH=EtsM*f| literal 622 zcmV-!0+IbkNk%w1VH*G&0M!5hy)aVa<>}F@x8kL=+S1sFHA%E)c>VqU>AJ=2?eOXA z?#zRi$60jp*4)|4)9lOB$!~|$yv6wG?Z=y^%YBlL+j^E+t0002YOKS7<_Q613@Xy!w>T&K7#=;Ffpbv7y$|gC>M@T5FZB{76AbyF1fk30Vh5K3{VvaJ}JD%$O(%8 zPyiu52^P|%B-Pc@31=i+L@Lh3(&6Ia2|5xL+(ZBmJ}q=~0tE#&?+PhCH2?%pkUnyA z3FOI(@Xi;43SL;O(2*j6LmUDzI8348z=u6gyfyGKB8A5Z1wa_^m_ktq5)QhExX^*) zi4+b%fS8ctgdzznAn>{Hp{0h44JR^yARt474+$SksNh3@0gGoEWK6)Z!DtN@Cid|W z0)a$_10w`17;)g-g{51E4D*p=!v;k(n57*Op#rEL88Qf9#X!JZAp#hnIAEZ#ff_3= zO!)hwE~p2E1^7T=!Y^YE2zVUWj7Kixx-@o_X~19&V<8j(d>Amm0|3*fg%A*7f&+w< Ie1ZS~JLA_Pb^rhX diff --git a/phpBB/styles/prosilver/theme/images/sticky_unread_locked.gif b/phpBB/styles/prosilver/theme/images/sticky_unread_locked.gif index 5792b8649a4e4e0a97c44a359d88b6326938ff64..a8f7ba84240f1968cc6ea0177baaa93595a43e77 100644 GIT binary patch literal 2023 zcmd5-`9IWa8~!q58>3>z>2OAkQ8L18$V|pM%#8gQZAxVsOBmA_497V~!_-(R%qwLn zO19KN(y5d++p%TK62_pilqI1PI=pY6^EbTLFZXlb&;7Zs`?{YW9xC0|gy@L}@W2WH z`1<;Wg@r{&M_1`OKG%1tHat>&=y;9sv0Bo}dW$m+)?P1ZzKsq6&CWs1uB?`$oTd|D zttZ3VJa`>Gzx{QN|0-C}9U^RF3p;sNdO{Nf0zpzzQd(MCc6Rn%;nlpnyrQC_^78Vk zs;WW3jo0y6!&h>LQ||Pq7mnR17ThZPY;0@*{|C_g z0+s>*H$ZQDmhCqIEp z1$+WTB%h8U5KIUdw3@sKLMTjfRud_r31qr6qmkiEBNNa{A~ok{Lc0!GZ4+A4&@jzJ zJ5|Z9TVQt&iX{(GZLF=$&26YdX4no0eS+@{1??o*HRix0sijC$oyOEQ9yZ6a;{1yr z+s=9gwLA;oJ@TkWCj=r=TgNA5;=}+nh9Rq>$yvN)d)eR;9G4HixX+_7zXYGcN=Vsj z%!epFEz?K|xAApa^z@36W)z%;o{hO9*@XmC9LsT&g>AR(lg8OA(tQQ+!Tjj<;yznt z)aKlPriR1^k_rbQvQ+RuE!6wGsN?cM*n_q_>O}nWG&(F%N;OK`u@xlmg0$dEkJsL~ zG~7bJ{CT0ziy@Fgr#hVA|0(Q$4H7@vkqDNVbX1hB(rJvs>r|Frh%r!EiSL!oghJP5 z9}1PV=(*Heo2N+JX$`vifMLZzPQnZIivpMf>g9>oL{ zO7&7=?Rh*f*xj=0Y;0ICBSV|V?CMdr$MQ5|;r=$YiB#ISNL~}J#+O6&ZURS8W(YPA z>Lk8CA+XQN=~G}B{G2WiaHsF4OC!o?tm|%+{b?5ds+4PtfrY6|4_2vAQO;DH4fAsi z0NC2Cj90u{vzNwxcnTl>-Hp#)Cl>F|Jh=n|sFN;G^A7+4XD|$G$|iX9nB= zvOo%8oh-xwIlae-n)DC2h^3Z&aaPiB^#Vl;>d^Wu^OsS&W(8c2FD=#48>PTcv4sE+ zwNsnVwspBep$Q6Bs60ZG2dmBnqN9K|Y=N2LDq4X!WZh6u;DVu+(J z^pc3yRliiYjI{#Q7-8#{d#}bi;6S}{(tzeS#p8}HNQx)db1Ryf^Vpu=flMyai|H4@ zBBSP?RilsrK4jD}BS)+w+nVVgK#Srq8BtDd-cf_1FOb`s)*&1w(#XJA-y26TK^`I+;EaeSctbrT z9*Z-^V2K!NR63_>`5 z7#xvE#9;9lJYIjRLq9Z<#r5RrvqH7DDgMVnVTO8h0@&Pu5EgQq)6**?j7vtLFxw)S z?+R`&)z#V2-u72(OLJ4>%ZB>8+M4PY&#Rt2ee&ny%10Fs%gajt zcyPbuUU5-jLH^ymJGXOlZr#kz%FMWNJ^fnRe?+M%$ycvjPD)IO7hbw3h>PW4i241u zU!#ACisVIvhjBwW=h-2w;Gn>B0selzOdoGA&$DMvdz?Dye&YDCqet8ru0OjtJ2^Vo z+tF!MTN{eCm8FHb8QJtOiD+`j*vOE8$6+xB`g#X-(K-jT_wUm}X(IRT(Lns9uJ+^Z dA5`Hm73Ez!cPK#>Aqw(xvNB+h^wyVh_#ZQaQAq#* literal 626 zcmV-&0*(DgNk%w1VH*G&0M$PLh&4&HW_aJ3s_n|t<+{ZE{r>Fj@XT9x(5kfP>h0Et zn!Y+&=IHC;;^+0=i6a9_v!7zJzddjgT$Pt z&t-m;LRQ2?WBTs#({hO3&(!Md@Amij$4qJS+26e_PyF`y<*d5#@$=&2=*d%W#z(^b diff --git a/phpBB/styles/prosilver/theme/images/sticky_unread_locked_mine.gif b/phpBB/styles/prosilver/theme/images/sticky_unread_locked_mine.gif index 93495770c8cfac457a7b60575bfe0f8a9a2a8763..bb140337815e690b2fb3e2390cc132694ba786f9 100644 GIT binary patch literal 2059 zcmchY`#;ltAIE1K(}c*W3pH!SmDzXZ)Rs98b5;&*$zhoDVb@G{m9CgAhbS4h4y3fY z8I@z*l`iL;S?VGs=A1(a6%}3FcaQ5&xL?0~KJU-x{dheeulMJNkDa~kVLS~7!ht@6 zK*7PmadB}82?@1_oS$Lb>I^*VOepon$Lmcf4FvBd3%_PkU<*0;xno$HYh>H8=yoq= zD>bgu`&5??yO;h)Z%ATiIOjzqw=X8Oi;>#PzW6dWy+0wF$Kz#WWaQ@N78DfRNxdWx z2ueyyDl02%YikD*a|d}>2h#H2q!+xscaP!+FIc*M#C5_lNFQ4VFG0z4>5F zP&HBfaPr=hsfuTl)%EWmHqJhMK3CV?-QE4Je`rhdP2FR?1B+d+mU{ZdgConY-mbhJ z9vYb#e>XNeGO_x0ba-@fbbNAra%SrN+|1m<=dr2JQ?qL`A3iL6{JQXQacOyF_0zYN zPhY;QegC}nWo><9V*~Vmm)1H|0t7k%LT{6|-vk8POgzC!=JL*`q^6}`NG2Po%EBNJ zn5-&5PWzRbkwG<*=NH{Bk~hldk|Bl#>3A8wbe<8OK)@RT>e74}JXakeQ+$u>*#MCR z2-dEiR1wwF)tUgv^3^?0xIp>FEnGLb99=V)7c;YNWJ>}WaMdW18RfW@%NkqHI6K5fP-02%E7H!Q5S^%$ypG%q3#c8_>gpzRLP~=#%OpyB1I|G86>52MR2DB zxn7{5YBrkeDvcdx!^X)rk5J85h^>EUFDcl=2J?t&q41DwQ>@`8(!ZyQ-z@h zkUor6pHXeifhx8kFR89+`Jx4>S-pkCWR(EaqN1))M^l_-;gM;hD%ISnNdFjcTOfsL z=LBY_@x3r)LWQ(P(Jlt} zzIz!#J6n{6(A{4_%xW^AQY7Y;k`An(4a+)8d@EXQp`B2|l2Um2(IITR>`~~Ms2ULV z!oB<|+%gvou}Fj{zMxpzluM~G0Of(;BuoWWtutEJrJhq?xnWOkf$L5jqMdVKV?*T6 zZhksoRr&!}1eS0qzAA_N;} zsJgF5`YKFZKR@DcenU>A$wqvAZ|mKY>a7aBb#eOKgCmb-E(jhrj?ETBR_8{Q;w<2n ztJg0o3qvF%cYas#tL^vju;dZ7otTz#B=&Wl63oXxSr+%2{}cr~$w`*iHbZbN&sT=U zxbA`qqH@~e#XmuN`M<_^xw0_7?oZS#48jH5Inwqm2w7>{D z3lTsM35zBo7oXN45n(|@vKu_V;KOjjb0QyMNo_e;y=yY#=j?!3v9sMr?c10%GD= zL?jZ}h5$b)Tk(K@@@*CWOo$%6H5TSpeu*EO8{fZuU0?h1`P1sk^2epcg%9&{vor6f zrzR)H$412?!|#UPz8QQy(Erz~mwhipy*=GsogM9Mt;8OJ`}E1<|2%qF zQ(aYAQU2imy|PkaN%6n$-Vxj`x^=VgMnV4dYge!2{VO+zpM5#&(#6b-3+ZX8Dd&0I zWKL4zxj)V(oH_kFJN{H0E0*~iBPKd3G9o-IG$fcF6c|AB_w)5R>3xDqIqv1@;ePC> zo2!enlcR$@+0NF6WNl?>VQxk=Jwm`AHZe9bG{EU&0gN76_t398+6NDy_9L|r`}S&T jsQ5W_Z+yn#V|I<*d5o=IZUr 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 diff --git a/phpBB/styles/prosilver/theme/images/topic_moved.gif b/phpBB/styles/prosilver/theme/images/topic_moved.gif index 3dafa46ed7c8a72ae11663f5792bdddc58475d75..707b9f5d3d887ca21a62cb33865cac1a118ba8c8 100644 GIT binary patch literal 2609 zcmeH|`#aO`AIIOA8Yv@@Lwaw+oW~q8Ic#k)6;Uc3KRL`Hr!_0mX+lXylCN66A%(~% zN=XvRF-rK9a@=gQVJGKv-|h45`uzO;1HRAeab5TQy6@NhdR?#Ab>G+R?&0Qu^~V4h zV3q*{2M23MR_H`k=*oDd7yW8e^ecUel-D5jHG*1+jHxuFRhq=UF^R1*jjgge`_}4g zHRfD3mR{qW_}(e8)+M>tHM!2`cGKa^Pe-#p9nWeByx&63Zja1qi^%(OGOvwR(0Qt$ z>ugcS#it$D%e$_X|CLL?SKrbq`!e44-L3AwS2K`ZH<(}7Ti!C5_mNrH zH2k!MUEInpZR1pQjJ*5Gs_A4`b@AUy>E<_fGe2~5n!j_}dqK|ec3~>gSoIxh{2W#{jXJT+{dWgkg4s(WB+#%M;(C`S0&1G{& zm~0-4!yo4GIUF9FJIWauV~z;8yfH3+e1t#F;S0H=A|8K?#~1KM1^hAL=(uQ1AQ~E* zW(j84!Wph;c5GZcCJ>Jc#R8#3Ad(1WObEpjBJl)IJUc!)FPvHsOD4q=lah(4iOK27 zsp%;hGgH%2W~XOnXQa%|%}SY@pPpZuU09l%o1dFsn3u93WpP2uqEt(Z%PUJVEiWz0 zw6wgkyu9+aen|!VU;lFl;PVhU0C)hH%TCDN1OQzDuu6KQ=Q(wW(DkNAj4AEcVH*+V zP}p%iLe0!QDpqbX?kP3W0UxHr}@1o%{6Yn&~|Z zxSb;u>dkC9kYKA0c@7dt`W08$=ZdKLq%`Ednr3Xi{VkZbro2Ipq(ZSlb!!jq8L=QW z?Mn{fV(GR5bzl3fF5VGooftU{JS?)+_sZ4u-pZJ<{q^}?PdrmD<$y4{9YIG9S^^@% z)*~%;=Iwmwm0hLj#xPJjh<{LCkBawMfqi|c1iNd*>ni@^OO4V79K%)(5C36VPYiH{ zgbjqGN-x+d>Csl)>n$2oV7uT1WDWxEaX1Ia~(i>5pVXhDt6TFo$WR zuZfK4bl0M<`l-m!NCSDfDe{Mo>smr6b+~ZI5TLp{Thj12>jK^wdhhh8$&(ObgTijz zlNbV^ZBW*N^nW>eqIe~O3N#kK{I)QPWEiC30UM~sHUL%Vb4>fA=1y~l>Bi#m^49u- zMkTo<5VlILn%-n|IxAQ3>Ss9?Q0a4%tF2^HKRw&T7?NxQHbOPGBRv=Pqy1i`6^%F`9Ua zuwDMfV+G%^{F3rk4LqILicIOQRWWx};2k-eHHe^zR3|;Fy*N)w&|1_%`@#AN3Y~ zwl6vk-ni0#Zt|IX-D*^uQpLB-kS1mds&tNZeapIsRpSfFCC^iN{_~tn#THYMQ8QqMRB4k zur&4kmrLo9cqJ~*ZUDLuo(RnWR+DPwb*$*g^c`t8gJ7x&B%4ey34$WkDIXGFQqS+Y z7GV46k`+&W-A{<23cg7#RMx{b@P*?`n3gU!X>%_3JMrFm=b;*scVC0 zT@T&$NargFH3Yrl(8x?7%hR>naf<8Hnjh)UR=V#hRJ40)^7+67tFUHC(ez$(lA%#u zv)ds=+Kn^2f{bFcypqV~WbDpEJ@uNeYqwj{&ajSN-jngjfNbLFam}|dU_(i0vYB&9 zK5l=fx-wv0xAf4k7aoe_B11}Mu( zh^CT3J4<_uKx-QZa0}Mb+79c0u{8%VR@U}tD=gaD*22o#(F*HmWexro!bKT$q6P&! z?jgGUPA0XS5ur31#Sx8;jg7U8wXuw*hM=vnSS;EKgT`Piq#hPAXQF8SaTZZANLh&g z#vqbo0;ypXT3B=xD2wSI5Pgc~j6k4eNzlKuNXtY2Q=ioMr$gi@XzcV0>(p&l}-#*uyO5(BMFSU+>Q!J>S3m)!o(kwd2d@_O?&0EzM1h z4Ie+$*VVqSc~||m>P_YAR~0W`l$SmKv-DX>@zbKhf+vsjALZrdJp6a|1IGP(S^vts zn{g*S?e?vkH?Chxy_$06a&l7Qr3CuL3+K literal 667 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 diff --git a/phpBB/styles/prosilver/theme/images/topic_read_hot.gif b/phpBB/styles/prosilver/theme/images/topic_read_hot.gif index dcb6f3bd60fa0397eb22bf686f5a9fbca112bc05..d118fdcc4f60be2b5ea1567c0c8dd004ec2e51d1 100644 GIT binary patch literal 2683 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 literal 1469 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 literal 1519 zcmZXSeLT|%9LImNEyHHUHrmKUqU5PkX}0_*YNHM9oVc252_@x-RP(UJ%H-)qGSh>n z6i&r;(QuU!LQgns9H%S|^HiK$_j=vydfk2h`u_KMe;(X+@7lVJO$3O*Ybqe0m^_@< z;+NIj|6W;IR<`u#pE-2{6}Fyk$&F(lK0fW0D`#fs7d}r;DThYJ=H?e}F^{OOeVhO2 z*!YBE>dWHN?A&~&DJAk|Yhz=RbZ9g;H+Nb&Gyi$<{rJT2=!b}iA7vkB`F#Gms7Hoj z4_aRjnn%=jc6JTOM!I`t?Qf*RzqVef>YRMu`CDq?r^)G=*Zs2LF}ZxgIJ~BHU}CVT z<&UnnZ%3!*6;sUAra8sbTi+Yvvbf-+g-_KfQ?FB*he|IoO7;MPH;tg9Jpc^euLvTn9ZEcdIg+$QNZ{OYlhw#>zCu8-D zjfwpO#FY-#y6U>twpr$D3?N2NV-=IJhU-UkHyEOE5Cg;t3Tn1lFNYMDdeqiTE^cT@ zg22qN^CCv&K>@{MZBWyIY%$L`82F5xvV2w$Gd2@B$G7^!+WX^6E|%Q ziQFJck~{iHMGqm2y9Co$BMi3jMO{-}C+UvbN?B8)u@8Ycr2e2DkGFb9@cHS81g|M? zQm$jcwL~s_{M`<9lx{ix8B?!h@8`Bj+W{6sdrj91u0z7$ll3K4iI!3M+pm3j zGjXS=Q8dJS21A5%+O9c-`AHV+ZntDv?SJG0sXphffk$LpIE!zD=aByGRvmx=IsjJH zZJ4+~KG&@yXf_R!_?rvzN+L3%b&cMYC$N{!)l1Q$KEAR&2%NL5PD{ResAzV7IWI$F zWacJAc*G48?&1;^#c^{=qLRsOWE(-e8!9{da)?&mbrw1*GN8ci#0hsC%!5ufVi8ut zV8klQUgvKapa2HIsTg?TL3EZ$r~@qiq{RQ(rna$93$J_&yAIfNjYn?j30))aKi`yb z-?6SayNwj!;9SwY4J22;m`QP^k^!1M58zz{5>lvGKaM{e#Aaq?r>5I5$#j&kAll=2 zx(6O4m6Vp;rn%j_R|Hnk@ee>Wx`qzN86lsD)7QdQlblGaVQZQHBm0_8uz0XT&7GdA zQRsE7M=5;y!>uSk>&>k>uY2`&J(O1ZS{miGbyxR(#>EWSXc_=%OJmeu0u~;1FNeg@ z$gxxu^&CjzU*;##3_)T>W=5b^PHs*hK3|wmL({yNdokX~{iW0!<>))K|H$k79Za%# z@RO@fTnq^#GYh4V?J^@$PWfJI6tak&DXzZkP-pCsiG?=`6Cwr0Agb(6Sr9KeI3&RH zc35y|F!ehSU008%SuPjD1gQ4B)2z4)d=^=dMn7QUpkjOG#V1)?ieyFjAR$e$nKf{>3@wzvNUi#wC;AHX-JhRCtx)HZTh*l5H;!;*MIB^4bE!_cf*Ox|CPDN<3Cq(TQY^-__d zn$lP)i&EYkW^6W_*_JueZ{AWAmnFeiA|d*&#jYRAX8ghv*_+;=-bb6w|CIXOAGxw-lI`NhS>WjAl%ymh<2zP_=s@%i)TEiElqo^+k5|DN;YdtO6d$+ORe zP5nj9{lzT<*Ix~m(T8rf4pp`dSGSMUFh?FRM``azA9Zr;Kk*t^V=sCH%?iH=Iy*bN zySsaOdU|_%`}+DAUx(X&OfUz;9|pypgOi;@li!B8KL$qzhDQ2_MhAvQKd~nV*rS7N z?%*(YXqeZ_l?@5y!<-S$$S9k`8|LuXoH6#u7-y6>Jj&;A1tVMmm&YIFjdRC@WBhR* zU&s@P#snh1K*$$N@W&^{g%bjycw96ooR}1eL~Nm)Gci3Xp5{%?2qz>Wv1CFlotTu0 zSCok*vPp@IFPRya&5C}`iKpfz(w`F9Pnk?6l}*Wh%70GDr>5izrlzK+@MY5_JYJyK z3$8;O3NbXa$}`@zS6KsNvMp9sJEKxX6G55<=$M1GHaZ_A)nV*C!M4`ANAsW+z-&#Y zoWKe*es|4&n*R|U?AiBPMkWwcf!4@gR^}ljio~v1ePvrf#e*a2@-HS9Zm!NT>Cg`c zGF&ZC9R(3gNJG)|UEmfKwIb`VZc)YEB-Ul)4TgWPr46gzt@RXPY`?C~FX}4yN?X-a zr5Ci#(><`Zuv?~V;A`{HmpkTL{G%yR_=x;2;KBZ@MRY1F-OE|M=vSSUXCj-}{szQI5g<-9Rv-N^whRx`z+K1MxCO|WkU1E4lgYcplPOjDc zYL3CJ+VGv4nm&La4=9S=s`I4Ao^jE2nm=+0Bd%s7_)%FHunJHI2y$CI3EmLstx7Kn z3MOn)+Y_~c3#F~;Rt9O8qqHKjcEC_pC02$h}% zp)C$G8onQ0;57zE-I&-&17~_E8-Xbv%I=3B`Y1JZ*^uZsy?9A0*vwTzr(#vGJCrWygM!FG@zQq&(X~>BzL!2|hxRt4^hHWhJeesY zr^?=&W_9|$4v<&0ccQw=WQ~sB`p>@AdO{|?plQ8nXJOYKVSM(nd`RhziIEwF2Ik7L zUa@@rY|YXlAIf_VCx3K=-Z$Q(1Ps>1cxq<^1=?+XrPSuoi)Q*)M<=bnn^g>~)XQ)cG_2}+@sfdVCu$WoUZuv`$Lr6m-+vBj(*AY~!sd4RRD zhp)rjH_Hn_2`^g?A3Ww}&Qz{z3Hhij0bOw7H07BW-2H2LUi55juK7UP+WoVMdZW;D zrPpXiz-;x~1!%+3LnZ{gXwA0ISezw+G zpEg*M=h=N|%&Kcm>2PS9V_l&}DaPX+JVcu31EPb=8`X53rMcIb`5}SYc@Cx0{HV@w zpg*1Abc+r+hV?mW{`J~x%qIOBrxg0aak+kBFx}GcAWJl}5}-qWA8Zi@D2(jb>FKGn zx)X2i9|i@8->99%U}1XoU~g2V-%-OWP#_Qh{iS|zcOV3dqu>;G*X>jiE+P(3frR6u z2}C#8Wb zHqwhdMbsQoOF_sNIpSIARdp8izUQFN8uwQ!f|28jvhH28gl61f#Cf?`}Xb$ z4DjFmhoA2*pPk-2uwI@XnClT#wbp8CtWj4}1+QME0#a5|d-_xu zsi~^*@$;adq3G!8>g(>Y&E_yLFxlJQI)T1_fPnAt@yg52+}+@gkB|NR{qywo*Vx+r z{{H6X=RSnM*4Nqh_xSz({CewhQR;- z|J&Z}IS-18IT|J^G6pYSL^BzL zF$9T=oDVq!F+K(XZ$lX~J~0{!tgWuCpe-R8LkklLDj*oU7z&#bj0(FTEeR8p0fZeI zyciE6(9k0iIlCGiJ`@2zI2RQ)AR6M#B_$l^XH#2|u$J`pGUDTLsoTL20^5GvFqqJ+H?5JzB8h|N;677%Qxv;l$x zv~w;+6kwqMgi4B|F8WwuqNfS(5Dm+f8&E)mg$E#duJB>$0uCP)eEw|6frkeV1&Ug@ zk<>(miWdgTU;v?mS)e>h3|QMBg;A~@ATW?Iuv@?g5c1j(aW!j-zeXSEiJ$_WlVm;^ zL|ANMK(xmVV7M?5fkC!yQf?)#Pyyi$78YPw2n_=Thz^#GQTmY~gbWo7Vnjgr!G&$x zA5O04?$ZDvN>Hi@1%*Zd5rrxi z(0WuFMcLu3Wix?Hbw2kG$W%(b~V! zCZN$aunBss32~y){uIUW^hfveZQhY>sHo0k=>F(yCKukDqTidLiRMYfZ;}D(z?eD+ zhO|4CvFq|nNnX>VJn9yQaeS{aYq7|%PH zFS?k2bg^D`vtCo#gg#Df|LpsLS>oVq{V=a#nD+r-gh!=PX&(oNhK7cRhet<8$H&Jd zBNOd^F*+s$T~orIX(4r5M5T#7(byBy%qbdklE#{%v4oQ>*#tv2IU}29_R&RCbk-D| zJq^HM(-@plwuCk>XUs5Xm@N7XhcUyU&&<-9vokCXgT!Lb9nq&9-qsb=kf&HIl4HQmkx0Z6nM4X8 zm&yPXGMOBZ44B9jayc+6LcR<)>F1Xx-GSOQQl0jSl>i%ZLZQEQeo%j)G7&8n6)%d1*-mRA7#kG=o` z{hxL%YHNW&8j$ts+UlJEtzQ8xer@hkQ_-Bgev8$)eTJiD=JrSNV>Mwve{Jg2NAW0a z-SIJpLZnvsynWJTayE057Yp2t`nd?3Q4w6_y%nA?*_y|UzEx^<;QK&L#qK+9#`?Bn zSA3Hvw;GzcjBydDqL*Pzp4eou$&ieK5&O*Qe}I;^{cbe zxv6}p8T525U2up%)LK^;=aE==>}ddjOvhYrIO$VZ;c?%svS&hQSZWD{7@;e&@{C2WB)o{O|$+_=9c+;y|%@%ihQ=6_J`#7fwFaSe6>*SlnnZH z(}F#11ZN1bv??+-mPXHYfgfI)<2@@mf2IdH#+UlrmT|o2 zkdb=YJ?mEXP%F1uRgA>Xzanui&%@PJsqX9N{Oke;bq!(D;h4n0Y>2wruDf=?d%xh_ zki%pAw3n0PoQgYp#5(9Jg%S*zA_1vc~g$?|r+3&ZSvA~A0x`rFP%V5`C}o2-7=>yWA;J{v!^Nla`w#;t z=(21CwX@eQbfw1FF!VS)raX**&(cfM*8!EO~ zWCrM~LCK*Z^sh4Aj9O7{pEn$Q-b`8Nyl~y{$-0A}eUw**$y;@N2lGQt6vX2evcY)E>uHlRgEwp(}RL>E?uTx90J@RfQ|B!k_Cj3c_Rtc@2**--uF^#Yw;1MBoy<>_~s zH+_y)Z7wDijHL5i#bpMM`rO;B&WQ7WNUYjIc)UZ1v)sw|xv{;&rycRs^Oq23%EnJ5 z5KISks1?5P(U^OO^JnqxSZ$C2hgh(aB);W|^$S@L-}W$-6y{PRv@$83-fNmc*Svhf z9bnn*F46lJJ5jDaoxbTKyNlCDK6}t1#tmaS(2Nn?(rtw|PBkD5Ty92sJY2K&MPQp% zaPyI%rWR|MAO(F@Gjt>zu_bt1+tQhl7m#@erDZ`c8#qb6yMDh8Kv` z_JcuQrz>Di0H$g z5O7?iD2!ss~VUwDU#)jc+(5bsuQ~WQ7S5#^QCN3EpmxKnd<_rr@x`=g!K%lEd zp#N3@+JpYrAK?6VLQ!boSTI2UT3=R{HR`2Bl~N&>NhRV1kx;;&pW|_7IcyelhC!!I zPfbpI9v}NO`q#+t(BMFSUoW+%yQ{OKy{+|QOEcxqrbhCIhI&#R@%_8nw}hHEuU}Qa z{Nu&*XHS2B^0=z9;l0J9^}M zUmukBcV3_}=hCWJkl1TQ=H=Xf3#F9uNzI5EV5(8Xt)~iakRJ8woxKC?EhA zmzf|dG%g$x94;|?KOrWPJqrMG(IOWAwmI?9=p*bN3xy~nGG-J&VgN%DDIjXB-~(O&Tpl!TBtZZn z0gxpGj66^viKGe;azYp}fSkVYo+KKukeQQYyOTavpje7xL`Qu17&IV}0laPtZ)J|FPWPQereFcM5pKB2q!2{pDSFkzdD zl@M+w>0UqGM+6E1%2WBFrh}jMaUv9u0mJ%yK36>8KnMv?-~|}+{WpaXNL;~$6aNJP F06Tz_Q6m5V diff --git a/phpBB/styles/prosilver/theme/images/topic_read_mine.gif b/phpBB/styles/prosilver/theme/images/topic_read_mine.gif index 18a1245b93a053cd2f84f8ea088dcd592c71deca..b0e9455d0eb61d038cd0ecaad1fac227eef8eb75 100644 GIT binary patch literal 2640 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 literal 652 zcmV;70(1RGNk%w1VH*G&0M!5h?8D9JyT;Fe&lHCF8H z@Xcd=#7$}B=IZ+H@zuD*z&%~bca8h;^Wfs=`1twu_xQpi@66TT;pY1L``?QJ@A&!o?#a^o z`~25|mh0^A;^XM(x5DSKy~S2>@5|Kj(b&RAW%Tv-=IHC^>Fn|H^zQHR>g?~mJX`<& z|J&ZOEj&2q=;`X`F9!}81`#ekHwZcR`1$(x2o)Y0 z5g5pbmM2e-g9sD$D2Sk&fEf?~MB_oRqQ#3Ay9FSSfJHO~AQdPa8FG&g76~HK+rhG> z%a<;1_}G|104otVMT}IKQ$z)+9}gpF@UTLM(W6L{B3f;e9{j_yo&^ahG|27WyA z@!^KouVBM^{ooCplm!latf)|7B-^)aSNLf*#6}DcDAvN=`*sD24KZvGDUg7K4-6(& zC|=BXg$WF$PCXgHfP@Dh2TXj}%=v?f13os;uwiL(f*5HJp*X-A1&T8&WCVg!z{Uaq mDlVf5y(R?%RB+-j&~PFK02y1lln!3xh>ac$m^c9w1OPh(-aZTf diff --git a/phpBB/styles/prosilver/theme/images/topic_unread_hot.gif b/phpBB/styles/prosilver/theme/images/topic_unread_hot.gif index e712f6e827d99a120f3a9d44cf9d7dc9875b69b4..1937164e08518575b8bd681501817fc0dbd7f585 100644 GIT binary patch literal 2682 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 diff --git a/phpBB/styles/prosilver/theme/images/topic_unread_hot_mine.gif b/phpBB/styles/prosilver/theme/images/topic_unread_hot_mine.gif index fa8b167c644fcf6e3dde78236fb2bf8b7a38daf4..28fdd88f4b05668343d01db547c8ce625634b1c6 100644 GIT binary patch literal 2192 zcmd5-`#;nBAODQGTQ;qZw2sf#%%#mPEVJe`GmMboTMk_eD~>|5a;d}2YD!V8Qc12w z9p%zJxuuLG_in-&qa~seN*uo59_MfPzJ7VXp6~bT@qE6XulElx7guMR9ghM~fUf{h zW$E$Iid$ptTVv~2&)D{e9sI;StkFAC&W&jFjcWAY-?Ah289(9q?xbgbh}*)FS_MZt zg{kdv>8**fo&;G}(wT1Qg;$5qy*_raCoQ)(Ew5Wv^ft4w`)qOF*^-_M*ZR(19mp>2 zEv$S~dS8)WK2&l?S^8kOyt=QdvG1XL_-5U^JC9Tk9*@>E_1CxbwRS5To{iQvD;wMX ze%d+S(lzn?g|hwS*z5ku_Lsf=L&~>`(Z0dYuLt@Dlmm*9F~#tpQZ+s@I;{Gj8XfU1czl~3RocQ$l%hcSLuhY{rKc;7^ZK4{-eS&` zq?J?GBQ#2GOX29ygQ%&bo;?}nBc5s2Y&IY={E(0GNI4U@^JJ*rCDY@dOPn2%ZS7^6 zv}o3?GdkxlXScb?qAJay>VX(%G`7OicT`T#+xawMr!VM!HwL*w}R=5=V8mS}E2 zBuW-WiXD%9F%lSaAR5{h0ci?e)-5dd!W`X`gB&uiT4-L-%lNK32=`mCpBrKXqOnfg z&FfD1*4M}N{xG|A;8l}WgB`KOtijL;hD9^D#koh3IEK%5WFnQ;4@Wmoi>*yK+8WET zZsrmyO_Ez5lo!Tib6GaU!3VHkvmArgU{8tFtW#bFr2@|LT&O1C1d5HFop(j=N2W;%##b{mms|=DlzwZ>DD4RoIwSuYAPYWpy?4J&qDh58V#*{+@x=lMq=*;KVY5c6qXTVQy4e z1H#8hW0^tQ77#-A^O>l&UELzlmidwPm9pf9A~k}^A?y1D_li7ZzN8Fsi01Mza+?%y)mjHNKoc%NsBdvyGlh7P4Z>R~P`Cq}9&nn?_T&W$noG5uFoXK51F7T-aGph$@@*AG(SA?A2jZHG=ynFIm@N_QgXAl1>U5DRaRhPZLKHVc%&vSo98{RK<0Wb)hh9 z*8p@Go;gc5*WN`_H|{WJg}gomLp9_=^|PSgEbCdUT8xo>do4jwp1LCtFe=Ec9gGi6 z!AMx!3Q2%vmR#F~$ug`2YfUK*kF5@n;Q)F;&(FgPWb=f)#gnlyHi{P<&KH6~{M}&@ z_Lz?kYA|3}h&^U2)q~^_<;V{W9KpG_VR^1Fm~^r zh-iAOJ%$$&8N{bA=1bQ^4EWy?VYofUVd()}(sYaz@Ik88dO|SSng-h1S&^xBG>Q!# zq>#w#i6lEB*@i$O(@A!85*hp%nBR0kh9G1Y-J9+FQ*060V?u?(C_0fC6BA<cRbcckkT3b+fXf zyzIvH(!Z`EXV~&6VTg?8J6tIWRZ=X3y9_x1-svr`lLk$Rwf_0l&`D!rTmJid~CAgC@VOL9I4k gW%SF+70Bg=2)MyAn7*E_j<%Mj22@>barbTb2WX*yxc~qF literal 1364 zcmZ?wbhEHblxC1-xN6UE^UAFc=dQhZ_u=u8)8}mB&t^6K`}gnLqv!k0!oPg|_CCMw z$B&g}1vX&*m*IpdvmCZ+cAj8(fVBfj2yyd*I7_O#{iK74xe?A4d+_ny6Y zeJrZ<)th&hvs{4OJ>G~=6A3Z-7ly`pG z^1nZRe*f`vr?&6=kDqV#F8KBP_ru389?oC4Uq9&irR)Fx{JDSl)b|gceth_J^Zd0x zfByFCx_tQfd9O|M|NsAQ-+Qe1pWDwhB-q(8z|~04fSHkjfkE*n3o93cJ%bLA4fLcm z0|VRt1M>?sSXP+r4coLmkg+2`V?jfQhuci&G?h*TuALfROpIm2_H9vo8!hXzd2)n? z7i*T?gar#C57*qRm8h-bWPW0-%*n07$|ucZ$Nz+L%Jl^Ydu4_B1R5HY zTlgiV1rF>A*pSfQEunvEgQ3!q1|G$V9~=z{#~7K#Emp*wELz$<#U?1u-~#tSMtMD! z0s#eu#pm~RYgO)A5c%mD^E{8qTA{xjuJUwl)brT;;qvn<+jqiZo@m{3azlQoyg_hQq zP`^$eG=q7-VOnTUJYxI2hQ>NJ1^Ut0$dun)L zRBM?1l7)+OR<6?FUS-d>+?LOW&C1GPhk+Fvs#92i!7Kvwqa!fKS{&KXA-t&bL=K<5 z!E)inE5nxd&R5gUb=vpfeSo9hWJ~+LgtKw{`X4N6Zmhojes6ro&iB8Bof_(zTl}n? z(L4w-H4GYZOc&l?$u_IMz^@_Zyl_>RFY~FlMfMLil)q`6aXxKb(%HDlJ7p}={rY#u soU8eF_Ui9S8$JGpmWH}2#m=s7#r8^t2@@wN)WrcKZ00QP>5dH60HaAu3jhEB diff --git a/phpBB/styles/prosilver/theme/images/topic_unread_locked.gif b/phpBB/styles/prosilver/theme/images/topic_unread_locked.gif index 0a9768ba7d2d0587c03dc6c432418c22a4b26f6c..177dae74f4b6d0c96b0d9fb876d20a9c57a8269f 100644 GIT binary patch literal 2601 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 literal 719 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 diff --git a/phpBB/styles/prosilver/theme/images/topic_unread_mine.gif b/phpBB/styles/prosilver/theme/images/topic_unread_mine.gif index 4ca8492e74d51a5b2b74a43c1ecfc286ebb9a418..fd16eeedef6a5427ac59a135cd000d7cf26c7049 100644 GIT binary patch literal 2622 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 literal 678 zcmV;X0$Ke>Nk%w1VH*G&0M!5h`1$$iyT;<==-!s7&ViQGtGU2DT*zE^_~Yp2=x|{r&y$ z@$=`>*ZTYW`0(=QvAxbbU-qZE)JkjGW`e;$U&2Rak1a&%?Cs4k}7~$PmNFjy!pKNSr7Uf(QmWL{QLi!UqHr1{OHXL9(RDk}X=~XfYzk z4j%y|NOS0+rU!~RCEE1RQGtWQko$ND9ZIw)Q5`TPkbt0Rgwqi@aXuZE2=+Gf2;lqR@ zZFr_CfC?6a5lcP{fQ5+wH;7D_8R7+i&!9sCcoD*f&s0MQWKf{OM+MKKM_2G+LctAa zPY5^&VCE2u3cy*gII|&!1Kd!=U|6uBH5%G$4rD+LCxU?tB?iP`5MxUQ8_3}lIdY>% Mh653tfC&NsJ8&sL3IG5A From 3e73413982dfa247c039f4c8a82b34d2c7483c2c Mon Sep 17 00:00:00 2001 From: hanakin Date: Mon, 23 Jan 2017 21:59:00 -0500 Subject: [PATCH 1488/1676] [ticket/15037]a attempt to fix stupid test issue PHPBB3-15037 --- phpBB/develop/test.gif | Bin 0 -> 807 bytes tests/functional/fileupload_remote_test.php | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 phpBB/develop/test.gif diff --git a/phpBB/develop/test.gif b/phpBB/develop/test.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd29009a65a4c35c56a9c296731e1ae8650fd789 GIT binary patch literal 807 zcmc(ev9VP_3`6y2UO*edqfQtYvn%VZ`yDQgw4er)UO?E4 zG}?&ude0I+aCWBTh&{G)+1Z^EH2%S&yR*F@2^#-k(M{6WB}?Lfl40@y3ddLk8ZD?9 zg$ociBaL=%^s=MQ51jIZB#U7`y9^j^TNb@FZ#UFVO{XJzi2OxCoPcgy&uO1 reI`&k%nR$;Tn^vIGfg}7`&jset_error_prefix('') ->set_allowed_extensions(array('gif')) ->set_max_filesize(1000); - $file = $upload->handle_upload('files.types.remote', self::$root_url . 'styles/prosilver/theme/images/forum_read.gif'); + $file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/test.gif'); $this->assertEquals(0, sizeof($file->error)); $this->assertTrue(file_exists($file->get('filename'))); $this->assertTrue($file->is_uploaded()); @@ -113,8 +113,8 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); $upload->set_error_prefix('') ->set_allowed_extensions(array('gif')) - ->set_max_filesize(100); - $file = $upload->handle_upload('files.types.remote', self::$root_url . 'styles/prosilver/theme/images/forum_read.gif'); + ->set_max_filesize(1); + $file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/test.gif'); $this->assertEquals(1, sizeof($file->error)); $this->assertEquals('WRONG_FILESIZE', $file->error[0]); } From 6f7b92ae1023f958e4b9894950a412fadc52b802 Mon Sep 17 00:00:00 2001 From: hanakin Date: Mon, 23 Jan 2017 22:41:08 -0500 Subject: [PATCH 1489/1676] [ticket/15307] fix for good! PHPBB3-15037 --- phpBB/develop/test.gif | Bin 807 -> 1131 bytes tests/functional/fileupload_remote_test.php | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/develop/test.gif b/phpBB/develop/test.gif index cd29009a65a4c35c56a9c296731e1ae8650fd789..0dbc9b04592ed92fd894adab6bb29e2d61a7640c 100644 GIT binary patch literal 1131 zcmc&z>rc;N6hB_HMHmggp}8!Vre2scie|JXtVKmpYg4NoY$TJlW|B>_70oQR<5n)2 zv89@}NMQ{#PYiQSOQV>SkzYvm_&nc#!t?Izob$Pz?|0?uxTwWh3upoTB(m-qYt>q@ zmaQdM8DouFBi67r{qZv7%PQ3R@w!%Eq!<7RzjzfMm&7QcGfqEujE5 zpn-*DOq1hrPmK{{*cfuOs8o%LQ8r3W1)8Ep#0VQ9CknHyhQ%-&CTPT}AvGk1*brEu z8ek9&m5_xVh=C1gU}2e@Ay?yxDyx$72U=7jDy%}zE>xh&qRh$!_Yj3yB~fA}*h3zW ziEYFI{}2I(Pz^AMhDwY=2Z(_UXkd{`&b3kFu?V>!;SaQ^n1uhy$8n7!IKtU=WQ>$bt?K0~^rfPUNQ1MvX_f7=na9(4t~;ABW4; zySHn4Cv-7;S8=mm&@Oc^JGbh^;f~-rbV#0PcN0&C1NNZtIp9hN51v5vzg~nRcK-qe zTJi;ktU8kEi@h2=FQYNZJ_tIpjm3#z$r^j_Wh`{h?>l}<=Ye0R4r=*G6; zU*C>hI})0`BqOo7XZ4{eX`d_Rth?BDGHOHrk5}BYwkmAb*xBh7vz}JP>!Q;e2eu|u zCl#(az2*DXxU=zDxqDYV34c+WJ@fdAp@qE&7^fjS5>36Pw zPw@Qo#?ZjnjR?(MxD9*>Ri{2!{KuS$|l$KTsbv+bJ1{Q{i6p7%Qj8w)BLPw z5lOz3F-_f{&R54)wrt<+?|;#_skgkX{Yzf^?L99C!;*aT^eyTHa=i`*>kExRSI&wyF tz|j5R{UcAj9KZk0Zr}6m0TVAKXYROO&{0%z>_b<~=#oo`*&{|!^gp<+^g93m literal 807 zcmc(ev9VP_3`6y2UO*edqfQtYvn%VZ`yDQgw4er)UO?E4 zG}?&ude0I+aCWBTh&{G)+1Z^EH2%S&yR*F@2^#-k(M{6WB}?Lfl40@y3ddLk8ZD?9 zg$ociBaL=%^s=MQ51jIZB#U7`y9^j^TNb@FZ#UFVO{XJzi2OxCoPcgy&uO1 reI`&k%nR$;Tn^vIGfg}7`&jfilesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); $upload->set_error_prefix('') ->set_allowed_extensions(array('gif')) - ->set_max_filesize(1000); + ->set_max_filesize(1100); $file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/test.gif'); $this->assertEquals(0, sizeof($file->error)); $this->assertTrue(file_exists($file->get('filename'))); @@ -113,7 +113,7 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); $upload->set_error_prefix('') ->set_allowed_extensions(array('gif')) - ->set_max_filesize(1); + ->set_max_filesize(100); $file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/test.gif'); $this->assertEquals(1, sizeof($file->error)); $this->assertEquals('WRONG_FILESIZE', $file->error[0]); From 8b6d043ca6b415be94e9e1517676e2e507e954c5 Mon Sep 17 00:00:00 2001 From: hanakin Date: Mon, 23 Jan 2017 23:08:52 -0500 Subject: [PATCH 1490/1676] [ticket/15037] try larger size limit PHPBB3-15037 --- tests/functional/fileupload_remote_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/fileupload_remote_test.php b/tests/functional/fileupload_remote_test.php index 09c123fa7b..88f8999005 100644 --- a/tests/functional/fileupload_remote_test.php +++ b/tests/functional/fileupload_remote_test.php @@ -100,7 +100,7 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); $upload->set_error_prefix('') ->set_allowed_extensions(array('gif')) - ->set_max_filesize(1100); + ->set_max_filesize(2000); $file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/test.gif'); $this->assertEquals(0, sizeof($file->error)); $this->assertTrue(file_exists($file->get('filename'))); From a03047da5b0f640d4428a74012453df3dfa4f070 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 24 Jan 2017 21:47:20 +0100 Subject: [PATCH 1491/1676] [ticket/15044] Add module task for creating search index during install PHPBB3-15044 --- .../container/services_install_data.yml | 10 ++ phpBB/language/en/install.php | 7 +- .../install_data/task/create_search_index.php | 134 ++++++++++++++++++ 3 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 phpBB/phpbb/install/module/install_data/task/create_search_index.php diff --git a/phpBB/config/installer/container/services_install_data.yml b/phpBB/config/installer/container/services_install_data.yml index df63d16d0d..5de00170e9 100644 --- a/phpBB/config/installer/container/services_install_data.yml +++ b/phpBB/config/installer/container/services_install_data.yml @@ -29,6 +29,16 @@ services: tags: - { name: install_data_install, order: 30 } + installer.install_data.create_search_index: + class: phpbb\install\module\install_data\task\create_search_index + arguments: + - '@config' + - '@installer.helper.container_factory' + - '%core.root_path%' + - '%core.php_ext%' + tags: + - { name: install_data_install, order: 40 } + installer.module.data_install_collection: class: phpbb\di\ordered_service_collection arguments: diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 264377e494..c2e741c6a7 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -297,9 +297,10 @@ $lang = array_merge($lang, array( 'TASK_CREATE_TABLES' => 'Creating tables', // Install data - 'TASK_ADD_BOTS' => 'Registering bots', - 'TASK_ADD_LANGUAGES' => 'Installing available languages', - 'TASK_ADD_MODULES' => 'Installing modules', + 'TASK_ADD_BOTS' => 'Registering bots', + 'TASK_ADD_LANGUAGES' => 'Installing available languages', + 'TASK_ADD_MODULES' => 'Installing modules', + 'TASK_CREATE_SEARCH_INDEX' => 'Creating search index', // Install finish tasks 'TASK_INSTALL_EXTENSIONS' => 'Installing packaged extensions', diff --git a/phpBB/phpbb/install/module/install_data/task/create_search_index.php b/phpBB/phpbb/install/module/install_data/task/create_search_index.php new file mode 100644 index 0000000000..8a2f6aa1de --- /dev/null +++ b/phpBB/phpbb/install/module/install_data/task/create_search_index.php @@ -0,0 +1,134 @@ + + * @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\install\module\install_data\task; + +use phpbb\auth\auth; +use phpbb\db\driver\driver_interface; +use phpbb\event\dispatcher; +use phpbb\config\config; +use phpbb\install\helper\container_factory; +use phpbb\language\language; +use phpbb\search\fulltext_native; +use phpbb\user; + +class create_search_index extends \phpbb\install\task_base +{ + /** + * @var auth + */ + protected $auth; + + /** + * @var config + */ + protected $config; + + /** + * @var driver_interface + */ + protected $db; + + /** + * @var dispatcher + */ + protected $phpbb_dispatcher; + + /** + * @var language + */ + protected $language; + + /** + * @var user + */ + protected $user; + + /** + * @var string phpBB root path + */ + protected $phpbb_root_path; + + /** + * @var string PHP file extension + */ + protected $php_ext; + + /** + * Constructor + * + * @param config $config phpBB config + * @param container_factory $container Installer's DI container + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP file extension + */ + public function __construct(config $config, container_factory $container, + $phpbb_root_path, $php_ext) + { + $this->auth = $container->get('auth'); + $this->config = $config; + $this->db = $container->get('dbal.conn'); + $this->language = $container->get('language'); + $this->phpbb_dispatcher = $container->get('dispatcher'); + $this->user = $container->get('user'); + + parent::__construct(true); + } + + /** + * {@inheritdoc} + */ + public function run() + { + // Make sure fulltext native load update is set + $this->config->set('fulltext_native_load_upd', 1); + + $error = false; + $search = new fulltext_native( + $error, + $this->phpbb_root_path, + $this->php_ext, + $this->auth, + $this->config, + $this->db, + $this->user, + $this->phpbb_dispatcher + ); + + $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id + FROM ' . POSTS_TABLE; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); + } + $this->db->sql_freeresult($result); + } + + /** + * {@inheritdoc} + */ + static public function get_step_count() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function get_task_lang_name() + { + return 'TASK_CREATE_SEARCH_INDEX'; + } +} From 10dee52c18286524e62b10499120f7f8a4ca99e4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 24 Jan 2017 21:47:37 +0100 Subject: [PATCH 1492/1676] [ticket/15044] Make sure fulltext native min and max are numbers PHPBB3-15044 --- phpBB/phpbb/search/fulltext_native.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index 2071a973e5..73dcfce9a5 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -120,7 +120,7 @@ class fulltext_native extends \phpbb\search\base $this->phpbb_dispatcher = $phpbb_dispatcher; $this->user = $user; - $this->word_length = array('min' => $this->config['fulltext_native_min_chars'], 'max' => $this->config['fulltext_native_max_chars']); + $this->word_length = array('min' => (int) $this->config['fulltext_native_min_chars'], 'max' => (int) $this->config['fulltext_native_max_chars']); /** * Load the UTF tools From f2bc4a99778cfa269430614639a46cf62d6da65a Mon Sep 17 00:00:00 2001 From: hanakin Date: Tue, 24 Jan 2017 16:35:30 -0500 Subject: [PATCH 1493/1676] [ticket/15037] Update topic icons to retina PHPBB3-15037 --- phpBB/images/icons/misc/fire.gif | Bin 278 -> 1903 bytes phpBB/images/icons/misc/heart.gif | Bin 284 -> 2017 bytes phpBB/images/icons/misc/radioactive.gif | Bin 300 -> 2069 bytes phpBB/images/icons/misc/star.gif | Bin 267 -> 1914 bytes phpBB/images/icons/misc/thinking.gif | Bin 284 -> 1414 bytes phpBB/images/icons/smile/alert.gif | Bin 271 -> 1399 bytes phpBB/images/icons/smile/info.gif | Bin 294 -> 1572 bytes phpBB/images/icons/smile/mrgreen.gif | Bin 297 -> 2123 bytes phpBB/images/icons/smile/question.gif | Bin 296 -> 2056 bytes phpBB/images/icons/smile/redface.gif | Bin 2463 -> 4740 bytes phpBB/styles/prosilver/theme/content.css | 1 + 11 files changed, 1 insertion(+) diff --git a/phpBB/images/icons/misc/fire.gif b/phpBB/images/icons/misc/fire.gif index e436d6e8c92e58a071f22f8e4a3b522063ef8c1d..5899c9c8019ec5e48ba32eb20e09117f8b1fab5d 100644 GIT binary patch literal 1903 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 w9oxS*Hi8YIe;91j-@0YKTds)-v9sr literal 284 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 KXX$?#&%XhCav}`? literal 267 zcmV+m0rdVyNk%w1VGsZi0K^{vcB9MJ*Vwbi*=d`}#nIlYzR%X%;DDvZp1RdXh{5#r z_51w%>g()6gumkA;;6ydxX~C_J1Gbi9(e{1dT}TN6bu&!2N(eb11JO&32#zBL2&y6>06Q*Pa~J>s diff --git a/phpBB/images/icons/misc/thinking.gif b/phpBB/images/icons/misc/thinking.gif index fdec41bc19be535d35d909b032328a6b6ca867c4..23f226774ddd07caddf2e4fcdcd4c6ffcf11d279 100644 GIT binary patch literal 1414 zcmZ?wbhEHbRANwK_{P8x6Z}YpO@mB zn;Mvx7M7n8R#Oy{l9HO5npTvTQka`wl%HNxT~SkASzlk@5XUnum!}~~c11bE#(K8K zESu&+zy6x&^OG3v&SQJDnE(G4hX32xAFYu8zeDirX377%r0y)&`@dKD-+rBc2TlJS zv76EuKd&>jqp{$@mazLf((mml|98y&--*C~r=tFyN&0s_=l${We-}&tU9M|rXlQI~ zXliV1Y3u0g>zhBbd;YBc2|zG$^5n^r=FgfiW5)CuGiJ;LqM5Vi&Yd%N?%eeoHUYur z&0Du@*|KZrwp}~7@7c9|_pTkgckkG>Yv-QbyY}td_x4Qx-)rqZulE1FG4b!MnFkIW zIDGi<(W6I?9Xod7#EFX+FJ8KI>B^NW*REZ=ee1@D4Y zlZBCiA(uf1WB@2m7})Yz$Mm+1+gEKp(2|*)n3$Z|vVTX{Mj4)_)Id)m zZf+sZz|6v-9O7C~?S5nAKu~iB;^)>JRtPXT0RVp4u-iLH{7KFAV%s4YP6>BId8E{{Q#)&+lJ9e|-P; z^~>i^A3wZ*_x8=}S1(^YfA;jr<3|r4+`o7C&h1+_Z(P52^~&W-7cZPYclONbQzuUx zKX&xU;X?-x?BBN+m}z(J*uHJ+md%?sZdku=?V8oAR<2mSZ0VB4ixw`JKX2}w*|TQO zm_BXll*yAOPU!FJ?dk67>}YRmZE0?5Y^blRt*Nf6tSB!lEh#Q4EXdEx&B@Nn%t%j5 zO-W8lOo)$*jfswmj0g`44G9hk4Dk2!_3`%d^l*1`b#Zobbg;LxwXwFcv@ka_H8D0a zG|<=6)zQ|{)KFJbRZ&(_RFIdGm64W`ln@sa6%iH^6yWFM<>BVy?J(92r9%5EU*43lssCK@Lf8Zm2qBO?A%xW`_NDds1Nxos%*>s+=ljmRbM978cP9b`0w7=_ z6fg~YxPpPO%sjlzoLOeUEMFN>4n~x(hAUP_Rji4sw2rRC9IwHhctnh=^+|r=n_BOu zV*@?2k$%0Anfp2-w<+RA6YIvC$h;^pp*BoGp({Ky}J8OeP2nV;CY9rplVu256XK*$g1cODf@?&y~CI8Iu0-$D2g`GabJ$o)bA(3kzYM*o|k?dvSMdn@QdYA*|9_i`iL$iQcso6Y_ zRe&*IkyVuJZ-_#p4E@te;)?;ZBP)PacdNMMdno548_O!{GHzK?jvQY8^m*OO`!21A ziA|MtHBi6@-;QT*yHT4(ZN7xr<$|IbE9(A53m14FH0`XCaWCZR=j6<{brL${72Pt( zh%?kPs}aucwT^PLSY)3t^lIK&t%YXY9(QV8;y&!B>U=v-&jho(KBao2i!h6W{23`- zrAaBqHcN~BF1H2l$aXlkt}3Q*?T##b0l9R+7%!RXcdfRr=+fc#wYVkAJYjO`9DCoD zNz-_%^J!VUy}3R{(FXhueS?&osO5Ef0E#4VkJG0YWz1Fc?5PN@tKDb@gKiqz96q0}ftTFQywUnC=nFqIt*e^r6Ov zPziyM%ci-`93m%-8AgLCASW!85lQ5bAWC3(0F8*8b=MdO{5J&-AwjOX2TP>G!{q15{OtF_!ZEmxu7#EFo?L9?EcjZ ziAYc|3^R!s44ciiW3RUhXC1}h2m}HKi^t&cXe0w28N+}n95f@+N+=R~Mu_%(wcG;9G}i45TeAq<+0GGoL^G{c(C~a$`nUzG-^>sGe| zx~j6GyzJqF`}ayq?*4V>_Mf+kZx$66pDu*wImNBrAd$&Ik()IYtjY8bk}E1|S3Cf9MxK-=7a2 z*uT%md+(mzyLNi**uKrvW2^g5WVbD@n_V`MoHr5)P8%E@?APOQSd1Oo)@I$0YpvI; tUS$PYf-5b|%~mWo{o(s%OP4H025J6x^GuBA&M`vGHZ+)}kBs=ne*o;Ik>mgX literal 271 zcmV+q0r37uNk%w1VGsZi0K^{vbdjm#Gc2q|J&Z^5nGyhi$A(dH;4Gd;!(eDU zz)umGL1+X70s#$c6apd=aDD-30fHVDVgeKe8;t=~mKz0y5)dAg8yf=yp_(2L5)&C6 VtgWuB85J5B9JRK$wHO*906Q;YecS*5 diff --git a/phpBB/images/icons/smile/info.gif b/phpBB/images/icons/smile/info.gif index d715ac7c750e8cfd179237b8d30de1ccc4c457f7..2b28d8c83a26b4a17545c74f79665784ba11ca89 100644 GIT binary patch literal 1572 zcmX|B2~?6<6#iXuL7UOC(z1fzrY1K)B?UD#T-q#`QrlDnG&4aFcQFUWrK!|bYtpev zt5K`bvdq158!a`;MBGI{5pY8VEghU`y62s9-@W%c-*>+I&Ur2eoUPC}5CDPs1VAse zd^4$BpZsDg`2~#f5~Nh@imEhEtg)a~qY`US7i#xhsI|OMYn4=IL$9+>sk3L)J22`U z)89B{ygh!cg?hh@TF@R@*dF_^gYtk$D`wJ5n2g7rX-}B+r=QbHKV5p(#VBK?ma(#4 z_FR3%zEv}Dr>ZBnhMil>&Z}kT)D9HXbw7N~DsEtxH1-xX_7^n`lr;7|Zt8#BGFaL= zT;9&9=ooqRfnUYsRWkY2^3x?~U=F_hG}_AIb@cKZ*uqA(u&Gzn+$ZYj7qs+=TKmOq z17aq7ggGb}7~u_$@K_undsH~c6?XGx`p0Jb$0Y*-$-snUh{GQq9piAvIXuBAPr&6* z4Dm(0F(GeU$R8Ju2}EN8@%V&TFd?20PI5%^LeZ3Ha#|>!5l_vCW~7sIi&N9H(=(Fk z*}0in$*g2fGB-arzc90~w6GwZUyvoq6h4%FJ51u*Yy;Tv=3-3scY)S{*0M)ye)4cFm9@lrH zv8fuMh1}_V4`!{X*$LzO??buT7XWy28`j7~S(ybZaMQ7_+ut{y?v|&gQfhkL<^)3t zSaVfPZ?}TKV(#s2T(DZwE?L}xG&CsuQ8MzeILBwX7n&cp4pLrSBo5qhsy%l$c zvHa!RPyOm?{)NXQxT3T?-=M;BukF|kD3`>ZhUV?ZJlu(0P{Gz?G-l%@i5hn|Gr?f|JuUJn#cjg4hgdaQX(j3iQQQbTCHn~}G zu1EZ^vs$Wn3DKaNeAwrm)qM@4C-r7+x5`<_6sJl;nYvb95(wG-Kv&!8cB(P6#UT5z zhx*-^n|f*hY(>Mz)eY*1qvGV*#x5odhYulAp#j98V3I93Sycx@g9)~vH_8>^8ipmF z4c;F|A$rCgIfjo5!J`SF-Cl@I3??QtER;yaL1RMClOixNwjho`4j^LW_tiEWg#HVm zhS-7*s{`n&CYDSgLQ$rBOz=o^E2t&f6p2DxnOPV^%@D{va0D8Tv@k&+F$gpUfrNew za4!UELm>oWJRF_BiODNl@GO-YhJnMQqoYlu%}vRaAUG0@M#B+ia5FO#Il?3&mPEzH zn2;h2Rw@4Da3n_HDZydXU@{51%83ggM^bG;5WXq`|E40h2mkI*UVPsWktAOWMebi= zW%=uurA3)^VSY|BJ2O2sDHaJQ1mk0T9(R;8GCVXm(BId~?qPL*?)vnR`JuC;{r$VP z*1ubtn;IM5zIk0=S6fqERr#vo<%{y?&&o>wdivyXNpaDij~+fKEV%#2z5L(va_|0j z=XTDmn>VgsyPBPqdFAq@UoU2)r=>DdlIg!BT}Y%Q#K*Jd;reh&-cvfQzuXOczYc`=IPVX)u(#W5Yh#T;TUqWw zS(uw45pYuzVwf^IN%-sl literal 294 zcmV+>0ondXNk%w1VGsZi0K^{vFLJAOrO#KC%IoXvgRaw;yW95m_PNa6`uh6m@%R!} zl4G3By3^{+-0JoD`_tm?{QdpJ(cjqI*ekB%hlkd#^aj5-k!qX zd!N7Y@$vuv|J&Z}Bn!t#lp+OK3j-o*;5J&+U!eBrE6b}S#5g}MSQ;HTdplUM{fx~0y7&6yF+fYN% zD3nU$dT3K<0s=H01059r00;wxfNCCu1_1y828$haUTgynhz$>mbZ8M#Y!-+UpMM?; s7#{=$G!H5X6m%X16C(jdKR!+^5)%sy2@nn!3@R-n5yF8gts@}-JHKv#mjD0& diff --git a/phpBB/images/icons/smile/mrgreen.gif b/phpBB/images/icons/smile/mrgreen.gif index 9cd2715824dad81420f7e1e21f2fc1b844f9ee2e..f6da47a1179dc596d49ae353d1ffb007a5dd2f30 100644 GIT binary patch literal 2123 zcmd^9`B#%?77kk=fwHf%eFTC5fh>TKm_QN|2!vo30)$19kN{yxNcfb1plpReK|nzf zP!UC@2qRR)iYUuO1WFaRqA<>Ar?JY28|}2!sSM0``cKUL<-Yg6_dL&eo^$SvijEA$ zix3b5BW$)I?Hqip zoqX(EJ)PY`99{7aUL+SEUz9frNhA@eA>P!`?KGkg8Oj^o4;ILx5kX@PP4 zP&N<8PTiTz!?V*v1^iu1v0rR)K%4~2%)zmRc)mQ0sSIY9Vi?hk^c2RPRB}Q>LUM{g zlu8!uVWySQgd(~qm!2hK=jREeSsb~NuiPt8C=_6!sJK)bTZN9T#?lUjuo{Axbp%co zj@J;#uL_Ip+Qn)O;kO3!+e6}yg~oRh;?9Ke&yx6Gh9^~$6B_6#jS)#LQKF_OX?09i z3sYXhRyJ{q+7pV~68Hm@)B$F~2tDa?RLWRP`Y1~{5tn(ISJa=FInK+z&dSwc_^I`U;^&_B|Qx5-cA%hfJ$RDyW^M%H*7WY&@-J3A5zSf!+p2Il5ySj zf*>yUJku4wT&%GK!b_izx4c){9Xhg;6*<40-FGj%Y<0G7{n_ViO|Je4qO6uu5qQW_ zxi*KGtn^h{uM71#yv}P!63kGAHDnF72KQrK!4o(f;$?mF(bM54Ep(;>OE{F(chcDW z4W#lSFx`b$^;aBmaOVX&7cRY+; z?jgVHKB&;>%{T|NBiJaJ2~`6_6riXk9%_u9#!dZZ%Gfn_vBKE(?86GEO}R1xrN6fl z3RGgq)kxwyRHYFKiig-z#8g9l@yp3Na!1$OT6cgvHQ&mkdLY~4;Q;*T0NE@?ou2#2A@ymvHyrB8tgL8TsrlPZ!q8kAFePo}yJ=~{K&kY>6=IFYi5 zA|<`Af!Ys@p^i2tcT*hF7KdCZnAl%u>*`%$uS zi;VPPwpM5(<5&>}%BvW`SbW%LH3gxoxiP-IAXf{qSy0h17Y zV6wtoAh|PbWq!$T5$QC`#tbuTOlhW0lU^XD-K9nEGynLEorb#R|KofzY%}fke7l<-)r63@dX369v#OtdQ2tXzwArgaG7*;`qG+V|f zQAv3vaq$@?xfyr~B0LOER1?(s1^H4?1gP`#!fDOin;)47D90t1+jlrX_LH-yl0fQ%Cu)wE4guwx# zN|H(7(jq^RZB`^iHV76F(CDI~qJW~n0EH?Gjm6{fXbcXG!})Jc_!kz-L6O>DUg)_6 z@jncjv@k;@D*$B*Ik1H(5-awCBm@GzMS}jsvMCS!hrZ3?4~L}kO$G{{HU| z?|=LCmw)~I)B3y3Tl#A4Gver^2f*p;s@k6s$N_|@>xg+C7tobUhgPkrZl&z|Wy-F@oh ziLTC$aoie<(`Gom8tv&$6bb!C#4qqSCc5kGYC&B}8cXM@d-sa@!U~gw@V{K(=Vg8w!DI8{E3^g(|(BC|p GyZ!^3j@#(~ literal 297 zcmV+^0oMLUNk%w1VGsZi0K^{vQ;|1TuS2r3vDew#WWrH@tz3cIX-sc2bjn+OeR67R zSbWoBmF#(l;%|-Sa%x~gQ%*TsT0~4tGDt%&Lp>@^RyE7b&uw>EOkXXWn2}vbDnK+N zR6;2L00960|J&ZI+%+~MrhpC61h}sS2dWyiJ39R8g}J=&9PgwC~ZPS zE-Oj7PI4KN%WN1lgBgaoVvNgBIpdt3{U^@*ywCG}-|zQ*KA-3Fd7k&{a^BeziG~0W zV51Vy3U54$Yt+Uy>fm1Wz&Jm?Q8 z>JNW3Kq`F~S^Az-HW>9}FsgirTs{<2F+?n<#XX}XRnt;yhSO_l$#ox+>c%qaKiqB@ z%WfFWeleE%oSycap4T+?Thqkd*OT{}C-U2v_gf|&wNDnbGs`;0E8ftbbxl@xPgQj@ zs(P5!-5+au81;SA4Sme2-kI9InY#Yjx_(xD|7_!XR^uT1)ex&~Xr^Oiwsn~OdSs!6 z#%ZQ4w90an*F~G|9OY2Q*!}eRzKMl?I%jBVp_jhcH7V$x6!c69dp`=_Gx*ex!hVM6 z9aBV`WQ|O5h8aBCG;eg8%Vcq;S)6eee`1z9#pW~FTsm7YIVYH&7mRbnjKx(3SHk2; zn0(0$dtr8Nkv-34b9gKce~!bOU*OLy2}bCTT5x>0H^|tcAePW2>|p3@Kw=q z{j>N@GDyP@k?cJ5)Th#!YZut#)p@&0Tx6$T?wk$+9dKOqbl6vA8VmbI(+QjRs}c~< zUo=7KeF`t}shVVi_NEl5Up7OVQU?#~86NLSN$4Iqo*ivH0Rq5pHQWkJ+_Mxa50*Nn zXWak}P|_;Ss%((GOfW z(0z3gx)Iz*{~9EK>?Vl55PrWQm<)i zbj<+-FjfwwPzuUZl?Qyp><|+gK^~+`CGEM3FOvi0D=k%?nJECHRS7Ne$9l|wH_4Gh19l$1iWrhi$hB>qS&CY{bdsooW2U#*O7 z@{is#f_+e1P_65&NNGN$6M@|SVIuhPrOeEe7vwzc8*1NtJ9QyND~(=6>Y^k=D1K>$ zSmny@-+v&y&S3h-2uH`SCmz!r_3`!BFH5+dYJU0qV02fm2TH{$?~*I#U7oj9{hYd6 zYoE_w20>xv-p<;ovj<%vcYzn#IY4)3?^SnCup^p;mYvq; z$OLrYO$-SffC&!8*+7KaSLc*kD!35>lNhzx?9vsJYw zTam*F;TRGcOb!pjMOu+=08Kw>C?6pF`z zcQMfc_$ZPM1OnY9fqrF?$%Fo_PuBeH5C$i+g(%Z6xAW!mr|m82=EnM(WL3Pfyd)9| z_&o070%v}X&6=H=W->lbO-|6q$3{Q=MH?9&8hk(SuD_4k+tc0kw(||8qrI)QrTO)% zrk9N`8lKnxSyx+A{j93;X+`;yveJ^r#gG1YSoGk2VL|@y_wsV@-udmV^IxGM!B|XCU;z5Y^=tk={^0lh)hm~M zeZ0Lcd3s!Qcl++bc~=)_Cr1Z+JJdN_8|$-HNXs)8=4Pe{I1FlHZ1m65h6bm;)jz2R r(FLD4eoROEsMe9g-yG7^P(OI!AN$qz?NwC)DJv-|?2(uKd1wCvfa8Hh literal 296 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 bTN^QPvQI7#J}M|vlTa?PdBo4l8}t7GN}vi( literal 2463 zcmeH{Ygm#A7RO)UMevSXOjc~r7#Ed%P|3VhqT!9u2#K`SvWup>0HAy<;P7i{opc5$eJOYWmUbk;gyG4%F#F*NskqRVTB(g6he}qA1+w8D#AaXNPe2f@0Hs(DR`q&uZL1EO}>Xl<}f0R zeJW-TXZEeb?K#A@j62pg+1yF3P<^)4?G_dKo zD-`QCc!&)Nc533?Ar_16g#iFyYHCW~|6l*B3D`o$q5k}^t-f4;S7$l`rq5yf2{gn5 zLV&iCY2{1+v>JdJf(#)u&pB#8#)_^U%XB_cXF^P=3^|7~McyEaR4l3GdT!*+33Z5} z55TLPzcXpp1&fj>`N0GE#qP-G%J7-$YBuGl$sUKcfkXGcPRQ$^up4U5p5JzqzE9Tp{fJerM_=^fOO(NNRRiPw50N9)K# zw>wS}<;2+$mpg+GF1TB{VL8!Y&zg0HR%RyX)gYRG2T=icN>lh}iIq?9IAxKz(FhA=oM7P{k_vddvv*n$YxZSPtVY$PJQmI7)HKfF+ zl?>XAcNmg7olW`O7`fExBMmwm78loZd%c2E9sk74ZAWvNJf9+ZM%r5+mncxK@ZRY3{6_j(TI0oo38(ICpN-~6clH+1BDw}= z#^qx|kfCH&6hv#=g{y(+4H%LdNfB|AeP(f&s(w2p;fG4_g zZ#Bl}ta1LPHB~EY<5h)j1vf`9L_?MP_5!(bbsh?nDLhz48qCaQIvWd&UT6(4lC=g0;m^pGWJA!)b3Um3fB_r^hg1D)EkruXMpN{oBDF#&!9M1Drfmr=8ClsBlVfjC%H{rk6ml zrpDB^%@{KoNK2%J9cyQ`P}>aRvEWdBTxJ=^>W{f7bLY8RIdeNIM3iJLD;{otnxMer zDEw0Tst$@*95lD*o+0QLhc6S~FC=-E$*!xo^kTaS>_LgSqy$MBIk(oXvjzqZXUYvCr=EE=pv#`LlVA`wwv}UE(;cAc(xzz3Q5m z>C=J?fcx7AC3XMod(M5A#N=jwRS!Y}e{SNtL&Z92Nv(SkKUf8JWpLg_l5{cM!IIc# z_`{jwQ%uUb1CcKAI30Fl!0x%mny;&LHk_ikK2=rxfa*x<4Q8#PCTznVAzT%lHnWqt zC!n5GkEq#IEu3y~SX71#T@oNAo$0TQu+7_AiipzdKiRkmhhN11wXe#8wl}YI^?#YV zGGKIfE Date: Tue, 24 Jan 2017 22:50:10 +0100 Subject: [PATCH 1494/1676] [ticket/15045] Fix user object instantiation in version_test PHPBB3-15045 --- tests/version/version_test.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/version/version_test.php b/tests/version/version_test.php index 698975bc72..abe51ef539 100644 --- a/tests/version/version_test.php +++ b/tests/version/version_test.php @@ -519,6 +519,11 @@ class phpbb_version_helper_test extends phpbb_test_case */ public function test_get_update_on_branch($current_version, $versions, $expected) { + global $phpbb_root_path, $phpEx; + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $version_helper = $this ->getMockBuilder('\phpbb\version_helper') ->setMethods(array( @@ -530,7 +535,7 @@ class phpbb_version_helper_test extends phpbb_test_case 'version' => $current_version, )), new \phpbb\file_downloader(), - new \phpbb\user('\phpbb\datetime'), + new \phpbb\user($lang, '\phpbb\datetime'), )) ->getMock() ; From f069e521dbbd6cbd99bbf6f32ea9afea5931d00e Mon Sep 17 00:00:00 2001 From: hanakin Date: Tue, 24 Jan 2017 17:15:41 -0500 Subject: [PATCH 1495/1676] [ticket/15037] Optimize what can be PHPBB3-15037 --- phpBB/images/icons/misc/fire.gif | Bin 1903 -> 1486 bytes .../theme/images/sticky_unread_locked.gif | Bin 2023 -> 2022 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/phpBB/images/icons/misc/fire.gif b/phpBB/images/icons/misc/fire.gif index 5899c9c8019ec5e48ba32eb20e09117f8b1fab5d..4adba205e5e607a63d9d872fc7a7c244275c4c89 100644 GIT binary patch delta 600 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 From f66594bf93ca2604be73ef094555af571a55ea9b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 25 Jan 2017 22:18:29 +0100 Subject: [PATCH 1496/1676] [ticket/15050] Use new file when new file already exists Instead of trying to diff the new file against a pre-existing file, we're just going to use the new file. It's impossible to know whether the pre-existing file is newer or older than the new file. As the system will rely on the files being in the "new" state it's better to simply use the file in "new" state. PHPBB3-15050 --- .../update_filesystem/task/diff_files.php | 77 ++++++++++++------- 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php index e3e6db6263..0c3658bd44 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php @@ -132,42 +132,63 @@ class diff_files extends task_base $file_contents = array(); // Handle the special case when user created a file with the filename that is now new in the core - $file_contents[0] = (file_exists($old_path . $filename)) ? file_get_contents($old_path . $filename) : ''; - - $filenames = array( - $this->phpbb_root_path . $filename, - $new_path . $filename - ); - - foreach ($filenames as $file_to_diff) + if (file_exists($old_path . $filename)) { - $file_contents[] = file_get_contents($file_to_diff); + $file_contents[0] = file_get_contents($old_path . $filename); - if ($file_contents[sizeof($file_contents) - 1] === false) + $filenames = array( + $this->phpbb_root_path . $filename, + $new_path . $filename + ); + + foreach ($filenames as $file_to_diff) + { + $file_contents[] = file_get_contents($file_to_diff); + + if ($file_contents[sizeof($file_contents) - 1] === false) + { + $this->iohandler->add_error_message(array('FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ', $files_to_diff)); + unset($file_contents); + throw new user_interaction_required_exception(); + } + } + + $diff = new \diff3($file_contents[0], $file_contents[1], $file_contents[2]); + unset($file_contents); + + // Handle conflicts + if ($diff->get_num_conflicts() !== 0) + { + $merge_conflicts[] = $filename; + } + + // Save merged output + $this->cache->put( + '_file_' . md5($filename), + base64_encode(implode("\n", $diff->merged_output())) + ); + + unset($diff); + } + else + { + $new_file_content = file_get_contents($new_path . $filename); + + if ($new_file_content === false) { $this->iohandler->add_error_message(array('FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ', $files_to_diff)); - unset($file_contents); + unset($new_file_content ); throw new user_interaction_required_exception(); } + + // Save new file content to cache + $this->cache->put( + '_file_' . md5($filename), + base64_encode($new_file_content) + ); + unset($new_file_content); } - $diff = new \diff3($file_contents[0], $file_contents[1], $file_contents[2]); - unset($file_contents); - - // Handle conflicts - if ($diff->get_num_conflicts() !== 0) - { - $merge_conflicts[] = $filename; - } - - // Save merged output - $this->cache->put( - '_file_' . md5($filename), - base64_encode(implode("\n", $diff->merged_output())) - ); - - unset($diff); - $progress_count++; $this->iohandler->set_progress('UPDATE_FILE_DIFF', $progress_count); From 66b0fe3b5d982220e593e945a71e95b3283ac4a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Wed, 25 Jan 2017 15:48:39 -0500 Subject: [PATCH 1497/1676] [ticket/15047] No index name length check for mssql --- phpBB/phpbb/db/tools/mssql.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php index a132832005..254599444d 100644 --- a/phpBB/phpbb/db/tools/mssql.php +++ b/phpBB/phpbb/db/tools/mssql.php @@ -524,8 +524,6 @@ class mssql extends tools { $statements = array(); - $this->check_index_name_length($table_name, $index_name); - $statements[] = 'CREATE UNIQUE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])'; return $this->_sql_run_sql($statements); @@ -538,8 +536,6 @@ class mssql extends tools { $statements = array(); - $this->check_index_name_length($table_name, $index_name); - // remove index length $column = preg_replace('#:.*$#', '', $column); From b52ee87df8add5666b6fbe7b30bbe9ede9a30371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Wed, 25 Jan 2017 16:23:59 -0500 Subject: [PATCH 1498/1676] [ticket/15047] Don't attempt to drop primary keys --- phpBB/phpbb/db/tools/mssql.php | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php index 254599444d..d4128f6bcd 100644 --- a/phpBB/phpbb/db/tools/mssql.php +++ b/phpBB/phpbb/db/tools/mssql.php @@ -713,6 +713,7 @@ class mssql extends tools AND cols.object_id = ix.object_id WHERE ix.object_id = object_id('{$table_name}') AND cols.name = '{$column_name}' + AND ix.is_primary_key = 0 AND ix.is_unique = " . ($unique ? '1' : '0'); } From c53054f2b7bb83a5b3ec39f310c8ea37bffa95ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Wed, 25 Jan 2017 16:27:59 -0500 Subject: [PATCH 1499/1676] [ticket/15047] Use brackets due to keyword usage --- phpBB/phpbb/db/tools/mssql.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php index d4128f6bcd..3518fb416b 100644 --- a/phpBB/phpbb/db/tools/mssql.php +++ b/phpBB/phpbb/db/tools/mssql.php @@ -477,7 +477,7 @@ class mssql extends tools { $statements = array(); - $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name; + $statements[] = 'DROP INDEX [' . $table_name . '].[' . $index_name . ']'; return $this->_sql_run_sql($statements); } From fae78b4c011de598e4e05e26ff3129610ae087a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Wed, 25 Jan 2017 16:45:04 -0500 Subject: [PATCH 1500/1676] [ticket/15047] Do not set default for identity cols --- phpBB/phpbb/db/tools/mssql.php | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php index 3518fb416b..81e7424136 100644 --- a/phpBB/phpbb/db/tools/mssql.php +++ b/phpBB/phpbb/db/tools/mssql.php @@ -597,7 +597,7 @@ class mssql extends tools // Change the column $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql']; - if (!empty($column_data['default'])) + if (!empty($column_data['default']) && !$this->mssql_is_column_identity($table_name, $column_name)) { // Add new default value constraint $statements[] = 'ALTER TABLE [' . $table_name . '] ADD CONSTRAINT [DF_' . $table_name . '_' . $column_name . '_1] ' . $column_data['default'] . ' FOR [' . $column_name . ']'; @@ -674,6 +674,37 @@ class mssql extends tools return $statements; } + /** + * Checks to see if column is an identity column + * + * Identity columns cannot have defaults set for them. + * + * @param string $table_name + * @param string $column_name + * @return bool true if identity, false if not + */ + protected function mssql_is_column_identity($table_name, $column_name) + { + if ($this->mssql_is_sql_server_2000()) + { + // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx + // Deprecated in SQL Server 2005 + $sql = "SELECT COLUMNPROPERTY(object_id('{$table_name}'), '{$column_name}', 'IsIdentity') AS is_identity"; + } + else + { + $sql = "SELECT is_identity FROM sys.columns + WHERE object_id = object_id('{$table_name}') + AND name = '{$column_name}'"; + } + + $result = $this->db->sql_query($sql); + $is_identity = $this->db->sql_fetchfield('is_identity'); + $this->db->sql_freeresult($result); + + return (bool)$is_identity; + } + /** * Get a list with existing indexes for the column * From 2416a743f51dd5b995bb2bf1d6316f347fa0000e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Thu, 26 Jan 2017 18:44:18 -0500 Subject: [PATCH 1501/1676] [ticket/15047] Reinstate length check for MSSQL 2000 --- phpBB/phpbb/db/tools/mssql.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php index 81e7424136..d31aa2ba0b 100644 --- a/phpBB/phpbb/db/tools/mssql.php +++ b/phpBB/phpbb/db/tools/mssql.php @@ -524,6 +524,11 @@ class mssql extends tools { $statements = array(); + if ($this->is_sql_server_2000()) + { + $this->check_index_name_length($table_name, $index_name); + } + $statements[] = 'CREATE UNIQUE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])'; return $this->_sql_run_sql($statements); @@ -536,6 +541,11 @@ class mssql extends tools { $statements = array(); + if ($this->is_sql_server_2000()) + { + $this->check_index_name_length($table_name, $index_name); + } + // remove index length $column = preg_replace('#:.*$#', '', $column); @@ -702,7 +712,7 @@ class mssql extends tools $is_identity = $this->db->sql_fetchfield('is_identity'); $this->db->sql_freeresult($result); - return (bool)$is_identity; + return (bool) $is_identity; } /** From b5ed02d03c2a28e01e68c9f52fc9044fae2de05c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 27 Jan 2017 08:40:35 +0100 Subject: [PATCH 1502/1676] [ticket/15050] Remove extra whitespace PHPBB3-15050 --- .../install/module/update_filesystem/task/diff_files.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php index 0c3658bd44..1792a3b723 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php @@ -172,9 +172,9 @@ class diff_files extends task_base } else { - $new_file_content = file_get_contents($new_path . $filename); + $new_file_content = file_get_contents($new_path . $filename); - if ($new_file_content === false) + if ($new_file_content === false) { $this->iohandler->add_error_message(array('FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ', $files_to_diff)); unset($new_file_content ); From f47d2441518e0608b87749ee2cee819d5d0644bb Mon Sep 17 00:00:00 2001 From: Saeed Hubaishan Date: Mon, 30 Jan 2017 07:39:25 +0300 Subject: [PATCH 1503/1676] [ticket/14975] add missing .rtl [ticket/14975] add missing .rtl and resolve conflict [PHPBB3-14975] --- phpBB/styles/prosilver/theme/bidi.css | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 78ecb1e6b6..3268c71515 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -13,7 +13,7 @@ text-align: left; } -p.jumpbox-return { +.rtl p.jumpbox-return { float: right; } @@ -122,7 +122,7 @@ p.jumpbox-return { float: left; } -.jumpbox .dropdown-contents a { +.rtl .jumpbox .dropdown-contents a { margin-right: 0px; margin-left: 20px; } @@ -270,11 +270,6 @@ p.jumpbox-return { margin-right: 0; } -.rtl .topic-poster { - float: right; - padding-left: 0.5em; -} - /* Action Bar styles ---------------------------------------- */ .rtl .action-bar .button { From 80ecad5cf922527b976680d570041bd47f888d5d Mon Sep 17 00:00:00 2001 From: Vinny Date: Wed, 1 Feb 2017 02:34:01 -0300 Subject: [PATCH 1504/1676] [ticket/15062] Update to Rhea version the CSS files PHPBB3-15062 --- phpBB/adm/style/admin.css | 2 +- phpBB/styles/prosilver/theme/stylesheet.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index bcf01fe597..d46530700f 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -1,4 +1,4 @@ -/* phpBB 3.1 Admin Style Sheet +/* phpBB 3.2 Admin Style Sheet ------------------------------------------------------------------------ Original author: subBlue ( http://www.subblue.com/ ) Copyright (c) phpBB Limited diff --git a/phpBB/styles/prosilver/theme/stylesheet.css b/phpBB/styles/prosilver/theme/stylesheet.css index f235f6030e..1faab8bbd2 100644 --- a/phpBB/styles/prosilver/theme/stylesheet.css +++ b/phpBB/styles/prosilver/theme/stylesheet.css @@ -1,6 +1,6 @@ /* phpBB3 Style Sheet -------------------------------------------------------------- - Style name: prosilver (the default phpBB 3.1.x style) + Style name: prosilver (the default phpBB 3.2.x style) Based on style: Original author: Tom Beddard ( http://www.subblue.com/ ) Modified by: phpBB Limited ( https://www.phpbb.com/ ) From f23d9bf2e0886498a3d9d5bb0a800d663b795e61 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 5 Feb 2017 21:47:31 +0100 Subject: [PATCH 1505/1676] [ticket/15068] Add template vars retrieval from the template object PHPBB3-15068 --- phpBB/phpbb/template/base.php | 29 ++++++++++++++++ phpBB/phpbb/template/context.php | 57 +++++++++++++++++++++++++++++++ phpBB/phpbb/template/template.php | 24 +++++++++++++ 3 files changed, 110 insertions(+) diff --git a/phpBB/phpbb/template/base.php b/phpBB/phpbb/template/base.php index 9a40702ba8..e84aef6abe 100644 --- a/phpBB/phpbb/template/base.php +++ b/phpBB/phpbb/template/base.php @@ -104,6 +104,27 @@ abstract class base implements template return $this; } + /** + * {@inheritdoc} + */ + public function retrieve_vars(array $vararray) + { + $result = array(); + foreach ($vararray as $varname) + { + $result[$varname] = $this->retrieve_var($varname); + } + return $result; + } + + /** + * {@inheritdoc} + */ + public function retrieve_var($varname) + { + return $this->context->retrieve_var($varname); + } + /** * {@inheritdoc} */ @@ -124,6 +145,14 @@ abstract class base implements template return $this; } + /** + * {@inheritdoc} + */ + public function retrieve_block_vars($blockname, array $vararray) + { + return $this->context->retrieve_block_vars($blockname, $vararray); + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 4ee48205c8..0e5f3287aa 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -86,6 +86,17 @@ class context return true; } + /** + * Retreive a single scalar value from a single key. + * + * @param string $varname Variable name + * @return mixed Variable value, or null if not set + */ + public function retrieve_var($varname) + { + return isset($this->rootref[$varname]) ? $this->rootref[$varname] : null; + } + /** * Returns a reference to template data array. * @@ -263,6 +274,52 @@ class context return true; } + /** + * Retrieve key variable pairs from the specified block + * + * @param string $blockname Name of block to retrieve $vararray from + * @param array $vararray An array of variable names + * @return array of hashes with variable name as key and retrieved value or null as value + */ + public function retrieve_block_vars($blockname, array $vararray) + { + // For nested block, $blockcount > 0, for top-level block, $blockcount == 0 + $blocks = explode('.', $blockname); + $blockcount = sizeof($blocks) - 1; + + $block = $this->tpldata; + for ($i = 0; $i <= $blockcount; $i++) + { + if (($pos = strpos($blocks[$i], '[')) !== false) + { + $name = substr($blocks[$i], 0, $pos); + + if (strpos($blocks[$i], '[]') === $pos) + { + $index = sizeof($block[$name]) - 1; + } + else + { + $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); + } + } + else + { + $name = $blocks[$i]; + $index = sizeof($block[$name]) - 1; + } + $block = $block[$name]; + $block = $block[$index]; + } + + $result = array(); + foreach ($vararray as $varname) + { + $result[$varname] = isset($block[$varname]) ? $block[$varname] : null; + } + return $result; + } + /** * Change already assigned key variable pair (one-dimensional - single loop entry) * diff --git a/phpBB/phpbb/template/template.php b/phpBB/phpbb/template/template.php index 041ecb12e4..183999d5f4 100644 --- a/phpBB/phpbb/template/template.php +++ b/phpBB/phpbb/template/template.php @@ -127,6 +127,22 @@ interface template */ public function append_var($varname, $varval); + /** + * Retrieve multiple template values + * + * @param array $vararray An array with variable names + * @return array A hash of variable name => value pairs (value is null if not set) + */ + public function retrieve_vars(array $vararray); + + /** + * Retreive a single scalar value from a single key. + * + * @param string $varname Variable name + * @return mixed Variable value, or null if not set + */ + public function retrieve_var($varname); + /** * Assign key variable pairs from an array to a specified block * @param string $blockname Name of block to assign $vararray to @@ -143,6 +159,14 @@ interface template */ public function assign_block_vars_array($blockname, array $block_vars_array); + /** + * Retrieve variable values from an specified block + * @param string $blockname Name of block to retrieve $vararray from + * @param array $vararray An array with variable names + * @return array A hash of variable name => value pairs (value is null if not set) + */ + public function retrieve_block_vars($blockname, array $vararray); + /** * Change already assigned key variable pair (one-dimensional - single loop entry) * From 46a0cde544a85691a07005768c59b5674eb16072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Fri, 10 Feb 2017 15:17:06 -0500 Subject: [PATCH 1506/1676] [ticket/15058] Force browser to redownload stylesheets --- phpBB/styles/prosilver/theme/stylesheet.css | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/phpBB/styles/prosilver/theme/stylesheet.css b/phpBB/styles/prosilver/theme/stylesheet.css index 1faab8bbd2..45eb5b6fc9 100644 --- a/phpBB/styles/prosilver/theme/stylesheet.css +++ b/phpBB/styles/prosilver/theme/stylesheet.css @@ -7,15 +7,15 @@ -------------------------------------------------------------- */ -@import url("normalize.css"); -@import url("base.css"); -@import url("utilities.css"); -@import url("common.css"); -@import url("links.css"); -@import url("content.css"); -@import url("buttons.css"); -@import url("cp.css"); -@import url("forms.css"); -@import url("icons.css"); -@import url("colours.css"); -@import url("responsive.css"); +@import url("normalize.css?v=3.2"); +@import url("base.css?v=3.2"); +@import url("utilities.css?v=3.2"); +@import url("common.css?v=3.2"); +@import url("links.css?v=3.2"); +@import url("content.css?v=3.2"); +@import url("buttons.css?v=3.2"); +@import url("cp.css?v=3.2"); +@import url("forms.css?v=3.2"); +@import url("icons.css?v=3.2"); +@import url("colours.css?v=3.2"); +@import url("responsive.css?v=3.2"); From b0abf6df883487ffbd12d5410cd03a23fc6bd66c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 10 Feb 2017 23:29:11 +0100 Subject: [PATCH 1507/1676] [ticket/15079] Parse message before inserting it into drafts table PHPBB3-15079 --- phpBB/posting.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpBB/posting.php b/phpBB/posting.php index aa10059796..0920f63888 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -694,13 +694,16 @@ if ($save && $user->data['is_registered'] && $auth->acl_get('u_savedrafts') && ( { if (confirm_box(true)) { + $message_parser->message = $message; + $message_parser->parse($post_data['enable_bbcode'], ($config['allow_post_links']) ? $post_data['enable_urls'] : false, $post_data['enable_smilies'], $img_status, $flash_status, $quote_status, $config['allow_post_links']); + $sql = 'INSERT INTO ' . DRAFTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( 'user_id' => (int) $user->data['user_id'], 'topic_id' => (int) $topic_id, 'forum_id' => (int) $forum_id, 'save_time' => (int) $current_time, 'draft_subject' => (string) $subject, - 'draft_message' => (string) $message) + 'draft_message' => (string) $message_parser->message) ); $db->sql_query($sql); From b4821907b7f8acf84229f95018688636c8aad159 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 11 Feb 2017 11:19:46 +0100 Subject: [PATCH 1508/1676] [ticket/15083] Fix invalid emoji sizing in ACP & print view PHPBB3-15083 --- phpBB/adm/style/admin.css | 7 +++++++ phpBB/styles/prosilver/theme/print.css | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index d46530700f..2ad964e6bb 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -2691,3 +2691,10 @@ fieldset.permissions .padding { word-wrap: break-word; word-break: break-all; } + +.emoji { + min-height: 18px; + min-width: 18px; + height: 1em; + width: 1em; +} diff --git a/phpBB/styles/prosilver/theme/print.css b/phpBB/styles/prosilver/theme/print.css index a3295ac367..e1ddaca308 100644 --- a/phpBB/styles/prosilver/theme/print.css +++ b/phpBB/styles/prosilver/theme/print.css @@ -137,3 +137,10 @@ div.spacer { clear: both; } .skip_link { display: none; } .codebox p { display: none; } + +.emoji { + min-height: 18px; + min-width: 18px; + height: 1em; + width: 1em; +} From af028f8d72e552a5c9b5a65424d1c90c2b1a7ada Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 11 Feb 2017 11:34:03 +0100 Subject: [PATCH 1509/1676] [ticket/14979] Do not display underline for unread icon PHPBB3-14979 --- phpBB/styles/prosilver/theme/links.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index 6da14c9326..f6c24bfb7c 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -89,6 +89,10 @@ a.lastsubject:hover { text-decoration: underline; } +a.unread { + text-decoration: none; +} + /* Post body links */ .postlink { text-decoration: none; From 17f8c53ef3c1101d8f90752b70f78a4f5c1c9ae2 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 12 Feb 2017 13:46:37 +0100 Subject: [PATCH 1510/1676] [ticket/15087] Optimize creation of metadata objects by caching Code for [ticket/14919] Do not directly use globals in acp_extensions for phpbb 3.2. PHPBB3-15087 --- phpBB/includes/acp/acp_extensions.php | 144 +++++++++++++------------- 1 file changed, 71 insertions(+), 73 deletions(-) diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index e915fa8c75..e01d95167a 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -25,35 +25,36 @@ if (!defined('IN_PHPBB')) class acp_extensions { var $u_action; + var $tpl_name; + var $page_title; - private $db; private $config; private $template; private $user; - private $cache; private $log; private $request; + private $phpbb_dispatcher; + private $ext_manager; function main() { // Start the page - global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpbb_log, $cache, $phpbb_dispatcher; + global $config, $user, $template, $request, $phpbb_extension_manager, $phpbb_root_path, $phpbb_log, $phpbb_dispatcher; - $this->db = $db; $this->config = $config; $this->template = $template; $this->user = $user; - $this->cache = $cache; $this->request = $request; $this->log = $phpbb_log; $this->phpbb_dispatcher = $phpbb_dispatcher; + $this->ext_manager = $phpbb_extension_manager; - $user->add_lang(array('install', 'acp/extensions', 'migrator')); + $this->user->add_lang(array('install', 'acp/extensions', 'migrator')); $this->page_title = 'ACP_EXTENSIONS'; - $action = $request->variable('action', 'list'); - $ext_name = $request->variable('ext_name', ''); + $action = $this->request->variable('action', 'list'); + $ext_name = $this->request->variable('ext_name', ''); // What is a safe limit of execution time? Half the max execution time should be safe. $safe_time_limit = (ini_get('max_execution_time') / 2); @@ -75,13 +76,13 @@ class acp_extensions extract($this->phpbb_dispatcher->trigger_event('core.acp_extensions_run_action', compact($vars))); // Cancel action - if ($request->is_set_post('cancel')) + if ($this->request->is_set_post('cancel')) { $action = 'list'; $ext_name = ''; } - if (in_array($action, array('enable', 'disable', 'delete_data')) && !check_link_hash($request->variable('hash', ''), $action . '.' . $ext_name)) + if (in_array($action, array('enable', 'disable', 'delete_data')) && !check_link_hash($this->request->variable('hash', ''), $action . '.' . $ext_name)) { trigger_error('FORM_INVALID', E_USER_WARNING); } @@ -89,7 +90,7 @@ class acp_extensions // If they've specified an extension, let's load the metadata manager and validate it. if ($ext_name) { - $md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $phpbb_root_path); + $md_manager = $this->ext_manager->create_extension_metadata_manager($ext_name); try { @@ -114,12 +115,12 @@ class acp_extensions 'force_unstable' => $force_unstable, )); - confirm_box(false, $user->lang('EXTENSION_FORCE_UNSTABLE_CONFIRM'), $s_hidden_fields); + confirm_box(false, $this->user->lang('EXTENSION_FORCE_UNSTABLE_CONFIRM'), $s_hidden_fields); } else { - $config->set('extension_force_unstable', false); - trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + $this->config->set('extension_force_unstable', false); + trigger_error($this->user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); } break; @@ -127,17 +128,17 @@ class acp_extensions default: if (confirm_box(true)) { - $config->set('extension_force_unstable', true); - trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + $this->config->set('extension_force_unstable', true); + trigger_error($this->user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); } - $this->list_enabled_exts($phpbb_extension_manager); - $this->list_disabled_exts($phpbb_extension_manager); - $this->list_available_exts($phpbb_extension_manager); + $this->list_enabled_exts(); + $this->list_disabled_exts(); + $this->list_available_exts(); $this->template->assign_vars(array( 'U_VERSIONCHECK_FORCE' => $this->u_action . '&action=list&versioncheck_force=1', - 'FORCE_UNSTABLE' => $config['extension_force_unstable'], + 'FORCE_UNSTABLE' => $this->config['extension_force_unstable'], 'U_ACTION' => $this->u_action, )); @@ -147,28 +148,28 @@ class acp_extensions case 'enable_pre': if (!$md_manager->validate_dir()) { - trigger_error($user->lang['EXTENSION_DIR_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($this->user->lang['EXTENSION_DIR_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } if (!$md_manager->validate_enable()) { - trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($this->user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING); } - $extension = $phpbb_extension_manager->get_extension($ext_name); + $extension = $this->ext_manager->get_extension($ext_name); if (!$extension->is_enableable()) { - trigger_error($user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($this->user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING); } - if ($phpbb_extension_manager->is_enabled($ext_name)) + if ($this->ext_manager->is_enabled($ext_name)) { redirect($this->u_action); } $this->tpl_name = 'acp_ext_enable'; - $template->assign_vars(array( + $this->template->assign_vars(array( 'PRE' => true, 'L_CONFIRM_MESSAGE' => $this->user->lang('EXTENSION_ENABLE_CONFIRM', $md_manager->get_metadata('display-name')), 'U_ENABLE' => $this->u_action . '&action=enable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('enable.' . $ext_name), @@ -178,55 +179,55 @@ class acp_extensions case 'enable': if (!$md_manager->validate_dir()) { - trigger_error($user->lang['EXTENSION_DIR_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($this->user->lang['EXTENSION_DIR_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } if (!$md_manager->validate_enable()) { - trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($this->user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING); } - $extension = $phpbb_extension_manager->get_extension($ext_name); + $extension = $this->ext_manager->get_extension($ext_name); if (!$extension->is_enableable()) { - trigger_error($user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($this->user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING); } try { - while ($phpbb_extension_manager->enable_step($ext_name)) + while ($this->ext_manager->enable_step($ext_name)) { // Are we approaching the time limit? If so we want to pause the update and continue after refreshing if ((time() - $start_time) >= $safe_time_limit) { - $template->assign_var('S_NEXT_STEP', true); + $this->template->assign_var('S_NEXT_STEP', true); meta_refresh(0, $this->u_action . '&action=enable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('enable.' . $ext_name)); } } - $this->log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_ENABLE', time(), array($ext_name)); + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_EXT_ENABLE', time(), array($ext_name)); } catch (\phpbb\db\migration\exception $e) { - $template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($user)); + $this->template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($this->user)); } $this->tpl_name = 'acp_ext_enable'; - $template->assign_vars(array( + $this->template->assign_vars(array( 'U_RETURN' => $this->u_action . '&action=list', )); break; case 'disable_pre': - if (!$phpbb_extension_manager->is_enabled($ext_name)) + if (!$this->ext_manager->is_enabled($ext_name)) { redirect($this->u_action); } $this->tpl_name = 'acp_ext_disable'; - $template->assign_vars(array( + $this->template->assign_vars(array( 'PRE' => true, 'L_CONFIRM_MESSAGE' => $this->user->lang('EXTENSION_DISABLE_CONFIRM', $md_manager->get_metadata('display-name')), 'U_DISABLE' => $this->u_action . '&action=disable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('disable.' . $ext_name), @@ -234,38 +235,38 @@ class acp_extensions break; case 'disable': - if (!$phpbb_extension_manager->is_enabled($ext_name)) + if (!$this->ext_manager->is_enabled($ext_name)) { redirect($this->u_action); } - while ($phpbb_extension_manager->disable_step($ext_name)) + while ($this->ext_manager->disable_step($ext_name)) { // Are we approaching the time limit? If so we want to pause the update and continue after refreshing if ((time() - $start_time) >= $safe_time_limit) { - $template->assign_var('S_NEXT_STEP', true); + $this->template->assign_var('S_NEXT_STEP', true); meta_refresh(0, $this->u_action . '&action=disable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('disable.' . $ext_name)); } } - $this->log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_DISABLE', time(), array($ext_name)); + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_EXT_DISABLE', time(), array($ext_name)); $this->tpl_name = 'acp_ext_disable'; - $template->assign_vars(array( + $this->template->assign_vars(array( 'U_RETURN' => $this->u_action . '&action=list', )); break; case 'delete_data_pre': - if ($phpbb_extension_manager->is_enabled($ext_name)) + if ($this->ext_manager->is_enabled($ext_name)) { redirect($this->u_action); } $this->tpl_name = 'acp_ext_delete_data'; - $template->assign_vars(array( + $this->template->assign_vars(array( 'PRE' => true, 'L_CONFIRM_MESSAGE' => $this->user->lang('EXTENSION_DELETE_DATA_CONFIRM', $md_manager->get_metadata('display-name')), 'U_PURGE' => $this->u_action . '&action=delete_data&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('delete_data.' . $ext_name), @@ -273,75 +274,75 @@ class acp_extensions break; case 'delete_data': - if ($phpbb_extension_manager->is_enabled($ext_name)) + if ($this->ext_manager->is_enabled($ext_name)) { redirect($this->u_action); } try { - while ($phpbb_extension_manager->purge_step($ext_name)) + while ($this->ext_manager->purge_step($ext_name)) { // Are we approaching the time limit? If so we want to pause the update and continue after refreshing if ((time() - $start_time) >= $safe_time_limit) { - $template->assign_var('S_NEXT_STEP', true); + $this->template->assign_var('S_NEXT_STEP', true); meta_refresh(0, $this->u_action . '&action=delete_data&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('delete_data.' . $ext_name)); } } - $this->log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_PURGE', time(), array($ext_name)); + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_EXT_PURGE', time(), array($ext_name)); } catch (\phpbb\db\migration\exception $e) { - $template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($user)); + $this->template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($this->user)); } $this->tpl_name = 'acp_ext_delete_data'; - $template->assign_vars(array( + $this->template->assign_vars(array( 'U_RETURN' => $this->u_action . '&action=list', )); break; case 'details': // Output it to the template - $md_manager->output_template_data($template); + $md_manager->output_template_data($this->template); $meta = $md_manager->get_metadata('all'); if (isset($meta['extra']['version-check'])) { try { - $updates_available = $phpbb_extension_manager->version_check($md_manager, $request->variable('versioncheck_force', false), $this->config['extension_force_unstable'] ? 'unstable' : null); + $updates_available = $this->ext_manager->version_check($md_manager, $this->request->variable('versioncheck_force', false), $this->config['extension_force_unstable'] ? 'unstable' : null); - $template->assign_vars(array( + $this->template->assign_vars(array( 'S_UP_TO_DATE' => empty($updates_available), 'UP_TO_DATE_MSG' => $this->user->lang(empty($updates_available) ? 'UP_TO_DATE' : 'NOT_UP_TO_DATE', $md_manager->get_metadata('display-name')), )); foreach ($updates_available as $branch => $version_data) { - $template->assign_block_vars('updates_available', $version_data); + $this->template->assign_block_vars('updates_available', $version_data); } } catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); - $template->assign_vars(array( + $this->template->assign_vars(array( 'S_VERSIONCHECK_FAIL' => true, 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== 'VERSIONCHECK_FAIL') ? $message : '', )); } - $template->assign_var('S_VERSIONCHECK', true); + $this->template->assign_var('S_VERSIONCHECK', true); } else { - $template->assign_var('S_VERSIONCHECK', false); + $this->template->assign_var('S_VERSIONCHECK', false); } - $template->assign_vars(array( + $this->template->assign_vars(array( 'U_BACK' => $this->u_action . '&action=list', 'U_VERSIONCHECK_FORCE' => $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')), )); @@ -354,16 +355,15 @@ class acp_extensions /** * Lists all the enabled extensions and dumps to the template * - * @param $phpbb_extension_manager An instance of the extension manager * @return null */ - public function list_enabled_exts(\phpbb\extension\manager $phpbb_extension_manager) + public function list_enabled_exts() { $enabled_extension_meta_data = array(); - foreach ($phpbb_extension_manager->all_enabled() as $name => $location) + foreach ($this->ext_manager->all_enabled() as $name => $location) { - $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name); + $md_manager = $this->ext_manager->create_extension_metadata_manager($name); try { @@ -378,7 +378,7 @@ class acp_extensions try { $force_update = $this->request->variable('versioncheck_force', false); - $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); + $updates = $this->ext_manager->version_check($md_manager, $force_update, !$force_update); $enabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; @@ -426,16 +426,15 @@ class acp_extensions /** * Lists all the disabled extensions and dumps to the template * - * @param $phpbb_extension_manager An instance of the extension manager * @return null */ - public function list_disabled_exts(\phpbb\extension\manager $phpbb_extension_manager) + public function list_disabled_exts() { $disabled_extension_meta_data = array(); - foreach ($phpbb_extension_manager->all_disabled() as $name => $location) + foreach ($this->ext_manager->all_disabled() as $name => $location) { - $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name); + $md_manager = $this->ext_manager->create_extension_metadata_manager($name); try { @@ -448,7 +447,7 @@ class acp_extensions if (isset($meta['extra']['version-check'])) { $force_update = $this->request->variable('versioncheck_force', false); - $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); + $updates = $this->ext_manager->version_check($md_manager, $force_update, !$force_update); $disabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; @@ -496,18 +495,17 @@ class acp_extensions /** * Lists all the available extensions and dumps to the template * - * @param $phpbb_extension_manager An instance of the extension manager * @return null */ - public function list_available_exts(\phpbb\extension\manager $phpbb_extension_manager) + public function list_available_exts() { - $uninstalled = array_diff_key($phpbb_extension_manager->all_available(), $phpbb_extension_manager->all_configured()); + $uninstalled = array_diff_key($this->ext_manager->all_available(), $this->ext_manager->all_configured()); $available_extension_meta_data = array(); foreach ($uninstalled as $name => $location) { - $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name); + $md_manager = $this->ext_manager->create_extension_metadata_manager($name); try { @@ -520,7 +518,7 @@ class acp_extensions if (isset($meta['extra']['version-check'])) { $force_update = $this->request->variable('versioncheck_force', false); - $updates = $phpbb_extension_manager->version_check($md_manager, $force_update, !$force_update); + $updates = $this->ext_manager->version_check($md_manager, $force_update, !$force_update); $available_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); $available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; From 5266821e1b5b271e69b00d717b9e9b1f77b65b9f Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 12 Feb 2017 14:10:58 +0100 Subject: [PATCH 1511/1676] [ticket/15087] Optimize creation of metadata objects by caching Code for [ticket/14938] Inconsistency in ext_mgr all_available vs is_available for phpbb 3.2. PHPBB3-15087 --- phpBB/phpbb/extension/manager.php | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index b2b60aaa9b..22522d0785 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -431,25 +431,11 @@ class manager if ($file_info->isFile() && $file_info->getFilename() == 'composer.json') { $ext_name = $iterator->getInnerIterator()->getSubPath(); - $composer_file = $iterator->getPath() . '/composer.json'; - - // Ignore the extension if there is no composer.json. - if (!is_readable($composer_file) || !($ext_info = file_get_contents($composer_file))) - { - continue; - } - - $ext_info = json_decode($ext_info, true); $ext_name = str_replace(DIRECTORY_SEPARATOR, '/', $ext_name); - - // Ignore the extension if directory depth is not correct or if the directory structure - // does not match the name value specified in composer.json. - if (substr_count($ext_name, '/') !== 1 || !isset($ext_info['name']) || $ext_name != $ext_info['name']) + if ($this->is_available($ext_name)) { - continue; + $available[$ext_name] = $this->get_extension_path($ext_name, true); } - - $available[$ext_name] = $this->phpbb_root_path . 'ext/' . $ext_name . '/'; } } ksort($available); @@ -527,7 +513,15 @@ class manager */ public function is_available($name) { - return file_exists($this->get_extension_path($name, true)); + $md_manager = $this->create_extension_metadata_manager($name); + try + { + return $md_manager->get_metadata('all') && $md_manager->validate_enable(); + } + catch (\phpbb\extension\exception $e) + { + return false; + } } /** From d3a687df270268b4cbbe3ae0d10e8c4e2ae29235 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 12 Feb 2017 14:39:26 +0100 Subject: [PATCH 1512/1676] [ticket/15087] Optimize creation of metadata objects by caching Code for [ticket/15080] Save unneeded file loads for extension metadata for phpbb 3.2. PHPBB3-15087 --- phpBB/phpbb/extension/metadata_manager.php | 64 ++++++---------------- 1 file changed, 16 insertions(+), 48 deletions(-) diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index 348b3c2cdf..089f9a7a32 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -81,13 +81,11 @@ class metadata_manager */ public function get_metadata($element = 'all') { - $this->set_metadata_file(); - - // Fetch the metadata - $this->fetch_metadata(); - - // Clean the metadata - $this->clean_metadata_array(); + // Fetch and clean the metadata if not done yet + if ($this->metadata === array()) + { + $this->fetch_metadata_from_file(); + } switch ($element) { @@ -121,52 +119,32 @@ class metadata_manager } /** - * Sets the filepath of the metadata file + * Sets the path of the metadata file, gets its contents and cleans loaded file * * @throws \phpbb\extension\exception */ - private function set_metadata_file() + private function fetch_metadata_from_file() { $ext_filepath = $this->extension_manager->get_extension_path($this->ext_name); - $metadata_filepath = $this->phpbb_root_path . $ext_filepath . 'composer.json'; - - $this->metadata_file = $metadata_filepath; + $this->metadata_file = $this->phpbb_root_path . $ext_filepath . 'composer.json'; if (!file_exists($this->metadata_file)) { throw new \phpbb\extension\exception('FILE_NOT_FOUND', array($this->metadata_file)); } - } - /** - * Gets the contents of the composer.json file - * - * @return bool True if success, throws an exception on failure - * @throws \phpbb\extension\exception - */ - private function fetch_metadata() - { - if (!file_exists($this->metadata_file)) + if (!($file_contents = file_get_contents($this->metadata_file))) { - throw new \phpbb\extension\exception('FILE_NOT_FOUND', array($this->metadata_file)); + throw new \phpbb\extension\exception('FILE_CONTENT_ERR', array($this->metadata_file)); } - else + + if (($metadata = json_decode($file_contents, true)) === null) { - if (!($file_contents = file_get_contents($this->metadata_file))) - { - throw new \phpbb\extension\exception('FILE_CONTENT_ERR', array($this->metadata_file)); - } - - if (($metadata = json_decode($file_contents, true)) === null) - { - throw new \phpbb\extension\exception('FILE_JSON_DECODE_ERR', array($this->metadata_file)); - } - - array_walk_recursive($metadata, array($this, 'sanitize_json')); - $this->metadata = $metadata; - - return true; + throw new \phpbb\extension\exception('FILE_JSON_DECODE_ERR', array($this->metadata_file)); } + + array_walk_recursive($metadata, array($this, 'sanitize_json')); + $this->metadata = $metadata; } /** @@ -180,16 +158,6 @@ class metadata_manager $value = htmlspecialchars($value); } - /** - * This array handles the cleaning of the array - * - * @return array Contains the cleaned metadata array - */ - private function clean_metadata_array() - { - return $this->metadata; - } - /** * Validate fields * From 2e3d90e05b7b08f6df89b9e3a98b1716d52cf340 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 12 Feb 2017 18:33:06 +0100 Subject: [PATCH 1513/1676] [ticket/15087] Optimize creation of metadata objects by caching Caching is done in ext_manager, and metadata_manager is further simplified by reducing the number of parameters needed. Also, move template output function from metadata_manager to acp_extensions, where it belongs. PHPBB3-15087 --- phpBB/includes/acp/acp_extensions.php | 45 ++++++++++- phpBB/phpbb/console/command/update/check.php | 2 +- phpBB/phpbb/extension/manager.php | 33 +++++--- phpBB/phpbb/extension/metadata_manager.php | 85 ++++---------------- 4 files changed, 79 insertions(+), 86 deletions(-) diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index e01d95167a..8ce910c242 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -307,23 +307,23 @@ class acp_extensions case 'details': // Output it to the template - $md_manager->output_template_data($this->template); - $meta = $md_manager->get_metadata('all'); + $this->output_metadata_to_template($meta); + if (isset($meta['extra']['version-check'])) { try { $updates_available = $this->ext_manager->version_check($md_manager, $this->request->variable('versioncheck_force', false), $this->config['extension_force_unstable'] ? 'unstable' : null); - $this->template->assign_vars(array( + $this->template->assign_vars(array( 'S_UP_TO_DATE' => empty($updates_available), 'UP_TO_DATE_MSG' => $this->user->lang(empty($updates_available) ? 'UP_TO_DATE' : 'NOT_UP_TO_DATE', $md_manager->get_metadata('display-name')), )); foreach ($updates_available as $branch => $version_data) { - $this->template->assign_block_vars('updates_available', $version_data); + $this->template->assign_block_vars('updates_available', $version_data); } } catch (exception_interface $e) @@ -583,4 +583,41 @@ class acp_extensions { return strnatcasecmp($val1['META_DISPLAY_NAME'], $val2['META_DISPLAY_NAME']); } + + /** + * Outputs extension metadata into the template + * + * @param array $metadata Array with all metadata for the extension + * @return null + */ + public function output_metadata_to_template($metadata) + { + $this->template->assign_vars(array( + 'META_NAME' => $metadata['name'], + 'META_TYPE' => $metadata['type'], + 'META_DESCRIPTION' => (isset($metadata['description'])) ? $metadata['description'] : '', + 'META_HOMEPAGE' => (isset($metadata['homepage'])) ? $metadata['homepage'] : '', + 'META_VERSION' => $metadata['version'], + 'META_TIME' => (isset($metadata['time'])) ? $metadata['time'] : '', + 'META_LICENSE' => $metadata['license'], + + 'META_REQUIRE_PHP' => (isset($metadata['require']['php'])) ? $metadata['require']['php'] : '', + 'META_REQUIRE_PHP_FAIL' => (isset($metadata['require']['php'])) ? false : true, + + 'META_REQUIRE_PHPBB' => (isset($metadata['extra']['soft-require']['phpbb/phpbb'])) ? $metadata['extra']['soft-require']['phpbb/phpbb'] : '', + 'META_REQUIRE_PHPBB_FAIL' => (isset($metadata['extra']['soft-require']['phpbb/phpbb'])) ? false : true, + + 'META_DISPLAY_NAME' => (isset($metadata['extra']['display-name'])) ? $metadata['extra']['display-name'] : '', + )); + + foreach ($metadata['authors'] as $author) + { + $this->template->assign_block_vars('meta_authors', array( + 'AUTHOR_NAME' => $author['name'], + 'AUTHOR_EMAIL' => (isset($author['email'])) ? $author['email'] : '', + 'AUTHOR_HOMEPAGE' => (isset($author['homepage'])) ? $author['homepage'] : '', + 'AUTHOR_ROLE' => (isset($author['role'])) ? $author['role'] : '', + )); + } + } } diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php index 1f1cfa25d2..ed8ad79eea 100644 --- a/phpBB/phpbb/console/command/update/check.php +++ b/phpBB/phpbb/console/command/update/check.php @@ -134,7 +134,7 @@ class check extends \phpbb\console\command\command try { $ext_manager = $this->phpbb_container->get('ext.manager'); - $md_manager = $ext_manager->create_extension_metadata_manager($ext_name, null); + $md_manager = $ext_manager->create_extension_metadata_manager($ext_name); $updates_available = $ext_manager->version_check($md_manager, $recheck, false, $stability); $metadata = $md_manager->get_metadata('all'); diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 22522d0785..5cafd9319a 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -152,7 +152,12 @@ class manager */ public function create_extension_metadata_manager($name) { - return new \phpbb\extension\metadata_manager($name, $this->config, $this, $this->phpbb_root_path); + if (!isset($this->extensions[$name]['metadata'])) + { + $metadata = new \phpbb\extension\metadata_manager($name, $this->get_extension_path($name, true)); + $this->extensions[$name]['metadata'] = $metadata; + } + return $this->extensions[$name]['metadata']; } /** @@ -168,7 +173,7 @@ class manager public function enable_step($name) { // ignore extensions that are already enabled - if (isset($this->extensions[$name]) && $this->extensions[$name]['ext_active']) + if ($this->is_enabled($name)) { return false; } @@ -258,7 +263,7 @@ class manager public function disable_step($name) { // ignore extensions that are already disabled - if (!isset($this->extensions[$name]) || !$this->extensions[$name]['ext_active']) + if ($this->is_disabled($name)) { return false; } @@ -336,8 +341,8 @@ class manager */ public function purge_step($name) { - // ignore extensions that do not exist - if (!isset($this->extensions[$name])) + // ignore extensions that are not configured + if (!$this->is_configured($name)) { return false; } @@ -458,8 +463,12 @@ class manager $configured = array(); foreach ($this->extensions as $name => $data) { - $data['ext_path'] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path']; - $configured[$name] = $data; + if ($this->is_configured($name)) + { + unset($data['metadata']); + $data['ext_path'] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path']; + $configured[$name] = $data; + } } return $configured; } @@ -476,7 +485,7 @@ class manager $enabled = array(); foreach ($this->extensions as $name => $data) { - if ($data['ext_active']) + if ($this->is_enabled($name)) { $enabled[$name] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path']; } @@ -497,7 +506,7 @@ class manager $disabled = array(); foreach ($this->extensions as $name => $data) { - if (!$data['ext_active']) + if ($this->is_disabled($name)) { $disabled[$name] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path']; } @@ -532,7 +541,7 @@ class manager */ public function is_enabled($name) { - return isset($this->extensions[$name]) && $this->extensions[$name]['ext_active']; + return isset($this->extensions[$name]['ext_active']) && $this->extensions[$name]['ext_active']; } /** @@ -543,7 +552,7 @@ class manager */ public function is_disabled($name) { - return isset($this->extensions[$name]) && !$this->extensions[$name]['ext_active']; + return isset($this->extensions[$name]['ext_active']) && !$this->extensions[$name]['ext_active']; } /** @@ -557,7 +566,7 @@ class manager */ public function is_configured($name) { - return isset($this->extensions[$name]); + return isset($this->extensions[$name]['ext_active']); } /** diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index 089f9a7a32..2dec6944b7 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -18,24 +18,6 @@ namespace phpbb\extension; */ class metadata_manager { - /** - * phpBB Config instance - * @var \phpbb\config\config - */ - protected $config; - - /** - * phpBB Extension Manager - * @var \phpbb\extension\manager - */ - protected $extension_manager; - - /** - * phpBB root path - * @var string - */ - protected $phpbb_root_path; - /** * Name (including vendor) of the extension * @var string @@ -58,19 +40,13 @@ class metadata_manager * Creates the metadata manager * * @param string $ext_name Name (including vendor) of the extension - * @param \phpbb\config\config $config phpBB Config instance - * @param \phpbb\extension\manager $extension_manager An instance of the phpBB extension manager - * @param string $phpbb_root_path Path to the phpbb includes directory. + * @param string $ext_path Path to the extension directory including root path */ - public function __construct($ext_name, \phpbb\config\config $config, \phpbb\extension\manager $extension_manager, $phpbb_root_path) + public function __construct($ext_name, $ext_path) { - $this->config = $config; - $this->extension_manager = $extension_manager; - $this->phpbb_root_path = $phpbb_root_path; - $this->ext_name = $ext_name; $this->metadata = array(); - $this->metadata_file = ''; + $this->metadata_file = $ext_path . 'composer.json'; } /** @@ -119,15 +95,12 @@ class metadata_manager } /** - * Sets the path of the metadata file, gets its contents and cleans loaded file + * Gets the metadata file contents and cleans loaded file * * @throws \phpbb\extension\exception */ private function fetch_metadata_from_file() { - $ext_filepath = $this->extension_manager->get_extension_path($this->ext_name); - $this->metadata_file = $this->phpbb_root_path . $ext_filepath . 'composer.json'; - if (!file_exists($this->metadata_file)) { throw new \phpbb\extension\exception('FILE_NOT_FOUND', array($this->metadata_file)); @@ -182,9 +155,19 @@ class metadata_manager case 'all': $this->validate('display'); - if (!$this->validate_enable()) + if (!$this->validate_dir()) { - throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array($name)); + throw new \phpbb\extension\exception('EXTENSION_DIR_INVALID'); + } + + if (!$this->validate_require_phpbb()) + { + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('soft-require')); + } + + if (!$this->validate_require_php()) + { + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('require php')); } break; @@ -296,40 +279,4 @@ class metadata_manager return true; } - - /** - * Outputs the metadata into the template - * - * @param \phpbb\template\template $template phpBB Template instance - */ - public function output_template_data(\phpbb\template\template $template) - { - $template->assign_vars(array( - 'META_NAME' => $this->metadata['name'], - 'META_TYPE' => $this->metadata['type'], - 'META_DESCRIPTION' => (isset($this->metadata['description'])) ? $this->metadata['description'] : '', - 'META_HOMEPAGE' => (isset($this->metadata['homepage'])) ? $this->metadata['homepage'] : '', - 'META_VERSION' => (isset($this->metadata['version'])) ? $this->metadata['version'] : '', - 'META_TIME' => (isset($this->metadata['time'])) ? $this->metadata['time'] : '', - 'META_LICENSE' => $this->metadata['license'], - - 'META_REQUIRE_PHP' => (isset($this->metadata['require']['php'])) ? $this->metadata['require']['php'] : '', - 'META_REQUIRE_PHP_FAIL' => !$this->validate_require_php(), - - 'META_REQUIRE_PHPBB' => (isset($this->metadata['extra']['soft-require']['phpbb/phpbb'])) ? $this->metadata['extra']['soft-require']['phpbb/phpbb'] : '', - 'META_REQUIRE_PHPBB_FAIL' => !$this->validate_require_phpbb(), - - 'META_DISPLAY_NAME' => (isset($this->metadata['extra']['display-name'])) ? $this->metadata['extra']['display-name'] : '', - )); - - foreach ($this->metadata['authors'] as $author) - { - $template->assign_block_vars('meta_authors', array( - 'AUTHOR_NAME' => $author['name'], - 'AUTHOR_EMAIL' => (isset($author['email'])) ? $author['email'] : '', - 'AUTHOR_HOMEPAGE' => (isset($author['homepage'])) ? $author['homepage'] : '', - 'AUTHOR_ROLE' => (isset($author['role'])) ? $author['role'] : '', - )); - } - } } From 7000db304995ae575d14f84d4f4f3c874d09c3e0 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 12 Feb 2017 19:25:42 +0100 Subject: [PATCH 1514/1676] [ticket/15087] Optimize creation of metadata objects by caching Fix constructor in test cases. PHPBB3-15087 --- tests/extension/metadata_manager_test.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index ce675f0d36..8ef41f3673 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -364,9 +364,7 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case { return new phpbb_mock_metadata_manager( $ext_name, - $this->config, - $this->extension_manager, - $this->phpbb_root_path + $this->extension_manager->get_extension_path($ext_name, true) ); } } From e1910b9a0fbd298fbc3a0fd6faf8b38f9f4a9109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Sun, 12 Feb 2017 22:26:40 -0500 Subject: [PATCH 1515/1676] [ticket/15089] Reverse the order of cookie secure radio buttons --- phpBB/includes/acp/acp_board.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 1f9c15dbd0..05a8b79137 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -323,7 +323,7 @@ class acp_board 'cookie_domain' => array('lang' => 'COOKIE_DOMAIN', 'validate' => 'string', 'type' => 'text::255', 'explain' => false), 'cookie_name' => array('lang' => 'COOKIE_NAME', 'validate' => 'string', 'type' => 'text::16', 'explain' => false), 'cookie_path' => array('lang' => 'COOKIE_PATH', 'validate' => 'string', 'type' => 'text::255', 'explain' => false), - 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'validate' => 'bool', 'type' => 'radio:disabled_enabled', 'explain' => true), + 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), 'cookie_notice' => array('lang' => 'COOKIE_NOTICE', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), ) ); From a52d5edd18a2218a95f7e3bc4bf02560b4dbf31f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 13 Feb 2017 21:09:28 +0100 Subject: [PATCH 1516/1676] [ticket/14979] Add text-decoration settings for lastpost links as well PHPBB3-14979 --- phpBB/styles/prosilver/theme/links.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index f6c24bfb7c..3553df4d1c 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -93,6 +93,14 @@ a.unread { text-decoration: none; } +dd.lastpost a:hover { + text-decoration: none; +} + +dd.lastpost a.username-coloured:hover, dd.lastpost a.username { + text-decoration: underline; +} + /* Post body links */ .postlink { text-decoration: none; From c5e699abe691be27814c98dd72dc1a39da12b04e Mon Sep 17 00:00:00 2001 From: Jim Mossing Holsteyn Date: Tue, 14 Feb 2017 15:03:56 +0100 Subject: [PATCH 1517/1676] Remove all instances of install/database_update.php --- phpBB/docs/INSTALL.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html index 748ae69cf7..704a9f13a7 100644 --- a/phpBB/docs/INSTALL.html +++ b/phpBB/docs/INSTALL.html @@ -265,7 +265,7 @@

      If you are currently using a stable release of phpBB, updating to this version is straightforward. You would have downloaded one of four packages and your choice determines what you need to do. Note: Before updating, we heavily recommend you do a full backup of your database and existing phpBB files! If you are unsure how to achieve this please ask your hosting provider for advice.

      -

      Please make sure you update your phpBB source files too, even if you run the database_update.php file. If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: php bin/phpbbcli.php --safe-mode db:migrate.

      +

      Please make sure you update your phpBB source files too, even if you just run the database updater. If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: php bin/phpbbcli.php --safe-mode db:migrate.

      4.i. Full package

      @@ -285,7 +285,7 @@

      The directory structure has been preserved, enabling you (if you wish) to simply upload the uncompressed contents of the archive to the appropriate location on your server, i.e. simply overwrite the existing files with the new versions. Do not forget that if you have installed any modifications (MODs) these files will overwrite the originals, possibly destroying them in the process. You will need to re-add MODs to any affected file before uploading.

      -

      As for the other update procedures, you should run install/database_update.php after you have finished updating the files. This will update your database schema and increment the version number. If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: php bin/phpbbcli.php --safe-mode db:migrate.

      +

      As for the other update procedures, you should go to /install/app.php/update, select "Update database only" and submit the page after you have finished updating the files. This will update your database schema and increment the version number. If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: php bin/phpbbcli.php --safe-mode db:migrate.

      4.iii. Patch file

      @@ -297,7 +297,7 @@

      If you do get failures, you should look at using the Changed Files package to replace the files which failed to patch. Please note that you will need to manually re-add any MODs to these particular files. Alternatively, if you know how, you can examine the .rej files to determine what failed where and make manual adjustments to the relevant source.

      -

      You should, of course, delete the patch file (or files) after use. As for the other update procedures, you should run install/database_update.php after you have finished updating the files. This will update your database schema and data (if appropriate) and increment the version number. If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: php bin/phpbbcli.php --safe-mode db:migrate.

      +

      You should, of course, delete the patch file (or files) after use. As for the other update procedures, you should navigate to /install/app.php/update, select "Update database only" and submit the page after you have finished updating the files. This will update your database schema and data (if appropriate) and increment the version number. If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: php bin/phpbbcli.php --safe-mode db:migrate.

      4.iv. Automatic update package

      From c06f4756eca4dfbbdad8984a62976745aeb183dd Mon Sep 17 00:00:00 2001 From: nomind60s Date: Fri, 17 Feb 2017 13:44:42 -0700 Subject: [PATCH 1518/1676] [ticket/15097] Add PHP version to Board statistics The ACP main page shows the phpBB version and the database version, but didn't show the PHP version. With this change the PHP version is displayed as part of the Board statistics. PHPBB3-15097 --- phpBB/adm/style/acp_main.html | 4 ++++ phpBB/includes/acp/acp_main.php | 1 + phpBB/language/en/acp/common.php | 1 + 3 files changed, 6 insertions(+) diff --git a/phpBB/adm/style/acp_main.html b/phpBB/adm/style/acp_main.html index 1bdb7b8d2a..944cf10ea5 100644 --- a/phpBB/adm/style/acp_main.html +++ b/phpBB/adm/style/acp_main.html @@ -167,6 +167,10 @@   + + {L_PHP_VERSION}{L_COLON} + {PHP_VERSION} + diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 6e7bd91a86..0c750abc0a 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -569,6 +569,7 @@ class acp_main 'S_TOTAL_ORPHAN' => ($total_orphan === false) ? false : true, 'GZIP_COMPRESSION' => ($config['gzip_compress'] && @extension_loaded('zlib')) ? $user->lang['ON'] : $user->lang['OFF'], 'DATABASE_INFO' => $db->sql_server_info(), + 'PHP_VERSION' => PHP_VERSION, 'BOARD_VERSION' => $config['version'], 'U_ACTION' => $this->u_action, diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 562b446f8a..3cb2828d09 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -373,6 +373,7 @@ $lang = array_merge($lang, array( 'NUMBER_USERS' => 'Number of users', 'NUMBER_ORPHAN' => 'Orphan attachments', + 'PHP_VERSION' => 'PHP version', 'PHP_VERSION_OLD' => 'The version of PHP on this server (%1$s) will no longer be supported by future versions of phpBB. The minimum required version will be PHP %2$s. %3$sDetails%4$s', 'POSTS_PER_DAY' => 'Posts per day', From c30ad4ce60267a1301a406c3d0279f95b856f5a5 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Fri, 17 Feb 2017 14:19:18 -0700 Subject: [PATCH 1519/1676] [ticket/15097] Add PHP version to Board statistics Rework commit message per DavidIQ's guidance and change variable name to avoid confusion PHPBB3-15907 --- phpBB/adm/style/acp_main.html | 2 +- phpBB/includes/acp/acp_main.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/adm/style/acp_main.html b/phpBB/adm/style/acp_main.html index 944cf10ea5..5f8040b57e 100644 --- a/phpBB/adm/style/acp_main.html +++ b/phpBB/adm/style/acp_main.html @@ -169,7 +169,7 @@ {L_PHP_VERSION}{L_COLON} - {PHP_VERSION} + {PHP_VERSION_INFO} diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 0c750abc0a..c611db5759 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -569,7 +569,7 @@ class acp_main 'S_TOTAL_ORPHAN' => ($total_orphan === false) ? false : true, 'GZIP_COMPRESSION' => ($config['gzip_compress'] && @extension_loaded('zlib')) ? $user->lang['ON'] : $user->lang['OFF'], 'DATABASE_INFO' => $db->sql_server_info(), - 'PHP_VERSION' => PHP_VERSION, + 'PHP_VERSION_INFO' => PHP_VERSION, 'BOARD_VERSION' => $config['version'], 'U_ACTION' => $this->u_action, From 65513c79f57d7e10dcc973d094bf723673738ada Mon Sep 17 00:00:00 2001 From: nomind60s Date: Fri, 17 Feb 2017 16:15:00 -0700 Subject: [PATCH 1520/1676] [ticket/15097] Resolve travis-ci error Make sure indentation is using tabs not spaces per code guidelines PHPBB3-15097 --- phpBB/includes/acp/acp_main.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index c611db5759..d40cda0358 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -569,7 +569,7 @@ class acp_main 'S_TOTAL_ORPHAN' => ($total_orphan === false) ? false : true, 'GZIP_COMPRESSION' => ($config['gzip_compress'] && @extension_loaded('zlib')) ? $user->lang['ON'] : $user->lang['OFF'], 'DATABASE_INFO' => $db->sql_server_info(), - 'PHP_VERSION_INFO' => PHP_VERSION, + 'PHP_VERSION_INFO' => PHP_VERSION, 'BOARD_VERSION' => $config['version'], 'U_ACTION' => $this->u_action, From 16dbc4195af2244405c201b49de7be8f25085eb2 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Fri, 17 Feb 2017 16:25:30 -0700 Subject: [PATCH 1521/1676] [ticket/15097] Resolve travis-ci error Make sure indentation is using tabs not spaces per code guidelines PHPBB3-15097 --- phpBB/language/en/acp/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 3cb2828d09..5c9e31f028 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -373,7 +373,7 @@ $lang = array_merge($lang, array( 'NUMBER_USERS' => 'Number of users', 'NUMBER_ORPHAN' => 'Orphan attachments', - 'PHP_VERSION' => 'PHP version', + 'PHP_VERSION' => 'PHP version', 'PHP_VERSION_OLD' => 'The version of PHP on this server (%1$s) will no longer be supported by future versions of phpBB. The minimum required version will be PHP %2$s. %3$sDetails%4$s', 'POSTS_PER_DAY' => 'Posts per day', From bdc31265cf1e25799daa7f2173e2b5e836e5bb10 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 19 Feb 2017 16:46:29 +0100 Subject: [PATCH 1522/1676] [ticket/14979] Use hanakin's CSS version PHPBB3-14979 --- phpBB/styles/prosilver/theme/links.css | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index 3553df4d1c..6a61e9a262 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -89,15 +89,14 @@ a.lastsubject:hover { text-decoration: underline; } -a.unread { - text-decoration: none; +.row-item a:hover { + text-decoration: none } -dd.lastpost a:hover { - text-decoration: none; -} - -dd.lastpost a.username-coloured:hover, dd.lastpost a.username { +.row-item .topictitle:hover, +.row-item .subforum:hover, +.row-item .username:hover, +.row-item .username-coloured:hover { text-decoration: underline; } From f677376b8ca4451e3a0c415f603ad1513ed24ef7 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Sun, 19 Feb 2017 11:49:07 -0700 Subject: [PATCH 1523/1676] [ticket/15097] New 'Installed software' lead section Created a new lead section showing the installed software (phpBB, PHP and Database server) and their versions. Implementation is inspired by MediaWiki's Special:Version page. Removed those items from Board statistics section. PHPBB3-15097 --- phpBB/adm/style/acp_main.html | 59 +++++++++++++++++++------------- phpBB/language/en/acp/common.php | 8 +++-- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/phpBB/adm/style/acp_main.html b/phpBB/adm/style/acp_main.html index 5f8040b57e..e306ce78e9 100644 --- a/phpBB/adm/style/acp_main.html +++ b/phpBB/adm/style/acp_main.html @@ -94,15 +94,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      {L_SOFTWARE_HEADING}
      {L_SOFTWARE_PRODUCT}{L_SOFTWARE_VERSION}
      {L_BOARD_VERSION}style="color: #228822;" style="color: #BC2A4D;" title="{L_MORE_INFORMATION}">{BOARD_VERSION}{L_VERSIONCHECK_FORCE_UPDATE} ] + {BOARD_VERSION}
      {L_PHP_VERSION}{PHP_VERSION_INFO}
      {L_DATABASE_SERVER_INFO}{DATABASE_INFO}
      + - - - - + + + + @@ -130,8 +160,6 @@ - - @@ -145,33 +173,16 @@ - - - - - - - - - - - + - - - - -
      {L_FORUM_STATS}
      {L_STATISTIC}{L_VALUE}{L_STATISTIC}{L_VALUE}{L_STATISTIC}{L_VALUE}{L_STATISTIC}{L_VALUE}
      {L_FILES_PER_DAY}{L_COLON} {FILES_PER_DAY}
      {L_BOARD_STARTED}{L_COLON} {START_DATE}{UPLOAD_DIR_SIZE}
      {L_DATABASE_SERVER_INFO}{L_COLON} {DATABASE_INFO} {L_GZIP_COMPRESSION}{L_COLON} {GZIP_COMPRESSION}
      {L_BOARD_VERSION}{L_COLON} - style="color: #228822;" style="color: #BC2A4D;" title="{L_MORE_INFORMATION}">{BOARD_VERSION}{L_VERSIONCHECK_FORCE_UPDATE} ] - {L_NUMBER_ORPHAN}{L_COLON} {TOTAL_ORPHAN}    
      {L_PHP_VERSION}{L_COLON} {PHP_VERSION_INFO}
      diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 5c9e31f028..f67aba162c 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -345,7 +345,7 @@ $lang = array_merge($lang, array( 'AVATAR_DIR_SIZE' => 'Avatar directory size', 'BOARD_STARTED' => 'Board started', - 'BOARD_VERSION' => 'Board version', + 'BOARD_VERSION' => 'phpBB', 'DATABASE_SERVER_INFO' => 'Database server', 'DATABASE_SIZE' => 'Database size', @@ -373,7 +373,7 @@ $lang = array_merge($lang, array( 'NUMBER_USERS' => 'Number of users', 'NUMBER_ORPHAN' => 'Orphan attachments', - 'PHP_VERSION' => 'PHP version', + 'PHP_VERSION' => 'PHP', 'PHP_VERSION_OLD' => 'The version of PHP on this server (%1$s) will no longer be supported by future versions of phpBB. The minimum required version will be PHP %2$s. %3$sDetails%4$s', 'POSTS_PER_DAY' => 'Posts per day', @@ -408,6 +408,10 @@ $lang = array_merge($lang, array( 'RESYNC_STATS_SUCCESS' => 'Resynchronised statistics', 'RUN' => 'Run now', + 'SOFTWARE_HEADING' => 'Installed software', + 'SOFTWARE_PRODUCT' => 'Product', + 'SOFTWARE_VERSION' => 'Version', + 'STATISTIC' => 'Statistic', 'STATISTIC_RESYNC_OPTIONS' => 'Resynchronise or reset statistics', From 3331581ee5218e54e2e5541af1c6321654a59dbc Mon Sep 17 00:00:00 2001 From: Saeed Hubaishan Date: Wed, 22 Feb 2017 13:30:48 +0300 Subject: [PATCH 1524/1676] [ticket/14975] Changes requested by hanakin [ticket/14975] Changes requested by hanakin [PHPBB3-14975] --- phpBB/styles/prosilver/theme/bidi.css | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 3268c71515..860c2f6cb4 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -123,7 +123,7 @@ } .rtl .jumpbox .dropdown-contents a { - margin-right: 0px; + margin-right: 0; margin-left: 20px; } @@ -604,15 +604,12 @@ li.breadcrumbs span:first-child > a { */ .rtl .caret { - left: -6px; - right: inherit; border-right: 1px solid; border-right-color: inherit; border-left: none; + right: 6px; } - - /* Post control buttons --------------------------------------------- */ .rtl .post-buttons { @@ -928,9 +925,9 @@ li.breadcrumbs span:first-child > a { } .rtl .button-search-end { + border-radius: 4px 0 0 4px; border-left-width: 1px; border-right-width: 0; - border-radius: 4px 0 0 4px; } .rtl .search-header .button-search-end { From 01046c2209cc589268f791d592691b3834a7fdd6 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 22 Feb 2017 21:37:02 +0100 Subject: [PATCH 1525/1676] [ticket/15083] Add stylelint definitions PHPBB3-15083 --- phpBB/styles/prosilver/theme/print.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/phpBB/styles/prosilver/theme/print.css b/phpBB/styles/prosilver/theme/print.css index e1ddaca308..a83270b742 100644 --- a/phpBB/styles/prosilver/theme/print.css +++ b/phpBB/styles/prosilver/theme/print.css @@ -138,9 +138,11 @@ div.spacer { clear: both; } .codebox p { display: none; } +/* stylelint-disable declaration-property-unit-whitelist */ .emoji { min-height: 18px; min-width: 18px; height: 1em; width: 1em; } +/* stylelint-enable declaration-property-unit-whitelist */ From f78ba39a1c61cc69b5ecd725ffaa0252cc6d8431 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Thu, 23 Feb 2017 08:44:56 -0700 Subject: [PATCH 1526/1676] [ticket/15086] Replace quote.gif with Font Awesome icon Use the Font Awesome icon for a quote rather than the quote.gif file. I believe I've handled the RTL case as well. PHPBB3-15086 --- phpBB/styles/prosilver/theme/bidi.css | 10 +++++++++- phpBB/styles/prosilver/theme/colours.css | 5 ----- phpBB/styles/prosilver/theme/content.css | 9 ++++++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index f23af1b5fc..66a6451e27 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -502,10 +502,18 @@ li.breadcrumbs span:first-child > a { .rtl blockquote cite { /* Username/source of quoter */ - margin-right: 20px; + margin-right: 0px; margin-left: 0; } +blockquote cite:before { + /* Font Awesome quote-right */ + content: '\f10e'; + font-family: FontAwesome; + padding-right: 0px; + padding-left: 5px; +} + .rtl blockquote .codebox { margin-right: 0; } diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index cf21ac216b..0301404881 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -409,14 +409,9 @@ dl.faq dt { /* Quote block */ blockquote { background-color: #EBEADD; - background-image: url("./images/quote.gif"); border-color:#DBDBCE; } -.rtl blockquote { - background-image: url("./images/quote_rtl.gif"); -} - blockquote blockquote { /* Nested quotes */ background-color:#EFEED9; diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 95168d1d97..15f44ee476 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -466,11 +466,18 @@ blockquote cite { /* Username/source of quoter */ font-style: normal; font-weight: bold; - margin-left: 20px; + margin-left: 0px; display: block; font-size: 0.9em; } +blockquote cite:before { + /* Font Awesome quote-left */ + content: '\f10d'; + font-family: FontAwesome; + padding-right: 5px; +} + blockquote cite cite { font-size: 1em; } From 34e867c5909c9fb861d64951f52eac59ee2af626 Mon Sep 17 00:00:00 2001 From: javiexin Date: Fri, 24 Feb 2017 00:25:04 +0100 Subject: [PATCH 1527/1676] [ticket/15102] Missing parameter calling version_check PHPBB3-15102 --- phpBB/includes/acp/acp_extensions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index e915fa8c75..df40cf6a5f 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -313,7 +313,7 @@ class acp_extensions { try { - $updates_available = $phpbb_extension_manager->version_check($md_manager, $request->variable('versioncheck_force', false), $this->config['extension_force_unstable'] ? 'unstable' : null); + $updates_available = $phpbb_extension_manager->version_check($md_manager, $request->variable('versioncheck_force', false), false, $this->config['extension_force_unstable'] ? 'unstable' : null); $template->assign_vars(array( 'S_UP_TO_DATE' => empty($updates_available), From 92fefcfe6fcaba5fa3f866432506101e21daca52 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Thu, 23 Feb 2017 22:33:43 -0700 Subject: [PATCH 1528/1676] [ticket/15086] corrections from vinny's review Changed instances of 0px; to 0; and add missing element PHPBB3-15086 --- phpBB/styles/prosilver/theme/bidi.css | 6 +++--- phpBB/styles/prosilver/theme/content.css | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 66a6451e27..3506e7f735 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -502,15 +502,15 @@ li.breadcrumbs span:first-child > a { .rtl blockquote cite { /* Username/source of quoter */ - margin-right: 0px; + margin-right: 0; margin-left: 0; } -blockquote cite:before { +.rtl blockquote cite:before { /* Font Awesome quote-right */ content: '\f10e'; font-family: FontAwesome; - padding-right: 0px; + padding-right: 0; padding-left: 5px; } diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 15f44ee476..3c4467cb19 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -466,7 +466,7 @@ blockquote cite { /* Username/source of quoter */ font-style: normal; font-weight: bold; - margin-left: 0px; + margin-left: 0; display: block; font-size: 0.9em; } From 4113fba04dff2f56201a7be35008b43e483c0d7d Mon Sep 17 00:00:00 2001 From: nomind60s Date: Fri, 24 Feb 2017 06:26:42 -0700 Subject: [PATCH 1529/1676] [ticket/15086] Handle the uncited case properly The blockquote uncited CSS needs the Font Awesome icon added as well PHPBB3-15086 --- phpBB/styles/prosilver/theme/content.css | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 3c4467cb19..9673079ee5 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -483,7 +483,14 @@ blockquote cite cite { } blockquote.uncited { - padding-top: 25px; + padding-top: 0; +} + +blockquote.uncited:before { + /* Font Awesome quote-left */ + content: '\f10d'; + font-family: FontAwesome; + padding-right: 5px; } blockquote cite > div { From 25c54beee773d80356de6c141b838d2a03f1a6bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Tue, 28 Feb 2017 00:24:57 -0500 Subject: [PATCH 1530/1676] [ticket/15106] Remove space before comma in sub-forum list --- phpBB/styles/prosilver/template/forumlist_body.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html index 0d6e930d60..4ab6de250f 100644 --- a/phpBB/styles/prosilver/template/forumlist_body.html +++ b/phpBB/styles/prosilver/template/forumlist_body.html @@ -53,9 +53,7 @@
      {forumrow.L_SUBFORUM_STR}{L_COLON} - {forumrow.subforum.SUBFORUM_NAME} - - {L_COMMA_SEPARATOR} + {forumrow.subforum.SUBFORUM_NAME}{L_COMMA_SEPARATOR} From 8227289eccab822481fa3142ed65944c5f691a61 Mon Sep 17 00:00:00 2001 From: Vinny Date: Tue, 28 Feb 2017 05:26:20 -0300 Subject: [PATCH 1531/1676] [ticket/14732] Remove PHP Code syntax highlighting references PHPBB3-14732 --- phpBB/language/en/help/bbcode.php | 2 +- phpBB/styles/prosilver/theme/colours.css | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/phpBB/language/en/help/bbcode.php b/phpBB/language/en/help/bbcode.php index dc39749963..aa5bc1666a 100644 --- a/phpBB/language/en/help/bbcode.php +++ b/phpBB/language/en/help/bbcode.php @@ -52,7 +52,7 @@ $lang = array_merge($lang, array( 'HELP_BBCODE_OTHERS_CUSTOM_ANSWER' => 'If you are an administrator on this board and have the proper permissions, you can add further BBCodes through the Custom BBCodes section.', 'HELP_BBCODE_OTHERS_CUSTOM_QUESTION' => 'Can I add my own tags?', - 'HELP_BBCODE_QUOTES_CODE_ANSWER' => 'If you want to output a piece of code or in fact anything that requires a fixed width, e.g. Courier type font you should enclose the text in [code][/code] tags, e.g.

      [code]echo "This is some code";[/code]

      All formatting used within [code][/code] tags is retained when you later view it. PHP syntax highlighting can be enabled using [code=php][/code] and is recommended when posting PHP code samples as it improves readability.', + 'HELP_BBCODE_QUOTES_CODE_ANSWER' => 'If you want to output a piece of code or in fact anything that requires a fixed width, e.g. Courier type font you should enclose the text in [code][/code] tags, e.g.

      [code]echo "This is some code";[/code]

      All formatting used within [code][/code] tags is retained when you later view it.', 'HELP_BBCODE_QUOTES_CODE_QUESTION' => 'Outputting code or fixed width data', 'HELP_BBCODE_QUOTES_TEXT_ANSWER' => 'There are two ways you can quote text, with a reference or without.
      • When you utilise the Quote function to reply to a post on the board you should notice that the post text is added to the message window enclosed in a [quote=""][/quote] block. This method allows you to quote with a reference to a person or whatever else you choose to put! For example to quote a piece of text Mr. Blobby wrote you would enter:

        [quote="Mr. Blobby"]The text Mr. Blobby wrote would go here[/quote]

        The resulting output will automatically add "Mr. Blobby wrote:" before the actual text. Remember you must include the quotation marks "" around the name you are quoting, they are not optional.
      • The second method allows you to blindly quote something. To utilise this enclose the text in [quote][/quote] tags. When you view the message it will simply show the text within a quotation block.
      ', 'HELP_BBCODE_QUOTES_TEXT_QUESTION' => 'Quoting text in replies', diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index cf21ac216b..35490c9338 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -441,13 +441,6 @@ blockquote blockquote blockquote { color: #2E8B57; } -.syntaxbg { color: #FFFFFF; } -.syntaxcomment { color: #FF8000; } -.syntaxdefault { color: #0000BB; } -.syntaxhtml { color: #000000; } -.syntaxkeyword { color: #007700; } -.syntaxstring { color: #DD0000; } - /* Attachments ----------------------------------------*/ .attachbox { From 51a55cee5dd52687054c548e3b893de0a9ba2cd9 Mon Sep 17 00:00:00 2001 From: Vinny Date: Tue, 28 Feb 2017 05:59:22 -0300 Subject: [PATCH 1532/1676] [ticket/14732] Remove references from tests PHPBB3-14732 --- tests/bbcode/parser_test.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/bbcode/parser_test.php b/tests/bbcode/parser_test.php index 5677e49636..4e85737c4f 100644 --- a/tests/bbcode/parser_test.php +++ b/tests/bbcode/parser_test.php @@ -65,11 +65,6 @@ class phpbb_bbcode_parser_test extends \phpbb_test_case '[code]unparsed code[/code]', '[code:]unparsed code[/code:]', ), - array( - 'Test default bbcodes: simple php code', - '[code=php]unparsed code[/code]', - '[code=php:]unparsed code[/code:]', - ), array( 'Test default bbcodes: simple list', '[list]no item[/list]', From e5eb7025141238a3486a0395c42c55411dafb259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Mon, 13 Feb 2017 14:03:54 -0500 Subject: [PATCH 1533/1676] [ticket/14992] Add indexes to user_notifications table [ticket/14992] Change how index length is checked [ticket/14992] Remove duplicates from user_notifications table [ticket/14992] Add unique index to user_notifications table [ticket/14992] Shorten unique index name [ticket/14992] Shorten another index for user notifications --- .../v32x/user_notifications_table_indexes.php | 50 +++++++++++++++++ ..._notifications_table_remove_duplicates.php | 55 +++++++++++++++++++ .../user_notifications_table_unique_index.php | 46 ++++++++++++++++ phpBB/phpbb/db/tools/tools.php | 14 ++--- 4 files changed, 157 insertions(+), 8 deletions(-) create mode 100644 phpBB/phpbb/db/migration/data/v32x/user_notifications_table_indexes.php create mode 100644 phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php create mode 100644 phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_indexes.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_indexes.php new file mode 100644 index 0000000000..86a3891b46 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_indexes.php @@ -0,0 +1,50 @@ + + * @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\v32x; + +class user_notifications_table_indexes extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\cookie_notice_p2', + ); + } + + public function update_schema() + { + return array( + 'add_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'user_id' => array('user_id'), + 'user_id_item_id' => array('user_id', 'item_id'), + 'user_itm_type_id' => array('user_id', 'item_type', 'item_id'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'user_id', + 'user_id_item_id', + 'user_itm_type_id', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php new file mode 100644 index 0000000000..f5f0305fda --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php @@ -0,0 +1,55 @@ + + * @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\v32x; + +class user_notifications_table_remove_duplicates extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_indexes', + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'remove_duplicates'))), + ); + } + + public function remove_duplicates() + { + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->table_prefix . 'user_notifications'); + + $sql = "SELECT item_type, item_id, user_id, method, MAX(notify) AS notify + FROM {$this->table_prefix}user_notifications + GROUP BY item_type, item_id, user_id, method + HAVING COUNT(item_type) > 1"; + + $result = $this->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + // Delete the duplicate entries + $this->sql_query("DELETE FROM {$this->table_prefix}user_notifications + WHERE user_id = {$row['user_id']} + AND item_type = '{$row['item_type']}' + AND method = '{$row['method']}'"); + + // And re-insert as a single one + $insert_buffer->insert($row); + } + $this->db->sql_freeresult($result); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php new file mode 100644 index 0000000000..925197a02b --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php @@ -0,0 +1,46 @@ + + * @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\v32x; + +class user_notifications_table_unique_index extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_remove_duplicates', + ); + } + + public function update_schema() + { + return array( + 'add_unique_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd' => array('item_type', 'item_id', 'user_id', 'method'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php index 9273d69cd6..4218addb8e 100644 --- a/phpBB/phpbb/db/tools/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -1487,17 +1487,17 @@ class tools implements tools_interface { $statements = array(); - $this->check_index_name_length($table_name, $index_name); - switch ($this->sql_layer) { case 'oracle': case 'sqlite3': + $this->check_index_name_length($table_name, $table_name . '_' . $index_name); $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; break; case 'mysql_40': case 'mysql_41': + $this->check_index_name_length($table_name, $index_name); $statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX ' . $index_name . '(' . implode(', ', $column) . ')'; break; } @@ -1512,8 +1512,6 @@ class tools implements tools_interface { $statements = array(); - $this->check_index_name_length($table_name, $index_name); - // remove index length unless MySQL4 if ('mysql_40' != $this->sql_layer) { @@ -1524,6 +1522,7 @@ class tools implements tools_interface { case 'oracle': case 'sqlite3': + $this->check_index_name_length($table_name, $table_name . '_' . $index_name); $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; break; @@ -1539,6 +1538,7 @@ class tools implements tools_interface } // no break case 'mysql_41': + $this->check_index_name_length($table_name, $index_name); $statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . ' (' . implode(', ', $column) . ')'; break; } @@ -1554,11 +1554,9 @@ class tools implements tools_interface */ protected function check_index_name_length($table_name, $index_name) { - $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) - if (strlen($table_name . $index_name) - strlen($table_prefix) > 24) + if (strlen($index_name) > 30) { - $max_length = strlen($table_prefix) + 24; - trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR); + trigger_error("Index name '$index_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR); } } From 59ac4a71b6dc53f2edf8bb5c669b14df9ce5544a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Col=C3=B3n?= Date: Wed, 1 Mar 2017 22:55:13 -0500 Subject: [PATCH 1534/1676] [ticket/14992] Check index name length in a more proper way [ticket/14992] Add indexes to user_notifications table --- ... => user_notifications_table_index_p1.php} | 6 +-- .../user_notifications_table_index_p2.php | 46 +++++++++++++++++++ .../user_notifications_table_index_p3.php | 46 +++++++++++++++++++ ..._notifications_table_remove_duplicates.php | 2 +- .../user_notifications_table_temp_index.php | 46 +++++++++++++++++++ .../user_notifications_table_unique_index.php | 7 ++- phpBB/phpbb/db/tools/tools.php | 45 ++++++++++++++---- 7 files changed, 181 insertions(+), 17 deletions(-) rename phpBB/phpbb/db/migration/data/v32x/{user_notifications_table_indexes.php => user_notifications_table_index_p1.php} (76%) create mode 100644 phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p2.php create mode 100644 phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p3.php create mode 100644 phpBB/phpbb/db/migration/data/v32x/user_notifications_table_temp_index.php diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_indexes.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p1.php similarity index 76% rename from phpBB/phpbb/db/migration/data/v32x/user_notifications_table_indexes.php rename to phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p1.php index 86a3891b46..93ff31ec6c 100644 --- a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_indexes.php +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p1.php @@ -13,7 +13,7 @@ namespace phpbb\db\migration\data\v32x; -class user_notifications_table_indexes extends \phpbb\db\migration\migration +class user_notifications_table_index_p1 extends \phpbb\db\migration\migration { static public function depends_on() { @@ -28,8 +28,6 @@ class user_notifications_table_indexes extends \phpbb\db\migration\migration 'add_index' => array( $this->table_prefix . 'user_notifications' => array( 'user_id' => array('user_id'), - 'user_id_item_id' => array('user_id', 'item_id'), - 'user_itm_type_id' => array('user_id', 'item_type', 'item_id'), ), ), ); @@ -41,8 +39,6 @@ class user_notifications_table_indexes extends \phpbb\db\migration\migration 'drop_keys' => array( $this->table_prefix . 'user_notifications' => array( 'user_id', - 'user_id_item_id', - 'user_itm_type_id', ), ), ); diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p2.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p2.php new file mode 100644 index 0000000000..e492b4e1f8 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p2.php @@ -0,0 +1,46 @@ + + * @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\v32x; + +class user_notifications_table_index_p2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_index_p1', + ); + } + + public function update_schema() + { + return array( + 'add_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'usr_id_itm_id' => array('user_id', 'item_id'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'usr_id_itm_id', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p3.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p3.php new file mode 100644 index 0000000000..1636b3024a --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p3.php @@ -0,0 +1,46 @@ + + * @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\v32x; + +class user_notifications_table_index_p3 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_index_p2', + ); + } + + public function update_schema() + { + return array( + 'add_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'usr_itm_tpe' => array('user_id', 'item_type', 'item_id'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'usr_itm_tpe', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php index f5f0305fda..50d0642056 100644 --- a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php @@ -18,7 +18,7 @@ class user_notifications_table_remove_duplicates extends \phpbb\db\migration\mig static public function depends_on() { return array( - '\phpbb\db\migration\data\v32x\user_notifications_table_indexes', + '\phpbb\db\migration\data\v32x\user_notifications_table_temp_index', ); } diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_temp_index.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_temp_index.php new file mode 100644 index 0000000000..eea44e168c --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_temp_index.php @@ -0,0 +1,46 @@ + + * @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\v32x; + +class user_notifications_table_temp_index extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_index_p3', + ); + } + + public function update_schema() + { + return array( + 'add_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd' => array('item_type', 'item_id', 'user_id', 'method'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php index 925197a02b..51cf90c8a0 100644 --- a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php @@ -25,7 +25,12 @@ class user_notifications_table_unique_index extends \phpbb\db\migration\migratio public function update_schema() { return array( - 'add_unique_index' => array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd', + ), + ), + 'add_unique_index' => array( $this->table_prefix . 'user_notifications' => array( 'itm_usr_mthd' => array('item_type', 'item_id', 'user_id', 'method'), ), diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php index 4218addb8e..112438fcdd 100644 --- a/phpBB/phpbb/db/tools/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -946,7 +946,8 @@ class tools implements tools_interface { case 'oracle': case 'sqlite3': - $row[$col] = substr($row[$col], strlen($table_name) + 1); + $index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name, false); + $row[$col] = strpos($row[$col], $table_name) === 0 ? substr($row[$col], strlen($table_name) + 1) : $row[$col]; break; } @@ -1359,12 +1360,14 @@ class tools implements tools_interface { case 'mysql_40': case 'mysql_41': + $index_name = $this->check_index_name_length($table_name, $index_name, false); $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name; break; case 'oracle': case 'sqlite3': - $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name; + $index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name, false); + $statements[] = 'DROP INDEX ' . $index_name; break; } @@ -1491,13 +1494,13 @@ class tools implements tools_interface { case 'oracle': case 'sqlite3': - $this->check_index_name_length($table_name, $table_name . '_' . $index_name); - $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + $index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name); + $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; break; case 'mysql_40': case 'mysql_41': - $this->check_index_name_length($table_name, $index_name); + $index_name = $this->check_index_name_length($table_name, $index_name); $statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX ' . $index_name . '(' . implode(', ', $column) . ')'; break; } @@ -1522,8 +1525,8 @@ class tools implements tools_interface { case 'oracle': case 'sqlite3': - $this->check_index_name_length($table_name, $table_name . '_' . $index_name); - $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + $index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name); + $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; break; case 'mysql_40': @@ -1538,7 +1541,7 @@ class tools implements tools_interface } // no break case 'mysql_41': - $this->check_index_name_length($table_name, $index_name); + $index_name = $this->check_index_name_length($table_name, $index_name); $statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . ' (' . implode(', ', $column) . ')'; break; } @@ -1551,13 +1554,35 @@ class tools implements tools_interface * * @param string $table_name * @param string $index_name + * @param bool $throw_error + * @return string The index name, shortened if too long */ - protected function check_index_name_length($table_name, $index_name) + protected function check_index_name_length($table_name, $index_name, $throw_error = true) { if (strlen($index_name) > 30) { - trigger_error("Index name '$index_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR); + // Try removing the table prefix if it's at the beginning + $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) + if (strpos($index_name, $table_prefix) === 0) + { + $index_name = substr($index_name, strlen($table_prefix) + 1); + return $this->check_index_name_length($table_name, $index_name); + } + + // Try removing the table name then + if (strpos($index_name, $table_name) === 0) + { + $index_name = substr($index_name, strlen($table_name) + 1); + return $this->check_index_name_length($table_name, $index_name); + } + + if ($throw_error) + { + trigger_error("Index name '$index_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR); + } } + + return $index_name; } /** From 6bbb7581c29b6d74e9b0449451b1fa9601253c44 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Tue, 7 Mar 2017 20:50:51 -0700 Subject: [PATCH 1535/1676] [ticket/15086] Merge cite and uncited definitions Per hanakin's suggested changes, merged the cite and uncited definitions. Handle the uncited case in RTL languages. PHPBB3-15086 --- phpBB/styles/prosilver/theme/bidi.css | 3 +-- phpBB/styles/prosilver/theme/content.css | 9 +-------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 3506e7f735..e2698d146f 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -506,10 +506,9 @@ li.breadcrumbs span:first-child > a { margin-left: 0; } -.rtl blockquote cite:before { +.rtl blockquote cite:before, .uncited:before { /* Font Awesome quote-right */ content: '\f10e'; - font-family: FontAwesome; padding-right: 0; padding-left: 5px; } diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 9673079ee5..2ceb2b4613 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -471,7 +471,7 @@ blockquote cite { font-size: 0.9em; } -blockquote cite:before { +blockquote cite:before, .uncited:before { /* Font Awesome quote-left */ content: '\f10d'; font-family: FontAwesome; @@ -486,13 +486,6 @@ blockquote.uncited { padding-top: 0; } -blockquote.uncited:before { - /* Font Awesome quote-left */ - content: '\f10d'; - font-family: FontAwesome; - padding-right: 5px; -} - blockquote cite > div { float: right; font-weight: normal; From f36eb932a4bfe0e56fd01753531dbc7a31db1b1f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 8 Mar 2017 21:36:27 +0100 Subject: [PATCH 1536/1676] [ticket/15083] Add stylelint exceptions for admin.css PHPBB3-15083 --- phpBB/adm/style/admin.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index 2ad964e6bb..2322b3da88 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -2692,9 +2692,11 @@ fieldset.permissions .padding { word-break: break-all; } +/* stylelint-disable declaration-property-unit-whitelist */ .emoji { min-height: 18px; min-width: 18px; height: 1em; width: 1em; } +/* stylelint-enable declaration-property-unit-whitelist */ From 96a90d3f81c1fcce3834ee72b7d1b9f76aa9354c Mon Sep 17 00:00:00 2001 From: javiexin Date: Thu, 9 Mar 2017 16:05:39 +0100 Subject: [PATCH 1537/1676] [ticket/15068] Add template vars retrieval from the template object Add possibility to retrieve full block of vars PHPBB3-15068 --- phpBB/phpbb/template/context.php | 22 +++++++++++++++++++--- phpBB/phpbb/template/template.php | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 0e5f3287aa..6975409ce3 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -278,7 +278,7 @@ class context * Retrieve key variable pairs from the specified block * * @param string $blockname Name of block to retrieve $vararray from - * @param array $vararray An array of variable names + * @param array $vararray An array of variable names, empty array retrieves all vars * @return array of hashes with variable name as key and retrieved value or null as value */ public function retrieve_block_vars($blockname, array $vararray) @@ -313,9 +313,25 @@ class context } $result = array(); - foreach ($vararray as $varname) + if ($vararray === array()) { - $result[$varname] = isset($block[$varname]) ? $block[$varname] : null; + // The calculated vars that depend on the block position are excluded from the complete block returned results + $excluded_vars = array('S_FIRST_ROW', 'S_LAST_ROW', 'S_BLOCK_NAME', 'S_NUM_ROWS', 'S_ROW_COUNT', 'S_ROW_NUM'); + + foreach ($block as $varname => $varvalue) + { + if ($varname === strtoupper($varname) && !is_array($varvalue) && !in_array($varname, $excluded_vars)) + { + $result[$varname] = $varvalue; + } + } + } + else + { + foreach ($vararray as $varname) + { + $result[$varname] = isset($block[$varname]) ? $block[$varname] : null; + } } return $result; } diff --git a/phpBB/phpbb/template/template.php b/phpBB/phpbb/template/template.php index 183999d5f4..dbb85dc110 100644 --- a/phpBB/phpbb/template/template.php +++ b/phpBB/phpbb/template/template.php @@ -162,7 +162,7 @@ interface template /** * Retrieve variable values from an specified block * @param string $blockname Name of block to retrieve $vararray from - * @param array $vararray An array with variable names + * @param array $vararray An array with variable names, empty array gets all vars * @return array A hash of variable name => value pairs (value is null if not set) */ public function retrieve_block_vars($blockname, array $vararray); From 6071a5b8aab9f6c74c256e049b13285ef198595a Mon Sep 17 00:00:00 2001 From: Vinny Date: Thu, 9 Mar 2017 14:34:42 -0300 Subject: [PATCH 1538/1676] [ticket/15118] Fix html error in jumpbox.html PHPBB3-15118 --- phpBB/styles/prosilver/template/jumpbox.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/template/jumpbox.html b/phpBB/styles/prosilver/template/jumpbox.html index 724a963264..d58e85d1e6 100644 --- a/phpBB/styles/prosilver/template/jumpbox.html +++ b/phpBB/styles/prosilver/template/jumpbox.html @@ -45,6 +45,6 @@
      -

      +

    • From b56be33e5bc712f156400203f2c1e066ce434a71 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Fri, 10 Mar 2017 11:42:50 -0700 Subject: [PATCH 1539/1676] [ticket/15086] Refactoring and moving to icons.css Per hanakin's github suggestions some refactoring and moved icons into icons.css for conistency. The RTL icons remain in bidi.css to keep all the RTL content in a consistant location. A number of places where setting something to zero have been removed. PHPBB3-15086 --- phpBB/styles/prosilver/theme/bidi.css | 4 +--- phpBB/styles/prosilver/theme/content.css | 12 ------------ phpBB/styles/prosilver/theme/icons.css | 17 +++++++++++++++++ 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index e2698d146f..f2c2c01cc6 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -502,15 +502,13 @@ li.breadcrumbs span:first-child > a { .rtl blockquote cite { /* Username/source of quoter */ - margin-right: 0; margin-left: 0; } .rtl blockquote cite:before, .uncited:before { - /* Font Awesome quote-right */ - content: '\f10e'; padding-right: 0; padding-left: 5px; + content: '\f10e'; /* Font Awesome quote-right */ } .rtl blockquote .codebox { diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 2ceb2b4613..1043a23cd4 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -466,26 +466,14 @@ blockquote cite { /* Username/source of quoter */ font-style: normal; font-weight: bold; - margin-left: 0; display: block; font-size: 0.9em; } -blockquote cite:before, .uncited:before { - /* Font Awesome quote-left */ - content: '\f10d'; - font-family: FontAwesome; - padding-right: 5px; -} - blockquote cite cite { font-size: 1em; } -blockquote.uncited { - padding-top: 0; -} - blockquote cite > div { float: right; font-weight: normal; diff --git a/phpBB/styles/prosilver/theme/icons.css b/phpBB/styles/prosilver/theme/icons.css index 411fecaf3b..c4aabb2b0f 100644 --- a/phpBB/styles/prosilver/theme/icons.css +++ b/phpBB/styles/prosilver/theme/icons.css @@ -85,3 +85,20 @@ line-height: .9; height: 12px; } + + +blockquote cite:before, .uncited:before { + -webkit-font-smoothing: antialiased; + -mos-osx-font-smoothing: grayscale; + font-family: FontAwesome; + font-size: 14px; + font-weight: normal; + font-style: normal; + font-variant: normal; + line-height: 1; + text-rendering: auto; + display: inline-block; + padding-right: 5px; + content: '\f10d'; /* Font Awesome quote-left */ +} + From 605af49562f5573a0b29320eafa9202a834b82a8 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Fri, 10 Mar 2017 22:11:47 -0700 Subject: [PATCH 1540/1676] [ticket/15086] Move RTL Font Awesome icon to icons.css Per github discussion, move the RTL Font Awesome coding from bidi.css to icons.css. PHPBB3-15086 --- phpBB/styles/prosilver/theme/bidi.css | 6 ------ phpBB/styles/prosilver/theme/icons.css | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index f2c2c01cc6..4f0eda7cff 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -505,12 +505,6 @@ li.breadcrumbs span:first-child > a { margin-left: 0; } -.rtl blockquote cite:before, .uncited:before { - padding-right: 0; - padding-left: 5px; - content: '\f10e'; /* Font Awesome quote-right */ -} - .rtl blockquote .codebox { margin-right: 0; } diff --git a/phpBB/styles/prosilver/theme/icons.css b/phpBB/styles/prosilver/theme/icons.css index c4aabb2b0f..4fcb0dc76c 100644 --- a/phpBB/styles/prosilver/theme/icons.css +++ b/phpBB/styles/prosilver/theme/icons.css @@ -102,3 +102,9 @@ blockquote cite:before, .uncited:before { content: '\f10d'; /* Font Awesome quote-left */ } +.rtl blockquote cite:before, .rtl .uncited:before { + padding-right: 0; + padding-left: 5px; + content: '\f10e'; /* Font Awesome quote-right */ +} + From 20a3801cf278d553c994d2227e8aa4b5c45ff4f8 Mon Sep 17 00:00:00 2001 From: rxu Date: Mon, 13 Mar 2017 00:29:00 +0700 Subject: [PATCH 1541/1676] [ticket/15124] Hide navbar icon titles in repsonsive view PHPBB3-15124 --- phpBB/styles/prosilver/theme/common.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index df9226e666..aa15fe2b45 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -1242,7 +1242,7 @@ ul.linklist:after, margin: 0 7px 0 0; } -.linklist.compact .rightside > a > span span { +.linklist.compact .rightside > a > span { display: none; } From 74f1b19dfe955f70fcc857e4bbd8921ec27dc82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Mon, 13 Mar 2017 03:05:29 +0100 Subject: [PATCH 1542/1676] [ticket/14974] make cookie notice configurable via language files PHPBB3-14974 --- phpBB/language/en/common.php | 1 + phpBB/styles/prosilver/template/overall_footer.html | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index a04a06331b..709b7d9731 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -181,6 +181,7 @@ $lang = array_merge($lang, array( 'COOKIE_CONSENT_INFO' => 'Learn more', 'COOKIE_CONSENT_MSG' => 'This website uses cookies to ensure you get the best experience on our website.', 'COOKIE_CONSENT_OK' => 'Got it!', + 'COOKIE_CONSENT_HREF' => 'http://cookiesandyou.com', 'COOKIES_DELETED' => 'All board cookies successfully deleted.', 'CURRENT_TIME' => 'It is currently %s', diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 413c93f79a..97a21f9a6e 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -76,7 +76,8 @@ "content": { "message": "{LA_COOKIE_CONSENT_MSG}", "dismiss": "{LA_COOKIE_CONSENT_OK}", - "link": "{LA_COOKIE_CONSENT_INFO}" + "link": "{LA_COOKIE_CONSENT_INFO}", + "href": "{LA_COOKIE_CONSENT_HREF}" } })}); From 6da3b5e93d4c32da804956fcc9ae6246ce5968e7 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Mon, 13 Mar 2017 09:04:02 -0600 Subject: [PATCH 1543/1676] [ticket/15086] Rework specification of properties to simplify Once more rework the property specifications to maintain backwards compatability and keep changes as small as possible. Thanks hanakin for the assistance. PHPBB3-15086 --- phpBB/styles/prosilver/theme/bidi.css | 4 ++++ phpBB/styles/prosilver/theme/content.css | 4 ++++ phpBB/styles/prosilver/theme/icons.css | 15 +-------------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 4f0eda7cff..5b0cdb8cdd 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -505,6 +505,10 @@ li.breadcrumbs span:first-child > a { margin-left: 0; } +.rtl blockquote cite:before, .rtl .uncited:before { + padding-left: 5px; +} + .rtl blockquote .codebox { margin-right: 0; } diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 1043a23cd4..72d8e8bd3b 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -474,6 +474,10 @@ blockquote cite cite { font-size: 1em; } +blockquote cite:before, .uncited:before { + padding-right: 5px; +} + blockquote cite > div { float: right; font-weight: normal; diff --git a/phpBB/styles/prosilver/theme/icons.css b/phpBB/styles/prosilver/theme/icons.css index 4fcb0dc76c..f5fe5558a4 100644 --- a/phpBB/styles/prosilver/theme/icons.css +++ b/phpBB/styles/prosilver/theme/icons.css @@ -9,7 +9,7 @@ * Just change the name of the font after the 14/1 to the name of * the font you wish to use. */ -.icon, .button .icon { +.icon, .button .icon, blockquote cite:before, .uncited:before { display: inline-block; font-weight: normal; font-style: normal; @@ -88,23 +88,10 @@ blockquote cite:before, .uncited:before { - -webkit-font-smoothing: antialiased; - -mos-osx-font-smoothing: grayscale; - font-family: FontAwesome; - font-size: 14px; - font-weight: normal; - font-style: normal; - font-variant: normal; - line-height: 1; - text-rendering: auto; - display: inline-block; - padding-right: 5px; content: '\f10d'; /* Font Awesome quote-left */ } .rtl blockquote cite:before, .rtl .uncited:before { - padding-right: 0; - padding-left: 5px; content: '\f10e'; /* Font Awesome quote-right */ } From 891aab05935e9ebc237a83cef0b248998cb5fccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Sat, 11 Mar 2017 20:34:40 +0100 Subject: [PATCH 1544/1676] [ticket/15123] add check before enable or disable extension PHPBB3-15123 --- phpBB/language/en/cli.php | 2 ++ phpBB/phpbb/console/command/extension/disable.php | 7 +++++++ phpBB/phpbb/console/command/extension/enable.php | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 9940609364..35f56be008 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -110,8 +110,10 @@ $lang = array_merge($lang, array( 'CLI_EXTENSION_DISABLE_FAILURE' => 'Could not disable extension %s', 'CLI_EXTENSION_DISABLE_SUCCESS' => 'Successfully disabled extension %s', + 'CLI_EXTENSION_ALREADY_DISABLED' => 'Extension %s was already disabled', 'CLI_EXTENSION_ENABLE_FAILURE' => 'Could not enable extension %s', 'CLI_EXTENSION_ENABLE_SUCCESS' => 'Successfully enabled extension %s', + 'CLI_EXTENSION_ALREADY_ENABLED' => 'Extension %s was already enabled', 'CLI_EXTENSION_NAME' => 'Name of the extension', 'CLI_EXTENSION_PURGE_FAILURE' => 'Could not purge extension %s', 'CLI_EXTENSION_PURGE_SUCCESS' => 'Successfully purged extension %s', diff --git a/phpBB/phpbb/console/command/extension/disable.php b/phpBB/phpbb/console/command/extension/disable.php index d022755753..be5c77a9a0 100644 --- a/phpBB/phpbb/console/command/extension/disable.php +++ b/phpBB/phpbb/console/command/extension/disable.php @@ -37,6 +37,13 @@ class disable extends command $io = new SymfonyStyle($input, $output); $name = $input->getArgument('extension-name'); + + if (!$this->manager->is_enabled($name)) + { + $io->error($this->user->lang('CLI_EXTENSION_ALREADY_DISABLED', $name)); + return 1; + } + $this->manager->disable($name); $this->manager->load_extensions(); diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index 14077d688b..2de7498c71 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -37,6 +37,13 @@ class enable extends command $io = new SymfonyStyle($input, $output); $name = $input->getArgument('extension-name'); + + if ($this->manager->is_enabled($name)) + { + $io->error($this->user->lang('CLI_EXTENSION_ALREADY_ENABLED', $name)); + return 1; + } + $this->manager->enable($name); $this->manager->load_extensions(); From 68c167fe7a5f0c86d97c9c3dda30f66d9df5b032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Sat, 11 Mar 2017 20:39:16 +0100 Subject: [PATCH 1545/1676] [ticket/15123] removed blank spaces PHPBB3-15123 --- phpBB/phpbb/console/command/extension/disable.php | 2 +- phpBB/phpbb/console/command/extension/enable.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/console/command/extension/disable.php b/phpBB/phpbb/console/command/extension/disable.php index be5c77a9a0..323f9b6d83 100644 --- a/phpBB/phpbb/console/command/extension/disable.php +++ b/phpBB/phpbb/console/command/extension/disable.php @@ -43,7 +43,7 @@ class disable extends command $io->error($this->user->lang('CLI_EXTENSION_ALREADY_DISABLED', $name)); return 1; } - + $this->manager->disable($name); $this->manager->load_extensions(); diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index 2de7498c71..e6b5f66c7f 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -43,7 +43,7 @@ class enable extends command $io->error($this->user->lang('CLI_EXTENSION_ALREADY_ENABLED', $name)); return 1; } - + $this->manager->enable($name); $this->manager->load_extensions(); From 8994295f2b7d5b2beece7bbd8f7a2861fa15625d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Sat, 11 Mar 2017 23:03:31 +0100 Subject: [PATCH 1546/1676] [ticket/15123] modified language string PHPBB3-15123 --- phpBB/language/en/cli.php | 4 ++-- phpBB/phpbb/console/command/extension/disable.php | 2 +- phpBB/phpbb/console/command/extension/enable.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 35f56be008..44b17c3147 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -110,10 +110,10 @@ $lang = array_merge($lang, array( 'CLI_EXTENSION_DISABLE_FAILURE' => 'Could not disable extension %s', 'CLI_EXTENSION_DISABLE_SUCCESS' => 'Successfully disabled extension %s', - 'CLI_EXTENSION_ALREADY_DISABLED' => 'Extension %s was already disabled', + 'CLI_EXTENSION_DISABLE_DISABLED' => 'Extension %s is not enabled', 'CLI_EXTENSION_ENABLE_FAILURE' => 'Could not enable extension %s', 'CLI_EXTENSION_ENABLE_SUCCESS' => 'Successfully enabled extension %s', - 'CLI_EXTENSION_ALREADY_ENABLED' => 'Extension %s was already enabled', + 'CLI_EXTENSION_ENABLE_ENABLED' => 'Extension %s was already enabled', 'CLI_EXTENSION_NAME' => 'Name of the extension', 'CLI_EXTENSION_PURGE_FAILURE' => 'Could not purge extension %s', 'CLI_EXTENSION_PURGE_SUCCESS' => 'Successfully purged extension %s', diff --git a/phpBB/phpbb/console/command/extension/disable.php b/phpBB/phpbb/console/command/extension/disable.php index 323f9b6d83..05f7ce9704 100644 --- a/phpBB/phpbb/console/command/extension/disable.php +++ b/phpBB/phpbb/console/command/extension/disable.php @@ -40,7 +40,7 @@ class disable extends command if (!$this->manager->is_enabled($name)) { - $io->error($this->user->lang('CLI_EXTENSION_ALREADY_DISABLED', $name)); + $io->error($this->user->lang('CLI_EXTENSION_DISABLE_DISABLED', $name)); return 1; } diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index e6b5f66c7f..c7c336cdc9 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -40,7 +40,7 @@ class enable extends command if ($this->manager->is_enabled($name)) { - $io->error($this->user->lang('CLI_EXTENSION_ALREADY_ENABLED', $name)); + $io->error($this->user->lang('CLI_EXTENSION_ENABLE_ENABLED', $name)); return 1; } From 9b3609d6f60af328e6681146014453da0af4ee01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Sun, 12 Mar 2017 22:44:18 +0100 Subject: [PATCH 1547/1676] [ticket/15123] modified language strings PHPBB3-15123 --- phpBB/language/en/cli.php | 4 ++-- phpBB/phpbb/console/command/extension/disable.php | 2 +- phpBB/phpbb/console/command/extension/enable.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 44b17c3147..9b3fa7f32c 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -110,10 +110,10 @@ $lang = array_merge($lang, array( 'CLI_EXTENSION_DISABLE_FAILURE' => 'Could not disable extension %s', 'CLI_EXTENSION_DISABLE_SUCCESS' => 'Successfully disabled extension %s', - 'CLI_EXTENSION_DISABLE_DISABLED' => 'Extension %s is not enabled', + 'CLI_EXTENSION_DISABLED' => 'Extension %s is not enabled', 'CLI_EXTENSION_ENABLE_FAILURE' => 'Could not enable extension %s', 'CLI_EXTENSION_ENABLE_SUCCESS' => 'Successfully enabled extension %s', - 'CLI_EXTENSION_ENABLE_ENABLED' => 'Extension %s was already enabled', + 'CLI_EXTENSION_ENABLED' => 'Extension %s is already enabled', 'CLI_EXTENSION_NAME' => 'Name of the extension', 'CLI_EXTENSION_PURGE_FAILURE' => 'Could not purge extension %s', 'CLI_EXTENSION_PURGE_SUCCESS' => 'Successfully purged extension %s', diff --git a/phpBB/phpbb/console/command/extension/disable.php b/phpBB/phpbb/console/command/extension/disable.php index 05f7ce9704..12674c16cb 100644 --- a/phpBB/phpbb/console/command/extension/disable.php +++ b/phpBB/phpbb/console/command/extension/disable.php @@ -40,7 +40,7 @@ class disable extends command if (!$this->manager->is_enabled($name)) { - $io->error($this->user->lang('CLI_EXTENSION_DISABLE_DISABLED', $name)); + $io->error($this->user->lang('CLI_EXTENSION_DISABLED', $name)); return 1; } diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index c7c336cdc9..079e4ce1f6 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -40,7 +40,7 @@ class enable extends command if ($this->manager->is_enabled($name)) { - $io->error($this->user->lang('CLI_EXTENSION_ENABLE_ENABLED', $name)); + $io->error($this->user->lang('CLI_EXTENSION_ENABLED', $name)); return 1; } From 45f0adcd0a4e6c7e43183fe641fa03ef2d90d45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Sun, 12 Mar 2017 22:45:33 +0100 Subject: [PATCH 1548/1676] [ticket/15123] modified return error codes PHPBB3-15123 --- phpBB/phpbb/console/command/extension/disable.php | 2 +- phpBB/phpbb/console/command/extension/enable.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/console/command/extension/disable.php b/phpBB/phpbb/console/command/extension/disable.php index 12674c16cb..b2e10fb960 100644 --- a/phpBB/phpbb/console/command/extension/disable.php +++ b/phpBB/phpbb/console/command/extension/disable.php @@ -41,7 +41,7 @@ class disable extends command if (!$this->manager->is_enabled($name)) { $io->error($this->user->lang('CLI_EXTENSION_DISABLED', $name)); - return 1; + return 2; } $this->manager->disable($name); diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index 079e4ce1f6..a8312d5c15 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -41,7 +41,7 @@ class enable extends command if ($this->manager->is_enabled($name)) { $io->error($this->user->lang('CLI_EXTENSION_ENABLED', $name)); - return 1; + return 2; } $this->manager->enable($name); From 568ce32ca85cbf30f510ce7f87ad05c423d48158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Fri, 10 Feb 2017 23:22:14 +0100 Subject: [PATCH 1549/1676] [ticket/15084] fix wrong order of breadcrumbs on module management PHPBB3-15084 --- phpBB/phpbb/module/module_manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/module/module_manager.php b/phpBB/phpbb/module/module_manager.php index 7ae16cdb61..67bac5b33e 100644 --- a/phpBB/phpbb/module/module_manager.php +++ b/phpBB/phpbb/module/module_manager.php @@ -208,7 +208,7 @@ class module_manager WHERE m1.module_class = '" . $this->db->sql_escape($module_class) . "' AND m2.module_class = '" . $this->db->sql_escape($module_class) . "' AND m1.module_id = $module_id - ORDER BY m2.left_id DESC"; + ORDER BY m2.left_id"; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) From d3eb85dd5d04463f78f77d371eddc89ac3985659 Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Wed, 15 Mar 2017 02:36:20 +0100 Subject: [PATCH 1550/1676] [ticket/15126] Disable HTML entities in quote helper PHPBB3-15126 --- phpBB/phpbb/textformatter/s9e/quote_helper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/textformatter/s9e/quote_helper.php b/phpBB/phpbb/textformatter/s9e/quote_helper.php index 24109ac8cc..86c33c7591 100644 --- a/phpBB/phpbb/textformatter/s9e/quote_helper.php +++ b/phpBB/phpbb/textformatter/s9e/quote_helper.php @@ -39,8 +39,8 @@ class quote_helper */ public function __construct(\phpbb\user $user, $root_path, $php_ext) { - $this->post_url = append_sid($root_path . 'viewtopic.' . $php_ext, 'p={POST_ID}#p{POST_ID}'); - $this->profile_url = append_sid($root_path . 'memberlist.' . $php_ext, 'mode=viewprofile&u={USER_ID}'); + $this->post_url = append_sid($root_path . 'viewtopic.' . $php_ext, 'p={POST_ID}#p{POST_ID}', false); + $this->profile_url = append_sid($root_path . 'memberlist.' . $php_ext, 'mode=viewprofile&u={USER_ID}', false); $this->user = $user; } From 018528b0623dab807c478e2bd3345606faa95ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Sun, 19 Mar 2017 17:29:11 +0100 Subject: [PATCH 1551/1676] [ticket/15134] Replace php native functions for filesystem service methods PHPBB3-15134 --- phpBB/phpbb/avatar/driver/upload.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index 2640e1ad1e..93b2353098 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -281,9 +281,13 @@ class upload extends \phpbb\avatar\driver\driver ); extract($this->dispatcher->trigger_event('core.avatar_driver_upload_delete_before', compact($vars))); - if (!sizeof($error) && file_exists($filename)) + if (!sizeof($error) && $this->filesystem->exists($filename)) { - @unlink($filename); + try + { + $this->filesystem->remove($filename); + } + catch(\phpbb\filesystem\exception\filesystem_exception $e) {} } return true; @@ -304,6 +308,6 @@ class upload extends \phpbb\avatar\driver\driver */ protected function can_upload() { - return (file_exists($this->phpbb_root_path . $this->config['avatar_path']) && $this->filesystem->is_writable($this->phpbb_root_path . $this->config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')); + return ($this->filesystem->exists($this->phpbb_root_path . $this->config['avatar_path']) && $this->filesystem->is_writable($this->phpbb_root_path . $this->config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')); } } From 12a70f63b4c1f4a60d19e1e5060fe527fadea54b Mon Sep 17 00:00:00 2001 From: Rishabh04-02 Date: Mon, 13 Mar 2017 09:56:36 +0530 Subject: [PATCH 1552/1676] [ticket/14928] fixing valid stability %s PHPBB3-14928 --- phpBB/language/en/cli.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 9b3fa7f32c..2f969ceede 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -91,7 +91,7 @@ $lang = array_merge($lang, array( 'CLI_DESCRIPTION_UPDATE_CHECK_OPTION_CACHE' => 'Run check command with cache.', 'CLI_DESCRIPTION_UPDATE_CHECK_OPTION_STABILITY' => 'Run command choosing to check only stable or unstable versions.', - 'CLI_ERROR_INVALID_STABILITY' => '"%s" is not a valid stability.', + 'CLI_ERROR_INVALID_STABILITY' => '"%s" needs to be set to "stable" or "unstable".', 'CLI_DESCRIPTION_USER_ACTIVATE' => 'Activate (or deactivate) a user account.', 'CLI_DESCRIPTION_USER_ACTIVATE_USERNAME' => 'Username of the account to activate.', From 29ce6e63527e395f086aff7936c8c4f32086956c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Sun, 19 Mar 2017 19:26:08 +0100 Subject: [PATCH 1553/1676] [ticket/15134] Follow coding guideliness PHPBB3-15134 --- phpBB/phpbb/avatar/driver/upload.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index 93b2353098..607db9067c 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -287,7 +287,10 @@ class upload extends \phpbb\avatar\driver\driver { $this->filesystem->remove($filename); } - catch(\phpbb\filesystem\exception\filesystem_exception $e) {} + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } return true; From 6f1de69bbe8c876ce3c69f7f23d3dcdf65a890b2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 19 Mar 2017 22:37:19 +0100 Subject: [PATCH 1554/1676] [ticket/15135] Parse language files in acp_extensions instead of md manager PHPBB3-15135 --- phpBB/includes/acp/acp_extensions.php | 3 ++- phpBB/phpbb/extension/metadata_manager.php | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 9effbe0f08..c38c492c1f 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -162,7 +162,8 @@ class acp_extensions } catch (\phpbb\extension\exception $e) { - trigger_error($e . adm_back_link($this->u_action), E_USER_WARNING); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + trigger_error($message, E_USER_WARNING); } $extension = $phpbb_extension_manager->get_extension($ext_name); diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index f929433bff..3dc6cdaee6 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -278,7 +278,7 @@ class metadata_manager { if (substr_count($this->ext_name, '/') !== 1 || $this->ext_name != $this->get_metadata('name')) { - throw new \phpbb\extension\exception($this->user->lang('EXTENSION_DIR_INVALID')); + throw new \phpbb\extension\exception('EXTENSION_DIR_INVALID'); } return true; @@ -295,7 +295,7 @@ class metadata_manager { if (!isset($this->metadata['extra']['soft-require']['phpbb/phpbb'])) { - throw new \phpbb\extension\exception($this->user->lang('META_FIELD_NOT_SET', 'soft-require')); + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', 'soft-require'); } return true; @@ -311,7 +311,7 @@ class metadata_manager { if (!isset($this->metadata['require']['php'])) { - throw new \phpbb\extension\exception($this->user->lang('META_FIELD_NOT_SET', 'require php')); + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', 'require php'); } return true; From 27ab639fbea160af2a003cb6ce3b2394195da297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Mon, 20 Mar 2017 11:49:34 +0100 Subject: [PATCH 1555/1676] [ticket/15134] Return false if error PHPBB3-15134 --- phpBB/phpbb/avatar/driver/upload.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index 607db9067c..4effa4c410 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -286,14 +286,15 @@ class upload extends \phpbb\avatar\driver\driver try { $this->filesystem->remove($filename); + return true; } catch (\phpbb\filesystem\exception\filesystem_exception $e) { - // Do nothing + // Fail is covered by return statement below } } - return true; + return false; } /** From 7609ba71e98071cf5549de9d9baea253609ecd00 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Mon, 20 Mar 2017 23:06:34 -0600 Subject: [PATCH 1556/1676] [ticket/15137] Global announcements can stick for a non-zero number of days To be consistent with Sticky and Announcements topic types, Global announcements can now stick for a non-zero number of days, i.e. they are no longer never ending. Before this change, if the topic type was Global and a non-zero number of days where set to stick topic, the number was silently ignored and a Global announcement was always never ending. PHPBB3-15137 --- phpBB/includes/functions_posting.php | 4 ++-- phpBB/language/en/posting.php | 2 +- phpBB/viewtopic.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index ba367e5eeb..e782414f62 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1814,7 +1814,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), 'topic_first_poster_colour' => $user->data['user_colour'], 'topic_type' => $topic_type, - 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, + 'topic_time_limit' => ($topic_type != POST_NORMAL) ? ($data['topic_time_limit'] * 86400) : 0, 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, 'topic_status' => (isset($data['topic_status'])) ? $data['topic_status'] : ITEM_UNLOCKED, ); @@ -1909,7 +1909,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, - 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, + 'topic_time_limit' => ($topic_type != POST_NORMAL) ? ($data['topic_time_limit'] * 86400) : 0, 'poll_title' => (isset($poll['poll_options'])) ? $poll['poll_title'] : '', 'poll_start' => (isset($poll['poll_options'])) ? $poll_start : 0, 'poll_max_options' => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1, diff --git a/phpBB/language/en/posting.php b/phpBB/language/en/posting.php index ef52f59753..2b2fdb7d22 100644 --- a/phpBB/language/en/posting.php +++ b/phpBB/language/en/posting.php @@ -241,7 +241,7 @@ $lang = array_merge($lang, array( 'SMILIES_ARE_ON' => 'Smilies are ON', 'STICKY_ANNOUNCE_TIME_LIMIT'=> 'Sticky/Announcement time limit', 'STICK_TOPIC_FOR' => 'Stick topic for', - 'STICK_TOPIC_FOR_EXPLAIN' => 'Enter 0 for a never ending Sticky/Announcement. Please note that this number is relative to the date of the post.', + 'STICK_TOPIC_FOR_EXPLAIN' => 'Enter 0 for a never ending Sticky/Announcement/Global. Please note that this number is relative to the date of the post.', 'STYLES_TIP' => 'Tip: Styles can be applied quickly to selected text.', 'TOO_FEW_CHARS' => 'Your message contains too few characters.', diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 378e2d8f97..e9cb2dd383 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -321,8 +321,8 @@ if ($post_id) $topic_id = (int) $topic_data['topic_id']; $topic_replies = $phpbb_content_visibility->get_count('topic_posts', $topic_data, $forum_id) - 1; -// Check sticky/announcement time limit -if (($topic_data['topic_type'] == POST_STICKY || $topic_data['topic_type'] == POST_ANNOUNCE) && $topic_data['topic_time_limit'] && ($topic_data['topic_time'] + $topic_data['topic_time_limit']) < time()) +// Check sticky/announcement/global time limit +if (($topic_data['topic_type'] != POST_NORMAL) && $topic_data['topic_time_limit'] && ($topic_data['topic_time'] + $topic_data['topic_time_limit']) < time()) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_type = ' . POST_NORMAL . ', topic_time_limit = 0 From d15b88af2acd45d19b983d75eaefdeba30d31e93 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Tue, 21 Mar 2017 06:50:25 -0600 Subject: [PATCH 1557/1676] [ticket/15137] Missed one language string change Change STICKY_ANNOUNCE_TIME_LIMIT for consistency PHPBB3-15137 --- phpBB/language/en/posting.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/language/en/posting.php b/phpBB/language/en/posting.php index 2b2fdb7d22..be90a9ce80 100644 --- a/phpBB/language/en/posting.php +++ b/phpBB/language/en/posting.php @@ -239,7 +239,7 @@ $lang = array_merge($lang, array( 'SMILIES' => 'Smilies', 'SMILIES_ARE_OFF' => 'Smilies are OFF', 'SMILIES_ARE_ON' => 'Smilies are ON', - 'STICKY_ANNOUNCE_TIME_LIMIT'=> 'Sticky/Announcement time limit', + 'STICKY_ANNOUNCE_TIME_LIMIT'=> 'Sticky/Announcement/Global time limit', 'STICK_TOPIC_FOR' => 'Stick topic for', 'STICK_TOPIC_FOR_EXPLAIN' => 'Enter 0 for a never ending Sticky/Announcement/Global. Please note that this number is relative to the date of the post.', 'STYLES_TIP' => 'Tip: Styles can be applied quickly to selected text.', From a975a3573435d56b837c78b9df5ef92dc2b6dba6 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 23 Mar 2017 21:52:35 +0100 Subject: [PATCH 1558/1676] [ticket/15135] Correctly pass exception arguments and add back link again PHPBB3-15135 --- phpBB/includes/acp/acp_extensions.php | 5 +++-- phpBB/phpbb/extension/metadata_manager.php | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index c38c492c1f..164e5872bb 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -163,7 +163,7 @@ class acp_extensions catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); - trigger_error($message, E_USER_WARNING); + trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING); } $extension = $phpbb_extension_manager->get_extension($ext_name); @@ -193,7 +193,8 @@ class acp_extensions } catch (\phpbb\extension\exception $e) { - trigger_error($e . adm_back_link($this->u_action), E_USER_WARNING); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING); } $extension = $phpbb_extension_manager->get_extension($ext_name); diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index 3dc6cdaee6..6fc6dc9891 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -295,7 +295,7 @@ class metadata_manager { if (!isset($this->metadata['extra']['soft-require']['phpbb/phpbb'])) { - throw new \phpbb\extension\exception('META_FIELD_NOT_SET', 'soft-require'); + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('soft-require')); } return true; @@ -311,7 +311,7 @@ class metadata_manager { if (!isset($this->metadata['require']['php'])) { - throw new \phpbb\extension\exception('META_FIELD_NOT_SET', 'require php'); + throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('require php')); } return true; From f62419e15815ac7ccc98343c4e79934e9536d838 Mon Sep 17 00:00:00 2001 From: nomind60s Date: Fri, 24 Mar 2017 05:39:30 -0600 Subject: [PATCH 1559/1676] [ticket/15086] Remove properties that are no longer used PHPBB3-15086 --- phpBB/styles/prosilver/theme/bidi.css | 1 - phpBB/styles/prosilver/theme/content.css | 1 - 2 files changed, 2 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 5b0cdb8cdd..d19d2d84e0 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -492,7 +492,6 @@ li.breadcrumbs span:first-child > a { /* Quote block */ .rtl blockquote { margin: 0.5em 25px 0 1px; - background-position: 99% 8px; } .rtl blockquote blockquote { diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 72d8e8bd3b..7ff6b4d5ef 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -448,7 +448,6 @@ ul.searchresults { ----------------------------------------*/ /* Quote block */ blockquote { - background: transparent none 6px 8px no-repeat; border: 1px solid transparent; font-size: 0.95em; margin: 1em 1px 1em 25px; From 38cf5c10f91b4af6f22059185f758a1da8e7d04e Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 24 Mar 2017 23:15:07 +0100 Subject: [PATCH 1560/1676] [ticket/15137] Global Announcements shouldn't always be never ending PHPBB3-15137 --- phpBB/includes/functions_posting.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 0edf9304a3..7bc9608536 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1676,7 +1676,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data 'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), 'topic_first_poster_colour' => $user->data['user_colour'], 'topic_type' => $topic_type, - 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data_ary['topic_time_limit'] * 86400) : 0, + 'topic_time_limit' => $topic_type != POST_NORMAL ? ($data_ary['topic_time_limit'] * 86400) : 0, 'topic_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0, 'topic_status' => (isset($data_ary['topic_status'])) ? $data_ary['topic_status'] : ITEM_UNLOCKED, ); @@ -1771,7 +1771,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, - 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data_ary['topic_time_limit'] * 86400) : 0, + 'topic_time_limit' => $topic_type != POST_NORMAL ? ($data_ary['topic_time_limit'] * 86400) : 0, 'poll_title' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_title'] : '', 'poll_start' => (isset($poll_ary['poll_options'])) ? $poll_start : 0, 'poll_max_options' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_max_options'] : 1, From 0b11f2947c9230b7c83aae5b5e07c77d650ae747 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 26 Mar 2017 14:57:48 +0200 Subject: [PATCH 1561/1676] [ticket/15103] Update fast-image-size to 1.1.3 This fixes issus with filename casing and JPEG files only using EXIF header data. PHPBB3-15103 --- phpBB/composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 427fbe4d1b..aee8e39a15 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -346,16 +346,16 @@ }, { "name": "marc1706/fast-image-size", - "version": "v1.1.2", + "version": "v1.1.3", "source": { "type": "git", "url": "https://github.com/marc1706/fast-image-size.git", - "reference": "8bb644f8f767c5763acd61140045a78d10e1eb06" + "reference": "5f7e8377746524e2b8a49a631c1fc9afeb9d8bee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/8bb644f8f767c5763acd61140045a78d10e1eb06", - "reference": "8bb644f8f767c5763acd61140045a78d10e1eb06", + "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/5f7e8377746524e2b8a49a631c1fc9afeb9d8bee", + "reference": "5f7e8377746524e2b8a49a631c1fc9afeb9d8bee", "shasum": "" }, "require": { @@ -393,7 +393,7 @@ "php", "size" ], - "time": "2016-10-30 19:00:39" + "time": "2017-03-26 12:48:28" }, { "name": "ocramius/proxy-manager", From f4036bd5b804b35953ad605ee789dad05843c7ac Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Sun, 26 Mar 2017 21:05:18 +0200 Subject: [PATCH 1562/1676] [ticket/15152] Updates Font Awesome Icons to version 4.7.0 PHPBB3-15152 --- phpBB/assets/css/font-awesome.min.css | 4 +- phpBB/assets/fonts/FontAwesome.otf | Bin 106260 -> 134808 bytes phpBB/assets/fonts/fontawesome-webfont.eot | Bin 68875 -> 165742 bytes phpBB/assets/fonts/fontawesome-webfont.svg | 3305 ++++++++++++++---- phpBB/assets/fonts/fontawesome-webfont.ttf | Bin 138204 -> 165548 bytes phpBB/assets/fonts/fontawesome-webfont.woff | Bin 81284 -> 98024 bytes phpBB/assets/fonts/fontawesome-webfont.woff2 | Bin 64464 -> 77160 bytes 7 files changed, 2670 insertions(+), 639 deletions(-) diff --git a/phpBB/assets/css/font-awesome.min.css b/phpBB/assets/css/font-awesome.min.css index 9c24364d62..540440ce89 100644 --- a/phpBB/assets/css/font-awesome.min.css +++ b/phpBB/assets/css/font-awesome.min.css @@ -1,4 +1,4 @@ /*! - * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.4.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"} \ No newline at end of file + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/phpBB/assets/fonts/FontAwesome.otf b/phpBB/assets/fonts/FontAwesome.otf index 681bdd4d4c8dddbaeb4d4f2a1f58c38cad92afe0..401ec0f36e4f73b8efa40bd6f604fe80d286db70 100644 GIT binary patch delta 76545 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

      >fgd}qNJ3O)4 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

      %%#AOa`crne)Q1eX`Eo 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 diff --git a/phpBB/assets/fonts/fontawesome-webfont.eot b/phpBB/assets/fonts/fontawesome-webfont.eot index a30335d748c65c0bab5880b4e6dba53f5c79206c..e9f60ca953f93e35eab4108bd414bc02ddcf3928 100644 GIT binary patch literal 165742 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 G*yFsbY~cLNXLP73aA74Mq6M9f^&YV`isWW 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

      5q!RY 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

      7r8$?kb-D3z%-c} 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 F002TuuHFCu diff --git a/phpBB/assets/fonts/fontawesome-webfont.svg b/phpBB/assets/fonts/fontawesome-webfont.svg index 6fd19abcb9..855c845e53 100644 --- a/phpBB/assets/fonts/fontawesome-webfont.svg +++ b/phpBB/assets/fonts/fontawesome-webfont.svg @@ -1,640 +1,2671 @@ - - + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpBB/assets/fonts/fontawesome-webfont.ttf b/phpBB/assets/fonts/fontawesome-webfont.ttf index d7994e13086b1ac1a216bd754c93e1bccd65f237..35acda2fa1196aad98c2adf4378a7611dd713aa3 100644 GIT binary patch delta 37888 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 SdSQM28?+M|D(2r_;{O0|uQ74} literal 81284 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äY>7uxS6S37IVP_>DW-kg%dn+sFHLnFhvXTU%&ox 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 ZUtABnb?tu81_!itTT%&fM`8Do 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 literal 64464 zcmV)4K+3;&Pew8T0RR910Q=AY4gdfE0vpr-0Q+$O1OWyB00000000000000000000 z0000#Mn+Uk92y=5U;u?`5eN#0*<6N{SOGQyBm62nVk>KX+wfW(Hek zvyp+(?)D*}+YmVX&(<`Z!i+@NrNIkT9jIaB0KojcX7>O8|Nq%XMaE3R(ryC)Kvh-$ zU)TtXtU;}Nq=b9uDJj@AW62eX%`$1Hntbp{o=%*VFKp~;#HbSWI^EoF@Q}N5qQgP! zXe3uW@<7Kk8y+0!#-n5DD^^Z)ywHbqdfzz6!f3GQI>kDq%MF`XHqXMmk(Fg9TU6mJ z5M(qrZjoUQHivF(b8Wk0(6O0pX^++qmrIy;kEUaaX2bR~0w&v*wz3D>u*oLFhHYMk z-h+bnPojwtd+Pcva?Kg$=$o?syro@!Lu(dOP4U%LW=Old_&$q9xu3I&{GCVKrQk^4IQ4Tt)tA5Wvg*01hHrVb#Mm_>WXRGR z`?Q33zOE|X`%F|-caNkR-DFfQz|-!WSGoy06FETJ>?j)q2?0eyOca%{Fo;x8K(Kpe zfjxC|MlW=8n{F;#yLMf_?N{#it6%^3;$6@)y-(Q#iE7)eqauutrbx~vq5pnA-JH2W z&=!ieLg8~8Fs9a%(Lb(-HLavOmXgCbgA^D7D5-{%jCaS&+2yqLG5p-|0rLPrSS7{I zK^$C!%Qymtr@8%GQrp;I)QBCUMu@~l)Q(X#Xc5@aqe4pIPEeVGl72)HhLxxo2+A4t zzlC5VGYg~s{~P*OXU!~EXYTsUdnyK}$f~v>8`A>m{gr^zj8huR>CuTm0ZTlAHgzZOuaN*4oL6!laS-dWDyakH zs#JCF_4=&#_eKsl2@}V##?&zb+h&a8n3w8QjP`w1^QMu*7T+*WRC!&AFn^4|9O z&w^?irPg>e>A^Y10q8(C&<%70oev2*|7TNMSw7MxEI2NMT}Hve&-MVQDpNhKlVXF|8J0=f+Lyon_s*X;b!*R=x%!LBDS{B9Ok8&dYw&Kw zc5w|oBU6n%veZl%Yj`8|*~#K-=>~)l8JrjL$N>Pi`7c$gD?kx8 zvm75Do_$Yg$5|gCfSKnCuySH(Y?`Wdexg^xOLy=&8d%l+{9~huiig{pHWfz!sFaif>vSC_%Q#!SdK8sA=~xto)AG=_bawA2T}60= zF*|eArIaQV!SZ}8#zk3B2n+P?e{Y$qzlAx8+LsGuH(Q#4q}SzkoQq{0>Ka98g{r8o zAFush2DVupQrUGRtz!#8LpAaC9-kXzP6t-|o~=5ih!FUK4-&|^L~V@B97roNBIj~! zN%B9)Y5ZT5-u0%|Of@Pb1l6_BZLIhH_=#=(|6<8j?asmA5@hjbO-Ft%ZLg%CY?=ah6y*p#&C14+Q97E~OU2J0)`#BGSJdHGkq!Sv? zjEBs>e_EvZ6&-W!7{opt#MRFIn%#nO?AoWMY0?4*Jt#GPE>hGFyJvCcN@{(-88l9CiBokU_O zEoWapTlnwa=k}S+lbM4~rI1NP0v?B8m=GqI31R|d8oH(`vLp&T#}NFj-&?=4erx^4 z`nB~dc&+@O_}#SeB>q$PiJB_+DE0Y&(m%b3f^Q#P$0Y55`)Oh6kW#F#N>2dTABoLy zej|Kxp-WLO*uP4i2gQWBl3_`{cH4r%pg0siUJQzDWl|N>kyk7^O)0hTVo>b!F5)D6 zX%jA+G*-5*9T5SX#+m8{tTGpaPj&}-UA$i1&EvH1uc0-gW$nD zaFoO?(kSV@TOhYv(Ed~nBD8KK1OfCsF=FkR9ngcv#6 zg`r}sL>#FtyPVe8bHNbs6lC?XOY>?@A?+c-(^F(+jgl;&etH9WVu{I++aI{9u-XbV zk<&s(N|)py# z{=Ok$Z>Ls8g-Eu~?5ds!_A?G5hx1vp6t1%NskL=Fn<<4qaUnN5eot4u0|pfFl56Hi z&K;jOUwy>^Ryk$`DAN%Ji>nlGb@Xayx41i8)q=W4^=c?63NMhARDvxTL3Ve&NFkyl zOeWLWb~SrPJdOpKiJ~oc4xa%UKFpA12Q*`msC_;^UwHI)liQYgtFYyGOcWCBVGbrH z1-H*ye{=nMyU9m;e0-1(1{)QLgUpsywV~7{D~_*e_?fw?_77eHYH%O>#hVsd6LH-z zL%W?&%4^H`TZ8`FeC8{d_pH{P}i3orrTQwhMW9E#f)3&KJKQN(TI1U06-J~Hb zX5Ww*42*{O`P$uY@EHWI8u8JSXLz#~>=k`UP^b%!QX6f5Owt_vIsi=SE8C*ooW8f0 zIzrHNtHXX>H~C$XUoqb&ZL}+n#D3x1JnDtYJUoiP0AoOy0ghym zDP+wYZ)K6~iuIx@GB+%kA+$+2zt18%Ae43$h9f@30#T}K<6#*D2fXwTQ;~inVz50z zJ^tBz=E?rJ6gg$p5a9V9w`C!SWF7GHuHk}~aK+XD*QAykGzFCIXw+yCP>(!foiA@@ zgx=@9h^WL@hu6iC1wxMNVdBTI23mK=^(bGFd?dIPSJWZfY{dN}vp8-YaxEzI17mrl z^~vM(171E*5{vEmD7N_svoR!FUSt%mi8<*z6RG^adK34LSt*iAZj61?AsPGJvJ;#S ztBX6~-*Jd(tEaD~}_t-Ej8QnL8dK{j!2J$GWwb__8#a=gxR)E%P zj4~;;K}bX#>1&Myzdy++x>|A7Xwi;_p6h-d5C@|g6=oyLO=QS0j)aLS3hLjY&?(N5 zDpiEUR;nmpYST?i)n(0_hqUUUb3L(XspX1@xngi!-9&4*UmsRQ7o99-vQDhKVi8kW zF@+(klDt@UdA8gPsI0{a1@HX zM+M}sZ4&}%jkZNLOpQp|!2}_z(MS)vOI@u8TISnCtjmIH#!4nfqFr4vxdFmpEQi^^ zj3X7%GzQ14li|SS#x-fWiCAfx6)`JG5JZ70{lFITn=OU<{h8D%%3i;$(-?7Q=2Gf% z36Z75SfZ-1--e`beW%-7-9mMTp>*b&*I#}_0@fm>(C#ur#xnEF(tWheu~Q&W zc+RQnbi$c~&p4tW=tL|LXk%inF!jte)2vdd9@<#WTls)!T>w|>ppMoq$P@U#H9hT(tvD5l?_1rgVyTa4yJJI+6Yw2FtU=Qb&fDh z?YnLh1iM^S>+w32u9Md_HgS7nf3Zl5YBIlm``~a%vTbT;z19<8y@u`Da0o|{)?#?B z^%?Ila`!AYp8<)5pTlZ(9ll!h$}gJPvGJ8b9t3z#n~Kz7!f3Q>XtQJ%CX=MQ+@K&g zU`~qCwWVgWJP%IUMwj;4Iw-5i-Fbkh;83-7>CM5cb+ndcD%n|; z52ZR;59GUJ`AqxvH8=4&jaYkYvJBh%f$^tGLZ)46?<{GDY{va|pd9 zW(~_FJojQou#Dqb%8-ypiZfrkmbN8Zra8at{hY0{+0AX;x24P21clE5ks{=Lw|39UH^_0&&WyiG+FCWIj}hu5Ep- z+T^Usw9*&DecV(lkDc*~x3;mq@f@zYqcBtz5K~!#)V&DzZO-|LiXhba{qN&^+7;d% zUF`Bi8QVvy8Ahq)U#Y!}86=c)zUak>NzKDoo!eY-qkE_4&&x@j8}Y^k4P=i94|=4p zS76(BG`>~%o~63YX9GMDWFl2iNl6Sw~3zEEKK0uT@il>87A<6sD>|5q@Jxmi#B}Q%hM6 zQ+d1q^)SF%#;95Ir2@*E*?tCAD@HswJi2=I9ES{vDb(+ZgtwOjJtJGaw!>GRO{KWn z#2)ZI6-#KJCXuymv{pSSfZ}U-%5kNqvAdJ0(}%saV>EDIbA@J~O*m{8oGzIcFsE^q z#pa;zk@Ct{32Q8js}SY6x#958>}&~^KZv3+Ba|_^^o7{*^fc*{PA@;RMJ^ZisoOi! zu5?~+-4_&;%18_#IGtF>UfDKvL$@A{Ol0y|JFuF@70rN1Ls=7Gc(RN*cw=GYV4E=Z zbcsOhtlvO<;N*QC*-{_CiqCIW@NFfUS?Th>cR$3J2gP^HItkVD)-J^m^Q>N#Wm?RZ zE$$xmtVdSHW} zdIOa&y@NT!gWkvp$}VdzrOtc879s&8+Nx$IVFok zatt|u&X(ntC&X`y`?I95)!<;D1J=$T{L+g{>>mApnVa78Mpy%iV{H`;=8Bv;Q*&pd)hSMvz1VV`N9p^6ri>D?yehdiP-xbHvclBJ} zvkpc_s7$*HF_IXkql?((qLMo`#C3ojW+=C^Y;V3!I1KM-rjtvOV%Qy?zgj|u@PfU) zc?UyI@IXKd_l}vP!Vi8hHWx05spb_sR8vkHy~AfMc30N{0{;fg+8ucy(0{-QLF14F z-iMjh7{pbE8tcP2Mvyy%r2Jbr4sTub*3e>Jstyb&4#wItH!jax_s$ zI@C zE33P#VX-aXZvg72IV+52)}GDVP{zcEf!2Xd+HCf}&7)Jnl`QFf@cX9p7)AgFjzlDL z9uP}yg@)BObVuwY4Sqk?{S<;%iVCg0a5mFCwlf)|{q-X*PE%Z*H4u}{!O+l{BZ!dh z$iM*E0I~FZR9tTy;4nj}jPvJlB*LAJ2scHG|4<_3b`=B7NkHP(kWx194gJ0r z9q73{k2e^i-sulXMlX9JET5IGy+javq}K#2y42dnOLJHk!iGN25J#7l=T`sfd($ALWRZnag1x;lDR_#)q%!7*VRkT>#Gbq>_2@zux(OEX zA_|*-eh^mq=Z8^B@A5;0OiHp&#r0P9Qrawx((+4VjwJE>hSsylgjtk0g62|i2Azu5 zO{7QRsXY)6wvZouQwoZUCsAOO-4}ka33;20G&~qe22R|x;%OQg!Gt4bseU6WlL`)X z&83VJuom*RhOe54mKBt(zX}sO2p?liU3Bvg%^g9eM|q9IeEsvGql1|BABnO$f}q(8 z_>8DmmePN{5kIRpD%V6a-;}B<-wc}6AG5$*DWc60-s?*IDWbbds1=HvTL~BDK(cuE z-Q?4?4YqWTb^wgh%ylu-I4hU6&kA^mIrX*adn~5L2_pJ**W0(Vh1{ts6bEa zi9Ezm9Km9O)kg|hAC{ruhiZhh#LQH$_ z^tDjq34m^KOxlY=n=z?cqu)Nbvwdv!(|sPPv5V> zM|LWE$kl7J=1sD}o(P`H`ho`3o&mq)$kAkg5tSV+A7x!*BF`a3I(|zL=RAgwT!pEy z=siwEr{sC>pVryeE|GV8LCzZR?EM@)zzJXXgLuLWg;+!b&*4xe9EPnTRE2P&P0#Kg zyq2^A)b;O2Hpt5LVYQ^^5d|gGal{R!Lm|M@`YOM~G=)DeDp~zv-c`LDh{lyt9Lr1~ zJJWMm-HYTo?JA#E>ZU9LLXN_WQL**-VAQHK?s{O`@7U828{d1_%SD}fPZ^CcZP(6l zCK`LYnx%&EsGh4cdj% z`+?BA&nSZHKB9Y;>+nnUA*c5o%JtaYWTBHY_g}}em?J2UO7O9il0X1w@*v~>Z>?n2 zrJL?|x{ey`+=j%r*njYEcP@oS(SdN3;YZvyLs!AnA^5My3uJD7{)`m2 zN6`kks?sRU8&6B@{L=~j#hY2XRAAw;z46m<@*`1Ywe0Y)6FEa-V5!d$)11MdO&~Pqo9FUKVq`$Gb>?;3l>0I%R~^UVrx5-!9CDMOCEVU&h*z>D z$}!$u4NvFBgLBiHsZA4qn(juqKoW9=~ODVcb%#Te6M7n1P8X{ z<4D4Vu^>B?gL8<)263E4{GRi)HV!3&sxAehra}}SUZ0tBd=(4qZqqW7hBAgOm+=B_AP5fMSDfJ^L-iy7x0Ic#dvcb1``lCw>y z$Ckqw%w)64S4F~n#yDKL0%k#PyCDBq@B#$4a)!{PM}AuvPHaC?<1%r;ZTCogT7wT< zTPr>&(##2Y0?@f+J65R5D0zhtTvFK!n?lpVqPxQ^7kV6_7a{N~kCR+RWflTc+(MyM z`(8Lts9a3ykZpTfWHfqOOa>*rTPtliqWR+y(VQ;3*VJS2I4uQ>_6M5hI89rN_&v!@ z?WbTA${qH?v6tk%uWXCtqz5>xAi)FF#n&uLINVGRgoJQVL>^>}vCRONUJ?hgP?2+p zF5_SqqD#S46buh>C%|MI{KQcxSv^c>lupOfw8<^RY`wgm;L_>e2t{Zy(59M-%-A6a zQ*Mi3Ta7?>_^6!>rh&M?TH`GjAEcZVnThAIR%Hj7^`>ZWicjGqh$SRAVJC$?WIW=l z{^mVSE&j7flL{5jyb_cO`>GZ!BnpbCkRuZlh}!uYM5d&OUGz!`#HS80V0Ri=9cw>? zJ4oES;Kq5Y&>#Q-jU(D_cm{VPQW5@Iwg$Py>MjbC7gSR#SbEQ>NYi&8#4MuW(~oq# z{a0!WUDy25Wumynz;FdA0j$8{yyLJUH$-dXD2g@>Xt2%UXt8^kE5>2fYgLB1lev!^ z15JRxg}>=#L!Ua{I8)*{rs-i7nhaz(YS_hdPX?Cd2YT+CZYjl^<_Q>I^xA^eF;LrV zS)|U@vQO)X4HY)c{=2tcYU1!coA0*Z3fg|vzaP6`X+?{Tu2i<~XJVx*#)RL0w{;NWxUFKhd54dG&CBQ1X5a_6r<2`DSEYj4jLIXOb2{Fet@b=7nsRvSsurgF!0 zg}%O4H`=1n)82TCLEcDk=r+hhr@O%*m;GtI$=24ffXUqBTLEm%HtT$A&!=ymx0P%7h;tlp@r=)}@{9EW1cX!dO zJajluO>FfFt`~oFbZ+qqjX0@DF+esCYh8cdvx`RLJ-xilP(Rpk zRq;v;REAPc$~0hRDDF(j3W<^;c7|fP`D!83)A=6=sywO3svfnXQTZ^Hz( z`w<9WQzD#Ssz2Qj7n#TaFjI$;GRa??T%j<|kGNN!@91V@OwT+hA8Dx;N= z7q*dA%q45>jWSHP^%KcwkOnuagEe^Dnv?nP{sF$kow-QLT*X1j;~?^?-$`li7q)wqR*c z3TAz3rZm)gB7q)>32RIgze1AXqZC@p&`WQQM8ieI9d<}O86=$0M@){PgEJ*YQxB}d zJ}E-83XR21p^6sZ_8>*ZL1I(%#k6fRN>HEz)D@{VnvNQ5Vf2#Sd(P4ZC1YO=hrISZBluvP@f z75olgIL00vXwuHT*wxSnHqICXFv?y;E)3pJXY+rAQ(m-ny_(j zk3dJ~6L16fz}&T&dZF=As3Q&B_Q8qRW({Q&r)kJB;*q=SB3o=Y!PFPVhCF0W`5Sfm z9=U2VG$wWW4xiHFVkolIlQq)5U+6?|=MAo6sn=7#vU+!s$gZeheN3U;@h0}+b1;L_ z7CQpSu67%uAF+9X#5uachz#+hJT^ikX^Muk)D@Og9$7a}w!hTW`KGFpDdyi^TcCX7`yH%|)1sc8?*V5Jy&kX|>`SqFa7SRm z)2nKMhv#WzET`X_R8?EZZjNb;A2_X*;BSe_KrLUr5KU)=vdL$RC+R=SFSl(hZF)PD z^_-}x@;dMK-knNk*qDOmEvi(j(s>`#Wc7bZRJ8e(R_83VLkVGwb8BI{^qWCc{1_oO+-yyxJYC?!5nT81O`10-Rc(9o#pH0U_W$|a zYhj2W0tjG$xgy?|gjo+#0w@$3XC01d^z0bKy_X4QabG&{5oGeSN2^w{dUfx-(-&wA zJ}5A;r>9z4{*E(&q3R8~p}_zF1QEm#$HUJB>4?z#omfMEp}#*oBzh+63O9Z$AhZhcsXN4kqmR>t@=*)-rn!U|f zGDev-dW`Hv(7wqAY4Un{!=p)D79CgkgJb)-^6owj`gZ!o z$F(l~#k+slVYE7lK;la%Q&=;>rBx|&7u+eP9qchXwgb=2G`l^dUSzY#H&1hLlro6WV#7!yH_XOxC;3kRhb}FTmAEOIrTD zW7!HM8x<%^sE68?VaFS0!{WL4EKfeLOQobG`Ywt7?9zl_DO|=9?EDFHb-zMmg;NY` zDxF;M0c*$40KIF#ZFpwnO_p&p*<7&wQp=BeoAh4nlSto5#6Lm8g|UoSs+nfU`ntN&+rf>X}XieWBckSD21M%6G zgOf7OQIA)ktWli6I;HrcH8Ff%?^Mn(dM~9r+cT!}dDssnM$)Og>*TGgro(i`ZSw&k zw!G$EpHv5Kj4R$YV%Sx+8N+pO4xz&WAjl@|goc4ZK~_Co6&k}`Fb4~@dbbmtk_%?b z7*V)@qp0#*1Wg_+m8;^Xp2Gp$v{@f@I#d6mD;t~c+cN~!v6={tBQYIf9TD_Vh=;Fa zkV7PY3{y-1VhoUBVOqU4BmPb5Rmzwtw)Zr$3#|Bu}d`&$PET7QRtMsS7OaqSc2{wQDP zZ@czHxS$DNpCF*wEWb(z=6?zvIhP3?`YhG81*y=Aq^un-C!me*bpfloME!a5*lMbpp>;v(TQBIyGtW~AVNLyvk)cs-4%8WfG z8?@fJ<9{AFP{JDvWHE@QXbOcH{(n<#Z{XP3k%_ZYi%z?jhnxrDK)o89FLnmZH5|KK zM+;#Y7KLGMl6zBqf(8;d>rU!@AdtJzByPp#`ksb0xM@6^Nqr-Hs_zEnIQM*SoIbf- z!`|0=W2lpJ#vCE)GnS16pV1`dGQ5QDJ6k@miJhHdp<>Kk>-v!?l2JtkjSoKeKJABK z*GO@jk>y=wb46Y8tywSvkhcCkEqu+Z$07Z1E+b;ULS{ z4zVoC@K|J9B4 zW^S$VRLprH{0+Y8v*H&?Lvawb$d3P|?9U|*D z)V7YsFbnI!AMHEPT}E@X?wn>79YQJ1^4K0(Z3(IPa~#C8Uvz>%J{r`?W!7W4E^!=@ z8ePwwHxP|rQrYdA3aVnX{o*}W+&43Zov)c#oj#YrTXO0aj z8kW7Kq?kfC^da3YJ8PuV&Ow4dL`0uTcSbrjWypcvXFSZX;UP;CUT>iCOV_P=n)=L|8E0lrLnTC%b{AE zuiCw(Dq0hUbFcp_^0wg^Qbu`);wmPizHe(4Qls=bS5%^9z zSPV2hkGtvGGq$IZC;h15qmu>Ed^J?6VpyBbvxd_?aLDoVw~tj!Qms|SD?9kOxuQoC zqpd_1d4_8gH4&wkFDiSM@trZLEY8*jpMy$m+W{6B&7>Zgbw4^J`OJat2%WJz!6rk_ zjE58Y^=ie}Qd#VeK0TNv2?Sv6z?+T3RO-Cji~X2<+}UeQ7fuFrKyF~YG5owldy;pq zM+d|U@)mMaS|cx;GRifQfa^#(w!RH37kxfql4H#^tk#j`=Z=|VwJlMiFDG4Q_xP3P z*SSA>KYbxV;XZmZG`?wqw`7C4{poSLhNQ54%TMWrH<0IeERv%yvM#S#WWI;EGsg_D z;@5CcB5QQ**LKeDYYnWTs7mL{I6X#xjUa+e-?gX&J|=(AYRqX4k2fnhToJ@@CKtDH z!$;@Na!1QgjHPbZk?JhRY`YE^dxIL&V8!toKJ4Y5*p8I?W`b{{=QwL-X0rb`@+kXO z6$=jP4K{0pW-ICs(^Pf=V);bqzAcz}|5LNFO`)b&eu@-vEY~gLI}vXfLu%VS_5YCs zfz`EJh?YD;`|hoU(>`^fWNeS`aaXa$_$^`e({cKj5?2vJ+i+ntL%Y{6^GNj(MeIY5)q~f zYW+c_s^ULxbEPOwxT+od0+r!V_Q5l{C!NFd@4G0my^rgcT~kT)b4%d@!_(|I7C6!^ zdF(4LE7WXY|1c`~A!;RCO@o@4p}nS;i8yyKHak%xuVc%itDtO&pLL?0<&tt{DVYUa zqt1cSicVm^#eoymsR0E+cgx&RAm>=!omT^tjC4rV)|?7b2}mrmhfj{tlFKl3Kpl_D z6Xh7l!^68RET=d9D>x;mPE>p$TKVS(r}yn2ixoVGbc2p>UxF{ODd0pIwDN{xVk+yr zOIj*>X9D`0MHi_m3+Nle*c_{^8&vXe|GZks)nmxa93WT#dpuiFX&w{k00Ux%2ws#= zrB|@_$belfyxMgNxRdB+-d0=i)msx0Nr{{f(ahyrBz@s(M-XxJYb-DmZAt(@KwvqoWEgIMh~Soqer_3KVv8ub zTU%gtgWY*2YX%b)>D*hXm>mN7x;# z2j3$b;M}expJBBr2+C-u3JriW*i6Q6R3AB(CVAEO7RTI|eJF=A7(S@J*K5xqK^902 z4MW*{3h!^nS3rkpIg0ECfb2;$ztg=tw_H#%C$k8jQ=+{-KESHfgQ zzlGTcM%ls0L7t;EXdJ}*_F!IM93qqKnL{F%dKzC*!odZ*AaJ4Ttx3h?6Mxk%jGy%; z{P+fr=WqGIX1&H@uugY{XrC!`#k2F(8FU}8V86XEy$y~DO-ntQL&}uEIdh$7XcWm-5mX!x zM}wUn`;<}(urPhr#=A0x92_z6nAM*cm4}@_U&bnZgK6M6H_u>GXO-hv5{G62BO?xu z@~zSs*U?+2hk9T#p`pV=MtjaM)&#G4UUF>4FMo{UY$JOOW2cLpFXl&XkK!A~m6&wd zF#|EK4i7a10BEwIr=9K)ns%E4ttn92OiU77NV|WUSfxkGspsk*SPe|xi8R=KWAlP0 z(M(93qWCxa4`o}|j=E&7lXY^V**hwSOOgK2HJ9%&O`r@F@J+lt4mMd^5G1fi&$an@ zOl%cq*rF<PsS#4d4dN<$7;_H3c26?*8fr^jt}-owK1@u5;d z0fo?RGN(+RXrm)G++EZtuSV)6hg)uF40aKp;AxttC@IGC4U5mRslGBP+h9CKd`1qq z{3j?SG}#(WP0jW7tr#x$0c|$=5(ERGD8ziN%w$@ zEFJ{g2F1HlWqtG{N}Qpj&erU7gD0JykkuZ3M)J6qQ7G_fgVI^CwQ@eWDP3= zVH7mPj#N|XP&*LV_>)XYa#7YCO$LKvI@RAlotq{HnAd0bg{91_yNk$N3v4=?)x;Cw z(&S`Gaiz+7dV1Ylda_~o{r32YF2PM2LTLms>TC}9s0N?bt9?fdImBAA96NSR_?k@p zo;)lAa+1)(<6-YM}pQFOlGPVy0X|FP&vlT&vDsy;^@Ci)8b#Z~tA+=1g8%J8L~IgPMmBDEXq= zjCuuJ_z0@Q5M^7Kn?@W?ckR>%dlW3edPpUd`-?MMG-~b8!;5Kl&Ko{6->m!GZ2Gd|*uI0wz+Lo4tMMKRfi6!R!MuyoRlR~m@T28ydb@+&>@~H4LW5G~VXQcRyL^Q^u$oWBPIFhP zm5U!siAzFLe2V@&VJ~-Rvc?wYZtyixHAmtG(x-#f!lCpEbyT<>fbPkV0?OVfVob#e zaTgLgLy7~I__K$G zJ(7Y4!bE!H6z>z4G>$#vwP2qn@;t?boB`Y767H6-fj+?M!>h+FEEBhlg<>-#;+&K2 znzXfD`8zF1zAH6RsL)2Vm8FX$WMkQ*tKO3WD|U108UTbU@1a`!Ue`fbx*RaxXOJRU zN*kDZI>jAU7(9%<`kf8_g%K2!y6hWOBRq7Ie8d%OjSf*mGt3vHT9ngMJ!(m&p58OR z!jiIHC*A{(ND#ey1LrhGUNi>F8zMF7Mb&4jIuw_3u zAeNzP>pbU@@<|tB7ze~kUp>JorwgHZreW4%KAU(>Pm@M0cdbe!s?;$nweKx$tx0?UyWh6Br`q1w$py~<{_n0ZOt znsVG?nax&Zqzv7&1`e7bdK!PoI#ZX0_obxgM3-MfCF*8g(`$C=5KnY&;sfY;xwu1W z=I~HIrYZn*5b-X1>Tjhuk{URCa4G7!qpRvgluxfv=2hl%gFeCN_Ayn5pW`qk?pO|c z=rv{|&g5f)k8Mo`@|?8sCa0V_?Ik$(=0BO+U<-CQ7~XLzD=rmhHis+91GkT|q)&qJ zuv^4EHmVFEHyU5bi-tz&NvT&^^vj$tgw<%<7`9ASOiM&|3O!7@GGQVP0Ya*_*9$ix(1%qzRXpTl7WYImmp_riMYMZcTcp9(JChcJ&NH|QsF?231 zc{oR9Sy7|(;kt)lk~A=()Mv;Wy4zq&0@Wp{AFUS2PuqZe5N43#gc*Z06fl|E>A@Z) zohp**0_EzZye&3ew+-6UkqQ|TzwcIa|E=t$e2!PzpvuvEz9p$U!Ja`ue99cIX# z&oE~OJ=ya6i!gP;Zh(FcpOpH()2|hBzw$>TO0vz=NorFE7@L1gd=Zg5_$jGKtz~xG zA8`(JG1A5Vm{ABPTU{L)dQY@sqKf+e;K+gZo*aae51~UnUWrw-%fUeO6K!WIw&m*5 z>~5lQf4oC?Sem@RV0zU4>caf^I5mS(!bZsOx+4)p&8x}tf0Qa2EP5)+2P9^-TCXg7 zG%MB0ga#Jyv2mBP2<$k#4`p<4^nr~&vG+?l5$JM{AG5pc(MVGLeDc=h6xJIm{k#Ri zPEtWN(s#uSr6Yt|cpFmmAeWnZa!zGN#~mWN{O4jj=?kz1JdG7h#HkZkqxY?zp;<)6 z#ETba@OrQSD!F^wrv!YHr!3Y~tQVO;?5u3GpYyO$pAQ_CCg1V0as;5}o<<`dW>yo8 z-KOYZMc+A3_|=U*xY6WOyR_Za2)mzSy-o>Z9~BNIQ#y1>EL3g-S}dE7L0vNZzy^bH zNB}e(I=@iN38pPh+pn z+J{FD*mR0bP)<7s_4Z*`ir|cJSG+(Wlw%1LfP0zpoLU?1ct1l_Eag4{nwgJ%JYHzn)5)u zb`YboN(F_-UhRJw)+frb&1TgrQI~0~hgZW&YVtvJCDGGr6-;6ax5qysz;&NGbuGtS zxUHB3KZ?aszZT}VQ8lCGjbkzgH1Ad zKY~~Rhh(pZwi@!OTvp0N3+$lM(Y^AZ35-%S`~S5b7o|@{^s<;b>Z{1wB0-|KF3!Ag z2Ab*BRH~tw9+!eTngGXP#Pe%FjD2wz8Fs$7}RC;HxQynPE^25TBdXGbDch z{#PW$P4UgMS1*pu9Fjlv!+1@Jo$SpWZY!@Ja=z_hWOlK8cCsr1TCUL8Z|gj;fA)iw zfn1P3b>>2G@tM*YHa#^zeez$nOdPB+UYzBLz28)Kb>&oqKFD;~dT30!2!nWKl#ioZ z&u8N!y9#noB|X9pRl=y-(Rp+RXFTT73zz;k^!q4^?UP?&;Y?jDXQB&@h5m1eFg4O5nV+)kl5sXNDxQst)XG6kV(H zh!2Rg_@Srq8EY2wuwK@OY5?fpQ$MZOGM`#J%fZ?>#;#RDm?D`%4x52Yhh~Ru48T z8H;^My}opQ-|}K&_rd$tg2qo9ii;mTU0my^qz1&PjDB~B?qYwzE`k_VjDGGFlycv> zqh~9Y20gzFaEi%U^;cn@?qT31Kk$bbdMh{}Lf>`T#Y|(9D&_OqjB`0sDVBCAD8$9R zTx7{r$;{;(tw;6Q8P4qEv)NtWari+<^Z|6>IYTw;F+BV$kME5?Pe`;131~ z8BJc#dVV%BpviR@i4z)@V!fzEebr$uE3YTr(5N}RnzRcQyoq=VR+jMf4f=bd)Q7!u zBOU!C7tboY`6jRQ-HEm|mGpQOZ}@05A#@&_(gKzo}VXa{KffAG-3vS5p@H699fF=;iKeqsE$U3 z?-cq-W+P8D=@7poT)zQe&aOo_lUVWiF%UiGWyLoh`eoWXbP9fX>0Xv{82sYbfAz_q zKeTd(MIX~JF1&*6Pzu>zZob@_`M&i65dv%XXwV|UNPKebwF|%j;C3*j6j*76UOvt7 zWV~J2acvjw!z7)k2O`?wDj_oizfW>Jqyc2h?9q0|X#Hz)_+x)s)SqMe0 zAzFCn{9MDMa_6*o@2+0g^rQo(Am!TQeTc(qzY&_bM@oM(Wt?pSjhQ3BcpN-1{z9o_ zibH)cf;HYW<~58{fAZEq36{#|?*uK!a3DN0ExUd~hg=mC71y@G<|8+uT!gpWmhF#h zXHYKlbxb>-Uvh{nKUAkWecK&QyV_$fu0P=udbWyh^QNBc)6VsmeT1OCzz!Km zG&wPB4jwO+0QDuEXLBdE`^RsbVGbY@v`YmO<_G__4BS za9>1Xhc+yN9dTLQ-ORSYn@(sfAQl8cq6U=eJB`828Ev=HG9R@tCsNW7; zoN*2qwF*Fx0jpHUz0}$%Uj&f9=%_i0%SNj?oU@VOHPcAxwLYZKkkrECGG=-qTQx08 zC-@Qz!wP><=86MMN?zi2IP+Jj2jtyT_i30l+k*`rJ1x+rM5O4Wz97mbEwTpLCDBp(_dHUW2Xb%P*ij8q)(3eM@q zKjKy<9Dy22RObANDfvO;uE)q5;+^LHU5WP#qI$eUUm6VF#Wr8|2fJDSJAwPR`+7`~ z;urDeC-lBM{?=IAaAke(drzMBdT&RQReGHI?8eYc{V>s@3VecPXeI@D$eIC1#kGE@ zJ%n;X^ibp>I4o?=*ba6QFyZY>6K0z36C7V4P8B;$_JQn>t5C*;`>rq*JbUCz9*zgbhox zC2^Q`wLSkRXN}N^8+4}$CwPVLX_xOoW#_GEktI%-@cs!rjSl7o+DL6yfG1_${@^09 z{NAH9p1R0!UjDdcR}HzFCNRf69Xlt^zf^e8l-n^36Lu%!-o=na9GG0$a3?MzP7oug zf@w|EMP=x1v;i3O3Pfcx34!R6_1CcUcQ0?-P`qIiXt-`!zk~&maBo4Z(cpKZZdWS2 zW!1MYB5siN^CqUkhPrim^6o|am@Qi|yLHPW8hTTT`0ev$v)Q}A9Nf%ZY{PA4M5B)( zr<1j-C~R$b?8p;W-KxhIryU0fiz=61lp0NBQ=O2RXk5ORaRiQ%GN#mzi=C^;;qLxT zON@mMxC*leUshO0Rat#znLGeDdcJiZ6(&~Me1$HNQuc5D`h!xdb@0aXByd06%0l{r z*~oTFYHv{6EiTF~nN;E!BG?aGn5E*!r_?aS`(dzZV|Icw1Ta9LMj@4G=2h*(=J(dp zhFM2LkRS%oXVIro1($S8`3aHgXXC$6WD@NmMhxAg9IHLNpHx^r8|>%tX8bw)84N#x zKLwVa}g6vIX5{2IuTKvLM_V3e>ej-s~5R;Lm zn;)(`iwm4MapMAljo&8~#wRC-+B=TZQ7uMf7s5sBPR4Sv{?rX;5*$+6H6lK8ji;p$2eh$yNaf@%*wAL9rT@_B-RxPKFAE4))ptqKFgY1?~|hDmY8yReQ9 z%10g&eCeI&x8+LLtLXs9JpV|UTKn>gQZKS6c$XL6fWv2T>#GVXrc6_%LWY>SyS0rA z!xOGIWKzvad>)`J(!Em_||3)8_sp~P2n!JnrDG%wJt)q$%0{_!bcVBdxNJ=EVzZ0@wt(>8JZTc@5}S_ zg~nY`32CSdX2(l&e)C5}P(>YVSc8gb1@eo7lw9<~bwp;QadoolkcqD)&Pz3*r6&GR zxk%K-q%of;vzIECdY=`q%q3rA<2ohfUyAxDiyBxk8z=XPGU3OYk8Dp z9QMkGL12WAf2*-tF-7`12VzGYsqF|RCp*Qi6|Be0iQqs7hhnS@Vf2$Ld||)1r=?Cm zjvi5UF-pWIEH095IxUK2@2y|eo~Sq*M})a1{Td$Hg4Epc;ER!fa1qfbB?GEw^J~K$ zZ}eyg{2OMz_9&^1y%e*rWh8lnQ%5VhN0rDou}Ny*YK@Fau{J>6%b&Yf6A+Zh1FlAE z{Cu9?yjFUj8FEdC5BrB|n&aqUKURn`Y+^lF6{mkZ({VxnmB8S;xZ@bht`YKY>n-tZ zx(M(BTg>Va9qc}@m?MR9Cudr-${JaP$7)R5X2)ooO*zeEBl=xM9}JNAOuw-j@f+n! zNiCQEsAhWEQ;`XXt(BkJH7uVwAGMnUtO}5n3Nol+R_rhvsBW%AJAEfnRmAJfb>@-d z20d(ekzlAYf_S<98|!Tq!wNfa)6jPLyG`C81ViHg^-a5M6xBbZ(I#U%HO@Q>9iX6Y zH4ibZ`gPo-)4O+nG=NqPlpiJ?ShP{eA)FsjR4q@?@QhlArt-P2#`Fu5#ASPN@ zy|!4r@qSV0*FS1Esm(#xrGrFAkPc!5v9W~%P(Lmb?xdycm&$uO6jvQLuARD zt6kAEq=6Xrguv56vOUg1EjcXS`2mQP+7keL?;#AU-p zDfd^HRowBQ_dC73e%Qlx49!@;eX&NDM!iMtV?IX}-3lB~t3m|xpip6K?=&IPavLlQ zV{DQeNTdfW?(w@7v_ei%E!Ny{Zx)+{4h_y=iB^;B|JYug0^>uVN%b~{FG4sSA@h=4 zg{DQVaMMjbhw;J>n8-VOV#^&4I_8l@76q4`33q%d5#5YXoX%7ha9#{?{m_X{E(?Gw zfu<^^1`+9)e?3sSn)kCs8dSavAIoAo8&wz+1cichg?%2ew@-hI_%n*?Rp*8UiP_V_ zD447OS8!zF&gJM{7X46AQ+8GLtZBG`GAxzmFx8y1GTFO0a8!k!*)KGM^=Dm|>xxr5 zDk_vV3{UMg;yP&3%_E3fNA<+z@n{p$Lhiw-ev|B!X<0g}nOEfDK^VU1h1$1 zpV4zESv#(R?GV%;&PF&Nj`VfPJvyX*OSbjuk$C6a38q%&M!Yx;U=lH#zQ+)dva zA?>mK`XtdM@av>Y9Sw6R=v70$xfOn0F#%^CynSc%ksyq>BBLioebp%X-k3&8^_0^* z68p~ZlG#6O1EnJx%vX4S6Z3{HrCwA29WrW#WrLF_+7qd~(c8%qZ_%~45NMy<#qzBF zWbNvmyAuxCH7Z|bWVvXdb<1@>|MQ=7)6L3b`xX^N;=slQV-Xig5T-c5%45aty{#V` zjn#|F$9j$M*+qCvr$;0wu2Mya;0`#h_l5sc?^7I~3I7`n9ML+u)8uZ0{2oTBXP_Yp z5vDk!SHWckWg1M(0Lp*HHE9R3nj%|hjwJqk8<3ILEa zm+rk%yW>=))0=nsryZ{JM594cX$a0ZJ&Di^)8U&JC4_KQtixt43!))Id)!jpmY@Q} z?r6UJYZex!a4;_=Q9!&7xSO%{3!?d-r&{a@;m~uYDr@ip?!YYbSZd_!H3SX0o2}Nw zvHEG#t4$T{>Y|-c?&TFwrDIs?Iak#YcT0>;*--(YG7X+Q{%lu!X%!`g@8OX4|HEAI zWh(oQsuk~yPu8-pF=me`XCv4}CMZ+At*Td^sMz_0W}PH_EsSomMV@GL)CtC>0_p1@jN;i}=0t^wd$J?V{^p6G^C-oac~Ib*@mCHgH- z=RgI)Cbv6r&tZ9Y_>+iL<23=fE~f$aFez&L4UNo!c$D$TBHuH?pC)}yCY?bv(83E! z_F~sr$tlZ1f$dk|&jR!=Y_BtizT0Z2axqsu7D3<5op_@A09DcrXC{-^8T{dz)XgTG zqzz|1&fY0eIE`H>2G(qL%S&4T)z<&5&m@enBDMk)fU>5Ik-nov$#;&f!wpclQvmpr z(?ZN&U>c&6{K@m4iB$O6i0@=&@e~S026Ex50wsX!3@s#f4s#dIHOjBLBBKcswJG%` z`L^Ro11Ms&q~K2>2Yk8qCn=Xi6m{;ZSHzQI(RN zYW4yB!`--@dyrGif|P48a!$5w;Iua7XDHLF<@3`ZxEGWe?ItgPgTTrQI&+UX)Un5O zxk|nbS7@tDmpSd16l+eLM-S51#>xI6PPHR49}1Q# zsJtvZY&hDa^LR21ZhM(immtm+R++u*6~A{ClRSi#(AJ4prnbcAO9*NB@WPX*DY0#A zKrX367#_sbvN)AUY3v~}3fg2n7{S2# zajo-^(SX^AnlR;1L9*!!$zNBDde)VwB|WbX3>q#4k!xIp_LPf9HCX;T;;YH}j_n6c zb=$*WCOS&U;(|_|Xzek_PdgbC*UVyWI@JYSaT!=S8b7qmaOmF)@)TrtAjKr{wlZti zOaXhz4Q>ciZWxH?9wjDQEPgs|jm=ZrYO`;kAXYx%bvI$HOQZ8pRuQth+xJdF9GDa7 z=}1_N>JAgqJ&PcuVqT(EvMdc%glP}4NmRaL`S^y|{mVJV?ADy}ytNsJmQfBllw3yt zh0(8}>FJVZN577y?pO};uF=qQL&P5z%AbquM(OdWwAWjzjIhKAO2F4~M=`SIO2Nv! zH|3&=<0dx*)v;t*omeo*M18wYr-=o$;$6vR$qocM(#%GOqqck56oq-3I@|8x>JvFG zn?O|Ho*k}{F`00y41rMYcy1tdoE|Pu93Ij+;=(=&`29F|Dw3w|IId8j^2;HWXCp;f9C4eo&5Xh4~JNAd0?u9M+ z!WQQOk?;<9mo`WFJ(jqxs>(ghXGwtan5TqNs-Gox|L2rB?_hyDPzq=#49F4cOT57i z7)L|ht_SXmKJ)Ik)VrmlEMvkr06o~w<)IA@}Q;@J@+93oh2^8Xprm@TdN0~_uoSuJL?T; zX7~iYX~BKxe+1qV|KR}}6HcH94&X9t9W(l8did(Bp(}HRh6lkTYz8Nl;w7QOFqHIi z@ky*Mp8nnl>ke^qDy;5$dj$UrKxnFHMc?l++f()djmlpyG|kmf;Pa8?n9yU4(n!z< zhs!jA*grrLr+EmGASB^1byk~TL6qDdOg+}Uf6tRtSSqDIz{GkqCiQ&}7*~H36Vo?q z$~`p>CEd_Sd!ODL7qFNl;3aOc;#{YN=-B==umAk>jEsZdzoCsRXY7PL zzd@0B1q;@*RzcYYZ=*#gykBs^4TjZWy$$G( zx-FzuRQ&~F#mJV|U_?{S4lc=n_mx+eR|Oxy5l91c_h_ub8>Kh)%Xu2s!V^pn&Md6u z){9f1eM1T2i)^~a?=)ShY)=f_-LDd-LqB6Z2!J(QO8QHq{wev3Rhj39?}Ttyufn^X z|3sm~pz~s8ewy?Te$&80Yj>}!?k7A13FB&G{l`w4D87&_Ekx03Au)km)TWNzP7n5 z{rNf23+LykA%mXE1kM_0L}tx_Mfaft9>@@kGOp}7ywY%RW^Hv%*ZvUC6CN!kO~EXu%_XzvsaF*wFw{P zF{KKlN#wQe{S-YcXm0P6STj@aWSS$VJ8OM(oamvy6x^L0e2tjK267cLo_|&897t5~ zsn_dhyF)t8R3%@Uu%=h@c1k|N>Bks2efq*6z9I#pnThzNn3Fe&li;s+h%(us*uvRMPsK`u4xt)k<>;)6*^fj|ZX zzC>wV+1O&IDt2-r5S*r4Wd{STD^XtnokvdtU?`ucqXA?qN7X@{^c~$*c;B@x37tkc zQ)~i(J(XkBnec3g_ob$FqEc9#o-QUrYPPXT;Hkg_tg;1t77-cV*^a9N9{l%1>4({s zhQ^3oT?e>zV|ISZbNvqS3SQk1z$ z&#LZQsPa7DhwotN)q#)}wljaL??j`53AX)1x744nJ8x2@$>1PeZ28m_TI#x1)fd)# z!*xPx4!fG0EzAfK=h*ma_}j$^mf5XXrh+uo@XfIa5(_i9+3aeP0n$r9rE(Ml=roM8 zo*8K>>(L-gd;$8|+^jI!d7%_?-qb>dB#wteiRK0xM#lhU(`?EaFGl=8rP_X2AluZ~ zoMe1@y0vvYfO`rG00dzx>yA!i2Z-(d|1=b*I?fpYSd}oHM^`H40`(c_^HakwV?<$i zxRCKTTe=_o&_fg(s5icH#kk&sAXZmzJa9ze-&MR{Mt}2*AsfmJE4*1RlT55!IU%_Y zfH=v7tiJH()iOg2*{?SR^r5a|g+Cg$9SO4SiIw$Fmf{Q)Lkgf3@C2>RiheegtRV0F z3@G1r2p4&W{><97BctL+w7>QoGqw_#hg@-9^OajVR_oL5tSmb6LA&!*k?A7_pJsei zds%zoI&H?T#){kmI<4VZNUGuR^&^~9U+FG?r`kAX{BU)hSh9hp+1}H+MxTCZWudUt z>O#3TeGIE{$!EN6?fQ7ccmO~o2%dFXIw%$0v>x>FC^o7;qa^W3${9OyI6l8x*5%tJ zbNe*x7)3_o)9X&lz18u@5D%%spl#2hT=_8H9nZ3+kih~e3Mn~>91H^(ro|}<5Q5)b z(E9l;MRR~>W}0xH}H#+TZRw*=JH4UBtujOz3E4nIbD5 zTKfk2T3fI4YXh0;? zWsm%lZ2#u3@9mFIRy&;^no;nXu|vMHRlUBrMcBD#-~_>YoG#Wn(4$jYn6nhSiXkB5 zpppU-Y4t_wbTdl|b1{r3V9Rl&Coka1<-z`kLNZspTpCoNu+6T~$LTaekFFCAI_ukV zVJKY<*6NSc?bh`jGFk|r>yLL+`GR^viG2b85pc&sd!6WII9=tU!=q9sN2Qx$A{D?3 zk3`263JB1dE)K$vsi~E-{TL1*8L%lp{@WZw)!bj9!tn5;^WO}lfkpoqt=fC5YQ66g z`-QHn?89*Fesv}%k@Et25jF6(cC2X3v(YQg#jVLU%{9)J&PfC^UA4`-$LScP7bh=F zfle*e8BoZgVB-KSlZ>q1{S^L&Xo7I}W>s)>7+;nSp{yrGUZ@v$407`B+19t*fJ8mJ z>RPKL2#`_0o2=k(l7Lcak}7eS2wDRLS^hDG;lr4&MPfH(P1M<88!-4raU&knfVI;R zt$QUzH}&a!S=+!pfoHAk^hB48h7bi;yJ>+SQbQUtT!?xi{Om93+YVg)VZ0rG7LMxD zvoqdjJP4?Z@3LkoP%+>E=gFp1f#16U18VG_Wmv{y{ty*rfUV1@9FT(n2Rn&<;?7tA z&<8{!0A>t@d^1o0*a*U&8_3${lFe^gLwq5oI7pMrL0}Dah5`t3feq%cgf+P+ISkGi zW(=?=YZY!eXp|~TTjYv=dzZtR+RIlGI0o)idhR>e6xYDfU%nJf=QXfxMEavrV9yoE z$UlxveL@OB8=i%5mH1Vw7I<%F8*1LWt7wsNZ+8UQorP1RS=nOZi5*D;5BZ)FoCYB~!`;xNuP3%G`#G>9BuS0eHsW+IEV19TI@nM1N;z zbb}(Y1s4C&qEEcfvAq+{ZFIi+3{v%HyCy%^KfdJij@f1ZQjdlb$f6(Cuo4SL7_1gM zP)@0|{ZhCYGI&aJ3VaGQo@qnCo!A%~ZVDmVn6m=kpaac9AdzsujuA!{);sNu2-O0&rZ?KEqE26|^g zSDEdR-g>x(9#M8e-DOW4tZ_g_;jw8b4P1u+k+u^V=Pfr`lFHHcT_7?05DHiUj8sfO zc0)Yqy?~{a$@MAmWQP{8E}_`8@(kWHDdYk| zqnkbpHkefjwlJ_`JI;+#t8IflNL7^V{_$G|0ERUL`&gx^pk?qR0cHJKk#GrU9ZV4H z&)XP8%a$mgZcq8KmNHS^tWA{1AE-Q5_s4WEP|f102wIv-73x7qeJ&xHVTXqR zA=4a)s%bwkBwZtF7;-LGZX)+E=)4qmw-?`DoShUJ8O=xE38b$xbkc+Pv`Fpx;j^mT zDquS#=6@_Y-QC-2ckHOejr2o^FrEScE)oq5sd^hX$45IX z@8;q+SF(TNK+&qyH*dxziZIM3TcNM7nP+O6r>RvHUK$z_kYI%(T7|Hm_DtLNV#{l;XK_eRAHzy>nk$7uLZO z@Ej|J*Mg)AGvkR*ib(^BRBZHH0>r_7xqz<_9?1i6Fj<7u$vE362M(1X|HNv;=Mh$C zJ6CP^9L+1N&c(=toq+BT%Kl@VGyphbX<0LuHJk7!7&dxZM}%bJ)~)i(pFc;FJ3-LM zo_J0`$2=c6%%1j^PU-QOVvOk>Fo-s04^A%P#)H8V| ztkeZO0k7|`$B$KT*RV{CSp@|yeo1C#tUro{{DI;Q+j~T{H>Gs#*4X4P=*-K^mh4;_ zvrQ17W*~41cQv9bozULh0@ye#UfuFbqR|*jo5jg%1JOm3YDjBM^EGsFT(J zW@;`J_oFxL9k600?p?wyQYebJlOO@+%`I|}D($&_IxH1$-Y6_Pu#OIZ`U*=$K@J8W z@PEsr2fkgN7i%1FGA7HV%1O<~s#hj8N%;<7*T6`Yi zSbRsbwO3e}6o|3hoSNT_K$*2(Yn@rSFf+lonm3f|P7a`oHMB|E%n{kxW9uf9Z5IT~ zhr2H+!P}b#bMH9)5fL37_n?9u9T5@h?i3Xj&Q)Qi@%@xX4OAk#dCztG8wM!`x~#Nc zUyiIZB-zqi25EP{xXa1gC@R^Q$GNL9=DI{2u0^?<$FXeT+ZhmOR67Z~-J!C`#H!^q17H);AU zxn~*`gZBJdN$qX-Hk5BaxI}T9zkle)wV=4`rkqyVI3LVq-A@+jzm<>5+j%R!0 za`7%93FKDmav&B=@zch3_y-RXs+%B1JGDfoN#mp;(IHN$u80_Q0t@=L#mlP}U~ap! z9De=`|D{kxAXB*S?Xzm1{Q9vAefL;>f(nj(%Px1$&Cn>^gFnu0Jb18?J+3#DR9~OO zc01)5=+gH54x4dDukD%3!0`+ioCUaFjA~Ev%bYA?aN=zQd5PCLR(wzc$;LN-DVT6d z8PcKE2mSI7F#GT|@Tc3!a=%Ewb#KmT!xyA7g~*T&WrNEUk@|~%t!?A8rOpQ58YWwU zoy&qGYj>|Y@hGfink9Q*H(q&gTcuxFhG^dbj|>1ae3Fqk78qJ>LJR9}+Q{EpkF_rU z#b9344B90casbmKP87^Bnl{Ws0N@SNq8-tvAmdQ*A&}&dL!!xu2!&$ksF;pQb7^Gg zNt*s2Fi~&{z9N;%8N|n{CjR`H*v6%8kRoyhm3c})B>utOp3mKdq7S~V8yp&nh?o=s zv;p;aDHn!dsc1MLmtYtIl^w~zLPRHfvJ)AYIMmw5g*GXz$&RFWHxLi$2$!3UJ82t6 zBLU?Zs3!%eG}4A4>BsTNH?+Alu-(G-UKlx=cFQG%A8z8HjLU{9e@n9GOynZbMbHz% zp#o68lIRve*Y`K~9oXiT7I}!81s{vi#{B$1Pwo4Y2i{SpAGK@N@KQ9ofPC!4}3m~%qZ}*mXhEj`_(l0n5bZG2lb?vc zVEXcTugA;4dT{Mkm3-4s_wI|YF2=JRwZMyb(1gX<$3zB8UxZ)FXM8rjlvcZK_Co-` zq_R-qo@ady#rZ3kFHb}`ZOxTFB6OLoh7rIG4;PxzZ?2~Y2uLHsfjuO4{AN3esDN^> zmyZizWoEK8%2<1OQtAEs<9xfQC_Dc6;Nbq|6Pqtz-mEy`?0iD8GCk3}KPyWr<=ta_ zHwS-i^!~({$oSZl1s?vuLpB}o%mgZNih3U}^!#~_mW^rNP${m|Xoq^EsvK3Z#&Fa7W*XSDuWHv#yUB zck#zTwC3A`)hJeIDJ>e12>(1Q8?BeEzE$1hIGXsq$*ZbaeY0LRDm(ipR{})yq-ZCY z8gX9eJkEdIr9LLkI@!8C%m$>q%hJ^M{9V%RyQ967NSl+4%cz+K|H?mbqR%&3% zWnOw{QtG&ECB3aX+E>KUtl7_MO+!+Q6nN12kNKYkx8<$1i!(&kGnzb%ERYa_mOi^D z7#!og6-K(sNl3?K@svRK+|+7%QtA3`EkLQEn!uLBe zt(CQZjfUeZiteVj*;bCHh9;%+QZ5IkvQ$cgPtNFQ?z~reQWZ@^6Swnq>`bIfnuXR@ zPyZ6A%xv+qDbb$}P;lig2F7tlUdgH*>j628r_939orEg7(OUs zb{>GPCv(YR@92C4f%Ls>P99oK%za4|5UXA;v(9`n;!wSDx)P%K zXNPdugnz`LSoVf{U7i>N8o@X`;#u$HDHac$%?3s=?E;W}aS9Nt2rRa;yLkjwJiN_s zNQ$FicI@BZ)<$`N4eXE$EhP{>1QfEb2UqEGpo-L+wK}-e9yUA$Qs+%5~*wa3&=Aj_W#9bM$iOxHd;HJsp*VwvGsC#gH?7U}zzFygO4r)?Hh{dkLw0 z@#jfPB#8btw43mc-|t_7GWOJB1D24W1#M#Te}H`eV&=|! zz*lWQzP5pAYo3a8>i0I+RheOeUVHHv**KwXFXIu_=ZtsszwI?VtixhZljIAqv%B|S(uKb$e zfS#`k91l9BstbDM6^ITu$7mFpI$QGvwiZn9fOhOZsC7UJ!PO2OJuArcOJXJ3Ie+;r zlGKt$Q+gR9kjMywmy(v|N{ZY?PPa>BCHZAyx}(u{h%78kvdKyE?;FQUj~SRAp--oc z`T7+CQ25F-XXN2X%un0QZEAdk3mC+eb*$bs5+`>FP2&tmDFA$7LwU9*lbrxLIzT7| z06%XXj@22M4-_~TFWLQDR5c;S65}Fu4_6BJ#aY+{@cjfxQ|kkX)O6q8Uf*<^a|!9D za5<#g+F~t_?$oe;s(8@STXI)45P%fPFQ$>PylH>`X`bc_ZdDrx889GH>5vf5F8`}i zZeXr3Em;h=ZwUuae7JYSvv7y?QlBH^`R=Y<(3S>=RH!{;q8K+YUkMdCslWn;YIRgB zBdlg9e(yQ+N_xk!V;!qfvI;RN{`9ikkVJF9``e#p8>4wL`Ee&_m;e7^{jz~f-%1KH`X=-H$%t3ohhYnY$%zL<*drVI#@AoUcE1P!4W3%J_3n>uvZ7=d&&v(x+dn8#lGri4&@( zauP7IUb7?Lc2Di14NZcQsSWoU!Olp%)Jzr|Bw~=XoCg?w`UeZcio!9dt$q}J>R!5Y zp~pjWU^;IoY(>23z~f>=@9qhp4H^`ljia0SZmS|9pw>{8AgL9wcC!6D^8 zYQewSU+j=jaC(EjU3@HXy8cyHxImA8I7C(O)0G;RTmLg#OZ%p#1C8e7jgI7PyJHmM zvXs1TKrsiT5c#^$g<|E+vKCvu-KbTkNGy1;vUOT9RmW|D{UR)XZy(ZNR;@jV)AMKsk-2=c8LFcAW65nK7PWTYqtq-g1*mUd6|8Hqrl<5jS z_0WeSP?rvi3J>N5PK%EN5?P4y_pxIV2{|6+%i~|*p1eEbR_E z6A{y!)9Odud5W`h%gtbJ_;+_onR(Kw&ISM99a+%&(aI6bRaZhgxW@S;R z6?E+UZYyx2Y4aWAz*r0z^BV?a?Ibp-%>z-@6djVfk@D+bgX&hVEEwdKAGN|iLt>T= zfn9-_js&?(I?6J$P>=+n4|TIsNN!tBtTJdNRGn0`*9ix9=mJg_Kpa1c?}Y!`oIW?$ zb(hZhW+`>woAN<``mGLF$v10qIo`+Em9bGLHQPFP2Kg`wd3F%w7$p+dIOhJ|2Q3Fl z{df>_)?@0^|I`}6zerM*_*ra5Iu~1jWqr6`j#T$Y#;(rhdy}1pJL7>l3flcV=m*#` zKh-qS1;S)loj$D=gQOA{xSYL}*a9<l<{~3RwZKHl3 z-_e{05~p9yYva6d{+Kopnwd z8F|#>f)g^^f7`lRq+C0&iE{ia?<;+_TqyBEaZhSP@Iwy|;PLzv)0PFytf<-Y9YQT~nY(S|{U=0Qe1OpgM zP-5jIXnVFS08U1LWYp6vaj%Y!s~BRZaSVjo^4agHrk_)eJbJx(9NK6(7}gB4|@u-s0*Tm`tdW*JOz5#E#uGarkZ ze*d`WWJZ@s;#TA}43j0*ZKi?#`T^dxcHy?vC1?S710X?Q{`j?P<9xeW-v4v9GVLX> zGVK-J$3OBIcKq=xS9jU+$GW@5Prlr^Yn*TMH){h7E@!oSQ&A?Qw#Z_%3;3)Pi`;25Lm+>R2?TJ3hdy{bGHn zxi7YFpf=PJA1laQO^pcW7i~+3UfIaFqG0&r-S+T{Ta9DHO z{m`dX%}NN&49jr4J}Tw8Ul42vHSL@4vY7@7$wnC*PtgIr!zD#baTyy|yUIl_L592T z?hM0rdEiU}k2hsfDguCNM{ui|(fc$=#z!mHudnRP$nYLCD=Awy`RK{ehO&~xq;V_c zRV2JWDLF!!o!>v4pBEnP-D>_(%a4lUYd?y`qcoD9MCl$M|CFB~t+X2NW3{EF+Su!2 zaYhq^dM&cK(Sud0VPBm;h>R8B&U8Vl;t`2C3R~IH|@&y9_7^?u%4tsvC z>1eID(4Puo^7;M4%^y?6CYLdI3Q*`|ev}QH86{u~+~3&}E)$q;y1=qz|3F2CR>l%( zHJ)N$Gc+i9V`$ob1PW1^-^r>nA~OoyfQ_zJ#PT6&cxO}oQ1YqPDETWDC?Xp9B7tH6 zSZ(y_(7lCTsR;+#4Q)+OR)vkgvdD4RA`)H~WD~YG3UCRn3fm(K^qi!4DRVtL zeRqq3A4XIXuDlP_spa+n1ZFNM1;;Gf1+iOAXwe#QIpn7QEjZcy7(dAMS{2-c3ZB7j zVT(Of?u#+ZxZG&F(y2eR+|AkYb&)1%hyj>B5GtnIOl5#>gY>$q=HcLKE0i8?>V73v zZlV83G_|p;gxA1MV+s-B>z(+DfH41jav^14royv|$qNe#$5vTKu2&s1Yt?5p9RgR{ z!N8MpV0mcN7h06+_0G0jI(Gb^kk>YmO7p2ZJ zLCvyr=UD&y;?@0WB!eS9ZP8s1Il~jk@n_rxf`8ex6aD0P%K$@!RO%Mk1|u*CUwQhp z9IggygU*UMy9lhSJRgAPQz0y(U|eMKA*u7=2cA{dgR$BSM)B*WUVU9^$6LFpMZ+!+ zNrRPsnBOYPCkH0lNSi(8ee?W-YmcwY`7}~ib>VqqZ{C4`rj+;w_jXZk-Lo&3W62UkIU#4xL7iaD`17_OZ5t4`bMM#l7B7!NBvu_Laqep zBlVuH78ldZ*d@*N3p((t^DjEdy1JSJ^8DQW{tYQ{b?$A#?1;5W@>xajT7EQ`6gzVL z?)KrW8=Gf4-sJ}=q92vgE3naI9}eFqSXUAyFG*W(n}HlZl=ZL40DCG#Ss~ZBMcBxk z7$Og*k4R0^A{dyB$PFVw*H^dqDv&{f2p%_5M=Rh2hw6j4>Nr|)-nE!e^Tg56?ADkh zV_h;%c$MH$y310-dhZ{@X3)h)RV1aQb5M;#UXUP1;NzkmoM`ZPbKtmxoEhX1VN-e1 z$TxmHSklG&7kf-6htDTL% zWiip&?%6?_ST-a(FEF1F&-P6UAv}9g>bv@z*o*pw!p(sfIcoj5i9D$!za+51-gjT& zJ==&!1&{6)-+fpBETdSeaj|T0r808p447hEe!j|Wjk3N`H6kED<~|nPvvshqJcwyV z&sBo_u{#{#lj1qFlP76&6xa*!3GsIJ%+qlIpA35;Q5g{0A00n01t?OD##A^h`X*(0 ztQq;rVhhcFhwMxJT;QxuakCM^aY^&N9$QWdB$BvQiSzAwe|4mHNtu=2Y!Jb9g6$f2 zZL5<#>2TLarmc~)s-X#?BYftLGa6eE!9a6n2cJ0-AF6+E`*6iTXoNOL#pI?7GLiu7 z^qOa3&ysxrd0v_htj$PMgk`60%}AC1;pnfh$x~NFhw8+_ooqJ+sQ0tBc32-cbW-Y< z?GQS5W7)JJSwsUtw#WS@p`UG3zgR^5i=?)pmQQPv0k%2v&9x)rrl<{7jpo zLHoT7P&5Jv1M>?suh@LLV;$R=Uh&DkBWM`Lt*VtJRD=D01Jmzk4+A)4*&EiVs#-w zfLuQyK5HCH@4oqNWl8VlW<|6QF~v6CQ#~3|SFojBY#Mwu*rB7dO3s^6JTy$Z+I!0G zibUT0u0z;sWSQr$+mo%$8%^;`^`k|h_nuIw;Njx|j;j>YUO%clL`UDLHXq!m&1N!9 zQvW3M-46K0Uq;VR&$eGALA#)qBCB}U;Y@Ecoy!g~tHFTaQluO`hB6D=e!VBH6p98) zMlCYmU8#$J;CB>$Y%nt-7}|>NB7i^ftoU}7<0iRW2BMp#Qf1=Z!4g}9u#nDh9$ae- z9^)A(u2#(DiMUfJn<=g+Z>~zQvg*%EY*5#!S|JXM@q~|A!g+8C!QtTlOkL-RRaTMD z1~&gf=>jcJrT2UEr>Blk8BK!Ew#+4g_g)@gxVtZJ*S>R6NMZEtmn%Px_>uu8i7t^y zgF6=ZaF*3v(#c`rlWe)Tz9^!@qnjW=>dLc35feQVhB2$YUj+y>Rw;@wWUkFFSqu#4 zmHE8$b?WYR;#@s%$b8P^MY5BH@L&jk{;FVWJ-+XJcx8d%i`gY>Gh(;*l^o=s5D*~Y zn!x0*k^}$~n5k!H=t?+3O9)z>08XRYd!6vej2@6*O-!}Urnig8l6+owVQOP- ze-|qb{Beja8tKCUWjXO8M3nf-pd=&M6hluPEX`=W64Kk6Bc;+C!q37V_uXCK9dQ31 zCsEDz{dO0Nt2SByFoQi_CPL)I2b9r=EgCV9J2(BnMuzxPZ%b&1G_9>?(qyTOmz->y zMnAgW32+jLCSCA-j{N?3>hpp8qr+zC%^!G9^+z1{!TU{U+(6$y2R5VI!uorXoMpk8 zer4_hd@=@XFKGi%0N<>KD3EagTh^ga&4$oX^2-IjQ3M1h{=XtKPKRz7jKPvjB3y2l z$Vq-f)npC7)8vB8mGG?tG(&(-!Li16Y3Yu-wOT6gdn=qtD1LUUi~tn|#j>97(9p8+ z@nwLMcuj!?kR;?95DPG7hw$-*7?Y|$4+I##wE3P@MRN}DT<8x;bIHee&%#Vf31gc)b^(W<_9qT$-NSzpfL^f>ztCPPo2!qg`X zFvhE65QM8f7n~x5Lx3VdmQr}uWti;QP1GX9rgg(Y2{?}7=%kRbTg63{9E@`(RS=Mf zkkI!6Fn~=&vwTNnl8)0&v=qq+Cn;b#u}WQkj>>yD{j7dY|J2l6V2#+A*Gi4Rg+SaK zAN?*(O~oi+@=!oD{QU!dotH+X`;b61a&P|VKT1%*-&uGYk?*ICIZojl2ZI+ zjheR`lq&>VOxjmobrOdp39{l!{-rAq_G0`Y$5=xgljfXhLn;NkeYH?939*D>o#}?PE++Jhb&kokyquqUM`mm+G;4DWJS zPLJCW=U}-r!w)xZR_%t*Vynm%W!>I5Z>@S-G)mc~vy$KHTaXRGz75ykw+?b*Q>tBZ zi#JCX#&`2J^|o+jv74ic9-nP>GDp%n1Q3+CW=s*RIG88;Qa9YNY*D&}5ay@a4O$gG zRfOX$3+>mOkzR;o6et*|--!}cUZWj>@tvFf?phaa=?V;hGh-pQsseXg;FSImNWZ>f zS$C=De}d4fYwBx#S#KD#B5MZ#7ODTiZTfcg#O1nQmq5;aw`Ung@<=!6f=tVdz4A1ZGdy4E+?MKT`@-U>Ws+UH z&t|Kz@>9NLZgH*+<7Eq%eSG{BaEONZsP^AEW0$1|_n+IXHofS?tx~_Pi^twn^*Shp zeDUIQ2G%#$9=AB8Z_xcnH*eIlP{0>XbUN4Vp`M854^#8h&i2>_`G2U=Jmmd*(^K_x z#8cDPt~&}KyPTkSOZ^dUfN-7&_%E9+Fn_c` zaAsHV3@_bM@F(Zmn^C^b7FBQ;EkfDq_%mf$|NLFZgJdsvbk5^|nBHku7$A;6=(=>9 zaC|<_eXVVP8f-j|w6pn;3wWra;tft(ZIm2Lu3A$kK(JQBsK5RmBaU?uyZ-(bWf23& z2I}h10HkeUvLWMdi+&{_Un{wly)@RRF5FDeXOw}mVmsCZFg&$E!)OHQ9 zT~2R`vO#^Miz6eW^tnlaSrU8)s`H=R5><((ug=YSI$Txgq9dD^RkQdiEe@Qt{fw+e ze&0-<%-10)U&=d@)!`dOKs6yhTL+>&qnZa)wCw~h_r%a(!46kh+zlJ63)2mkR1K5n z-s+9P%{iJ8AVr>Smp+4U#J~~m++_yMGh3z>y}&Ye$wzm8fEx6xiQTe!)Q8$LTvC5#JEc?MIRr`*^-{hXScFr?J-^NKpFGW@-h!UAIg!rcofZ`7q)7e)oaZB0P`Pah~weXQA?g5_^$(vFZk#02kDw@bCAc_;re@%K021Sd( zw!hp^dKu;9Z5vQd@nE3sfvvOjNl!4o9)!Q-$hhBX^d z+CBgyA~Vx1yO>VRl@2)M<{I()xA|#PQc_ukhuuv~48*9xYK7>>k8$F-Mk5DQ^xNZT zdu?GMz+!{4H&+5;BHtJrUQy$h9`@!ajWhz1X6(pnmM^Y~Z43?je%R#j_pk*DIDm_Q zct_H1*ay%?3g}R3MW3vaj@D*V(M^XKjmoFl3Q_L(U9A^_z|3PcG%_?P9iGwxviIqC z?yrJ&?{^7QxMW9`X&K~Q<{0ed6XxVjvXsDY2Q5kX-aefxv z__;w>S`i}|KOVoD!f*j4Eq|teM{8NY7bX=V_upo9=5T~0IA|9flYY;dR|m>@a<>zJ z$Mx0a1rU}<1ADa_N8+^ql*(zly2_~}&E1hW>G!D@kWa1lGsnxw{vVlj{e$1w<6JMR zxV1|+&sp!PU}7_|FU|_iaID&PW3hP|P*7gF54jDo|H9pM+lU!#P_Qw0Bft_GlaT;& zE0-lG=603R3^)6MEmJS2MB0S_*TYUH762dei?8aw8L6o_zfvfCU1DNYZ|~Nt1OYN( zB?4OEhl_#Ek1H?xl#wBf|FdBT-I-fvV7gyYA-xOZkZN21G&Zwy2>oY+Fg_!rBv8no z2oREhtne?T@P)CgZ?qpL@c};Zw`^e3up90{`%|N46O3qdDCe4!t)=mm1RT_|jp=~^ z25y_^ahpchv z&8~3^L)79GYQoK%3r((Ap?+TH_$=y=YjB2sFTV|<&(kn|?oW<NRqF4sUz3L0c^@#l}9fpk{izW4pqxe3Ztqn)Ia` zeNu(mcMLSzOrHiQBBI+v zP;KSOAW(o3KgLH76* zoxHLVZeVFr-ZrJjYUU6q1XX0Cf61MGjIjJLM&H5L@0nUB8A#YOcVak2Ci#vMq=#17 zT5s_M2E(MyX>|WjvrhErQP-H%6Vqkblc>qnCH}(uKrKU1;XFMJH03+Ocy)llHRob; zeLjDYpI9OO+8u;5ft2o`7~H4^19>h?Z%*gr;3x4pTXJq~g-Mohqsg3` z3)s7#V(9&u5y ze=(vC424(Nl@D8Wn@Cv&DoHuB39ErDum2|L`@VizM+TrTIvgx!l?@=(7G$dcW%1@a z03Tf6uzzAfu76E@k2a}w$O#Ney_rtGzfX!k8UtfRfXw2|`kX~zC~W!6{FbNmA8L#D zL4q7M#Rp8;^NAq^;6pp3Lr4Ih4BSb2GCKO?UNSlBZO*epLV2j@p#MVd5X>RseL>S~ z7oJ^;k4jqs5LTVLNA~ap8A`SQW%8)dC*^dbYeTy7?^Xcz4k1)Gl*4a-D~~Th?pZkt z0b`K8HgC#nUi!tApkkhH2j6PO{#y-qY|f|Thcnmw!LJjZPtKRV9Nu&o5MCb0!B{`$ zj}&kV>cdfiIEIk#+6K98d?3KH6klf*0vR3KPJX%PMQM~NTcUssz}|@fC7}Eq%(K!! z=bkL}G5=?Fq<)VA=%8nzF?l>ru%b*JE@nx%Y5EZUrs#uj2%*ZaFj7Q$y$ zaez29ybVNGqJ(Q5qKQgEojavZM{Fi=noDy^twqrQYC~IB_S{i6jmVT^K7wBN!12yD z;S7}1{qkUJL}@92B;kQ=q_l5$VJx63FO9$km*027*rJurczD}u&__9jNu;rl&SiJC ztwjN%BCko|jV)vczLu(I!e%0*^NqzK*Fq<1Pl_{5h`@sw40bX;q-cPXdDzX-%u@70 zwDBKHx5JrV515lkPJ3p!oO5BkW?taA>@DGe%60*phK~bT>RB56;lGZ}XRqV%G2i#t zXx9n?H+Ld1=uv$?KX5HNdgnYkYJ$((yb|He?#+DOL|v;Fn-}L2&N|IG9Z^M2$fjj) zy%a{NZV6PL^I>mM2I_xEZejbJ3){~Vm5J<TO*#B4#{O93PZAQjqMQoEMNuiTfB=_t4IU4u%TjI(@45GrbdcB%M=qnfkJ} zJd7KS^FHtGYqCnCg(t8H8C0euW?xR^=5&!beShT6$g}AZIfv+ucZQt49TY9OEsefD z`x~MB=a|UhLzq`OcsMrlGNJgRdCS&==$D{J{+o%AOhk4~uXUz1JdD{z&$f%omzo@q z?AGiTN<`WN>fP%7T9HJ!KSJ|If}e`TJX_7~PAH~=tZeLlZUmg-v-G6mhc%H<0VaG!>N8XpVD3pRBH zB@OpMXW~|`Za^L;JF?3)1*oGAw222G=pz zwb2>$!#M;OjWYz7rLYzSav5&XehZ~rz# zd&<7>Egb{^=ncJaAVqHn1^^sw=l-G~MB8J_o5ZbwpEm{w1f8R& zfl;0y;W!vnOaUot^QZDz#@Lg5tKmhy=GOLu&i&)dT>6OQD4VP7zq(ppuj`cw-qb7% z5!yxoiBQqX&Jb~v;qIfwE$3_zxHx3>N+ONuNnqLS{daVi(a<1Q%V4}Yu*JTHw2M?@ zzlBsSJcjC>@2fQB;P zzMQ}Db6c7!!Xs1dHFg@ckK8i92njDdSDMCn7ghrnL*fSv38wL;wWBX;17)-YQySC8 zd+Wn5ghvUq+=DOdAKAT@ZU5IKEc;_EBGXF9khAq(*O_O**~t4+w1)a83!g$hlY)Ob z==W?;qWQ-%eu1!6_gb}Y4*1iU<@67+zxbW8{xm_hShWy;%c@$Mg zca5I#F@1En`qC(y9e&0>E$zM$6jcv?35Kb6>%~Y=={_D9n-G;G{E8D))s*T$%Itj^p)^{Q=v9P{RzkC(f6l6sN`L8eIP<5F^jQT0LO{6h!2>*R z-_9}HUeIYkI$>rWf!A|#GW8<-mX=Kc?&Z;W6Z~|L80hdK(!Bz`<*%x5H-gII&-wpWAOxw+sj8~^#nVgG$a#Gdtl z=?saIJq$)uj^bnzJ=XVD-*7+bzKbyzeU!25!ASfWJ;7Y|41d8mY7$>`Yi@=+s{+4- zF_)PWJBRXp4QDIYSGsYqHy2fEZkG?qK0?{w`Vo_Yrsf|BnJ}tFxwB zpnMZ69&91p`{O`egHz^CZ$Cbro|C8Xw)O-YprIrZi>t}D$qC7I_p-OhH0g#;Dpoj_ zBceA_%4gDEya%;=JHj1KT>($1n$=NU4w}C)=a-%85>1p*XeSuky! zMKxN3vU|V!Q1oD4JAFz-M-WPiY4`%D4wxpk@9FO3|C4{X{b_J^$J-tB_ z*=I$})S!T@D;6mZVLmY&*bF!Y)ZP zlKN}}ZQQu;nPuN0%FQe!@=hS6+V34$a)J8M+^F=xLIyBgR^_8I06Fbg>CcPBWmTq% z)@jPM$%-S^Stc5M;V|;%d^9>7>^(2F3w51eoaTLZ{OUVb5;j7Owy+)=f{Z=VL(Hd2 zX&5>G54z2&>jdnfaIS^6xyX}(=Nj=Yl^J9{JblZYBZ}|aS9AQ20L7_UKQ9=~^jTU3 zJxlK-Vz21EV_6J22a03YMY?AS_<8n$UE&Q;5j2@rMJ-9s&5yl-h%SLiZ8!FB+?<3& z&e-%k#^{nzQGcT)HVx){KWQAaWa_jWFZgqJ?pF&)0hT^O-2Sls>plPmblcBq02uj~ zZcy16-MN~k{O!>2Z*4&X{2#uF`6h@ZF-wuLKCuH6T}gGKB&9bd`(E|k`psSZlV7+a z%;3dOQ{LwtqCdL6ED9U^)%%YXAOJ*kE=>O$8DZ11t?Z7NP%D;lkN*1NA@Ozp9-z%% z7#il^AQ#)UxnVo#93@050`He>z1v@VVN->)@2{~BS3f;BH#9>gOlX9C{-Ur zWLx5Mi0HM()2}#o&NEePa3~597AbSC>eZfUPE54UkDJhG*g* zE!!0B^dgC%B7aR5u%wopNTs!+-myn!jlxHpG`77;3@rNyfn0_GESJihJFVDfNF2?iK7=~HI6wiLn{8@@$N?I{l$D{HD#!ph6uE`3W~KK&1M z4QPdOG{!28p;u@dDcVxz1#}0kR2355!)YN* zrfQ`i5jYvCvDf>BDm= z$2e#VOpBHjre0Gid7*~&tq%#wo*8BsAwZuHW!>Zx8|9N=8qbOVn}|gHZs*pdnsBd} zc{Ns5gw;+U`axrHVr5ONCy7R9#jcb@aa3lo>XvFYg{qMDfLj3xP9z$C3<%XVg+A>0 zFqi@#hhoRBTjqz$Rq1NHoZ+Du0xUdy^IC6|tu-mybUWOw#m0lcBzfIJ&wW64NNlcF;OeQ|i%n z-@@K{$2smr(}|^8+hl3mi=^9K#SyMrp3Vnfc;9;wa1hz}*y=v#SJM-uG<-9&?$zE`2=ce%&)t+>}&ijMF%o%znIN zD96w*ME+AA3M9|{8=_SQrzKM60{ymT5_wU2o|lsQ-gh%M&v&}o7QHjbD}3df#yA(T z!Rp9hFW>MJYdN|8Yq_JiAdNccZRk1)$P9nc%A^XCsczVA3w8+|3X zAYBB{lP5p1j+@Jy_N(?5m~eA*1G)JZ%T+_5g$Rv4Az{xp24n_`0T9n&vnT659$niv z`iM7}Yg=HeepvFYe4;}?j#d}Z~oiee(`(S<~v4v z?pW#1cB~UTe{BjV60fOKmdj}s-ElQR3X?r-=%2;Fhe}lW#I13bn@AC0vYdlqDir`2 zkcc-X0?Pn^okQN)Be+27`f#!aDE(%FwzPo>29j_zW#rJujE`2 z>Cd5Zv(MtsOb821cg;kyi&7_>Mvd{PZNbH@f4sh*&(3jDQ@UlvvW+Wa+QN!yZ;?pF zS{^-A94Cw~?)~)=yfxBVOxe^I2c!hb7x~wL@8+r$>I@g$2?fLzrOW?6v3c_Ua-xp@ zb8QU}H9YQwvBN}8&Z4jraZVzmPEMHUtHwtn$z(Uj?T3XBFL*ey!^E~aC*S_Z-gKSV zZ=Z=Vj?Q68BtDLckMX2l+e_!pkB8Sw$$jddbz~=@kyH?PVD#$M!1rR03qnf9ua7^T zAGDVIB;*O1a+QBoLmrDi1z#RlbpKeQ8i#Oy-|lSv4`x*q@33QTP-mWHKdeak%!6^% z-QmkRxozF29ox2#hg(O8S+&G^akAV1H{RhmVn}3p@l<(Hq#fpn^L9+lXq~pKRI4c~ zQRC5b7-phW;c+?*8^;&)%=U z_gctJ7)NwR7=?4+KkuIZ_GQP)(*eCxatnO?o^L4RxX>ynT%sFyD-x-txSqs z4Is!88^hzcj9u7ycdmuR7#`nWMdNj=-Nzd-G@L3gI=LR!aNG4dP1v|K*J}QUNSM&^ zh}`rr(}Np*O8B5MjkPu|HCtf>!rku|nT&C7Z|f_>K602xJym7Xaj+ zSVGTxrPQ$I&jDtZZ?hn^{FwC!1)`ouW zQw8zm(qM1e^B)WL)tqaa>+v^EU<$kmWp~e`c2jZATLbGgC1GKj(D!cl6?Df7_q`dh zrfTCv`>{FIcBP+AER<<0eH)#(1LDUwh9*ZwpYTI>c&_{~&VmS(Al zLT_jKRurI1hm|J5rFy#~43TJV+~o6u8WkQRGamREE?S8% z$)c9#-$$ZQfTB0M3f;#AG(nptKV{IsT>{#4OP9B|9UZ)Mf!@qke>>2?7I-gSpLHxe znEc3LAp2CJ7cVl!0rF5-@is zADf#AjmLEjbd_F?nR5ray+3dwA}O+bf?rMR+SVg}gU6|^X*2ri45764Sx zv}ms*8N+TujD_?mt@=#dDP0Y!w3;o!=L)5b*(SL!NsTFZO`=h*^MVB-^4#fmkh#ZKCrOxxZ4xJU<~ScSXkJ3R9&q;`r<`75txzk>wTY#oOKOy%8yY6E9=X6 zYZX5&s=5nK=sna?l`3URkz{R{I;x6$H?QkrR-sNG!j&`a-wP}l;*W8m!tb$RhX$gH zZ*Sdsqf&M|I7a1^9~8!$s4G)}>I&Z4`m&51RaBKaOtQA6NC|7DCB}j3z=8Cszv66$ zC2?A4B;??n2?4076=%D!gt@f?y9mM@c!2aq+7k4YsC?|dp{`Ux1diUyNpw;?>H11< z3&5Y}pFXKdc1UiH^fU$NdUVnY-7G5W*~1;4F0MkO_O<91Ohg5pT+VY8)zq4Dy;XKFoFrx%IEw?dxQltE(=z<~&@+T@v6N zp>T^rDud@2rmN$VQzH&PJl;^6Yfcu+!X<0XF>OQh&Bp1umd^Fl9oK?SbZ?Zqc&{k6 zsQuqhBFHljRfPiS&&Zd1dq?%TaD+Ge`*ZEKEX13-gKnA(q&wJ#DpzNAcw^6Lz+(i||T@YwSiqM=VUok6BoN zsLgIur6p4(uO&N5;`hrZzpdqETK}YgHS9Zws#&Y*S=ARb6dgtzdV0ltHZndZMkfqZ zr{s?Jm}kd+8@YXZZSQh_4c)p)7+ew<(cyPptL{>&|CVO1UUhNRsC{*2R{SRkAn-3n z6l16DSr7i)o`X=dQWJ10OGd!Hx`BicS!$nGu0s@^b3D`BF13^y(a@vM1>=rp9|P0S zQjE@S3xARPPY_oojZTB49`|)8_&=JN`Mo6Sxc`3x{Tg_i1fp_vT7E#(WrQCDo z64WND>{WsP>H7DpwT~(`p-1%8Sk1UNktejW>II&}pU8AyF_>*Eg~nK|J%o@V+_m=9PCFcvG|wm+3pD4BPs7(>F-zh zjSsthXA@`y)7!O_X4{+f4T$omzyhRKRij)LHh*=JnfSwgr@xV#YX>KdB*mvC3j zHPnr+9eox5wR&f%rOClO%-6oARyw(F?n^_X)7gL6KeH-LI>cPew-JLXAIksAUq9BD zGuYozifz69OKpaLlCQhCi_9vM5v%UleBteIW@Eo-7M-4lYBHdor5Lcv>X59_F@XGkW@laheSEn5H`)z547RZ-g|*DBM* zQv~6bY_CTooQbxYbFCZSVK?M%6dQjK80*SAo&oAtF*O4i~ZtiF&`H`&Aaz72$T? z2q(}i*FzmN7D%UuCJn!4xRK4sHei3(tZ#C9NLt`g5TAZPM8H5Tp;G)BN|}Dl#z(+7 zP&Pr7ejvUen0g&v=M(b7v!|p3G7y*~L`!oW^QV;gUQ>J$d72<9uq_D7-r&2}(Z=Ru zcl=!524w-QKzz*l6fqnN_s>Gh@{?w|lpBP&2!mFmsQ&GDZAn2Q18PuhRl|8+qK$j{ z(N9$Et&HFp#`#wal;tD?w^U?d@(em zE<_J1j&wLSXvdCD{N6rh+i0RNj{Zabju@(Us9k&#Rz*&htnpn0`{DRe=|jlP%v1Sb z%Mnn<7X8$^ff=V6x4Hwro7mtsjvuId?s5AzSwW0oecrDBPQ5fS+Z<}2eCjQHMgU3O z=g#Ng()gVh;TxykMtW$x=J}l5(v04+r4*Cs6~yaygoiP?HOSg?5h=5?mG4)}Ho6>M zyzzDa-s86yhXR^XTSaqxXR<@KCMF<`#SKkQICAT!O(DSjqWJzC)zdJ?MWeN|+4P;; zYTsi>*=~J+b9X0x8Rx|JD{r9|jo>gxt3!l_Y;Ok54aa8DlpacDCe97{Xa!1|zn6Nh zJYTo@-J9*uCCFhAn6lIS-K(udD-I`c4>HQ9H&&)71H#6gkM7%QJGBWtZDJZPK-SHy zZs^KR|06_xT*z1XDTTgVrHJdHcH@iq8o5R-DsdCkZtbnEompMKCN1^Zi-l_ip-N7q zfE}O^2QVUNtb!M%MpWb$TDNT#;IIw2+p04OZ`dAp>Qt=Vc7kY!|FrgYW6gE}@>&bF zHwXka)8@@3t2{w|x7F&7fSC3KlxR_1-N*ab7niV%KT|XEXM=e)FD@)H6o26hp7gt0xsVYf;yR~&uWXROP$^CHW5~{Z@L*_GTKD+F=M&{x1nmU1A_+%C9phin6 z>d5`_dfO^UJ-OH|+grQp=Hdgj0bt3g2mweG>8|j~vdgh)27-y;him&^E*}mb{OzAM z4dAQD7T$oRUC*2AU);m@ADnr_Kc;7{1N6RQ#p>D?a=gp;E zzd;d}@GX)0M~uN4zW<)u_&1RcqaVJGaYzs<7dH9}<4|6o0}=z=EDq%_T-Yd7IwZVy z{4#H1D2ambErFt#?oWpc55paUDh3N11>yIcgnUpPyXD*lXZe0{F2=mMl6MJS?$ zTQio9iBdvU@XZLkhiN1tZbc-1tz5dHi|E(N#C17)uVnpaR)5!-t9{NfH#c9Dr*&NA zNA?P;WPwPZphV(bCkgRowKL!EA^mST%!!VX!ZNh?4F9WZoL=UZ4Y^r6Mj`tWgLxWW zLw{#Owbj+j-rK&~8v6Iv~D2D{7H%ml=t6e zX`MZL?6b8#m)>HHu+!bh7UJoRtA?Za20Ahl{))vW{IZOnY=haRjC2Y6>}@=XZ*4*H zAAl@%O^fuu!*4R;rg@PoxxX7oFGy9K&Pf?c9`h!i z9=lCE@M8orY2WyND=NzyM96s(Sf+J@-4jw5b0T*CLSf6w!i|RZFHg< z?CebJA%qrU%$YEVt_@>x=&f@%pu4{s^WVYeK@P-vAo96LL5jq)yoY1mxkdt;P$*rW z(`!x>9EpWQN5ba;%QR+VfS@L{qIYXdbxdWAYZ0CGjKBs`s{K9uq=DE`DTz3V>3+6s zTnZ5i@CzZJnBzkJU@#?y8i*kMpj0CeNdz*?z`?L~D{Rib1bvgKyS*tv|1=G2Wk+!w zo}e0_20um`8e?^rK39_wTyMXmi>+z%4Gr^+4Y8(z{2(g!13-?Adf?b@n$jpow7s)* zI`|XVGJeA6kFEm7mMx5evCyuwmhQIHD5Eio+Rba;`Q(q^MIsuPwj8TCxTZBsyaN(h zb8sql*>>e3(O1T}6}&$_u8Y_;MjVTaAG3S(aR+`@4~=!%by+5mkJzISNHq>S5X8<& z2$j%?I6lrTq=Uq`Ob0pjn#1rBER4(mbXXFi-r&0nLzllna$`R|^AomP4qy8i!KruH z05HJ@cJ+2x1`9tu%Z-J68@fztmAG`fm5VE!|0W2Kr+PDs&35xO{6Cr1Y7Jd*u%@gL)Cgp0g6S-XOL%11D&^h)E6Wf|%Y6ZPMv-BxaL6_f ztS)F`l#Xcz9LPQtH4k&p>u<3b?O2<+Ao<>EDu5N8^LTmV3D0B5h2v`k4WM35H} zRS=6{!yBi|N2oC87FJ>X$AYWJS4b%;3r-VM<=LPlU?ib(OR7A=WU)^X2In!bAw!tE^La+IPUb??}!|+GZZjC$U zf{*Q3LHcY?8lWuR;)X?S7=?2@=>$TQ0R!xNs2%aj@?EQy3gMS9aet; zVTuFui{U^MmEqxDEgvi`RR??sxQGYY?);J;bf+r8L~z0~)n0pBR_156R?m$;uA@u# zqW78&mhS3eRQ;{3U3(P+R4`i`F!6r+=QiryvmFOT0p84M6=gpD;)LoDLLp2g1C|kl zeeuwRsfzisWbx`u&LdB?tgfZkoQM7nQuApVk^)B|XTj-%>4;)-j`ey0kLzD3D6U;6Z-PBO%O&3U zL~|Lk@KW;{&3&dgSC;i`zpJIXxjC-HboLvvegJ-`tR+zVA&t7{owwXnom_0^ZP>YV z4Je}cIGcY#JU=OZj_3)`dcqZK@krTsPxy=Q3Q;P3xL~z$0O{R(DCX_g$M!ntK@CRB zCDX%4I+A*QKs@Q5dXeXPlL$zy+noIR?H(wv{A*J=I`(m{kkZ1>P zoMHu()p}QbjCS?P(3i4Xb;yV8GcYrI) zB_c)Pz|k6I>A=h&4=X8tmzZfYco=YsfZ*kL9I{a0SN)AnYeE-Nh|v&?Q&&|oCsNws zwi}Cte!2R&y5z;;Pjag$a6X?M+?iEFCvOR}UN>_n;G;y$@8U-R z^bycAP%2>5KP=p5dYjg%hF3pNwyiyaE>JfD28a|<-FZ>iT#$#-nwCTanr#@9H7lia zqBwAq=w1Od2h@g&9oIF{DkqA-6|=;c9x6x#Tct%p0VbSU6mETtpSiOwbX0aIB;4rc z?PhV&+q={@Zf8gKth>eBO8ZaFni(=(5*F-?_j*RN3QbOf=&*md!qpOCM(0V_<4H7~kuQ&so0ajxpot z60t7uP5Mk}8vb6_LXZXd$`j)vbnl^4c_c$m|0g zA`_;UYP+?D+lhdhS(>*=`as5Q17YYYzOBzH@Pm{%(2xk-<&}iq&RJ-H4EIw*n|b}L zN#!&96xvti;pF$^U9EHE%%Qlm0&05@V&f$@x-hF$X4OnZd+)8rKd}l zIAE_DB4I?@%lY%=Gptf^t%panxa+cH!4?G_iMwrGXyA9jzYl?qTcj~ch>WLZ)GgUI zDui|B~uA%L}oOcmM72-F7qZ`cYv z@Q6?7SEx^7h#viS5+WjiBXA2^?Su9+^I{{*P*l>qd7wl?Gwqw%QsC6)w|X}O2~O4K z?Y#3^;U2#vsU3LDLg@hSvYh)4v0c8^MFy}e^dQAgTW zAGf2%&gYdbrkPod*?3vN>f3tWroL^Zv3h|-50JbSsB8jZUCy0eY;rlxiN^DgiFx@@5AzxJ!W;K2o5ARTR>igS=6 zYJfuj5cA}FY+&qi5D#pBXN}C@sDWnAyhyn|7_mMu(D0#uP8KQE*JqIScDHu$$LVgg z-%Mad=UlUMl929;P^p4t99}RUs^=n(M4s#1>m2KkzHzKKqr7~?j}a+cZT*o)nq0|p zP{XzQ_E*Q0oP^32*gq6iD^ z%;p2ZbEOPut_;bhdOKPp4kT1KYSDcw#dy^Svh|o*Kj;56Gy1td=voAH~dLuDf5ou!0 z!}Pk$kQ{mRLB;iJmS3$rfchcuAJF}da3~52!$J*euDAA<1iAE0y7y3$FJzW?vx=ll zt18pEH8U)k1xs?oV5(mD>9`LPt@M(D@6{Lf)Z8oW$!|IOdr9(_;@Y>db!>0M=@;?K zcah|-=#!>Cn#$Ur41O$eNXJM+z0P7^CU0Svr9yZTwNL&|PF9N6>G!&Bek;+gZne?< zQn7ETCTY1*-HQ!wAf{ct3XGrUp`igl%X}uo*Qz2tUs_T1Qi*5tG0lpU?_M!@IS&Pa zO{~eA_kwc|dQC>E9>bpZcw7->BD;(*s)3hv>n&C97|%E5w2;#pQyS7&A5! z#$UWbxH90)FzmcWvI;tmn!LV&+!QGCcn;-ZYD>Rv9j?amnH3CGH zZ{mqcVo|L=%U}J0^TFoc!@PPoN{h*4%VfqY<`}8xs=;!<>S_9!I9k|AY6wlF)ki<< zb4^R*Y}=k}4H}H4DFE6$Y+G zMy@F^w+o`__)(5%AfBpXbI3?%wDE5-s}Gl78S6h>#@)r=8YwT%A;D9- zf_HzL4B~~IM4lVKNSb>rpD-e6qwP`bQI9ON#H%PG7lHfD#1qQzUf6D~|S)VQA)`;I*{2 z?amWNy(b5vS1--(-DcCbA^1qD-wBUmrGm;>}+gQq1#l>9o6tsB)9$D<~S>D`x_fHtynla8<3(n zx0j2}9eC4qChbf7Prfu-;V=akF9kILY3WP`eS$C5Ia^37uGmKAv&1QIWWg`1$)eE)~p@5*#&%2tkHh4%)?0M%FsvWMa` zE8VImVJzxjVTC@%8#W1qM5Qlbdq#f7CRJf+#6ovL&NZQ!%k8TwQ@c1d!;9DH#`t1D zGh=P@nb7L2K6BcjCXUjLTD~~jJ*#OFU!Y=KT>`4bt#zA?vh8Y|jGyF}%R!Eo}`Cs~FIisLGy2 z^t}j@PZGWO;nKR(*W=G#>(5wk>w-2#U_9U}<->U_C;q}cS0d^*&&G%VdxWyEboZ+N zPh<&k{{0HSPKrA>g@eJ!`NC=+NII; zMe3K^M^MtnmYG1;6wlF0#GLn%sv0TrU~8{IcmZAQ9Z%pKXR(YNfDNk^2jM2|M}8;% zXZSeUn;eab-U<88-vpH98ppnOY5v-3qvhdy|FmXb8EWRHC94+!lTZgNWJT3IEetV0 zk(%Vay}EyCPSNvZWlEEOLWYwxiihz*BcL)N<)ybxxRbRi_tt;VP>acZxNukOK` z-Xz4nD=1bf{wNyb@J_tINj=6tN&%Dvh#++Fr6Y58BTt%`NXkM443)dszVlvCef>vJ zZ(+SpZN(FLzMTw`!SWqx2V-sumu7HwpZ+lRV3Nc^+wA5#wpNEPcav_XRelR7rstr} zk7JAa3x{x>@d+yIS@fvzjfEb-jDx?b!6}G(&w1L!5$F@W|HdEND}g(4#C4}UJG)$m zwr}yh=`n!0fP5C77!0lGw7-^;z<$zbxy4r1z!(r_D|)-HCu84g=Eju1LU#&AAT)&D z7XhvaSg1+#V7d#Pc&!`5`KK91t_r6!%9jregiwQPYYLu$S!4r=vGT{|vk_fbEj8lx zxoT;a!($vV-q`+*pi?)uB~*S{r@`AGiC088(U%yUW{xN}=bu1-F>somXgf;ZrrSsF z-S*oKJOYVINQ_h0zB^^Bky{bjd*ALnarOYvhn141hB@9HRe=YA>hN~iLc_P?<72iH z3w<#wV>bBW`8Mlke5nJR)8qX#w|&)cFeDnIAA#C%x2{{evm=7C-SGHP{Em)3{;UI(wAZ#hoR+@? z5xABTOs=J0Yywz^YzrRSs-^mPXiF8)B6xjYQ$SUtw4knX^ShfO_6vPq>UX}s)tj{u1ojJtL1xzi`Q^ql zd*KN!_Jg_WGwqMN`!p4MUEwTkt?^$-qrrXAYWgMdQ zR>$*pr)})gz^z*qpWp)PDv>GHYTt_!A-&eKw-lo?6H{8V5tamD~U@$<{P^ac+ zESa5R9pMB73>;^>vo3u<`(eUH^;UTnA4HFh#ObJmZrSm)Ze?7~a!lc&2N--0|c3nZ#Wkf3m39+@v|^q~mha zi7>eK$SJOs9jC`4JQw?%GrGv!yGxb4_U>Qpux4K4o28ht3;43*oRx}GAJ!C{;{JOG)i`}xKxh^fy# z!!md8uiN_jSHt1@Pa0syb$6*t%nsKU@9)9P;19>$jgW0{hit{TMZ+Lf&sz1{8BX4{f(Z)X=DH*H0fx9fho~t?CzApto9DAir$M{3=p`UI?PUbWn1ykNCI9Ckio}H!)mGptS!2j8 zdJdF}-wYYpO|@LB8uiUrgjX`j@Z$@A^Hk`lGT5ke(f2Bb+`fY^k_yUok}?vaDoUpK zK;r>7q}9v6)@`6vG1HAt@{HPUsB<5JKplyuaAQ?CShf1vFo2~3W?V|W`Vp-mbO_W; zS&z&2o!y5P@dg1Lj9*CaYhp)|N|W1($*>kRqw2*GDayza3M!r( zV{4`?&RbM1Wi$MHC3YL>v?4b-o}4&oxRED#i0|PobkS)owa`Dw`SKS3A&YI{CtHS5 zuv%^JsNcnLtp%eEGOI+7z&q zADY%V)-XVdX~IOs98y@4a6)$%3sXBW7`IQ?IP-WSJSD?KlI@Xxz>~?xX=#hsO;tD4 zjP=)bq{py~==T?bCl>2MZj{;z1V#~<3jT3&h@Yb>R7XA_EOmkQl!dUFYQetG4TKN~ z)NwC}!zoVH7K>7Z$$?OA!A6zCvsH5mZhlMWGbG99+(E}SlTP0FfggH0i2rc#y~!au z7)e-Z%2J;~5#7b5S)HUSooe<>u`n|7nv&TM@*xrJ;joN2T_Mcm`a$+29c&FFeceY; z0KrLzU;HlDu8nxs@Ou|DojFDjKVMZjo~CCj+Tn>fzQ?3rMg06dd=r+8B28}gC zIxaFu>QrrC)Z{XT&wcPf7Ml}$KW;l1{f)V#2NelL>n_HGgto`(&>vA9z=t#<`TafX zOWlN#eg8QWi#a`}qGPQ&H9>QIj`6!}Je#1Urn+&MxVJU%)a&6J=cJ?ScJ@645RV># zR{eTPTnRyZ{+!uQv9ezo4}z^4>@vD`&^(3mRxb{OWUGsE?%WS$Lr0$QO2kt2#QWCH zq4;dweyiYR_$dvfF<%nd49F5h%l9TFYWL23ko-kkviX6iJmN)<-+$GEXXTb5$7Rf5 zlI;AaHOjW9taekLQ|$she@3K^lo48@?DU zf@r37fiKz5Fu!hib%ayrR+0RDu2K@c((k5P-onAucx>~2Rk(B@rCpDrYec?W>76ct ztzX*xUMTRbbZh~|Qnrzlz&JeYpwm5aw2*5ARj;9)VXg|}@L!HW#eECbKWK>fx5C=ZMIOCb(`RxMM~NUT?5{ukf3PseaAVrAKx z^WSa6uG(z*Rw&}aU9hQSnW1zZy3R)z!vSweTsYij;dAQWrW@jND)_8*bfg~p+A7QP zbFGuWC5nEhCt;DBe3gEHocBIOpssT2cKhk#aGFQ*=?AWDpSQJ>j~oolWgup`d0!jQ zZkC5db7T|yThGw?))RDyI)|2ZQeVQ~rI7+JQW>mVJRs$rD5d=L8R?WOr(C6BXNV<~ z93@1Z&<&@hkvfgNV=^^m()FH8An@=Df5EI%zJqgr66NFzw?>)yr?SVT9Bou7Pe68b z)K2D;&Dq>15;*%*U{C;!v6VAyFmaQjY<5=u^{CeV1?^)0SR@Y@IK+A6s>_zB z$R-8Ib++mZQus|cz}fGENdA-Mz%{$T_ve9A0s&I4V-l&TF{GXFOU)GJv*Wv~ZLaAQmT^grN!6}FfsU$*A zeHTee1VE=AePk6Z9GsloQD+nuc98vSbg=LR)?-a>ss9n)<==}*Q2A%fBmM#o!P_Ct z%ZGF2>+_88VXFAo|4jIU|0lOyrEh;eqyBj5(0BudqqZNrq5~|tPZVCG)3!+aW!f~%H=U5@vc@MmnOF--GMulEx4 zY2*=XofNujekyYJ-}D$JSz1O37JZ{M$Id$*AG;=W3Pc|hpzuXxhRXxBolV6yr_Fn2 zc^P^XoZ{F#VU!fhNR0cFmm7F0C?w=of`HxbVd2;2=kFILeGoQ6*<=N|uYS6k7CRM( zNO2y47L#7of$Thdx8vqA_*5rO--l#1KkOhG{F`MqrzxgF4_z*2G>NW(*+7t1eA(ni z#hCWAgI#$v#TN|;K~{I#($Hvxm(*{E{(KA?rl7B;Ml=6tksbRBA`TB2ri zB_9b)tOuzC*bw((1l0qJ+S@n*$|Bo*`1|%tt$O^|$51(IEe}(HCjD+s(`_`o;QN`44 z`To$6^x1SgRz;4vYwy^t%lLX8%gf2k(o&fY1KLyD@m{>^4S^7jhQzY2s4){GKbV_W z*dkHAsj1IYD|Q!lXkKsB03dyS^&TE50CjS0>dLmg@83{gPM71iog(KzO5TLDFRPgi z4@Xp`pr@nM z>wj+ad;{H9#@I+SloOgdD3JKrW10?Jg;cb{8Q3KCk(jY==j@-eULkGS2Km0bE(5OR z(xw^#>H<8=iah6MpY~cfBaAhh2LiWPBHafKo3qU{ygs=8IFny7adA%D-eb!QPPURrI z-#^7yQLMUMy>d$oNIegeFNx+`+uE*$0Fe!RaV*BT1bGH^3!QLal>dA~(@k~7(mG(M z38TEJfdGhG&o_txtx^J`vK@~xAQeF2Fc;x~1b{I_{+=T`^7k1adHkBWBm^i4FI5(X_{3m0;O_(m%&5g@6S3sA%~bMqsA6BjbpJyHwVx?kkSrDmkSUYh5>@_`zX-IeS z2KBPv#*pY#<__Wbx-0D;3EPnB#oOj0w@qg^;_aG!dAsROY2kjI z*8X5UJ^Q=R>P5R`fR+%r1UKWd!5iztbWz!dB7!jP$^{2%R(kV;^!upWC|3w)S(TWv}rL!-=RuxLtHzPf~^DcD4Mp0@jJLA3@H5`_3n#%dP zLW-hF-nJnUazfd-x!KrkAT?4^tkf?fL2&2uS5@IMIBhxEA}#ON35Q2JweeO+)$tC( z-q1|MKKedO87&!e>D=Qisf+0?`w!rxYn@3_?*`P#8!RI4(;4YIhyXLb${Dtih8v=2 zYJ8zc-V2gWcJ-mRz!1w#I-F+m#2?-yb%`w0x{c+g;zy{?H#An$q;`#;dVT%zjY8OmR#^&d=>lXgr1C3k_44;W3WPK6nipyNB zEuyRQ3qpl{`aAsQ+Nl@Wo%gxis0NuCpbZ7=YCCTAtNOnsesbo8t+CX~2w4E`IA;v9r{YHn z3?+ZazM`KaWdFMFVSafDu%K+fkL4++s_&bJhM9NM^ev{%p_UDu%_Uwk92Gv-2w(nd zO*#!;Vb^KoPBmzcuz@!lolj;kWPIKR~5=XmELnYY)*%$ZgO=!pLIa6jym| z{=4TFcVRzvW*w4*p2TlRpf;sEGWqVN{XtQmd=im{Pj%CdrkCVX8lO|rb_a!loU#>mFBvWxC#Sli`oIEVbYF@a!?z|BK+0sfyRZoT^M2c=!sqs=&aac&A|;pO5f6L76OOPfE(}PQqVRM=e94Had!Ar|dJV&y`#Qq*8Jgh_=%>E7Kfy}J5%!GW+=43lSMMpEVm|cmMN-xn` zIw2E5z^KvZ@*K$G=A@Zd#er&f3b-2BI#3P)&VIB(_YXlQ=78rv4#edfxxx!~ zTPLJ71I^E-9a`PrgtL8<-yovZJTTgcFjrd2SM!J^GfBKS4|%%y6DzCDP`NK5U_cn2 z4Ss$BnHj~$=(so%$(dLuZKes9`m&5Ze_2ezqEGa2_*6vJKDwpFu8TDI2 z1}*okCFZ-0lgVSfV`z*E`6qndbMR@)Vs|Dw?Ey*@P;F{FUnb~)+~Q(Pi6w`B;#rb}7h|CL&>s`=hz&uAcPHFmu{3IKovZ zG-VOmU8j3P3%^RA^4jr0#4?>Jt8>Wlg~|g(e5@?7ph^zs^rXr+d$`)`M7EHCPS1dA z7xUv%y7%w)&CZAD#EV}3zYs3JE>N=lrHGqVWQx-fH zEr17RZal~|ksH34za)abTFq;K;*zk2rB!FZF1gKZl7~r`e;eP-`%YA&+JP(q8h{5b zf>#AaLQt&9e55y_uqx55NnAuRqz^g2 z@G5j}4!hrnCl-{~+xL>uls`Vb0fr3x!EV>ywJ)Zbq+P8PCBsA{jSoOqmtS9J_>_Hx zKy}yCQO;l|rS zL}KSil2;D0M&sF_<{essGp$J6;2z_R7huq$b6uZBgK<3k){Wj>=cfBJ&hv7ZS_LTe z)%13z@#zbe5J(VK3$*b39lhA8a96Tv78WqQCuRkU0s&K)XF5#!4%qy6wAy)Uc>>$e z!m;;{&N1}Bf-;~`C`-RMpf%y%mba_oDDKQwi=kAqYDgbnf?*9aXe-NTM=Gp$(ugcV zDUzk$DkzkjP2+`{BrgmL{&?8!RAB2(z7Rs>9_0tyB8;Mp63N|9$7bY{Zw?`omq5z3 zX9B3Pj&ysb$Fb}5;C8dMsEYT?E>pwQ%y{*2JUjQ%{WBe~6`nJM8U>=cA;ui@OU_gy zO9xC8h-I1IC{GoMTvttTNWvAv{~SM(XzzN}F0|{N1&LlkUOl7ECd2=L0awA`rpB7? zYvN1X|7<2Y$L$csvjYrPF77x)v)p#O+gX7H*SB-3D<9we3}AQk-$PBHJRL z1hqq5)qV)C)Nc7HJU4B~?8^p{sa=guO{eo0*wR zfEK&A2TQ1(BkZG2ksH3fufTsVIH|^qUSqk+NwQo$2AA-H&zeXcy5o}D1&j)HCLlw= za@M4hef6X6D5Y1el-d`|C#cX-g9cKYESPAP#`4t57totG0gsjDrFt#Uv)dV7Fzzeg zR$RdMe;%-_n~)q>3mJu>iIP)8b#1!EUdDDt?`*_Oy_Q(%?u*e%onXjNfxq77%LOm7 zOGh&xBY_Y}Ja*ObFKe&NCPV-UZq26VPN`KU{r$UnJFG71-cc3U>~U-n?2YW=$IBQ2 z`(U-2gJhmnJR|gNyf&`#I|y{E;YtQ%g6w3_lu6iezIzz9%))a!2cj2y^GF=^rL92yzd znp8aq?ul35B~~8edk;~_@GCVsiUlkNkk9uULP6xKKFntWXYbHSIP6-lq`%ajn0>C{#}HLTw6HVKO6jYt_+?aQxv$UF!dnHg{d!+kr$$@6zDZ}{#uT%;1 z9B$9vjlLC@EAa#S?vbnVc_#U!?&T`K&HEzyZR4F5Dg-}a7jBvIFWZ#LN)D&%A2`cq%{|4l}Gfi5N%*fMgOCEGmqS3 zD>&*w5}vslA^j6W*caH1FR@Y}%7MR6r2+C% z|JtP6>7P&S(7Ei?Ru#5TA`KGl?udFo_~Md1$!-_OD(Qv1CK;`K`toOzi2Cgzx=fqh zA`}rBrjm-wi_@X=<9ce$(UPDNo&%<#O60!C+{d---NY5LU$j!dx8F`d>r>j^$MSh! zXoO#V#<^d6HaugY_vD15Ul_5V8zxZFI)BPBW$Kw<6A(1UfK&zvKuWVva?$qh!hmAj z$kQgg_hwy}YH**+=Rd6-nnLqe=zB%f6j<&bE;&mi`T}=DT+kZZ;XV8SXf1^|&~S$| zc4#4>XEfc#X}o;f2~1S-i)m(%oI27W`_WwD+}>BB$IUiqH!gLNs}k7?VFv9v=PwTm zj(=bsX|ccnZA$3YMZl*4K{H3dR=(XE@0jSfaMp3h>ZY zymc|gEvi;4yeDK@8Fm!|j(McdU0(xXfHMRzP1AudJY#AVZz$>pXa2k@2AM9<Fw=XRaVSHTXB!&}O0Rzly6hPD}(M~%C6h`#ak}63`M@c;bF>t6`&D#O^#_F+~#w@-#7v{83CVOGxO{NAg zqBWc7;p8mrhI;|Oj`FqTFnseBpqxiZ?}+A%kzQyVXez;Qc3V9FAa!*_$NQM4h3aVo ziY3K6F%Sw!L8;Huz0dpXDB-fuM}BDe+yKz#p(&z)88Yydk+3*@&PC79Fb>8UQ(|OT zFtZMLEp>_$y(u3SZKaZtAG`_@{8TPZG>PIUE0`2@c#E;pm9^=NH{P(IW_Y~5|ndh^H%(>YN z$fe|2zwvwwt+k0RLHT1*<&if5e{0EsdqXIccB?So8X#l>TpG|r+tQbtWhxzyu?;HF zZJC`<0&n8{Ge*lSrS-Rm&Ppw@jemKVYYAC-m}rR(d>C$_N@TV3j%eYs-kgM4Ro&Dh zyhyI~N>;J&0>jVru`{wkaO~>zJ4*40hi+MUl{mkdUe#wXp2>*#vX~vF46fwGe9n24 zab@3+`A7Bgh?&Hp8+-lqz^D6%^YJZJvr8|2gmIe|e6T7rRCQ>W`Qfsd2!=p6seUwGIKp9eXnCp)f3J-25+zgbR&W!jfkMo}UG z(rMK)xA$GzdG&Jf0SGY!>-!HuB4BzzWB0>Nl?7N++-H zKmK=B<3`SHJUs&cl3Ub(SRqudWZlHo-EYC9UB%Wpc<$uUYf1e1WHz)J-Z_PrfMj_q*nLVk;ne(=X`#nmQ?7Q z-@>T-8U32~_#6;cF|uFJJf4(s1G`RacL?*!9RC4UFg^=hYSXibMzD{dFM<6?cji#o z!o$a^tFC(I)d$1JPXH0(c?`&XKa65N2 z;GtcQ>h3*;=pB!6uH$ytybSTk*~R7&nDz27bfH3r!a#7jhN|RJ4Oq;;y>kIC^O?V> z_bjCtOUY+rF5h;3ZRQ}Lmh_&G{Q58{J5sC0YKuQ;e77YfvVzkwY&p+Ol4o#vH;cmf znhItcbORJ7vY2pSDW<4%MP@zL){wD9+B`*I!CJ_1w&=wKjg8hT#Gy~%7^rg183t>O z=ELbNS!uE6bS@a-*!s!@juB$F#P&Ow#~%H+)MRC*c=&NOI<@&?Hgd<3^7ic=W}x-w z=PKB%9k{XtXXz4Od;MX0-2+LaMto&hF_hqtw|Sc};*JYV_aO?1pZ)DGzMXG%v?24} zaeEW^!n(qu{gXCvhwEuAI)d--7EnK^^8&jlJ1cS>rbRl;`(HlvBgaChB=;TfxID|B$k0%B-v!1*c!S#7914%K}No31ECyN%keYM42rJASjS zF#KQfD1M$FM{a3qd;w)0d~KTAGd*#*FxPT(R|TacMV@`MyaN-h3X!H354+*9wKUa9 zS}wpWitJDU`aXQiE-6j!|h%#kvdMsMIgMUH>WWeEQ#m_pnH}_5CkK2iNzx1OjBv!6z~C;>_cC0;xy6cK^eV&xj>{s; z16Sz$@-4}8z_->k-tC-F?YRi;{1Bqbn+NUj&IWWD7wIpM&r3R6Ne%r%1q+)889-GL z1F|jkRj@MdCf6xk1~9jrWM(L%DK@Zw_!2QW;3Rsd@hARShY@^8op5Pw-byy`&bND+pKSFtm zOn3@DSl1Hu^Es#W`yF|Ut4S6m1$|eIr24g&%P&^Gq>>$fNj}R_1%jO7h`{@r-xER2 zaU#;)%VMA|o9->cGB|`R2~v&=#IKs)v1PF^?-vI-xwU$OR~!$l2BlIf1}UDBM3Dh~ z=*j`PyU5P|Je77&wZ_OKDkRKmnW6A7o82F zbU$HKZQ*halnz{aKZ(xGhG8`aak*L7{R0ms(wa1#{q3>id6eW9&&pNO-@2H{)an`g zd)4}viv7L(rCwy5a-)1}hbO0ax%MmhyL1nPt^AiA!R1CGNpk=+B(&u52Vb_>xDHYp zukvhPLjH>6rM9${ejy_}@KBzNrrDnEbBvzJ-%;bP@!B4KY}e%eqh4~!^rSayq7dDT zKl{y#f^D=_{gQv?$7wmz3Rq(6ck*R&^9uogOxrJHN9a-+IEH}Eo3DTC=CjX*$bo@3 z8~3p_9?3j70WdwzoHO7n{(+&?)icueYo_F;#LJ#Q0a67hS>!yADPP>z^Y1mqrxe~b z1hE@eCK*^A{ZX}9Y3du7Fj6rrfn%$4sESwA?6)6(`Hk zi<4HgtgD+>Mlg({8AkvB1XzP%000pG4QTT+fdiRlc?3kod7?f+q~SmiX6DA`f75N( o-IM%8o*ehr=#Iq=Q0BvwUBdJ3D Date: Tue, 28 Mar 2017 09:56:41 -0400 Subject: [PATCH 1563/1676] [ticket/15157] Add proper google font call PHPBB3-15157 --- phpBB/styles/prosilver/template/overall_header.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index 4438137f7d..09824d0a16 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -33,7 +33,7 @@