PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.1
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
← All changes | class/class-mainwp-system-handler.php +1237 -933 4.6.0.1 → 6.2.1 View file →
@@ -6,1066 +6,1370 @@
6 6 */
7 7
8 8 namespace MainWP\Dashboard;
9 9
10 +// Exit if accessed directly.
11 +if ( ! defined( 'ABSPATH' ) ) {
12 + exit;
13 +}
14 +
10 15 /**
11 16 * Class MainWP_System_Handler
12 17 *
13 18 * @package MainWP\Dashboard
14 19 */
15 -class MainWP_System_Handler {
20 +class MainWP_System_Handler { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
16 21
17 - // phpcs:disable WordPress.WP.AlternativeFunctions -- use system functions
22 + // phpcs:disable WordPress.WP.AlternativeFunctions -- use system functions
18 23
19 - /**
20 - * Private static variable to hold the single instance of the class.
21 - *
22 - * @static
23 - *
24 - * @var mixed Default null
25 - */
26 - private static $instance = null;
24 + /**
25 + * Private static variable to hold the single instance of the class.
26 + *
27 + * @static
28 + *
29 + * @var mixed Default null
30 + */
31 + private static $instance = null;
27 32
28 - /**
29 - * Private variable to hold the upgrade version info.
30 - *
31 - * @var null Version info.
32 - */
33 - private $upgradeVersionInfo = null;
33 + /**
34 + * Private variable to hold the upgrade version info.
35 + *
36 + * @var \stdClass|null Version info.
37 + */
38 + private $upgradeVersionInfo = null;
34 39
35 - /**
36 - * Method instance()
37 - *
38 - * Create public static instance.
39 - *
40 - * @static
41 - * @return MainWP_System
42 - */
43 - public static function instance() {
44 - if ( null === self::$instance ) {
45 - self::$instance = new self();
46 - }
40 + /**
41 + * Method instance()
42 + *
43 + * Create public static instance.
44 + *
45 + * @static
46 + * @return MainWP_System
47 + */
48 + public static function instance() {
49 + if ( null === static::$instance ) {
50 + static::$instance = new self();
51 + }
47 52
48 - return self::$instance;
49 - }
53 + return static::$instance;
54 + }
50 55
51 - /**
52 - * MainWP_System_Handler constructor.
53 - *
54 - * Run each time the class is called.
55 - *
56 - * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_class_name()
57 - */
58 - public function __construct() {
59 - add_filter( 'mainwp-extension-enabled-check', array( MainWP_Extensions_Handler::get_class_name(), 'is_extension_enabled' ) ); // @deprecated Use 'mainwp_extension_enabled_check' instead.
60 - add_filter( 'mainwp_extension_enabled_check', array( MainWP_Extensions_Handler::get_class_name(), 'is_extension_enabled' ) );
56 + /**
57 + * MainWP_System_Handler constructor.
58 + *
59 + * Run each time the class is called.
60 + *
61 + * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_class_name()
62 + */
63 + public function __construct() {
64 + add_filter( 'mainwp-extension-enabled-check', array( MainWP_Extensions_Handler::get_class_name(), 'is_extension_enabled' ) ); // @deprecated Use 'mainwp_extension_enabled_check' instead.
65 + add_filter( 'mainwp_extension_enabled_check', array( MainWP_Extensions_Handler::get_class_name(), 'is_extension_enabled' ) );
61 66
62 - /**
63 - * This hook allows you to get a list of sites via the 'mainwp-getsites' filter.
64 - *
65 - * @link http://codex.mainwp.com/#mainwp-getsites
66 - *
67 - * @see \MainWP_Extensions::hook_get_sites
68 - */
69 - add_filter( 'mainwp-getsites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_sites' ), 10, 5 ); // @deprecated Use 'mainwp_getsites' instead.
70 - add_filter( 'mainwp-getdbsites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_db_sites' ), 10, 5 ); // @deprecated Use 'mainwp_getdbsites' instead.
67 + /**
68 + * This hook allows you to get a list of sites via the 'mainwp-getsites' filter.
69 + *
70 + * @link http://codex.mainwp.com/#mainwp-getsites
71 + *
72 + * @see \MainWP_Extensions::hook_get_sites
73 + */
74 + add_filter( 'mainwp-getsites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_sites' ), 10, 5 ); // @deprecated Use 'mainwp_getsites' instead.
75 + add_filter( 'mainwp-getdbsites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_db_sites' ), 10, 6 ); // @deprecated Use 'mainwp_getdbsites' instead.
71 76
72 - add_filter( 'mainwp_getsites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_sites' ), 10, 5 );
73 - add_filter( 'mainwp_getdbsites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_db_sites' ), 10, 5 );
74 - add_filter( 'mainwp_get_db_websites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_db_websites' ), 10, 5 );
77 + add_filter( 'mainwp_getsites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_sites' ), 10, 5 );
78 + add_filter( 'mainwp_getdbsites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_db_sites' ), 10, 6 );
79 + add_filter( 'mainwp_get_db_websites', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_db_websites' ), 10, 5 );
75 80
76 - /**
77 - * This hook allows you to get a information about groups via the 'mainwp-getgroups' filter.
78 - *
79 - * @link http://codex.mainwp.com/#mainwp-getgroups
80 - *
81 - * @see \MainWP_Extensions::hook_get_groups
82 - */
83 - add_filter( 'mainwp-getgroups', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_groups' ), 10, 4 ); // @deprecated Use 'mainwp_getgroups' instead.
84 - add_filter( 'mainwp_getgroups', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_groups' ), 10, 4 );
85 - add_action( 'mainwp_fetchurlsauthed', array( &$this, 'filter_fetch_urls_authed' ), 10, 7 );
86 - add_filter( 'mainwp_fetchurlauthed', array( &$this, 'filter_fetch_url_authed' ), 10, 6 );
87 - add_filter( 'mainwp_getsqlwebsites_for_current_user', array( self::class, 'hook_get_sql_websites_for_current_user' ), 10, 4 );
88 - add_filter( 'mainwp_fetchurlverifyaction', array( &$this, 'hook_fetch_url_verify_action' ), 10, 4 );
81 + /**
82 + * This hook allows you to get a information about groups via the 'mainwp-getgroups' filter.
83 + *
84 + * @link http://codex.mainwp.com/#mainwp-getgroups
85 + *
86 + * @see \MainWP_Extensions::hook_get_groups
87 + */
88 + add_filter( 'mainwp-getgroups', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_groups' ), 10, 4 ); // @deprecated Use 'mainwp_getgroups' instead.
89 + add_filter( 'mainwp_getgroups', array( MainWP_Extensions_Handler::get_class_name(), 'hook_get_groups' ), 10, 4 );
90 + add_action( 'mainwp_fetchurlsauthed', array( &$this, 'filter_fetch_urls_authed' ), 10, 7 );
91 + add_filter( 'mainwp_fetchurlauthed', array( &$this, 'filter_fetch_url_authed' ), 10, 6 );
92 + add_filter( 'mainwp_getsqlwebsites_for_current_user', array( static::class, 'hook_get_sql_websites_for_current_user' ), 10, 4 );
93 + add_filter( 'mainwp_fetchurlverifyaction', array( &$this, 'hook_fetch_url_verify_action' ), 10, 4 );
89 94
90 - add_filter(
91 - 'mainwp_getdashboardsites',
92 - array(
93 - MainWP_Extensions_Handler::get_class_name(),
94 - 'hook_get_dashboard_sites',
95 - ),
96 - 10,
97 - 7
98 - );
95 + add_filter(
96 + 'mainwp_getdashboardsites',
97 + array(
98 + MainWP_Extensions_Handler::get_class_name(),
99 + 'hook_get_dashboard_sites',
100 + ),
101 + 10,
102 + 7
103 + );
99 104
100 - // @deprecated Use 'mainwp_manager_getextensions' instead.
101 - add_filter(
102 - 'mainwp-manager-getextensions',
103 - array(
104 - MainWP_Extensions_Handler::get_class_name(),
105 - 'hook_get_all_extensions',
106 - )
107 - );
105 + // @deprecated Use 'mainwp_manager_getextensions' instead.
106 + add_filter(
107 + 'mainwp-manager-getextensions',
108 + array(
109 + MainWP_Extensions_Handler::get_class_name(),
110 + 'hook_get_all_extensions',
111 + )
112 + );
108 113
109 - add_filter(
110 - 'mainwp_manager_getextensions',
111 - array(
112 - MainWP_Extensions_Handler::get_class_name(),
113 - 'hook_get_all_extensions',
114 - )
115 - );
114 + add_filter(
115 + 'mainwp_manager_getextensions',
116 + array(
117 + MainWP_Extensions_Handler::get_class_name(),
118 + 'hook_get_all_extensions',
119 + )
120 + );
116 121
117 - add_action( 'admin_init', array( &$this, 'admin_init' ) );
122 + add_action( 'admin_init', array( &$this, 'admin_init' ) );
118 123
119 - if ( false !== get_option( 'mainwp_upgradeVersionInfo' ) && '' !== get_option( 'mainwp_upgradeVersionInfo' ) ) {
120 - $this->upgradeVersionInfo = get_option( 'mainwp_upgradeVersionInfo' );
121 - if ( ! is_object( $this->upgradeVersionInfo ) ) {
122 - $this->upgradeVersionInfo = new \stdClass();
123 - }
124 - }
125 - }
124 + if ( false !== get_option( 'mainwp_upgradeVersionInfo' ) && '' !== get_option( 'mainwp_upgradeVersionInfo' ) ) {
125 + $this->upgradeVersionInfo = get_option( 'mainwp_upgradeVersionInfo' );
126 + if ( ! is_object( $this->upgradeVersionInfo ) ) {
127 + $this->upgradeVersionInfo = new \stdClass();
128 + }
129 + }
130 + }
126 131
127 - /**
128 - * Method filter_fetch_urls_authed()
129 - *
130 - * Filter fetch authorized urls.
131 - *
132 - * @param mixed $pluginFile MainWP extention.
133 - * @param string $key MainWP Licence Key.
134 - * @param object $dbwebsites Child Sites.
135 - * @param string $what Function to perform.
136 - * @param array $params Function paramerters.
137 - * @param mixed $handle Function handle.
138 - * @param mixed $output Function output.
139 - *
140 - * @return mixed MainWP_Extensions_Handler::hook_fetch_urls_authed() Hook fetch authorized URLs.
141 - *
142 - * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::hook_fetch_urls_authed()
143 - */
144 - public function filter_fetch_urls_authed( $pluginFile, $key, $dbwebsites, $what, $params, $handle, $output ) {
145 - return MainWP_Extensions_Handler::hook_fetch_urls_authed( $pluginFile, $key, $dbwebsites, $what, $params, $handle, $output );
146 - }
132 + /**
133 + * Method filter_fetch_urls_authed()
134 + *
135 + * Filter fetch authorized urls.
136 + *
137 + * @param mixed $pluginFile MainWP extention.
138 + * @param string $key MainWP Licence Key.
139 + * @param object $dbwebsites Child Sites.
140 + * @param string $what Function to perform.
141 + * @param array $params Function paramerters.
142 + * @param mixed $handle Function handle.
143 + * @param mixed $output Function output.
144 + *
145 + * @return mixed MainWP_Extensions_Handler::hook_fetch_urls_authed() Hook fetch authorized URLs.
146 + *
147 + * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::hook_fetch_urls_authed()
148 + */
149 + public function filter_fetch_urls_authed( $pluginFile, $key, $dbwebsites, $what, $params, $handle, $output ) {
150 + return MainWP_Extensions_Handler::hook_fetch_urls_authed( $pluginFile, $key, $dbwebsites, $what, $params, $handle, $output );
151 + }
147 152
148 - /**
149 - * Method filter_fetch_url_authed()
150 - *
151 - * Filter fetch Authorized URL.
152 - *
153 - * @param mixed $pluginFile MainWP extention.
154 - * @param string $key MainWP licence key.
155 - * @param int $websiteId Website ID.
156 - * @param string $what Function to perform.
157 - * @param array $params Function paramerters.
158 - * @param null $raw_response Raw response.
159 - *
160 - * @return mixed MainWP_Extensions_Handler::hook_fetch_url_authed() Hook fetch authorized URL.
161 - *
162 - * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::hook_fetch_url_authed()
163 - */
164 - public function filter_fetch_url_authed( $pluginFile, $key, $websiteId, $what, $params, $raw_response = null ) {
165 - return MainWP_Extensions_Handler::hook_fetch_url_authed( $pluginFile, $key, $websiteId, $what, $params, $raw_response );
166 - }
153 + /**
154 + * Method filter_fetch_url_authed()
155 + *
156 + * Filter fetch Authorized URL.
157 + *
158 + * @param mixed $pluginFile MainWP extention.
159 + * @param string $key MainWP licence key.
160 + * @param int $websiteId Website ID.
161 + * @param string $what Function to perform.
162 + * @param array $params Function paramerters.
163 + * @param null $raw_response Raw response.
164 + *
165 + * @return mixed MainWP_Extensions_Handler::hook_fetch_url_authed() Hook fetch authorized URL.
166 + *
167 + * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::hook_fetch_url_authed()
168 + */
169 + public function filter_fetch_url_authed( $pluginFile, $key, $websiteId, $what, $params, $raw_response = null ) {
170 + return MainWP_Extensions_Handler::hook_fetch_url_authed( $pluginFile, $key, $websiteId, $what, $params, $raw_response );
171 + }
167 172
168 - /**
169 - * Method hook_fetch_url_verify_action()
170 - *
171 - * Filter fetch Authorized URL.
172 - *
173 - * @param mixed $pluginFile MainWP extention.
174 - * @param string $childKey Extension child key.
175 - * @param int $websiteId Website ID.
176 - * @param array $params Function paramerters.
177 - *
178 - * @return mixed MainWP_Extensions_Handler::hook_fetch_url_authed() Hook fetch authorized URL.
179 - */
180 - public function hook_fetch_url_verify_action( $pluginFile, $childKey, $websiteId, $params ) {
181 - if ( ! is_array( $params ) || ! isset( $params['actionnonce'] ) ) {
182 - return false;
183 - }
184 - $what = 'verify_action';
185 - return MainWP_Extensions_Handler::hook_fetch_url_authed( $pluginFile, $childKey, $websiteId, $what, $params );
186 - }
173 + /**
174 + * Method hook_fetch_url_verify_action()
175 + *
176 + * Filter fetch Authorized URL.
177 + *
178 + * @param mixed $pluginFile MainWP extention.
179 + * @param string $childKey Extension child key.
180 + * @param int $websiteId Website ID.
181 + * @param array $params Function paramerters.
182 + *
183 + * @return mixed MainWP_Extensions_Handler::hook_fetch_url_authed() Hook fetch authorized URL.
184 + */
185 + public function hook_fetch_url_verify_action( $pluginFile, $childKey, $websiteId, $params ) {
186 + if ( ! is_array( $params ) || ! isset( $params['actionnonce'] ) ) {
187 + return false;
188 + }
189 + $what = 'verify_action';
190 + return MainWP_Extensions_Handler::hook_fetch_url_authed( $pluginFile, $childKey, $websiteId, $what, $params );
191 + }
187 192
188 - /**
189 - * Method apply_filter()
190 - *
191 - * Apply filter
192 - *
193 - * @param string $filter The filter.
194 - * @param array $value Input value.
195 - *
196 - * @return array $output Output array.
197 - *
198 - * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::hook_verify()
199 - */
200 - public function apply_filters( $filter, $value = array() ) {
193 + /**
194 + * Method apply_filter()
195 + *
196 + * Apply filter
197 + *
198 + * @param string $filter The filter.
199 + * @param array $value Input value.
200 + *
201 + * @return array $output Output array.
202 + *
203 + * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::hook_verify()
204 + */
205 + public function apply_filters( $filter, $value = array() ) {
201 206
202 - if ( 'mainwp-getmetaboxes' === $filter ) {
203 - $output = apply_filters_deprecated( 'mainwp-getmetaboxes', array( $value ), '4.0.7.2', 'mainwp_getmetaboxes' ); // @deprecated Use 'mainwp_getmetaboxes' instead.
204 - } else {
205 - $output = apply_filters( $filter, $value );
206 - }
207 + if ( 'mainwp-getmetaboxes' === $filter ) {
208 + $output = apply_filters_deprecated( 'mainwp-getmetaboxes', array( $value ), '4.0.7.2', 'mainwp_getmetaboxes' ); // @deprecated Use 'mainwp_getmetaboxes' instead. NOSONAR - not IP.
209 + } else {
210 + $output = apply_filters( $filter, $value );
211 + }
207 212
208 - if ( ! is_array( $output ) ) {
209 - return array();
210 - }
211 - $count = count( $output );
212 - for ( $i = 0; $i < $count; $i++ ) {
213 + if ( ! is_array( $output ) ) {
214 + return array();
215 + }
216 + return $output;
217 + }
213 218
214 - if ( 'mainwp_getmetaboxes' === $filter ) {
215 - // pass custom widget.
216 - if ( isset( $output[ $i ]['custom'] ) && $output[ $i ]['custom'] && isset( $output[ $i ]['plugin'] ) ) {
217 - continue;
218 - }
219 - }
220 - }
219 + /**
220 + * Method admin_init()
221 + *
222 + * Do nothing if current user is not an Admin.
223 + */
224 + public function admin_init() { // phpcs:ignore -- NOSONAR - complex function.
225 + if ( ! MainWP_System_Utility::is_admin() ) {
226 + return;
227 + }
221 228
222 - return $output;
223 - }
229 + $this->handle_quick_theme_change();
224 230
225 - /**
226 - * Method admin_init()
227 - *
228 - * Do nothing if current user is not an Admin.
229 - */
230 - public function admin_init() { // phpcs:ignore -- complex function.
231 - if ( ! MainWP_System_Utility::is_admin() ) {
232 - return;
233 - }
231 + global $pagenow;
234 232
235 - global $pagenow;
233 + if ( 'plugins.php' === $pagenow && isset( $_GET['do'] ) && 'checkUpgrade' === $_GET['do'] && ( ( time() - $this->upgradeVersionInfo->updated ) > 30 ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
234 + $this->check_upgrade();
235 + delete_site_transient( 'update_plugins' ); // to forced refresh 'update_plugins' transient.
236 + wp_safe_redirect( admin_url( 'plugins.php' ) );
237 + exit;
238 + }
239 + }
236 240
237 - if ( 'plugins.php' === $pagenow && isset( $_GET['do'] ) && 'checkUpgrade' === $_GET['do'] && ( ( time() - $this->upgradeVersionInfo->updated ) > 30 ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
238 - $this->check_upgrade();
239 - delete_site_transient( 'update_plugins' ); // to forced refresh 'update_plugins' transient.
240 - wp_safe_redirect( admin_url( 'plugins.php' ) );
241 - exit;
242 - }
243 - }
241 + /**
242 + * Method hook_get_sql_websites_for_current_user()
243 + *
244 + * Get sql websites for current user.
245 + *
246 + * @param mixed $input_value First input filter value.
247 + * @param string $pluginFile Extension plugin file to verify.
248 + * @param string $key The child-key.
249 + * @param mixed $params Input params data.
250 + *
251 + * @return string sql.
252 + */
253 + public static function hook_get_sql_websites_for_current_user( $input_value, $pluginFile, $key, $params ) {
254 + unset( $input_value );
255 + if ( ! MainWP_Extensions_Handler::hook_verify( $pluginFile, $key ) ) {
256 + return false;
257 + }
244 258
259 + // Prevent conflicts in wp_options query conditions.
260 + // If use_join_wp_options is not enabled,
261 + // force the use of a compatible subquery approach to ensure the query remains correct.
262 + if ( is_array( $params ) && empty( $params['use_join_wp_options'] ) ) {
263 + $params['use_compatible_subquery'] = 1;
264 + }
245 265
266 + return MainWP_DB::instance()->get_sql_wp_for_current_user( $params );
267 + }
268 + /**
269 + * Method handle_manage_sites_screen_settings()
270 + *
271 + * Handle manage sites screen settings
272 + */
273 + public function handle_manage_sites_screen_settings() { // phpcs:ignore -- NOSONAR - required to achieve desired results, pull request solutions appreciated.
274 + if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'ManageSitesScrOptions' ) ) {
275 + $show_cols = array();
276 + foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST ) ) as $key => $val ) {
277 + if ( false !== strpos( $key, 'mainwp_show_column_' ) ) {
278 + $col = str_replace( 'mainwp_show_column_', '', $key );
279 + $show_cols[ $col ] = 1;
280 + }
281 + }
282 + if ( isset( $_POST['show_columns_name'] ) ) {
283 + foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST['show_columns_name'] ) ) as $col ) {
284 + if ( ! isset( $show_cols[ $col ] ) ) {
285 + $show_cols[ $col ] = 0; // uncheck, hide columns.
286 + }
287 + }
288 + }
289 + MainWP_Utility::update_option( 'mainwp_use_favicon', 1 );
290 + MainWP_Utility::update_option( 'mainwp_optimize', ( ! isset( $_POST['mainwp_optimize'] ) ? 0 : 1 ) );
291 + $user = wp_get_current_user();
292 + if ( $user ) {
293 + $val = ( isset( $_POST['mainwp_sitesviewmode'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_sitesviewmode'] ) ) : 'grid' );
294 + if ( 'grid' !== $val && 'table' !== $val ) {
295 + $val = 'grid';
296 + }
297 + update_user_option( $user->ID, 'mainwp_sitesviewmode', $val, true );
298 + update_user_option( $user->ID, 'mainwp_settings_show_manage_sites_columns', $show_cols, true );
299 + update_option( 'mainwp_default_sites_per_page', ( isset( $_POST['mainwp_default_sites_per_page'] ) ? intval( $_POST['mainwp_default_sites_per_page'] ) : 25 ) );
300 + }
301 + } elseif ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'SreenshotsSitesScrOptions' ) ) {
302 + $user = wp_get_current_user();
303 + if ( $user ) {
304 + $val = ( isset( $_POST['mainwp_sitesviewmode'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_sitesviewmode'] ) ) : 'grid' );
305 + if ( 'grid' !== $val && 'table' !== $val ) {
306 + $val = 'grid';
307 + }
308 + update_user_option( $user->ID, 'mainwp_sitesviewmode', $val, true );
309 + }
310 + }
311 + }
246 312
247 - /**
248 - * Method hook_get_sql_websites_for_current_user()
249 - *
250 - * Get sql websites for current user.
251 - *
252 - * @param mixed $input_value First input filter value.
253 - * @param string $pluginFile Extension plugin file to verify.
254 - * @param string $key The child-key.
255 - * @param mixed $params Input params data.
256 - *
257 - * @return string sql.
258 - */
259 - public static function hook_get_sql_websites_for_current_user( $input_value, $pluginFile, $key, $params ) {
260 - if ( ! MainWP_Extensions_Handler::hook_verify( $pluginFile, $key ) ) {
261 - return false;
262 - }
263 - return MainWP_DB::instance()->get_sql_wp_for_current_user( $params );
264 - }
265 - /**
266 - * Method handle_manage_sites_screen_settings()
267 - *
268 - * Handle manage sites screen settings
269 - */
270 - public function handle_manage_sites_screen_settings() { // phpcs:ignore -- required to achieve desired results, pull request solutions appreciated.
271 - if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'ManageSitesScrOptions' ) ) {
272 - $show_cols = array();
273 - foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST ) ) as $key => $val ) {
274 - if ( false !== strpos( $key, 'mainwp_show_column_' ) ) {
275 - $col = str_replace( 'mainwp_show_column_', '', $key );
276 - $show_cols[ $col ] = 1;
277 - }
278 - }
279 - if ( isset( $_POST['show_columns_name'] ) ) {
280 - foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST['show_columns_name'] ) ) as $col ) {
281 - if ( ! isset( $show_cols[ $col ] ) ) {
282 - $show_cols[ $col ] = 0; // uncheck, hide columns.
283 - }
284 - }
285 - }
286 - MainWP_Utility::update_option( 'mainwp_use_favicon', ( ! isset( $_POST['mainwp_use_favicon'] ) ? 0 : 1 ) );
287 - MainWP_Utility::update_option( 'mainwp_optimize', ( ! isset( $_POST['mainwp_optimize'] ) ? 0 : 1 ) );
288 - $user = wp_get_current_user();
289 - if ( $user ) {
290 - $val = ( isset( $_POST['mainwp_sitesviewmode'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_sitesviewmode'] ) ) : 'grid' );
291 - if ( 'grid' !== $val && 'table' !== $val ) {
292 - $val = 'grid';
293 - }
294 - update_user_option( $user->ID, 'mainwp_sitesviewmode', $val, true );
295 - update_user_option( $user->ID, 'mainwp_settings_show_manage_sites_columns', $show_cols, true );
296 - update_option( 'mainwp_default_sites_per_page', ( isset( $_POST['mainwp_default_sites_per_page'] ) ? intval( $_POST['mainwp_default_sites_per_page'] ) : 25 ) );
297 - }
298 - } elseif ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'SreenshotsSitesScrOptions' ) ) {
299 - $user = wp_get_current_user();
300 - if ( $user ) {
301 - $val = ( isset( $_POST['mainwp_sitesviewmode'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_sitesviewmode'] ) ) : 'grid' );
302 - if ( 'grid' !== $val && 'table' !== $val ) {
303 - $val = 'grid';
304 - }
305 - update_user_option( $user->ID, 'mainwp_sitesviewmode', $val, true );
306 - }
307 - }
308 - }
313 + /**
314 + * Method handle_monitoring_sites_screen_settings()
315 + *
316 + * Handle monitoring sites screen settings
317 + */
318 + public function handle_monitoring_sites_screen_settings() { // phpcs:ignore -- NOSONAR - complex.
319 + if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MonitoringSitesScrOptions' ) ) {
320 + $show_cols = array();
321 + foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST ) ) as $key => $val ) {
322 + if ( false !== strpos( $key, 'mainwp_show_column_' ) ) {
323 + $col = str_replace( 'mainwp_show_column_', '', $key );
324 + $show_cols[ $col ] = 1;
325 + }
326 + }
327 + if ( isset( $_POST['show_columns_name'] ) ) {
328 + foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST['show_columns_name'] ) ) as $col ) {
329 + if ( ! isset( $show_cols[ $col ] ) ) {
330 + $show_cols[ $col ] = 0; // uncheck, hide columns.
331 + }
332 + }
333 + }
309 334
310 - /**
311 - * Method handle_monitoring_sites_screen_settings()
312 - *
313 - * Handle monitoring sites screen settings
314 - */
315 - public function handle_monitoring_sites_screen_settings() {
316 - if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MonitoringSitesScrOptions' ) ) {
317 - $show_cols = array();
318 - foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST ) ) as $key => $val ) {
319 - if ( false !== strpos( $key, 'mainwp_show_column_' ) ) {
320 - $col = str_replace( 'mainwp_show_column_', '', $key );
321 - $show_cols[ $col ] = 1;
322 - }
323 - }
324 - if ( isset( $_POST['show_columns_name'] ) ) {
325 - foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST['show_columns_name'] ) ) as $col ) {
326 - if ( ! isset( $show_cols[ $col ] ) ) {
327 - $show_cols[ $col ] = 0; // uncheck, hide columns.
328 - }
329 - }
330 - }
335 + $user = wp_get_current_user();
336 + if ( $user ) {
337 + update_user_option( $user->ID, 'mainwp_settings_show_monitoring_sites_columns', $show_cols, true );
338 + update_option( 'mainwp_default_monitoring_sites_per_page', ( isset( $_POST['mainwp_default_monitoring_sites_per_page'] ) ? intval( $_POST['mainwp_default_monitoring_sites_per_page'] ) : 25 ) );
339 + }
331 340
332 - $user = wp_get_current_user();
333 - if ( $user ) {
334 - update_user_option( $user->ID, 'mainwp_settings_show_monitoring_sites_columns', $show_cols, true );
335 - update_option( 'mainwp_default_monitoring_sites_per_page', ( isset( $_POST['mainwp_default_monitoring_sites_per_page'] ) ? intval( $_POST['mainwp_default_monitoring_sites_per_page'] ) : 25 ) );
336 - }
341 + update_option( 'mainwp_disableSitesHealthMonitoring', ( ! isset( $_POST['mainwp_disable_sitesHealthMonitoring'] ) ? 1 : 0 ) );
337 342
338 - update_option( 'mainwp_disableSitesChecking', ( ! isset( $_POST['mainwp_disableSitesChecking'] ) ? 1 : 0 ) );
343 + $val = isset( $_POST['mainwp_site_healthThreshold'] ) ? intval( $_POST['mainwp_site_healthThreshold'] ) : 80;
344 + update_option( 'mainwp_sitehealthThreshold', $val );
345 + }
346 + }
339 347
340 - $val = isset( $_POST['mainwp_frequency_sitesChecking'] ) ? intval( $_POST['mainwp_frequency_sitesChecking'] ) : 1440;
341 - update_option( 'mainwp_frequencySitesChecking', $val );
348 + /**
349 + * Method handle_clients_screen_settings()
350 + *
351 + * Handle manage clients screen settings
352 + */
353 + public function handle_clients_screen_settings() { // phpcs:ignore -- NOSONAR - complex.
354 + if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'ManageClientsScrOptions' ) ) {
355 + $show_cols = array();
356 + foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST ) ) as $key => $val ) {
357 + if ( false !== strpos( $key, 'mainwp_show_column_' ) ) {
358 + $col = str_replace( 'mainwp_show_column_', '', $key );
359 + $show_cols[ $col ] = 1;
360 + }
361 + }
362 + if ( isset( $_POST['show_columns_name'] ) ) {
363 + foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST['show_columns_name'] ) ) as $col ) {
364 + if ( ! isset( $show_cols[ $col ] ) ) {
365 + $show_cols[ $col ] = 0; // uncheck, hide columns.
366 + }
367 + }
368 + }
342 369
343 - update_option( 'mainwp_disableSitesHealthMonitoring', ( ! isset( $_POST['mainwp_disable_sitesHealthMonitoring'] ) ? 1 : 0 ) );
370 + $user = wp_get_current_user();
371 + if ( $user ) {
372 + update_user_option( $user->ID, 'mainwp_settings_show_manage_clients_columns', $show_cols, true );
373 + update_option( 'mainwp_default_manage_clients_per_page', ( isset( $_POST['mainwp_default_manage_clients_per_page'] ) ? intval( $_POST['mainwp_default_manage_clients_per_page'] ) : 25 ) );
374 + }
375 + }
376 + }
344 377
345 - $val = isset( $_POST['mainwp_site_healthThreshold'] ) ? intval( $_POST['mainwp_site_healthThreshold'] ) : 80;
346 - update_option( 'mainwp_sitehealthThreshold', $val );
347 - }
348 - }
378 + /**
379 + * Method handle_insights_events_screen_settings()
380 + *
381 + * Handle manage insights events screen settings
382 + */
383 + public function handle_insights_events_screen_settings() { // phpcs:ignore -- NOSONAR - complex.
384 + if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'ManageEventsScrOptions' ) ) {
385 + $show_cols = array();
386 + foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST ) ) as $key => $val ) {
387 + if ( false !== strpos( $key, 'mainwp_show_column_' ) ) {
388 + $col = str_replace( 'mainwp_show_column_', '', $key );
389 + $show_cols[ $col ] = 1;
390 + }
391 + }
392 + if ( isset( $_POST['show_columns_name'] ) ) {
393 + foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST['show_columns_name'] ) ) as $col ) {
394 + if ( ! isset( $show_cols[ $col ] ) ) {
395 + $show_cols[ $col ] = 0; // uncheck, hide columns.
396 + }
397 + }
398 + }
349 399
350 - /**
351 - * Method handle_clients_screen_settings()
352 - *
353 - * Handle manage clients screen settings
354 - */
355 - public function handle_clients_screen_settings() {
356 - if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'ManageClientsScrOptions' ) ) {
357 - $show_cols = array();
358 - foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST ) ) as $key => $val ) {
359 - if ( false !== strpos( $key, 'mainwp_show_column_' ) ) {
360 - $col = str_replace( 'mainwp_show_column_', '', $key );
361 - $show_cols[ $col ] = 1;
362 - }
363 - }
364 - if ( isset( $_POST['show_columns_name'] ) ) {
365 - foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST['show_columns_name'] ) ) as $col ) {
366 - if ( ! isset( $show_cols[ $col ] ) ) {
367 - $show_cols[ $col ] = 0; // uncheck, hide columns.
368 - }
369 - }
370 - }
400 + $user = wp_get_current_user();
401 + if ( $user ) {
402 + update_user_option( $user->ID, 'mainwp_settings_show_insights_events_columns', $show_cols, true );
403 + update_option( 'mainwp_default_manage_insights_events_per_page', ( isset( $_POST['mainwp_default_sites_per_page'] ) ? intval( $_POST['mainwp_default_sites_per_page'] ) : 25 ) );
404 + }
405 + wp_safe_redirect( admin_url( 'admin.php?page=InsightsManage&message=savedscreenopts' ) );
406 + exit();
407 + }
408 + }
371 409
372 - $user = wp_get_current_user();
373 - if ( $user ) {
374 - update_user_option( $user->ID, 'mainwp_settings_show_manage_clients_columns', $show_cols, true );
375 - update_option( 'mainwp_default_manage_clients_per_page', ( isset( $_POST['mainwp_default_manage_clients_per_page'] ) ? intval( $_POST['mainwp_default_manage_clients_per_page'] ) : 25 ) );
376 - }
377 - }
378 - }
410 + /**
411 + * Method handle_clients_screen_settings()
412 + *
413 + * Handle manage clients screen settings
414 + */
415 + public function handle_updates_screen_settings() { //phpcs:ignore -- NOSONAR - complex.
416 + if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'UpdatesScrOptions' ) ) {
417 + $val = ( ! isset( $_POST['mainwp_pluginAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_pluginAutomaticDailyUpdate'] ) );
418 + MainWP_Utility::update_option( 'mainwp_pluginAutomaticDailyUpdate', $val );
419 + $val = ( ! isset( $_POST['mainwp_themeAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_themeAutomaticDailyUpdate'] ) );
420 + MainWP_Utility::update_option( 'mainwp_themeAutomaticDailyUpdate', $val );
421 + $val = ( ! isset( $_POST['mainwp_transAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_transAutomaticDailyUpdate'] ) );
422 + MainWP_Utility::update_option( 'mainwp_transAutomaticDailyUpdate', $val );
423 + $val = ( ! isset( $_POST['mainwp_automaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_automaticDailyUpdate'] ) );
424 + MainWP_Utility::update_option( 'mainwp_automaticDailyUpdate', $val );
425 + $val = ( isset( $_POST['mainwp_delay_autoupdate'] ) ? intval( $_POST['mainwp_delay_autoupdate'] ) : 1 );
426 + MainWP_Utility::update_option( 'mainwp_delay_autoupdate', $val );
427 + $val = ( ! isset( $_POST['mainwp_show_language_updates'] ) ? 0 : 1 );
428 + MainWP_Utility::update_option( 'mainwp_show_language_updates', $val );
429 + $val = ( ! isset( $_POST['mainwp_disable_update_confirmations'] ) ? 0 : intval( $_POST['mainwp_disable_update_confirmations'] ) );
430 + MainWP_Utility::update_option( 'mainwp_disable_update_confirmations', $val );
431 + }
432 + }
379 433
380 - /**
381 - * Method handle_clients_screen_settings()
382 - *
383 - * Handle manage clients screen settings
384 - */
385 - public function handle_updates_screen_settings() {
386 - if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'UpdatesScrOptions' ) ) {
387 - $val = ( ! isset( $_POST['mainwp_pluginAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_pluginAutomaticDailyUpdate'] ) );
388 - MainWP_Utility::update_option( 'mainwp_pluginAutomaticDailyUpdate', $val );
389 - $val = ( ! isset( $_POST['mainwp_themeAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_themeAutomaticDailyUpdate'] ) );
390 - MainWP_Utility::update_option( 'mainwp_themeAutomaticDailyUpdate', $val );
391 - $val = ( ! isset( $_POST['mainwp_automaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_automaticDailyUpdate'] ) );
392 - MainWP_Utility::update_option( 'mainwp_automaticDailyUpdate', $val );
393 - $val = ( isset( $_POST['mainwp_delay_autoupdate'] ) ? intval( $_POST['mainwp_delay_autoupdate'] ) : 1 );
394 - MainWP_Utility::update_option( 'mainwp_delay_autoupdate', $val );
395 - $val = ( ! isset( $_POST['mainwp_show_language_updates'] ) ? 0 : 1 );
396 - MainWP_Utility::update_option( 'mainwp_show_language_updates', $val );
397 - $val = ( ! isset( $_POST['mainwp_disable_update_confirmations'] ) ? 0 : intval( $_POST['mainwp_disable_update_confirmations'] ) );
398 - MainWP_Utility::update_option( 'mainwp_disable_update_confirmations', $val );
399 - }
400 - }
434 + /**
435 + * Method handle_quick_theme_change()
436 + *
437 + * Handle quick theme switching via URL parameter.
438 + */
439 + public function handle_quick_theme_change() {
440 + if ( ! isset( $_GET['mainwp_quick_theme_change'] ) || ! isset( $_GET['_wpnonce'] ) ) {
441 + return;
442 + }
401 443
444 + if ( ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'mainwp_quick_theme_change' ) ) {
445 + wp_die( esc_html__( 'Security check failed', 'mainwp' ) );
446 + }
402 447
403 - /**
404 - * Method handle_mainwp_tools_settings()
405 - *
406 - * Handle mainwp tools settings.
407 - *
408 - * @uses \MainWP\Dashboard\MainWP_Twitter::clear_all_twitter_messages()
409 - * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
410 - */
411 - public function handle_mainwp_tools_settings() { // phpcs:ignore -- Current complexity is the only way to achieve desired results, pull request solutions appreciated.
448 + $user = wp_get_current_user();
412 449
413 - $user = wp_get_current_user();
450 + if ( ! $user || ! $user->ID || $user->ID <= 0 ) {
451 + wp_die( esc_html__( 'Authentication required', 'mainwp' ) );
452 + }
414 453
415 - $update_selected_mainwp_themes = false;
454 + $theme = sanitize_text_field( wp_unslash( $_GET['mainwp_quick_theme_change'] ) );
416 455
417 - if ( isset( $_GET['page'] ) && 'MainWPTools' === $_GET['page'] ) {
418 - if ( isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MainWPTools' ) ) {
419 - if ( isset( $_POST['mainwp_restore_info_messages'] ) && ! empty( $_POST['mainwp_restore_info_messages'] ) ) {
420 - delete_user_option( $user->ID, 'mainwp_notice_saved_status' );
421 - }
422 - $enabled_tours = ! isset( $_POST['mainwp-guided-tours-option'] ) ? 0 : 1;
423 - MainWP_Utility::update_option( 'mainwp_enable_guided_tours', $enabled_tours );
456 + $allowed_themes = array( 'default', 'default-dark' );
457 + if ( ! in_array( $theme, $allowed_themes, true ) ) {
458 + wp_die( esc_html__( 'Invalid theme selection', 'mainwp' ) );
459 + }
424 460
425 - if ( isset( $_POST['mainwp_settings_custom_theme'] ) ) {
426 - $update_selected_mainwp_themes = true;
427 - }
428 - }
429 - }
461 + update_user_option( $user->ID, 'mainwp_selected_theme', $theme );
462 + set_transient( 'mainwp_settings_saved', 1, 30 );
430 463
431 - if ( isset( $_POST['wp_scr_options_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_scr_options_nonce'] ), 'MainWPSelectThemes' ) ) {
432 - $update_selected_mainwp_themes = true;
433 - }
464 + $redirect_url = remove_query_arg( array( 'mainwp_quick_theme_change', '_wpnonce' ) );
465 + wp_safe_redirect( $redirect_url );
466 + exit;
467 + }
434 468
435 - if ( $update_selected_mainwp_themes ) {
436 - if ( isset( $_POST['mainwp_settings_custom_theme'] ) ) {
437 - $custom_theme = sanitize_text_field( wp_unslash( $_POST['mainwp_settings_custom_theme'] ) );
438 - update_user_option( $user->ID, 'mainwp_selected_theme', $custom_theme );
439 - }
440 - }
469 + /**
470 + * Method handle_mainwp_tools_settings()
471 + *
472 + * Handle mainwp tools settings.
473 + *
474 + * @uses \MainWP\Dashboard\MainWP_Twitter::clear_all_twitter_messages()
475 + * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
476 + */
477 + public function handle_mainwp_tools_settings() { // phpcs:ignore -- NOSONAR -Current complexity is the only way to achieve desired results, pull request solutions appreciated.
441 478
442 - $update_screen_options = false;
443 - if ( isset( $_POST['wp_nonce'] ) && ( wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'Settings' ) || wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MainWPScrOptions' ) ) ) {
444 - $update_screen_options = true;
445 - }
479 + $user = wp_get_current_user();
446 480
447 - if ( $update_screen_options ) {
448 - $show_wids = array();
449 - if ( isset( $_POST['mainwp_show_widgets'] ) && is_array( $_POST['mainwp_show_widgets'] ) ) {
450 - $selected_wids = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_show_widgets'] ) );
451 - foreach ( $selected_wids as $name ) {
452 - $show_wids[ $name ] = 1;
453 - }
454 - }
481 + $update_selected_mainwp_themes = false;
482 + $should_redirect = false; // Redirect status.
455 483
456 - if ( isset( $_POST['mainwp_widgets_name'] ) && is_array( $_POST['mainwp_widgets_name'] ) ) {
457 - $name_wids = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_widgets_name'] ) );
458 - foreach ( $name_wids as $name ) {
459 - if ( ! isset( $show_wids[ $name ] ) ) {
460 - $show_wids[ $name ] = 0;
461 - }
462 - }
463 - }
484 + if ( isset( $_GET['page'] ) && 'MainWPTools' === $_GET['page'] && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MainWPTools' ) ) {
464 485
465 - $show_cols = array();
466 - if ( isset( $_POST['mainwp_show_columns'] ) && is_array( $_POST['mainwp_show_columns'] ) ) {
467 - $selected_cols = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_show_columns'] ) );
468 - foreach ( $selected_cols as $name ) {
469 - $show_cols[ $name ] = 1;
470 - }
471 - }
486 + $old_settings = MainWP_Settings::get_all_settings_values();
472 487
473 - if ( isset( $_POST['mainwp_columns_name'] ) && is_array( $_POST['mainwp_columns_name'] ) ) {
474 - $name_cols = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_columns_name'] ) );
475 - foreach ( $name_cols as $name ) {
476 - if ( ! isset( $show_cols[ $name ] ) ) {
477 - $show_cols[ $name ] = 0;
478 - }
479 - }
480 - }
488 + if ( isset( $_POST['mainwp_restore_info_messages'] ) && ! empty( $_POST['mainwp_restore_info_messages'] ) ) {
489 + delete_user_option( $user->ID, 'mainwp_notice_saved_status' );
490 + }
491 + $enabled_tours = ! isset( $_POST['mainwp-guided-tours-option'] ) ? 0 : 1;
492 + MainWP_Utility::update_option( 'mainwp_enable_guided_tours', $enabled_tours );
481 493
482 - $val = ( isset( $_POST['mainwp_sidebarPosition'] ) ? intval( $_POST['mainwp_sidebarPosition'] ) : 1 );
483 - if ( $user ) {
484 - update_user_option( $user->ID, 'mainwp_settings_show_widgets', $show_wids, true );
485 - update_user_option( $user->ID, 'mainwp_sidebarPosition', $val, true );
494 + $enabled1 = ! isset( $_POST['mainwp-guided-chatbase-option'] ) ? 0 : 1;
495 + MainWP_Utility::update_option( 'mainwp_enable_guided_chatbase', $enabled1 );
486 496
487 - if ( isset( $_POST['mainwp_manageposts_show_columns_settings'] ) ) {
488 - update_user_option( $user->ID, 'mainwp_manageposts_show_columns', $show_cols, true );
489 - }
497 + $enabled2 = ! isset( $_POST['mainwp-guided-video-option'] ) ? 0 : 1;
498 + MainWP_Utility::update_option( 'mainwp_enable_guided_video', $enabled2 );
490 499
491 - if ( isset( $_POST['mainwp_managepages_show_columns_settings'] ) ) {
492 - update_user_option( $user->ID, 'mainwp_managepages_show_columns', $show_cols, true );
493 - }
500 + if ( isset( $_POST['mainwp_settings_custom_theme'] ) ) {
501 + $update_selected_mainwp_themes = true;
502 + }
494 503
495 - if ( isset( $_POST['mainwp_manageusers_show_columns_settings'] ) ) {
496 - update_user_option( $user->ID, 'mainwp_manageusers_show_columns', $show_cols, true );
497 - }
498 - }
504 + $new_settings = MainWP_Settings::get_all_settings_values();
499 505
500 - MainWP_Utility::update_option( 'mainwp_hide_update_everything', ( ! isset( $_POST['hide_update_everything'] ) ? 0 : 1 ) );
506 + /**
507 + * Action: mainwp_after_save_settings
508 + *
509 + * Fires after save settings.
510 + *
511 + * @since 6.0
512 + *
513 + * @param array $new_settings The new settings.
514 + * @param array $old_settings The old settings.
515 + */
516 + do_action( 'mainwp_after_save_settings', $new_settings, $old_settings );
517 + $should_redirect = true;
518 + set_transient( 'mainwp_settings_saved', 1, 30 );
519 + }
501 520
502 - if ( isset( $_POST['reset_overview_settings'] ) && ! empty( $_POST['reset_overview_settings'] ) && isset( $_POST['reset_overview_which_settings'] ) && 'overview_settings' === $_POST['reset_overview_which_settings'] ) {
503 - update_user_option( $user->ID, 'mainwp_widgets_sorted_toplevel_page_mainwp_tab', false, true );
504 - update_user_option( $user->ID, 'mainwp_widgets_sorted_mainwp_page_managesites', false, true );
505 - }
506 - }
521 + if ( isset( $_POST['wp_scr_options_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_scr_options_nonce'] ), 'MainWPSelectThemes' ) ) {
522 + $update_selected_mainwp_themes = true;
523 + $should_redirect = true;
524 + set_transient( 'mainwp_settings_saved', 1, 30 );
525 + }
507 526
508 - $update_clients_screen_options = false;
509 - if ( isset( $_POST['wp_scr_options_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_scr_options_nonce'] ), 'MainWPClientsScrOptions' ) ) {
510 - $update_clients_screen_options = true;
511 - }
512 - if ( $update_clients_screen_options ) {
527 + if ( $update_selected_mainwp_themes && isset( $_POST['mainwp_settings_custom_theme'] ) ) {
528 + $custom_theme = sanitize_text_field( wp_unslash( $_POST['mainwp_settings_custom_theme'] ) );
529 + update_user_option( $user->ID, 'mainwp_selected_theme', $custom_theme );
530 + }
513 531
514 - $show_wids = array();
515 - if ( isset( $_POST['mainwp_show_widgets'] ) && is_array( $_POST['mainwp_show_widgets'] ) ) {
516 - $selected_wids = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_show_widgets'] ) );
517 - foreach ( $selected_wids as $name ) {
518 - $show_wids[ $name ] = 1;
519 - }
520 - }
532 + $update_screen_options = false;
533 + if ( isset( $_POST['wp_nonce'] ) && ( wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'Settings' ) || wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MainWPScrOptions' ) ) ) {
534 + $update_screen_options = true;
535 + }
521 536
522 - if ( isset( $_POST['mainwp_widgets_name'] ) && is_array( $_POST['mainwp_widgets_name'] ) ) {
523 - $name_wids = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_widgets_name'] ) );
524 - foreach ( $name_wids as $name ) {
525 - if ( ! isset( $show_wids[ $name ] ) ) {
526 - $show_wids[ $name ] = 0;
527 - }
528 - }
529 - }
537 + if ( $update_screen_options ) {
538 + $show_wids = array();
539 + if ( isset( $_POST['mainwp_show_widgets'] ) && is_array( $_POST['mainwp_show_widgets'] ) ) {
540 + $selected_wids = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_show_widgets'] ) );
541 + foreach ( $selected_wids as $name ) {
542 + $show_wids[ $name ] = 1;
543 + }
544 + }
530 545
531 - if ( $user ) {
532 - update_user_option( $user->ID, 'mainwp_clients_show_widgets', $show_wids, true );
533 - }
546 + if ( isset( $_POST['mainwp_widgets_name'] ) && is_array( $_POST['mainwp_widgets_name'] ) ) {
547 + $name_wids = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_widgets_name'] ) );
548 + foreach ( $name_wids as $name ) {
549 + if ( ! isset( $show_wids[ $name ] ) ) {
550 + $show_wids[ $name ] = 0;
551 + }
552 + }
553 + }
534 554
535 - if ( isset( $_POST['reset_client_overview_settings'] ) && ! empty( $_POST['reset_client_overview_settings'] ) ) {
536 - update_user_option( $user->ID, 'mainwp_widgets_sorted_mainwp_page_manageclients', false, true );
537 - }
538 - }
539 - }
555 + $show_cols = array();
556 + if ( isset( $_POST['mainwp_show_columns'] ) && is_array( $_POST['mainwp_show_columns'] ) ) {
557 + $selected_cols = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_show_columns'] ) );
558 + foreach ( $selected_cols as $name ) {
559 + $show_cols[ $name ] = 1;
560 + }
561 + }
540 562
541 - /**
542 - * Method handle_settings_post()
543 - *
544 - * Handle saving settings page.
545 - *
546 - * @uses \MainWP\Dashboard\MainWP_Backup_Handler::handle_settings_post()
547 - * @uses \MainWP\Dashboard\MainWP_DB_Common::get_user_extension()
548 - * @uses \MainWP\Dashboard\MainWP_DB_Common::update_user_extension()
549 - * @uses \MainWP\Dashboard\MainWP_Monitoring_Handler::handle_settings_post()
550 - * @uses \MainWP\Dashboard\MainWP_Settings::handle_settings_post()
551 - */
552 - public function handle_settings_post() { // phpcs:ignore -- complex method.
563 + if ( isset( $_POST['mainwp_columns_name'] ) && is_array( $_POST['mainwp_columns_name'] ) ) {
564 + $name_cols = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_columns_name'] ) );
565 + foreach ( $name_cols as $name ) {
566 + if ( ! isset( $show_cols[ $name ] ) ) {
567 + $show_cols[ $name ] = 0;
568 + }
569 + }
570 + }
553 571
554 - if ( isset( $_GET['page'] ) && ( isset( $_POST['wp_nonce'] ) || isset( $_POST['wp_scr_options_nonce'] ) ) ) {
555 - $this->include_pluggable();
556 - $this->handle_mainwp_tools_settings();
557 - $this->handle_manage_sites_screen_settings();
558 - $this->handle_monitoring_sites_screen_settings();
559 - $this->handle_clients_screen_settings();
560 - $this->handle_updates_screen_settings();
561 - }
572 + $val = ( isset( $_POST['mainwp_sidebarPosition'] ) ? intval( $_POST['mainwp_sidebarPosition'] ) : 1 );
573 + if ( $user ) {
574 + update_user_option( $user->ID, 'mainwp_settings_show_widgets', $show_wids, true );
575 + update_user_option( $user->ID, 'mainwp_sidebarPosition', $val, true );
562 576
563 - if ( isset( $_POST['select_mainwp_options_siteview'] ) ) {
564 - $this->include_pluggable();
565 - if ( check_admin_referer( 'mainwp-admin-nonce' ) ) {
566 - $userExtension = MainWP_DB_Common::instance()->get_user_extension();
567 - $userExtension->site_view = ( empty( $_POST['select_mainwp_options_siteview'] ) ? MAINWP_VIEW_PER_PLUGIN_THEME : intval( $_POST['select_mainwp_options_siteview'] ) );
568 - MainWP_DB_Common::instance()->update_user_extension( $userExtension );
569 - }
570 - }
577 + if ( isset( $_POST['mainwp_manageposts_show_columns_settings'] ) ) {
578 + update_user_option( $user->ID, 'mainwp_manageposts_show_columns', $show_cols, true );
579 + }
571 580
572 - if ( isset( $_POST['select_mainwp_options_plugintheme_view'] ) ) {
573 - $this->include_pluggable();
574 - if ( check_admin_referer( 'mainwp-admin-nonce' ) ) {
575 - $view_per = ( empty( $_POST['select_mainwp_options_plugintheme_view'] ) ? MAINWP_VIEW_PER_PLUGIN_THEME : intval( $_POST['select_mainwp_options_plugintheme_view'] ) );
576 - $which = isset( $_POST['whichview'] ) ? sanitize_text_field( wp_unslash( $_POST['whichview'] ) ) : '';
577 - if ( 'plugin' === $which ) {
578 - MainWP_Utility::update_user_option( 'mainwp_manage_plugin_view', $view_per );
579 - } else {
580 - MainWP_Utility::update_user_option( 'mainwp_manage_theme_view', $view_per );
581 - }
582 - }
583 - }
581 + if ( isset( $_POST['mainwp_managepages_show_columns_settings'] ) ) {
582 + update_user_option( $user->ID, 'mainwp_managepages_show_columns', $show_cols, true );
583 + }
584 584
585 - if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) ) {
586 - $this->include_pluggable();
587 - if ( wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'Settings' ) ) {
588 - $updated = MainWP_Settings::handle_settings_post();
589 - $updated |= MainWP_Backup_Handler::handle_settings_post();
590 - $updated |= MainWP_Monitoring_Handler::handle_settings_post();
591 - $msg = '';
592 - if ( $updated ) {
593 - $msg = '&message=saved';
594 - }
595 - wp_safe_redirect( admin_url( 'admin.php?page=Settings' . $msg ) );
596 - exit();
597 - }
598 - }
585 + if ( isset( $_POST['mainwp_manageusers_show_columns_settings'] ) ) {
586 + update_user_option( $user->ID, 'mainwp_manageusers_show_columns', $show_cols, true );
587 + }
588 + }
599 589
600 - if ( isset( $_POST['mainwp_sidebar_position'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'onchange_sidebarposition' ) ) {
601 - $val = isset( $_POST['mainwp_sidebar_position'] ) && ! empty( $_POST['mainwp_sidebar_position'] ) ? 1 : 0;
602 - $user = wp_get_current_user();
603 - if ( $user ) {
604 - update_user_option( $user->ID, 'mainwp_sidebarPosition', $val, true );
605 - }
606 - return true;
607 - }
590 + MainWP_Utility::update_option( 'mainwp_hide_update_everything', ( ! isset( $_POST['hide_update_everything'] ) ? 0 : 1 ) );
608 591
609 - if ( isset( $_GET['viewmode'] ) && isset( $_GET['modenonce'] ) ) {
610 - $viewmode = sanitize_text_field( wp_unslash( $_GET['viewmode'] ) );
611 - $nonce = sanitize_key( $_GET['modenonce'] );
612 - if ( ( 'table' === $viewmode || 'grid' === $viewmode ) && wp_verify_nonce( sanitize_key( $nonce ), 'viewmode' ) ) {
613 - $user = wp_get_current_user();
614 - if ( $user ) {
615 - update_user_option( $user->ID, 'mainwp_sitesviewmode', $viewmode, true );
616 - wp_safe_redirect( admin_url( 'admin.php?page=managesites' ) );
617 - exit;
618 - }
619 - }
620 - }
621 - }
592 + if ( isset( $_POST['reset_overview_settings'] ) && ! empty( $_POST['reset_overview_settings'] ) && isset( $_POST['reset_overview_which_settings'] ) && 'overview_settings' === $_POST['reset_overview_which_settings'] ) {
593 + update_user_option( $user->ID, 'mainwp_widgets_sorted_toplevel_page_mainwp_tab', false, true );
594 + update_user_option( $user->ID, 'mainwp_widgets_sorted_mainwp_page_managesites', false, true );
595 + MainWP_Cache_Warm_Helper::invalidate_manage_pages( array( 'mainwp_tab' ) );
596 + }
597 + }
622 598
623 - /**
624 - * Method include_pluggable()
625 - *
626 - * Include pluggable functions.
627 - */
628 - public function include_pluggable() {
629 - // may causing of conflict with Post S m t p plugin.
630 - if ( ! function_exists( 'wp_create_nonce' ) ) {
631 - include_once ABSPATH . WPINC . '/pluggable.php';
632 - }
633 - }
599 + $update_clients_screen_options = false;
600 + if ( isset( $_POST['wp_scr_options_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_scr_options_nonce'] ), 'MainWPClientsScrOptions' ) ) {
601 + $update_clients_screen_options = true;
602 + }
603 + if ( $update_clients_screen_options ) {
634 604
635 - /**
636 - * Method plugins_api_extension_info()
637 - *
638 - * Get MainWP Extension api information.
639 - *
640 - * @param mixed $input_value Return value.
641 - * @param mixed $action Action being performed.
642 - * @param mixed $arg Action arguments. Should be the plugin slug.
643 - *
644 - * @return mixed $info|$input_value
645 - *
646 - * @uses \MainWP\Dashboard\MainWP_API_Handler::get_update_information()
647 - * @uses \MainWP\Dashboard\MainWP_Extensions_View::get_available_extensions()
648 - * @uses \MainWP\Dashboard\MainWP_System::get_plugin_slug()
649 - * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_slugs()
650 - */
651 - public function plugins_api_extension_info( $input_value, $action, $arg ) {
652 - if ( 'plugin_information' !== $action ) {
653 - return $input_value;
654 - }
605 + $show_wids = array();
606 + if ( isset( $_POST['mainwp_show_widgets'] ) && is_array( $_POST['mainwp_show_widgets'] ) ) {
607 + $selected_wids = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_show_widgets'] ) );
608 + foreach ( $selected_wids as $name ) {
609 + $show_wids[ $name ] = 1;
610 + }
611 + }
655 612
656 - if ( is_array( $arg ) ) {
657 - $arg = (object) $arg;
658 - }
613 + if ( isset( $_POST['mainwp_widgets_name'] ) && is_array( $_POST['mainwp_widgets_name'] ) ) {
614 + $name_wids = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_widgets_name'] ) );
615 + foreach ( $name_wids as $name ) {
616 + if ( ! isset( $show_wids[ $name ] ) ) {
617 + $show_wids[ $name ] = 0;
618 + }
619 + }
620 + }
659 621
660 - if ( ! isset( $arg->slug ) || ( '' === $arg->slug ) ) {
661 - return $input_value;
662 - }
622 + if ( $user ) {
623 + update_user_option( $user->ID, 'mainwp_clients_show_widgets', $show_wids, true );
624 + }
663 625
664 - if ( dirname( MainWP_System::instance()->get_plugin_slug() ) === $arg->slug ) {
665 - return $input_value;
666 - }
626 + if ( isset( $_POST['reset_client_overview_settings'] ) && ! empty( $_POST['reset_client_overview_settings'] ) ) {
627 + update_user_option( $user->ID, 'mainwp_widgets_sorted_mainwp_page_manageclients', false, true );
628 + }
629 + }
667 630
668 - $result = MainWP_Extensions_Handler::get_slugs();
669 - $am_slugs = $result['am_slugs'];
631 + // Redirect after save settings and redirect to the same page.
632 + if ( $should_redirect ) {
633 + $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : 'MainWPTools';
634 + wp_safe_redirect( admin_url( 'admin.php?page=' . $page ) );
635 + exit();
636 + }
637 + }
670 638
671 - if ( '' !== $am_slugs ) {
672 - $am_slugs = explode( ',', $am_slugs );
673 - if ( false !== strpos( $arg->slug, '/' ) ) { // to fix.
674 - $dir_slug = dirname( $arg->slug );
675 - } else {
676 - $dir_slug = $arg->slug;
677 - }
678 - if ( in_array( $dir_slug, $am_slugs ) ) {
679 - $info = MainWP_API_Handler::get_update_information( $dir_slug );
680 - if ( is_object( $info ) && property_exists( $info, 'sections' ) ) {
681 - if ( ! is_array( $info->sections ) || ! isset( $info->sections['changelog'] ) || empty( $info->sections['changelog'] ) ) {
682 - $exts_data = MainWP_Extensions_View::get_available_extensions();
683 - if ( isset( $exts_data[ $arg->slug ] ) ) {
684 - $ext_info = $exts_data[ $arg->slug ];
685 - $changelog_link = rtrim( $ext_info['link'], '/' );
686 - $info->sections['changelog'] = '<a href="' . $changelog_link . '#tab-changelog" target="_blank">' . $changelog_link . '#tab-changelog</a>';
687 - }
688 - }
689 - return $info;
690 - }
691 - return $info;
692 - }
693 - }
639 + /**
640 + * Method handle_settings_post()
641 + *
642 + * Handle saving settings page.
643 + *
644 + * @uses \MainWP\Dashboard\MainWP_Backup_Handler::handle_settings_post()
645 + * @uses \MainWP\Dashboard\MainWP_DB_Common::get_user_extension()
646 + * @uses \MainWP\Dashboard\MainWP_DB_Common::update_user_extension()
647 + * @uses \MainWP\Dashboard\MainWP_Monitoring_Handler::handle_settings_post()
648 + * @uses \MainWP\Dashboard\MainWP_Settings::handle_settings_post()
649 + */
650 + public function handle_settings_post() { // phpcs:ignore -- NOSONAR - complex method.
694 651
695 - return $input_value;
696 - }
652 + if ( isset( $_GET['page'] ) && ( isset( $_POST['wp_nonce'] ) || isset( $_POST['wp_scr_options_nonce'] ) ) ) {
653 + $this->include_pluggable();
654 + $this->handle_mainwp_tools_settings();
655 + $this->handle_manage_sites_screen_settings();
656 + $this->handle_monitoring_sites_screen_settings();
657 + $this->handle_clients_screen_settings();
658 + $this->handle_updates_screen_settings();
659 + $this->handle_insights_events_screen_settings();
660 + }
697 661
698 - /**
699 - * Method plugins_api_wp_plugins_api_result()
700 - *
701 - * Hook after get plugins api information.
702 - *
703 - * @param mixed $res api information value.
704 - * @param mixed $action Action being performed.
705 - * @param mixed $arg Action arguments. Should be the plugin slug.
706 - *
707 - * @return mixed $res
708 - */
709 - public function plugins_api_wp_plugins_api_result( $res, $action, $arg ) {
662 + if ( isset( $_POST['select_mainwp_options_siteview'] ) ) {
663 + $this->include_pluggable();
664 + if ( check_admin_referer( 'mainwp-admin-nonce' ) ) {
665 + $userExtension = MainWP_DB_Common::instance()->get_user_extension();
666 + $userExtension->site_view = ( empty( $_POST['select_mainwp_options_siteview'] ) ? MAINWP_VIEW_PER_PLUGIN_THEME : intval( $_POST['select_mainwp_options_siteview'] ) );
667 + MainWP_DB_Common::instance()->update_user_extension( $userExtension );
668 + }
669 + }
710 670
711 - if ( 'plugin_information' !== $action ) {
712 - return $res;
713 - }
671 + if ( isset( $_POST['select_mainwp_options_plugintheme_view'] ) ) {
672 + $this->include_pluggable();
673 + if ( check_admin_referer( 'mainwp-admin-nonce' ) ) {
674 + $view_per = ( empty( $_POST['select_mainwp_options_plugintheme_view'] ) ? MAINWP_VIEW_PER_PLUGIN_THEME : intval( $_POST['select_mainwp_options_plugintheme_view'] ) );
675 + $which = isset( $_POST['whichview'] ) ? sanitize_text_field( wp_unslash( $_POST['whichview'] ) ) : '';
676 + if ( 'plugin' === $which ) {
677 + MainWP_Utility::update_user_option( 'mainwp_manage_plugin_view', $view_per );
678 + } else {
679 + MainWP_Utility::update_user_option( 'mainwp_manage_theme_view', $view_per );
680 + }
681 + }
682 + }
714 683
715 - if ( is_object( $res ) && property_exists( $res, 'slug' ) && property_exists( $res, 'sections' ) ) {
716 - return $res;
717 - }
684 + if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) ) {
685 + $this->include_pluggable();
686 + $nonce = sanitize_key( $_POST['wp_nonce'] );
687 + // Check for both 'Settings' or 'MonitoringSettings' nonces.
688 + $is_valid_nonce = wp_verify_nonce( $nonce, 'Settings' ) || wp_verify_nonce( $nonce, 'MonitoringSettings' );
689 + if ( $is_valid_nonce ) {
690 + $updated = MainWP_Settings::handle_settings_post();
691 + $updated |= MainWP_Backup_Handler::handle_settings_post();
692 + $updated |= MainWP_Monitoring_Handler::handle_settings_post();
693 + $msg = '';
694 + if ( $updated ) {
695 + $msg = '&message=saved';
696 + }
718 697
719 - if ( ! isset( $_GET['wpplugin'] ) || ! is_numeric( $_GET['wpplugin'] ) || empty( $_GET['wpplugin'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
720 - return $res;
721 - }
698 + // Redirect to the correct page based on the nonce.
699 + $url_page = 'admin.php?page=Settings' . $msg;
700 + if ( wp_verify_nonce( $nonce, 'MonitoringSettings' ) ) {
701 + $url_page = 'admin.php?page=MonitoringSettings' . $msg;
702 + }
703 + wp_safe_redirect( admin_url( $url_page ) );
704 + exit();
705 + }
706 + }
722 707
723 - if ( is_array( $arg ) ) {
724 - $arg = (object) $arg;
725 - }
708 + if ( isset( $_POST['mainwp_sidebar_position'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'onchange_sidebarposition' ) ) {
709 + $val = isset( $_POST['mainwp_sidebar_position'] ) && ! empty( $_POST['mainwp_sidebar_position'] ) ? 1 : 0;
710 + $user = wp_get_current_user();
711 + if ( $user ) {
712 + update_user_option( $user->ID, 'mainwp_sidebarPosition', $val, true );
713 + }
714 + return true;
715 + }
726 716
727 - if ( ! isset( $arg->slug ) || ( '' === $arg->slug ) ) {
728 - return $res;
729 - }
717 + if ( isset( $_GET['viewmode'] ) && isset( $_GET['modenonce'] ) ) {
718 + $viewmode = sanitize_text_field( wp_unslash( $_GET['viewmode'] ) );
719 + $nonce = sanitize_key( $_GET['modenonce'] );
720 + if ( ( 'table' === $viewmode || 'grid' === $viewmode ) && wp_verify_nonce( sanitize_key( $nonce ), 'viewmode' ) ) {
721 + $user = wp_get_current_user();
722 + if ( $user ) {
723 + update_user_option( $user->ID, 'mainwp_sitesviewmode', $viewmode, true );
724 + wp_safe_redirect( admin_url( 'admin.php?page=managesites' ) );
725 + exit;
726 + }
727 + }
728 + }
730 729
731 - $site_id = intval( $_GET['wpplugin'] ); // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
730 + // Redirect current page after reset and save overview settings.
731 + if ( isset( $_GET['page'] ) && isset( $_POST['reset_overview_settings'] ) && ( isset( $_POST['reset_overview_which_settings'] ) && 'overview_settings' === $_POST['reset_overview_which_settings'] ) ) {
732 + $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
733 + $url = 'admin.php?page=' . $page;
732 734
733 - if ( $site_id ) {
734 - $website = MainWP_DB::instance()->get_website_by_id( $site_id );
735 - if ( $website && ! empty( $website->plugin_upgrades ) ) {
736 - $plugin_upgrades = json_decode( $website->plugin_upgrades, true );
735 + $dashboard_id = isset( $_GET['dashboard'] ) ? absint( $_GET['dashboard'] ) : 0;
736 + if ( ! empty( $dashboard_id ) ) {
737 + $url .= '&dashboard=' . $dashboard_id;
738 + }
737 739
738 - if ( is_array( $plugin_upgrades ) ) {
739 - $found_update = false;
740 - $empty_sections = false;
741 - foreach ( $plugin_upgrades as $plugin_slug => $info ) {
742 - if ( false !== strpos( $plugin_slug, $arg->slug ) && isset( $info['update'] ) ) {
743 - $found_update = true;
744 - if ( isset( $info['update']['slug'] ) && $arg->slug === $info['update']['slug'] && isset( $info['update']['new_version'] ) && ! empty( $info['update']['new_version'] ) && isset( $info['update']['sections'] ) && ! empty( $info['update']['sections'] ) ) {
745 - $info_update = (object) $info['update'];
746 - $info_update->external = false;
747 - return $info_update;
748 - }
749 - $empty_sections = true;
750 - break;
751 - }
752 - }
740 + wp_safe_redirect( admin_url( $url ) );
741 + exit;
742 + }
743 + }
753 744
754 - if ( $found_update && $empty_sections ) {
755 - try {
756 - $info = MainWP_Connect::fetch_url_authed(
757 - $website,
758 - 'plugin_action',
759 - array(
760 - 'action' => 'changelog_info', // try to get changelog from the child site.
761 - 'slug' => $arg->slug,
762 - )
763 - );
764 - if ( is_array( $info ) && isset( $info['update'] ) && ! empty( $info['update']['sections'] ) ) {
765 - $info_update = (object) $info['update'];
766 - $info_update->external = true;
767 - return $info_update;
768 - }
769 - } catch ( \Exception $e ) {
770 - // error happen.
771 - }
772 - }
773 - }
774 - }
775 - }
745 + /**
746 + * Method include_pluggable()
747 + *
748 + * Include pluggable functions.
749 + */
750 + public function include_pluggable() {
751 + // may causing of conflict with Post S m t p plugin.
752 + if ( ! function_exists( 'wp_create_nonce' ) ) {
753 + include_once ABSPATH . WPINC . '/pluggable.php'; // NOSONAR - WP compatible.
754 + }
755 + }
776 756
777 - return $res;
778 - }
757 + /**
758 + * Method plugins_api_extension_info()
759 + *
760 + * Get MainWP Extension api information.
761 + *
762 + * @param mixed $input_value Return value.
763 + * @param mixed $action Action being performed.
764 + * @param mixed $arg Action arguments. Should be the plugin slug.
765 + *
766 + * @return mixed $info|$input_value
767 + *
768 + * @uses \MainWP\Dashboard\MainWP_API_Handler::get_update_information()
769 + * @uses \MainWP\Dashboard\MainWP_Extensions_View::get_available_extensions()
770 + * @uses \MainWP\Dashboard\MainWP_System::get_plugin_slug()
771 + * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_slugs()
772 + */
773 + public function plugins_api_extension_info( $input_value, $action, $arg ) { // phpcs:ignore -- NOSONAR - complex.
774 + if ( 'plugin_information' !== $action ) {
775 + return $input_value;
776 + }
779 777
780 - /**
781 - * Method check_update_custom()
782 - *
783 - * Check MainWP Extensions for updates.
784 - *
785 - * @param object $transient Transient information.
786 - *
787 - * @return object $transient Transient information.
788 - *
789 - * @uses \MainWP\Dashboard\MainWP_API_Handler::get_upgrade_information()
790 - * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_indexed_extensions_infor()
791 - * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_extension_slug()
792 - * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
793 - */
794 - public function check_update_custom( $transient ) { // phpcs:ignore -- Current complexity is the only way to achieve desired results, pull request solutions appreciated.
795 - if ( isset( $_POST['action'] ) && ( ( 'update-plugin' === $_POST['action'] ) || ( 'update-selected' === $_POST['action'] ) ) && is_object( $transient ) && property_exists( $transient, 'response' ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
796 - $extensions = MainWP_Extensions_Handler::get_indexed_extensions_infor( array( 'activated' => true ) );
797 - if ( defined( 'DOING_AJAX' ) && isset( $_POST['plugin'] ) && 'update-plugin' === $_POST['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
778 + if ( is_array( $arg ) ) {
779 + $arg = (object) $arg;
780 + }
798 781
799 - if ( empty( $transient->response ) ) {
800 - $transient->response = array();
801 - }
782 + if ( ! isset( $arg->slug ) || ( '' === $arg->slug ) ) {
783 + return $input_value;
784 + }
802 785
803 - $plugin_slug = sanitize_text_field( wp_unslash( $_POST['plugin'] ) ); // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
804 - if ( isset( $extensions[ $plugin_slug ] ) ) {
786 + if ( dirname( MainWP_System::instance()->get_plugin_slug() ) === $arg->slug ) {
787 + return $input_value;
788 + }
805 789
806 - if ( ! isset( $transient->response[ $plugin_slug ] ) || ! is_object( $transient->response[ $plugin_slug ] ) || ! property_exists( $transient->response[ $plugin_slug ], 'new_version' ) ) {
807 - return $transient;
808 - }
790 + $result = MainWP_Extensions_Handler::get_slugs();
791 + $am_slugs = $result['am_slugs'];
809 792
810 - if ( isset( $transient->response[ $plugin_slug ] ) && version_compare( $transient->response[ $plugin_slug ]->new_version, $extensions[ $plugin_slug ]['version'], '=' ) ) {
811 - return $transient;
812 - }
793 + if ( '' !== $am_slugs ) {
794 + $am_slugs = explode( ',', $am_slugs );
795 + if ( false !== strpos( $arg->slug, '/' ) ) { // to fix.
796 + $dir_slug = dirname( $arg->slug );
797 + } else {
798 + $dir_slug = $arg->slug;
799 + }
800 + if ( in_array( $dir_slug, $am_slugs ) ) {
801 + $info = MainWP_API_Handler::get_update_information( $dir_slug );
802 + if ( is_object( $info ) && property_exists( $info, 'sections' ) ) {
803 + if ( ! is_array( $info->sections ) || ! isset( $info->sections['changelog'] ) || empty( $info->sections['changelog'] ) ) {
804 + $exts_data = MainWP_Extensions_View::get_available_extensions();
805 + if ( isset( $exts_data[ $arg->slug ] ) ) {
806 + $ext_info = $exts_data[ $arg->slug ];
807 + $changelog_link = rtrim( $ext_info['changelog_url'], '/' );
808 + $info->sections['changelog'] = '<a href="' . $changelog_link . '" target="_blank">' . $changelog_link . '</a>';
809 + }
810 + }
811 + return $info;
812 + }
813 + return $info;
814 + }
815 + }
813 816
814 - $api_slug = dirname( $plugin_slug );
815 - $rslt = MainWP_API_Handler::get_upgrade_information( $api_slug );
817 + return $input_value;
818 + }
816 819
817 - if ( ! empty( $rslt ) && is_object( $rslt ) && property_exists( $rslt, 'new_version' ) && ! empty( $rslt->new_version ) && version_compare( $rslt->new_version, $extensions[ $plugin_slug ]['version'], '>' ) ) {
818 - $transient->response[ $plugin_slug ] = self::map_rslt_obj( $rslt );
819 - }
820 + /**
821 + * Method plugins_api_wp_plugins_api_result()
822 + *
823 + * Hook after get plugins api information.
824 + *
825 + * @param mixed $res api information value.
826 + * @param mixed $action Action being performed.
827 + * @param mixed $arg Action arguments. Should be the plugin slug.
828 + *
829 + * @return mixed $res
830 + */
831 + public function plugins_api_wp_plugins_api_result( $res, $action, $arg ) { // phpcs:ignore -- NOSONAR - complex.
820 832
821 - return $transient;
822 - }
823 - } elseif ( 'update-selected' === $_POST['action'] && isset( $_POST['checked'] ) && is_array( $_POST['checked'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
833 + if ( 'plugin_information' !== $action ) {
834 + return $res;
835 + }
824 836
825 - if ( empty( $transient->response ) ) {
826 - $transient->response = array();
827 - }
837 + if ( is_object( $res ) && property_exists( $res, 'slug' ) && property_exists( $res, 'sections' ) ) {
838 + return $res;
839 + }
828 840
829 - $updated = false;
830 - foreach ( wp_unslash( $_POST['checked'] ) as $plugin_slug ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
831 - if ( isset( $extensions[ $plugin_slug ] ) ) {
841 + if ( ! isset( $_GET['wpplugin'] ) || ! is_numeric( $_GET['wpplugin'] ) || empty( $_GET['wpplugin'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
842 + return $res;
843 + }
832 844
833 - if ( ! isset( $transient->response[ $plugin_slug ] ) ) {
834 - $transient->response[ $plugin_slug ] = new \stdClass();
835 - }
845 + if ( is_array( $arg ) ) {
846 + $arg = (object) $arg;
847 + }
836 848
837 - if ( isset( $transient->response[ $plugin_slug ] ) && version_compare( $transient->response[ $plugin_slug ]->new_version, $extensions[ $plugin_slug ]['version'], '=' ) ) {
838 - continue;
839 - }
840 - $api_slug = dirname( $plugin_slug );
841 - $rslt = MainWP_API_Handler::get_upgrade_information( $api_slug );
842 - if ( ! empty( $rslt ) && is_object( $rslt ) && property_exists( $rslt, 'new_version' ) && ! empty( $rslt->new_version ) && version_compare( $rslt->new_version, $extensions[ $plugin_slug ]['version'], '>' ) ) {
843 - $this->upgradeVersionInfo->result[ $api_slug ] = $rslt;
844 - $transient->response[ $plugin_slug ] = self::map_rslt_obj( $rslt );
845 - $updated = true;
846 - }
847 - }
848 - }
849 - if ( $updated ) {
850 - MainWP_Utility::update_option( 'mainwp_upgradeVersionInfo', $this->upgradeVersionInfo );
851 - }
849 + if ( ! isset( $arg->slug ) || ( '' === $arg->slug ) ) {
850 + return $res;
851 + }
852 852
853 - return $transient;
854 - }
855 - }
853 + $site_id = intval( $_GET['wpplugin'] ); // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
856 854
857 - if ( empty( $transient->checked ) ) {
858 - return $transient;
859 - }
855 + if ( $site_id ) {
856 + $website = MainWP_DB::instance()->get_website_by_id( $site_id );
857 + if ( $website && ! empty( $website->plugin_upgrades ) ) {
858 + $plugin_upgrades = json_decode( $website->plugin_upgrades, true );
860 859
861 - if ( ! empty( $this->upgradeVersionInfo ) && property_exists( $this->upgradeVersionInfo, 'result' ) && is_array( $this->upgradeVersionInfo->result ) ) {
862 - foreach ( $this->upgradeVersionInfo->result as $rslt ) {
863 - if ( ! isset( $rslt->slug ) ) {
864 - continue;
865 - }
860 + if ( is_array( $plugin_upgrades ) ) {
861 + $found_update = false;
862 + $empty_sections = false;
863 + foreach ( $plugin_upgrades as $plugin_slug => $info ) {
864 + if ( false !== strpos( $plugin_slug, $arg->slug ) && isset( $info['update'] ) ) {
865 + $found_update = true;
866 + if ( isset( $info['update']['slug'] ) && $arg->slug === $info['update']['slug'] && isset( $info['update']['new_version'] ) && ! empty( $info['update']['new_version'] ) && isset( $info['update']['sections'] ) && ! empty( $info['update']['sections'] ) ) {
867 + $info_update = (object) $info['update'];
868 + $info_update->external = false;
869 + return $info_update;
870 + }
871 + $empty_sections = true;
872 + break;
873 + }
874 + }
866 875
867 - $plugin_slug = MainWP_Extensions_Handler::get_extension_slug( $rslt->slug );
868 - if ( isset( $transient->checked[ $plugin_slug ] ) && property_exists( $rslt, 'new_version' ) && ! empty( $rslt->new_version ) && version_compare( $rslt->new_version, $transient->checked[ $plugin_slug ], '>' ) ) {
869 - $transient->response[ $plugin_slug ] = self::map_rslt_obj( $rslt );
870 - }
871 - }
872 - }
876 + if ( $found_update && $empty_sections ) {
877 + try {
878 + $info = MainWP_Connect::fetch_url_authed(
879 + $website,
880 + 'plugin_action',
881 + array(
882 + 'action' => 'changelog_info', // try to get changelog from the child site.
883 + 'slug' => $arg->slug,
884 + )
885 + );
886 + if ( is_array( $info ) && isset( $info['update'] ) && ! empty( $info['update']['sections'] ) ) {
887 + $info_update = (object) $info['update'];
888 + $info_update->external = true;
889 + return $info_update;
890 + }
891 + } catch ( \Exception $e ) {
892 + // error happen.
893 + }
894 + }
895 + }
896 + }
897 + }
873 898
874 - return $transient;
875 - }
899 + return $res;
900 + }
876 901
902 + /**
903 + * Method check_update_custom()
904 + *
905 + * Check MainWP Extensions for updates.
906 + *
907 + * @param object $transient Transient information.
908 + *
909 + * @return object $transient Transient information.
910 + *
911 + * @uses \MainWP\Dashboard\MainWP_API_Handler::get_upgrade_information()
912 + * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_indexed_extensions_infor()
913 + * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_extension_slug()
914 + * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
915 + */
916 + public function check_update_custom( $transient ) { // phpcs:ignore -- NOSONAR -Current complexity is the only way to achieve desired results, pull request solutions appreciated.
917 + if ( isset( $_POST['action'] ) && ( ( 'update-plugin' === $_POST['action'] ) || ( 'update-selected' === $_POST['action'] ) ) && is_object( $transient ) && property_exists( $transient, 'response' ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
918 + $extensions = MainWP_Extensions_Handler::get_indexed_extensions_infor( array( 'activated' => true ) );
919 + if ( defined( 'DOING_AJAX' ) && isset( $_POST['plugin'] ) && 'update-plugin' === $_POST['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
877 920
878 - /**
879 - * Method map_rslt_obj()
880 - *
881 - * Map resulting object.
882 - *
883 - * @param object $result Resulting information.
884 - *
885 - * @return object $obj Mapped resulting object.
886 - */
887 - public static function map_rslt_obj( $result ) {
888 - $obj = new \stdClass();
889 - $obj->slug = $result->slug;
890 - $obj->new_version = $result->new_version;
891 - $obj->url = 'https://mainwp.com/';
892 - $obj->package = $result->package;
921 + if ( empty( $transient->response ) ) {
922 + $transient->response = array();
923 + }
893 924
894 - return $obj;
895 - }
925 + $plugin_slug = sanitize_text_field( wp_unslash( $_POST['plugin'] ) ); // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
926 + if ( isset( $extensions[ $plugin_slug ] ) ) {
896 927
897 - /**
898 - * Method check_upgrade()
899 - *
900 - * Check if Extension has an update.
901 - *
902 - * @uses \MainWP\Dashboard\MainWP_API_Handler::check_exts_upgrade()
903 - * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
904 - */
905 - private function check_upgrade() {
906 - $result = MainWP_API_Handler::check_exts_upgrade();
907 - if ( null === $this->upgradeVersionInfo ) {
908 - $this->upgradeVersionInfo = new \stdClass();
909 - }
910 - $this->upgradeVersionInfo->updated = time();
911 - if ( ! empty( $result ) ) {
912 - $this->upgradeVersionInfo->result = $result;
913 - }
914 - MainWP_Utility::update_option( 'mainwp_upgradeVersionInfo', $this->upgradeVersionInfo );
915 - }
928 + if ( ! isset( $transient->response[ $plugin_slug ] ) || ! is_object( $transient->response[ $plugin_slug ] ) || ! property_exists( $transient->response[ $plugin_slug ], 'new_version' ) ) {
929 + return $transient;
930 + }
916 931
917 - /**
918 - * Method pre_check_update_custom()
919 - *
920 - * Pre-check for extension updates.
921 - *
922 - * @param object $transient Transient information.
923 - *
924 - * @return object $transient Transient information.
925 - *
926 - * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_indexed_extensions_infor()
927 - * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_extension_slug()
928 - */
929 - public function pre_check_update_custom( $transient ) {
930 - if ( ! isset( $transient->checked ) ) {
931 - return $transient;
932 - }
932 + if ( isset( $transient->response[ $plugin_slug ] ) && version_compare( $transient->response[ $plugin_slug ]->new_version, $extensions[ $plugin_slug ]['version'], '=' ) ) {
933 + return $transient;
934 + }
933 935
934 - if ( ( null === $this->upgradeVersionInfo ) || ! property_exists( $this->upgradeVersionInfo, 'updated' ) || ( ( time() - $this->upgradeVersionInfo->updated ) > 60 ) ) {
935 - $this->check_upgrade();
936 - }
936 + $api_slug = dirname( $plugin_slug );
937 + $rslt = MainWP_API_Handler::get_upgrade_information( $api_slug );
937 938
938 - if ( empty( $transient->response ) ) {
939 - $transient->response = array();
940 - }
939 + if ( ! empty( $rslt ) && is_object( $rslt ) && property_exists( $rslt, 'new_version' ) && ! empty( $rslt->new_version ) && version_compare( $rslt->new_version, $extensions[ $plugin_slug ]['version'], '>' ) ) {
940 + $transient->response[ $plugin_slug ] = static::map_rslt_obj( $rslt );
941 + }
941 942
942 - if ( ! empty( $this->upgradeVersionInfo ) && property_exists( $this->upgradeVersionInfo, 'result' ) && is_array( $this->upgradeVersionInfo->result ) ) {
943 - $extensions = MainWP_Extensions_Handler::get_indexed_extensions_infor( array( 'activated' => true ) );
944 - foreach ( $this->upgradeVersionInfo->result as $rslt ) {
945 - $plugin_slug = MainWP_Extensions_Handler::get_extension_slug( $rslt->slug );
946 - if ( isset( $extensions[ $plugin_slug ] ) && property_exists( $rslt, 'new_version' ) && ! empty( $rslt->new_version ) && version_compare( $rslt->new_version, $extensions[ $plugin_slug ]['version'], '>' ) ) {
947 - $transient->response[ $plugin_slug ] = self::map_rslt_obj( $rslt );
948 - }
949 - }
950 - }
943 + return $transient;
944 + }
945 + } elseif ( 'update-selected' === $_POST['action'] && isset( $_POST['checked'] ) && is_array( $_POST['checked'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
951 946
952 - return $transient;
953 - }
947 + if ( empty( $transient->response ) ) {
948 + $transient->response = array();
949 + }
954 950
955 - /**
956 - * Method upload_file()
957 - *
958 - * Upload a file.
959 - *
960 - * @param mixed $file File to upload.
961 - *
962 - * @return void
963 - *
964 - * @uses \MainWP\Dashboard\MainWP_Utility::ends_with()
965 - */
966 - public function upload_file( $file ) {
967 - header( 'Content-Description: File Transfer' );
968 - if ( MainWP_Utility::ends_with( $file, '.tar.gz' ) ) {
969 - header( 'Content-Type: application/x-gzip' );
970 - header( 'Content-Encoding: gzip' );
971 - } else {
972 - header( 'Content-Type: application/octet-stream' );
973 - }
974 - header( 'Content-Disposition: attachment; filename="' . basename( $file ) . '"' );
975 - header( 'Expires: 0' );
976 - header( 'Cache-Control: must-revalidate' );
977 - header( 'Pragma: public' );
978 - header( 'Content-Length: ' . filesize( $file ) );
979 - while ( ob_get_level() ) {
980 - ob_end_clean();
981 - }
982 - $this->readfile_chunked( $file );
983 - exit();
984 - }
951 + $updated = false;
952 + foreach ( wp_unslash( $_POST['checked'] ) as $plugin_slug ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
953 + if ( isset( $extensions[ $plugin_slug ] ) ) {
985 954
986 - /**
987 - * Method readfile_chunked()
988 - *
989 - * Read Chunked File.
990 - *
991 - * @param mixed $filename Name of file.
992 - *
993 - * @return mixed echo $buffer|false|$handle.
994 - */
995 - public function readfile_chunked( $filename ) {
996 - $chunksize = 1024;
997 - $handle = fopen( $filename, 'rb' );
998 - if ( false === $handle ) {
999 - return false;
1000 - }
955 + if ( ! isset( $transient->response[ $plugin_slug ] ) ) {
956 + $transient->response[ $plugin_slug ] = new \stdClass();
957 + }
1001 958
1002 - while ( ! feof( $handle ) ) {
1003 - $buffer = fread( $handle, $chunksize );
1004 - echo $buffer; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1005 - if ( ob_get_length() ) {
1006 - ob_flush();
1007 - flush();
1008 - }
1009 - $buffer = null;
1010 - }
959 + if ( isset( $transient->response[ $plugin_slug ] ) && version_compare( $transient->response[ $plugin_slug ]->new_version, $extensions[ $plugin_slug ]['version'], '=' ) ) {
960 + continue;
961 + }
962 + $api_slug = dirname( $plugin_slug );
963 + $rslt = MainWP_API_Handler::get_upgrade_information( $api_slug );
964 + if ( ! empty( $rslt ) && is_object( $rslt ) && property_exists( $rslt, 'new_version' ) && ! empty( $rslt->new_version ) && version_compare( $rslt->new_version, $extensions[ $plugin_slug ]['version'], '>' ) ) {
965 + $this->upgradeVersionInfo->result[ $api_slug ] = $rslt;
966 + $transient->response[ $plugin_slug ] = static::map_rslt_obj( $rslt );
967 + $updated = true;
968 + }
969 + }
970 + }
971 + if ( $updated ) {
972 + MainWP_Utility::update_option( 'mainwp_upgradeVersionInfo', $this->upgradeVersionInfo );
973 + }
1011 974
1012 - return fclose( $handle );
1013 - }
975 + return $transient;
976 + }
977 + }
1014 978
1015 - /**
1016 - * Method activate_redirection()
1017 - *
1018 - * Redirect after activating MainWP Extension.
1019 - *
1020 - * @param mixed $location Location to redirect to.
1021 - *
1022 - * @return $location Admin URL + the page to redirect to.
1023 - */
1024 - public function activate_redirect( $location ) {
1025 - $location = admin_url( 'admin.php?page=Extensions' );
1026 - return $location;
1027 - }
979 + if ( empty( $transient->checked ) ) {
980 + return $transient;
981 + }
1028 982
1029 - /**
1030 - * Method activate_extension()
1031 - *
1032 - * Activate MainWP Extension.
1033 - *
1034 - * @param mixed $ext_key Extension API Key.
1035 - * @param array $info Extension Info.
1036 - *
1037 - * @uses \MainWP\Dashboard\MainWP_Api_Manager::set_activation_info()
1038 - * @uses \MainWP\Dashboard\MainWP_Api_Manager_Password_Management::generate_password()
1039 - */
1040 - public function activate_extension( $ext_key, $info = array() ) {
983 + if ( ! empty( $this->upgradeVersionInfo ) && property_exists( $this->upgradeVersionInfo, 'result' ) && is_array( $this->upgradeVersionInfo->result ) ) {
984 + foreach ( $this->upgradeVersionInfo->result as $rslt ) {
985 + if ( ! isset( $rslt->slug ) ) {
986 + continue;
987 + }
1041 988
1042 - add_filter( 'wp_redirect', array( $this, 'activate_redirect' ) );
989 + $plugin_slug = MainWP_Extensions_Handler::get_extension_slug( $rslt->slug );
990 + if ( isset( $transient->checked[ $plugin_slug ] ) && property_exists( $rslt, 'new_version' ) && ! empty( $rslt->new_version ) && version_compare( $rslt->new_version, $transient->checked[ $plugin_slug ], '>' ) ) {
991 + $transient->response[ $plugin_slug ] = static::map_rslt_obj( $rslt );
992 + }
993 + }
994 + }
1043 995
1044 - if ( is_array( $info ) && isset( $info['product_id'] ) && isset( $info['software_version'] ) ) {
1045 - $act_info = array(
1046 - 'product_id' => $info['product_id'],
1047 - 'software_version' => $info['software_version'],
1048 - 'activated_key' => 'Deactivated',
1049 - 'instance_id' => MainWP_Api_Manager_Password_Management::generate_password( 12, false ),
1050 - );
1051 - MainWP_Api_Manager::instance()->set_activation_info( $ext_key, $act_info );
1052 - }
1053 - }
996 + return $transient;
997 + }
1054 998
1055 - /**
1056 - * Method deactivate_extension()
1057 - *
1058 - * Deactivate MaiNWP Extension.
1059 - *
1060 - * @param mixed $ext_key Exnension API Key.
1061 - *
1062 - * @uses \MainWP\Dashboard\MainWP_Api_Manager::set_activation_info()
1063 - */
1064 - public function deactivate_extension( $ext_key ) {
1065 - // try to deactivate license.
1066 - $mainwp_api_key = MainWP_Api_Manager_Key::instance()->get_decrypt_master_api_key();
1067 - $result = MainWP_Api_Manager::instance()->license_key_deactivation( $ext_key, $mainwp_api_key );
1068 999
1069 - MainWP_Api_Manager::instance()->remove_activation_info( $ext_key );
1070 - }
1000 + /**
1001 + * Method map_rslt_obj()
1002 + *
1003 + * Map resulting object.
1004 + *
1005 + * @param object $result Resulting information.
1006 + *
1007 + * @return object $obj Mapped resulting object.
1008 + */
1009 + public static function map_rslt_obj( $result ) {
1010 + $obj = new \stdClass();
1011 + $obj->slug = $result->slug;
1012 + $obj->new_version = $result->new_version;
1013 + $obj->url = 'https://mainwp.com/';
1014 + $obj->package = $result->package;
1015 +
1016 + return $obj;
1017 + }
1018 +
1019 + /**
1020 + * Method check_upgrade()
1021 + *
1022 + * Check if Extension has an update.
1023 + *
1024 + * @uses \MainWP\Dashboard\MainWP_API_Handler::check_exts_upgrade()
1025 + * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
1026 + */
1027 + private function check_upgrade() { // phpcs:ignore -- NOSONAR - validates and preserves per-extension update state.
1028 + $expected_extensions = $this->get_expected_extension_updates();
1029 + $has_full_scope = $this->has_full_extension_update_scope( $expected_extensions );
1030 +
1031 + if ( null === $this->upgradeVersionInfo ) {
1032 + $this->upgradeVersionInfo = new \stdClass();
1033 + }
1034 +
1035 + $this->upgradeVersionInfo->updated = time();
1036 +
1037 + if ( empty( $expected_extensions ) ) {
1038 + if ( $has_full_scope ) {
1039 + $this->clear_extension_update_failure();
1040 + }
1041 + MainWP_Utility::update_option( 'mainwp_upgradeVersionInfo', $this->upgradeVersionInfo );
1042 + return $has_full_scope;
1043 + }
1044 +
1045 + $result = MainWP_API_Handler::check_exts_upgrade();
1046 + $previous_result = property_exists( $this->upgradeVersionInfo, 'result' ) && is_array( $this->upgradeVersionInfo->result ) ? $this->upgradeVersionInfo->result : array();
1047 + $fresh_result = array();
1048 + $failed = ! is_array( $result );
1049 +
1050 + foreach ( $expected_extensions as $api_slug => $installed_version ) {
1051 + $fresh = is_array( $result ) && isset( $result[ $api_slug ] ) ? $result[ $api_slug ] : null;
1052 + if ( $this->is_usable_extension_update_result( $fresh, $api_slug, $installed_version ) ) {
1053 + $fresh_result[ $api_slug ] = $fresh;
1054 + } else {
1055 + $failed = true;
1056 + }
1057 + }
1058 +
1059 + if ( ! $failed ) {
1060 + $this->upgradeVersionInfo->result = $has_full_scope ? $fresh_result : array_merge( $previous_result, $fresh_result );
1061 + }
1062 +
1063 + if ( $has_full_scope ) {
1064 + if ( $failed ) {
1065 + $this->record_extension_update_failure();
1066 + } else {
1067 + $this->clear_extension_update_failure();
1068 + }
1069 + }
1070 +
1071 + MainWP_Utility::update_option( 'mainwp_upgradeVersionInfo', $this->upgradeVersionInfo );
1072 + return ! $failed;
1073 + }
1074 +
1075 + /**
1076 + * Get Add-ons expected in an update-check response.
1077 + *
1078 + * @return array API slugs keyed to installed versions.
1079 + */
1080 + private function get_expected_extension_updates() {
1081 + $expected = array();
1082 +
1083 + foreach ( MainWP_Extensions_Handler::get_extensions() as $extension ) {
1084 + if ( ! isset( $extension['activated_key'] ) || 'Activated' !== $extension['activated_key'] || empty( $extension['api'] ) ) {
1085 + continue;
1086 + }
1087 +
1088 + $expected[ $extension['api'] ] = isset( $extension['version'] ) ? (string) $extension['version'] : '';
1089 + }
1090 +
1091 + return $expected;
1092 + }
1093 +
1094 + /**
1095 + * Check whether visible Add-ons cover the shared update cache.
1096 + *
1097 + * @param array $expected Visible Add-ons expected in the response.
1098 + *
1099 + * @return bool Whether this request covers every activated Add-on.
1100 + */
1101 + private function has_full_extension_update_scope( $expected ) {
1102 + $all_expected = array();
1103 +
1104 + foreach ( get_option( 'mainwp_extensions', array() ) as $extension ) {
1105 + if ( isset( $extension['activated_key'], $extension['api'] ) && 'Activated' === $extension['activated_key'] && '' !== $extension['api'] ) {
1106 + $all_expected[] = $extension['api'];
1107 + }
1108 + }
1109 +
1110 + $visible = array_keys( $expected );
1111 + sort( $all_expected );
1112 + sort( $visible );
1113 +
1114 + return $all_expected === $visible;
1115 + }
1116 +
1117 + /**
1118 + * Check whether an Add-on update result is safe to persist.
1119 + *
1120 + * @param mixed $result Update result.
1121 + * @param string $api_slug Expected API slug.
1122 + * @param string $installed_version Installed Add-on version.
1123 + *
1124 + * @return bool Whether the result is usable.
1125 + */
1126 + private function is_usable_extension_update_result( $result, $api_slug, $installed_version ) {
1127 + if ( ! is_object( $result ) || ! isset( $result->slug ) || $api_slug !== $result->slug || ! property_exists( $result, 'new_version' ) || ! is_string( $result->new_version ) ) {
1128 + return false;
1129 + }
1130 +
1131 + $new_version = trim( $result->new_version );
1132 + if ( '' === $new_version || ( property_exists( $result, 'error' ) && ! empty( $result->error ) ) ) {
1133 + return false;
1134 + }
1135 +
1136 + if ( version_compare( $new_version, $installed_version, '>' ) ) {
1137 + return property_exists( $result, 'package' ) && is_string( $result->package ) && '' !== trim( $result->package );
1138 + }
1139 +
1140 + return true;
1141 + }
1142 +
1143 + /**
1144 + * Record a failed Add-on update-check attempt.
1145 + */
1146 + private function record_extension_update_failure() {
1147 + $failure_count = property_exists( $this->upgradeVersionInfo, 'extension_update_failure_count' ) ? (int) $this->upgradeVersionInfo->extension_update_failure_count : 0;
1148 +
1149 + if ( $failure_count < 1 || ! property_exists( $this->upgradeVersionInfo, 'extension_update_failure_episode' ) || empty( $this->upgradeVersionInfo->extension_update_failure_episode ) ) {
1150 + $this->upgradeVersionInfo->extension_update_failure_episode = wp_generate_uuid4();
1151 + }
1152 +
1153 + $this->upgradeVersionInfo->extension_update_failure_count = $failure_count + 1;
1154 + }
1155 +
1156 + /**
1157 + * Clear Add-on update-check failure state after a complete response.
1158 + */
1159 + private function clear_extension_update_failure() {
1160 + unset( $this->upgradeVersionInfo->extension_update_failure_count, $this->upgradeVersionInfo->extension_update_failure_episode );
1161 + }
1162 +
1163 + /**
1164 + * Get the active repeated-failure notice ID.
1165 + *
1166 + * @return string Notice ID, or an empty string before the second consecutive failure.
1167 + */
1168 + public function get_extension_update_failure_notice_id() {
1169 + if ( ! $this->has_full_extension_update_scope( $this->get_expected_extension_updates() ) || ! is_object( $this->upgradeVersionInfo ) || ! property_exists( $this->upgradeVersionInfo, 'extension_update_failure_count' ) || 2 > (int) $this->upgradeVersionInfo->extension_update_failure_count || ! property_exists( $this->upgradeVersionInfo, 'extension_update_failure_episode' ) ) {
1170 + return '';
1171 + }
1172 +
1173 + $episode = sanitize_key( $this->upgradeVersionInfo->extension_update_failure_episode );
1174 + return '' !== $episode ? 'mainwp-extension-update-check-failure-' . $episode : '';
1175 + }
1176 +
1177 + /**
1178 + * Retry the Add-on update check and refresh WordPress update data.
1179 + *
1180 + * @return bool Whether every expected Add-on returned a usable result.
1181 + */
1182 + public function retry_extension_update_check() {
1183 + $success = $this->check_upgrade();
1184 + delete_site_transient( 'update_plugins' );
1185 + return $success;
1186 + }
1187 +
1188 + /**
1189 + * Method pre_check_update_custom()
1190 + *
1191 + * Pre-check for extension updates.
1192 + *
1193 + * @param object $transient Transient information.
1194 + *
1195 + * @return object $transient Transient information.
1196 + *
1197 + * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_indexed_extensions_infor()
1198 + * @uses \MainWP\Dashboard\MainWP_Extensions_Handler::get_extension_slug()
1199 + */
1200 + public function pre_check_update_custom( $transient ) {
1201 + if ( ! isset( $transient->checked ) ) {
1202 + return $transient;
1203 + }
1204 +
1205 + if ( defined( 'MAINWP_PLUGIN_UPGRADING' ) && true === MAINWP_PLUGIN_UPGRADING ) {
1206 + return $transient;
1207 + }
1208 +
1209 + MainWP_Logger::instance()->log_events( 'extension-updates-check', 'pre_set_site_transient_update_plugins' );
1210 +
1211 + if ( ( null === $this->upgradeVersionInfo ) || ! property_exists( $this->upgradeVersionInfo, 'updated' ) || ( ( time() - $this->upgradeVersionInfo->updated ) > 60 ) ) {
1212 + $this->check_upgrade();
1213 + }
1214 +
1215 + if ( empty( $transient->response ) ) {
1216 + $transient->response = array();
1217 + }
1218 +
1219 + if ( ! empty( $this->upgradeVersionInfo ) && property_exists( $this->upgradeVersionInfo, 'result' ) && is_array( $this->upgradeVersionInfo->result ) ) {
1220 + $extensions = MainWP_Extensions_Handler::get_indexed_extensions_infor( array( 'activated' => true ) );
1221 + foreach ( $this->upgradeVersionInfo->result as $rslt ) {
1222 + $plugin_slug = MainWP_Extensions_Handler::get_extension_slug( $rslt->slug );
1223 + if ( isset( $extensions[ $plugin_slug ] ) && property_exists( $rslt, 'new_version' ) && ! empty( $rslt->new_version ) && version_compare( $rslt->new_version, $extensions[ $plugin_slug ]['version'], '>' ) ) {
1224 + $transient->response[ $plugin_slug ] = static::map_rslt_obj( $rslt );
1225 + }
1226 + }
1227 + }
1228 +
1229 + return $transient;
1230 + }
1231 +
1232 + /**
1233 + * Method hook_refresh_trusted_extension_package_url
1234 + *
1235 + * @param mixed $reply The reply from the upgrader.
1236 + * @param mixed $package The package URL.
1237 + * @param mixed $upgrader The upgrader instance.
1238 + * @param mixed $hook_extra Extra information about the upgrade, including the plugin being updated.
1239 + * @return void
1240 + */
1241 + public function hook_refresh_trusted_extension_package_url( $reply, $package, $upgrader, $hook_extra ) {
1242 + if ( isset( $hook_extra['plugin'] ) ) { // && isset( $_POST['mainwpsignature'] ) && isset( $_POST['function'] ) && 'upgradeplugintheme' === $_POST['function'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- NOSONAR - hook for plugin update action, it is safe to use $_POST here.
1243 + $ext_api_slug = dirname( $hook_extra['plugin'] );
1244 + if ( ! empty( $ext_api_slug ) ) {
1245 + $rslt_info = MainWP_API_Handler::get_upgrade_information( $ext_api_slug );
1246 + if ( ! empty( $rslt_info ) && is_object( $rslt_info ) && property_exists( $rslt_info, 'package' ) && ! empty( $rslt_info->package ) ) {
1247 + // Replace package URL.
1248 + $upgrader->skin->options['package'] = $rslt_info->package;
1249 + unset( $package );
1250 + }
1251 + }
1252 + }
1253 + return $reply;
1254 + }
1255 +
1256 +
1257 + /**
1258 + * Method upload_file()
1259 + *
1260 + * Upload a file.
1261 + *
1262 + * @param mixed $file File to upload.
1263 + *
1264 + * @return void
1265 + *
1266 + * @uses \MainWP\Dashboard\MainWP_Utility::ends_with()
1267 + */
1268 + public function upload_file( $file ) {
1269 + header( 'Content-Description: File Transfer' );
1270 + $dwl_fname = basename( $file );
1271 + if ( 'tar.gz' === $dwl_fname || '.tar.gz' === $dwl_fname ) {
1272 + $dwl_fname = 'noname.tar.gz'; // to fix name of zip file.
1273 + }
1274 + header( 'Content-Type: application/octet-stream' );
1275 + header( 'Content-Disposition: attachment; filename="' . $dwl_fname . '"' );
1276 + header( 'Expires: 0' );
1277 + header( 'Cache-Control: must-revalidate' );
1278 + header( 'Pragma: public' );
1279 + header( 'Content-Length: ' . filesize( $file ) );
1280 + while ( ob_get_level() ) {
1281 + ob_end_clean();
1282 + }
1283 + $this->readfile_chunked( $file );
1284 + exit();
1285 + }
1286 +
1287 + /**
1288 + * Method readfile_chunked()
1289 + *
1290 + * Read Chunked File.
1291 + *
1292 + * @param mixed $filename Name of file.
1293 + *
1294 + * @return mixed echo $buffer|false|$handle.
1295 + */
1296 + public function readfile_chunked( $filename ) {
1297 + $chunksize = 1024;
1298 + $handle = fopen( $filename, 'rb' );
1299 + if ( false === $handle ) {
1300 + return false;
1301 + }
1302 +
1303 + while ( ! feof( $handle ) ) {
1304 + $buffer = fread( $handle, $chunksize );
1305 + echo $buffer; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1306 + if ( ob_get_length() ) {
1307 + ob_flush();
1308 + flush();
1309 + }
1310 + $buffer = null;
1311 + }
1312 +
1313 + return fclose( $handle );
1314 + }
1315 +
1316 + /**
1317 + * Method activate_redirection()
1318 + *
1319 + * Redirect after activating MainWP Extension.
1320 + *
1321 + * @param mixed $location Location to redirect to.
1322 + *
1323 + * @return $location Admin URL + the page to redirect to.
1324 + */
1325 + public function activate_redirect( $location ) {
1326 + unset( $location );
1327 + return admin_url( 'admin.php?page=Extensions' );
1328 + }
1329 +
1330 + /**
1331 + * Method activate_extension()
1332 + *
1333 + * Activate MainWP Extension.
1334 + *
1335 + * @param mixed $ext_key Extension API Key.
1336 + * @param array $info Extension Info.
1337 + *
1338 + * @uses \MainWP\Dashboard\MainWP_Api_Manager::set_activation_info()
1339 + * @uses \MainWP\Dashboard\MainWP_Api_Manager_Password_Management::generate_password()
1340 + */
1341 + public function activate_extension( $ext_key, $info = array() ) {
1342 +
1343 + add_filter( 'wp_redirect', array( $this, 'activate_redirect' ) );
1344 +
1345 + if ( is_array( $info ) && isset( $info['product_id'] ) && isset( $info['software_version'] ) ) {
1346 + $act_info = array(
1347 + 'product_id' => $info['product_id'],
1348 + 'software_version' => $info['software_version'],
1349 + 'activated_key' => 'Deactivated',
1350 + 'instance_id' => MainWP_Api_Manager_Password_Management::generate_password( 12, false ),
1351 + );
1352 + MainWP_Api_Manager::instance()->set_activation_info( $ext_key, $act_info );
1353 + }
1354 + }
1355 +
1356 + /**
1357 + * Method deactivate_extension()
1358 + *
1359 + * Deactivate MaiNWP Extension.
1360 + *
1361 + * @param mixed $ext_key Exnension API Key.
1362 + * @param bool $dashboard_only Deactive API Key on dashboard only.
1363 + *
1364 + * @uses \MainWP\Dashboard\MainWP_Api_Manager::set_activation_info()
1365 + */
1366 + public function deactivate_extension( $ext_key, $dashboard_only = false ) {
1367 + // try to deactivate license.
1368 + if ( ! $dashboard_only ) {
1369 + $mainwp_api_key = MainWP_Api_Manager_Key::instance()->get_decrypt_master_api_key();
1370 + MainWP_Api_Manager::instance()->license_key_deactivation( $ext_key, $mainwp_api_key );
1371 + }
1372 +
1373 + MainWP_Api_Manager::instance()->remove_activation_info( $ext_key );
1374 + }
1071 1375 }