| @@ -8,8 +8,13 @@ | ||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | namespace MainWP\Dashboard; |
| 11 | 11 | |
| 12 | +// Exit if accessed directly. | |
| 13 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 14 | + exit; | |
| 15 | +} | |
| 16 | + | |
| 12 | 17 | /** |
| 13 | 18 | * Class MainWP_DB |
| 14 | 19 | * |
| 15 | 20 | * @package MainWP\Dashboard |
| @@ -57,8 +62,12 @@ | ||
| 57 | 62 | * |
| 58 | 63 | * @return object|null Database query result or null on failure. |
| 59 | 64 | */ |
| 60 | 65 | public function get_websites_check_updates( $limit, $lasttime_start, $connected = false, $not_suspended = false ) { |
| 66 | + global $wpdb; | |
| 67 | + | |
| 68 | + // do not use cache for this function because it is used for automatic updates and it needs to be accurate, and the result is not used in other places, so it will not cause performance issues. | |
| 69 | + | |
| 61 | 70 | $where = ''; |
| 62 | 71 | if ( true === $connected ) { |
| 63 | 72 | $where .= ' wp_sync.sync_errors = "" AND'; |
| 64 | 73 | } |
| @@ -65,9 +74,28 @@ | ||
| 65 | 74 | if ( true === $not_suspended ) { |
| 66 | 75 | $where .= ' wp.suspended = 0 AND'; |
| 67 | 76 | } |
| 68 | 77 | |
| 69 | - return $this->wpdb->get_results( 'SELECT wp.*,wp_sync.*,wp_optionview.* FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid JOIN ' . $this->get_option_view( array( 'favi_icon' ), false ) . ' wp_optionview ON wp.id = wp_optionview.wpid WHERE ' . $where . ' ( wp_sync.dtsAutomaticSyncStart = 0 OR ( wp_sync.dtsAutomaticSyncStart <= ' . intval( $lasttime_start ) . ' ) ) ORDER BY wp_sync.dtsAutomaticSyncStart ASC LIMIT ' . $limit, OBJECT ); | |
| 78 | + $view_selects = ''; | |
| 79 | + $view_joins = ''; | |
| 80 | + | |
| 81 | + $opts_view = $this->get_wp_options_join( array( 'favi_icon' ) ); | |
| 82 | + | |
| 83 | + if ( is_array( $opts_view ) && ! empty( $opts_view['selects'] ) ) { | |
| 84 | + $view_selects = ',' . $opts_view['selects']; | |
| 85 | + $view_joins = $opts_view['joins']; | |
| 86 | + } | |
| 87 | + | |
| 88 | + $sql = $wpdb->prepare( | |
| 89 | + 'SELECT wp.*,wp_sync.*' . $view_selects . ' FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid ' . $view_joins . ' WHERE ' . $where . ' ( wp_sync.dtsAutomaticSyncStart = 0 OR wp_sync.dtsAutomaticSyncStart < %d ) GROUP BY wp.id ORDER BY wp_sync.dtsAutomaticSyncStart ASC LIMIT %d', | |
| 90 | + $lasttime_start, | |
| 91 | + $limit | |
| 92 | + ); | |
| 93 | + | |
| 94 | + // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- $sql is prepared by $wpdb->prepare() with parameterized values; direct query required for complex joins. | |
| 95 | + $result = $wpdb->get_results( $sql, OBJECT ); | |
| 96 | + | |
| 97 | + return $result; | |
| 70 | 98 | } |
| 71 | 99 | |
| 72 | 100 | |
| 73 | 101 | /** |
| @@ -121,18 +149,23 @@ | ||
| 121 | 149 | if ( true === $not_suspended ) { |
| 122 | 150 | $where .= ' wp.suspended = 0 AND'; |
| 123 | 151 | } |
| 124 | 152 | |
| 153 | + $orderby = ' wp_sync.dtsAutomaticSyncStart ASC '; | |
| 154 | + | |
| 125 | 155 | $where = rtrim( $where, 'AND' ); |
| 126 | 156 | |
| 127 | 157 | $params = array( |
| 128 | - 'view' => 'updates_view', | |
| 129 | - 'where' => $where, | |
| 130 | - 'limit' => $limit, | |
| 158 | + 'view' => 'updates_view', | |
| 159 | + 'where' => $where, | |
| 160 | + 'limit' => $limit, | |
| 161 | + 'orderby' => $orderby, // to fix. | |
| 131 | 162 | ); |
| 132 | 163 | |
| 133 | - $results = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user_by_params( $params ) ); | |
| 164 | + $sql = MainWP_DB::instance()->get_sql_websites_for_current_user_by_params( $params ); | |
| 134 | 165 | |
| 166 | + $results = MainWP_DB::instance()->query( $sql ); | |
| 167 | + | |
| 135 | 168 | $websites = array(); |
| 136 | 169 | while ( $results && $website = static::fetch_object( $results ) ) { |
| 137 | 170 | $websites[] = $website; |
| 138 | 171 | } |
| @@ -160,9 +193,9 @@ | ||
| 160 | 193 | } |
| 161 | 194 | |
| 162 | 195 | $where = ' wp_sync.sync_errors = "" AND '; |
| 163 | 196 | $where .= ' wp.suspended = 0 AND '; |
| 164 | - $where .= ' wp_optionview.batch_individual_queue_time >= ' . intval( $lasttime_start ) . ' '; | |
| 197 | + $where .= ' owp_batch_individual_queue_time.value >= ' . intval( $lasttime_start ) . ' '; // owp_batch_individual_queue_time left join alias. | |
| 165 | 198 | |
| 166 | 199 | $params = array( |
| 167 | 200 | 'view' => 'updates_view', |
| 168 | 201 | 'where' => $where, |
| @@ -192,11 +225,29 @@ | ||
| 192 | 225 | * |
| 193 | 226 | * @return int Child sites update count. |
| 194 | 227 | */ |
| 195 | 228 | public function get_websites_check_updates_count( $lasttime_start ) { |
| 229 | + global $wpdb; | |
| 230 | + | |
| 231 | + $cache_identifier = array( 'lasttime_start' => absint( $lasttime_start ) ); | |
| 232 | + $cache_key = 'mainwp_auto_updates_count_' . md5( wp_json_encode( $cache_identifier ) ); // NOSONAR - MD5 for cache key only. | |
| 233 | + $cached = wp_cache_get( $cache_key ); | |
| 234 | + if ( false !== $cached ) { | |
| 235 | + return $cached; | |
| 236 | + } | |
| 237 | + | |
| 196 | 238 | $where = $this->get_sql_where_allow_access_sites( 'wp' ); |
| 197 | 239 | |
| 198 | - return $this->wpdb->get_var( 'SELECT count(wp.id) FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid WHERE ( wp_sync.dtsAutomaticSyncStart = 0 OR wp_sync.dtsAutomaticSyncStart < ' . intval( $lasttime_start ) . ')' . $where ); | |
| 240 | + $sql = $wpdb->prepare( | |
| 241 | + 'SELECT count(wp.id) FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid WHERE ( wp_sync.dtsAutomaticSyncStart = 0 OR wp_sync.dtsAutomaticSyncStart < %d)' . $where, | |
| 242 | + $lasttime_start | |
| 243 | + ); | |
| 244 | + | |
| 245 | + // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery -- $sql is prepared by $wpdb->prepare() with parameterized values; direct query required for complex joins. | |
| 246 | + $result = $wpdb->get_var( $sql ); | |
| 247 | + wp_cache_set( $cache_key, $result, '', HOUR_IN_SECONDS ); | |
| 248 | + | |
| 249 | + return $result; | |
| 199 | 250 | } |
| 200 | 251 | |
| 201 | 252 | /** |
| 202 | 253 | * Get child site count where date & time Session sync is smaller then start. |
| @@ -205,9 +256,27 @@ | ||
| 205 | 256 | * |
| 206 | 257 | * @return int Returned child site count. |
| 207 | 258 | */ |
| 208 | 259 | public function get_websites_count_where_dts_automatic_sync_smaller_then_start( $lasttime_start ) { |
| 209 | - return $this->wpdb->get_var( 'SELECT count(wp.id) FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid WHERE wp.suspended = 0 AND ( ( wp_sync.dtsAutomaticSync < wp_sync.dtsAutomaticSyncStart AND wp_sync.dtsAutomaticSyncStart > ' . intval( $lasttime_start ) . ') OR (wp_sync.dtsAutomaticSyncStart = 0) ) ' ); | |
| 260 | + global $wpdb; | |
| 261 | + | |
| 262 | + $cache_identifier = array( 'lasttime_start' => absint( $lasttime_start ) ); | |
| 263 | + $cache_key = 'mainwp_auto_updates_sync_smaller_' . md5( wp_json_encode( $cache_identifier ) ); // NOSONAR - MD5 for cache key only. | |
| 264 | + $cached = wp_cache_get( $cache_key ); | |
| 265 | + if ( false !== $cached ) { | |
| 266 | + return $cached; | |
| 267 | + } | |
| 268 | + | |
| 269 | + $sql = $wpdb->prepare( | |
| 270 | + 'SELECT count(wp.id) FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid WHERE wp.suspended = 0 AND ( ( wp_sync.dtsAutomaticSync < wp_sync.dtsAutomaticSyncStart AND wp_sync.dtsAutomaticSyncStart > %d) OR (wp_sync.dtsAutomaticSyncStart = 0) ) ', | |
| 271 | + $lasttime_start | |
| 272 | + ); | |
| 273 | + | |
| 274 | + // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery -- $sql is prepared by $wpdb->prepare() with parameterized values; direct query required for complex joins. | |
| 275 | + $result = $wpdb->get_var( $sql ); | |
| 276 | + wp_cache_set( $cache_key, $result, '', HOUR_IN_SECONDS ); | |
| 277 | + | |
| 278 | + return $result; | |
| 210 | 279 | } |
| 211 | 280 | |
| 212 | 281 | /** |
| 213 | 282 | * Get child site last automatic sync date & time. |
| @@ -214,7 +283,21 @@ | ||
| 214 | 283 | * |
| 215 | 284 | * @return string Date and time of last automatic sync. |
| 216 | 285 | */ |
| 217 | 286 | public function get_websites_last_automatic_sync() { |
| 218 | - return $this->wpdb->get_var( 'SELECT MAX(wp_sync.dtsAutomaticSync) FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid' ); | |
| 287 | + global $wpdb; | |
| 288 | + | |
| 289 | + $cache_key = 'mainwp_auto_updates_last_sync'; | |
| 290 | + $cached = wp_cache_get( $cache_key ); | |
| 291 | + if ( false !== $cached ) { | |
| 292 | + return $cached; | |
| 293 | + } | |
| 294 | + | |
| 295 | + $sql = 'SELECT MAX(wp_sync.dtsAutomaticSync) FROM ' . $this->table_name( 'wp' ) . ' wp JOIN ' . $this->table_name( 'wp_sync' ) . ' wp_sync ON wp.id = wp_sync.wpid'; | |
| 296 | + | |
| 297 | + // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery -- Table names come from safe $this->table_name() methods only, no user input in this query; direct query required for complex joins. | |
| 298 | + $result = $wpdb->get_var( $sql ); | |
| 299 | + wp_cache_set( $cache_key, $result, '', HOUR_IN_SECONDS ); | |
| 300 | + | |
| 301 | + return $result; | |
| 219 | 302 | } |
| 220 | 303 | } |