PluginProbe
wpForo Forum / 2.3.0
wpForo Forum v2.3.0
3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.2 All 137 releases
wpforo / includes / installation.php

installation.php in wpForo Forum 2.3.0, at includes/installation.php

1,561 lines 64.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Exit if accessed directly
3 if( ! defined( 'ABSPATH' ) ) exit;
4
5 function wpforo_activation() {
6 #################################################################
7 // Create wpForo Tables /////////////////////////////////////////
8 wpforo_create_tables();
9
10 #################################################################
11 // Alter wpForo Tables //////////////////////////////////////////
12 wpforo_alter_tables();
13
14 #################################################################
15 // Permalink Settings ///////////////////////////////////////////
16 wpforo_fix_wp_permalink_structure();
17
18 #################################################################
19 // Access Sets //////////////////////////////////////////////////
20 wpforo_import_default_accesses();
21
22 #################################################################
23 // fix already installed options ////////////////////////////////
24 wpforo_fix_installed_options();
25
26 #################################################################
27 // synchronize users ////////////////////////////////////////////
28 WPF()->member->synchronize_users( 100 );
29 WPF()->member->init_current_user();
30 WPF()->member->clear_db_cache();
31
32 #################################################################
33 // Importing Language Packs and Phrases /////////////////////////
34 WPF()->phrase->xml_import( 'english.xml' );
35 WPF()->phrase->clear_cache();
36
37 #################################################################
38 // Creating Forum Page //////////////////////////////////////////
39 wpforo_create_forum_page();
40
41 #################################################################
42 // Forum Navigation and Menu ////////////////////////////////////
43 wpforo_import_default_menus();
44
45 #################################################################
46 // Boards ////////////////////////////////////////////////////
47 wpforo_import_default_board();
48
49 #################################################################
50 // Usergroup ////////////////////////////////////////////////////
51 wpforo_import_default_usergroups();
52
53 #################################################################
54 // Forums ////////////////////////////////////////////////////
55 wpforo_import_default_forums();
56
57 #################################################################
58 // UPDATE THEME OPTIONS ////////////////////////////////////////
59 wpforo_update_theme_options();
60
61 #################################################################
62 // wpForo Upgrade ///////////////////////////////
63 wpforo_upgrade();
64
65 #################################################################
66 // UPDATE VERSION - END /////////////////////////////////////////
67 wpforo_update_option( 'version', WPFORO_VERSION );
68 WPF()->notice->clear();
69
70 #################################################################
71 // DELETE ALL CAHCES /////////////////////////////////////////
72 wpforo_clean_cache();
73 // At the moment only Redis Object Cache should be flushed because it causes 404 error for all forum pages.
74 if( function_exists( 'redis_object_cache' ) ) {
75 wp_cache_flush();
76 }
77 }
78
79 function wpforo_upgrade(){
80 if( version_compare( wpforo_get_option( 'version', '', false ), '2.0.3', '<' ) ){
81 // #### migrate old options to new settings
82 require_once WPFORO_DIR . "/includes/options-migration.php";
83 _wpforo_migrate_old_options_to_new();
84 _wpforo_migrate_old_widgets_to_new();
85 }
86 }
87
88 function wpforo_create_tables() {
89 require_once( WPFORO_DIR . '/includes/install-sql.php' );
90 foreach( wpforo_get_install_sqls() as $sql ) {
91 if( false === @WPF()->db->query( $sql ) ) {
92 @WPF()->db->query( preg_replace( '#\)\s*ENGINE.*$#isu', ')', $sql ) );
93 }
94 }
95 }
96
97 function wpforo_alter_tables() {
98 #################################################################
99 // ADD `status` field in `languages` TABLE //////////////////////////////////////////////
100 if( ! wpforo_db_check( [ 'table' => WPF()->tables->languages, 'col' => 'status', 'check' => 'col_exists' ] ) ) {
101 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->languages . "` ADD COLUMN `status` TINYINT(1) NOT NULL DEFAULT 1" );
102 }
103
104 #################################################################
105 // ADD `package` field in `phrases` TABLE //////////////////////////////////////////////
106 if( ! wpforo_db_check( [ 'table' => WPF()->tables->phrases, 'col' => 'package', 'check' => 'col_exists' ] ) ) {
107 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->phrases . "` ADD `package` VARCHAR(255) NOT NULL DEFAULT 'wpforo'" );
108 }
109 // WPF()->phrase->clear_cache();
110
111 #################################################################
112 // ADD `private` field in TOPIC TABLE ///////////////////////////
113 if( ! wpforo_db_check( [ 'table' => WPF()->tables->topics, 'col' => 'private', 'check' => 'col_exists' ] ) ) {
114 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "` ADD `private` TINYINT(1) NOT NULL DEFAULT '0', ADD INDEX `is_private` (`private`);" );
115 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "` ADD INDEX `own_private` ( `userid`, `private`);" );
116 }
117 // ADD `solved` field in TOPIC TABLE ///////////////////////////
118 if( ! wpforo_db_check( [ 'table' => WPF()->tables->topics, 'col' => 'solved', 'check' => 'col_exists' ] ) ) {
119 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "` ADD `solved` TINYINT(1) NOT NULL DEFAULT 0 AFTER `type`, ADD INDEX `solved` (`solved`)" );
120 @WPF()->db->query(
121 "UPDATE `" . WPF()->tables->topics . "` t
122 INNER JOIN `" . WPF()->tables->posts . "` p ON p.`topicid` = t.`topicid` AND p.`is_answer` = 1
123 SET t.`solved` = 1
124 WHERE t.`solved` = 0"
125 );
126 wpforo_clean_cache();
127 }
128 // ADD `status` field in TOPICS & POSTS TABLE ///////////////////////////
129 if( ! wpforo_db_check( [ 'table' => WPF()->tables->topics, 'col' => 'status', 'check' => 'col_exists' ] ) ) {
130 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "` ADD `status` TINYINT(1) NOT NULL DEFAULT '0', ADD INDEX `status` (`status`);" );
131 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD `status` TINYINT(1) NOT NULL DEFAULT '0', ADD INDEX `status` (`status`);" );
132 }
133 // ADD `name` and `email` field in TOPIC TABLE ///////////////////////////
134 if( ! wpforo_db_check( [ 'table' => WPF()->tables->topics, 'col' => 'name', 'check' => 'col_exists' ] ) ) {
135 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "` ADD `name` VARCHAR(50) NOT NULL, ADD `email` VARCHAR(50) NOT NULL" );
136 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD `name` VARCHAR(50) NOT NULL, ADD `email` VARCHAR(50) NOT NULL" );
137 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "` ADD KEY `email` (`email`)" );
138 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD KEY `email` (`email`)" );
139 }
140 // ADD `utitle`, `role` and `access` to USERGROUP TABLE /////////
141 if( ! wpforo_db_check( [ 'table' => WPF()->tables->usergroups, 'col' => 'utitle', 'check' => 'col_exists' ] ) ) {
142 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->usergroups . "` ADD `utitle` VARCHAR(100), ADD `role` VARCHAR(50), ADD `access` VARCHAR(50)" );
143 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `utitle` = 'Admin', `role` = 'administrator', `access` = 'full' WHERE `groupid` = 1" );
144 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `utitle` = 'Moderator', `role` = 'editor', `access` = 'moderator' WHERE `groupid` = 2" );
145 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `utitle` = 'Registered', `role` = 'subscriber', `access` = 'standard' WHERE `groupid` = 3" );
146 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `utitle` = 'Guest', `role` = '', `access` = 'read_only' WHERE `groupid` = 4" );
147 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `utitle` = 'Customer', `role` = 'customer', `access` = 'standard' WHERE `groupid` = 5" );
148 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `utitle` = 'name', `role` = 'subscriber', `access` = 'standard' WHERE `utitle` IS NULL OR `utitle` = ''" );
149 }
150 #################################################################
151 // ADD `color` field in usergroups TABLE ///////////////////////////
152 if( ! wpforo_db_check( [ 'table' => WPF()->tables->usergroups, 'col' => 'color', 'check' => 'col_exists' ] ) ) {
153 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->usergroups . "` ADD `color` varchar(7) NOT NULL DEFAULT ''" );
154 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `color` = '#FF3333' WHERE `groupid` = 1" );
155 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `color` = '#0066FF' WHERE `groupid` = 2" );
156 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `color` = '#222222' WHERE `groupid` = 4" );
157 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `color` = '#993366' WHERE `groupid` = 5" );
158 }
159 #################################################################
160 // ADD `visible` field in usergroups TABLE ///////////////////////////
161 if( ! wpforo_db_check( [ 'table' => WPF()->tables->usergroups, 'col' => 'visible', 'check' => 'col_exists' ] ) ) {
162 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->usergroups . "` ADD `visible` TINYINT(1) NOT NULL DEFAULT 1;" );
163 }
164 #################################################################
165 // ADD `status` field in `languages` TABLE //////////////////////////////////////////////
166 if( ! wpforo_db_check( [ 'table' => WPF()->tables->usergroups, 'col' => 'is_default', 'check' => 'col_exists' ] ) ) {
167 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->usergroups . "` ADD COLUMN `is_default` TINYINT(1) NOT NULL DEFAULT 0" );
168 }
169 #################################################################
170 // ADD `online_time` field in profiles TABLE ///////////////////////////
171 if( ! wpforo_db_check( [ 'table' => WPF()->tables->profiles, 'col' => 'online_time', 'check' => 'col_exists' ] ) ) {
172 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->profiles . "` ADD `online_time` INT UNSIGNED NOT NULL DEFAULT 0, ADD KEY (`online_time`)" );
173 }
174 // ADD `is_email_confirmed` field in profiles TABLE ///////////////////////////
175 if( ! wpforo_db_check( [ 'table' => WPF()->tables->profiles, 'col' => 'is_email_confirmed', 'check' => 'col_exists' ] ) ) {
176 WPF()->db->query( "ALTER TABLE `" . WPF()->tables->profiles . "` ADD `is_email_confirmed` TINYINT(1) NOT NULL DEFAULT 0, ADD KEY (`is_email_confirmed`)" );
177 WPF()->db->query(
178 "UPDATE `" . WPF()->tables->profiles . "`
179 JOIN `" . WPF()->tables->subscribes . "`
180 ON `" . WPF()->tables->subscribes . "`.`userid` = `" . WPF()->tables->profiles . "`.`userid`
181 SET `" . WPF()->tables->profiles . "`.`is_email_confirmed` = 1
182 WHERE `" . WPF()->tables->subscribes . "`.`active` = 1"
183 );
184 WPF()->db->query( "UPDATE `" . WPF()->tables->profiles . "` SET `is_email_confirmed` = 1 WHERE `groupid` = 1" );
185 }
186 #################################################################
187 // DROP uname unique key from profiles TABLE ///////////////////////////
188 if( wpforo_db_check( [ 'table' => WPF()->tables->profiles, 'col' => 'UNIQUE USERNAME', 'check' => 'key_exists' ] ) ) {
189 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->profiles . "` DROP KEY `UNIQUE USERNAME`" );
190 }
191 if( wpforo_db_check( [ 'table' => WPF()->tables->profiles, 'col' => 'UNIQUE ID', 'check' => 'key_exists' ] ) ) {
192 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->profiles . "` DROP KEY `UNIQUE ID`" );
193 }
194 #################################################################
195 // ADD `private` field in post TABLE ///////////////////////////
196 if( ! wpforo_db_check( [ 'table' => WPF()->tables->posts, 'col' => 'private', 'check' => 'col_exists' ] ) ) {
197 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD `private` TINYINT(1) NOT NULL DEFAULT 0, ADD INDEX `is_private` (`private`)" );
198 }
199 #################################################################
200 //Add user_name col in subsciption table///////////////////////////
201 if( ! wpforo_db_check( [ 'table' => WPF()->tables->subscribes, 'col' => 'user_name', 'check' => 'col_exists' ] ) ) {
202 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->subscribes . "` ADD `user_name` VARCHAR(60) NOT NULL DEFAULT ''" );
203 }
204 //Add user_email col in subsciption table
205 if( ! wpforo_db_check( [ 'table' => WPF()->tables->subscribes, 'col' => 'user_email', 'check' => 'col_exists' ] ) ) {
206 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->subscribes . "` ADD `user_email` VARCHAR(60) NOT NULL DEFAULT ''" );
207 }
208 //Add indexes for subscribe new fields
209 if( ! wpforo_db_check( [ 'table' => WPF()->tables->subscribes, 'col' => 'fld_group_unq', 'check' => 'key_exists' ] ) ) {
210 $args = [ 'table' => WPF()->tables->subscribes, 'col' => 'itemid', 'check' => 'key_exists' ];
211 if( wpforo_db_check( $args ) ) @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->subscribes . "` DROP KEY `itemid`" );
212 wpforo_add_unique_key( WPF()->tables->subscribes, 'subid', 'fld_group_unq', '`itemid`, `type`, `userid`, `user_email`(60)' );
213 }
214 if( strtolower( (string) wpforo_db_check( [ 'table' => WPF()->tables->subscribes, 'col' => 'type', 'check' => 'col_type' ] ) ) !== 'varchar(50)' ) {
215 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->subscribes . "` MODIFY `type` VARCHAR(50) NOT NULL" );
216 }
217 ####################################################################
218 //Add index for double condition queries to avoid SQl caching///////
219 if( ! wpforo_db_check( [ 'table' => WPF()->tables->posts, 'col' => 'forumid_status', 'check' => 'key_exists' ] ) ) {
220 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD KEY `forumid_status` (`forumid`,`status`)" );
221 }
222 if( ! wpforo_db_check( [ 'table' => WPF()->tables->posts, 'col' => 'topicid_status', 'check' => 'key_exists' ] ) ) {
223 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD KEY `topicid_status` (`topicid`,`status`)" );
224 }
225 if( ! wpforo_db_check( [ 'table' => WPF()->tables->posts, 'col' => 'topicid_solved', 'check' => 'key_exists' ] ) ) {
226 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD KEY `topicid_solved` (`topicid`,`is_answer`)" );
227 }
228 if( ! wpforo_db_check( [ 'table' => WPF()->tables->topics, 'col' => 'forumid_status', 'check' => 'key_exists' ] ) ) {
229 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "` ADD KEY `forumid_status` (`forumid`,`status`)" );
230 }
231 $topic_slug_key = @WPF()->db->get_row( "SHOW KEYS FROM `" . WPF()->tables->topics . "` WHERE `Key_name` LIKE 'slug'", ARRAY_A );
232 if( $topic_slug_key && intval( wpfval( $topic_slug_key, 'Non_unique' ) ) === 0 ) {
233 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "` DROP INDEX slug, ADD KEY slug (`slug`(191))" );
234 }
235 if( ! wpforo_db_check( [ 'table' => WPF()->tables->posts, 'col' => 'topicid_parentid', 'check' => 'key_exists' ] ) ) {
236 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD KEY `topicid_parentid` (`topicid`,`parentid`)" );
237 }
238 #################################################################
239 // ADD `secondary_groupids` field in profiles TABLE //////////////
240 /*if( ! wpforo_db_check( [ 'table' => WPF()->tables->profiles, 'col' => 'secondary_groups', 'check' => 'col_exists' ] ) ) {
241 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->profiles . "` ADD `secondary_groups` VARCHAR(255)" );
242 }*/
243 if( ! wpforo_db_check( [ 'table' => WPF()->tables->usergroups, 'col' => 'secondary', 'check' => 'col_exists' ] ) ) {
244 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->usergroups . "` ADD `secondary` TINYINT(1) NOT NULL DEFAULT 0;" );
245 @WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `secondary` = 1 WHERE `groupid` IN(3,5)" );
246 }
247 #################################################################
248 // ADD `fields` field in profiles TABLE ////////////////////////
249 if( ! wpforo_db_check( [ 'table' => WPF()->tables->profiles, 'col' => 'fields', 'check' => 'col_exists' ] ) ) {
250 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->profiles . "` ADD `fields` LONGTEXT" );
251 }
252 #################################################################
253 // Change `phrase_key` type in phrases TABLE ///////////////////
254 if( strtolower( (string) wpforo_db_check( [ 'table' => WPF()->tables->phrases, 'col' => 'phrase_key', 'check' => 'col_type' ] ) ) !== 'text' ) {
255 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->phrases . "` MODIFY `phrase_key` TEXT" );
256 }
257 #################################################################
258 // ADD `prefix` and `tags` fields in TOPIC TABLE ///////////////
259 if( ! wpforo_db_check( [ 'table' => WPF()->tables->topics, 'col' => 'tags', 'check' => 'col_exists' ] ) ) {
260 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "`
261 ADD `prefix` VARCHAR(100) NOT NULL DEFAULT '',
262 ADD `tags` TEXT,
263 ADD KEY (`prefix`),
264 ADD KEY (`tags`(190))"
265 );
266 }
267 #################################################################
268 //Add last_post indexes for forums and topics tables ////////////
269 if( ! wpforo_db_check( [ 'table' => WPF()->tables->forums, 'col' => 'last_postid', 'check' => 'key_exists' ] ) ) {
270 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->forums . "` ADD KEY(`last_postid`)" );
271 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->topics . "` ADD KEY `forumid_status_private` ( `forumid`,`status`,`private` ), ADD KEY(`last_post`)" );
272 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD KEY `forumid_status_private` (`forumid`, `status`, `private`)" );
273 }
274 #################################################################
275 //Add cover and cover_height fields to forums table ////////////
276 if( ! wpforo_db_check( [ 'table' => WPF()->tables->forums, 'col' => 'cover', 'check' => 'col_exists' ] ) ){
277 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->forums . "`
278 ADD COLUMN `cover` BIGINT UNSIGNED NOT NULL DEFAULT 0,
279 ADD COLUMN `cover_height` INT(4) UNSIGNED NOT NULL DEFAULT 150"
280 );
281 }
282
283 #################################################################
284 //rename column from cat_layout to layout in forums table ////////////
285 if( wpforo_db_check( [ 'table' => WPF()->tables->forums, 'col' => 'cat_layout', 'check' => 'col_exists' ] ) ){
286 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->forums . "`
287 CHANGE COLUMN `cat_layout` `layout` tinyint(1) UNSIGNED NOT NULL DEFAULT 0"
288 );
289 }
290 #################################################################
291 //Add unique keys in VISITS TABLE ///////////////////////////////
292 if( ! wpforo_db_check( [ 'table' => WPF()->tables->visits, 'col' => 'unique_tracking', 'check' => 'key_exists' ] ) ) {
293 wpforo_add_unique_key( WPF()->tables->visits, 'id', 'unique_tracking', '`userid`,`ip`,`forumid`,`topicid`' );
294 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->visits . "` ADD KEY `time_forumid` (`time`, `forumid`)" );
295 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->visits . "` ADD KEY `time_topicid` (`time`, `topicid`)" );
296 }
297 #################################################################
298 // ADD `color` field in forums TABLE ///////////////////////////
299 if( ! wpforo_db_check( [ 'table' => WPF()->tables->forums, 'col' => 'color', 'check' => 'col_exists' ] ) ) {
300 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->forums . "` ADD `color` varchar(7) NOT NULL DEFAULT ''" );
301 @WPF()->db->query( "UPDATE `" . WPF()->tables->forums . "` SET `color` = concat('#',SUBSTRING((lpad(hex(round(rand() * 10000000)),6,0)),-6))" );
302 }
303 #################################################################
304 // ADD `root` fields in POSTS TABLE ///////////////
305 //$post_table_count = @WPF()->db->get_var("SELECT COUNT(*) FROM `".WPF()->tables->posts."`");
306 //if( $post_table_count < 100000 ){
307 if( ! wpforo_db_check( [ 'table' => WPF()->tables->posts, 'col' => 'root', 'check' => 'col_exists' ] ) ) {
308 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->posts . "` ADD `root` BIGINT, ADD KEY(`root`)" );
309 }
310 //}
311 #################################################################
312 // ADD `new` in ACTIVITY TABLE /////////////////////////////////
313 if( ! wpforo_db_check( [ 'table' => WPF()->tables->activity, 'col' => 'new', 'check' => 'col_exists' ] ) ) {
314 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->activity . "` ADD `new` TINYINT NOT NULL DEFAULT '0' AFTER `permalink`, ADD KEY `itemtype_userid_new` (`itemtype`, `userid`, `new`)" );
315 }
316
317 #################################################################
318 // Change `last_userid` type in forums TABLE ///////////////////
319 if( strtolower( (string) wpforo_db_check( [ 'table' => WPF()->tables->forums, 'col' => 'last_userid', 'check' => 'col_type' ] ) ) !== 'varchar(255)' ) {
320 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->forums . "` CHANGE `last_userid` `last_userid` VARCHAR(255) NOT NULL" );
321 @WPF()->db->query( "ALTER TABLE `" . WPF()->tables->forums . "` ADD KEY `last_userid` (`last_userid`(191));" );
322 }
323
324 ################################################################
325 // likes and votes Table to new reactions table ////////////////
326 if( wpforo_db_check( [ 'table' => wpforo_fix_table_name( 'votes' ), 'check' => 'table_exists' ] ) ){
327 $sql = "INSERT IGNORE INTO `". WPF()->tables->reactions ."` (
328 SELECT NULL, `userid`, `postid`, `post_userid`, `reaction`, IF( `reaction` = 1, 'up', 'down' ), NULL, NULL
329 FROM `". wpforo_fix_table_name( 'votes' ) ."`
330 )";
331 WPF()->db->query($sql);
332 $sql = "DROP TABLE `". wpforo_fix_table_name( 'votes' ) ."`";
333 WPF()->db->query($sql);
334 }
335
336 if( wpforo_db_check( [ 'table' => wpforo_fix_table_name( 'likes' ), 'check' => 'table_exists' ] ) ){
337 $sql = "INSERT IGNORE INTO `". WPF()->tables->reactions ."` (
338 SELECT NULL, `userid`, `postid`, `post_userid`, 1, 'up', NULL, NULL
339 FROM `". wpforo_fix_table_name( 'likes' ) ."`
340 )";
341 WPF()->db->query($sql);
342 $sql = "DROP TABLE `". wpforo_fix_table_name( 'likes' ) ."`";
343 WPF()->db->query($sql);
344 }
345
346 ################################################################
347 // profiles table fields fixing ////////////////////////////////
348 if( wpforo_db_check( [ 'table' => WPF()->tables->profiles, 'col' => 'facebook', 'check' => 'col_exists' ] ) ){
349 $sql = "SELECT `userid`, `facebook`, `twitter`, `skype`, `fields`
350 FROM `". WPF()->tables->profiles ."`
351 WHERE (`facebook` IS NOT NULL AND `facebook` <> '')
352 OR (`twitter` IS NOT NULL AND `twitter` <> '')
353 OR (`skype` IS NOT NULL AND `skype` <> '')";
354 if( $users = (array) WPF()->db->get_results( $sql, ARRAY_A ) ){
355 foreach( $users as $user ){
356 $user['userid'] = wpforo_bigintval( $user['userid'] );
357 $facebook = trim( (string) $user['facebook'] );
358 $twitter = trim( (string) $user['twitter'] );
359 $skype = trim( (string) $user['skype'] );
360 $user['fields'] = array_merge( (array) json_decode($user['fields'], true), compact( 'facebook', 'twitter', 'skype' ) );
361 $user['fields'] = json_encode( $user['fields'] );
362 WPF()->db->update(
363 WPF()->tables->profiles,
364 [ 'fields' => $user['fields'] ],
365 [ 'userid' => $user['userid'] ],
366 '%s',
367 '%d'
368 );
369 }
370 }
371
372 @WPF()->db->query(
373 "ALTER TABLE `". WPF()->tables->profiles ."`
374 DROP COLUMN `username`,
375 DROP COLUMN `last_login`,
376 DROP COLUMN `icq`,
377 DROP COLUMN `aim`,
378 DROP COLUMN `yahoo`,
379 DROP COLUMN `msn`,
380 DROP COLUMN `gtalk`,
381 DROP COLUMN `like`,
382 DROP COLUMN `site`,
383 DROP COLUMN `facebook`,
384 DROP COLUMN `twitter`,
385 DROP COLUMN `skype`,
386 ADD COLUMN `topics` INT UNSIGNED NOT NULL DEFAULT 0 AFTER `posts`,
387 ADD COLUMN `reactions_in` TEXT AFTER `comments`,
388 ADD COLUMN `reactions_out` TEXT AFTER `reactions_in`,
389 ADD COLUMN `points` INT NOT NULL DEFAULT 0 AFTER `reactions_out`,
390 CHANGE COLUMN `secondary_groups` `secondary_groupids` VARCHAR(255) AFTER `groupid`,
391 CHANGE COLUMN `rank` `custom_points` INT NOT NULL DEFAULT 0 AFTER `points`,
392 MODIFY COLUMN `avatar` VARCHAR(255) AFTER `secondary_groupids`,
393 MODIFY COLUMN `online_time` INT UNSIGNED AFTER `custom_points`,
394 MODIFY COLUMN `timezone` VARCHAR(255) NOT NULL DEFAULT '' AFTER `online_time`,
395 MODIFY COLUMN `location` VARCHAR(255) AFTER `timezone`,
396 ADD COLUMN `cover` VARCHAR(255) NOT NULL DEFAULT '' AFTER `avatar`,
397 ADD COLUMN `is_mention_muted` TINYINT(1) NOT NULL DEFAULT 0 AFTER `is_email_confirmed`"
398 );
399 }
400
401 WPF()->db->query( "TRUNCATE TABLE `" . WPF()->tables->visits . "`" );
402 }
403
404 function wpforo_board_repair( $boardid ){
405 if( ! wpforo_is_admin() ) return;
406 if( ! current_user_can( 'activate_plugins' ) ) return;
407
408 WPF()->change_board( $boardid );
409
410 wpforo_activation();
411
412 foreach( wpforo_get_addons_info() as $key => $addon ){
413 if( ( $addon['base'] || wpforo_is_module_enabled( $key ) ) && is_callable( wpfval( $addon, 'install_func' ) ) ){
414 call_user_func( $addon['install_func'] );
415 }
416 }
417 }
418
419 function wpforo_board_uninstall( $boardid ) {
420 if( ! wpforo_is_admin() ) return;
421 if( ! current_user_can( 'activate_plugins' ) ) return;
422
423 WPF()->change_board( $boardid );
424 WPF()->board->delete( $boardid );
425 foreach( WPF()->_tables as $table ) WPF()->db->query( "DROP TABLE IF EXISTS `" . wpforo_fix_table_name( $table ) . "`" );
426
427 WPF()->db->query(
428 "DELETE FROM `" . WPF()->db->options . "`
429 WHERE `option_name` LIKE 'widget_wpforo_widget_%'
430 OR `option_name` REGEXP '^" . wpforo_prefix() . "'"
431 );
432 WPF()->db->query( "DELETE FROM `" . WPF()->db->usermeta . "` WHERE `meta_key` REGEXP '^" . wpforo_prefix() . "'" );
433
434 wpforo_remove_directory( WPF()->folders['upload']['dir'] );
435 }
436
437 function wpforo_uninstall(){
438 if( ! wpforo_is_admin() ) return;
439 if( ! current_user_can( 'activate_plugins' ) ) return;
440 require_once ABSPATH . 'wp-admin/includes/plugin.php';
441 foreach( WPF()->board->get_boards( [ 'orderby' => '`boardid` DESC' ] ) as $board ) wpforo_board_uninstall( $board['boardid'] );
442 WPF()->db->query(
443 "DELETE FROM `" . WPF()->db->options . "`
444 WHERE `option_name` LIKE 'widget_wpforo%'
445 OR `option_name` REGEXP '^" . WPF()->base_prefix . "'"
446 );
447 WPF()->db->query( "DELETE FROM `" . WPF()->db->usermeta . "` WHERE `meta_key` REGEXP '^" . WPF()->base_prefix . "'" );
448 foreach( WPF()->_base_tables as $table ) WPF()->db->query( "DROP TABLE IF EXISTS `" . wpforo_fix_table_name( $table ) . "`" );
449 deactivate_plugins( WPFORO_BASENAME );
450 }
451
452 function wpforo_profile_notice() {
453 if( is_multisite() ) {
454 $users = WPF()->db->get_var( "SELECT COUNT(*) FROM `" . WPF()->db->usermeta . "` WHERE `meta_key` LIKE '" . WPF()->blog_prefix . "capabilities'" );
455 } else {
456 $users = WPF()->db->get_var( "SELECT COUNT(*) FROM `" . WPF()->db->users . "`" );
457 }
458 $profiles = WPF()->db->get_var( "SELECT COUNT(*) FROM `" . WPF()->tables->profiles . "`" );
459 $delta = $users - $profiles;
460 $status = ( $delta > 2 ) ? round( ( ( $profiles * 100 ) / $users ), 1 ) . '% (' . $profiles . ' / ' . $users . ') ' : '100%';
461 if( $status === '100%' ) return null;
462 $btext = ( $profiles == 0 ) ? __( 'Start Profile Synchronization', 'wpforo' ) : __( 'Continue Synchronization', 'wpforo' );
463 $url = wp_nonce_url( admin_url( 'admin.php?page=wpforo-overview&wpfaction=synch_user_profiles' ), 'wpforo_synch_user_profiles' );
464 $class = 'wpforo-mnote notice notice-warning is-dismissible';
465 $note = __( 'This process may take a few seconds or dozens of minutes, please be patient and don\'t close this page.', 'wpforo' );
466 $info = __( 'You can permanently disable this message using this documentation', 'wpforo' );
467 $button = '<a href="' . $url . '" class="button button-primary button-large" style="font-size:14px;">' . $btext . ' &gt;&gt;</a>';
468 $header = __( 'wpForo Forum Installation | ', 'wpforo' );
469 $message = __( 'Forum users\' profile data are not synchronized yet, this step is required! Please click the button below to complete installation.', 'wpforo' );
470 echo '<div class="' . $class . '" style="padding:15px 20px;"><h2 style="margin:0;">' . esc_html( $header ) . $status . ' </h2><p style="font-size:15px;margin:5px 0;">' . $message . '</p><p style="margin:0 0 10px 0;">' . $button . '</p><hr /><p style="margin:0;color:#dd0000;">' . $note . '</p></div>';
471 }
472
473 function wpforo_database_notice() {
474 $url = admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) . '&tab=tables' );
475 $class = 'wpforo-dbnote notice notice-error is-dismissible';
476 $button = '<a href="' . $url . '" class="button button-primary button-large" style="font-size:13px;">Go to Database Troubleshooter &gt;&gt;</a>';
477 $header = __( 'wpForo Database Update Problem - Action Required!', 'wpforo' );
478 $message = __( 'Forum database is not updated properly. Please click the button below for further instruction.', 'wpforo' );
479 echo '<div class="' . $class . '" style="padding:15px 20px;"><h2 style="margin:0;">' . esc_html( $header ) . ' </h2><p style="font-size:15px;margin:5px 0;">' . $message . '</p><p style="margin:15px 0 0 0;">' . $button . '</p></div>';
480 }
481
482 function wpforo_cache_information() {
483 $plugin_names = [];
484 $plugin_steps = [];
485 $not_excluded_plugins = WPF()->cache->cache_plugins_status();
486 if( !empty($not_excluded_plugins) ){
487 foreach( $not_excluded_plugins as $key => $plugin ){
488 $plugin_names[$key] = '&laquo;' . $plugin['name'] . '&raquo;';
489 $plugin_steps[$key] = '<h4 style="margin: 0; font-size: 14px;">' . __('Exclude forum page(s) from') . ' ' . $plugin['name'] . ' ' . __('plugin', 'wpforo') . '</h4><ol style="font-size: 14px; color: #6203a2;"><li style="margin-bottom: 4px;">' . implode('</li><li style="margin-bottom: 4px;">', $plugin['steps']) . '</ol></li>';
490 }
491 }
492 $class = 'wpforo-cache-conflict-note notice notice-error is-dismissible';
493 $note = sprintf( __( 'If you have already excluded the forum page from your cache plugin please ignore and close this message using the top %s (x) button.', 'wpforo' ), ( is_rtl() ? __('left', 'wpforo') : __('right', 'wpforo') ) );
494 $info = __( 'Please find more information here: ', 'wpforo' ) . '<a href="https://wpforo.com/community/faq/wpforo-and-cache-plugins/" target="_blank">wpForo and Cache Plugins</a>';
495 $header = 'wpForo ' . __(' and ', 'wpforo') . implode( __(' and ', 'wpforo'), $plugin_names) . ' ' . __('conflict', 'wpforo') . ' - ' . __( 'Action Required!', 'wpforo' );
496 $message = __( 'Please exclude the forum page from your cache plugin! wpForo has a built-in cache system. It does dynamic cache of all forum pages, which will be affected by your cache plugin and the forum data will not be updated on the front-end. The user login and logout actions will also be corrupted.', 'wpforo' ) . '<br />' .
497 implode('<br>', $plugin_steps);
498
499 echo '<div class="' . $class . '" style="padding:15px 20px;"><h2 style="margin:0;">' . esc_html( $header ) . ' </h2><p style="font-size:15px;margin:10px 0;">' . $message . '</p><hr /><p style="margin:0;color:#dd0000; font-size:14px;">' . $note . '</p><p style="margin:0;font-size:12px;">' . $info . '</p></div>';
500 echo "<script>jQuery(document).on('click', '.wpforo-cache-conflict-note .notice-dismiss', function () {jQuery.ajax({ url: ajaxurl, data: { action: 'dismiss_wpforo_cache_conflict_note' } })})</script>";
501 }
502
503 function wpforo_get_shortcode_pageid( $exclude = [] ) {
504 $exclude = array_filter( array_map( 'wpforo_bigintval', (array) $exclude ) );
505 $sql = "SELECT `ID` FROM `" . WPF()->db->posts . "`
506 WHERE `post_content` LIKE '%[wpforo]%'
507 AND `post_status` LIKE 'publish'
508 AND `post_type` IN('" . implode( "','", wpforo_get_blog_content_types() ) . "')";
509 if( $exclude ) $sql .= " AND `ID` NOT IN(" . implode( ',', $exclude ) . ")";
510
511 return WPF()->db->get_var( $sql );
512 }
513
514 function wpforo_create_forum_page() {
515 $pageid = WPF()->board->get_current( 'pageid' );
516 if( ! $pageid || ! WPF()->db->get_var( "SELECT `ID` FROM `" . WPF()->db->posts . "` WHERE `ID` = '" . $pageid . "' AND ( `post_content` LIKE '%[wpforo]%' OR `post_content` LIKE '%[wpforo-index]%' ) AND `post_status` LIKE 'publish' AND `post_type` IN('" . implode( "','", wpforo_get_blog_content_types() ) . "')" ) ) {
517 if( ! $page_id = wpforo_get_shortcode_pageid( get_option( 'page_on_front' ) ) ) {
518 $wpforo_page = [
519 'post_date' => current_time( 'mysql', 1 ),
520 'post_date_gmt' => current_time( 'mysql', 1 ),
521 'post_content' => '[wpforo]',
522 'post_title' => 'Forum',
523 'post_status' => 'publish',
524 'comment_status' => 'close',
525 'ping_status' => 'close',
526 'post_name' => 'community',
527 'post_modified' => current_time( 'mysql', 1 ),
528 'post_modified_gmt' => current_time( 'mysql', 1 ),
529 'post_parent' => 0,
530 'menu_order' => 0,
531 'post_type' => 'page',
532 ];
533 $page_id = wp_insert_post( $wpforo_page );
534 }
535 if( $page_id && ! is_wp_error( $page_id ) ) {
536 wpforo_update_option( 'wpforo_pageid', $page_id );
537 }
538 }
539
540 flush_rewrite_rules( false );
541 nocache_headers();
542 }
543
544 function wpforo_repair_main_shortcode_page() {
545 $pageid = WPF()->board->get_current( 'pageid' );
546 $sql = "SELECT `ID` FROM `" . WPF()->db->posts . "`
547 WHERE `ID` = " . $pageid . "
548 AND `post_content` LIKE '%[wpforo%'
549 AND `post_status` LIKE 'publish'
550 AND `post_type` IN('" . implode( "','", wpforo_get_blog_content_types() ) . "')";
551 if( ! $pageid || ! WPF()->db->get_var( $sql ) ) {
552 wpforo_create_forum_page();
553 } else {
554 flush_rewrite_rules( false );
555 nocache_headers();
556 }
557 }
558
559 function wpforo_import_default_board() {
560 if( ! WPF()->board->get_current( 'boardid' ) && ! WPF()->board->_get_board( 0 ) ) {
561 $blogname = get_option( 'blogname', '' );
562 $_general = wpforo_get_option( 'wpforo_general_options', [
563 'title' => $blogname . ' ' . __( 'Forum', 'wpforo' ),
564 'description' => $blogname . ' ' . __( 'Discussion Board', 'wpforo' ),
565 'lang' => 1
566 ], false );
567 $board = WPF()->board->get_current();
568 $board['slug'] = basename( trim( (string) wpforo_get_option( 'wpforo_permastruct', 'community', false ), '/' ) );
569 $board['is_standalone'] = wpforo_get_option( 'wpforo_use_home_url', false );
570 $board['excld_urls'] = array_filter( array_map( 'trim', explode( PHP_EOL, (string) wpforo_get_option( 'wpforo_excld_urls', '' ) ) ) );
571 $board['settings'] = [];
572 $board['settings']['title'] = $_general['title'];
573 $board['settings']['desc'] = $_general['description'];
574 if( $boardid = WPF()->board->add( $board ) ){
575 WPF()->board->edit( [ 'boardid' => 0 ], $boardid );
576 }
577 }
578 }
579
580 function wpforo_import_default_menus() {
581 $boardid = WPF()->board->get_current( 'boardid' );
582 $menu_name = wpforo_phrase( 'wpForo Navigation', false, 'orig' ) . ( $boardid ? ' #' . $boardid : '' );
583 $menu_location = wpforo_prefix_slug( 'menu' );
584 $menu_exists = wp_get_nav_menu_object( $menu_name );
585 if( ! $menu_exists ) {
586 $id = [];
587 $menu_id = wp_create_nav_menu( $menu_name );
588 $id['wpforo-home'] = wp_update_nav_menu_item( $menu_id, 0, [
589 'menu-item-title' => wpforo_phrase( 'Forums', false ),
590 'menu-item-classes' => 'wpforo-home',
591 'menu-item-url' => '/%wpforo-home%/',
592 'menu-item-status' => 'publish',
593 'menu-item-parent-id' => 0,
594 'menu-item-position' => 0,
595 ] );
596
597 $id['wpforo-members'] = wp_update_nav_menu_item( $menu_id, 0, [
598 'menu-item-title' => wpforo_phrase( 'Members', false ),
599 'menu-item-classes' => 'wpforo-members',
600 'menu-item-url' => '/%wpforo-members%/',
601 'menu-item-status' => 'publish',
602 'menu-item-parent-id' => 0,
603 'menu-item-position' => 0,
604 ] );
605
606 $id['wpforo-recent'] = wp_update_nav_menu_item( $menu_id, 0, [
607 'menu-item-title' => wpforo_phrase( 'Recent Posts', false ),
608 'menu-item-classes' => 'wpforo-recent',
609 'menu-item-url' => '/%wpforo-recent%/',
610 'menu-item-status' => 'publish',
611 'menu-item-parent-id' => 0,
612 'menu-item-position' => 0,
613 ] );
614
615 $id['wpforo-profile'] = wp_update_nav_menu_item( $menu_id, 0, [
616 'menu-item-title' => wpforo_phrase( 'My Profile', false ),
617 'menu-item-classes' => 'wpforo-profile',
618 'menu-item-url' => '/%wpforo-profile-home%/',
619 'menu-item-status' => 'publish',
620 'menu-item-parent-id' => 0,
621 'menu-item-position' => 0,
622 ] );
623
624 if( isset( $id['wpforo-profile'] ) && $id['wpforo-profile'] ) {
625 $id['wpforo-profile-account'] = wp_update_nav_menu_item( $menu_id, 0, [
626 'menu-item-title' => wpforo_phrase( 'Account', false ),
627 'menu-item-classes' => 'wpforo-profile-account',
628 'menu-item-url' => '/%wpforo-profile-account%/',
629 'menu-item-status' => 'publish',
630 'menu-item-parent-id' => $id['wpforo-profile'],
631 'menu-item-position' => 1,
632 ] );
633 $id['wpforo-profile-activity'] = wp_update_nav_menu_item( $menu_id, 0, [
634 'menu-item-title' => wpforo_phrase( 'Activity', false ),
635 'menu-item-classes' => 'wpforo-profile-activity',
636 'menu-item-url' => '/%wpforo-profile-activity%/',
637 'menu-item-status' => 'publish',
638 'menu-item-parent-id' => $id['wpforo-profile'],
639 'menu-item-position' => 1,
640 ] );
641 $id['wpforo-profile-subscriptions'] = wp_update_nav_menu_item( $menu_id, 0, [
642 'menu-item-title' => wpforo_phrase( 'Subscriptions', false ),
643 'menu-item-classes' => 'wpforo-profile-subscriptions',
644 'menu-item-url' => '/%wpforo-profile-subscriptions%/',
645 'menu-item-status' => 'publish',
646 'menu-item-parent-id' => $id['wpforo-profile'],
647 'menu-item-position' => 2,
648 ] );
649 }
650
651 $id['wpforo-register'] = wp_update_nav_menu_item( $menu_id, 0, [
652 'menu-item-title' => wpforo_phrase( 'Register', false ),
653 'menu-item-classes' => 'wpforo-register',
654 'menu-item-url' => '/%wpforo-register%/',
655 'menu-item-status' => 'publish',
656 'menu-item-parent-id' => 0,
657 'menu-item-position' => 0,
658 ] );
659
660 $id['wpforo-login'] = wp_update_nav_menu_item( $menu_id, 0, [
661 'menu-item-title' => wpforo_phrase( 'Login', false ),
662 'menu-item-classes' => 'wpforo-login',
663 'menu-item-url' => '/%wpforo-login%/',
664 'menu-item-status' => 'publish',
665 'menu-item-parent-id' => 0,
666 'menu-item-position' => 0,
667 ] );
668
669 $id['wpforo-logout'] = wp_update_nav_menu_item( $menu_id, 0, [
670 'menu-item-title' => wpforo_phrase( 'Logout', false ),
671 'menu-item-classes' => 'wpforo-logout',
672 'menu-item-url' => '/%wpforo-logout%/',
673 'menu-item-status' => 'publish',
674 'menu-item-parent-id' => 0,
675 'menu-item-position' => 0,
676 ] );
677
678 if( ! has_nav_menu( $menu_location ) ) {
679 $locations = get_theme_mod( 'nav_menu_locations' );
680 if( empty( $locations ) ) $locations = [];
681 $locations[ $menu_location ] = $menu_id;
682 set_theme_mod( 'nav_menu_locations', $locations );
683 }
684 }
685 }
686
687 function wpforo_import_default_accesses() {
688 $cans_n = [
689 'vf' => 0,
690 'enf' => 0,
691 'ct' => 0,
692 'vt' => 0,
693 'ent' => 0,
694 'et' => 0,
695 'dt' => 0,
696 'cr' => 0,
697 'ocr' => 0,
698 'vr' => 0,
699 'er' => 0,
700 'dr' => 0,
701 'tag' => 0,
702 'eot' => 0,
703 'eor' => 0,
704 'dot' => 0,
705 'dor' => 0,
706 'sb' => 0,
707 'l' => 0,
708 'r' => 0,
709 's' => 0,
710 'au' => 0,
711 'p' => 0,
712 'op' => 0,
713 'vp' => 0,
714 'sv' => 0,
715 'osv' => 0,
716 'v' => 0,
717 'vop' => 0,
718 'vlp' => 0,
719 'a' => 0,
720 'va' => 0,
721 'at' => 0,
722 'oat' => 0,
723 'aot' => 0,
724 'cot' => 0,
725 'mt' => 0,
726 'ccp' => 0,
727 'cvp' => 0,
728 'cvpr' => 0,
729 ];
730 $cans_r = [
731 'vf' => 1,
732 'enf' => 1,
733 'ct' => 0,
734 'vt' => 1,
735 'ent' => 1,
736 'et' => 0,
737 'dt' => 0,
738 'cr' => 0,
739 'ocr' => 0,
740 'vr' => 1,
741 'er' => 0,
742 'dr' => 0,
743 'tag' => 0,
744 'eot' => 0,
745 'eor' => 0,
746 'dot' => 0,
747 'dor' => 0,
748 'sb' => 1,
749 'l' => 0,
750 'r' => 0,
751 's' => 0,
752 'au' => 0,
753 'p' => 0,
754 'op' => 0,
755 'vp' => 0,
756 'sv' => 0,
757 'osv' => 0,
758 'v' => 0,
759 'vop' => 0,
760 'vlp' => 1,
761 'a' => 0,
762 'va' => 1,
763 'at' => 0,
764 'oat' => 0,
765 'aot' => 0,
766 'cot' => 0,
767 'mt' => 0,
768 'ccp' => 0,
769 'cvp' => 0,
770 'cvpr' => 1,
771 ];
772 $cans_s = [
773 'vf' => 1,
774 'enf' => 1,
775 'ct' => 1,
776 'vt' => 1,
777 'ent' => 1,
778 'et' => 0,
779 'dt' => 0,
780 'cr' => 1,
781 'ocr' => 1,
782 'vr' => 1,
783 'er' => 0,
784 'dr' => 0,
785 'tag' => 1,
786 'eot' => 1,
787 'eor' => 1,
788 'dot' => 1,
789 'dor' => 1,
790 'sb' => 1,
791 'l' => 1,
792 'r' => 1,
793 's' => 0,
794 'au' => 0,
795 'p' => 0,
796 'op' => 1,
797 'vp' => 0,
798 'sv' => 0,
799 'osv' => 1,
800 'v' => 1,
801 'vop' => 1,
802 'vlp' => 1,
803 'a' => 1,
804 'va' => 1,
805 'at' => 0,
806 'oat' => 1,
807 'aot' => 1,
808 'cot' => 0,
809 'mt' => 0,
810 'ccp' => 1,
811 'cvp' => 1,
812 'cvpr' => 1,
813 ];
814 $cans_m = [
815 'vf' => 1,
816 'enf' => 1,
817 'ct' => 1,
818 'vt' => 1,
819 'ent' => 1,
820 'et' => 1,
821 'dt' => 1,
822 'cr' => 1,
823 'ocr' => 1,
824 'vr' => 1,
825 'er' => 1,
826 'dr' => 1,
827 'tag' => 1,
828 'eot' => 1,
829 'eor' => 1,
830 'dot' => 1,
831 'dor' => 1,
832 'sb' => 1,
833 'l' => 1,
834 'r' => 1,
835 's' => 1,
836 'au' => 1,
837 'p' => 1,
838 'op' => 1,
839 'vp' => 1,
840 'sv' => 1,
841 'osv' => 1,
842 'v' => 1,
843 'vop' => 1,
844 'vlp' => 1,
845 'a' => 1,
846 'va' => 1,
847 'at' => 1,
848 'oat' => 1,
849 'aot' => 1,
850 'cot' => 1,
851 'mt' => 1,
852 'ccp' => 1,
853 'cvp' => 1,
854 'cvpr' => 1,
855 ];
856 $cans_a = [
857 'vf' => 1,
858 'enf' => 1,
859 'ct' => 1,
860 'vt' => 1,
861 'ent' => 1,
862 'et' => 1,
863 'dt' => 1,
864 'cr' => 1,
865 'ocr' => 1,
866 'vr' => 1,
867 'er' => 1,
868 'dr' => 1,
869 'tag' => 1,
870 'eot' => 1,
871 'eor' => 1,
872 'dot' => 1,
873 'dor' => 1,
874 'sb' => 1,
875 'l' => 1,
876 'r' => 1,
877 's' => 1,
878 'au' => 1,
879 'p' => 1,
880 'op' => 1,
881 'vp' => 1,
882 'sv' => 1,
883 'osv' => 1,
884 'v' => 1,
885 'vop' => 1,
886 'vlp' => 1,
887 'a' => 1,
888 'va' => 1,
889 'at' => 1,
890 'oat' => 1,
891 'aot' => 1,
892 'cot' => 1,
893 'mt' => 1,
894 'ccp' => 1,
895 'cvp' => 1,
896 'cvpr' => 1,
897 ];
898
899 //Add new Accesses in this array to add those in custom Accesses created by forum admin
900 $cans_default = [
901 'sb' => 1,
902 'au' => 1,
903 'p' => 0,
904 'op' => 1,
905 'vp' => 0,
906 'ccp' => 0,
907 'cvp' => 0,
908 'cvpr' => 1,
909 'aot' => 1,
910 'tag' => 1,
911 'ocr' => 0,
912 'enf' => 1,
913 'ent' => 1,
914 'vop' => 1,
915 'vlp' => 1,
916 ];
917
918 $sql = "SELECT * FROM `" . WPF()->tables->accesses . "`";
919 $accesses = WPF()->db->get_results( $sql, ARRAY_A );
920 if( empty( $accesses ) ) {
921 $cans_n = serialize( $cans_n );
922 $cans_r = serialize( $cans_r );
923 $cans_s = serialize( $cans_s );
924 $cans_m = serialize( $cans_m );
925 $cans_a = serialize( $cans_a );
926
927 $sql = "INSERT IGNORE INTO `" . WPF()->tables->accesses . "`
928 (`access`, `title`, cans) VALUES
929 ('no_access', 'No access', '" . $cans_n . "'),
930 ('read_only', 'Read only access', '" . $cans_r . "'),
931 ('standard', 'Standard access', '" . $cans_s . "'),
932 ('moderator', 'Moderator access', '" . $cans_m . "'),
933 ('full', 'Full access', '" . $cans_a . "')";
934
935 WPF()->db->query( $sql );
936 } else {
937 foreach( $accesses as $access ) {
938 $current = unserialize( $access['cans'] );
939 if( strtolower( (string) $access['access'] ) === 'no_access' ) {
940 $default = $cans_n;
941 } elseif( strtolower( (string) $access['access'] ) === 'read_only' ) {
942 $default = $cans_r;
943 } elseif( strtolower( (string) $access['access'] ) === 'standard' ) {
944 $default = $cans_s;
945 } elseif( strtolower( (string) $access['access'] ) === 'moderator' ) {
946 $default = $cans_m;
947 } elseif( strtolower( (string) $access['access'] ) === 'full' ) {
948 $default = $cans_a;
949 } else {
950 $default = $cans_default;
951 }
952 if( ! empty( $default ) ) {
953 $data_update = array_merge( $default, $current );
954 if( ! empty( $data_update ) ) {
955 $data_update = serialize( $data_update );
956 WPF()->db->query( "UPDATE `" . WPF()->tables->accesses . "` SET `cans` = '" . WPF()->db->_real_escape( $data_update ) . "' WHERE `accessid` = " . intval( $access['accessid'] ) );
957 }
958 }
959 }
960 }
961 }
962
963 function wpforo_import_default_usergroups() {
964 $cans_admin = [
965 'mf' => 1,
966 'ms' => 1,
967 'mt' => 1,
968 'mp' => 1,
969 'mth' => 1,
970 'vm' => 1,
971 'aum' => 1,
972 'em' => 1,
973 'vmg' => 1,
974 'aup' => 1,
975 'vmem' => 1,
976 'view_stat' => 1,
977 'vprf' => 1,
978 'vpra' => 1,
979 'vprs' => 1,
980 'bm' => 1,
981 'dm' => 1,
982 'upc' => 1,
983 'upa' => 1,
984 'ups' => 1,
985 'va' => 1,
986 'vmu' => 1,
987 'vmm' => 1,
988 'vmt' => 1,
989 'vmct' => 1,
990 'vmr' => 1,
991 'vmw' => 1,
992 'vmsn' => 1,
993 'vmrd' => 1,
994 'vml' => 1,
995 'vmo' => 1,
996 'vms' => 1,
997 'vmam' => 1,
998 'vwpm' => 1,
999 'caa' => 1,
1000 'vt_add_topic' => 1,
1001 ];
1002 $cans_moder = [
1003 'mf' => 0,
1004 'ms' => 0,
1005 'mt' => 0,
1006 'mp' => 0,
1007 'mth' => 0,
1008 'vm' => 0,
1009 'aum' => 1,
1010 'em' => 0,
1011 'vmg' => 0,
1012 'aup' => 1,
1013 'vmem' => 1,
1014 'view_stat' => 1,
1015 'vprf' => 1,
1016 'vpra' => 1,
1017 'vprs' => 1,
1018 'bm' => 1,
1019 'dm' => 1,
1020 'upc' => 1,
1021 'upa' => 1,
1022 'ups' => 1,
1023 'va' => 1,
1024 'vmu' => 0,
1025 'vmm' => 1,
1026 'vmt' => 1,
1027 'vmct' => 1,
1028 'vmr' => 1,
1029 'vmw' => 1,
1030 'vmsn' => 1,
1031 'vmrd' => 1,
1032 'vml' => 1,
1033 'vmo' => 1,
1034 'vms' => 1,
1035 'vmam' => 1,
1036 'vwpm' => 1,
1037 'caa' => 1,
1038 'vt_add_topic' => 1,
1039 ];
1040 $cans_reg = [
1041 'mf' => 0,
1042 'ms' => 0,
1043 'mt' => 0,
1044 'mp' => 0,
1045 'mth' => 0,
1046 'vm' => 0,
1047 'aum' => 0,
1048 'em' => 0,
1049 'vmg' => 0,
1050 'aup' => 1,
1051 'vmem' => 1,
1052 'view_stat' => 1,
1053 'vprf' => 1,
1054 'vpra' => 1,
1055 'vprs' => 0,
1056 'bm' => 0,
1057 'dm' => 0,
1058 'upc' => 1,
1059 'upa' => 1,
1060 'ups' => 1,
1061 'va' => 1,
1062 'vmu' => 0,
1063 'vmm' => 0,
1064 'vmt' => 1,
1065 'vmct' => 1,
1066 'vmr' => 1,
1067 'vmw' => 1,
1068 'vmsn' => 1,
1069 'vmrd' => 1,
1070 'vml' => 1,
1071 'vmo' => 1,
1072 'vms' => 1,
1073 'vmam' => 1,
1074 'vwpm' => 1,
1075 'caa' => 1,
1076 'vt_add_topic' => 1,
1077 ];
1078 $cans_guest = [
1079 'mf' => 0,
1080 'ms' => 0,
1081 'mt' => 0,
1082 'mp' => 0,
1083 'mth' => 0,
1084 'vm' => 0,
1085 'aum' => 0,
1086 'em' => 0,
1087 'vmg' => 0,
1088 'aup' => 0,
1089 'vmem' => 1,
1090 'view_stat' => 1,
1091 'vprf' => 1,
1092 'vpra' => 1,
1093 'vprs' => 0,
1094 'bm' => 0,
1095 'dm' => 0,
1096 'upc' => 0,
1097 'upa' => 0,
1098 'ups' => 0,
1099 'va' => 1,
1100 'vmu' => 0,
1101 'vmm' => 0,
1102 'vmt' => 1,
1103 'vmct' => 1,
1104 'vmr' => 1,
1105 'vmw' => 0,
1106 'vmsn' => 1,
1107 'vmrd' => 1,
1108 'vml' => 1,
1109 'vmo' => 1,
1110 'vms' => 1,
1111 'vmam' => 1,
1112 'vwpm' => 0,
1113 'caa' => 1,
1114 'vt_add_topic' => 0,
1115 ];
1116 $cans_customer = [
1117 'mf' => 0,
1118 'ms' => 0,
1119 'mt' => 0,
1120 'mp' => 0,
1121 'mth' => 0,
1122 'vm' => 0,
1123 'aum' => 0,
1124 'em' => 0,
1125 'vmg' => 0,
1126 'aup' => 0,
1127 'vmem' => 1,
1128 'view_stat' => 1,
1129 'vprf' => 1,
1130 'vpra' => 1,
1131 'vprs' => 0,
1132 'bm' => 0,
1133 'dm' => 0,
1134 'upc' => 1,
1135 'upa' => 1,
1136 'ups' => 1,
1137 'va' => 1,
1138 'vmu' => 0,
1139 'vmm' => 0,
1140 'vmt' => 1,
1141 'vmct' => 1,
1142 'vmr' => 1,
1143 'vmw' => 1,
1144 'vmsn' => 1,
1145 'vmrd' => 1,
1146 'vml' => 1,
1147 'vmo' => 1,
1148 'vms' => 1,
1149 'vmam' => 1,
1150 'vwpm' => 1,
1151 'caa' => 1,
1152 'vt_add_topic' => 1,
1153 ];
1154
1155 //Add new Cans in this array to add those in custom Usergroup created by forum admin
1156 $cans_defaults = [
1157 'mf' => 0,
1158 'ms' => 0,
1159 'mt' => 0,
1160 'mp' => 0,
1161 'mth' => 0,
1162 'vmem' => 1,
1163 'view_stat' => 1,
1164 'vprf' => 1,
1165 'caa' => 1,
1166 'vt_add_topic' => 1,
1167 'upc' => 1,
1168 ];
1169
1170 $sql = "SELECT * FROM `" . WPF()->tables->usergroups . "`";
1171 if( ! $usergroups = WPF()->db->get_results( $sql, ARRAY_A ) ) {
1172 WPF()->usergroup->add( 'Admin', $cans_admin, '', 'administrator', 'full', '#FF3333' );
1173 WPF()->usergroup->add( 'Moderator', $cans_moder, '', 'editor', 'moderator', '#0066FF' );
1174 WPF()->usergroup->add( 'Registered', $cans_reg, '', 'subscriber', 'standard', '', 1, 1 );
1175 WPF()->usergroup->add( 'Guest', $cans_guest, '', '', 'read_only', '#222222', 0 );
1176 WPF()->usergroup->add( 'Customer', $cans_customer, '', 'customer', 'standard', '#993366', 1, 1 );
1177 } else {
1178 foreach( $usergroups as $usergroup ) {
1179 $current = unserialize( $usergroup['cans'] );
1180 if( strtolower( (string) $usergroup['name'] ) === 'admin' ) {
1181 $default = $cans_admin;
1182 } elseif( strtolower( (string) $usergroup['name'] ) === 'moderator' ) $default = $cans_moder;
1183 elseif( strtolower( (string) $usergroup['name'] ) === 'registered' ) $default = $cans_reg;
1184 elseif( strtolower( (string) $usergroup['name'] ) === 'guest' ) $default = $cans_guest;
1185 elseif( strtolower( (string) $usergroup['name'] ) === 'customer' ) $default = $cans_customer;
1186 else {
1187 $default = $cans_defaults;
1188 }
1189 if( ! empty( $default ) ) {
1190 $data_update = array_merge( $default, $current );
1191 if( ! empty( $data_update ) ) {
1192 $data_update = serialize( $data_update );
1193 WPF()->db->query( "UPDATE `" . WPF()->tables->usergroups . "` SET `cans` = '" . WPF()->db->_real_escape( $data_update ) . "' WHERE `groupid` = " . intval( $usergroup['groupid'] ) );
1194 }
1195 }
1196 }
1197 }
1198 }
1199
1200 function wpforo_import_default_forums() {
1201 $sql = "SELECT COUNT(*) FROM `" . WPF()->tables->forums . "`";
1202 $count = WPF()->db->get_var( $sql );
1203 if( ! $count ) {
1204 if( $parentid = WPF()->forum->add( [ 'title' => __( 'Main Category', 'wpforo' ), 'description' => __( 'This is a simple category / section', 'wpforo' ), 'layout' => 4, 'icon' => 'fas fa-comments' ], false ) ) {
1205 WPF()->forum->add( [ 'title' => __( 'Main Forum', 'wpforo' ), 'description' => __( 'This is a simple parent forum', 'wpforo' ), 'parentid' => $parentid, 'layout' => 4, 'icon' => 'fas fa-comments' ], false );
1206 }
1207 }
1208 }
1209
1210 function wpforo_fix_wp_permalink_structure() {
1211 $permalink_structure = get_option( 'permalink_structure' );
1212 if( ! $permalink_structure ) {
1213 global $wp_rewrite;
1214 $wp_rewrite->set_permalink_structure( '/%postname%/' );
1215 }
1216 }
1217
1218 function wpforo_fix_installed_options() {
1219 /**
1220 * in the update process, using old features settings set the right profile setting for the new option
1221 */
1222 if( $features = wpforo_get_option( 'features', [], false ) ) {
1223 if( ! (int) wpfval( $features, 'profile' ) ) {
1224 if( (int) wpfval( $features, 'bp_profile' ) && class_exists( 'BP_Component' ) ) {
1225 $features['profile'] = 3;
1226 } elseif( (int) wpfval( $features, 'um_profile' ) && function_exists( 'UM' ) ) {
1227 $features['profile'] = 4;
1228 } elseif( (int) wpfval( $features, 'comment-author-link' ) ) {
1229 $features['profile'] = 2;
1230 } else {
1231 $features['profile'] = 1;
1232 }
1233 wpforo_update_option( 'features', array_map( 'intval', $features ) );
1234 }
1235 }
1236
1237 #################################################################
1238 // CHECK Addon Notice /////////////////////////////////////////
1239 $lastHash = get_option( 'wpforo_addon_note_dismissed' );
1240 $first = get_option( 'wpforo_addon_note_first' );
1241 if( $lastHash && $first === 'true' ) {
1242 update_option( 'wpforo_addon_note_first', 'false' );
1243 }
1244
1245 #################################################################
1246 // AVOID PLUGIN CONFLICTS ///////////////////////////////////////
1247 /* Autoptimize *************************************************/
1248 $autopt = get_option( 'autoptimize_js_exclude' );
1249 if( $autopt && strpos( (string) $autopt, 'wp-includes/js/tinymce' ) === false ) {
1250 $autopt = $autopt . ', wp-includes/js/tinymce';
1251 update_option( 'autoptimize_js_exclude', $autopt );
1252 if( class_exists( 'autoptimizeCache' ) && is_callable( [ 'autoptimizeCache', 'clearall' ] ) ) {
1253 autoptimizeCache::clearall();
1254 }
1255 }
1256
1257 #################################################################
1258 // Adding #wpforo to custom css /////////////////////////////////
1259 if( $style_options = wpforo_get_option( 'style_options', [], false ) ) {
1260 $custom_css = wpfval( $style_options, 'custom_css' );
1261 if( $custom_css && strpos( (string) $custom_css, '#wpforo #wpforo-wrap' ) === false ) {
1262 $style_options['custom_css'] = str_replace( '#wpforo-wrap', '#wpforo #wpforo-wrap', $style_options['custom_css'] );
1263 wpforo_update_option( 'style_options', $style_options );
1264 }
1265 }
1266 }
1267
1268 function wpforo_update_theme_options() {
1269 if( $current_theme = wpforo_get_option( 'theme_options_' . WPF()->tpl->theme, [], false ) ) {
1270 $theme = WPF()->tpl->find_theme( '2022' );
1271 if( wpfval( $theme, 'layouts' ) ) {
1272 $current_theme['layouts'] = $theme['layouts'];
1273 $theme = wpforo_deep_merge( $theme, $current_theme );
1274 wpforo_update_option( 'theme_options_' . WPF()->tpl->theme, $theme );
1275 }
1276 }
1277 }
1278
1279 function wpforo_clean_up() {
1280 WPF()->db->delete( WPF()->tables->topics, [ 'first_postid' => 0 ], [ '%d' ] );
1281 }
1282
1283 // wpforo database checker fixer tools
1284 function wpforo_update_db() {
1285 $problems = wpforo_database_check();
1286 if( ! empty( $problems ) ) {
1287 $SQL = wpforo_database_fixer( $problems );
1288 if( wpfval( $SQL, 'fields' ) ) {
1289 foreach( $SQL['fields'] as $query ) WPF()->db->query( $query );
1290 }
1291 if( wpfval( $SQL, 'keys' ) ) {
1292 foreach( $SQL['keys'] as $query ) WPF()->db->query( $query );
1293 }
1294 if( wpfval( $SQL, 'tables' ) ) {
1295 foreach( $SQL['tables'] as $query ) {
1296 if( false === WPF()->db->query( $query ) ) {
1297 WPF()->db->query( preg_replace( '#\)[\r\n\t\s]*ENGINE.*$#isu', ')', $query ) );
1298 }
1299 }
1300 }
1301 if( wpfval( $SQL, 'data' ) ) {
1302 foreach( $SQL['data'] as $query ) {
1303 WPF()->db->query( $query );
1304 }
1305 }
1306 }
1307 wpforo_update_option( 'version_db', WPFORO_VERSION );
1308 }
1309
1310 /**
1311 * @param array $args
1312 *
1313 * @return bool|string|null
1314 */
1315 function wpforo_db_check( $args = [] ) {
1316 $key = [ 'wpforo_db_check', $args ];
1317 if( WPF()->ram_cache->exists( $key ) ) return WPF()->ram_cache->get( $key );
1318
1319 global $wpdb;
1320
1321 $col = esc_sql( trim( (string) wpfval( $args, 'col' ) ) );
1322 $table = esc_sql( trim( (string) wpfval( $args, 'table' ) ) );
1323
1324 $result = null;
1325 switch( trim( (string) wpfval( $args, 'check' ) ) ) {
1326 case 'table_exists':
1327 $result = (bool) $wpdb->get_var( "SHOW TABLES LIKE '$table'" );
1328 break;
1329 case 'col_exists':
1330 $result = (bool) $wpdb->get_var( "SHOW COLUMNS FROM `$table` LIKE '$col'" );
1331 break;
1332 case 'key_exists':
1333 $result = (bool) $wpdb->get_var( "SHOW KEYS FROM `$table` WHERE `Key_name` = '$col'" );
1334 break;
1335 case 'default_value':
1336 $c = (array) $wpdb->get_row( "SHOW COLUMNS FROM `$table` LIKE '$col'", ARRAY_A );
1337 $result = wpfval( $c, 'Default' );
1338 break;
1339 case 'col_type':
1340 $c = (array) $wpdb->get_row( "SHOW COLUMNS FROM `$table` LIKE '$col'", ARRAY_A );
1341 $result = wpfval( $c, 'Type' );
1342 break;
1343 }
1344
1345 WPF()->ram_cache->set( $key, $result );
1346
1347 return $result;
1348 }
1349
1350 function wpforo_database_check() {
1351 $_tables = [];
1352 $_table_diffs = [];
1353 require_once( WPFORO_DIR . '/includes/install-sql.php' );
1354 $wpforo_sql = wpforo_get_install_sqls();
1355 if( ! empty( $wpforo_sql ) ) {
1356 foreach( $wpforo_sql as $sql ) {
1357 if( preg_match( '|EXISTS \`([^\(]+)\`\s*\((.+)(PRIMARY.+)\)\s*ENGINE|is', $sql, $table ) ) {
1358 if( wpfval( $table, 1 ) ) {
1359 if( wpfval( $table, 2 ) ) {
1360 if( preg_match_all( '|\`([^\`]+)\`|is', $table[2], $fields, PREG_SET_ORDER ) ) {
1361 foreach( $fields as $field ) {
1362 if( wpfval( $field, 1 ) ) $_tables[ $table[1] ]['fields'][] = $field[1];
1363 }
1364 }
1365 }
1366 if( wpfval( $table, 3 ) ) {
1367 if( preg_match( '|PRIMARY KEY \(\`([^\`]+)\`\)|is', $table[3], $primary_key ) ) {
1368 $_tables[ $table[1] ]['keys'][] = $primary_key[1];
1369 }
1370 if( preg_match_all( '|KEY \`([^\`]+)\`|is', $table[3], $keys, PREG_SET_ORDER ) ) {
1371 foreach( $keys as $key ) {
1372 if( wpfval( $key, 1 ) ) $_tables[ $table[1] ]['keys'][] = $key[1];
1373 }
1374 }
1375 }
1376 }
1377 }
1378 }
1379 if( ! empty( $_tables ) ) {
1380 foreach( $_tables as $_name => $_structure ) {
1381 $_table_fields = [];
1382 $_table_keys = [];
1383 $_table_exists = WPF()->db->get_var( "SHOW TABLES LIKE '" . esc_sql( $_name ) . "'" );
1384 if( $_table_exists ) {
1385 //Problems - Missing Field
1386 if( wpfval( $_structure, 'fields' ) ) {
1387 $_fields = WPF()->db->get_results( "SHOW FULL COLUMNS FROM " . esc_sql( $_name ), ARRAY_A );
1388 foreach( $_fields as $_field ) $_table_fields[] = $_field['Field'];
1389 $_count_orig = count( $_structure['fields'] );
1390 $_count_curr = count( $_table_fields );
1391 if( $_count_curr < $_count_orig ) {
1392 $diff = array_diff( $_structure['fields'], $_table_fields );
1393 if( ! empty( $diff ) ) $_table_diffs[ $_name ]['fields'][ $_name ] = $diff;
1394 }
1395 }
1396 //Problems - Missing Key
1397 if( wpfval( $_structure, 'keys' ) ) {
1398 $_keys = WPF()->db->get_results( "SHOW KEYS FROM " . esc_sql( $_name ), ARRAY_A );
1399 foreach( $_keys as $_key ) {
1400 if( strpos( (string) $_key['Key_name'], 'PRIMARY' ) !== false ) {
1401 $_table_keys[] = $_key['Column_name'];
1402 } else {
1403 $_table_keys[] = $_key['Key_name'];
1404 }
1405 }
1406 $_table_keys = array_unique( $_table_keys );
1407 $_table_keys = array_values( $_table_keys );
1408 $_count_orig = count( $_structure['keys'] );
1409 $_count_curr = count( $_table_keys );
1410 if( $_count_curr < $_count_orig ) {
1411 $diff_keys = array_diff( $_structure['keys'], $_table_keys );
1412 if( ! empty( $diff_keys ) ) $_table_diffs[ $_name ]['keys'][ $_name ] = $diff_keys;
1413 }
1414 }
1415 } else {
1416 //Problems - Missing Table
1417 $_table_diffs[ $_name ]['exists'] = 'no';
1418 }
1419 }
1420 }
1421 }
1422
1423 $first_board = WPF()->db->get_row( "SELECT `boardid` FROM `" . WPF()->tables->boards . "` WHERE `boardid` = 0", ARRAY_A );
1424 if( empty($first_board) ){
1425 $_table_diffs['data']['default_board'] = 'no';
1426 }
1427
1428 return $_table_diffs;
1429 }
1430
1431 function wpforo_database_parse() {
1432 $_tables = [];
1433 $_table_diffs = [];
1434 require_once( WPFORO_DIR . '/includes/install-sql.php' );
1435 $wpforo_sql = wpforo_get_install_sqls();
1436 if( ! empty( $wpforo_sql ) ) {
1437 foreach( $wpforo_sql as $sql ) {
1438 if( preg_match( '|EXISTS \`([^\(]+)\`\s*\((.+)(PRIMARY.+)\)\s*ENGINE|is', $sql, $table ) ) {
1439 if( wpfval( $table, 1 ) ) {
1440 if( wpfval( $table, 2 ) ) {
1441 $_tables[ $table[1] ]['fields'] = array_map( 'trim', explode( ',', $table[2] ) );
1442 }
1443 if( wpfval( $table, 3 ) ) {
1444 $_tables[ $table[1] ]['keys'] = array_map( 'trim', explode( PHP_EOL, $table[3] ) );
1445 }
1446 }
1447 }
1448 }
1449 }
1450
1451 return $_tables;
1452 }
1453
1454 function wpforo_database_fixer( $problems ) {
1455 $SQL = [];
1456 if( ! empty( $problems ) ) {
1457 require_once( WPFORO_DIR . '/includes/install-sql.php' );
1458 $table_structure = wpforo_database_parse();
1459 if( ! empty( $table_structure ) ) {
1460 foreach( $problems as $table_name => $problem ) {
1461 if( wpfval( $problem, 'fields' ) ) {
1462 foreach( $problem['fields'] as $problem_fields ) {
1463 if( ! empty( $problem_fields ) ) {
1464 foreach( $problem_fields as $problem_field ) {
1465 if( wpfval( $table_structure, $table_name, 'fields' ) ) {
1466 foreach( $table_structure[ $table_name ]['fields'] as $field_sql ) {
1467 if( strpos( (string) $field_sql, '`' . $problem_field . '`' ) !== false ) {
1468 $SQL['fields'][] = 'ALTER TABLE `' . $table_name . '` ADD ' . $field_sql . ';';
1469 }
1470 }
1471 }
1472 }
1473 }
1474 }
1475 }
1476 if( wpfval( $problem, 'keys' ) ) {
1477 foreach( $problem['keys'] as $problem_keys ) {
1478 if( ! empty( $problem_keys ) ) {
1479 foreach( $problem_keys as $problem_key ) {
1480 if( wpfval( $table_structure, $table_name, 'keys' ) ) {
1481 foreach( $table_structure[ $table_name ]['keys'] as $key_sql ) {
1482 if( preg_match( '|KEY \`' . $problem_key . '\`|is', (string) $key_sql ) ) {
1483 $SQL['keys'][] = 'ALTER TABLE `' . $table_name . '` ADD ' . trim( (string) $key_sql, ',' ) . ';';
1484 }
1485 }
1486 }
1487 }
1488 }
1489 }
1490 }
1491 if( wpfval( $problem, 'exists' ) ) {
1492 $wpforo_sql = wpforo_get_install_sqls();
1493 if( wpfval( $wpforo_sql, $table_name ) ) {
1494 $SQL['tables'][] = preg_replace( '|\t+|', ' ', $wpforo_sql[ $table_name ] );
1495 }
1496 }
1497 }
1498 }
1499 if( wpfval( $problems, 'data' ) ) {
1500 if( wpfval($problems, 'data', 'default_board') ){
1501 // Missing default board (ID:0)
1502 $board = [];
1503 $blogname = get_option( 'blogname', '' );
1504 $_general = wpforo_get_option( 'wpforo_general_options', [
1505 'title' => $blogname . ' ' . __( 'Forum', 'wpforo' ),
1506 'description' => $blogname . ' ' . __( 'Discussion Board', 'wpforo' )
1507 ], false );
1508 $board['title'] = ( wpfval($_general, 'title') ) ? : 'Forum';
1509 $board['settings']['title'] = ( wpfval($_general, 'title') ) ? : 'Forum';
1510 $board['settings']['desc'] = ( wpfval($_general, 'description') ) ? : 'Discussion Board';
1511 $settings = json_encode($board['settings']);
1512 WPF()->db->query("UPDATE `" . WPF()->tables->boards . "` SET `slug` = CONCAT('community-', `boardid`) WHERE `slug` = 'community' AND `boardid` != 0");
1513 $slug = basename( trim( (string) wpforo_get_option( 'wpforo_permastruct', 'community', false ), '/' ) );
1514 $board['slug'] = ( $slug ) ? : 'community';
1515 $board['locale'] = wpforo_get_site_default_locale();
1516 $board['pageid'] = wpforo_get_option( 'wpforo_pageid', 0 );
1517 $all_modules = array_map( '__return_true', wpforo_get_modules_info() );
1518 $all_addons = array_map( '__return_true', wpforo_get_addons_info() );
1519 $modules = array_merge( $all_modules, $all_addons );
1520 $board['modules'] = json_encode( array_map( function( $a ) { return (bool) intval( $a ); }, $modules ));
1521 $SQL['data']['pre_board'] = "SET sql_mode='NO_AUTO_VALUE_ON_ZERO';";
1522 $SQL['data']['default_board'] = "INSERT INTO `" . WPF()->tables->boards . "` (`boardid`, `title`, `slug`, `pageid`, `modules`, `locale`, `is_standalone`, `excld_urls`, `status`, `settings`)
1523 VALUES(0, '" . esc_sql($board['title']) . "', '" . esc_sql($board['slug']) . "', " . intval($board['pageid']) . ",
1524 '" . esc_sql($board['modules']) . "',
1525 '" . esc_sql($board['locale']) . "', 0, '[]', 1, '" . esc_sql($settings) . "');";
1526 }
1527 //Other data checking here...
1528 }
1529 }
1530
1531 return $SQL;
1532 }
1533
1534 function wpforo_add_unique_key( $table, $primary_key, $unique_key_name = '', $unique_fields = '' ) {
1535
1536 $table = esc_sql( trim( (string) $table ) );
1537 $primary_key = esc_sql( trim( (string) $primary_key ) );
1538 $unique_fields = esc_sql( trim( (string) $unique_fields, ',' ) );
1539 $unique_fields_clean = preg_replace( '|\([^()]+\)|', '', (string) $unique_fields );
1540 $remove_rows = '';
1541 $sql = "SELECT GROUP_CONCAT(`$primary_key`) duplicated_row_ids,
1542 COUNT(*) duplication_count FROM
1543 `$table` GROUP BY $unique_fields_clean HAVING duplication_count > 1";
1544
1545 $rows = WPF()->db->get_results( $sql, ARRAY_A );
1546 if( ! empty( $rows ) ) {
1547 foreach( $rows as $row ) {
1548 $ids = explode( ',', $row['duplicated_row_ids'] );
1549 $ids = array_reverse( $ids );
1550 $ids = array_slice( $ids, 1 );
1551 $remove_rows .= trim( implode( ',', $ids ), ',' ) . ',';
1552 }
1553 $remove_rows = esc_sql( trim( $remove_rows, ',' ) );
1554 if( $remove_rows ) {
1555 WPF()->db->query( "DELETE FROM `$table` WHERE `$primary_key` IN($remove_rows)" );
1556 }
1557 }
1558 $sql = "ALTER TABLE `$table` ADD UNIQUE KEY `$unique_key_name`( $unique_fields )";
1559 WPF()->db->query( $sql );
1560 }
1561