PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 5.3
MainWP Dashboard: Self-hosted WordPress Management for Agencies v5.3
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 5.2.2 5.3 All 153 releases
mainwp / class / class-mainwp-db.php

class-mainwp-db.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 5.3, at class/class-mainwp-db.php

3,234 lines 129.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Database Controller
4 *
5 * This file handles all interactions with the DB.
6 *
7 * @package MainWP/Dashboard
8 */
9
10 namespace MainWP\Dashboard;
11
12 /**
13 * Class MainWP_DB
14 *
15 * @package MainWP\Dashboard
16 *
17 * @uses \MainWP\Dashboard\MainWP_DB_Base
18 */
19 class MainWP_DB extends MainWP_DB_Base { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
20
21 // 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.
22
23 /**
24 * Private static variable to hold the single instance of the class.
25 *
26 * @static
27 *
28 * @var mixed Default null
29 */
30 private static $instance = null;
31
32 /**
33 * Private static variable to hold the single instance.
34 *
35 * @static
36 *
37 * @var mixed Default null
38 */
39 private static $general_options = null;
40
41 /**
42 * Possible options.
43 *
44 * @var array $possible_options
45 */
46 private static $possible_options = array(
47 'plugin_upgrades',
48 'theme_upgrades',
49 'premium_upgrades',
50 'plugins',
51 'themes',
52 'dtsSync',
53 'version',
54 'sync_errors',
55 'ignored_plugins',
56 'wp_upgrades',
57 'site_info',
58 'client',
59 'signature_algo',
60 'verify_method',
61 'pubkey',
62 );
63
64 /**
65 * Create public static instance.
66 *
67 * @static
68 *
69 * @return MainWP_DB
70 */
71 public static function instance() {
72 if ( null === static::$instance ) {
73 static::$instance = new self();
74 }
75
76 static::$instance->test_connection();
77
78 return static::$instance;
79 }
80
81 /**
82 * Get wp_options database table view.
83 *
84 * @param array $fields Extra option fields.
85 * @param string $view_query view query.
86 *
87 * @return array wp_options view.
88 */
89 public function get_option_view( $fields = array(), $view_query = 'default' ) {
90
91 if ( ! is_array( $fields ) ) {
92 $fields = array();
93 }
94
95 $view = '(SELECT intwp.id AS wpid ';
96
97 $included_opts = array();
98
99 if ( empty( $fields ) || 'default' === $view_query ) {
100 $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,
101 (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,
102 (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,
103 (SELECT phpversion.value FROM ' . $this->table_name( 'wp_options' ) . ' phpversion WHERE phpversion.wpid = intwp.id AND phpversion.name = "phpversion" LIMIT 1) AS phpversion,
104 (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,
105 (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 ';
106 $included_opts = array( 'recent_comments', 'recent_posts', 'recent_pages', 'phpversion', 'added_timestamp', 'wp_upgrades' );
107 }
108
109 if ( ! in_array( 'signature_algo', $fields ) ) {
110 $fields[] = 'signature_algo';
111 }
112
113 if ( ! in_array( 'verify_method', $fields ) ) {
114 $fields[] = 'verify_method';
115 }
116
117 if ( ! in_array( 'cust_site_icon_info', $fields, true ) ) {
118 $fields[] = 'cust_site_icon_info';
119 }
120
121 if ( is_array( $fields ) ) {
122 foreach ( $fields as $field ) {
123 if ( empty( $field ) ) {
124 continue;
125 }
126 if ( in_array( $field, $included_opts ) ) {
127 continue;
128 }
129 $view .= ', ';
130 $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 );
131 }
132 }
133
134 $view .= ' FROM ' . $this->table_name( 'wp' ) . ' intwp)';
135
136 return $view;
137 }
138
139
140
141 /**
142 * Get SQL to get child sites for current user.
143 *
144 * @since 5.2.
145 * @param array $params other params.
146 *
147 * @return object|null Database query results or null on failure.
148 */
149 public function get_sql_websites_for_current_user_by_params( $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
150
151 if ( ! is_array( $params ) ) {
152 $params = array();
153 }
154 $view = isset( $params['view'] ) ? $params['view'] : 'default';
155 $with_clients = isset( $params['with_clients'] ) && $params['with_clients'] ? true : false;
156
157 // legacy support.
158 $selectgroups = isset( $params['with_tags'] ) && $params['with_tags'] ? true : false;
159 $orderBy = isset( $params['orderby'] ) ? $params['orderby'] : 'wp.url';
160 $offset = isset( $params['offset'] ) ? intval( $params['offset'] ) : false;
161 $rowcount = isset( $params['rowcount'] ) && $params['rowcount'] ? true : false;
162 $extraWhere = isset( $params['where'] ) ? $params['where'] : null; // NOTE: without 'AND' at begining and ending of 'where'.
163 $for_manager = isset( $params['for_manager'] ) && $params['for_manager'] ? true : false;
164 $others_fields = isset( $params['others_fields'] ) && is_array( $params['others_fields'] ) ? $params['others_fields'] : array( 'favi_icon' );
165 $is_staging = isset( $params['is_staging'] ) && in_array( $params['is_staging'], array( 'yes', 'no' ) ) ? $params['is_staging'] : 'no';
166 $limit = isset( $params['limit'] ) ? intval( $params['limit'] ) : '';
167
168 $s = isset( $params['s'] ) ? $params['s'] : '';
169 $exclude = isset( $params['exclude'] ) ? wp_parse_id_list( $params['exclude'] ) : array();
170 $include = isset( $params['include'] ) ? wp_parse_id_list( $params['include'] ) : array();
171 $status = isset( $params['status'] ) ? wp_parse_list( $params['status'] ) : array();
172 $page = isset( $params['page'] ) ? intval( $params['page'] ) : false;
173 $per_page = isset( $params['per_page'] ) ? intval( $params['per_page'] ) : false;
174
175 $where = '';
176
177 if ( ! empty( $extraWhere ) ) {
178 $where .= ' AND ' . $extraWhere;
179 }
180
181 if ( ! $for_manager ) {
182 $where .= $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
183 }
184
185 $connected_sql = '';
186
187 if ( is_array( $params ) && isset( $params['connected'] ) && 'yes' === $params['connected'] ) {
188 $connected_sql = ' AND wp_sync.sync_errors = "" ';
189 } elseif ( is_array( $params ) && isset( $params['connected'] ) && 'no' === $params['connected'] ) {
190 $connected_sql = ' AND wp_sync.sync_errors <> "" ';
191 }
192
193 if ( ! empty( $s ) ) {
194 $where .= ' AND ( wp.id LIKE "%' . $this->escape( $s ) . '%" OR wp.name LIKE "%' . $this->escape( $s ) . '%" OR wp.url LIKE "%' . $this->escape( $s ) . '%" ) ';
195 }
196
197 if ( ! empty( $exclude ) ) {
198 $where .= ' AND wp.id NOT IN (' . implode( ',', $exclude ) . ') ';
199 }
200
201 if ( ! empty( $include ) ) {
202 $where .= ' AND wp.id IN (' . implode( ',', $include ) . ') ';
203 }
204
205 // any, connected, disconnected, suspended, available_update.
206 if ( ! empty( $status ) && is_array( $status ) && ! in_array( 'any', $status ) ) {
207 $status_conds = array();
208 if ( in_array( 'available_update', $status ) ) {
209 $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 <> '[]' ) ";
210 $results = $this->wpdb->get_results( 'SELECT wpid FROM ' . $this->table_name( 'wp_options' ) . " WHERE name = 'wp_upgrades' AND value <> '' AND value <> '[]' " );
211 if ( $results ) {
212 $wp_ids = array();
213 foreach ( $results as $item ) {
214 if ( ! empty( $item->wpid ) ) {
215 $wp_ids[] = $item->wpid;
216 }
217 }
218 $wp_ids = ! empty( $wp_ids ) ? array_unique( $wp_ids ) : array();
219 if ( ! empty( $wp_ids ) ) {
220 $available_sql .= ' OR wp.id IN ( ' . implode( ',', $wp_ids ) . ' )';
221 }
222 }
223 $status_conds[] = ' ( ' . $available_sql . ') ';
224 }
225
226 if ( in_array( 'connected', $status ) ) {
227 $status_conds[] = ' ( wp_sync.sync_errors == "" ) ';
228 }
229 if ( in_array( 'disconnected', $status ) ) {
230 $status_conds[] = " wp_sync.sync_errors <> '' ";
231 }
232
233 if ( in_array( 'suspended', $status ) ) {
234 $status_conds[] = ' wp.suspended = 1 ';
235 }
236
237 if ( ! empty( $status_conds ) ) {
238 $where .= ' AND ( ' . implode( ' OR ', $status_conds ) . ' ) ';
239 }
240 }
241
242 if ( ! empty( $page ) && ! empty( $per_page ) ) {
243 $limit = ( $page - 1 ) * $per_page . ',' . $per_page;
244 }
245
246 if ( 'wp.url' === $orderBy ) {
247 $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '')";
248 }
249
250 $select_clients = '';
251 $join_clients = '';
252
253 if ( $with_clients ) {
254 $select_clients = ', wpclient.name as client_name ';
255 $join_clients = ' LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id ';
256 }
257
258 $base_fields = array(
259 'wp.id',
260 'wp.url',
261 'wp.name',
262 'wp.client_id',
263 'wp.verify_certificate',
264 'wp.http_user',
265 'wp.http_pass',
266 'wp.ssl_version',
267 'wp.adminname',
268 'wp.privkey',
269 'wp.pubkey',
270 'wp.wpe',
271 'wp.is_staging',
272 'wp.pubkey',
273 'wp.force_use_ipv4',
274 'wp.siteurl',
275 'wp.suspended',
276 'wp.mainwpdir',
277 'wp.is_ignoreCoreUpdates',
278 'wp.is_ignorePluginUpdates',
279 'wp.is_ignoreThemeUpdates',
280 'wp_sync.sync_errors',
281 'wp.backup_before_upgrade',
282 'wp.userid',
283 'wp.plugins',
284 'wp.themes',
285 'wp.offline_check_result', // 1 - online, -1 offline.
286 );
287
288 $select = ' wp.*,wp_sync.* ';
289 if ( 'base_view' === $view ) {
290 $select = implode( ',', $base_fields );
291 } elseif ( 'updates_view' === $view ) {
292 $updates_fields = array(
293 'wp.plugin_upgrades',
294 'wp.theme_upgrades',
295 'wp.translation_upgrades',
296 'wp.premium_upgrades',
297 'wp.ignored_themes',
298 'wp.ignored_plugins',
299 );
300 $select = implode( ',', array_merge( $updates_fields, $base_fields ) );
301 }
302
303 $select .= ',wp_optionview.* '; // to fix bug.
304
305 // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax.
306 if ( $selectgroups ) {
307 $qry = 'SELECT ' . $select . ', 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,
308 ' . $select_clients . '
309 FROM ' . $this->table_name( 'wp' ) . ' wp
310 LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
311 LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
312 ' . $join_clients . '
313 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
314 JOIN ' . $this->get_option_view_by( $view, $others_fields ) . ' wp_optionview ON wp.id = wp_optionview.wpid
315 WHERE 1 ' . $where . $connected_sql . '
316 GROUP BY wp.id, wp_sync.sync_id
317 ORDER BY ' . $orderBy;
318 } else {
319 $qry = 'SELECT ' . $select .
320 $select_clients . '
321 FROM ' . $this->table_name( 'wp' ) . ' wp
322 ' . $join_clients . '
323 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
324 JOIN ' . $this->get_option_view_by( $view, $others_fields ) . ' wp_optionview ON wp.id = wp_optionview.wpid
325 WHERE 1 ' . $where . $connected_sql . '
326 GROUP BY wp.id, wp_sync.sync_id
327 ORDER BY ' . $orderBy;
328 }
329
330 if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
331 $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
332 } elseif ( false !== $rowcount ) {
333 $qry .= ' LIMIT ' . $rowcount;
334 } elseif ( ! empty( $limit ) ) {
335 $qry .= ' LIMIT ' . $limit;
336 } else {
337 // load all sites so check to support limit sites loading.
338 $limit_sites = ! empty( $params['limit_sites'] ) ? intval( $params['limit_sites'] ) : 0;
339 if ( ! empty( $limit_sites ) ) {
340 $current_page = (int) get_option( 'mainwp_manage_updates_limit_current_page', 0 );
341 $current_page = $current_page > 0 ? $current_page - 1 : 0;
342 $start = $current_page * $limit_sites;
343 $qry .= ' LIMIT ' . intval( $start ) . ', ' . intval( $limit_sites );
344 }
345 }
346
347 return $qry;
348 }
349
350 /**
351 * Get wp_options database table view.
352 *
353 * @param array $view Option view.
354 * @param array $other_fields Extra option fields.
355 *
356 * @return array wp_options view.
357 */
358 public function get_option_view_by( $view = '', $other_fields = array() ) {
359
360 $default = array(
361 'recent_comments',
362 'recent_posts',
363 'recent_pages',
364 'phpversion',
365 'added_timestamp',
366 'wp_upgrades',
367 );
368
369 if ( 'updates_view' === $view ) {
370 $fields = array(
371 'wp_upgrades',
372 'ignored_wp_upgrades',
373 );
374 } elseif ( in_array( $view, array( 'simple_view', 'base_view', 'monitor_view', 'ping_view', 'uptime_notification' ) ) ) {
375 $fields = array();
376 } else {
377 $fields = $default;
378 }
379
380 if ( is_array( $other_fields ) && ! empty( $other_fields ) ) {
381 $fields = array_unique( array_merge( $fields, $other_fields ) );
382 }
383
384 $view_query = '(SELECT intwp.id AS wpid ';
385
386 if ( ! in_array( 'signature_algo', $fields ) ) {
387 $fields[] = 'signature_algo';
388 }
389
390 if ( ! in_array( 'verify_method', $fields ) ) {
391 $fields[] = 'verify_method';
392 }
393
394 foreach ( $fields as $field ) {
395
396 if ( empty( $field ) ) {
397 continue;
398 }
399
400 $view_query .= ', ';
401 $view_query .= '(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 );
402 }
403
404 $view_query .= ' FROM ' . $this->table_name( 'wp' ) . ' intwp)';
405
406 return $view_query;
407 }
408
409 /**
410 * Method get_select_groups_belong().
411 *
412 * @return string sql.
413 */
414 public function get_select_groups_belong() {
415 return ', ( SELECT GROUP_CONCAT(grbl.name ORDER BY grbl.name SEPARATOR ",")
416 FROM ' . $this->table_name( 'wp_group' ) . ' wpgrbl
417 JOIN ' . $this->table_name( 'group' ) . ' grbl ON grbl.id = wpgrbl.groupid WHERE wpgrbl.wpid = wp.id ) as wpgroups_belong,
418 ( SELECT GROUP_CONCAT(grbl.id ORDER BY grbl.name SEPARATOR ",") FROM ' . $this->table_name( 'wp_group' ) . ' wpgrbl
419 JOIN ' . $this->table_name( 'group' ) . ' grbl ON grbl.id = wpgrbl.groupid WHERE wpgrbl.wpid = wp.id ) as wpgroupids_belong,
420 ( SELECT GROUP_CONCAT(grbl.color ORDER BY grbl.name SEPARATOR ",") FROM ' . $this->table_name( 'wp_group' ) . ' wpgrbl
421 JOIN ' . $this->table_name( 'group' ) . ' grbl ON grbl.id = wpgrbl.groupid WHERE wpgrbl.wpid = wp.id ) as wpgroupcolors_belong ';
422 }
423
424 /**
425 * Get connected child sites.
426 *
427 * @param array $sites_ids Websites ids - option field.
428 *
429 * @return array $connected_sites Array of connected sites.
430 */
431 public function get_connected_websites( $sites_ids = false ) {
432 $where = $this->get_sql_where_allow_access_sites( 'wp' );
433
434 $sql = 'SELECT wp.*,wp_sync.*
435 FROM ' . $this->table_name( 'wp' ) . ' wp
436 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync
437 ON wp.id = wp_sync.wpid
438 WHERE (wp_sync.sync_errors IS NOT NULL) AND (wp_sync.sync_errors = "") ' .
439 $where;
440
441 $websites = $this->wpdb->get_results( $sql );
442 $connected_sites = array();
443 if ( $websites ) {
444 foreach ( $websites as $website ) {
445
446 if ( ! empty( $sites_ids ) && ! in_array( $website->id, $sites_ids ) ) {
447 continue;
448 }
449
450 $connected_sites[] = array(
451 'id' => $website->id,
452 'name' => $website->name,
453 'url' => $website->url,
454 );
455 }
456 }
457 return $connected_sites;
458 }
459
460 /**
461 * Get disconnected child sites.
462 *
463 * @param array $sites_ids Websites ids - option field.
464 *
465 * @return array $disc_sites Array of disonnected sites.
466 */
467 public function get_disconnected_websites( $sites_ids = false ) {
468 $where = $this->get_sql_where_allow_access_sites( 'wp' );
469
470 $sql = 'SELECT wp.*,wp_sync.*
471 FROM ' . $this->table_name( 'wp' ) . ' wp
472 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync
473 ON wp.id = wp_sync.wpid
474 WHERE (wp_sync.sync_errors IS NOT NULL) AND (wp_sync.sync_errors <> "") ' .
475 $where;
476
477 $websites = $this->wpdb->get_results( $sql );
478 $disc_sites = array();
479 if ( $websites ) {
480 foreach ( $websites as $website ) {
481
482 if ( ! empty( $sites_ids ) && ! in_array( $website->id, $sites_ids ) ) {
483 continue;
484 }
485
486 $disc_sites[] = array(
487 'id' => $website->id,
488 'name' => $website->name,
489 'url' => $website->url,
490 );
491 }
492 }
493 return $disc_sites;
494 }
495
496 /**
497 * Get child site count.
498 *
499 * @param null $userId Current user ID.
500 * @param bool $all_access Check if user has access to all sites.
501 *
502 * @return int Child site count.
503 *
504 * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
505 */
506 public function get_websites_count( $userId = null, $all_access = false ) {
507 static $total_sites;
508 if ( null !== $total_sites ) { // NOSONAR -- static value.
509 return $total_sites;
510 }
511 if ( ( null === $userId ) && MainWP_System::instance()->is_multi_user() ) {
512
513 /**
514 * Current user global.
515 *
516 * @global string
517 */
518 global $current_user;
519
520 $userId = $current_user->ID;
521 }
522 $where = ( null === $userId ? '' : ' wp.userid = ' . $userId );
523 if ( ! $all_access ) {
524 $where .= $this->get_sql_where_allow_access_sites( 'wp' );
525 }
526 $qry = 'SELECT COUNT(wp.id) FROM ' . $this->table_name( 'wp' ) . ' wp WHERE 1 ' . $where;
527
528 $total = $this->wpdb->get_var( $qry );
529 $total_sites = $total;// NOSONAR -- static value.
530 return $total;
531 }
532
533
534 /**
535 * Get child sites stats count.
536 *
537 * @param array $params Params.
538 */
539 public function get_websites_stats_count( $params = array() ) {
540 if ( ! is_array( $params ) ) {
541 $params = array();
542 }
543
544 if ( isset( $params['all_access'] ) ) {
545 $all_access = ! empty( $params['all_access'] ) ? true : false;
546 } else {
547 $all_access = true;
548 }
549
550 $where = '';
551 if ( ! $all_access ) {
552 $where .= $this->get_sql_where_allow_access_sites( 'wp' );
553 }
554
555 $select_stats = ' ( SELECT COUNT(wp.id) as count_all ';
556 if ( ! empty( $params['count_disconnected'] ) ) {
557 $select_stats .= ',( SELECT COUNT(wp_disconnected.id) FROM ' . $this->table_name( 'wp' ) . ' wp_disconnected LEFT JOIN ' . $this->table_name( 'wp_sync' ) . ' as wp_sync ';
558 $select_stats .= ' ON wp_disconnected.id = wp_sync.wpid WHERE wp_sync.sync_errors != "" ) as count_disconnected ';
559 }
560 if ( ! empty( $params['count_suspended'] ) ) {
561 $select_stats .= ',( SELECT COUNT(wp_suspended.id) FROM ' . $this->table_name( 'wp' ) . ' wp_suspended WHERE wp_suspended.suspended = 1 ) as count_suspended ';
562 }
563 $qry = 'SELECT * FROM ' . $select_stats;
564 $qry .= ' FROM ' . $this->table_name( 'wp' ) . ' wp ' . $where . ' ) as wp_stats ';
565
566 return $this->wpdb->get_row( $qry, ARRAY_A ); //phpcs:ignore -- ok.
567 }
568
569 /**
570 * Get Child site wp_options database table.
571 *
572 * @param array $website Child Site array.
573 * @param mixed $option Child Site wp_options table name.
574 * @param mixed $default_value default value.
575 * @param mixed $json_format Is json format value.
576 *
577 * @return string|null Database query result (as string), or null on failure.
578 */
579 public function get_website_option( $website, $option, $default_value = null, $json_format = false ) { //phpcs:ignore -- NOSONAR - complex.
580
581 if ( is_array( $website ) ) {
582 if ( isset( $website[ $option ] ) ) {
583 $value = $website[ $option ];
584 if ( true === $json_format ) {
585 $value = ! empty( $value ) ? json_decode( $value, true ) : array();
586 return is_array( $value ) ? $value : array();
587 } else {
588 return $value;
589 }
590 }
591 $site_id = $website['id'];
592 } elseif ( is_object( $website ) ) {
593 if ( property_exists( $website, $option ) ) {
594 $value = $website->{$option};
595 if ( true === $json_format ) {
596 $value = ! empty( $value ) ? json_decode( $value, true ) : array();
597 return is_array( $value ) ? $value : array();
598 } else {
599 return $value;
600 }
601 }
602 $site_id = $website->id;
603 } elseif ( is_numeric( $website ) ) { // to support $site_id = 0, for global options.
604 $site_id = $website;
605 } else {
606 return false;
607 }
608
609 $value = $this->wpdb->get_var( $this->wpdb->prepare( 'SELECT value FROM ' . $this->table_name( 'wp_options' ) . ' WHERE wpid = %d AND name = "' . $this->escape( $option ) . '"', $site_id ) );
610
611 if ( null === $value && null !== $default_value ) {
612 return $default_value;
613 }
614
615 if ( true === $json_format ) {
616 $value = ! empty( $value ) ? json_decode( $value, true ) : array();
617 return is_array( $value ) ? $value : array();
618 } else {
619 return $value;
620 }
621 }
622
623 /**
624 * Get Child site wp_options json value.
625 *
626 * @since 5.1.1
627 *
628 * @param array $website Child Site array.
629 * @param mixed $option Child Site wp_options table name.
630 * @param mixed $default_value default value.
631 *
632 * @return string|null Database query result (as string), or null on failure.
633 */
634 public function get_json_website_option( $website, $option, $default_value = null ) {
635 return $this->get_website_option( $website, $option, $default_value, true );
636 }
637
638 /**
639 * Get child site options.
640 *
641 * @param array $website Child site.
642 * @param mixed $options Child site options name.
643 *
644 * @return string|null Database query result (as string), or null on failure.
645 */
646 public function get_website_options_array( &$website, $options ) { // phpcs:ignore -- NOSONAR - complex.
647
648 if ( ! is_array( $options ) || empty( $options ) ) {
649 return array();
650 }
651
652 if ( is_array( $website ) ) {
653 $site_id = $website['id'];
654 } elseif ( is_object( $website ) ) {
655 $site_id = $website->id;
656 } elseif ( is_numeric( $website ) ) { // to support $site_id = 0 for global options.
657 $site_id = $website;
658 } else {
659 return array();
660 }
661
662 $arr_options = array();
663 $get_options = array();
664
665 foreach ( $options as $option ) {
666 if ( is_array( $website ) ) {
667 if ( isset( $website[ $option ] ) ) {
668 $arr_options[ $option ] = $website[ $option ];
669 } else {
670 $get_options[] = $option;
671 }
672 } elseif ( is_object( $website ) ) {
673 if ( property_exists( $website, $option ) ) {
674 $arr_options[ $option ] = $website->{$option};
675 } else {
676 $get_options[] = $option;
677 }
678 } else {
679 $get_options[] = $option;
680 }
681 }
682
683 if ( empty( $get_options ) ) {
684 return $arr_options; // all options.
685 }
686
687 $options_name = implode( "','", $get_options );
688 $options_name = "'" . $options_name . "'";
689
690 $options_db = $this->wpdb->get_results( $this->wpdb->prepare( 'SELECT name, value FROM ' . $this->table_name( 'wp_options' ) . ' WHERE wpid = %d AND name IN (' . $options_name . ')', $site_id ) );
691
692 $fill_options = array(
693 'primary_lasttime_backup',
694 );
695
696 foreach ( (array) $options_db as $o ) {
697 $arr_options[ $o->name ] = $o->value;
698 if ( in_array( $o->name, $fill_options ) ) {
699 if ( is_array( $website ) ) {
700 if ( ! isset( $website[ $o->name ] ) ) {
701 $website[ $o->name ] = $o->value;
702 }
703 } elseif ( is_object( $website ) ) {
704 if ( ! property_exists( $website, $o->name ) ) {
705 $website->{$o->name} = $o->value;
706 }
707 }
708 }
709 }
710 return $arr_options;
711 }
712
713 /**
714 * Update child site options.
715 *
716 * @param object $website Child site object.
717 * @param mixed $option Option to update.
718 * @param mixed $value Value to update with.
719 */
720 public function update_website_option( $website, $option, $value ) {
721
722 if ( is_numeric( $website ) ) {
723 $site_id = intval( $website );
724 } else {
725 $site_id = $website->id;
726 }
727
728 $rslt = $this->wpdb->get_results( $this->wpdb->prepare( 'SELECT name FROM ' . $this->table_name( 'wp_options' ) . ' WHERE wpid = %d AND name = "' . $this->escape( $option ) . '"', $site_id ) );
729 if ( empty( $rslt ) ) {
730 $this->wpdb->insert(
731 $this->table_name( 'wp_options' ),
732 array(
733 'wpid' => $site_id,
734 'name' => $option,
735 'value' => $value,
736 )
737 );
738 } else {
739 $this->wpdb->update(
740 $this->table_name( 'wp_options' ),
741 array( 'value' => $value ),
742 array(
743 'wpid' => $site_id,
744 'name' => $option,
745 )
746 );
747 }
748 }
749
750
751 /**
752 * Get general Child site option.
753 *
754 * @param mixed $option Child Site option name.
755 *
756 * @return string|null Database query result (as string), or null on failure.
757 */
758 private function get_general_website_option( $option ) {
759
760 if ( null !== static::$general_options ) {
761 if ( isset( static::$general_options[ $option ] ) ) {
762 return static::$general_options[ $option ];
763 }
764 } else {
765 static::$general_options[] = array();
766 }
767
768 $val = $this->wpdb->get_var( $this->wpdb->prepare( 'SELECT value FROM ' . $this->table_name( 'wp_options' ) . ' WHERE wpid = %d AND name = "' . $this->escape( $option ) . '"', 0 ) );
769
770 static::$general_options[ $option ] = $val;
771 return $val;
772 }
773
774 /**
775 * Get child site options.
776 *
777 * @param mixed $options Child site options name.
778 *
779 * @return string|null Database query result (as string), or null on failure.
780 */
781 public function get_general_options_array( $options ) {
782
783 if ( ! is_array( $options ) || empty( $options ) ) {
784 return array();
785 }
786
787 $return_options = array();
788 if ( null !== static::$general_options ) {
789 foreach ( static::$general_options as $opt => $val ) {
790 if ( in_array( $opt, $options ) ) {
791 $return_options[ $opt ] = $val;
792 }
793 }
794 } else {
795 static::$general_options[] = array();
796 }
797
798 $diff_options = array();
799 foreach ( $options as $opt ) {
800 if ( ! isset( $return_options[ $opt ] ) ) {
801 $diff_options[] = $opt;
802 }
803 }
804
805 $options_name = implode( "','", $diff_options );
806 $options_name = "'" . $options_name . "'";
807
808 $options_db = $this->wpdb->get_results( $this->wpdb->prepare( 'SELECT name, value FROM ' . $this->table_name( 'wp_options' ) . ' WHERE wpid = %d AND name IN (' . $options_name . ')', 0 ) );
809
810 foreach ( (array) $options_db as $o ) {
811 $return_options[ $o->name ] = $o->value;
812 static::$general_options[ $o->name ] = $o->value;
813 }
814 return $return_options;
815 }
816
817 /**
818 * Update general site options.
819 *
820 * @param mixed $option Option to update.
821 * @param mixed $value Value to update with.
822 * @param string $type_value Type values: single|array.
823 */
824 public function update_general_option( $option, $value, $type_value = 'single' ) {
825
826 if ( 'array' === $type_value ) {
827 if ( empty( $value ) ) {
828 $value = array();
829 } elseif ( ! is_array( $value ) ) {
830 return false;
831 }
832 $value = wp_json_encode( $value );
833 }
834
835 if ( null === static::$general_options ) {
836 static::$general_options[] = array();
837 }
838 static::$general_options[ $option ] = $value;
839
840 $rslt = $this->wpdb->get_results( $this->wpdb->prepare( 'SELECT name FROM ' . $this->table_name( 'wp_options' ) . ' WHERE wpid = %d AND name = "' . $this->escape( $option ) . '"', 0 ) );
841
842 if ( empty( $rslt ) ) {
843 $this->wpdb->insert(
844 $this->table_name( 'wp_options' ),
845 array(
846 'wpid' => 0,
847 'name' => $option,
848 'value' => $value,
849 )
850 );
851 } else {
852 $this->wpdb->update(
853 $this->table_name( 'wp_options' ),
854 array( 'value' => $value ),
855 array(
856 'wpid' => 0,
857 'name' => $option,
858 )
859 );
860 }
861 return true;
862 }
863
864 /**
865 * Get general Child site option.
866 *
867 * @param mixed $opt Child Site option name.
868 * @param string $type_value Type values: single|array.
869 *
870 * @return string|null Database query result (as string), or null on failure.
871 */
872 public function get_general_option( $opt, $type_value = 'single' ) {
873 if ( 'single' === $type_value ) {
874 return $this->get_general_website_option( $opt );
875 } elseif ( 'array' === $type_value ) {
876 $json_value = $this->get_general_website_option( $opt );
877 if ( empty( $json_value ) ) {
878 return array();
879 }
880 return json_decode( $json_value, true );
881 }
882 return false;
883 }
884
885 /**
886 * Get child sites by user ID.
887 *
888 * @param int $userid User ID.
889 * @param bool $selectgroups Selected groups.
890 * @param null $search_site Site search field value.
891 * @param string $orderBy Order list by. Default: URL.
892 *
893 * @return array|object|null Database query results or null on failer.
894 */
895 public function get_websites_by_user_id( $userid, $selectgroups = false, $search_site = null, $orderBy = 'wp.url' ) {
896 return $this->get_results_result( $this->get_sql_websites_by_user_id( $userid, $selectgroups, $search_site, $orderBy ) );
897 }
898
899 /**
900 * Get child sites.
901 *
902 * @return string SQL string.
903 */
904 public function get_sql_websites() {
905 $where = $this->get_sql_where_allow_access_sites( 'wp' );
906
907 return 'SELECT wp.*,wp_sync.*,wp_optionview.*
908 FROM ' . $this->table_name( 'wp' ) . ' wp
909 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
910 JOIN ' . $this->get_option_view() . ' wp_optionview ON wp.id = wp_optionview.wpid
911 WHERE 1 ' . $where;
912 }
913
914 /**
915 * Get child sites by user id via SQL.
916 *
917 * @param int $userid Given user ID.
918 * @param bool $selectgroups Selected groups. Default: false.
919 * @param null $search_site Site search field value. Default: null.
920 * @param string $orderBy Order list by. Default: URL.
921 * @param bool $offset Query offset. Default: false.
922 * @param bool $rowcount Row count. Default: falese.
923 *
924 * @return object|null Return database query or null on failure.
925 *
926 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
927 */
928 public function get_sql_websites_by_user_id( $userid, $selectgroups = false, $search_site = null, $orderBy = 'wp.url', $offset = false, $rowcount = false ) {
929 if ( MainWP_Utility::ctype_digit( $userid ) ) {
930 $where = '';
931 if ( null !== $search_site ) {
932 $search_site = trim( $search_site );
933 $where = ' AND (wp.name LIKE "%' . $search_site . '%" OR wp.url LIKE "%' . $search_site . '%") ';
934 }
935
936 $where .= $this->get_sql_where_allow_access_sites( 'wp' );
937
938 if ( $selectgroups ) {
939 $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*, 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
940 FROM ' . $this->table_name( 'wp' ) . ' wp
941 LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
942 LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
943 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
944 JOIN ' . $this->get_option_view() . ' wp_optionview ON wp.id = wp_optionview.wpid
945 WHERE wp.userid = ' . $userid . "
946 $where
947 GROUP BY wp.id, wp_sync.sync_id
948 ORDER BY " . $orderBy;
949 } else {
950 $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*
951 FROM ' . $this->table_name( 'wp' ) . ' wp
952 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
953 JOIN ' . $this->get_option_view() . ' wp_optionview ON wp.id = wp_optionview.wpid
954 WHERE wp.userid = ' . $userid . "
955 $where
956 ORDER BY " . $orderBy;
957 }
958
959 if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
960 $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
961 } elseif ( false !== $rowcount ) {
962 $qry .= ' LIMIT ' . $rowcount;
963 }
964
965 return $qry;
966 }
967
968 return null;
969 }
970
971 /**
972 * Get SQL to get child sites for current user.
973 *
974 * @param bool $selectgroups Selected groups. Default: false.
975 * @param null $search_site Site search field value. Default: null.
976 * @param string $orderBy Order list by. Default: URL.
977 * @param bool $offset Query offset. Default: false.
978 * @param bool $rowcount Row count. Default: false.
979 * @param null $extraWhere Extra WHERE. Default: null.
980 * @param bool $for_manager For role manager. Default: false.
981 * @param mixed $extra_view Extra view. Default favi_icon.
982 * @param string $is_staging yes|no Is child site a staging site.
983 * @param array $params other params.
984 *
985 * @return object|null Database query results or null on failure.
986 *
987 * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
988 */
989 public function get_sql_websites_for_current_user( // phpcs:ignore -- NOSONAR - complex.
990 $selectgroups = false,
991 $search_site = null,
992 $orderBy = 'wp.url',
993 $offset = false,
994 $rowcount = false,
995 $extraWhere = null,
996 $for_manager = false,
997 $extra_view = array( 'favi_icon' ),
998 $is_staging = 'no',
999 $params = array()
1000 ) {
1001
1002 $where = '';
1003 if ( MainWP_System::instance()->is_multi_user() ) {
1004
1005 /**
1006 * Current user global.
1007 *
1008 * @global string
1009 */
1010 global $current_user;
1011
1012 $where .= ' AND wp.userid = ' . $current_user->ID . ' ';
1013 }
1014
1015 if ( null !== $search_site ) {
1016 $search_site = trim( $search_site );
1017 $where .= ' AND (wp.name LIKE "%' . $search_site . '%" OR wp.url LIKE "%' . $search_site . '%") ';
1018 }
1019
1020 if ( ! empty( $extraWhere ) ) {
1021 $where .= ' AND ' . $extraWhere . ' ';
1022 }
1023
1024 if ( ! $for_manager ) {
1025 $where .= $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
1026 }
1027
1028 $connected_sql = '';
1029
1030 if ( is_array( $params ) && isset( $params['connected'] ) && 'yes' === $params['connected'] ) {
1031 $connected_sql = ' AND wp_sync.sync_errors = "" ';
1032 } elseif ( is_array( $params ) && isset( $params['connected'] ) && 'no' === $params['connected'] ) {
1033 $connected_sql = ' AND wp_sync.sync_errors <> "" ';
1034 }
1035
1036 $limit = '';
1037 if ( $params && is_array( $params ) ) {
1038 $s = isset( $params['s'] ) ? $params['s'] : '';
1039 $exclude = isset( $params['exclude'] ) ? wp_parse_id_list( $params['exclude'] ) : array();
1040 $include = isset( $params['include'] ) ? wp_parse_id_list( $params['include'] ) : array();
1041 $status = isset( $params['status'] ) ? wp_parse_list( $params['status'] ) : array();
1042 $page = isset( $params['page'] ) ? intval( $params['page'] ) : false;
1043 $per_page = isset( $params['per_page'] ) ? intval( $params['per_page'] ) : false;
1044
1045 if ( ! empty( $s ) ) {
1046 $where .= ' AND ( wp.id LIKE "%' . $this->escape( $s ) . '%" OR wp.name LIKE "%' . $this->escape( $s ) . '%" OR wp.url LIKE "%' . $this->escape( $s ) . '%" ) ';
1047 }
1048
1049 if ( ! empty( $exclude ) ) {
1050 $where .= ' AND wp.id NOT IN (' . implode( ',', $exclude ) . ') ';
1051 }
1052
1053 if ( ! empty( $include ) ) {
1054 $where .= ' AND wp.id IN (' . implode( ',', $include ) . ') ';
1055 }
1056
1057 // any, connected, disconnected, suspended, available_update.
1058 if ( ! empty( $status ) && is_array( $status ) && ! in_array( 'any', $status ) ) {
1059 $status_conds = array();
1060 if ( in_array( 'available_update', $status ) ) {
1061 $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 <> '[]' ) ";
1062 $results = $this->wpdb->get_results( 'SELECT wpid FROM ' . $this->table_name( 'wp_options' ) . " WHERE name = 'wp_upgrades' AND value <> '' AND value <> '[]' " );
1063 if ( $results ) {
1064 $wp_ids = array();
1065 foreach ( $results as $item ) {
1066 if ( ! empty( $item->wpid ) ) {
1067 $wp_ids[] = $item->wpid;
1068 }
1069 }
1070 $wp_ids = ! empty( $wp_ids ) ? array_unique( $wp_ids ) : array();
1071 if ( ! empty( $wp_ids ) ) {
1072 $available_sql .= ' OR wp.id IN ( ' . implode( ',', $wp_ids ) . ' )';
1073 }
1074 }
1075 $status_conds[] = ' ( ' . $available_sql . ') ';
1076 }
1077
1078 if ( in_array( 'connected', $status ) ) {
1079 $status_conds[] = ' ( wp_sync.sync_errors == "" ) ';
1080 }
1081 if ( in_array( 'disconnected', $status ) ) {
1082 $status_conds[] = " wp_sync.sync_errors <> '' ";
1083 }
1084
1085 if ( in_array( 'suspended', $status ) ) {
1086 $status_conds[] = ' wp.suspended = 1 ';
1087 }
1088
1089 if ( ! empty( $status_conds ) ) {
1090 $where .= ' AND ( ' . implode( ' OR ', $status_conds ) . ' ) ';
1091 }
1092 }
1093
1094 if ( ! empty( $page ) && ! empty( $per_page ) ) {
1095 $limit = ( $page - 1 ) * $per_page . ',' . $per_page;
1096 }
1097 }
1098
1099 if ( 'wp.url' === $orderBy ) {
1100 $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '')";
1101 }
1102
1103 // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax.
1104 if ( $selectgroups ) {
1105 $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*, 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,
1106 wpclient.name as client_name
1107 FROM ' . $this->table_name( 'wp' ) . ' wp
1108 LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
1109 LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
1110 LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id
1111 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1112 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
1113 WHERE 1 ' . $where . $connected_sql . '
1114 GROUP BY wp.id, wp_sync.sync_id
1115 ORDER BY ' . $orderBy;
1116 } else {
1117 $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*, wpclient.name as client_name
1118 FROM ' . $this->table_name( 'wp' ) . ' wp
1119 LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id
1120 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1121 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
1122 WHERE 1 ' . $where . $connected_sql . '
1123 GROUP BY wp.id, wp_sync.sync_id
1124 ORDER BY ' . $orderBy;
1125 }
1126
1127 if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
1128 $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
1129 } elseif ( false !== $rowcount ) {
1130 $qry .= ' LIMIT ' . $rowcount;
1131 } elseif ( ! empty( $limit ) ) {
1132 $qry .= ' LIMIT ' . $limit;
1133 } else {
1134 // load all sites so check to support limit sites loading.
1135 $limit_sites = ! empty( $params['limit_sites'] ) ? intval( $params['limit_sites'] ) : 0;
1136 if ( ! empty( $limit_sites ) ) {
1137 $current_page = (int) get_option( 'mainwp_manage_updates_limit_current_page', 0 );
1138 $current_page = $current_page > 0 ? $current_page - 1 : 0;
1139 $start = $current_page * $limit_sites;
1140 $qry .= ' LIMIT ' . intval( $start ) . ', ' . intval( $limit_sites );
1141 }
1142 }
1143
1144 return $qry;
1145 }
1146
1147
1148
1149 /**
1150 * Get SQL to get wp child sites for current user.
1151 *
1152 * @since 4.3
1153 *
1154 * @param array $params params .
1155 *
1156 * @return object|null Database query results or null on failure.
1157 */
1158 public function get_sql_wp_for_current_user( $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
1159 if ( ! is_array( $params ) ) {
1160 $params = array();
1161 }
1162
1163 $selectgroups = ! empty( $params['select_groups'] ) ? true : false;
1164 $search_site = isset( $params['search_site'] ) && ! empty( $params['search_site'] ) ? $params['search_site'] : null;
1165 $orderBy = isset( $params['order_by'] ) && ! empty( $params['order_by'] ) ? $params['order_by'] : 'wp.url';
1166 $offset = isset( $params['offset'] ) ? $params['offset'] : false;
1167 $rowcount = isset( $params['row_count'] ) ? $params['row_count'] : false;
1168 $for_manager = isset( $params['for_manager'] ) ? $params['for_manager'] : false;
1169 $extraWhere = isset( $params['extra_where'] ) && ! empty( $params['extra_where'] ) ? $params['extra_where'] : null;
1170 $extra_view = isset( $params['extra_view'] ) && is_array( $params['extra_view'] ) && ! empty( $params['extra_view'] ) ? $params['extra_view'] : array( 'favi_icon' );
1171 $extra_join = isset( $params['extra_join'] ) ? $params['extra_join'] : '';
1172
1173 $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();
1174 $extra_select_sql_fields = isset( $params['extra_select_sql_fields'] ) && ! empty( $params['extra_select_sql_fields'] ) ? $params['extra_select_sql_fields'] : '';
1175
1176 $is_staging = isset( $params['is_staging'] ) && 'yes' === $params['is_staging'] ? 'yes' : 'no';
1177 $count_only = isset( $params['count_only'] ) && $params['count_only'] ? true : false;
1178
1179 $where = '';
1180
1181 if ( null !== $search_site ) {
1182 $search_site = trim( $search_site );
1183 $where .= ' AND (wp.name LIKE "%' . $this->escape( $search_site ) . '%" OR wp.url LIKE "%' . $this->escape( $search_site ) . '%") ';
1184 }
1185
1186 if ( null !== $extraWhere ) {
1187 $where .= ' AND ' . $extraWhere;
1188 }
1189
1190 if ( ! $for_manager ) {
1191 $where .= $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
1192 }
1193
1194 if ( 'wp.url' === $orderBy ) {
1195 $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '')";
1196 }
1197
1198 $select_wp_fields = $this->get_sql_select_wp_valid_fields( $extra_select_wp_fields );
1199
1200 if ( ! empty( $extra_select_sql_fields ) ) {
1201 $extra_select_sql_fields = ',' . $extra_select_sql_fields;
1202 }
1203
1204 // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax.
1205 if ( $selectgroups ) {
1206 if ( $count_only ) {
1207 $select = ' COUNT(DISTINCT(wp.id)) ';
1208 } else {
1209 $select = $select_wp_fields . '
1210 ' . $extra_select_sql_fields . '
1211 ,wp_sync.sync_errors,wp_optionview.*, 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 ';
1212 }
1213 $qry = 'SELECT ' . $select . '
1214 FROM ' . $this->table_name( 'wp' ) . ' wp
1215 LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
1216 LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
1217 LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id
1218 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1219 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid ' .
1220 $extra_join . '
1221 WHERE 1 ' . $where;
1222 if ( ! $count_only ) {
1223 $qry .= ' GROUP BY wp.id, wp_sync.sync_id';
1224 }
1225 $qry .= ' ORDER BY ' . $orderBy;
1226 } else {
1227 if ( $count_only ) {
1228 $select = ' COUNT(DISTINCT(wp.id)) ';
1229 } else {
1230 $select = $select_wp_fields . '
1231 ' . $extra_select_sql_fields . '
1232 ,wp_sync.sync_errors,wp_optionview.*, wpclient.name as client_name ';
1233 }
1234 $qry = 'SELECT ' . $select . '
1235 FROM ' . $this->table_name( 'wp' ) . ' wp
1236 LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id
1237 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1238 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid ' .
1239 $extra_join . '
1240 WHERE 1 ' . $where;
1241 if ( ! $count_only ) {
1242 $qry .= ' GROUP BY wp.id, wp_sync.sync_id';
1243 }
1244 $qry .= ' ORDER BY ' . $orderBy;
1245 }
1246
1247 if ( ! $count_only ) {
1248 if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
1249 $qry .= ' LIMIT ' . intval( $offset ) . ', ' . intval( $rowcount );
1250 } elseif ( false !== $rowcount ) {
1251 $qry .= ' LIMIT ' . intval( $rowcount );
1252 }
1253 }
1254 return $qry;
1255 }
1256 /**
1257 * Get SQL select websites fields.
1258 *
1259 * @since 4.3
1260 *
1261 * @param array $other_fields extra select wp fields .
1262 *
1263 * @return string sql string.
1264 */
1265 public function get_sql_select_wp_valid_fields( $other_fields = array() ) {
1266
1267 $allow_other_fields = array(
1268 'offline_checks_last',
1269 'offline_check_result', // 1 - online, -1 offline.
1270 'http_response_code',
1271 'disable_health_check',
1272 'health_threshold',
1273 'note',
1274 'statsUpdate',
1275 'directories',
1276 'plugin_upgrades',
1277 'theme_upgrades',
1278 'translation_upgrades',
1279 'premium_upgrades',
1280 'securityIssues',
1281 'themes',
1282 'ignored_themes',
1283 'plugins',
1284 'ignored_plugins',
1285 'users',
1286 'categories',
1287 'pluginDir',
1288 'automatic_update',
1289 'backup_before_upgrade',
1290 'mainwpdir',
1291 'is_ignoreCoreUpdates',
1292 'is_ignorePluginUpdates',
1293 'is_ignoreThemeUpdates',
1294 'verify_certificate',
1295 'force_use_ipv4',
1296 'ssl_version',
1297 'http_user',
1298 'http_pass',
1299 'wpe',
1300 'is_staging',
1301 'client_id',
1302 );
1303
1304 $default_fields = array( 'id', 'url', 'name', 'adminname', 'verify_certificate', 'ssl_version', 'http_user', 'http_pass', 'suspended' );
1305
1306 $select = ' ';
1307
1308 foreach ( $default_fields as $field ) {
1309 $select .= 'wp.' . $this->escape( $field ) . ',';
1310 }
1311 foreach ( $other_fields as $field ) {
1312 if ( ! in_array( $field, $allow_other_fields ) ) {
1313 continue;
1314 }
1315 if ( in_array( $field, $default_fields ) ) {
1316 continue;
1317 }
1318 $select .= 'wp.' . $this->escape( $field ) . ',';
1319 }
1320 $select = rtrim( $select, ',' );
1321 return $select;
1322 }
1323
1324 /**
1325 * Get child sites for current user.
1326 *
1327 * @param array $params to get sites. Default: array().
1328 *
1329 * @return array Results or null on failure.
1330 *
1331 * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
1332 */
1333 public function get_websites_for_current_user( $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
1334 if ( ! is_array( $params ) ) {
1335 $params = array();
1336 }
1337
1338 $selectgroups = isset( $params['selectgroups'] ) ? $params['selectgroups'] : false;
1339 $search_site = isset( $params['search_site'] ) ? $params['search_site'] : null;
1340 $orderBy = isset( $params['order_by'] ) ? $params['order_by'] : 'wp.url';
1341 $offset = isset( $params['offset'] ) ? $params['offset'] : false;
1342 $rowcount = isset( $params['rowcount'] ) ? $params['rowcount'] : false;
1343 $extraWhere = isset( $params['where'] ) ? $params['where'] : null;
1344 $extra_view = isset( $params['extra_view'] ) && is_array( $params['extra_view'] ) ? $params['extra_view'] : array( 'favi_icon' );
1345 $is_staging = isset( $params['is_staging'] ) ? $params['is_staging'] : 'no';
1346 $full_data = isset( $params['full_data'] ) && $params['full_data'] && ( 'no' !== $params['full_data'] ) ? true : false;
1347 $select_data = isset( $params['select_data'] ) && is_array( $params['select_data'] ) ? $params['select_data'] : false;
1348 $format = isset( $params['format'] ) ? $params['format'] : '';
1349 $clients = isset( $params['client'] ) ? $params['client'] : '';
1350 $fields = isset( $params['fields'] ) && is_array( $params['fields'] ) ? $params['fields'] : array();
1351
1352 $for_manager = false;
1353
1354 $urlsWhere = '';
1355
1356 if ( isset( $params['urls'] ) && ! empty( $params['urls'] ) ) {
1357 $urls = explode( ';', $params['urls'] );
1358 foreach ( $urls as $url ) {
1359 $url = str_replace( array( 'https://www.', 'http://www.', 'https://', 'http://', 'www.' ), array( '', '', '', '', '' ), $url );
1360 if ( '/' !== substr( $url, - 1 ) ) {
1361 $url .= '/';
1362 }
1363 $urlsWhere .= '"' . $this->escape( $url ) . '", ';
1364 }
1365 $urlsWhere = rtrim( $urlsWhere, ', ' );
1366 }
1367
1368 if ( ! empty( $urlsWhere ) ) {
1369 $urlsWhere = " ( replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '') IN ( " . $urlsWhere . ') ) ';
1370
1371 if ( empty( $extraWhere ) ) {
1372 $extraWhere = $urlsWhere;
1373 } else {
1374 $extraWhere = $extraWhere . ' AND ' . $urlsWhere;
1375 }
1376 }
1377
1378 $clientWhere = '';
1379 if ( ! empty( $clients ) ) {
1380 $clients = explode( ';', $clients );
1381 foreach ( $clients as $client ) {
1382 if ( is_numeric( $client ) ) {
1383 $clientWhere .= intval( $client ) . ', ';
1384 }
1385 }
1386 $clientWhere = rtrim( $clientWhere, ', ' );
1387 }
1388
1389 if ( ! empty( $clientWhere ) ) {
1390 $clientWhere = ' ( wp.client_id IN ( ' . $clientWhere . ') ) ';
1391 if ( empty( $extraWhere ) ) {
1392 $extraWhere = $clientWhere;
1393 } else {
1394 $extraWhere = $extraWhere . ' AND ' . $clientWhere;
1395 }
1396 }
1397
1398 $args = array(
1399 's' => isset( $params['s'] ) ? $params['s'] : '',
1400 'exclude' => isset( $params['exclude'] ) && ! empty( $params['exclude'] ) ? wp_parse_id_list( $params['exclude'] ) : array(),
1401 'include' => isset( $params['include'] ) && ! empty( $params['include'] ) ? wp_parse_id_list( $params['include'] ) : array(),
1402 'status' => isset( $params['status'] ) && ! empty( $params['status'] ) ? wp_parse_list( $params['status'] ) : '',
1403 'page' => isset( $params['paged'] ) ? intval( $params['paged'] ) : false,
1404 'per_page' => isset( $params['items_per_page'] ) ? intval( $params['items_per_page'] ) : false,
1405 );
1406
1407 $data = array( 'id', 'url', 'name', 'client_id' );
1408
1409 if ( $full_data ) {
1410 $data = array(
1411 'id',
1412 'url',
1413 'name',
1414 'offline_checks_last',
1415 'offline_check_result', // 1 - online, -1 offline.
1416 'http_response_code',
1417 'disable_health_check',
1418 'health_threshold',
1419 'note',
1420 'dbsize',
1421 'plugin_upgrades',
1422 'theme_upgrades',
1423 'translation_upgrades',
1424 'securityIssues',
1425 'themes',
1426 'plugins',
1427 'automatic_update',
1428 'sync_errors',
1429 'dtsAutomaticSync',
1430 'dtsAutomaticSyncStart',
1431 'dtsSync',
1432 'dtsSyncStart',
1433 'last_post_gmt',
1434 'health_value',
1435 'phpversion',
1436 'wp_upgrades',
1437 'security_stats',
1438 'client_id',
1439 'adminname',
1440 'privkey',
1441 'http_user',
1442 'http_pass',
1443 'ssl_version',
1444 'signature_algo',
1445 'verify_method',
1446 'verify_certificate',
1447 'suspended',
1448 );
1449
1450 if ( ! in_array( 'security_stats', $extra_view ) ) {
1451 $extra_view[] = 'security_stats';
1452 }
1453 }
1454
1455 if ( ! empty( $select_data ) && is_array( $select_data ) ) {
1456 $data = $select_data;
1457 }
1458
1459 if ( $selectgroups ) {
1460 $data[] = 'wpgroups';
1461 $data[] = 'wpgroupids';
1462 }
1463
1464 if ( ! empty( $fields ) ) {
1465 $data = array_unique( array_merge( $fields, $data ) ); // to prevent difference fields name.
1466 }
1467
1468 $dbwebsites = array();
1469 $websites = $this->query( $this->get_sql_websites_for_current_user( $selectgroups, $search_site, $orderBy, $offset, $rowcount, $extraWhere, $for_manager, $extra_view, $is_staging, $args ) );
1470 while ( $websites && ( $website = static::fetch_object( $websites ) ) ) {
1471
1472 $obj_data = MainWP_Utility::map_site( $website, $data );
1473
1474 if ( $full_data ) {
1475 $sum_upgrades = 0;
1476 if ( '' !== $obj_data->plugin_upgrades ) {
1477 $plugin_upgrades = json_decode( $obj_data->plugin_upgrades, true );
1478 if ( is_array( $plugin_upgrades ) ) {
1479 $sum_upgrades += count( $plugin_upgrades );
1480 }
1481 }
1482
1483 if ( '' !== $obj_data->theme_upgrades ) {
1484 $theme_upgrades = json_decode( $obj_data->theme_upgrades, true );
1485 if ( is_array( $theme_upgrades ) ) {
1486 $sum_upgrades += count( $theme_upgrades );
1487 }
1488 }
1489
1490 if ( '' !== $obj_data->wp_upgrades ) {
1491 $wp_upgrades = json_decode( $obj_data->wp_upgrades, true );
1492 if ( is_array( $wp_upgrades ) ) {
1493 $sum_upgrades += count( $wp_upgrades );
1494 }
1495 }
1496 $obj_data->sum_of_upgrades = $sum_upgrades;
1497 }
1498
1499 if ( 'array' === $format ) {
1500 $dbwebsites[] = $obj_data;
1501 } else {
1502 $dbwebsites[ $website->id ] = $obj_data;
1503 }
1504 }
1505 static::free_result( $websites );
1506 return $dbwebsites;
1507 }
1508
1509 /**
1510 * Get the child sites the current user has searched for.
1511 *
1512 * @param array $params Query parameters.
1513 *
1514 * @return boolean|null $qry Database query results or null on failure.
1515 *
1516 * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
1517 */
1518 public function get_sql_search_websites_for_current_user( $params ) { // phpcs:ignore -- NOSONAR - complex.
1519
1520 if ( ! is_array( $params ) ) {
1521 $params = array();
1522 }
1523
1524 $view = isset( $params['view'] ) ? $params['view'] : 'default'; // must be default to compatible with get_option_view().
1525 $selectgroups = isset( $params['selectgroups'] ) && $params['selectgroups'] ? true : false;
1526 $search_site = isset( $params['search'] ) ? $this->escape( trim( $params['search'] ) ) : null;
1527 $orderBy = isset( $params['orderby'] ) ? $params['orderby'] : 'wp.url';
1528 $offset = isset( $params['offset'] ) ? intval( $params['offset'] ) : false;
1529 $rowcount = isset( $params['rowcount'] ) ? intval( $params['rowcount'] ) : false;
1530 $extraWhere = isset( $params['extra_where'] ) ? $params['extra_where'] : null; // without AND prefix.
1531 $for_manager = isset( $params['for_manager'] ) && $params['for_manager'] ? true : false;
1532 $extra_view = isset( $params['extra_view'] ) ? $params['extra_view'] : array( 'favi_icon' );
1533 $is_staging = isset( $params['is_staging'] ) && 'yes' === $params['is_staging'] ? 'yes' : 'no';
1534 $is_count = isset( $params['count_only'] ) && $params['count_only'] ? true : false;
1535 $group_ids = isset( $params['group_id'] ) && ! empty( $params['group_id'] ) ? $params['group_id'] : array();
1536 $client_ids = isset( $params['client_id'] ) && ! empty( $params['client_id'] ) ? $params['client_id'] : array();
1537 $is_not = isset( $params['isnot'] ) && ! empty( $params['isnot'] ) ? true : false;
1538 $selected_sites = isset( $params['selected_sites'] ) ? $params['selected_sites'] : array();
1539
1540 if ( ! is_array( $group_ids ) ) {
1541 $group_ids = array();
1542 }
1543
1544 // valid group ids.
1545 $group_ids = array_filter(
1546 $group_ids,
1547 function ( $e ) {
1548 if ( 'nogroups' === $e ) {
1549 return true;
1550 }
1551 return ( is_numeric( $e ) && 0 < $e ) ? true : false;
1552 }
1553 );
1554
1555 if ( ! is_array( $client_ids ) ) {
1556 $client_ids = array();
1557 }
1558
1559 // valid group ids.
1560 $client_ids = array_filter(
1561 $client_ids,
1562 function ( $e ) {
1563 if ( 'noclients' === $e ) {
1564 return true;
1565 }
1566 return is_numeric( $e ) && ! empty( $e ) ? true : false; // to valid client ids.
1567 }
1568 );
1569
1570 if ( $selectgroups ) {
1571 $staging_group = get_option( 'mainwp_stagingsites_group_id' );
1572 if ( $staging_group && in_array( $staging_group, $group_ids ) ) {
1573 if ( empty( $group_ids ) ) {
1574 $is_staging = 'yes';
1575 } else {
1576 $is_staging = 'nocheckstaging';
1577 }
1578 }
1579 }
1580
1581 if ( ! is_array( $selected_sites ) ) {
1582 $selected_sites = array();
1583 }
1584 $selected_sites = MainWP_Utility::array_numeric_filter( $selected_sites );
1585
1586 $where = '';
1587 if ( MainWP_System::instance()->is_multi_user() ) {
1588
1589 /**
1590 * Current user global.
1591 *
1592 * @global string
1593 */
1594 global $current_user;
1595
1596 $where .= ' AND wp.userid = ' . $current_user->ID . ' ';
1597 }
1598
1599 if ( ! empty( $selected_sites ) ) {
1600 $where .= ' AND wp.id IN (' . implode( ',', $selected_sites ) . ') ';
1601 }
1602
1603 // for searching.
1604 if ( null !== $search_site && '' !== $search_site ) {
1605 $where .= ' AND (wp.name LIKE "%' . $search_site . '%" OR wp.url LIKE "%' . $search_site . '%") ';
1606 }
1607
1608 if ( null !== $extraWhere ) {
1609 $where .= ' AND ' . $extraWhere;
1610 }
1611
1612 if ( ! $for_manager ) {
1613 $where .= $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
1614 }
1615
1616 if ( $is_count ) {
1617 $orderBy = '';
1618 } elseif ( 'wp.url' === $orderBy ) {
1619 $orderBy = "replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '')";
1620 }
1621
1622 if ( ! empty( $orderBy ) ) {
1623 $orderBy = ' ORDER BY ' . $orderBy;
1624 }
1625
1626 $join_group = '';
1627 $where_group = '';
1628
1629 if ( in_array( 'nogroups', $group_ids ) ) {
1630 $join_group = ' LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid ';
1631 $group_ids = array_filter(
1632 $group_ids,
1633 function ( $e ) {
1634 return 'nogroups' !== $e;
1635 }
1636 );
1637 if ( ! empty( $group_ids ) ) {
1638 $groups = implode( ',', $group_ids );
1639 if ( $is_not ) {
1640 $where_group = ' AND wpgroup.groupid IS NOT NULL AND wpgroup.groupid NOT IN (' . $groups . ') ';
1641 // to fix.
1642 $sub_select_is_not = ' SELECT wp.id FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid WHERE wpgroup.groupid IN (' . $groups . ') ';
1643 $where_group .= ' AND wp.id NOT IN ( ' . $sub_select_is_not . ' ) ';
1644 } else {
1645 $where_group = ' AND ( wpgroup.groupid IS NULL OR wpgroup.groupid IN (' . $groups . ') ) ';
1646 }
1647 } elseif ( $is_not ) {
1648 $where_group = ' AND wpgroup.groupid IS NOT NULL ';
1649 } else {
1650 $where_group = ' AND wpgroup.groupid IS NULL ';
1651 }
1652 } elseif ( $group_ids ) {
1653 $groups = implode( ',', $group_ids );
1654 if ( $is_not ) {
1655 $join_group = ' LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid ';
1656 $where_group = ' AND ( wpgroup.groupid NOT IN (' . $groups . ') OR wpgroup.groupid IS NULL ) ';
1657 // to fix.
1658 $sub_select_is_not = ' SELECT wp.id FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid WHERE wpgroup.groupid IN (' . $groups . ') ';
1659 $where_group .= ' AND wp.id NOT IN ( ' . $sub_select_is_not . ' ) ';
1660 } else {
1661 $join_group = ' JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid ';
1662 $where_group = ' AND wpgroup.groupid IN (' . $groups . ') ';
1663 }
1664 }
1665
1666 $select_groups_belong = '';
1667
1668 if ( ! $is_count && $group_ids ) {
1669 $select_groups_belong = $this->get_select_groups_belong();
1670 }
1671
1672 $join_client = '';
1673 $where_client = '';
1674
1675 if ( in_array( 'noclients', $client_ids ) ) {
1676 $join_client = ' LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id ';
1677 $client_ids = array_filter(
1678 $client_ids,
1679 function ( $e ) {
1680 return 'noclients' !== $e;
1681 }
1682 );
1683 if ( ! empty( $client_ids ) ) {
1684 $clients = implode( ',', $client_ids );
1685 if ( $is_not ) {
1686 $where_client = ' AND wpclient.client_id IS NOT NULL AND wp.client_id NOT IN (' . $clients . ') ';
1687 } else {
1688 $where_client = ' AND wpclient.client_id IN (' . $clients . ') ';
1689 }
1690 } elseif ( $is_not ) {
1691 $where_client = ' AND wpclient.client_id IS NOT NULL ';
1692 } else {
1693 $where_client = ' AND wpclient.client_id IS NULL ';
1694 }
1695 } elseif ( $client_ids && ! empty( $client_ids ) ) {
1696 $clients = implode( ',', $client_ids );
1697 if ( $is_not ) {
1698 $join_client = ' LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id ';
1699 $where_client = ' AND ( wpclient.client_id NOT IN (' . $clients . ') OR wpclient.client_id IS NULL ) ';
1700 } else {
1701 $join_client = ' JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id ';
1702 $where_client = ' AND wpclient.client_id IN (' . $clients . ') ';
1703 }
1704 }
1705
1706 if ( '' === $join_client ) {
1707 $join_client = ' LEFT JOIN ' . $this->table_name( 'wp_clients' ) . ' wpclient ON wp.client_id = wpclient.client_id ';
1708 }
1709
1710 $light_fields = array(
1711 'wp.id',
1712 'wp.url',
1713 'wp.name',
1714 'wp.client_id',
1715 'wp.verify_certificate',
1716 'wp.http_user',
1717 'wp.http_pass',
1718 'wp.ssl_version',
1719 'wp.adminname',
1720 'wp.privkey',
1721 'wp.pubkey',
1722 'wp.wpe',
1723 'wp.is_staging',
1724 'wp.pubkey',
1725 'wp.force_use_ipv4',
1726 'wp.siteurl',
1727 'wp.suspended',
1728 'wp.mainwpdir',
1729 'wp.is_ignoreCoreUpdates',
1730 'wp.is_ignorePluginUpdates',
1731 'wp.is_ignoreThemeUpdates',
1732 'wp.backup_before_upgrade',
1733 'wp.userid',
1734 'wp_sync.sync_errors',
1735 );
1736
1737 $legacy_status_fields = array(
1738 'wp.offline_check_result', // 1 - online, -1 offline.
1739 'wp.http_response_code',
1740 'wp.http_code_noticed',
1741 'wp.offline_checks_last',
1742 );
1743
1744 $light_fields = array_merge( $light_fields, $legacy_status_fields );
1745
1746 $join_monitors = '';
1747
1748 $select_fields = array(
1749 'wp.*',
1750 'wp_sync.*',
1751 );
1752
1753 if ( 'light_view' === $view ) {
1754 $select_fields = $light_fields;
1755 } elseif ( 'monitor_view' === $view ) {
1756 $select_fields = $light_fields;
1757 $select_fields[] = 'mo.*';
1758 $join_monitors = ' LEFT JOIN ' . $this->table_name( 'monitors' ) . ' mo ON wp.id = mo.wpid AND mo.issub = 0 ';
1759 }
1760
1761 $select = implode( ',', $select_fields );
1762
1763 // wpgroups to fix issue for mysql 8.0, as groups will generate error syntax.
1764 if ( $selectgroups ) {
1765
1766 if ( empty( $join_group ) ) {
1767 $join_group = ' LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid ';
1768 }
1769
1770 $qry = 'SELECT ' . $select . ', wp_optionview.*, 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 ' .
1771 $select_groups_belong . ' FROM ' . $this->table_name( 'wp' ) . ' wp ' .
1772 $join_client . ' ' .
1773 $join_group .
1774 $join_monitors . '
1775 LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgroup.groupid = gr.id
1776
1777 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1778 JOIN ' . $this->get_option_view( $extra_view, $view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
1779 WHERE 1 ' . $where . $where_group . $where_client . '
1780 GROUP BY wp.id, wp_sync.sync_id ' .
1781 $orderBy;
1782 } else {
1783 $qry = 'SELECT ' . $select . ', wp_optionview.*, wpclient.name as client_name ' .
1784 $select_groups_belong . ' FROM ' . $this->table_name( 'wp' ) . ' wp ' .
1785 $join_group . ' ' .
1786 $join_client .
1787 $join_monitors . '
1788 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1789 JOIN ' . $this->get_option_view( $extra_view, $view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
1790 WHERE 1 ' . $where . $where_group . $where_client . '
1791 GROUP BY wp.id, wp_sync.sync_id ' .
1792 $orderBy;
1793 }
1794
1795 if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
1796 $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
1797 } elseif ( false !== $rowcount ) {
1798 $qry .= ' LIMIT ' . $rowcount;
1799 }
1800
1801 if ( ! empty( $params['dev_log_query'] ) ) {
1802 error_log( $qry ); //phpcs:ignore -- NOSONAR - for dev.
1803 }
1804
1805 return $qry;
1806 }
1807
1808 /**
1809 * Get child sites where allowed access via SQL.
1810 *
1811 * @param string $site_table_alias Child site table alias.
1812 * @param string $is_staging yes|no Is child site a staging site.
1813 *
1814 * @return boolean|null $_where Database query results or null on failure.
1815 */
1816 public function get_sql_where_allow_access_sites( $site_table_alias = '', $is_staging = 'no' ) { // phpcs:ignore -- NOSONAR - complex.
1817
1818 if ( empty( $site_table_alias ) ) {
1819 $site_table_alias = $this->table_name( 'wp' );
1820 }
1821
1822 // check to filter the staging sites.
1823 $where_staging = ' AND ' . $site_table_alias . '.is_staging = 0 ';
1824 if ( 'no' === $is_staging ) {
1825 $where_staging = ' AND ' . $site_table_alias . '.is_staging = 0 ';
1826 } elseif ( 'yes' === $is_staging ) {
1827 $where_staging = ' AND ' . $site_table_alias . '.is_staging = 1 ';
1828 } elseif ( 'nocheckstaging' === $is_staging ) {
1829 $where_staging = '';
1830 }
1831 // end staging filter.
1832
1833 $_where = $where_staging;
1834 // To fix bug run from cron job.
1835 if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
1836 return $_where;
1837 }
1838
1839 // To fix bug run from wp cli.
1840 if ( defined( 'WP_CLI' ) && WP_CLI ) {
1841 return $_where;
1842 }
1843
1844 // Run from Rest Api.
1845 if ( defined( 'MAINWP_REST_API_DOING' ) && MAINWP_REST_API_DOING ) {
1846 return $_where;
1847 }
1848
1849 /**
1850 * Filter: mainwp_currentuserallowedaccesssites
1851 *
1852 * Filters allowed sites for the current user.
1853 *
1854 * @since Unknown
1855 */
1856 $allowed_sites = apply_filters( 'mainwp_currentuserallowedaccesssites', 'all' );
1857
1858 if ( 'all' === $allowed_sites ) {
1859 return $_where;
1860 }
1861
1862 if ( is_array( $allowed_sites ) && ! empty( $allowed_sites ) ) {
1863 // valid group ids.
1864 $allowed_sites = array_filter(
1865 $allowed_sites,
1866 function ( $e ) {
1867 return is_numeric( $e ) ? true : false;
1868 }
1869 );
1870 $_where .= ' AND ' . $site_table_alias . '.id IN (' . implode( ',', $allowed_sites ) . ') ';
1871 } else {
1872 $_where .= ' AND 0 ';
1873 }
1874
1875 return $_where;
1876 }
1877
1878 /**
1879 * Get groupd where allowed access via SQL.
1880 *
1881 * @param string $group_table_alias Child site table alias.
1882 * @param string $with_staging yes|no Is child site a staging site.
1883 *
1884 * @return boolean|null $_where Database query results or null on failer.
1885 */
1886 public function get_sql_where_allow_groups( $group_table_alias = '', $with_staging = 'no' ) { // phpcs:ignore -- NOSONAR - complex.
1887
1888 if ( empty( $group_table_alias ) ) {
1889 $group_table_alias = $this->table_name( 'group' );
1890 }
1891
1892 // check to filter the staging group.
1893 $where_staging_group = '';
1894 $staging_group = get_option( 'mainwp_stagingsites_group_id' );
1895 if ( $staging_group ) {
1896 $where_staging_group = ' AND ' . $group_table_alias . '.id <> ' . $staging_group . ' ';
1897 if ( 'yes' === $with_staging ) {
1898 $where_staging_group = '';
1899 }
1900 }
1901
1902 // end staging filter.
1903 $_where = $where_staging_group;
1904
1905 // To fix bug run from cron job.
1906 if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
1907 return $_where;
1908 }
1909
1910 // Run from wp cli.
1911 if ( defined( 'WP_CLI' ) && WP_CLI ) {
1912 return $_where;
1913 }
1914
1915 // Run from Rest Api.
1916 if ( defined( 'MAINWP_REST_API_DOING' ) && MAINWP_REST_API_DOING ) {
1917 return $_where;
1918 }
1919
1920 /**
1921 * Filter: mainwp_currentuserallowedaccessgroups
1922 *
1923 * Filters allowed groups for the current user.
1924 *
1925 * @since Unknown
1926 */
1927 $allowed_groups = apply_filters( 'mainwp_currentuserallowedaccessgroups', 'all' );
1928
1929 if ( 'all' === $allowed_groups ) {
1930 return $_where;
1931 }
1932
1933 if ( is_array( $allowed_groups ) && ! empty( $allowed_groups ) ) {
1934
1935 // valid group ids.
1936 $allowed_groups = array_filter(
1937 $allowed_groups,
1938 function ( $e ) {
1939 return is_numeric( $e ) ? true : false;
1940 }
1941 );
1942
1943 return ' AND ' . $group_table_alias . '.id IN (' . implode( ',', $allowed_groups ) . ') ' . $_where;
1944 } else {
1945 return ' AND 0 ';
1946 }
1947 }
1948
1949
1950 /**
1951 * Get child site by id and params.
1952 *
1953 * @param int $id Child site ID.
1954 * @param array $params params.
1955 * @param string $obj OBJECT|ARRAY_A.
1956 *
1957 * @return object|null Database query results or null on failure.
1958 */
1959 public function get_website_by_id_params( $id, $params = array(), $obj = OBJECT ) {
1960 return $this->get_row_result( $this->get_sql_website_by_params( $id, $params ), $obj );
1961 }
1962
1963 /**
1964 * Get sql child site by id and params.
1965 *
1966 * @param int $id Child site ID.
1967 * @param array $params params.
1968 *
1969 * @return object|null Database query results or null on failure.
1970 */
1971 public function get_sql_website_by_params( $id, $params = array() ) {
1972
1973 if ( ! is_array( $params ) ) {
1974 $params = array();
1975 }
1976
1977 $select_groups = ! empty( $params['select_groups'] ) ? true : false;
1978
1979 $view = ! empty( $params['view'] ) ? $params['view'] : 'simple_view';
1980 $view_fields = isset( $params['view_fields'] ) ? $params['view_fields'] : array();
1981
1982 if ( is_string( $view_fields ) ) {
1983 $view_fields = (array) $view_fields;
1984 } elseif ( ! is_array( $view_fields ) ) {
1985 $view_fields = array();
1986 }
1987
1988 if ( MainWP_Utility::ctype_digit( $id ) ) {
1989 $where = $this->get_sql_where_allow_access_sites( 'wp', 'nocheckstaging' );
1990 if ( $select_groups ) {
1991 return 'SELECT wp.*,wp_sync.*,wp_optionview.*, 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
1992 FROM ' . $this->table_name( 'wp' ) . ' wp
1993 LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
1994 LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
1995 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
1996 JOIN ' . $this->get_option_view_by( $view, $view_fields ) . ' wp_optionview ON wp.id = wp_optionview.wpid
1997 WHERE wp.id = ' . $id . $where . '
1998 GROUP BY wp.id, wp_sync.sync_id';
1999 }
2000
2001 return 'SELECT wp.*,wp_sync.*,wp_optionview.*
2002 FROM ' . $this->table_name( 'wp' ) . ' wp
2003 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2004 JOIN ' . $this->get_option_view_by( $view, $view_fields ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2005 WHERE id = ' . $id . $where;
2006 }
2007 return null;
2008 }
2009
2010 /**
2011 * Get child site by id.
2012 *
2013 * @param int $id Child site ID.
2014 * @param array $selectGroups Select groups.
2015 * @param array $extra_view Get extra option fields.
2016 * @param int $obj OBJECT|ARRAY_A.
2017 *
2018 * @return object|null Database query results or null on failure.
2019 */
2020 public function get_website_by_id( $id, $selectGroups = false, $extra_view = array(), $obj = OBJECT ) {
2021 return $this->get_row_result( $this->get_sql_website_by_id( $id, $selectGroups, $extra_view ), $obj );
2022 }
2023
2024 /**
2025 * Get child site by id via SQL.
2026 *
2027 * @param int $id Child site ID.
2028 * @param bool $selectGroups Selected groups.
2029 * @param mixed $extra_view Extra view value.
2030 *
2031 * @return object|null Database query result or null on failure.
2032 *
2033 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
2034 */
2035 public function get_sql_website_by_id( $id, $selectGroups = false, $extra_view = array() ) {
2036
2037 if ( ! is_array( $extra_view ) || empty( $extra_view ) ) {
2038 $extra_view = array( 'favi_icon', 'site_info' );
2039 }
2040
2041 if ( MainWP_Utility::ctype_digit( $id ) ) {
2042 $where = $this->get_sql_where_allow_access_sites( 'wp', 'nocheckstaging' );
2043 if ( $selectGroups ) {
2044 return 'SELECT wp.*,wp_sync.*,wp_optionview.*, 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
2045 FROM ' . $this->table_name( 'wp' ) . ' wp
2046 LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
2047 LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
2048 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2049 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2050 WHERE wp.id = ' . $id . $where . '
2051 GROUP BY wp.id, wp_sync.sync_id';
2052 }
2053
2054 return 'SELECT wp.*,wp_sync.*,wp_optionview.*
2055 FROM ' . $this->table_name( 'wp' ) . ' wp
2056 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2057 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2058 WHERE id = ' . $id . $where;
2059 }
2060
2061 return null;
2062 }
2063
2064 /**
2065 * Method get_websites_by_ids()
2066 *
2067 * Get child sites by child site IDs.
2068 *
2069 * @param array $ids Child site IDs.
2070 * @param int $userId User ID.
2071 *
2072 * @return object|null Database query result or null on failure.
2073 *
2074 * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
2075 */
2076 public function get_websites_by_ids( $ids, $userId = null ) {
2077 if ( ( null === $userId ) && MainWP_System::instance()->is_multi_user() ) {
2078
2079 /**
2080 * Current user global.
2081 *
2082 * @global string
2083 */
2084 global $current_user;
2085
2086 $userId = $current_user->ID;
2087 }
2088
2089 // valid group ids.
2090 $ids = array_filter(
2091 $ids,
2092 function ( $e ) {
2093 return ( is_numeric( $e ) && 0 < $e ) ? true : false;
2094 }
2095 );
2096
2097 $where = $this->get_sql_where_allow_access_sites();
2098
2099 return $this->wpdb->get_results( 'SELECT * FROM ' . $this->table_name( 'wp' ) . ' WHERE id IN (' . implode( ',', $ids ) . ')' . ( null !== $userId ? ' AND userid = ' . intval( $userId ) : '' ) . $where, OBJECT );
2100 }
2101
2102 /**
2103 * Get child sites by groups IDs.
2104 *
2105 * @param array $ids Groups IDs.
2106 * @param int $userId User ID.
2107 * @param array $fields array fields .
2108 *
2109 * @return object|null Database query result or null on failure.
2110 *
2111 * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
2112 */
2113 public function get_websites_by_group_ids( $ids, $userId = null, $fields = array() ) {
2114 if ( empty( $ids ) ) {
2115 return array();
2116 }
2117 if ( ( null === $userId ) && MainWP_System::instance()->is_multi_user() ) {
2118
2119 /**
2120 * Current user global.
2121 *
2122 * @global string
2123 */
2124 global $current_user;
2125
2126 $userId = $current_user->ID;
2127 }
2128
2129 // valid group ids.
2130 $group_ids = array_filter(
2131 $ids,
2132 function ( $e ) {
2133 return is_numeric( $e ) ? true : false;
2134 }
2135 );
2136
2137 $select = '*';
2138 if ( ! empty( $fields ) && is_array( $fields ) ) {
2139 $fields = array_filter( array_map( 'trim', $fields ) );
2140 if ( $fields ) {
2141 $select = '';
2142 foreach ( $fields as $field ) {
2143 $select .= $this->escape( $field ) . ',';
2144 }
2145 $select = rtrim( $select, ',' );
2146 }
2147 }
2148 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 );
2149 }
2150
2151 /**
2152 * Get child sites by group ID.
2153 *
2154 * @param int $id Group ID.
2155 *
2156 * @return object|null Database query result or null on failure.
2157 */
2158 public function get_websites_by_group_id( $id ) {
2159 return $this->get_results_result( $this->get_sql_websites_by_group_id( $id ) );
2160 }
2161
2162 /**
2163 * Get child sites by group id via SQL.
2164 *
2165 * @param int $id Group ID.
2166 * @param bool $selectgroups Selected groups. Default: false.
2167 * @param string $orderBy Order list by. Default: URL.
2168 * @param bool $offset Query offset. Default: false.
2169 * @param bool $rowcount Row count. Default: falese.
2170 * @param null $where SQL WHERE value.
2171 * @param null $search_site Site search field value. Default: null.
2172 * @param array $others Others params.
2173 *
2174 * @return object|null Return database query or null on failure.
2175 *
2176 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
2177 */
2178 public function get_sql_websites_by_group_id( // phpcs:ignore -- NOSONAR - complex.
2179 $id,
2180 $selectgroups = false,
2181 $orderBy = 'wp.url',
2182 $offset = false,
2183 $rowcount = false,
2184 $where = null,
2185 $search_site = null,
2186 $others = array()
2187 ) {
2188
2189 $is_staging = 'no';
2190 if ( $selectgroups ) {
2191 $staging_group = get_option( 'mainwp_stagingsites_group_id' );
2192 if ( $staging_group && $id === $staging_group ) {
2193 $is_staging = 'yes';
2194 }
2195 }
2196
2197 $where_search = '';
2198 if ( ! empty( $search_site ) ) {
2199 $search_site = trim( $search_site );
2200 $where_search .= ' AND (wp.name LIKE "%' . $this->escape( $search_site ) . '%" OR wp.url LIKE "%' . $this->escape( $search_site ) . '%") ';
2201 }
2202
2203 $extra_view = is_array( $others ) && isset( $others['extra_view'] ) && is_array( $others['extra_view'] ) && ! empty( $others['extra_view'] ) ? $others['extra_view'] : array( 'site_info' );
2204
2205 if ( MainWP_Utility::ctype_digit( $id ) ) {
2206 $where_allowed = $this->get_sql_where_allow_access_sites( 'wp', $is_staging );
2207 if ( $selectgroups ) {
2208 $qry = 'SELECT wp.*,wp_sync.*,wp_optionview.*, 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
2209 FROM ' . $this->table_name( 'wp' ) . ' wp
2210 JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
2211 LEFT JOIN ' . $this->table_name( 'wp_group' ) . ' wpgr ON wp.id = wpgr.wpid
2212 LEFT JOIN ' . $this->table_name( 'group' ) . ' gr ON wpgr.groupid = gr.id
2213 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2214 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2215 WHERE wpgroup.groupid = ' . $id . ' ' .
2216 ( empty( $where ) ? '' : ' AND ' . $where ) . $where_allowed . $where_search . '
2217 GROUP BY wp.id, wp_sync.sync_id
2218 ORDER BY ' . $orderBy;
2219 } else {
2220 $qry = 'SELECT wp.*,wp_optionview.*, wp_sync.* FROM ' . $this->table_name( 'wp' ) . ' wp
2221 JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
2222 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2223 JOIN ' . $this->get_option_view( $extra_view, 'group' ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2224 WHERE wpgroup.groupid = ' . $id . ' ' . $where_allowed . $where_search .
2225 ( empty( $where ) ? '' : ' AND ' . $where ) . ' ORDER BY ' . $orderBy;
2226 }
2227 if ( ( false !== $offset ) && ( false !== $rowcount ) ) {
2228 $qry .= ' LIMIT ' . $offset . ', ' . $rowcount;
2229 } elseif ( false !== $rowcount ) {
2230 $qry .= ' LIMIT ' . $rowcount;
2231 }
2232
2233 return $qry;
2234 }
2235
2236 return null;
2237 }
2238
2239 /**
2240 * Get child sites by group name.
2241 *
2242 * @param int $userid Current user ID.
2243 * @param string $groupname Group name.
2244 *
2245 * @return object|null Database query result or null on failure.
2246 */
2247 public function get_websites_by_group_name( $userid, $groupname ) {
2248 return $this->get_results_result( $this->get_sql_websites_by_group_name( $groupname, $userid ) );
2249 }
2250
2251 /**
2252 * Get child sites by group name.
2253 *
2254 * @param string $groupname Group name.
2255 * @param int $userid Current user ID.
2256 *
2257 * @return object|null Database query result or null on failure.
2258 *
2259 * @uses \MainWP\Dashboard\MainWP_System::is_multi_user()
2260 */
2261 public function get_sql_websites_by_group_name( $groupname, $userid = null ) {
2262 if ( ( null === $userid ) && MainWP_System::instance()->is_multi_user() ) {
2263
2264 /**
2265 * Current user global.
2266 *
2267 * @global string
2268 */
2269 global $current_user;
2270
2271 $userid = $current_user->ID;
2272 }
2273
2274 $sql = 'SELECT wp.*,wp_sync.*,wp_optionview.* FROM ' . $this->table_name( 'wp' ) . ' wp
2275 INNER JOIN ' . $this->table_name( 'wp_group' ) . ' wpgroup ON wp.id = wpgroup.wpid
2276 JOIN ' . $this->table_name( 'group' ) . ' g ON wpgroup.groupid = g.id
2277 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2278 JOIN ' . $this->get_option_view() . ' wp_optionview ON wp.id = wp_optionview.wpid
2279 WHERE g.name="' . $this->escape( $groupname ) . '"';
2280 if ( null !== $userid ) {
2281 $sql .= ' AND g.userid = "' . intval( $userid ) . '"';
2282 }
2283
2284 return $sql;
2285 }
2286
2287 /**
2288 * Get child site IP address.
2289 *
2290 * @param int $wpid Child site ID.
2291 *
2292 * @return string|null Child site IP address or null on failure.
2293 */
2294 public function get_wp_ip( $wpid ) {
2295 return $this->wpdb->get_var( $this->wpdb->prepare( 'SELECT ip FROM ' . $this->table_name( 'request_log' ) . ' WHERE wpid = %d', $wpid ) );
2296 }
2297
2298 /**
2299 * Add website to the MainWP Dashboard.
2300 *
2301 * @param int $userid Current user ID.
2302 * @param string $name Child site name.
2303 * @param string $url Child site URL.
2304 * @param string $admin Child site administrator username.
2305 * @param string $pubkey OpenSSL public key.
2306 * @param string $privkey OpenSSL private key.
2307 * @param array $params Other params.
2308 *
2309 * @return int|false Child site ID or false on failure.
2310 *
2311 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
2312 */
2313 public function add_website( // phpcs:ignore -- NOSONAR - complex.
2314 $userid,
2315 $name,
2316 $url,
2317 $admin,
2318 $pubkey,
2319 $privkey,
2320 $params = array()
2321 ) {
2322
2323 if ( ! is_array( $params ) ) {
2324 $params = array();
2325 }
2326
2327 $groupids = isset( $params['groupids'] ) ? $params['groupids'] : array();
2328 $groupnames = isset( $params['groupnames'] ) ? $params['groupnames'] : array();
2329 $verifyCertificate = isset( $params['verifyCertificate'] ) ? (int) $params['verifyCertificate'] : 1;
2330 $uniqueId = isset( $params['uniqueId'] ) ? $params['uniqueId'] : '';
2331 $http_user = isset( $params['http_user'] ) ? $params['http_user'] : null;
2332 $http_pass = isset( $params['http_pass'] ) ? $params['http_pass'] : null;
2333 $sslVersion = isset( $params['sslVersion'] ) ? $params['sslVersion'] : 0;
2334 $wpe = isset( $params['wpe'] ) ? $params['wpe'] : 0;
2335 $isStaging = isset( $params['isStaging'] ) ? $params['isStaging'] : 0;
2336
2337 if ( MainWP_Utility::ctype_digit( $userid ) ) {
2338 if ( '/' !== substr( $url, - 1 ) ) {
2339 $url .= '/';
2340 }
2341
2342 $en_pk_data = MainWP_Encrypt_Data_Lib::instance()->encrypt_privkey( base64_decode( $privkey ) ); // phpcs:ignore -- NOSONAR - base64_encode trust.
2343 $en_privkey = isset( $en_pk_data['en_data'] ) ? $en_pk_data['en_data'] : '';
2344
2345 $values = array(
2346 'userid' => $userid,
2347 'adminname' => $this->escape( $admin ),
2348 'name' => $this->escape( wp_strip_all_tags( $name ) ),
2349 'url' => $this->escape( $url ),
2350 'pubkey' => $this->escape( $pubkey ),
2351 'privkey' => $this->escape( base64_encode( $en_privkey ) ), // phpcs:ignore -- NOSONAR - trust.
2352 'siteurl' => '',
2353 'ga_id' => '',
2354 'gas_id' => 0,
2355 'offline_checks_last' => 0,
2356 'offline_check_result' => 0,
2357 'note' => '',
2358 'statsUpdate' => 0,
2359 'directories' => '',
2360 'plugin_upgrades' => '',
2361 'theme_upgrades' => '',
2362 'translation_upgrades' => '',
2363 'securityIssues' => '',
2364 'themes' => '',
2365 'ignored_themes' => '',
2366 'plugins' => '',
2367 'ignored_plugins' => '',
2368 'users' => '',
2369 'categories' => '',
2370 'pluginDir' => '',
2371 'automatic_update' => 0,
2372 'backup_before_upgrade' => 2,
2373 'verify_certificate' => intval( $verifyCertificate ),
2374 'ssl_version' => $sslVersion,
2375 'uniqueId' => $uniqueId,
2376 'mainwpdir' => 0,
2377 'http_user' => $http_user,
2378 'http_pass' => $http_pass,
2379 'wpe' => $wpe,
2380 'is_staging' => $isStaging,
2381 );
2382
2383 $syncValues = array(
2384 'dtsSync' => 0,
2385 'dtsSyncStart' => 0,
2386 'dtsAutomaticSync' => 0,
2387 'dtsAutomaticSyncStart' => 0,
2388 'totalsize' => 0,
2389 'extauth' => '',
2390 'sync_errors' => '',
2391 );
2392 if ( $this->wpdb->insert( $this->table_name( 'wp' ), $values ) ) {
2393 $websiteid = $this->wpdb->insert_id;
2394 MainWP_Encrypt_Data_Lib::instance()->encrypt_save_keys( $websiteid, $en_pk_data );
2395 $syncValues['wpid'] = $websiteid;
2396 $this->wpdb->insert( $this->table_name( 'wp_sync' ), $syncValues );
2397 $this->wpdb->insert(
2398 $this->table_name( 'wp_settings_backup' ),
2399 array(
2400 'wpid' => $websiteid,
2401 'archiveFormat' => 'global',
2402 )
2403 );
2404
2405 foreach ( $groupnames as $groupname ) {
2406 if ( $this->wpdb->insert(
2407 $this->table_name( 'group' ),
2408 array(
2409 'userid' => $userid,
2410 'name' => $this->escape( htmlspecialchars( $groupname ) ),
2411 )
2412 )
2413 ) {
2414 $groupids[] = $this->wpdb->insert_id;
2415 }
2416 }
2417 // add groupids.
2418 foreach ( $groupids as $groupid ) {
2419 $this->wpdb->insert(
2420 $this->table_name( 'wp_group' ),
2421 array(
2422 'wpid' => $websiteid,
2423 'groupid' => $groupid,
2424 )
2425 );
2426 }
2427
2428 return $websiteid;
2429 }
2430 }
2431
2432 return false;
2433 }
2434
2435 /**
2436 * Remove child site from the MainWP Dashboard.
2437 *
2438 * @param int $websiteid Child site ID.
2439 *
2440 * @return int|boolean Return child site ID that was removed or false on failure.
2441 *
2442 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
2443 */
2444 public function remove_website( $websiteid ) {
2445 if ( MainWP_Utility::ctype_digit( $websiteid ) ) {
2446 $nr = $this->wpdb->query( $this->wpdb->prepare( 'DELETE FROM ' . $this->table_name( 'wp' ) . ' WHERE id=%d', $websiteid ) );
2447 $this->wpdb->query( $this->wpdb->prepare( 'DELETE FROM ' . $this->table_name( 'wp_group' ) . ' WHERE wpid=%d', $websiteid ) );
2448 $this->wpdb->query( $this->wpdb->prepare( 'DELETE FROM ' . $this->table_name( 'wp_sync' ) . ' WHERE wpid=%d', $websiteid ) );
2449 $this->wpdb->query( $this->wpdb->prepare( 'DELETE FROM ' . $this->table_name( 'wp_options' ) . ' WHERE wpid=%d', $websiteid ) );
2450 MainWP_Encrypt_Data_Lib::remove_key_file( $websiteid );
2451 MainWP_DB_Uptime_Monitoring::instance()->delete_monitor( array( 'wpid' => $websiteid ) );
2452 return $nr;
2453 }
2454
2455 return false;
2456 }
2457
2458 /**
2459 * Update child site db values.
2460 *
2461 * @param int $websiteid Child site ID.
2462 * @param array $fields Database fields to update.
2463 *
2464 * @return int|boolean The number of rows updated, or false on error.
2465 */
2466 public function update_website_values( $websiteid, $fields ) {
2467 if ( ! empty( $fields ) ) {
2468 // Lock the data stream to prevent other processes from updating at the same time.
2469 $sql = $this->wpdb->prepare(
2470 'SELECT * FROM ' . $this->table_name( 'wp' ) . ' WHERE id = %d FOR UPDATE',
2471 $websiteid
2472 );
2473 $this->wpdb->get_row( $sql );
2474
2475 return $this->wpdb->update( $this->table_name( 'wp' ), $fields, array( 'id' => $websiteid ) );
2476 }
2477
2478 return false;
2479 }
2480
2481 /**
2482 * Update child site sync values.
2483 *
2484 * @param int $websiteid Child site ID.
2485 * @param array $fields Database fields to update.
2486 *
2487 * @return int|boolean The number of rows updated, or false on error.
2488 */
2489 public function update_website_sync_values( $websiteid, $fields ) {
2490 if ( ! empty( $fields ) ) {
2491 return $this->wpdb->update( $this->table_name( 'wp_sync' ), $fields, array( 'wpid' => $websiteid ) );
2492 }
2493
2494 return false;
2495 }
2496
2497 /**
2498 * Update child site.
2499 *
2500 * @param int $websiteid Website ID.
2501 * @param string $url Child site URL.
2502 * @param int $userid Current user ID.
2503 * @param string $name Child site name.
2504 * @param string $siteadmin Child site administrator username.
2505 * @param array $groupids Group IDs.
2506 * @param array $groupnames Group Names.
2507 * @param string $pluginDir Plugin directory.
2508 * @param mixed $maximumFileDescriptorsOverride Overwrite the Maximum File Descriptors option.
2509 * @param mixed $maximumFileDescriptorsAuto Auto set the Maximum File Descriptors option.
2510 * @param mixed $maximumFileDescriptors Set the Maximum File Descriptors option.
2511 * @param int $verifyCertificate Whether or not to verify SSL Certificate.
2512 * @param mixed $archiveFormat Backup archive formate.
2513 * @param string $uniqueId Unique security ID.
2514 * @param string $http_user HTTP Basic Authentication username.
2515 * @param string $http_pass HTTP Basic Authentication password.
2516 * @param int $sslVersion SSL Version.
2517 * @param bool $disableHealthChecking Disable Site health threshold.
2518 * @param int $healthThreshold Site health threshold.
2519 * @param int $wpe Is it WP Engine hosted site.
2520 *
2521 * @return boolean ture on success or false on failure.
2522 *
2523 * @uses \MainWP\Dashboard\MainWP_System_Utility::can_edit_website()
2524 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
2525 */
2526 public function update_website( // phpcs:ignore -- NOSONAR - complex.
2527 $websiteid,
2528 $url,
2529 $userid,
2530 $name,
2531 $siteadmin,
2532 $groupids,
2533 $groupnames,
2534 $pluginDir,
2535 $maximumFileDescriptorsOverride,
2536 $maximumFileDescriptorsAuto,
2537 $maximumFileDescriptors,
2538 $verifyCertificate = 1,
2539 $archiveFormat = 'global',
2540 $uniqueId = '',
2541 $http_user = null,
2542 $http_pass = null,
2543 $sslVersion = 0,
2544 $disableHealthChecking = 1,
2545 $healthThreshold = 80,
2546 $wpe = 0
2547 ) {
2548
2549 if ( MainWP_Utility::ctype_digit( $websiteid ) && MainWP_Utility::ctype_digit( $userid ) ) {
2550 $website = $this->get_website_by_id( $websiteid );
2551 if ( MainWP_System_Utility::can_edit_website( $website ) ) {
2552 // update admin.
2553 $this->wpdb->query( $this->wpdb->prepare( 'UPDATE ' . $this->table_name( 'wp' ) . ' SET url="' . $this->escape( $url ) . '", name="' . $this->escape( wp_strip_all_tags( $name ) ) . '", adminname="' . $this->escape( $siteadmin ) . '",pluginDir="' . $this->escape( $pluginDir ) . '", 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 ) . '", disable_health_check="' . $this->escape( $disableHealthChecking ) . '", health_threshold="' . $this->escape( $healthThreshold ) . '" WHERE id=%d', $websiteid ) );
2554 $this->wpdb->query( $this->wpdb->prepare( 'UPDATE ' . $this->table_name( 'wp_settings_backup' ) . ' SET archiveFormat = "' . $this->escape( $archiveFormat ) . '" WHERE wpid=%d', $websiteid ) );
2555
2556 if ( get_option( 'mainwp_enableLegacyBackupFeature' ) ) {
2557 $this->wpdb->query( $this->wpdb->prepare( 'UPDATE ' . $this->table_name( 'wp' ) . ' SET maximumFileDescriptorsOverride = ' . ( $maximumFileDescriptorsOverride ? 1 : 0 ) . ',maximumFileDescriptorsAuto= ' . ( $maximumFileDescriptorsAuto ? 1 : 0 ) . ',maximumFileDescriptors = ' . $maximumFileDescriptors . ' WHERE id=%d', $websiteid ) );
2558 }
2559
2560 // remove groups.
2561 $this->wpdb->query( $this->wpdb->prepare( 'DELETE FROM ' . $this->table_name( 'wp_group' ) . ' WHERE wpid=%d', $websiteid ) );
2562 // Remove GA stats.
2563 $showErrors = $this->wpdb->hide_errors();
2564
2565 /**
2566 * Action: mainwp_ga_delete_site
2567 *
2568 * Fires upon site removal process in order to delete Google Analytics data.
2569 *
2570 * @param int $websiteid Child site ID.
2571 *
2572 * @since Unknown
2573 */
2574 do_action( 'mainwp_ga_delete_site', $websiteid );
2575
2576 if ( $showErrors ) {
2577 $this->wpdb->show_errors();
2578 }
2579 // add groups with groupnames.
2580 foreach ( $groupnames as $groupname ) {
2581 if ( $this->wpdb->insert(
2582 $this->table_name( 'group' ),
2583 array(
2584 'userid' => $userid,
2585 'name' => $this->escape( $groupname ),
2586 )
2587 )
2588 ) {
2589 $groupids[] = $this->wpdb->insert_id;
2590 }
2591 }
2592 // add groupids.
2593 foreach ( $groupids as $groupid ) {
2594 $this->wpdb->insert(
2595 $this->table_name( 'wp_group' ),
2596 array(
2597 'wpid' => $websiteid,
2598 'groupid' => $groupid,
2599 )
2600 );
2601 }
2602
2603 return true;
2604 }
2605 }
2606
2607 return false;
2608 }
2609
2610
2611 /**
2612 * Get website update stats via SQL.
2613 *
2614 * @return object|null Database query result of null on failure.
2615 */
2616 public function get_websites_stats_update_sql() {
2617 $where = $this->get_sql_where_allow_access_sites( 'wp' );
2618 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';
2619 }
2620
2621 /**
2622 * Update child site statistics.
2623 *
2624 * Update whether or not a child site has been updated.
2625 *
2626 * @param mixed $websiteid Child site ID.
2627 * @param mixed $statsUpdated Child site Update status.
2628 *
2629 * @return (int|boolean) Number of rows effected in update or false on failure.
2630 */
2631 public function update_website_stats( $websiteid, $statsUpdated ) {
2632 return $this->wpdb->update(
2633 $this->table_name( 'wp' ),
2634 array( 'statsUpdate' => $statsUpdated ),
2635 array( 'id' => $websiteid )
2636 );
2637 }
2638
2639 /**
2640 * Get child site by url.
2641 *
2642 * @param string $url Child site URL.
2643 *
2644 * @return object|null Database query result or null on failure.
2645 */
2646 public function get_websites_by_url( $url ) {
2647 if ( '/' !== substr( $url, - 1 ) ) {
2648 $url .= '/';
2649 }
2650 $results = $this->wpdb->get_results( $this->wpdb->prepare( 'SELECT * FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid WHERE wp.url = %s ', $this->escape( $url ) ), OBJECT );
2651 if ( $results ) {
2652 return $results;
2653 }
2654
2655 if ( stristr( $url, '/www.' ) ) {
2656 // remove www if it's there!
2657 $url = str_replace( '/www.', '/', $url );
2658 } else {
2659 // add www if it's not there!
2660 $url = str_replace( 'https://', 'https://www.', $url );
2661 $url = str_replace( 'http://', 'http://www.', $url );
2662 }
2663
2664 $results = $this->wpdb->get_results( $this->wpdb->prepare( 'SELECT * FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid WHERE wp.url = %s ', $this->escape( $url ) ), OBJECT );
2665 if ( $results ) {
2666 return $results;
2667 }
2668
2669 $url = str_replace( array( 'https://www.', 'http://www.', 'https://', 'http://', 'www.' ), array( '', '', '', '', '' ), $url );
2670
2671 return $this->wpdb->get_results( $this->wpdb->prepare( 'SELECT * FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . " wp_sync ON wp.id = wp_sync.wpid WHERE replace(replace(replace(replace(replace(wp.url, 'https://www.',''), 'http://www.',''), 'https://', ''), 'http://', ''), 'www.', '') = %s ", $this->escape( $url ) ), OBJECT );
2672 }
2673
2674 /**
2675 *
2676 * Get websites offline status.
2677 *
2678 * @deprecated see new compatible uptime monitoring.
2679 *
2680 * @since 5.3.
2681 *
2682 * @return array Child site monitoring status.
2683 */
2684 public function get_websites_offline_status_to_send_notice() {
2685 $where = $this->get_sql_where_allow_access_sites( 'wp' );
2686 $extra_view = array( 'monitoring_notification_emails', 'settings_notification_emails' );
2687
2688 return $this->wpdb->get_results(
2689 'SELECT wp.*,wp_sync.*,wp_optionview.* FROM ' . $this->table_name( 'wp' ) . ' wp
2690 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2691 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2692 WHERE wp.disable_status_check <> 1 AND wp.offline_check_result <> 1 AND wp.offline_check_result <> 0 AND wp.http_code_noticed = 0' . // http_code_noticed = 0: not noticed yet.
2693 $where,
2694 OBJECT
2695 );
2696 }
2697
2698 /**
2699 * Method get_websites_to_notice_health_threshold()
2700 *
2701 * Get websites to notice site health.
2702 *
2703 * @param int $globalThreshold Global site health threshold.
2704 */
2705 public function get_websites_to_notice_health_threshold( $globalThreshold ) {
2706
2707 $where = $this->get_sql_where_allow_access_sites( 'wp' );
2708 $extra_view = array( 'monitoring_notification_emails', 'settings_notification_emails' );
2709
2710 if ( 80 >= $globalThreshold ) { // actual is 80.
2711 // should-be-improved site health.
2712 $where_global_threshold = '( wp.health_threshold = 0 AND wp_sync.health_value < 80 )';
2713 } else {
2714 // good site health.
2715 $where_global_threshold = '( wp.health_threshold = 0 AND wp_sync.health_value >= 80 )';
2716 }
2717
2718 $where_site_threshold = ' ( wp.health_threshold = 80 AND wp_sync.health_value < 80 ) '; // should-be-improved site health.
2719 $where_site_threshold .= ' OR ( wp.health_threshold = 100 AND wp_sync.health_value >= 80 ) '; // good site health.
2720
2721 return $this->wpdb->get_results(
2722 'SELECT wp.*,wp_sync.*,wp_optionview.* FROM ' . $this->table_name( 'wp' ) . ' wp
2723 JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid
2724 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2725 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 ' .
2726 $where,
2727 OBJECT
2728 );
2729 }
2730
2731 /**
2732 * Get websites offline status.
2733 *
2734 * @return array Sites with offline status.
2735 */
2736 public function get_websites_http_check_status() {
2737 $where = $this->get_sql_where_allow_access_sites( 'wp' );
2738 $extra_view = array( 'settings_notification_emails' );
2739
2740 return $this->wpdb->get_results(
2741 'SELECT wp.*,wp_optionview.* FROM ' . $this->table_name( 'wp' ) . ' wp
2742 JOIN ' . $this->get_option_view( $extra_view ) . ' wp_optionview ON wp.id = wp_optionview.wpid
2743 WHERE wp.disable_status_check <> 1 AND wp.offline_check_result = -1' . // offline checked status.
2744 $where,
2745 OBJECT
2746 );
2747 }
2748
2749 /**
2750 * Get DB Sites.
2751 *
2752 * @since 4.6
2753 *
2754 * @param mixed $params params.
2755 *
2756 * @return array $dbwebsites.
2757 */
2758 public function get_db_sites( $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
2759
2760 $dbwebsites = array();
2761
2762 $data_fields = MainWP_System_Utility::get_default_map_site_fields();
2763 $data_fields[] = 'verify_certificate';
2764 $data_fields[] = 'client_id';
2765
2766 $fields = isset( $params['fields'] ) && is_array( $params['fields'] ) ? $params['fields'] : array();
2767 $sites = isset( $params['sites'] ) && is_array( $params['sites'] ) ? $params['sites'] : array();
2768 $groups = isset( $params['groups'] ) && is_array( $params['groups'] ) ? $params['groups'] : array();
2769 $clients = isset( $params['clients'] ) && is_array( $params['clients'] ) ? $params['clients'] : array();
2770 $schema_fields = isset( $params['schema_fields'] ) && is_array( $params['schema_fields'] ) ? $params['schema_fields'] : array(); // since 5.2.
2771 $selectgroups = isset( $params['selectgroups'] ) && ! empty( $params['selectgroups'] ) ? true : false; // since 5.2.
2772
2773 if ( ! empty( $schema_fields ) ) { // since 5.2.
2774 foreach ( $schema_fields as $field_name ) {
2775 if ( ! in_array( $field_name, $data_fields ) ) {
2776 $data_fields[] = $field_name;
2777 }
2778 }
2779 } elseif ( is_array( $fields ) ) {
2780 foreach ( $fields as $field_indx => $field_name ) {
2781
2782 $get_field = $field_name;
2783 if ( is_numeric( $get_field ) || is_bool( $get_field ) ) { // to compatible fix.
2784 $get_field = $field_indx;
2785 }
2786
2787 if ( in_array( $get_field, static::$possible_options ) && ! in_array( $get_field, $data_fields ) ) {
2788 $data_fields[] = $get_field;
2789 }
2790 }
2791 }
2792
2793 if ( ! empty( $sites ) ) {
2794 foreach ( $sites as $v ) {
2795 if ( MainWP_Utility::ctype_digit( $v ) ) {
2796 $website = static::instance()->get_website_by_id( $v, $selectgroups );
2797 if ( empty( $website ) ) {
2798 continue;
2799 }
2800 $dbwebsites[ $website->id ] = MainWP_Utility::map_site( $website, $data_fields );
2801 }
2802 }
2803 }
2804
2805 if ( ! empty( $groups ) ) {
2806 foreach ( $groups as $v ) {
2807 if ( MainWP_Utility::ctype_digit( $v ) ) {
2808 $websites = static::instance()->query( static::instance()->get_sql_websites_by_group_id( $v, $selectgroups ) );
2809 while ( $websites && ( $website = static::fetch_object( $websites ) ) ) {
2810 $dbwebsites[ $website->id ] = MainWP_Utility::map_site( $website, $data_fields );
2811 }
2812 static::free_result( $websites );
2813 }
2814 }
2815 }
2816
2817 $params = array(
2818 'full_data' => true,
2819 'selectgroups' => $selectgroups,
2820 );
2821 $client_sites = MainWP_DB_Client::instance()->get_websites_by_client_ids( $clients, $params );
2822 if ( $client_sites ) {
2823 foreach ( $client_sites as $website ) {
2824 $dbwebsites[ $website->id ] = MainWP_Utility::map_site( $website, $data_fields );
2825 }
2826 }
2827 return $dbwebsites;
2828 }
2829
2830 /**
2831 * Get Sites.
2832 *
2833 * @param int $websiteid The id of the child site you wish to retrieve.
2834 * @param bool $for_manager Check Team Control.
2835 * @param array $others Array of others.
2836 *
2837 * @return array $output Array of content to output.
2838 *
2839 * @uses \MainWP\Dashboard\MainWP_System_Utility::can_edit_website()
2840 * @uses \MainWP\Dashboard\MainWP_Utility::get_nice_url()
2841 */
2842 public function get_sites( $websiteid = null, $for_manager = false, $others = array() ) { // phpcs:ignore -- NOSONAR - not quite complex function.
2843
2844 if ( ! is_array( $others ) ) {
2845 $others = array();
2846 }
2847
2848 $search_site = null;
2849 $orderBy = 'wp.url';
2850 $offset = false;
2851 $rowcount = false;
2852 $extraWhere = null;
2853
2854 if ( isset( $websiteid ) && ( null !== $websiteid ) ) {
2855 $website = static::instance()->get_website_by_id( $websiteid );
2856
2857 if ( ! MainWP_System_Utility::can_edit_website( $website ) ) {
2858 return false;
2859 }
2860
2861 if ( ! \mainwp_current_user_can( 'site', $websiteid ) ) {
2862 return false;
2863 }
2864
2865 return array(
2866 array(
2867 'id' => $websiteid,
2868 'url' => MainWP_Utility::get_nice_url( $website->url, true ),
2869 'name' => $website->name,
2870 'totalsize' => $website->totalsize,
2871 'sync_errors' => $website->sync_errors,
2872 ),
2873 );
2874 } else {
2875 if ( isset( $others['orderby'] ) ) {
2876 if ( 'site' === $others['orderby'] ) {
2877 $orderBy = 'wp.name ' . ( 'asc' === $others['order'] ? 'asc' : 'desc' );
2878 } elseif ( 'url' === $others['orderby'] ) {
2879 $orderBy = 'wp.url ' . ( 'asc' === $others['order'] ? 'asc' : 'desc' );
2880 }
2881 }
2882 if ( isset( $others['search'] ) ) {
2883 $search_site = trim( $others['search'] );
2884 }
2885
2886 if ( is_array( $others ) && isset( $others['plugins_slug'] ) ) {
2887 $slugs = explode( ',', $others['plugins_slug'] );
2888 $extraWhere = '';
2889 foreach ( $slugs as $slug ) {
2890 $slug = wp_json_encode( $slug );
2891 $slug = trim( $slug, '"' );
2892 $slug = str_replace( '\\', '.', $slug );
2893 $extraWhere .= ' wp.plugins REGEXP "' . $slug . '" OR';
2894 }
2895 $extraWhere = trim( rtrim( $extraWhere, 'OR' ) );
2896
2897 if ( '' === $extraWhere ) {
2898 $extraWhere = null;
2899 } else {
2900 $extraWhere = '(' . $extraWhere . ')';
2901 }
2902 }
2903 }
2904
2905 $totalRecords = '';
2906
2907 if ( isset( $others['per_page'] ) && ! empty( $others['per_page'] ) ) {
2908 $sql = static::instance()->get_sql_websites_for_current_user( false, $search_site, $orderBy, false, false, $extraWhere, $for_manager );
2909 $websites_total = static::instance()->query( $sql );
2910 $totalRecords = ( $websites_total ? static::num_rows( $websites_total ) : 0 );
2911
2912 if ( $websites_total ) {
2913 static::free_result( $websites_total );
2914 }
2915
2916 $rowcount = absint( $others['per_page'] );
2917 $pagenum = isset( $others['paged'] ) ? absint( $others['paged'] ) : 0;
2918 if ( $pagenum > $totalRecords ) {
2919 $pagenum = $totalRecords;
2920 }
2921 $pagenum = max( 1, $pagenum );
2922 $offset = ( $pagenum - 1 ) * $rowcount;
2923
2924 }
2925
2926 $sql = static::instance()->get_sql_websites_for_current_user( false, $search_site, $orderBy, $offset, $rowcount, $extraWhere, $for_manager );
2927 $websites = static::instance()->query( $sql );
2928
2929 $output = array();
2930 while ( $websites && ( $website = static::fetch_object( $websites ) ) ) {
2931 $re = array(
2932 'id' => $website->id,
2933 'url' => MainWP_Utility::get_nice_url( $website->url, true ),
2934 'name' => $website->name,
2935 'totalsize' => $website->totalsize,
2936 'sync_errors' => $website->sync_errors,
2937 'client_id' => $website->client_id,
2938 );
2939
2940 if ( 0 < $totalRecords ) {
2941 $re['totalRecords'] = $totalRecords;
2942 $totalRecords = 0;
2943 }
2944
2945 $output[] = $re;
2946 }
2947 static::free_result( $websites );
2948
2949 return $output;
2950 }
2951
2952 /**
2953 * Method get_lookup_items().
2954 *
2955 * Get bulk lookup items to reduce number of db queries.
2956 *
2957 * @param string $item_name lookup item name.
2958 * @param int $item_id lookup item id.
2959 * @param string $obj_name loockup object name.
2960 *
2961 * @return mixed Result
2962 */
2963 public function get_lookup_items( $item_name, $item_id, $obj_name ) {
2964 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.
2965 }
2966
2967 /**
2968 * Method insert_lookup_item().
2969 *
2970 * Insert lookup item, need checks existed before to prevent double values.
2971 *
2972 * @param string $item_name item name.
2973 * @param int $item_id item id.
2974 * @param string $obj_name object name.
2975 * @param int $obj_id object id.
2976 *
2977 * @return mixed Result
2978 */
2979 public function insert_lookup_item( $item_name, $item_id, $obj_name, $obj_id ) {
2980 if ( empty( $item_name ) || empty( $item_id ) || empty( $obj_name ) || empty( $obj_id ) ) {
2981 return false;
2982 }
2983 $data = array(
2984 'item_name' => 'cost',
2985 'item_id' => $item_id,
2986 'object_name' => $obj_name,
2987 'object_id' => $obj_id,
2988 );
2989 $this->wpdb->insert( $this->table_name( 'lookup_item_objects' ), $data );
2990 return $this->wpdb->insert_id; // must return lookup id.
2991 }
2992
2993 /**
2994 * Method delete_lookup_items().
2995 *
2996 * Delete bulk lookup items by lookup ids or object names with item id and item name, to reduce number of db queries.
2997 *
2998 * @param string $by Delete by.
2999 * @param array $params params.
3000 *
3001 * @return mixed Result
3002 */
3003 public function delete_lookup_items( $by = 'lookup_id', $params = array() ) { // phpcs:ignore -- NOSONAR - complex.
3004 if ( ! is_array( $params ) ) {
3005 return false;
3006 }
3007
3008 $lookup_ids = isset( $params['lookup_ids'] ) ? $params['lookup_ids'] : null;
3009 $item_id = isset( $params['item_id'] ) ? $params['item_id'] : null;
3010 $object_id = isset( $params['object_id'] ) ? $params['object_id'] : null;
3011 $item_name = isset( $params['item_name'] ) ? $params['item_name'] : null;
3012 $obj_names = isset( $params['object_names'] ) ? $params['object_names'] : null;
3013
3014 if ( 'object_name' === $by ) {
3015 if ( empty( $item_id ) || empty( $item_name ) ) {
3016 return false;
3017 }
3018
3019 $obj_names = $this->escape_array( $obj_names );
3020 if ( ! empty( $obj_names ) ) {
3021 $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.
3022 return true;
3023 }
3024 } elseif ( 'object_id' === $by ) {
3025 if ( empty( $object_id ) || empty( $item_name ) || empty( $obj_names ) ) {
3026 return false;
3027 }
3028
3029 $obj_names = $this->escape_array( $obj_names );
3030 if ( ! empty( $obj_names ) ) {
3031 $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.
3032 return true;
3033 }
3034 } elseif ( 'lookup_id' === $by ) {
3035 if ( empty( $lookup_ids ) ) {
3036 return false;
3037 }
3038 if ( is_numeric( $lookup_ids ) ) {
3039 $lookup_ids = array( $lookup_ids );
3040 } elseif ( is_array( $lookup_ids ) ) {
3041 $lookup_ids = MainWP_Utility::array_numeric_filter( $lookup_ids );
3042 } else {
3043 return false;
3044 }
3045 $this->wpdb->query( 'DELETE FROM ' . $this->table_name( 'lookup_item_objects' ) . ' WHERE lookup_id IN (' . implode( ',', $lookup_ids ) . ') ' ); //phpcs:ignore -- ok.
3046 return true;
3047 }
3048 return false;
3049 }
3050
3051
3052 /**
3053 * Return the user data for the given consumer_key.
3054 *
3055 * @param string $consumer_key Consumer key.
3056 * @param string $consumer_secret Secret key.
3057 * @param string $scope scope.
3058 * @param string $description description.
3059 * @param int $enabled 1 or 0.
3060 * @param array $others others.
3061 *
3062 * @return array
3063 */
3064 public function insert_rest_api_key( $consumer_key, $consumer_secret, $scope, $description, $enabled, $others = array() ) {
3065 global $current_user;
3066
3067 if ( $current_user ) {
3068 $user_id = $current_user->ID;
3069 }
3070
3071 if ( empty( $user_id ) ) {
3072 return false;
3073 }
3074
3075 if ( ! is_array( $others ) ) {
3076 $others = array();
3077 }
3078
3079 $pass = isset( $others['key_pass'] ) ? $others['key_pass'] : '';
3080 $type = isset( $others['key_type'] ) ? intval( $others['key_type'] ) : 0;
3081
3082 // Created API keys.
3083 $permissions = in_array( $scope, array( 'read', 'write', 'read_write' ), true ) ? sanitize_text_field( $scope ) : 'read';
3084 $this->wpdb->insert(
3085 $this->table_name( 'api_keys' ),
3086 array(
3087 'user_id' => $user_id,
3088 'description' => $description,
3089 'permissions' => $permissions,
3090 'consumer_key' => mainwp_api_hash( $consumer_key ),
3091 'consumer_secret' => $consumer_secret,
3092 'truncated_key' => substr( $consumer_key, -7 ),
3093 'enabled' => $enabled,
3094 'key_pass' => $pass,
3095 'key_type' => $type,
3096 ),
3097 array(
3098 '%d',
3099 '%s',
3100 '%s',
3101 '%s',
3102 '%s',
3103 '%s',
3104 '%d',
3105 '%s',
3106 '%d',
3107 ),
3108 );
3109
3110 return array(
3111 'key_id' => $this->wpdb->insert_id,
3112 'user_id' => $user_id,
3113 'consumer_key' => $consumer_key,
3114 'consumer_secret' => $consumer_secret,
3115 'key_permissions' => $permissions,
3116 );
3117 }
3118
3119 /**
3120 * Update rest api key.
3121 *
3122 * @param int $key_id Consumer key.
3123 * @param string $scope scope.
3124 * @param string $description description.
3125 * @param int $enabled Enabled.
3126 *
3127 * @return array
3128 */
3129 public function update_rest_api_key( $key_id, $scope, $description, $enabled = 1 ) {
3130 $permissions = in_array( $scope, array( 'read', 'write', 'read_write' ), true ) ? sanitize_text_field( $scope ) : 'read';
3131 return $this->wpdb->update(
3132 $this->table_name( 'api_keys' ),
3133 array(
3134 'description' => $description,
3135 'permissions' => $permissions,
3136 'enabled' => $enabled ? 1 : 0,
3137 ),
3138 array(
3139 'key_id' => $key_id,
3140 )
3141 );
3142 }
3143
3144
3145 /**
3146 * Method is_existed_enabled_rest_key().
3147 *
3148 * @return bool result.
3149 */
3150 public function is_existed_enabled_rest_key() {
3151 $enabled = $this->wpdb->get_row( 'SELECT * FROM ' . $this->table_name( 'api_keys' ) . ' WHERE enabled = 1 LIMIT 1' );
3152 return $enabled ? true : false;
3153 }
3154
3155 /**
3156 * Method get_rest_api_key_by().
3157 *
3158 * @param int $id To get key.
3159 *
3160 * @return array
3161 */
3162 public function get_rest_api_key_by( $id ) {
3163 return $this->wpdb->get_row( $this->wpdb->prepare( 'SELECT * FROM ' . $this->table_name( 'api_keys' ) . ' WHERE key_id = %d ', $id ) );
3164 }
3165
3166 /**
3167 * Method remove_rest_api_key().
3168 *
3169 * @param string $id to delete.
3170 *
3171 * @return array
3172 */
3173 public function remove_rest_api_key( $id ) {
3174 return $this->wpdb->query( $this->wpdb->prepare( 'DELETE FROM ' . $this->table_name( 'api_keys' ) . ' WHERE key_id = %s', $id ) );
3175 }
3176
3177 /**
3178 * Method get_rest_api_keys().
3179 *
3180 * @return array
3181 */
3182 public function get_rest_api_keys() {
3183 return $this->wpdb->get_results( 'SELECT * FROM ' . $this->table_name( 'api_keys' ) . ' ORDER BY key_id DESC' );
3184 }
3185
3186
3187 /**
3188 * Update regular process.
3189 *
3190 * @param array $data process data.
3191 * @return mixed
3192 */
3193 public function update_regular_process( $data ) {
3194 if ( is_array( $data ) ) {
3195 if ( isset( $data['process_id'] ) ) {
3196 $process_id = $data['process_id'];
3197 unset( $data['process_id'] );
3198 return $this->wpdb->update( $this->table_name( 'schedule_processes' ), $data, array( 'process_id' => $process_id ) );
3199 } else {
3200 return $this->wpdb->insert( $this->table_name( 'schedule_processes' ), $data );
3201 }
3202 }
3203 return false;
3204 }
3205
3206
3207 /**
3208 * Method get_regular_process_by_item_id_type_slug
3209 *
3210 * @param integer $item_id item id.
3211 * @param string $type type.
3212 * @param string $process_slug process slug.
3213 *
3214 * @return mixed result
3215 */
3216 public function get_regular_process_by_item_id_type_slug( $item_id, $type, $process_slug ) {
3217 return $this->wpdb->get_row( $this->wpdb->prepare( ' SELECT pr.* FROM ' . $this->table_name( 'schedule_processes' ) . ' pr WHERE pr.item_id = %d AND pr.type = %s AND pr.process_slug = %s', $item_id, $type, $process_slug ) );
3218 }
3219
3220 /**
3221 * Method log_system_query
3222 *
3223 * @param array $params params.
3224 * @param string $sql query.
3225 * @return void
3226 */
3227 public function log_system_query( $params, $sql ) {
3228 if ( is_array( $params ) && ! empty( $params['dev_log_query'] ) && ! empty( $sql ) ) {
3229 error_log( $sql ); //phpcs:ignore -- NOSONAR - for dev.
3230 do_action( 'mainwp_log_system_query', $params, $sql );
3231 }
3232 }
3233 }
3234