PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 4.0.5
MainWP Dashboard: Self-hosted WordPress Management for Agencies v4.0.5
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
← All changes | class/class-mainwp-db.php +1677 -3857 6.1 → 4.0.5 View file →
@@ -1,4191 +1,2011 @@
1 1 <?php
2 -/**
3 - * MainWP Database Controller
4 - *
5 - * This file handles all interactions with the DB.
6 - *
7 - * @package MainWP/Dashboard
8 - */
9 2
10 -namespace MainWP\Dashboard;
3 +class MainWP_DB {
11 4
12 -// Exit if accessed directly.
13 -if ( ! defined( 'ABSPATH' ) ) {
14 - exit;
15 -}
5 + //Config
6 + private $mainwp_db_version = '8.14';
7 + //Private
8 + private $table_prefix;
9 + //Singleton
10 + /** @var $instance MainWP_DB */
11 + private static $instance = null;
16 12
17 -/**
18 - * Class MainWP_DB
19 - *
20 - * @package MainWP\Dashboard
21 - *
22 - * @uses \MainWP\Dashboard\MainWP_DB_Base
23 - */
24 -class MainWP_DB extends MainWP_DB_Base { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
13 + /** @var $wpdb wpdb */
14 + private $wpdb;
25 15
26 - // phpcs:disable WordPress.DB.RestrictedFunctions, WordPress.DB.PreparedSQL.NotPrepared, Generic.Metrics.CyclomaticComplexity -- This is the only way to achieve desired results, pull request solutions appreciated.
16 + /**
17 + * @static
18 + * @return MainWP_DB
19 + */
20 + static function Instance() {
21 + if ( MainWP_DB::$instance == null ) {
22 + MainWP_DB::$instance = new MainWP_DB();
23 + }
27 24
28 - /**
29 - * Private static variable to hold the single instance of the class.
30 - *
31 - * @static
32 - *
33 - * @var mixed Default null
34 - */
35 - private static $instance = null;
25 + MainWP_DB::$instance->test_connection();
36 26
37 - /**
38 - * Private static variable to hold the single instance.
39 - *
40 - * @static
41 - *
42 - * @var mixed Default null
43 - */
44 - private static $general_options = null;
27 + return MainWP_DB::$instance;
28 + }
45 29
46 - /**
47 - * Possible options.
48 - *
49 - * @var array $possible_options
50 - */
51 - private static $possible_options = array(
52 - 'plugin_upgrades',
53 - 'theme_upgrades',
54 - 'premium_upgrades',
55 - 'plugins',
56 - 'themes',
57 - 'dtsSync',
58 - 'version',
59 - 'sync_errors',
60 - 'ignored_plugins',
61 - 'wp_upgrades',
62 - 'site_info',
63 - 'client',
64 - 'signature_algo',
65 - 'verify_method',
66 - 'pubkey',
67 - );
30 + //Constructor
31 + function __construct() {
32 + /** @var $this ->wpdb wpdb */
33 + global $wpdb;
68 34
69 - /**
70 - * Create public static instance.
71 - *
72 - * @static
73 - *
74 - * @return MainWP_DB
75 - */
76 - public static function instance() {
77 - if ( null === static::$instance ) {
78 - static::$instance = new self();
79 - }
35 + $this->wpdb = &$wpdb;
36 + $this->table_prefix = $wpdb->prefix . 'mainwp_';
37 + }
80 38
81 - static::$instance->test_connection();
39 + private function test_connection() {
40 + if ( !self::ping( $this->wpdb->dbh ) ) {
41 + MainWP_Logger::Instance()->info( __( 'Trying to reconnect WordPress database connection...', 'mainwp' ) );
42 + $this->wpdb->db_connect();
43 + }
44 + }
82 45
83 - return static::$instance;
84 - }
46 + private function tableName( $suffix, $tablePrefix = null ) {
47 + return ( $tablePrefix == null ? $this->table_prefix : $tablePrefix ) . $suffix;
48 + }
85 49
86 - /**
87 - * Get wp_options database table view.
88 - *
89 - * @compatible function.
90 - *
91 - * @param array $fields Extra option fields.
92 - * @param string $view_query view query.
93 - *
94 - * @return array wp_options view.
95 - */
96 - public function get_option_view( $fields = array(), $view_query = 'default' ) {
50 + //Installs new DB
51 + function install() {
52 + //get_site_option is multisite aware!
53 + $currentVersion = get_site_option( 'mainwp_db_version' );
97 54
98 - if ( ! is_array( $fields ) ) {
99 - $fields = array();
100 - }
55 + if ( empty( $currentVersion ) ) {
56 + //set_transient( '_mainwp_activation_redirect', 1, 30 );
57 + update_option( 'mainwp_run_quick_setup', 'yes' );
58 + MainWP_Utility::update_option( 'mainwp_enableLegacyBackupFeature', 0 );
59 + } else if ( false === get_option( 'mainwp_enableLegacyBackupFeature' ) ) {
60 + MainWP_Utility::update_option( 'mainwp_enableLegacyBackupFeature', 1 );
61 + }
101 62
102 - $view = '(SELECT intwp.id AS wpid ';
63 + $rslt = MainWP_DB::Instance()->query( "SHOW TABLES LIKE '" . $this->tableName( 'wp' ) . "'" );
64 + if ( @MainWP_DB::num_rows( $rslt ) == 0 ) {
65 + $currentVersion = false;
66 + }
103 67
104 - $included_opts = array();
68 + if ( $currentVersion == $this->mainwp_db_version ) {
69 + return;
70 + }
105 71
106 - if ( empty( $fields ) || 'default' === $view_query || 'manage_site' === $view_query ) {
107 - $view .= ',(SELECT recent_comments.value FROM ' . $this->table_name( 'wp_options' ) . ' recent_comments WHERE recent_comments.wpid = intwp.id AND recent_comments.name = "recent_comments" LIMIT 1) AS recent_comments,
108 - (SELECT recent_posts.value FROM ' . $this->table_name( 'wp_options' ) . ' recent_posts WHERE recent_posts.wpid = intwp.id AND recent_posts.name = "recent_posts" LIMIT 1) AS recent_posts,
109 - (SELECT recent_pages.value FROM ' . $this->table_name( 'wp_options' ) . ' recent_pages WHERE recent_pages.wpid = intwp.id AND recent_pages.name = "recent_pages" LIMIT 1) AS recent_pages,
110 - (SELECT phpversion.value FROM ' . $this->table_name( 'wp_options' ) . ' phpversion WHERE phpversion.wpid = intwp.id AND phpversion.name = "phpversion" LIMIT 1) AS phpversion,
111 - (SELECT added_timestamp.value FROM ' . $this->table_name( 'wp_options' ) . ' added_timestamp WHERE added_timestamp.wpid = intwp.id AND added_timestamp.name = "added_timestamp" LIMIT 1) AS added_timestamp,
112 - (SELECT wp_upgrades.value FROM ' . $this->table_name( 'wp_options' ) . ' wp_upgrades WHERE wp_upgrades.wpid = intwp.id AND wp_upgrades.name = "wp_upgrades" LIMIT 1) AS wp_upgrades ';
113 - $included_opts = array( 'recent_comments', 'recent_posts', 'recent_pages', 'phpversion', 'added_timestamp', 'wp_upgrades' );
114 - }
72 + $charset_collate = $this->wpdb->get_charset_collate();
115 73
116 - if ( ! in_array( 'signature_algo', $fields ) ) {
117 - $fields[] = 'signature_algo';
118 - }
74 + $sql = array();
75 + $tbl = 'CREATE TABLE ' . $this->tableName( 'wp' ) . ' (
76 + id int(11) NOT NULL auto_increment,
77 + userid int(11) NOT NULL,
78 + adminname text NOT NULL,
79 + name text NOT NULL,
80 + url text NOT NULL,
81 + pubkey text NOT NULL,
82 + privkey text NOT NULL,
83 + nossl tinyint(1) NOT NULL,
84 + nosslkey text NOT NULL,
85 + siteurl text NOT NULL,
86 + ga_id text NOT NULL,
87 + gas_id int(11) NOT NULL,
88 + offline_checks text NOT NULL,
89 + offline_checks_last int(11) NOT NULL,
90 + offline_check_result int(11) NOT NULL,
91 + http_response_code int(11) NOT NULL DEFAULT 0,
92 + note text NOT NULL,
93 + note_lastupdate int(11) NOT NULL DEFAULT 0,
94 + statsUpdate int(11) NOT NULL,
95 + pagerank int(11) NOT NULL,
96 + indexed int(11) NOT NULL,
97 + alexia int(11) NOT NULL,
98 + pagerank_old int(11) DEFAULT NULL,
99 + indexed_old int(11) DEFAULT NULL,
100 + alexia_old int(11) DEFAULT NULL,
101 + directories longtext NOT NULL,
102 + plugin_upgrades longtext NOT NULL,
103 + theme_upgrades longtext NOT NULL,
104 + translation_upgrades longtext NOT NULL,
105 + premium_upgrades longtext NOT NULL,
106 + securityIssues longtext NOT NULL,
107 + themes longtext NOT NULL,
108 + ignored_themes longtext NOT NULL,
109 + plugins longtext NOT NULL,
110 + ignored_plugins longtext NOT NULL,
111 + pages longtext NOT NULL,
112 + users longtext NOT NULL,
113 + categories longtext NOT NULL,
114 + pluginDir text NOT NULL,
115 + automatic_update tinyint(1) NOT NULL,
116 + backup_before_upgrade tinyint(1) NOT NULL DEFAULT 2,
117 + last_db_backup_size int(11) NOT NULL,
118 + backups text NOT NULL,
119 + mainwpdir int(11) NOT NULL,
120 + loadFilesBeforeZip tinyint(1) NOT NULL DEFAULT 1,
121 + is_ignoreCoreUpdates tinyint(1) NOT NULL DEFAULT 0,
122 + is_ignorePluginUpdates tinyint(1) NOT NULL DEFAULT 0,
123 + is_ignoreThemeUpdates tinyint(1) NOT NULL DEFAULT 0,
124 + verify_certificate tinyint(1) NOT NULL DEFAULT 1,
125 + force_use_ipv4 tinyint(1) NOT NULL DEFAULT 0,
126 + ssl_version tinyint(1) NOT NULL DEFAULT 0,
127 + ip text NOT NULL DEFAULT "",
128 + uniqueId text NOT NULL,
129 + maximumFileDescriptorsOverride tinyint(1) NOT NULL DEFAULT 0,
130 + maximumFileDescriptorsAuto tinyint(1) NOT NULL DEFAULT 1,
131 + maximumFileDescriptors int(11) NOT NULL DEFAULT 150,
132 + http_user text NOT NULL DEFAULT "",
133 + http_pass text NOT NULL DEFAULT "",
134 + wpe tinyint(1) NOT NULL,
135 + is_staging tinyint(1) NOT NULL DEFAULT 0,
136 + KEY idx_userid (userid)';
137 + if ( $currentVersion == '' ) {
138 + $tbl .= ',
139 + PRIMARY KEY (id) ';
140 + }
141 + $tbl .= ') ' . $charset_collate;
142 + $sql[] = $tbl;
119 143
120 - if ( ! in_array( 'verify_method', $fields ) ) {
121 - $fields[] = 'verify_method';
122 - }
144 + $tbl = 'CREATE TABLE ' . $this->tableName( 'wp_sync' ) . ' (
145 + wpid int(11) NOT NULL,
146 + version text NOT NULL DEFAULT "",
147 + sync_errors longtext NOT NULL DEFAULT "",
148 + uptodate longtext NOT NULL DEFAULT "",
149 + dtsAutomaticSync int(11) NOT NULL DEFAULT 0,
150 + dtsAutomaticSyncStart int(11) NOT NULL DEFAULT 0,
151 + dtsSync int(11) NOT NULL DEFAULT 0,
152 + dtsSyncStart int(11) NOT NULL DEFAULT 0,
153 + totalsize int(11) NOT NULL DEFAULT 0,
154 + dbsize int(11) NOT NULL DEFAULT 0,
155 + extauth text NOT NULL DEFAULT "",
156 + last_post_gmt int(11) NOT NULL DEFAULT 0,
157 + KEY idx_wpid (wpid)) ' . $charset_collate;
158 + $sql[] = $tbl;
123 159
124 - if ( ! in_array( 'cust_site_icon_info', $fields, true ) ) {
125 - $fields[] = 'cust_site_icon_info';
126 - }
160 + $tbl = 'CREATE TABLE ' . $this->tableName( 'wp_options' ) . ' (
161 + wpid int(11) NOT NULL,
162 + name text NOT NULL DEFAULT "",
163 + value longtext NOT NULL DEFAULT "",
164 + KEY idx_wpid (wpid)) ' . $charset_collate;
165 + $sql[] = $tbl;
127 166
128 - if ( is_array( $fields ) ) {
129 - foreach ( $fields as $field ) {
130 - if ( empty( $field ) ) {
131 - continue;
132 - }
133 - if ( in_array( $field, $included_opts ) ) {
134 - continue;
135 - }
136 - $view .= ', ';
137 - $view .= '(SELECT ' . $this->escape( $field ) . '.value FROM ' . $this->table_name( 'wp_options' ) . ' ' . $this->escape( $field ) . ' WHERE ' . $this->escape( $field ) . '.wpid = intwp.id AND ' . $this->escape( $field ) . '.name = "' . $this->escape( $field ) . '" LIMIT 1) AS ' . $this->escape( $field );
138 - }
139 - }
167 + $tbl = 'CREATE TABLE ' . $this->tableName( 'wp_settings_backup' ) . ' (
168 + wpid int(11) NOT NULL,
169 + archiveFormat text NOT NULL,
170 + KEY idx_wpid (wpid)) ' . $charset_collate;
171 + $sql[] = $tbl;
140 172
141 - $view .= ' FROM ' . $this->table_name( 'wp' ) . ' intwp)';
173 + $tbl = 'CREATE TABLE ' . $this->tableName( 'tips' ) . ' (
174 + id int(11) NOT NULL auto_increment,
175 + seq int(11) NOT NULL,
176 + content text NOT NULL';
177 + if ( $currentVersion == '' ) {
178 + $tbl .= ',
179 + PRIMARY KEY (id) ';
180 + }
181 + $tbl .= ') ' . $charset_collate;
182 + $sql[] = $tbl;
142 183
143 - return $view;
144 - }
184 + $tbl = 'CREATE TABLE ' . $this->tableName( 'users' ) . " (
185 + userid int(11) NOT NULL,
186 + user_email text NOT NULL DEFAULT '',
187 + tips tinyint(1) NOT NULL DEFAULT '1',
188 + offlineChecksOnlineNotification tinyint(1) NOT NULL DEFAULT '0',
189 + heatMap tinyint(1) NOT NULL DEFAULT '0',
190 + ignored_plugins longtext NOT NULL DEFAULT '',
191 + trusted_plugins longtext NOT NULL DEFAULT '',
192 + trusted_plugins_notes longtext NOT NULL DEFAULT '',
193 + ignored_themes longtext NOT NULL DEFAULT '',
194 + trusted_themes longtext NOT NULL DEFAULT '',
195 + trusted_themes_notes longtext NOT NULL DEFAULT '',
196 + site_view tinyint(1) NOT NULL DEFAULT '0',
197 + pluginDir text NOT NULL DEFAULT '',
198 + dismissed_plugins longtext NOT NULL DEFAULT '',
199 + dismissed_themes longtext NOT NULL DEFAULT ''";
200 + if ( $currentVersion == '' ) {
201 + $tbl .= ',
202 + PRIMARY KEY (userid) ';
203 + }
204 + $tbl .= ') ' . $charset_collate;
205 + $sql[] = $tbl;
145 206
146 - /**
147 - * Method get_wp_options_join().
148 - *
149 - * @param array $fields Extra option fields.
150 - * @param string $view_query view query.
151 - * @param array $params Additional parameters.
207 + $tbl = 'CREATE TABLE ' . $this->tableName( 'group' ) . ' (
208 + id int(11) NOT NULL auto_increment,
209 + userid int(11) NOT NULL,
210 + name text NOT NULL';
211 + if ( $currentVersion == '' ) {
212 + $tbl .= ',
213 + PRIMARY KEY (id) ';
214 + }
215 + $tbl .= ') ' . $charset_collate;
216 + $sql[] = $tbl;
152 217
153 - *
154 - * NOTE: This method is used to improve the performance of wp_options view, as the old view with subquery for each field will cause performance issue when there are many sites, and this method will generate the SQL with LEFT JOIN which will be much faster than subquery.
155 - * The alias of wp table must be 'wp' to make sure the LEFT JOIN works, and the alias of wp_options table will be 'owp' + key of field in fields array, and the join condition is owp.wpid = wp.id AND owp.name = field name, and the select field is owp.value AS field name.
156 - *
157 - * @since 6.0.8
158 - *
159 - * @return array wp_options view.
160 - */
161 - public function get_wp_options_join( $fields = array(), $view_query = 'default', $params = array() ) {
218 + $sql[] = 'CREATE TABLE ' . $this->tableName( 'wp_group' ) . ' (
219 + wpid int(11) NOT NULL,
220 + groupid int(11) NOT NULL,
221 + KEY idx_wpid (wpid),
222 + KEY idx_groupid (groupid)
223 + ) ' . $charset_collate;
162 224
163 - if ( ! is_array( $fields ) ) {
164 - $fields = array();
165 - }
225 + $tbl = 'CREATE TABLE ' . $this->tableName( 'wp_backup_progress' ) . ' (
226 + task_id int(11) NOT NULL,
227 + wp_id int(11) NOT NULL,
228 + dtsFetched int(11) NOT NULL DEFAULT 0,
229 + fetchResult text NOT NULL DEFAULT "",
230 + downloadedDB text NOT NULL DEFAULT "",
231 + downloadedFULL text NOT NULL DEFAULT "",
232 + downloadedDBComplete tinyint(1) NOT NULL DEFAULT 0,
233 + downloadedFULLComplete tinyint(1) NOT NULL DEFAULT 0,
234 + removedFiles tinyint(1) NOT NULL DEFAULT 0,
235 + attempts int(11) NOT NULL DEFAULT 0,
236 + last_error text NOT NULL DEFAULT "",
237 + pid int(11) NOT NULL DEFAULT 0,
238 + KEY idx_task_id (task_id)
239 + ) ' . $charset_collate;
240 + $sql[] = $tbl;
166 241
167 - if ( empty( $fields ) || 'default' === $view_query || 'manage_site' === $view_query ) {
168 - $fields[] = 'recent_comments';
169 - $fields[] = 'recent_posts';
170 - $fields[] = 'recent_pages';
171 - $fields[] = 'phpversion';
172 - $fields[] = 'added_timestamp';
173 - $fields[] = 'wp_upgrades';
174 - }
242 + $tbl = 'CREATE TABLE ' . $this->tableName( 'wp_backup' ) . ' (
243 + id int(11) NOT NULL auto_increment,
244 + userid int(11) NOT NULL,
245 + name text NOT NULL,
246 + schedule text NOT NULL,
247 + type text NOT NULL,
248 + exclude text NOT NULL,
249 + sites text NOT NULL,
250 + groups text NOT NULL,
251 + last int(11) NOT NULL,
252 + last_run int(11) NOT NULL,
253 + lastStartNotificationSent int(11) NOT NULL DEFAULT 0,
254 + last_run_manually int(11) NOT NULL,
255 + completed_sites text NOT NULL,
256 + completed int(11) NOT NULL,
257 + backup_errors text NOT NULL,
258 + subfolder text NOT NULL,
259 + filename text NOT NULL,
260 + paused tinyint(1) NOT NULL,
261 + template tinyint(1) DEFAULT 0,
262 + excludebackup tinyint(1) DEFAULT 0,
263 + excludecache tinyint(1) DEFAULT 0,
264 + excludenonwp tinyint(1) DEFAULT 0,
265 + excludezip tinyint(1) DEFAULT 0,
266 + archiveFormat text NOT NULL,
267 + loadFilesBeforeZip tinyint(1) NOT NULL DEFAULT 1,
268 + maximumFileDescriptorsOverride tinyint(1) NOT NULL DEFAULT 0,
269 + maximumFileDescriptorsAuto tinyint(1) NOT NULL DEFAULT 1,
270 + maximumFileDescriptors int(11) NOT NULL DEFAULT 150';
271 + if ( $currentVersion == '' ) {
272 + $tbl .= ',
273 + PRIMARY KEY (id) ';
274 + }
275 + $tbl .= ') ' . $charset_collate;
276 + $sql[] = $tbl;
175 277
176 - if ( ! in_array( 'signature_algo', $fields ) ) {
177 - $fields[] = 'signature_algo';
178 - }
278 + $tbl = 'CREATE TABLE ' . $this->tableName( 'request_log' ) . ' (
279 + id int(11) NOT NULL auto_increment,
280 + wpid int(11) NOT NULL,
281 + ip text NOT NULL DEFAULT "",
282 + subnet text NOT NULL DEFAULT "",
283 + micro_timestamp_stop DECIMAL( 12, 2 ) NOT NULL DEFAULT 0,
284 + micro_timestamp_start DECIMAL( 12, 2 ) NOT NULL DEFAULT 0';
285 + if ( $currentVersion == '' || version_compare( $currentVersion, '5.7', '<=' ) ) {
286 + $tbl .= ',
287 + PRIMARY KEY (id) ';
288 + }
289 + $tbl .= ') ' . $charset_collate . ";";
290 + $sql[] = $tbl;
179 291
180 - if ( ! in_array( 'verify_method', $fields ) ) {
181 - $fields[] = 'verify_method';
182 - }
292 + require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
293 + foreach ( $sql as $query ) {
294 + dbDelta( $query );
295 + }
183 296
184 - if ( ! in_array( 'cust_site_icon_info', $fields, true ) ) {
185 - $fields[] = 'cust_site_icon_info';
186 - }
297 + // /** @var $this->wpdb wpdb */
298 + // $this->wpdb->query('CREATE OR REPLACE VIEW ' . $this->tableName('wp_optionview') . ' AS
299 + // SELECT intwp.id AS wpid,
300 + // recent_comments.value AS recent_comments,
301 + // recent_posts.value AS recent_posts,
302 + // recent_pages.value AS recent_pages
303 + // FROM ' . $this->tableName('wp') . ' intwp
304 + // LEFT JOIN ' . $this->tableName('wp_options') . ' recent_comments ON recent_comments.wpid = intwp.id AND recent_comments.name = "recent_comments"
305 + // LEFT JOIN ' . $this->tableName('wp_options') . ' recent_posts ON recent_posts.wpid = intwp.id AND recent_posts.name = "recent_posts"
306 + // LEFT JOIN ' . $this->tableName('wp_options') . ' recent_pages ON recent_pages.wpid = intwp.id AND recent_pages.name = "recent_pages"');
187 307
188 - $fields = array_values( array_unique( array_filter( $fields ) ) );
308 + $this->post_update();
189 309
190 - $tbl_wp_options = $this->table_name( 'wp_options' );
310 + if ( !is_multisite() ) {
311 + MainWP_Utility::update_option( 'mainwp_db_version', $this->mainwp_db_version );
312 + } else {
313 + update_site_option( 'mainwp_db_version', $this->mainwp_db_version );
314 + }
315 + }
191 316
192 - $selects = array();
193 - $joins = array();
317 + //Check for update - if required, update..
318 + function update() {
194 319
195 - foreach ( $fields as $name ) {
196 - $alias = 'owp_' . preg_replace( '/[^a-z0-9_]/i', '_', $name );
320 + }
197 321
198 - // SELECT.
199 - $selects[] = "{$alias}.value AS `" . $this->escape( $name ) . '`';
322 + function getOptionView( $extra = array()) {
323 + $view = '(SELECT intwp.id AS wpid,
324 + (SELECT recent_comments.value FROM ' . $this->tableName( 'wp_options' ) . ' recent_comments WHERE recent_comments.wpid = intwp.id AND recent_comments.name = "recent_comments" LIMIT 1) AS recent_comments,
325 + (SELECT recent_posts.value FROM ' . $this->tableName( 'wp_options' ) . ' recent_posts WHERE recent_posts.wpid = intwp.id AND recent_posts.name = "recent_posts" LIMIT 1) AS recent_posts,
326 + (SELECT recent_pages.value FROM ' . $this->tableName( 'wp_options' ) . ' recent_pages WHERE recent_pages.wpid = intwp.id AND recent_pages.name = "recent_pages" LIMIT 1) AS recent_pages,
327 + (SELECT phpversion.value FROM ' . $this->tableName( 'wp_options' ) . ' phpversion WHERE phpversion.wpid = intwp.id AND phpversion.name = "phpversion" LIMIT 1) AS phpversion,
328 + (SELECT wp_upgrades.value FROM ' . $this->tableName( 'wp_options' ) . ' wp_upgrades WHERE wp_upgrades.wpid = intwp.id AND wp_upgrades.name = "wp_upgrades" LIMIT 1) AS wp_upgrades ';
200 329
201 - // JOIN.
202 - $joins[] = "LEFT JOIN {$tbl_wp_options} {$alias}
203 - ON {$alias}.wpid = wp.id
204 - AND {$alias}.name = '" . $this->escape( $name ) . "'";
205 - }
206 -
207 - return array(
208 - 'selects' => implode( ', ', $selects ),
209 - 'joins' => implode( "\n", $joins ),
210 - );
211 - }
212 -
213 - /**
214 - * Method get_wp_options_view().
215 - *
216 - * @param array $fields Extra option fields.
217 - * @param string $view_query view query.
218 - * @param int $siteid Site id.
219 - *
220 - * @return string SQL subquery for wp_options view.
221 - */
222 - public function get_wp_options_view( $fields = array(), $view_query = 'default', $siteid = 0 ) {
223 -
224 - if ( ! is_array( $fields ) ) {
225 - $fields = array();
226 - }
227 -
228 - $where_site = '';
229 -
230 - if ( ! empty( $siteid ) && is_numeric( $siteid ) ) {
231 - $where_site = ' AND wpid = ' . intval( $siteid ) . ' ';
232 - }
233 -
234 - $view = '(SELECT wpid ';
235 -
236 - $included_opts = array();
237 -
238 - if ( empty( $fields ) || 'default' === $view_query || 'manage_site' === $view_query ) {
239 - $view .= ',
240 - MAX(CASE WHEN name = "recent_comments" THEN value END) AS recent_comments,
241 - MAX(CASE WHEN name = "recent_posts" THEN value END) AS recent_posts,
242 - MAX(CASE WHEN name = "recent_pages" THEN value END) AS recent_pages,
243 - MAX(CASE WHEN name = "phpversion" THEN value END) AS phpversion,
244 - MAX(CASE WHEN name = "added_timestamp" THEN value END) AS added_timestamp,
245 - MAX(CASE WHEN name = "wp_upgrades" THEN value END) AS wp_upgrades ';
246 - $included_opts = array( 'recent_comments', 'recent_posts', 'recent_pages', 'phpversion', 'added_timestamp', 'wp_upgrades' );
247 - }
248 -
249 - if ( ! in_array( 'signature_algo', $fields ) ) {
250 - $fields[] = 'signature_algo';
251 - }
252 -
253 - if ( ! in_array( 'verify_method', $fields ) ) {
254 - $fields[] = 'verify_method';
255 - }
256 -
257 - if ( ! in_array( 'cust_site_icon_info', $fields, true ) ) {
258 - $fields[] = 'cust_site_icon_info';
259 - }
260 -
261 - if ( is_array( $fields ) ) {
262 - foreach ( $fields as $field ) {
263 - if ( empty( $field ) ) {
330 + if (is_array($extra)) {
331 + foreach($extra as $field) {
332 + if (empty($field))
264 333 continue;
265 - }
266 - if ( in_array( $field, $included_opts ) ) {
267 - continue;
268 - }
269 334 $view .= ', ';
270 - $view .= 'MAX(CASE WHEN name = "' . $this->escape( $field ) . '" THEN value END) AS ' . $this->escape( $field );
271 -
272 - $included_opts[] = $this->escape( $field );
335 + $view .= '(SELECT ' . $this->escape($field) . '.value FROM ' . $this->tableName( 'wp_options' ) . ' ' . $this->escape($field) . ' WHERE ' . $this->escape($field) . '.wpid = intwp.id AND ' . $this->escape($field) . '.name = "' . $this->escape($field) . '" LIMIT 1) AS ' . $this->escape($field);
273 336 }
274 337 }
275 338
276 - $view .= ' FROM ' . $this->table_name( 'wp_options' ) .
277 - " WHERE 1 {$where_site} AND name IN ('" . implode( "','", $included_opts ) . "')
278 - GROUP BY wpid ) ";
339 + $view .= ' FROM ' . $this->tableName( 'wp' ) . ' intwp)';
279 340
280 341 return $view;
281 - }
342 + }
282 343
344 + function post_update() {
345 + //get_site_option is multisite aware!
346 + $currentVersion = get_site_option( 'mainwp_db_version' );
347 + if ( $currentVersion === false ) {
348 + return;
349 + }
283 350
351 +// if ( version_compare( $currentVersion, '2.8', '<' ) ) {
352 +// $this->wpdb->update( $this->tableName( 'wp_backup' ), array( 'subfolder' => 'MainWP Backups/%url%/%type%/%date%' ), array( 'template' => '0' ) );
353 +// }
284 354
285 - /**
286 - * Get SQL to get child sites for current user.
287 - *
288 - * @since 5.2.
289 - * @param array $params other params.
290 - *
291 - * @return object|null Database query results or null on failure.
292 - */
293 - public function get_sql_websites_for_current_user_by_params( $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
355 +// if ( version_compare( $currentVersion, '4.3', '<' ) ) {
356 +// $row = $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'users' ), OBJECT );
357 +// if ( $row != null ) {
358 +// $row->userid = 0;
359 +// $this->updateUserExtension( $row );
360 +// }
361 +// }
294 362
295 - if ( ! is_array( $params ) ) {
296 - $params = array();
297 - }
363 +// if ( version_compare( $currentVersion, '5.3', '<' ) ) {
364 +// if ( MainWP_System::Instance()->isSingleUser() ) {
365 +// $row = $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'ga' ), OBJECT );
366 +//
367 +// $this->wpdb->update( $this->tableName( 'ga' ), array( 'userid' => 0 ), array( 'userid' => $row->userid ) );
368 +// }
369 +// }
298 370
299 - /**
300 - * The hook mainwp_get_sql_websites_by_params
301 - *
302 - * @since 5.5
303 - */
304 - $params = apply_filters( 'mainwp_get_sql_websites_by_params', $params );
371 +// if ( version_compare( $currentVersion, '6.0', '=' ) ) {
372 +// $this->wpdb->query( 'ALTER TABLE ' . $this->tableName( 'request_log' ) . ' CHANGE micro_timestamp_stop micro_timestamp_stop DECIMAL( 12, 2 ) NOT NULL DEFAULT 0' );
373 +// $this->wpdb->query( 'ALTER TABLE ' . $this->tableName( 'request_log' ) . ' CHANGE micro_timestamp_start micro_timestamp_start DECIMAL( 12, 2 ) NOT NULL DEFAULT 0' );
374 +// $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'request_log' ) . ' WHERE 1 ' );
375 +// }
305 376
306 - $view = isset( $params['view'] ) ? $params['view'] : 'default';
307 - $with_clients = isset( $params['with_clients'] ) && $params['with_clients'] ? true : false;
377 +// if ( version_compare( $currentVersion, '6.2', '<' ) ) {
378 +// $options = array(
379 +// 'mainwp_db_version',
380 +// //'mainwp_requests',
381 +// 'mainwp_plugin_version',
382 +// 'mainwp_upgradeVersionInfo',
383 +// 'mainwp_cron_last_offlinecheck',
384 +// 'mainwp_cron_last_updatescheck',
385 +// 'mainwp_automaticUpdate_backupChecks',
386 +// 'mainwp_updatescheck_mail_update_core_new',
387 +// 'mainwp_updatescheck_mail_update_plugins_new',
388 +// 'mainwp_updatescheck_mail_update_themes_new',
389 +// 'mainwp_updatescheck_mail_update_core',
390 +// 'mainwp_updatescheck_mail_update_plugins',
391 +// 'mainwp_updatescheck_mail_update_themes',
392 +// 'mainwp_updatescheck_mail_ignore_core',
393 +// 'mainwp_updatescheck_mail_ignore_plugins',
394 +// 'mainwp_updatescheck_mail_ignore_themes',
395 +// 'mainwp_updatescheck_mail_ignore_core_new',
396 +// 'mainwp_updatescheck_mail_ignore_plugins_new',
397 +// 'mainwp_updatescheck_mail_ignore_themes_new',
398 +// 'mainwp_updatescheck_last',
399 +// 'mainwp_updatescheck_mail_email',
400 +// 'mainwp_cron_last_ping',
401 +// 'mainwp_cron_last_backups_continue',
402 +// 'mainwp_cron_last_backups',
403 +// 'mainwp_cron_last_stats',
404 +// 'mainwp_backupsOnServer',
405 +// 'mainwp_maximumFileDescriptors',
406 +// 'mainwp_backupOnExternalSources',
407 +// 'mainwp_notificationOnBackupFail',
408 +// 'mainwp_notificationOnBackupStart',
409 +// 'mainwp_chunkedBackupTasks',
410 +// 'mainwp_maximumRequests',
411 +// 'mainwp_minimumDelay',
412 +// 'mainwp_maximumIPRequests',
413 +// 'mainwp_minimumIPDelay',
414 +// 'mainwp_extensions',
415 +// 'mainwp_api_username',
416 +// 'mainwp_api_password',
417 +// 'mainwp_extension_widget_view',
418 +// 'mainwp_news',
419 +// 'mainwp_news_timestamp',
420 +// 'mainwp_optimize',
421 +// 'mainwp_automaticDailyUpdate',
422 +// 'mainwp_backup_before_upgrade',
423 +// 'mainwp_show_language_updates',
424 +// 'mainwp_maximumPosts',
425 +// 'mainwp_maximumComments',
426 +// 'mainwp_cron_jobs',
427 +// 'mainwp_wp_cron',
428 +// );
429 +// foreach ( $options as $option ) {
430 +// MainWP_Utility::fix_option( $option );
431 +// }
432 +// }
308 433
309 - // legacy support.
310 - $selectgroups = isset( $params['with_tags'] ) && $params['with_tags'] ? true : false;
311 - $orderBy = isset( $params['orderby'] ) ? $params['orderby'] : 'wp.url';
312 - $offset = isset( $params['offset'] ) ? intval( $params['offset'] ) : false;
313 - $rowcount = isset( $params['rowcount'] ) && $params['rowcount'] ? true : false;
314 - $extraWhere = isset( $params['where'] ) ? $params['where'] : null; // NOTE: without 'AND' at begining and ending of 'where'.
315 - $for_manager = isset( $params['for_manager'] ) && $params['for_manager'] ? true : false;
316 - $others_fields = isset( $params['others_fields'] ) && is_array( $params['others_fields'] ) ? $params['others_fields'] : array( 'favi_icon' );
317 - $is_staging = isset( $params['is_staging'] ) && in_array( $params['is_staging'], array( 'yes', 'no' ) ) ? $params['is_staging'] : 'no';
318 - $limit = isset( $params['limit'] ) ? intval( $params['limit'] ) : '';
434 +// if ( version_compare( $currentVersion, '7.3', '<' ) ) {
435 +// //get all sites
436 +// $sites = $this->wpdb->get_results( 'SELECT id FROM ' . $this->tableName( 'wp' ) );
437 +// if ( !empty( $sites ) ) {
438 +// foreach ( $sites as $site ) {
439 +// $this->wpdb->insert( $this->tableName( 'wp_settings_backup' ), array(
440 +// 'wpid' => $site->id,
441 +// 'archiveFormat' => 'global',
442 +// ) );
443 +// }
444 +// }
445 +// }
319 446
320 - $use_comp_subquery = ! empty( $params['use_compatible_subquery'] ) ? true : false;
447 +// if ( version_compare( $currentVersion, '8', '<' ) ) {
448 +// $apiPass = get_option( 'mainwp_api_password' );
449 +// MainWP_Utility::update_option( 'mainwp_api_password', MainWP_Utility::encrypt( $apiPass, 'MainWPAPI' ) );
450 +// }
321 451
322 - $s = isset( $params['s'] ) ? $params['s'] : '';
323 - $exclude = isset( $params['exclude'] ) ? wp_parse_id_list( $params['exclude'] ) : array();
324 - $include = isset( $params['include'] ) ? wp_parse_id_list( $params['include'] ) : array();
325 - $status = isset( $params['status'] ) ? wp_parse_list( $params['status'] ) : array();
326 - $page = isset( $params['page'] ) ? intval( $params['page'] ) : false;
327 - $per_page = isset( $params['per_page'] ) ? intval( $params['per_page'] ) : false;
452 + if ( version_compare( $currentVersion, '8.1', '<' ) ) {
453 + //We can't split up here!
454 + $wpSyncColumns = array(
455 + 'version',
456 + 'totalsize',
457 + 'dbsize',
458 + 'extauth',
459 + 'last_post_gmt',
460 + 'uptodate',
461 + 'sync_errors',
462 + 'dtsSync',
463 + 'dtsSyncStart',
464 + 'dtsAutomaticSync',
465 + 'dtsAutomaticSyncStart',
466 + );
467 + foreach ( $wpSyncColumns as $wpSyncColumn ) {
468 + $rslts = $this->wpdb->get_results( 'SELECT id,' . $wpSyncColumn . ' FROM ' . $this->tableName( 'wp' ), ARRAY_A );
469 + if ( empty( $rslts ) ) {
470 + continue;
471 + }
328 472
329 - // This parameter is used to enable caching in certain cases.
330 - $_included_cache_ids = isset( $params['_included_cache_ids'] ) ? wp_parse_id_list( $params['_included_cache_ids'] ) : array();
473 + foreach ( $rslts as $rslt ) {
474 + $exists = $this->wpdb->get_results( 'SELECT wpid FROM ' . $this->tableName( 'wp_sync' ) . ' WHERE wpid = ' . $rslt[ 'id' ], ARRAY_A );
475 + if ( empty( $exists ) ) {
476 + $this->wpdb->insert( $this->tableName( 'wp_sync' ), array(
477 + 'wpid' => $rslt[ 'id' ],
478 + $wpSyncColumn => $rslt[ $wpSyncColumn ],
479 + ) );
480 + } else {
481 + $this->wpdb->update( $this->tableName( 'wp_sync' ), array( $wpSyncColumn => $rslt[ $wpSyncColumn ] ), array( 'wpid' => $rslt[ 'id' ] ) );
482 + }
483 + }
331 484
332 - $select_wpfields = isset( $params['select_wp_fields'] ) ? wp_parse_list( $params['select_wp_fields'] ) : '';
333 - $select_syncfields = isset( $params['select_sync_fields'] ) ? wp_parse_list( $params['select_sync_fields'] ) : '';
485 + $suppress = $this->wpdb->suppress_errors();
486 + $this->wpdb->query( 'ALTER TABLE ' . $this->tableName( 'wp' ) . ' DROP COLUMN ' . $wpSyncColumn );
487 + $this->wpdb->suppress_errors( $suppress );
488 + }
334 489
335 - $where = '';
490 + $optionColumns = array(
491 + 'last_wp_upgrades',
492 + 'last_plugin_upgrades',
493 + 'last_theme_upgrades',
494 + 'wp_upgrades',
495 + 'recent_comments',
496 + 'recent_posts',
497 + 'recent_pages',
498 + );
499 + foreach ( $optionColumns as $optionColumn ) {
500 + $rslts = $this->wpdb->get_results( 'SELECT id,' . $optionColumn . ' FROM ' . $this->tableName( 'wp' ), ARRAY_A );
501 + if ( empty( $rslts ) ) {
502 + continue;
503 + }
336 504
337 - if ( ! empty( $extraWhere ) ) {
338 - $where .= ' AND ' . $extraWhere;
339 - }
505 + foreach ( $rslts as $rslt ) {
506 + MainWP_DB::updateWebsiteOption( (object) $rslt, $optionColumn, $rslt[ $optionColumn ] );
507 + }
340 508
341 - if ( ! $for_manager ) {
342 - $where .= $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
509 + $suppress = $this->wpdb->suppress_errors();
510 + $this->wpdb->query( 'ALTER TABLE ' . $this->tableName( 'wp' ) . ' DROP COLUMN ' . $optionColumn );
511 + $this->wpdb->suppress_errors( $suppress );
512 + }
513 + }
343 514 }
344 515
345 - $connected_sql = '';
516 + public function getFirstSyncedSite( $userId = null ) {
517 + if ( ( $userId == null ) && MainWP_System::Instance()->isMultiUser() ) {
518 + global $current_user;
519 + $userId = $current_user->ID;
520 + }
521 + $where = ( $userId != null ) ? ' userid = ' . $userId : '';
522 + $where .= $this->getWhereAllowAccessSites( 'wp' );
523 + $qry = 'SELECT wp_sync.dtsSync FROM ' . $this->tableName( 'wp' ) . ' wp JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid WHERE wp_sync.sync_errors = "" ' . $where . ' ORDER BY wp_sync.dtsSync ASC LIMIT 1';
346 524
347 - if ( is_array( $params ) && isset( $params['connected'] ) && 'yes' === $params['connected'] ) {
348 - $connected_sql = ' AND wp_sync.sync_errors = "" ';
349 - } elseif ( is_array( $params ) && isset( $params['connected'] ) && 'no' === $params['connected'] ) {
350 - $connected_sql = ' AND wp_sync.sync_errors <> "" ';
351 - }
525 + return $this->wpdb->get_var( $qry );
526 + }
352 527
353 - if ( ! empty( $s ) ) {
354 - $s = trim( $s );
355 - // Use esc_like() to escape LIKE wildcards (%, _) then prepare() for SQL safety.
356 - $like_pattern = '%' . $this->wpdb->esc_like( $s ) . '%';
357 - $where .= $this->wpdb->prepare(
358 - ' AND ( wp.id LIKE %s OR wp.name LIKE %s OR wp.url LIKE %s ) ',
359 - $like_pattern,
360 - $like_pattern,
361 - $like_pattern
362 - );
363 - }
528 + public function getLastSyncStatus( $userId = null ) {
529 + $sql = MainWP_DB::Instance()->getSQLWebsitesForCurrentUser();
530 + $websites = MainWP_DB::Instance()->query( $sql );
364 531
365 - if ( ! empty( $exclude ) ) {
366 - $where .= ' AND wp.id NOT IN (' . implode( ',', $exclude ) . ') ';
367 - }
532 + $return = array(
533 + 'sync_status' => false,
534 + 'last_sync' => 0
535 + );
368 536
369 - if ( ! empty( $include ) ) {
370 - $where .= ' AND wp.id IN (' . implode( ',', $include ) . ') ';
371 - }
537 + if ( !$websites ) {
538 + $return[ 'sync_status' ] = 'all_synced';
539 + return $return;
540 + }
372 541
373 - if ( ! empty( $_included_cache_ids ) ) {
374 - $where .= ' AND wp.id IN (' . implode( ',', $_included_cache_ids ) . ') ';
375 - }
542 + $total_sites = 0;
543 + $synced_sites = 0;
544 + $last_sync = 0;
545 + @MainWP_DB::data_seek( $websites, 0 );
546 + while ( $websites && ( $website = @MainWP_DB::fetch_object( $websites ) ) ) {
547 + if ( empty( $website ) || $website->sync_errors != '' ) {
548 + continue;
549 + }
550 + $total_sites++;
551 + if ( time() - $website->dtsSync < 60 * 60 * 24 ) {
552 + $synced_sites++;
553 + }
554 + if ( $last_sync < $website->dtsSync ) {
555 + $last_sync = $website->dtsSync;
556 + }
557 + }
376 558
377 - $specific_wp_fields = '';
378 - if ( ! empty( $select_wpfields ) ) {
379 - foreach ( $select_wpfields as $_field ) {
380 - $specific_wp_fields .= 'wp.' . $this->escape( $_field ) . ',';
381 - }
382 - $specific_wp_fields = rtrim( $specific_wp_fields, ',' );
383 - }
559 + if ( $total_sites == $synced_sites ) {
560 + $return[ 'sync_status' ] = 'all_synced';
561 + } else if ( $synced_sites == 0 ) {
562 + $return[ 'sync_status' ] = 'not_synced';
563 + }
564 + $return[ 'last_sync' ] = $last_sync;
565 + return $return;
566 + }
384 567
385 - $specific_sync_fields = '';
386 - if ( ! empty( $select_syncfields ) ) {
387 - foreach ( $select_syncfields as $_field ) {
388 - $specific_sync_fields .= 'wp_sync.' . $this->escape( $_field ) . ',';
389 - }
390 - $specific_sync_fields = rtrim( $specific_sync_fields, ',' );
391 - }
568 + public function getDisconnectedWebsites() {
569 + $sql = MainWP_DB::Instance()->getSQLWebsitesForCurrentUser();
570 + $websites = MainWP_DB::Instance()->query( $sql );
392 571
393 - // any, connected, disconnected, suspended, available_update.
394 - if ( ! empty( $status ) && is_array( $status ) && ! in_array( 'any', $status ) ) {
395 - $status_conds = array();
396 - if ( in_array( 'available_update', $status ) ) {
397 - $available_sql = " ( wp.plugin_upgrades <> '' && wp.plugin_upgrades <> '[]' ) OR ( wp.theme_upgrades <> '' && wp.theme_upgrades <> '[]' ) OR ( wp.translation_upgrades <> '' && wp.translation_upgrades <> '[]' ) OR ( wp.premium_upgrades <> '' && wp.premium_upgrades <> '[]' ) ";
398 - $table_name = esc_sql( $this->table_name( 'wp_options' ) );
399 - $results = $this->wpdb->get_results( "SELECT wpid FROM {$table_name} WHERE name = 'wp_upgrades' AND value <> '' AND value <> '[]'" );
400 - if ( $results ) {
401 - $wp_ids = array();
402 - foreach ( $results as $item ) {
403 - if ( ! empty( $item->wpid ) ) {
404 - $wp_ids[] = $item->wpid;
405 - }
406 - }
407 - $wp_ids = ! empty( $wp_ids ) ? array_unique( $wp_ids ) : array();
408 - if ( ! empty( $wp_ids ) ) {
409 - $available_sql .= ' OR wp.id IN ( ' . implode( ',', $wp_ids ) . ' )';
410 - }
411 - }
412 - $status_conds[] = ' ( ' . $available_sql . ') ';
413 - }
572 + if ( !$websites ) {
573 + return array();
574 + }
414 575
415 - if ( in_array( 'connected', $status ) ) {
416 - $status_conds[] = ' ( wp_sync.sync_errors = "" ) ';
417 - }
418 - if ( in_array( 'disconnected', $status ) ) {
419 - $status_conds[] = " wp_sync.sync_errors <> '' ";
420 - }
576 + $disc_sites = array();
421 577
422 - if ( in_array( 'suspended', $status ) ) {
423 - $status_conds[] = ' wp.suspended = 1 ';
578 + @MainWP_DB::data_seek( $websites, 0 );
579 + while ( $websites && ( $website = @MainWP_DB::fetch_object( $websites ) ) ) {
580 + if ( empty( $website ) ) {
581 + continue;
582 + }
583 + if ( $website->sync_errors != '' ) {
584 + $disc_sites[$website->id] = $website->url;
424 585 }
425 586
426 - if ( ! empty( $status_conds ) ) {
427 - $where .= ' AND ( ' . implode( ' OR ', $status_conds ) . ' ) ';
428 - }
429 - if ( in_array( 'unsuspended', $status ) && ! in_array( 'suspended', $status ) ) { // to sure not conflict the suspended status.
430 - $where .= ' AND wp.suspended = 0 ';
431 - }
432 - }
587 + }
433 588
434 - if ( ! empty( $page ) && ! empty( $per_page ) ) {
435 - $limit = ( $page - 1 ) * $per_page . ',' . $per_page;
436 - }
589 + return $disc_sites;
590 + }
437 591
438 - if ( 'wp.url' === $orderBy ) {
439 - $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '')";
440 - }
592 + public function getRequestsSince( $pSeconds ) {
593 + $where = $this->getWhereAllowAccessSites( 'wp' );
594 + $qry = 'SELECT count(*) FROM ' . $this->tableName( 'wp' ) . ' wp JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid WHERE wp_sync.dtsSyncStart > ' . ( time() - $pSeconds ) . $where;
441 595
442 - $select_clients = '';
443 - $join_clients = '';
596 + return $this->wpdb->get_var( $qry );
597 + }
444 598
445 - if ( $with_clients ) {
446 - $select_clients = ', wpclient.name as client_name ';
447 - $clients_table = esc_sql( $this->table_name( 'wp_clients' ) );
448 - $join_clients = " LEFT JOIN {$clients_table} wpclient ON wp.client_id = wpclient.client_id ";
449 - }
599 + //Database actions
600 + public function getWebsitesCount( $userId = null, $all_access = false ) {
601 + if ( ( $userId == null ) && MainWP_System::Instance()->isMultiUser() ) {
602 + global $current_user;
603 + $userId = $current_user->ID;
604 + }
605 + $where = ( $userId == null ? '' : ' wp.userid = ' . $userId );
606 + if ( ! $all_access ) {
607 + $where .= $this->getWhereAllowAccessSites( 'wp' );
608 + }
609 + $qry = 'SELECT COUNT(wp.id) FROM ' . $this->tableName( 'wp' ) . ' wp WHERE 1 ' . $where;
450 610
451 - $base_fields = array(
452 - 'wp.id',
453 - 'wp.url',
454 - 'wp.name',
455 - 'wp.client_id',
456 - 'wp.verify_certificate',
457 - 'wp.http_user',
458 - 'wp.http_pass',
459 - 'wp.ssl_version',
460 - 'wp.adminname',
461 - 'wp.privkey',
462 - 'wp.pubkey',
463 - 'wp.wpe',
464 - 'wp.is_staging',
465 - 'wp.force_use_ipv4',
466 - 'wp.siteurl',
467 - 'wp.suspended',
468 - 'wp.mainwpdir',
469 - 'wp.is_ignoreCoreUpdates',
470 - 'wp.is_ignorePluginUpdates',
471 - 'wp.is_ignoreThemeUpdates',
472 - 'wp_sync.sync_errors',
473 - 'wp.backup_before_upgrade',
474 - 'wp.userid',
475 - 'wp.plugins',
476 - 'wp.themes',
477 - 'wp.offline_check_result', // 1 - online, -1 offline.
478 - );
611 + return $this->wpdb->get_var( $qry );
612 + }
479 613
480 - $select = ' wp.*,wp_sync.* ';
481 - if ( 'base_view' === $view ) {
482 - $select = implode( ',', $base_fields );
483 - } elseif ( 'updates_view' === $view ) {
484 - $updates_fields = array(
485 - 'wp.plugin_upgrades',
486 - 'wp.theme_upgrades',
487 - 'wp.translation_upgrades',
488 - 'wp.premium_upgrades',
489 - 'wp.ignored_themes',
490 - 'wp.ignored_plugins',
491 - );
492 - $select = implode( ',', array_merge( $updates_fields, $base_fields ) );
493 - }
614 + public function getWebsiteOption( $website, $option ) {
494 615
495 - $view_selects = '';
496 - $view_joins = '';
497 -
498 - if ( $use_comp_subquery ) {
499 - $view_selects = ',wp_optionview.* ';
500 - $view_joins = ' JOIN ' . $this->get_option_view_by( $view, $others_fields ) . ' wp_optionview ON wp.id = wp_optionview.wpid ';
501 - } else {
502 - $opts_view = $this->get_option_view_by_join( $view, $others_fields );
503 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
504 - $view_selects = ',' . $opts_view['selects'];
505 - $view_joins = $opts_view['joins'];
616 + if ( is_array($website) ) {
617 + if ( isset($website[$option]) ) {
618 + return $website[$option];
506 619 }
507 - }
508 -
509 - // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax.
510 - if ( $selectgroups ) {
511 - $qry = 'SELECT ' . $select . $view_selects . ', GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ",") as wpgroups, GROUP_CONCAT(gr.id ORDER BY gr.name SEPARATOR ",") as wpgroupids, GROUP_CONCAT(gr.color ORDER BY gr.name SEPARATOR ",") as wpgroups_colors ' .
512 - $select_clients . '
513 -
514 - FROM ' . $this->table_name( 'wp' ) . ' wp
515 - LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
516 - LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
517 - ' . $join_clients . '
518 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
519 - ' . $view_joins . '
520 - WHERE 1 ' . $where . $connected_sql . '
521 - GROUP BY wp.id, wp_sync.sync_id
522 - ORDER BY ' . $orderBy;
523 - } elseif ( ! empty( $specific_wp_fields ) ) { // Optimize select sites data.
524 - $select = $specific_wp_fields;
525 - $join_sync = '';
526 - $group_by = 'wp.id';
527 -
528 - if ( ! empty( $specific_sync_fields ) ) {
529 - $select .= ',' . $specific_sync_fields;
530 - $join_sync = ' JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid';
531 - $group_by .= ', wp_sync.sync_id';
532 - }
533 - $qry = 'SELECT ' . $select . $view_selects . '
534 - FROM ' . $this->table_name( 'wp' ) . ' wp
535 - ' . $join_sync . ' ' . $view_joins . '
536 - WHERE 1 ' . $where . $connected_sql . '
537 - GROUP BY ' . $group_by . '
538 - ORDER BY ' . $orderBy;
539 - } else {
540 - $qry = 'SELECT ' . $select . $view_selects . $select_clients . '
541 - FROM ' . $this->table_name( 'wp' ) . ' wp
542 - ' . $join_clients . '
543 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
544 - ' . $view_joins . '
545 - WHERE 1 ' . $where . $connected_sql . '
546 - GROUP BY wp.id, wp_sync.sync_id
547 - ORDER BY ' . $orderBy;
548 - }
549 -
550 - if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
551 - $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
552 - } elseif ( false !== $rowcount ) {
553 - $qry .= ' LIMIT ' . $rowcount;
554 - } elseif ( ! empty( $limit ) ) {
555 - $qry .= ' LIMIT ' . $limit;
556 - } else {
557 - // load all sites so check to support limit sites loading.
558 - $limit_sites = ! empty( $params['limit_sites'] ) ? intval( $params['limit_sites'] ) : 0;
559 - if ( ! empty( $limit_sites ) ) {
560 - $current_page = (int) get_option( 'mainwp_manage_updates_limit_current_page', 0 );
561 - $current_page = $current_page > 0 ? $current_page - 1 : 0;
562 - $start = $current_page * $limit_sites;
563 - $qry .= ' LIMIT ' . intval( $start ) . ', ' . intval( $limit_sites );
564 - }
565 - }
566 -
567 - if ( ! empty( $_included_cache_ids ) ) {
568 - MainWP_Logger::instance()->log_events( 'cache-metrics', sprintf( '[sql websites by params=%s]', $qry ) );
569 - }
570 - MainWP_Logger::instance()->log_events( 'db-queries', sprintf( '[sql websites by params=%s]', $qry ) );
571 - return $qry;
572 - }
573 -
574 - /**
575 - * Improve get wp_options database table view.
576 - *
577 - * @param array $view Option view.
578 - * @param array $other_fields Extra option fields.
579 - *
580 - * @return array wp_options view.
581 - */
582 - public function get_option_view_by_join( $view = '', $other_fields = array() ) {
583 -
584 - $default = array(
585 - 'recent_comments',
586 - 'recent_posts',
587 - 'recent_pages',
588 - 'phpversion',
589 - 'added_timestamp',
590 - 'wp_upgrades',
591 - );
592 -
593 - $fields = array();
594 -
595 - if ( 'updates_view' === $view ) {
596 - $fields = array(
597 - 'wp_upgrades',
598 - 'ignored_wp_upgrades',
599 - 'ignored_trans_updates',
600 - );
601 - } elseif ( in_array( $view, array( 'simple_view', 'base_view', 'monitor_view', 'ping_view', 'uptime_notification' ) ) ) {
602 - $fields = array();
603 - if ( 'monitor_view' === $view ) {
604 - $fields[] = 'health_site_status';
605 - }
606 - } elseif ( 'custom_view' !== $view ) {
607 - $fields = $default;
608 - }
609 -
610 - if ( is_array( $other_fields ) && ! empty( $other_fields ) ) {
611 - $fields = array_unique( array_merge( $fields, $other_fields ) );
612 - }
613 -
614 - if ( 'custom_view' !== $view ) {
615 - if ( ! in_array( 'signature_algo', $fields ) ) {
616 - $fields[] = 'signature_algo';
617 - }
618 -
619 - if ( ! in_array( 'verify_method', $fields ) ) {
620 - $fields[] = 'verify_method';
621 - }
622 - }
623 -
624 - $fields = array_values( array_filter( $fields ) );
625 -
626 - $tbl_wp_options = $this->table_name( 'wp_options' );
627 -
628 - $selects = array();
629 - $joins = array();
630 -
631 - foreach ( $fields as $name ) {
632 - $alias = 'owp_' . preg_replace( '/[^a-z0-9_]/i', '_', $name );
633 -
634 - // SELECT.
635 - $selects[] = "{$alias}.value AS `" . $this->escape( $name ) . '`';
636 -
637 - // JOIN.
638 - $joins[] = "LEFT JOIN {$tbl_wp_options} {$alias}
639 - ON {$alias}.wpid = wp.id
640 - AND {$alias}.name = '" . $this->escape( $name ) . "'";
641 - }
642 -
643 - return array(
644 - 'selects' => implode( ', ', $selects ),
645 - 'joins' => implode( "\n", $joins ),
646 - );
647 - }
648 -
649 - /**
650 - * Get wp_options database table view.
651 - *
652 - * Use new get_option_view_by_join() method to improve the performance of wp_options view, and this method is used to generate the SQL with LEFT JOIN which will be much faster than subquery, but it will return the same result as get_option_view() method, and the alias of wp table must be 'wp' to make sure the LEFT JOIN works, and the alias of wp_options table will be 'owp' + key of field in fields array, and the join condition is owp.wpid = wp.id AND owp.name = field name, and the select field is owp.value AS field name.
653 - *
654 - * @param array $view Option view.
655 - * @param array $other_fields Extra option fields.
656 - *
657 - * @return array wp_options view.
658 - */
659 - public function get_option_view_by( $view = '', $other_fields = array() ) {
660 -
661 - $default = array(
662 - 'recent_comments',
663 - 'recent_posts',
664 - 'recent_pages',
665 - 'phpversion',
666 - 'added_timestamp',
667 - 'wp_upgrades',
668 - );
669 -
670 - $fields = array();
671 -
672 - if ( 'updates_view' === $view ) {
673 - $fields = array(
674 - 'wp_upgrades',
675 - 'ignored_wp_upgrades',
676 - 'ignored_trans_updates',
677 - );
678 - } elseif ( in_array( $view, array( 'simple_view', 'base_view', 'monitor_view', 'ping_view', 'uptime_notification' ) ) ) {
679 - $fields = array();
680 - if ( 'monitor_view' === $view ) {
681 - $fields[] = 'health_site_status';
682 - }
683 - } elseif ( 'custom_view' !== $view ) {
684 - $fields = $default;
685 - }
686 -
687 - if ( is_array( $other_fields ) && ! empty( $other_fields ) ) {
688 - $fields = array_unique( array_merge( $fields, $other_fields ) );
689 - }
690 -
691 - $view_query = '(SELECT wpid ';
692 -
693 - if ( 'custom_view' !== $view ) {
694 - if ( ! in_array( 'signature_algo', $fields ) ) {
695 - $fields[] = 'signature_algo';
696 - }
697 -
698 - if ( ! in_array( 'verify_method', $fields ) ) {
699 - $fields[] = 'verify_method';
700 - }
701 - }
702 -
703 - foreach ( $fields as $field ) {
704 -
705 - if ( empty( $field ) ) {
706 - continue;
707 - }
708 -
709 - $view_query .= ', ';
710 - $view_query .= 'MAX(CASE WHEN name = "' . $this->escape( $field ) . '" THEN value END) AS ' . $this->escape( $field );
711 - }
712 -
713 - $view_query .= ' FROM ' . $this->table_name( 'wp_options' ) .
714 - " WHERE name IN ('" . implode( "','", $fields ) . "')
715 - GROUP BY wpid ) ";
716 -
717 - return $view_query;
718 - }
719 -
720 - /**
721 - * Method get_select_groups_belong().
722 - *
723 - * @return string sql.
724 - */
725 - public function get_select_groups_belong() {
726 - return ', ( SELECT GROUP_CONCAT(grbl.name ORDER BY grbl.name SEPARATOR ",")
727 - FROM ' . $this->table_name( 'wp_group' ) . ' wpgrbl
728 - JOIN ' . $this->table_name( 'group' ) . ' grbl ON grbl.id = wpgrbl.groupid WHERE wpgrbl.wpid = wp.id ) as wpgroups_belong,
729 - ( SELECT GROUP_CONCAT(grbl.id ORDER BY grbl.name SEPARATOR ",") FROM ' . $this->table_name( 'wp_group' ) . ' wpgrbl
730 - JOIN ' . $this->table_name( 'group' ) . ' grbl ON grbl.id = wpgrbl.groupid WHERE wpgrbl.wpid = wp.id ) as wpgroupids_belong,
731 - ( SELECT GROUP_CONCAT(grbl.color ORDER BY grbl.name SEPARATOR ",") FROM ' . $this->table_name( 'wp_group' ) . ' wpgrbl
732 - JOIN ' . $this->table_name( 'group' ) . ' grbl ON grbl.id = wpgrbl.groupid WHERE wpgrbl.wpid = wp.id ) as wpgroupcolors_belong ';
733 - }
734 -
735 - /**
736 - * Get connected child sites.
737 - *
738 - * @param array $sites_ids Websites ids - option field.
739 - *
740 - * @return array $connected_sites Array of connected sites.
741 - */
742 - public function get_connected_websites( $sites_ids = false ) {
743 - $where = $this->get_sql_where_allow_access_sites( 'wp' );
744 - $wp_table = esc_sql( $this->table_name( 'wp' ) );
745 - $wp_sync_table = esc_sql( $this->table_name( 'wp_sync' ) );
746 -
747 - $sql = "SELECT wp.*,wp_sync.*
748 - FROM {$wp_table} wp
749 - JOIN {$wp_sync_table} wp_sync
750 - ON wp.id = wp_sync.wpid
751 - WHERE (wp_sync.sync_errors IS NOT NULL) AND (wp_sync.sync_errors = \"\") " .
752 - $where;
753 -
754 - $websites = $this->wpdb->get_results( $sql ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Query is fully escaped: table names via esc_sql(), WHERE fragment from validated get_sql_where_allow_access_sites()
755 - $connected_sites = array();
756 - if ( $websites ) {
757 - foreach ( $websites as $website ) {
758 -
759 - if ( ! empty( $sites_ids ) && ! in_array( $website->id, $sites_ids ) ) {
760 - continue;
761 - }
762 -
763 - $connected_sites[] = array(
764 - 'id' => $website->id,
765 - 'name' => $website->name,
766 - 'url' => $website->url,
767 - );
768 - }
769 - }
770 - return $connected_sites;
771 - }
772 -
773 - /**
774 - * Get disconnected child sites.
775 - *
776 - * @param array $sites_ids Websites ids - option field.
777 - *
778 - * @return array $disc_sites Array of disonnected sites.
779 - */
780 - public function get_disconnected_websites( $sites_ids = false ) {
781 - $where = $this->get_sql_where_allow_access_sites( 'wp' );
782 - $wp_table = esc_sql( $this->table_name( 'wp' ) );
783 - $wp_sync_table = esc_sql( $this->table_name( 'wp_sync' ) );
784 -
785 - $sql = "SELECT wp.*,wp_sync.*
786 - FROM {$wp_table} wp
787 - JOIN {$wp_sync_table} wp_sync
788 - ON wp.id = wp_sync.wpid
789 - WHERE (wp_sync.sync_errors IS NOT NULL) AND (wp_sync.sync_errors <> \"\") " .
790 - $where;
791 -
792 - $websites = $this->wpdb->get_results( $sql ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Query is fully escaped: table names via esc_sql(), WHERE fragment from validated get_sql_where_allow_access_sites()
793 - $disc_sites = array();
794 - if ( $websites ) {
795 - foreach ( $websites as $website ) {
796 -
797 - if ( ! empty( $sites_ids ) && ! in_array( $website->id, $sites_ids ) ) {
798 - continue;
799 - }
800 -
801 - $disc_sites[] = array(
802 - 'id' => $website->id,
803 - 'name' => $website->name,
804 - 'url' => $website->url,
805 - );
806 - }
807 - }
808 - return $disc_sites;
809 - }
810 -
811 - /**
812 - * Get child site count.
813 - *
814 - * @param null $userId Current user ID.
815 - * @param bool $all_access Check if user has access to all sites.
816 - *
817 - * @return int Child site count.
818 - *
819 - * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
820 - *
821 - * @see get_websites_count_for_current_user() For Abilities API with status/tags/client filters.
822 - * This method is intentionally simple for UI display purposes (total sites count).
823 - * The two methods serve different use cases and should not be consolidated.
824 - */
825 - public function get_websites_count( $userId = null, $all_access = false ) {
826 - static $total_sites;
827 - if ( null !== $total_sites ) { // NOSONAR -- static value.
828 - return $total_sites;
829 - }
830 - if ( ( null === $userId ) && MainWP_System::instance()->is_multi_user() ) {
831 -
832 - /**
833 - * Current user global.
834 - *
835 - * @global string
836 - */
837 - global $current_user;
838 -
839 - $userId = $current_user->ID;
840 - }
841 - $where = ( null === $userId ? '' : ' wp.userid = ' . intval( $userId ) );
842 - if ( ! $all_access ) {
843 - $where .= $this->get_sql_where_allow_access_sites( 'wp' );
844 - }
845 - $table_name = esc_sql( $this->table_name( 'wp' ) );
846 - $qry = "SELECT COUNT(wp.id) FROM {$table_name} wp WHERE 1 {$where}";
847 -
848 - $total = $this->wpdb->get_var( $qry ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Query is fully escaped: table names via esc_sql(), WHERE fragment from validated get_sql_where_allow_access_sites()
849 - $total_sites = $total;// NOSONAR -- static value.
850 - return $total;
851 - }
852 -
853 -
854 - /**
855 - * Get child sites stats count.
856 - *
857 - * @param array $params Params.
858 - */
859 - public function get_websites_stats_count( $params = array() ) {
860 - if ( ! is_array( $params ) ) {
861 - $params = array();
862 - }
863 -
864 - if ( isset( $params['all_access'] ) ) {
865 - $all_access = ! empty( $params['all_access'] ) ? true : false;
866 - } else {
867 - $all_access = true;
868 - }
869 -
870 - $where = '';
871 - if ( ! $all_access ) {
872 - $where .= $this->get_sql_where_allow_access_sites( 'wp' );
873 - }
874 -
875 - $select_stats = ' ( SELECT COUNT(wp.id) as count_all ';
876 - if ( ! empty( $params['count_disconnected'] ) ) {
877 - $select_stats .= ',( SELECT COUNT(wp_disconnected.id) FROM ' . $this->table_name( 'wp' ) . ' wp_disconnected LEFT JOIN ' . $this->table_name( 'wp_sync' ) . ' as wp_sync ';
878 - $select_stats .= ' ON wp_disconnected.id = wp_sync.wpid WHERE wp_sync.sync_errors <> "" ) as count_disconnected ';
879 - }
880 - if ( ! empty( $params['count_suspended'] ) ) {
881 - $select_stats .= ',( SELECT COUNT(wp_suspended.id) FROM ' . $this->table_name( 'wp' ) . ' wp_suspended WHERE wp_suspended.suspended = 1 ) as count_suspended ';
882 - }
883 - $qry = 'SELECT * FROM ' . $select_stats;
884 - $qry .= ' FROM ' . $this->table_name( 'wp' ) . ' wp ' . $where . ' ) as wp_stats ';
885 -
886 - return $this->wpdb->get_row( $qry, ARRAY_A ); //phpcs:ignore -- ok.
887 - }
888 -
889 - /**
890 - * Get Child site wp_options database table.
891 - *
892 - * @param array $website Child Site array.
893 - * @param mixed $option Child Site wp_options table name.
894 - * @param mixed $default_value default value.
895 - * @param mixed $json_format Is json format value.
896 - *
897 - * @return string|null Database query result (as string), or null on failure.
898 - */
899 - public function get_website_option( $website, $option, $default_value = null, $json_format = false ) { //phpcs:ignore -- NOSONAR - complex.
900 -
901 - if ( is_array( $website ) ) {
902 - if ( isset( $website[ $option ] ) ) {
903 - $value = $website[ $option ];
904 - if ( true === $json_format ) {
905 - $value = ! empty( $value ) ? json_decode( $value, true ) : array();
906 - return is_array( $value ) ? $value : array();
907 - } else {
908 - return $value;
909 - }
910 - }
911 620 $site_id = $website['id'];
912 - } elseif ( is_object( $website ) ) {
621 + } else if ( is_object($website) ) {
913 622 if ( property_exists( $website, $option ) ) {
914 - $value = $website->{$option};
915 - if ( true === $json_format ) {
916 - $value = ! empty( $value ) ? json_decode( $value, true ) : array();
917 - return is_array( $value ) ? $value : array();
918 - } else {
919 - return $value;
920 - }
623 + return $website->{$option};
921 624 }
922 625 $site_id = $website->id;
923 - } elseif ( is_numeric( $website ) ) { // to support $site_id = 0, for global options.
924 - $site_id = $website;
925 - } else {
926 - return false;
927 626 }
928 627
929 - $table_name = esc_sql( $this->table_name( 'wp_options' ) );
930 - $value = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT value FROM {$table_name} WHERE wpid = %d AND name = %s", $site_id, $option ) );
628 + return $this->wpdb->get_var( 'SELECT value FROM ' . $this->tableName( 'wp_options' ) . ' WHERE wpid = ' . $site_id . ' AND name = "' . $this->escape( $option ) . '"' );
629 + }
931 630
932 - if ( null === $value && null !== $default_value ) {
933 - return $default_value;
934 - }
631 + public function updateWebsiteOption( $website, $option, $value ) {
632 + $rslt = $this->wpdb->get_results( 'SELECT name FROM ' . $this->tableName( 'wp_options' ) . ' WHERE wpid = ' . $website->id . ' AND name = "' . $this->escape( $option ) . '"' );
633 + if ( count( $rslt ) > 0 ) {
634 + $this->wpdb->delete( $this->tableName( 'wp_options' ), array(
635 + 'wpid' => $website->id,
636 + 'name' => $this->escape( $option ),
637 + ) );
638 + $rslt = $this->wpdb->get_results( 'SELECT name FROM ' . $this->tableName( 'wp_options' ) . ' WHERE wpid = ' . $website->id . ' AND name = "' . $this->escape( $option ) . '"' );
639 + }
935 640
936 - if ( true === $json_format ) {
937 - $value = ! empty( $value ) ? json_decode( $value, true ) : array();
938 - return is_array( $value ) ? $value : array();
939 - } else {
940 - return $value;
941 - }
942 - }
641 + if ( count( $rslt ) == 0 ) {
642 + $this->wpdb->insert( $this->tableName( 'wp_options' ), array(
643 + 'wpid' => $website->id,
644 + 'name' => $option,
645 + 'value' => $value,
646 + ) );
647 + } else {
648 + $this->wpdb->update( $this->tableName( 'wp_options' ), array( 'value' => $value ), array(
649 + 'wpid' => $website->id,
650 + 'name' => $option,
651 + ) );
652 + }
653 + }
943 654
944 - /**
945 - * Get Child site wp_options json value.
946 - *
947 - * @since 5.1.1
948 - *
949 - * @param array $website Child Site array.
950 - * @param mixed $option Child Site wp_options table name.
951 - * @param mixed $default_value default value.
952 - *
953 - * @return string|null Database query result (as string), or null on failure.
954 - */
955 - public function get_json_website_option( $website, $option, $default_value = null ) {
956 - return $this->get_website_option( $website, $option, $default_value, true );
957 - }
655 + public function getWebsitesByUserId( $userid, $selectgroups = false, $search_site = null, $orderBy = 'wp.url' ) {
656 + return $this->getResultsResult( $this->getSQLWebsitesByUserId( $userid, $selectgroups, $search_site, $orderBy ) );
657 + }
958 658
959 - /**
960 - * Get child site options.
961 - *
962 - * @param array $website Child site.
963 - * @param mixed $options Child site options name.
964 - *
965 - * @return string|null Database query result (as string), or null on failure.
966 - */
967 - public function get_website_options_array( &$website, $options ) { // phpcs:ignore -- NOSONAR - complex.
659 + public function getSQLWebsites() {
660 + $where = $this->getWhereAllowAccessSites( 'wp' );
968 661
969 - if ( ! is_array( $options ) || empty( $options ) ) {
970 - return array();
971 - }
662 + return 'SELECT wp.*,wp_sync.*,wp_optionview.*
663 + FROM ' . $this->tableName( 'wp' ) . ' wp
664 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
665 + JOIN ' . $this->getOptionView() . ' wp_optionview ON wp.id = wp_optionview.wpid
666 + ' . $where;
667 + }
972 668
973 - if ( is_array( $website ) ) {
974 - $site_id = $website['id'];
975 - } elseif ( is_object( $website ) ) {
976 - $site_id = $website->id;
977 - } elseif ( is_numeric( $website ) ) { // to support $site_id = 0 for global options.
978 - $site_id = $website;
979 - } else {
980 - return array();
981 - }
669 + public function getSQLWebsitesByUserId( $userid, $selectgroups = false, $search_site = null, $orderBy = 'wp.url',
670 + $offset = false, $rowcount = false ) {
671 + if ( MainWP_Utility::ctype_digit( $userid ) ) {
672 + $where = '';
673 + if ( $search_site !== null ) {
674 + $search_site = trim( $search_site );
675 + $where = ' AND (wp.name LIKE "%' . $search_site . '%" OR wp.url LIKE "%' . $search_site . '%") ';
676 + }
982 677
983 - $arr_options = array();
984 - $get_options = array();
678 + $where .= $this->getWhereAllowAccessSites( 'wp' );
985 679
986 - foreach ( $options as $option ) {
987 - if ( is_array( $website ) ) {
988 - if ( isset( $website[ $option ] ) ) {
989 - $arr_options[ $option ] = $website[ $option ];
990 - } else {
991 - $get_options[] = $option;
992 - }
993 - } elseif ( is_object( $website ) ) {
994 - if ( property_exists( $website, $option ) ) {
995 - $arr_options[ $option ] = $website->{$option};
996 - } else {
997 - $get_options[] = $option;
998 - }
999 - } else {
1000 - $get_options[] = $option;
1001 - }
1002 - }
1003 -
1004 - if ( empty( $get_options ) ) {
1005 - return $arr_options; // all options.
1006 - }
1007 -
1008 - $table_name = esc_sql( $this->table_name( 'wp_options' ) );
1009 - $placeholders = implode( ',', array_fill( 0, count( $get_options ), '%s' ) );
1010 - $options_db = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT name, value FROM {$table_name} WHERE wpid = %d AND name IN ({$placeholders})", array_merge( array( $site_id ), $get_options ) ) );
1011 -
1012 - $fill_options = array(
1013 - 'primary_lasttime_backup',
1014 - );
1015 -
1016 - foreach ( (array) $options_db as $o ) {
1017 - $arr_options[ $o->name ] = $o->value;
1018 - if ( in_array( $o->name, $fill_options ) ) {
1019 - if ( is_array( $website ) ) {
1020 - if ( ! isset( $website[ $o->name ] ) ) {
1021 - $website[ $o->name ] = $o->value;
1022 - }
1023 - } elseif ( is_object( $website ) ) {
1024 - if ( ! property_exists( $website, $o->name ) ) {
1025 - $website->{$o->name} = $o->value;
1026 - }
1027 - }
1028 - }
1029 - }
1030 - return $arr_options;
1031 - }
1032 -
1033 - /**
1034 - * Update child site options.
1035 - *
1036 - * @param object $website Child site object.
1037 - * @param mixed $option Option to update.
1038 - * @param mixed $value Value to update with.
1039 - */
1040 - public function update_website_option( $website, $option, $value ) {
1041 -
1042 - if ( is_numeric( $website ) ) {
1043 - $site_id = intval( $website );
1044 - } else {
1045 - $site_id = $website->id;
1046 - }
1047 -
1048 - $table_name = esc_sql( $this->table_name( 'wp_options' ) );
1049 - $rslt = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT name FROM {$table_name} WHERE wpid = %d AND name = %s", $site_id, $option ) );
1050 - if ( empty( $rslt ) ) {
1051 - $this->wpdb->insert(
1052 - $this->table_name( 'wp_options' ),
1053 - array(
1054 - 'wpid' => $site_id,
1055 - 'name' => $option,
1056 - 'value' => $value,
1057 - )
1058 - );
1059 - } else {
1060 - $this->wpdb->update(
1061 - $this->table_name( 'wp_options' ),
1062 - array( 'value' => $value ),
1063 - array(
1064 - 'wpid' => $site_id,
1065 - 'name' => $option,
1066 - )
1067 - );
1068 - }
1069 - }
1070 -
1071 -
1072 - /**
1073 - * Remove child site options.
1074 - *
1075 - * @param object $website Child site object.
1076 - * @param mixed $options Option to update.
1077 - */
1078 - public function remove_website_option( $website, $options ) {
1079 -
1080 - if ( empty( $options ) ) {
1081 - return;
1082 - }
1083 -
1084 - if ( is_numeric( $website ) ) {
1085 - $site_id = intval( $website );
1086 - } else {
1087 - $site_id = $website->id;
1088 - }
1089 -
1090 - if ( ! is_array( $options ) ) {
1091 - $options = (array) $options;
1092 - }
1093 -
1094 - $table_name = esc_sql( $this->table_name( 'wp_options' ) );
1095 - foreach ( $options as $opt ) {
1096 - $this->wpdb->query( $this->wpdb->prepare( "DELETE FROM {$table_name} WHERE wpid=%d AND name=%s", $site_id, $opt ) );
1097 - }
1098 - }
1099 -
1100 -
1101 - /**
1102 - * Get general Child site option.
1103 - *
1104 - * @param mixed $option Child Site option name.
1105 - *
1106 - * @return string|null Database query result (as string), or null on failure.
1107 - */
1108 - private function get_general_website_option( $option ) {
1109 -
1110 - if ( null !== static::$general_options ) {
1111 - if ( isset( static::$general_options[ $option ] ) ) {
1112 - return static::$general_options[ $option ];
1113 - }
1114 - } else {
1115 - static::$general_options[] = array();
1116 - }
1117 -
1118 - $table_name = esc_sql( $this->table_name( 'wp_options' ) );
1119 - $val = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT value FROM {$table_name} WHERE wpid = %d AND name = %s", 0, $option ) );
1120 -
1121 - static::$general_options[ $option ] = $val;
1122 - return $val;
1123 - }
1124 -
1125 - /**
1126 - * Get child site options.
1127 - *
1128 - * @param mixed $options Child site options name.
1129 - *
1130 - * @return string|null Database query result (as string), or null on failure.
1131 - */
1132 - public function get_general_options_array( $options ) {
1133 -
1134 - if ( ! is_array( $options ) || empty( $options ) ) {
1135 - return array();
1136 - }
1137 -
1138 - $return_options = array();
1139 - if ( null !== static::$general_options ) {
1140 - foreach ( static::$general_options as $opt => $val ) {
1141 - if ( in_array( $opt, $options ) ) {
1142 - $return_options[ $opt ] = $val;
1143 - }
1144 - }
1145 - } else {
1146 - static::$general_options[] = array();
1147 - }
1148 -
1149 - $diff_options = array();
1150 - foreach ( $options as $opt ) {
1151 - if ( ! isset( $return_options[ $opt ] ) ) {
1152 - $diff_options[] = $opt;
1153 - }
1154 - }
1155 -
1156 - if ( empty( $diff_options ) ) {
1157 - return $return_options;
1158 - }
1159 -
1160 - $table_name = esc_sql( $this->table_name( 'wp_options' ) );
1161 - $placeholders = implode( ',', array_fill( 0, count( $diff_options ), '%s' ) );
1162 - $options_db = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT name, value FROM {$table_name} WHERE wpid = %d AND name IN ({$placeholders})", array_merge( array( 0 ), $diff_options ) ) );
1163 -
1164 - foreach ( (array) $options_db as $o ) {
1165 - $return_options[ $o->name ] = $o->value;
1166 - static::$general_options[ $o->name ] = $o->value;
1167 - }
1168 - return $return_options;
1169 - }
1170 -
1171 - /**
1172 - * Update general site options.
1173 - *
1174 - * @param mixed $option Option to update.
1175 - * @param mixed $value Value to update with.
1176 - * @param string $type_value Type values: single|array.
1177 - */
1178 - public function update_general_option( $option, $value, $type_value = 'single' ) {
1179 -
1180 - if ( 'array' === $type_value ) {
1181 - if ( empty( $value ) ) {
1182 - $value = array();
1183 - } elseif ( ! is_array( $value ) ) {
1184 - return false;
1185 - }
1186 - $value = wp_json_encode( $value );
1187 - }
1188 -
1189 - if ( null === static::$general_options ) {
1190 - static::$general_options[] = array();
1191 - }
1192 - static::$general_options[ $option ] = $value;
1193 -
1194 - $table_name = esc_sql( $this->table_name( 'wp_options' ) );
1195 - $rslt = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT name FROM {$table_name} WHERE wpid = %d AND name = %s", 0, $option ) );
1196 -
1197 - if ( empty( $rslt ) ) {
1198 - $this->wpdb->insert(
1199 - $this->table_name( 'wp_options' ),
1200 - array(
1201 - 'wpid' => 0,
1202 - 'name' => $option,
1203 - 'value' => $value,
1204 - )
1205 - );
1206 - } else {
1207 - $this->wpdb->update(
1208 - $this->table_name( 'wp_options' ),
1209 - array( 'value' => $value ),
1210 - array(
1211 - 'wpid' => 0,
1212 - 'name' => $option,
1213 - )
1214 - );
1215 - }
1216 - return true;
1217 - }
1218 -
1219 - /**
1220 - * Get general Child site option.
1221 - *
1222 - * @param mixed $opt Child Site option name.
1223 - * @param string $type_value Type values: single|array.
1224 - *
1225 - * @return string|null Database query result (as string), or null on failure.
1226 - */
1227 - public function get_general_option( $opt, $type_value = 'single' ) {
1228 - if ( 'single' === $type_value ) {
1229 - return $this->get_general_website_option( $opt );
1230 - } elseif ( 'array' === $type_value ) {
1231 - $json_value = $this->get_general_website_option( $opt );
1232 - if ( empty( $json_value ) ) {
1233 - return array();
1234 - }
1235 - return json_decode( $json_value, true );
1236 - }
1237 - return false;
1238 - }
1239 -
1240 - /**
1241 - * Get child sites by user ID.
1242 - *
1243 - * @param int $userid User ID.
1244 - * @param bool $selectgroups Selected groups.
1245 - * @param null $search_site Site search field value.
1246 - * @param string $orderBy Order list by. Default: URL.
1247 - *
1248 - * @return array|object|null Database query results or null on failer.
1249 - */
1250 - public function get_websites_by_user_id( $userid, $selectgroups = false, $search_site = null, $orderBy = 'wp.url' ) {
1251 - return $this->get_results_result( $this->get_sql_websites_by_user_id( $userid, $selectgroups, $search_site, $orderBy ) );
1252 - }
1253 -
1254 - /**
1255 - * Get child sites.
1256 - *
1257 - * @return string SQL string.
1258 - */
1259 - public function get_sql_websites() {
1260 - $where = $this->get_sql_where_allow_access_sites( 'wp' );
1261 -
1262 - $view_selects = '';
1263 - $view_joins = '';
1264 -
1265 - $opts_view = $this->get_wp_options_join();
1266 -
1267 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
1268 - $view_selects = ',' . $opts_view['selects'];
1269 - $view_joins = $opts_view['joins'];
1270 - }
1271 -
1272 - return 'SELECT wp.*,wp_sync.*' . $view_selects . '
1273 - FROM ' . $this->table_name( 'wp' ) . ' wp
1274 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1275 - ' . $view_joins . '
1276 - WHERE 1 ' . $where . ' ORDER BY wp.id';
1277 - }
1278 -
1279 - /**
1280 - * Get child sites by user id via SQL.
1281 - *
1282 - * @param int $userid Given user ID.
1283 - * @param bool $selectgroups Selected groups. Default: false.
1284 - * @param null $search_site Site search field value. Default: null.
1285 - * @param string $orderBy Order list by. Default: URL.
1286 - * @param bool $offset Query offset. Default: false.
1287 - * @param bool $rowcount Row count. Default: falese.
1288 - *
1289 - * @return object|null Return database query or null on failure.
1290 - *
1291 - * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
1292 - */
1293 - public function get_sql_websites_by_user_id( $userid, $selectgroups = false, $search_site = null, $orderBy = 'wp.url', $offset = false, $rowcount = false ) {
1294 - if ( MainWP_Utility::ctype_digit( $userid ) ) {
1295 - $where = '';
1296 - if ( null !== $search_site ) {
1297 - $search_site = trim( $search_site );
1298 - $where = ' AND (wp.name LIKE "%' . $search_site . '%" OR wp.url LIKE "%' . $search_site . '%") ';
1299 - }
1300 -
1301 - $where .= $this->get_sql_where_allow_access_sites( 'wp' );
1302 -
1303 - $view_selects = '';
1304 - $view_joins = '';
1305 -
1306 - $opts_view = $this->get_wp_options_join();
1307 -
1308 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
1309 - $view_selects = ',' . $opts_view['selects'];
1310 - $view_joins = $opts_view['joins'];
1311 - }
1312 -
1313 - if ( $selectgroups ) {
1314 - $qry = 'SELECT wp.*,wp_sync.*' . $view_selects . ', GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ",") as wpgroups, GROUP_CONCAT(gr.id ORDER BY gr.name SEPARATOR ",") as wpgroupids, GROUP_CONCAT(gr.color ORDER BY gr.name SEPARATOR ",") as wpgroups_colors
1315 - FROM ' . $this->table_name( 'wp' ) . ' wp
1316 - LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
1317 - LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
1318 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1319 - ' . $view_joins . '
680 + if ( $selectgroups ) {
681 + $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*, GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ", ") as wpgroups
682 + FROM ' . $this->tableName( 'wp' ) . ' wp
683 + LEFT JOIN ' . $this->tableName( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
684 + LEFT JOIN ' . $this->tableName( 'group' ) . ' gr ON wpgr.groupid = gr.id
685 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
686 + JOIN ' . $this->getOptionView() . ' wp_optionview ON wp.id = wp_optionview.wpid
1320 687 WHERE wp.userid = ' . $userid . "
1321 688 $where
1322 - GROUP BY wp.id, wp_sync.sync_id
689 + GROUP BY wp.id
1323 690 ORDER BY " . $orderBy;
1324 - } else {
1325 - $qry = 'SELECT wp.*,wp_sync.*' . $view_selects . '
1326 - FROM ' . $this->table_name( 'wp' ) . ' wp
1327 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1328 - ' . $view_joins . '
691 + } else {
692 + $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*
693 + FROM ' . $this->tableName( 'wp' ) . ' wp
694 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
695 + JOIN ' . $this->getOptionView() . ' wp_optionview ON wp.id = wp_optionview.wpid
1329 696 WHERE wp.userid = ' . $userid . "
1330 697 $where
1331 698 ORDER BY " . $orderBy;
1332 - }
699 + }
1333 700
1334 - if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
1335 - $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
1336 - } elseif ( false !== $rowcount ) {
1337 - $qry .= ' LIMIT ' . $rowcount;
1338 - }
701 + if ( ( $offset !== false ) && ( $rowcount !== false ) ) {
702 + $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
703 + }
1339 704
1340 - return $qry;
1341 - }
705 + return $qry;
706 + }
1342 707
1343 - return null;
1344 - }
708 + return null;
709 + }
1345 710
1346 - /**
1347 - * Get SQL to get child sites for current user.
1348 - *
1349 - * @param bool $selectgroups Selected groups. Default: false.
1350 - * @param null $search_site Site search field value. Default: null.
1351 - * @param string $orderBy Order list by. Default: URL.
1352 - * @param bool $offset Query offset. Default: false.
1353 - * @param bool $rowcount Row count. Default: false.
1354 - * @param null $extraWhere Extra WHERE. Default: null.
1355 - * @param bool $for_manager For role manager. Default: false.
1356 - * @param mixed $extra_view Extra view. Default favi_icon.
1357 - * @param string $is_staging yes|no Is child site a staging site.
1358 - * @param array $params other params.
1359 - *
1360 - * @return object|null Database query results or null on failure.
1361 - *
1362 - * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
1363 - */
1364 - public function get_sql_websites_for_current_user( // phpcs:ignore -- NOSONAR - complex.
1365 - $selectgroups = false,
1366 - $search_site = null,
1367 - $orderBy = 'wp.url',
1368 - $offset = false,
1369 - $rowcount = false,
1370 - $extraWhere = null,
1371 - $for_manager = false,
1372 - $extra_view = array( 'favi_icon' ),
1373 - $is_staging = 'no',
1374 - $params = array()
1375 - ) {
711 + public function getSQLWebsitesForCurrentUser( $selectgroups = false, $search_site = null, $orderBy = 'wp.url',
712 + $offset = false, $rowcount = false, $extraWhere = null, $for_manager = false,
713 + $extra_view = array( 'favi_icon' ), $is_staging = 'no' ) {
714 + $where = '';
715 + if ( MainWP_System::Instance()->isMultiUser() ) {
716 + global $current_user;
717 + $where .= ' AND wp.userid = ' . $current_user->ID . ' ';
718 + }
1376 719
1377 - /**
1378 - * The hook mainwp_get_sql_websites
1379 - *
1380 - * @since 5.5
1381 - */
1382 - $params = apply_filters( 'mainwp_get_sql_websites', $params, $selectgroups, $search_site, $orderBy, $offset, $rowcount, $extraWhere, $for_manager, $extra_view, $is_staging );
720 + if ( $search_site !== null ) {
721 + $search_site = trim( $search_site );
722 + $where .= ' AND (wp.name LIKE "%' . $search_site . '%" OR wp.url LIKE "%' . $search_site . '%") ';
723 + }
1383 724
1384 - $where = '';
1385 - if ( MainWP_System::instance()->is_multi_user() ) {
725 + if ( $extraWhere !== null ) {
726 + $where .= ' AND ' . $extraWhere;
727 + }
1386 728
1387 - /**
1388 - * Current user global.
1389 - *
1390 - * @global string
1391 - */
1392 - global $current_user;
729 + if ( !$for_manager ) {
730 + $where .= $this->getWhereAllowAccessSites( 'wp', $is_staging );
731 + }
1393 732
1394 - $where .= ' AND wp.userid = ' . $current_user->ID . ' ';
1395 - }
733 + if ( $orderBy == 'wp.url' ) {
734 + $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www', '')";
735 + }
1396 736
1397 - if ( null !== $search_site ) {
1398 - $search_site = trim( $search_site );
1399 - // Use esc_like() to escape LIKE wildcards (%, _) then prepare() for SQL safety.
1400 - $like_pattern = '%' . $this->wpdb->esc_like( $search_site ) . '%';
1401 - $where .= $this->wpdb->prepare(
1402 - ' AND (wp.name LIKE %s OR wp.url LIKE %s) ',
1403 - $like_pattern,
1404 - $like_pattern
1405 - );
1406 - }
1407 -
1408 - if ( ! empty( $extraWhere ) ) {
1409 - $where .= ' AND ' . $extraWhere . ' ';
1410 - }
1411 -
1412 - if ( ! $for_manager ) {
1413 - $where .= $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
1414 - }
1415 -
1416 - $connected_sql = '';
1417 -
1418 - if ( is_array( $params ) && isset( $params['connected'] ) && 'yes' === $params['connected'] ) {
1419 - $connected_sql = ' AND wp_sync.sync_errors = "" ';
1420 - } elseif ( is_array( $params ) && isset( $params['connected'] ) && 'no' === $params['connected'] ) {
1421 - $connected_sql = ' AND wp_sync.sync_errors <> "" ';
1422 - }
1423 -
1424 - $use_comp_subquery = false;
1425 -
1426 - $limit = '';
1427 - if ( $params && is_array( $params ) ) {
1428 - $s = isset( $params['s'] ) ? $params['s'] : '';
1429 - $exclude = isset( $params['exclude'] ) ? wp_parse_id_list( $params['exclude'] ) : array();
1430 - $include = isset( $params['include'] ) ? wp_parse_id_list( $params['include'] ) : array();
1431 - $status = isset( $params['status'] ) ? wp_parse_list( $params['status'] ) : array();
1432 - $page = isset( $params['page'] ) ? intval( $params['page'] ) : false;
1433 - $per_page = isset( $params['per_page'] ) ? intval( $params['per_page'] ) : false;
1434 -
1435 - // This parameter is used to enable caching in certain cases.
1436 - $_included_cache_ids = isset( $params['_included_cache_ids'] ) ? wp_parse_id_list( $params['_included_cache_ids'] ) : array();
1437 -
1438 - if ( ! empty( $s ) ) {
1439 - $s = trim( $s );
1440 - // Note: This SQL is executed via m_query() which bypasses wpdb, so we can't
1441 - // use wpdb->prepare() (its placeholders won't be resolved). Instead, escape
1442 - // LIKE wildcards and the value manually. First escape LIKE special chars,
1443 - // then SQL escape the result.
1444 - $like_value = '%' . $this->escape( $this->wpdb->esc_like( $s ) ) . '%';
1445 - $where .= " AND ( wp.id LIKE '{$like_value}' OR wp.name LIKE '{$like_value}' OR wp.url LIKE '{$like_value}' ) ";
1446 - }
1447 -
1448 - if ( ! empty( $exclude ) ) {
1449 - $where .= ' AND wp.id NOT IN (' . implode( ',', $exclude ) . ') ';
1450 - }
1451 -
1452 - if ( ! empty( $include ) ) {
1453 - $where .= ' AND wp.id IN (' . implode( ',', $include ) . ') ';
1454 - }
1455 -
1456 - if ( ! empty( $_included_cache_ids ) ) {
1457 - $where .= ' AND wp.id IN (' . implode( ',', $_included_cache_ids ) . ') ';
1458 - }
1459 -
1460 - // any, connected, disconnected, suspended, available_update.
1461 - if ( ! empty( $status ) && is_array( $status ) && ! in_array( 'any', $status ) ) {
1462 - $status_conds = array();
1463 - if ( in_array( 'available_update', $status ) ) {
1464 - $available_sql = " ( wp.plugin_upgrades <> '' && wp.plugin_upgrades <> '[]' ) OR ( wp.theme_upgrades <> '' && wp.theme_upgrades <> '[]' ) OR ( wp.translation_upgrades <> '' && wp.translation_upgrades <> '[]' ) OR ( wp.premium_upgrades <> '' && wp.premium_upgrades <> '[]' ) ";
1465 - $options_table = esc_sql( $this->table_name( 'wp_options' ) );
1466 - $results = $this->wpdb->get_results( "SELECT wpid FROM {$options_table} WHERE name = 'wp_upgrades' AND value <> '' AND value <> '[]'" );
1467 - if ( $results ) {
1468 - $wp_ids = array();
1469 - foreach ( $results as $item ) {
1470 - if ( ! empty( $item->wpid ) ) {
1471 - $wp_ids[] = $item->wpid;
1472 - }
1473 - }
1474 - $wp_ids = ! empty( $wp_ids ) ? array_unique( $wp_ids ) : array();
1475 - if ( ! empty( $wp_ids ) ) {
1476 - $available_sql .= ' OR wp.id IN ( ' . implode( ',', $wp_ids ) . ' )';
1477 - }
1478 - }
1479 - $status_conds[] = ' ( ' . $available_sql . ') ';
1480 - }
1481 -
1482 - if ( in_array( 'connected', $status ) ) {
1483 - $status_conds[] = ' ( wp_sync.sync_errors = "" ) ';
1484 - }
1485 - if ( in_array( 'disconnected', $status ) ) {
1486 - $status_conds[] = " wp_sync.sync_errors <> '' ";
1487 - }
1488 -
1489 - if ( in_array( 'suspended', $status ) ) {
1490 - $status_conds[] = ' wp.suspended = 1 ';
1491 - }
1492 -
1493 - if ( ! empty( $status_conds ) ) {
1494 - $where .= ' AND ( ' . implode( ' OR ', $status_conds ) . ' ) ';
1495 - }
1496 -
1497 - if ( in_array( 'unsuspended', $status ) && ! in_array( 'suspended', $status ) ) { // to sure not conflict the suspended status.
1498 - $where .= ' AND wp.suspended = 0 ';
1499 - }
1500 - }
1501 -
1502 - if ( ! empty( $page ) && ! empty( $per_page ) ) {
1503 - $limit = ( $page - 1 ) * $per_page . ',' . $per_page;
1504 - }
1505 - $use_comp_subquery = ! empty( $params['use_compatible_subquery'] ) ? true : false;
1506 - }
1507 -
1508 - if ( 'wp.url' === $orderBy ) {
1509 - $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '')";
1510 - }
1511 -
1512 - $view_selects = '';
1513 - $view_joins = '';
1514 -
1515 - if ( $use_comp_subquery ) {
1516 - $view_selects = ',wp_optionview.* ';
1517 - $view_joins = ' JOIN ' . $this->get_wp_options_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid ';
1518 - } else {
1519 - $opts_view = $this->get_wp_options_join( $extra_view );
1520 -
1521 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
1522 - $view_selects = ',' . $opts_view['selects'];
1523 - $view_joins = $opts_view['joins'];
1524 - }
1525 - }
1526 -
1527 - // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax.
1528 - if ( $selectgroups ) {
1529 - $qry = 'SELECT wp.*,wp_sync.*' . $view_selects . ', GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ",") as wpgroups, GROUP_CONCAT(gr.id ORDER BY gr.name SEPARATOR ",") as wpgroupids, GROUP_CONCAT(gr.color ORDER BY gr.name SEPARATOR ",") as wpgroups_colors,
1530 - wpclient.name as client_name
1531 - FROM ' . $this->table_name( 'wp' ) . ' wp
1532 - LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
1533 - LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
1534 - LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id
1535 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1536 - ' . $view_joins . '
1537 - WHERE 1 ' . $where . $connected_sql . '
1538 - GROUP BY wp.id, wp_sync.sync_id
737 + // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax
738 + if ( $selectgroups ) {
739 + $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*, GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ", ") as wpgroups
740 + FROM ' . $this->tableName( 'wp' ) . ' wp
741 + LEFT JOIN ' . $this->tableName( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
742 + LEFT JOIN ' . $this->tableName( 'group' ) . ' gr ON wpgr.groupid = gr.id
743 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
744 + JOIN ' . $this->getOptionView( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
745 + WHERE 1 ' . $where . '
746 + GROUP BY wp.id
1539 747 ORDER BY ' . $orderBy;
1540 - } else {
1541 - $qry = 'SELECT wp.*,wp_sync.*' . $view_selects . ', wpclient.name as client_name
1542 - FROM ' . $this->table_name( 'wp' ) . ' wp
1543 - LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id
1544 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1545 - ' . $view_joins . '
1546 - WHERE 1 ' . $where . $connected_sql . '
1547 - GROUP BY wp.id, wp_sync.sync_id
748 + } else {
749 + $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*
750 + FROM ' . $this->tableName( 'wp' ) . ' wp
751 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
752 + JOIN ' . $this->getOptionView( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
753 + WHERE 1 ' . $where . '
1548 754 ORDER BY ' . $orderBy;
1549 - }
755 + }
1550 756
1551 - if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
1552 - $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
1553 - } elseif ( false !== $rowcount ) {
1554 - $qry .= ' LIMIT ' . $rowcount;
1555 - } elseif ( ! empty( $limit ) ) {
1556 - $qry .= ' LIMIT ' . $limit;
1557 - } else {
1558 - // load all sites so check to support limit sites loading.
1559 - $limit_sites = ! empty( $params['limit_sites'] ) ? intval( $params['limit_sites'] ) : 0;
1560 - if ( ! empty( $limit_sites ) ) {
1561 - $current_page = (int) get_option( 'mainwp_manage_updates_limit_current_page', 0 );
1562 - $current_page = $current_page > 0 ? $current_page - 1 : 0;
1563 - $start = $current_page * $limit_sites;
1564 - $qry .= ' LIMIT ' . intval( $start ) . ', ' . intval( $limit_sites );
1565 - }
1566 - }
757 + if ( ( $offset !== false ) && ( $rowcount !== false ) ) {
758 + $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
759 + }
1567 760
1568 - if ( ! empty( $_included_cache_ids ) ) {
1569 - MainWP_Logger::instance()->log_events( 'cache-metrics', sprintf( '[sql websites=%s]', $qry ) );
1570 - }
1571 - MainWP_Logger::instance()->log_events( 'db-queries', sprintf( '[sql websites=%s]', $qry ) );
761 + return $qry;
762 + }
1572 763
1573 - return $qry;
1574 - }
764 + public function getSQLSearchWebsitesForCurrentUser( $params ) {
1575 765
1576 -
1577 - /**
1578 - * Get SQL to get wp child sites for current user.
1579 - *
1580 - * @since 4.3
1581 - *
1582 - * @param array $params params .
1583 - *
1584 - * @return object|null Database query results or null on failure.
1585 - */
1586 - public function get_sql_wp_for_current_user( $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
1587 - if ( ! is_array( $params ) ) {
766 + if ( !is_array($params) )
1588 767 $params = array();
1589 - }
1590 768
1591 - $selectgroups = ! empty( $params['select_groups'] ) ? true : false;
1592 - $search_site = isset( $params['search_site'] ) && ! empty( $params['search_site'] ) ? $params['search_site'] : null;
1593 - $orderBy = isset( $params['order_by'] ) && ! empty( $params['order_by'] ) ? $params['order_by'] : 'wp.url';
1594 - $offset = isset( $params['offset'] ) ? $params['offset'] : false;
1595 - $rowcount = isset( $params['row_count'] ) ? $params['row_count'] : false;
1596 - $for_manager = isset( $params['for_manager'] ) ? $params['for_manager'] : false;
1597 - $extraWhere = isset( $params['extra_where'] ) && ! empty( $params['extra_where'] ) ? $params['extra_where'] : null;
1598 - $extra_view = isset( $params['extra_view'] ) && is_array( $params['extra_view'] ) && ! empty( $params['extra_view'] ) ? $params['extra_view'] : array( 'favi_icon' );
1599 - $extra_join = isset( $params['extra_join'] ) ? $params['extra_join'] : '';
1600 - $use_comp_subquery = ! empty( $params['use_compatible_subquery'] ) ? true : false;
769 + $selectgroups = isset($params['selectgroups']) && $params['selectgroups'] ? true : false;
770 + $search_site = isset($params['search']) ? $this->escape(trim($params['search'])) : null;
771 + $orderBy = isset($params['orderby']) ? $params['orderby'] : 'wp.url';
772 + $offset = isset($params['offset']) ? intval($params['offset']) : false;
773 + $rowcount = isset($params['rowcount']) ? intval($params['rowcount']) : false;
774 + $extraWhere = isset($params['extra_where']) ? $params['extra_where'] : null;
775 + $for_manager = isset($params['for_manager']) && $params['for_manager'] ? true : false;
776 + $extra_view = isset($params['extra_view']) ? $params['extra_view'] : array( 'favi_icon' ) ;
777 + $is_staging = isset($params['is_staging']) && $params['is_staging'] == 'yes' ? 'yes' : 'no' ;
1601 778
1602 - $extra_select_wp_fields = isset( $params['extra_select_wp_fields'] ) && is_array( $params['extra_select_wp_fields'] ) && ! empty( $params['extra_select_wp_fields'] ) ? $params['extra_select_wp_fields'] : array();
1603 - $extra_select_sql_fields = isset( $params['extra_select_sql_fields'] ) && ! empty( $params['extra_select_sql_fields'] ) ? $params['extra_select_sql_fields'] : '';
779 + $group_id = isset($params['group_id']) && $params['group_id'] ? intval($params['group_id']) : false;
1604 780
1605 - $is_staging = isset( $params['is_staging'] ) && 'yes' === $params['is_staging'] ? 'yes' : 'no';
1606 - $count_only = isset( $params['count_only'] ) && $params['count_only'] ? true : false;
781 + if ( $selectgroups ) {
782 + if ( $staging_group = get_option( 'mainwp_stagingsites_group_id' ) ) {
783 + if ( $group_id == $staging_group ) {
784 + $is_staging = 'yes'; // will list staging sites
785 + }
786 + }
787 + }
1607 788
1608 - $where = '';
789 + $where = '';
790 + if ( MainWP_System::Instance()->isMultiUser() ) {
791 + global $current_user;
792 + $where .= ' AND wp.userid = ' . $current_user->ID . ' ';
793 + }
1609 794
1610 - if ( null !== $search_site ) {
1611 - $search_site = trim( $search_site );
1612 - // Use esc_like() to escape LIKE wildcards (%, _) then prepare() for SQL safety.
1613 - $like_pattern = '%' . $this->wpdb->esc_like( $search_site ) . '%';
1614 - $where .= $this->wpdb->prepare(
1615 - ' AND (wp.name LIKE %s OR wp.url LIKE %s) ',
1616 - $like_pattern,
1617 - $like_pattern
1618 - );
1619 - }
795 + // for searching
796 + if ( $search_site !== null && $search_site != '' ) {
797 + $where .= ' AND (wp.name LIKE "%' . $search_site . '%" OR wp.url LIKE "%' . $search_site . '%") ';
798 + }
1620 799
1621 - if ( null !== $extraWhere ) {
1622 - $where .= ' AND ' . $extraWhere;
1623 - }
800 + if ( $extraWhere !== null ) {
801 + $where .= ' AND ' . $extraWhere;
802 + }
1624 803
1625 - if ( ! $for_manager ) {
1626 - $where .= $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
1627 - }
804 + if ( ! $for_manager ) {
805 + $where .= $this->getWhereAllowAccessSites( 'wp', $is_staging );
806 + }
1628 807
1629 - if ( 'wp.url' === $orderBy ) {
1630 - $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '')";
1631 - }
808 + if ( $orderBy == 'wp.url' ) {
809 + $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www', '')";
810 + }
1632 811
1633 - $select_wp_fields = $this->get_sql_select_wp_valid_fields( $extra_select_wp_fields );
812 + $join_group = "";
813 + $where_group = "";
1634 814
1635 - if ( ! empty( $extra_select_sql_fields ) ) {
1636 - $extra_select_sql_fields = ',' . $extra_select_sql_fields;
1637 - }
815 + if ( MainWP_Utility::ctype_digit( $group_id ) && $group_id > 0 ) {
816 + $join_group = " JOIN " . $this->tableName( 'wp_group' ) . " wpgroup ON wp.id = wpgroup.wpid ";
817 + $where_group = " AND wpgroup.groupid = " . $group_id;
818 + }
1638 819
1639 - $view_selects = '';
1640 - $view_joins = '';
820 + // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax
821 + if ( $selectgroups ) {
822 + $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*, GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ", ") as wpgroups
823 + FROM ' . $this->tableName( 'wp' ) . ' wp ' .
824 + $join_group . '
825 + LEFT JOIN ' . $this->tableName( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
826 + LEFT JOIN ' . $this->tableName( 'group' ) . ' gr ON wpgr.groupid = gr.id
827 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
828 + JOIN ' . $this->getOptionView( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
829 + WHERE 1 ' . $where . $where_group . '
830 + GROUP BY wp.id
831 + ORDER BY ' . $orderBy;
832 + } else {
833 + $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*
834 + FROM ' . $this->tableName( 'wp' ) . ' wp ' .
835 + $join_group . '
836 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
837 + JOIN ' . $this->getOptionView( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
838 + WHERE 1 ' . $where . $where_group . '
839 + ORDER BY ' . $orderBy;
840 + }
1641 841
1642 - if ( $use_comp_subquery ) {
1643 - $view_selects = ',wp_optionview.* ';
1644 - $view_joins = ' JOIN ' . $this->get_wp_options_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid ';
1645 - } else {
1646 - $opts_view = $this->get_wp_options_join( $extra_view );
1647 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
1648 - $view_selects = ',' . $opts_view['selects'];
1649 - $view_joins = $opts_view['joins'];
1650 - }
1651 - }
842 + if ( ( $offset !== false ) && ( $rowcount !== false ) ) {
843 + $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
844 + }
1652 845
1653 - // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax.
1654 - if ( $selectgroups ) {
1655 - if ( $count_only ) {
1656 - $select = ' COUNT(DISTINCT(wp.id)) ';
1657 - } else {
1658 - $select = $select_wp_fields . '
1659 - ' . $extra_select_sql_fields . '
1660 - ,wp_sync.sync_errors' . $view_selects . ', GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ",") as wpgroups, GROUP_CONCAT(gr.id ORDER BY gr.name SEPARATOR ",") as wpgroupids, GROUP_CONCAT(gr.color ORDER BY gr.name SEPARATOR ",") as wpgroups_colors, wpclient.name as client_name ';
1661 - }
1662 - $qry = 'SELECT ' . $select . '
1663 - FROM ' . $this->table_name( 'wp' ) . ' wp
1664 - LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
1665 - LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
1666 - LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id
1667 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1668 - ' . $view_joins . '
1669 - ' . $extra_join . '
1670 - WHERE 1 ' . $where;
1671 - if ( ! $count_only ) {
1672 - $qry .= ' GROUP BY wp.id, wp_sync.sync_id';
1673 - }
1674 - $qry .= ' ORDER BY ' . $orderBy;
1675 - } else {
1676 - if ( $count_only ) {
1677 - $select = ' COUNT(DISTINCT(wp.id)) ';
1678 - } else {
1679 - $select = $select_wp_fields . '
1680 - ' . $extra_select_sql_fields . '
1681 - ,wp_sync.sync_errors' . $view_selects . ', wpclient.name as client_name ';
1682 - }
1683 - $qry = 'SELECT ' . $select . '
1684 - FROM ' . $this->table_name( 'wp' ) . ' wp
1685 - LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id
1686 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1687 - ' . $view_joins . '
1688 - ' . $extra_join . '
1689 - WHERE 1 ' . $where;
1690 - if ( ! $count_only ) {
1691 - $qry .= ' GROUP BY wp.id, wp_sync.sync_id';
1692 - }
1693 - $qry .= ' ORDER BY ' . $orderBy;
1694 - }
846 + return $qry;
847 + }
1695 848
1696 - if ( ! $count_only ) {
1697 - if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
1698 - $qry .= ' LIMIT ' . intval( $offset ) . ', ' . intval( $rowcount );
1699 - } elseif ( false !== $rowcount ) {
1700 - $qry .= ' LIMIT ' . intval( $rowcount );
1701 - }
1702 - }
1703 - return $qry;
1704 - }
1705 - /**
1706 - * Get SQL select websites fields.
1707 - *
1708 - * @since 4.3
1709 - *
1710 - * @param array $other_fields extra select wp fields .
1711 - *
1712 - * @return string sql string.
1713 - */
1714 - public function get_sql_select_wp_valid_fields( $other_fields = array() ) {
1715 849
1716 - $allow_other_fields = array(
1717 - 'offline_checks_last',
1718 - 'offline_check_result', // 1 - online, -1 offline.
1719 - 'http_response_code',
1720 - 'disable_health_check',
1721 - 'health_threshold',
1722 - 'note',
1723 - 'statsUpdate',
1724 - 'directories',
1725 - 'plugin_upgrades',
1726 - 'theme_upgrades',
1727 - 'translation_upgrades',
1728 - 'premium_upgrades',
1729 - 'securityIssues',
1730 - 'themes',
1731 - 'ignored_themes',
1732 - 'plugins',
1733 - 'ignored_plugins',
1734 - 'users',
1735 - 'categories',
1736 - 'pluginDir',
1737 - 'automatic_update',
1738 - 'backup_before_upgrade',
1739 - 'mainwpdir',
1740 - 'is_ignoreCoreUpdates',
1741 - 'is_ignorePluginUpdates',
1742 - 'is_ignoreThemeUpdates',
1743 - 'verify_certificate',
1744 - 'force_use_ipv4',
1745 - 'ssl_version',
1746 - 'http_user',
1747 - 'http_pass',
1748 - 'wpe',
1749 - 'is_staging',
1750 - 'client_id',
1751 - );
850 + public function getWhereAllowAccessSites( $site_table_alias = '', $is_staging = 'no' ) {
1752 851
1753 - $default_fields = array( 'id', 'url', 'name', 'adminname', 'verify_certificate', 'ssl_version', 'http_user', 'http_pass', 'suspended' );
852 + if ( empty( $site_table_alias ) ) {
853 + $site_table_alias = $this->tableName( 'wp' );
854 + }
1754 855
1755 - $select = ' ';
856 + // check to filter the staging sites
857 + $where_staging = ' AND ' . $site_table_alias . '.is_staging = 0 ';
858 + if ( $is_staging == 'no' ) {
859 + $where_staging = ' AND ' . $site_table_alias . '.is_staging = 0 ';
860 + } else if ( $is_staging == 'yes' ) {
861 + $where_staging = ' AND ' . $site_table_alias . '.is_staging = 1 ';
862 + } else if ( $is_staging == 'nocheckstaging' ) {
863 + $where_staging = '';
864 + }
865 + // end staging filter
1756 866
1757 - foreach ( $default_fields as $field ) {
1758 - $select .= 'wp.' . $this->escape( $field ) . ',';
1759 - }
1760 - foreach ( $other_fields as $field ) {
1761 - if ( ! in_array( $field, $allow_other_fields ) ) {
1762 - continue;
1763 - }
1764 - if ( in_array( $field, $default_fields ) ) {
1765 - continue;
1766 - }
1767 - $select .= 'wp.' . $this->escape( $field ) . ',';
1768 - }
1769 - $select = rtrim( $select, ',' );
1770 - return $select;
1771 - }
867 + $_where = $where_staging;
868 + // To fix bug run from cron job
869 + if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
870 + return $_where;
871 + }
1772 872
1773 - /**
1774 - * Get child sites for current user.
1775 - *
1776 - * @param array $params to get sites. Default: array().
1777 - *
1778 - * @return array Results or null on failure.
1779 - *
1780 - * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
1781 - */
1782 - public function get_websites_for_current_user( $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
1783 - if ( ! is_array( $params ) ) {
1784 - $params = array();
1785 - }
873 + // To fix bug run from wp cli
874 + if ( defined( 'WP_CLI' ) && WP_CLI ) {
875 + return $_where;
876 + }
1786 877
1787 - $selectgroups = isset( $params['selectgroups'] ) ? $params['selectgroups'] : false;
1788 - $search_site = isset( $params['search_site'] ) ? $params['search_site'] : null;
1789 - $orderBy = isset( $params['order_by'] ) ? $params['order_by'] : 'wp.url';
1790 - $offset = isset( $params['offset'] ) ? $params['offset'] : false;
1791 - $rowcount = isset( $params['rowcount'] ) ? $params['rowcount'] : false;
1792 - $extraWhere = isset( $params['where'] ) ? $params['where'] : null;
1793 - $extra_view = isset( $params['extra_view'] ) && is_array( $params['extra_view'] ) ? $params['extra_view'] : array( 'favi_icon' );
1794 - $is_staging = isset( $params['is_staging'] ) ? $params['is_staging'] : 'no';
1795 - $full_data = isset( $params['full_data'] ) && $params['full_data'] && ( 'no' !== $params['full_data'] ) ? true : false;
1796 - $select_data = isset( $params['select_data'] ) && is_array( $params['select_data'] ) ? $params['select_data'] : false;
1797 - $format = isset( $params['format'] ) ? $params['format'] : '';
1798 - $clients = isset( $params['client'] ) ? $params['client'] : '';
1799 - $fields = isset( $params['fields'] ) && is_array( $params['fields'] ) ? $params['fields'] : array();
878 + $allowed_sites = apply_filters( 'mainwp_currentuserallowedaccesssites', 'all' );
1800 879
1801 - $for_manager = isset( $params['no_perm_check'] ) && true === $params['no_perm_check'];
880 + if ( $allowed_sites == 'all' ) {
881 + return $_where; // allow access all sites
882 + }
1802 883
1803 - $urlsWhere = '';
1804 884
1805 - if ( isset( $params['urls'] ) && ! empty( $params['urls'] ) ) {
1806 - $urls = explode( ';', $params['urls'] );
1807 - foreach ( $urls as $url ) {
1808 - $url = str_replace( array( 'https://www.', 'http://www.', 'https://', 'http://', 'www.' ), array( '', '', '', '', '' ), $url );
1809 - if ( '/' !== substr( $url, - 1 ) ) {
1810 - $url .= '/';
1811 - }
1812 - $urlsWhere .= '"' . $this->escape( $url ) . '", ';
1813 - }
1814 - $urlsWhere = rtrim( $urlsWhere, ', ' );
1815 - }
885 + if ( is_array( $allowed_sites ) && count( $allowed_sites ) > 0 ) {
886 + $_where .= ' AND ' . $site_table_alias . '.id IN (' . implode( ',', $allowed_sites ) . ') ';
887 + } else {
888 + $_where .= ' AND 0 '; // denied access
889 + }
1816 890
1817 - if ( ! empty( $urlsWhere ) ) {
1818 - $urlsWhere = " ( replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '') IN ( " . $urlsWhere . ') ) ';
891 + return $_where;
892 + }
1819 893
1820 - if ( empty( $extraWhere ) ) {
1821 - $extraWhere = $urlsWhere;
1822 - } else {
1823 - $extraWhere = $extraWhere . ' AND ' . $urlsWhere;
1824 - }
1825 - }
894 + public function getWhereAllowGroups( $group_table_alias = '', $with_staging = 'no' ) {
895 + // To fix bug run from cron job
896 + if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
897 + return '';
898 + }
1826 899
1827 - $clientWhere = '';
1828 - if ( ! empty( $clients ) ) {
1829 - $clients = explode( ';', $clients );
1830 - foreach ( $clients as $client ) {
1831 - if ( is_numeric( $client ) ) {
1832 - $clientWhere .= intval( $client ) . ', ';
1833 - }
1834 - }
1835 - $clientWhere = rtrim( $clientWhere, ', ' );
1836 - }
900 + if ( empty( $group_table_alias ) ) {
901 + $group_table_alias = $this->tableName( 'group' );
902 + }
1837 903
1838 - if ( ! empty( $clientWhere ) ) {
1839 - $clientWhere = ' ( wp.client_id IN ( ' . $clientWhere . ') ) ';
1840 - if ( empty( $extraWhere ) ) {
1841 - $extraWhere = $clientWhere;
1842 - } else {
1843 - $extraWhere = $extraWhere . ' AND ' . $clientWhere;
1844 - }
1845 - }
904 + // check to filter the staging group
905 + $where_staging_group = '';
906 + $staging_group = get_option( 'mainwp_stagingsites_group_id' );
907 + if ( $staging_group ) {
908 + $where_staging_group = ' AND ' . $group_table_alias . '.id <> ' . $staging_group . ' '; // filter the staging group
909 + if ( $with_staging == 'yes' ) {
910 + $where_staging_group = ''; // will do not the filter staging group
911 + }
912 + }
913 + // end staging filter
1846 914
1847 - $args = array(
1848 - 's' => isset( $params['s'] ) ? $params['s'] : '',
1849 - 'exclude' => isset( $params['exclude'] ) && ! empty( $params['exclude'] ) ? wp_parse_id_list( $params['exclude'] ) : array(),
1850 - 'include' => isset( $params['include'] ) && ! empty( $params['include'] ) ? wp_parse_id_list( $params['include'] ) : array(),
1851 - 'status' => isset( $params['status'] ) && ! empty( $params['status'] ) ? wp_parse_list( $params['status'] ) : '',
1852 - 'page' => isset( $params['paged'] ) ? intval( $params['paged'] ) : false,
1853 - 'per_page' => isset( $params['items_per_page'] ) ? intval( $params['items_per_page'] ) : false,
1854 - );
915 + $_where = $where_staging_group;
1855 916
1856 - $data = array( 'id', 'url', 'name', 'client_id' );
917 + $allowed_groups = apply_filters( 'mainwp_currentuserallowedaccessgroups', 'all' );
1857 918
1858 - if ( $full_data ) {
1859 - $data = array(
1860 - 'id',
1861 - 'url',
1862 - 'name',
1863 - 'offline_checks_last',
1864 - 'offline_check_result', // 1 - online, -1 offline.
1865 - 'http_response_code',
1866 - 'disable_health_check',
1867 - 'health_threshold',
1868 - 'note',
1869 - 'dbsize',
1870 - 'plugin_upgrades',
1871 - 'theme_upgrades',
1872 - 'translation_upgrades',
1873 - 'securityIssues',
1874 - 'themes',
1875 - 'plugins',
1876 - 'automatic_update',
1877 - 'sync_errors',
1878 - 'dtsAutomaticSync',
1879 - 'dtsAutomaticSyncStart',
1880 - 'dtsSync',
1881 - 'dtsSyncStart',
1882 - 'last_post_gmt',
1883 - 'health_value',
1884 - 'phpversion',
1885 - 'wp_upgrades',
1886 - 'security_stats',
1887 - 'client_id',
1888 - 'adminname',
1889 - 'privkey',
1890 - 'http_user',
1891 - 'http_pass',
1892 - 'ssl_version',
1893 - 'signature_algo',
1894 - 'verify_method',
1895 - 'verify_certificate',
1896 - 'suspended',
1897 - );
919 + if ( $allowed_groups == 'all' ) {
920 + return $_where;
921 + } // allow all groups
1898 922
1899 - if ( ! in_array( 'security_stats', $extra_view ) ) {
1900 - $extra_view[] = 'security_stats';
1901 - }
1902 - }
1903 923
1904 - if ( ! empty( $select_data ) && is_array( $select_data ) ) {
1905 - $data = $select_data;
1906 - }
924 + if ( is_array( $allowed_groups ) && count( $allowed_groups ) > 0 ) {
925 + return ' AND ' . $group_table_alias . '.id IN (' . implode( ',', $allowed_groups ) . ') ' . $_where;
926 + } else {
927 + return ' AND 0 '; // not allow access groups
928 + }
929 + }
1907 930
1908 - if ( $selectgroups ) {
1909 - $data[] = 'wpgroups';
1910 - $data[] = 'wpgroupids';
1911 - }
931 + public function getGroupByNameForUser( $name, $userid = null ) {
932 + if ( ( $userid == null ) && MainWP_System::Instance()->isMultiUser() ) {
933 + global $current_user;
934 + $userid = $current_user->ID;
935 + }
936 + $where = ( $userid != null ) ? ' AND userid=' . $userid : '';
937 + $where .= $this->getWhereAllowGroups();
1912 938
1913 - if ( ! empty( $fields ) ) {
1914 - $data = array_unique( array_merge( $fields, $data ) ); // to prevent difference fields name.
1915 - }
939 + return $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'group' ) . ' WHERE 1 ' . $where . ' AND name="' . $this->escape( $name ) . '"' );
940 + }
1916 941
1917 - $dbwebsites = array();
942 + public function getGroupById( $id ) {
943 + if ( MainWP_Utility::ctype_digit( $id ) ) {
944 + return $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'group' ) . ' WHERE id=' . $id );
945 + }
1918 946
1919 - $sql = $this->get_sql_websites_for_current_user( $selectgroups, $search_site, $orderBy, $offset, $rowcount, $extraWhere, $for_manager, $extra_view, $is_staging, $args );
1920 - $websites = $this->query( $sql );
947 + return null;
948 + }
1921 949
1922 - while ( $websites && ( $website = static::fetch_object( $websites ) ) ) {
950 + public function getGroupsByUserId( $userid ) {
951 + if ( MainWP_Utility::ctype_digit( $userid ) ) {
952 + $where = $this->getWhereAllowGroups();
1923 953
1924 - $obj_data = MainWP_Utility::map_site( $website, $data );
954 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'group' ) . ' WHERE userid = ' . $userid . $where . ' ORDER BY name', OBJECT_K );
955 + }
1925 956
1926 - if ( $full_data ) {
1927 - $sum_upgrades = 0;
1928 - if ( '' !== $obj_data->plugin_upgrades ) {
1929 - $plugin_upgrades = json_decode( $obj_data->plugin_upgrades, true );
1930 - if ( is_array( $plugin_upgrades ) ) {
1931 - $sum_upgrades += count( $plugin_upgrades );
1932 - }
1933 - }
957 + return null;
958 + }
1934 959
1935 - if ( '' !== $obj_data->theme_upgrades ) {
1936 - $theme_upgrades = json_decode( $obj_data->theme_upgrades, true );
1937 - if ( is_array( $theme_upgrades ) ) {
1938 - $sum_upgrades += count( $theme_upgrades );
1939 - }
1940 - }
960 + public function getGroupsForManageSites() {
961 + $where = ' 1 ';
962 + if ( MainWP_System::Instance()->isMultiUser() ) {
963 + global $current_user;
964 + $where = ' userid = ' . $current_user->ID . ' ';
965 + }
966 + $with_staging = 'yes';
967 + $staging_enabled = apply_filters('mainwp-extension-available-check', 'mainwp-staging-extension') || apply_filters('mainwp-extension-available-check', 'mainwp-timecapsule-extension');
1941 968
1942 - if ( '' !== $obj_data->wp_upgrades ) {
1943 - $wp_upgrades = json_decode( $obj_data->wp_upgrades, true );
1944 - if ( is_array( $wp_upgrades ) ) {
1945 - $sum_upgrades += count( $wp_upgrades );
1946 - }
1947 - }
1948 - $obj_data->sum_of_upgrades = $sum_upgrades;
1949 - }
1950 -
1951 - if ( 'array' === $format ) {
1952 - $dbwebsites[] = $obj_data;
1953 - } else {
1954 - $dbwebsites[ $website->id ] = $obj_data;
1955 - }
969 + if ( !$staging_enabled ) {
970 + $with_staging = 'no';
1956 971 }
1957 - static::free_result( $websites );
1958 - return $dbwebsites;
1959 - }
1960 972
1961 - /**
1962 - * Get count of child sites for the current user with filters.
1963 - *
1964 - * This method is optimized for the Abilities API to return site counts
1965 - * with filtering support for status, tags (groups), and client_id.
1966 - *
1967 - * IMPORTANT: This method is intended ONLY for Abilities API consumers.
1968 - * For legacy UI code paths (e.g., admin dashboard widgets, site count displays),
1969 - * use get_websites_count() instead. The two methods serve different purposes:
1970 - * - get_websites_count(): Simple total count for UI display (cached, no filters)
1971 - * - get_websites_count_for_current_user(): Filtered count for API pagination
1972 - *
1973 - * @since 5.3
1974 - *
1975 - * @param array $params Filter parameters:
1976 - * - status (string): 'connected', 'disconnected', 'suspended'
1977 - * - tags (array): Array of tag/group IDs to filter by
1978 - * - client_id (int): Client ID to filter by.
1979 - *
1980 - * @return int Count of sites matching the filters.
1981 - */
1982 - public function get_websites_count_for_current_user( $params = array() ) { //phpcs:ignore -- NOSONAR - complex.
973 + $where .= $this->getWhereAllowGroups('' , $with_staging );
974 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'group' ) . ' WHERE ' . $where . ' ORDER BY name', OBJECT_K );
975 + }
1983 976
1984 - if ( ! is_array( $params ) ) {
1985 - $params = array();
1986 - }
977 + public function getGroupsForCurrentUser() {
978 + $where = ' 1 ';
979 + if ( MainWP_System::Instance()->isMultiUser() ) {
980 + global $current_user;
981 + $where = ' userid = ' . $current_user->ID . ' ';
982 + }
983 + $where .= $this->getWhereAllowGroups();
1987 984
1988 - $status = isset( $params['status'] ) ? $params['status'] : '';
1989 - $tags = isset( $params['tags'] ) && is_array( $params['tags'] ) ? $params['tags'] : array();
1990 - $client_id = isset( $params['client_id'] ) ? intval( $params['client_id'] ) : 0;
1991 - $s = isset( $params['s'] ) ? $params['s'] : '';
985 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'group' ) . ' WHERE ' . $where . ' ORDER BY name', OBJECT_K );
986 + }
1992 987
1993 - // Validate status value (defense-in-depth for direct callers outside Abilities API).
1994 - $valid_statuses = array( 'connected', 'disconnected', 'suspended', '' );
1995 - if ( ! in_array( $status, $valid_statuses, true ) ) {
1996 - $status = '';
1997 - }
988 + public function getGroupsByWebsiteId( $websiteid ) {
989 + if ( MainWP_Utility::ctype_digit( $websiteid ) ) {
990 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'group' ) . ' gr
991 + JOIN ' . $this->tableName( 'wp_group' ) . ' wpgr ON gr.id = wpgr.groupid
992 + WHERE wpgr.wpid = ' . $websiteid . ' ORDER BY name', OBJECT_K );
993 + }
1998 994
1999 - $where = '';
2000 - $sql_params = array();
995 + return null;
996 + }
2001 997
2002 - // Multi-user support: filter by current user.
2003 - if ( MainWP_System::instance()->is_multi_user() ) {
2004 - global $current_user;
2005 - $where .= ' AND wp.userid = %d ';
2006 - $sql_params[] = (int) $current_user->ID;
2007 - }
998 + public function getGroupsAndCount( $userid = null, $for_manager = false ) {
999 + if ( ( $userid == null ) && MainWP_System::Instance()->isMultiUser() ) {
1000 + global $current_user;
1001 + $userid = $current_user->ID;
1002 + }
2008 1003
2009 - // Access control for sites.
2010 - $where .= $this->get_sql_where_allow_access_sites( 'wp', 'no' );
1004 + $where = '';
2011 1005
2012 - // Status filtering: connected, disconnected, suspended.
2013 - if ( ! empty( $status ) ) {
2014 - switch ( $status ) {
2015 - case 'connected':
2016 - $where .= ' AND wp_sync.sync_errors = "" AND wp.suspended = 0 ';
2017 - break;
2018 - case 'disconnected':
2019 - $where .= ' AND wp_sync.sync_errors <> "" ';
2020 - break;
2021 - case 'suspended':
2022 - $where .= ' AND wp.suspended = 1 ';
2023 - break;
2024 - default:
2025 - // No additional filtering.
2026 - break;
2027 - }
2028 - }
1006 + if ( $userid != null ) {
1007 + $where = ' AND gr.userid = ' . $userid;
1008 + }
2029 1009
2030 - // Client ID filtering.
2031 - if ( ! empty( $client_id ) ) {
2032 - $where .= ' AND wp.client_id = %d ';
2033 - $sql_params[] = (int) $client_id;
2034 - }
1010 + if ( !$for_manager ) {
1011 + $where .= $this->getWhereAllowGroups( 'gr' );
1012 + }
2035 1013
2036 - // Search filtering.
2037 - if ( ! empty( $s ) ) {
2038 - $s = trim( $s );
2039 - $like_pattern = '%' . $this->wpdb->esc_like( $s ) . '%';
2040 - $where .= $this->wpdb->prepare(
2041 - ' AND ( wp.id LIKE %s OR wp.name LIKE %s OR wp.url LIKE %s ) ',
2042 - $like_pattern,
2043 - $like_pattern,
2044 - $like_pattern
2045 - );
2046 - }
1014 + return $this->wpdb->get_results( 'SELECT gr.*, COUNT(DISTINCT(wpgr.wpid)) as nrsites
1015 + FROM ' . $this->tableName( 'group' ) . ' gr
1016 + LEFT JOIN ' . $this->tableName( 'wp_group' ) . ' wpgr ON gr.id = wpgr.groupid
1017 + WHERE 1 ' . $where . '
1018 + GROUP BY gr.id
1019 + ORDER BY gr.name', OBJECT_K );
1020 + }
2047 1021
2048 - // Tags (groups) filtering.
2049 - $join_group = '';
2050 - if ( ! empty( $tags ) ) {
2051 - $tags = array_map( 'intval', $tags );
2052 - $tags = array_filter(
2053 - $tags,
2054 - function ( $id ) {
2055 - return $id > 0;
2056 - }
2057 - );
2058 - if ( ! empty( $tags ) ) {
2059 - $join_group = ' JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid ';
2060 - $placeholders = implode( ', ', array_fill( 0, count( $tags ), '%d' ) );
2061 - $where .= " AND wpgroup.groupid IN ( $placeholders ) ";
2062 - $sql_params = array_merge( $sql_params, $tags );
2063 - }
2064 - }
1022 + public function getGroupsByName( $name ) {
1023 + return $this->wpdb->get_results( 'SELECT gr.*
1024 + FROM ' . $this->tableName( 'group' ) . ' gr
1025 + WHERE gr.name = "' . $this->escape( $name ) . '"'
1026 + , OBJECT_K );
1027 + }
2065 1028
2066 - $qry = 'SELECT COUNT(DISTINCT wp.id) FROM ' . $this->table_name( 'wp' ) . ' wp ' .
2067 - 'JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid ' .
2068 - $join_group .
2069 - 'WHERE 1 ' . $where;
1029 + public function getNotEmptyGroups( $userid = null, $enableOfflineSites = true ) {
1030 + if ( ( $userid == null ) && MainWP_System::Instance()->isMultiUser() ) {
1031 + global $current_user;
1032 + $userid = $current_user->ID;
1033 + }
2070 1034
2071 - // Only call prepare() when we have placeholders.
2072 - $result = $sql_params
2073 - ? $this->wpdb->get_var( $this->wpdb->prepare( $qry, $sql_params ) ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- We have already prepared the query with the parameters.
2074 - : $this->wpdb->get_var( $qry ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- We have already prepared the query with the parameters.
1035 + $where = ' WHERE 1 ';
1036 + $where .= $this->getWhereAllowGroups( 'g' );
2075 1037
2076 - return (int) $result;
2077 - }
1038 + if ( $userid != null ) {
1039 + $where .= ' AND g.userid = ' . $userid;
1040 + }
1041 + if ( !$enableOfflineSites ) {
1042 + $where .= ' AND wp_sync.sync_errors = ""';
1043 + }
2078 1044
2079 - /**
2080 - * Get the child sites the current user has searched for.
2081 - *
2082 - * @param array $params Query parameters.
2083 - *
2084 - * @return boolean|null $qry Database query results or null on failure.
2085 - *
2086 - * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
2087 - */
2088 - public function get_sql_search_websites_for_current_user( $params ) { // phpcs:ignore -- NOSONAR - complex.
1045 + return $this->wpdb->get_results( 'SELECT DISTINCT(g.id), g.name, count(wp.wpid)
1046 + FROM ' . $this->tableName( 'group' ) . ' g
1047 + JOIN ' . $this->tableName( 'wp_group' ) . ' wp ON g.id = wp.groupid
1048 + JOIN ' . $this->tableName( 'wp' ) . ' wpsite ON wp.wpid = wpsite.id
1049 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.wpid = wp_sync.wpid
1050 + ' . $where . '
1051 + GROUP BY g.id
1052 + HAVING count(wp.wpid) > 0
1053 + ORDER BY g.name', OBJECT_K );
1054 + }
2089 1055
2090 - if ( ! is_array( $params ) ) {
2091 - $params = array();
2092 - }
1056 + public function getWebsitesByUrl( $url ) {
1057 + if ( substr( $url, - 1 ) != '/' ) {
1058 + $url .= '/';
1059 + }
1060 + $where = '';
1061 + $results = $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp' ) . ' WHERE url = "' . $this->escape( $url ) . '"' . $where, OBJECT );
1062 + if ( $results ) {
1063 + return $results;
1064 + }
2093 1065
2094 - $view = isset( $params['view'] ) ? $params['view'] : 'default'; // must be default.
2095 - $selectgroups = isset( $params['selectgroups'] ) && $params['selectgroups'] ? true : false;
2096 - $search_site = isset( $params['search'] ) ? trim( $params['search'] ) : null;
2097 - $orderBy = isset( $params['orderby'] ) ? $params['orderby'] : 'wp.url';
2098 - $offset = isset( $params['offset'] ) ? intval( $params['offset'] ) : false;
2099 - $rowcount = isset( $params['rowcount'] ) ? intval( $params['rowcount'] ) : false;
2100 - $extraWhere = isset( $params['extra_where'] ) ? $params['extra_where'] : null; // without AND prefix.
2101 - $for_manager = isset( $params['for_manager'] ) && $params['for_manager'] ? true : false;
2102 - $extra_view = isset( $params['extra_view'] ) ? $params['extra_view'] : array( 'favi_icon' );
2103 - $is_staging = isset( $params['is_staging'] ) && 'yes' === $params['is_staging'] ? 'yes' : 'no';
2104 - $is_count = isset( $params['count_only'] ) && $params['count_only'] ? true : false;
2105 - $group_ids = isset( $params['group_id'] ) && ! empty( $params['group_id'] ) ? $params['group_id'] : array();
2106 - $client_ids = isset( $params['client_id'] ) && ! empty( $params['client_id'] ) ? $params['client_id'] : array();
2107 - $group_logic = ( isset( $params['group_logic'] ) && 'and' === $params['group_logic'] ) ? 'and' : 'or';
2108 - $is_not = isset( $params['isnot'] ) && ! empty( $params['isnot'] ) ? true : false;
2109 - $selected_sites = isset( $params['selected_sites'] ) ? $params['selected_sites'] : array();
1066 + if ( stristr( $url, '/www.' ) ) {
1067 + //remove www if it's there!
1068 + $url = str_replace( '/www.', '/', $url );
1069 + } else {
1070 + //add www if it's not there!
1071 + $url = str_replace( 'https://', 'https://www.', $url );
1072 + $url = str_replace( 'http://', 'http://www.', $url );
1073 + }
2110 1074
2111 - // This parameter is used to enable caching in certain cases.
2112 - $_included_cache_ids = isset( $params['_included_cache_ids'] ) ? wp_parse_id_list( $params['_included_cache_ids'] ) : array();
2113 - $where_cache_ids = '';
1075 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp' ) . ' WHERE url = "' . $this->escape( $url ) . '"' . $where, OBJECT );
1076 + }
2114 1077
2115 - if ( ! is_array( $group_ids ) ) {
2116 - $group_ids = array();
2117 - }
1078 + public function getWebsiteBackupSettings( $websiteid ) {
1079 + if ( !MainWP_Utility::ctype_digit( $websiteid ) ) {
1080 + return null;
1081 + }
2118 1082
2119 - // valid group ids.
2120 - $group_ids = array_filter(
2121 - $group_ids,
2122 - function ( $e ) {
2123 - if ( 'nogroups' === $e ) {
2124 - return true;
2125 - }
2126 - return ( is_numeric( $e ) && 0 < $e ) ? true : false;
2127 - }
2128 - );
1083 + return $this->getRowResult( 'SELECT * FROM ' . $this->tableName( 'wp_settings_backup' ) . ' WHERE wpid = ' . $websiteid );
1084 + }
2129 1085
2130 - if ( ! is_array( $client_ids ) ) {
2131 - $client_ids = array();
2132 - }
1086 + public function getWebsiteById( $id, $selectGroups = false ) {
1087 + return $this->getRowResult( $this->getSQLWebsiteById( $id, $selectGroups ) );
1088 + }
2133 1089
2134 - // valid group ids.
2135 - $client_ids = array_filter(
2136 - $client_ids,
2137 - function ( $e ) {
2138 - if ( 'noclients' === $e ) {
2139 - return true;
2140 - }
2141 - return is_numeric( $e ) && ! empty( $e ) ? true : false; // to valid client ids.
2142 - }
2143 - );
2144 -
2145 - if ( $selectgroups ) {
2146 - $staging_group = get_option( 'mainwp_stagingsites_group_id' );
2147 - if ( $staging_group && in_array( $staging_group, $group_ids ) ) {
2148 - if ( empty( $group_ids ) ) {
2149 - $is_staging = 'yes';
2150 - } else {
2151 - $is_staging = 'nocheckstaging';
2152 - }
2153 - }
2154 - }
2155 -
2156 - if ( ! is_array( $selected_sites ) ) {
2157 - $selected_sites = array();
2158 - }
2159 - $selected_sites = MainWP_Utility::array_numeric_filter( $selected_sites );
2160 -
2161 - $where = '';
2162 - if ( MainWP_System::instance()->is_multi_user() ) {
2163 -
2164 - /**
2165 - * Current user global.
2166 - *
2167 - * @global string
2168 - */
2169 - global $current_user;
2170 -
2171 - $where .= ' AND wp.userid = ' . $current_user->ID . ' ';
2172 - }
2173 -
2174 - if ( ! empty( $_included_cache_ids ) ) {
2175 - $where_cache_ids .= ' AND wp.id IN (' . implode( ',', $_included_cache_ids ) . ') ';
2176 - } else {
2177 - if ( ! empty( $selected_sites ) ) {
2178 - $where .= ' AND wp.id IN (' . implode( ',', $selected_sites ) . ') ';
2179 - }
2180 -
2181 - if ( ! empty( $extraWhere ) ) {
2182 - $where .= ' AND ' . $extraWhere;
2183 - }
2184 - }
2185 -
2186 - // Search filtering.
2187 - if ( null !== $search_site && '' !== $search_site ) {
2188 - // Escape LIKE wildcards first (%, _, \).
2189 - // Note: Cannot use WordPress escaping functions (esc_like, esc_sql, prepare) because
2190 - // WordPress 6.2+ creates placeholder tokens that are only substituted during query execution.
2191 - // Since this method returns a SQL string for later execution, tokens would never be substituted.
2192 - // We use direct mysqli_real_escape_string() which is the same underlying function WordPress uses.
2193 - $search_escaped = str_replace( array( '\\', '%', '_' ), array( '\\\\', '\\%', '\\_' ), $search_site );
2194 - $like_pattern = '%' . $search_escaped . '%';
2195 -
2196 - // SQL escape using direct mysqli function to bypass WordPress placeholder tokens.
2197 - if ( $this->wpdb->dbh instanceof \mysqli ) {
2198 - $like_pattern_escaped = mysqli_real_escape_string( $this->wpdb->dbh, $like_pattern );
2199 - } else {
2200 - // Fallback: reject if no mysqli connection available.
2201 - $like_pattern_escaped = '';
2202 - }
2203 -
2204 - if ( '' !== $like_pattern_escaped ) {
2205 - $where .= " AND (wp.name LIKE '" . $like_pattern_escaped . "' OR wp.url LIKE '" . $like_pattern_escaped . "') ";
2206 - }
2207 - }
2208 -
2209 - $staging_enabled = is_plugin_active( 'mainwp-staging-extension/mainwp-staging-extension.php' ) || is_plugin_active( 'mainwp-timecapsule-extension/mainwp-timecapsule-extension.php' );
2210 - if ( ! $staging_enabled ) {
2211 - $is_staging = 'no';
2212 - }
2213 -
2214 - if ( ! $for_manager ) {
2215 - $where .= $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
2216 - }
2217 -
2218 - if ( $is_count ) {
2219 - $orderBy = '';
2220 - } elseif ( 'wp.url' === $orderBy ) {
2221 - $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '')";
2222 - }
2223 -
2224 - if ( ! empty( $orderBy ) ) {
2225 - $orderBy = ' ORDER BY ' . $orderBy;
2226 - }
2227 -
2228 - $join_group = '';
2229 - $where_group = '';
2230 - $having_group = '';
2231 -
2232 - if ( in_array( 'nogroups', $group_ids ) ) {
2233 - $join_group = ' LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid ';
2234 - $group_ids = array_filter(
2235 - $group_ids,
2236 - function ( $e ) {
2237 - return 'nogroups' !== $e;
2238 - }
2239 - );
2240 - if ( ! empty( $group_ids ) ) {
2241 - $groups = implode( ',', $group_ids );
2242 - $groups_count = count( $group_ids );
2243 - if ( $is_not ) {
2244 - $where_group = ' AND wpgroup.groupid IS NOT NULL ';
2245 - if ( 'and' === $group_logic ) {
2246 - $sub_select_match_all = ' SELECT wpand.id FROM ' . $this->table_name( 'wp' ) . ' wpand JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup_and ON wpand.id = wpgroup_and.wpid WHERE wpgroup_and.groupid IN (' . $groups . ') GROUP BY wpand.id HAVING COUNT(DISTINCT wpgroup_and.groupid) = ' . $groups_count . ' ';
2247 - $where_group .= ' AND wp.id NOT IN ( ' . $sub_select_match_all . ' ) ';
2248 - } else {
2249 - $sub_select_is_not = ' SELECT wp_or.id FROM ' . $this->table_name( 'wp' ) . ' wp_or JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup_or ON wp_or.id = wpgroup_or.wpid WHERE wpgroup_or.groupid IN (' . $groups . ') ';
2250 - $where_group .= ' AND wp.id NOT IN ( ' . $sub_select_is_not . ' ) ';
2251 - }
2252 - } elseif ( 'and' === $group_logic ) {
2253 - $where_group = ' AND 1 = 0 ';
2254 - } else {
2255 - $where_group = ' AND ( wpgroup.groupid IS NULL OR wpgroup.groupid IN (' . $groups . ') ) ';
2256 - }
2257 - } elseif ( $is_not ) {
2258 - $where_group = ' AND wpgroup.groupid IS NOT NULL ';
2259 - } else {
2260 - $where_group = ' AND wpgroup.groupid IS NULL ';
2261 - }
2262 - } elseif ( $group_ids ) {
2263 - $groups = implode( ',', $group_ids );
2264 - $groups_count = count( $group_ids );
2265 - if ( $is_not ) {
2266 - $join_group = ' LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid ';
2267 - $where_group = '';
2268 - if ( 'and' === $group_logic ) {
2269 - $sub_select_match_all = ' SELECT wpand.id FROM ' . $this->table_name( 'wp' ) . ' wpand JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup_and ON wpand.id = wpgroup_and.wpid WHERE wpgroup_and.groupid IN (' . $groups . ') GROUP BY wpand.id HAVING COUNT(DISTINCT wpgroup_and.groupid) = ' . $groups_count . ' ';
2270 - $where_group .= ' AND wp.id NOT IN ( ' . $sub_select_match_all . ' ) ';
2271 - } else {
2272 - $sub_select_is_not = ' SELECT wp_or.id FROM ' . $this->table_name( 'wp' ) . ' wp_or JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup_or ON wp_or.id = wpgroup_or.wpid WHERE wpgroup_or.groupid IN (' . $groups . ') ';
2273 - $where_group .= ' AND wp.id NOT IN ( ' . $sub_select_is_not . ' ) ';
2274 - }
2275 - } else {
2276 - $join_group = ' JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid ';
2277 - $where_group = ' AND wpgroup.groupid IN (' . $groups . ') ';
2278 - if ( 'and' === $group_logic ) {
2279 - $having_group = 'COUNT(DISTINCT wpgroup.groupid) = ' . $groups_count;
2280 - }
2281 - }
2282 - }
2283 -
2284 - $select_groups_belong = '';
2285 -
2286 - if ( ! $is_count && $group_ids ) {
2287 - $select_groups_belong = $this->get_select_groups_belong();
2288 - }
2289 -
2290 - $join_client = '';
2291 - $where_client = '';
2292 - $group_by = ' GROUP BY wp.id, wp_sync.sync_id';
2293 - if ( ! empty( $having_group ) ) {
2294 - $group_by .= ' HAVING ' . $having_group;
2295 - }
2296 - $group_by = ' GROUP BY wp.id, wp_sync.sync_id';
2297 - if ( ! empty( $having_group ) ) {
2298 - $group_by .= ' HAVING ' . $having_group;
2299 - }
2300 - if ( in_array( 'noclients', $client_ids ) ) {
2301 - $join_client = ' LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id ';
2302 - $client_ids = array_filter(
2303 - $client_ids,
2304 - function ( $e ) {
2305 - return 'noclients' !== $e;
2306 - }
2307 - );
2308 - if ( ! empty( $client_ids ) ) {
2309 - $clients = implode( ',', $client_ids );
2310 - if ( $is_not ) {
2311 - $where_client = ' AND wpclient.client_id IS NOT NULL AND wp.client_id NOT IN (' . $clients . ') ';
2312 - } else {
2313 - $where_client = ' AND wpclient.client_id IN (' . $clients . ') ';
2314 - }
2315 - } elseif ( $is_not ) {
2316 - $where_client = ' AND wpclient.client_id IS NOT NULL ';
2317 - } else {
2318 - $where_client = ' AND wpclient.client_id IS NULL ';
2319 - }
2320 - } elseif ( $client_ids && ! empty( $client_ids ) ) {
2321 - $clients = implode( ',', $client_ids );
2322 - if ( $is_not ) {
2323 - $join_client = ' LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id ';
2324 - $where_client = ' AND ( wpclient.client_id NOT IN (' . $clients . ') OR wpclient.client_id IS NULL ) ';
2325 - } else {
2326 - $join_client = ' JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id ';
2327 - $where_client = ' AND wpclient.client_id IN (' . $clients . ') ';
2328 - }
2329 - }
2330 -
2331 - if ( '' === $join_client ) {
2332 - $join_client = ' LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id ';
2333 - }
2334 -
2335 - $light_fields = array(
2336 - 'wp.id',
2337 - 'wp.url',
2338 - 'wp.name',
2339 - 'wp.client_id',
2340 - 'wp.verify_certificate',
2341 - 'wp.http_user',
2342 - 'wp.http_pass',
2343 - 'wp.ssl_version',
2344 - 'wp.adminname',
2345 - 'wp.privkey',
2346 - 'wp.pubkey',
2347 - 'wp.wpe',
2348 - 'wp.is_staging',
2349 - 'wp.force_use_ipv4',
2350 - 'wp.siteurl',
2351 - 'wp.suspended',
2352 - 'wp.mainwpdir',
2353 - 'wp.is_ignoreCoreUpdates',
2354 - 'wp.is_ignorePluginUpdates',
2355 - 'wp.is_ignoreThemeUpdates',
2356 - 'wp.backup_before_upgrade',
2357 - 'wp.userid',
2358 - 'wp_sync.sync_errors',
2359 - );
2360 -
2361 - $legacy_status_fields = array(
2362 - 'wp.offline_check_result', // 1 - online, -1 offline.
2363 - 'wp.http_response_code',
2364 - 'wp.offline_checks_last',
2365 - );
2366 -
2367 - $light_fields = array_merge( $light_fields, $legacy_status_fields );
2368 -
2369 - $join_monitors = '';
2370 -
2371 - $select_fields = array(
2372 - 'wp.*',
2373 - 'wp_sync.*',
2374 - );
2375 -
2376 - if ( 'light_view' === $view ) {
2377 - $select_fields = $light_fields;
2378 - } elseif ( 'monitor_view' === $view ) {
2379 - $select_fields = $light_fields;
2380 - $select_fields[] = 'mo.*';
2381 - $join_monitors = 'LEFT JOIN (
2382 - SELECT m1.*
2383 - FROM ' . $this->table_name( 'monitors' ) . ' m1
2384 - JOIN (
2385 - SELECT wpid, MAX(monitor_id) AS max_id
2386 - FROM ' . $this->table_name( 'monitors' ) . '
2387 - WHERE issub = 0
2388 - GROUP BY wpid
2389 - ) mm ON mm.wpid = m1.wpid AND m1.monitor_id = mm.max_id
2390 - ) mo ON mo.wpid = wp.id ';
2391 - } elseif ( 'manage_site' === $view ) {
2392 - $select_fields[] = 'mo.monitor_id';
2393 - $join_monitors = ' LEFT JOIN (
2394 - SELECT wpid, MAX(monitor_id) AS monitor_id
2395 - FROM ' . $this->table_name( 'monitors' ) . '
2396 - WHERE issub = 0
2397 - GROUP BY wpid
2398 - ) AS mo
2399 - ON mo.wpid = wp.id ';
2400 -
2401 - }
2402 -
2403 - $select = implode( ',', $select_fields );
2404 -
2405 - $view_selects = '';
2406 - $view_joins = '';
2407 -
2408 - $opts_view = $this->get_wp_options_join( $extra_view, $view );
2409 -
2410 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
2411 - $view_selects = ',' . $opts_view['selects'];
2412 - $view_joins = $opts_view['joins'];
2413 - }
2414 -
2415 - // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax.
2416 - if ( $selectgroups ) {
2417 -
2418 - if ( empty( $join_group ) ) {
2419 - $join_group = ' LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid ';
2420 - }
2421 -
2422 - $qry = 'SELECT ' . $select . $view_selects . ', GROUP_CONCAT(DISTINCT gr.name ORDER BY gr.name SEPARATOR ",") as wpgroups, GROUP_CONCAT(DISTINCT gr.id ORDER BY gr.name SEPARATOR ",") as wpgroupids, GROUP_CONCAT(DISTINCT gr.color ORDER BY gr.name SEPARATOR ",") as wpgroups_colors, wpclient.name as client_name ' .
2423 - $select_groups_belong . ' FROM ' . $this->table_name( 'wp' ) . ' wp ' .
2424 - $join_client . ' ' .
2425 - $join_group .
2426 - $join_monitors . '
2427 - LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgroup.groupid = gr.id
2428 -
2429 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2430 - ' . $view_joins . '
2431 - WHERE 1 ' . $where_cache_ids . $where . $where_group . $where_client . $group_by .
2432 - $orderBy;
2433 - } else {
2434 - $qry = 'SELECT ' . $select . $view_selects . ', wpclient.name as client_name ' .
2435 - $select_groups_belong . ' FROM ' . $this->table_name( 'wp' ) . ' wp ' .
2436 - $join_group . ' ' .
2437 - $join_client .
2438 - $join_monitors . '
2439 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2440 - ' . $view_joins . '
2441 - WHERE 1 ' . $where_cache_ids . $where . $where_group . $where_client . $group_by .
2442 - $orderBy;
2443 - }
2444 -
2445 - if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
2446 - // When cache IDs are provided, they already represent the page-specific subset,
2447 - // so the effective offset within that subset is always 0.
2448 - $effective_offset = ! empty( $_included_cache_ids ) ? 0 : $offset;
2449 - $qry .= ' LIMIT ' . $effective_offset . ', ' . $rowcount;
2450 - } elseif ( false !== $rowcount ) {
2451 - $qry .= ' LIMIT ' . $rowcount;
2452 - }
2453 -
2454 - if ( ! empty( $_included_cache_ids ) ) {
2455 - MainWP_Logger::instance()->log_events( 'cache-metrics', sprintf( '[sql search websites=%s]', $qry ) );
2456 - }
2457 - MainWP_Logger::instance()->log_events( 'db-queries', sprintf( '[sql search websites=%s]', $qry ) );
2458 -
2459 - return $qry;
2460 - }
2461 -
2462 - /**
2463 - * Get child sites where allowed access via SQL.
2464 - *
2465 - * @param string $site_table_alias Child site table alias.
2466 - * @param string $is_staging yes|no Is child site a staging site.
2467 - *
2468 - * @return boolean|null $_where Database query results or null on failure.
2469 - */
2470 - public function get_sql_where_allow_access_sites( $site_table_alias = '', $is_staging = 'no' ) { // phpcs:ignore -- NOSONAR - complex.
2471 -
2472 - if ( empty( $site_table_alias ) ) {
2473 - $site_table_alias = $this->table_name( 'wp' );
2474 - }
2475 -
2476 - // check to filter the staging sites.
2477 - $where_staging = ' AND ' . $site_table_alias . '.is_staging = 0 ';
2478 - if ( 'no' === $is_staging ) {
2479 - $where_staging = ' AND ' . $site_table_alias . '.is_staging = 0 ';
2480 - } elseif ( 'yes' === $is_staging ) {
2481 - $where_staging = ' AND ' . $site_table_alias . '.is_staging = 1 ';
2482 - } elseif ( 'nocheckstaging' === $is_staging ) {
2483 - $where_staging = '';
2484 - }
2485 - // end staging filter.
2486 -
2487 - $_where = $where_staging;
2488 - // To fix bug run from cron job.
2489 - if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
2490 - return $_where;
2491 - }
2492 -
2493 - // To fix bug run from wp cli.
2494 - if ( defined( 'WP_CLI' ) && WP_CLI ) {
2495 - return $_where;
2496 - }
2497 -
2498 - // Run from Rest Api.
2499 - if ( defined( 'MAINWP_REST_API_DOING' ) && MAINWP_REST_API_DOING ) {
2500 - return $_where;
2501 - }
2502 -
2503 - /**
2504 - * Filter: mainwp_currentuserallowedaccesssites
2505 - *
2506 - * Filters allowed sites for the current user.
2507 - *
2508 - * @since Unknown
2509 - */
2510 - $allowed_sites = apply_filters( 'mainwp_currentuserallowedaccesssites', 'all' );
2511 -
2512 - if ( 'all' === $allowed_sites ) {
2513 - return $_where;
2514 - }
2515 -
2516 - if ( is_array( $allowed_sites ) && ! empty( $allowed_sites ) ) {
2517 - // valid group ids.
2518 - $allowed_sites = array_filter(
2519 - $allowed_sites,
2520 - function ( $e ) {
2521 - return is_numeric( $e ) ? true : false;
2522 - }
2523 - );
2524 - $_where .= ' AND ' . $site_table_alias . '.id IN (' . implode( ',', $allowed_sites ) . ') ';
2525 - } else {
2526 - $_where .= ' AND 0 ';
2527 - }
2528 -
2529 - return $_where;
2530 - }
2531 -
2532 - /**
2533 - * Get groupd where allowed access via SQL.
2534 - *
2535 - * @param string $group_table_alias Child site table alias.
2536 - * @param string $with_staging yes|no Is child site a staging site.
2537 - *
2538 - * @return boolean|null $_where Database query results or null on failer.
2539 - */
2540 - public function get_sql_where_allow_groups( $group_table_alias = '', $with_staging = 'no' ) { // phpcs:ignore -- NOSONAR - complex.
2541 -
2542 - if ( empty( $group_table_alias ) ) {
2543 - $group_table_alias = $this->table_name( 'group' );
2544 - }
2545 -
2546 - // check to filter the staging group.
2547 - $where_staging_group = '';
2548 - $staging_group = get_option( 'mainwp_stagingsites_group_id' );
2549 - if ( $staging_group ) {
2550 - $where_staging_group = ' AND ' . $group_table_alias . '.id <> ' . $staging_group . ' ';
2551 - if ( 'yes' === $with_staging ) {
2552 - $where_staging_group = '';
2553 - }
2554 - }
2555 -
2556 - // end staging filter.
2557 - $_where = $where_staging_group;
2558 -
2559 - // To fix bug run from cron job.
2560 - if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
2561 - return $_where;
2562 - }
2563 -
2564 - // Run from wp cli.
2565 - if ( defined( 'WP_CLI' ) && WP_CLI ) {
2566 - return $_where;
2567 - }
2568 -
2569 - // Run from Rest Api.
2570 - if ( defined( 'MAINWP_REST_API_DOING' ) && MAINWP_REST_API_DOING ) {
2571 - return $_where;
2572 - }
2573 -
2574 - /**
2575 - * Filter: mainwp_currentuserallowedaccessgroups
2576 - *
2577 - * Filters allowed groups for the current user.
2578 - *
2579 - * @since Unknown
2580 - */
2581 - $allowed_groups = apply_filters( 'mainwp_currentuserallowedaccessgroups', 'all' );
2582 -
2583 - if ( 'all' === $allowed_groups ) {
2584 - return $_where;
2585 - }
2586 -
2587 - if ( is_array( $allowed_groups ) && ! empty( $allowed_groups ) ) {
2588 -
2589 - // valid group ids.
2590 - $allowed_groups = array_filter(
2591 - $allowed_groups,
2592 - function ( $e ) {
2593 - return is_numeric( $e ) ? true : false;
2594 - }
2595 - );
2596 -
2597 - return ' AND ' . $group_table_alias . '.id IN (' . implode( ',', $allowed_groups ) . ') ' . $_where;
2598 - } else {
2599 - return ' AND 0 ';
2600 - }
2601 - }
2602 -
2603 -
2604 - /**
2605 - * Get child site by id and params.
2606 - *
2607 - * @param int $id Child site ID.
2608 - * @param array $params params.
2609 - * @param string $obj OBJECT|ARRAY_A.
2610 - *
2611 - * @return object|null Database query results or null on failure.
2612 - */
2613 - public function get_website_by_id_params( $id, $params = array(), $obj = OBJECT ) {
2614 - return $this->get_row_result( $this->get_sql_website_by_params( $id, $params ), $obj );
2615 - }
2616 -
2617 - /**
2618 - * Get sql child site by id and params.
2619 - *
2620 - * @param int $id Child site ID.
2621 - * @param array $params params.
2622 - *
2623 - * @return object|null Database query results or null on failure.
2624 - */
2625 - public function get_sql_website_by_params( $id, $params = array() ) {
2626 -
2627 - if ( ! is_array( $params ) ) {
2628 - $params = array();
2629 - }
2630 -
2631 - $select_groups = ! empty( $params['select_groups'] ) ? true : false;
2632 -
2633 - $view = ! empty( $params['view'] ) ? $params['view'] : 'simple_view';
2634 - $view_fields = isset( $params['view_fields'] ) ? $params['view_fields'] : array();
2635 -
2636 - if ( is_string( $view_fields ) ) {
2637 - $view_fields = (array) $view_fields;
2638 - } elseif ( ! is_array( $view_fields ) ) {
2639 - $view_fields = array();
2640 - }
2641 -
2642 - if ( MainWP_Utility::ctype_digit( $id ) ) {
2643 -
2644 - $use_comp_subquery = ! empty( $params['use_compatible_subquery'] ) ? true : false;
2645 -
2646 - $view_selects = '';
2647 - $view_joins = '';
2648 -
2649 - if ( $use_comp_subquery ) {
2650 - $view_selects = ',wp_optionview.* ';
2651 - $view_joins = ' JOIN ' . $this->get_option_view_by( $view, $view_fields ) . ' wp_optionview ON wp.id = wp_optionview.wpid ';
2652 - } else {
2653 - $opts_view = $this->get_option_view_by_join( $view, $view_fields );
2654 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
2655 - $view_selects = ',' . $opts_view['selects'];
2656 - $view_joins = $opts_view['joins'];
2657 - }
2658 - }
2659 -
2660 - $where = $this->get_sql_where_allow_access_sites( 'wp', 'nocheckstaging' );
2661 - if ( $select_groups ) {
2662 - return 'SELECT wp.*,wp_sync.*' . $view_selects . ', GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ",") as wpgroups, GROUP_CONCAT(gr.id ORDER BY gr.name SEPARATOR ",") as wpgroupids, GROUP_CONCAT(gr.color ORDER BY gr.name SEPARATOR ",") as wpgroups_colors
2663 - FROM ' . $this->table_name( 'wp' ) . ' wp
2664 - LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
2665 - LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
2666 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2667 - ' . $view_joins . '
1090 + public function getSQLWebsiteById( $id, $selectGroups = false, $extra_view = array( 'favi_icon' ) ) {
1091 + if ( MainWP_Utility::ctype_digit( $id ) ) {
1092 + $where = $this->getWhereAllowAccessSites( 'wp', 'nocheckstaging' ); // no check staging
1093 + if ( $selectGroups ) {
1094 + return 'SELECT wp.*,wp_sync.*,wp_optionview.*, GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ", ") as wpgroups
1095 + FROM ' . $this->tableName( 'wp' ) . ' wp
1096 + LEFT JOIN ' . $this->tableName( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
1097 + LEFT JOIN ' . $this->tableName( 'group' ) . ' gr ON wpgr.groupid = gr.id
1098 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1099 + JOIN ' . $this->getOptionView( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2668 1100 WHERE wp.id = ' . $id . $where . '
2669 - GROUP BY wp.id, wp_sync.sync_id';
2670 - }
1101 + GROUP BY wp.id';
1102 + }
2671 1103
2672 - return 'SELECT wp.*,wp_sync.*' . $view_selects . '
2673 - FROM ' . $this->table_name( 'wp' ) . ' wp
2674 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2675 - ' . $view_joins . '
1104 + return 'SELECT wp.*,wp_sync.*,wp_optionview.*
1105 + FROM ' . $this->tableName( 'wp' ) . ' wp
1106 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1107 + JOIN ' . $this->getOptionView( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2676 1108 WHERE id = ' . $id . $where;
2677 - }
2678 - return null;
2679 - }
1109 + }
2680 1110
2681 - /**
2682 - * Get child site by id.
2683 - *
2684 - * @param int $id Child site ID.
2685 - * @param array $selectGroups Select groups.
2686 - * @param array $extra_view Get extra option fields.
2687 - * @param int $obj OBJECT|ARRAY_A.
2688 - *
2689 - * @return object|null Database query results or null on failure.
2690 - */
2691 - public function get_website_by_id( $id, $selectGroups = false, $extra_view = array(), $obj = OBJECT ) {
2692 - return $this->get_row_result( $this->get_sql_website_by_id( $id, $selectGroups, $extra_view ), $obj );
2693 - }
1111 + return null;
1112 + }
2694 1113
2695 - /**
2696 - * Get child site by id via SQL.
2697 - *
2698 - * @param int $id Child site ID.
2699 - * @param bool $selectGroups Selected groups.
2700 - * @param mixed $extra_view Extra view value.
2701 - *
2702 - * @return object|null Database query result or null on failure.
2703 - *
2704 - * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
2705 - */
2706 - public function get_sql_website_by_id( $id, $selectGroups = false, $extra_view = array() ) {
1114 + public function getWebsitesByIds( $ids, $userId = null ) {
1115 + if ( ( $userId == null ) && MainWP_System::Instance()->isMultiUser() ) {
1116 + global $current_user;
1117 + $userId = $current_user->ID;
1118 + }
1119 + $where = $this->getWhereAllowAccessSites();
2707 1120
2708 - if ( ! is_array( $extra_view ) || empty( $extra_view ) ) {
2709 - $extra_view = array( 'favi_icon', 'site_info' );
2710 - }
1121 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp' ) . ' WHERE id IN (' . implode( ',', $ids ) . ')' . ( $userId != null ? ' AND userid = ' . $userId : '' ) . $where, OBJECT );
1122 + }
2711 1123
2712 - if ( MainWP_Utility::ctype_digit( $id ) ) {
1124 + public function getWebsitesByGroupIds( $ids, $userId = null ) {
1125 + if ( empty( $ids ) ) {
1126 + return array();
1127 + }
1128 + if ( ( $userId == null ) && MainWP_System::Instance()->isMultiUser() ) {
1129 + global $current_user;
1130 + $userId = $current_user->ID;
1131 + }
2713 1132
2714 - $view_selects = '';
2715 - $view_joins = '';
1133 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp' ) . ' wp JOIN ' . $this->tableName( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid WHERE wpgroup.groupid IN (' . implode( ',', $ids ) . ') ' . ( $userId != null ? ' AND wp.userid = ' . $userId : '' ), OBJECT );
1134 + }
2716 1135
2717 - $opts_view = $this->get_wp_options_join( $extra_view );
1136 + public function getWebsitesByGroupId( $id ) {
1137 + return $this->getResultsResult( $this->getSQLWebsitesByGroupId( $id ) );
1138 + }
2718 1139
2719 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
2720 - $view_selects = ',' . $opts_view['selects'];
2721 - $view_joins = $opts_view['joins'];
2722 - }
1140 + public function getSQLWebsitesByGroupId( $id, $selectgroups = false, $orderBy = 'wp.url', $offset = false,
1141 + $rowcount = false, $where = null, $search_site = null) {
2723 1142
2724 - $where = $this->get_sql_where_allow_access_sites( 'wp', 'nocheckstaging' );
2725 - if ( $selectGroups ) {
2726 - return 'SELECT wp.*,wp_sync.*' . $view_selects . ', GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ",") as wpgroups, GROUP_CONCAT(gr.id ORDER BY gr.name SEPARATOR ",") as wpgroupids, GROUP_CONCAT(gr.color ORDER BY gr.name SEPARATOR ",") as wpgroups_colors
2727 - FROM ' . $this->table_name( 'wp' ) . ' wp
2728 - LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
2729 - LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
2730 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2731 - ' . $view_joins . '
2732 - WHERE wp.id = ' . $id . $where . '
2733 - GROUP BY wp.id, wp_sync.sync_id';
2734 - }
1143 + $is_staging = 'no';
1144 + if ( $selectgroups ) {
1145 + if ( $staging_group = get_option( 'mainwp_stagingsites_group_id' ) ) {
1146 + if ( $id == $staging_group ) {
1147 + $is_staging = 'yes'; // will list staging sites
1148 + }
1149 + }
1150 + }
2735 1151
2736 - return 'SELECT wp.*,wp_sync.*' . $view_selects . '
2737 - FROM ' . $this->table_name( 'wp' ) . ' wp
2738 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2739 - ' . $view_joins . '
2740 - WHERE id = ' . $id . $where;
2741 - }
1152 + $where_search = '';
1153 + if ( !empty( $search_site ) ) {
1154 + $search_site = trim( $search_site );
1155 + $where_search .= ' AND (wp.name LIKE "%' . $this->escape( $search_site ) . '%" OR wp.url LIKE "%' . $this->escape( $search_site ) . '%") ';
1156 + }
2742 1157
2743 - return null;
2744 - }
1158 + if ( MainWP_Utility::ctype_digit( $id ) ) {
1159 + $where_allowed = $this->getWhereAllowAccessSites( 'wp', $is_staging );
1160 + if ( $selectgroups ) {
1161 + $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*, GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ", ") as wpgroups
1162 + FROM ' . $this->tableName( 'wp' ) . ' wp
1163 + JOIN ' . $this->tableName( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
1164 + LEFT JOIN ' . $this->tableName( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
1165 + LEFT JOIN ' . $this->tableName( 'group' ) . ' gr ON wpgr.groupid = gr.id
1166 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1167 + JOIN ' . $this->getOptionView() . ' wp_optionview ON wp.id = wp_optionview.wpid
1168 + WHERE wpgroup.groupid = ' . $id . ' ' .
1169 + ( $where == null ? '' : ' AND ' . $where ) . $where_allowed . $where_search . '
1170 + GROUP BY wp.id
1171 + ORDER BY ' . $orderBy;
1172 + } else {
1173 + $qry = 'SELECT wp.*,wp_sync.* FROM ' . $this->tableName( 'wp' ) . ' wp
1174 + JOIN ' . $this->tableName( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
1175 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1176 + WHERE wpgroup.groupid = ' . $id . ' ' . $where_allowed . $where_search .
1177 + ( $where == null ? '' : ' AND ' . $where ) . ' ORDER BY ' . $orderBy;
1178 + }
1179 + if ( ( $offset !== false ) && ( $rowcount !== false ) ) {
1180 + $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
1181 + }
2745 1182
2746 - /**
2747 - * Method get_websites_by_ids()
2748 - *
2749 - * Get child sites by child site IDs.
2750 - *
2751 - * @param array $ids Child site IDs.
2752 - * @param int $userId User ID.
2753 - *
2754 - * @return object|null Database query result or null on failure.
2755 - *
2756 - * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
2757 - */
2758 - public function get_websites_by_ids( $ids, $userId = null ) {
2759 - if ( ( null === $userId ) && MainWP_System::instance()->is_multi_user() ) {
1183 + return $qry;
1184 + }
2760 1185
2761 - /**
2762 - * Current user global.
2763 - *
2764 - * @global string
2765 - */
2766 - global $current_user;
1186 + return null;
1187 + }
2767 1188
2768 - $userId = $current_user->ID;
2769 - }
1189 + public function getWebsitesByGroupName( $userid, $groupname ) {
1190 + return $this->getResultsResult( $this->getSQLWebsitesByGroupName( $groupname, $userid ) );
1191 + }
2770 1192
2771 - // valid group ids.
2772 - $ids = array_filter(
2773 - $ids,
2774 - function ( $e ) {
2775 - return ( is_numeric( $e ) && 0 < $e ) ? true : false;
2776 - }
2777 - );
1193 + public function getSQLWebsitesByGroupName( $groupname, $userid = null ) {
1194 + if ( ( $userid == null ) && MainWP_System::Instance()->isMultiUser() ) {
1195 + global $current_user;
1196 + $userid = $current_user->ID;
1197 + }
2778 1198
2779 - $where = $this->get_sql_where_allow_access_sites();
2780 - $table_name = esc_sql( $this->table_name( 'wp' ) );
2781 - $placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) );
2782 - $sql = "SELECT * FROM {$table_name} WHERE id IN ({$placeholders})";
2783 - $params = $ids;
1199 + $sql = 'SELECT wp.*,wp_sync.*,wp_optionview.* FROM ' . $this->tableName( 'wp' ) . ' wp
1200 + INNER JOIN ' . $this->tableName( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
1201 + JOIN ' . $this->tableName( 'group' ) . ' g ON wpgroup.groupid = g.id
1202 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1203 + JOIN ' . $this->getOptionView() . ' wp_optionview ON wp.id = wp_optionview.wpid
1204 + WHERE g.name="' . $this->escape( $groupname ) . '"';
1205 + if ( $userid != null ) {
1206 + $sql .= ' AND g.userid = "' . $userid . '"';
1207 + }
2784 1208
2785 - if ( null !== $userId ) {
2786 - $sql .= ' AND userid = %d';
2787 - $params[] = intval( $userId );
2788 - }
1209 + return $sql;
1210 + }
2789 1211
2790 - $sql .= ' ' . $where;
1212 + public function getWPIp( $wpid ) {
1213 + return $this->wpdb->get_var( 'SELECT ip FROM ' . $this->tableName( 'request_log' ) . ' WHERE wpid = "' . $wpid . '"' );
1214 + }
2791 1215
2792 - return $this->wpdb->get_results( $this->wpdb->prepare( $sql, ...$params ), OBJECT ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $where fragment is from validated get_sql_where_access_sites() with numeric IDs
2793 - }
1216 + public function insertOrUpdateRequestLog( $wpid, $ip, $start, $stop ) {
1217 + $updateValues = array();
1218 + if ( $ip != null ) {
1219 + $updateValues[ 'ip' ] = $ip;
1220 + }
1221 + if ( $start != null ) {
1222 + $updateValues[ 'micro_timestamp_start' ] = $start;
1223 + }
1224 + if ( $stop != null ) {
1225 + $updateValues[ 'micro_timestamp_stop' ] = $stop;
1226 + }
2794 1227
2795 - /**
2796 - * Get child sites by groups IDs.
2797 - *
2798 - * @param array $ids Groups IDs.
2799 - * @param int $userId User ID.
2800 - * @param array $fields array fields .
2801 - *
2802 - * @return object|null Database query result or null on failure.
2803 - *
2804 - * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
2805 - */
2806 - public function get_websites_by_group_ids( $ids, $userId = null, $fields = array() ) {
2807 - if ( empty( $ids ) ) {
2808 - return array();
2809 - }
2810 - if ( ( null === $userId ) && MainWP_System::instance()->is_multi_user() ) {
1228 + $var = $this->wpdb->get_var( 'SELECT id FROM ' . $this->tableName( 'request_log' ) . ' WHERE wpid = "' . $wpid . '"' );
1229 + if ( $var !== null ) {
1230 + $this->wpdb->update( $this->tableName( 'request_log' ), $updateValues, array( 'wpid' => $wpid ) );
1231 + } else {
1232 + $updateValues[ 'wpid' ] = $wpid;
1233 + $this->wpdb->insert( $this->tableName( 'request_log' ), $updateValues );
1234 + }
1235 + }
2811 1236
2812 - /**
2813 - * Current user global.
2814 - *
2815 - * @global string
2816 - */
2817 - global $current_user;
1237 + public function closeOpenRequests() {
1238 + //Close requests open longer then 7 seconds.. something is wrong here..
1239 + $this->wpdb->query( 'UPDATE ' . $this->tableName( 'request_log' ) . ' SET micro_timestamp_stop = micro_timestamp_start WHERE micro_timestamp_stop < micro_timestamp_start and ' . microtime( true ) . ' - micro_timestamp_start > 7' );
1240 + }
2818 1241
2819 - $userId = $current_user->ID;
2820 - }
1242 + public function getNrOfOpenRequests( $ip = null ) {
1243 + if ( $ip == null ) {
1244 + return $this->wpdb->get_var( 'select count(id) from ' . $this->tableName( 'request_log' ) . ' where micro_timestamp_stop < micro_timestamp_start' );
1245 + }
2821 1246
2822 - // valid group ids.
2823 - $group_ids = array_filter(
2824 - $ids,
2825 - function ( $e ) {
2826 - return is_numeric( $e ) ? true : false;
2827 - }
2828 - );
1247 + return $this->wpdb->get_var( 'select count(id) from ' . $this->tableName( 'request_log' ) . ' where micro_timestamp_stop < micro_timestamp_start and ip = "' . esc_sql( $ip ) . '"' );
1248 + }
2829 1249
2830 - $select = '*';
2831 - if ( ! empty( $fields ) && is_array( $fields ) ) {
2832 - $fields = array_filter( array_map( 'trim', $fields ) );
2833 - if ( $fields ) {
2834 - $select = '';
2835 - foreach ( $fields as $field ) {
2836 - $select .= $this->escape( $field ) . ',';
2837 - }
2838 - $select = rtrim( $select, ',' );
2839 - }
2840 - }
2841 - return $this->wpdb->get_results( 'SELECT ' . $select . ' FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid WHERE wpgroup.groupid IN (' . implode( ',', $group_ids ) . ') ' . ( null !== $userId ? ' AND wp.userid = ' . intval( $userId ) : '' ), OBJECT );
2842 - }
1250 + public function getLastRequestTimestamp( $ip = null ) {
1251 + if ( $ip == null ) {
1252 + return $this->wpdb->get_var( 'select micro_timestamp_start from ' . $this->tableName( 'request_log' ) . ' order by micro_timestamp_start desc limit 1' );
1253 + }
2843 1254
2844 - /**
2845 - * Get child sites by group ID.
2846 - *
2847 - * @param int $id Group ID.
2848 - * @param bool $selectgroups Selected groups. Default: false.
2849 - * @param string $orderBy Order list by. Default: URL.
2850 - * @param bool $offset Query offset. Default: false.
2851 - * @param bool $rowcount Row count. Default: falese.
2852 - * @param null $where SQL WHERE value.
2853 - * @param null $search_site Site search field value. Default: null.
2854 - * @param array $others Others params.
2855 - *
2856 - * @return object|null Database query result or null on failure.
2857 - */
2858 - public function get_websites_by_group_id( //phpcs:ignore -- NOSONAR -ok.
2859 - $id,
2860 - $selectgroups = false,
2861 - $orderBy = 'wp.url',
2862 - $offset = false,
2863 - $rowcount = false,
2864 - $where = null,
2865 - $search_site = null,
2866 - $others = array()
2867 - ) {
2868 - return $this->get_results_result(
2869 - $this->get_sql_websites_by_group_id(
2870 - $id,
2871 - $selectgroups,
2872 - $orderBy,
2873 - $offset,
2874 - $rowcount,
2875 - $where,
2876 - $search_site,
2877 - $others
2878 - )
2879 - );
2880 - }
1255 + return $this->wpdb->get_var( 'SELECT micro_timestamp_start FROM ' . $this->tableName( 'request_log' ) . ' WHERE ip = "' . esc_sql( $ip ) . '" order by micro_timestamp_start desc limit 1' );
1256 + }
2881 1257
2882 - /**
2883 - * Get count of child sites by group ID.
2884 - *
2885 - * Uses an efficient COUNT query instead of fetching all rows.
2886 - *
2887 - * @param int $id Group ID.
2888 - *
2889 - * @return int Number of sites in the group.
2890 - *
2891 - * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
2892 - */
2893 - public function get_websites_count_by_group_id( $id ) {
2894 - if ( ! MainWP_Utility::ctype_digit( $id ) ) {
2895 - return 0;
2896 - }
1258 + public function addWebsite( $userid, $name, $url, $admin, $pubkey, $privkey, $nossl, $nosslkey, $groupids, $groupnames,
1259 + $verifyCertificate = 1, $uniqueId = '', $http_user, $http_pass, $sslVersion = 0, $wpe = 0, $isStaging = 0 ) {
1260 + if ( MainWP_Utility::ctype_digit( $userid ) && ( $nossl == 0 || $nossl == 1 ) ) {
1261 + $values = array(
1262 + 'userid' => $userid,
1263 + 'adminname' => $this->escape( $admin ),
1264 + 'name' => $this->escape( strip_tags( $name ) ), // escape by insert
1265 + 'url' => $this->escape( $url ),
1266 + 'pubkey' => $this->escape( $pubkey ),
1267 + 'privkey' => $this->escape( $privkey ),
1268 + 'nossl' => $nossl,
1269 + 'nosslkey' => ( $nosslkey == null ? '' : $this->escape( $nosslkey ) ),
1270 + 'siteurl' => '',
1271 + 'ga_id' => '',
1272 + 'gas_id' => 0,
1273 + 'offline_checks' => '',
1274 + 'offline_checks_last' => 0,
1275 + 'offline_check_result' => 0,
1276 + 'note' => '',
1277 + 'statsUpdate' => 0,
1278 + 'pagerank' => 0,
1279 + 'indexed' => 0,
1280 + 'alexia' => 0,
1281 + 'pagerank_old' => 0,
1282 + 'indexed_old' => 0,
1283 + 'alexia_old' => 0,
1284 + 'directories' => '',
1285 + 'plugin_upgrades' => '',
1286 + 'theme_upgrades' => '',
1287 + 'translation_upgrades' => '',
1288 + 'securityIssues' => '',
1289 + 'themes' => '',
1290 + 'ignored_themes' => '',
1291 + 'plugins' => '',
1292 + 'ignored_plugins' => '',
1293 + 'pages' => '',
1294 + 'users' => '',
1295 + 'categories' => '',
1296 + 'pluginDir' => '',
1297 + 'automatic_update' => 0,
1298 + 'backup_before_upgrade' => 2,
1299 + 'verify_certificate' => intval( $verifyCertificate ),
1300 + 'ssl_version' => $sslVersion,
1301 + 'uniqueId' => $uniqueId,
1302 + 'mainwpdir' => 0,
1303 + 'http_user' => $http_user,
1304 + 'http_pass' => $http_pass,
1305 + 'wpe' => $wpe,
1306 + 'is_staging' => $isStaging
1307 + );
2897 1308
2898 - // Determine if this is the staging group.
2899 - $is_staging = 'no';
2900 - $staging_group = get_option( 'mainwp_stagingsites_group_id' );
2901 - if ( $staging_group && (int) $id === (int) $staging_group ) {
2902 - $is_staging = 'yes';
2903 - }
1309 + $syncValues = array(
1310 + 'dtsSync' => 0,
1311 + 'dtsSyncStart' => 0,
1312 + 'dtsAutomaticSync' => 0,
1313 + 'dtsAutomaticSyncStart' => 0,
1314 + 'totalsize' => 0,
1315 + 'extauth' => '',
1316 + 'sync_errors' => '',
1317 + );
1318 + if ( $this->wpdb->insert( $this->tableName( 'wp' ), $values ) ) {
1319 + $websiteid = $this->wpdb->insert_id;
1320 + $syncValues[ 'wpid' ] = $websiteid;
1321 + $this->wpdb->insert( $this->tableName( 'wp_sync' ), $syncValues );
1322 + $this->wpdb->insert( $this->tableName( 'wp_settings_backup' ), array(
1323 + 'wpid' => $websiteid,
1324 + 'archiveFormat' => 'global',
1325 + ) );
2904 1326
2905 - $where_allowed = $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
1327 + foreach ( $groupnames as $groupname ) {
1328 + if ( $this->wpdb->insert( $this->tableName( 'group' ), array(
1329 + 'userid' => $userid,
1330 + 'name' => $this->escape( htmlspecialchars( $groupname ) ),
1331 + ) )
1332 + ) {
1333 + $groupids[] = $this->wpdb->insert_id;
1334 + }
1335 + }
1336 + //add groupids
1337 + foreach ( $groupids as $groupid ) {
1338 + $this->wpdb->insert( $this->tableName( 'wp_group' ), array(
1339 + 'wpid' => $websiteid,
1340 + 'groupid' => $groupid,
1341 + ) );
1342 + }
2906 1343
2907 - // Use prepare() for the groupid parameter.
2908 - $qry = $this->wpdb->prepare(
2909 - 'SELECT COUNT(DISTINCT wp.id) FROM ' . $this->table_name( 'wp' ) . ' wp
2910 - JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
2911 - WHERE wpgroup.groupid = %d',
2912 - $id
2913 - ) . $where_allowed;
1344 + return $websiteid;
1345 + }
1346 + }
2914 1347
2915 - return (int) $this->wpdb->get_var( $qry ); //phpcs:ignore PluginCheck.Security.DirectDB.Unprepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- $where_allowed is from validated get_sql_where_access_sites() with numeric IDs.
2916 - }
1348 + return false;
1349 + }
2917 1350
2918 - /**
2919 - * Get child sites by group id via SQL.
2920 - *
2921 - * @param int $id Group ID.
2922 - * @param bool $selectgroups Selected groups. Default: false.
2923 - * @param string $orderBy Order list by. Default: URL.
2924 - * @param bool $offset Query offset. Default: false.
2925 - * @param bool $rowcount Row count. Default: falese.
2926 - * @param null $where SQL WHERE value.
2927 - * @param null $search_site Site search field value. Default: null.
2928 - * @param array $others Others params.
2929 - *
2930 - * @return object|null Return database query or null on failure.
2931 - *
2932 - * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
2933 - */
2934 - public function get_sql_websites_by_group_id( // phpcs:ignore -- NOSONAR - complex.
2935 - $id,
2936 - $selectgroups = false,
2937 - $orderBy = 'wp.url',
2938 - $offset = false,
2939 - $rowcount = false,
2940 - $where = null,
2941 - $search_site = null,
2942 - $others = array()
2943 - ) {
1351 + public function updateGroupSite( $groupId, $websiteId ) {
1352 + $this->wpdb->insert( $this->tableName( 'wp_group' ), array( 'wpid' => $websiteId, 'groupid' => $groupId ) );
1353 + }
2944 1354
2945 - $is_staging = 'no';
2946 - if ( $selectgroups ) {
2947 - $staging_group = get_option( 'mainwp_stagingsites_group_id' );
2948 - if ( $staging_group && $id === $staging_group ) {
2949 - $is_staging = 'yes';
2950 - }
2951 - }
1355 + public function clearGroup( $groupId ) {
1356 + $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'wp_group' ) . ' WHERE groupid=' . $groupId );
1357 + }
2952 1358
2953 - $where_search = '';
2954 - if ( ! empty( $search_site ) ) {
2955 - $search_site = trim( $search_site );
2956 - // Use esc_like() to escape LIKE wildcards (%, _) then prepare() for SQL safety.
2957 - $like_pattern = '%' . $this->wpdb->esc_like( $search_site ) . '%';
2958 - $where_search .= $this->wpdb->prepare(
2959 - ' AND (wp.name LIKE %s OR wp.url LIKE %s) ',
2960 - $like_pattern,
2961 - $like_pattern
2962 - );
2963 - }
1359 + public function addGroup( $userid, $name ) {
1360 + if ( MainWP_Utility::ctype_digit( $userid ) ) {
1361 + if ( $this->wpdb->insert( $this->tableName( 'group' ), array(
1362 + 'userid' => $userid,
1363 + 'name' => $this->escape( $name ),
1364 + ) )
1365 + ) {
1366 + return $this->wpdb->insert_id;
1367 + }
1368 + }
2964 1369
2965 - $extra_view = is_array( $others ) && isset( $others['extra_view'] ) && is_array( $others['extra_view'] ) && ! empty( $others['extra_view'] ) ? $others['extra_view'] : array( 'site_info' );
1370 + return false;
1371 + }
2966 1372
2967 - $view_query = null;
2968 - if ( is_array( $others ) && ! empty( $others['view_query'] ) ) {
2969 - $view_query = $others['view_query'];
2970 - }
1373 + public function removeWebsite( $websiteid ) {
1374 + if ( MainWP_Utility::ctype_digit( $websiteid ) ) {
1375 + $nr = $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'wp' ) . ' WHERE id=' . $websiteid );
1376 + $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'wp_group' ) . ' WHERE wpid=' . $websiteid );
1377 + $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'wp_sync' ) . ' WHERE wpid=' . $websiteid );
1378 + $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'wp_options' ) . ' WHERE wpid=' . $websiteid );
2971 1379
2972 - if ( empty( $view_query ) ) {
2973 - $view_query = $selectgroups ? 'default' : 'group'; // To compatible.
2974 - }
1380 + return $nr;
1381 + }
2975 1382
2976 - $view_selects = '';
2977 - $view_joins = '';
1383 + return false;
1384 + }
2978 1385
2979 - $opts_view = $this->get_wp_options_join( $extra_view, $view_query );
1386 + public function removeGroup( $groupid ) {
1387 + if ( MainWP_Utility::ctype_digit( $groupid ) ) {
1388 + $nr = $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'group' ) . ' WHERE id=' . $groupid );
1389 + $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'wp_group' ) . ' WHERE groupid=' . $groupid );
2980 1390
2981 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
2982 - $view_selects = ',' . $opts_view['selects'];
2983 - $view_joins = $opts_view['joins'];
2984 - }
1391 + return $nr;
1392 + }
2985 1393
2986 - if ( MainWP_Utility::ctype_digit( $id ) ) {
2987 - $where_allowed = $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
2988 - if ( $selectgroups ) {
2989 - $qry = 'SELECT wp.*,wp_sync.*' . $view_selects . ', GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ",") as wpgroups, GROUP_CONCAT(gr.id ORDER BY gr.name SEPARATOR ",") as wpgroupids, GROUP_CONCAT(gr.color ORDER BY gr.name SEPARATOR ",") as wpgroups_colors
2990 - FROM ' . $this->table_name( 'wp' ) . ' wp
2991 - JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
2992 - LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
2993 - LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
2994 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2995 - ' . $view_joins . '
2996 - WHERE wpgroup.groupid = ' . $id . ' ' .
2997 - ( empty( $where ) ? '' : ' AND ' . $where ) . $where_allowed . $where_search . '
2998 - GROUP BY wp.id, wp_sync.sync_id
2999 - ORDER BY ' . $orderBy;
3000 - } else {
3001 - $qry = 'SELECT wp.*' . $view_selects . ', wp_sync.* FROM ' . $this->table_name( 'wp' ) . ' wp
3002 - JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
3003 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
3004 - ' . $view_joins . '
3005 - WHERE wpgroup.groupid = ' . $id . ' ' . $where_allowed . $where_search .
3006 - ( empty( $where ) ? '' : ' AND ' . $where ) . ' ORDER BY ' . $orderBy;
3007 - }
3008 - if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
3009 - $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
3010 - } elseif ( false !== $rowcount ) {
3011 - $qry .= ' LIMIT ' . $rowcount;
3012 - }
1394 + return false;
1395 + }
3013 1396
3014 - return $qry;
3015 - }
1397 + public function updateNote( $websiteid, $note ) {
1398 + $this->wpdb->query( 'UPDATE ' . $this->tableName( 'wp' ) . ' SET note="' . $this->escape( $note ) . '", note_lastupdate = ' . time() . ' WHERE id=' . $websiteid );
1399 + }
3016 1400
3017 - return null;
3018 - }
1401 + public function updateWebsiteOfflineCheckSetting( $websiteid, $offlineChecks ) {
1402 + return $this->wpdb->query( 'UPDATE ' . $this->tableName( 'wp' ) . ' SET offline_checks="' . $this->escape( $offlineChecks ) . '" WHERE id=' . $websiteid, OBJECT );
1403 + }
3019 1404
3020 - /**
3021 - * Get child sites by group name.
3022 - *
3023 - * @param int $userid Current user ID.
3024 - * @param string $groupname Group name.
3025 - *
3026 - * @return object|null Database query result or null on failure.
3027 - */
3028 - public function get_websites_by_group_name( $userid, $groupname ) {
3029 - return $this->get_results_result( $this->get_sql_websites_by_group_name( $groupname, $userid ) );
3030 - }
1405 + public function updateWebsiteValues( $websiteid, $fields ) {
1406 + if ( count( $fields ) > 0 ) {
1407 + return $this->wpdb->update( $this->tableName( 'wp' ), $fields, array( 'id' => $websiteid ) );
1408 + }
3031 1409
3032 - /**
3033 - * Get child sites by group name.
3034 - *
3035 - * @param string $groupname Group name.
3036 - * @param int $userid Current user ID.
3037 - *
3038 - * @return object|null Database query result or null on failure.
3039 - *
3040 - * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
3041 - */
3042 - public function get_sql_websites_by_group_name( $groupname, $userid = null ) {
3043 - if ( ( null === $userid ) && MainWP_System::instance()->is_multi_user() ) {
1410 + return false;
1411 + }
3044 1412
3045 - /**
3046 - * Current user global.
3047 - *
3048 - * @global string
3049 - */
3050 - global $current_user;
1413 + public function updateWebsiteSyncValues( $websiteid, $fields ) {
1414 + if ( count( $fields ) > 0 ) {
1415 + return $this->wpdb->update( $this->tableName( 'wp_sync' ), $fields, array( 'wpid' => $websiteid ) );
1416 + }
3051 1417
3052 - $userid = $current_user->ID;
3053 - }
1418 + return false;
1419 + }
3054 1420
3055 - $view_selects = '';
3056 - $view_joins = '';
1421 + public function updateWebsite( $websiteid, $url, $userid, $name, $siteadmin, $groupids, $groupnames, $offlineChecks,
1422 + $pluginDir, $maximumFileDescriptorsOverride, $maximumFileDescriptorsAuto, $maximumFileDescriptors,
1423 + $verifyCertificate = 1, $archiveFormat, $uniqueId = '', $http_user = null, $http_pass = null, $sslVersion = 0,
1424 + $wpe = 0 ) {
1425 + if ( MainWP_Utility::ctype_digit( $websiteid ) && MainWP_Utility::ctype_digit( $userid ) ) {
1426 + $website = MainWP_DB::Instance()->getWebsiteById( $websiteid );
1427 + if ( MainWP_Utility::can_edit_website( $website ) ) {
1428 + //update admin
1429 + $this->wpdb->query( 'UPDATE ' . $this->tableName( 'wp' ) . ' SET url="' . $this->escape( $url ) . '", name="' . $this->escape( strip_tags($name) ) . '", adminname="' . $this->escape( $siteadmin ) . '",offline_checks="' . $this->escape( $offlineChecks ) . '",pluginDir="' . $this->escape( $pluginDir ) . '",maximumFileDescriptorsOverride = ' . ( $maximumFileDescriptorsOverride ? 1 : 0 ) . ',maximumFileDescriptorsAuto= ' . ( $maximumFileDescriptorsAuto ? 1 : 0 ) . ',maximumFileDescriptors = ' . $maximumFileDescriptors . ', verify_certificate="' . intval( $verifyCertificate ) . '", ssl_version="' . intval( $sslVersion ) . '", wpe="' . intval( $wpe ) . '", uniqueId="' . $this->escape( $uniqueId ) . '", http_user="' . $this->escape( $http_user ) . '", http_pass="' . $this->escape( $http_pass ) . '" WHERE id=' . $websiteid );
1430 + $this->wpdb->query( 'UPDATE ' . $this->tableName( 'wp_settings_backup' ) . ' SET archiveFormat = "' . $this->escape( $archiveFormat ) . '" WHERE wpid=' . $websiteid );
1431 + //remove groups
1432 + $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'wp_group' ) . ' WHERE wpid=' . $websiteid );
1433 + //Remove GA stats
1434 + $showErrors = $this->wpdb->hide_errors();
1435 + do_action( 'mainwp_ga_delete_site', $websiteid );
1436 + if ( $showErrors ) {
1437 + $this->wpdb->show_errors();
1438 + }
1439 + //add groups with groupnames
1440 + foreach ( $groupnames as $groupname ) {
1441 + if ( $this->wpdb->insert( $this->tableName( 'group' ), array(
1442 + 'userid' => $userid,
1443 + 'name' => $this->escape( $groupname ),
1444 + ) )
1445 + ) {
1446 + $groupids[] = $this->wpdb->insert_id;
1447 + }
1448 + }
1449 + //add groupids
1450 + foreach ( $groupids as $groupid ) {
1451 + $this->wpdb->insert( $this->tableName( 'wp_group' ), array(
1452 + 'wpid' => $websiteid,
1453 + 'groupid' => $groupid,
1454 + ) );
1455 + }
3057 1456
3058 - $opts_view = $this->get_wp_options_join();
1457 + return true;
1458 + }
1459 + }
3059 1460
3060 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
3061 - $view_selects = ',' . $opts_view['selects'];
3062 - $view_joins = $opts_view['joins'];
3063 - }
1461 + return false;
1462 + }
3064 1463
3065 - $sql = 'SELECT wp.*,wp_sync.*' . $view_selects . ' FROM ' . $this->table_name( 'wp' ) . ' wp
3066 - INNER JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
3067 - JOIN ' . $this->table_name( 'group' ) . ' g ON wpgroup.groupid = g.id
3068 - JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
3069 - ' . $view_joins . '
3070 - WHERE g.name="' . $this->escape( $groupname ) . '"';
3071 - if ( null !== $userid ) {
3072 - $sql .= ' AND g.userid = "' . intval( $userid ) . '"';
3073 - }
1464 + public function updateGroup( $groupid, $groupname ) {
1465 + if ( MainWP_Utility::ctype_digit( $groupid ) ) {
1466 + //update groupname
1467 + $this->wpdb->query( 'UPDATE ' . $this->tableName( 'group' ) . ' SET name="' . $this->escape( $groupname ) . '" WHERE id=' . $groupid );
3074 1468
3075 - return $sql;
3076 - }
1469 + return true;
1470 + }
3077 1471
3078 - /**
3079 - * Get child site IP address.
3080 - *
3081 - * @param int $wpid Child site ID.
3082 - *
3083 - * @return string|null Child site IP address or null on failure.
3084 - */
3085 - public function get_wp_ip( $wpid ) {
3086 - $table_name = esc_sql( $this->table_name( 'request_log' ) );
3087 - return $this->wpdb->get_var( $this->wpdb->prepare( "SELECT ip FROM {$table_name} WHERE wpid = %d", $wpid ) );
3088 - }
1472 + return false;
1473 + }
3089 1474
3090 - /**
3091 - * Add website to the MainWP Dashboard.
3092 - *
3093 - * @param int $userid Current user ID.
3094 - * @param string $name Child site name.
3095 - * @param string $url Child site URL.
3096 - * @param string $admin Child site administrator username.
3097 - * @param string $pubkey OpenSSL public key.
3098 - * @param string $privkey OpenSSL private key.
3099 - * @param array $params Other params.
3100 - *
3101 - * @return int|false Child site ID or false on failure.
3102 - *
3103 - * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
3104 - */
3105 - public function add_website( // phpcs:ignore -- NOSONAR - complex.
3106 - $userid,
3107 - $name,
3108 - $url,
3109 - $admin,
3110 - $pubkey,
3111 - $privkey,
3112 - $params = array()
3113 - ) {
1475 + public function updateBackupTaskProgress( $task_id, $wp_id, $values ) {
1476 + $this->wpdb->update( $this->tableName( 'wp_backup_progress' ), $values, array(
1477 + 'task_id' => $task_id,
1478 + 'wp_id' => $wp_id,
1479 + ) );
3114 1480
3115 - if ( ! is_array( $params ) ) {
3116 - $params = array();
3117 - }
1481 + return $this->getBackupTaskProgress( $task_id, $wp_id );
1482 + }
3118 1483
3119 - $groupids = isset( $params['groupids'] ) ? $params['groupids'] : array();
3120 - $groupnames = isset( $params['groupnames'] ) ? $params['groupnames'] : array();
3121 - $verifyCertificate = isset( $params['verifyCertificate'] ) ? (int) $params['verifyCertificate'] : 2;
3122 - $uniqueId = isset( $params['uniqueId'] ) ? $params['uniqueId'] : '';
3123 - $http_user = isset( $params['http_user'] ) ? $params['http_user'] : null;
3124 - $http_pass = isset( $params['http_pass'] ) ? $params['http_pass'] : null;
3125 - $sslVersion = isset( $params['sslVersion'] ) ? $params['sslVersion'] : 0;
3126 - $wpe = isset( $params['wpe'] ) ? $params['wpe'] : 0;
3127 - $isStaging = isset( $params['isStaging'] ) ? $params['isStaging'] : 0;
1484 + public function addBackupTaskProgress( $task_id, $wp_id, $information ) {
1485 + $values = array(
1486 + 'task_id' => $task_id,
1487 + 'wp_id' => $wp_id,
1488 + 'dtsFetched' => time(),
1489 + 'fetchResult' => json_encode( $information ),
1490 + 'removedFiles' => 0,
1491 + 'downloadedDB' => '',
1492 + 'downloadedFULL' => '',
1493 + );
3128 1494
3129 - // MWP-1548: encrypt http_user / http_pass at rest. Empty / null
3130 - // values pass through unchanged (encrypt_credential is a no-op
3131 - // for those). A non-empty value that fails to encrypt produces
3132 - // false here, which we treat as a hard failure -- refuse to
3133 - // persist plaintext credentials when the encryption layer is
3134 - // unhealthy (missing keyfile, un-writable uploads dir).
3135 - $encrypted_http_user = MainWP_Credential_Storage::encrypt_credential( $http_user, 'http_user' );
3136 - $encrypted_http_pass = MainWP_Credential_Storage::encrypt_credential( $http_pass, 'http_pass' );
3137 - if ( false === $encrypted_http_user || false === $encrypted_http_pass ) {
3138 - return false;
3139 - }
1495 + if ( $this->wpdb->insert( $this->tableName( 'wp_backup_progress' ), $values ) ) {
1496 + return $this->getBackupTaskProgress( $task_id, $wp_id );
1497 + }
3140 1498
3141 - if ( MainWP_Utility::ctype_digit( $userid ) ) {
3142 - if ( '/' !== substr( $url, - 1 ) ) {
3143 - $url .= '/';
3144 - }
1499 + return null;
1500 + }
3145 1501
3146 - $en_pk_data = MainWP_Encrypt_Data_Lib::instance()->encrypt_privkey( base64_decode( $privkey ) ); // phpcs:ignore -- NOSONAR - base64_encode trust.
3147 - $en_privkey = isset( $en_pk_data['en_data'] ) ? $en_pk_data['en_data'] : '';
1502 + public function getBackupTaskProgress( $task_id, $wp_id ) {
1503 + $progress = $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'wp_backup_progress' ) . ' WHERE task_id= ' . $task_id . ' AND wp_id = ' . $wp_id );
3148 1504
3149 - $values = array(
3150 - 'userid' => $userid,
3151 - 'adminname' => $this->escape( $admin ),
3152 - 'name' => $this->escape( wp_strip_all_tags( $name ) ),
3153 - 'url' => $this->escape( $url ),
3154 - 'pubkey' => $this->escape( $pubkey ),
3155 - 'privkey' => $this->escape( base64_encode( $en_privkey ) ), // phpcs:ignore -- NOSONAR - trust.
3156 - 'siteurl' => '',
3157 - 'ga_id' => '',
3158 - 'gas_id' => 0,
3159 - 'offline_checks_last' => 0,
3160 - 'offline_check_result' => 0,
3161 - 'note' => '',
3162 - 'statsUpdate' => 0,
3163 - 'directories' => '',
3164 - 'plugin_upgrades' => '',
3165 - 'theme_upgrades' => '',
3166 - 'translation_upgrades' => '',
3167 - 'securityIssues' => '',
3168 - 'premium_upgrades' => '',
3169 - 'themes' => '',
3170 - 'ignored_themes' => '',
3171 - 'plugins' => '',
3172 - 'ignored_plugins' => '',
3173 - 'users' => '',
3174 - 'categories' => '',
3175 - 'pluginDir' => '',
3176 - 'automatic_update' => 0,
3177 - 'backup_before_upgrade' => 2,
3178 - 'verify_certificate' => intval( $verifyCertificate ),
3179 - 'ssl_version' => $sslVersion,
3180 - 'uniqueId' => $uniqueId,
3181 - 'mainwpdir' => 0,
3182 - 'http_user' => $encrypted_http_user,
3183 - 'http_pass' => $encrypted_http_pass,
3184 - 'wpe' => $wpe,
3185 - 'is_staging' => $isStaging,
3186 - );
1505 + if ( $progress->fetchResult != '' ) {
1506 + $progress->fetchResult = json_decode( $progress->fetchResult, true );
1507 + }
3187 1508
3188 - $syncValues = array(
3189 - 'dtsSync' => 0,
3190 - 'dtsSyncStart' => 0,
3191 - 'dtsAutomaticSync' => 0,
3192 - 'dtsAutomaticSyncStart' => 0,
3193 - 'totalsize' => 0,
3194 - 'extauth' => '',
3195 - 'sync_errors' => '',
3196 - );
3197 - if ( $this->wpdb->insert( $this->table_name( 'wp' ), $values ) ) {
3198 - $websiteid = $this->wpdb->insert_id;
3199 - MainWP_Logger::instance()->log_events( 'db-queries', sprintf( '[Insert site=%s]', $this->get_last_query() ) ); // after: $this->wpdb->insert_id.
3200 - MainWP_Encrypt_Data_Lib::instance()->encrypt_save_keys( $websiteid, $en_pk_data );
3201 - $syncValues['wpid'] = $websiteid;
3202 - $this->wpdb->insert( $this->table_name( 'wp_sync' ), $syncValues );
3203 - MainWP_Logger::instance()->log_events( 'db-queries', sprintf( '[Insert sync data=%s]', $this->get_last_query() ) );
3204 - $this->wpdb->insert(
3205 - $this->table_name( 'wp_settings_backup' ),
3206 - array(
3207 - 'wpid' => $websiteid,
3208 - 'archiveFormat' => 'global',
3209 - )
3210 - );
1509 + return $progress;
1510 + }
3211 1511
3212 - foreach ( $groupnames as $groupname ) {
3213 - if ( $this->wpdb->insert(
3214 - $this->table_name( 'group' ),
3215 - array(
3216 - 'userid' => $userid,
3217 - 'name' => $this->escape( htmlspecialchars( $groupname ) ),
3218 - )
3219 - )
3220 - ) {
3221 - $groupids[] = $this->wpdb->insert_id;
3222 - }
3223 - }
3224 - // add groupids.
3225 - foreach ( $groupids as $groupid ) {
3226 - $this->wpdb->insert(
3227 - $this->table_name( 'wp_group' ),
3228 - array(
3229 - 'wpid' => $websiteid,
3230 - 'groupid' => $groupid,
3231 - )
3232 - );
3233 - }
3234 - MainWP_Manage_Sites_List_Table::invalidate_manage_sites_cache();
3235 - return $websiteid;
3236 - }
3237 - }
1512 + public function backupFullTaskRunning( $wp_id ) {
3238 1513
3239 - return false;
3240 - }
1514 + if (!get_option('mainwp_enableLegacyBackupFeature')) {
1515 + return false;
1516 + }
3241 1517
3242 - /**
3243 - * Remove child site from the MainWP Dashboard.
3244 - *
3245 - * @param int $websiteid Child site ID.
3246 - *
3247 - * @return int|boolean Return child site ID that was removed or false on failure.
3248 - *
3249 - * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
3250 - */
3251 - public function remove_website( $websiteid ) {
3252 - if ( MainWP_Utility::ctype_digit( $websiteid ) ) {
3253 - $nr = $this->wpdb->delete( $this->table_name( 'wp' ), array( 'id' => $websiteid ) );
3254 - $this->wpdb->delete( $this->table_name( 'wp_group' ), array( 'wpid' => $websiteid ) );
3255 - $this->wpdb->delete( $this->table_name( 'wp_sync' ), array( 'wpid' => $websiteid ) );
3256 - $this->wpdb->delete( $this->table_name( 'wp_options' ), array( 'wpid' => $websiteid ) );
3257 - MainWP_Encrypt_Data_Lib::remove_key_file( $websiteid );
3258 - MainWP_DB_Uptime_Monitoring::instance()->delete_monitor( array( 'wpid' => $websiteid ) );
3259 - MainWP_Manage_Sites_List_Table::invalidate_manage_sites_cache();
3260 - return $nr;
3261 - }
1518 + $progresses = $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp_backup_progress' ) . ' WHERE wp_id = ' . $wp_id . ' AND dtsFetched > ' . (time() - (30 * 60)) );
1519 + if ( is_array( $progresses ) ) {
1520 + foreach ( $progresses as $progress ) {
1521 + if ( ( $progress->downloadedDBComplete == 0 ) && ( $progress->downloadedFULLComplete == 0 ) ) {
1522 + if ( $task = $this->getBackupTaskById( $progress->task_id ) ) {
1523 + if ( ( 'full' == $task->type ) && !$task->paused ) {
1524 + return true;
1525 + }
1526 + }
1527 + }
1528 + }
1529 + }
1530 + return false;
1531 + }
3262 1532
3263 - return false;
3264 - }
1533 + public function removeBackupTask( $id ) {
1534 + $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'wp_backup' ) . ' WHERE id = ' . $id );
1535 + }
3265 1536
3266 - /**
3267 - * Update child site db values.
3268 - *
3269 - * @param int $websiteid Child site ID.
3270 - * @param array $fields Database fields to update.
3271 - *
3272 - * @return int|boolean The number of rows updated, or false on error.
3273 - */
3274 - public function update_website_values( $websiteid, $fields ) {
3275 - if ( ! empty( $fields ) ) {
3276 - // MWP-1548: encrypt http_user / http_pass at rest if either
3277 - // is present in $fields. Generic-fields updaters (clone
3278 - // flow in extensions-handler, callers that pass arbitrary
3279 - // column subsets) must go through the same fail-closed
3280 - // contract as add_website / update_website.
3281 - if ( array_key_exists( 'http_user', $fields ) ) {
3282 - $encrypted = MainWP_Credential_Storage::encrypt_credential( $fields['http_user'], 'http_user' );
3283 - if ( false === $encrypted ) {
3284 - return false;
3285 - }
3286 - $fields['http_user'] = $encrypted;
3287 - }
3288 - if ( array_key_exists( 'http_pass', $fields ) ) {
3289 - $encrypted = MainWP_Credential_Storage::encrypt_credential( $fields['http_pass'], 'http_pass' );
3290 - if ( false === $encrypted ) {
3291 - return false;
3292 - }
3293 - $fields['http_pass'] = $encrypted;
3294 - }
3295 - // Lock the data stream to prevent other processes from updating at the same time.
3296 - $table_name = esc_sql( $this->table_name( 'wp' ) );
3297 - $sql = $this->wpdb->prepare(
3298 - "SELECT * FROM {$table_name} WHERE id = %d FOR UPDATE",
3299 - $websiteid
3300 - );
3301 - $this->wpdb->get_row( $sql );
1537 + public function getBackupTaskById( $id ) {
1538 + return $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'wp_backup' ) . ' WHERE id= ' . $id );
1539 + }
3302 1540
3303 - return $this->wpdb->update( $this->table_name( 'wp' ), $fields, array( 'id' => $websiteid ) );
3304 - }
1541 + public function getBackupTasksForUser( $orderBy = 'name' ) {
1542 + if ( MainWP_System::Instance()->isSingleUser() ) {
1543 + return $this->getBackupTasks( null, $orderBy );
1544 + }
3305 1545
3306 - return false;
3307 - }
1546 + global $current_user;
3308 1547
3309 - /**
3310 - * Update child site sync values.
3311 - *
3312 - * @param int $websiteid Child site ID.
3313 - * @param array $fields Database fields to update.
3314 - *
3315 - * @return int|boolean The number of rows updated, or false on error.
3316 - */
3317 - public function update_website_sync_values( $websiteid, $fields ) {
3318 - if ( ! empty( $fields ) ) {
3319 - return $this->wpdb->update( $this->table_name( 'wp_sync' ), $fields, array( 'wpid' => $websiteid ) );
3320 - }
1548 + return $this->getBackupTasks( $current_user->ID, $orderBy );
1549 + }
3321 1550
3322 - return false;
3323 - }
1551 + public function getBackupTasks( $userid = null, $orderBy = null ) {
1552 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp_backup' ) . ' WHERE ' . ( $userid == null ? '' : 'userid= ' . $userid . ' AND ' ) . ' template = 0 ' . ( $orderBy != null ? 'ORDER BY ' . $orderBy : '' ), OBJECT );
1553 + }
3324 1554
3325 - /**
3326 - * Update child site.
3327 - *
3328 - * @param int $websiteid Website ID.
3329 - * @param string $url Child site URL.
3330 - * @param int $userid Current user ID.
3331 - * @param string $name Child site name.
3332 - * @param string $siteadmin Child site administrator username.
3333 - * @param array $groupids Group IDs.
3334 - * @param array $groupnames Group Names.
3335 - * @param string $pluginDir Plugin directory.
3336 - * @param mixed $maximumFileDescriptorsOverride Overwrite the Maximum File Descriptors option.
3337 - * @param mixed $maximumFileDescriptorsAuto Auto set the Maximum File Descriptors option.
3338 - * @param mixed $maximumFileDescriptors Set the Maximum File Descriptors option.
3339 - * @param int $verifyCertificate Whether or not to verify SSL Certificate.
3340 - * @param mixed $archiveFormat Backup archive formate.
3341 - * @param string $uniqueId Unique security ID.
3342 - * @param string $http_user HTTP Basic Authentication username.
3343 - * @param string $http_pass HTTP Basic Authentication password.
3344 - * @param int $sslVersion SSL Version.
3345 - * @param bool $disableHealthChecking Disable Site health threshold.
3346 - * @param int $healthThreshold Site health threshold.
3347 - * @param string $backup_method Primary backup method.
3348 - *
3349 - * @return boolean ture on success or false on failure.
3350 - *
3351 - * @uses \MainWP\Dashboard\MainWP_System_Utility::can_edit_website()
3352 - * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
3353 - */
3354 - public function update_website( // phpcs:ignore -- NOSONAR - complex.
3355 - $websiteid,
3356 - $url,
3357 - $userid,
3358 - $name,
3359 - $siteadmin,
3360 - $groupids,
3361 - $groupnames,
3362 - $pluginDir,
3363 - $maximumFileDescriptorsOverride,
3364 - $maximumFileDescriptorsAuto,
3365 - $maximumFileDescriptors,
3366 - $verifyCertificate = 1,
3367 - $archiveFormat = 'global',
3368 - $uniqueId = '',
3369 - $http_user = null,
3370 - $http_pass = null,
3371 - $sslVersion = 0,
3372 - $disableHealthChecking = 1,
3373 - $healthThreshold = 0,
3374 - $backup_method = 'global'
3375 - ) {
1555 + public function addBackupTask( $userid, $name, $schedule, $type, $exclude, $sites, $groups, $subfolder, $filename,
1556 + $template, $excludebackup, $excludecache, $excludenonwp, $excludezip, $archiveFormat,
1557 + $maximumFileDescriptorsOverride, $maximumFileDescriptorsAuto, $maximumFileDescriptors, $loadFilesBeforeZip ) {
1558 + if ( MainWP_Utility::ctype_digit( $userid ) ) {
1559 + $values = array(
1560 + 'userid' => $userid,
1561 + 'name' => $name,
1562 + 'schedule' => $schedule,
1563 + 'type' => $type,
1564 + 'exclude' => $exclude,
1565 + 'sites' => $sites,
1566 + 'groups' => $groups,
1567 + 'last' => 0,
1568 + 'last_run' => 0,
1569 + 'last_run_manually' => 0,
1570 + 'completed_sites' => '',
1571 + 'completed' => 0,
1572 + 'backup_errors' => '',
1573 + 'subfolder' => MainWP_Utility::removePreSlashSpaces( $subfolder ),
1574 + 'filename' => $filename,
1575 + 'paused' => 0,
1576 + 'template' => $template,
1577 + 'excludebackup' => $excludebackup,
1578 + 'excludecache' => $excludecache,
1579 + 'excludenonwp' => $excludenonwp,
1580 + 'excludezip' => $excludezip,
1581 + 'archiveFormat' => $archiveFormat,
1582 + 'loadFilesBeforeZip' => $loadFilesBeforeZip,
1583 + 'maximumFileDescriptorsOverride' => $maximumFileDescriptorsOverride,
1584 + 'maximumFileDescriptorsAuto' => $maximumFileDescriptorsAuto,
1585 + 'maximumFileDescriptors' => $maximumFileDescriptors,
1586 + );
3376 1587
3377 - $wpe = 0; // going to update when sync.
1588 + if ( $this->wpdb->insert( $this->tableName( 'wp_backup' ), $values ) ) {
1589 + return $this->getBackupTaskById( $this->wpdb->insert_id );
1590 + }
1591 + }
3378 1592
3379 - if ( MainWP_Utility::ctype_digit( $websiteid ) && MainWP_Utility::ctype_digit( $userid ) ) {
3380 - $website = $this->get_website_by_id( $websiteid );
3381 - if ( MainWP_System_Utility::can_edit_website( $website ) ) {
3382 - // MWP-1548: encrypt http_user / http_pass at rest. Same
3383 - // fail-closed contract as add_website -- a non-empty
3384 - // value that fails to encrypt aborts the update so we
3385 - // never overwrite an existing encrypted row with
3386 - // plaintext when the encryption layer is unhealthy.
3387 - $encrypted_http_user = MainWP_Credential_Storage::encrypt_credential( $http_user, 'http_user' );
3388 - $encrypted_http_pass = MainWP_Credential_Storage::encrypt_credential( $http_pass, 'http_pass' );
3389 - if ( false === $encrypted_http_user || false === $encrypted_http_pass ) {
3390 - return false;
3391 - }
3392 - // update admin.
3393 - $this->wpdb->update(
3394 - $this->table_name( 'wp' ),
3395 - array(
3396 - 'url' => $url,
3397 - 'name' => wp_strip_all_tags( $name ),
3398 - 'adminname' => $siteadmin,
3399 - 'pluginDir' => $pluginDir,
3400 - 'verify_certificate' => intval( $verifyCertificate ),
3401 - 'ssl_version' => intval( $sslVersion ),
3402 - 'wpe' => intval( $wpe ),
3403 - 'uniqueId' => $uniqueId,
3404 - 'http_user' => $encrypted_http_user,
3405 - 'http_pass' => $encrypted_http_pass,
3406 - 'disable_health_check' => $disableHealthChecking,
3407 - 'health_threshold' => $healthThreshold,
3408 - 'primary_backup_method' => $backup_method,
3409 - ),
3410 - array( 'id' => $websiteid )
3411 - );
3412 - $this->wpdb->update(
3413 - $this->table_name( 'wp_settings_backup' ),
3414 - array( 'archiveFormat' => $archiveFormat ),
3415 - array( 'wpid' => $websiteid )
3416 - );
1593 + return false;
1594 + }
3417 1595
3418 - if ( get_option( 'mainwp_enableLegacyBackupFeature' ) ) {
3419 - $this->wpdb->update(
3420 - $this->table_name( 'wp' ),
3421 - array(
3422 - 'maximumFileDescriptorsOverride' => (int) $maximumFileDescriptorsOverride,
3423 - 'maximumFileDescriptorsAuto' => (int) $maximumFileDescriptorsAuto,
3424 - 'maximumFileDescriptors' => (int) $maximumFileDescriptors,
3425 - ),
3426 - array( 'id' => $websiteid )
3427 - );
3428 - }
1596 + public function updateBackupTask( $id, $userid, $name, $schedule, $type, $exclude, $sites, $groups, $subfolder,
1597 + $filename, $excludebackup, $excludecache, $excludenonwp, $excludezip, $archiveFormat,
1598 + $maximumFileDescriptorsOverride, $maximumFileDescriptorsAuto, $maximumFileDescriptors, $loadFilesBeforeZip ) {
1599 + if ( MainWP_Utility::ctype_digit( $userid ) && MainWP_Utility::ctype_digit( $id ) ) {
1600 + return $this->wpdb->update( $this->tableName( 'wp_backup' ), array(
1601 + 'userid' => $userid,
1602 + 'name' => $name,
1603 + 'schedule' => $schedule,
1604 + 'type' => $type,
1605 + 'exclude' => $exclude,
1606 + 'sites' => $sites,
1607 + 'groups' => $groups,
1608 + 'subfolder' => MainWP_Utility::removePreSlashSpaces( $subfolder ),
1609 + 'filename' => $filename,
1610 + 'excludebackup' => $excludebackup,
1611 + 'excludecache' => $excludecache,
1612 + 'excludenonwp' => $excludenonwp,
1613 + 'excludezip' => $excludezip,
1614 + 'archiveFormat' => $archiveFormat,
1615 + 'loadFilesBeforeZip' => $loadFilesBeforeZip,
1616 + 'maximumFileDescriptorsOverride' => $maximumFileDescriptorsOverride,
1617 + 'maximumFileDescriptorsAuto' => $maximumFileDescriptorsAuto,
1618 + 'maximumFileDescriptors' => $maximumFileDescriptors,
1619 + ), array( 'id' => $id ) );
1620 + }
3429 1621
3430 - // remove groups.
3431 - $this->wpdb->delete( $this->table_name( 'wp_group' ), array( 'wpid' => $websiteid ) );
3432 - // Remove GA stats.
3433 - $showErrors = $this->wpdb->hide_errors();
1622 + return false;
1623 + }
3434 1624
3435 - /**
3436 - * Action: mainwp_ga_delete_site
3437 - *
3438 - * Fires upon site removal process in order to delete Google Analytics data.
3439 - *
3440 - * @param int $websiteid Child site ID.
3441 - *
3442 - * @since Unknown
3443 - */
3444 - do_action( 'mainwp_ga_delete_site', $websiteid );
1625 + public function updateBackupTaskWithValues( $id, $values ) {
1626 + if ( !is_array( $values ) ) {
1627 + return false;
1628 + }
3445 1629
3446 - if ( $showErrors ) {
3447 - $this->wpdb->show_errors();
3448 - }
3449 - // add groups with groupnames.
3450 - foreach ( $groupnames as $groupname ) {
3451 - if ( $this->wpdb->insert(
3452 - $this->table_name( 'group' ),
3453 - array(
3454 - 'userid' => $userid,
3455 - 'name' => $this->escape( $groupname ),
3456 - )
3457 - )
3458 - ) {
3459 - $groupids[] = $this->wpdb->insert_id;
3460 - }
3461 - }
3462 - // add groupids.
3463 - foreach ( $groupids as $groupid ) {
3464 - $this->wpdb->insert(
3465 - $this->table_name( 'wp_group' ),
3466 - array(
3467 - 'wpid' => $websiteid,
3468 - 'groupid' => $groupid,
3469 - )
3470 - );
3471 - }
1630 + return $this->wpdb->update( $this->tableName( 'wp_backup' ), $values, array( 'id' => $id ) );
1631 + }
3472 1632
3473 - return true;
3474 - }
3475 - }
1633 + public function updateBackupRun( $id ) {
1634 + if ( MainWP_Utility::ctype_digit( $id ) ) {
1635 + return $this->wpdb->update( $this->tableName( 'wp_backup' ), array(
1636 + 'last_run' => time(),
1637 + 'last' => time(),
1638 + 'completed_sites' => json_encode( array() ),
1639 + ), array( 'id' => $id ) );
1640 + }
3476 1641
3477 - return false;
3478 - }
1642 + return false;
1643 + }
3479 1644
1645 + public function updateBackupRunManually( $id ) {
1646 + if ( MainWP_Utility::ctype_digit( $id ) ) {
1647 + return $this->wpdb->update( $this->tableName( 'wp_backup' ), array( 'last_run_manually' => time() ), array( 'id' => $id ) );
1648 + }
3480 1649
3481 - /**
3482 - * Get website update stats via SQL.
3483 - *
3484 - * @return object|null Database query result of null on failure.
3485 - */
3486 - public function get_websites_stats_update_sql() {
3487 - $where = $this->get_sql_where_allow_access_sites( 'wp' );
3488 - return 'SELECT wp.*,wp_sync.sync_errors FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid WHERE (wp.statsUpdate = 0 OR ' . time() . ' - wp.statsUpdate >= ' . ( 60 * 60 * 24 ) . ')' . $where . ' ORDER BY wp.statsUpdate ASC';
3489 - }
1650 + return false;
1651 + }
3490 1652
3491 - /**
3492 - * Update child site statistics.
3493 - *
3494 - * Update whether or not a child site has been updated.
3495 - *
3496 - * @param mixed $websiteid Child site ID.
3497 - * @param mixed $statsUpdated Child site Update status.
3498 - *
3499 - * @return (int|boolean) Number of rows effected in update or false on failure.
3500 - */
3501 - public function update_website_stats( $websiteid, $statsUpdated ) {
3502 - return $this->wpdb->update(
3503 - $this->table_name( 'wp' ),
3504 - array( 'statsUpdate' => $statsUpdated ),
3505 - array( 'id' => $websiteid )
3506 - );
3507 - }
1653 + public function updateBackupCompleted( $id ) {
1654 + if ( MainWP_Utility::ctype_digit( $id ) ) {
1655 + return $this->wpdb->update( $this->tableName( 'wp_backup' ), array( 'completed' => time() ), array( 'id' => $id ) );
1656 + }
3508 1657
3509 - /**
3510 - * Get child site by url.
3511 - *
3512 - * @param string $url Child site URL.
3513 - *
3514 - * @return object|null Database query result or null on failure.
3515 - */
3516 - public function get_websites_by_url( $url ) {
3517 - if ( '/' !== substr( $url, - 1 ) ) {
3518 - $url .= '/';
3519 - }
3520 - $wp_table = esc_sql( $this->table_name( 'wp' ) );
3521 - $wp_sync_table = esc_sql( $this->table_name( 'wp_sync' ) );
3522 - $results = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT * FROM {$wp_table} wp JOIN {$wp_sync_table} wp_sync ON wp.id = wp_sync.wpid WHERE wp.url = %s", $url ), OBJECT );
3523 - if ( $results ) {
3524 - return $results;
3525 - }
1658 + return false;
1659 + }
3526 1660
3527 - if ( stristr( $url, '/www.' ) ) {
3528 - // remove www if it's there!
3529 - $url = str_replace( '/www.', '/', $url );
3530 - } else {
3531 - // add www if it's not there!
3532 - $url = str_replace( 'https://', 'https://www.', $url );
3533 - $url = str_replace( 'http://', 'http://www.', $url );
3534 - }
1661 + public function updateBackupErrors( $id, $errors ) {
1662 + if ( MainWP_Utility::ctype_digit( $id ) ) {
1663 + if ( $errors == '' ) {
1664 + return $this->wpdb->update( $this->tableName( 'wp_backup' ), array( 'backup_errors' => '' ), array( 'id' => $id ) );
1665 + } else {
1666 + $task = $this->getBackupTaskById( $id );
3535 1667
3536 - $results = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT * FROM {$wp_table} wp JOIN {$wp_sync_table} wp_sync ON wp.id = wp_sync.wpid WHERE wp.url = %s", $url ), OBJECT );
3537 - if ( $results ) {
3538 - return $results;
3539 - }
1668 + return $this->wpdb->update( $this->tableName( 'wp_backup' ), array( 'backup_errors' => $task->backup_errors . $errors ), array( 'id' => $id ) );
1669 + }
1670 + }
3540 1671
3541 - $url = str_replace( array( 'https://www.', 'http://www.', 'https://', 'http://', 'www.' ), array( '', '', '', '', '' ), $url );
1672 + return false;
1673 + }
3542 1674
3543 - return $this->wpdb->get_results( $this->wpdb->prepare( "SELECT * FROM {$wp_table} wp JOIN {$wp_sync_table} wp_sync ON wp.id = wp_sync.wpid WHERE replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '') = %s", $url ), OBJECT );
3544 - }
1675 + public function updateCompletedSites( $id, $completedSites ) {
1676 + if ( MainWP_Utility::ctype_digit( $id ) ) {
1677 + return $this->wpdb->update( $this->tableName( 'wp_backup' ), array( 'completed_sites' => json_encode( $completedSites ) ), array( 'id' => $id ) );
1678 + }
3545 1679
3546 - /**
3547 - * Method get_websites_to_notice_health_threshold()
3548 - *
3549 - * Get websites to notice site health.
3550 - *
3551 - * @param int $globalThreshold Global site health threshold.
3552 - */
3553 - public function get_websites_to_notice_health_threshold( $globalThreshold ) {
1680 + return false;
1681 + }
3554 1682
3555 - $where = $this->get_sql_where_allow_access_sites( 'wp' );
3556 - $extra_view = array( 'monitoring_notification_emails', 'settings_notification_emails' );
1683 + public function getOfflineChecks() {
1684 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp' ) . ' WHERE (offline_checks="hourly" AND ' . time() . ' - offline_checks_last >= ' . ( 60 * 60 * 1 ) . ') OR (offline_checks="2xday" AND ' . time() . ' - offline_checks_last >= ' . ( 60 * 60 * 12 * 1 ) . ') OR (offline_checks="daily" AND ' . time() . ' - offline_checks_last >= ' . ( 60 * 60 * 24 * 1 ) . ') OR (offline_checks="weekly" AND ' . time() . ' - offline_checks_last >= ' . ( 60 * 60 * 24 * 7 ) . ')', OBJECT );
1685 + }
3557 1686
3558 - if ( 80 >= $globalThreshold ) { // actual is 80.
3559 - // should-be-improved site health.
3560 - $where_global_threshold = '( wp.health_threshold = 0 AND wp_sync.health_value < 80 )';
3561 - } else {
3562 - // good site health.
3563 - $where_global_threshold = '( wp.health_threshold = 0 AND wp_sync.health_value >= 80 )';
3564 - }
1687 + public function getWebsitesCheckUpdatesCount() {
1688 + $where = $this->getWhereAllowAccessSites( 'wp' );
3565 1689
3566 - $where_site_threshold = ' ( wp.health_threshold = 80 AND wp_sync.health_value < 80 ) '; // should-be-improved site health.
3567 - $where_site_threshold .= ' OR ( wp.health_threshold = 100 AND wp_sync.health_value >= 80 ) '; // good site health.
1690 + return $this->wpdb->get_var( 'SELECT count(wp.id) FROM ' . $this->tableName( 'wp' ) . ' wp
1691 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1692 + WHERE (wp_sync.dtsAutomaticSyncStart = 0 OR DATE(FROM_UNIXTIME(wp_sync.dtsAutomaticSyncStart)) <> DATE(NOW())) ' . $where );
1693 + }
3568 1694
3569 - $wp_table = esc_sql( $this->table_name( 'wp' ) );
3570 - $wp_sync_table = esc_sql( $this->table_name( 'wp_sync' ) );
1695 + public function getWebsitesCountWhereDtsAutomaticSyncSmallerThenStart() {
1696 + $where = $this->getWhereAllowAccessSites( 'wp' );
3571 1697
3572 - $view_selects = '';
3573 - $view_joins = '';
1698 + //once a day
1699 + return $this->wpdb->get_var( 'SELECT count(wp.id) FROM ' . $this->tableName( 'wp' ) . ' wp
1700 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1701 + WHERE ((wp_sync.dtsAutomaticSync < wp_sync.dtsAutomaticSyncStart) OR (wp_sync.dtsAutomaticSyncStart = 0) OR (DATE(FROM_UNIXTIME(wp_sync.dtsAutomaticSyncStart)) <> DATE(NOW()))) ' . $where );
1702 + }
3574 1703
3575 - $opts_view = $this->get_wp_options_join( $extra_view );
1704 + public function getWebsitesLastAutomaticSync() {
1705 + //once a day
1706 + return $this->wpdb->get_var( 'SELECT MAX(wp_sync.dtsAutomaticSync) FROM ' . $this->tableName( 'wp' ) . ' wp
1707 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid' );
1708 + }
3576 1709
3577 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
3578 - $view_selects = ',' . $opts_view['selects'];
3579 - $view_joins = $opts_view['joins'];
3580 - }
3581 - return $this->wpdb->get_results( // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $option_view is a validated SQL subquery
3582 - "SELECT wp.*,wp_sync.* {$view_selects} FROM {$wp_table} wp
3583 - JOIN {$wp_sync_table} wp_sync ON wp.id = wp_sync.wpid
3584 - {$view_joins}
3585 - WHERE wp.disable_health_check <> 1 AND wp.offline_check_result = 1 AND ( {$where_global_threshold} OR{$where_site_threshold} ) AND wp_sync.health_site_noticed = 0 " .
3586 - $where . ' GROUP BY wp.id ',
3587 - OBJECT
3588 - );
3589 - }
1710 + public function getWebsitesCheckUpdates( $limit ) {
1711 + $where = $this->getWhereAllowAccessSites( 'wp' );
3590 1712
3591 - /**
3592 - * Get websites offline status.
3593 - *
3594 - * @return array Sites with offline status.
3595 - */
3596 - public function get_websites_http_check_status() {
3597 - $where = $this->get_sql_where_allow_access_sites( 'wp' );
3598 - $extra_view = array( 'settings_notification_emails' );
3599 - $wp_table = esc_sql( $this->table_name( 'wp' ) );
1713 + //once a day
1714 + return $this->wpdb->get_results( 'SELECT wp.*,wp_sync.*,wp_optionview.*
1715 + FROM ' . $this->tableName( 'wp' ) . ' wp
1716 + JOIN ' . $this->tableName( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1717 + JOIN ' . $this->getOptionView() . ' wp_optionview ON wp.id = wp_optionview.wpid
1718 + WHERE (wp_sync.dtsAutomaticSyncStart = 0 OR DATE(FROM_UNIXTIME(wp_sync.dtsAutomaticSyncStart)) <> DATE(NOW())) ' . $where . ' LIMIT 0,' . $limit, OBJECT );
1719 + }
3600 1720
3601 - $view_selects = '';
3602 - $view_joins = '';
1721 + public function getWebsitesStatsUpdateSQL() {
1722 + $where = $this->getWhereAllowAccessSites();
3603 1723
3604 - $opts_view = $this->get_wp_options_join( $extra_view );
1724 + //once a week
1725 + return 'SELECT * FROM ' . $this->tableName( 'wp' ) . ' WHERE (statsUpdate = 0 OR ' . time() . ' - statsUpdate >= ' . ( 60 * 60 * 24 * 7 ) . ')' . $where . ' ORDER BY statsUpdate ASC';
1726 + }
3605 1727
3606 - if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) {
3607 - $view_selects = ',' . $opts_view['selects'];
3608 - $view_joins = $opts_view['joins'];
3609 - }
1728 + public function updateWebsiteStats( $websiteid, $statsUpdated ) {
1729 + return $this->wpdb->update( $this->tableName( 'wp' ), array(
1730 + 'statsUpdate' => $statsUpdated,
1731 + ), array( 'id' => $websiteid ) );
1732 + }
3610 1733
3611 - // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- is a validated SQL subquery.
3612 - return $this->wpdb->get_results(
3613 - "SELECT wp.*{$view_selects} FROM {$wp_table} wp
3614 - {$view_joins}" . ' WHERE wp.suspended = 0 AND wp.http_code_noticed = 0 AND wp.offline_check_result = -1 ' .
3615 - $where . ' GROUP BY wp.id ',
3616 - OBJECT
3617 - );
3618 - }
1734 + public function getBackupTasksToComplete() {
1735 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp_backup' ) . ' WHERE paused = 0 AND completed < last_run'//AND '. time() . ' - last_run >= 120 AND ' . time() . ' - last >= 120'
1736 + , OBJECT );
1737 + }
3619 1738
3620 - /**
3621 - * Method set_website_noticed_http_check().
3622 - *
3623 - * @param array $site_id The site id .
3624 - *
3625 - * @return void
3626 - */
3627 - public function set_website_noticed_http_check( $site_id = array() ) {
3628 - if ( empty( $site_id ) ) {
3629 - return;
3630 - }
3631 - $this->wpdb->query( $this->wpdb->prepare( 'UPDATE ' . esc_sql( $this->table_name( 'wp' ) ) . ' SET http_code_noticed = 1 WHERE id = %d', $site_id ) ); // phpcs:ignore PluginCheck.Security.DirectDB.UnpreparedSQL -- $site_id is an integer that is validated by ctype_digit() before being passed to this method.
3632 - }
1739 + public function getBackupTasksTodoDaily() {
1740 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp_backup' ) . ' WHERE paused = 0 AND schedule="daily" AND ' . time() . ' - last_run >= ' . ( 60 * 60 * 24 ), OBJECT );
1741 + }
3633 1742
3634 - /**
3635 - * Get DB Sites.
3636 - *
3637 - * @since 4.6
3638 - *
3639 - * @param mixed $params params.
3640 - *
3641 - * @return array $dbwebsites.
3642 - */
3643 - public function get_db_sites( $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
1743 + public function getBackupTasksTodoWeekly() {
1744 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp_backup' ) . ' WHERE paused = 0 AND schedule="weekly" AND ' . time() . ' - last_run >= ' . ( 60 * 60 * 24 * 7 ), OBJECT );
1745 + }
3644 1746
3645 - $dbwebsites = array();
1747 + public function getBackupTasksTodoMonthly() {
1748 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'wp_backup' ) . ' WHERE paused = 0 AND schedule="monthly" AND ' . time() . ' - last_run >= ' . ( 60 * 60 * 24 * 30 ), OBJECT );
1749 + }
3646 1750
3647 - $data_fields = MainWP_System_Utility::get_default_map_site_fields();
3648 - $data_fields[] = 'verify_certificate';
3649 - $data_fields[] = 'client_id';
1751 + public function getUserNotificationEmail( $userid ) {
1752 + $theUserId = $userid;
1753 + if ( MainWP_System::Instance()->isSingleUser() ) {
1754 + $theUserId = 0;
1755 + }
1756 + $user_email = $this->wpdb->get_var( 'SELECT user_email FROM ' . $this->tableName( 'users' ) . ' WHERE userid = ' . $theUserId );
3650 1757
3651 - $fields = isset( $params['fields'] ) && is_array( $params['fields'] ) ? $params['fields'] : array();
3652 - $sites = isset( $params['sites'] ) && is_array( $params['sites'] ) ? $params['sites'] : array();
3653 - $groups = isset( $params['groups'] ) && is_array( $params['groups'] ) ? $params['groups'] : array();
3654 - $clients = isset( $params['clients'] ) && is_array( $params['clients'] ) ? $params['clients'] : array();
3655 - $schema_fields = isset( $params['schema_fields'] ) && is_array( $params['schema_fields'] ) ? $params['schema_fields'] : array(); // since 5.2.
3656 - $selectgroups = isset( $params['selectgroups'] ) && ! empty( $params['selectgroups'] ) ? true : false; // since 5.2.
1758 + if ( $user_email == null || $user_email == '' ) {
1759 + $user_email = $this->wpdb->get_var( 'SELECT user_email FROM ' . $this->wpdb->prefix . 'users WHERE id = ' . $userid );
1760 + }
3657 1761
3658 - if ( ! empty( $schema_fields ) ) { // since 5.2.
3659 - foreach ( $schema_fields as $field_name ) {
3660 - if ( ! in_array( $field_name, $data_fields ) ) {
3661 - $data_fields[] = $field_name;
3662 - }
3663 - }
3664 - } elseif ( is_array( $fields ) ) {
3665 - foreach ( $fields as $field_indx => $field_name ) {
1762 + return $user_email;
1763 + }
3666 1764
3667 - $get_field = $field_name;
3668 - if ( is_numeric( $get_field ) || is_bool( $get_field ) ) { // to compatible fix.
3669 - $get_field = $field_indx;
3670 - }
1765 + public function getUserExtension() {
1766 + global $current_user;
3671 1767
3672 - if ( in_array( $get_field, static::$possible_options ) && ! in_array( $get_field, $data_fields ) ) {
3673 - $data_fields[] = $get_field;
3674 - }
3675 - }
3676 - }
1768 + if ( empty( $current_user ) ) {
1769 + if ( MainWP_System::Instance()->isSingleUser() ) {
1770 + $userid = 0;
1771 + } else {
1772 + return false;
1773 + }
1774 + } else {
1775 + $userid = $current_user->ID;
1776 + }
3677 1777
3678 - if ( ! empty( $sites ) ) {
3679 - foreach ( $sites as $v ) {
3680 - if ( MainWP_Utility::ctype_digit( $v ) ) {
3681 - $website = static::instance()->get_website_by_id( $v, $selectgroups );
3682 - if ( empty( $website ) ) {
3683 - continue;
3684 - }
3685 - $dbwebsites[ $website->id ] = MainWP_Utility::map_site( $website, $data_fields );
3686 - }
3687 - }
3688 - }
1778 + return $this->getUserExtensionByUserId( $userid );
1779 + }
3689 1780
3690 - if ( ! empty( $groups ) ) {
3691 - foreach ( $groups as $v ) {
3692 - if ( MainWP_Utility::ctype_digit( $v ) ) {
3693 - $websites = static::instance()->query( static::instance()->get_sql_websites_by_group_id( $v, $selectgroups ) );
3694 - while ( $websites && ( $website = static::fetch_object( $websites ) ) ) {
3695 - $dbwebsites[ $website->id ] = MainWP_Utility::map_site( $website, $data_fields );
3696 - }
3697 - static::free_result( $websites );
3698 - }
3699 - }
3700 - }
1781 + public function getUserExtensionByUserId( $userid ) {
1782 + if ( MainWP_System::Instance()->isSingleUser() ) {
1783 + $userid = 0;
1784 + }
3701 1785
3702 - $params = array(
3703 - 'full_data' => true,
3704 - 'selectgroups' => $selectgroups,
3705 - );
3706 - $client_sites = MainWP_DB_Client::instance()->get_websites_by_client_ids( $clients, $params );
3707 - if ( $client_sites ) {
3708 - foreach ( $client_sites as $website ) {
3709 - $dbwebsites[ $website->id ] = MainWP_Utility::map_site( $website, $data_fields );
3710 - }
3711 - }
3712 - return $dbwebsites;
3713 - }
1786 + $row = $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'users' ) . ' WHERE userid= ' . $userid, OBJECT );
1787 + if ( $row == null ) {
1788 + $this->createUserExtension( $userid );
1789 + $row = $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'users' ) . ' WHERE userid= ' . $userid, OBJECT );
1790 + }
3714 1791
3715 - /**
3716 - * Get Sites.
3717 - *
3718 - * @param int $websiteid The id of the child site you wish to retrieve.
3719 - * @param bool $for_manager Check Team Control.
3720 - * @param array $others Array of others.
3721 - *
3722 - * @return array $output Array of content to output.
3723 - *
3724 - * @uses \MainWP\Dashboard\MainWP_System_Utility::can_edit_website()
3725 - * @uses \MainWP\Dashboard\MainWP_Utility::get_nice_url()
3726 - */
3727 - public function get_sites( $websiteid = null, $for_manager = false, $others = array() ) { // phpcs:ignore -- NOSONAR - not quite complex function.
1792 + return $row;
1793 + }
3728 1794
3729 - if ( ! is_array( $others ) ) {
3730 - $others = array();
3731 - }
1795 + protected function createUserExtension( $userId ) {
1796 + $fields = array(
1797 + 'userid' => $userId,
1798 + 'user_email' => '',
1799 + 'ignored_plugins' => '',
1800 + 'trusted_plugins' => '',
1801 + 'trusted_plugins_notes' => '',
1802 + 'ignored_themes' => '',
1803 + 'trusted_themes' => '',
1804 + 'trusted_themes_notes' => '',
1805 + 'pluginDir' => ''
1806 + );
3732 1807
3733 - $search_site = null;
3734 - $orderBy = 'wp.url';
3735 - $offset = false;
3736 - $rowcount = false;
3737 - $extraWhere = null;
1808 + $this->wpdb->insert( $this->tableName( 'users' ), $fields );
1809 + }
3738 1810
3739 - if ( isset( $websiteid ) && ( null !== $websiteid ) ) {
3740 - $website = static::instance()->get_website_by_id( $websiteid );
1811 + public function updateUserExtension( $userExtension ) {
3741 1812
3742 - if ( ! MainWP_System_Utility::can_edit_website( $website ) ) {
3743 - return false;
3744 - }
3745 -
3746 - if ( ! \mainwp_current_user_can( 'site', $websiteid ) ) {
3747 - return false;
3748 - }
3749 -
3750 - return array(
3751 - array(
3752 - 'id' => $websiteid,
3753 - 'url' => MainWP_Utility::get_nice_url( $website->url, true ),
3754 - 'name' => $website->name,
3755 - 'totalsize' => $website->totalsize,
3756 - 'sync_errors' => $website->sync_errors,
3757 - ),
3758 - );
1813 + if (is_object($userExtension)) {
1814 + $userid = $userExtension->userid;
1815 + } else if (is_array($userExtension)) {
1816 + $userid = $userExtension['userid']; // fix for some
3759 1817 } else {
3760 - if ( isset( $others['orderby'] ) ) {
3761 - if ( 'site' === $others['orderby'] ) {
3762 - $orderBy = 'wp.name ' . ( 'asc' === $others['order'] ? 'asc' : 'desc' );
3763 - } elseif ( 'url' === $others['orderby'] ) {
3764 - $orderBy = 'wp.url ' . ( 'asc' === $others['order'] ? 'asc' : 'desc' );
3765 - }
3766 - }
3767 - if ( isset( $others['search'] ) ) {
3768 - $search_site = trim( $others['search'] );
3769 - }
3770 -
3771 - if ( is_array( $others ) && isset( $others['plugins_slug'] ) ) {
3772 - $slugs = explode( ',', $others['plugins_slug'] );
3773 - $extraWhere = '';
3774 - foreach ( $slugs as $slug ) {
3775 - $slug = wp_json_encode( $slug );
3776 - $slug = trim( $slug, '"' );
3777 - $slug = str_replace( '\\', '.', $slug );
3778 - $extraWhere .= ' wp.plugins REGEXP "' . $slug . '" OR';
3779 - }
3780 - $extraWhere = trim( rtrim( $extraWhere, 'OR' ) );
3781 -
3782 - if ( '' === $extraWhere ) {
3783 - $extraWhere = null;
3784 - } else {
3785 - $extraWhere = '(' . $extraWhere . ')';
3786 - }
3787 - }
1818 + $userid = null;
3788 1819 }
3789 1820
3790 - $totalRecords = '';
1821 + if ( $userid == null ) {
1822 + if ( MainWP_System::Instance()->isSingleUser() ) {
1823 + $userid = '0';
1824 + } else {
1825 + global $current_user;
1826 + $userid = $current_user->ID;
1827 + }
1828 + }
1829 + $row = $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'users' ) . ' WHERE userid= ' . $userid, OBJECT );
1830 + if ( $row == null ) {
1831 + $this->createUserExtension( $userid );
1832 + }
3791 1833
3792 - if ( isset( $others['per_page'] ) && ! empty( $others['per_page'] ) ) {
3793 - $sql = static::instance()->get_sql_websites_for_current_user( false, $search_site, $orderBy, false, false, $extraWhere, $for_manager );
3794 - $websites_total = static::instance()->query( $sql );
3795 - $totalRecords = ( $websites_total ? static::num_rows( $websites_total ) : 0 );
1834 + $fields = array();
1835 + foreach ( $userExtension as $field => $value ) {
1836 + if ( $value != $row->$field ) {
1837 + $fields[ $field ] = $value;
1838 + }
1839 + }
3796 1840
3797 - if ( $websites_total ) {
3798 - static::free_result( $websites_total );
3799 - }
1841 + if ( count( $fields ) > 0 ) {
1842 + $this->wpdb->update( $this->tableName( 'users' ), $fields, array( 'userid' => $userid ) );
1843 + }
3800 1844
3801 - $rowcount = absint( $others['per_page'] );
3802 - $pagenum = isset( $others['paged'] ) ? absint( $others['paged'] ) : 0;
3803 - if ( $pagenum > $totalRecords ) {
3804 - $pagenum = $totalRecords;
3805 - }
3806 - $pagenum = max( 1, $pagenum );
3807 - $offset = ( $pagenum - 1 ) * $rowcount;
1845 + $row = $this->wpdb->get_row( 'SELECT * FROM ' . $this->tableName( 'users' ) . ' WHERE userid= ' . $userid, OBJECT );
3808 1846
3809 - }
1847 + return $row;
1848 + }
3810 1849
3811 - $sql = static::instance()->get_sql_websites_for_current_user( false, $search_site, $orderBy, $offset, $rowcount, $extraWhere, $for_manager );
3812 - $websites = static::instance()->query( $sql );
1850 + public function getTips() {
1851 + return $this->wpdb->get_results( 'SELECT * FROM ' . $this->tableName( 'tips' ) . ' ORDER BY seq ASC', OBJECT );
1852 + }
3813 1853
3814 - $output = array();
3815 - while ( $websites && ( $website = static::fetch_object( $websites ) ) ) {
3816 - $re = array(
3817 - 'id' => $website->id,
3818 - 'url' => MainWP_Utility::get_nice_url( $website->url, true ),
3819 - 'name' => $website->name,
3820 - 'totalsize' => $website->totalsize,
3821 - 'sync_errors' => $website->sync_errors,
3822 - 'client_id' => $website->client_id,
3823 - );
1854 + public function addTip( $tip_seq, $tip_content ) {
1855 + return $this->wpdb->insert( $this->tableName( 'tips' ), array( 'seq' => $tip_seq, 'content' => $tip_content ) );
1856 + }
3824 1857
3825 - if ( 0 < $totalRecords ) {
3826 - $re['totalRecords'] = $totalRecords;
3827 - $totalRecords = 0;
3828 - }
1858 + public function updateTip( $tip_id, $tip_seq, $tip_content ) {
1859 + return $this->wpdb->update( $this->tableName( 'tips' ), array(
1860 + 'seq' => $tip_seq,
1861 + 'content' => $tip_content,
1862 + ), array( 'id' => $tip_id ) );
1863 + }
3829 1864
3830 - $output[] = $re;
3831 - }
3832 - static::free_result( $websites );
1865 + public function deleteTip( $tip_id ) {
1866 + return $this->wpdb->query( 'DELETE FROM ' . $this->tableName( 'tips' ) . ' WHERE id = ' . $tip_id );
1867 + }
3833 1868
3834 - return $output;
3835 - }
1869 + public function getMySQLVersion() {
1870 + return $this->wpdb->get_var( 'SHOW VARIABLES LIKE "version"', 1 );
1871 + }
3836 1872
3837 - /**
3838 - * Method get_lookup_items().
3839 - *
3840 - * Get bulk lookup items to reduce number of db queries.
3841 - *
3842 - * @param string $item_name lookup item name.
3843 - * @param int $item_id lookup item id.
3844 - * @param string $obj_name loockup object name.
3845 - *
3846 - * @return mixed Result
3847 - */
3848 - public function get_lookup_items( $item_name, $item_id, $obj_name ) {
3849 - return $this->wpdb->get_results( $this->wpdb->prepare( 'SELECT * FROM ' . $this->table_name( 'lookup_item_objects' ) . ' WHERE item_name=%s AND item_id = %d AND object_name = %s', $item_name, $item_id, $obj_name ) ); //phpcs:ignore -- ok.
3850 - }
1873 + public function getRowResult( $sql ) {
1874 + if ( $sql == null ) {
1875 + return null;
1876 + }
3851 1877
3852 - /**
3853 - * Method insert_lookup_item().
3854 - *
3855 - * Insert lookup item, need checks existed before to prevent double values.
3856 - *
3857 - * @param string $item_name item name.
3858 - * @param int $item_id item id.
3859 - * @param string $obj_name object name.
3860 - * @param int $obj_id object id.
3861 - *
3862 - * @return mixed Result
3863 - */
3864 - public function insert_lookup_item( $item_name, $item_id, $obj_name, $obj_id ) {
3865 - if ( empty( $item_name ) || empty( $item_id ) || empty( $obj_name ) || empty( $obj_id ) ) {
3866 - return false;
3867 - }
3868 - $data = array(
3869 - 'item_name' => 'cost',
3870 - 'item_id' => $item_id,
3871 - 'object_name' => $obj_name,
3872 - 'object_id' => $obj_id,
3873 - );
3874 - $this->wpdb->insert( $this->table_name( 'lookup_item_objects' ), $data );
3875 - return $this->wpdb->insert_id; // must return lookup id.
3876 - }
1878 + return $this->wpdb->get_row( $sql, OBJECT );
1879 + }
3877 1880
3878 - /**
3879 - * Method delete_lookup_items().
3880 - *
3881 - * Delete bulk lookup items by lookup ids or object names with item id and item name, to reduce number of db queries.
3882 - *
3883 - * @param string $by Delete by.
3884 - * @param array $params params.
3885 - *
3886 - * @return mixed Result
3887 - */
3888 - public function delete_lookup_items( $by = 'lookup_id', $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
3889 - if ( ! is_array( $params ) ) {
3890 - return false;
3891 - }
1881 + public function getResultsResult( $sql ) {
1882 + if ( $sql == null ) {
1883 + return null;
1884 + }
3892 1885
3893 - $lookup_ids = isset( $params['lookup_ids'] ) ? $params['lookup_ids'] : null;
3894 - $item_id = isset( $params['item_id'] ) ? $params['item_id'] : null;
3895 - $object_id = isset( $params['object_id'] ) ? $params['object_id'] : null;
3896 - $item_name = isset( $params['item_name'] ) ? $params['item_name'] : null;
3897 - $obj_names = isset( $params['object_names'] ) ? $params['object_names'] : null;
1886 + return $this->wpdb->get_results( $sql, OBJECT_K );
1887 + }
3898 1888
3899 - if ( 'object_name' === $by ) {
3900 - if ( empty( $item_id ) || empty( $item_name ) ) {
3901 - return false;
3902 - }
1889 + public function query( $sql ) {
1890 + if ( $sql == null ) {
1891 + return false;
1892 + }
3903 1893
3904 - $obj_names = $this->escape_array( $obj_names );
3905 - if ( ! empty( $obj_names ) ) {
3906 - $this->wpdb->query( $this->wpdb->prepare( 'DELETE FROM ' . $this->table_name( 'lookup_item_objects' ) . ' WHERE item_name = %s AND item_id = %d AND object_name IN ("' . implode( '","', $obj_names ) . '") ', $item_name, $item_id ) ); //phpcs:ignore -- ok.
3907 - return true;
3908 - }
3909 - } elseif ( 'object_id' === $by ) {
3910 - if ( empty( $object_id ) || empty( $item_name ) || empty( $obj_names ) ) {
3911 - return false;
3912 - }
1894 + $result = @self::_query( $sql, $this->wpdb->dbh );
3913 1895
3914 - $obj_names = $this->escape_array( $obj_names );
3915 - if ( ! empty( $obj_names ) ) {
3916 - $this->wpdb->query( $this->wpdb->prepare( 'DELETE FROM ' . $this->table_name( 'lookup_item_objects' ) . ' WHERE item_name = %s AND object_id = %d AND object_name IN ("' . implode( '","', $obj_names ) . '") ', $item_name, $object_id ) ); //phpcs:ignore -- ok.
3917 - return true;
3918 - }
3919 - } elseif ( 'lookup_id' === $by ) {
3920 - if ( empty( $lookup_ids ) ) {
3921 - return false;
3922 - }
3923 - if ( is_numeric( $lookup_ids ) ) {
3924 - $lookup_ids = array( $lookup_ids );
3925 - } elseif ( is_array( $lookup_ids ) ) {
3926 - $lookup_ids = MainWP_Utility::array_numeric_filter( $lookup_ids );
3927 - } else {
3928 - return false;
3929 - }
3930 - $this->wpdb->query( 'DELETE FROM ' . $this->table_name( 'lookup_item_objects' ) . ' WHERE lookup_id IN (' . implode( ',', $lookup_ids ) . ') ' ); //phpcs:ignore -- ok.
3931 - return true;
3932 - }
3933 - return false;
3934 - }
1896 + if ( !$result || ( @MainWP_DB::num_rows( $result ) == 0 ) ) {
1897 + return false;
1898 + }
3935 1899
1900 + return $result;
1901 + }
3936 1902
3937 - /**
3938 - * Insert a new REST API key row and return the credential payload.
3939 - *
3940 - * Returns an array with key_id, user_id, plaintext consumer_key,
3941 - * plaintext consumer_secret, and key_permissions on success. Returns
3942 - * false when the wpdb->insert() call fails (no current user, missing
3943 - * table, schema mismatch, etc.). Callers must check the return type
3944 - * before treating it as an array.
3945 - *
3946 - * @param string $consumer_key Consumer key.
3947 - * @param string $consumer_secret Secret key.
3948 - * @param string $scope scope.
3949 - * @param string $description description.
3950 - * @param int $enabled 1 or 0.
3951 - * @param array $others others.
3952 - *
3953 - * @return array|false Credential payload on success, false on failure.
3954 - */
3955 - public function insert_rest_api_key( $consumer_key, $consumer_secret, $scope, $description, $enabled, $others = array() ) {
3956 - global $current_user;
1903 + protected function escape( $data ) {
1904 + if ( function_exists( 'esc_sql' ) ) {
1905 + return esc_sql( $data );
1906 + } else {
1907 + return $this->wpdb->escape( $data );
1908 + }
1909 + }
3957 1910
3958 - if ( $current_user ) {
3959 - $user_id = $current_user->ID;
3960 - }
1911 + //Support old & new versions of wordpress (3.9+)
1912 + public static function use_mysqli() {
1913 + /** @var $this ->wpdb wpdb */
1914 + if ( !function_exists( 'mysqli_connect' ) ) {
1915 + return false;
1916 + }
3961 1917
3962 - if ( empty( $user_id ) ) {
3963 - return false;
3964 - }
1918 + return ( self::$instance->wpdb->dbh instanceof mysqli );
1919 + }
3965 1920
3966 - unset( $others ); // Parameter retained for signature compatibility; key_pass/key_type fields are vestigial after MWP-1544 cleanup.
1921 + public static function ping( $link ) {
1922 + if ( self::use_mysqli() ) {
1923 + return mysqli_ping( $link );
1924 + } else {
1925 + return mysql_ping( $link );
1926 + }
1927 + }
3967 1928
3968 - // Hash the consumer_secret with WordPress's password hasher so the
3969 - // value at rest is no longer reversible by a DB-read primitive.
3970 - // The plaintext is returned to the caller below so it can be shown
3971 - // to the admin once at creation time. See MWP-1540.
3972 - $hashed_secret = wp_hash_password( $consumer_secret );
1929 + public static function _query( $query, $link ) {
1930 + if ( self::use_mysqli() ) {
1931 + return mysqli_query( $link, $query );
1932 + } else {
1933 + return mysql_query( $query, $link );
1934 + }
1935 + }
3973 1936
3974 - // Created API keys.
3975 - $permissions = in_array( $scope, array( 'read', 'write', 'delete', 'read_write' ), true ) ? sanitize_text_field( $scope ) : 'read';
3976 - $inserted = $this->wpdb->insert(
3977 - $this->table_name( 'api_keys' ),
3978 - array(
3979 - 'user_id' => $user_id,
3980 - 'description' => $description,
3981 - 'permissions' => $permissions,
3982 - 'consumer_key' => mainwp_api_hash( $consumer_key ),
3983 - 'consumer_secret' => $hashed_secret,
3984 - 'truncated_key' => substr( $consumer_key, -7 ),
3985 - 'enabled' => $enabled,
3986 - ),
3987 - array(
3988 - '%d',
3989 - '%s',
3990 - '%s',
3991 - '%s',
3992 - '%s',
3993 - '%s',
3994 - '%d',
3995 - ),
3996 - );
1937 + public static function fetch_object( $result ) {
1938 + if ( $result === false ) {
1939 + return false;
1940 + }
3997 1941
3998 - // wpdb->insert() returns false on failure. Without this guard the
3999 - // function would still hand back the plaintext consumer_secret plus
4000 - // $wpdb->insert_id, but that insert_id is the LAST successful insert
4001 - // on the connection (typically from earlier in the same request),
4002 - // not this row. The caller's empty-key_id check would pass and the
4003 - // operator would receive a credential that was never persisted.
4004 - // See MWP-1540 PR review feedback.
4005 - if ( false === $inserted ) {
4006 - return false;
4007 - }
1942 + if ( self::use_mysqli() ) {
1943 + return mysqli_fetch_object( $result );
1944 + } else {
1945 + return mysql_fetch_object( $result );
1946 + }
1947 + }
4008 1948
4009 - return array(
4010 - 'key_id' => $this->wpdb->insert_id,
4011 - 'user_id' => $user_id,
4012 - 'consumer_key' => $consumer_key,
4013 - 'consumer_secret' => $consumer_secret,
4014 - 'key_permissions' => $permissions,
4015 - );
4016 - }
1949 + public static function free_result( $result ) {
1950 + if ( $result === false ) {
1951 + return false;
1952 + }
4017 1953
4018 - /**
4019 - * Update rest api key.
4020 - *
4021 - * @param int $key_id Consumer key.
4022 - * @param string $scope scope.
4023 - * @param string $description description.
4024 - * @param int $enabled Enabled.
4025 - *
4026 - * @return array
4027 - */
4028 - public function update_rest_api_key( $key_id, $scope, $description, $enabled = 1 ) {
4029 - $permissions = in_array( $scope, array( 'read', 'write', 'delete', 'read_write' ), true ) ? sanitize_text_field( $scope ) : 'read';
4030 - return $this->wpdb->update(
4031 - $this->table_name( 'api_keys' ),
4032 - array(
4033 - 'description' => $description,
4034 - 'permissions' => $permissions,
4035 - 'enabled' => $enabled ? 1 : 0,
4036 - ),
4037 - array(
4038 - 'key_id' => $key_id,
4039 - )
4040 - );
4041 - }
1954 + if ( self::use_mysqli() ) {
1955 + return mysqli_free_result( $result );
1956 + } else {
1957 + return mysql_free_result( $result );
1958 + }
1959 + }
4042 1960
1961 + public static function data_seek( $result, $offset ) {
1962 + if ( $result === false ) {
1963 + return false;
1964 + }
4043 1965
4044 - /**
4045 - * Method is_existed_enabled_rest_key().
4046 - *
4047 - * @return bool result.
4048 - */
4049 - public function is_existed_enabled_rest_key() {
4050 - $table_name = esc_sql( $this->table_name( 'api_keys' ) );
4051 - $enabled = $this->wpdb->get_row( "SELECT * FROM {$table_name} WHERE enabled = 1 LIMIT 1" );
4052 - return $enabled ? true : false;
4053 - }
1966 + if ( self::use_mysqli() ) {
1967 + return mysqli_data_seek( $result, $offset );
1968 + } else {
1969 + return mysql_data_seek( $result, $offset );
1970 + }
1971 + }
4054 1972
4055 - /**
4056 - * Method get_rest_api_key_by().
4057 - *
4058 - * @param int $id To get key.
4059 - *
4060 - * @return array
4061 - */
4062 - public function get_rest_api_key_by( $id ) {
4063 - $table_name = esc_sql( $this->table_name( 'api_keys' ) );
4064 - return $this->wpdb->get_row( $this->wpdb->prepare( "SELECT * FROM {$table_name} WHERE key_id = %d", $id ) );
4065 - }
1973 + public static function fetch_array( $result, $result_type = null ) {
1974 + if ( $result === false ) {
1975 + return false;
1976 + }
4066 1977
4067 - /**
4068 - * Method remove_rest_api_key().
4069 - *
4070 - * @param string $id to delete.
4071 - *
4072 - * @return array
4073 - */
4074 - public function remove_rest_api_key( $id ) {
4075 - $table_name = esc_sql( $this->table_name( 'api_keys' ) );
4076 - return $this->wpdb->query( $this->wpdb->prepare( "DELETE FROM {$table_name} WHERE key_id = %s", $id ) );
4077 - }
1978 + if ( self::use_mysqli() ) {
1979 + return mysqli_fetch_array( $result, ( $result_type == null ? MYSQLI_BOTH : $result_type ) );
1980 + } else {
1981 + return mysql_fetch_array( $result, ( $result_type == null ? MYSQL_BOTH : $result_type ) );
1982 + }
1983 + }
4078 1984
4079 - /**
4080 - * Method get_rest_api_keys().
4081 - *
4082 - * @return array
4083 - */
4084 - public function get_rest_api_keys() {
4085 - $table_name = esc_sql( $this->table_name( 'api_keys' ) );
4086 - return $this->wpdb->get_results( "SELECT * FROM {$table_name} ORDER BY key_id DESC" );
4087 - }
1985 + public static function num_rows( $result ) {
1986 + if ( $result === false ) {
1987 + return 0;
1988 + }
4088 1989
1990 + if ( self::use_mysqli() ) {
1991 + return mysqli_num_rows( $result );
1992 + } else {
1993 + return mysql_num_rows( $result );
1994 + }
1995 + }
4089 1996
4090 - /**
4091 - * Update regular process.
4092 - *
4093 - * @param array $data process data.
4094 - * @return mixed
4095 - */
4096 - public function update_regular_process( $data ) {
4097 - if ( isset( $data['process_id'] ) ) {
4098 - $process_id = $data['process_id'];
4099 - unset( $data['process_id'] );
4100 - return $this->wpdb->update( $this->table_name( 'schedule_processes' ), $data, array( 'process_id' => $process_id ) );
4101 - } elseif ( is_array( $data ) && isset( $data['type'] ) && isset( $data['process_slug'] ) ) {
4102 - return $this->wpdb->insert( $this->table_name( 'schedule_processes' ), $data );
4103 - }
4104 - return false;
4105 - }
1997 + public static function is_result( $result ) {
1998 + if ( $result === false ) {
1999 + return false;
2000 + }
4106 2001
4107 - /**
4108 - * Delete regular process.
4109 - *
4110 - * @param int $process_id Process id.
4111 - * @param int $item_id Item id.
4112 - * @param string $pro_type Process type.
4113 - * @param string $pro_slug Process slug.
4114 - *
4115 - * @return mixed
4116 - */
4117 - public function delete_regular_process( $process_id = false, $item_id = false, $pro_type = false, $pro_slug = false ) {
2002 + if ( self::use_mysqli() ) {
2003 + return ( $result instanceof mysqli_result );
2004 + } else {
2005 + return is_resource( $result );
2006 + }
2007 + }
4118 2008
4119 - if ( is_numeric( $process_id ) && ! empty( $process_id ) ) {
4120 - return $this->wpdb->delete(
4121 - $this->table_name( 'schedule_processes' ),
4122 - array(
4123 - 'process_id' => $process_id,
4124 - )
4125 - );
4126 - } elseif ( ! empty( $pro_type ) || ! empty( $pro_slug ) ) {
2009 +}
4127 2010
4128 - $data = array();
4129 -
4130 - if ( ! empty( $pro_type ) ) {
4131 - $data['type'] = $pro_type;
4132 - }
4133 -
4134 - if ( ! empty( $pro_slug ) ) {
4135 - $data['process_slug'] = $pro_slug;
4136 - }
4137 -
4138 - if ( ! empty( $item_id ) ) {
4139 - $data['item_id'] = $item_id;
4140 - }
4141 - // Bulk delete.
4142 - return $this->wpdb->delete( $this->table_name( 'schedule_processes' ), $data );
4143 - }
4144 - return false;
4145 - }
4146 -
4147 - /**
4148 - * Method get_regular_process_by_item_id_type_slug
4149 - *
4150 - * @param integer $item_id item id.
4151 - * @param string $type type.
4152 - * @param string $process_slug process slug.
4153 - *
4154 - * @return mixed result
4155 - */
4156 - public function get_regular_process_by_item_id_type_slug( $item_id, $type, $process_slug ) {
4157 - $table_name = esc_sql( $this->table_name( 'schedule_processes' ) );
4158 - return $this->wpdb->get_row( $this->wpdb->prepare( "SELECT pr.* FROM {$table_name} pr WHERE pr.item_id = %d AND pr.type = %s AND pr.process_slug = %s", $item_id, $type, $process_slug ) );
4159 - }
4160 -
4161 - /**
4162 - * Log SQL queries for debugging via hook.
4163 - *
4164 - * This method provides a structured way to log SQL queries for development/debugging.
4165 - * It does NOT use error_log() directly - instead, it fires the `mainwp_log_system_query`
4166 - * action hook, allowing external listeners (logging plugins, debug tools) to handle
4167 - * the log output appropriately.
4168 - *
4169 - * To enable query logging:
4170 - * 1. Set `$params['dev_log_query'] = 1` when calling database methods
4171 - * 2. Add a listener to the `mainwp_log_system_query` action hook
4172 - *
4173 - * Example listener:
4174 - * ```php
4175 - * add_action( 'mainwp_log_system_query', function( $params, $sql, $caller ) {
4176 - * error_log( 'MainWP Query: ' . $sql );
4177 - * }, 10, 3 );
4178 - * ```
4179 - *
4180 - * @param array $params Query parameters. Set 'dev_log_query' to enable logging.
4181 - * @param string $sql The SQL query string.
4182 - * @param mixed $caller Instance of caller class (optional).
4183 - * @return void
4184 - */
4185 - public function log_system_query( $params, $sql, $caller = false ) {
4186 - $params = apply_filters( 'mainwp_log_system_query_params', $params, $sql, $caller );
4187 - if ( is_array( $params ) && ! empty( $params['dev_log_query'] ) && ! empty( $sql ) ) {
4188 - do_action( 'mainwp_log_system_query', $params, $sql, $caller );
4189 - }
4190 - }
4191 -}
2011 +?>