PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
6.2.3 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 All 156 releases
← All changes | pages/page-mainwp-settings.php +2674 -1665 5.0.3 → 6.2.2 View file →
@@ -9,1823 +9,2832 @@
9 9 */
10 10
11 11 namespace MainWP\Dashboard;
12 12
13 +use MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Settings;
14 +
15 +// Exit if accessed directly.
16 +if ( ! defined( 'ABSPATH' ) ) {
17 + exit;
18 +}
19 +
13 20 /**
14 21 * Class MainWP_Settings
15 22 *
16 23 * @package MainWP\Dashboard
17 24 */
18 -class MainWP_Settings {
25 +class MainWP_Settings { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
19 26
20 - // phpcs:disable Generic.Metrics.CyclomaticComplexity -- complexity.
27 + // phpcs:disable Generic.Metrics.CyclomaticComplexity -- complexity.
21 28
22 - /**
23 - * Protected static variable to hold the single instance of the class.
24 - *
25 - * @var mixed Default null
26 - */
27 - protected static $instance = null;
29 + /**
30 + * Protected static variable to hold the single instance of the class.
31 + *
32 + * @var mixed Default null
33 + */
34 + protected static $instance = null;
28 35
29 - /**
30 - * Public static varable to hold Subpages information.
31 - *
32 - * @var array $subPages
33 - */
34 - public static $subPages;
36 + /**
37 + * Public static varable to hold Subpages information.
38 + *
39 + * @var array $subPages
40 + */
41 + public static $subPages;
35 42
36 - /**
37 - * Get Class Name
38 - *
39 - * @return __CLASS__
40 - */
41 - public static function get_class_name() {
42 - return __CLASS__;
43 - }
43 + /**
44 + * Get Class Name
45 + *
46 + * @return __CLASS__
47 + */
48 + public static function get_class_name() {
49 + return __CLASS__;
50 + }
44 51
45 - /**
46 - * Return the single instance of the class.
47 - *
48 - * @return mixed $instance The single instance of the class.
49 - */
50 - public static function get_instance() {
51 - if ( is_null( self::$instance ) ) {
52 - self::$instance = new self();
53 - }
54 - return self::$instance;
55 - }
52 + /**
53 + * Return the single instance of the class.
54 + *
55 + * @return mixed $instance The single instance of the class.
56 + */
57 + public static function get_instance() {
58 + if ( is_null( static::$instance ) ) {
59 + static::$instance = new self();
60 + }
61 + return static::$instance;
62 + }
56 63
57 - /** Instantiate Hooks for the Settings Page. */
58 - public static function init() {
59 - /**
60 - * This hook allows you to render the Settings page header via the 'mainwp_pageheader_settings' action.
61 - *
62 - * This hook is normally used in the same context of 'mainwp_getsubpages_settings'
63 - *
64 - * @see \MainWP_Settings::render_header
65 - */
66 - add_action( 'mainwp-pageheader-settings', array( self::get_class_name(), 'render_header' ) ); // deprecated, use mainwp_pageheader_settings.
64 + /** Instantiate Hooks for the Settings Page. */
65 + public static function init() {
66 + /**
67 + * This hook allows you to render the Settings page header via the 'mainwp_pageheader_settings' action.
68 + *
69 + * This hook is normally used in the same context of 'mainwp_getsubpages_settings'
70 + *
71 + * @see \MainWP_Settings::render_header
72 + */
73 + add_action( 'mainwp-pageheader-settings', array( static::get_class_name(), 'render_header' ) ); // deprecated, use mainwp_pageheader_settings.
67 74
68 - add_action( 'mainwp_pageheader_settings', array( self::get_class_name(), 'render_header' ) );
75 + add_action( 'mainwp_pageheader_settings', array( static::get_class_name(), 'render_header' ) );
69 76
70 - /**
71 - * This hook allows you to render the Settings page footer via the 'mainwp-pagefooter-settings' action.
72 - *
73 - * This hook is normally used in the same context of 'mainwp-getsubpages-settings'
74 - *
75 - * @see \MainWP_Settings::render_footer
76 - */
77 - add_action( 'mainwp-pagefooter-settings', array( self::get_class_name(), 'render_footer' ) ); // deprecated, use mainwp_pagefooter_settings.
77 + /**
78 + * This hook allows you to render the Settings page footer via the 'mainwp-pagefooter-settings' action.
79 + *
80 + * This hook is normally used in the same context of 'mainwp-getsubpages-settings'
81 + *
82 + * @see \MainWP_Settings::render_footer
83 + */
84 + add_action( 'mainwp-pagefooter-settings', array( static::get_class_name(), 'render_footer' ) ); // deprecated, use mainwp_pagefooter_settings.
78 85
79 - add_action( 'mainwp_pagefooter_settings', array( self::get_class_name(), 'render_footer' ) );
86 + add_action( 'mainwp_pagefooter_settings', array( static::get_class_name(), 'render_footer' ) );
80 87
81 - add_action( 'admin_init', array( self::get_class_name(), 'admin_init' ) );
88 + add_action( 'admin_init', array( static::get_class_name(), 'admin_init' ) );
82 89
83 - add_action( 'mainwp_help_sidebar_content', array( self::get_class_name(), 'mainwp_help_content' ) );
84 - }
90 + add_action( 'mainwp_help_sidebar_content', array( static::get_class_name(), 'mainwp_help_content' ) );
91 + }
85 92
86 - /** Run the export_sites method that exports the Child Sites .csv file */
87 - public static function admin_init() {
88 - self::export_sites();
89 - if ( isset( $_GET['clearActivationData'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'clear_activation_data' ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
90 - delete_option( 'mainwp_extensions_api_username' );
91 - delete_option( 'mainwp_extensions_api_password' );
92 - delete_option( 'mainwp_extensions_api_save_login' );
93 - delete_option( 'mainwp_extensions_plan_info' );
94 - MainWP_Keys_Manager::instance()->update_key_value( 'mainwp_extensions_master_api_key', false );
93 + /**
94 + * Get the registered Settings subpages.
95 + *
96 + * @return array<int, array<string, mixed>> Settings subpages.
97 + */
98 + private static function get_subpages() {
99 + if ( isset( static::$subPages ) && is_array( static::$subPages ) ) {
100 + return static::$subPages;
101 + }
95 102
96 - $new_extensions = array();
97 - $extensions = get_option( 'mainwp_extensions', array() );
103 + /**
104 + * Settings Subpages
105 + *
106 + * Filters subpages for the Settings page.
107 + *
108 + * @since Unknown
109 + */
110 + $sub_pages = apply_filters_deprecated( 'mainwp-getsubpages-settings', array( array() ), '4.0.7.2', 'mainwp_getsubpages_settings' ); // @deprecated Use 'mainwp_getsubpages_settings' instead. NOSONAR - not IP.
111 + static::$subPages = apply_filters( 'mainwp_getsubpages_settings', $sub_pages );
98 112
99 - if ( is_array( $extensions ) ) {
100 - foreach ( $extensions as $ext ) {
101 - if ( isset( $ext['api'] ) && isset( $ext['apiManager'] ) && ! empty( $ext['apiManager'] ) ) {
102 - if ( isset( $ext['api_key'] ) ) {
103 - $ext['api_key'] = '';
104 - }
105 - if ( isset( $ext['activation_email'] ) ) {
106 - $ext['activation_email'] = '';
107 - }
108 - if ( isset( $ext['activated_key'] ) ) {
109 - $ext['activated_key'] = 'Deactivated';
110 - }
113 + return is_array( static::$subPages ) ? static::$subPages : array();
114 + }
111 115
112 - $act_info = MainWP_Api_Manager::instance()->get_activation_info( $ext['api'] );
113 - if ( isset( $act_info['api_key'] ) ) {
114 - $act_info['api_key'] = '';
115 - }
116 - if ( isset( $act_info['activation_email'] ) ) {
117 - $act_info['activation_email'] = '';
118 - }
119 - if ( isset( $act_info['activated_key'] ) ) {
120 - $act_info['activated_key'] = 'Deactivated';
121 - }
122 - MainWP_Api_Manager::instance()->set_activation_info( $ext['api'], $act_info );
123 - }
124 - $new_extensions[] = $ext;
125 - }
126 - }
116 + /**
117 + * Get the built-in Settings pages used across menu registration and navigation rendering.
118 + *
119 + * @return array<int, array<string, mixed>> Settings page definitions.
120 + */
121 + private static function get_core_pages() {
122 + $pages = array(
123 + array(
124 + 'slug' => 'Settings',
125 + 'page_title' => __( 'Settings Global options', 'mainwp' ),
126 + 'menu_title' => ' <span id="mainwp-Settings">' . esc_html__( 'Settings', 'mainwp' ) . '</span>',
127 + 'nav_title' => esc_html__( 'General Settings', 'mainwp' ),
128 + 'callback' => array( static::get_class_name(), 'render' ),
129 + 'active_keys' => array( '', 'Settings' ),
130 + ),
131 + array(
132 + 'slug' => 'MainWPTools',
133 + 'page_title' => __( 'Tools', 'mainwp' ),
134 + 'menu_title' => ' <div class="mainwp-hidden">' . esc_html__( 'Tools', 'mainwp' ) . '</div>',
135 + 'nav_title' => esc_html__( 'Tools', 'mainwp' ),
136 + 'callback' => array( static::get_class_name(), 'render_mainwp_tools' ),
137 + 'active_keys' => array( 'MainWPTools' ),
138 + ),
139 + array(
140 + 'slug' => 'CostTrackerSettings',
141 + 'page_title' => esc_html__( 'Cost Tracker Settings', 'mainwp' ),
142 + 'menu_title' => '<div class="mainwp-hidden">' . esc_html__( 'Cost Tracker', 'mainwp' ) . '</div>',
143 + 'nav_title' => esc_html__( 'Cost Tracker Settings', 'mainwp' ),
144 + 'callback' => array( Cost_Tracker_Settings::get_instance(), 'render_settings_page' ),
145 + 'active_keys' => array( 'CostTrackerSettings' ),
146 + ),
147 + array(
148 + 'slug' => 'SettingsAdvanced',
149 + 'page_title' => __( 'Advanced Options', 'mainwp' ),
150 + 'menu_title' => ' <div class="mainwp-hidden">' . esc_html__( 'Advanced Options', 'mainwp' ) . '</div>',
151 + 'nav_title' => esc_html__( 'Advanced Settings', 'mainwp' ),
152 + 'callback' => array( static::get_class_name(), 'render_advanced' ),
153 + 'active_keys' => array( 'Advanced', 'SettingsAdvanced' ),
154 + ),
155 + array(
156 + 'slug' => 'MonitoringSettings',
157 + 'page_title' => __( 'Monitoring Options', 'mainwp' ),
158 + 'menu_title' => ' <div class="mainwp-hidden">' . esc_html__( 'Monitoring Options', 'mainwp' ) . '</div>',
159 + 'nav_title' => esc_html__( 'Monitoring Settings', 'mainwp' ),
160 + 'callback' => array( static::get_class_name(), 'render_monitoring' ),
161 + 'active_keys' => array( 'Monitoring', 'MonitoringSettings' ),
162 + ),
163 + array(
164 + 'slug' => 'SettingsEmail',
165 + 'page_title' => __( 'Email Settings', 'mainwp' ),
166 + 'menu_title' => ' <div class="mainwp-hidden">' . esc_html__( 'Email Settings', 'mainwp' ) . '</div>',
167 + 'nav_title' => esc_html__( 'Email Settings', 'mainwp' ),
168 + 'callback' => array( static::get_class_name(), 'render_email_settings' ),
169 + 'active_keys' => array( 'Emails', 'SettingsEmail' ),
170 + ),
171 + array(
172 + 'slug' => 'PremiumUpdates',
173 + 'page_title' => __( 'Premium Updates', 'mainwp' ),
174 + 'menu_title' => ' <div class="mainwp-hidden">' . esc_html__( 'Premium Updates', 'mainwp' ) . '</div>',
175 + 'nav_title' => esc_html__( 'Premium Updates', 'mainwp' ),
176 + 'callback' => array( MainWP_Settings_Premium_Updates::get_class_name(), 'render' ),
177 + 'active_keys' => array( 'Premium', 'PremiumUpdates' ),
178 + ),
179 + );
127 180
128 - MainWP_Utility::update_option( 'mainwp_extensions', $new_extensions );
129 - update_option( 'mainwp_extensions_all_activation_cached', '' );
130 - wp_safe_redirect( esc_url( admin_url( 'admin.php?page=MainWPTools' ) ) );
131 - die();
132 - }
133 - }
181 + $visible_pages = array();
134 182
135 - /**
136 - * Instantiate the Settings Menu.
137 - *
138 - * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
139 - */
140 - public static function init_menu() {
141 - add_submenu_page(
142 - 'mainwp_tab',
143 - __( 'Settings Global options', 'mainwp' ),
144 - ' <span id="mainwp-Settings">' . esc_html__( 'Settings', 'mainwp' ) . '</span>',
145 - 'read',
146 - 'Settings',
147 - array(
148 - self::get_class_name(),
149 - 'render',
150 - )
151 - );
183 + foreach ( $pages as $page ) {
184 + if ( 'Settings' !== $page['slug'] && MainWP_Menu::is_disable_menu_item( 3, $page['slug'] ) ) {
185 + continue;
186 + }
152 187
153 - if ( ! MainWP_Menu::is_disable_menu_item( 3, 'MainWPTools' ) ) {
154 - add_submenu_page(
155 - 'mainwp_tab',
156 - __( 'Tools', 'mainwp' ),
157 - ' <div class="mainwp-hidden">' . esc_html__( 'Tools', 'mainwp' ) . '</div>',
158 - 'read',
159 - 'MainWPTools',
160 - array(
161 - self::get_class_name(),
162 - 'render_mainwp_tools',
163 - )
164 - );
165 - }
188 + $visible_pages[] = $page;
189 + }
166 190
167 - if ( ! MainWP_Menu::is_disable_menu_item( 3, 'SettingsAdvanced' ) ) {
168 - add_submenu_page(
169 - 'mainwp_tab',
170 - __( 'Advanced Options', 'mainwp' ),
171 - ' <div class="mainwp-hidden">' . esc_html__( 'Advanced Options', 'mainwp' ) . '</div>',
172 - 'read',
173 - 'SettingsAdvanced',
174 - array(
175 - self::get_class_name(),
176 - 'render_advanced',
177 - )
178 - );
179 - }
191 + return $visible_pages;
192 + }
180 193
181 - if ( ! MainWP_Menu::is_disable_menu_item( 3, 'SettingsEmail' ) ) {
182 - add_submenu_page(
183 - 'mainwp_tab',
184 - __( 'Email Settings', 'mainwp' ),
185 - ' <div class="mainwp-hidden">' . esc_html__( 'Email Settings', 'mainwp' ) . '</div>',
186 - 'read',
187 - 'SettingsEmail',
188 - array(
189 - self::get_class_name(),
190 - 'render_email_settings',
191 - )
192 - );
193 - }
194 + /**
195 + * Convert a navigation href into a usable URL.
196 + *
197 + * @param string $href Navigation href.
198 + *
199 + * @return string Navigation URL.
200 + */
201 + private static function get_navigation_item_url( $href ) {
202 + $href = trim( wp_specialchars_decode( (string) $href, ENT_QUOTES ) );
194 203
195 - /**
196 - * Settings Subpages
197 - *
198 - * Filters subpages for the Settings page.
199 - *
200 - * @since Unknown
201 - */
202 - $sub_pages = apply_filters_deprecated( 'mainwp-getsubpages-settings', array( array() ), '4.0.7.2', 'mainwp_getsubpages_settings' ); // @deprecated Use 'mainwp_getsubpages_settings' instead.
203 - self::$subPages = apply_filters( 'mainwp_getsubpages_settings', $sub_pages );
204 + if ( empty( $href ) ) {
205 + return '';
206 + }
204 207
205 - if ( isset( self::$subPages ) && is_array( self::$subPages ) ) {
206 - foreach ( self::$subPages as $subPage ) {
207 - if ( MainWP_Menu::is_disable_menu_item( 3, 'Settings' . $subPage['slug'] ) ) {
208 - continue;
209 - }
210 - add_submenu_page( 'mainwp_tab', $subPage['title'], '<div class="mainwp-hidden">' . $subPage['title'] . '</div>', 'read', 'Settings' . $subPage['slug'], $subPage['callback'] );
211 - }
212 - }
213 - }
208 + if ( preg_match( '/^https?:\/\//i', $href ) ) {
209 + return $href;
210 + }
214 211
215 - /**
216 - * Instantiate Settings SubPages Menu.
217 - *
218 - * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
219 - */
220 - public static function init_subpages_menu() {
221 - ?>
222 - <div id="menu-mainwp-Settings" class="mainwp-submenu-wrapper">
223 - <div class="wp-submenu sub-open" style="">
224 - <div class="mainwp_boxout">
225 - <div class="mainwp_boxoutin"></div>
226 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=Settings' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'General Settings', 'mainwp' ); ?></a>
227 - <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'SettingsAdvanced' ) ) { ?>
228 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=SettingsAdvanced' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Advanced Settings', 'mainwp' ); ?></a>
229 - <?php } ?>
230 - <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'SettingsEmail' ) ) { ?>
231 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=SettingsEmail' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Email Settings', 'mainwp' ); ?></a>
232 - <?php } ?>
233 - <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'MainWPTools' ) ) { ?>
234 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=MainWPTools' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Tools', 'mainwp' ); ?></a>
235 - <?php } ?>
236 - <?php
237 - if ( isset( self::$subPages ) && is_array( self::$subPages ) && ( count( self::$subPages ) > 0 ) ) {
238 - foreach ( self::$subPages as $subPage ) {
239 - if ( MainWP_Menu::is_disable_menu_item( 3, 'Settings' . $subPage['slug'] ) ) {
240 - continue;
241 - }
242 - ?>
243 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=Settings' . $subPage['slug'] ) ); ?>" class="mainwp-submenu"><?php echo isset( $subPage['before_title'] ) ? $subPage['before_title'] : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?> <?php echo esc_html( $subPage['title'] ); ?></a>
244 - <?php
245 - }
246 - }
247 - ?>
248 - </div>
249 - </div>
250 - </div>
251 - <?php
252 - }
212 + return admin_url( ltrim( $href, '/' ) );
213 + }
253 214
254 - /**
255 - * Instantiate left menu
256 - *
257 - * Settings Page & SubPage link data.
258 - *
259 - * @param array $subPages SubPages Array.
260 - *
261 - * @uses \MainWP\Dashboard\MainWP_Menu::add_left_menu()
262 - * @uses \MainWP\Dashboard\MainWP_Menu::init_subpages_left_menu()
263 - * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
264 - */
265 - public static function init_left_menu( $subPages = array() ) {
266 - MainWP_Menu::add_left_menu(
267 - array(
268 - 'title' => esc_html__( 'Settings', 'mainwp' ),
269 - 'parent_key' => 'mainwp_tab',
270 - 'slug' => 'Settings',
271 - 'href' => 'admin.php?page=Settings',
272 - 'icon' => '<i class="cog icon"></i>',
273 - ),
274 - 0
275 - );
215 + /**
216 + * Get dynamic Settings subpage items using the legacy left-menu normalization path.
217 + *
218 + * @return array<int, array<string, mixed>> Settings navigation items.
219 + */
220 + private static function get_filtered_subpage_navigation_items() {
221 + $menu_items = array();
222 + $core_slugs = array();
276 223
277 - $init_sub_subleftmenu = array(
278 - array(
279 - 'title' => esc_html__( 'General Settings', 'mainwp' ),
280 - 'parent_key' => 'Settings',
281 - 'href' => 'admin.php?page=Settings',
282 - 'slug' => 'Settings',
283 - 'right' => '',
284 - ),
285 - array(
286 - 'title' => esc_html__( 'Advanced Settings', 'mainwp' ),
287 - 'parent_key' => 'Settings',
288 - 'href' => 'admin.php?page=SettingsAdvanced',
289 - 'slug' => 'SettingsAdvanced',
290 - 'right' => '',
291 - ),
292 - array(
293 - 'title' => esc_html__( 'Email Settings', 'mainwp' ),
294 - 'parent_key' => 'Settings',
295 - 'href' => 'admin.php?page=SettingsEmail',
296 - 'slug' => 'SettingsEmail',
297 - 'right' => '',
298 - ),
299 - array(
300 - 'title' => esc_html__( 'Tools', 'mainwp' ),
301 - 'parent_key' => 'Settings',
302 - 'href' => 'admin.php?page=MainWPTools',
303 - 'slug' => 'MainWPTools',
304 - 'right' => '',
305 - ),
306 - );
224 + foreach ( static::get_navigation_items( 'left_menu_core' ) as $item ) {
225 + $core_slugs[ $item['slug'] ] = true;
226 + $menu_items[] = array(
227 + 'title' => $item['title'],
228 + 'parent_key' => 'Settings',
229 + 'href' => $item['href'],
230 + 'slug' => $item['slug'],
231 + 'right' => '',
232 + 'before_title' => isset( $item['before_title'] ) ? $item['before_title'] : '',
233 + );
234 + }
307 235
308 - MainWP_Menu::init_subpages_left_menu( $subPages, $init_sub_subleftmenu, 'Settings', 'Settings' );
309 - foreach ( $init_sub_subleftmenu as $item ) {
310 - if ( MainWP_Menu::is_disable_menu_item( 3, $item['slug'] ) ) {
311 - continue;
312 - }
236 + MainWP_Menu::init_subpages_left_menu( static::get_subpages(), $menu_items, 'Settings', 'Settings' );
313 237
314 - MainWP_Menu::add_left_menu( $item, 2 );
315 - }
316 - }
238 + $items = array();
317 239
318 - /**
319 - * Render Page Header.
320 - *
321 - * @param string $shownPage The page slug shown at this moment.
322 - *
323 - * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
324 - * @uses \MainWP\Dashboard\MainWP_UI::render_top_header()
325 - * @uses \MainWP\Dashboard\MainWP_UI::render_page_navigation()
326 - */
327 - public static function render_header( $shownPage = '' ) {
240 + foreach ( $menu_items as $menu_item ) {
241 + if ( empty( $menu_item['slug'] ) || empty( $menu_item['title'] ) || empty( $menu_item['href'] ) ) {
242 + continue;
243 + }
328 244
329 - $params = array(
330 - 'title' => esc_html__( 'MainWP Settings', 'mainwp' ),
331 - );
245 + if ( isset( $core_slugs[ $menu_item['slug'] ] ) ) {
246 + continue;
247 + }
332 248
333 - MainWP_UI::render_top_header( $params );
249 + if ( isset( $menu_item['item_slug'] ) ) {
250 + if ( MainWP_Menu::is_disable_menu_item( 3, $menu_item['item_slug'] ) ) {
251 + continue;
252 + }
253 + } elseif ( MainWP_Menu::is_disable_menu_item( 3, $menu_item['slug'] ) ) {
254 + continue;
255 + }
334 256
335 - $renderItems = array();
257 + $active_slug = 0 === strpos( $menu_item['slug'], 'Settings' ) ? substr( $menu_item['slug'], strlen( 'Settings' ) ) : $menu_item['slug'];
258 + $item = array(
259 + 'slug' => $menu_item['slug'],
260 + 'title' => $menu_item['title'],
261 + 'href' => $menu_item['href'],
262 + 'active_keys' => array( $active_slug, $menu_item['slug'] ),
263 + 'menu_hidden' => false,
264 + );
336 265
337 - $renderItems[] = array(
338 - 'title' => esc_html__( 'General Settings', 'mainwp' ),
339 - 'href' => 'admin.php?page=Settings',
340 - 'active' => ( '' === $shownPage ) ? true : false,
341 - );
266 + if ( ! empty( $menu_item['before_title'] ) ) {
267 + $item['before_title'] = $menu_item['before_title'];
268 + }
342 269
343 - if ( ! MainWP_Menu::is_disable_menu_item( 3, 'SettingsAdvanced' ) ) {
344 - $renderItems[] = array(
345 - 'title' => esc_html__( 'Advanced Settings', 'mainwp' ),
346 - 'href' => 'admin.php?page=SettingsAdvanced',
347 - 'active' => ( 'Advanced' === $shownPage ) ? true : false,
348 - );
349 - }
270 + if ( isset( $menu_item['item_slug'] ) ) {
271 + $item['item_slug'] = $menu_item['item_slug'];
272 + }
350 273
351 - if ( ! MainWP_Menu::is_disable_menu_item( 3, 'SettingsEmail' ) ) {
352 - $renderItems[] = array(
353 - 'title' => esc_html__( 'Email Settings', 'mainwp' ),
354 - 'href' => 'admin.php?page=SettingsEmail',
355 - 'active' => ( 'Emails' === $shownPage ) ? true : false,
356 - );
357 - }
274 + $items[] = $item;
275 + }
358 276
359 - if ( ! MainWP_Menu::is_disable_menu_item( 3, 'MainWPTools' ) ) {
360 - $renderItems[] = array(
361 - 'title' => esc_html__( 'Tools', 'mainwp' ),
362 - 'href' => 'admin.php?page=MainWPTools',
363 - 'active' => ( 'MainWPTools' === $shownPage ) ? true : false,
364 - );
365 - }
277 + return $items;
278 + }
366 279
367 - if ( isset( self::$subPages ) && is_array( self::$subPages ) ) {
368 - foreach ( self::$subPages as $subPage ) {
369 - if ( MainWP_Menu::is_disable_menu_item( 3, 'Settings' . $subPage['slug'] ) ) {
370 - continue;
371 - }
372 - $item = array();
373 - $item['title'] = $subPage['title'];
374 - $item['href'] = 'admin.php?page=Settings' . $subPage['slug'];
375 - $item['active'] = ( $subPage['slug'] === $shownPage ) ? true : false;
376 - if ( ! empty( $subPage['before_title'] ) ) {
377 - $item['before_title'] = $subPage['before_title'];
378 - }
280 + /**
281 + * Get the Settings navigation items.
282 + *
283 + * @return array<int, array<string, mixed>> Settings navigation items.
284 + */
285 + public static function get_navigation_items( $context = 'default' ) {
286 + $core_items = array();
287 + $dynamic_items = array();
288 + $items = array();
379 289
380 - if ( isset( $subPage['class'] ) ) {
381 - $item['class'] = $subPage['class'];
382 - }
383 - $renderItems[] = $item;
384 - }
385 - }
290 + foreach ( static::get_core_pages() as $page ) {
291 + $core_items[ $page['slug'] ] = array(
292 + 'slug' => $page['slug'],
293 + 'title' => $page['nav_title'],
294 + 'href' => 'admin.php?page=' . $page['slug'],
295 + 'active_keys' => $page['active_keys'],
296 + 'menu_hidden' => false,
297 + );
298 + }
386 299
387 - MainWP_UI::render_page_navigation( $renderItems );
300 + if ( 'command_palette' === $context ) {
301 + $dynamic_items = static::get_filtered_subpage_navigation_items();
302 + } else {
303 + foreach ( static::get_subpages() as $subPage ) {
304 + if ( empty( $subPage['slug'] ) || MainWP_Menu::is_disable_menu_item( 3, 'Settings' . $subPage['slug'] ) ) {
305 + continue;
306 + }
388 307
389 - $saved_status = MainWP_Settings_Indicator::get_instance()->get_saved_indicator_status();
308 + $item = array(
309 + 'slug' => 'Settings' . $subPage['slug'],
310 + 'title' => $subPage['title'],
311 + 'href' => ! empty( $subPage['href'] ) ? $subPage['href'] : 'admin.php?page=Settings' . $subPage['slug'],
312 + 'active_keys' => array( $subPage['slug'], 'Settings' . $subPage['slug'] ),
313 + 'menu_hidden' => ! empty( $subPage['menu_hidden'] ),
314 + );
390 315
391 - ?>
316 + if ( ! empty( $subPage['before_title'] ) ) {
317 + $item['before_title'] = $subPage['before_title'];
318 + }
392 319
393 - <script type="text/javascript">
394 - var mainwp_settings_saved_menu_indicator_status = '<?php echo !empty($saved_status) ? wp_json_encode( $saved_status ) : ''; //phpcs:ignore -- ok. ?>';
395 - </script>
396 - <?php
397 - }
320 + if ( isset( $subPage['class'] ) ) {
321 + $item['class'] = $subPage['class'];
322 + }
398 323
399 - /**
400 - * Close the HTML container.
401 - */
402 - public static function render_footer() {
403 - echo '</div>';
404 - }
324 + if ( isset( $subPage['item_slug'] ) ) {
325 + $item['item_slug'] = $subPage['item_slug'];
326 + }
405 327
406 - /**
407 - * Method handle_settings_post().
408 - *
409 - * This class handles the $_POST of Settings Options.
410 - *
411 - * @uses MainWP_DB::instance()
412 - * @uses MainWP_Utility::update_option()
413 - *
414 - * @return boolean True|False Posts On True.
415 - *
416 - * @uses \MainWP\Dashboard\MainWP_DB_Common::get_user_extension()
417 - * @uses \MainWP\Dashboard\MainWP_DB_Common::update_user_extension()
418 - * @uses \MainWP\Dashboard\MainWP_System_Utility::is_admin()
419 - * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
420 - */
421 - public static function handle_settings_post() {
422 - if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'Settings' ) ) {
423 - $userExtension = MainWP_DB_Common::instance()->get_user_extension();
424 - $userExtension->pluginDir = '';
328 + $dynamic_items[] = $item;
329 + }
330 + }
425 331
426 - MainWP_DB_Common::instance()->update_user_extension( $userExtension );
427 - if ( MainWP_System_Utility::is_admin() ) {
332 + $base_order = array( 'Settings', 'SettingsAdvanced', 'MonitoringSettings', 'SettingsEmail', 'PremiumUpdates' );
428 333
429 - /**
430 - * Action: mainwp_before_save_general_settings
431 - *
432 - * Fires before general settings save.
433 - *
434 - * @since 4.1
435 - */
436 - do_action( 'mainwp_before_save_general_settings', $_POST );
334 + if ( in_array( $context, array( 'left_menu', 'left_menu_core' ), true ) ) {
335 + $base_order[] = 'MainWPTools';
336 + $base_order[] = 'CostTrackerSettings';
337 + } else {
338 + $base_order[] = 'CostTrackerSettings';
339 + }
437 340
438 - $val = ( ! isset( $_POST['mainwp_pluginAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_pluginAutomaticDailyUpdate'] ) );
439 - MainWP_Utility::update_option( 'mainwp_pluginAutomaticDailyUpdate', $val );
440 - $val = ( ! isset( $_POST['mainwp_themeAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_themeAutomaticDailyUpdate'] ) );
441 - MainWP_Utility::update_option( 'mainwp_themeAutomaticDailyUpdate', $val );
442 - $val = ( ! isset( $_POST['mainwp_automaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_automaticDailyUpdate'] ) );
443 - MainWP_Utility::update_option( 'mainwp_automaticDailyUpdate', $val );
444 - $val = ( ! isset( $_POST['mainwp_show_language_updates'] ) ? 0 : 1 );
445 - MainWP_Utility::update_option( 'mainwp_show_language_updates', $val );
446 - $val = ( ! isset( $_POST['mainwp_disable_update_confirmations'] ) ? 0 : intval( $_POST['mainwp_disable_update_confirmations'] ) );
447 - MainWP_Utility::update_option( 'mainwp_disable_update_confirmations', $val );
448 - $val = ( ! isset( $_POST['mainwp_backup_before_upgrade'] ) ? 0 : 1 );
449 - MainWP_Utility::update_option( 'mainwp_backup_before_upgrade', $val );
450 - $val = ( ! isset( $_POST['mainwp_backup_before_upgrade_days'] ) ? 7 : intval( $_POST['mainwp_backup_before_upgrade_days'] ) );
451 - MainWP_Utility::update_option( 'mainwp_backup_before_upgrade_days', $val );
341 + foreach ( $base_order as $slug ) {
342 + if ( isset( $core_items[ $slug ] ) ) {
343 + $items[] = $core_items[ $slug ];
344 + }
345 + }
452 346
453 - if ( is_plugin_active( 'mainwp-comments-extension/mainwp-comments-extension.php' ) ) {
454 - MainWP_Utility::update_option( 'mainwp_maximumComments', isset( $_POST['mainwp_maximumComments'] ) ? intval( $_POST['mainwp_maximumComments'] ) : 50 );
455 - }
347 + if ( 'left_menu_core' !== $context ) {
348 + $items = array_merge( $items, $dynamic_items );
349 + }
456 350
457 - $current_timeDailyUpdate = get_option( 'mainwp_timeDailyUpdate' );
458 - $new_timeDailyUpdate = isset( $_POST['mainwp_timeDailyUpdate'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_timeDailyUpdate'] ) ) : '';
351 + if ( ! in_array( $context, array( 'left_menu', 'left_menu_core' ), true ) && isset( $core_items['MainWPTools'] ) ) {
352 + $items[] = $core_items['MainWPTools'];
353 + }
459 354
460 - if ( $current_timeDailyUpdate !== $new_timeDailyUpdate ) {
461 - MainWP_Utility::update_option( 'mainwp_timeDailyUpdate', $new_timeDailyUpdate );
462 - }
355 + return $items;
356 + }
463 357
464 - $new_freq = ( isset( $_POST['mainwp_frequencyDailyUpdate'] ) ? intval( $_POST['mainwp_frequencyDailyUpdate'] ) : 2 );
465 - MainWP_Utility::update_option( 'mainwp_frequencyDailyUpdate', $new_freq );
358 + /**
359 + * Get the Settings command palette items.
360 + *
361 + * @return array<int, array<string, mixed>> Command palette item definitions.
362 + */
363 + public static function get_command_palette_items() {
364 + $items = array();
466 365
467 - $new_delay = ( isset( $_POST['mainwp_delay_autoupdate'] ) ? intval( $_POST['mainwp_delay_autoupdate'] ) : 1 );
468 - MainWP_Utility::update_option( 'mainwp_delay_autoupdate', $new_delay );
366 + foreach ( static::get_navigation_items( 'command_palette' ) as $item ) {
367 + if ( ! empty( $item['menu_hidden'] ) ) {
368 + continue;
369 + }
469 370
470 - $val = ( isset( $_POST['mainwp_sidebarPosition'] ) ? intval( $_POST['mainwp_sidebarPosition'] ) : 1 );
471 - $user = wp_get_current_user();
472 - if ( $user ) {
473 - update_user_option( $user->ID, 'mainwp_sidebarPosition', $val, true );
474 - }
371 + $path_title = $item['title'];
372 + $path_titles = array( esc_html__( 'Settings', 'mainwp' ), $path_title );
475 373
476 - MainWP_Utility::update_option( 'mainwp_numberdays_Outdate_Plugin_Theme', ! empty( $_POST['mainwp_numberdays_Outdate_Plugin_Theme'] ) ? intval( $_POST['mainwp_numberdays_Outdate_Plugin_Theme'] ) : 365 );
477 - $ignore_http = isset( $_POST['mainwp_ignore_http_response_status'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_ignore_http_response_status'] ) ) : '';
478 - MainWP_Utility::update_option( 'mainwp_ignore_HTTP_response_status', $ignore_http );
374 + if ( ! empty( $item['before_title'] ) ) {
375 + $path_title = trim( wp_strip_all_tags( $item['before_title'] ) . ' ' . $item['title'] );
376 + $path_titles[1] = $path_title;
377 + }
479 378
480 - $check_http_response = ( isset( $_POST['mainwp_check_http_response'] ) ? 1 : 0 );
481 - MainWP_Utility::update_option( 'mainwp_check_http_response', $check_http_response );
379 + if ( 'Settings' === $item['slug'] ) {
380 + $path_titles[1] = esc_html__( 'General Settings', 'mainwp' );
381 + }
482 382
483 - $actions_notification_enable = ( isset( $_POST['mainwp_site_actions_notification_enable'] ) ? 1 : 0 );
484 - MainWP_Utility::update_option( 'mainwp_site_actions_notification_enable', $actions_notification_enable );
383 + $items[] = array(
384 + 'slug' => $item['slug'],
385 + 'href' => $item['href'],
386 + 'path_titles' => $path_titles,
387 + );
388 + }
485 389
486 - //phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
487 - // Handle custom date/time formats.
488 - if ( ! empty( $_POST['date_format'] ) && isset( $_POST['date_format_custom'] )
489 - && '\c\u\s\t\o\m' === wp_unslash( $_POST['date_format'] )
490 - ) {
491 - $_POST['date_format'] = wp_unslash( $_POST['date_format_custom'] );
492 - }
390 + return $items;
391 + }
493 392
494 - if ( ! empty( $_POST['time_format'] ) && isset( $_POST['time_format_custom'] )
495 - && '\c\u\s\t\o\m' === wp_unslash( $_POST['time_format'] )
496 - ) {
497 - $_POST['time_format'] = wp_unslash( $_POST['time_format_custom'] );
498 - }
393 + /** Run the export_sites method that exports the Child Sites .csv file */
394 + public static function admin_init() { // phpcs:ignore -- NOSONAR - complex.
395 + static::export_sites();
396 + if ( isset( $_GET['clearActivationData'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'clear_activation_data' ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
397 + delete_option( 'mainwp_extensions_api_username' );
398 + delete_option( 'mainwp_extensions_api_password' );
399 + delete_option( 'mainwp_extensions_api_save_login' );
400 + delete_option( 'mainwp_extensions_plan_info' );
401 + MainWP_Keys_Manager::instance()->update_key_value( 'mainwp_extensions_master_api_key', false );
499 402
500 - if ( isset( $_POST['timezone_string'] ) ) {
501 - // Map UTC+- timezones to gmt_offsets and set timezone_string to empty.
502 - if ( ! empty( $_POST['timezone_string'] ) && preg_match( '/^UTC[+-]/', wp_unslash( $_POST['timezone_string'] ) ) ) {
503 - $_POST['gmt_offset'] = wp_unslash( $_POST['timezone_string'] );
504 - $_POST['gmt_offset'] = preg_replace( '/UTC\+?/', '', wp_unslash( $_POST['gmt_offset'] ) ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
505 - $_POST['timezone_string'] = '';
506 - }
403 + $new_extensions = array();
404 + $extensions = get_option( 'mainwp_extensions', array() );
507 405
508 - $options = array(
509 - 'gmt_offset',
510 - 'date_format',
511 - 'time_format',
512 - 'timezone_string',
513 - );
406 + if ( is_array( $extensions ) ) {
407 + foreach ( $extensions as $ext ) {
408 + if ( isset( $ext['api'] ) && isset( $ext['apiManager'] ) && ! empty( $ext['apiManager'] ) ) {
409 + if ( isset( $ext['api_key'] ) ) {
410 + $ext['api_key'] = '';
411 + }
412 + if ( isset( $ext['activation_email'] ) ) {
413 + $ext['activation_email'] = '';
414 + }
415 + if ( isset( $ext['activated_key'] ) ) {
416 + $ext['activated_key'] = 'Deactivated';
417 + }
514 418
515 - foreach ( $options as $option ) {
516 - $value = null;
517 - if ( isset( $_POST[ $option ] ) ) {
518 - $value = wp_unslash( $_POST[ $option ] );
519 - if ( ! is_array( $value ) ) {
520 - $value = trim( $value );
521 - }
522 - }
523 - update_option( $option, $value );
524 - }
525 - }
526 - //phpcs:enable
419 + $act_info = MainWP_Api_Manager::instance()->get_activation_info( $ext['api'] );
420 + if ( isset( $act_info['api_key'] ) ) {
421 + $act_info['api_key'] = '';
422 + }
423 + if ( isset( $act_info['activation_email'] ) ) {
424 + $act_info['activation_email'] = '';
425 + }
426 + if ( isset( $act_info['activated_key'] ) ) {
427 + $act_info['activated_key'] = 'Deactivated';
428 + }
429 + MainWP_Api_Manager::instance()->set_activation_info( $ext['api'], $act_info );
430 + }
431 + $new_extensions[] = $ext;
432 + }
433 + }
527 434
528 - MainWP_Utility::update_option( 'mainwp_use_favicon', 1 );
435 + MainWP_Utility::update_option( 'mainwp_extensions', $new_extensions );
436 + update_option( 'mainwp_extensions_all_activation_cached', '' );
437 + wp_safe_redirect( esc_url( admin_url( 'admin.php?page=MainWPTools' ) ) );
438 + die();
439 + }
440 + }
529 441
530 - /**
531 - * Action: mainwp_after_save_general_settings
532 - *
533 - * Fires after save general settings.
534 - *
535 - * @since 4.1
536 - */
537 - do_action( 'mainwp_after_save_general_settings', $_POST );
538 - }
442 + /**
443 + * Instantiate the Settings Menu.
444 + *
445 + * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
446 + */
447 + public static function init_menu() {
448 + foreach ( static::get_core_pages() as $page ) {
449 + add_submenu_page(
450 + 'mainwp_tab',
451 + $page['page_title'],
452 + $page['menu_title'],
453 + 'read',
454 + $page['slug'],
455 + $page['callback']
456 + );
457 + }
539 458
540 - return true;
541 - }
459 + foreach ( static::get_subpages() as $subPage ) {
460 + if ( empty( $subPage['slug'] ) || MainWP_Menu::is_disable_menu_item( 3, 'Settings' . $subPage['slug'] ) ) {
461 + continue;
462 + }
542 463
543 - return false;
544 - }
464 + add_submenu_page( 'mainwp_tab', $subPage['title'], '<div class="mainwp-hidden">' . $subPage['title'] . '</div>', 'read', 'Settings' . $subPage['slug'], $subPage['callback'] );
465 + }
466 + }
545 467
546 - /**
547 - * Render the MainWP Settings Page.
548 - *
549 - * @uses \MainWP\Dashboard\MainWP_Monitoring_View
550 - * @uses \MainWP\Dashboard\MainWP_Manage_Backups::render_settings()
551 - * @uses \MainWP\Dashboard\MainWP_Utility::get_http_codes()
552 - */
553 - public static function render() { //phpcs:ignore -- complex method.
554 - if ( ! mainwp_current_user_have_right( 'dashboard', 'manage_dashboard_settings' ) ) {
555 - mainwp_do_not_have_permissions( esc_html__( 'manage dashboard settings', 'mainwp' ) );
556 - return;
557 - }
468 + /**
469 + * Instantiate Settings SubPages Menu.
470 + *
471 + * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
472 + */
473 + public static function init_subpages_menu() {
474 + ?>
475 + <div id="menu-mainwp-Settings" class="mainwp-submenu-wrapper">
476 + <div class="wp-submenu sub-open" style="">
477 + <div class="mainwp_boxout">
478 + <div class="mainwp_boxoutin"></div>
479 + <?php foreach ( static::get_navigation_items() as $item ) { ?>
480 + <a href="<?php echo esc_url( static::get_navigation_item_url( $item['href'] ) ); ?>" class="mainwp-submenu"><?php echo isset( $item['before_title'] ) ? $item['before_title'] . ' ' : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?><?php echo esc_html( $item['title'] ); ?></a>
481 + <?php } ?>
482 + </div>
483 + </div>
484 + </div>
485 + <?php
486 + }
558 487
559 - self::render_header( '' );
560 - ?>
561 - <div id="mainwp-general-settings" class="ui segment">
562 - <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-general-settings-info-message' ) ) : ?>
563 - <div class="ui info message">
564 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-general-settings-info-message"></i>
565 - <?php printf( esc_html__( 'Manage MainWP general settings. For additional help, review this %1$shelp document%2$s.', 'mainwp' ), '<a href="https://kb.mainwp.com/docs/mainwp-dashboard-settings/" target="_blank">', '</a> <i class="external alternate icon"></i>' ); ?>
566 - </div>
567 - <?php endif; ?>
568 - <?php if ( isset( $_GET['message'] ) && 'saved' === $_GET['message'] ) : // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?>
569 - <div class="ui green message"><i class="close icon"></i><?php esc_html_e( 'Settings have been saved successfully!', 'mainwp' ); ?></div>
570 - <?php endif; ?>
571 - <div class="ui form">
572 - <form method="POST" action="admin.php?page=Settings" id="mainwp-settings-page-form">
573 - <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
574 - <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'Settings' ) ); ?>" />
575 - <?php
576 - /**
577 - * Action: mainwp_settings_form_top
578 - *
579 - * Fires at the top of settings form.
580 - *
581 - * @since 4.1
582 - */
583 - do_action( 'mainwp_settings_form_top' );
584 - ?>
585 - <h3 class="ui dividing header">
586 - <?php echo MainWP_Settings_Indicator::get_indicator( 'header', 'settings-field-indicator-general', 'general-settings' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
587 - <?php esc_html_e( 'General Settings', 'mainwp' ); ?></h3>
588 - <?php
589 - $timeDailyUpdate = get_option( 'mainwp_timeDailyUpdate' );
590 - $frequencyDailyUpdate = (int) get_option( 'mainwp_frequencyDailyUpdate', 2 );
591 - $run_timestamp = MainWP_System_Cron_Jobs::get_timestamp_from_hh_mm( $timeDailyUpdate );
592 - $delay_autoupdate = (int) get_option( 'mainwp_delay_autoupdate', 1 );
488 + /**
489 + * Instantiate left menu
490 + *
491 + * Settings Page & SubPage link data.
492 + *
493 + * @param array $subPages SubPages Array.
494 + *
495 + * @uses \MainWP\Dashboard\MainWP_Menu::add_left_menu()
496 + * @uses \MainWP\Dashboard\MainWP_Menu::init_subpages_left_menu()
497 + * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
498 + */
499 + public static function init_left_menu( $subPages = array() ) {
500 + MainWP_Menu::add_left_menu(
501 + array(
502 + 'title' => esc_html__( 'Settings', 'mainwp' ),
503 + 'parent_key' => 'mainwp_tab',
504 + 'slug' => 'Settings',
505 + 'href' => 'admin.php?page=Settings',
506 + 'icon' => '<i class="cog icon"></i>',
507 + ),
508 + 0
509 + );
593 510
594 - ?>
595 - <div class="ui grid field settings-field-indicator-general">
596 - <label class="six wide column middle aligned">
597 - <?php
598 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_timeDailyUpdate', $timeDailyUpdate );
599 - esc_html_e( 'Daily sync & update time', 'mainwp' );
600 - ?>
601 - </label>
602 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Choose a specific time to initiate the first daily synchronization and update process.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
603 - <div class="time-selector">
604 - <div class="ui input left icon">
605 - <i class="clock icon"></i>
606 - <input type="text" current-utc-datetime="<?php echo date( 'Y-m-d H:i:s' ); ?>" sync-time-local-datetime="<?php echo date( 'Y-m-d H:i:s', $run_timestamp ); ?>" local-datetime="<?php echo date( 'Y-m-d H:i:s', MainWP_Utility::get_timestamp() ); // phpcs:ignore -- to get local time. ?>" name="mainwp_timeDailyUpdate" id="mainwp_timeDailyUpdate" value="<?php echo esc_attr( $timeDailyUpdate ); ?>" />
607 - </div>
608 - </div>
609 - <script type="text/javascript">
610 - jQuery( document ).ready( function() {
611 - jQuery( '.time-selector' ).calendar( {
612 - type: 'time',
613 - ampm: false,
614 - formatter: {
615 - time: 'H:mm',
616 - cellTime: 'H:mm'
617 - }
618 - } );
619 - } );
620 - </script>
621 - </div>
622 - </div>
623 - <div class="ui grid field settings-field-indicator-general">
624 - <label class="six wide column middle aligned">
625 - <?php
626 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_frequencyDailyUpdate', $frequencyDailyUpdate );
627 - esc_html_e( 'Frequency of auto sync & updates', 'mainwp' );
628 - ?>
629 - </label>
630 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Set the frequency for automatic synchronization and updates throughout the day.', 'mainwp' ); ?>" data-inverted="" data-position="top left" >
631 - <select name="mainwp_frequencyDailyUpdate" id="mainwp_frequencyDailyUpdate" class="ui dropdown">
632 - <option value="1" <?php echo ( 1 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Once per day', 'mainwp' ); ?></option>
633 - <option value="2" <?php echo ( 2 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Twice per day', 'mainwp' ); ?></option>
634 - <option value="3" <?php echo ( 3 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Three times per day', 'mainwp' ); ?></option>
635 - <option value="4" <?php echo ( 4 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Four times per day', 'mainwp' ); ?></option>
636 - <option value="5" <?php echo ( 5 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Five times per day', 'mainwp' ); ?></option>
637 - <option value="6" <?php echo ( 6 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Six times per day', 'mainwp' ); ?></option>
638 - <option value="7" <?php echo ( 7 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Seven times per day', 'mainwp' ); ?></option>
639 - <option value="8" <?php echo ( 8 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Eight times per day', 'mainwp' ); ?></option>
640 - <option value="9" <?php echo ( 9 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Nine times per day', 'mainwp' ); ?></option>
641 - <option value="10" <?php echo ( 10 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Ten times per day', 'mainwp' ); ?></option>
642 - <option value="11" <?php echo ( 11 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Eleven times per day', 'mainwp' ); ?></option>
643 - <option value="12" <?php echo ( 12 === $frequencyDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Twelve times per day', 'mainwp' ); ?></option>
644 - </select>
645 - </div>
646 - </div>
511 + $init_sub_subleftmenu = array();
647 512
648 - <?php
649 - self::render_timezone_settings();
650 - self::render_datetime_settings();
513 + foreach ( static::get_navigation_items( 'left_menu_core' ) as $item ) {
514 + $init_sub_subleftmenu[] = array(
515 + 'title' => $item['title'],
516 + 'parent_key' => 'Settings',
517 + 'href' => $item['href'],
518 + 'slug' => $item['slug'],
519 + 'right' => '',
520 + 'before_title' => isset( $item['before_title'] ) ? $item['before_title'] : '',
521 + );
522 + }
651 523
652 - $sidebarPosition = get_user_option( 'mainwp_sidebarPosition' );
653 - if ( false === $sidebarPosition ) {
654 - $sidebarPosition = 1;
655 - }
524 + if ( empty( $subPages ) ) {
525 + $subPages = static::get_subpages();
526 + }
656 527
657 - ?>
658 - <div class="ui grid field settings-field-indicator-general">
659 - <label class="six wide column middle aligned">
660 - <?php
661 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_sidebarPosition', (int) $sidebarPosition );
662 - esc_html_e( 'Sidebar position', 'mainwp' );
663 - ?>
664 - </label>
665 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Select if you want to show sidebar with option on left or right.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
666 - <select name="mainwp_sidebarPosition" id="mainwp_sidebarPosition" class="ui dropdown">
667 - <option value="1" <?php echo ( 1 === (int) $sidebarPosition ? 'selected' : '' ); ?>><?php esc_html_e( 'Right (default)', 'mainwp' ); ?></option>
668 - <option value="0" <?php echo ( 0 === (int) $sidebarPosition ? 'selected' : '' ); ?>><?php esc_html_e( 'Left', 'mainwp' ); ?></option>
669 - </select>
670 - </div>
671 - </div>
672 - <?php MainWP_UI::render_screen_options(); ?>
673 -
674 - <h3 class="ui dividing header">
675 - <?php echo MainWP_Settings_Indicator::get_indicator( 'header', 'settings-field-indicator-updates', 'general-settings' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
676 - <?php esc_html_e( 'Updates Settings', 'mainwp' ); ?></h3>
677 - <?php
678 - $snAutomaticDailyUpdate = (int) get_option( 'mainwp_automaticDailyUpdate', 0 );
679 - $snPluginAutomaticDailyUpdate = (int) get_option( 'mainwp_pluginAutomaticDailyUpdate', 0 );
680 - $snThemeAutomaticDailyUpdate = (int) get_option( 'mainwp_themeAutomaticDailyUpdate', 0 );
681 - $backup_before_upgrade = get_option( 'mainwp_backup_before_upgrade' );
682 - $mainwp_backup_before_upgrade_days = get_option( 'mainwp_backup_before_upgrade_days' );
683 - if ( empty( $mainwp_backup_before_upgrade_days ) || ! ctype_digit( $mainwp_backup_before_upgrade_days ) ) {
684 - $mainwp_backup_before_upgrade_days = 7;
685 - }
528 + MainWP_Menu::init_subpages_left_menu( $subPages, $init_sub_subleftmenu, 'Settings', 'Settings' );
686 529
687 - $mainwp_show_language_updates = get_option( 'mainwp_show_language_updates', 1 );
530 + foreach ( $init_sub_subleftmenu as $item ) {
531 + if ( isset( $item['item_slug'] ) ) {
532 + if ( MainWP_Menu::is_disable_menu_item( 3, $item['item_slug'] ) ) {
533 + continue;
534 + }
535 + } elseif ( MainWP_Menu::is_disable_menu_item( 3, $item['slug'] ) ) {
536 + continue;
537 + }
688 538
689 - $update_time = self::get_websites_automatic_update_time();
690 - $lastAutomaticUpdate = $update_time['last'];
691 - $nextAutomaticUpdate = $update_time['next'];
539 + MainWP_Menu::add_left_menu( $item, 2 );
540 + }
541 + }
692 542
693 - $enableLegacyBackupFeature = get_option( 'mainwp_enableLegacyBackupFeature' );
694 - $primaryBackup = get_option( 'mainwp_primaryBackup' );
695 - $disableUpdateConfirmations = (int) get_option( 'mainwp_disable_update_confirmations', 0 );
543 + /**
544 + * Render Page Header.
545 + *
546 + * @param string $shownPage The page slug shown at this moment.
547 + *
548 + * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
549 + * @uses \MainWP\Dashboard\MainWP_UI::render_top_header()
550 + * @uses \MainWP\Dashboard\MainWP_UI::render_page_navigation()
551 + */
552 + public static function render_header( $shownPage = '' ) { // phpcs:ignore -- NOSONAR - complex.
696 553
697 - $http_error_codes = MainWP_Utility::get_http_codes();
698 - ?>
699 - <div class="ui grid field settings-field-indicator-updates">
700 - <label class="six wide column middle aligned">
701 - <?php
702 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_pluginAutomaticDailyUpdate', $snPluginAutomaticDailyUpdate );
703 - esc_html_e( 'Plugin advanced automatic updates', 'mainwp' );
704 - ?>
705 - </label>
706 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Enable or disable automatic plugins updates. If enabled, MainWP will update only plugins that you have marked as Trusted.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
707 - <select name="mainwp_pluginAutomaticDailyUpdate" id="mainwp_pluginAutomaticDailyUpdate" class="ui dropdown">
708 - <option value="1" <?php echo ( 1 === $snPluginAutomaticDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Install Trusted Updates', 'mainwp' ); ?></option>
709 - <option value="0" <?php echo ( ( 0 === $snPluginAutomaticDailyUpdate ) || 2 === $snPluginAutomaticDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Disabled', 'mainwp' ); ?></option>
710 - </select>
711 - </div>
712 - </div>
713 - <div class="ui grid field settings-field-indicator-updates">
714 - <label class="six wide column middle aligned">
715 - <?php
716 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_themeAutomaticDailyUpdate', $snThemeAutomaticDailyUpdate );
717 - esc_html_e( 'Theme advanced automatic updates', 'mainwp' );
718 - ?>
719 - </label>
720 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Enable or disable automatic themes updates. If enabled, MainWP will update only themes that you have marked as Trusted.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
721 - <select name="mainwp_themeAutomaticDailyUpdate" id="mainwp_themeAutomaticDailyUpdate" class="ui dropdown">
722 - <option value="1" <?php echo ( 1 === $snThemeAutomaticDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Install Trusted Updates', 'mainwp' ); ?></option>
723 - <option value="0" <?php echo ( 0 === $snThemeAutomaticDailyUpdate || 2 === $snThemeAutomaticDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Disabled', 'mainwp' ); ?></option>
724 - </select>
725 - </div>
726 - </div>
727 - <div class="ui grid field settings-field-indicator-updates">
728 - <label class="six wide column middle aligned">
729 - <?php
730 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_automaticDailyUpdate', $snAutomaticDailyUpdate );
731 - esc_html_e( 'WP Core advanced automatic updates', 'mainwp' );
732 - ?>
733 - </label>
734 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Enable or disable automatic WordPress core updates.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
735 - <select name="mainwp_automaticDailyUpdate" id="mainwp_automaticDailyUpdate" class="ui dropdown">
736 - <option value="1" <?php echo ( 1 === $snAutomaticDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Install Trusted Updates', 'mainwp' ); ?></option>
737 - <option value="0" <?php echo ( 0 === $snAutomaticDailyUpdate || 2 === (int) $snAutomaticDailyUpdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Disabled', 'mainwp' ); ?></option>
738 - </select>
739 - </div>
740 - </div>
741 - <div class="ui grid field settings-field-indicator-updates">
742 - <label class="six wide column middle aligned">
743 - <?php
744 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_delay_autoupdate', $delay_autoupdate );
745 - esc_html_e( 'Advanced automatic updates delay', 'mainwp' );
746 - ?>
747 - </label>
748 - <div class="ten wide column ui input" data-tooltip="<?php esc_attr_e( 'Set the number of days to delay automatic updates.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
749 - <select name="mainwp_delay_autoupdate" id="mainwp_delay_autoupdate" class="ui dropdown">
750 - <option value="0" <?php echo ( 0 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( 'Delay off', 'mainwp' ); ?></option>
751 - <option value="1" <?php echo ( 1 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( '1 day', 'mainwp' ); ?></option>
752 - <option value="2" <?php echo ( 2 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( '2 days', 'mainwp' ); ?></option>
753 - <option value="3" <?php echo ( 3 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( '3 days', 'mainwp' ); ?></option>
754 - <option value="4" <?php echo ( 4 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( '4 days', 'mainwp' ); ?></option>
755 - <option value="5" <?php echo ( 5 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( '5 days', 'mainwp' ); ?></option>
756 - <option value="6" <?php echo ( 6 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( '6 days', 'mainwp' ); ?></option>
757 - <option value="7" <?php echo ( 7 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( '7 days', 'mainwp' ); ?></option>
758 - <option value="14" <?php echo ( 14 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( '14 days', 'mainwp' ); ?></option>
759 - <option value="30" <?php echo ( 30 === $delay_autoupdate ? 'selected' : '' ); ?>><?php esc_html_e( '30 days', 'mainwp' ); ?></option>
760 - </select>
761 - </div>
762 - </div>
763 - <div class="ui grid field settings-field-indicator-updates">
764 - <label class="six wide column middle aligned">
765 - <?php
766 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_show_language_updates', $mainwp_show_language_updates );
767 - esc_html_e( 'Show WordPress language updates', 'mainwp' );
768 - ?>
769 - </label>
770 - <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Enable if you want to manage Translation updates', 'mainwp' ); ?>" data-inverted="" data-position="top left">
771 - <input type="checkbox" name="mainwp_show_language_updates" id="mainwp_show_language_updates" <?php echo ( 1 === (int) $mainwp_show_language_updates ? 'checked="true"' : '' ); ?>/>
772 - </div>
773 - </div>
774 - <div class="ui grid field settings-field-indicator-updates">
775 - <label class="six wide column middle aligned">
776 - <?php
777 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_disable_update_confirmations', $disableUpdateConfirmations );
778 - esc_html_e( 'Update confirmations', 'mainwp' );
779 - ?>
780 - </label>
781 - <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Choose if you want to disable the popup confirmations when performing updates.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
782 - <select name="mainwp_disable_update_confirmations" id="mainwp_disable_update_confirmations" class="ui dropdown">
783 - <option value="0" <?php echo ( 0 === $disableUpdateConfirmations ? 'selected' : '' ); ?>><?php esc_html_e( 'Enable', 'mainwp' ); ?></option>
784 - <option value="2" <?php echo ( 2 === $disableUpdateConfirmations ? 'selected' : '' ); ?>><?php esc_html_e( 'Disable', 'mainwp' ); ?></option>
785 - <option value="1" <?php echo ( 1 === $disableUpdateConfirmations ? 'selected' : '' ); ?>><?php esc_html_e( 'Disable for single updates', 'mainwp' ); ?></option>
786 - </select>
787 - </div>
788 - </div>
789 - <div class="ui grid field settings-field-indicator-updates">
790 - <label class="six wide column middle aligned">
791 - <?php
792 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_check_http_response', get_option( 'mainwp_check_http_response', '' ) );
793 - esc_html_e( 'Check site HTTP response after update', 'mainwp' );
794 - ?>
795 - </label>
796 - <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Enable if you want your MainWP Dashboard to check child site header response after updates.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
797 - <input type="checkbox" name="mainwp_check_http_response" id="mainwp_check_http_response" <?php echo ( ( 1 === (int) get_option( 'mainwp_check_http_response', 0 ) ) ? 'checked="true"' : '' ); ?>/>
798 - </div>
799 - </div>
800 - <div class="ui grid field settings-field-indicator-updates">
801 - <label class="six wide column middle aligned">
802 - <?php
803 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_ignore_HTTP_response_status', (int) get_option( 'mainwp_ignore_HTTP_response_status', 0 ) );
804 - esc_html_e( 'Ignored HTTP response statuses', 'mainwp' );
805 - ?>
806 - </label>
807 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Select response codes that you want your MainWP Dashboard to ignore.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
808 - <div class="ui multiple selection dropdown" init-value="<?php echo esc_attr( ( get_option( 'mainwp_ignore_HTTP_response_status', '' ) ) ); ?>">
809 - <input name="mainwp_ignore_http_response_status" type="hidden">
810 - <i class="dropdown icon"></i>
811 - <div class="default text"></div>
812 - <div class="menu">
813 - <?php
814 - foreach ( $http_error_codes as $error_code => $label ) {
815 - ?>
816 - <div class="item" data-value="<?php echo esc_attr( $error_code ); ?>"><?php echo esc_html( $error_code . ' (' . $label . ')' ); ?></div>
817 - <?php
818 - }
819 - ?>
820 - </div>
821 - </div>
822 - </div>
823 - </div>
824 - <?php if ( ( ( $enableLegacyBackupFeature && empty( $primaryBackup ) ) || ( empty( $enableLegacyBackupFeature ) && ! empty( $primaryBackup ) ) ) ) { ?>
825 - <div class="ui grid field mainwp-parent-toggle settings-field-indicator-updates">
826 - <label class="six wide column middle aligned">
827 - <?php
828 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_backup_before_upgrade', (int) $backup_before_upgrade );
829 - esc_html_e( 'Require a backup before an update', 'mainwp' );
830 - ?>
831 - </label>
832 - <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'If enabled, your MainWP Dashboard will check if full backups exists before updating.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
833 - <input type="checkbox" name="mainwp_backup_before_upgrade" id="mainwp_backup_before_upgrade" <?php echo ( 1 === (int) $backup_before_upgrade ? 'checked="true"' : '' ); ?>/>
834 - </div>
835 - </div>
836 - <div class="ui grid field mainwp-child-field settings-field-indicator-updates" <?php echo ( 1 === (int) $backup_before_upgrade ? '' : 'style="display:none"' ); ?> >
837 - <label class="six wide column middle aligned">
838 - <?php
839 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_backup_before_upgrade_days', (int) $mainwp_backup_before_upgrade_days );
840 - esc_html_e( 'Days without of a full backup tolerance', 'mainwp' );
841 - ?>
842 - </label>
843 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Set the number of days without of backup tolerance.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
844 - <input type="text" name="mainwp_backup_before_upgrade_days" id="mainwp_backup_before_upgrade_days" value="<?php echo esc_attr( $mainwp_backup_before_upgrade_days ); ?>" />
845 - </div>
846 - </div>
847 - <?php } ?>
554 + $params = array(
555 + 'title' => esc_html__( 'MainWP Settings', 'mainwp' ),
556 + );
848 557
849 - <div class="ui grid field settings-field-indicator-updates">
850 - <label class="six wide column middle aligned">
851 - <?php
852 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_numberdays_Outdate_Plugin_Theme', (int) get_option( 'mainwp_numberdays_Outdate_Plugin_Theme', 365 ) );
558 + MainWP_UI::render_top_header( $params );
853 559
854 - esc_html_e( 'Abandoned plugins/themes tolerance', 'mainwp' );
855 - ?>
856 - </label>
857 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Set how many days without an update before plugin or theme will be considered as abandoned.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
858 - <input type="text" name="mainwp_numberdays_Outdate_Plugin_Theme" id="mainwp_numberdays_Outdate_Plugin_Theme" value="<?php echo ( ( false === get_option( 'mainwp_numberdays_Outdate_Plugin_Theme' ) ) ? 365 : intval( get_option( 'mainwp_numberdays_Outdate_Plugin_Theme' ) ) ); ?>"/>
859 - </div>
860 - </div>
861 - <?php MainWP_Monitoring_View::render_settings(); ?>
862 - <?php MainWP_Manage_Backups::render_settings(); ?>
863 - <?php
864 - /**
865 - * Action: mainwp_settings_form_bottom
866 - *
867 - * Fires at the bottom of settings form.
868 - *
869 - * @since 4.1
870 - */
871 - do_action( 'mainwp_settings_form_bottom' );
872 - ?>
873 - <div class="ui divider"></div>
874 - <input type="submit" name="submit" id="submit" class="ui button green big" value="<?php esc_attr_e( 'Save Settings', 'mainwp' ); ?>"/>
875 - <div style="clear:both"></div>
876 - </form>
877 - </div>
878 - </div>
879 - <?php
880 - self::render_footer( '' );
881 - }
560 + $renderItems = array();
882 561
883 - /**
884 - * Render Timezone settings.
885 - */
886 - public static function render_timezone_settings() {
562 + foreach ( static::get_navigation_items() as $item ) {
563 + $render_item = array(
564 + 'title' => $item['title'],
565 + 'href' => $item['href'],
566 + 'active' => in_array( $shownPage, $item['active_keys'], true ),
567 + );
887 568
888 - $current_offset = get_option( 'gmt_offset' );
889 - $tzstring = get_option( 'timezone_string' );
890 - $check_zone_info = true;
569 + if ( ! empty( $item['before_title'] ) ) {
570 + $render_item['before_title'] = $item['before_title'];
571 + }
891 572
892 - // Remove old Etc mappings. Fallback to gmt_offset.
893 - if ( false !== strpos( $tzstring, 'Etc/GMT' ) ) {
894 - $tzstring = '';
895 - }
573 + if ( isset( $item['class'] ) ) {
574 + $render_item['class'] = $item['class'];
575 + }
896 576
897 - if ( empty( $tzstring ) ) { // Create a UTC+- zone if no timezone string exists.
898 - $check_zone_info = false;
899 - if ( empty( $current_offset ) ) {
900 - $tzstring = 'UTC+0';
901 - } elseif ( $current_offset < 0 ) {
902 - $tzstring = 'UTC' . $current_offset;
903 - } else {
904 - $tzstring = 'UTC+' . $current_offset;
905 - }
906 - }
577 + $renderItems[] = $render_item;
578 + }
907 579
908 - $timezone_format = _x( 'Y-m-d H:i:s', 'timezone date format' );
580 + MainWP_UI::render_page_navigation( $renderItems, 'nav_mainwp_settings' );
581 + }
909 582
910 - ?>
911 - <div class="ui grid field settings-field-indicator-general">
912 - <label class="six wide column middle aligned"><?php esc_html_e( 'Timezone', 'mainwp' ); ?></label>
913 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Choose either a city in the same timezone as you or a %s (Coordinated Universal Time) time offset.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
914 - <select id="timezone_string" class="ui dropdown" name="timezone_string" aria-describedby="timezone-description">
915 - <?php echo wp_timezone_choice( $tzstring, get_user_locale() ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
916 - </select>
917 - <div class="ui hidden fitted divider"></div>
918 - <div class="ui secondary segment">
919 - <?php printf( esc_html__( 'Universal time is %s.' ), '<code>' . esc_html( date_i18n( $timezone_format, false, true ) ) . '</code>' ); ?>
920 - <div class="ui hidden fitted divider"></div>
921 - <?php if ( get_option( 'timezone_string' ) || ! empty( $current_offset ) ) : ?>
922 - <?php printf( esc_html__( 'Local time is %s.' ), '<code>' . esc_html( date_i18n( $timezone_format ) ) . '</code>' ); ?>
923 - <div class="ui hidden fitted divider"></div>
924 - <?php endif; ?>
925 - <?php if ( $check_zone_info && $tzstring ) : ?>
926 - <?php
927 - $now = new \DateTime( 'now', new \DateTimeZone( $tzstring ) );
928 - $dst = (bool) $now->format( 'I' );
583 + /**
584 + * Close the HTML container.
585 + */
586 + public static function render_footer() {
587 + echo '</div>';
588 + }
929 589
930 - if ( $dst ) {
931 - esc_html_e( 'This timezone is currently in daylight saving time.', 'mainwp' );
932 - } else {
933 - esc_html_e( 'This timezone is currently in standard time.', 'mainwp' );
934 - }
935 - ?>
936 - <div class="ui hidden fitted divider"></div>
937 - <?php
938 - if ( in_array( $tzstring, timezone_identifiers_list(), true ) ) {
939 - $transitions = timezone_transitions_get( timezone_open( $tzstring ), time() );
590 + /**
591 + * Method handle_settings_post().
592 + *
593 + * This class handles the $_POST of Settings Options.
594 + *
595 + * @uses MainWP_DB::instance()
596 + * @uses MainWP_Utility::update_option()
597 + *
598 + * @return boolean True|False Posts On True.
599 + *
600 + * @uses \MainWP\Dashboard\MainWP_DB_Common::get_user_extension()
601 + * @uses \MainWP\Dashboard\MainWP_DB_Common::update_user_extension()
602 + * @uses \MainWP\Dashboard\MainWP_System_Utility::is_admin()
603 + * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
604 + */
605 + public static function handle_settings_post() { // phpcs:ignore -- NOSONAR - complex.
606 + if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'Settings' ) ) {
607 + $userExtension = MainWP_DB_Common::instance()->get_user_extension();
608 + $userExtension->pluginDir = '';
940 609
941 - if ( ! empty( $transitions[1] ) ) {
942 - echo ' ';
943 - $message = $transitions[1]['isdst'] ? esc_html__( 'Daylight saving time begins on: %s.', 'mainwp' ) : esc_html__( 'Standard time begins on: %s.', 'mainwp' );
944 - printf( $message, '<code>' . wp_date( esc_html__( 'F j, Y' ) . ' ' . esc_html__( 'g:i a' ), esc_html( $transitions[1]['ts'] ) ) . '</code>' ); // phpcs:ignore WordPress.Security.EscapeOutput
945 - } else {
946 - esc_html_e( 'This timezone does not observe daylight saving time.', 'mainwp' );
947 - }
948 - }
949 - ?>
950 - <?php endif; ?>
951 - </div>
952 - </div>
953 - </div>
954 - <?php
955 - }
610 + MainWP_DB_Common::instance()->update_user_extension( $userExtension );
611 + if ( MainWP_System_Utility::is_admin() ) {
956 612
957 - /**
958 - * Render Date/Time settings.
959 - */
960 - public static function render_datetime_settings() {
961 - ?>
962 - <div class="ui grid field settings-field-indicator-general">
963 - <label class="six wide column middle aligned">
964 - <?php
965 - MainWP_Settings_Indicator::render_not_default_indicator( 'date_formats', get_option( 'date_format' ) );
966 - esc_html_e( 'Date format', 'mainwp' );
967 - ?>
968 - </label>
969 - <div class="ten wide column fieldset-wrapper" data-tooltip="<?php esc_attr_e( 'Choose the display format for date.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
970 - <?php
971 - /**
972 - * Filters the default date formats.
973 - *
974 - * @since 2.7.0
975 - * @since 4.0.0 Added ISO date standard YYYY-MM-DD format.
976 - *
977 - * @param string[] $default_date_formats Array of default date formats.
978 - */
979 - $date_formats = array_unique( apply_filters( 'date_formats', array( esc_html__( 'F j, Y' ), 'Y-m-d', 'm/d/Y', 'd/m/Y' ) ) );
613 + $old_settings = self::get_all_settings_values();
980 614
981 - $custom = true;
615 + /**
616 + * Action: mainwp_before_save_general_settings
617 + *
618 + * Fires before general settings save.
619 + *
620 + * @since 4.1
621 + */
622 + do_action( 'mainwp_before_save_general_settings', $_POST );
982 623
983 - foreach ( $date_formats as $format ) {
984 - echo "\t<label><input type='radio' name='date_format' value='" . esc_attr( $format ) . "'";
985 - if ( get_option( 'date_format' ) === $format ) { // checked() uses "==" rather than "===".
986 - echo " checked='checked'";
987 - $custom = false;
988 - }
989 - echo ' /> <span class="date-time-text format-i18n">' . esc_html( date_i18n( $format ) ) . '</span><code>' . esc_html( $format ) . "</code></label><br />\n";
990 - }
624 + $val = ( ! isset( $_POST['mainwp_pluginAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_pluginAutomaticDailyUpdate'] ) );
625 + MainWP_Utility::update_option( 'mainwp_pluginAutomaticDailyUpdate', $val );
626 + $val = ( ! isset( $_POST['mainwp_themeAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_themeAutomaticDailyUpdate'] ) );
627 + MainWP_Utility::update_option( 'mainwp_themeAutomaticDailyUpdate', $val );
628 + $val = ( ! isset( $_POST['mainwp_transAutomaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_transAutomaticDailyUpdate'] ) );
629 + MainWP_Utility::update_option( 'mainwp_transAutomaticDailyUpdate', $val );
630 + $val = ( ! isset( $_POST['mainwp_automaticDailyUpdate'] ) ? 0 : intval( $_POST['mainwp_automaticDailyUpdate'] ) );
631 + MainWP_Utility::update_option( 'mainwp_automaticDailyUpdate', $val );
632 + $val = ( ! isset( $_POST['mainwp_show_language_updates'] ) ? 0 : 1 );
633 + MainWP_Utility::update_option( 'mainwp_show_language_updates', $val );
634 + $val = ( ! isset( $_POST['mainwp_disable_update_confirmations'] ) ? 0 : intval( $_POST['mainwp_disable_update_confirmations'] ) );
635 + MainWP_Utility::update_option( 'mainwp_disable_update_confirmations', $val );
636 + $val = ( ! isset( $_POST['mainwp_backup_before_upgrade'] ) ? 0 : 1 );
637 + MainWP_Utility::update_option( 'mainwp_backup_before_upgrade', $val );
638 + $val = ( ! isset( $_POST['mainwp_backup_before_upgrade_days'] ) ? 7 : intval( $_POST['mainwp_backup_before_upgrade_days'] ) );
639 + MainWP_Utility::update_option( 'mainwp_backup_before_upgrade_days', $val );
991 640
992 - echo '<label><input type="radio" name="date_format" id="date_format_custom_radio" value="\c\u\s\t\o\m"';
993 - checked( $custom );
994 - echo '/> <span class="date-time-text date-time-custom-text">' . esc_html__( 'Custom:' ) . '<span class="screen-reader-text"> ' . esc_html__( 'enter a custom date format in the following field' ) . '</span></span></label>' .
995 - '<label for="date_format_custom" class="screen-reader-text">' . esc_html__( 'Custom date format:' ) . '</label>' .
996 - '<input type="text" name="date_format_custom" id="date_format_custom" value="' . esc_attr( get_option( 'date_format' ) ) . '" class="small-text" />' .
997 - '<br />' .
998 - '<em><strong>' . esc_html__( 'Preview:' ) . '</strong> <span class="example">' . esc_html( date_i18n( get_option( 'date_format' ) ) ) . '</span>' .
999 - "<span class='spinner'></span>\n" . '</em>';
1000 - ?>
1001 - </div>
1002 - </div>
641 + if ( is_plugin_active( 'mainwp-comments-extension/mainwp-comments-extension.php' ) ) {
642 + MainWP_Utility::update_option( 'mainwp_maximumComments', isset( $_POST['mainwp_maximumComments'] ) ? intval( $_POST['mainwp_maximumComments'] ) : 50 );
643 + }
1003 644
1004 - <div class="ui grid field">
1005 - <label class="six wide column middle aligned">
1006 - <?php
1007 - MainWP_Settings_Indicator::render_not_default_indicator( 'time_format', get_option( 'time_format' ) );
1008 - esc_html_e( 'Time format', 'mainwp' );
1009 - ?>
1010 - </label>
1011 - <div class="ten wide column fieldset-wrapper" data-tooltip="<?php esc_attr_e( 'Choose the display format for time.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1012 - <?php
1013 - /**
1014 - * Filters the default time formats.
1015 - *
1016 - * @since 2.7.0
1017 - *
1018 - * @param string[] $default_time_formats Array of default time formats.
1019 - */
1020 - $time_formats = array_unique( apply_filters( 'time_formats', array( esc_html__( 'g:i a' ), 'g:i A', 'H:i' ) ) );
645 + $current_timeDailyUpdate = get_option( 'mainwp_timeDailyUpdate' );
646 + $new_timeDailyUpdate = isset( $_POST['mainwp_timeDailyUpdate'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_timeDailyUpdate'] ) ) : '';
1021 647
1022 - $custom = true;
648 + if ( $current_timeDailyUpdate !== $new_timeDailyUpdate ) {
649 + MainWP_Utility::update_option( 'mainwp_timeDailyUpdate', $new_timeDailyUpdate );
650 + }
1023 651
1024 - foreach ( $time_formats as $format ) {
1025 - echo "\t<label><input type='radio' name='time_format' value='" . esc_attr( $format ) . "'";
1026 - if ( get_option( 'time_format' ) === $format ) { // checked() uses "==" rather than "===".
1027 - echo " checked='checked'";
1028 - $custom = false;
1029 - }
1030 - echo ' /> <span class="date-time-text format-i18n">' . esc_html( date_i18n( $format ) ) . '</span><code>' . esc_html( $format ) . "</code></label><br />\n";
1031 - }
1032 - echo '<label><input type="radio" name="time_format" id="time_format_custom_radio" value="\c\u\s\t\o\m"';
1033 - checked( $custom );
1034 - echo '/> <span class="date-time-text date-time-custom-text">' . esc_html__( 'Custom:' ) . '<span class="screen-reader-text"> ' . esc_html__( 'enter a custom time format in the following field' ) . '</span></span></label>' .
1035 - '<label for="time_format_custom" class="screen-reader-text">' . esc_html__( 'Custom time format:' ) . '</label>' .
1036 - '<input type="text" name="time_format_custom" id="time_format_custom" value="' . esc_attr( get_option( 'time_format' ) ) . '" class="small-text" />' .
1037 - '<br />' .
1038 - '<em><strong>' . esc_html__( 'Preview:' ) . '</strong> <span class="example">' . esc_html( date_i18n( get_option( 'time_format' ) ) ) . '</span>' .
1039 - "<span class='spinner'></span>\n" . '</em>';
1040 - ?>
1041 - </div>
1042 - </div>
1043 - <script type="text/javascript">
1044 - jQuery(document).ready( function($) {
1045 - $( 'input[name="date_format"]' ).on( 'click', function() {
1046 - if ( 'date_format_custom_radio' !== $( this ).attr( 'id' ) )
1047 - $( 'input[name="date_format_custom"]' ).val( $( this ).val() ).closest( '.fieldset-wrapper' ).find( '.example' ).text( $( this ).parent( 'label' ).children( '.format-i18n' ).text() );
1048 - } );
652 + $old_freq = (int) get_option( 'mainwp_frequencyDailyUpdate', 2 );
653 + $new_freq = ( isset( $_POST['mainwp_frequencyDailyUpdate'] ) ? intval( $_POST['mainwp_frequencyDailyUpdate'] ) : 2 );
654 + if ( $old_freq !== $new_freq ) {
655 + MainWP_Utility::update_option( 'mainwp_frequencyDailyUpdate', $new_freq );
656 + MainWP_Logger::instance()->log_update_check( 'New frequency daily :: ' . $new_freq );
657 + }
1049 658
1050 - $( 'input[name="date_format_custom"]' ).on( 'click input', function() {
1051 - $( '#date_format_custom_radio' ).prop( 'checked', true );
1052 - } );
659 + $curr_frequency_updates = get_option( 'mainwp_frequency_AutoUpdate', 'daily' );
660 + $new_frequency_updates = isset( $_POST['mainwp_frequency_AutoUpdate'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_frequency_AutoUpdate'] ) ) : 'daily';
661 + if ( $new_frequency_updates !== $curr_frequency_updates ) {
662 + MainWP_Utility::update_option( 'mainwp_frequency_AutoUpdate', $new_frequency_updates );
663 + }
1053 664
1054 - $( 'input[name="time_format"]' ).on( 'click', function() {
1055 - if ( 'time_format_custom_radio' !== $(this).attr( 'id' ) )
1056 - $( 'input[name="time_format_custom"]' ).val( $( this ).val() ).closest( '.fieldset-wrapper' ).find( '.example' ).text( $( this ).parent( 'label' ).children( '.format-i18n' ).text() );
1057 - } );
665 + $curr_day_updates = (int) get_option( 'mainwp_dayinweek_AutoUpdate', 0 );
666 + $new_day_updates = isset( $_POST['mainwp_dayinweek_AutoUpdate'] ) ? intval( wp_unslash( $_POST['mainwp_dayinweek_AutoUpdate'] ) ) : 0;
667 + if ( $new_day_updates !== $curr_day_updates ) {
668 + MainWP_Utility::update_option( 'mainwp_dayinweek_AutoUpdate', $new_day_updates );
669 + }
1058 670
1059 - $( 'input[name="time_format_custom"]' ).on( 'click input', function() {
1060 - $( '#time_format_custom_radio' ).prop( 'checked', true );
1061 - } );
671 + $curr_dayinmonth_updates = (int) get_option( 'mainwp_dayinmonth_AutoUpdate', 1 );
672 + $new_dayinmonth_updates = isset( $_POST['mainwp_dayinmonth_AutoUpdate'] ) ? intval( wp_unslash( $_POST['mainwp_dayinmonth_AutoUpdate'] ) ) : 1;
673 + if ( $new_dayinmonth_updates !== $curr_dayinmonth_updates ) {
674 + MainWP_Utility::update_option( 'mainwp_dayinmonth_AutoUpdate', $new_dayinmonth_updates );
675 + }
1062 676
1063 - $( 'input[name="date_format_custom"], input[name="time_format_custom"]' ).on( 'input', function() {
1064 - var format = $( this ),
1065 - fieldset = format.closest( '.fieldset-wrapper' ),
1066 - example = fieldset.find( '.example' ),
1067 - spinner = fieldset.find( '.spinner' );
677 + $curr_time_updates = get_option( 'mainwp_time_AutoUpdate', '00:00' );
678 + $new_time_updates = isset( $_POST['mainwp_time_AutoUpdate'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_time_AutoUpdate'] ) ) : '00:00';
679 + if ( $new_time_updates !== $curr_time_updates ) {
680 + MainWP_Utility::update_option( 'mainwp_time_AutoUpdate', $new_time_updates );
681 + }
1068 682
1069 - // Debounce the event callback while users are typing.
1070 - clearTimeout( $.data( this, 'timer' ) );
1071 - $( this ).data( 'timer', setTimeout( function() {
1072 - // If custom date is not empty.
1073 - if ( format.val() ) {
1074 - spinner.addClass( 'is-active' );
683 + MainWP_Cron_Jobs_Auto_Updates::set_next_auto_updates_time();
1075 684
1076 - $.post( ajaxurl, {
1077 - action: 'date_format_custom' === format.attr( 'name' ) ? 'date_format' : 'time_format',
1078 - date : format.val()
1079 - }, function( d ) { spinner.removeClass( 'is-active' ); example.text( d ); } );
1080 - }
1081 - }, 500 ) );
1082 - } );
1083 - });
1084 - </script>
1085 - <?php
1086 - }
685 + $new_delay = ( isset( $_POST['mainwp_delay_autoupdate'] ) ? intval( $_POST['mainwp_delay_autoupdate'] ) : 1 );
686 + MainWP_Utility::update_option( 'mainwp_delay_autoupdate', $new_delay );
1087 687
1088 - /**
1089 - * Method get_websites_automatic_update_time()
1090 - *
1091 - * Get websites automatic update time.
1092 - *
1093 - * @return mixed array
1094 - *
1095 - * @uses \MainWP\Dashboard\MainWP_DB::get_websites_last_automatic_sync()
1096 - * @uses \MainWP\Dashboard\MainWP_DB::get_websites_count_where_dts_automatic_sync_smaller_then_start()
1097 - * @uses \MainWP\Dashboard\MainWP_Utility::format_timestamp()
1098 - */
1099 - public static function get_websites_automatic_update_time() {
1100 - $lastAutomaticUpdate = MainWP_DB::instance()->get_websites_last_automatic_sync();
1101 - $lasttimeAutomatic = get_option( 'mainwp_updatescheck_last_timestamp' );
1102 - $lasttimeStartAutomatic = get_option( 'mainwp_updatescheck_start_last_timestamp' );
1103 - $local_timestamp = MainWP_Utility::get_timestamp();
1104 - $running = get_option( 'mainwp_cron_checksites_running' );
688 + $val = ( isset( $_POST['mainwp_sidebarPosition'] ) ? intval( $_POST['mainwp_sidebarPosition'] ) : 1 );
689 + $user = wp_get_current_user();
690 + if ( $user ) {
691 + update_user_option( $user->ID, 'mainwp_sidebarPosition', $val, true );
692 + }
1105 693
1106 - if ( empty( $lasttimeStartAutomatic ) && ! empty( $lasttimeAutomatic ) ) {
1107 - $lasttimeStartAutomatic = $lasttimeAutomatic;
1108 - }
694 + MainWP_Utility::update_option( 'mainwp_numberdays_Outdate_Plugin_Theme', ! empty( $_POST['mainwp_numberdays_Outdate_Plugin_Theme'] ) ? intval( $_POST['mainwp_numberdays_Outdate_Plugin_Theme'] ) : 365 );
1109 695
1110 - if ( empty( $lastAutomaticUpdate ) ) {
1111 - $nextAutomaticUpdate = esc_html__( 'Any minute', 'mainwp' );
1112 - } elseif ( 'yes' === $running && ( 0 < MainWP_DB::instance()->get_websites_count_where_dts_automatic_sync_smaller_then_start( $lasttimeStartAutomatic ) || 0 < MainWP_DB::instance()->get_websites_check_updates_count( $lasttimeStartAutomatic ) ) ) {
1113 - $nextAutomaticUpdate = esc_html__( 'Processing your websites.', 'mainwp' );
1114 - } else {
1115 - $next_time = MainWP_System_Cron_Jobs::get_next_time_automatic_update_to_show();
1116 - if ( $next_time < $local_timestamp + 5 * MINUTE_IN_SECONDS ) {
1117 - $nextAutomaticUpdate = esc_html__( 'Any minute', 'mainwp' );
1118 - } else {
1119 - $nextAutomaticUpdate = MainWP_Utility::format_timestamp( $next_time );
1120 - }
1121 - }
696 + $actions_notification_enable = ( isset( $_POST['mainwp_site_actions_notification_enable'] ) ? 1 : 0 );
697 + MainWP_Utility::update_option( 'mainwp_site_actions_notification_enable', $actions_notification_enable );
1122 698
1123 - if ( empty( $lastAutomaticUpdate ) ) {
1124 - $lastAutomaticUpdate = esc_html__( 'Never', 'mainwp' );
1125 - } else {
1126 - $lastAutomaticUpdate = MainWP_Utility::format_timestamp( $lastAutomaticUpdate );
1127 - }
699 + //phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
700 + // Handle custom date/time formats.
701 + if ( ! empty( $_POST['date_format'] ) && isset( $_POST['date_format_custom'] )
702 + && '\c\u\s\t\o\m' === wp_unslash( $_POST['date_format'] )
703 + ) {
704 + $_POST['date_format'] = wp_unslash( $_POST['date_format_custom'] );
705 + }
1128 706
1129 - return array(
1130 - 'last' => $lastAutomaticUpdate,
1131 - 'next' => $nextAutomaticUpdate,
1132 - );
1133 - }
707 + if ( ! empty( $_POST['time_format'] ) && isset( $_POST['time_format_custom'] )
708 + && '\c\u\s\t\o\m' === wp_unslash( $_POST['time_format'] )
709 + ) {
710 + $_POST['time_format'] = wp_unslash( $_POST['time_format_custom'] );
711 + }
1134 712
1135 - /**
1136 - * Returns false or the location of the OpenSSL Lib File.
1137 - *
1138 - * @return mixed false|opensslLibLocation
1139 - *
1140 - * @uses \MainWP\Dashboard\MainWP_Server_Information_Handler::is_openssl_config_warning()
1141 - */
1142 - public static function show_openssl_lib_config() {
1143 - if ( MainWP_Server_Information_Handler::is_openssl_config_warning() ) {
1144 - return true;
1145 - } else {
1146 - return false;
1147 - }
1148 - }
713 + if ( isset( $_POST['timezone_string'] ) ) {
714 + // Map UTC+- timezones to gmt_offsets and set timezone_string to empty.
715 + if ( ! empty( $_POST['timezone_string'] ) && preg_match( '/^UTC[+-]/', wp_unslash( $_POST['timezone_string'] ) ) ) {
716 + $_POST['gmt_offset'] = wp_unslash( $_POST['timezone_string'] );
717 + $_POST['gmt_offset'] = preg_replace( '/UTC\+?/', '', wp_unslash( $_POST['gmt_offset'] ) ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
718 + $_POST['timezone_string'] = '';
719 + }
1149 720
1150 - /**
1151 - * Render Advanced Options Subpage.
1152 - *
1153 - * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
1154 - */
1155 - public static function render_advanced() { //phpcs:ignore -- complex method.
1156 - if ( ! mainwp_current_user_have_right( 'dashboard', 'manage_dashboard_settings' ) ) {
1157 - mainwp_do_not_have_permissions( esc_html__( 'manage dashboard settings', 'mainwp' ) );
1158 - return;
1159 - }
721 + $options = array(
722 + 'gmt_offset',
723 + 'date_format',
724 + 'time_format',
725 + 'timezone_string',
726 + );
1160 727
1161 - if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'SettingsAdvanced' ) ) {
728 + foreach ( $options as $option ) {
729 + $value = null;
730 + if ( isset( $_POST[ $option ] ) ) {
731 + $value = wp_unslash( $_POST[ $option ] );
732 + if ( ! is_array( $value ) ) {
733 + $value = trim( $value );
734 + }
735 + }
736 + update_option( $option, $value );
737 + }
738 + }
739 + //phpcs:enable
1162 740
1163 - /**
1164 - * Action: mainwp_before_save_advanced_settings
1165 - *
1166 - * Fires before save advanced settings.
1167 - *
1168 - * @since 4.1
1169 - */
1170 - do_action( 'mainwp_before_save_advanced_settings', $_POST );
741 + MainWP_Utility::update_option( 'mainwp_use_favicon', 1 );
742 + /**
743 + * Action: mainwp_after_save_general_settings
744 + *
745 + * Fires after save general settings.
746 + *
747 + * @since 4.1
748 + */
749 + do_action( 'mainwp_after_save_general_settings', $_POST );
1171 750
1172 - MainWP_Utility::update_option( 'mainwp_maximumRequests', ! empty( $_POST['mainwp_maximumRequests'] ) ? intval( $_POST['mainwp_maximumRequests'] ) : 4 );
1173 - MainWP_Utility::update_option( 'mainwp_minimumDelay', ! empty( $_POST['mainwp_minimumDelay'] ) ? intval( $_POST['mainwp_minimumDelay'] ) : 200 );
1174 - MainWP_Utility::update_option( 'mainwp_maximumIPRequests', ! empty( $_POST['mainwp_maximumIPRequests'] ) ? intval( $_POST['mainwp_maximumIPRequests'] ) : 1 );
1175 - MainWP_Utility::update_option( 'mainwp_minimumIPDelay', ! empty( $_POST['mainwp_minimumIPDelay'] ) ? intval( $_POST['mainwp_minimumIPDelay'] ) : 1000 );
1176 - MainWP_Utility::update_option( 'mainwp_maximumSyncRequests', ! empty( $_POST['mainwp_maximumSyncRequests'] ) ? intval( $_POST['mainwp_maximumSyncRequests'] ) : 8 );
1177 - MainWP_Utility::update_option( 'mainwp_maximumInstallUpdateRequests', ! empty( $_POST['mainwp_maximumInstallUpdateRequests'] ) ? intval( $_POST['mainwp_maximumInstallUpdateRequests'] ) : 3 );
1178 - MainWP_Utility::update_option( 'mainwp_sslVerifyCertificate', isset( $_POST['mainwp_sslVerifyCertificate'] ) ? 1 : 0 );
1179 - MainWP_Utility::update_option( 'mainwp_connect_signature_algo', isset( $_POST['mainwp_settings_openssl_alg'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_settings_openssl_alg'] ) ) : 0 );
1180 - MainWP_Utility::update_option( 'mainwp_verify_connection_method', isset( $_POST['mainwp_settings_verify_connection_method'] ) ? intval( $_POST['mainwp_settings_verify_connection_method'] ) : 0 );
1181 - MainWP_Utility::update_option( 'mainwp_forceUseIPv4', isset( $_POST['mainwp_forceUseIPv4'] ) ? 1 : 0 );
1182 - MainWP_Utility::update_option( 'mainwp_wp_cron', ( ! isset( $_POST['mainwp_options_wp_cron'] ) ? 0 : 1 ) );
1183 - MainWP_Utility::update_option( 'mainwp_optimize', ( ! isset( $_POST['mainwp_optimize'] ) ? 0 : 1 ) );
751 + $new_settings = self::get_all_settings_values();
1184 752
1185 - if ( isset( $_POST['mainwp_openssl_lib_location'] ) ) {
1186 - $openssl_loc = ! empty( $_POST['mainwp_openssl_lib_location'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_openssl_lib_location'] ) ) : '';
1187 - MainWP_Utility::update_option( 'mainwp_opensslLibLocation', $openssl_loc );
1188 - }
753 + /**
754 + * Action: mainwp_after_save_settings
755 + *
756 + * Fires after save settings.
757 + *
758 + * @since 6.0
759 + *
760 + * @param array $new_settings The new settings.
761 + * @param array $old_settings The old settings.
762 + */
763 + do_action( 'mainwp_after_save_settings', $new_settings, $old_settings );
1189 764
1190 - /**
1191 - * Action: mainwp_after_save_advanced_settings
1192 - *
1193 - * Fires after advanced settings save.
1194 - *
1195 - * @since 4.1
1196 - */
1197 - do_action( 'mainwp_after_save_advanced_settings', $_POST );
1198 - }
1199 - self::render_header( 'Advanced' );
1200 - ?>
765 + }
1201 766
1202 - <div id="mainwp-advanced-settings" class="ui segment">
1203 - <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-advanced-settings-info-notice' ) ) : ?>
1204 - <div class="ui info message">
1205 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-advanced-settings-info-notice"></i>
1206 - <?php echo esc_html__( 'Set how many requests are performed at once and delay between requests in order to optimize your MainWP Dashboard performance. Both Cross IP and IP Settings handle the majority of work connecting to your Child sites, while the sync, update, and installation request have specialized options under the Frontend Requests Settings section.', 'mainwp' ); ?>
1207 - </div>
1208 - <?php endif; ?>
1209 - <?php if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'SettingsAdvanced' ) ) : ?>
1210 - <div class="ui green message"><i class="close icon"></i><?php esc_html_e( 'Settings have been saved successfully!', 'mainwp' ); ?></div>
1211 - <?php endif; ?>
1212 - <div class="ui form">
1213 - <form method="POST" action="">
1214 - <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
1215 - <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'SettingsAdvanced' ) ); ?>" />
1216 - <?php
767 + return true;
768 + }
1217 769
1218 - /**
1219 - * Action: mainwp_advanced_settings_form_top
1220 - *
1221 - * Fires at the top of advanced settings form.
1222 - *
1223 - * @since 4.1
1224 - */
1225 - do_action( 'mainwp_advanced_settings_form_top' );
770 + return false;
771 + }
1226 772
1227 - if ( self::show_openssl_lib_config() ) {
1228 - $openssl_loc = MainWP_System_Utility::get_openssl_conf();
1229 - ?>
1230 - <h3 class="ui dividing header">
1231 - <?php esc_html_e( 'OpenSSL Settings', 'mainwp' ); ?>
1232 - <div class="sub header"><?php esc_html_e( 'Due to bug with PHP on some servers it is required to set the OpenSSL Library location so MainWP Dashboard can connect to your child sites.', 'mainwp' ); ?></div>
1233 - </h3>
1234 - <div class="ui grid field">
1235 - <label class="six wide column middle aligned"><?php esc_html_e( 'OpenSSL.cnf location', 'mainwp' ); ?></label>
1236 - <div class="ten wide column ui field">
1237 - <input type="text" name="mainwp_openssl_lib_location" value="<?php echo esc_html( $openssl_loc ); ?>">
1238 - <em><?php esc_html_e( 'If your openssl.cnf file is saved to a different path from what is entered please enter your exact path.', 'mainwp' ); ?> <?php printf( esc_html__( 'If you are not sure how to find the openssl.cnf location, please %1$scheck this help document%2$s.', 'mainwp' ), '<a href="https://kb.mainwp.com/docs/how-to-find-the-openssl-cnf-file/" target="_blank">', '</a> <i class="external alternate icon"></i>' ); ?></em>
1239 - <em><?php esc_html_e( 'If you have confirmed the placement of your openssl.cnf and are still receiving an error banner, click the "Error Fixed" button to dismiss it.', 'mainwp' ); ?></em>
1240 - </div>
1241 - </div>
1242 - <?php } ?>
773 + /**
774 + * Method get_all_settings_values().
775 + *
776 + * @param mixed $keys_only True if get Keys only.
777 + *
778 + * @return array All Settings Fields.
779 + */
780 + public static function get_all_settings_values( $keys_only = false ) {
781 + $keys = array(
782 + 'mainwp_hide_update_everything',
783 + 'mainwp_pluginAutomaticDailyUpdate',
784 + 'mainwp_themeAutomaticDailyUpdate',
785 + 'mainwp_transAutomaticDailyUpdate',
786 + 'mainwp_automaticDailyUpdate',
787 + 'mainwp_show_language_updates',
788 + 'mainwp_disable_update_confirmations',
789 + 'mainwp_backup_before_upgrade',
790 + 'mainwp_backup_before_upgrade_days',
791 + 'mainwp_maximumComments',
792 + 'mainwp_automatic_update_next_run_timestamp',
793 + 'mainwp_delay_autoupdate',
794 + 'mainwp_numberdays_Outdate_Plugin_Theme',
795 + 'mainwp_check_http_response',
796 + 'mainwp_check_http_response_method',
797 + 'mainwp_site_actions_notification_enable',
798 + 'mainwp_use_favicon',
799 + 'mainwp_backupsOnServer',
800 + 'mainwp_maximumFileDescriptors',
801 + 'mainwp_maximumFileDescriptorsAuto',
802 + 'mainwp_backupOnExternalSources',
803 + 'mainwp_archiveFormat',
804 + 'mainwp_notificationOnBackupFail',
805 + 'mainwp_notificationOnBackupStart',
806 + 'mainwp_chunkedBackupTasks',
807 + 'mainwp_primaryBackup',
808 + 'mainwp_enableLegacyBackupFeature',
809 + 'mainwp_global_uptime_monitoring_settings',
810 + 'mainwp_disableSitesHealthMonitoring',
811 + 'mainwp_sitehealthThreshold',
812 + 'mainwp_maximumRequests',
813 + 'mainwp_minimumDelay',
814 + 'mainwp_maximumIPRequests',
815 + 'mainwp_minimumIPDelay',
816 + 'mainwp_maximumSyncRequests',
817 + 'mainwp_maximumInstallUpdateRequests',
818 + 'mainwp_sslVerifyCertificate',
819 + 'mainwp_connect_signature_algo',
820 + 'mainwp_verify_connection_method',
821 + 'mainwp_forceUseIPv4',
822 + 'mainwp_wp_cron',
823 + 'mainwp_warm_cache_pages_ttl',
824 + 'mainwp_optimize',
825 + 'mainwp_maximum_uptime_monitoring_requests',
826 + 'mainwp_chunksitesnumber',
827 + 'mainwp_chunksleepinterval',
828 + 'mainwp_settings_sync_data',
829 + 'mainwp_module_log_settings',
830 + 'mainwp_module_log_settings_logs_selection_data',
831 + 'mainwp_uptimecheck_running',
832 + 'mainwp_uptimecheck_auto_main_counter_lasttime_started',
833 + 'mainwp_enable_guided_tours',
834 + 'mainwp_enable_guided_chatbase',
835 + 'mainwp_enable_guided_video',
836 + 'mainwp_enable_cloudways_api',
837 + 'mainwp_enable_gridpane_api',
838 + 'mainwp_enable_vultr_api',
839 + 'mainwp_enable_linode_api',
840 + 'mainwp_enable_digitalocean_api',
841 + 'mainwp_enable_cpanel_api',
842 + 'mainwp_enable_plesk_api',
843 + 'mainwp_enable_kinsta_api',
844 + );
1243 845
1244 - <h3 class="ui dividing header">
1245 - <?php echo MainWP_Settings_Indicator::get_indicator( 'header', 'settings-field-indicator-cross-ip', 'advanced-settings' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1246 - <?php esc_html_e( 'Cross IP Settings', 'mainwp' ); ?></h3>
846 + if ( $keys_only ) {
847 + return $keys;
848 + }
1247 849
1248 - <div class="ui grid field settings-field-indicator-cross-ip">
1249 - <label class="six wide column middle aligned">
1250 - <?php
1251 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_maximumRequests', (int) get_option( 'mainwp_maximumRequests', 4 ) );
1252 - esc_html_e( 'Maximum simultaneous requests (Default: 4)', 'mainwp' );
1253 - ?>
1254 - </label>
1255 - <div class="ten wide column ui input" data-tooltip="<?php esc_attr_e( 'If too many requests are sent out, they will begin to time out. This causes your sites to be shown as offline while they are up and running.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1256 - <input type="text" name="mainwp_maximumRequests" id="mainwp_maximumRequests" value="<?php echo ( ( false === get_option( 'mainwp_maximumRequests' ) ) ? 4 : esc_attr( get_option( 'mainwp_maximumRequests' ) ) ); ?>"/>
1257 - </div>
1258 - </div>
850 + $values = array();
851 + foreach ( $keys as $key ) {
852 + $values[ $key ] = get_option( $key );
853 + }
854 + return $values;
855 + }
1259 856
1260 - <div class="ui grid field settings-field-indicator-cross-ip">
1261 - <label class="six wide column middle aligned">
1262 - <?php
1263 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_minimumDelay', (int) get_option( 'mainwp_minimumDelay', 200 ) );
1264 - esc_html_e( 'Minimum delay between requests (Default: 200)', 'mainwp' );
1265 - ?>
1266 - </label>
1267 - <div class="ten wide column ui input" data-tooltip="<?php esc_attr_e( 'This option allows you to control minimum time delay between two requests.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1268 - <input type="text" name="mainwp_minimumDelay" id="mainwp_minimumDelay" value="<?php echo ( ( false === get_option( 'mainwp_minimumDelay' ) ) ? 200 : esc_attr( get_option( 'mainwp_minimumDelay' ) ) ); ?>"/>
1269 - </div>
1270 - </div>
857 + /**
858 + * Render the MainWP Settings Page.
859 + *
860 + * @uses \MainWP\Dashboard\MainWP_Monitoring_View
861 + * @uses \MainWP\Dashboard\MainWP_Manage_Backups::render_settings()
862 + * @uses \MainWP\Dashboard\MainWP_Utility::get_http_codes()
863 + */
864 + public static function render() { //phpcs:ignore -- NOSONAR - complex method.
865 + if ( ! \mainwp_current_user_can( 'dashboard', 'manage_dashboard_settings' ) ) {
866 + \mainwp_do_not_have_permissions( esc_html__( 'manage dashboard settings', 'mainwp' ) );
867 + return;
868 + }
1271 869
1272 - <h3 class="ui dividing header">
1273 - <?php echo MainWP_Settings_Indicator::get_indicator( 'header', 'settings-field-indicator-per-ip', 'advanced-settings' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1274 - <?php esc_html_e( 'Per IP Settings', 'mainwp' ); ?></h3>
870 + static::render_header( '' );
871 + ?>
872 + <div id="mainwp-general-settings" class="ui padded segment">
1275 873
1276 - <div class="ui grid field settings-field-indicator-per-ip">
1277 - <label class="six wide column middle aligned">
1278 - <?php
1279 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_maximumIPRequests', (int) get_option( 'mainwp_maximumIPRequests', 1 ) );
1280 - esc_html_e( 'Maximum simultaneous requests per IP (Default: 1)', 'mainwp' );
1281 - ?>
1282 - </label>
1283 - <div class="ten wide column ui input" data-tooltip="<?php esc_attr_e( 'If too many requests are sent out, they will begin to time out. This causes your sites to be shown as offline while they are up and running.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1284 - <input type="text" name="mainwp_maximumIPRequests" id="mainwp_maximumIPRequests" value="<?php echo ( ( false === get_option( 'mainwp_maximumIPRequests' ) ) ? 1 : esc_attr( get_option( 'mainwp_maximumIPRequests' ) ) ); ?>"/>
1285 - </div>
1286 - </div>
874 + <?php if ( isset( $_GET['message'] ) && 'saved' === $_GET['message'] ) : // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?>
875 + <div class="ui green message"><i class="close icon"></i><?php esc_html_e( 'Settings have been saved successfully!', 'mainwp' ); ?></div>
876 + <?php endif; ?>
877 + <div class="ui form">
878 + <form method="POST" action="admin.php?page=Settings" id="mainwp-settings-page-form">
879 + <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
880 + <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'Settings' ) ); ?>" />
881 + <?php
882 + /**
883 + * Action: mainwp_settings_form_top
884 + *
885 + * Fires at the top of settings form.
886 + *
887 + * @since 4.1
888 + */
889 + do_action( 'mainwp_settings_form_top' );
890 + ?>
891 + <h3 class="ui dividing header">
892 + <?php MainWP_Settings_Indicator::render_indicator( 'header', 'settings-field-indicator-general' ); ?>
893 + <?php esc_html_e( 'General Settings', 'mainwp' ); ?></h3>
894 + <?php
895 + $timeDailyUpdate = get_option( 'mainwp_timeDailyUpdate' );
896 + $frequencyDailyUpdate = (int) get_option( 'mainwp_frequencyDailyUpdate', 2 );
897 + $run_timestamp = MainWP_System_Cron_Jobs::get_timestamp_from_hh_mm( $timeDailyUpdate );
898 + $delay_autoupdate = (int) get_option( 'mainwp_delay_autoupdate', 1 );
1287 899
1288 - <div class="ui grid field settings-field-indicator-per-ip">
1289 - <label class="six wide column middle aligned">
1290 - <?php
1291 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_minimumIPDelay', (int) get_option( 'mainwp_minimumIPDelay', 1000 ) );
1292 - esc_html_e( 'Minimum delay between requests to the same IP (Default: 1000)', 'mainwp' );
1293 - ?>
1294 - </label>
1295 - <div class="ten wide column ui input" data-tooltip="<?php esc_attr_e( 'This option allows you to control minimum time delay between two requests.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1296 - <input type="text" name="mainwp_minimumIPDelay" id="mainwp_minimumIPDelay" value="<?php echo ( ( false === get_option( 'mainwp_minimumIPDelay' ) ) ? 1000 : esc_attr( get_option( 'mainwp_minimumIPDelay' ) ) ); ?>"/>
1297 - </div>
1298 - </div>
900 + ?>
901 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-general">
902 + <label class="six wide column middle aligned">
903 + <?php
904 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_timeDailyUpdate', $timeDailyUpdate );
905 + esc_html_e( 'Daily sync time', 'mainwp' );
906 + ?>
907 + </label>
908 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Choose a specific time to initiate the first daily synchronization process.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
909 + <div class="time-selector">
910 + <div class="ui input left icon">
911 + <i class="clock icon"></i>
912 + <input type="text" class="settings-field-value-change-handler" current-utc-datetime="<?php echo esc_attr( gmdate( 'Y-m-d H:i:s' ) ); ?>" sync-time-local-datetime="<?php echo esc_attr( gmdate( 'Y-m-d H:i:s', $run_timestamp ) ); ?>" local-datetime="<?php echo esc_attr( gmdate( 'Y-m-d H:i:s', MainWP_Utility::get_timestamp() ) ); // phpcs:ignore -- to get local time. ?>" name="mainwp_timeDailyUpdate" id="mainwp_timeDailyUpdate" value="<?php echo esc_attr( $timeDailyUpdate ); ?>" />
913 + </div>
914 + </div>
915 + </div>
916 + </div>
917 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-general" default-indi-value="2">
918 + <label class="six wide column middle aligned">
919 + <?php
920 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_frequencyDailyUpdate', $frequencyDailyUpdate );
921 + esc_html_e( 'Frequency of auto sync', 'mainwp' );
922 + ?>
923 + </label>
924 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Set the frequency for automatic synchronization throughout the day.', 'mainwp' ); ?>" data-inverted="" data-position="top left" >
925 + <select name="mainwp_frequencyDailyUpdate" id="mainwp_frequencyDailyUpdate" class="ui dropdown settings-field-value-change-handler">
926 + <option value="1" <?php echo 1 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Once per day', 'mainwp' ); ?></option>
927 + <option value="2" <?php echo 2 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Twice per day', 'mainwp' ); ?></option>
928 + <option value="3" <?php echo 3 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Three times per day', 'mainwp' ); ?></option>
929 + <option value="4" <?php echo 4 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Four times per day', 'mainwp' ); ?></option>
930 + <option value="5" <?php echo 5 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Five times per day', 'mainwp' ); ?></option>
931 + <option value="6" <?php echo 6 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Six times per day', 'mainwp' ); ?></option>
932 + <option value="7" <?php echo 7 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Seven times per day', 'mainwp' ); ?></option>
933 + <option value="8" <?php echo 8 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Eight times per day', 'mainwp' ); ?></option>
934 + <option value="9" <?php echo 9 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Nine times per day', 'mainwp' ); ?></option>
935 + <option value="10" <?php echo 10 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Ten times per day', 'mainwp' ); ?></option>
936 + <option value="11" <?php echo 11 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Eleven times per day', 'mainwp' ); ?></option>
937 + <option value="12" <?php echo 12 === $frequencyDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Twelve times per day', 'mainwp' ); ?></option>
938 + </select>
939 + </div>
940 + </div>
941 + <script type="text/javascript">
942 + jQuery( document ).ready( function() {
943 + jQuery( '.time-selector' ).calendar( {
944 + type: 'time',
945 + ampm: false,
946 + formatter: {
947 + time: 'H:mm',
948 + cellTime: 'H:mm'
949 + }
950 + } );
951 + } );
952 + </script>
1299 953
1300 - <h3 class="ui dividing header">
1301 - <?php echo MainWP_Settings_Indicator::get_indicator( 'header', 'settings-field-indicator-frontend-request', 'advanced-settings' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1302 - <?php esc_html_e( 'Frontend Request Settings', 'mainwp' ); ?></h3>
954 + <?php
1303 955
1304 - <div class="ui grid field settings-field-indicator-frontend-request">
1305 - <label class="six wide column middle aligned">
1306 - <?php
1307 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_maximumSyncRequests', (int) get_option( 'mainwp_maximumSyncRequests', 8 ) );
1308 - esc_html_e( 'Maximum simultaneous sync requests (Default: 8)', 'mainwp' );
1309 - ?>
1310 - </label>
1311 - <div class="ten wide column ui input" data-tooltip="<?php esc_attr_e( 'This option allows you to control how many sites your MainWP Dashboard should sync at once.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1312 - <input type="text" name="mainwp_maximumSyncRequests" id="mainwp_maximumSyncRequests" value="<?php echo ( ( false === get_option( 'mainwp_maximumSyncRequests' ) ) ? 8 : esc_attr( get_option( 'mainwp_maximumSyncRequests' ) ) ); ?>"/>
1313 - </div>
1314 - </div>
956 + static::render_timezone_settings();
957 + static::render_datetime_settings();
1315 958
1316 - <div class="ui grid field settings-field-indicator-frontend-request">
1317 - <label class="six wide column middle aligned">
1318 - <?php
1319 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_maximumInstallUpdateRequests', (int) get_option( 'mainwp_maximumInstallUpdateRequests', 3 ) );
1320 - esc_html_e( 'Maximum simultaneous install and update requests (Default: 3)', 'mainwp' );
1321 - ?>
1322 - </label>
1323 - <div class="ten wide column ui input" data-tooltip="<?php esc_attr_e( 'This option allows you to control how many update and install requests your MainWP Dashboard should process at once.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1324 - <input type="text" name="mainwp_maximumInstallUpdateRequests" id="mainwp_maximumInstallUpdateRequests" value="<?php echo ( ( false === get_option( 'mainwp_maximumInstallUpdateRequests' ) ) ? 3 : esc_attr( get_option( 'mainwp_maximumInstallUpdateRequests' ) ) ); ?>"/>
1325 - </div>
1326 - </div>
959 + $sidebarPosition = get_user_option( 'mainwp_sidebarPosition' );
960 + if ( false === $sidebarPosition ) {
961 + $sidebarPosition = 1;
962 + }
1327 963
1328 - <h3 class="ui dividing header">
1329 - <?php echo MainWP_Settings_Indicator::get_indicator( 'header', 'settings-field-indicator-miscellaneous', 'advanced-settings' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1330 - <?php esc_html_e( 'Miscellaneous Settings', 'mainwp' ); ?></h3>
1331 - <div class="ui grid field settings-field-indicator-miscellaneous">
1332 - <label class="six wide column middle aligned">
1333 - <?php
1334 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_optimize', (int) get_option( 'mainwp_optimize', 1 ) );
1335 - esc_html_e( 'Optimize data loading', 'mainwp' );
1336 - ?>
1337 - </label>
1338 - <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'If enabled, your MainWP Dashboard will cache updates for faster loading.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
1339 - <input type="checkbox" name="mainwp_optimize" id="mainwp_optimize" <?php echo ( ( 1 === (int) get_option( 'mainwp_optimize', 1 ) ) ? 'checked="true"' : '' ); ?> /><label><?php esc_html_e( 'Default: Off', 'mainwp' ); ?></label>
1340 - </div>
1341 - </div>
1342 - <div class="ui grid field settings-field-indicator-miscellaneous">
1343 - <label class="six wide column middle aligned">
1344 - <?php
1345 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_wp_cron', (int) get_option( 'mainwp_wp_cron', 1 ) );
1346 - esc_html_e( 'Use WP Cron', 'mainwp' );
1347 - ?>
1348 - </label>
1349 - <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Disabling this option will disable the WP Cron so all scheduled events will stop working.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1350 - <input type="checkbox" name="mainwp_options_wp_cron" id="mainwp_options_wp_cron" <?php echo ( ( 1 === (int) get_option( 'mainwp_wp_cron' ) ) || ( false === get_option( 'mainwp_wp_cron' ) ) ? 'checked="true"' : '' ); ?>/><label><?php esc_html_e( 'Default: On', 'mainwp' ); ?></label>
1351 - </div>
1352 - </div>
1353 - <div class="ui grid field settings-field-indicator-miscellaneous" >
1354 - <label class="six wide column middle aligned"><?php esc_html_e( 'Verify SSL certificate', 'mainwp' ); ?></label>
1355 - <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'If enabled, your MainWP Dashboard will verify the SSL Certificate on your Child Site (if exists) while connecting the Child Site.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1356 - <input type="checkbox" name="mainwp_sslVerifyCertificate" id="mainwp_sslVerifyCertificate" value="checked" <?php echo ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 === (int) get_option( 'mainwp_sslVerifyCertificate' ) ) ) ? 'checked="checked"' : ''; ?>/><label><?php esc_html_e( 'Default: On', 'mainwp' ); ?></label>
1357 - </div>
1358 - </div>
1359 - <?php
1360 - $general_verify_con = (int) get_option( 'mainwp_verify_connection_method', 1 );
1361 - ?>
1362 - <div class="ui grid field settings-field-indicator-miscellaneous">
1363 - <label class="six wide column middle aligned">
1364 - <?php
1365 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_verify_connection_method', (int) $general_verify_con );
1366 - esc_html_e( 'Verify connection method', 'mainwp' );
1367 - ?>
1368 - </label>
1369 - <div class="ui six wide column" data-tooltip="<?php esc_attr_e( 'Select Verify connection method. If you are not sure, select "Default".', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1370 - <select class="ui dropdown" id="mainwp_settings_verify_connection_method" name="mainwp_settings_verify_connection_method">
1371 - <option <?php echo ( empty( $general_verify_con ) || 1 === $general_verify_con ) ? 'selected' : ''; ?> value="1"><?php esc_html_e( 'OpenSSL (default)', 'mainwp' ); ?></option>
1372 - <option <?php echo ( 2 === $general_verify_con ) ? 'selected' : ''; ?> value="2"><?php esc_html_e( 'PHPSECLIB (fallback)', 'mainwp' ); ?></option>
1373 - </select>
1374 - </div>
1375 - </div>
1376 - <?php
1377 - $sign_note = MainWP_Connect_Lib::get_connection_algo_settings_note();
1378 - $sign_algs = MainWP_System_Utility::get_open_ssl_sign_algos();
1379 - $general_sign_alg = get_option( 'mainwp_connect_signature_algo', false );
1380 - if ( false === $general_sign_alg ) {
1381 - $general_sign_alg = defined( 'OPENSSL_ALGO_SHA256' ) ? OPENSSL_ALGO_SHA256 : 1;
1382 - MainWP_Utility::update_option( 'mainwp_connect_signature_algo', $general_sign_alg );
1383 - } else {
1384 - $general_sign_alg = intval( $general_sign_alg );
1385 - }
1386 - ?>
1387 - <div class="ui grid field mainwp-hide-elemenent-sign-algo settings-field-indicator-miscellaneous" <?php echo ( 2 === $general_verify_con ) ? 'style="display:none;"' : ''; ?> >
1388 - <label class="six wide column middle aligned">
1389 - <?php
1390 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_connect_signature_algo', (int) $general_sign_alg );
1391 - esc_html_e( 'OpenSSL signature algorithm', 'mainwp' );
1392 - ?>
1393 - </label>
1394 - <div class="ui six wide column" data-tooltip="<?php esc_attr_e( 'Select OpenSSL signature algorithm. If you are not sure, select "Default".', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1395 - <select class="ui dropdown" id="mainwp_settings_openssl_alg" name="mainwp_settings_openssl_alg">
1396 - <?php
1397 - foreach ( $sign_algs as $val => $text ) {
1398 - ?>
1399 - <option <?php echo ( $val === $general_sign_alg ) ? 'selected' : ''; ?> value="<?php echo esc_attr( $val ); ?>"><?php echo esc_html( $text ); ?></option>
1400 - <?php
1401 - }
1402 - ?>
1403 - </select>
1404 - <div class="ui yellow message mainwp-hide-elemenent-sign-algo-note" <?php echo ( 1 === $general_sign_alg ) ? '' : 'style="display:none;"'; ?>><?php echo esc_html( $sign_note ); ?></div>
1405 - </div>
1406 - </div>
1407 - <div class="ui grid field settings-field-indicator-miscellaneous">
1408 - <label class="six wide column middle aligned">
1409 - <?php
1410 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_forceUseIPv4', (int) get_option( 'mainwp_forceUseIPv4' ) );
1411 - esc_html_e( 'Force IPv4', 'mainwp' );
1412 - ?>
1413 - </label>
1414 - <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Enable if you want to force your MainWP Dashboard to use IPv4 while tryig to connect child sites.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
1415 - <input type="checkbox" name="mainwp_forceUseIPv4" id="mainwp_forceUseIPv4" value="checked" <?php echo ( 1 === (int) get_option( 'mainwp_forceUseIPv4' ) ) ? 'checked="checked"' : ''; ?>/><label><?php esc_html_e( 'Default: Off', 'mainwp' ); ?></label>
1416 - </div>
1417 - </div>
1418 - <?php
964 + ?>
965 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-general" default-indi-value="1">
966 + <label class="six wide column middle aligned">
967 + <?php
968 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_sidebarPosition', (int) $sidebarPosition );
969 + esc_html_e( 'Sidebar position', 'mainwp' );
970 + ?>
971 + </label>
972 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Select if you want to show sidebar with option on left or right.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
973 + <select name="mainwp_sidebarPosition" id="mainwp_sidebarPosition" class="ui dropdown settings-field-value-change-handler">
974 + <option value="1" <?php echo 1 === (int) $sidebarPosition ? 'selected' : ''; ?>><?php esc_html_e( 'Right (default)', 'mainwp' ); ?></option>
975 + <option value="0" <?php echo 0 === (int) $sidebarPosition ? 'selected' : ''; ?>><?php esc_html_e( 'Left', 'mainwp' ); ?></option>
976 + </select>
977 + </div>
978 + </div>
979 + <?php MainWP_UI::render_screen_options(); ?>
1419 980
1420 - /**
1421 - * Action: mainwp_advanced_settings_form_bottom
1422 - *
1423 - * Fires at the bottom of advanced settings form.
1424 - *
1425 - * @since 4.1
1426 - */
1427 - do_action( 'mainwp_advanced_settings_form_bottom' );
981 + <h3 class="ui dividing header">
982 + <?php MainWP_Settings_Indicator::render_indicator( 'header', 'settings-field-indicator-updates' ); ?>
983 + <?php esc_html_e( 'Updates Settings', 'mainwp' ); ?></h3>
984 + <?php
985 + $snAutomaticDailyUpdate = (int) get_option( 'mainwp_automaticDailyUpdate', 0 );
986 + $snPluginAutomaticDailyUpdate = (int) get_option( 'mainwp_pluginAutomaticDailyUpdate', 0 );
987 + $snThemeAutomaticDailyUpdate = (int) get_option( 'mainwp_themeAutomaticDailyUpdate', 0 );
988 + $snTransAutomaticUpdate = (int) get_option( 'mainwp_transAutomaticDailyUpdate', 0 );
1428 989
1429 - ?>
1430 - <div class="ui divider"></div>
1431 - <input type="submit" name="submit" id="submit" class="ui green big button" value="<?php esc_attr_e( 'Save Settings', 'mainwp' ); ?>"/>
1432 - </form>
1433 - </div>
1434 - </div>
1435 - <?php
1436 - self::render_footer( 'Advanced' );
1437 - }
990 + $backup_before_upgrade = get_option( 'mainwp_backup_before_upgrade' );
991 + $mainwp_backup_before_upgrade_days = get_option( 'mainwp_backup_before_upgrade_days' );
992 + if ( empty( $mainwp_backup_before_upgrade_days ) || ! ctype_digit( $mainwp_backup_before_upgrade_days ) ) {
993 + $mainwp_backup_before_upgrade_days = 7;
994 + }
995 + $mainwp_show_language_updates = get_option( 'mainwp_show_language_updates', 1 );
996 + $enableLegacyBackupFeature = get_option( 'mainwp_enableLegacyBackupFeature' );
997 + $primaryBackup = get_option( 'mainwp_primaryBackup' );
998 + $disableUpdateConfirmations = (int) get_option( 'mainwp_disable_update_confirmations', 0 );
999 + ?>
1000 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-updates">
1001 + <label class="six wide column middle aligned">
1002 + <?php
1003 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_pluginAutomaticDailyUpdate', $snPluginAutomaticDailyUpdate );
1004 + esc_html_e( 'Plugin advanced automatic updates', 'mainwp' );
1005 + ?>
1006 + </label>
1007 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Enable or disable automatic plugin updates. If enabled, MainWP will update only plugins that you have marked as Trusted.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1008 + <select name="mainwp_pluginAutomaticDailyUpdate" id="mainwp_pluginAutomaticDailyUpdate" class="ui dropdown settings-field-value-change-handler">
1009 + <option value="1" <?php echo 1 === $snPluginAutomaticDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Install Trusted Updates', 'mainwp' ); ?></option>
1010 + <option value="0" <?php echo 0 === $snPluginAutomaticDailyUpdate || 2 === $snPluginAutomaticDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Disabled', 'mainwp' ); ?></option>
1011 + </select>
1012 + </div>
1013 + </div>
1014 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-updates">
1015 + <label class="six wide column middle aligned">
1016 + <?php
1017 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_themeAutomaticDailyUpdate', $snThemeAutomaticDailyUpdate );
1018 + esc_html_e( 'Theme advanced automatic updates', 'mainwp' );
1019 + ?>
1020 + </label>
1021 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Enable or disable automatic theme updates. If enabled, MainWP will update only themes that you have marked as Trusted.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1022 + <select name="mainwp_themeAutomaticDailyUpdate" id="mainwp_themeAutomaticDailyUpdate" class="ui dropdown settings-field-value-change-handler">
1023 + <option value="1" <?php echo 1 === $snThemeAutomaticDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Install Trusted Updates', 'mainwp' ); ?></option>
1024 + <option value="0" <?php echo 0 === $snThemeAutomaticDailyUpdate || 2 === $snThemeAutomaticDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Disabled', 'mainwp' ); ?></option>
1025 + </select>
1026 + </div>
1027 + </div>
1028 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-updates">
1029 + <label class="six wide column middle aligned">
1030 + <?php
1031 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_stransAutomaticUpdate', $snTransAutomaticUpdate );
1032 + esc_html_e( 'Translation advanced automatic updates', 'mainwp' );
1033 + ?>
1034 + </label>
1035 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Enable or disable automatic Translation updates.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1036 + <select name="mainwp_transAutomaticDailyUpdate" id="mainwp_transAutomaticDailyUpdate" class="ui dropdown settings-field-value-change-handler">
1037 + <option value="1" <?php echo 1 === $snTransAutomaticUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Install Trusted Updates', 'mainwp' ); ?></option>
1038 + <option value="0" <?php echo 0 === $snTransAutomaticUpdate || 2 === (int) $snTransAutomaticUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Disabled', 'mainwp' ); ?></option>
1039 + </select>
1040 + </div>
1041 + </div>
1042 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-updates">
1043 + <label class="six wide column middle aligned">
1044 + <?php
1045 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_automaticDailyUpdate', $snAutomaticDailyUpdate );
1046 + esc_html_e( 'WP Core advanced automatic updates', 'mainwp' );
1047 + ?>
1048 + </label>
1049 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Enable or disable automatic WordPress core updates.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1050 + <select name="mainwp_automaticDailyUpdate" id="mainwp_automaticDailyUpdate" class="ui dropdown settings-field-value-change-handler">
1051 + <option value="1" <?php echo 1 === $snAutomaticDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Install Trusted Updates', 'mainwp' ); ?></option>
1052 + <option value="0" <?php echo 0 === $snAutomaticDailyUpdate || 2 === (int) $snAutomaticDailyUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Disabled', 'mainwp' ); ?></option>
1053 + </select>
1054 + </div>
1055 + </div>
1056 + <?php static::render_auto_updates_settings(); ?>
1057 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-updates" default-indi-value="1">
1058 + <label class="six wide column middle aligned">
1059 + <?php
1060 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_delay_autoupdate', $delay_autoupdate );
1061 + esc_html_e( 'Advanced automatic updates delay', 'mainwp' );
1062 + ?>
1063 + </label>
1064 + <div class="ten wide column ui input" data-tooltip="<?php esc_attr_e( 'Set the number of days to delay automatic updates.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1065 + <select name="mainwp_delay_autoupdate" id="mainwp_delay_autoupdate" class="ui dropdown settings-field-value-change-handler">
1066 + <option value="0" <?php echo 0 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( 'Delay off', 'mainwp' ); ?></option>
1067 + <option value="1" <?php echo 1 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( '1 day', 'mainwp' ); ?></option>
1068 + <option value="2" <?php echo 2 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( '2 days', 'mainwp' ); ?></option>
1069 + <option value="3" <?php echo 3 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( '3 days', 'mainwp' ); ?></option>
1070 + <option value="4" <?php echo 4 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( '4 days', 'mainwp' ); ?></option>
1071 + <option value="5" <?php echo 5 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( '5 days', 'mainwp' ); ?></option>
1072 + <option value="6" <?php echo 6 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( '6 days', 'mainwp' ); ?></option>
1073 + <option value="7" <?php echo 7 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( '7 days', 'mainwp' ); ?></option>
1074 + <option value="14" <?php echo 14 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( '14 days', 'mainwp' ); ?></option>
1075 + <option value="30" <?php echo 30 === $delay_autoupdate ? 'selected' : ''; ?>><?php esc_html_e( '30 days', 'mainwp' ); ?></option>
1076 + </select>
1077 + </div>
1078 + </div>
1079 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-updates" default-indi-value="1">
1080 + <label class="six wide column middle aligned">
1081 + <?php
1082 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_show_language_updates', $mainwp_show_language_updates );
1083 + esc_html_e( 'Show WordPress language updates', 'mainwp' );
1084 + ?>
1085 + </label>
1086 + <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Enable if you want to manage Translation updates', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1087 + <input type="checkbox" name="mainwp_show_language_updates" class="settings-field-value-change-handler" id="mainwp_show_language_updates" <?php echo 1 === (int) $mainwp_show_language_updates ? 'checked="true"' : ''; ?>/>
1088 + </div>
1089 + </div>
1090 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-updates">
1091 + <label class="six wide column middle aligned">
1092 + <?php
1093 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_disable_update_confirmations', $disableUpdateConfirmations );
1094 + esc_html_e( 'Update confirmations', 'mainwp' );
1095 + ?>
1096 + </label>
1097 + <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Choose if you want to disable the popup confirmations when performing updates.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1098 + <select name="mainwp_disable_update_confirmations" id="mainwp_disable_update_confirmations" class="ui dropdown settings-field-value-change-handler">
1099 + <option value="0" <?php echo 0 === $disableUpdateConfirmations ? 'selected' : ''; ?>><?php esc_html_e( 'Enable', 'mainwp' ); ?></option>
1100 + <option value="2" <?php echo 2 === $disableUpdateConfirmations ? 'selected' : ''; ?>><?php esc_html_e( 'Disable', 'mainwp' ); ?></option>
1101 + <option value="1" <?php echo 1 === $disableUpdateConfirmations ? 'selected' : ''; ?>><?php esc_html_e( 'Disable for single updates', 'mainwp' ); ?></option>
1102 + </select>
1103 + </div>
1104 + </div>
1105 + <?php if ( ( $enableLegacyBackupFeature && empty( $primaryBackup ) ) || ( empty( $enableLegacyBackupFeature ) && ! empty( $primaryBackup ) ) ) { ?>
1106 + <div class="ui grid field mainwp-parent-toggle settings-field-indicator-wrapper settings-field-indicator-updates">
1107 + <label class="six wide column middle aligned">
1108 + <?php
1109 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_backup_before_upgrade', (int) $backup_before_upgrade );
1110 + esc_html_e( 'Require a backup before an update', 'mainwp' );
1111 + ?>
1112 + </label>
1113 + <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'If enabled, your MainWP Dashboard will check if full backups exists before updating.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1114 + <input type="checkbox" class="settings-field-value-change-handler" name="mainwp_backup_before_upgrade" id="mainwp_backup_before_upgrade" <?php echo 1 === (int) $backup_before_upgrade ? 'checked="true"' : ''; ?>/>
1115 + </div>
1116 + </div>
1117 + <div class="ui grid field mainwp-child-field settings-field-indicator-wrapper settings-field-indicator-updates" default-indi-value="7" <?php echo 1 === (int) $backup_before_upgrade ? '' : 'style="display:none"'; ?> >
1118 + <label class="six wide column middle aligned">
1119 + <?php
1120 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_backup_before_upgrade_days', (int) $mainwp_backup_before_upgrade_days );
1121 + esc_html_e( 'Days without of a full backup tolerance', 'mainwp' );
1122 + ?>
1123 + </label>
1124 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Set the number of days without of backup tolerance.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1125 + <input type="text" class="settings-field-value-change-handler" name="mainwp_backup_before_upgrade_days" id="mainwp_backup_before_upgrade_days" value="<?php echo esc_attr( $mainwp_backup_before_upgrade_days ); ?>" />
1126 + </div>
1127 + </div>
1128 + <?php } ?>
1438 1129
1439 - /**
1440 - * Render MainWP Tools SubPage.
1441 - *
1442 - * @uses \MainWP\Dashboard\MainWP_UI::render_screen_options()
1443 - */
1444 - public static function render_mainwp_tools() {
1445 - if ( ! mainwp_current_user_have_right( 'dashboard', 'manage_dashboard_settings' ) ) {
1446 - mainwp_do_not_have_permissions( esc_html__( 'manage dashboard settings', 'mainwp' ) );
1130 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-updates" default-indi-value="365">
1131 + <label class="six wide column middle aligned">
1132 + <?php
1133 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_numberdays_Outdate_Plugin_Theme', (int) get_option( 'mainwp_numberdays_Outdate_Plugin_Theme', 365 ) );
1447 1134
1448 - return;
1449 - }
1450 - self::render_header( 'MainWPTools' );
1451 - $is_demo = MainWP_Demo_Handle::is_demo_mode();
1452 - ?>
1453 - <div id="mainwp-tools-settings" class="ui segment">
1454 - <div id="mainwp-message-zone" style="display:none;" class="ui message"></div>
1455 - <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-tools-info-message' ) ) : ?>
1456 - <div class="ui info message">
1457 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-tools-info-message"></i>
1458 - <?php printf( esc_html__( 'Use MainWP tools to adjust your MainWP Dashboard to your needs and perform specific actions when needed. For additional help, review this %1$shelp document%2$s.', 'mainwp' ), '<a href="https://kb.mainwp.com/docs/mainwp-dashboard-settings/" target="_blank">', '</a> <i class="external alternate icon"></i>' ); ?>
1459 - </div>
1460 - <?php endif; ?>
1461 - <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-tools-info-custom-theme' ) ) : ?>
1462 - <div class="ui info message">
1463 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-tools-info-custom-theme"></i>
1464 - <div><?php esc_html_e( 'Here you can select a theme for your MainWP Dashboard.', 'mainwp' ); ?></div>
1465 - <div><?php esc_html_e( 'To create a custom theme, copy the `mainwp-dark-theme.css` file from the MainWP Custom Dashboard Extension located in the `css` directory, make your edits and upload the file to the `../wp-content/uploads/mainwp/custom-dashboard/` directory.', 'mainwp' ); ?></div>
1466 - </div>
1467 - <?php endif; ?>
1468 - <?php if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MainWPTools' ) ) : ?>
1469 - <div class="ui green message"><i class="close icon"></i><?php esc_html_e( 'Settings have been saved successfully!', 'mainwp' ); ?></div>
1470 - <?php endif; ?>
1471 - <?php if ( isset( $_POST['mainwp_restore_info_messages'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MainWPTools' ) ) : ?>
1472 - <div class="ui green message"><i class="close icon"></i><?php esc_html_e( 'Info messages have been restored successfully!', 'mainwp' ); ?></div>
1473 - <?php endif; ?>
1474 - <div class="ui form">
1475 - <form method="POST" action="">
1476 - <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
1477 - <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'MainWPTools' ) ); ?>" />
1478 - <h3 class="ui dividing header">
1479 - <?php echo MainWP_Settings_Indicator::get_indicator( 'header', 'settings-field-indicator-tools', 'mainwp-tools' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1480 - <?php esc_html_e( 'MainWP Dashboard Tools', 'mainwp' ); ?></h3>
1481 - <?php
1482 - /**
1483 - * Action: mainwp_tools_form_top
1484 - *
1485 - * Fires at the top of MainWP tools form.
1486 - *
1487 - * @since 4.1
1488 - */
1489 - do_action( 'mainwp_tools_form_top' );
1135 + esc_html_e( 'Abandoned plugins/themes tolerance', 'mainwp' );
1136 + ?>
1137 + </label>
1138 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Set how many days without an update before plugin or theme will be considered as abandoned.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1139 + <input type="text" class="settings-field-value-change-handler" name="mainwp_numberdays_Outdate_Plugin_Theme" id="mainwp_numberdays_Outdate_Plugin_Theme" value="<?php echo false === get_option( 'mainwp_numberdays_Outdate_Plugin_Theme' ) ? 365 : intval( get_option( 'mainwp_numberdays_Outdate_Plugin_Theme' ) ); ?>"/>
1140 + </div>
1141 + </div>
1490 1142
1491 - $show_qsw = apply_filters( 'mainwp_show_qsw', true );
1143 + <?php MainWP_Manage_Backups::render_settings(); ?>
1144 + <?php
1145 + /**
1146 + * Action: mainwp_settings_form_bottom
1147 + *
1148 + * Fires at the bottom of settings form.
1149 + *
1150 + * @since 4.1
1151 + */
1152 + do_action( 'mainwp_settings_form_bottom' );
1153 + ?>
1154 + <div class="ui divider"></div>
1155 + <input type="submit" name="submit" id="submit" class="ui button green big" value="<?php esc_attr_e( 'Save Settings', 'mainwp' ); ?>"/>
1156 + <div style="clear:both"></div>
1157 + </form>
1158 + </div>
1159 + </div>
1160 + <?php
1161 + static::render_footer( '' );
1162 + }
1492 1163
1493 - self::get_instance()->render_select_custom_themes();
1164 + /**
1165 + * Method render_auto_updates_settings().
1166 + */
1167 + public static function render_auto_updates_settings() { // phpcs:ignore -- NOSONAR - complex.
1494 1168
1495 - ?>
1496 - <div class="ui grid field settings-field-indicator-tools">
1497 - <label class="six wide column middle aligned">
1498 - <?php
1499 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_enable_guided_tours', (int) get_option( 'mainwp_enable_guided_tours', 0 ) );
1500 - esc_html_e( 'Enable MainWP guided tours', 'mainwp' );
1501 - ?>
1502 - <span class="ui blue mini label"><?php esc_html_e( 'BETA', 'mainwp' ); ?></span></label>
1503 - <div class="ten wide column " data-tooltip="<?php esc_attr_e( 'Check this option to enable, or uncheck to disable MainWP guided tours.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
1504 - <div class="ui info message" style="display:block!important;">
1505 - <?php printf( esc_html__( 'This feature is implemented using Javascript provided by Usetiful and is subject to the %1$sUsetiful Privacy Policy%2$s.', 'mainwp' ), '<a href="https://www.usetiful.com/privacy-policy" target="_blank">', '</a>' ); ?>
1506 - </div>
1507 - <div class="ui toggle checkbox">
1508 - <input type="checkbox" name="mainwp-guided-tours-option" id="mainwp-guided-tours-option" <?php echo ( ( 1 === (int) get_option( 'mainwp_enable_guided_tours', 0 ) ) ? 'checked="true"' : '' ); ?> />
1509 - </div>
1510 - </div>
1511 - </div>
1512 - <div class="ui grid field">
1513 - <label class="six wide column middle aligned"><?php esc_html_e( 'Force your MainWP Dashboard to establish a new connection', 'mainwp' ); ?></label>
1514 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Force your MainWP Dashboard to reconnect with your child sites. Only needed if suggested by MainWP Support.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1515 - <?php
1516 - if ( $is_demo ) {
1517 - MainWP_Demo_Handle::get_instance()->render_demo_disable_button( '<input type="button" disabled="disabled" class="ui green basic button disabled" value="' . esc_attr__( 'Re-establish Connections', 'mainwp' ) . '" />' );
1518 - } else {
1519 - ?>
1520 - <input type="button" name="" id="force-destroy-sessions-button" data-inverted="" data-position="top right" data-tooltip="<?php esc_attr_e( 'Forces your dashboard to reconnect with your child sites. This feature will log out any currently logged in users on the Child sites and require them to re-log in. Only needed if suggested by MainWP Support.', 'mainwp' ); ?>" class="ui green basic button" value="<?php esc_attr_e( 'Re-establish Connections', 'mainwp' ); ?>" />
1521 - <?php } ?>
1522 - </div>
1523 - </div>
1524 - <div class="ui grid field">
1525 - <label class="six wide column middle aligned"><?php esc_html_e( 'Force your MainWP Dashbaord to set new pair of OpenSSL Keys', 'mainwp' ); ?></label>
1526 - <div class="ten wide column" id="mainwp-renew-connections-tool" data-content="<?php esc_attr_e( 'This will function renew connection and reconnect site right away.', 'mainwp' ); ?>" data-variation="inverted" data-position="top left">
1527 - <?php
1528 - if ( $is_demo ) {
1529 - MainWP_Demo_Handle::get_instance()->render_demo_disable_button( '<a href="javascript:void(0)" disabled="disabled" class="ui button green basic disabled">' . esc_html__( 'Reset OpenSSL Key Pair', 'mainwp' ) . '</a>' );
1530 - } else {
1531 - ?>
1532 - <a href="javascript:void(0)" onclick="mainwp_tool_renew_connections_show(); return false;" class="ui button green basic"><?php esc_html_e( 'Reset OpenSSL Key Pair', 'mainwp' ); ?></a>
1533 - <?php } ?>
1534 - </div>
1535 - </div>
1536 - <?php if ( $show_qsw ) { ?>
1537 - <div class="ui grid field">
1538 - <label class="six wide column middle aligned"><?php esc_html_e( 'Start the MainWP Quick Setup Wizard', 'mainwp' ); ?></label>
1539 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Click this button to start the Quick Setup Wizard', 'mainwp' ); ?>" data-inverted="" data-position="top left"><a href="admin.php?page=mainwp-setup" class="ui green button basic" ><?php esc_html_e( 'Start Quick Setup Wizard', 'mainwp' ); ?></a></div>
1540 - </div>
1541 - <?php } ?>
1542 - <div class="ui grid field">
1543 - <label class="six wide column middle aligned"><?php esc_html_e( 'Export child sites to CSV file', 'mainwp' ); ?></label>
1544 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Click this button to export all connected sites to a CSV file.', 'mainwp' ); ?>" data-inverted="" data-position="top left"><a href="admin.php?page=MainWPTools&doExportSites=yes&_wpnonce=<?php echo esc_attr( wp_create_nonce( 'export_sites' ) ); ?>" class="ui button green basic"><?php esc_html_e( 'Export Child Sites', 'mainwp' ); ?></a></div>
1545 - </div>
1546 - <div class="ui grid field">
1547 - <label class="six wide column middle aligned"><?php esc_html_e( 'Import child sites', 'mainwp' ); ?></label>
1548 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Click this button to import websites to your MainWP Dashboard.', 'mainwp' ); ?>" data-inverted="" data-position="top left"><a href="admin.php?page=managesites&do=bulknew" class="ui button green basic"><?php esc_html_e( 'Import Child Sites', 'mainwp' ); ?></a></div>
1549 - </div>
1550 - <div class="ui grid field">
1551 - <label class="six wide column middle aligned"><?php esc_html_e( 'Disconnect all child sites', 'mainwp' ); ?></label>
1552 - <div class="ten wide column" id="mainwp-disconnect-sites-tool" data-content="<?php esc_attr_e( 'This will function will break the connection and leave the MainWP Child plugin active and which makes your sites vulnerable. Use only if you attend to reconnect site to the same or a different dashboard right away.', 'mainwp' ); ?>" data-variation="inverted" data-position="top left">
1553 - <?php
1554 - if ( $is_demo ) {
1555 - MainWP_Demo_Handle::get_instance()->render_demo_disable_button( '<a href="#" class="ui button green basic disabled" disabled="disabled">' . esc_html__( 'Disconnect Sites', 'mainwp' ) . '</a>' );
1556 - } else {
1557 - ?>
1558 - <a href="admin.php?page=MainWPTools&disconnectSites=yes&_wpnonce=<?php echo esc_attr( wp_create_nonce( 'disconnect_sites' ) ); ?>" onclick="mainwp_tool_disconnect_sites(); return false;" class="ui button green basic"><?php esc_html_e( 'Disconnect Sites', 'mainwp' ); ?></a>
1559 - <?php } ?>
1560 - </div>
1561 - </div>
1562 - <div class="ui grid field">
1563 - <label class="six wide column middle aligned"><?php esc_html_e( 'Delete extensions API Activation data', 'mainwp' ); ?></label>
1564 - <div class="ten wide column" id="mainwp-clear-activation-data" data-content="<?php esc_attr_e( 'Delete extensions API activation data. This will not affect extensions settings, it just removes API activation data.', 'mainwp' ); ?>" data-variation="inverted" data-position="top left">
1565 - <a href="admin.php?page=MainWPTools&clearActivationData=yes&_wpnonce=<?php echo esc_attr( wp_create_nonce( 'clear_activation_data' ) ); ?>" onclick="mainwp_tool_clear_activation_data(this); return false;" class="ui button green basic"><?php esc_html_e( 'Delete Extensions API Activation Data', 'mainwp' ); ?></a>
1566 - </div>
1567 - </div>
1568 - <div class="ui grid field">
1569 - <label class="six wide column middle aligned"><?php esc_html_e( 'Restore all info messages', 'mainwp' ); ?></label>
1570 - <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Click this button to restore all info messages in your MainWP Dashboard and Extensions.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1571 - <input type="submit" name="mainwp_restore_info_messages" id="mainwp_restore_info_messages" class="ui button" value="<?php esc_attr_e( 'Restore Info Messages', 'mainwp' ); ?>"/>
1572 - </div>
1573 - </div>
1574 - <?php
1575 - $enabled_demo = MainWP_Demo_Handle::is_demo_mode();
1576 - $is_new = MainWP_Demo_Handle::get_instance()->is_new_instance();
1577 - if ( ! MainWP_Demo_Handle::is_instawp_site() ) {
1578 - ?>
1579 - <div class="ui grid field">
1580 - <label class="six wide column middle aligned"><?php echo esc_html__( 'Demo mode', 'mainwp' ); ?></label>
1581 - <div class="ten wide column">
1582 - <?php if ( ! $enabled_demo ) { ?>
1583 - <span data-tooltip="<?php esc_attr_e( 'Demo Mode can not be enabled on MainWP Dashboards that already have sites connected, clients created or extensions installed.', 'mainwp' ); ?>" data-inverted="" data-position="top left"><button page-import="settings" class="ui green button mainwp-import-demo-data-button" <?php echo ( ! $is_new ? 'disabled="disabled"' : '' ); ?>><?php esc_html_e( 'Import Demo Content', 'mainwp' ); ?></button></span>
1584 - <?php } else { ?>
1585 - <span data-tooltip="<?php esc_attr_e( 'Click this button to delete the Demo content from your MainWP Dashboard and disable the Demo mode.', 'mainwp' ); ?>" data-inverted="" data-position="top left"><button class="ui green button mainwp-remove-demo-data-button"><?php esc_html_e( 'Delete Demo Content', 'mainwp' ); ?></button></span>
1586 - <?php } ?>
1587 - </div>
1588 - </div>
1589 - <?php
1590 - }
1591 - /**
1592 - * Action: mainwp_tools_form_bottom
1593 - *
1594 - * Fires at the bottom of mainwp tools form.
1595 - *
1596 - * @since 4.1
1597 - */
1598 - do_action( 'mainwp_tools_form_bottom' );
1599 - ?>
1600 - <div class="ui divider"></div>
1601 - <input type="submit" name="submit" id="submit" class="ui green big button" value="<?php esc_attr_e( 'Save Settings', 'mainwp' ); ?>"/>
1602 - </form>
1603 - </div>
1604 - </div>
1605 - <script type="text/javascript">
1606 - jQuery( '#mainwp-disconnect-sites-tool' ).popup();
1607 - jQuery( '#mainwp-clear-activation-data' ).popup();
1608 - </script>
1609 - <?php
1610 - self::render_footer( 'MainWPTools' );
1611 - MainWP_Connect_Helper::render_renew_connections_modal();
1612 - }
1169 + $time_AutoUpdate = get_option( 'mainwp_time_AutoUpdate' );
1170 + $dayinweek_AutoUpdate = (int) get_option( 'mainwp_dayinweek_AutoUpdate', 0 );
1171 + $dayinmonth_AutoUpdate = (int) get_option( 'mainwp_dayinmonth_AutoUpdate', 1 );
1172 + $frequency_AutoUpdate = get_option( 'mainwp_frequency_AutoUpdate', 'daily' );
1613 1173
1614 - /**
1615 - * Render MainWP themes selection.
1616 - */
1617 - public function render_select_custom_themes() {
1618 - $custom_theme = $this->get_current_user_theme();
1619 - if ( false === $custom_theme ) {
1620 - // to compatible with Custom Dashboard extension settings.
1621 - $compat_settings = get_option( 'mainwp_custom_dashboard_settings' );
1622 - if ( is_array( $compat_settings ) && isset( $compat_settings['theme'] ) ) {
1623 - $compat_theme = $compat_settings['theme'];
1624 - }
1625 - if ( null !== $compat_theme ) {
1626 - $custom_theme = $compat_theme;
1627 - }
1628 - }
1629 - $themes_files = self::get_instance()->get_custom_themes_files();
1630 - if ( empty( $themes_files ) ) {
1631 - $themes_files = array();
1632 - }
1633 - ?>
1634 - <div class="ui grid field settings-field-indicator-tools">
1635 - <label class="six wide column middle aligned">
1636 - <?php
1637 - MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_selected_theme', $custom_theme );
1638 - esc_html_e( 'Select MainWP Theme', 'mainwp' );
1639 - ?>
1640 - </label>
1641 - <div class="ten wide column" tabindex="0" data-tooltip="<?php esc_attr_e( 'Select your MainWP Dashboard theme.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1642 - <select name="mainwp_settings_custom_theme" id="mainwp_settings_custom_theme" class="ui dropdown selection">
1643 - <option value="default" <?php echo ( 'default' === $custom_theme || empty( $custom_theme ) ) ? 'selected' : ''; ?>><?php esc_html_e( 'Default', 'mainwp' ); ?></option>
1644 - <option value="classic" <?php echo ( 'classic' === $custom_theme ) ? 'selected' : ''; ?>><?php esc_html_e( 'Classic', 'mainwp' ); ?></option>
1645 - <option value="dark" <?php echo ( 'dark' === $custom_theme ) ? 'selected' : ''; ?>><?php esc_html_e( 'Dark', 'mainwp' ); ?></option>
1646 - <option value="wpadmin" <?php echo ( 'wpadmin' === $custom_theme ) ? 'selected' : ''; ?>><?php esc_html_e( 'WP Admin', 'mainwp' ); ?></option>
1647 - <option value="minimalistic" <?php echo ( 'minimalistic' === $custom_theme ) ? 'selected' : ''; ?>><?php esc_html_e( 'Minimalistic', 'mainwp' ); ?></option>
1648 - <?php
1649 - foreach ( $themes_files as $file_name => $theme ) {
1650 - $theme = ucfirst( $theme );
1651 - $_select = '';
1652 - if ( $custom_theme === $file_name ) {
1653 - $_select = 'selected';
1654 - }
1655 - echo '<option value="' . esc_attr( $file_name ) . '" ' . esc_attr( $_select ) . '>' . esc_html( $theme ) . '</option>';
1656 - }
1657 - ?>
1658 - </select>
1659 - </div>
1660 - </div>
1661 - <?php
1662 - }
1174 + if ( empty( $time_AutoUpdate ) ) {
1175 + $time_AutoUpdate = '00:00';
1176 + }
1663 1177
1664 - /**
1665 - * Get custom themes files.
1666 - */
1667 - public function get_custom_themes_files() {
1668 - // get themes files.
1669 - $dirs = $this->get_custom_theme_folder();
1670 - $scan_dir = $dirs[0];
1671 - $handle = opendir( $scan_dir );
1672 - $themes = array();
1673 - $scan_files = array();
1674 - if ( $handle ) {
1675 - $filename = readdir( $handle );
1676 - while ( false !== $filename ) {
1677 - $correct_file = true;
1678 - if ( '.' === substr( $filename, 0, 1 ) || 'index.php' === $filename ) {
1679 - $correct_file = false;
1680 - } elseif ( '.css' !== substr( $filename, - 4 ) ) {
1681 - $correct_file = false;
1682 - }
1683 - if ( $correct_file ) {
1684 - $theme = basename( $filename, '.css' );
1685 - $theme = str_replace( '-theme', '', $theme );
1686 - $themes[ $filename ] = trim( $theme );
1687 - }
1688 - $filename = readdir( $handle ); // to while loop.
1689 - }
1690 - closedir( $handle );
1691 - }
1692 - return $themes;
1693 - }
1178 + if ( ! in_array( $frequency_AutoUpdate, array( 'daily', 'weekly', 'monthly' ) ) ) {
1179 + $frequency_AutoUpdate = 'daily';
1180 + }
1694 1181
1695 - /**
1696 - * Get selected MainWP theme name.
1697 - */
1698 - public function get_selected_theme() {
1699 - $selected_theme = false;
1182 + ?>
1183 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-general" default-indi-value="daily">
1184 + <label class="six wide column middle aligned">
1185 + <?php
1186 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_frequency_AutoUpdate', $frequency_AutoUpdate );
1187 + esc_html_e( 'Frequency of automatic updates', 'mainwp' );
1188 + ?>
1189 + </label>
1190 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Set the frequency for automatic updates process.', 'mainwp' ); ?>" data-inverted="" data-position="top left" >
1191 + <select name="mainwp_frequency_AutoUpdate" id="mainwp_frequency_AutoUpdate" class="ui dropdown settings-field-value-change-handler">
1192 + <option value="daily" <?php echo 'daily' === $frequency_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Daily', 'mainwp' ); ?></option>
1193 + <option value="weekly" <?php echo 'weekly' === $frequency_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Weekly', 'mainwp' ); ?></option>
1194 + <option value="monthly" <?php echo 'monthly' === $frequency_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Monthly', 'mainwp' ); ?></option>
1195 + </select>
1196 + </div>
1197 + </div>
1700 1198
1701 - $custom_theme = $this->get_current_user_theme();
1199 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-general" id="mainwp-dayinmonth-autoupdate-wrapper" <?php echo in_array( $frequency_AutoUpdate, array( 'monthly' ) ) ? '' : 'style="display:none;"'; ?>>
1200 + <label class="six wide column middle aligned">
1201 + <?php
1202 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_dayinmonth_AutoUpdate', $dayinmonth_AutoUpdate );
1203 + esc_html_e( 'Select day', 'mainwp' );
1204 + ?>
1205 + </label>
1206 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Choose a specific day in month to initiate automatic updates process.', 'mainwp' ); ?>" data-inverted="" data-position="top left" >
1207 + <select name="mainwp_dayinmonth_AutoUpdate" id="mainwp_dayinmonth_AutoUpdate" class="ui dropdown settings-field-value-change-handler">
1208 + <?php
1209 + $day_suffix = array(
1210 + 1 => 'st',
1211 + 2 => 'nd',
1212 + 3 => 'rd',
1213 + );
1214 + for ( $x = 1; $x <= 31; $x++ ) {
1215 + $_select = '';
1216 + if ( $dayinmonth_AutoUpdate === $x ) {
1217 + $_select = 'selected';
1218 + }
1219 + $remain = $x % 10;
1220 + $day_sf = isset( $day_suffix[ $remain ] ) ? $day_suffix[ $remain ] : 'th';
1221 + echo '<option value="' . intval( $x ) . '" ' . esc_html( $_select ) . '>' . esc_html( $x . $day_sf ) . ' of the month</option>';
1222 + }
1223 + ?>
1224 + </select>
1225 + </div>
1226 + </div>
1702 1227
1703 - if ( false === $custom_theme ) {
1704 - // to compatible with Custom Dashboard extension settings.
1705 - $compat_settings = get_option( 'mainwp_custom_dashboard_settings' );
1706 - if ( is_array( $compat_settings ) && isset( $compat_settings['theme'] ) ) {
1707 - $compat_theme = $compat_settings['theme'];
1708 - }
1228 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-general" id="mainwp-dayinweek-autoupdate-wrapper" <?php echo in_array( $frequency_AutoUpdate, array( 'weekly' ) ) ? '' : 'style="display:none;"'; ?>>
1229 + <label class="six wide column middle aligned">
1230 + <?php
1231 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_dayinweek_AutoUpdate', $dayinweek_AutoUpdate );
1232 + esc_html_e( 'Select day', 'mainwp' );
1233 + ?>
1234 + </label>
1235 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Choose a specific day in week to initiate automatic updates process.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1236 + <select name="mainwp_dayinweek_AutoUpdate" id="mainwp_dayinweek_AutoUpdate" class="ui dropdown settings-field-value-change-handler">
1237 + <option value="0" <?php echo 0 === $dayinweek_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Mon', 'mainwp' ); ?></option>
1238 + <option value="1" <?php echo 1 === $dayinweek_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Tue', 'mainwp' ); ?></option>
1239 + <option value="2" <?php echo 2 === $dayinweek_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Wed', 'mainwp' ); ?></option>
1240 + <option value="3" <?php echo 3 === $dayinweek_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Thus', 'mainwp' ); ?></option>
1241 + <option value="4" <?php echo 4 === $dayinweek_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Fri', 'mainwp' ); ?></option>
1242 + <option value="5" <?php echo 5 === $dayinweek_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Sat', 'mainwp' ); ?></option>
1243 + <option value="6" <?php echo 6 === $dayinweek_AutoUpdate ? 'selected' : ''; ?>><?php esc_html_e( 'Sun', 'mainwp' ); ?></option>
1244 + </select>
1245 + </div>
1246 + </div>
1247 + <div id="mainwp-time-autoupdate-wrapper" class="ui grid field settings-field-indicator-wrapper settings-field-indicator-general" default-indi-value="00:00">
1248 + <label class="six wide column middle aligned">
1249 + <?php
1250 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_time_AutoUpdate', $time_AutoUpdate );
1251 + esc_html_e( 'Select time', 'mainwp' );
1252 + $_last_start_auto_updates = get_option( 'mainwp_automatic_updates_start_lasttime', 0 );
1253 + $_next_auto_updates = get_option( 'mainwp_automatic_update_next_run_timestamp', 0 );
1254 + ?>
1255 + </label>
1256 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Choose a specific time to initiate automatic updates process.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1257 + <div class="time-selector">
1258 + <div class="ui input left icon">
1259 + <i class="clock icon"></i>
1260 + <input type="text" class="settings-field-value-change-handler" current-utc-datetime="<?php echo date( 'Y-m-d H:i:s' ); ?>" auto-updates-last-start-time="<?php echo date( 'Y-m-d H:i:s', $_last_start_auto_updates ); ?>" auto-updates-next-time="<?php echo date( 'Y-m-d H:i:s', $_next_auto_updates ); ?>" local-datetime="<?php echo date( 'Y-m-d H:i:s', MainWP_Utility::get_timestamp() ); // phpcs:ignore -- to get local time. ?>" name="mainwp_time_AutoUpdate" id="mainwp_time_AutoUpdate" value="<?php echo esc_attr( $time_AutoUpdate ); ?>" />
1261 + </div>
1262 + </div>
1263 + </div>
1264 + </div>
1265 + <script type="text/javascript">
1266 + jQuery(document).on('change', '#mainwp_frequency_AutoUpdate', function () {
1267 + if( jQuery(this).val() == 'monthly' ){
1268 + jQuery('#mainwp-dayinweek-autoupdate-wrapper').hide();
1269 + jQuery('#mainwp-dayinmonth-autoupdate-wrapper').show();
1270 + } else if( jQuery(this).val() == 'weekly'){
1271 + jQuery('#mainwp-dayinweek-autoupdate-wrapper').show();
1272 + jQuery('#mainwp-dayinmonth-autoupdate-wrapper').hide();
1273 + } else {
1274 + jQuery('#mainwp-dayinweek-autoupdate-wrapper').hide();
1275 + jQuery('#mainwp-dayinmonth-autoupdate-wrapper').hide();
1276 + }
1277 + });
1278 + </script>
1279 + <?php
1280 + }
1709 1281
1710 - if ( null !== $compat_theme ) {
1711 - $custom_theme = $compat_theme;
1712 - }
1713 - }
1282 + /**
1283 + * Render Timezone settings.
1284 + */
1285 + public static function render_timezone_settings() { // phpcs:ignore -- NOSONAR - complex.
1714 1286
1715 - if ( ! empty( $custom_theme ) ) {
1716 - if ( 'default' === $custom_theme || 'dark' === $custom_theme || 'wpadmin' === $custom_theme || 'minimalistic' === $custom_theme ) {
1717 - return $custom_theme;
1718 - }
1719 - $dirs = $this->get_custom_theme_folder();
1720 - $theme_dir = $dirs[0];
1721 - $file = $theme_dir . $custom_theme;
1722 - if ( file_exists( $file ) && '.css' === substr( $file, - 4 ) ) {
1723 - $selected_theme = $custom_theme;
1724 - }
1725 - }
1726 - return $selected_theme;
1727 - }
1287 + $current_offset = get_option( 'gmt_offset' );
1288 + $tzstring = get_option( 'timezone_string' );
1289 + $tzstring = MainWP_Utility::clean_wp_timezone_string( $tzstring );
1728 1290
1291 + $check_zone_info = true;
1729 1292
1730 - /**
1731 - * Get custom MainWP theme folder.
1732 - */
1733 - public function get_custom_theme_folder() {
1734 - $dirs = MainWP_System_Utility::get_mainwp_dir();
1735 - global $wp_filesystem;
1736 - if ( is_array( $dirs ) && ! $wp_filesystem->exists( $dirs[0] . 'themes' ) && $wp_filesystem->exists( $dirs[0] . 'custom-dashboard' ) ) {
1737 - // re-name the custom-dashboard folder to compatible.
1738 - $wp_filesystem->move( $dirs[0] . 'custom-dashboard', $dirs[0] . 'themes' );
1739 - }
1740 - $dirs = MainWP_System_Utility::get_mainwp_dir_allow_access( 'themes' );
1741 - return $dirs;
1742 - }
1293 + // Remove old Etc mappings. Fallback to gmt_offset.
1294 + if ( false !== strpos( $tzstring, 'Etc/GMT' ) ) {
1295 + $tzstring = '';
1296 + }
1743 1297
1298 + if ( empty( $tzstring ) ) { // Create a UTC+- zone if no timezone string exists.
1299 + $check_zone_info = false;
1300 + if ( empty( $current_offset ) ) {
1301 + $tzstring = 'UTC+0';
1302 + } elseif ( $current_offset < 0 ) {
1303 + $tzstring = 'UTC' . $current_offset;
1304 + } else {
1305 + $tzstring = 'UTC+' . $current_offset;
1306 + }
1307 + }
1744 1308
1745 - /**
1746 - * Get current user's selected theme.
1747 - */
1748 - public function get_current_user_theme() {
1749 - $custom_theme = get_user_option( 'mainwp_selected_theme' );
1750 - if ( empty( $custom_theme ) ) {
1751 - $custom_theme = get_option( 'mainwp_selected_theme', 'default' );
1752 - }
1753 - return $custom_theme;
1754 - }
1309 + $timezone_format = _x( 'Y-m-d H:i:s', 'timezone date format', 'mainwp' );
1755 1310
1756 - /**
1757 - * Export Child Sites and save as .csv file.
1758 - *
1759 - * @uses \MainWP\Dashboard\MainWP_DB::query()
1760 - * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_for_current_user()
1761 - * @uses \MainWP\Dashboard\MainWP_DB::data_seek()
1762 - * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
1763 - * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
1764 - */
1765 - public static function export_sites() {
1766 - if ( isset( $_GET['doExportSites'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'export_sites' ) ) {
1311 + ?>
1312 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-general">
1313 + <label class="six wide column middle aligned"><?php esc_html_e( 'Timezone', 'mainwp' ); ?></label>
1314 + <?php
1315 + // translators: %s is the abbreviation "UTC".
1316 + $timezone_tooltip = esc_attr__( 'Choose either a city in the same timezone as you or a %s (Coordinated Universal Time) time offset.', 'mainwp' );
1317 + ?>
1318 + <div class="ten wide column" data-tooltip="<?php echo $timezone_tooltip; // phpcs:ignore WordPress.Security.EscapeOutput ?>" data-inverted="" data-position="top left">
1319 + <select id="timezone_string" class="ui dropdown" name="timezone_string" aria-describedby="timezone-description">
1320 + <?php echo wp_timezone_choice( $tzstring, get_user_locale() ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
1321 + </select>
1322 + <div class="ui hidden fitted divider"></div>
1323 + <div class="ui secondary segment">
1324 + <?php
1325 + // translators: %s is the current UTC date and time.
1326 + printf( esc_html__( 'Universal time is %s.', 'mainwp' ), '<code>' . esc_html( date_i18n( $timezone_format, false, true ) ) . '</code>' );
1327 + ?>
1328 + <div class="ui hidden fitted divider"></div>
1329 + <?php if ( get_option( 'timezone_string' ) || ! empty( $current_offset ) ) : ?>
1330 + <?php
1331 + // translators: %s is the current local date and time.
1332 + printf( esc_html__( 'Local time is %s.', 'mainwp' ), '<code>' . esc_html( date_i18n( $timezone_format ) ) . '</code>' );
1333 + ?>
1334 + <div class="ui hidden fitted divider"></div>
1335 + <?php endif; ?>
1336 + <?php if ( $check_zone_info && $tzstring ) : ?>
1337 + <?php
1338 + $now = new \DateTime( 'now', new \DateTimeZone( $tzstring ) );
1339 + $dst = (bool) $now->format( 'I' );
1767 1340
1768 - $sql = MainWP_DB::instance()->get_sql_websites_for_current_user( true );
1769 - $websites = MainWP_DB::instance()->query( $sql );
1341 + if ( $dst ) {
1342 + esc_html_e( 'This timezone is currently in daylight saving time.', 'mainwp' );
1343 + } else {
1344 + esc_html_e( 'This timezone is currently in standard time.', 'mainwp' );
1345 + }
1346 + ?>
1347 + <div class="ui hidden fitted divider"></div>
1348 + <?php
1349 + if ( in_array( $tzstring, timezone_identifiers_list(), true ) ) {
1350 + $transitions = timezone_transitions_get( timezone_open( $tzstring ), time() );
1770 1351
1771 - if ( ! $websites ) {
1772 - die( 'Not found sites' );
1773 - }
1352 + if ( ! empty( $transitions[1] ) ) {
1353 + echo ' ';
1354 + // translators: %s is the date and time when the timezone transition occurs.
1355 + $message = $transitions[1]['isdst'] ? esc_html__( 'Daylight saving time begins on: %s.', 'mainwp' ) : esc_html__( 'Standard time begins on: %s.', 'mainwp' );
1356 + printf( $message, '<code>' . wp_date( esc_html__( 'F j, Y', 'mainwp' ) . ' ' . esc_html__( 'g:i a', 'mainwp' ), esc_html( $transitions[1]['ts'] ) ) . '</code>' ); // phpcs:ignore WordPress.Security.EscapeOutput
1357 + } else {
1358 + esc_html_e( 'This timezone does not observe daylight saving time.', 'mainwp' );
1359 + }
1360 + }
1361 + ?>
1362 + <?php endif; ?>
1363 + </div>
1364 + </div>
1365 + </div>
1366 + <?php
1367 + }
1774 1368
1775 - $keys = array( 'name', 'url', 'adminname', 'wpgroups', 'uniqueId', 'http_user', 'http_pass', 'verify_certificate', 'ssl_version' );
1776 - $allowedHeaders = array( 'site name', 'url', 'admin name', 'group', 'security id', 'http username', 'http password', 'verify certificate', 'ssl version' );
1369 + /**
1370 + * Render Date/Time settings.
1371 + */
1372 + public static function render_datetime_settings() {
1373 + ?>
1374 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-general" default-indi-value="F j, Y">
1375 + <label class="six wide column middle aligned">
1376 + <?php
1377 + MainWP_Settings_Indicator::render_not_default_indicator( 'date_format', get_option( 'date_format' ) );
1378 + esc_html_e( 'Date format', 'mainwp' );
1379 + ?>
1380 + </label>
1381 + <div class="ten wide column fieldset-wrapper" data-tooltip="<?php esc_attr_e( 'Choose the display format for date.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1382 + <?php
1383 + /**
1384 + * Filters the default date formats.
1385 + *
1386 + * @since 2.7.0
1387 + * @since 4.0.0 Added ISO date standard YYYY-MM-DD format.
1388 + *
1389 + * @param string[] $default_date_formats Array of default date formats.
1390 + */
1391 + $date_formats = array_unique( apply_filters( 'date_formats', array( esc_html__( 'F j, Y', 'mainwp' ), 'Y-m-d', 'm/d/Y', 'd/m/Y' ) ) );
1777 1392
1778 - $csv = implode( ',', $allowedHeaders ) . "\r";
1779 - MainWP_DB::data_seek( $websites, 0 );
1780 - while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
1781 - if ( empty( $website ) ) {
1782 - continue;
1783 - }
1784 - $row = MainWP_Utility::map_site( $website, $keys, false );
1785 - $csv .= '"' . implode( '","', $row ) . '"' . "\r";
1786 - }
1393 + $custom = true;
1787 1394
1788 - header( 'Content-Type: text/csv; charset=utf-8' );
1789 - header( 'Content-Disposition: attachment; filename=export-sites.csv' );
1790 - echo $csv; // phpcs:ignore WordPress.Security.EscapeOutput
1791 - exit();
1792 - }
1793 - }
1395 + foreach ( $date_formats as $format ) {
1396 + echo "\t<label><input type='radio' name='date_format' value='" . esc_attr( $format ) . "'";
1397 + if ( get_option( 'date_format' ) === $format ) { // checked() uses "==" rather than "===".
1398 + echo " checked='checked'";
1399 + $custom = false;
1400 + }
1401 + echo ' /> <span class="date-time-text format-i18n">' . esc_html( date_i18n( $format ) ) . '</span><code>' . esc_html( $format ) . "</code></label><br />\n";
1402 + }
1403 + echo '<label><input type="radio" name="date_format" id="date_format_custom_radio" value="\c\u\s\t\o\m"';
1404 + checked( $custom );
1405 + echo '/> <span class="date-time-text date-time-custom-text">' . esc_html__( 'Custom:', 'mainwp' ) . '<span class="screen-reader-text"> ' . esc_html__( 'enter a custom date format in the following field', 'mainwp' ) . '</span></span></label>' .
1406 + '<label for="date_format_custom" class="screen-reader-text">' . esc_html__( 'Custom date format:', 'mainwp' ) . '</label>' .
1407 + '<input type="text" name="date_format_custom" id="date_format_custom" value="' . esc_attr( get_option( 'date_format' ) ) . '" class="small-text settings-field-value-change-handler" />' .
1408 + '<br />' .
1409 + '<em><strong>' . esc_html__( 'Preview:', 'mainwp' ) . '</strong> <span class="example">' . esc_html( date_i18n( get_option( 'date_format' ) ) ) . '</span>' .
1410 + "<span class='spinner'></span>\n" . '</em>';
1411 + ?>
1412 + </div>
1413 + </div>
1794 1414
1795 - /**
1796 - * Render MainWP Email Settings SubPage.
1797 - *
1798 - * @uses \MainWP\Dashboard\MainWP_Notification_Settings::get_notification_types()
1799 - * @uses \MainWP\Dashboard\MainWP_Notification_Settings::render_edit_settings()
1800 - * @uses \MainWP\Dashboard\MainWP_Notification_Settings::emails_general_settings_handle()
1801 - * @uses \MainWP\Dashboard\MainWP_Notification_Settings::render_all_settings()
1802 - * @uses \MainWP\Dashboard\MainWP_Notification_Template::handle_template_file_action()
1803 - */
1804 - public static function render_email_settings() {
1805 - $notification_emails = MainWP_Notification_Settings::get_notification_types();
1806 - self::render_header( 'Emails' );
1807 - $edit_email = isset( $_GET['edit-email'] ) ? sanitize_text_field( wp_unslash( $_GET['edit-email'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1808 - if ( ! empty( $edit_email ) && isset( $notification_emails[ $edit_email ] ) ) {
1809 - $updated_templ = MainWP_Notification_Template::instance()->handle_template_file_action();
1810 - MainWP_Notification_Settings::instance()->render_edit_settings( $edit_email, $updated_templ );
1811 - } else {
1812 - $updated = MainWP_Notification_Settings::emails_general_settings_handle();
1813 - MainWP_Notification_Settings::instance()->render_all_settings( $updated );
1814 - }
1815 - self::render_footer( 'Emails' );
1816 - }
1415 + <div class="ui grid field settings-field-indicator-wrapper" default-indi-value="g:i a">
1416 + <label class="six wide column middle aligned">
1417 + <?php
1418 + MainWP_Settings_Indicator::render_not_default_indicator( 'time_format', get_option( 'time_format' ) );
1419 + esc_html_e( 'Time format', 'mainwp' );
1420 + ?>
1421 + </label>
1422 + <div class="ten wide column fieldset-wrapper" data-tooltip="<?php esc_attr_e( 'Choose the display format for time.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1423 + <?php
1424 + /**
1425 + * Filters the default time formats.
1426 + *
1427 + * @since 2.7.0
1428 + *
1429 + * @param string[] $default_time_formats Array of default time formats.
1430 + */
1431 + $time_formats = array_unique( apply_filters( 'time_formats', array( esc_html__( 'g:i a', 'mainwp' ), 'g:i A', 'H:i' ) ) );
1817 1432
1818 - /**
1819 - * Hook the section help content to the Help Sidebar element
1820 - */
1821 - public static function mainwp_help_content() {
1822 - if ( isset( $_GET['page'] ) && ( 'Settings' === $_GET['page'] || 'SettingsAdvanced' === $_GET['page'] || 'MainWPTools' === $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1823 - ?>
1824 - <p><?php esc_html_e( 'If you need help with your MainWP Dashboard settings, please review following help documents', 'mainwp' ); ?></p>
1825 - <div class="ui relaxed bulleted list">
1826 - <div class="item"><a href="https://kb.mainwp.com/docs/mainwp-dashboard-settings/" target="_blank">MainWP Dashboard Settings</a> <i class="external alternate icon"></i></div>
1827 - </div>
1828 - <?php
1829 - }
1830 - }
1433 + $custom = true;
1434 +
1435 + foreach ( $time_formats as $format ) {
1436 + echo "\t<label><input type='radio' name='time_format' value='" . esc_attr( $format ) . "'";
1437 + if ( get_option( 'time_format' ) === $format ) { // checked() uses "==" rather than "===".
1438 + echo " checked='checked'";
1439 + $custom = false;
1440 + }
1441 + echo ' /> <span class="date-time-text format-i18n">' . esc_html( date_i18n( $format ) ) . '</span><code>' . esc_html( $format ) . "</code></label><br />\n";
1442 + }
1443 + echo '<label><input type="radio" name="time_format" id="time_format_custom_radio" value="\c\u\s\t\o\m"';
1444 + checked( $custom );
1445 + echo '/> <span class="date-time-text date-time-custom-text">' . esc_html__( 'Custom:', 'mainwp' ) . '<span class="screen-reader-text"> ' . esc_html__( 'enter a custom time format in the following field', 'mainwp' ) . '</span></span></label>' .
1446 + '<label for="time_format_custom" class="screen-reader-text">' . esc_html__( 'Custom time format:', 'mainwp' ) . '</label>' .
1447 + '<input type="text" class="small-text settings-field-value-change-handler" name="time_format_custom" id="time_format_custom" value="' . esc_attr( get_option( 'time_format' ) ) . '" />' .
1448 + '<br />' .
1449 + '<em><strong>' . esc_html__( 'Preview:', 'mainwp' ) . '</strong> <span class="example">' . esc_html( date_i18n( get_option( 'time_format' ) ) ) . '</span>' .
1450 + "<span class='spinner'></span>\n" . '</em>';
1451 + ?>
1452 + </div>
1453 + </div>
1454 + <script type="text/javascript">
1455 + jQuery(function($) {
1456 + $( 'input[name="date_format"]' ).on( 'click', function() {
1457 + if ( 'date_format_custom_radio' !== $( this ).attr( 'id' ) ){
1458 + $( 'input[name="date_format_custom"]' ).val( $( this ).val() ).closest( '.fieldset-wrapper' ).find( '.example' ).text( $( this ).parent( 'label' ).children( '.format-i18n' ).text() );
1459 + $( 'input[name="date_format_custom"]' ).trigger("change"); // support indicator.
1460 + }
1461 + } );
1462 +
1463 + $( 'input[name="date_format_custom"]' ).on( 'click input', function() {
1464 + $( '#date_format_custom_radio' ).prop( 'checked', true );
1465 + } );
1466 +
1467 + $( 'input[name="time_format"]' ).on( 'click', function() {
1468 + if ( 'time_format_custom_radio' !== $(this).attr( 'id' ) ){
1469 + $( 'input[name="time_format_custom"]' ).val( $( this ).val() ).closest( '.fieldset-wrapper' ).find( '.example' ).text( $( this ).parent( 'label' ).children( '.format-i18n' ).text() );
1470 + $( 'input[name="time_format_custom"]' ).trigger("change"); // support indicator.
1471 + }
1472 + } );
1473 +
1474 + $( 'input[name="time_format_custom"]' ).on( 'click input', function() {
1475 + $( '#time_format_custom_radio' ).prop( 'checked', true );
1476 + } );
1477 +
1478 + $( 'input[name="date_format_custom"], input[name="time_format_custom"]' ).on( 'input', function() {
1479 + let format = $( this ),
1480 + fieldset = format.closest( '.fieldset-wrapper' ),
1481 + example = fieldset.find( '.example' ),
1482 + spinner = fieldset.find( '.spinner' );
1483 +
1484 + // Debounce the event callback while users are typing.
1485 + clearTimeout( $.data( this, 'timer' ) );
1486 + $( this ).data( 'timer', setTimeout( function() {
1487 + // If custom date is not empty.
1488 + if ( format.val() ) {
1489 + spinner.addClass( 'is-active' );
1490 +
1491 + $.post( ajaxurl, {
1492 + action: 'date_format_custom' === format.attr( 'name' ) ? 'date_format' : 'time_format',
1493 + date : format.val()
1494 + }, function( d ) { spinner.removeClass( 'is-active' ); example.text( d ); } );
1495 + }
1496 + }, 500 ) );
1497 + } );
1498 + });
1499 + </script>
1500 + <?php
1501 + }
1502 +
1503 + /**
1504 + * Method get_websites_automatic_update_time()
1505 + *
1506 + * Get websites automatic update time.
1507 + *
1508 + * @return mixed array
1509 + *
1510 + * @uses \MainWP\Dashboard\MainWP_Utility::format_timestamp()
1511 + */
1512 + public static function get_websites_automatic_update_time() {
1513 + $lastAutomaticUpdate = MainWP_Auto_Updates_DB::instance()->get_websites_last_automatic_sync();
1514 + $lasttimeAutomatic = get_option( 'mainwp_updatescheck_last_timestamp' );
1515 + $lasttimeStartAutomatic = get_option( 'mainwp_updatescheck_start_last_timestamp' );
1516 + $local_timestamp = MainWP_Utility::get_timestamp();
1517 +
1518 + if ( empty( $lasttimeStartAutomatic ) && ! empty( $lasttimeAutomatic ) ) {
1519 + $lasttimeStartAutomatic = $lasttimeAutomatic;
1520 + }
1521 +
1522 + if ( empty( $lastAutomaticUpdate ) ) {
1523 + $nextAutomaticUpdate = esc_html__( 'Any minute', 'mainwp' );
1524 + } elseif ( 0 < MainWP_Auto_Updates_DB::instance()->get_websites_check_updates_count( $lasttimeStartAutomatic ) ) {
1525 + $nextAutomaticUpdate = esc_html__( 'Processing your websites.', 'mainwp' );
1526 + } else {
1527 + $next_time = MainWP_System_Cron_Jobs::get_next_time_automatic_update_to_show();
1528 + if ( $next_time < $local_timestamp + 5 * MINUTE_IN_SECONDS ) {
1529 + $nextAutomaticUpdate = esc_html__( 'Any minute', 'mainwp' );
1530 + } else {
1531 + $nextAutomaticUpdate = MainWP_Utility::format_timestamp( $next_time );
1532 + }
1533 + }
1534 +
1535 + if ( empty( $lastAutomaticUpdate ) ) {
1536 + $lastAutomaticUpdate = esc_html__( 'Never', 'mainwp' );
1537 + } else {
1538 + $lastAutomaticUpdate = MainWP_Utility::format_timestamp( $lastAutomaticUpdate );
1539 + }
1540 +
1541 + return array(
1542 + 'last' => $lastAutomaticUpdate,
1543 + 'next' => $nextAutomaticUpdate,
1544 + );
1545 + }
1546 +
1547 + /**
1548 + * Returns false or the location of the OpenSSL Lib File.
1549 + *
1550 + * @return mixed false|opensslLibLocation
1551 + *
1552 + * @uses \MainWP\Dashboard\MainWP_Server_Information_Handler::is_openssl_config_warning()
1553 + */
1554 + public static function show_openssl_lib_config() {
1555 + return MainWP_Server_Information_Handler::is_openssl_config_warning() ? true : false;
1556 + }
1557 +
1558 + /**
1559 + * Render Advanced Options Subpage.
1560 + *
1561 + * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
1562 + */
1563 + public static function render_advanced() { //phpcs:ignore -- NOSONAR - complex method.
1564 + if ( ! \mainwp_current_user_can( 'dashboard', 'manage_dashboard_settings' ) ) {
1565 + \mainwp_do_not_have_permissions( esc_html__( 'manage dashboard settings', 'mainwp' ) );
1566 + return;
1567 + }
1568 +
1569 + if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'SettingsAdvanced' ) ) {
1570 +
1571 + $old_settings = static::get_all_settings_values();
1572 +
1573 + /**
1574 + * Action: mainwp_before_save_advanced_settings
1575 + *
1576 + * Fires before save advanced settings.
1577 + *
1578 + * @since 4.1
1579 + */
1580 + do_action( 'mainwp_before_save_advanced_settings', $_POST );
1581 +
1582 + MainWP_Utility::update_option( 'mainwp_maximumRequests', ! empty( $_POST['mainwp_maximumRequests'] ) ? intval( $_POST['mainwp_maximumRequests'] ) : 4 );
1583 + MainWP_Utility::update_option( 'mainwp_minimumDelay', ! empty( $_POST['mainwp_minimumDelay'] ) ? intval( $_POST['mainwp_minimumDelay'] ) : 200 );
1584 + MainWP_Utility::update_option( 'mainwp_maximumIPRequests', ! empty( $_POST['mainwp_maximumIPRequests'] ) ? intval( $_POST['mainwp_maximumIPRequests'] ) : 1 );
1585 + MainWP_Utility::update_option( 'mainwp_minimumIPDelay', ! empty( $_POST['mainwp_minimumIPDelay'] ) ? intval( $_POST['mainwp_minimumIPDelay'] ) : 1000 );
1586 + MainWP_Utility::update_option( 'mainwp_maximumSyncRequests', ! empty( $_POST['mainwp_maximumSyncRequests'] ) ? intval( $_POST['mainwp_maximumSyncRequests'] ) : 8 );
1587 + MainWP_Utility::update_option( 'mainwp_maximumInstallUpdateRequests', ! empty( $_POST['mainwp_maximumInstallUpdateRequests'] ) ? intval( $_POST['mainwp_maximumInstallUpdateRequests'] ) : 3 );
1588 + MainWP_Utility::update_option( 'mainwp_sslVerifyCertificate', isset( $_POST['mainwp_sslVerifyCertificate'] ) ? 1 : 0 );
1589 + MainWP_Utility::update_option( 'mainwp_connect_signature_algo', isset( $_POST['mainwp_settings_openssl_alg'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_settings_openssl_alg'] ) ) : 0 );
1590 + MainWP_Utility::update_option( 'mainwp_verify_connection_method', isset( $_POST['mainwp_settings_verify_connection_method'] ) ? intval( $_POST['mainwp_settings_verify_connection_method'] ) : 0 );
1591 + MainWP_Utility::update_option( 'mainwp_forceUseIPv4', isset( $_POST['mainwp_forceUseIPv4'] ) ? 1 : 0 );
1592 + $use_wpcron = ! isset( $_POST['mainwp_options_wp_cron'] ) ? 0 : 1;
1593 + MainWP_Utility::update_option( 'mainwp_wp_cron', $use_wpcron );
1594 + MainWP_Utility::update_option( 'mainwp_warm_cache_pages_ttl', intval( $_POST['mainwp_warm_cache_pages_ttl'] ) );
1595 +
1596 + MainWP_Utility::update_option( 'mainwp_optimize', ( ! isset( $_POST['mainwp_optimize'] ) ? 0 : 1 ) );
1597 + MainWP_Utility::update_option( 'mainwp_auto_correct_site_url', ( ! isset( $_POST['mainwp_auto_correct_site_url'] ) ? 0 : 1 ) );
1598 + MainWP_Utility::update_option( 'mainwp_maximum_uptime_monitoring_requests', ! empty( $_POST['mainwp_maximumUptimeMonitoringRequests'] ) ? intval( $_POST['mainwp_maximumUptimeMonitoringRequests'] ) : 10 );
1599 + MainWP_Utility::update_option( 'mainwp_chunksitesnumber', isset( $_POST['mainwp_chunksitesnumber'] ) ? intval( $_POST['mainwp_chunksitesnumber'] ) : 10 );
1600 + MainWP_Utility::update_option( 'mainwp_chunksleepinterval', isset( $_POST['mainwp_chunksleepinterval'] ) ? intval( $_POST['mainwp_chunksleepinterval'] ) : 5 );
1601 +
1602 + $sync_data = array();
1603 +
1604 + if ( isset( $_POST['mainwp_settings_sync_data'] ) && is_array( $_POST['mainwp_settings_sync_data'] ) ) {
1605 + $selected_data = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_settings_sync_data'] ) );
1606 + foreach ( $selected_data as $name ) {
1607 + $sync_data[ $name ] = 1;
1608 + }
1609 + }
1610 +
1611 + if ( isset( $_POST['mainwp_settings_sync_name'] ) && is_array( $_POST['mainwp_settings_sync_name'] ) ) {
1612 + $name_data = array_map( 'sanitize_text_field', wp_unslash( $_POST['mainwp_settings_sync_name'] ) );
1613 + foreach ( $name_data as $name ) {
1614 + if ( ! isset( $sync_data[ $name ] ) ) {
1615 + $sync_data[ $name ] = 0;
1616 + }
1617 + }
1618 + }
1619 +
1620 + MainWP_Utility::update_option( 'mainwp_settings_sync_data', wp_json_encode( $sync_data ) );
1621 +
1622 + // required check.
1623 + MainWP_Uptime_Monitoring_Schedule::instance()->check_to_disable_schedule_individual_uptime_monitoring(); // required a check to sync the settings.
1624 +
1625 + if ( isset( $_POST['mainwp_openssl_lib_location'] ) ) {
1626 + $openssl_loc = ! empty( $_POST['mainwp_openssl_lib_location'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_openssl_lib_location'] ) ) : '';
1627 + MainWP_Utility::update_option( 'mainwp_opensslLibLocation', $openssl_loc );
1628 + }
1629 + /**
1630 + * Action: mainwp_after_save_advanced_settings
1631 + *
1632 + * Fires after advanced settings save.
1633 + *
1634 + * @since 4.1
1635 + */
1636 + do_action( 'mainwp_after_save_advanced_settings', $_POST );
1637 +
1638 + $new_settings = self::get_all_settings_values();
1639 +
1640 + /**
1641 + * Action: mainwp_after_save_settings
1642 + *
1643 + * Fires after save settings.
1644 + *
1645 + * @since 6.0
1646 + *
1647 + * @param array $new_settings The new settings.
1648 + * @param array $old_settings The old settings.
1649 + */
1650 + do_action( 'mainwp_after_save_settings', $new_settings, $old_settings );
1651 +
1652 + }
1653 + static::render_header( 'Advanced' );
1654 + ?>
1655 +
1656 + <div id="mainwp-advanced-settings" class="ui padded segment">
1657 + <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-advanced-settings-info-notice' ) ) : ?>
1658 + <div class="ui info message">
1659 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-advanced-settings-info-notice"></i>
1660 + <?php echo esc_html__( 'Set how many requests are performed at once and delay between requests in order to optimize your MainWP Dashboard performance. Both Cross IP and IP Settings handle the majority of work connecting to your Child sites, while the sync, update, and installation request have specialized options under the Frontend Requests Settings section.', 'mainwp' ); ?>
1661 + </div>
1662 + <?php endif; ?>
1663 + <?php if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'SettingsAdvanced' ) ) : ?>
1664 + <div class="ui green message"><i class="close icon"></i><?php esc_html_e( 'Settings have been saved successfully!', 'mainwp' ); ?></div>
1665 + <?php endif; ?>
1666 + <div class="ui form">
1667 + <form method="POST" action="">
1668 + <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
1669 + <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'SettingsAdvanced' ) ); ?>" />
1670 + <?php
1671 +
1672 + /**
1673 + * Action: mainwp_advanced_settings_form_top
1674 + *
1675 + * Fires at the top of advanced settings form.
1676 + *
1677 + * @since 4.1
1678 + */
1679 + do_action( 'mainwp_advanced_settings_form_top' );
1680 +
1681 + if ( static::show_openssl_lib_config() ) {
1682 + $openssl_loc = MainWP_System_Utility::get_openssl_conf();
1683 + ?>
1684 + <h3 class="ui dividing header">
1685 + <?php esc_html_e( 'OpenSSL Settings', 'mainwp' ); ?>
1686 + <div class="sub header"><?php esc_html_e( 'Due to bug with PHP on some servers it is required to set the OpenSSL Library location so MainWP Dashboard can connect to your child sites.', 'mainwp' ); ?></div>
1687 + </h3>
1688 + <div class="ui grid field">
1689 + <label class="six wide column middle aligned"><?php esc_html_e( 'OpenSSL.cnf location', 'mainwp' ); ?></label>
1690 + <div class="ten wide column ui field">
1691 + <input type="text" name="mainwp_openssl_lib_location" value="<?php echo esc_html( $openssl_loc ); ?>">
1692 + <em><?php esc_html_e( 'If your openssl.cnf file is saved to a different path from what is entered please enter your exact path.', 'mainwp' ); ?>
1693 + <?php
1694 + // translators: 1: Opening anchor tag. 2: Closing anchor tag.
1695 + printf( esc_html__( 'If you are not sure how to find the openssl.cnf location, please %1$scheck this help document%2$s.', 'mainwp' ), '<a href="https://docs.mainwp.com/troubleshooting/potential-issues#openssl-library-error-invalid-request" target="_blank">', '</a> <i class="external alternate icon"></i>' );
1696 + ?>
1697 + </em>
1698 + <em><?php esc_html_e( 'If you have confirmed the placement of your openssl.cnf and are still receiving an error banner, click the "Error Fixed" button to dismiss it.', 'mainwp' ); ?></em>
1699 + </div>
1700 + </div>
1701 + <?php } ?>
1702 +
1703 + <h3 class="ui dividing header">
1704 + <?php MainWP_Settings_Indicator::render_indicator( 'header', 'settings-field-indicator-cross-ip' ); ?>
1705 + <?php esc_html_e( 'Rate Limiting & Concurrency Controls', 'mainwp' ); ?>
1706 + <div class="sub header"><?php esc_html_e( 'Fine-tune how your system handles outgoing requests by managing both global and per-server concurrency limits.', 'mainwp' ); ?></div>
1707 + </h3>
1708 +
1709 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-cross-ip" default-indi-value="4">
1710 + <label class="six wide column middle aligned">
1711 + <?php
1712 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_maximumRequests', (int) get_option( 'mainwp_maximumRequests', 4 ) );
1713 + esc_html_e( 'Global request limit (Default: 4)', 'mainwp' );
1714 + ?>
1715 + </label>
1716 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Defines the overall maximum number of simultaneous requests that can be active. Adjust this setting to balance system throughput with resource constraints (default is 4).', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1717 + <div class="ui bottom aligned labeled slider" id="mainwp_maximumRequests_slider"></div>
1718 + <div class="ui input">
1719 + <input type="hidden" class="settings-field-value-change-handler" name="mainwp_maximumRequests" id="mainwp_maximumRequests" value="<?php echo false === get_option( 'mainwp_maximumRequests' ) ? 4 : esc_attr( get_option( 'mainwp_maximumRequests' ) ); ?>"/>
1720 + </div>
1721 + </div>
1722 + </div>
1723 +
1724 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-cross-ip" default-indi-value="200">
1725 + <label class="six wide column middle aligned">
1726 + <?php
1727 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_minimumDelay', (int) get_option( 'mainwp_minimumDelay', 200 ) );
1728 + esc_html_e( 'Minimum delay between requests in milliseconds (Default: 200ms)', 'mainwp' );
1729 + ?>
1730 + </label>
1731 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'This option allows you to control minimum time delay between two requests.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1732 + <div class="ui bottom aligned labeled slider" id="mainwp_minimumDelay_slider"></div>
1733 + <div class="ui input">
1734 + <input type="hidden" class="settings-field-value-change-handler" name="mainwp_minimumDelay" id="mainwp_minimumDelay" value="<?php echo false === get_option( 'mainwp_minimumDelay' ) ? 200 : esc_attr( get_option( 'mainwp_minimumDelay' ) ); ?>"/>
1735 + </div>
1736 + </div>
1737 + </div>
1738 +
1739 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-per-ip" default-indi-value="1">
1740 + <label class="six wide column middle aligned">
1741 + <?php
1742 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_maximumIPRequests', (int) get_option( 'mainwp_maximumIPRequests', 1 ) );
1743 + esc_html_e( 'Per-IP request limit (Default: 1)', 'mainwp' );
1744 + ?>
1745 + </label>
1746 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Sets the maximum number of concurrent requests allowed for any individual website\'s IP address. This setting safeguards target servers from excessive load (default is 1).', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1747 + <div class="ui bottom aligned labeled slider" id="mainwp_maximumIPRequests_slider"></div>
1748 + <div class="ui input">
1749 + <input type="hidden" class="settings-field-value-change-handler" name="mainwp_maximumIPRequests" id="mainwp_maximumIPRequests" value="<?php echo false === get_option( 'mainwp_maximumIPRequests' ) ? 1 : esc_attr( get_option( 'mainwp_maximumIPRequests' ) ); ?>"/>
1750 + </div>
1751 + </div>
1752 + </div>
1753 +
1754 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-per-ip" default-indi-value="1000">
1755 + <label class="six wide column middle aligned">
1756 + <?php
1757 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_minimumIPDelay', (int) get_option( 'mainwp_minimumIPDelay', 1000 ) );
1758 + esc_html_e( 'Minimum delay between requests to the same IP in milliseconds (Default: 1000ms)', 'mainwp' );
1759 + ?>
1760 + </label>
1761 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'This option allows you to control minimum time delay between two requests.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1762 + <div class="ui bottom aligned labeled slider" id="mainwp_minimumIPDelay_slider"></div>
1763 + <div class="ui input">
1764 + <input type="hidden" class="settings-field-value-change-handler" name="mainwp_minimumIPDelay" id="mainwp_minimumIPDelay" value="<?php echo false === get_option( 'mainwp_minimumIPDelay' ) ? 1000 : esc_attr( get_option( 'mainwp_minimumIPDelay' ) ); ?>"/>
1765 + </div>
1766 + </div>
1767 + </div>
1768 +
1769 + <h3 class="ui dividing header">
1770 + <?php MainWP_Settings_Indicator::render_indicator( 'header', 'settings-field-indicator-chunk-site' ); ?>
1771 + <?php esc_html_e( 'Batch Processing Settings', 'mainwp' ); ?>
1772 + <div class="sub header"><?php esc_html_e( 'Configure how many websites are processed at once and the delay between each batch to optimize system performance and prevent server overload.', 'mainwp' ); ?></div>
1773 + </h3>
1774 +
1775 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-cross-ip" default-indi-value="10">
1776 + <label class="six wide column middle aligned">
1777 + <?php
1778 + MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', 10 === (int) get_option( 'mainwp_chunksitesnumber', 10 ) ? '' : 1 );
1779 + esc_html_e( 'Maximum sites per batch (Default: 10)', 'mainwp' );
1780 + ?>
1781 + </label>
1782 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'The maximum number of websites processed concurrently. If too many requests are sent out, they will begin to time out.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1783 + <div class="ui bottom aligned labeled slider" id="mainwp_chunksitesnumber_slider"></div>
1784 + <div class="ui input">
1785 + <input type="hidden" class="settings-field-value-change-handler" name="mainwp_chunksitesnumber" id="mainwp_chunksitesnumber" value="<?php echo false === get_option( 'mainwp_chunksitesnumber' ) ? 10 : (int) get_option( 'mainwp_chunksitesnumber' ); ?>"/>
1786 + </div>
1787 + </div>
1788 + </div>
1789 +
1790 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-cross-ip" default-indi-value="5">
1791 + <label class="six wide column middle aligned">
1792 + <?php
1793 + MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', 5 === (int) get_option( 'mainwp_chunksleepinterval', 5 ) ? '' : 1 );
1794 + esc_html_e( 'Delay between batches (Default: 5ms)', 'mainwp' );
1795 + ?>
1796 + </label>
1797 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'The pause duration between processing each batch of websites.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1798 + <div class="ui bottom aligned labeled slider" id="mainwp_chunksleepinterval_slider"></div>
1799 + <div class="ui input">
1800 + <input type="hidden" class="settings-field-value-change-handler" name="mainwp_chunksleepinterval" id="mainwp_chunksleepinterval" value="<?php echo false === get_option( 'mainwp_chunksleepinterval' ) ? 5 : (int) get_option( 'mainwp_chunksleepinterval' ); ?>"/>
1801 + </div>
1802 + </div>
1803 + </div>
1804 +
1805 + <h3 class="ui dividing header">
1806 + <?php MainWP_Settings_Indicator::render_indicator( 'header', 'settings-field-indicator-frontend-request' ); ?>
1807 + <?php esc_html_e( 'Frontend Request Settings', 'mainwp' ); ?>
1808 + <div class="sub header"><?php esc_html_e( 'Configure limits for concurrent background tasks such as synchronization, installation/updating, and uptime monitoring, ensuring efficient resource use and system stability.', 'mainwp' ); ?></div>
1809 + </h3>
1810 +
1811 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-frontend-request" default-indi-value="8">
1812 + <label class="six wide column middle aligned">
1813 + <?php
1814 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_maximumSyncRequests', (int) get_option( 'mainwp_maximumSyncRequests', 8 ) );
1815 + esc_html_e( 'Maximum simultaneous sync requests (Default: 8)', 'mainwp' );
1816 + ?>
1817 + </label>
1818 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'This option allows you to control how many sites your MainWP Dashboard should sync at once.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1819 + <div class="ui bottom aligned labeled slider" id="mainwp_maximumSyncRequests_slider"></div>
1820 + <div class="ui input">
1821 + <input type="hidden" class="settings-field-value-change-handler" name="mainwp_maximumSyncRequests" id="mainwp_maximumSyncRequests" value="<?php echo false === get_option( 'mainwp_maximumSyncRequests' ) ? 8 : esc_attr( get_option( 'mainwp_maximumSyncRequests' ) ); ?>"/>
1822 + </div>
1823 + </div>
1824 + </div>
1825 +
1826 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-frontend-request" default-indi-value="3">
1827 + <label class="six wide column middle aligned">
1828 + <?php
1829 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_maximumInstallUpdateRequests', (int) get_option( 'mainwp_maximumInstallUpdateRequests', 3 ) );
1830 + esc_html_e( 'Maximum simultaneous install and update requests (Default: 3)', 'mainwp' );
1831 + ?>
1832 + </label>
1833 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'This option allows you to control how many update and install requests your MainWP Dashboard should process at once.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1834 + <div class="ui bottom aligned labeled slider" id="mainwp_maximumInstallUpdateRequests_slider"></div>
1835 + <div class="ui input">
1836 + <input type="hidden" class="settings-field-value-change-handler" name="mainwp_maximumInstallUpdateRequests" id="mainwp_maximumInstallUpdateRequests" value="<?php echo false === get_option( 'mainwp_maximumInstallUpdateRequests' ) ? 3 : esc_attr( get_option( 'mainwp_maximumInstallUpdateRequests' ) ); ?>"/>
1837 + </div>
1838 + </div>
1839 + </div>
1840 +
1841 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-frontend-request" default-indi-value="10">
1842 + <label class="six wide column middle aligned">
1843 + <?php
1844 + $maximum_monitoring_requests = (int) get_option( 'mainwp_maximum_uptime_monitoring_requests', 10 );
1845 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_maximum_uptime_monitoring_requests', $maximum_monitoring_requests );
1846 + esc_html_e( 'Maximum simultaneous uptime monitoring requests (Default: 10)', 'mainwp' );
1847 + ?>
1848 + </label>
1849 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'This option allows you to control how many uptime monitoring requests your MainWP Dashboard should process at once.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1850 + <div class="ui bottom aligned labeled slider settings-field-value-change-handler" id="mainwp_maximumUptimeMonitoringRequests_slider"></div>
1851 + <div class="ui input">
1852 + <input type="hidden" class="settings-field-value-change-handler" name="mainwp_maximumUptimeMonitoringRequests" id="mainwp_maximumUptimeMonitoringRequests" value="<?php echo false === get_option( 'mainwp_maximum_uptime_monitoring_requests' ) ? 10 : esc_attr( get_option( 'mainwp_maximum_uptime_monitoring_requests' ) ); ?>"/>
1853 + </div>
1854 + </div>
1855 + </div>
1856 +
1857 + <h3 class="ui dividing header">
1858 + <?php MainWP_Settings_Indicator::render_indicator( 'header', 'settings-field-indicator-miscellaneous' ); ?>
1859 + <?php esc_html_e( 'Miscellaneous Settings', 'mainwp' ); ?></h3>
1860 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-miscellaneous" default-indi-value="1">
1861 + <label class="six wide column middle aligned">
1862 + <?php
1863 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_optimize', (int) get_option( 'mainwp_optimize', 1 ) );
1864 + esc_html_e( 'Optimize data loading', 'mainwp' );
1865 + ?>
1866 + </label>
1867 + <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'If enabled, your MainWP Dashboard will cache updates for faster loading.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
1868 + <input type="checkbox" class="settings-field-value-change-handler" name="mainwp_optimize" id="mainwp_optimize" <?php echo 1 === (int) get_option( 'mainwp_optimize', 1 ) ? 'checked="true"' : ''; ?> /><label><?php esc_html_e( 'Default: Enabled', 'mainwp' ); ?></label>
1869 + </div>
1870 + </div>
1871 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-miscellaneous" default-indi-value="1">
1872 + <label class="six wide column middle aligned">
1873 + <?php
1874 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_auto_correct_site_url', (int) get_option( 'mainwp_auto_correct_site_url', 1 ) );
1875 + esc_html_e( 'Auto-correct site URLs', 'mainwp' );
1876 + ?>
1877 + </label>
1878 + <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'If enabled, your MainWP Dashboard will automatically correct the stored site URL when the child site reports a different address. Only safe changes are applied (www variant and HTTP to HTTPS); the corrected URL is verified before saving, and sites with a locked URL are never changed.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1879 + <input type="checkbox" class="settings-field-value-change-handler" name="mainwp_auto_correct_site_url" id="mainwp_auto_correct_site_url" <?php echo 1 === (int) get_option( 'mainwp_auto_correct_site_url', 1 ) ? 'checked="true"' : ''; ?> /><label><?php esc_html_e( 'Default: Enabled', 'mainwp' ); ?></label>
1880 + </div>
1881 + </div>
1882 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-miscellaneous" default-indi-value="10">
1883 + <label class="six wide column middle aligned">
1884 + <?php
1885 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_warm_cache_pages_ttl', (int) get_option( 'mainwp_warm_cache_pages_ttl', 10 ) );
1886 + esc_html_e( 'Browser cache expiration time', 'mainwp' );
1887 + $browser_cache_ttl = (int) get_option( 'mainwp_warm_cache_pages_ttl', 10 );
1888 + ?>
1889 + </label>
1890 + <div class="five wide column" data-tooltip="<?php esc_attr_e( 'Set how many minutes the browser cache should retain page content before it expires', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1891 + <input type="number" class="settings-field-value-change-handler small-text" name="mainwp_warm_cache_pages_ttl" id="mainwp_warm_cache_pages_ttl" placeholder="" min="1" max="24" step="1" value="<?php echo intval( $browser_cache_ttl ); ?>">
1892 + </div>
1893 + </div>
1894 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-miscellaneous" default-indi-value="1">
1895 + <label class="six wide column middle aligned">
1896 + <?php
1897 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_wp_cron', (int) get_option( 'mainwp_wp_cron', 1 ) );
1898 + esc_html_e( 'Use WP Cron', 'mainwp' );
1899 + ?>
1900 + </label>
1901 + <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Disabling this option will disable the WP Cron so all scheduled events will stop working.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1902 + <input type="checkbox" class="settings-field-value-change-handler" name="mainwp_options_wp_cron" id="mainwp_options_wp_cron" <?php echo 1 === (int) get_option( 'mainwp_wp_cron' ) || ( false === get_option( 'mainwp_wp_cron' ) ) ? 'checked="true"' : ''; ?>/><label><?php esc_html_e( 'Default: Enabled', 'mainwp' ); ?></label>
1903 + </div>
1904 + </div>
1905 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-miscellaneous" default-indi-value="1" >
1906 + <label class="six wide column middle aligned">
1907 + <?php
1908 + $indi_val = (int) get_option( 'mainwp_sslVerifyCertificate', 1 );
1909 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_sslVerifyCertificate', $indi_val );
1910 + esc_html_e( 'Verify SSL certificate', 'mainwp' );
1911 + ?>
1912 + </label>
1913 + <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'If enabled, your MainWP Dashboard will verify the SSL Certificate on your Child Site (if exists) while connecting the Child Site.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1914 + <input type="checkbox" class="settings-field-value-change-handler" name="mainwp_sslVerifyCertificate" id="mainwp_sslVerifyCertificate" value="checked" <?php echo false === get_option( 'mainwp_sslVerifyCertificate' ) || 1 === (int) get_option( 'mainwp_sslVerifyCertificate' ) ? 'checked="checked"' : ''; ?>/><label><?php esc_html_e( 'Default: Enabled', 'mainwp' ); ?></label>
1915 + </div>
1916 + </div>
1917 + <?php
1918 + $general_verify_con = (int) get_option( 'mainwp_verify_connection_method', 1 );
1919 + ?>
1920 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-miscellaneous" default-indi-value="1">
1921 + <label class="six wide column middle aligned">
1922 + <?php
1923 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_verify_connection_method', (int) $general_verify_con );
1924 + esc_html_e( 'Verify connection method', 'mainwp' );
1925 + ?>
1926 + </label>
1927 + <div class="ui six wide column" data-tooltip="<?php esc_attr_e( 'Select Verify connection method. If you are not sure, select "Default".', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1928 + <select class="ui dropdown settings-field-value-change-handler" id="mainwp_settings_verify_connection_method" name="mainwp_settings_verify_connection_method">
1929 + <option <?php echo ( empty( $general_verify_con ) || 1 === $general_verify_con ) ? 'selected' : ''; ?> value="1"><?php esc_html_e( 'OpenSSL (default)', 'mainwp' ); ?></option>
1930 + <option <?php echo ( 2 === $general_verify_con ) ? 'selected' : ''; ?> value="2"><?php esc_html_e( 'PHPSECLIB (fallback)', 'mainwp' ); ?></option>
1931 + </select>
1932 + </div>
1933 + </div>
1934 + <?php
1935 + $sign_note = MainWP_Connect_Lib::get_connection_algo_settings_note();
1936 + $sign_algs = MainWP_System_Utility::get_open_ssl_sign_algos();
1937 + $general_sign_alg = get_option( 'mainwp_connect_signature_algo', false );
1938 + if ( false === $general_sign_alg ) {
1939 + $general_sign_alg = defined( 'OPENSSL_ALGO_SHA256' ) ? OPENSSL_ALGO_SHA256 : 1;
1940 + MainWP_Utility::update_option( 'mainwp_connect_signature_algo', $general_sign_alg );
1941 + } else {
1942 + $general_sign_alg = intval( $general_sign_alg );
1943 + }
1944 + $algo_def = defined( 'OPENSSL_ALGO_SHA256' ) ? (int) OPENSSL_ALGO_SHA256 : 1;
1945 + ?>
1946 + <div default-indi-value="<?php echo esc_attr( $algo_def ); ?>" class="ui grid field mainwp-hide-elemenent-sign-algo settings-field-indicator-wrapper settings-field-indicator-miscellaneous" <?php echo ( 2 === $general_verify_con ) ? 'style="display:none;"' : ''; ?> >
1947 + <label class="six wide column middle aligned">
1948 + <?php
1949 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_connect_signature_algo', (int) $general_sign_alg );
1950 + esc_html_e( 'OpenSSL signature algorithm', 'mainwp' );
1951 + ?>
1952 + </label>
1953 + <div class="ui six wide column" data-tooltip="<?php esc_attr_e( 'Select OpenSSL signature algorithm. If you are not sure, select "Default".', 'mainwp' ); ?>" data-inverted="" data-position="top left">
1954 + <select class="ui dropdown settings-field-value-change-handler" id="mainwp_settings_openssl_alg" name="mainwp_settings_openssl_alg">
1955 + <?php
1956 + foreach ( $sign_algs as $val => $text ) {
1957 + ?>
1958 + <option <?php echo ( $val === $general_sign_alg ) ? 'selected' : ''; ?> value="<?php echo esc_attr( $val ); ?>"><?php echo esc_html( $text ); ?></option>
1959 + <?php
1960 + }
1961 + ?>
1962 + </select>
1963 + <div class="ui yellow message mainwp-hide-elemenent-sign-algo-note" <?php echo ( 1 === $general_sign_alg ) ? '' : 'style="display:none;"'; ?>><?php echo esc_html( $sign_note ); ?></div>
1964 + </div>
1965 + </div>
1966 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-miscellaneous">
1967 + <label class="six wide column middle aligned">
1968 + <?php
1969 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_forceUseIPv4', (int) get_option( 'mainwp_forceUseIPv4' ) );
1970 + esc_html_e( 'Force IPv4', 'mainwp' );
1971 + ?>
1972 + </label>
1973 + <div class="ten wide column ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Enable if you want to force your MainWP Dashboard to use IPv4 while trying to connect child sites.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
1974 + <input type="checkbox" class="settings-field-value-change-handler" name="mainwp_forceUseIPv4" id="mainwp_forceUseIPv4" value="checked" <?php echo ( 1 === (int) get_option( 'mainwp_forceUseIPv4' ) ) ? 'checked="checked"' : ''; ?>/><label><?php esc_html_e( 'Default: Disabled', 'mainwp' ); ?></label>
1975 + </div>
1976 + </div>
1977 + <?php
1978 + static::render_sync_data_selection();
1979 + /**
1980 + * Action: mainwp_advanced_settings_form_bottom
1981 + *
1982 + * Fires at the bottom of advanced settings form.
1983 + *
1984 + * @since 4.1
1985 + */
1986 + do_action( 'mainwp_advanced_settings_form_bottom' );
1987 +
1988 + ?>
1989 + <div class="ui divider"></div>
1990 + <input type="submit" name="submit" id="submit" class="ui green big button" value="<?php esc_attr_e( 'Save Settings', 'mainwp' ); ?>"/>
1991 + </form>
1992 + </div>
1993 + </div>
1994 + <?php static::render_disable_installed_plugins_sync_modal(); ?>
1995 + <script>
1996 + jQuery(document).ready(function() {
1997 + const maximumRequests = <?php echo ! empty( get_option( 'mainwp_maximumRequests' ) ) ? esc_js( get_option( 'mainwp_maximumRequests' ) ) : 4; ?>;
1998 + jQuery('#mainwp_maximumRequests_slider').slider({
1999 + min: 1,
2000 + max: 20,
2001 + start: maximumRequests,
2002 + step: 1,
2003 + restrictedLabels: [1,20],
2004 + showThumbTooltip: true,
2005 + tooltipConfig: {
2006 + position: 'top center',
2007 + variation: 'small visible black'
2008 + },
2009 + onChange: function(value) {
2010 + jQuery('#mainwp_maximumRequests').val(value);
2011 + }
2012 + });
2013 + const minimumDelay = <?php echo ! empty( get_option( 'mainwp_minimumDelay' ) ) ? esc_js( get_option( 'mainwp_minimumDelay' ) ) : 200; ?>;
2014 + jQuery('#mainwp_minimumDelay_slider').slider({
2015 + min: 100,
2016 + max: 5000,
2017 + start: minimumDelay,
2018 + step: 100,
2019 + restrictedLabels: [100,5000],
2020 + showThumbTooltip: true,
2021 + tooltipConfig: {
2022 + position: 'top center',
2023 + variation: 'small visible black'
2024 + },
2025 + onChange: function(value) {
2026 + jQuery('#mainwp_minimumDelay').val(value);
2027 + }
2028 + });
2029 + const maximumIPRequests = <?php echo ! empty( get_option( 'mainwp_maximumIPRequests' ) ) ? esc_js( get_option( 'mainwp_maximumIPRequests' ) ) : 1; ?>;
2030 + jQuery('#mainwp_maximumIPRequests_slider').slider({
2031 + min: 1,
2032 + max: 10,
2033 + start: maximumIPRequests,
2034 + step: 1,
2035 + restrictedLabels: [1,10],
2036 + showThumbTooltip: true,
2037 + tooltipConfig: {
2038 + position: 'top center',
2039 + variation: 'small visible black'
2040 + },
2041 + onChange: function(value) {
2042 + jQuery('#mainwp_maximumIPRequests').val(value);
2043 + }
2044 + });
2045 + const minimumIPDelay = <?php echo ! empty( get_option( 'mainwp_minimumIPDelay' ) ) ? esc_js( get_option( 'mainwp_minimumIPDelay' ) ) : 1000; ?>;
2046 + jQuery('#mainwp_minimumIPDelay_slider').slider({
2047 + min: 500,
2048 + max: 5000,
2049 + start: minimumIPDelay,
2050 + step: 100,
2051 + restrictedLabels: [500,5000],
2052 + showThumbTooltip: true,
2053 + tooltipConfig: {
2054 + position: 'top center',
2055 + variation: 'small visible black'
2056 + },
2057 + onChange: function(value) {
2058 + jQuery('#mainwp_minimumIPDelay').val(value);
2059 + }
2060 + });
2061 + const maximumSyncRequests = <?php echo ! empty( get_option( 'mainwp_maximumSyncRequests' ) ) ? esc_js( get_option( 'mainwp_maximumSyncRequests' ) ) : 8; ?>;
2062 + jQuery('#mainwp_maximumSyncRequests_slider').slider({
2063 + min: 1,
2064 + max: 20,
2065 + start: maximumSyncRequests,
2066 + step: 1,
2067 + restrictedLabels: [1,20],
2068 + showThumbTooltip: true,
2069 + tooltipConfig: {
2070 + position: 'top center',
2071 + variation: 'small visible black'
2072 + },
2073 + onChange: function(value) {
2074 + jQuery('#mainwp_maximumSyncRequests').val(value);
2075 + }
2076 + });
2077 + const maximumInstallUpdateRequests = <?php echo ! empty( get_option( 'mainwp_maximumInstallUpdateRequests' ) ) ? esc_js( get_option( 'mainwp_maximumInstallUpdateRequests' ) ) : 3; ?>;
2078 + jQuery('#mainwp_maximumInstallUpdateRequests_slider').slider({
2079 + min: 1,
2080 + max: 20,
2081 + start: maximumInstallUpdateRequests,
2082 + step: 1,
2083 + restrictedLabels: [1,20],
2084 + showThumbTooltip: true,
2085 + tooltipConfig: {
2086 + position: 'top center',
2087 + variation: 'small visible black'
2088 + },
2089 + onChange: function(value) {
2090 + jQuery('#mainwp_maximumInstallUpdateRequests').val(value);
2091 + }
2092 + });
2093 + const maximumUptimeMonitoringRequests = <?php echo ! empty( get_option( 'mainwp_maximum_uptime_monitoring_requests' ) ) ? esc_js( get_option( 'mainwp_maximum_uptime_monitoring_requests' ) ) : 10; ?>;
2094 + jQuery('#mainwp_maximumUptimeMonitoringRequests_slider').slider({
2095 + min: 1,
2096 + max: 100,
2097 + start: maximumUptimeMonitoringRequests,
2098 + step: 1,
2099 + restrictedLabels: [1,100],
2100 + showThumbTooltip: true,
2101 + tooltipConfig: {
2102 + position: 'top center',
2103 + variation: 'small visible black'
2104 + },
2105 + onChange: function(value) {
2106 + jQuery('#mainwp_maximumUptimeMonitoringRequests').val(value).change();
2107 + }
2108 + });
2109 + jQuery('#mainwp_maximumUptimeMonitoringRequests_slider').slider('set value', maximumUptimeMonitoringRequests);
2110 +
2111 + jQuery('#mainwp_chunksitesnumber_slider').slider({
2112 + min: 1,
2113 + max: 30,
2114 + start: <?php echo false !== get_option( 'mainwp_chunksitesnumber' ) ? intval( get_option( 'mainwp_chunksitesnumber' ) ) : 10; ?>,
2115 + step: 1,
2116 + restrictedLabels: [1,30],
2117 + showThumbTooltip: true,
2118 + tooltipConfig: {
2119 + position: 'top center',
2120 + variation: 'small visible black'
2121 + },
2122 + onChange: function(value) {
2123 + jQuery('#mainwp_chunksitesnumber').val(value).change();
2124 + }
2125 + });
2126 +
2127 + jQuery('#mainwp_chunksleepinterval_slider').slider({
2128 + min: 0,
2129 + max: 20,
2130 + start: <?php echo false !== get_option( 'mainwp_chunksleepinterval' ) ? intval( get_option( 'mainwp_chunksleepinterval' ) ) : 5; ?>,
2131 + step: 1,
2132 + restrictedLabels: [0,20],
2133 + showThumbTooltip: true,
2134 + tooltipConfig: {
2135 + position: 'top center',
2136 + variation: 'small visible black'
2137 + },
2138 + onChange: function(value) {
2139 + jQuery('#mainwp_chunksleepinterval').val(value).change();
2140 + }
2141 + });
2142 + });
2143 + </script>
2144 + <?php
2145 + static::render_footer( 'Advanced' );
2146 + }
2147 +
2148 + /**
2149 + * Method render_sync_data_selection().
2150 + *
2151 + * @return void
2152 + */
2153 + public static function render_sync_data_selection() {
2154 +
2155 + $default_sync = static::get_data_sync_default();
2156 +
2157 + $sync_data_settings = get_option( 'mainwp_settings_sync_data' );
2158 +
2159 + $sync_data_settings = ! empty( $sync_data_settings ) ? json_decode( $sync_data_settings, true ) : array();
2160 +
2161 + if ( ! is_array( $sync_data_settings ) ) {
2162 + $sync_data_settings = array();
2163 + }
2164 +
2165 + $setting_page = true;
2166 +
2167 + ?>
2168 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-miscellaneous">
2169 + <label class="six wide column top aligned">
2170 + <?php
2171 + MainWP_Settings_Indicator::render_indicator( 'header', 'settings-field-indicator-sync-data' );
2172 + esc_html_e( 'Select data to sync', 'mainwp' );
2173 + ?>
2174 + </label>
2175 + <div class="ten wide column" <?php echo $setting_page ? 'data-tooltip="' . esc_attr__( 'Select data that you want to sync.', 'mainwp' ) . '"' : ''; ?> data-inverted="" data-position="top left">
2176 + <ul class="mainwp_hide_wpmenu_checkboxes">
2177 + <?php
2178 + foreach ( $default_sync as $name => $title ) {
2179 + $_selected = '';
2180 + if ( ! isset( $sync_data_settings[ $name ] ) || 1 === (int) $sync_data_settings[ $name ] ) {
2181 + $_selected = 'checked';
2182 + }
2183 + ?>
2184 + <li>
2185 + <div class="ui checkbox">
2186 + <input type="checkbox" class="settings-field-value-change-handler" id="mainwp_select_sync_<?php echo esc_attr( $name ); ?>" name="mainwp_settings_sync_data[]" <?php echo esc_html( $_selected ); ?> value="<?php echo esc_attr( $name ); ?>">
2187 + <label for="mainwp_select_sync_<?php echo esc_attr( $name ); ?>" ><?php echo esc_html( $title ); ?></label>
2188 + </div>
2189 + <input type="hidden" name="mainwp_settings_sync_name[]" value="<?php echo esc_attr( $name ); ?>">
2190 + </li>
2191 + <?php
2192 + }
2193 + ?>
2194 + </ul>
2195 + </div>
2196 + </div>
2197 + <?php
2198 + }
2199 +
2200 + /**
2201 + * Render the Installed plugins sync warning modal.
2202 + *
2203 + * @since 6.1.3
2204 + *
2205 + * @return void
2206 + */
2207 + public static function render_disable_installed_plugins_sync_modal() {
2208 + ?>
2209 + <div class="ui small modal" id="mainwp-disable-installed-plugins-sync-modal">
2210 + <div class="header"><?php esc_html_e( 'Disable Installed Plugins Sync?', 'mainwp' ); ?></div>
2211 + <div class="content">
2212 + <div class="ui yellow message">
2213 + <div class="header"><?php esc_html_e( 'MainWP Add-ons may not work as expected', 'mainwp' ); ?></div>
2214 + <p><?php esc_html_e( 'Some MainWP Add-ons need the installed plugins data to detect required plugins on your Child Sites. If you disable this option, those Add-ons may not work as expected.', 'mainwp' ); ?></p>
2215 + </div>
2216 + </div>
2217 + <div class="actions">
2218 + <div class="ui basic cancel button"><?php esc_html_e( 'Cancel', 'mainwp' ); ?></div>
2219 + <div class="ui green approve button"><?php esc_html_e( 'I understand', 'mainwp' ); ?></div>
2220 + </div>
2221 + </div>
2222 + <script type="text/javascript">
2223 + jQuery( document ).ready( function () {
2224 + const installedPluginsCheckbox = jQuery( '#mainwp_select_sync_plugins' );
2225 + const warningModal = jQuery( '#mainwp-disable-installed-plugins-sync-modal' );
2226 + let disableConfirmed = false;
2227 +
2228 + installedPluginsCheckbox.on( 'change', function () {
2229 + if ( installedPluginsCheckbox.is( ':checked' ) ) {
2230 + disableConfirmed = false;
2231 + return;
2232 + }
2233 +
2234 + if ( disableConfirmed ) {
2235 + return;
2236 + }
2237 +
2238 + warningModal.modal( {
2239 + closable: false,
2240 + onApprove: function () {
2241 + disableConfirmed = true;
2242 + },
2243 + onDeny: function () {
2244 + installedPluginsCheckbox.prop( 'checked', true ).trigger( 'change' );
2245 + }
2246 + } ).modal( 'show' );
2247 + } );
2248 + } );
2249 + </script>
2250 + <?php
2251 + }
2252 +
2253 + /**
2254 + * Method get_data_sync_default().
2255 + *
2256 + * @return array data.
2257 + */
2258 + public static function get_data_sync_default() {
2259 + return array(
2260 + 'wp_updates' => __( 'WordPress updates information', 'mainwp' ),
2261 + 'plugin_updates' => __( 'Plugins updates information', 'mainwp' ),
2262 + 'theme_updates' => __( 'Themes updates information', 'mainwp' ),
2263 + 'translation_updates' => __( 'Translations updates information', 'mainwp' ),
2264 + 'recent_comments' => __( 'Recent comments', 'mainwp' ),
2265 + 'recent_posts' => __( 'Recent posts', 'mainwp' ),
2266 + 'recent_pages' => __( 'Recent pages', 'mainwp' ),
2267 + 'securityStats' => __( 'Site hardening information', 'mainwp' ),
2268 + 'directories' => __( 'Site directory listing (needed for legacy backup feature)', 'mainwp' ),
2269 + 'categories' => __( 'Posts catetegories', 'mainwp' ),
2270 + 'totalsize' => __( 'Website size (needed for Clone and legacy backup features)', 'mainwp' ),
2271 + 'dbsize' => __( 'Database size information', 'mainwp' ),
2272 + 'plugins' => __( 'Installed plugins', 'mainwp' ),
2273 + 'themes' => __( 'Installed Themes', 'mainwp' ),
2274 + 'users' => __( 'Users information', 'mainwp' ),
2275 + 'plugins_outdate_info' => __( 'Abandoned plugins information', 'mainwp' ),
2276 + 'themes_outdate_info' => __( 'Abandoned themes information', 'mainwp' ),
2277 + 'health_site_status' => __( 'Site health information', 'mainwp' ),
2278 + 'child_site_actions_data' => __( 'Non-MainWP changes data', 'mainwp' ),
2279 + 'othersData' => __( 'Other data (required by some extensions)', 'mainwp' ),
2280 + );
2281 + }
2282 +
2283 + /**
2284 + * Method get_data_list_to_sync().
2285 + *
2286 + * @return array Data list to sync.
2287 + */
2288 + public function get_data_list_to_sync() {
2289 + $sync_data_settings = get_option( 'mainwp_settings_sync_data' );
2290 +
2291 + if ( false === $sync_data_settings ) {
2292 + $default_sync = static::get_data_sync_default();
2293 + $sync_lists = array_fill_keys( array_keys( $default_sync ), 1 );
2294 + MainWP_Utility::update_option( 'mainwp_settings_sync_data', wp_json_encode( $sync_lists ) );
2295 + return $sync_lists;
2296 + }
2297 +
2298 + $sync_lists = ! empty( $sync_data_settings ) ? json_decode( $sync_data_settings, true ) : array();
2299 +
2300 + if ( ! is_array( $sync_lists ) ) {
2301 + $sync_lists = array();
2302 + }
2303 + return $sync_lists;
2304 + }
2305 +
2306 +
2307 + /**
2308 + * Render MainWP Tools SubPage.
2309 + *
2310 + * @uses \MainWP\Dashboard\MainWP_UI::render_screen_options()
2311 + */
2312 + public static function render_mainwp_tools() { // phpcs:ignore -- NOSONAR - complex.
2313 + if ( ! \mainwp_current_user_can( 'dashboard', 'manage_dashboard_settings' ) ) {
2314 + \mainwp_do_not_have_permissions( esc_html__( 'manage dashboard settings', 'mainwp' ) );
2315 + return;
2316 + }
2317 + static::render_header( 'MainWPTools' );
2318 + ?>
2319 + <div id="mainwp-tools-settings" class="ui padded segment">
2320 + <div id="mainwp-message-zone" style="display:none;" class="ui message"></div>
2321 + <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-tools-info-message' ) ) : ?>
2322 + <div class="ui info message">
2323 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-tools-info-message"></i>
2324 + <?php
2325 + // translators: 1: Opening anchor tag. 2: Closing anchor tag.
2326 + printf( esc_html__( 'Use MainWP tools to adjust your MainWP Dashboard to your needs and perform specific actions when needed. For additional help, review this %1$shelp document%2$s.', 'mainwp' ), '<a href="https://docs.mainwp.com/sites/management/mainwp-dashboard-settings#mainwp-dashboard-settings" target="_blank">', '</a> <i class="external alternate icon"></i>' );
2327 + ?>
2328 + </div>
2329 + <?php endif; ?>
2330 + <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-tools-info-custom-theme' ) ) : ?>
2331 + <div class="ui info message">
2332 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-tools-info-custom-theme"></i>
2333 + <div><?php esc_html_e( 'Here you can select a theme for your MainWP Dashboard.', 'mainwp' ); ?></div>
2334 + <div><?php esc_html_e( 'To create a custom theme, copy the `mainwp-dark-theme.css` file from the MainWP Custom Dashboard Extension located in the `css` directory, make your edits and upload the file to the `../wp-content/uploads/mainwp/custom-dashboard/` directory.', 'mainwp' ); ?></div>
2335 + </div>
2336 + <?php endif; ?>
2337 + <?php
2338 + $show_saved_message = false;
2339 + if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MainWPTools' ) ) {
2340 + $show_saved_message = true;
2341 + } elseif ( get_transient( 'mainwp_settings_saved' ) ) {
2342 + $show_saved_message = true;
2343 + delete_transient( 'mainwp_settings_saved' ); // Remove transient after showing message.
2344 + }
2345 + ?>
2346 + <?php if ( $show_saved_message ) : ?>
2347 + <div class="ui green message">
2348 + <i class="close icon"></i>
2349 + <?php esc_html_e( 'Settings have been saved successfully!', 'mainwp' ); ?>
2350 + </div>
2351 + <?php endif; ?>
2352 + <?php if ( isset( $_POST['mainwp_restore_info_messages'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'MainWPTools' ) ) : ?>
2353 + <div class="ui green message"><i class="close icon"></i><?php esc_html_e( 'Info messages have been restored successfully!', 'mainwp' ); ?></div>
2354 + <?php endif; ?>
2355 + <div class="ui form">
2356 + <form method="POST" action="">
2357 + <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
2358 + <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'MainWPTools' ) ); ?>" />
2359 +
2360 + <?php
2361 + /**
2362 + * Action: mainwp_tools_form_top
2363 + *
2364 + * Fires at the top of MainWP tools form.
2365 + *
2366 + * @since 4.1
2367 + */
2368 + do_action( 'mainwp_tools_form_top' );
2369 +
2370 + $show_qsw = apply_filters( 'mainwp_show_qsw', true );
2371 +
2372 + static::get_instance()->render_select_custom_themes();
2373 +
2374 + ?>
2375 + <?php if ( get_option( 'mainwp_not_start_encrypt_keys' ) ) { ?>
2376 + <div class="ui grid field">
2377 + <label class="six wide column middle aligned"><?php esc_html_e( 'OpenSSL Key Encryption', 'mainwp' ); ?></label>
2378 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'To enhance security, we\'ve added a feature to encrypt your private keys stored in the database.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
2379 + <input type="button" name="" id="increase-connection-security-btn" data-inverted="" data-position="top right" data-tooltip="<?php esc_attr_e( 'To enhance security, we\'ve added a feature to encrypt your private keys stored in the database.', 'mainwp' ); ?>" class="ui green basic button" value="<?php esc_attr_e( 'Encrypt Keys Now', 'mainwp' ); ?>" />
2380 + </div>
2381 + </div>
2382 + <?php } ?>
2383 + <div class="ui grid field">
2384 + <label class="six wide column middle aligned"><?php esc_html_e( 'Force your MainWP Dashboard to establish a new connection', 'mainwp' ); ?></label>
2385 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Force your MainWP Dashboard to reconnect with your child sites. Only needed if suggested by MainWP Support.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
2386 + <input type="button" name="" id="force-destroy-sessions-button" data-inverted="" data-position="top right" data-tooltip="<?php esc_attr_e( 'Forces your dashboard to reconnect with your child sites. This feature will log out any currently logged in users on the Child sites and require them to re-log in. Only needed if suggested by MainWP Support.', 'mainwp' ); ?>" class="ui green basic button" value="<?php esc_attr_e( 'Re-establish Connections', 'mainwp' ); ?>" />
2387 + </div>
2388 + </div>
2389 + <div class="ui grid field">
2390 + <label class="six wide column middle aligned"><?php esc_html_e( 'Force your MainWP Dashboard to set a new pair of OpenSSL Keys', 'mainwp' ); ?></label>
2391 + <div class="ten wide column" id="mainwp-renew-connections-tool" data-content="<?php esc_attr_e( 'This will function renew connection and reconnect site right away.', 'mainwp' ); ?>" data-variation="inverted" data-position="top left">
2392 + <a href="javascript:void(0)" onclick="mainwp_tool_renew_connections_show(); return false;" class="ui button green basic"><?php esc_html_e( 'Reset OpenSSL Key Pair', 'mainwp' ); ?></a>
2393 + </div>
2394 + </div>
2395 + <?php if ( $show_qsw ) { ?>
2396 + <div class="ui grid field">
2397 + <label class="six wide column middle aligned"><?php esc_html_e( 'Start the MainWP Quick Setup Wizard', 'mainwp' ); ?></label>
2398 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Click this button to start the Quick Setup Wizard', 'mainwp' ); ?>" data-inverted="" data-position="top left"><a href="admin.php?page=mainwp-setup" class="ui green button basic" ><?php esc_html_e( 'Start Quick Setup Wizard', 'mainwp' ); ?></a></div>
2399 + </div>
2400 + <?php } ?>
2401 + <div class="ui grid field">
2402 + <label class="six wide column middle aligned"><?php esc_html_e( 'Export child sites to CSV file', 'mainwp' ); ?></label>
2403 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Click this button to export all connected sites to a CSV file.', 'mainwp' ); ?>" data-inverted="" data-position="top left"><a href="admin.php?page=MainWPTools&doExportSites=yes&_wpnonce=<?php echo esc_attr( wp_create_nonce( 'export_sites' ) ); ?>" class="ui button green basic"><?php esc_html_e( 'Export Child Sites', 'mainwp' ); ?></a></div>
2404 + </div>
2405 + <div class="ui grid field">
2406 + <label class="six wide column middle aligned"><?php esc_html_e( 'Import child sites', 'mainwp' ); ?></label>
2407 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Click this button to import websites to your MainWP Dashboard.', 'mainwp' ); ?>" data-inverted="" data-position="top left"><a href="admin.php?page=managesites&do=bulknew" class="ui button green basic"><?php esc_html_e( 'Import Child Sites', 'mainwp' ); ?></a></div>
2408 + </div>
2409 + <div class="ui grid field">
2410 + <label class="six wide column middle aligned"><?php esc_html_e( 'Disconnect all child sites', 'mainwp' ); ?></label>
2411 + <div class="ten wide column" id="mainwp-disconnect-sites-tool" data-content="<?php esc_attr_e( 'This will function will break the connection and leave the MainWP Child plugin active and which makes your sites vulnerable. Use only if you attend to reconnect site to the same or a different dashboard right away.', 'mainwp' ); ?>" data-variation="inverted" data-position="top left">
2412 + <a href="admin.php?page=MainWPTools&disconnectSites=yes&_wpnonce=<?php echo esc_attr( wp_create_nonce( 'disconnect_sites' ) ); ?>" onclick="mainwp_tool_disconnect_sites(); return false;" class="ui button green basic"><?php esc_html_e( 'Disconnect Sites', 'mainwp' ); ?></a>
2413 + </div>
2414 + </div>
2415 + <div class="ui grid field">
2416 + <label class="six wide column middle aligned"><?php esc_html_e( 'Delete add-ons API Activation data', 'mainwp' ); ?></label>
2417 + <div class="ten wide column" id="mainwp-clear-activation-data" data-content="<?php esc_attr_e( 'This does not affect extensions settings, it just removes API activation data.', 'mainwp' ); ?>" data-variation="inverted" data-position="top left">
2418 + <a href="admin.php?page=MainWPTools&clearActivationData=yes&_wpnonce=<?php echo esc_attr( wp_create_nonce( 'clear_activation_data' ) ); ?>" onclick="mainwp_tool_confirm_to_process(this); return false;" class="ui button green basic"><?php esc_html_e( 'Delete Add-ons API Activation Data', 'mainwp' ); ?></a>
2419 + </div>
2420 + </div>
2421 + <div class="ui grid field">
2422 + <label class="six wide column middle aligned"><?php esc_html_e( 'Delete archived Network Activity data', 'mainwp' ); ?></label>
2423 + <div class="ten wide column" id="mainwp-clear-archived-sites-changes-data" data-content="<?php esc_attr_e( 'Delete archived sNetwork Activity data.', 'mainwp' ); ?>" data-variation="inverted" data-position="top left">
2424 + <a href="admin.php?page=MainWPTools&clearArchivedSitesChangesData=yes&_wpnonce=<?php echo esc_attr( wp_create_nonce( 'clear_archived_sites_changes' ) ); ?>" onclick="mainwp_tool_confirm_to_process(this); return false;" class="ui button green basic"><?php esc_html_e( 'Delete Archived Network Activity Data', 'mainwp' ); ?></a>
2425 + </div>
2426 + </div>
2427 + <div class="ui grid field">
2428 + <label class="six wide column middle aligned"><?php esc_html_e( 'Restore all info messages', 'mainwp' ); ?></label>
2429 + <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Click this button to restore all info messages in your MainWP Dashboard and Extensions.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
2430 + <input type="submit" name="mainwp_restore_info_messages" id="mainwp_restore_info_messages" class="ui button" value="<?php esc_attr_e( 'Restore Info Messages', 'mainwp' ); ?>"/>
2431 + </div>
2432 + </div>
2433 +
2434 + <h3 class="ui dividing header">
2435 + <?php esc_html_e( 'Privacy & Third-Party Services Permissions', 'mainwp' ); ?>
2436 + <div class="sub header"><?php esc_html_e( 'These tools are implemented using JavaScript and are subject to their respective privacy policies. You can choose which services to enable below, and update preferences at any time.', 'mainwp' ); ?></div>
2437 + </h3>
2438 +
2439 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-tools">
2440 + <label class="six wide column middle aligned">
2441 + <?php
2442 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_enable_guided_tours', (int) get_option( 'mainwp_enable_guided_tours', 0 ) );
2443 + esc_html_e( 'Usetiful (Interactive Guides & Tips)', 'mainwp' );
2444 + ?>
2445 + <span class="ui blue mini label"><?php esc_html_e( 'BETA', 'mainwp' ); ?></span>
2446 + </label>
2447 + <div class="ten wide column " data-tooltip="<?php esc_attr_e( 'Check this option to enable, or uncheck to disable MainWP guided tours.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
2448 + <div class="ui toggle checkbox">
2449 + <input type="checkbox" class="settings-field-value-change-handler" name="mainwp-guided-tours-option" id="mainwp-guided-tours-option" <?php echo 1 === (int) get_option( 'mainwp_enable_guided_tours', 0 ) ? 'checked="true"' : ''; ?> />
2450 + <label><?php esc_html_e( 'Enable guided tours, tooltips, and onboarding assistance to help you navigate MainWP more efficiently.', 'mainwp' ); ?></label>
2451 + </div>
2452 + </div>
2453 + </div>
2454 +
2455 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-tools">
2456 + <label class="six wide column middle aligned">
2457 + <?php
2458 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_enable_guided_chatbase', (int) get_option( 'mainwp_enable_guided_chatbase', 0 ) );
2459 + esc_html_e( 'Chatbase (AI-Powered Chat Support)', 'mainwp' );
2460 + ?>
2461 + <span class="ui blue mini label"><?php esc_html_e( 'BETA', 'mainwp' ); ?></span>
2462 + </label>
2463 + <div class="ten wide column " data-tooltip="<?php esc_attr_e( 'Check this option to enable, or uncheck to disable MainWP AI drive support.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
2464 + <div class="ui toggle checkbox">
2465 + <input type="checkbox" class="settings-field-value-change-handler" name="mainwp-guided-chatbase-option" id="mainwp-guided-chatbase-option" <?php echo 1 === (int) get_option( 'mainwp_enable_guided_chatbase', 0 ) ? 'checked="true"' : ''; ?> />
2466 + <label><?php esc_html_e( 'Get AI-driven support within the MainWP Dashboard for quick answers to common questions.', 'mainwp' ); ?></label>
2467 + </div>
2468 + </div>
2469 + </div>
2470 +
2471 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-tools">
2472 + <label class="six wide column middle aligned">
2473 + <?php
2474 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_enable_guided_video', (int) get_option( 'mainwp_enable_guided_video', 0 ) );
2475 + esc_html_e( 'Youtube Embeds (Video Tutorials)', 'mainwp' );
2476 + ?>
2477 + </label>
2478 + <div class="ten wide column " data-tooltip="<?php esc_attr_e( 'Check this option to enable, or uncheck to disable MainWP video tutorials.', 'mainwp' ); ?>" data-inverted="" data-position="bottom left">
2479 + <div class="ui toggle checkbox">
2480 + <input type="checkbox" class="settings-field-value-change-handler" name="mainwp-guided-video-option" id="mainwp-guided-video-option" <?php echo 1 === (int) get_option( 'mainwp_enable_guided_video', 0 ) ? 'checked="true"' : ''; ?> />
2481 + <label><?php esc_html_e( 'Enable embedded YouTube video tutorials within MainWP for step-by-step guidance.', 'mainwp' ); ?></label>
2482 + </div>
2483 + </div>
2484 + </div>
2485 + <?php
2486 + /**
2487 + * Action: mainwp_tools_form_bottom
2488 + *
2489 + * Fires at the bottom of mainwp tools form.
2490 + *
2491 + * @since 4.1
2492 + */
2493 + do_action( 'mainwp_tools_form_bottom' );
2494 + $el_id_sbm_btn_1 = 'submit';
2495 + ?>
2496 + <div class="ui divider"></div>
2497 + <input type="submit" name="submit" id="<?php echo esc_attr( $el_id_sbm_btn_1 ); ?>" class="ui green big button" value="<?php esc_attr_e( 'Save Settings', 'mainwp' ); ?>"/>
2498 + </form>
2499 + </div>
2500 + </div>
2501 + <script type="text/javascript">
2502 + jQuery( '#mainwp-disconnect-sites-tool' ).popup();
2503 + jQuery( '#mainwp-clear-activation-data' ).popup();
2504 + </script>
2505 + <?php
2506 + static::render_footer( 'MainWPTools' );
2507 + MainWP_Connect_Helper::render_renew_connections_modal();
2508 + }
2509 +
2510 + /**
2511 + * Method is_basic_auth_dashboard_enabled.
2512 + *
2513 + * @return bool true|false.
2514 + */
2515 + public static function is_basic_auth_dashboard_enabled() { // phpcs:ignore -- NOSONAR - complex.
2516 + $response = wp_remote_get( get_site_url() . '/wp-json' );
2517 + $code = wp_remote_retrieve_response_code( $response );
2518 + if ( 404 === (int) $code || 401 === (int) $code ) {
2519 + return true;
2520 + }
2521 + return false;
2522 + }
2523 +
2524 +
2525 + /**
2526 + * Render MainWP themes selection.
2527 + */
2528 + public function render_select_custom_themes() { // phpcs:ignore -- NOSONAR - complex.
2529 + $custom_theme = $this->get_current_user_theme();
2530 + if ( false === $custom_theme ) {
2531 + // to compatible with Custom Dashboard extension settings.
2532 + $compat_settings = get_option( 'mainwp_custom_dashboard_settings' );
2533 + if ( is_array( $compat_settings ) && isset( $compat_settings['theme'] ) ) {
2534 + $compat_theme = $compat_settings['theme'];
2535 + }
2536 + if ( null !== $compat_theme ) {
2537 + $custom_theme = $compat_theme;
2538 + }
2539 + }
2540 + $themes_files = static::get_instance()->get_custom_themes_files();
2541 + if ( empty( $themes_files ) ) {
2542 + $themes_files = array();
2543 + }
2544 + ?>
2545 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-tools" default-indi-value="default">
2546 + <label class="six wide column middle aligned">
2547 + <?php
2548 + MainWP_Settings_Indicator::render_not_default_indicator( 'mainwp_selected_theme', $custom_theme );
2549 + esc_html_e( 'Select MainWP Dashboard theme', 'mainwp' );
2550 + ?>
2551 + </label>
2552 + <div class="ten wide column" tabindex="0" data-tooltip="<?php esc_attr_e( 'Select your MainWP Dashboard theme.', 'mainwp' ); ?>" data-inverted="" data-position="top left">
2553 + <select name="mainwp_settings_custom_theme" id="mainwp_settings_custom_theme" class="ui dropdown selection settings-field-value-change-handler">
2554 + <option value="default" <?php echo ( 'default' === $custom_theme || empty( $custom_theme ) ) ? 'selected' : ''; ?>><?php esc_html_e( 'Light', 'mainwp' ); ?></option>
2555 + <option value="default-dark" <?php echo ( 'default-dark' === $custom_theme || empty( $custom_theme ) ) ? 'selected' : ''; ?>><?php esc_html_e( 'Dark', 'mainwp' ); ?></option>
2556 + <?php if ( 'default-2024' === $custom_theme ) { ?>
2557 + <option value="default-2024" <?php echo ( 'default-2024' === $custom_theme ) ? 'selected' : ''; ?>><?php esc_html_e( 'Default 2024', 'mainwp' ); ?></option>
2558 + <?php } ?>
2559 + <?php if ( 'dark' === $custom_theme ) { ?>
2560 + <option value="dark" <?php echo ( 'dark' === $custom_theme ) ? 'selected' : ''; ?>><?php esc_html_e( 'Dark 2024', 'mainwp' ); ?></option>
2561 + <?php } ?>
2562 + <?php if ( 'classic' === $custom_theme ) { ?>
2563 + <option value="classic" <?php echo ( 'classic' === $custom_theme ) ? 'selected' : ''; ?>><?php esc_html_e( 'Classic (Legacy)', 'mainwp' ); ?></option>
2564 + <?php } ?>
2565 + <?php if ( 'wpadmin' === $custom_theme ) { ?>
2566 + <option value="wpadmin" <?php echo ( 'wpadmin' === $custom_theme ) ? 'selected' : ''; ?>><?php esc_html_e( 'WP Admin (Legacy)', 'mainwp' ); ?></option>
2567 + <?php } ?>
2568 + <?php if ( 'minimalistic' === $custom_theme ) { ?>
2569 + <option value="minimalistic" <?php echo ( 'minimalistic' === $custom_theme ) ? 'selected' : ''; ?>><?php esc_html_e( 'Minimalistic (Legacy)', 'mainwp' ); ?></option>
2570 + <?php } ?>
2571 + <?php
2572 + foreach ( $themes_files as $file_name => $theme ) {
2573 + $theme = ucfirst( $theme );
2574 + $_select = '';
2575 + if ( $custom_theme === $file_name ) {
2576 + $_select = 'selected';
2577 + }
2578 + echo '<option value="' . esc_attr( $file_name ) . '" ' . esc_attr( $_select ) . '>' . esc_html( $theme ) . '</option>';
2579 + }
2580 + ?>
2581 + </select>
2582 + </div>
2583 + </div>
2584 + <?php
2585 + }
2586 +
2587 + /**
2588 + * Get custom themes files.
2589 + */
2590 + public function get_custom_themes_files() {
2591 + // get themes files.
2592 + $dirs = $this->get_custom_theme_folder();
2593 + $scan_dir = $dirs[0];
2594 + $handle = opendir( $scan_dir );
2595 + $themes = array();
2596 + if ( $handle ) {
2597 + $filename = readdir( $handle );
2598 + while ( false !== $filename ) {
2599 + $correct_file = true;
2600 + if ( '.' === substr( $filename, 0, 1 ) || 'index.php' === $filename || '.css' !== substr( $filename, - 4 ) ) {
2601 + $correct_file = false;
2602 + }
2603 + if ( $correct_file ) {
2604 + $theme = basename( $filename, '.css' );
2605 + $theme = str_replace( '-theme', '', $theme );
2606 + $themes[ $filename ] = trim( $theme );
2607 + }
2608 + $filename = readdir( $handle ); // to while loop.
2609 + }
2610 + closedir( $handle );
2611 + }
2612 + return $themes;
2613 + }
2614 +
2615 + /**
2616 + * Get selected MainWP theme name.
2617 + */
2618 + public function get_selected_theme() {
2619 + $selected_theme = false;
2620 +
2621 + $custom_theme = $this->get_current_user_theme();
2622 +
2623 + if ( false === $custom_theme ) {
2624 + // to compatible with Custom Dashboard extension settings.
2625 + $compat_settings = get_option( 'mainwp_custom_dashboard_settings' );
2626 + if ( is_array( $compat_settings ) && isset( $compat_settings['theme'] ) ) {
2627 + $compat_theme = $compat_settings['theme'];
2628 + }
2629 +
2630 + if ( null !== $compat_theme ) {
2631 + $custom_theme = $compat_theme;
2632 + }
2633 + }
2634 +
2635 + if ( ! empty( $custom_theme ) ) {
2636 + if ( 'default' === $custom_theme || 'default-dark' === $custom_theme || 'default-2024' === $custom_theme || 'dark' === $custom_theme || 'wpadmin' === $custom_theme || 'minimalistic' === $custom_theme ) {
2637 + return $custom_theme;
2638 + }
2639 + $dirs = $this->get_custom_theme_folder();
2640 + $theme_dir = $dirs[0];
2641 + $file = $theme_dir . $custom_theme;
2642 + if ( file_exists( $file ) && '.css' === substr( $file, - 4 ) ) {
2643 + $selected_theme = $custom_theme;
2644 + }
2645 + }
2646 + return $selected_theme;
2647 + }
2648 +
2649 +
2650 + /**
2651 + * Get custom MainWP theme folder.
2652 + */
2653 + public function get_custom_theme_folder() {
2654 + $dirs = MainWP_System_Utility::get_mainwp_dir();
2655 + global $wp_filesystem;
2656 + if ( is_array( $dirs ) && ! $wp_filesystem->exists( $dirs[0] . 'themes' ) && $wp_filesystem->exists( $dirs[0] . 'custom-dashboard' ) ) {
2657 + // re-name the custom-dashboard folder to compatible.
2658 + $wp_filesystem->move( $dirs[0] . 'custom-dashboard', $dirs[0] . 'themes' );
2659 + }
2660 + return MainWP_System_Utility::get_mainwp_dir_allow_access( 'themes' );
2661 + }
2662 +
2663 +
2664 + /**
2665 + * Get current user's selected theme.
2666 + */
2667 + public function get_current_user_theme() {
2668 + $custom_theme = get_user_option( 'mainwp_selected_theme' );
2669 + if ( empty( $custom_theme ) ) {
2670 + $custom_theme = get_option( 'mainwp_selected_theme', 'default' );
2671 + }
2672 + return $custom_theme;
2673 + }
2674 +
2675 + /**
2676 + * Export Child Sites and save as .csv file.
2677 + *
2678 + * @uses \MainWP\Dashboard\MainWP_DB::query()
2679 + * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_for_current_user()
2680 + * @uses \MainWP\Dashboard\MainWP_DB::data_seek()
2681 + * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
2682 + * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
2683 + */
2684 + public static function export_sites() {
2685 + if ( isset( $_GET['doExportSites'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'export_sites' ) ) {
2686 +
2687 + $sql = MainWP_DB::instance()->get_sql_websites_for_current_user( true );
2688 + $websites = MainWP_DB::instance()->query( $sql );
2689 +
2690 + if ( ! $websites ) {
2691 + die( 'Not found sites' );
2692 + }
2693 +
2694 + $keys = array( 'name', 'url', 'adminname', 'adminpasswd', 'wpgroups', 'uniqueId', 'http_user', 'http_pass', 'verify_certificate', 'ssl_version' );
2695 + $allowedHeaders = array( 'site name', 'url', 'admin name', 'admin password', 'tag', 'security id', 'http username', 'http password', 'verify certificate', 'ssl version' );
2696 + $csv = "#\r";
2697 + $csv .= '# Your password is never stored by your Dashboard and never sent to MainWP.com. Once this initial connection is complete, your MainWP Dashboard generates a secure Public and Private key pair (2048 bits) using OpenSSL, allowing future connections without needing your password again. For added security, you can even change this admin password once connected, just be sure not to delete the admin account, as this would disrupt the connection.' . "\r";
2698 + $csv .= "#\r";
2699 + $csv .= implode( ',', $allowedHeaders ) . "\r";
2700 + MainWP_DB::data_seek( $websites, 0 );
2701 + while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
2702 + if ( empty( $website ) ) {
2703 + continue;
2704 + }
2705 + $row = MainWP_Utility::map_site( $website, $keys, false );
2706 + // MWP-1548: decrypt http_user / http_pass before they hit
2707 + // the CSV. The export file is meant for cross-install
2708 + // transfer (admin re-imports on another dashboard); a
2709 + // file_key envelope from this install would be unreadable
2710 + // there. Plaintext on disk preserves today's portability
2711 + // contract -- the export was already plaintext pre-fix,
2712 + // and this hop neither widens nor narrows that exposure.
2713 + if ( isset( $row['http_user'] ) ) {
2714 + $row['http_user'] = MainWP_Credential_Storage::decrypt_credential( $row['http_user'] );
2715 + }
2716 + if ( isset( $row['http_pass'] ) ) {
2717 + $row['http_pass'] = MainWP_Credential_Storage::decrypt_credential( $row['http_pass'] );
2718 + }
2719 +
2720 + $row = array_map(
2721 + static function ( $value ) {
2722 + return str_replace( '"', '""', (string) $value );
2723 + },
2724 + $row
2725 + );
2726 +
2727 + $csv .= '"' . implode( '","', $row ) . '"' . "\r";
2728 + }
2729 +
2730 + header( 'Content-Type: text/csv; charset=utf-8' );
2731 + header( 'Content-Disposition: attachment; filename=export-sites.csv' );
2732 + echo $csv; // phpcs:ignore WordPress.Security.EscapeOutput
2733 + exit();
2734 + }
2735 + }
2736 +
2737 + /**
2738 + * Render MainWP Email Settings SubPage.
2739 + *
2740 + * @uses \MainWP\Dashboard\MainWP_Notification_Settings::get_notification_types()
2741 + * @uses \MainWP\Dashboard\MainWP_Notification_Settings::render_edit_settings()
2742 + * @uses \MainWP\Dashboard\MainWP_Notification_Settings::emails_general_settings_handle()
2743 + * @uses \MainWP\Dashboard\MainWP_Notification_Settings::render_all_settings()
2744 + * @uses \MainWP\Dashboard\MainWP_Notification_Template::handle_template_file_action()
2745 + */
2746 + public static function render_email_settings() {
2747 + $notification_emails = MainWP_Notification_Settings::get_notification_types();
2748 + static::render_header( 'Emails' );
2749 + $edit_email = isset( $_GET['edit-email'] ) ? sanitize_text_field( wp_unslash( $_GET['edit-email'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2750 + if ( ! empty( $edit_email ) && isset( $notification_emails[ $edit_email ] ) ) {
2751 + $updated_templ = MainWP_Notification_Template::instance()->handle_template_file_action();
2752 + MainWP_Notification_Settings::instance()->render_edit_settings( $edit_email, $updated_templ );
2753 + } else {
2754 + $updated = MainWP_Notification_Settings::emails_general_settings_handle();
2755 + MainWP_Notification_Settings::instance()->render_all_settings( $updated );
2756 + }
2757 + static::render_footer( 'Emails' );
2758 + }
2759 +
2760 + /**
2761 + * Method mainwp_help_content()
2762 + *
2763 + * Creates the MainWP Help Documentation List for the help component in the sidebar.
2764 + */
2765 + public static function mainwp_help_content() {
2766 + if ( isset( $_GET['page'] ) && ( 'Settings' === $_GET['page'] || 'SettingsAdvanced' === $_GET['page'] || 'MainWPTools' === $_GET['page'] || 'MonitoringSettings' === $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2767 + ?>
2768 + <p><?php esc_html_e( 'If you need help with your MainWP Dashboard settings, please review following help documents', 'mainwp' ); ?></p>
2769 + <div class="ui list">
2770 + <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/sites/management/mainwp-dashboard-settings#mainwp-dashboard-settings" target="_blank">MainWP Dashboard Settings</a></div>
2771 + </div>
2772 + <?php
2773 + /**
2774 + * Action: mainwp_settings_help_item
2775 + *
2776 + * Fires at the bottom of the help articles list in the Help sidebar on the Settings page.
2777 + *
2778 + * Suggested HTML markup:
2779 + *
2780 + * <div class="item"><a href="Your custom URL">Your custom text</a></div>
2781 + *
2782 + * @since 5.2
2783 + */
2784 + do_action( 'mainwp_settings_help_item' );
2785 +
2786 + }
2787 + }
2788 +
2789 + /**
2790 + * Method render_monitoring()
2791 + *
2792 + * Render Monitoring Settings.
2793 + *
2794 + * @uses \MainWP\Dashboard\MainWP_Monitoring_View::render_settings()
2795 + */
2796 + public static function render_monitoring() {
2797 + if ( ! \mainwp_current_user_can( 'dashboard', 'manage_dashboard_settings' ) ) {
2798 + \mainwp_do_not_have_permissions( esc_html__( 'manage dashboard settings', 'mainwp' ) );
2799 + return;
2800 + }
2801 + static::render_header( 'Monitoring' );
2802 + ?>
2803 + <div id="mainwp-monitoring-settings" class="ui padded segment">
2804 + <?php if ( isset( $_GET['message'] ) && 'saved' === sanitize_text_field( wp_unslash( $_GET['message'] ) ) ) : // phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>
2805 + <div class="ui green message"><i class="close icon"></i><?php esc_html_e( 'Monitoring settings have been saved successfully!', 'mainwp' ); ?></div>
2806 + <?php endif; ?>
2807 + <div class="ui form">
2808 + <form method="POST" action="">
2809 + <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
2810 + <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'MonitoringSettings' ) ); ?>" />
2811 + <?php
2812 + /**
2813 + * Action: mainwp_monitoring_settings_form_top
2814 + *
2815 + * Fires at the top of monitoring settings form.
2816 + *
2817 + * @since 4.1
2818 + */
2819 + do_action( 'mainwp_monitoring_settings_form_top' );
2820 + ?>
2821 + <?php MainWP_Monitoring_View::render_settings(); ?>
2822 + <?php
2823 + /**
2824 + * Action: mainwp_monitoring_form_bottom
2825 + *
2826 + * Fires at the bottom of mainwp monitoring form.
2827 + *
2828 + * @since 4.1
2829 + */
2830 + do_action( 'mainwp_monitoring_settings_form_bottom' );
2831 + ?>
2832 + <div class="ui divider"></div>
2833 + <input type="submit" name="submit" id="submit-monitoring" class="ui green big button" value="<?php esc_attr_e( 'Save Settings', 'mainwp' ); ?>"/>
2834 + </form>
2835 + </div>
2836 + </div>
2837 + <?php
2838 + static::render_footer( 'Monitoring' );
2839 + }
1831 2840 }