PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 5.2.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v5.2.1
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 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.2.1, at class/class-mainwp-db.php

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